diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 589bb2ed4..000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,21 +0,0 @@ -// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.101.1/containers/ubuntu-18.04-git -{ - "name": "Ubuntu 18.04 EQEMU", - // Moved from dockerfile to image so it builds faster - "image": "eqemu/devcontainer:0.0.2", - - // Set *default* container specific settings.json values on container create. - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - }, - - "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], - - // Add the IDs of extensions you want installed when the container is created. - "extensions": ["ms-vscode.cpptools", "ms-azuretools.vscode-docker"], - "mounts": ["source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"], - "remoteEnv": { - "HOST_PROJECT_PATH": "${localWorkspaceFolder}" - } -} diff --git a/.drone.yml b/.drone.yml index 38757e006..26221a5f9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,11 +15,13 @@ volumes: steps: - name: server-build # Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20 - image: akkadius/eqemu-server:latest + image: akkadius/eqemu-server:v11 commands: - sudo chown eqemu:eqemu /drone/src/ * -R - sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R - - git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O0 -g -DNDEBUG" -G 'Unix Makefiles' .. && make -j$((`nproc`-4)) + - git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O0 -g -DNDEBUG" -G 'Unix Makefiles' .. && make -j$((`nproc`-4)) + - curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json + - ./bin/tests volumes: - name: cache path: /home/eqemu/.ccache/ diff --git a/.gitignore b/.gitignore index d835a1ceb..40075fa6c 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,10 @@ bin/ /client_files/**/CMakeFiles/ .idea + +# Clangd Generated Files. +compile_flags.txt +.cache/ + +# vscode generated settings +.vscode/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 38db9d797..000000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: cpp -compiler: gcc -dist: bionic - -addons: - apt: - packages: - - libmysqlclient-dev - - libperl-dev - - libboost-dev - - liblua5.1-0-dev - - zlib1g-dev - - uuid-dev - - libssl-dev - -script: - - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON - - make -j2 - - ./bin/tests diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 4aee577ae..000000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/**", - "/usr/include/mysql" - ], - "defines": [], - "compilerPath": "/usr/bin/gcc", - "cStandard": "c11", - "cppStandard": "c++17" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a955aa60c..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "make", - "type": "shell", - "command": "cd bin && make", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [ - "$gcc" - ] - }, - { - "label": "make clean", - "type": "shell", - "command": "cd bin && make clean", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [ - "$gcc" - ] - }, - { - "label": "cmake", - "type": "shell", - "command": "mkdir -p bin && cd bin && rm CMakeCache.txt && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' ..", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher":{ - "owner": "cpp", - "fileLocation": "relative", - "pattern":[ - { - "regexp": "([\\w+|\\\\]*\\.\\w+)\\((\\d+)\\)\\: (warning|error) (.*)$", - "file": 1, - "location": 2, - "severity": 3, - "message": 4 - } - ] - } - }, - { - "label": "download maps", - "type": "shell", - "command": "mkdir -p bin && cd bin && wget https://codeload.github.com/Akkadius/EQEmuMaps/zip/master -O maps.zip && unzip -o maps.zip && rm ./maps -rf && mv EQEmuMaps-master maps && rm maps.zip", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [ - "$gcc" - ] - }, - { - "label": "download quests", - "type": "shell", - "command": "mkdir -p bin && cd bin && cd server && git -C ./quests pull 2> /dev/null || git clone https://github.com/ProjectEQ/projecteqquests.git quests", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [ - "$gcc" - ] - }, - { - "label": "download eqemu_config", - "type": "shell", - "command": "mkdir -p bin && cd bin && wget --no-check-certificate https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/eqemu_config_docker.json -O eqemu_config.json", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [ - "$gcc" - ] - }, - { - "label": "rebuild database (mariadb must be started)", - "type": "shell", - "command": "mkdir -p bin && cd bin && docker run -i --rm --privileged -v ${HOST_PROJECT_PATH}/bin:/src --network=eqemu -it eqemu/server:0.0.3 bash -c './eqemu_server.pl source_peq_db && ./eqemu_server.pl check_db_updates && ./eqemu_server.pl linux_login_server_setup'", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [ - "$gcc" - ] - }, - { - "label": "zone 7000", - "type": "shell", - "command": "docker stop zone7000 | true && docker network create eqemu | true && docker run -i --rm --name zone7000 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 --network=eqemu -p 7000:7000/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7000:7000", - "group": { - "kind": "test", - "isDefault": true - } - }, - { - "label": "zone 7001", - "type": "shell", - "command": "docker stop zone7001 | true && docker network create eqemu | true && docker run -i --rm --name zone7001 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 --network=eqemu -p 7001:7001/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7001:7001", - "group": { - "kind": "test", - "isDefault": true - } - }, - { - "label": "loginserver", - "type": "shell", - "command": "docker stop loginserver | true && docker network create eqemu | true && docker run -i --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 --network=eqemu --name loginserver -p 5999:5999/udp -p 5998:5998/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./loginserver", - "group": { - "kind": "test", - "isDefault": true - } - }, - { - "label": "shared_memory, world", - "type": "shell", - "command": "docker stop sharedmemory | true && docker stop world | true && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src --network=eqemu --name sharedmemory eqemu/server:0.0.3 ./shared_memory && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name world -p 9000:9000 -p 9000:9000/udp -p 9001:9001 -p 9080:9080 eqemu/server:0.0.3 gdb -ex run ./world", - "group": { - "kind": "test", - "isDefault": true - } - }, - { - "label": "queryserv", - "type": "shell", - "command": "docker stop queryserv | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name queryserv eqemu/server:0.0.3 gdb -ex run ./queryserv", - "group": { - "kind": "test", - "isDefault": true - } - }, - { - "label": "mariadb", - "type": "shell", - "command": "docker stop mariadb | true && cd bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin/db:/bitnami/mariadb -p 3306:3306 -e MARIADB_DATABASE=peq -e MARIADB_USER=eqemu -e MARIADB_PASSWORD=eqemupass -e ALLOW_EMPTY_PASSWORD=yes --name mariadb --network=eqemu bitnami/mariadb:latest", - "group": { - "kind": "test", - "isDefault": true - } - }, - { - "label": "ucs", - "type": "shell", - "command": "docker stop ucs | true && cd bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/bin:/src -p 7778:7778 --name ucs --network=eqemu eqemu/server:0.0.3 gdb -ex run ./ucs", - "group": { - "kind": "test", - "isDefault": true - } - } - ] -} diff --git a/BUILD.md b/BUILD.md index 1cc3cd99b..c1051f2b6 100644 --- a/BUILD.md +++ b/BUILD.md @@ -40,14 +40,14 @@ Assuming it is starting in c:/projects/eqemu and the x64 dependencies were extra mkdir build cd build - cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DEQEMU_ENABLE_BOTS=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" .. + cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" .. ##### Linux Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator. mkdir build cd build - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON .. + cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON .. ### Building diff --git a/CMakeLists.txt b/CMakeLists.txt index 407b1a221..5428e6c06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.7) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) @@ -12,7 +12,7 @@ IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) -SET(CMAKE_CXX_STANDARD 14) +SET(CMAKE_CXX_STANDARD 20) SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(CMAKE_CXX_EXTENSIONS OFF) @@ -20,7 +20,8 @@ IF(MSVC) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) ADD_DEFINITIONS(-DNOMINMAX) ADD_DEFINITIONS(-DCRASH_LOGGING) - + ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17 + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") ELSE(MSVC) ADD_DEFINITIONS(-DHAS_UNION_SEMUN) @@ -121,8 +122,6 @@ ENDIF() MESSAGE(STATUS "**************************************************") #options -OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON) -OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF) OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON) OPTION(EQEMU_BUILD_SERVER "Build the game server." ON) OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON) @@ -176,17 +175,13 @@ IF(EQEMU_COMMANDS_LOGGING) ADD_DEFINITIONS(-DCOMMANDS_LOGGING) ENDIF(EQEMU_COMMANDS_LOGGING) -IF(EQEMU_ENABLE_BOTS) - ADD_DEFINITIONS(-DBOTS) -ENDIF(EQEMU_ENABLE_BOTS) - #database IF(MySQL_FOUND AND MariaDB_FOUND) SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use: MySQL MariaDB" ) - + IF(DATABASE_LIBRARY_SELECTION STREQUAL "MySQL") SET(DATABASE_LIBRARY_TYPE " MySQL") SET(DATABASE_LIBRARY_LIBS ${MySQL_LIBRARIES}) @@ -217,7 +212,7 @@ IF(OpenSSL_FOUND AND MBEDTLS_FOUND) OpenSSL mbedTLS" ) - + IF(TLS_LIBRARY_SELECTION STREQUAL "OpenSSL") SET(TLS_LIBRARY_TYPE " OpenSSL") SET(TLS_LIBRARY_ENABLED ON) @@ -340,10 +335,8 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp") -OPTION(EQEMU_BUILD_LOGGING "Build Logging (To speed up compilation)" ON) -IF(EQEMU_BUILD_LOGGING) - ADD_DEFINITIONS(-DBUILD_LOGGING) -ENDIF() +# silence obnoxious deprecation message +ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS) IF(TLS_LIBRARY_ENABLED) SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS}) @@ -357,12 +350,12 @@ ENDIF() IF(LUA_LIBRARY_ENABLED) OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON) - + IF(EQEMU_BUILD_LUA) ADD_DEFINITIONS(-DLUA_EQEMU) SET(ZONE_LIBS ${LUA_LIBRARY_LIBS}) INCLUDE_DIRECTORIES(SYSTEM "${LUA_LIBRARY_INCLUDE}") - + OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON) IF(EQEMU_SANITIZE_LUA_LIBS) ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS) @@ -373,7 +366,7 @@ ENDIF() IF(PERL_LIBRARY_ENABLED) OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) IF(EQEMU_BUILD_PERL) - SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS}) + SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS} perlbind) INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}") ADD_DEFINITIONS(-DEMBPERL) ADD_DEFINITIONS(-DEMBPERL_PLUGIN) @@ -410,13 +403,13 @@ IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_H ADD_SUBDIRECTORY(libs) ADD_SUBDIRECTORY(submodules/fmt) ADD_SUBDIRECTORY(submodules/libuv) - + IF(EQEMU_BUILD_ZLIB) SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API") SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries") ADD_SUBDIRECTORY(libs/zlibng) ENDIF() - + SET(RECASTNAVIGATION_DEMO OFF CACHE BOOL "Build demo") SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests") SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples") diff --git a/appveyor-bots.yml b/appveyor-bots.yml index 540d9b3df..63f40abe1 100644 --- a/appveyor-bots.yml +++ b/appveyor-bots.yml @@ -9,7 +9,7 @@ init: - ps: git config --global core.autocrlf input cache: c:\tools\vcpkg\installed\ before_build: -- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .." +- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .." build: project: C:\projects\eqemu\build\EQEmu.sln parallel: true diff --git a/appveyor-no-bots.yml b/appveyor-no-bots.yml index 0b0f5b8a2..962f15cab 100644 --- a/appveyor-no-bots.yml +++ b/appveyor-no-bots.yml @@ -9,7 +9,7 @@ init: - ps: git config --global core.autocrlf input cache: c:\tools\vcpkg\installed\ before_build: -- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=OFF -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .." +- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .." build: project: C:\projects\eqemu\build\EQEmu.sln parallel: true diff --git a/client_files/export/CMakeLists.txt b/client_files/export/CMakeLists.txt index 08cbbc822..b7f15dddb 100644 --- a/client_files/export/CMakeLists.txt +++ b/client_files/export/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(export_sources main.cpp diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index ff7f1f3dd..505a4ac05 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -25,11 +25,15 @@ #include "../../common/platform.h" #include "../../common/crash.h" #include "../../common/rulesys.h" -#include "../../common/string_util.h" +#include "../../common/strings.h" #include "../../common/content/world_content_service.h" +#include "../../common/zone_store.h" +#include "../../common/path_manager.h" EQEmuLogSys LogSys; WorldContentService content_service; +ZoneStore zone_store; +PathManager path; void ExportSpells(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db); @@ -42,6 +46,8 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + LogInfo("Client Files Export Utility"); if (!EQEmuConfig::LoadConfig()) { LogError("Unable to load configuration file"); @@ -84,6 +90,7 @@ int main(int argc, char **argv) } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); @@ -124,7 +131,8 @@ void ExportSpells(SharedDatabase *db) { LogInfo("Exporting Spells"); - FILE *f = fopen("export/spells_us.txt", "w"); + std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/spells_us.txt to write, skipping."); return; @@ -206,7 +214,8 @@ void ExportSkillCaps(SharedDatabase *db) { LogInfo("Exporting Skill Caps"); - FILE *f = fopen("export/SkillCaps.txt", "w"); + std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/SkillCaps.txt to write, skipping."); return; @@ -236,7 +245,8 @@ void ExportBaseData(SharedDatabase *db) { LogInfo("Exporting Base Data"); - FILE *f = fopen("export/BaseData.txt", "w"); + std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/BaseData.txt to write, skipping."); return; @@ -269,7 +279,8 @@ void ExportDBStrings(SharedDatabase *db) { LogInfo("Exporting DB Strings"); - FILE *f = fopen("export/dbstr_us.txt", "w"); + std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/dbstr_us.txt to write, skipping."); return; diff --git a/client_files/import/CMakeLists.txt b/client_files/import/CMakeLists.txt index a76bab416..da08cda6e 100644 --- a/client_files/import/CMakeLists.txt +++ b/client_files/import/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(import_sources main.cpp diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index 2fbdf421a..c80ed8194 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -23,11 +23,15 @@ #include "../../common/platform.h" #include "../../common/crash.h" #include "../../common/rulesys.h" -#include "../../common/string_util.h" +#include "../../common/strings.h" #include "../../common/content/world_content_service.h" +#include "../../common/zone_store.h" +#include "../../common/path_manager.h" EQEmuLogSys LogSys; WorldContentService content_service; +ZoneStore zone_store; +PathManager path; void ImportSpells(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db); @@ -39,6 +43,8 @@ int main(int argc, char **argv) { LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + LogInfo("Client Files Import Utility"); if(!EQEmuConfig::LoadConfig()) { LogError("Unable to load configuration file."); @@ -81,6 +87,7 @@ int main(int argc, char **argv) { } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); @@ -125,9 +132,10 @@ bool IsStringField(int i) { void ImportSpells(SharedDatabase *db) { LogInfo("Importing Spells"); - FILE *f = fopen("import/spells_us.txt", "r"); + std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/spells_us.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } @@ -146,8 +154,8 @@ void ImportSpells(SharedDatabase *db) { } } - std::string escaped = ::EscapeString(buffer); - auto split = SplitString(escaped, '^'); + std::string escaped = ::Strings::Escape(buffer); + auto split = Strings::Split(escaped, '^'); int line_columns = (int)split.size(); std::string sql; @@ -214,9 +222,10 @@ void ImportSpells(SharedDatabase *db) { void ImportSkillCaps(SharedDatabase *db) { LogInfo("Importing Skill Caps"); - FILE *f = fopen("import/SkillCaps.txt", "r"); + std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/SkillCaps.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } @@ -225,7 +234,7 @@ void ImportSkillCaps(SharedDatabase *db) { char buffer[2048]; while(fgets(buffer, 2048, f)) { - auto split = SplitString(buffer, '^'); + auto split = Strings::Split(buffer, '^'); if(split.size() < 4) { continue; @@ -249,9 +258,10 @@ void ImportSkillCaps(SharedDatabase *db) { void ImportBaseData(SharedDatabase *db) { LogInfo("Importing Base Data"); - FILE *f = fopen("import/BaseData.txt", "r"); + std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/BaseData.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } @@ -260,7 +270,7 @@ void ImportBaseData(SharedDatabase *db) { char buffer[2048]; while(fgets(buffer, 2048, f)) { - auto split = SplitString(buffer, '^'); + auto split = Strings::Split(buffer, '^'); if(split.size() < 10) { continue; @@ -294,9 +304,10 @@ void ImportBaseData(SharedDatabase *db) { void ImportDBStrings(SharedDatabase *db) { LogInfo("Importing DB Strings"); - FILE *f = fopen("import/dbstr_us.txt", "r"); + std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/dbstr_us.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } @@ -318,7 +329,7 @@ void ImportDBStrings(SharedDatabase *db) { } } - auto split = SplitString(buffer, '^'); + auto split = Strings::Split(buffer, '^'); if(split.size() < 2) { continue; @@ -332,7 +343,7 @@ void ImportDBStrings(SharedDatabase *db) { type = atoi(split[1].c_str()); if(split.size() >= 3) { - value = ::EscapeString(split[2]); + value = ::Strings::Escape(split[2]); } sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')", diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index e9de82316..b9b4fa21c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,761 +1,783 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(common_sources - base_packet.cpp - classes.cpp - cli/eqemu_command_handler.cpp - compression.cpp - condition.cpp - content/world_content_service.cpp - crash.cpp - crc16.cpp - crc32.cpp - database/database_dump_service.cpp - database.cpp - database_conversions.cpp - database_instances.cpp - dbcore.cpp - deity.cpp - dynamic_zone_base.cpp - emu_constants.cpp - emu_limits.cpp - emu_opcodes.cpp - emu_versions.cpp - eqdb.cpp - eqdb_res.cpp - eqemu_exception.cpp - eqemu_config.cpp - eqemu_logsys.cpp - eq_limits.cpp - eq_packet.cpp - eq_stream_ident.cpp - eq_stream_proxy.cpp - eqtime.cpp - event_sub.cpp - expedition_lockout_timer.cpp - extprofile.cpp - faction.cpp - file_util.cpp - guild_base.cpp - guilds.cpp - inventory_profile.cpp - inventory_slot.cpp - ipc_mutex.cpp - ip_util.cpp - item_data.cpp - item_instance.cpp - json_config.cpp - light_source.cpp - md5.cpp - memory_buffer.cpp - memory_mapped_file.cpp - misc.cpp - misc_functions.cpp - mutex.cpp - mysql_request_result.cpp - mysql_request_row.cpp - opcode_map.cpp - opcodemgr.cpp - packet_dump.cpp - packet_dump_file.cpp - packet_functions.cpp - perl_eqdb.cpp - perl_eqdb_res.cpp - proc_launcher.cpp - profanity_manager.cpp - ptimer.cpp - races.cpp - rdtsc.cpp - rulesys.cpp - say_link.cpp - serialize_buffer.cpp - server_event_scheduler.cpp - serverinfo.cpp - shared_tasks.cpp - shareddb.cpp - skills.cpp - spdat.cpp - string_util.cpp - struct_strategy.cpp - textures.cpp - timer.cpp - unix.cpp - platform.cpp - json/jsoncpp.cpp - net/console_server.cpp - net/console_server_connection.cpp - net/crc32.cpp - net/daybreak_connection.cpp - net/eqstream.cpp - net/packet.cpp - net/servertalk_client_connection.cpp - net/servertalk_legacy_client_connection.cpp - net/servertalk_server.cpp - net/servertalk_server_connection.cpp - net/tcp_connection.cpp - net/tcp_server.cpp - net/websocket_server.cpp - net/websocket_server_connection.cpp - patches/patches.cpp - patches/sod.cpp - patches/sod_limits.cpp - patches/sof.cpp - patches/sof_limits.cpp - patches/rof.cpp - patches/rof_limits.cpp - patches/rof2.cpp - patches/rof2_limits.cpp - patches/titanium.cpp - patches/titanium_limits.cpp - patches/uf.cpp - patches/uf_limits.cpp - StackWalker/StackWalker.cpp - util/directory.cpp - util/uuid.cpp) + base_packet.cpp + classes.cpp + cli/eqemu_command_handler.cpp + compression.cpp + condition.cpp + content/world_content_service.cpp + discord/discord.cpp + crash.cpp + crc16.cpp + crc32.cpp + database/database_dump_service.cpp + database.cpp + database_conversions.cpp + database_instances.cpp + dbcore.cpp + deity.cpp + dynamic_zone_base.cpp + emu_constants.cpp + emu_limits.cpp + emu_opcodes.cpp + emu_versions.cpp + eqdb.cpp + eqdb_res.cpp + eqemu_exception.cpp + eqemu_config.cpp + eqemu_logsys.cpp + eq_limits.cpp + eq_packet.cpp + eq_stream_ident.cpp + eq_stream_proxy.cpp + eqtime.cpp + event_sub.cpp + expedition_lockout_timer.cpp + extprofile.cpp + discord_manager.cpp + faction.cpp + file.cpp + guild_base.cpp + guilds.cpp + inventory_profile.cpp + inventory_slot.cpp + ipc_mutex.cpp + ip_util.cpp + item_data.cpp + item_instance.cpp + json_config.cpp + light_source.cpp + md5.cpp + memory_buffer.cpp + memory_mapped_file.cpp + misc.cpp + misc_functions.cpp + mutex.cpp + mysql_request_result.cpp + mysql_request_row.cpp + opcode_map.cpp + opcodemgr.cpp + packet_dump.cpp + packet_dump_file.cpp + packet_functions.cpp + path_manager.cpp + perl_eqdb.cpp + perl_eqdb_res.cpp + process/process.cpp + proc_launcher.cpp + profanity_manager.cpp + ptimer.cpp + races.cpp + rdtsc.cpp + rulesys.cpp + say_link.cpp + serialize_buffer.cpp + server_event_scheduler.cpp + serverinfo.cpp + shared_tasks.cpp + shareddb.cpp + skills.cpp + spdat.cpp + strings.cpp + struct_strategy.cpp + textures.cpp + timer.cpp + unix.cpp + platform.cpp + json/jsoncpp.cpp + zone_store.cpp + net/console_server.cpp + net/console_server_connection.cpp + net/crc32.cpp + net/daybreak_connection.cpp + net/eqstream.cpp + net/packet.cpp + net/servertalk_client_connection.cpp + net/servertalk_legacy_client_connection.cpp + net/servertalk_server.cpp + net/servertalk_server_connection.cpp + net/tcp_connection.cpp + net/tcp_server.cpp + net/websocket_server.cpp + net/websocket_server_connection.cpp + patches/patches.cpp + patches/sod.cpp + patches/sod_limits.cpp + patches/sof.cpp + patches/sof_limits.cpp + patches/rof.cpp + patches/rof_limits.cpp + patches/rof2.cpp + patches/rof2_limits.cpp + patches/titanium.cpp + patches/titanium_limits.cpp + patches/uf.cpp + patches/uf_limits.cpp + StackWalker/StackWalker.cpp + util/directory.cpp + util/uuid.cpp) SET(repositories - # Criteria - repositories/criteria/content_filter_criteria.h + # Criteria + repositories/criteria/content_filter_criteria.h - # Base Repositories - repositories/base/base_aa_ability_repository.h - repositories/base/base_aa_ranks_repository.h - repositories/base/base_aa_rank_effects_repository.h - repositories/base/base_aa_rank_prereqs_repository.h - repositories/base/base_account_repository.h - repositories/base/base_account_flags_repository.h - repositories/base/base_account_ip_repository.h - repositories/base/base_account_rewards_repository.h - repositories/base/base_adventure_details_repository.h - repositories/base/base_adventure_members_repository.h - repositories/base/base_adventure_stats_repository.h - repositories/base/base_adventure_template_repository.h - repositories/base/base_adventure_template_entry_repository.h - repositories/base/base_adventure_template_entry_flavor_repository.h - repositories/base/base_alternate_currency_repository.h - repositories/base/base_auras_repository.h - repositories/base/base_base_data_repository.h - repositories/base/base_blocked_spells_repository.h - repositories/base/base_bugs_repository.h - repositories/base/base_bug_reports_repository.h - repositories/base/base_buyer_repository.h - repositories/base/base_character_activities_repository.h - repositories/base/base_character_alternate_abilities_repository.h - repositories/base/base_character_alt_currency_repository.h - repositories/base/base_character_auras_repository.h - repositories/base/base_character_bandolier_repository.h - repositories/base/base_character_bind_repository.h - repositories/base/base_character_buffs_repository.h - repositories/base/base_character_corpses_repository.h - repositories/base/base_character_corpse_items_repository.h - repositories/base/base_character_currency_repository.h - repositories/base/base_character_data_repository.h - repositories/base/base_character_disciplines_repository.h - repositories/base/base_character_expedition_lockouts_repository.h - repositories/base/base_character_inspect_messages_repository.h - repositories/base/base_character_instance_safereturns_repository.h - repositories/base/base_character_item_recast_repository.h - repositories/base/base_character_languages_repository.h - repositories/base/base_character_leadership_abilities_repository.h - repositories/base/base_character_material_repository.h - repositories/base/base_character_memmed_spells_repository.h - repositories/base/base_character_pet_buffs_repository.h - repositories/base/base_character_pet_info_repository.h - repositories/base/base_character_pet_inventory_repository.h - repositories/base/base_character_potionbelt_repository.h - repositories/base/base_character_skills_repository.h - repositories/base/base_character_spells_repository.h - repositories/base/base_character_task_timers_repository.h - repositories/base/base_character_tasks_repository.h - repositories/base/base_char_create_combinations_repository.h - repositories/base/base_char_create_point_allocations_repository.h - repositories/base/base_char_recipe_list_repository.h - repositories/base/base_completed_tasks_repository.h - repositories/base/base_completed_shared_tasks_repository.h - repositories/base/base_completed_shared_task_members_repository.h - repositories/base/base_completed_shared_task_activity_state_repository.h - repositories/base/base_content_flags_repository.h - repositories/base/base_damageshieldtypes_repository.h - repositories/base/base_data_buckets_repository.h - repositories/base/base_db_str_repository.h - repositories/base/base_discovered_items_repository.h - repositories/base/base_doors_repository.h - repositories/base/base_dynamic_zones_repository.h - repositories/base/base_dynamic_zone_members_repository.h - repositories/base/base_eventlog_repository.h - repositories/base/base_expeditions_repository.h - repositories/base/base_expedition_lockouts_repository.h - repositories/base/base_faction_base_data_repository.h - repositories/base/base_faction_list_repository.h - repositories/base/base_faction_list_mod_repository.h - repositories/base/base_faction_values_repository.h - repositories/base/base_fishing_repository.h - repositories/base/base_forage_repository.h - repositories/base/base_friends_repository.h - repositories/base/base_global_loot_repository.h - repositories/base/base_gm_ips_repository.h - repositories/base/base_goallists_repository.h - repositories/base/base_graveyard_repository.h - repositories/base/base_grid_repository.h - repositories/base/base_grid_entries_repository.h - repositories/base/base_ground_spawns_repository.h - repositories/base/base_group_id_repository.h - repositories/base/base_group_leaders_repository.h - repositories/base/base_guilds_repository.h - repositories/base/base_guild_members_repository.h - repositories/base/base_guild_ranks_repository.h - repositories/base/base_guild_relations_repository.h - repositories/base/base_hackers_repository.h - repositories/base/base_instance_list_repository.h - repositories/base/base_instance_list_player_repository.h - repositories/base/base_inventory_repository.h - repositories/base/base_inventory_snapshots_repository.h - repositories/base/base_ip_exemptions_repository.h - repositories/base/base_items_repository.h - repositories/base/base_item_tick_repository.h - repositories/base/base_ldon_trap_entries_repository.h - repositories/base/base_ldon_trap_templates_repository.h - repositories/base/base_level_exp_mods_repository.h - repositories/base/base_lfguild_repository.h - repositories/base/base_login_accounts_repository.h - repositories/base/base_login_api_tokens_repository.h - repositories/base/base_login_server_admins_repository.h - repositories/base/base_login_server_list_types_repository.h - repositories/base/base_login_world_servers_repository.h - repositories/base/base_logsys_categories_repository.h - repositories/base/base_lootdrop_repository.h - repositories/base/base_lootdrop_entries_repository.h - repositories/base/base_loottable_repository.h - repositories/base/base_loottable_entries_repository.h - repositories/base/base_mail_repository.h - repositories/base/base_merchantlist_repository.h - repositories/base/base_merchantlist_temp_repository.h - repositories/base/base_name_filter_repository.h - repositories/base/base_npc_emotes_repository.h - repositories/base/base_npc_faction_repository.h - repositories/base/base_npc_faction_entries_repository.h - repositories/base/base_npc_scale_global_base_repository.h - repositories/base/base_npc_spells_repository.h - repositories/base/base_npc_spells_effects_repository.h - repositories/base/base_npc_spells_effects_entries_repository.h - repositories/base/base_npc_spells_entries_repository.h - repositories/base/base_npc_types_repository.h - repositories/base/base_npc_types_tint_repository.h - repositories/base/base_object_repository.h - repositories/base/base_object_contents_repository.h - repositories/base/base_perl_event_export_settings_repository.h - repositories/base/base_petitions_repository.h - repositories/base/base_pets_repository.h - repositories/base/base_pets_equipmentset_repository.h - repositories/base/base_pets_equipmentset_entries_repository.h - repositories/base/base_player_titlesets_repository.h - repositories/base/base_proximities_repository.h - repositories/base/base_quest_globals_repository.h - repositories/base/base_raid_details_repository.h - repositories/base/base_raid_members_repository.h - repositories/base/base_reports_repository.h - repositories/base/base_respawn_times_repository.h - repositories/base/base_rule_sets_repository.h - repositories/base/base_rule_values_repository.h - repositories/base/base_saylink_repository.h - repositories/base/base_server_scheduled_events_repository.h - repositories/base/base_shared_tasks_repository.h - repositories/base/base_shared_task_activity_state_repository.h - repositories/base/base_shared_task_dynamic_zones_repository.h - repositories/base/base_shared_task_members_repository.h - repositories/base/base_skill_caps_repository.h - repositories/base/base_spawn2_repository.h - repositories/base/base_spawnentry_repository.h - repositories/base/base_spawngroup_repository.h - repositories/base/base_spawn_conditions_repository.h - repositories/base/base_spawn_condition_values_repository.h - repositories/base/base_spawn_events_repository.h - repositories/base/base_spells_new_repository.h - repositories/base/base_spell_buckets_repository.h - repositories/base/base_spell_globals_repository.h - repositories/base/base_starting_items_repository.h - repositories/base/base_start_zones_repository.h - repositories/base/base_tasks_repository.h - repositories/base/base_tasksets_repository.h - repositories/base/base_task_activities_repository.h - repositories/base/base_timers_repository.h - repositories/base/base_titles_repository.h - repositories/base/base_trader_repository.h - repositories/base/base_tradeskill_recipe_repository.h - repositories/base/base_tradeskill_recipe_entries_repository.h - repositories/base/base_traps_repository.h - repositories/base/base_tributes_repository.h - repositories/base/base_tribute_levels_repository.h - repositories/base/base_veteran_reward_templates_repository.h - repositories/base/base_zone_repository.h - repositories/base/base_zone_points_repository.h + repositories/base/base_grid_repository.h + repositories/base/base_grid_entries_repository.h - # Extended Repositories - repositories/aa_ability_repository.h - repositories/aa_ranks_repository.h - repositories/aa_rank_effects_repository.h - repositories/aa_rank_prereqs_repository.h - repositories/account_repository.h - repositories/account_flags_repository.h - repositories/account_ip_repository.h - repositories/account_rewards_repository.h - repositories/adventure_details_repository.h - repositories/adventure_members_repository.h - repositories/adventure_stats_repository.h - repositories/adventure_template_repository.h - repositories/adventure_template_entry_repository.h - repositories/adventure_template_entry_flavor_repository.h - repositories/alternate_currency_repository.h - repositories/auras_repository.h - repositories/base_data_repository.h - repositories/blocked_spells_repository.h - repositories/bugs_repository.h - repositories/bug_reports_repository.h - repositories/buyer_repository.h - repositories/character_activities_repository.h - repositories/character_alternate_abilities_repository.h - repositories/character_alt_currency_repository.h - repositories/character_auras_repository.h - repositories/character_bandolier_repository.h - repositories/character_bind_repository.h - repositories/character_buffs_repository.h - repositories/character_corpses_repository.h - repositories/character_corpse_items_repository.h - repositories/character_currency_repository.h - repositories/character_data_repository.h - repositories/character_disciplines_repository.h - repositories/character_expedition_lockouts_repository.h - repositories/character_inspect_messages_repository.h - repositories/character_instance_safereturns_repository.h - repositories/character_item_recast_repository.h - repositories/character_languages_repository.h - repositories/character_leadership_abilities_repository.h - repositories/character_material_repository.h - repositories/character_memmed_spells_repository.h - repositories/character_pet_buffs_repository.h - repositories/character_pet_info_repository.h - repositories/character_pet_inventory_repository.h - repositories/character_potionbelt_repository.h - repositories/character_skills_repository.h - repositories/character_spells_repository.h - repositories/character_task_timers_repository.h - repositories/character_tasks_repository.h - repositories/char_create_combinations_repository.h - repositories/char_create_point_allocations_repository.h - repositories/char_recipe_list_repository.h - repositories/completed_tasks_repository.h - repositories/completed_shared_tasks_repository.h - repositories/completed_shared_task_members_repository.h - repositories/completed_shared_task_activity_state_repository.h - repositories/content_flags_repository.h - repositories/damageshieldtypes_repository.h - repositories/data_buckets_repository.h - repositories/db_str_repository.h - repositories/discovered_items_repository.h - repositories/doors_repository.h - repositories/dynamic_zones_repository.h - repositories/dynamic_zone_members_repository.h - repositories/eventlog_repository.h - repositories/expeditions_repository.h - repositories/expedition_lockouts_repository.h - repositories/faction_base_data_repository.h - repositories/faction_list_repository.h - repositories/faction_list_mod_repository.h - repositories/faction_values_repository.h - repositories/fishing_repository.h - repositories/forage_repository.h - repositories/friends_repository.h - repositories/global_loot_repository.h - repositories/gm_ips_repository.h - repositories/goallists_repository.h - repositories/graveyard_repository.h - repositories/grid_repository.h - repositories/grid_entries_repository.h - repositories/ground_spawns_repository.h - repositories/group_id_repository.h - repositories/group_leaders_repository.h - repositories/guilds_repository.h - repositories/guild_members_repository.h - repositories/guild_ranks_repository.h - repositories/guild_relations_repository.h - repositories/hackers_repository.h - repositories/instance_list_repository.h - repositories/instance_list_player_repository.h - repositories/inventory_repository.h - repositories/inventory_snapshots_repository.h - repositories/ip_exemptions_repository.h - repositories/items_repository.h - repositories/item_tick_repository.h - repositories/ldon_trap_entries_repository.h - repositories/ldon_trap_templates_repository.h - repositories/level_exp_mods_repository.h - repositories/lfguild_repository.h - repositories/login_accounts_repository.h - repositories/login_api_tokens_repository.h - repositories/login_server_admins_repository.h - repositories/login_server_list_types_repository.h - repositories/login_world_servers_repository.h - repositories/logsys_categories_repository.h - repositories/lootdrop_repository.h - repositories/lootdrop_entries_repository.h - repositories/loottable_repository.h - repositories/loottable_entries_repository.h - repositories/mail_repository.h - repositories/merchantlist_repository.h - repositories/merchantlist_temp_repository.h - repositories/name_filter_repository.h - repositories/npc_emotes_repository.h - repositories/npc_faction_repository.h - repositories/npc_faction_entries_repository.h - repositories/npc_scale_global_base_repository.h - repositories/npc_spells_repository.h - repositories/npc_spells_effects_repository.h - repositories/npc_spells_effects_entries_repository.h - repositories/npc_spells_entries_repository.h - repositories/npc_types_repository.h - repositories/npc_types_tint_repository.h - repositories/object_repository.h - repositories/object_contents_repository.h - repositories/perl_event_export_settings_repository.h - repositories/petitions_repository.h - repositories/pets_repository.h - repositories/pets_equipmentset_repository.h - repositories/pets_equipmentset_entries_repository.h - repositories/player_titlesets_repository.h - repositories/proximities_repository.h - repositories/quest_globals_repository.h - repositories/raid_details_repository.h - repositories/raid_members_repository.h - repositories/reports_repository.h - repositories/respawn_times_repository.h - repositories/rule_sets_repository.h - repositories/rule_values_repository.h - repositories/saylink_repository.h - repositories/server_scheduled_events_repository.h - repositories/shared_tasks_repository.h - repositories/shared_task_activity_state_repository.h - repositories/shared_task_dynamic_zones_repository.h - repositories/shared_task_members_repository.h - repositories/skill_caps_repository.h - repositories/spawn2_repository.h - repositories/spawnentry_repository.h - repositories/spawngroup_repository.h - repositories/spawn_conditions_repository.h - repositories/spawn_condition_values_repository.h - repositories/spawn_events_repository.h - repositories/spells_new_repository.h - repositories/spell_buckets_repository.h - repositories/spell_globals_repository.h - repositories/starting_items_repository.h - repositories/start_zones_repository.h - repositories/tasks_repository.h - repositories/tasksets_repository.h - repositories/task_activities_repository.h - repositories/timers_repository.h - repositories/titles_repository.h - repositories/trader_repository.h - repositories/tradeskill_recipe_repository.h - repositories/tradeskill_recipe_entries_repository.h - repositories/traps_repository.h - repositories/tributes_repository.h - repositories/tribute_levels_repository.h - repositories/veteran_reward_templates_repository.h - repositories/zone_repository.h - repositories/zone_points_repository.h + # Base Repositories + repositories/base/base_aa_ability_repository.h + repositories/base/base_aa_ranks_repository.h + repositories/base/base_aa_rank_effects_repository.h + repositories/base/base_aa_rank_prereqs_repository.h + repositories/base/base_account_repository.h + repositories/base/base_account_flags_repository.h + repositories/base/base_account_ip_repository.h + repositories/base/base_account_rewards_repository.h + repositories/base/base_adventure_details_repository.h + repositories/base/base_adventure_members_repository.h + repositories/base/base_adventure_stats_repository.h + repositories/base/base_adventure_template_repository.h + repositories/base/base_adventure_template_entry_repository.h + repositories/base/base_adventure_template_entry_flavor_repository.h + repositories/base/base_alternate_currency_repository.h + repositories/base/base_auras_repository.h + repositories/base/base_base_data_repository.h + repositories/base/base_blocked_spells_repository.h + repositories/base/base_books_repository.h + repositories/base/base_bugs_repository.h + repositories/base/base_bug_reports_repository.h + repositories/base/base_buyer_repository.h + repositories/base/base_character_activities_repository.h + repositories/base/base_character_alternate_abilities_repository.h + repositories/base/base_character_alt_currency_repository.h + repositories/base/base_character_auras_repository.h + repositories/base/base_character_bandolier_repository.h + repositories/base/base_character_bind_repository.h + repositories/base/base_character_buffs_repository.h + repositories/base/base_character_corpses_repository.h + repositories/base/base_character_corpse_items_repository.h + repositories/base/base_character_currency_repository.h + repositories/base/base_character_data_repository.h + repositories/base/base_character_disciplines_repository.h + repositories/base/base_character_expedition_lockouts_repository.h + repositories/base/base_character_exp_modifiers_repository.h + repositories/base/base_character_inspect_messages_repository.h + repositories/base/base_character_instance_safereturns_repository.h + repositories/base/base_character_item_recast_repository.h + repositories/base/base_character_languages_repository.h + repositories/base/base_character_leadership_abilities_repository.h + repositories/base/base_character_material_repository.h + repositories/base/base_character_memmed_spells_repository.h + repositories/base/base_character_peqzone_flags_repository.h + repositories/base/base_character_pet_buffs_repository.h + repositories/base/base_character_pet_info_repository.h + repositories/base/base_character_pet_inventory_repository.h + repositories/base/base_character_potionbelt_repository.h + repositories/base/base_character_skills_repository.h + repositories/base/base_character_spells_repository.h + repositories/base/base_character_tasks_repository.h + repositories/base/base_character_task_timers_repository.h + repositories/base/base_char_create_combinations_repository.h + repositories/base/base_char_create_point_allocations_repository.h + repositories/base/base_char_recipe_list_repository.h + repositories/base/base_chatchannels_repository.h + repositories/base/base_chatchannel_reserved_names_repository.h + repositories/base/base_completed_shared_tasks_repository.h + repositories/base/base_completed_shared_task_activity_state_repository.h + repositories/base/base_completed_shared_task_members_repository.h + repositories/base/base_completed_tasks_repository.h + repositories/base/base_content_flags_repository.h + repositories/base/base_damageshieldtypes_repository.h + repositories/base/base_data_buckets_repository.h + repositories/base/base_db_str_repository.h + repositories/base/base_discord_webhooks_repository.h + repositories/base/base_discovered_items_repository.h + repositories/base/base_doors_repository.h + repositories/base/base_dynamic_zones_repository.h + repositories/base/base_dynamic_zone_members_repository.h + repositories/base/base_dynamic_zone_templates_repository.h + repositories/base/base_eventlog_repository.h + repositories/base/base_expeditions_repository.h + repositories/base/base_expedition_lockouts_repository.h + repositories/base/base_faction_association_repository.h + repositories/base/base_faction_base_data_repository.h + repositories/base/base_faction_list_repository.h + repositories/base/base_faction_list_mod_repository.h + repositories/base/base_faction_values_repository.h + repositories/base/base_fishing_repository.h + repositories/base/base_forage_repository.h + repositories/base/base_friends_repository.h + repositories/base/base_global_loot_repository.h + repositories/base/base_gm_ips_repository.h + repositories/base/base_graveyard_repository.h + repositories/base/base_ground_spawns_repository.h + repositories/base/base_group_id_repository.h + repositories/base/base_group_leaders_repository.h + repositories/base/base_guilds_repository.h + repositories/base/base_guild_ranks_repository.h + repositories/base/base_guild_relations_repository.h + repositories/base/base_hackers_repository.h + repositories/base/base_horses_repository.h + repositories/base/base_instance_list_repository.h + repositories/base/base_instance_list_player_repository.h + repositories/base/base_inventory_repository.h + repositories/base/base_inventory_snapshots_repository.h + repositories/base/base_ip_exemptions_repository.h + repositories/base/base_items_repository.h + repositories/base/base_item_tick_repository.h + repositories/base/base_ldon_trap_entries_repository.h + repositories/base/base_ldon_trap_templates_repository.h + repositories/base/base_level_exp_mods_repository.h + repositories/base/base_lfguild_repository.h + repositories/base/base_login_accounts_repository.h + repositories/base/base_login_api_tokens_repository.h + repositories/base/base_login_server_admins_repository.h + repositories/base/base_login_server_list_types_repository.h + repositories/base/base_login_world_servers_repository.h + repositories/base/base_logsys_categories_repository.h + repositories/base/base_lootdrop_repository.h + repositories/base/base_lootdrop_entries_repository.h + repositories/base/base_loottable_repository.h + repositories/base/base_loottable_entries_repository.h + repositories/base/base_mail_repository.h + repositories/base/base_merchantlist_repository.h + repositories/base/base_merchantlist_temp_repository.h + repositories/base/base_name_filter_repository.h + repositories/base/base_npc_emotes_repository.h + repositories/base/base_npc_faction_repository.h + repositories/base/base_npc_faction_entries_repository.h + repositories/base/base_npc_scale_global_base_repository.h + repositories/base/base_npc_spells_repository.h + repositories/base/base_npc_spells_effects_repository.h + repositories/base/base_npc_spells_effects_entries_repository.h + repositories/base/base_npc_spells_entries_repository.h + repositories/base/base_npc_types_repository.h + repositories/base/base_npc_types_tint_repository.h + repositories/base/base_object_repository.h + repositories/base/base_object_contents_repository.h + repositories/base/base_perl_event_export_settings_repository.h + repositories/base/base_petitions_repository.h + repositories/base/base_pets_repository.h + repositories/base/base_pets_beastlord_data_repository.h + repositories/base/base_pets_equipmentset_repository.h + repositories/base/base_pets_equipmentset_entries_repository.h + repositories/base/base_player_titlesets_repository.h + repositories/base/base_quest_globals_repository.h + repositories/base/base_raid_details_repository.h + repositories/base/base_raid_members_repository.h + repositories/base/base_reports_repository.h + repositories/base/base_respawn_times_repository.h + repositories/base/base_rule_sets_repository.h + repositories/base/base_rule_values_repository.h + repositories/base/base_saylink_repository.h + repositories/base/base_server_scheduled_events_repository.h + repositories/base/base_shared_tasks_repository.h + repositories/base/base_shared_task_activity_state_repository.h + repositories/base/base_shared_task_dynamic_zones_repository.h + repositories/base/base_shared_task_members_repository.h + repositories/base/base_skill_caps_repository.h + repositories/base/base_spawn2_repository.h + repositories/base/base_spawnentry_repository.h + repositories/base/base_spawngroup_repository.h + repositories/base/base_spawn_conditions_repository.h + repositories/base/base_spawn_condition_values_repository.h + repositories/base/base_spawn_events_repository.h + repositories/base/base_spells_new_repository.h + repositories/base/base_spell_buckets_repository.h + repositories/base/base_spell_globals_repository.h + repositories/base/base_starting_items_repository.h + repositories/base/base_start_zones_repository.h + repositories/base/base_tasks_repository.h + repositories/base/base_tasksets_repository.h + repositories/base/base_task_activities_repository.h + repositories/base/base_timers_repository.h + repositories/base/base_titles_repository.h + repositories/base/base_trader_repository.h + repositories/base/base_tradeskill_recipe_repository.h + repositories/base/base_tradeskill_recipe_entries_repository.h + repositories/base/base_traps_repository.h + repositories/base/base_tributes_repository.h + repositories/base/base_tribute_levels_repository.h + repositories/base/base_veteran_reward_templates_repository.h + repositories/base/base_zone_repository.h + repositories/base/base_zone_points_repository.h - # Non-Comformative - repositories/character_recipe_list_repository.h -) + # Extended Repositories + repositories/aa_ability_repository.h + repositories/aa_ranks_repository.h + repositories/aa_rank_effects_repository.h + repositories/aa_rank_prereqs_repository.h + repositories/account_repository.h + repositories/account_flags_repository.h + repositories/account_ip_repository.h + repositories/account_rewards_repository.h + repositories/adventure_details_repository.h + repositories/adventure_members_repository.h + repositories/adventure_stats_repository.h + repositories/adventure_template_repository.h + repositories/adventure_template_entry_repository.h + repositories/adventure_template_entry_flavor_repository.h + repositories/alternate_currency_repository.h + repositories/auras_repository.h + repositories/base_data_repository.h + repositories/blocked_spells_repository.h + repositories/books_repository.h + repositories/bugs_repository.h + repositories/bug_reports_repository.h + repositories/buyer_repository.h + repositories/character_activities_repository.h + repositories/character_alternate_abilities_repository.h + repositories/character_alt_currency_repository.h + repositories/character_auras_repository.h + repositories/character_bandolier_repository.h + repositories/character_bind_repository.h + repositories/character_buffs_repository.h + repositories/character_corpses_repository.h + repositories/character_corpse_items_repository.h + repositories/character_currency_repository.h + repositories/character_data_repository.h + repositories/character_disciplines_repository.h + repositories/character_expedition_lockouts_repository.h + repositories/character_exp_modifiers_repository.h + repositories/character_inspect_messages_repository.h + repositories/character_instance_safereturns_repository.h + repositories/character_item_recast_repository.h + repositories/character_languages_repository.h + repositories/character_leadership_abilities_repository.h + repositories/character_material_repository.h + repositories/character_memmed_spells_repository.h + repositories/character_peqzone_flags_repository.h + repositories/character_pet_buffs_repository.h + repositories/character_pet_info_repository.h + repositories/character_pet_inventory_repository.h + repositories/character_potionbelt_repository.h + repositories/character_skills_repository.h + repositories/character_spells_repository.h + repositories/character_tasks_repository.h + repositories/character_task_timers_repository.h + repositories/char_create_combinations_repository.h + repositories/char_create_point_allocations_repository.h + repositories/char_recipe_list_repository.h + repositories/chatchannels_repository.h + repositories/chatchannel_reserved_names_repository.h + repositories/completed_shared_tasks_repository.h + repositories/completed_shared_task_activity_state_repository.h + repositories/completed_shared_task_members_repository.h + repositories/completed_tasks_repository.h + repositories/content_flags_repository.h + repositories/damageshieldtypes_repository.h + repositories/data_buckets_repository.h + repositories/db_str_repository.h + repositories/discord_webhooks_repository.h + repositories/discovered_items_repository.h + repositories/doors_repository.h + repositories/dynamic_zones_repository.h + repositories/dynamic_zone_members_repository.h + repositories/dynamic_zone_templates_repository.h + repositories/eventlog_repository.h + repositories/expeditions_repository.h + repositories/expedition_lockouts_repository.h + repositories/faction_association_repository.h + repositories/faction_base_data_repository.h + repositories/faction_list_repository.h + repositories/faction_list_mod_repository.h + repositories/faction_values_repository.h + repositories/fishing_repository.h + repositories/forage_repository.h + repositories/friends_repository.h + repositories/global_loot_repository.h + repositories/gm_ips_repository.h + repositories/graveyard_repository.h + repositories/ground_spawns_repository.h + repositories/group_id_repository.h + repositories/group_leaders_repository.h + repositories/guilds_repository.h + repositories/guild_ranks_repository.h + repositories/guild_relations_repository.h + repositories/hackers_repository.h + repositories/horses_repository.h + repositories/instance_list_repository.h + repositories/instance_list_player_repository.h + repositories/inventory_repository.h + repositories/inventory_snapshots_repository.h + repositories/ip_exemptions_repository.h + repositories/items_repository.h + repositories/item_tick_repository.h + repositories/ldon_trap_entries_repository.h + repositories/ldon_trap_templates_repository.h + repositories/level_exp_mods_repository.h + repositories/lfguild_repository.h + repositories/login_accounts_repository.h + repositories/login_api_tokens_repository.h + repositories/login_server_admins_repository.h + repositories/login_server_list_types_repository.h + repositories/login_world_servers_repository.h + repositories/logsys_categories_repository.h + repositories/lootdrop_repository.h + repositories/lootdrop_entries_repository.h + repositories/loottable_repository.h + repositories/loottable_entries_repository.h + repositories/mail_repository.h + repositories/merchantlist_repository.h + repositories/merchantlist_temp_repository.h + repositories/name_filter_repository.h + repositories/npc_emotes_repository.h + repositories/npc_faction_repository.h + repositories/npc_faction_entries_repository.h + repositories/npc_scale_global_base_repository.h + repositories/npc_spells_repository.h + repositories/npc_spells_effects_repository.h + repositories/npc_spells_effects_entries_repository.h + repositories/npc_spells_entries_repository.h + repositories/npc_types_repository.h + repositories/npc_types_tint_repository.h + repositories/object_repository.h + repositories/object_contents_repository.h + repositories/perl_event_export_settings_repository.h + repositories/petitions_repository.h + repositories/pets_repository.h + repositories/pets_beastlord_data_repository.h + repositories/pets_equipmentset_repository.h + repositories/pets_equipmentset_entries_repository.h + repositories/player_titlesets_repository.h + repositories/quest_globals_repository.h + repositories/raid_details_repository.h + repositories/raid_members_repository.h + repositories/reports_repository.h + repositories/respawn_times_repository.h + repositories/rule_sets_repository.h + repositories/rule_values_repository.h + repositories/saylink_repository.h + repositories/server_scheduled_events_repository.h + repositories/shared_tasks_repository.h + repositories/shared_task_activity_state_repository.h + repositories/shared_task_dynamic_zones_repository.h + repositories/shared_task_members_repository.h + repositories/skill_caps_repository.h + repositories/spawn2_repository.h + repositories/spawnentry_repository.h + repositories/spawngroup_repository.h + repositories/spawn_conditions_repository.h + repositories/spawn_condition_values_repository.h + repositories/spawn_events_repository.h + repositories/spells_new_repository.h + repositories/spell_buckets_repository.h + repositories/spell_globals_repository.h + repositories/starting_items_repository.h + repositories/start_zones_repository.h + repositories/tasks_repository.h + repositories/tasksets_repository.h + repositories/task_activities_repository.h + repositories/timers_repository.h + repositories/titles_repository.h + repositories/trader_repository.h + repositories/tradeskill_recipe_repository.h + repositories/tradeskill_recipe_entries_repository.h + repositories/traps_repository.h + repositories/tributes_repository.h + repositories/tribute_levels_repository.h + repositories/veteran_reward_templates_repository.h + repositories/zone_repository.h + repositories/zone_points_repository.h + + ) SET(common_headers - additive_lagged_fibonacci_engine.h - any.h - base_packet.h - base_data.h - bodytypes.h - classes.h - compression.h - condition.h - content/world_content_service.h - crash.h - crc16.h - crc32.h - cli/argh.h - cli/eqemu_command_handler.h - cli/terminal_color.hpp - cron/croncpp.h - database/database_dump_service.h - data_verification.h - database.h - database_schema.h - dbcore.h - deity.h - dynamic_zone_base.h - emu_constants.h - emu_limits.h - emu_opcodes.h - emu_oplist.h - emu_versions.h - eq_constants.h - eq_packet_structs.h - eqdb.h - eqdb_res.h - eqemu_exception.h - eqemu_config.h - eqemu_config_elements.h - eqemu_logsys.h - eqemu_logsys_log_aliases.h - eq_limits.h - eq_packet.h - eq_stream_ident.h - eq_stream_intf.h - eq_stream_locator.h - eq_stream_proxy.h - eqtime.h - errmsg.h - event_sub.h - expedition_lockout_timer.h - extprofile.h - faction.h - file_util.h - features.h - fixed_memory_hash_set.h - fixed_memory_variable_hash_set.h - global_define.h - guild_base.h - guilds.h - http/httplib.h - http/uri.h - inventory_profile.h - inventory_slot.h - ipc_mutex.h - ip_util.h - item_data.h - item_fieldlist.h - item_instance.h - json_config.h - languages.h - light_source.h - linked_list.h - loottable.h - mail_oplist.h - md5.h - memory_buffer.h - memory_mapped_file.h - misc.h - misc_functions.h - mutex.h - mysql_request_result.h - mysql_request_row.h - op_codes.h - opcode_dispatch.h - opcodemgr.h - packet_dump.h - packet_dump_file.h - packet_functions.h - platform.h - proc_launcher.h - profanity_manager.h - profiler.h - ptimer.h - queue.h - races.h - random.h - rdtsc.h - rulesys.h - ruletypes.h - say_link.h - seperator.h - serialize_buffer.h - server_event_scheduler.h - serverinfo.h - servertalk.h - shared_tasks.h - shareddb.h - skills.h - spdat.h - string_util.h - struct_strategy.h - tasks.h - textures.h - timer.h - types.h - unix.h - useperl.h - version.h - zone_numbers.h - event/event_loop.h - event/task.h - event/timer.h - json/json.h - json/json-forwards.h - net/console_server.h - net/console_server_connection.h - net/crc32.h - net/daybreak_connection.h - net/daybreak_structs.h - net/dns.h - net/endian.h - net/eqstream.h - net/packet.h - net/servertalk_client_connection.h - net/servertalk_legacy_client_connection.h - net/servertalk_common.h - net/servertalk_server.h - net/servertalk_server_connection.h - net/tcp_connection.h - net/tcp_server.h - net/websocket_server.h - net/websocket_server_connection.h - patches/patches.h - patches/sod.h - patches/sod_limits.h - patches/sod_ops.h - patches/sod_structs.h - patches/sof.h - patches/sof_limits.h - patches/sof_ops.h - patches/sof_structs.h - patches/ss_declare.h - patches/ss_define.h - patches/ss_register.h - patches/rof.h - patches/rof_limits.h - patches/rof_ops.h - patches/rof_structs.h - patches/rof2.h - patches/rof2_limits.h - patches/rof2_ops.h - patches/rof2_structs.h - patches/titanium.h - patches/titanium_limits.h - patches/titanium_ops.h - patches/titanium_structs.h - patches/uf.h - patches/uf_limits.h - patches/uf_ops.h - patches/uf_structs.h - StackWalker/StackWalker.h - util/memory_stream.h - util/directory.h - util/uuid.h -) + additive_lagged_fibonacci_engine.h + base_packet.h + base_data.h + bodytypes.h + classes.h + compression.h + condition.h + content/world_content_service.h + crash.h + crc16.h + crc32.h + cli/argh.h + cli/eqemu_command_handler.h + cli/terminal_color.hpp + cron/croncpp.h + database/database_dump_service.h + data_verification.h + database.h + database_schema.h + dbcore.h + deity.h + discord/discord.h + discord_manager.h + dynamic_zone_base.h + emu_constants.h + emu_limits.h + emu_opcodes.h + emu_oplist.h + emu_versions.h + eq_constants.h + eq_packet_structs.h + eqdb.h + eqdb_res.h + eqemu_exception.h + eqemu_config.h + eqemu_config_elements.h + eqemu_logsys.h + eqemu_logsys_log_aliases.h + eq_limits.h + eq_packet.h + eq_stream_ident.h + eq_stream_intf.h + eq_stream_locator.h + eq_stream_proxy.h + eqtime.h + errmsg.h + event_sub.h + expedition_lockout_timer.h + extprofile.h + faction.h + file.h + features.h + fixed_memory_hash_set.h + fixed_memory_variable_hash_set.h + global_define.h + guild_base.h + guilds.h + http/httplib.h + http/uri.h + inventory_profile.h + inventory_slot.h + ipc_mutex.h + ip_util.h + item_data.h + item_fieldlist.h + item_instance.h + json_config.h + languages.h + light_source.h + linked_list.h + loottable.h + mail_oplist.h + md5.h + memory_buffer.h + memory_mapped_file.h + misc.h + misc_functions.h + mutex.h + mysql_request_result.h + mysql_request_row.h + op_codes.h + opcode_dispatch.h + opcodemgr.h + packet_dump.h + packet_dump_file.h + packet_functions.h + path_manager.cpp + platform.h + process/process.h + proc_launcher.h + profanity_manager.h + profiler.h + ptimer.h + queue.h + races.h + random.h + rdtsc.h + rulesys.h + ruletypes.h + say_link.h + seperator.h + serialize_buffer.h + server_event_scheduler.h + serverinfo.h + servertalk.h + shared_tasks.h + shareddb.h + skills.h + spdat.h + strings.h + struct_strategy.h + tasks.h + textures.h + timer.h + types.h + unix.h + useperl.h + version.h + zone_numbers.h + zone_store.h + event/event_loop.h + event/task.h + event/timer.h + json/json.h + json/json-forwards.h + net/console_server.h + net/console_server_connection.h + net/crc32.h + net/daybreak_connection.h + net/daybreak_structs.h + net/dns.h + net/endian.h + net/eqstream.h + net/packet.h + net/servertalk_client_connection.h + net/servertalk_legacy_client_connection.h + net/servertalk_common.h + net/servertalk_server.h + net/servertalk_server_connection.h + net/tcp_connection.h + net/tcp_server.h + net/websocket_server.h + net/websocket_server_connection.h + patches/patches.h + patches/sod.h + patches/sod_limits.h + patches/sod_ops.h + patches/sod_structs.h + patches/sof.h + patches/sof_limits.h + patches/sof_ops.h + patches/sof_structs.h + patches/ss_declare.h + patches/ss_define.h + patches/ss_register.h + patches/rof.h + patches/rof_limits.h + patches/rof_ops.h + patches/rof_structs.h + patches/rof2.h + patches/rof2_limits.h + patches/rof2_ops.h + patches/rof2_structs.h + patches/titanium.h + patches/titanium_limits.h + patches/titanium_ops.h + patches/titanium_structs.h + patches/uf.h + patches/uf_limits.h + patches/uf_ops.h + patches/uf_structs.h + termcolor/rang.hpp + stacktrace/backward.hpp + StackWalker/StackWalker.h + util/memory_stream.h + util/directory.h + util/uuid.h + ) SOURCE_GROUP(Event FILES - event/event_loop.h - event/timer.h - event/task.h -) + event/event_loop.h + event/timer.h + event/task.h + ) SOURCE_GROUP(Json FILES - json/json.h - json/jsoncpp.cpp - json/json-forwards.h -) + json/json.h + json/jsoncpp.cpp + json/json-forwards.h + ) SOURCE_GROUP(Net FILES - net/console_server.cpp - net/console_server.h - net/console_server_connection.cpp - net/console_server_connection.h - net/crc32.cpp - net/crc32.h - net/daybreak_connection.cpp - net/daybreak_connection.h - net/daybreak_structs.h - net/dns.h - net/endian.h - net/eqmq.cpp - net/eqmq.h - net/eqstream.cpp - net/eqstream.h - net/packet.cpp - net/packet.h - net/servertalk_client_connection.cpp - net/servertalk_client_connection.h - net/servertalk_legacy_client_connection.cpp - net/servertalk_legacy_client_connection.h - net/servertalk_common.h - net/servertalk_server.cpp - net/servertalk_server.h - net/servertalk_server_connection.cpp - net/servertalk_server_connection.h - net/tcp_connection.cpp - net/tcp_connection.h - net/tcp_server.cpp - net/tcp_server.h - net/websocket_server.cpp - net/websocket_server.h - net/websocket_server_connection.cpp - net/websocket_server_connection.h -) + net/console_server.cpp + net/console_server.h + net/console_server_connection.cpp + net/console_server_connection.h + net/crc32.cpp + net/crc32.h + net/daybreak_connection.cpp + net/daybreak_connection.h + net/daybreak_structs.h + net/dns.h + net/endian.h + net/eqmq.cpp + net/eqmq.h + net/eqstream.cpp + net/eqstream.h + net/packet.cpp + net/packet.h + net/servertalk_client_connection.cpp + net/servertalk_client_connection.h + net/servertalk_legacy_client_connection.cpp + net/servertalk_legacy_client_connection.h + net/servertalk_common.h + net/servertalk_server.cpp + net/servertalk_server.h + net/servertalk_server_connection.cpp + net/servertalk_server_connection.h + net/tcp_connection.cpp + net/tcp_connection.h + net/tcp_server.cpp + net/tcp_server.h + net/websocket_server.cpp + net/websocket_server.h + net/websocket_server_connection.cpp + net/websocket_server_connection.h + ) SOURCE_GROUP(Patches FILES - patches/patches.h - patches/sod.h - patches/sod_limits.h - patches/sod_ops.h - patches/sod_structs.h - patches/sof.h - patches/sof_limits.h - patches/sof_ops.h - patches/sof_structs.h - patches/ss_declare.h - patches/ss_define.h - patches/ss_register.h - patches/rof.h - patches/rof_limits.h - patches/rof_ops.h - patches/rof_structs.h - patches/rof2.h - patches/rof2_limits.h - patches/rof2_ops.h - patches/rof2_structs.h - patches/titanium.h - patches/titanium_limits.h - patches/titanium_ops.h - patches/titanium_structs.h - patches/uf.h - patches/uf_limits.h - patches/uf_ops.h - patches/uf_structs.h - patches/patches.cpp - patches/sod.cpp - patches/sod_limits.cpp - patches/sof.cpp - patches/sof_limits.cpp - patches/rof.cpp - patches/rof_limits.cpp - patches/rof2.cpp - patches/rof2_limits.cpp - patches/titanium.cpp - patches/titanium_limits.cpp - patches/uf.cpp - patches/uf_limits.cpp -) + patches/patches.h + patches/sod.h + patches/sod_limits.h + patches/sod_ops.h + patches/sod_structs.h + patches/sof.h + patches/sof_limits.h + patches/sof_ops.h + patches/sof_structs.h + patches/ss_declare.h + patches/ss_define.h + patches/ss_register.h + patches/rof.h + patches/rof_limits.h + patches/rof_ops.h + patches/rof_structs.h + patches/rof2.h + patches/rof2_limits.h + patches/rof2_ops.h + patches/rof2_structs.h + patches/titanium.h + patches/titanium_limits.h + patches/titanium_ops.h + patches/titanium_structs.h + patches/uf.h + patches/uf_limits.h + patches/uf_ops.h + patches/uf_structs.h + patches/patches.cpp + patches/sod.cpp + patches/sod_limits.cpp + patches/sof.cpp + patches/sof_limits.cpp + patches/rof.cpp + patches/rof_limits.cpp + patches/rof2.cpp + patches/rof2_limits.cpp + patches/titanium.cpp + patches/titanium_limits.cpp + patches/uf.cpp + patches/uf_limits.cpp + ) SOURCE_GROUP(StackWalker FILES - StackWalker/StackWalker.h - StackWalker/StackWalker.cpp -) + StackWalker/StackWalker.h + StackWalker/StackWalker.cpp + ) SOURCE_GROUP(Util FILES - util/memory_stream.h - util/directory.cpp - util/directory.h - util/uuid.cpp - util/uuid.h -) + util/memory_stream.h + util/directory.cpp + util/directory.h + util/uuid.cpp + util/uuid.h + ) INCLUDE_DIRECTORIES(Patches SocketLib StackWalker) ADD_LIBRARY(common ${common_sources} ${common_headers} ${repositories}) -IF(UNIX) - SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) - SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) -ENDIF(UNIX) +IF (UNIX) + SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) + SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) +ENDIF (UNIX) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/common/any.h b/common/any.h deleted file mode 100644 index 1ec59cdb4..000000000 --- a/common/any.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Boost Software License - Version 1.0 - August 17th, 2003 - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -// EQ::Any is a modified version of Boost::Any and as such retains the Boost licensing. - -#ifndef EQEMU_COMMON_ANY_H -#define EQEMU_COMMON_ANY_H - -#include -#include - -namespace EQ -{ - class Any - { - public: - Any() - : content(nullptr) - { - } - - template - Any(const ValueType &value) - : content(new Holder(value)) - { - } - - Any(const Any &other) - : content(other.content ? other.content->clone() : 0) - { - } - - ~Any() - { - if(content) - delete content; - } - - Any& swap(Any &rhs) - { - std::swap(content, rhs.content); - return *this; - } - - template - Any& operator=(const ValueType &rhs) - { - Any(rhs).swap(*this); - return *this; - } - - Any& operator=(Any rhs) - { - rhs.swap(*this); - return *this; - } - - bool empty() const - { - return !content; - } - - const std::type_info& type() const - { - return content ? content->type() : typeid(void); - } - - class Placeholder - { - public: - virtual ~Placeholder() - { - } - - virtual const std::type_info& type() const = 0; - virtual Placeholder* clone() const = 0; - }; - - - template - class Holder : public Placeholder - { - public: - Holder(const ValueType &value) - : held(value) - { - } - - virtual const std::type_info& type() const - { - return typeid(ValueType); - } - - virtual Placeholder* clone() const - { - return new Holder(held); - } - - ValueType held; - - private: - Holder& operator=(const Holder&); - }; - - private: - template - friend ValueType* any_cast(Any*); - - template - friend ValueType* unsafe_any_cast(Any*); - - Placeholder* content; - }; - - class bad_any_cast : public std::bad_cast - { - public: - virtual const char * what() const throw() - { - return "DBI::bad_any_cast: failed conversion using DBI::any_cast"; - } - }; - - template - ValueType* any_cast(Any* operand) - { - return operand && - operand->type() == typeid(ValueType) ? &static_cast*>(operand->content)->held : nullptr; - } - - template - inline const ValueType* any_cast(const Any* operand) - { - return any_cast(const_cast(operand)); - } - - template - ValueType any_cast(Any& operand) - { - typedef typename std::remove_reference::type nonref; - nonref* result = any_cast(&operand); - if(!result) - throw bad_any_cast(); - return *result; - } - - template - inline ValueType any_cast(const Any& operand) - { - typedef typename std::remove_reference::type nonref; - return any_cast(const_cast(operand)); - } - - template - inline ValueType* unsafe_any_cast(Any* operand) - { - return &static_cast*>(operand->content)->held; - } - - template - inline const ValueType* unsafe_any_cast(const Any* operand) - { - return unsafe_any_cast(const_cast(operand)); - } -} - -#endif diff --git a/common/classes.cpp b/common/classes.cpp index b9445443f..886412791 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -380,12 +380,12 @@ const char *GetClassIDName(uint8 class_id, uint8 level) return "Merchant"; case DISCORD_MERCHANT: return "Discord Merchant"; - case ADVENTURERECRUITER: + case ADVENTURE_RECRUITER: return "Adventure Recruiter"; - case ADVENTUREMERCHANT: + case ADVENTURE_MERCHANT: return "Adventure Merchant"; - case CORPSE_CLASS: - return "Corpse Class"; + case LDON_TREASURE: + return "LDoN Treasure"; case TRIBUTE_MASTER: return "Tribute Master"; case GUILD_TRIBUTE_MASTER: @@ -400,7 +400,7 @@ const char *GetClassIDName(uint8 class_id, uint8 level) return "Fellowship Master"; case ALT_CURRENCY_MERCHANT: return "Alternate Currency Merchant"; - case MERCERNARY_MASTER: + case MERCENARY_MASTER: return "Mercenary Liaison"; default: return "Unknown"; diff --git a/common/classes.h b/common/classes.h index a35014d94..15481a613 100644 --- a/common/classes.h +++ b/common/classes.h @@ -20,6 +20,7 @@ #include "../common/types.h" +#define NO_CLASS 0 #define WARRIOR 1 #define CLERIC 2 #define PALADIN 3 @@ -55,10 +56,9 @@ #define BANKER 40 #define MERCHANT 41 #define DISCORD_MERCHANT 59 -#define ADVENTURERECRUITER 60 -#define ADVENTUREMERCHANT 61 -#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs -#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far.. +#define ADVENTURE_RECRUITER 60 +#define ADVENTURE_MERCHANT 61 +#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva #define TRIBUTE_MASTER 63 #define GUILD_TRIBUTE_MASTER 64 // not sure #define GUILD_BANKER 66 @@ -66,7 +66,7 @@ #define DARK_REIGN_MERCHANT 68 #define FELLOWSHIP_MASTER 69 #define ALT_CURRENCY_MERCHANT 70 -#define MERCERNARY_MASTER 71 +#define MERCENARY_MASTER 71 // player class values diff --git a/common/content/world_content_service.cpp b/common/content/world_content_service.cpp index 381bf5dc1..27be467cf 100644 --- a/common/content/world_content_service.cpp +++ b/common/content/world_content_service.cpp @@ -158,25 +158,25 @@ bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag) bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f) { // if we're not set to (-1 All) then fail when we aren't within minimum expansion - if (f.min_expansion > Expansion::EXPANSION_ALL && current_expansion < f.min_expansion) { + if (f.min_expansion > Expansion::EXPANSION_ALL && current_expansion < f.min_expansion && current_expansion != -1) { return false; } // if we're not set to (-1 All) then fail when we aren't within max expansion - if (f.max_expansion > Expansion::EXPANSION_ALL && current_expansion > f.max_expansion) { + if (f.max_expansion > Expansion::EXPANSION_ALL && current_expansion > f.max_expansion && current_expansion != -1) { return false; } // if we don't have any enabled flag in enabled flags, we fail - for (const auto& flag: SplitString(f.content_flags)) { - if (!contains(GetContentFlagsEnabled(), flag)) { + for (const auto& flag: Strings::Split(f.content_flags)) { + if (!Strings::Contains(GetContentFlagsEnabled(), flag)) { return false; } } // if we don't have any disabled flag in disabled flags, we fail - for (const auto& flag: SplitString(f.content_flags_disabled)) { - if (!contains(GetContentFlagsDisabled(), flag)) { + for (const auto& flag: Strings::Split(f.content_flags_disabled)) { + if (!Strings::Contains(GetContentFlagsDisabled(), flag)) { return false; } } diff --git a/common/crash.cpp b/common/crash.cpp index cecb52f02..8fc7323e8 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -1,6 +1,15 @@ #include "global_define.h" #include "eqemu_logsys.h" #include "crash.h" +#include "strings.h" +#include "process/process.h" + +#include + +#if WINDOWS +#define popen _popen +#endif + #if defined(_WINDOWS) && defined(CRASH_LOGGING) #include "StackWalker.h" @@ -125,9 +134,27 @@ void set_exception_handler() { void print_trace() { - auto uid = geteuid(); + bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU"); + if (!does_gdb_exist) { + LogCrash( + "[Error] GDB is not installed, if you want crash dumps on Linux to work properly you will need GDB installed" + ); + std::exit(1); + } - std::string temp_output_file = "/tmp/dump-output"; + auto uid = geteuid(); + std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10)); + + // check for passwordless sudo if not root + if (uid != 0) { + bool sudo_password_required = Strings::Contains(Process::execute("sudo -n true"), "a password is required"); + if (sudo_password_required) { + LogCrash( + "[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root." + ); + std::exit(1); + } + } char pid_buf[30]; sprintf(pid_buf, "%d", getpid()); @@ -136,7 +163,6 @@ void print_trace() int child_pid = fork(); if (!child_pid) { int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - dup2(fd, 1); // redirect output to stderr fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf); if (uid == 0) { @@ -151,7 +177,7 @@ void print_trace() abort(); /* If gdb failed to start */ } else { - waitpid(child_pid, NULL, 0); + waitpid(child_pid, nullptr, 0); } std::ifstream input(temp_output_file); diff --git a/common/database.cpp b/common/database.cpp index a065b5dbe..a93cb7669 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -45,11 +45,14 @@ #include "database.h" #include "eq_packet_structs.h" #include "extprofile.h" -#include "string_util.h" +#include "strings.h" #include "database_schema.h" #include "http/httplib.h" #include "http/uri.h" +#include "repositories/zone_repository.h" +#include "zone_store.h" + extern Client client; Database::Database () { @@ -68,11 +71,11 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c uint32 errnum= 0; char errbuf[MYSQL_ERRMSG_SIZE]; if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { - LogError("[MySQL] Connection [{}] Failed to connect to database: Error [{}]", connection_label, errbuf); + LogError("Connection [{}] Failed to connect to database Error [{}]", connection_label, errbuf); return false; } else { - LogInfo("[MySQL] Connection [{}] database [{}] at [{}]:[{}]", connection_label, database, host,port); + LogInfo("Connected to database [{}] [{}] @ [{}:{}]", connection_label, database, host,port); return true; } } @@ -105,7 +108,7 @@ uint32 Database::CheckLogin(const char* name, const char* password, const char * "SELECT id, status FROM account WHERE `name` = '{}' AND ls_id = '{}' AND password is NOT NULL " "AND length(password) > 0 AND (password = '{}' OR password = MD5('{}'))", temporary_username, - EscapeString(loginserver), + Strings::Escape(loginserver), temporary_password, temporary_password ); @@ -146,8 +149,8 @@ bool Database::CheckBannedIPs(std::string login_ip) bool Database::AddBannedIP(std::string banned_ip, std::string notes) { auto query = fmt::format( "INSERT into banned_ips SET ip_address = '{}', notes = '{}'", - EscapeString(banned_ip), - EscapeString(notes) + Strings::Escape(banned_ip), + Strings::Escape(notes) ); auto results = QueryDatabase(query); @@ -278,7 +281,7 @@ bool Database::DeleteAccount(const char* name, const char *loginserver) { } bool Database::SetLocalPassword(uint32 accid, const char* password) { - std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", EscapeString(password).c_str(), accid); + std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", Strings::Escape(password).c_str(), accid); auto results = QueryDatabase(query); @@ -373,9 +376,10 @@ bool Database::ReserveName(uint32 account_id, char* name) { * @param character_name * @return */ -bool Database::DeleteCharacter(char *character_name) { +bool Database::DeleteCharacter(char *character_name) +{ uint32 character_id = 0; - if(!character_name || !strlen(character_name)) { + if (!character_name || !strlen(character_name)) { LogInfo("DeleteCharacter: request to delete without a name (empty char slot)"); return false; } @@ -387,45 +391,60 @@ bool Database::DeleteCharacter(char *character_name) { } if (character_id <= 0) { - LogError("DeleteCharacter | Invalid Character ID [{}]", character_name); + LogError("Invalid Character ID [{}]", character_name); return false; } std::string delete_type = "hard-deleted"; if (RuleB(Character, SoftDeletes)) { - delete_type = "soft-deleted"; - std::string query = fmt::format( + delete_type = "soft-deleted"; + query = fmt::format( SQL( UPDATE - character_data + character_data SET - name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64), + name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64), deleted_at = NOW() - WHERE - id = '{}' + WHERE + id = '{}' ), character_id ); QueryDatabase(query); + if (RuleB(Bots, Enabled)) { + query = fmt::format( + SQL( + UPDATE + bot_data + SET + name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64) + WHERE + owner_id = '{}' + ), + character_id + ); + QueryDatabase(query); + LogInfo( + "[DeleteCharacter] character_name [{}] ({}) bots are being [{}]", + character_name, + character_id, + delete_type + ); + } + return true; } - LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type); - - for (const auto& iter : DatabaseSchema::GetCharacterTables()) { + for (const auto &iter: DatabaseSchema::GetCharacterTables()) { std::string table_name = iter.first; std::string character_id_column_name = iter.second; QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id)); } -#ifdef BOTS - query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById() - QueryDatabase(query); -#endif - + LogInfo("character_name [{}] ({}) is being [{}]", character_name, character_id, delete_type); return true; } @@ -617,8 +636,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe ")", character_id, // " id, " account_id, // " account_id, " - EscapeString(pp->name).c_str(), // " `name`, " - EscapeString(pp->last_name).c_str(), // " last_name, " + Strings::Escape(pp->name).c_str(), // " `name`, " + Strings::Escape(pp->last_name).c_str(), // " last_name, " pp->gender, // " gender, " pp->race, // " race, " pp->class_, // " class, " @@ -642,8 +661,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe pp->ability_number, // " ability_number, " pp->ability_time_minutes, // " ability_time_minutes, " pp->ability_time_hours, // " ability_time_hours, " - EscapeString(pp->title).c_str(), // " title, " - EscapeString(pp->suffix).c_str(), // " suffix, " + Strings::Escape(pp->title).c_str(), // " title, " + Strings::Escape(pp->suffix).c_str(), // " suffix, " pp->exp, // " exp, " pp->points, // " points, " pp->mana, // " mana, " @@ -779,7 +798,7 @@ uint32 Database::GetCharacterID(const char *name) { Zero will also be returned if there is a database error. */ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { - std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", EscapeString(charname).c_str()); + std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", Strings::Escape(charname).c_str()); auto results = QueryDatabase(query); @@ -823,8 +842,8 @@ uint32 Database::GetAccountIDByName(std::string account_name, std::string logins auto query = fmt::format( "SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '{}' AND `ls_id` = '{}' LIMIT 1", - EscapeString(account_name), - EscapeString(loginserver) + Strings::Escape(account_name), + Strings::Escape(loginserver) ); auto results = QueryDatabase(query); @@ -956,6 +975,8 @@ bool Database::LoadVariables() { varcache.Add(key, value); } + LogInfo("Loaded [{}] variable(s)", Strings::Commify(std::to_string(results.RowCount()))); + return true; } @@ -980,8 +1001,8 @@ bool Database::GetVariable(std::string varname, std::string &varvalue) bool Database::SetVariable(const std::string varname, const std::string &varvalue) { - std::string escaped_name = EscapeString(varname); - std::string escaped_value = EscapeString(varvalue); + std::string escaped_name = Strings::Escape(varname); + std::string escaped_value = Strings::Escape(varvalue); std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str()); auto results = QueryDatabase(query); @@ -1016,112 +1037,6 @@ void Database::SetAccountCRCField(uint32 account_id, std::string field_name, uin ); } -// Get zone starting points from DB -bool Database::GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x, float* safe_y, float* safe_z, float* safe_heading, int16* min_status, uint8* min_level, char *flag_needed) { - - if (zone_short_name == nullptr) - return false; - - std::string query = fmt::format( - SQL( - SELECT - `safe_x`, `safe_y`, `safe_z`, `safe_heading`, `min_status`, `min_level`, `flag_needed` - FROM - zone - WHERE - `short_name` = '{}' - AND - (`version` = {} OR `version` = 0) - ORDER BY `version` DESC - ), zone_short_name, instance_version - ); - auto results = QueryDatabase(query); - - if (!results.Success()) - return false; - - if (results.RowCount() == 0) - return false; - - auto row = results.begin(); - - if (safe_x != nullptr) - *safe_x = atof(row[0]); - - if (safe_y != nullptr) - *safe_y = atof(row[1]); - - if (safe_z != nullptr) - *safe_z = atof(row[2]); - - if (safe_heading != nullptr) - *safe_heading = atof(row[3]); - - if (min_status != nullptr) - *min_status = atoi(row[4]); - - if (min_level != nullptr) - *min_level = atoi(row[5]); - - if (flag_needed != nullptr) - strcpy(flag_needed, row[6]); - - return true; -} - -bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) { - - std::string query = StringFormat("SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name); - auto results = QueryDatabase(query); - - if (!results.Success()) { - return false; - } - - if (results.RowCount() == 0) - return false; - - auto row = results.begin(); - - if (long_name != nullptr) - *long_name = strcpy(new char[strlen(row[0])+1], row[0]); - - if (file_name != nullptr) { - if (row[1] == nullptr) - strcpy(file_name, short_name); - else - strcpy(file_name, row[1]); - } - - if (safe_x != nullptr) - *safe_x = atof(row[2]); - if (safe_y != nullptr) - *safe_y = atof(row[3]); - if (safe_z != nullptr) - *safe_z = atof(row[4]); - if (graveyard_id != nullptr) - *graveyard_id = atoi(row[5]); - if (maxclients != nullptr) - *maxclients = atoi(row[6]); - - return true; -} - -uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { - - std::string query = StringFormat("SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { std::string query = StringFormat("SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id); @@ -1151,107 +1066,73 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon } uint8 Database::GetPEQZone(uint32 zone_id, uint32 version){ - std::string query = fmt::format( - "SELECT peqzone FROM zone WHERE zoneidnumber = {} AND (version = {} OR version = 0) ORDER BY version DESC LIMIT 1", - zone_id, - version - ); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - return 0; - } + auto z = GetZoneVersionWithFallback(zone_id, version); - auto row = results.begin(); - - return static_cast(std::stoi(row[0])); + return z ? z->peqzone : 0; } -bool Database::CheckNameFilter(const char* name, bool surname) +bool Database::CheckNameFilter(std::string name, bool surname) { - std::string str_name = name; + name = Strings::ToLower(name); // the minimum 4 is enforced by the client too - if (!name || strlen(name) < 4) - { + if (name.empty() || name.size() < 4) { return false; } // Given name length is enforced by the client too - if (!surname && strlen(name) > 15) - { + if (!surname && name.size() > 15) { return false; } - for (size_t i = 0; i < str_name.size(); i++) - { - if(!isalpha(str_name[i])) - { + for (size_t i = 0; i < name.size(); i++) { + if (!isalpha(name[i])) { return false; } } - for(size_t x = 0; x < str_name.size(); ++x) - { - str_name[x] = tolower(str_name[x]); - } - char c = '\0'; uint8 num_c = 0; - for(size_t x = 0; x < str_name.size(); ++x) - { - if(str_name[x] == c) - { + for (size_t x = 0; x < name.size(); ++x) { + if (name[x] == c) { num_c++; - } - else - { + } else { num_c = 1; - c = str_name[x]; + c = name[x]; } - if(num_c > 2) - { + + if (num_c > 2) { return false; } } - - std::string query("SELECT name FROM name_filter"); + std::string query = "SELECT name FROM name_filter"; auto results = QueryDatabase(query); - - if (!results.Success()) - { - // false through to true? shouldn't it be falls through to false? + if (!results.Success()) { return true; } - for (auto row = results.begin();row != results.end();++row) - { - std::string current_row = row[0]; - - for(size_t x = 0; x < current_row.size(); ++x) - current_row[x] = tolower(current_row[x]); - - if(str_name.find(current_row) != std::string::npos) + for (auto row : results) { + std::string current_row = Strings::ToLower(row[0]); + if (name.find(current_row) != std::string::npos) { return false; + } } return true; } -bool Database::AddToNameFilter(const char* name) { - - std::string query = StringFormat("INSERT INTO name_filter (name) values ('%s')", name); +bool Database::AddToNameFilter(std::string name) { + auto query = fmt::format( + "INSERT INTO name_filter (name) values ('{}')", + name + ); auto results = QueryDatabase(query); - - if (!results.Success()) - { + if (!results.Success() || !results.RowsAffected()) { return false; } - if (results.RowsAffected() == 0) - return false; - return true; } @@ -1339,16 +1220,16 @@ bool Database::UpdateName(const char* oldname, const char* newname) { } // If the name is used or an error occurs, it returns false, otherwise it returns true -bool Database::CheckUsedName(const char* name) { - std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); +bool Database::CheckUsedName(std::string name) { + auto query = fmt::format( + "SELECT `id` FROM `character_data` WHERE `name` = '{}'", + name + ); auto results = QueryDatabase(query); - if (!results.Success()) { + if (!results.Success() || results.RowCount()) { return false; } - if (results.RowCount() > 0) - return false; - return true; } @@ -1506,41 +1387,25 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 return base_cap; } -uint32 Database::GetCharacterInfo( - const char *iName, - uint32 *oAccID, - uint32 *oZoneID, - uint32 *oInstanceID, - float *oX, - float *oY, - float *oZ -) +uint32 Database::GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id) { - std::string query = StringFormat( - "SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'", - EscapeString(iName).c_str() + auto query = fmt::format( + "SELECT `id`, `account_id`, `zone_id`, `zone_instance` FROM `character_data` WHERE `name` = '{}'", + Strings::Escape(character_name) ); auto results = QueryDatabase(query); - - if (!results.Success()) { + if (!results.Success() || !results.RowCount()) { return 0; } - if (results.RowCount() != 1) { - return 0; - } + auto row = results.begin(); + auto character_id = std::stoul(row[0]); + *account_id = std::stoul(row[1]); + *zone_id = std::stoul(row[2]); + *instance_id = std::stoul(row[3]); - auto row = results.begin(); - uint32 charid = atoi(row[0]); - if (oAccID) { *oAccID = atoi(row[1]); } - if (oZoneID) { *oZoneID = atoi(row[2]); } - if (oInstanceID) { *oInstanceID = atoi(row[3]); } - if (oX) { *oX = atof(row[4]); } - if (oY) { *oY = atof(row[5]); } - if (oZ) { *oZ = atof(row[6]); } - - return charid; + return character_id; } bool Database::UpdateLiveChar(char* charname, uint32 account_id) { @@ -1599,7 +1464,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines auto escape_str = new char[lines.size() * 2 + 1]; DoEscapeString(escape_str, lines.c_str(), lines.size()); - std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str); + std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", Strings::Escape(who).c_str(), Strings::Escape(against).c_str(), escape_str); QueryDatabase(query); safe_delete_array(escape_str); } @@ -1664,33 +1529,40 @@ uint32 Database::GetGroupID(const char* name){ return atoi(row[0]); } -/* Is this really getting used properly... A half implementation ? Akkadius */ -char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) { - strcpy(leaderbuf, ""); +std::string Database::GetGroupLeaderForLogin(std::string character_name) { uint32 group_id = 0; - std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name` = '%s'", name); + auto query = fmt::format( + "SELECT `groupid` FROM `group_id` WHERE `name` = '{}'", + character_name + ); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) - if (row[0]) - group_id = atoi(row[0]); + if (results.Success() && results.RowCount()) { + auto row = results.begin(); + group_id = std::stoul(row[0]); + } - if (group_id == 0) - return leaderbuf; + if (!group_id) { + return std::string(); + } - query = StringFormat("SELECT `leadername` FROM `group_leaders` WHERE `gid` = '%u' LIMIT 1", group_id); + query = fmt::format( + "SELECT `leadername` FROM `group_leaders` WHERE `gid` = {} LIMIT 1", + group_id + ); results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) - if (row[0]) - strcpy(leaderbuf, row[0]); + if (results.Success() && results.RowCount()) { + auto row = results.begin(); + return row[0]; + } - return leaderbuf; + return std::string(); } void Database::SetGroupLeaderName(uint32 gid, const char* name) { - std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", EscapeString(name).c_str(), gid); + std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", Strings::Escape(name).c_str(), gid); auto result = QueryDatabase(query); if(result.RowsAffected() != 0) { @@ -1698,7 +1570,7 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) { } query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')", - gid, EscapeString(name).c_str()); + gid, Strings::Escape(name).c_str()); result = QueryDatabase(query); if(!result.Success()) { @@ -2281,28 +2153,32 @@ bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year } int Database::GetIPExemption(std::string account_ip) { - std::string query = StringFormat("SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '%s'", account_ip.c_str()); - auto results = QueryDatabase(query); - - if (results.Success() && results.RowCount() > 0) { - auto row = results.begin(); - return atoi(row[0]); - } - - return RuleI(World, MaxClientsPerIP); -} - -void Database::SetIPExemption(std::string account_ip, int exemption_amount) { - std::string query = fmt::format( - "SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'", + auto query = fmt::format( + "SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'", account_ip ); auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + return RuleI(World, MaxClientsPerIP); + } + + auto row = results.begin(); + return std::stoi(row[0]); +} + +void Database::SetIPExemption(std::string account_ip, int exemption_amount) { + auto query = fmt::format( + "SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'", + account_ip + ); + uint32 exemption_id = 0; - if (results.Success() && results.RowCount() > 0) { + + auto results = QueryDatabase(query); + if (results.Success() && results.RowCount()) { auto row = results.begin(); - exemption_id = atoi(row[0]); + exemption_id = std::stoul(row[0]); } query = fmt::format( @@ -2311,13 +2187,14 @@ void Database::SetIPExemption(std::string account_ip, int exemption_amount) { exemption_amount ); - if (exemption_id != 0) { + if (exemption_id) { query = fmt::format( "UPDATE `ip_exemptions` SET `exemption_amount` = {} WHERE `exemption_ip` = '{}'", exemption_amount, account_ip ); } + QueryDatabase(query); } @@ -2340,9 +2217,9 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) { * @return */ bool Database::CopyCharacter( - std::string source_character_name, - std::string destination_character_name, - std::string destination_account_name + const std::string& source_character_name, + const std::string& destination_character_name, + const std::string& destination_account_name ) { auto results = QueryDatabase( @@ -2354,6 +2231,7 @@ bool Database::CopyCharacter( if (results.RowCount() == 0) { LogError("No character found with name [{}]", source_character_name); + return false; } auto row = results.begin(); @@ -2368,6 +2246,7 @@ bool Database::CopyCharacter( if (results.RowCount() == 0) { LogError("No account found with name [{}]", destination_account_name); + return false; } row = results.begin(); @@ -2399,7 +2278,7 @@ bool Database::CopyCharacter( results = QueryDatabase( fmt::format( "SELECT {} FROM {} WHERE {} = {}", - implode(",", wrap(columns, "`")), + Strings::Implode(",", Strings::Wrap(columns, "`")), table_name, character_id_column_name, source_character_id @@ -2435,7 +2314,7 @@ bool Database::CopyCharacter( std::vector insert_rows; for (auto &r: new_rows) { - std::string insert_row = "(" + implode(",", wrap(r, "'")) + ")"; + std::string insert_row = "(" + Strings::Implode(",", Strings::Wrap(r, "'")) + ")"; insert_rows.emplace_back(insert_row); } @@ -2453,8 +2332,8 @@ bool Database::CopyCharacter( fmt::format( "INSERT INTO {} ({}) VALUES {}", table_name, - implode(",", wrap(columns, "`")), - implode(",", insert_rows) + Strings::Implode(",", Strings::Wrap(columns, "`")), + Strings::Implode(",", insert_rows) ) ); @@ -2477,7 +2356,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur uri request_uri(url); LogHTTP( - "[SourceDatabaseTableFromUrl] parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]", + "parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]", url, request_uri.get_path(), request_uri.get_host(), @@ -2506,8 +2385,8 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur if (auto res = cli.Get(request_uri.get_path().c_str())) { if (res->status == 200) { - for (auto &s: SplitString(res->body, ';')) { - if (!trim(s).empty()) { + for (auto &s: Strings::Split(res->body, ';')) { + if (!Strings::Trim(s).empty()) { auto results = QueryDatabase(s); if (!results.ErrorMessage().empty()) { LogError("Error sourcing SQL [{}]", results.ErrorMessage()); @@ -2531,7 +2410,20 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur } catch (std::invalid_argument iae) { - LogError("[SourceDatabaseTableFromUrl] URI parser error [{}]", iae.what()); + LogError("URI parser error [{}]", iae.what()); } } +uint8 Database::GetMinStatus(uint32 zone_id, uint32 instance_version) +{ + auto zones = ZoneRepository::GetWhere( + *this, + fmt::format( + "zoneidnumber = {} AND (version = {} OR version = 0) ORDER BY version DESC LIMIT 1", + zone_id, + instance_version + ) + ); + + return !zones.empty() ? zones[0].min_status : 0; +} diff --git a/common/database.h b/common/database.h index b7492ac9f..33ec0e474 100644 --- a/common/database.h +++ b/common/database.h @@ -88,7 +88,6 @@ public: /* Character Creation */ - bool AddToNameFilter(const char *name); bool CreateCharacter( uint32 account_id, char *name, @@ -114,24 +113,25 @@ public: bool SetMQDetectionFlag(const char *accountname, const char *charactername, const std::string &hacked, const char *zone); bool UpdateName(const char *oldname, const char *newname); bool CopyCharacter( - std::string source_character_name, - std::string destination_character_name, - std::string destination_account_name + const std::string& source_character_name, + const std::string& destination_character_name, + const std::string& destination_account_name ); /* General Information Queries */ bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table. + bool AddToNameFilter(std::string name); bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table. bool CheckGMIPs(std::string login_ip, uint32 account_id); - bool CheckNameFilter(const char* name, bool surname = false); - bool CheckUsedName(const char* name); + bool CheckNameFilter(std::string name, bool surname = false); + bool CheckUsedName(std::string name); uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0); uint32 GetCharacterID(const char *name); - uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0); + uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id); uint32 GetGuildIDByCharID(uint32 char_id); uint32 GetGroupIDByCharID(uint32 char_id); uint32 GetRaidIDByCharID(uint32 char_id); @@ -145,31 +145,30 @@ public: /* Instancing */ - bool AddClientToInstance(uint16 instance_id, uint32 char_id); - bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id); + bool AddClientToInstance(uint16 instance_id, uint32 character_id); + bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id); bool CheckInstanceExists(uint16 instance_id); bool CheckInstanceExpired(uint16 instance_id); bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); bool GetUnusedInstanceID(uint16 &instance_id); - bool GlobalInstance(uint16 instance_id); + bool IsGlobalInstance(uint16 instance_id); bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id); bool RemoveClientsFromInstance(uint16 instance_id); - bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id); + bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id); bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version); - uint16 GetInstanceVersion(uint16 instance_id); + std::vector GetInstanceIDs(uint32 zone_id, uint32 character_id); + uint8_t GetInstanceVersion(uint16 instance_id); uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); - uint32 VersionFromInstanceID(uint16 instance_id); - uint32 ZoneIDFromInstanceID(uint16 instance_id); + uint32 GetInstanceZoneID(uint16 instance_id); void AssignGroupToInstance(uint32 gid, uint32 instance_id); void AssignRaidToInstance(uint32 rid, uint32 instance_id); - void BuryCorpsesInInstance(uint16 instance_id); void DeleteInstance(uint16 instance_id); - void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid); - void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid); - void GetCharactersInInstance(uint16 instance_id, std::list &charid_list); + void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id); + void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id); + void GetCharactersInInstance(uint16 instance_id, std::list &character_ids); void PurgeExpiredInstances(); void SetInstanceDuration(uint16 instance_id, uint32 new_duration); @@ -207,8 +206,8 @@ public: /* Groups */ - char* GetGroupLeaderForLogin(const char* name,char* leaderbuf); - char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); + std::string GetGroupLeaderForLogin(std::string character_name); + char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); uint32 GetGroupID(const char* name); @@ -246,14 +245,11 @@ public: /* General Queries */ - bool GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, float* safe_heading = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr); bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); - bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0); bool LoadPTimers(uint32 charid, PTimerList &into); - uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version); - uint8 GetPEQZone(uint32 zone_id, uint32 version); + uint8 GetMinStatus(uint32 zone_id, uint32 instance_version); uint8 GetRaceSkill(uint8 skillid, uint8 in_race); uint8 GetServerType(); uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 7efd80f83..3aa528665 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -23,10 +23,11 @@ #include #include "database_dump_service.h" #include "../eqemu_logsys.h" -#include "../string_util.h" +#include "../strings.h" #include "../eqemu_config.h" #include "../database_schema.h" -#include "../file_util.h" +#include "../file.h" +#include "../process/process.h" #include @@ -40,38 +41,6 @@ #define DATABASE_DUMP_PATH "backups/" -/** - * @param cmd - * @param return_result - * @return - */ -std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true) -{ - const char *file_name = "db-exec-result.txt"; - - if (return_result) { -#ifdef _WINDOWS - std::system((cmd + " > " + file_name + " 2>&1").c_str()); -#else - std::system((cmd + " > " + file_name).c_str()); -#endif - } - else { - std::system((cmd).c_str()); - } - - std::string result; - - if (return_result) { - std::ifstream file(file_name); - result = {std::istreambuf_iterator(file), std::istreambuf_iterator()}; - std::remove(file_name); - - } - - return result; -} - /** * @return bool */ @@ -88,7 +57,7 @@ bool DatabaseDumpService::IsMySQLInstalled() */ bool DatabaseDumpService::IsTarAvailable() { - std::string version_output = execute("tar --version"); + std::string version_output = Process::execute("tar --version"); return version_output.find("GNU tar") != std::string::npos; } @@ -99,7 +68,7 @@ bool DatabaseDumpService::IsTarAvailable() */ bool DatabaseDumpService::Is7ZipAvailable() { - std::string version_output = execute("7z --help"); + std::string version_output = Process::execute("7z --help"); return version_output.find("7-Zip") != std::string::npos; } @@ -117,9 +86,9 @@ bool DatabaseDumpService::HasCompressionBinary() */ std::string DatabaseDumpService::GetMySQLVersion() { - std::string version_output = execute("mysql --version"); + std::string version_output = Process::execute("mysql --version"); - return trim(version_output); + return Strings::Trim(version_output); } /** @@ -149,95 +118,53 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand() ); } -/** - * @return - */ std::string DatabaseDumpService::GetPlayerTablesList() { - std::string tables_list; - std::vector tables = DatabaseSchema::GetPlayerTables(); - for (const auto &table : tables) { - tables_list += table + " "; - } - - return trim(tables_list); + return Strings::Join(DatabaseSchema::GetPlayerTables(), " "); +} + +std::string DatabaseDumpService::GetBotTablesList() +{ + return Strings::Join(DatabaseSchema::GetBotTables(), " "); +} + +std::string DatabaseDumpService::GetMercTablesList() +{ + return Strings::Join(DatabaseSchema::GetMercTables(), " "); } -/** - * @return - */ std::string DatabaseDumpService::GetLoginTableList() { - std::string tables_list; - std::vector tables = DatabaseSchema::GetLoginTables(); - for (const auto &table : tables) { - tables_list += table + " "; - } - - return trim(tables_list); + return Strings::Join(DatabaseSchema::GetLoginTables(), " "); } -/** - * @return - */ std::string DatabaseDumpService::GetQueryServTables() { - std::string tables_list; - std::vector tables = DatabaseSchema::GetQueryServerTables(); - for (const auto &table : tables) { - tables_list += table + " "; - } - - return trim(tables_list); + return Strings::Join(DatabaseSchema::GetQueryServerTables(), " "); } -/** - * @return - */ std::string DatabaseDumpService::GetSystemTablesList() { - std::string tables_list; + auto system_tables = DatabaseSchema::GetServerTables(); + auto version_tables = DatabaseSchema::GetVersionTables(); - std::vector tables = DatabaseSchema::GetServerTables(); - for (const auto &table : tables) { - tables_list += table + " "; - } + system_tables.insert( + std::end(system_tables), + std::begin(version_tables), + std::end(version_tables) + ); - tables = DatabaseSchema::GetVersionTables(); - for (const auto &table : tables) { - tables_list += table + " "; - } - - return trim(tables_list); + return Strings::Join(system_tables, " "); } -/** - * @return - */ + std::string DatabaseDumpService::GetStateTablesList() { - std::string tables_list; - - std::vector tables = DatabaseSchema::GetStateTables(); - for (const auto &table : tables) { - tables_list += table + " "; - } - - return trim(tables_list); + return Strings::Join(DatabaseSchema::GetStateTables(), " "); } -/** - * @return - */ std::string DatabaseDumpService::GetContentTablesList() { - std::string tables_list; - - std::vector tables = DatabaseSchema::GetContentTables(); - for (const auto &table : tables) { - tables_list += table + " "; - } - - return trim(tables_list); + return Strings::Join(DatabaseSchema::GetContentTables(), " "); } /** @@ -318,6 +245,16 @@ void DatabaseDumpService::Dump() dump_descriptor += "-player"; } + if (IsDumpBotTables()) { + tables_to_dump += GetBotTablesList() + " "; + dump_descriptor += "-bots"; + } + + if (IsDumpMercTables()) { + tables_to_dump += GetMercTablesList() + " "; + dump_descriptor += "-mercs"; + } + if (IsDumpSystemTables()) { tables_to_dump += GetSystemTablesList() + " "; dump_descriptor += "-system"; @@ -364,12 +301,12 @@ void DatabaseDumpService::Dump() pipe_file ); - if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { - FileUtil::mkdir(GetSetDumpPath()); + if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { + File::Makedir(GetSetDumpPath()); } if (IsDumpDropTableSyntaxOnly()) { - std::vector tables = SplitString(tables_to_dump, ' '); + std::vector tables = Strings::Split(tables_to_dump, ' '); for (auto &table : tables) { std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl; @@ -380,14 +317,14 @@ void DatabaseDumpService::Dump() } } else { - std::string execution_result = execute(execute_command, IsDumpOutputToConsole()); - if (!execution_result.empty()) { + std::string execution_result = Process::execute(execute_command); + if (!execution_result.empty() && IsDumpOutputToConsole()) { std::cout << execution_result; } } if (!tables_to_dump.empty()) { - LogInfo("Dumping Tables [{}]", tables_to_dump); + LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump)); } LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath()); @@ -397,7 +334,7 @@ void DatabaseDumpService::Dump() LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath()); if (IsTarAvailable()) { - execute( + Process::execute( fmt::format( "tar -zcvf {}.tar.gz -C {} {}.sql", GetDumpFileNameWithPath(), @@ -408,7 +345,7 @@ void DatabaseDumpService::Dump() LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath()); } else if (Is7ZipAvailable()) { - execute( + Process::execute( fmt::format( "7z a -t7z {}.zip {}.sql", GetDumpFileNameWithPath(), @@ -436,6 +373,7 @@ void DatabaseDumpService::Dump() // LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false")); // LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false")); // LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false")); +// LogDebug("[{}] bot", (IsDumpBotTables() ? "true" : "false")); } bool DatabaseDumpService::IsDumpSystemTables() const @@ -577,3 +515,23 @@ void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables) { DatabaseDumpService::dump_state_tables = dump_state_tables; } + +bool DatabaseDumpService::IsDumpBotTables() const +{ + return dump_bot_tables; +} + +void DatabaseDumpService::SetDumpBotTables(bool dump_bot_tables) +{ + DatabaseDumpService::dump_bot_tables = dump_bot_tables; +} + +bool DatabaseDumpService::IsDumpMercTables() const +{ + return dump_merc_tables; +} + +void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables) +{ + DatabaseDumpService::dump_merc_tables = dump_merc_tables; +} diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index f0614e85b..06f39dda1 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -53,6 +53,10 @@ public: void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only); bool IsDumpStateTables() const; void SetDumpStateTables(bool dump_state_tables); + bool IsDumpBotTables() const; + void SetDumpBotTables(bool dump_bot_tables); + bool IsDumpMercTables() const; + void SetDumpMercTables(bool dump_bot_tables); private: bool dump_all_tables = false; @@ -67,14 +71,17 @@ private: bool dump_with_compression = false; bool dump_output_to_console = false; bool dump_drop_table_syntax_only = false; + bool dump_bot_tables = false; + bool dump_merc_tables = false; std::string dump_path; std::string dump_file_name; - std::string execute(const std::string &cmd, bool return_result); bool IsMySQLInstalled(); std::string GetMySQLVersion(); std::string GetBaseMySQLDumpCommand(); std::string GetPlayerTablesList(); + std::string GetBotTablesList(); + std::string GetMercTablesList(); std::string GetSystemTablesList(); std::string GetStateTablesList(); std::string GetContentTablesList(); diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index d3dfd92ab..e52786b0b 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -18,11 +18,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/global_define.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/timer.h" #include "database.h" #include "extprofile.h" +#include "path_manager.h" #include #include @@ -475,8 +476,16 @@ bool Database::CheckDatabaseConversions() { CheckDatabaseConvertPPDeblob(); CheckDatabaseConvertCorpseDeblob(); + RuleManager::Instance()->LoadRules(this, "default", false); + if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) { + LogInfo("Bot tables found but rule not enabled, enabling"); + RuleManager::Instance()->SetRule("Bots:Enabled", "true", this, true, true); + } + /* Run EQEmu Server script (Checks for database updates) */ - system("perl eqemu_server.pl ran_from_world"); + + const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath()); + system(fmt::format("perl {} ran_from_world", file).c_str()); return true; } @@ -961,7 +970,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)" "VALUES (%u, '%s')", character_id, - EscapeString(inspectmessage).c_str() + Strings::Escape(inspectmessage).c_str() ); auto results = QueryDatabase(rquery); } @@ -1097,95 +1106,95 @@ bool Database::CheckDatabaseConvertPPDeblob(){ "e_expended_aa_spent" ")" "VALUES (" - "%u," // id - "%u," // account_id - "'%s'," // `name` - "'%s'," // last_name - "%u," // gender - "%u," // race - "%u," // class - "%u," // `level` - "%u," // deity - "%u," // birthday - "%u," // last_login - "%u," // time_played - "%u," // pvp_status - "%u," // level2 - "%u," // anon - "%u," // gm - "%u," // intoxication - "%u," // hair_color - "%u," // beard_color - "%u," // eye_color_1 - "%u," // eye_color_2 - "%u," // hair_style - "%u," // beard - "%u," // ability_time_seconds - "%u," // ability_number - "%u," // ability_time_minutes - "%u," // ability_time_hours - "'%s'," // title - "'%s'," // suffix - "%u," // exp - "%u," // points - "%u," // mana - "%u," // cur_hp - "%u," // str - "%u," // sta - "%u," // cha - "%u," // dex - "%u," // `int` - "%u," // agi - "%u," // wis - "%u," // face - "%f," // y - "%f," // x - "%f," // z - "%f," // heading - "%u," // pvp2 - "%u," // pvp_type - "%u," // autosplit_enabled - "%u," // zone_change_count - "%u," // drakkin_heritage - "%u," // drakkin_tattoo - "%u," // drakkin_details - "%i," // toxicity - "%u," // hunger_level - "%u," // thirst_level - "%u," // ability_up - "%u," // zone_id - "%u," // zone_instance - "%u," // leadership_exp_on - "%u," // ldon_points_guk - "%u," // ldon_points_mir - "%u," // ldon_points_mmc - "%u," // ldon_points_ruj - "%u," // ldon_points_tak - "%u," // ldon_points_available - "%u," // tribute_time_remaining - "%u," // show_helm - "%u," // career_tribute_points - "%u," // tribute_points - "%u," // tribute_active - "%u," // endurance - "%u," // group_leadership_exp - "%u," // raid_leadership_exp - "%u," // group_leadership_points - "%u," // raid_leadership_points - "%u," // air_remaining - "%u," // pvp_kills - "%u," // pvp_deaths - "%u," // pvp_current_points - "%u," // pvp_career_points - "%u," // pvp_best_kill_streak - "%u," // pvp_worst_death_streak - "%u," // pvp_current_kill_streak - "%u," // aa_points_spent - "%u," // aa_exp - "%u," // aa_points - "%u," // group_auto_consent - "%u," // raid_auto_consent - "%u," // guild_auto_consent + "%u," // id + "%u," // account_id + "'%s'," // `name` + "'%s'," // last_name + "%u," // gender + "%u," // race + "%u," // class + "%u," // `level` + "%u," // deity + "%u," // birthday + "%u," // last_login + "%u," // time_played + "%u," // pvp_status + "%u," // level2 + "%u," // anon + "%u," // gm + "%u," // intoxication + "%u," // hair_color + "%u," // beard_color + "%u," // eye_color_1 + "%u," // eye_color_2 + "%u," // hair_style + "%u," // beard + "%u," // ability_time_seconds + "%u," // ability_number + "%u," // ability_time_minutes + "%u," // ability_time_hours + "'%s'," // title + "'%s'," // suffix + "%u," // exp + "%u," // points + "%u," // mana + "%u," // cur_hp + "%u," // str + "%u," // sta + "%u," // cha + "%u," // dex + "%u," // `int` + "%u," // agi + "%u," // wis + "%u," // face + "%f," // y + "%f," // x + "%f," // z + "%f," // heading + "%u," // pvp2 + "%u," // pvp_type + "%u," // autosplit_enabled + "%u," // zone_change_count + "%u," // drakkin_heritage + "%u," // drakkin_tattoo + "%u," // drakkin_details + "%i," // toxicity + "%u," // hunger_level + "%u," // thirst_level + "%u," // ability_up + "%u," // zone_id + "%u," // zone_instance + "%u," // leadership_exp_on + "%u," // ldon_points_guk + "%u," // ldon_points_mir + "%u," // ldon_points_mmc + "%u," // ldon_points_ruj + "%u," // ldon_points_tak + "%u," // ldon_points_available + "%u," // tribute_time_remaining + "%u," // show_helm + "%u," // career_tribute_points + "%u," // tribute_points + "%u," // tribute_active + "%u," // endurance + "%u," // group_leadership_exp + "%u," // raid_leadership_exp + "%u," // group_leadership_points + "%u," // raid_leadership_points + "%u," // air_remaining + "%u," // pvp_kills + "%u," // pvp_deaths + "%u," // pvp_current_points + "%u," // pvp_career_points + "%u," // pvp_best_kill_streak + "%u," // pvp_worst_death_streak + "%u," // pvp_current_kill_streak + "%u," // aa_points_spent + "%u," // aa_exp + "%u," // aa_points + "%u," // group_auto_consent + "%u," // raid_auto_consent + "%u," // guild_auto_consent "%u," // RestTimer "%u," // First Logon - References online status for EVENT_CONNECT/EVENT_DISCONNECt "%u," // Looking for Group @@ -1198,8 +1207,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){ ")", character_id, account_id, - EscapeString(pp->name).c_str(), - EscapeString(pp->last_name).c_str(), + Strings::Escape(pp->name).c_str(), + Strings::Escape(pp->last_name).c_str(), pp->gender, pp->race, pp->class_, @@ -1223,8 +1232,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){ pp->ability_number, pp->ability_time_minutes, pp->ability_time_hours, - EscapeString(pp->title).c_str(), - EscapeString(pp->suffix).c_str(), + Strings::Escape(pp->title).c_str(), + Strings::Escape(pp->suffix).c_str(), pp->exp, pp->points, pp->mana, diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 75edd9fd3..27945a4aa 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -18,10 +18,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/global_define.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/timer.h" +#include "../common/repositories/character_corpses_repository.h" #include "../common/repositories/dynamic_zone_members_repository.h" #include "../common/repositories/dynamic_zones_repository.h" +#include "../common/repositories/group_id_repository.h" +#include "../common/repositories/instance_list_repository.h" +#include "../common/repositories/instance_list_player_repository.h" +#include "../common/repositories/raid_members_repository.h" +#include "../common/repositories/respawn_times_repository.h" +#include "../common/repositories/spawn_condition_values_repository.h" + #include "database.h" @@ -41,115 +49,83 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #endif -/** - * @param instance_id - * @param char_id - * @return - */ -bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) +bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id) { - std::string query = StringFormat( - "REPLACE INTO `instance_list_player` (id, charid) " - "VALUES " - "(%lu, %lu)", - (unsigned long) instance_id, - (unsigned long) char_id - ); + auto e = InstanceListPlayerRepository::NewEntity(); - auto results = QueryDatabase(query); + e.id = instance_id; + e.charid = character_id; - return results.Success(); + return InstanceListPlayerRepository::ReplaceOne(*this, e); } -bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) +bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id) { - - std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id); - auto results = QueryDatabase(query); - - if (!results.Success()) + if (!instance_id) { return false; + } - if (results.RowCount() != 1) + auto l = InstanceListPlayerRepository::GetWhere( + *this, + fmt::format( + "id = {} AND charid = {}", + instance_id, + character_id + ) + ); + if (l.empty()) { return false; + } return true; } -bool Database::CheckInstanceExists(uint16 instance_id) { - std::string query = StringFormat( - "SELECT " - "`id` " - "FROM " - "`instance_list` " - "WHERE " - "`id` = %u", - instance_id - ); - auto results = QueryDatabase(query); - - if (!results.Success()) +bool Database::CheckInstanceExists(uint16 instance_id) +{ + if (!instance_id) { return false; + } - if (results.RowCount() == 0) + auto i = InstanceListRepository::FindOne(*this, instance_id); + if (!i.id) { return false; + } return true; } bool Database::CheckInstanceExpired(uint16 instance_id) { - - int32 start_time = 0; - int32 duration = 0; - uint32 never_expires = 0; - - std::string query = StringFormat( - "SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", - instance_id - ); - - auto results = QueryDatabase(query); - - if (!results.Success()) { + if (!instance_id) { return true; } - if (results.RowCount() == 0) { + auto i = InstanceListRepository::FindOne(*this, instance_id); + if (!i.id) { return true; } - auto row = results.begin(); - - start_time = atoi(row[0]); - duration = atoi(row[1]); - never_expires = atoi(row[2]); - - if (never_expires == 1) { + if (i.never_expires) { return false; } timeval tv{}; gettimeofday(&tv, nullptr); - return (start_time + duration) <= tv.tv_sec; - + return (i.start_time + i.duration) <= tv.tv_sec; } bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) { - std::string query = StringFormat( - "INSERT INTO instance_list (id, zone, version, start_time, duration)" - " values (%u, %u, %u, UNIX_TIMESTAMP(), %u)", - instance_id, - zone_id, - version, - duration - ); + auto e = InstanceListRepository::NewEntity(); - auto results = QueryDatabase(query); + e.id = instance_id; + e.zone = zone_id; + e.version = version; + e.start_time = std::time(nullptr); + e.duration = duration; - return results.Success(); + return InstanceListRepository::InsertOne(*this, e).id; } bool Database::GetUnusedInstanceID(uint16 &instance_id) @@ -157,8 +133,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances); uint32 max = 32000; - std::string query = StringFormat( - "SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", + auto query = fmt::format( + "SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}", max_reserved_instance_id, max_reserved_instance_id ); @@ -202,7 +178,7 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) return true; } - query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id); + query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id); results = QueryDatabase(query); if (!results.Success()) { @@ -216,8 +192,9 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) } max_reserved_instance_id++; - for (auto row = results.begin(); row != results.end(); ++row) { - if (max_reserved_instance_id < atoi(row[0])) { + + for (auto row : results) { + if (max_reserved_instance_id < std::stoul(row[0])) { instance_id = max_reserved_instance_id; return true; } @@ -235,57 +212,45 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) return true; } -bool Database::GlobalInstance(uint16 instance_id) +bool Database::IsGlobalInstance(uint16 instance_id) { - std::string query = StringFormat( - "SELECT " - "is_global " - "FROM " - "instance_list " - "WHERE " - "id = %u " - "LIMIT 1 ", - instance_id - ); - auto results = QueryDatabase(query); - - if (!results.Success()) + if (!instance_id) { return false; + } - if (results.RowCount() == 0) + auto i = InstanceListRepository::FindOne(*this, instance_id); + if (!i.id) { return false; + } - auto row = results.begin(); - - return (atoi(row[0]) == 1) ? true : false; + return i.is_global; } bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) { - std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", - (unsigned long)instance_id, (unsigned long)char_id); - auto results = QueryDatabase(query); - - return results.Success(); + return InstanceListPlayerRepository::DeleteWhere( + *this, + fmt::format( + "id = {} AND charid = {}", + instance_id, + char_id + ) + ); } - bool Database::RemoveClientsFromInstance(uint16 instance_id) { - std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id); - auto results = QueryDatabase(query); - - return results.Success(); + return InstanceListPlayerRepository::DeleteOne(*this, instance_id); } -bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) +bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id) { //we are not saved to this instance so set our instance to 0 - if (!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id)) + if (!IsGlobalInstance(instance_id) && !CheckInstanceByCharID(instance_id, character_id)) { return false; + } - if (CheckInstanceExpired(instance_id)) - { + if (CheckInstanceExpired(instance_id)) { DeleteInstance(instance_id); return false; } @@ -295,99 +260,102 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) { - - std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u", instance_id, zone_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return false; - - if (results.RowCount() == 0) + auto l = InstanceListRepository::GetWhere( + *this, + fmt::format( + "id = {} AND zone = {}", + instance_id, + zone_id + ) + ); + if (l.empty()) { return false; + } return true; } -uint16 Database::GetInstanceID(uint32 zone, uint32 character_id, int16 version) +uint16 Database::GetInstanceID(uint32 zone_id, uint32 character_id, int16 version) { - if (!zone) + if (!zone_id) { return 0; + } - std::string query = StringFormat( - "SELECT " - "instance_list.id " - "FROM " - "instance_list, " - "instance_list_player " - "WHERE " - "instance_list.zone = %u " - "AND instance_list.version = %u " - "AND instance_list.id = instance_list_player.id " - "AND instance_list_player.charid = %u " - "LIMIT 1; ", - zone, + const auto query = fmt::format( + "SELECT instance_list.id FROM " + "instance_list, instance_list_player WHERE " + "instance_list.zone = {} AND " + "instance_list.version = {} AND " + "instance_list.id = instance_list_player.id AND " + "instance_list_player.charid = {} " + "LIMIT 1;", + zone_id, version, character_id - ); + ); auto results = QueryDatabase(query); - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) + if (!results.Success() || !results.RowCount()) { return 0; + } auto row = results.begin(); - return atoi(row[0]); + return static_cast(std::stoul(row[0])); } -uint16 Database::GetInstanceVersion(uint16 instance_id) { - if (instance_id == 0) - return 0; +std::vector Database::GetInstanceIDs(uint32 zone_id, uint32 character_id) +{ + std::vector l; - std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); + if (!zone_id) { + return l; + } + + const auto query = fmt::format( + "SELECT instance_list.id FROM " + "instance_list, instance_list_player WHERE " + "instance_list.zone = {} AND " + "instance_list.id = instance_list_player.id AND " + "instance_list_player.charid = {}", + zone_id, + character_id + ); auto results = QueryDatabase(query); - if (!results.Success()) - return 0; + if (!results.Success() || !results.RowCount()) { + return l; + } - if (results.RowCount() == 0) - return 0; + for (auto row : results) { + l.push_back(static_cast(std::stoul(row[0]))); + } - auto row = results.begin(); - return atoi(row[0]); + return l; +} + +uint8_t Database::GetInstanceVersion(uint16 instance_id) { + if (!instance_id) { + return 0; + } + + auto i = InstanceListRepository::FindOne(*this, instance_id); + if (!i.id) { + return 0; + } + + return i.version; } uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) { - uint32 start_time = 0; - uint32 duration = 0; - uint32 never_expires = 0; - - std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - { + auto i = InstanceListRepository::FindOne(*this, instance_id); + if (!i.id) { is_perma = false; return 0; } - if (results.RowCount() == 0) - { - is_perma = false; - return 0; - } - - auto row = results.begin(); - - start_time = atoi(row[0]); - duration = atoi(row[1]); - never_expires = atoi(row[2]); - - if (never_expires == 1) - { + if (i.never_expires) { is_perma = true; return 0; } @@ -396,204 +364,175 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) timeval tv; gettimeofday(&tv, nullptr); - return ((start_time + duration) - tv.tv_sec); + return ((i.start_time + i.duration) - tv.tv_sec); } -uint32 Database::VersionFromInstanceID(uint16 instance_id) +uint32 Database::GetInstanceZoneID(uint16 instance_id) { - - std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) + if (!instance_id) { return 0; + } - if (results.RowCount() == 0) + auto i = InstanceListRepository::FindOne(*this, instance_id); + if (!i.id) { return 0; + } - auto row = results.begin(); - - return atoi(row[0]); -} - -uint32 Database::ZoneIDFromInstanceID(uint16 instance_id) -{ - - std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); + return i.zone; } void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id) { + auto zone_id = GetInstanceZoneID(instance_id); + auto version = GetInstanceVersion(instance_id); - uint32 zone_id = ZoneIDFromInstanceID(instance_id); - uint16 version = VersionFromInstanceID(instance_id); - - std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id); - auto results = QueryDatabase(query); - - if (!results.Success()) + auto l = GroupIdRepository::GetWhere( + *this, + fmt::format( + "groupid = {}", + group_id + ) + ); + if (l.empty()) { return; + } - for (auto row = results.begin(); row != results.end(); ++row) - { - uint32 charid = atoi(row[0]); - if (GetInstanceID(zone_id, charid, version) == 0) - AddClientToInstance(instance_id, charid); + for (const auto& e : l) { + if (!GetInstanceID(zone_id, e.charid, version)) { + AddClientToInstance(instance_id, e.charid); + } } } void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id) { + auto zone_id = GetInstanceZoneID(instance_id); + auto version = GetInstanceVersion(instance_id); - uint32 zone_id = ZoneIDFromInstanceID(instance_id); - uint16 version = VersionFromInstanceID(instance_id); - - std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return; - - for (auto row = results.begin(); row != results.end(); ++row) - { - uint32 charid = atoi(row[0]); - if (GetInstanceID(zone_id, charid, version) == 0) - AddClientToInstance(instance_id, charid); - } -} - -void Database::BuryCorpsesInInstance(uint16 instance_id) { - QueryDatabase( + auto l = GroupIdRepository::GetWhere( + *this, fmt::format( - "UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id = {}", - instance_id + "raidid = {}", + raid_id ) ); + if (l.empty()) { + return; + } + + for (const auto& e : l) { + if (!GetInstanceID(zone_id, e.charid, version)) { + AddClientToInstance(instance_id, e.charid); + } + } } void Database::DeleteInstance(uint16 instance_id) { std::string query; - - query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id); - QueryDatabase(query); - query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id); - QueryDatabase(query); + InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id)); - query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id); - QueryDatabase(query); + RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); + + SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id); DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); - BuryCorpsesInInstance(instance_id); + CharacterCorpsesRepository::BuryInstance(*this, instance_id); } -void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid) +void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id) { - uint16 id = GetInstanceID(zone, charid, version); - if (id != 0) + auto instance_id = GetInstanceID(zone_id, character_id, version); + if (instance_id) { return; + } char ln[128]; memset(ln, 0, 128); - GetGroupLeadershipInfo(gid, ln); - uint32 l_charid = GetCharacterID((const char*)ln); - uint16 l_id = GetInstanceID(zone, l_charid, version); + GetGroupLeadershipInfo(group_id, ln); - if (l_id == 0) + auto group_leader_id = GetCharacterID((const char*)ln); + auto group_leader_instance_id = GetInstanceID(zone_id, group_leader_id, version); + + if (!group_leader_instance_id) { return; + } - AddClientToInstance(l_id, charid); + AddClientToInstance(group_leader_instance_id, character_id); } -void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid) +void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id) { - uint16 id = GetInstanceID(zone, charid, version); - if (id != 0) + uint16 instance_id = GetInstanceID(zone_id, character_id, version); + if (instance_id) { return; + } - uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid)); - uint16 l_id = GetInstanceID(zone, l_charid, version); + auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id)); + auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version); - if (l_id == 0) + if (!raid_leader_instance_id) { return; + } - AddClientToInstance(l_id, charid); + AddClientToInstance(raid_leader_instance_id, character_id); } -void Database::GetCharactersInInstance(uint16 instance_id, std::list &charid_list) { - - std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) +void Database::GetCharactersInInstance(uint16 instance_id, std::list &character_ids) +{ + auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id)); + if (l.empty()) { return; + } - for (auto row = results.begin(); row != results.end(); ++row) - charid_list.push_back(atoi(row[0])); + for (const auto& e : l) { + character_ids.push_back(e.charid); + } } void Database::PurgeExpiredInstances() { - /** * Delay purging by a day so that we can continue using adjacent free instance id's * from the table without risking the chance we immediately re-allocate a zone that freshly expired but * has not been fully de-allocated */ - std::string query = - SQL( - SELECT - id - FROM - instance_list - where - (start_time + duration) <= (UNIX_TIMESTAMP() - 86400) - and never_expires = 0 - ); - - auto results = QueryDatabase(query); - - if (!results.Success()) { - return; - } - - if (results.RowCount() == 0) { + auto l = InstanceListRepository::GetWhere( + *this, + "(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0" + ); + if (l.empty()) { return; } std::vector instance_ids; - for (auto row = results.begin(); row != results.end(); ++row) { - instance_ids.emplace_back(row[0]); + for (const auto& e : l) { + instance_ids.emplace_back(std::to_string(e.id)); } - std::string imploded_instance_ids = implode(",", instance_ids); + const auto imploded_instance_ids = Strings::Implode(",", instance_ids); - QueryDatabase(fmt::format("DELETE FROM instance_list WHERE id IN ({})", imploded_instance_ids)); - QueryDatabase(fmt::format("DELETE FROM instance_list_player WHERE id IN ({})", imploded_instance_ids)); - QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids)); - QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids)); - QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids)); + InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids)); + InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids)); + RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); + SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); + CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids); DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids); DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); } void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) { - std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " - "duration=%u WHERE id=%u", new_duration, instance_id); - auto results = QueryDatabase(query); + auto i = InstanceListRepository::FindOne(*this, instance_id); + if (!i.id) { + return; + } + + i.start_time = std::time(nullptr); + i.duration = new_duration; + + InstanceListRepository::UpdateOne(*this, i); } diff --git a/common/database_schema.h b/common/database_schema.h index 072e1e799..af88774be 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -189,13 +189,14 @@ namespace DatabaseSchema { "char_create_point_allocations", "damageshieldtypes", "doors", + "dynamic_zone_templates", + "faction_association", "faction_base_data", "faction_list", "faction_list_mod", "fishing", "forage", "global_loot", - "goallists", "graveyard", "grid", "grid_entries", @@ -224,7 +225,6 @@ namespace DatabaseSchema { "pets_beastlord_data", "pets_equipmentset", "pets_equipmentset_entries", - "proximities", "skill_caps", "spawn2", "spawn_conditions", @@ -318,6 +318,7 @@ namespace DatabaseSchema { "completed_shared_task_activity_state", "completed_shared_task_members", "completed_shared_tasks", + "discord_webhooks", "dynamic_zone_members", "dynamic_zones", "eventlog", @@ -331,7 +332,9 @@ namespace DatabaseSchema { "ip_exemptions", "item_tick", "lfguild", + "merc_buffs", "merchantlist_temp", + "mercs", "object_contents", "raid_details", "raid_leaders", @@ -376,6 +379,60 @@ namespace DatabaseSchema { }; } + /** + * @description Gets all player bot tables + * @note These tables have no content in the PEQ daily dump + * + * @return + */ + static std::vector GetBotTables() + { + return { + "bot_buffs", + "bot_command_settings", + "bot_create_combinations", + "bot_data", + "bot_group_members", + "bot_groups", + "bot_guild_members", + "bot_heal_rotation_members", + "bot_heal_rotation_targets", + "bot_heal_rotations", + "bot_inspect_messages", + "bot_inventories", + "bot_owner_options", + "bot_pet_buffs", + "bot_pet_inventories", + "bot_pets", + "bot_spell_casting_chances", + "bot_spell_settings", + "bot_spells_entries", + "bot_stances", + "bot_timers" + }; + } + + static std::vector GetMercTables() + { + return { + "merc_armorinfo", + "merc_inventory", + "merc_merchant_entries", + "merc_merchant_template_entries", + "merc_merchant_templates", + "merc_name_types", + "merc_npc_types", + "merc_spell_list_entries", + "merc_spell_lists", + "merc_stance_entries", + "merc_stats", + "merc_subtypes", + "merc_templates", + "merc_types", + "merc_weaponinfo" + }; + } + } #endif //EQEMU_DATABASE_SCHEMA_H diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 7f1f52363..3aa62c402 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -167,7 +167,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) { if ((strncasecmp(query, "select", 6) == 0)) { LogMySQLQuery( - "{0} ({1} row{2} returned) ({3}s)", + "{0} -- ({1} row{2} returned) ({3}s)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s", @@ -176,7 +176,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo } else { LogMySQLQuery( - "{0} ({1} row{2} affected) ({3}s)", + "{0} -- ({1} row{2} affected) ({3}s)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s", diff --git a/common/discord/discord.cpp b/common/discord/discord.cpp new file mode 100644 index 000000000..294f51c65 --- /dev/null +++ b/common/discord/discord.cpp @@ -0,0 +1,91 @@ +#include "discord.h" +#include "../http/httplib.h" +#include "../json/json.h" +#include "../strings.h" +#include "../eqemu_logsys.h" + +constexpr int MAX_RETRIES = 10; + +void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url) +{ + // validate + if (webhook_url.empty()) { + LogDiscord("[webhook_url] is empty"); + return; + } + + // validate + if (webhook_url.find("http://") == std::string::npos && webhook_url.find("https://") == std::string::npos) { + LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url); + return; + } + + // split + auto s = Strings::Split(webhook_url, '/'); + + // url + std::string base_url = fmt::format("{}//{}", s[0], s[2]); + std::string endpoint = Strings::Replace(webhook_url, base_url, ""); + + // client + httplib::Client cli(base_url.c_str()); + cli.set_connection_timeout(0, 15000000); // 15 sec + cli.set_read_timeout(15, 0); // 15 seconds + cli.set_write_timeout(15, 0); // 15 seconds + httplib::Headers headers = { + {"Content-Type", "application/json"} + }; + + // payload + Json::Value p; + p["content"] = message; + std::stringstream payload; + payload << p; + + bool retry = true; + int retries = 0; + int retry_timer = 1000; + while (retry) { + if (auto res = cli.Post(endpoint.c_str(), payload.str(), "application/json")) { + if (res->status != 200 && res->status != 204) { + LogError("Code [{}] Error [{}]", res->status, res->body); + } + if (res->status == 429) { + if (!res->body.empty()) { + std::stringstream ss(res->body); + Json::Value response; + + try { + ss >> response; + } + catch (std::exception const &ex) { + LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body); + } + + retry_timer = std::stoi(response["retry_after"].asString()) + 500; + } + + LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer); + std::this_thread::sleep_for(std::chrono::milliseconds(retry_timer + 500)); + } + if (res->status == 204) { + retry = false; + } + if (retries > MAX_RETRIES) { + LogDiscord("Retries exceeded for message [{}]", message); + retry = false; + } + + retries++; + } + } +} + +std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string &message) +{ + if (category_id == Logs::LogCategory::MySQLQuery) { + return fmt::format("```sql\n{}\n```", message); + } + + return message + "\n"; +} diff --git a/common/discord/discord.h b/common/discord/discord.h new file mode 100644 index 000000000..d4ebc73f1 --- /dev/null +++ b/common/discord/discord.h @@ -0,0 +1,15 @@ +#ifndef EQEMU_DISCORD_H +#define EQEMU_DISCORD_H + + +#include +#include "../types.h" + +class Discord { +public: + static void SendWebhookMessage(const std::string& message, const std::string& webhook_url); + static std::string FormatDiscordMessage(uint16 category_id, const std::string& message); +}; + + +#endif //EQEMU_DISCORD_H diff --git a/common/discord_manager.cpp b/common/discord_manager.cpp new file mode 100644 index 000000000..aac1dadcc --- /dev/null +++ b/common/discord_manager.cpp @@ -0,0 +1,69 @@ +#include "discord_manager.h" +#include "../common/discord/discord.h" +#include "../common/eqemu_logsys.h" +#include "../common/strings.h" + +void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message) +{ + webhook_queue_lock.lock(); + webhook_message_queue[webhook_id].emplace_back(message); + webhook_queue_lock.unlock(); +} + +constexpr int MAX_MESSAGE_LENGTH = 1900; + +void DiscordManager::ProcessMessageQueue() +{ + if (webhook_message_queue.empty()) { + return; + } + + webhook_queue_lock.lock(); + for (auto &q: webhook_message_queue) { + LogDiscord("Processing [{}] messages in queue for webhook ID [{}]...", q.second.size(), q.first); + + if (q.first >= MAX_DISCORD_WEBHOOK_ID) { + LogDiscord("Out of bounds webhook ID [{}] max [{}]", q.first, MAX_DISCORD_WEBHOOK_ID); + continue; + } + + auto webhook = LogSys.GetDiscordWebhooks()[q.first]; + std::string message; + + for (auto &m: q.second) { + // next message would become too large + bool next_message_too_large = ((int) m.length() + (int) message.length()) > MAX_MESSAGE_LENGTH; + if (next_message_too_large) { + Discord::SendWebhookMessage( + message, + webhook.webhook_url + ); + message = ""; + } + + message += m; + + // one single message was too large + // this should rarely happen but the message will need to be split + if ((int) message.length() > MAX_MESSAGE_LENGTH) { + for (unsigned mi = 0; mi < message.length(); mi += MAX_MESSAGE_LENGTH) { + Discord::SendWebhookMessage( + message.substr(mi, MAX_MESSAGE_LENGTH), + webhook.webhook_url + ); + } + message = ""; + } + } + + // final flush + if (!message.empty()) { + Discord::SendWebhookMessage( + message, + webhook.webhook_url + ); + } + } + webhook_message_queue.clear(); + webhook_queue_lock.unlock(); +} diff --git a/common/discord_manager.h b/common/discord_manager.h new file mode 100644 index 000000000..cc3573630 --- /dev/null +++ b/common/discord_manager.h @@ -0,0 +1,19 @@ +#ifndef EQEMU_DISCORD_MANAGER_H +#define EQEMU_DISCORD_MANAGER_H + +#include +#include +#include +#include "../common/types.h" + +class DiscordManager { +public: + void QueueWebhookMessage(uint32 webhook_id, const std::string& message); + void ProcessMessageQueue(); +private: + std::mutex webhook_queue_lock{}; + std::map> webhook_message_queue{}; +}; + + +#endif diff --git a/common/dynamic_zone_base.cpp b/common/dynamic_zone_base.cpp index 8269c3b23..78b38de21 100644 --- a/common/dynamic_zone_base.cpp +++ b/common/dynamic_zone_base.cpp @@ -79,6 +79,7 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn m_max_players = dz_entry.max_players; m_instance_id = dz_entry.instance_id; m_type = static_cast(dz_entry.type); + m_dz_switch_id = dz_entry.dz_switch_id; m_compass.zone_id = dz_entry.compass_zone_id; m_compass.x = dz_entry.compass_x; m_compass.y = dz_entry.compass_y; @@ -129,6 +130,7 @@ uint32_t DynamicZoneBase::SaveToDatabase() insert_dz.max_players = m_max_players; insert_dz.instance_id = m_instance_id, insert_dz.type = static_cast(m_type); + insert_dz.dz_switch_id = m_dz_switch_id; insert_dz.compass_zone_id = m_compass.zone_id; insert_dz.compass_x = m_compass.x; insert_dz.compass_y = m_compass.y; @@ -316,6 +318,17 @@ void DynamicZoneBase::SetZoneInLocation(float x, float y, float z, float heading SetZoneInLocation({ 0, x, y, z, heading }, update_db); } +void DynamicZoneBase::SetSwitchID(int dz_switch_id, bool update_db) +{ + m_dz_switch_id = dz_switch_id; + + if (update_db) + { + DynamicZonesRepository::UpdateSwitchID(GetDatabase(), m_id, dz_switch_id); + SendServerPacket(CreateServerDzSwitchIDPacket().get()); + } +} + void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update_db) { m_leader = new_leader; @@ -403,6 +416,17 @@ std::unique_ptr DynamicZoneBase::CreateServerDzLocationPacket( return pack; } +std::unique_ptr DynamicZoneBase::CreateServerDzSwitchIDPacket() +{ + constexpr uint32_t pack_size = sizeof(ServerDzSwitchID_Struct); + auto pack = std::make_unique(ServerOP_DzSetSwitchID, pack_size); + auto buf = reinterpret_cast(pack->pBuffer); + buf->dz_id = GetID(); + buf->dz_switch_id = GetSwitchID(); + + return pack; +} + std::unique_ptr DynamicZoneBase::CreateServerMemberStatusPacket( uint32_t character_id, DynamicZoneMemberStatus status) { @@ -598,3 +622,28 @@ void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_ cereal::BinaryInputArchive archive(ss); archive(*this); } + +void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template) +{ + m_zone_id = dz_template.zone_id; + m_zone_version = dz_template.zone_version; + m_name = dz_template.name; + m_min_players = dz_template.min_players; + m_max_players = dz_template.max_players; + m_duration = std::chrono::seconds(dz_template.duration_seconds); + m_dz_switch_id = dz_template.dz_switch_id; + m_compass.zone_id = dz_template.compass_zone_id; + m_compass.x = dz_template.compass_x; + m_compass.y = dz_template.compass_y; + m_compass.z = dz_template.compass_z; + m_safereturn.zone_id = dz_template.return_zone_id; + m_safereturn.x = dz_template.return_x; + m_safereturn.y = dz_template.return_y; + m_safereturn.z = dz_template.return_z; + m_safereturn.heading = dz_template.return_h; + m_has_zonein = dz_template.override_zone_in; + m_zonein.x = dz_template.zone_in_x; + m_zonein.y = dz_template.zone_in_y; + m_zonein.z = dz_template.zone_in_z; + m_zonein.heading = dz_template.zone_in_h; +} diff --git a/common/dynamic_zone_base.h b/common/dynamic_zone_base.h index eafea5ca0..b92f18ec2 100644 --- a/common/dynamic_zone_base.h +++ b/common/dynamic_zone_base.h @@ -5,6 +5,7 @@ #include "net/packet.h" #include "repositories/dynamic_zones_repository.h" #include "repositories/dynamic_zone_members_repository.h" +#include "repositories/dynamic_zone_templates_repository.h" #include #include #include @@ -74,6 +75,7 @@ public: virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0; + int GetDuration() const { return static_cast(m_duration.count()); } uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); } uint32_t GetID() const { return m_id; } uint16_t GetInstanceID() const { return static_cast(m_instance_id); } @@ -85,6 +87,7 @@ public: uint16_t GetZoneID() const { return static_cast(m_zone_id); } uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); } uint32_t GetZoneVersion() const { return m_zone_version; } + int GetSwitchID() const { return m_dz_switch_id; } DynamicZoneType GetType() const { return m_type; } const std::string& GetLeaderName() const { return m_leader.name; } const std::string& GetName() const { return m_name; } @@ -112,6 +115,7 @@ public: bool IsValid() const { return m_instance_id != 0; } bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; } void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size); + void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template); void RemoveAllMembers(); bool RemoveMember(uint32_t character_id); bool RemoveMember(const std::string& character_name); @@ -127,6 +131,7 @@ public: void SetName(const std::string& name) { m_name = name; } void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false); void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false); + void SetSwitchID(int dz_switch_id, bool update_db = false); void SetType(DynamicZoneType type) { m_type = type; } void SetUUID(std::string uuid) { m_uuid = std::move(uuid); } void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false); @@ -141,6 +146,7 @@ protected: virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed); virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status); virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); } + virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; } virtual bool SendServerPacket(ServerPacket* packet) = 0; void AddInternalMember(const DynamicZoneMember& member); @@ -153,6 +159,7 @@ protected: std::unique_ptr CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id); std::unique_ptr CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location); + std::unique_ptr CreateServerDzSwitchIDPacket(); std::unique_ptr CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed); std::unique_ptr CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status); std::unique_ptr CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member); @@ -164,6 +171,7 @@ protected: uint32_t m_zone_version = 0; uint32_t m_min_players = 0; uint32_t m_max_players = 0; + int m_dz_switch_id = 0; bool m_never_expires = false; bool m_has_zonein = false; bool m_has_member_statuses = false; @@ -190,6 +198,7 @@ public: m_zone_version, m_min_players, m_max_players, + m_dz_switch_id, m_never_expires, m_has_zonein, m_has_member_statuses, diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp index 4d5c40b64..4d60b4297 100644 --- a/common/emu_constants.cpp +++ b/common/emu_constants.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -18,10 +18,12 @@ */ #include "emu_constants.h" -#include "languages.h" -#include "data_verification.h" #include "bodytypes.h" - +#include "data_verification.h" +#include "eqemu_logsys.h" +#include "eqemu_logsys_log_aliases.h" +#include "languages.h" +#include "rulesys.h" int16 EQ::invtype::GetInvTypeSize(int16 inv_type) { static const int16 local_array[] = { @@ -118,7 +120,7 @@ EQ::bug::CategoryID EQ::bug::CategoryNameToCategoryID(const char* category_name) return catLoNTCG; if (!strcmp(category_name, "Mercenaries")) return catMercenaries; - + return catOther; } @@ -189,15 +191,16 @@ const std::map& EQ::constants::GetLanguageMap() { LANG_HADAL, "Hadal" }, { LANG_UNKNOWN, "Unknown" } }; + return language_map; } std::string EQ::constants::GetLanguageName(int language_id) { if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) { - auto languages = EQ::constants::GetLanguageMap(); - return languages[language_id]; + return EQ::constants::GetLanguageMap().find(language_id)->second; } + return std::string(); } @@ -211,21 +214,22 @@ const std::map& EQ::constants::GetLDoNThemeMap() { LDoNThemes::RUJ, "Rujarkian Hills" }, { LDoNThemes::TAK, "Takish-Hiz" }, }; + return ldon_theme_map; } std::string EQ::constants::GetLDoNThemeName(uint32 theme_id) { if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) { - auto ldon_themes = EQ::constants::GetLDoNThemeMap(); - return ldon_themes[theme_id]; + return EQ::constants::GetLDoNThemeMap().find(theme_id)->second; } - return std::string(); + + return std::string(); } -const std::map& EQ::constants::GetFlyModeMap() +const std::map& EQ::constants::GetFlyModeMap() { - static const std::map flymode_map = { + static const std::map flymode_map = { { GravityBehavior::Ground, "Ground" }, { GravityBehavior::Flying, "Flying" }, { GravityBehavior::Levitating, "Levitating" }, @@ -233,15 +237,16 @@ const std::map& EQ::constants::GetFlyModeMap() { GravityBehavior::Floating, "Floating" }, { GravityBehavior::LevitateWhileRunning, "Levitating While Running" }, }; + return flymode_map; } -std::string EQ::constants::GetFlyModeName(uint8 flymode_id) +std::string EQ::constants::GetFlyModeName(int8 flymode_id) { if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) { - auto flymodes = EQ::constants::GetFlyModeMap(); - return flymodes[flymode_id]; + return EQ::constants::GetFlyModeMap().find(flymode_id)->second; } + return std::string(); } @@ -288,15 +293,16 @@ const std::map& EQ::constants::GetBodyTypeMap() { BT_InvisMan, "Invisible Man" }, { BT_Special, "Special" }, }; + return bodytype_map; } std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id) { - auto bodytypes = EQ::constants::GetBodyTypeMap(); - if (!bodytypes[bodytype_id].empty()) { - return bodytypes[bodytype_id]; + if (EQ::constants::GetBodyTypeMap().find(bodytype_id) != EQ::constants::GetBodyTypeMap().end()) { + return EQ::constants::GetBodyTypeMap().find(bodytype_id)->second; } + return std::string(); } @@ -318,24 +324,26 @@ const std::map& EQ::constants::GetAccountStatusMap() { AccountStatus::GMAreas, "GM Areas" }, { AccountStatus::GMCoder, "GM Coder" }, { AccountStatus::GMMgmt, "GM Mgmt" }, - { AccountStatus::GMImpossible, "GM Impossible" }, + { AccountStatus::GMImpossible, "GM Impossible" }, { AccountStatus::Max, "GM Max" } }; + return account_status_map; } std::string EQ::constants::GetAccountStatusName(uint8 account_status) { - auto account_statuses = EQ::constants::GetAccountStatusMap(); - std::string status_name; - for (auto status_level = account_statuses.rbegin(); status_level != account_statuses.rend(); ++status_level) { + for ( + auto status_level = EQ::constants::GetAccountStatusMap().rbegin(); + status_level != EQ::constants::GetAccountStatusMap().rend(); + ++status_level + ) { if (account_status >= status_level->first) { - status_name = status_level->second; - break; + return status_level->second; } } - return status_name; + return std::string(); } const std::map& EQ::constants::GetConsiderLevelMap() @@ -351,15 +359,16 @@ const std::map& EQ::constants::GetConsiderLevelMap() { ConsiderLevel::Threateningly, "Threateningly" }, { ConsiderLevel::Scowls, "Scowls" } }; + return consider_level_map; } std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level) { - auto consider_levels = EQ::constants::GetConsiderLevelMap(); - if (!consider_levels[faction_consider_level].empty()) { - return consider_levels[faction_consider_level]; + if (EQ::constants::GetConsiderLevelMap().find(faction_consider_level) != EQ::constants::GetConsiderLevelMap().end()) { + return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second; } + return std::string(); } @@ -371,14 +380,202 @@ const std::map& EQ::constants::GetEnvironmentalDamageMap() { EnvironmentalDamage::Falling, "Falling" }, { EnvironmentalDamage::Trap, "Trap" } }; + return damage_type_map; } std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type) { if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) { - auto damage_types = EQ::constants::GetEnvironmentalDamageMap(); - return damage_types[damage_type]; + return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second; } + + return std::string(); +} + +const std::map& EQ::constants::GetStuckBehaviorMap() +{ + static const std::map stuck_behavior_map = { + { StuckBehavior::RunToTarget, "Run To Target" }, + { StuckBehavior::WarpToTarget, "Warp To Target" }, + { StuckBehavior::TakeNoAction, "Take No Action" }, + { StuckBehavior::EvadeCombat, "Evade Combat" } + }; + + return stuck_behavior_map; +} + +std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id) +{ + if (EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) { + return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second; + } + + return std::string(); +} + +const std::map& EQ::constants::GetSpawnAnimationMap() +{ + static const std::map spawn_animation_map = { + { SpawnAnimations::Standing, "Standing" }, + { SpawnAnimations::Sitting, "Sitting" }, + { SpawnAnimations::Crouching, "Crouching" }, + { SpawnAnimations::Laying, "Laying" }, + { SpawnAnimations::Looting, "Looting" } + }; + + return spawn_animation_map; +} + +std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id) +{ + if (EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) { + return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second; + } + + return std::string(); +} + +const std::map& EQ::constants::GetObjectTypeMap() +{ + static const std::map object_type_map = { + { ObjectTypes::SmallBag, "Small Bag" }, + { ObjectTypes::LargeBag, "Large Bag" }, + { ObjectTypes::Quiver, "Quiver" }, + { ObjectTypes::BeltPouch, "Belt Pouch" }, + { ObjectTypes::WristPouch, "Wrist Pouch" }, + { ObjectTypes::Backpack, "Backpack" }, + { ObjectTypes::SmallChest, "Small Chest" }, + { ObjectTypes::LargeChest, "Large Chest" }, + { ObjectTypes::Bandolier, "Bandolier" }, + { ObjectTypes::Medicine, "Medicine" }, + { ObjectTypes::Tinkering, "Tinkering" }, + { ObjectTypes::Lexicon, "Lexicon" }, + { ObjectTypes::PoisonMaking, "Mortar and Pestle" }, + { ObjectTypes::Quest, "Quest" }, + { ObjectTypes::MixingBowl, "Mixing Bowl" }, + { ObjectTypes::Baking, "Baking" }, + { ObjectTypes::Tailoring, "Tailoring" }, + { ObjectTypes::Blacksmithing, "Blacksmithing" }, + { ObjectTypes::Fletching, "Fletching" }, + { ObjectTypes::Brewing, "Brewing" }, + { ObjectTypes::JewelryMaking, "Jewelry Making" }, + { ObjectTypes::Pottery, "Pottery" }, + { ObjectTypes::Kiln, "Kiln" }, + { ObjectTypes::KeyMaker, "Key Maker" }, + { ObjectTypes::ResearchWIZ, "Lexicon" }, + { ObjectTypes::ResearchMAG, "Lexicon" }, + { ObjectTypes::ResearchNEC, "Lexicon" }, + { ObjectTypes::ResearchENC, "Lexicon" }, + { ObjectTypes::Unknown, "Unknown" }, + { ObjectTypes::ResearchPractice, "Lexicon" }, + { ObjectTypes::Alchemy, "Alchemy" }, + { ObjectTypes::HighElfForge, "High Elf Forge" }, + { ObjectTypes::DarkElfForge, "Dark Elf Forge" }, + { ObjectTypes::OgreForge, "Ogre Forge" }, + { ObjectTypes::DwarfForge, "Dwarf Forge" }, + { ObjectTypes::GnomeForge, "Gnome Forge" }, + { ObjectTypes::BarbarianForge, "Barbarian Forge" }, + { ObjectTypes::IksarForge, "Iksar Forge" }, + { ObjectTypes::HumanForgeOne, "Human Forge" }, + { ObjectTypes::HumanForgeTwo, "Human Forge" }, + { ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" }, + { ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" }, + { ObjectTypes::EruditeTailoring, "Erudite Tailoring" }, + { ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" }, + { ObjectTypes::WoodElfFletching, "Wood Elf Fletching" }, + { ObjectTypes::IksarPottery, "Iksar Pottery" }, + { ObjectTypes::Fishing, "Fishing" }, + { ObjectTypes::TrollForge, "Troll Forge" }, + { ObjectTypes::WoodElfForge, "Wood Elf Forge" }, + { ObjectTypes::HalflingForge, "Halfling Forge" }, + { ObjectTypes::EruditeForge, "Erudite Forge" }, + { ObjectTypes::Merchant, "Merchant" }, + { ObjectTypes::FroglokForge, "Froglok Forge" }, + { ObjectTypes::Augmenter, "Augmenter" }, + { ObjectTypes::Churn, "Churn" }, + { ObjectTypes::TransformationMold, "Transformation Mold" }, + { ObjectTypes::DetransformationMold, "Detransformation Mold" }, + { ObjectTypes::Unattuner, "Unattuner" }, + { ObjectTypes::TradeskillBag, "Tradeskill Bag" }, + { ObjectTypes::CollectibleBag, "Collectible Bag" }, + { ObjectTypes::NoDeposit, "No Deposit" } + }; + + return object_type_map; +} + +std::string EQ::constants::GetObjectTypeName(int object_type) +{ + if (EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) { + return EQ::constants::GetObjectTypeMap().find(object_type)->second; + } + + return std::string(); +} + +const std::map &EQ::constants::GetWeatherTypeMap() +{ + static const std::map weather_type_map = { + {WeatherTypes::None, "None"}, + {WeatherTypes::Raining, "Raining"}, + {WeatherTypes::Snowing, "Snowing"} + }; + + return weather_type_map; +} + +std::string EQ::constants::GetWeatherTypeName(uint8 weather_type) +{ + if (EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) { + return EQ::constants::GetWeatherTypeMap().find(weather_type)->second; + } + + return std::string(); +} + +const std::map &EQ::constants::GetEmoteEventTypeMap() +{ + static const std::map emote_event_type_map = { + { EmoteEventTypes::LeaveCombat, "Leave Combat" }, + { EmoteEventTypes::EnterCombat, "Enter Combat" }, + { EmoteEventTypes::OnDeath, "On Death" }, + { EmoteEventTypes::AfterDeath, "After Death" }, + { EmoteEventTypes::Hailed, "Hailed" }, + { EmoteEventTypes::KilledPC, "Killed PC" }, + { EmoteEventTypes::KilledNPC, "Killed NPC" }, + { EmoteEventTypes::OnSpawn, "On Spawn" }, + { EmoteEventTypes::OnDespawn, "On Despawn" } + }; + + return emote_event_type_map; +} + +std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type) +{ + if (EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) { + return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second; + } + + return std::string(); +} + +const std::map &EQ::constants::GetEmoteTypeMap() +{ + static const std::map emote_type_map = { + { EmoteTypes::Emote, "Emote" }, + { EmoteTypes::Shout, "Shout" }, + { EmoteTypes::Proximity, "Proximity" } + }; + + return emote_type_map; +} + +std::string EQ::constants::GetEmoteTypeName(uint8 emote_type) +{ + if (EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) { + return EQ::constants::GetEmoteTypeMap().find(emote_type)->second; + } + return std::string(); } diff --git a/common/emu_constants.h b/common/emu_constants.h index 80e7a0b05..0d18f1179 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -32,10 +32,6 @@ namespace EQ { using RoF2::IINVALID; using RoF2::INULL; - - namespace inventory { - - } /*inventory*/ namespace invtype { using namespace RoF2::invtype::enum_; @@ -201,7 +197,7 @@ namespace EQ using RoF2::constants::EXPANSIONS_MASK; using RoF2::constants::CHARACTER_CREATION_LIMIT; - + const size_t SAY_LINK_OPENER_SIZE = 1; using RoF2::constants::SAY_LINK_BODY_SIZE; const size_t SAY_LINK_TEXT_SIZE = 256; // this may be varied until it breaks something (tested:374) - the others are constant @@ -221,7 +217,26 @@ namespace EQ stanceBurnAE }; - enum GravityBehavior : uint8 { + enum BotSpellIDs : int { + Warrior = 3001, + Cleric, + Paladin, + Ranger, + Shadowknight, + Druid, + Monk, + Bard, + Rogue, + Shaman, + Necromancer, + Wizard, + Magician, + Enchanter, + Beastlord, + Berserker + }; + + enum GravityBehavior : int8 { Ground, Flying, Levitating, @@ -237,6 +252,109 @@ namespace EQ Trap }; + enum StuckBehavior : uint8 { + RunToTarget, + WarpToTarget, + TakeNoAction, + EvadeCombat + }; + + enum SpawnAnimations : uint8 { + Standing, + Sitting, + Crouching, + Laying, + Looting + }; + + enum ObjectTypes : int { + SmallBag, + LargeBag, + Quiver, + BeltPouch, + WristPouch, + Backpack, + SmallChest, + LargeChest, + Bandolier, + Medicine, + Tinkering, + Lexicon, + PoisonMaking, + Quest, + MixingBowl, + Baking, + Tailoring, + Blacksmithing, + Fletching, + Brewing, + JewelryMaking, + Pottery, + Kiln, + KeyMaker, + ResearchWIZ, + ResearchMAG, + ResearchNEC, + ResearchENC, + Unknown, + ResearchPractice, + Alchemy, + HighElfForge, + DarkElfForge, + OgreForge, + DwarfForge, + GnomeForge, + BarbarianForge, + IksarForge, + HumanForgeOne, + HumanForgeTwo, + HalflingTailoringOne, + HalflingTailoringTwo, + EruditeTailoring, + WoodElfTailoring, + WoodElfFletching, + IksarPottery, + Fishing, + TrollForge, + WoodElfForge, + HalflingForge, + EruditeForge, + Merchant, + FroglokForge, + Augmenter, + Churn, + TransformationMold, + DetransformationMold, + Unattuner, + TradeskillBag, + CollectibleBag, + NoDeposit + }; + + enum WeatherTypes : uint8 { + None, + Raining, + Snowing + }; + + enum EmoteEventTypes : uint8 { + LeaveCombat, + EnterCombat, + OnDeath, + AfterDeath, + Hailed, + KilledPC, + KilledNPC, + OnSpawn, + OnDespawn + }; + + enum EmoteTypes : uint8 { + Emote, + Shout, + Proximity + }; + const char *GetStanceName(StanceType stance_type); int ConvertStanceTypeToIndex(StanceType stance_type); @@ -245,9 +363,9 @@ namespace EQ extern const std::map& GetLDoNThemeMap(); std::string GetLDoNThemeName(uint32 theme_id); - - extern const std::map& GetFlyModeMap(); - std::string GetFlyModeName(uint8 flymode_id); + + extern const std::map& GetFlyModeMap(); + std::string GetFlyModeName(int8 flymode_id); extern const std::map& GetBodyTypeMap(); std::string GetBodyTypeName(bodyType bodytype_id); @@ -261,6 +379,24 @@ namespace EQ extern const std::map& GetEnvironmentalDamageMap(); std::string GetEnvironmentalDamageName(uint8 damage_type); + extern const std::map& GetStuckBehaviorMap(); + std::string GetStuckBehaviorName(uint8 behavior_id); + + extern const std::map& GetSpawnAnimationMap(); + std::string GetSpawnAnimationName(uint8 animation_id); + + extern const std::map& GetObjectTypeMap(); + std::string GetObjectTypeName(int object_type); + + extern const std::map& GetWeatherTypeMap(); + std::string GetWeatherTypeName(uint8 weather_type); + + extern const std::map& GetEmoteEventTypeMap(); + std::string GetEmoteEventTypeName(uint8 emote_event_type); + + extern const std::map& GetEmoteTypeMap(); + std::string GetEmoteTypeName(uint8 emote_type); + const int STANCE_TYPE_FIRST = stancePassive; const int STANCE_TYPE_LAST = stanceBurnAE; const int STANCE_TYPE_COUNT = stanceBurnAE; @@ -270,7 +406,7 @@ namespace EQ namespace profile { using RoF2::profile::BANDOLIERS_SIZE; using RoF2::profile::BANDOLIER_ITEM_COUNT; - + using RoF2::profile::POTION_BELT_SIZE; using RoF2::profile::SKILL_ARRAY_SIZE; @@ -431,7 +567,7 @@ enum ReloadWorld : uint8 { ForceRepop }; -enum MerchantBucketComparison : uint8 { +enum BucketComparison : uint8 { BucketEqualTo = 0, BucketNotEqualTo, BucketGreaterThanOrEqualTo, @@ -444,4 +580,17 @@ enum MerchantBucketComparison : uint8 { BucketIsNotBetween }; +enum class EntityFilterType { + All, + Bots, + Clients, + NPCs +}; + +enum class ApplySpellType { + Solo, + Group, + Raid +}; + #endif /*COMMON_EMU_CONSTANTS_H*/ diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 2af98de1c..d8798c594 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest), N(OP_AltCurrencyPurchase), N(OP_AltCurrencyReclaim), N(OP_AltCurrencySell), -N(OP_AltCurrencySellSelection), +N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069 N(OP_Animation), N(OP_AnnoyingZoneUnknown), N(OP_ApplyPoison), @@ -71,6 +71,7 @@ N(OP_Camp), N(OP_CancelSneakHide), N(OP_CancelTask), N(OP_CancelTrade), +N(OP_CashReward), N(OP_CastSpell), N(OP_ChangeSize), N(OP_ChannelMessage), @@ -303,6 +304,7 @@ N(OP_LockoutTimerInfo), N(OP_Login), N(OP_LoginAccepted), N(OP_LoginComplete), +N(OP_LoginExpansionPacketData), //added for Rof2 client to send expansion data packet. Requires login_opcodes_sod.conf to be updated. N(OP_LoginUnknown1), N(OP_LoginUnknown2), N(OP_Logout), diff --git a/common/eq_constants.h b/common/eq_constants.h index 8949ea109..ce65ab59b 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -684,14 +684,6 @@ namespace Zones { constexpr uint16 APPRENTICE = 999; // Designer Apprentice } -//ZoneChange_Struct->success values -#define ZONE_ERROR_NOMSG 0 -#define ZONE_ERROR_NOTREADY -1 -#define ZONE_ERROR_VALIDPC -2 -#define ZONE_ERROR_STORYZONE -3 -#define ZONE_ERROR_NOEXPANSION -6 -#define ZONE_ERROR_NOEXPERIENCE -7 - typedef enum { FilterNone = 0, @@ -718,7 +710,7 @@ typedef enum { FilterPetMisses = 21, //0=show, 1=hide FilterFocusEffects = 22, //0=show, 1=hide FilterPetSpells = 23, //0=show, 1=hide - FilterHealOverTime = 24, //0=show, 1=hide + FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide FilterUnknown25 = 25, FilterUnknown26 = 26, FilterUnknown27 = 27, @@ -1009,4 +1001,29 @@ enum StartZoneIndex { SharVahl }; +enum FVNoDropFlagRule +{ + Disabled = 0, + Enabled = 1, + AdminOnly = 2 +}; + +enum Anonymity : uint8 +{ + NotAnonymous, + Anonymous, + Roleplaying +}; + +enum ZoningMessage : int8 +{ + ZoneNoMessage = 0, + ZoneSuccess = 1, + ZoneNotReady = -1, + ZoneValidPC = -2, + ZoneStoryZone = -3, + ZoneNoExpansion = -6, + ZoneNoExperience = -7 +}; + #endif /*COMMON_EQ_CONSTANTS_H*/ diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 188c8f888..051857681 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -11,7 +11,7 @@ are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -26,7 +26,7 @@ static bool global_dictionary_init = false; void EQ::InitializeDynamicLookups() { - if (global_dictionary_init == true) + if (global_dictionary_init) return; constants::InitializeDynamicLookups(); @@ -167,7 +167,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL ), - + ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, @@ -175,7 +175,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, - + false, false, false, @@ -194,7 +194,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers Client62::INULL, Client62::INULL, Client62::INULL, Client62::INULL ), - + Client62::INULL, Client62::INULL, Client62::INULL, @@ -202,7 +202,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers Client62::INULL, Client62::INULL, Client62::INULL, - + false, false, false, @@ -221,7 +221,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers Titanium::INULL, Titanium::INULL, Titanium::INULL, Titanium::invtype::OTHER_SIZE ), - + Titanium::invslot::EQUIPMENT_BITMASK, Titanium::invslot::GENERAL_BITMASK, Titanium::invslot::CURSOR_BITMASK, @@ -229,7 +229,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers Titanium::invslot::CORPSE_BITMASK, Titanium::invbag::SLOT_COUNT, Titanium::invaug::SOCKET_COUNT, - + Titanium::inventory::AllowEmptyBagInBag, Titanium::inventory::AllowClickCastFromBag, Titanium::inventory::ConcatenateInvTypeLimbo, @@ -248,7 +248,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers SoF::INULL, SoF::INULL, SoF::INULL, SoF::invtype::OTHER_SIZE ), - + SoF::invslot::EQUIPMENT_BITMASK, SoF::invslot::GENERAL_BITMASK, SoF::invslot::CURSOR_BITMASK, @@ -256,7 +256,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers SoF::invslot::CORPSE_BITMASK, SoF::invbag::SLOT_COUNT, SoF::invaug::SOCKET_COUNT, - + SoF::inventory::AllowEmptyBagInBag, SoF::inventory::AllowClickCastFromBag, SoF::inventory::ConcatenateInvTypeLimbo, @@ -763,7 +763,7 @@ void EQ::inventory::InitializeDynamicLookups() { // Notes: // - Currently, there are only 3 known expansions that affect inventory-related settings in the clients.. // -- Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots - // -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear) + // -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear) // -- Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 activated (set) and deactivated (clear) // - Corspe size does not appear to reflect loss of active possessions slots // - Inspect size does not appear to reflect loss of active equipment slots @@ -772,7 +772,7 @@ void EQ::inventory::InitializeDynamicLookups() { // - General9 and General10 slots are activated by GM flag when expansion bit is (clear) // - Obviously, the client must support the expansion to allow any (set) or override condition - const uint32 dynamic_check_mask = + const uint32 dynamic_check_mask = ( EQ::expansions::bitPoR | EQ::expansions::bitTBS | @@ -1210,10 +1210,10 @@ void EQ::spells::InitializeDynamicLookups() { if (spells_dictionary_init == true) return; spells_dictionary_init = true; - + if (RuleB(World, UseClientBasedExpansionSettings)) return; - + // use static references for now } @@ -1239,7 +1239,7 @@ const EQ::spells::LookupEntry* EQ::spells::DynamicGMLookup(versions::ClientVersi client_version = versions::ValidateClientVersion(client_version); if (spells_dynamic_gm_lookup_entries[static_cast(client_version)]) return spells_dynamic_gm_lookup_entries[static_cast(client_version)].get(); - + return &spells_static_lookup_entries[static_cast(client_version)]; } diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 47bfabb23..979c8b86e 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -374,18 +374,18 @@ struct NewZone_Struct { /*0684*/ uint16 zone_id; /*0686*/ uint16 zone_instance; /*0688*/ uint32 unknown688; -/*0692*/ uint8 unknown692[8]; +/*0692*/ uint8 unknown692[8]; // Titanium doesn't have a translator, but we can still safely add stuff under here without issues since client memcpy's only what it knows // Just wastes some bandwidth sending to tit clients /shrug -/*0700*/ float fog_density; -/*0704*/ uint32 SuspendBuffs; -/*0708*/ uint32 FastRegenHP; -/*0712*/ uint32 FastRegenMana; -/*0716*/ uint32 FastRegenEndurance; -/*0720*/ uint32 NPCAggroMaxDist; -/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld -/*0728*/ uint32 LavaDamage; // Seen 50 -/*0732*/ uint32 MinLavaDamage; // Seen 10 +/*0700*/ float fog_density; +/*0704*/ uint32 suspend_buffs; +/*0708*/ uint32 fast_regen_hp; +/*0712*/ uint32 fast_regen_mana; +/*0716*/ uint32 fast_regen_endurance; +/*0720*/ uint32 npc_aggro_max_dist; +/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld +/*0728*/ uint32 lava_damage; // Seen 50 +/*0732*/ uint32 min_lava_damage; // Seen 10 /*0736*/ }; @@ -2192,11 +2192,19 @@ struct QuestReward_Struct /*068*/ }; +struct CashReward_Struct +{ + /*000*/ uint32 copper; + /*004*/ uint32 silver; + /*008*/ uint32 gold; + /*012*/ uint32 platinum; +}; + // Size: 8 struct Camera_Struct { uint32 duration; // Duration in ms - uint32 intensity; // Between 1023410176 and 1090519040 + float intensity; }; struct ZonePoint_Entry { @@ -3634,7 +3642,7 @@ struct MerchantList { uint8 probability; std::string bucket_name; std::string bucket_value; - uint8 bucket_comparison; + uint8 bucket_comparison; }; struct TempMerchantList { @@ -4998,7 +5006,7 @@ struct DynamicZoneCompassEntry_Struct /*000*/ uint16 dz_zone_id; // target dz id pair /*002*/ uint16 dz_instance_id; /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) -/*008*/ uint32 unknown008; +/*008*/ uint32 dz_switch_id; /*012*/ float y; /*016*/ float x; /*020*/ float z; @@ -5155,10 +5163,10 @@ struct AltCurrencySelectItemReply_Struct { /*000*/ uint32 unknown000; /*004*/ uint8 unknown004; //0xff /*005*/ uint8 unknown005; //0xff -/*006*/ uint8 unknown006; //0xff -/*007*/ uint8 unknown007; //0xff -/*008*/ char item_name[64]; -/*072*/ uint32 unknown074; +/*006*/ uint16 unknown006; //0xffff +/*008*/ uint16 unknown008; //0xffff +/*010*/ char item_name[64]; +/*074*/ uint16 unknown074; /*076*/ uint32 cost; /*080*/ uint32 unknown080; /*084*/ uint32 unknown084; diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 61162580a..0182c53f4 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -23,7 +23,7 @@ #include "op_codes.h" #include "crc16.h" #include "platform.h" -#include "string_util.h" +#include "strings.h" #include #include @@ -406,7 +406,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { LogNetcode(_L "Pre-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } - + //if the packet they got out of order is between our last acked packet and the last sent packet, then its valid. if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) { Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, @@ -453,7 +453,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) (unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta), (unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta), (unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta)); - + AdjustRates(ntohl(ClientStats->average_delta)); if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { @@ -951,7 +951,7 @@ EQRawApplicationPacket *p=nullptr; EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); if (emu_op == OP_Unknown) { // Log(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str()); - } + } p->SetOpcode(emu_op); } } @@ -1359,11 +1359,11 @@ void EQStream::AdjustRates(uint32 average_delta) DecayRate=DECAYBASE/average_delta; if (BytesWritten > RateThreshold) BytesWritten = RateThreshold + DecayRate; - Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, + Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, RateThreshold, DecayRate, average_delta); MRate.unlock(); } else { - Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, + Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, average_delta, AVERAGE_DELTA_MAX); AverageDelta = AVERAGE_DELTA_MAX; } @@ -1374,7 +1374,7 @@ void EQStream::AdjustRates(uint32 average_delta) BytesWritten = 0; RateThreshold=RATEBASE/average_delta; DecayRate=DECAYBASE/average_delta; - Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, + Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, RateThreshold, DecayRate, average_delta); MRate.unlock(); } diff --git a/common/eq_stream.h b/common/eq_stream.h index 6f43cc337..a05fb5319 100644 --- a/common/eq_stream.h +++ b/common/eq_stream.h @@ -218,13 +218,13 @@ class EQStream : public EQStreamInterface { void init(bool resetSession=true); public: - EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED; - StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2; - bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0; + EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED; + StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2; + bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0; streamactive = false; } - EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr; - remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream; - compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0; + EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr; + remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream; + compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); } virtual ~EQStream() { RemoveData(); SetState(CLOSED); } void SetMaxLen(uint32 length) { MaxLen=length; } @@ -243,6 +243,11 @@ class EQStream : public EQStreamInterface { virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; } + virtual OpcodeManager* GetOpcodeManager() const + { + return (*OpMgr); + }; + void CheckTimeout(uint32 now, uint32 timeout=30); bool HasOutgoingData(); void Process(const unsigned char *data, const uint32 length); diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index b2c889244..e2b7b21c7 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -30,7 +30,7 @@ struct EQStreamManagerInterfaceOptions //World seems to support both compression and xor zone supports one or the others. //Enforce one or the other in the convienence construct - //Login I had trouble getting to recognize compression at all + //Login I had trouble getting to recognize compression at all //but that might be because it was still a bit buggy when i was testing that. if (compressed) { daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression; @@ -100,6 +100,7 @@ public: virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; } virtual EQStreamState GetState() = 0; virtual void SetOpcodeManager(OpcodeManager **opm) = 0; + virtual OpcodeManager* GetOpcodeManager() const = 0; virtual const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; } virtual Stats GetStats() const = 0; virtual void ResetStats() = 0; diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index ca8cb2142..824e68013 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -38,12 +38,8 @@ void EQStreamProxy::SetOpcodeManager(OpcodeManager **opm) } void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) { - if(p == nullptr) + if (p == nullptr) { return; - - if (p->GetOpcode() != OP_SpecialMesg) { - Log(Logs::General, Logs::PacketServerClient, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size()); - Log(Logs::General, Logs::PacketServerClientWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str()); } EQApplicationPacket *newp = p->Copy(); @@ -112,3 +108,8 @@ bool EQStreamProxy::CheckState(EQStreamState state) { return false; } +OpcodeManager *EQStreamProxy::GetOpcodeManager() const +{ + return (*m_opcodes); +} + diff --git a/common/eq_stream_proxy.h b/common/eq_stream_proxy.h index 9d007b48e..fce5b557f 100644 --- a/common/eq_stream_proxy.h +++ b/common/eq_stream_proxy.h @@ -34,13 +34,15 @@ public: virtual Stats GetStats() const; virtual void ResetStats(); virtual EQStreamManagerInterface* GetManager() const; + virtual OpcodeManager* GetOpcodeManager() const; protected: std::shared_ptr const m_stream; //we own this stream object. const StructStrategy *const m_structs; //we do not own this object. //this is a pointer to a pointer to make it less likely that a packet will //reference an invalid opcode manager when they are being reloaded. - OpcodeManager **const m_opcodes; //we do not own this object. + OpcodeManager **const m_opcodes; + //we do not own this object. }; #endif /*EQSTREAMPROXY_H_*/ diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 1790e7788..85161ba8a 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -100,6 +100,10 @@ void EQEmuConfig::parse_config() WorldHTTPEnabled = true; } + if (_root["server"].get("disable_config_checks", "false").asString() == "true") { + DisableConfigChecks = true; + } + /** * UCS */ diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 2f36a6317..d0434399a 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -20,7 +20,9 @@ #include "json/json.h" #include "linked_list.h" +#include "path_manager.h" #include +#include struct LoginConfig { std::string LoginHost; @@ -58,6 +60,7 @@ class EQEmuConfig uint16 WorldHTTPPort; std::string WorldHTTPMimeFile; std::string SharedKey; + bool DisableConfigChecks; // From std::string ChatHost; @@ -130,7 +133,7 @@ class EQEmuConfig void parse_config(); EQEmuConfig() - { + { } virtual ~EQEmuConfig() {} @@ -151,30 +154,38 @@ class EQEmuConfig } // Load the config - static bool LoadConfig() + static bool LoadConfig(const std::string& path = "") { if (_config != nullptr) { return true; } _config = new EQEmuConfig; - return parseFile(); + return parseFile(path); } // Load config file and parse data - static bool parseFile() { + static bool parseFile(const std::string& file_path = ".") + { if (_config == nullptr) { - return LoadConfig(); + return LoadConfig(file_path); } - std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary); + std::string file = fmt::format( + "{}/{}", + (file_path.empty() ? path.GetServerPath() : file_path), + EQEmuConfig::ConfigFile + ); + + std::ifstream fconfig(file, std::ifstream::binary); + try { fconfig >> _config->_root; _config->parse_config(); } catch (std::exception &) { return false; - } + } return true; } diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 8365e6989..078c17455 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -21,20 +21,20 @@ #include "eqemu_logsys.h" #include "rulesys.h" #include "platform.h" -#include "string_util.h" -#include "misc.h" +#include "strings.h" +#include "repositories/discord_webhooks_repository.h" #include "repositories/logsys_categories_repository.h" +#include "termcolor/rang.hpp" #include -#include #include -#include #include #include -#include std::ofstream process_log; +#include + #ifdef _WINDOWS #include #include @@ -46,50 +46,17 @@ std::ofstream process_log; #include #include +#include #endif -/** - * Linux ANSI console color defines - */ -#define LC_RESET "\033[0m" -#define LC_BLACK "\033[30m" /* Black */ -#define LC_RED "\033[31m" /* Red */ -#define LC_GREEN "\033[32m" /* Green */ -#define LC_YELLOW "\033[33m" /* Yellow */ -#define LC_BLUE "\033[34m" /* Blue */ -#define LC_MAGENTA "\033[35m" /* Magenta */ -#define LC_CYAN "\033[36m" /* Cyan */ -#define LC_WHITE "\033[37m" /* White */ - -namespace Console { - enum Color { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Magenta = 5, - Brown = 6, - LightGray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - LightMagenta = 13, - Yellow = 14, - White = 15 - }; -} - /** * EQEmuLogSys Constructor */ EQEmuLogSys::EQEmuLogSys() { - on_log_gmsay_hook = [](uint16 log_type, const std::string &) {}; - on_log_console_hook = [](uint16 debug_level, uint16 log_type, const std::string &) {}; + m_on_log_gmsay_hook = [](uint16 log_type, const char *func, const std::string &) {}; + m_on_log_console_hook = [](uint16 log_type, const std::string &) {}; } /** @@ -102,28 +69,23 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults() /** * Get Executable platform currently running this code (Zone/World/etc) */ - log_platform = GetExecutablePlatformInt(); + m_log_platform = GetExecutablePlatformInt(); for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) { log_settings[log_category_id].log_to_console = 0; log_settings[log_category_id].log_to_file = 0; log_settings[log_category_id].log_to_gmsay = 0; + log_settings[log_category_id].log_to_discord = 0; log_settings[log_category_id].is_category_enabled = 0; } - file_logs_enabled = false; + m_file_logs_enabled = false; /** * Set Defaults */ - log_settings[Logs::WorldServer].log_to_console = static_cast(Logs::General); - log_settings[Logs::ZoneServer].log_to_console = static_cast(Logs::General); - log_settings[Logs::QSServer].log_to_console = static_cast(Logs::General); - log_settings[Logs::UCSServer].log_to_console = static_cast(Logs::General); log_settings[Logs::Crash].log_to_console = static_cast(Logs::General); log_settings[Logs::MySQLError].log_to_console = static_cast(Logs::General); - log_settings[Logs::Loginserver].log_to_console = static_cast(Logs::General); - log_settings[Logs::HeadlessClient].log_to_console = static_cast(Logs::General); log_settings[Logs::NPCScaling].log_to_gmsay = static_cast(Logs::General); log_settings[Logs::HotReload].log_to_gmsay = static_cast(Logs::General); log_settings[Logs::HotReload].log_to_console = static_cast(Logs::General); @@ -135,16 +97,15 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults() log_settings[Logs::ChecksumVerification].log_to_console = static_cast(Logs::General); log_settings[Logs::ChecksumVerification].log_to_gmsay = static_cast(Logs::General); log_settings[Logs::CombatRecord].log_to_gmsay = static_cast(Logs::General); + log_settings[Logs::Discord].log_to_console = static_cast(Logs::General); + log_settings[Logs::QuestErrors].log_to_gmsay = static_cast(Logs::General); + log_settings[Logs::QuestErrors].log_to_console = static_cast(Logs::General); /** * RFC 5424 */ - log_settings[Logs::Emergency].log_to_console = static_cast(Logs::General); - log_settings[Logs::Alert].log_to_console = static_cast(Logs::General); - log_settings[Logs::Critical].log_to_console = static_cast(Logs::General); log_settings[Logs::Error].log_to_console = static_cast(Logs::General); log_settings[Logs::Warning].log_to_console = static_cast(Logs::General); - log_settings[Logs::Notice].log_to_console = static_cast(Logs::General); log_settings[Logs::Info].log_to_console = static_cast(Logs::General); /** @@ -154,7 +115,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults() const bool log_to_console = log_settings[log_category_id].log_to_console > 0; const bool log_to_file = log_settings[log_category_id].log_to_file > 0; const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0; - const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay; + const bool log_to_discord = log_settings[log_category_id].log_to_discord > 0; + const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord; if (is_category_enabled) { log_settings[log_category_id].is_category_enabled = 1; } @@ -163,99 +125,37 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults() /** * Declare process file names for log writing= */ - if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) { - platform_file_name = "world"; + if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld) { + m_platform_file_name = "world"; } - else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) { - platform_file_name = "query_server"; + else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformQueryServ) { + m_platform_file_name = "query_server"; } - else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) { - platform_file_name = "zone"; + else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) { + m_platform_file_name = "zone"; } - else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) { - platform_file_name = "ucs"; + else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformUCS) { + m_platform_file_name = "ucs"; } - else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) { - platform_file_name = "login"; + else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLogin) { + m_platform_file_name = "login"; } - else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) { - platform_file_name = "launcher"; + else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLaunch) { + m_platform_file_name = "launcher"; } - else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) { - platform_file_name = "hc"; + else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformHC) { + m_platform_file_name = "hc"; } return this; } -/** - * @param log_category - * @return - */ -bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category) -{ - return ( - log_category == Logs::Emergency || - log_category == Logs::Alert || - log_category == Logs::Critical || - log_category == Logs::Error || - log_category == Logs::Warning || - log_category == Logs::Notice || - log_category == Logs::Info || - log_category == Logs::Debug - ); -} - -/** - * @param log_category - * @param in_message - * @return - */ -std::string EQEmuLogSys::FormatOutMessageString( - uint16 log_category, - const std::string &in_message -) -{ - std::string return_string = "[" + GetPlatformName() + "] "; - - return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message; -} - -/** - * @param debug_level - * @param log_category - * @param message - */ -void EQEmuLogSys::ProcessGMSay( - uint16 debug_level, - uint16 log_category, - const std::string &message -) -{ - /** - * Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash - */ - if (log_category == Logs::LogCategory::Netcode) { - return; - } - - /** - * Processes that actually support hooks - */ - if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone || - EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld - ) { - on_log_gmsay_hook(log_category, message); - } -} - /** * @param debug_level * @param log_category * @param message */ void EQEmuLogSys::ProcessLogWrite( - uint16 debug_level, uint16 log_category, const std::string &message ) @@ -266,79 +166,20 @@ void EQEmuLogSys::ProcessLogWrite( std::ofstream crash_log; EQEmuLogSys::MakeDirectory("logs/crashes"); crash_log.open( - StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()), + StringFormat("logs/crashes/crash_%s_%i.log", m_platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out ); crash_log << time_stamp << " " << message << "\n"; crash_log.close(); } - char time_stamp[80]; - EQEmuLogSys::SetCurrentTimeStamp(time_stamp); - if (process_log) { + char time_stamp[80]; + EQEmuLogSys::SetCurrentTimeStamp(time_stamp); process_log << time_stamp << " " << message << std::endl; } } -/** - * @param log_category - * @return - */ -uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category) -{ - switch (log_category) { - case Logs::Status: - case Logs::Normal: - return Console::Color::Yellow; - case Logs::MySQLError: - case Logs::Error: - return Console::Color::LightRed; - case Logs::MySQLQuery: - case Logs::Debug: - return Console::Color::LightGreen; - case Logs::Quests: - return Console::Color::LightCyan; - case Logs::Commands: - case Logs::Mercenaries: - return Console::Color::LightMagenta; - case Logs::Crash: - return Console::Color::LightRed; - default: - return Console::Color::Yellow; - } -} - -/** - * @param log_category - * @return - */ -std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category) -{ - switch (log_category) { - case Logs::Status: - case Logs::Normal: - return LC_YELLOW; - case Logs::MySQLError: - case Logs::Warning: - case Logs::Critical: - case Logs::Error: - return LC_RED; - case Logs::MySQLQuery: - case Logs::Debug: - return LC_GREEN; - case Logs::Quests: - return LC_CYAN; - case Logs::Commands: - case Logs::Mercenaries: - return LC_MAGENTA; - case Logs::Crash: - return LC_RED; - default: - return LC_YELLOW; - } -} - /** * @param log_category * @return @@ -346,10 +187,8 @@ std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category) uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) { switch (log_category) { - case Logs::Status: - case Logs::Normal: - return Chat::Yellow; case Logs::MySQLError: + case Logs::QuestErrors: case Logs::Error: return Chat::Red; case Logs::MySQLQuery: @@ -367,30 +206,146 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) } } + /** * @param debug_level * @param log_category * @param message */ -void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message) +void EQEmuLogSys::ProcessConsoleMessage( + uint16 log_category, + const std::string &message, + const char *file, + const char *func, + int line +) { -#ifdef _WINDOWS - HANDLE console_handle; - console_handle = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_FONT_INFOEX info = { 0 }; - info.cbSize = sizeof(info); - info.dwFontSize.Y = 12; // leave X as zero - info.FontWeight = FW_NORMAL; - wcscpy(info.FaceName, L"Lucida Console"); - SetCurrentConsoleFontEx(console_handle, NULL, &info); - SetConsoleTextAttribute(console_handle, EQEmuLogSys::GetWindowsConsoleColorFromCategory(log_category)); - std::cout << message << "\n"; - SetConsoleTextAttribute(console_handle, Console::Color::White); -#else - std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl; -#endif + bool is_error = ( + log_category == Logs::LogCategory::Error || + log_category == Logs::LogCategory::MySQLError || + log_category == Logs::LogCategory::Crash || + log_category == Logs::LogCategory::QuestErrors + ); + bool is_warning = ( + log_category == Logs::LogCategory::Warning + ); - on_log_console_hook(debug_level, log_category, message); + (!is_error ? std::cout : std::cerr) + << "" + << rang::fgB::black + << rang::style::bold + << fmt::format("{:>6}", GetPlatformName().substr(0, 6)) + << rang::style::reset + << rang::fgB::gray + << " | " + << ((is_error || is_warning) ? rang::fgB::red : rang::fgB::gray) + << rang::style::bold + << fmt::format("{:^10}", fmt::format("{}", Logs::LogCategoryName[log_category]).substr(0, 10)) + << rang::style::reset + << rang::fgB::gray + << " | " + << rang::fgB::gray + << rang::style::bold + << fmt::format("{}", func) + << rang::style::reset + << rang::fgB::gray + << " "; + + if (RuleB(Logging, PrintFileFunctionAndLine)) { + (!is_error ? std::cout : std::cerr) + << "" + << rang::fgB::green + << rang::style::bold + << fmt::format("{:}", fmt::format("{}:{}:{}", std::filesystem::path(file).filename().string(), func, line)) + << rang::style::reset + << " | "; + } + + if (log_category == Logs::LogCategory::MySQLQuery) { + auto s = Strings::Split(message, "--"); + if (s.size() > 1) { + std::string query = Strings::Trim(s[0]); + std::string meta = Strings::Trim(s[1]); + + std::cout << + rang::fgB::green + << + query + << + rang::style::reset; + + std::cout << + rang::fgB::black + << + " -- " + << + meta + << + rang::style::reset; + } + } + else if (Strings::Contains(message, "[")) { + for (auto &e: Strings::Split(message, " ")) { + if (Strings::Contains(e, "[") && Strings::Contains(e, "]")) { + e = Strings::Replace(e, "[", ""); + e = Strings::Replace(e, "]", ""); + + bool is_upper = false; + + for (int i = 0; i < strlen(e.c_str()); i++) { + if (isupper(e[i])) { + is_upper = true; + } + } + + if (!is_upper) { + (!is_error ? std::cout : std::cerr) + << rang::fgB::gray + << "[" + << rang::style::bold + << rang::fgB::yellow + << e + << rang::fgB::gray + << "] " + ; + } + else { + (!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] "; + } + } + else { + (!is_error ? std::cout : std::cerr) + << (is_error ? rang::fgB::red : rang::fgB::gray) + << e + << " "; + } + } + } + else { + (!is_error ? std::cout : std::cerr) + << (is_error ? rang::fgB::red : rang::fgB::gray) + << message + << " "; + } + + if (!origination_info.zone_short_name.empty()) { + (!is_error ? std::cout : std::cerr) + << + rang::fgB::black + << + "-- " + << + fmt::format( + "[{}] ({}) inst_id [{}]", + origination_info.zone_short_name, + origination_info.zone_long_name, + origination_info.instance_id + ); + } + + (!is_error ? std::cout : std::cerr) << rang::style::reset << std::endl; + + m_on_log_console_hook(log_category, message); } /** @@ -402,33 +357,6 @@ constexpr const char *str_end(const char *str) return *str ? str_end(str + 1) : str; } -/** - * @param str - * @return - */ -constexpr bool str_slant(const char *str) -{ - return *str == '/' ? true : (*str ? str_slant(str + 1) : false); -} - -/** - * @param str - * @return - */ -constexpr const char *r_slant(const char *str) -{ - return *str == '/' ? (str + 1) : r_slant(str - 1); -} - -/** - * @param str - * @return - */ -constexpr const char *base_file_name(const char *str) -{ - return str_slant(str) ? r_slant(str_end(str)) : str; -} - /** * Core logging function * @@ -447,47 +375,55 @@ void EQEmuLogSys::Out( ... ) { - bool log_to_console = true; - if (log_settings[log_category].log_to_console < debug_level) { - log_to_console = false; - } + auto l = GetLogsEnabled(debug_level, log_category); - bool log_to_file = true; - if (log_settings[log_category].log_to_file < debug_level) { - log_to_file = false; - } - - bool log_to_gmsay = true; - if (log_settings[log_category].log_to_gmsay < debug_level) { - log_to_gmsay = false; - } - - const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay; - if (nothing_to_log) { + // bail out if nothing to log + if (!l.log_enabled) { return; } std::string prefix; - if (RuleB(Logging, PrintFileFunctionAndLine)) { - prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line); + prefix = fmt::format("[{0}::{1}:{2}] ", std::filesystem::path(file).filename().string(), func, line); } - va_list args; - va_start(args, message); - std::string output_message = vStringFormat(message, args); - va_end(args); + // remove this when we remove all legacy logs + bool ignore_log_legacy_format = ( + log_category == Logs::Netcode || + log_category == Logs::PacketServerClient || + log_category == Logs::PacketClientServer || + log_category == Logs::PacketServerToServer + ); - std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message); + // remove this when we remove all legacy logs + std::string output_message = message; + if (!ignore_log_legacy_format) { + va_list args; + va_start(args, message); + output_message = vStringFormat(message, args); + va_end(args); + } - if (log_to_console) { - EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message); + if (l.log_to_console_enabled) { + EQEmuLogSys::ProcessConsoleMessage( + log_category, + output_message, + file, + func, + line + ); } - if (log_to_gmsay) { - EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message); + if (l.log_to_gmsay_enabled) { + m_on_log_gmsay_hook(log_category, func, output_message); } - if (log_to_file) { - EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message); + if (l.log_to_file_enabled) { + EQEmuLogSys::ProcessLogWrite( + log_category, + fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message) + ); + } + if (l.log_to_discord_enabled && m_on_log_discord_hook) { + m_on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message); } } @@ -500,7 +436,7 @@ void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp) struct tm *time_info; time(&raw_time); time_info = localtime(&raw_time); - strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info); + strftime(time_stamp, 80, "[%m-%d-%Y %H:%M:%S]", time_info); } /** @@ -539,53 +475,45 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name) /** * When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... */ - if (!file_logs_enabled) { + if (!m_file_logs_enabled) { return; } /** * Zone */ - if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) { + if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) { if (!log_name.empty()) { - platform_file_name = log_name; + m_platform_file_name = log_name; } - if (platform_file_name.empty()) { + if (m_platform_file_name.empty()) { return; } - LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid()); + LogInfo("Starting File Log [{}/zone/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid()); - /** - * Make directory if not exists - */ - EQEmuLogSys::MakeDirectory("logs/zone"); + // Make directory if not exists + EQEmuLogSys::MakeDirectory(fmt::format("{}/zone", GetLogPath())); - /** - * Open file pointer - */ + // Open file pointer process_log.open( - StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()), + fmt::format("{}/zone/{}_{}.log", GetLogPath(), m_platform_file_name, getpid()), std::ios_base::app | std::ios_base::out ); } else { - /** - * All other processes - */ - if (platform_file_name.empty()) { + // All other processes + if (m_platform_file_name.empty()) { return; } - LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid()); + LogInfo("Starting File Log [{}/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid()); - /** - * Open file pointer - */ + // Open file pointer process_log.open( - StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()), + fmt::format("{}/{}_{}.log", GetLogPath(), m_platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out ); } @@ -600,6 +528,8 @@ void EQEmuLogSys::SilenceConsoleLogging() log_settings[log_index].log_to_console = 0; log_settings[log_index].is_category_enabled = 0; } + + log_settings[Logs::Crash].log_to_console = static_cast(Logs::General); } /** @@ -615,6 +545,8 @@ void EQEmuLogSys::EnableConsoleLogging() EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings() { + InjectTablesIfNotExist(); + auto categories = LogsysCategoriesRepository::GetWhere( *m_database, "TRUE ORDER BY log_category_id" @@ -630,16 +562,20 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings() continue; } - log_settings[c.log_category_id].log_to_console = static_cast(c.log_to_console); - log_settings[c.log_category_id].log_to_file = static_cast(c.log_to_file); - log_settings[c.log_category_id].log_to_gmsay = static_cast(c.log_to_gmsay); + log_settings[c.log_category_id].log_to_console = static_cast(c.log_to_console); + log_settings[c.log_category_id].log_to_file = static_cast(c.log_to_file); + log_settings[c.log_category_id].log_to_gmsay = static_cast(c.log_to_gmsay); + log_settings[c.log_category_id].log_to_discord = static_cast(c.log_to_discord); + log_settings[c.log_category_id].discord_webhook_id = c.discord_webhook_id; // Determine if any output method is enabled for the category // and set it to 1 so it can used to check if category is enabled const bool log_to_console = log_settings[c.log_category_id].log_to_console > 0; const bool log_to_file = log_settings[c.log_category_id].log_to_file > 0; const bool log_to_gmsay = log_settings[c.log_category_id].log_to_gmsay > 0; - const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay; + const bool log_to_discord = log_settings[c.log_category_id].log_to_discord > 0 && + log_settings[c.log_category_id].discord_webhook_id > 0; + const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord; if (is_category_enabled) { log_settings[c.log_category_id].is_category_enabled = 1; @@ -649,7 +585,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings() // If we go through this whole loop and nothing is set to any debug level, there // is no point to create a file or keep anything open if (log_settings[c.log_category_id].log_to_file > 0) { - LogSys.file_logs_enabled = true; + LogSys.m_file_logs_enabled = true; } db_categories.emplace_back(c.log_category_id); @@ -657,18 +593,32 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings() // Auto inject categories that don't exist in the database... for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) { - if (std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end()) { + + bool is_missing_in_database = std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end(); + bool is_deprecated_category = Strings::Contains(fmt::format("{}", Logs::LogCategoryName[i]), "Deprecated"); + if (!is_missing_in_database && is_deprecated_category) { LogInfo( - "Automatically adding new log category [{0}]", - Logs::LogCategoryName[i] + "Logging category [{}] ({}) is now deprecated, deleting from database", + Logs::LogCategoryName[i], + i + ); + LogsysCategoriesRepository::DeleteOne(*m_database, i); + } + + if (is_missing_in_database && !is_deprecated_category) { + LogInfo( + "Automatically adding new log category [{}] ({})", + Logs::LogCategoryName[i], + i ); auto new_category = LogsysCategoriesRepository::NewEntity(); new_category.log_category_id = i; - new_category.log_category_description = EscapeString(Logs::LogCategoryName[i]); + new_category.log_category_description = Strings::Escape(Logs::LogCategoryName[i]); new_category.log_to_console = log_settings[i].log_to_console; new_category.log_to_gmsay = log_settings[i].log_to_gmsay; new_category.log_to_file = log_settings[i].log_to_file; + new_category.log_to_discord = log_settings[i].log_to_discord; LogsysCategoriesRepository::InsertOne(*m_database, new_category); } @@ -676,6 +626,19 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings() LogInfo("Loaded [{}] log categories", categories.size()); + auto webhooks = DiscordWebhooksRepository::GetWhere(*m_database, fmt::format("id < {}", MAX_DISCORD_WEBHOOK_ID)); + if (!webhooks.empty()) { + for (auto &w: webhooks) { + m_discord_webhooks[w.id] = {w.id, w.webhook_name, w.webhook_url}; + } + LogInfo("Loaded [{}] Discord webhooks", webhooks.size()); + } + + // force override this setting + log_settings[Logs::Crash].log_to_console = static_cast(Logs::General); + log_settings[Logs::Crash].log_to_gmsay = static_cast(Logs::General); + log_settings[Logs::Crash].log_to_file = static_cast(Logs::General); + return this; } @@ -685,3 +648,97 @@ EQEmuLogSys *EQEmuLogSys::SetDatabase(Database *db) return this; } + +void EQEmuLogSys::InjectTablesIfNotExist() +{ + // do not run injections for zone as its unnecessary hits every time a zone boots + // other processes less frequently ran can pick up injection + if (m_log_platform == EQEmuExePlatform::ExePlatformZone) { + return; + } + + // inject discord_webhooks + if (!m_database->DoesTableExist("discord_webhooks")) { + LogInfo("Creating table [discord_webhooks]"); + m_database->QueryDatabase( + SQL( + CREATE TABLE discord_webhooks + ( + id INT auto_increment primary key NULL, + webhook_name varchar(100) NULL, + webhook_url varchar(255) NULL, + created_at DATETIME NULL, + deleted_at DATETIME NULL + ) ENGINE=InnoDB + DEFAULT CHARSET=utf8mb4 + COLLATE=utf8mb4_general_ci; + ) + ); + } + + // inject logsys_categories + if (!m_database->DoesTableExist("logsys_categories")) { + LogInfo("Creating table [logsys_categories]"); + m_database->QueryDatabase( + SQL( + CREATE TABLE `logsys_categories` ( + `log_category_id` int(11) NOT NULL, + `log_category_description` varchar(150) DEFAULT NULL, + `log_to_console` smallint(11) DEFAULT 0, + `log_to_file` smallint(11) DEFAULT 0, + `log_to_gmsay` smallint(11) DEFAULT 0, + `log_to_discord` smallint(11) DEFAULT 0, + `discord_webhook_id` int(11) DEFAULT 0, + PRIMARY KEY (`log_category_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1 + ) + ); + } +} + +const EQEmuLogSys::DiscordWebhooks *EQEmuLogSys::GetDiscordWebhooks() const +{ + return m_discord_webhooks; +} + +EQEmuLogSys::LogEnabled EQEmuLogSys::GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category) +{ + auto e = LogEnabled{}; + + e.log_to_console_enabled = log_settings[log_category].log_to_console > 0 && + log_settings[log_category].log_to_console >= debug_level; + e.log_to_file_enabled = log_settings[log_category].log_to_file > 0 && + log_settings[log_category].log_to_file >= debug_level; + e.log_to_gmsay_enabled = log_settings[log_category].log_to_gmsay > 0 && + log_settings[log_category].log_to_gmsay >= debug_level && + log_category != Logs::LogCategory::Netcode && + (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone || + EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld); + e.log_to_discord_enabled = EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone && + log_settings[log_category].log_to_discord > 0 && + log_settings[log_category].log_to_discord >= debug_level && + log_settings[log_category].discord_webhook_id > 0 && + log_settings[log_category].discord_webhook_id < MAX_DISCORD_WEBHOOK_ID; + e.log_enabled = + e.log_to_console_enabled || e.log_to_file_enabled || e.log_to_gmsay_enabled || e.log_to_discord_enabled; + + return e; +} + +bool EQEmuLogSys::IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category) +{ + return GetLogsEnabled(debug_level, log_category).log_enabled; +} + +const std::string &EQEmuLogSys::GetLogPath() const +{ + return m_log_path; +} + +EQEmuLogSys *EQEmuLogSys::SetLogPath(const std::string &log_path) +{ + EQEmuLogSys::m_log_path = log_path; + + return this; +} + diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 0ec2c0701..0c8ec1ae3 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -39,8 +39,7 @@ namespace Logs { enum DebugLevel { General = 1, // 1 - Low-Level general debugging, useful info on single line - Moderate, // 2 - Informational based, used in functions, when particular things load - Detail // 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication + Detail // 2 - Use this for very chatty logging you want to leave in but don't want on by default }; /** @@ -54,7 +53,7 @@ namespace Logs { AI, Aggro, Attack, - PacketClientServer, + DeprecatedCS, // deprecated Combat, Commands, Crash, @@ -65,36 +64,36 @@ namespace Logs { Inventory, Launcher, Netcode, - Normal, + Normal, // deprecated Object, Pathing, - QSServer, + QSServer, // deprecated Quests, Rules, Skills, Spawns, Spells, - Status, + Status, // deprecated TCPConnection, Tasks, Tradeskills, Trading, Tribute, - UCSServer, - WebInterfaceServer, - WorldServer, - ZoneServer, + UCSServer, // deprecated + WebInterfaceServer, // deprecated + WorldServer, // deprecated + ZoneServer, // deprecated MySQLError, MySQLQuery, Mercenaries, QuestDebug, - PacketServerClient, - PacketClientServerUnhandled, - PacketServerClientWithDump, - PacketClientServerWithDump, - Loginserver, + DeprecatedSC, // deprecated + DeprecatedCSU, // deprecated + DeprecatedSCD, // deprecated + DeprecatedCSD, // deprecated + Loginserver, // deprecated ClientLogin, - HeadlessClient, + HeadlessClient, // deprecated HPUpdate, FixZ, Food, @@ -104,10 +103,10 @@ namespace Logs { MobAppearance, Info, Warning, - Critical, - Emergency, - Alert, - Notice, + Critical, // deprecated + Emergency, // deprecated + Alert, // deprecated + Notice, // deprecated AIScanClose, AIYellForHelp, AICastBeneficialClose, @@ -130,6 +129,13 @@ namespace Logs { ChecksumVerification, CombatRecord, Hate, + Discord, + Faction, + PacketServerClient, + PacketClientServer, + PacketServerToServer, + Bugs, + QuestErrors, MaxCategoryID /* Don't Remove this */ }; @@ -142,7 +148,7 @@ namespace Logs { "AI", "Aggro", "Attack", - "Packet :: Client -> Server", + "Deprecated", "Combat", "Commands", "Crash", @@ -153,52 +159,52 @@ namespace Logs { "Inventory", "Launcher", "Netcode", - "Normal", + "Normal (Deprecated)", "Object", "Pathing", - "QS Server", + "QS Server (Deprecated)", "Quests", "Rules", "Skills", "Spawns", "Spells", - "Status", + "Status (Deprecated)", "TCP Connection", "Tasks", "Tradeskills", "Trading", "Tribute", - "UCS Server", - "WebInterface Server", - "World Server", - "Zone Server", - "MySQL Error", - "MySQL Query", + "UCS Server (Deprecated)", + "Web Interface (Deprecated)", + "World Server (Deprecated)", + "Zone Server (Deprecated)", + "QueryErr", + "Query", "Mercenaries", "Quest Debug", - "Packet :: Server -> Client", - "Packet :: Client -> Server Unhandled", - "Packet :: Server -> Client (Dump)", - "Packet :: Client -> Server (Dump)", - "Login Server", + "Legacy Packet Logging (Deprecated)", + "Legacy Packet Logging (Deprecated)", + "Legacy Packet Logging (Deprecated)", + "Legacy Packet Logging (Deprecated)", + "Login Server (Deprecated)", "Client Login", - "Headless Client", + "Headless Client (Deprecated)", "HP Update", "FixZ", "Food", "Traps", "NPC Roam Box", "NPC Scaling", - "Mob Appearance", + "MobAppearance", "Info", "Warning", - "Critical", - "Emergency", - "Alert", - "Notice", - "AI Scan Close", - "AI Yell For Help", - "AI Cast Beneficial Close", + "Critical (Deprecated)", + "Emergency (Deprecated)", + "Alert (Deprecated)", + "Notice (Deprecated)", + "AI Scan", + "AI Yell", + "AI CastBeneficial", "AOE Cast", "Entity Management", "Flee", @@ -215,9 +221,16 @@ namespace Logs { "DialogueWindow", "HTTP", "Saylink", - "ChecksumVerification", + "ChecksumVer", "CombatRecord", "Hate", + "Discord", + "Faction", + "Packet S->C", + "Packet C->S", + "Packet S->S", + "Bugs", + "QuestErrors" }; } @@ -225,6 +238,8 @@ namespace Logs { class Database; +constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300; + class EQEmuLogSys { public: EQEmuLogSys(); @@ -287,9 +302,19 @@ public: uint8 log_to_file; uint8 log_to_console; uint8 log_to_gmsay; + uint8 log_to_discord; + int discord_webhook_id; uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */ }; + struct OriginationInfo { + std::string zone_short_name; + std::string zone_long_name; + int instance_id; + }; + + OriginationInfo origination_info{}; + /** * Internally used memory reference for all log settings per category * These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults @@ -297,50 +322,78 @@ public: */ LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{}; - bool file_logs_enabled = false; + struct LogEnabled { + bool log_to_file_enabled; + bool log_to_console_enabled; + bool log_to_gmsay_enabled; + bool log_to_discord_enabled; + bool log_enabled; + }; - int log_platform = 0; - std::string platform_file_name; + LogEnabled GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category); + bool IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category); + struct DiscordWebhooks { + int id; + std::string webhook_name; + std::string webhook_url; + }; + + const DiscordWebhooks *GetDiscordWebhooks() const; // gmsay uint16 GetGMSayColorFromCategory(uint16 log_category); - EQEmuLogSys * SetGMSayHandler(std::function f) { - on_log_gmsay_hook = f; + EQEmuLogSys *SetGMSayHandler(const std::function& f) + { + m_on_log_gmsay_hook = f; + return this; + } + + EQEmuLogSys *SetDiscordHandler(std::function f) + { + m_on_log_discord_hook = f; return this; } // console void SetConsoleHandler( std::function f - ) { on_log_console_hook = f; } + ) { m_on_log_console_hook = f; } void SilenceConsoleLogging(); void EnableConsoleLogging(); // database EQEmuLogSys *SetDatabase(Database *db); + [[nodiscard]] const std::string &GetLogPath() const; + EQEmuLogSys * SetLogPath(const std::string &log_path); + private: // reference to database - Database *m_database; + Database *m_database; + std::function m_on_log_gmsay_hook; + std::function m_on_log_discord_hook; + std::function m_on_log_console_hook; + DiscordWebhooks m_discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{}; + bool m_file_logs_enabled = false; + int m_log_platform = 0; + std::string m_platform_file_name; + std::string m_log_path; - std::function on_log_gmsay_hook; - std::function on_log_console_hook; - - std::string FormatOutMessageString(uint16 log_category, const std::string &in_message); - std::string GetLinuxConsoleColorFromCategory(uint16 log_category); - uint16 GetWindowsConsoleColorFromCategory(uint16 log_category); - - void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message); - void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message); - void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message); - bool IsRfc5424LogCategory(uint16 log_category); + void ProcessConsoleMessage( + uint16 log_category, + const std::string &message, + const char *file, + const char *func, + int line + ); + void ProcessLogWrite(uint16 log_category, const std::string &message); + void InjectTablesIfNotExist(); }; extern EQEmuLogSys LogSys; diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index 15a0d7787..4db8b6edc 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -21,1160 +21,778 @@ #ifndef EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H #define EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H -#ifdef BUILD_LOGGING - -/** - * RFC 5424 - */ - -#define LogEmergency(message, ...) do {\ - if (LogSys.log_settings[Logs::Emergency].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Emergency, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogAlert(message, ...) do {\ - if (LogSys.log_settings[Logs::Alert].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Alert, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogCritical(message, ...) do {\ - if (LogSys.log_settings[Logs::Critical].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Critical, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogError(message, ...) do {\ - if (LogSys.log_settings[Logs::Error].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogWarning(message, ...) do {\ - if (LogSys.log_settings[Logs::Warning].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogNotice(message, ...) do {\ - if (LogSys.log_settings[Logs::Notice].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Notice, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogInfo(message, ...) do {\ - if (LogSys.log_settings[Logs::Info].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogDebug(message, ...) do {\ - if (LogSys.log_settings[Logs::Debug].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Debug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -/** - * Category - */ - #define LogAA(message, ...) do {\ - if (LogSys.log_settings[Logs::AA].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::AA))\ OutF(LogSys, Logs::General, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAADetail(message, ...) do {\ - if (LogSys.log_settings[Logs::AA].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::AA))\ OutF(LogSys, Logs::Detail, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAI(message, ...) do {\ - if (LogSys.log_settings[Logs::AI].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::AI))\ OutF(LogSys, Logs::General, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::AI].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::AI))\ OutF(LogSys, Logs::Detail, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAggro(message, ...) do {\ - if (LogSys.log_settings[Logs::Aggro].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Aggro))\ OutF(LogSys, Logs::General, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAggroDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Aggro].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Aggro))\ OutF(LogSys, Logs::Detail, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAttack(message, ...) do {\ - if (LogSys.log_settings[Logs::Attack].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Attack))\ OutF(LogSys, Logs::General, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAttackDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Attack].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Attack))\ OutF(LogSys, Logs::Detail, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketClientServer(message, ...) do {\ - if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::PacketClientServer))\ OutF(LogSys, Logs::General, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketClientServerDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer))\ OutF(LogSys, Logs::Detail, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombat(message, ...) do {\ - if (LogSys.log_settings[Logs::Combat].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Combat))\ OutF(LogSys, Logs::General, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombatDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Combat].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Combat))\ OutF(LogSys, Logs::Detail, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCommands(message, ...) do {\ - if (LogSys.log_settings[Logs::Commands].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Commands))\ OutF(LogSys, Logs::General, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCommandsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Commands].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Commands))\ OutF(LogSys, Logs::Detail, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCrash(message, ...) do {\ - if (LogSys.log_settings[Logs::Crash].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Crash))\ OutF(LogSys, Logs::General, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCrashDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Crash].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Crash))\ OutF(LogSys, Logs::Detail, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogDebug(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Debug))\ + OutF(LogSys, Logs::General, Logs::Debug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogDebugDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Debug))\ + OutF(LogSys, Logs::Detail, Logs::Debug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + #define LogDoors(message, ...) do {\ - if (LogSys.log_settings[Logs::Doors].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Doors))\ OutF(LogSys, Logs::General, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDoorsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Doors].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Doors))\ OutF(LogSys, Logs::Detail, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) -#define LogGroup(message, ...) do {\ - if (LogSys.log_settings[Logs::Group].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Group, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +#define LogError(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Error))\ + OutF(LogSys, Logs::General, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) -#define LogGroupDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Group].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Group, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +#define LogErrorDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Error))\ + OutF(LogSys, Logs::Detail, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogGuilds(message, ...) do {\ - if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Guilds))\ OutF(LogSys, Logs::General, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogGuildsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Guilds))\ OutF(LogSys, Logs::Detail, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogInventory(message, ...) do {\ - if (LogSys.log_settings[Logs::Inventory].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Inventory))\ OutF(LogSys, Logs::General, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogInventoryDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Inventory].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Inventory))\ OutF(LogSys, Logs::Detail, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLauncher(message, ...) do {\ - if (LogSys.log_settings[Logs::Launcher].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Launcher))\ OutF(LogSys, Logs::General, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLauncherDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Launcher].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Launcher))\ OutF(LogSys, Logs::Detail, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetcode(message, ...) do {\ - if (LogSys.log_settings[Logs::Netcode].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Netcode))\ OutF(LogSys, Logs::General, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetcodeDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Netcode].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Netcode))\ OutF(LogSys, Logs::Detail, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNormal(message, ...) do {\ - if (LogSys.log_settings[Logs::Normal].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Normal))\ OutF(LogSys, Logs::General, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNormalDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Normal].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Normal))\ OutF(LogSys, Logs::Detail, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogObject(message, ...) do {\ - if (LogSys.log_settings[Logs::Object].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Object))\ OutF(LogSys, Logs::General, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogObjectDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Object].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Object))\ OutF(LogSys, Logs::Detail, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPathing(message, ...) do {\ - if (LogSys.log_settings[Logs::Pathing].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Pathing))\ OutF(LogSys, Logs::General, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPathingDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Pathing].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Pathing))\ OutF(LogSys, Logs::Detail, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) -#define LogQSServer(message, ...) do {\ - if (LogSys.log_settings[Logs::QSServer].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogQSServerDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::QSServer].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - #define LogQuests(message, ...) do {\ - if (LogSys.log_settings[Logs::Quests].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Quests))\ OutF(LogSys, Logs::General, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogQuestsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Quests].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Quests))\ OutF(LogSys, Logs::Detail, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogRules(message, ...) do {\ - if (LogSys.log_settings[Logs::Rules].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Rules))\ OutF(LogSys, Logs::General, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogRulesDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Rules].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Rules))\ OutF(LogSys, Logs::Detail, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSkills(message, ...) do {\ - if (LogSys.log_settings[Logs::Skills].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Skills))\ OutF(LogSys, Logs::General, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSkillsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Skills].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Skills))\ OutF(LogSys, Logs::Detail, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpawns(message, ...) do {\ - if (LogSys.log_settings[Logs::Spawns].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Spawns))\ OutF(LogSys, Logs::General, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpawnsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Spawns].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Spawns))\ OutF(LogSys, Logs::Detail, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpells(message, ...) do {\ - if (LogSys.log_settings[Logs::Spells].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Spells))\ OutF(LogSys, Logs::General, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpellsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Spells].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Spells))\ OutF(LogSys, Logs::Detail, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) -#define LogTCPConnection(message, ...) do {\ - if (LogSys.log_settings[Logs::TCPConnection].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTCPConnectionDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::TCPConnection].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTasks(message, ...) do {\ - if (LogSys.log_settings[Logs::Tasks].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTasksDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Tasks].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTradeskills(message, ...) do {\ - if (LogSys.log_settings[Logs::Tradeskills].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTradeskillsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Tradeskills].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTrading(message, ...) do {\ - if (LogSys.log_settings[Logs::Trading].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTradingDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Trading].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTribute(message, ...) do {\ - if (LogSys.log_settings[Logs::Tribute].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTributeDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Tribute].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMySQLError(message, ...) do {\ - if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMySQLErrorDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMySQLQuery(message, ...) do {\ - if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMySQLQueryDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMercenaries(message, ...) do {\ - if (LogSys.log_settings[Logs::Mercenaries].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMercenariesDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Mercenaries].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogQuestDebug(message, ...) do {\ - if (LogSys.log_settings[Logs::QuestDebug].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogQuestDebugDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::QuestDebug].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogLoginserver(message, ...) do {\ - if (LogSys.log_settings[Logs::Loginserver].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogLoginserverDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Loginserver].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogClientLogin(message, ...) do {\ - if (LogSys.log_settings[Logs::ClientLogin].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogClientLoginDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::ClientLogin].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogHeadlessClient(message, ...) do {\ - if (LogSys.log_settings[Logs::HeadlessClient].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogHeadlessClientDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::HeadlessClient].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogHPUpdate(message, ...) do {\ - if (LogSys.log_settings[Logs::HPUpdate].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogHPUpdateDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::HPUpdate].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogFixZ(message, ...) do {\ - if (LogSys.log_settings[Logs::FixZ].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogFixZDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::FixZ].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogFood(message, ...) do {\ - if (LogSys.log_settings[Logs::Food].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogFoodDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Food].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTraps(message, ...) do {\ - if (LogSys.log_settings[Logs::Traps].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogTrapsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Traps].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogNPCRoamBox(message, ...) do {\ - if (LogSys.log_settings[Logs::NPCRoamBox].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogNPCRoamBoxDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::NPCRoamBox].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogNPCScaling(message, ...) do {\ - if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogNPCScalingDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMobAppearance(message, ...) do {\ - if (LogSys.log_settings[Logs::MobAppearance].is_category_enabled == 1)\ - OutF(LogSys, Logs::General, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - -#define LogMobAppearanceDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::MobAppearance].is_category_enabled == 1)\ - OutF(LogSys, Logs::Detail, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - #define LogStatus(message, ...) do {\ - if (LogSys.log_settings[Logs::Status].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Status))\ OutF(LogSys, Logs::General, Logs::Status, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogStatusDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Status].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Status))\ OutF(LogSys, Logs::Detail, Logs::Status, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogTCPConnection(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::TCPConnection))\ + OutF(LogSys, Logs::General, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTCPConnectionDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::TCPConnection))\ + OutF(LogSys, Logs::Detail, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTasks(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Tasks))\ + OutF(LogSys, Logs::General, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTasksDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Tasks))\ + OutF(LogSys, Logs::Detail, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTradeskills(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Tradeskills))\ + OutF(LogSys, Logs::General, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTradeskillsDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Tradeskills))\ + OutF(LogSys, Logs::Detail, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTrading(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Trading))\ + OutF(LogSys, Logs::General, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTradingDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Trading))\ + OutF(LogSys, Logs::Detail, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTribute(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Tribute))\ + OutF(LogSys, Logs::General, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTributeDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Tribute))\ + OutF(LogSys, Logs::Detail, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMySQLError(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::MySQLError))\ + OutF(LogSys, Logs::General, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMySQLErrorDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::MySQLError))\ + OutF(LogSys, Logs::Detail, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMySQLQuery(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::MySQLQuery))\ + OutF(LogSys, Logs::General, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMySQLQueryDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::MySQLQuery))\ + OutF(LogSys, Logs::Detail, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMercenaries(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Mercenaries))\ + OutF(LogSys, Logs::General, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMercenariesDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Mercenaries))\ + OutF(LogSys, Logs::Detail, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogQuestDebug(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::QuestDebug))\ + OutF(LogSys, Logs::General, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogQuestDebugDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::QuestDebug))\ + OutF(LogSys, Logs::Detail, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogPacketServerClient(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::PacketServerClient))\ + OutF(LogSys, Logs::General, Logs::PacketServerClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogPacketServerClientDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient))\ + OutF(LogSys, Logs::Detail, Logs::PacketServerClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + + +#define LogLoginserver(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Loginserver))\ + OutF(LogSys, Logs::General, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogLoginserverDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Loginserver))\ + OutF(LogSys, Logs::Detail, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogClientLogin(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::ClientLogin))\ + OutF(LogSys, Logs::General, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogClientLoginDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::ClientLogin))\ + OutF(LogSys, Logs::Detail, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogHPUpdate(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::HPUpdate))\ + OutF(LogSys, Logs::General, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogHPUpdateDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::HPUpdate))\ + OutF(LogSys, Logs::Detail, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogFixZ(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::FixZ))\ + OutF(LogSys, Logs::General, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogFixZDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::FixZ))\ + OutF(LogSys, Logs::Detail, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogFood(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Food))\ + OutF(LogSys, Logs::General, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogFoodDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Food))\ + OutF(LogSys, Logs::Detail, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTraps(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Traps))\ + OutF(LogSys, Logs::General, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogTrapsDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Traps))\ + OutF(LogSys, Logs::Detail, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogNPCRoamBox(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::NPCRoamBox))\ + OutF(LogSys, Logs::General, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogNPCRoamBoxDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::NPCRoamBox))\ + OutF(LogSys, Logs::Detail, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogNPCScaling(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::NPCScaling))\ + OutF(LogSys, Logs::General, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogNPCScalingDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::NPCScaling))\ + OutF(LogSys, Logs::Detail, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMobAppearance(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::MobAppearance))\ + OutF(LogSys, Logs::General, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogMobAppearanceDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::MobAppearance))\ + OutF(LogSys, Logs::Detail, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogInfo(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Info))\ + OutF(LogSys, Logs::General, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogInfoDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Info))\ + OutF(LogSys, Logs::Detail, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogWarning(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Warning))\ + OutF(LogSys, Logs::General, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogWarningDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Warning))\ + OutF(LogSys, Logs::Detail, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogCritical(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Critical))\ + OutF(LogSys, Logs::General, Logs::Critical, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogCriticalDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Critical))\ + OutF(LogSys, Logs::Detail, Logs::Critical, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogEmergency(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Emergency))\ + OutF(LogSys, Logs::General, Logs::Emergency, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogEmergencyDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Emergency))\ + OutF(LogSys, Logs::Detail, Logs::Emergency, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogAlert(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Alert))\ + OutF(LogSys, Logs::General, Logs::Alert, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogAlertDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Alert))\ + OutF(LogSys, Logs::Detail, Logs::Alert, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogNotice(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Notice))\ + OutF(LogSys, Logs::General, Logs::Notice, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogNoticeDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Notice))\ + OutF(LogSys, Logs::Detail, Logs::Notice, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + #define LogAIScanClose(message, ...) do {\ - if (LogSys.log_settings[Logs::AIScanClose].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::AIScanClose))\ OutF(LogSys, Logs::General, Logs::AIScanClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIScanCloseDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::AIScanClose].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::AIScanClose))\ OutF(LogSys, Logs::Detail, Logs::AIScanClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIYellForHelp(message, ...) do {\ - if (LogSys.log_settings[Logs::AIYellForHelp].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::AIYellForHelp))\ OutF(LogSys, Logs::General, Logs::AIYellForHelp, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIYellForHelpDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::AIYellForHelp].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::AIYellForHelp))\ OutF(LogSys, Logs::Detail, Logs::AIYellForHelp, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAICastBeneficialClose(message, ...) do {\ - if (LogSys.log_settings[Logs::AICastBeneficialClose].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::AICastBeneficialClose))\ OutF(LogSys, Logs::General, Logs::AICastBeneficialClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAICastBeneficialCloseDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::AICastBeneficialClose].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::AICastBeneficialClose))\ OutF(LogSys, Logs::Detail, Logs::AICastBeneficialClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAoeCast(message, ...) do {\ - if (LogSys.log_settings[Logs::AoeCast].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::AoeCast))\ OutF(LogSys, Logs::General, Logs::AoeCast, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAoeCastDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::AoeCast].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::AoeCast))\ OutF(LogSys, Logs::Detail, Logs::AoeCast, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEntityManagement(message, ...) do {\ - if (LogSys.log_settings[Logs::EntityManagement].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::EntityManagement))\ OutF(LogSys, Logs::General, Logs::EntityManagement, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEntityManagementDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::EntityManagement].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::EntityManagement))\ OutF(LogSys, Logs::Detail, Logs::EntityManagement, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFlee(message, ...) do {\ - if (LogSys.log_settings[Logs::Flee].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Flee))\ OutF(LogSys, Logs::General, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFleeDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Flee].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Flee))\ OutF(LogSys, Logs::Detail, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAura(message, ...) do {\ - if (LogSys.log_settings[Logs::Aura].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Aura))\ OutF(LogSys, Logs::General, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAuraDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Aura].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Aura))\ OutF(LogSys, Logs::Detail, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHotReload(message, ...) do {\ - if (LogSys.log_settings[Logs::HotReload].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::HotReload))\ OutF(LogSys, Logs::General, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHotReloadDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::HotReload].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::HotReload))\ OutF(LogSys, Logs::Detail, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMerchants(message, ...) do {\ - if (LogSys.log_settings[Logs::Merchants].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Merchants))\ OutF(LogSys, Logs::General, Logs::Merchants, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMerchantsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Merchants].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Merchants))\ OutF(LogSys, Logs::Detail, Logs::Merchants, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZonePoints(message, ...) do {\ - if (LogSys.log_settings[Logs::ZonePoints].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::ZonePoints))\ OutF(LogSys, Logs::General, Logs::ZonePoints, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZonePointsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::ZonePoints].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::ZonePoints))\ OutF(LogSys, Logs::Detail, Logs::ZonePoints, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLoot(message, ...) do {\ - if (LogSys.log_settings[Logs::Loot].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Loot))\ OutF(LogSys, Logs::General, Logs::Loot, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLootDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Loot].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Loot))\ OutF(LogSys, Logs::Detail, Logs::Loot, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogExpeditions(message, ...) do {\ - if (LogSys.log_settings[Logs::Expeditions].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Expeditions))\ OutF(LogSys, Logs::General, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) -#define LogExpeditionsModerate(message, ...) do {\ - if (LogSys.log_settings[Logs::Expeditions].is_category_enabled == 1)\ - OutF(LogSys, Logs::Moderate, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ -} while (0) - #define LogExpeditionsDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Expeditions].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Expeditions))\ OutF(LogSys, Logs::Detail, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDynamicZones(message, ...) do {\ - if (LogSys.log_settings[Logs::DynamicZones].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::DynamicZones))\ OutF(LogSys, Logs::General, Logs::DynamicZones, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDynamicZonesDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::DynamicZones].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::DynamicZones))\ OutF(LogSys, Logs::Detail, Logs::DynamicZones, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogScheduler(message, ...) do {\ - if (LogSys.log_settings[Logs::Scheduler].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Scheduler))\ OutF(LogSys, Logs::General, Logs::Scheduler, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSchedulerDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Scheduler].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Scheduler))\ OutF(LogSys, Logs::Detail, Logs::Scheduler, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCheat(message, ...) do {\ - if (LogSys.log_settings[Logs::Cheat].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Cheat))\ OutF(LogSys, Logs::General, Logs::Cheat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCheatDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Cheat].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Cheat))\ OutF(LogSys, Logs::Detail, Logs::Cheat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogClientList(message, ...) do {\ - if (LogSys.log_settings[Logs::ClientList].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::ClientList))\ OutF(LogSys, Logs::General, Logs::ClientList, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogClientListDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::ClientList].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::ClientList))\ OutF(LogSys, Logs::Detail, Logs::ClientList, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDiaWind(message, ...) do {\ - if (LogSys.log_settings[Logs::DiaWind].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::DiaWind))\ OutF(LogSys, Logs::General, Logs::DiaWind, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDiaWindDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::DiaWind].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::DiaWind))\ OutF(LogSys, Logs::Detail, Logs::DiaWind, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHTTP(message, ...) do {\ - if (LogSys.log_settings[Logs::HTTP].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::HTTP))\ OutF(LogSys, Logs::General, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHTTPDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::HTTP].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::HTTP))\ OutF(LogSys, Logs::Detail, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSaylink(message, ...) do {\ - if (LogSys.log_settings[Logs::Saylink].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Saylink))\ OutF(LogSys, Logs::General, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSaylinkDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Saylink].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Saylink))\ OutF(LogSys, Logs::Detail, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogChecksumVerification(message, ...) do {\ - if (LogSys.log_settings[Logs::ChecksumVerification].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::ChecksumVerification))\ OutF(LogSys, Logs::General, Logs::ChecksumVerification, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogChecksumVerificationDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::ChecksumVerification].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::ChecksumVerification))\ OutF(LogSys, Logs::Detail, Logs::ChecksumVerification, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombatRecord(message, ...) do {\ - if (LogSys.log_settings[Logs::CombatRecord].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::CombatRecord))\ OutF(LogSys, Logs::General, Logs::CombatRecord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombatRecordDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::CombatRecord].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::CombatRecord))\ OutF(LogSys, Logs::Detail, Logs::CombatRecord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHate(message, ...) do {\ - if (LogSys.log_settings[Logs::Hate].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Hate))\ OutF(LogSys, Logs::General, Logs::Hate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHateDetail(message, ...) do {\ - if (LogSys.log_settings[Logs::Hate].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Hate))\ OutF(LogSys, Logs::Detail, Logs::Hate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogDiscord(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Discord))\ + OutF(LogSys, Logs::General, Logs::Discord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogDiscordDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Discord))\ + OutF(LogSys, Logs::Detail, Logs::Discord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogFaction(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Faction))\ + OutF(LogSys, Logs::General, Logs::Faction, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogFactionDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Faction))\ + OutF(LogSys, Logs::Detail, Logs::Faction, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogPacketServerToServer(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::PacketServerToServer))\ + OutF(LogSys, Logs::General, Logs::PacketServerToServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogPacketServerToServerDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer))\ + OutF(LogSys, Logs::Detail, Logs::PacketServerToServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +// manually created + +#define LogBugs(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::Bugs))\ + OutF(LogSys, Logs::General, Logs::Bugs, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogBugsDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::Bugs))\ + OutF(LogSys, Logs::Detail, Logs::Bugs, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogQuestErrors(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::QuestErrors))\ + OutF(LogSys, Logs::General, Logs::QuestErrors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogQuestErrorsDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::QuestErrors))\ + OutF(LogSys, Logs::Detail, Logs::QuestErrors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + #define Log(debug_level, log_category, message, ...) do {\ - if (LogSys.log_settings[log_category].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(debug_level, log_category))\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogF(debug_level, log_category, message, ...) do {\ - if (LogSys.log_settings[log_category].is_category_enabled == 1)\ + if (LogSys.IsLogEnabled(debug_level, log_category))\ OutF(LogSys, debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) -#else -#define LogEmergency(message, ...) do {\ -} while (0) - -#define LogAlert(message, ...) do {\ -} while (0) - -#define LogCritical(message, ...) do {\ -} while (0) - -#define LogError(message, ...) do {\ -} while (0) - -#define LogWarning(message, ...) do {\ -} while (0) - -#define LogNotice(message, ...) do {\ -} while (0) - -#define LogInfo(message, ...) do {\ -} while (0) - -#define LogDebug(message, ...) do {\ -} while (0) - -/** - * Category - */ - -#define LogAA(message, ...) do {\ -} while (0) - -#define LogAADetail(message, ...) do {\ -} while (0) - -#define LogAI(message, ...) do {\ -} while (0) - -#define LogAIDetail(message, ...) do {\ -} while (0) - -#define LogAggro(message, ...) do {\ -} while (0) - -#define LogAggroDetail(message, ...) do {\ -} while (0) - -#define LogAttack(message, ...) do {\ -} while (0) - -#define LogAttackDetail(message, ...) do {\ -} while (0) - -#define LogPacketClientServer(message, ...) do {\ -} while (0) - -#define LogPacketClientServerDetail(message, ...) do {\ -} while (0) - -#define LogCombat(message, ...) do {\ -} while (0) - -#define LogCombatDetail(message, ...) do {\ -} while (0) - -#define LogCommands(message, ...) do {\ -} while (0) - -#define LogCommandsDetail(message, ...) do {\ -} while (0) - -#define LogCrash(message, ...) do {\ -} while (0) - -#define LogCrashDetail(message, ...) do {\ -} while (0) - -#define LogDoors(message, ...) do {\ -} while (0) - -#define LogDoorsDetail(message, ...) do {\ -} while (0) - -#define LogGroup(message, ...) do {\ -} while (0) - -#define LogGroupDetail(message, ...) do {\ -} while (0) - -#define LogGuilds(message, ...) do {\ -} while (0) - -#define LogGuildsDetail(message, ...) do {\ -} while (0) - -#define LogInventory(message, ...) do {\ -} while (0) - -#define LogInventoryDetail(message, ...) do {\ -} while (0) - -#define LogLauncher(message, ...) do {\ -} while (0) - -#define LogLauncherDetail(message, ...) do {\ -} while (0) - -#define LogNetcode(message, ...) do {\ -} while (0) - -#define LogNetcodeDetail(message, ...) do {\ -} while (0) - -#define LogNormal(message, ...) do {\ -} while (0) - -#define LogNormalDetail(message, ...) do {\ -} while (0) - -#define LogObject(message, ...) do {\ -} while (0) - -#define LogObjectDetail(message, ...) do {\ -} while (0) - -#define LogPathing(message, ...) do {\ -} while (0) - -#define LogPathingDetail(message, ...) do {\ -} while (0) - -#define LogQSServer(message, ...) do {\ -} while (0) - -#define LogQSServerDetail(message, ...) do {\ -} while (0) - -#define LogQuests(message, ...) do {\ -} while (0) - -#define LogQuestsDetail(message, ...) do {\ -} while (0) - -#define LogRules(message, ...) do {\ -} while (0) - -#define LogRulesDetail(message, ...) do {\ -} while (0) - -#define LogSkills(message, ...) do {\ -} while (0) - -#define LogSkillsDetail(message, ...) do {\ -} while (0) - -#define LogSpawns(message, ...) do {\ -} while (0) - -#define LogSpawnsDetail(message, ...) do {\ -} while (0) - -#define LogSpells(message, ...) do {\ -} while (0) - -#define LogSpellsDetail(message, ...) do {\ -} while (0) - -#define LogTCPConnection(message, ...) do {\ -} while (0) - -#define LogTCPConnectionDetail(message, ...) do {\ -} while (0) - -#define LogTasks(message, ...) do {\ -} while (0) - -#define LogTasksDetail(message, ...) do {\ -} while (0) - -#define LogTradeskills(message, ...) do {\ -} while (0) - -#define LogTradeskillsDetail(message, ...) do {\ -} while (0) - -#define LogTrading(message, ...) do {\ -} while (0) - -#define LogTradingDetail(message, ...) do {\ -} while (0) - -#define LogTribute(message, ...) do {\ -} while (0) - -#define LogTributeDetail(message, ...) do {\ -} while (0) - -#define LogMySQLError(message, ...) do {\ -} while (0) - -#define LogMySQLErrorDetail(message, ...) do {\ -} while (0) - -#define LogMySQLQuery(message, ...) do {\ -} while (0) - -#define LogMySQLQueryDetail(message, ...) do {\ -} while (0) - -#define LogMercenaries(message, ...) do {\ -} while (0) - -#define LogMercenariesDetail(message, ...) do {\ -} while (0) - -#define LogQuestDebug(message, ...) do {\ -} while (0) - -#define LogQuestDebugDetail(message, ...) do {\ -} while (0) - -#define LogLoginserver(message, ...) do {\ -} while (0) - -#define LogLoginserverDetail(message, ...) do {\ -} while (0) - -#define LogClientLogin(message, ...) do {\ -} while (0) - -#define LogClientLoginDetail(message, ...) do {\ -} while (0) - -#define LogHeadlessClient(message, ...) do {\ -} while (0) - -#define LogHeadlessClientDetail(message, ...) do {\ -} while (0) - -#define LogHPUpdate(message, ...) do {\ -} while (0) - -#define LogHPUpdateDetail(message, ...) do {\ -} while (0) - -#define LogFixZ(message, ...) do {\ -} while (0) - -#define LogFixZDetail(message, ...) do {\ -} while (0) - -#define LogFood(message, ...) do {\ -} while (0) - -#define LogFoodDetail(message, ...) do {\ -} while (0) - -#define LogTraps(message, ...) do {\ -} while (0) - -#define LogTrapsDetail(message, ...) do {\ -} while (0) - -#define LogNPCRoamBox(message, ...) do {\ -} while (0) - -#define LogNPCRoamBoxDetail(message, ...) do {\ -} while (0) - -#define LogNPCScaling(message, ...) do {\ -} while (0) - -#define LogNPCScalingDetail(message, ...) do {\ -} while (0) - -#define LogMobAppearance(message, ...) do {\ -} while (0) - -#define LogMobAppearanceDetail(message, ...) do {\ -} while (0) - -#define LogStatus(message, ...) do {\ -} while (0) - -#define LogStatusDetail(message, ...) do {\ -} while (0) - -#define LogAIScanClose(message, ...) do {\ -} while (0) - -#define LogAIScanCloseDetail(message, ...) do {\ -} while (0) - -#define LogAIYellForHelp(message, ...) do {\ -} while (0) - -#define LogAIYellForHelpDetail(message, ...) do {\ -} while (0) - -#define LogAICastBeneficialClose(message, ...) do {\ -} while (0) - -#define LogAICastBeneficialCloseDetail(message, ...) do {\ -} while (0) - -#define LogAoeCast(message, ...) do {\ -} while (0) - -#define LogAoeCastDetail(message, ...) do {\ -} while (0) - -#define LogEntityManagement(message, ...) do {\ -} while (0) - -#define LogEntityManagementDetail(message, ...) do {\ -} while (0) - -#define LogFlee(message, ...) do {\ -} while (0) - -#define LogFleeDetail(message, ...) do {\ -} while (0) - -#define LogAura(message, ...) do {\ -} while (0) - -#define LogAuraDetail(message, ...) do {\ -} while (0) - -#define LogHotReload(message, ...) do {\ -} while (0) - -#define LogHotReloadDetail(message, ...) do {\ -} while (0) - -#define LogMerchants(message, ...) do {\ -} while (0) - -#define LogMerchantsDetail(message, ...) do {\ -} while (0) - -#define LogZonePoints(message, ...) do {\ -} while (0) - -#define LogZonePointsDetail(message, ...) do {\ -} while (0) - -#define LogExpeditions(message, ...) do {\ -} while (0) - -#define LogExpeditionsModerate(message, ...) do {\ -} while (0) - -#define LogExpeditionsDetail(message, ...) do {\ -} while (0) - -#define LogDynamicZones(message, ...) do {\ -} while (0) - -#define LogDynamicZonesDetail(message, ...) do {\ -} while (0) - -#define LogCheatList(message, ...) do {\ -} while (0) - -#define LogCheatDetail(message, ...) do {\ -} while (0) - -#define LogClientList(message, ...) do {\ -} while (0) - -#define LogClientListDetail(message, ...) do {\ -} while (0) - -#define LogDiaWind(message, ...) do {\ -} while (0) - -#define LogDiaWindDetail(message, ...) do {\ -} while (0) - -#define LogHTTP(message, ...) do {\ -} while (0) - -#define LogHTTPDetail(message, ...) do {\ -} while (0) - -#define LogSaylink(message, ...) do {\ -} while (0) - -#define LogSaylinkDetail(message, ...) do {\ -} while (0) - -#define LogScheduler(message, ...) do {\ -} while (0) - -#define LogSchedulerDetail(message, ...) do {\ -} while (0) - -#define LogCheat(message, ...) do {\ -} while (0) - -#define LogCheatDetail(message, ...) do {\ -} while (0) - -#define LogLoot(message, ...) do {\ -} while (0) - -#define LogLootDetail(message, ...) do {\ -} while (0) - -#define LogFood(message, ...) do {\ -} while (0) - -#define LogFoodDetail(message, ...) do {\ -} while (0) - -#define LogChecksumVerification(message, ...) do {\ -} while (0) - -#define LogChecksumVerificationDetail(message, ...) do {\ -} while (0) - -#define LogCombatRecord(message, ...) do {\ -} while (0) - -#define LogCombatRecordDetail(message, ...) do {\ -} while (0) - -#define LogHate(message, ...) do {\ -} while (0) - -#define LogHateDetail(message, ...) do {\ -} while (0) - -#define Log(debug_level, log_category, message, ...) do {\ -} while (0) - -#define LogF(debug_level, log_category, message, ...) do {\ -} while (0) -#endif #endif //EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H diff --git a/common/event/task.h b/common/event/task.h index 89077734f..a58fd875a 100644 --- a/common/event/task.h +++ b/common/event/task.h @@ -1,14 +1,14 @@ #pragma once +#include #include #include #include "event_loop.h" -#include "../any.h" namespace EQ { class Task { public: - typedef std::function ResolveFn; + typedef std::function ResolveFn; typedef std::function RejectFn; typedef std::function FinallyFn; typedef std::function TaskFn; @@ -19,7 +19,7 @@ namespace EQ { RejectFn on_catch; FinallyFn on_finally; bool has_result; - EQ::Any result; + std::any result; bool has_error; std::exception error; }; @@ -63,7 +63,7 @@ namespace EQ { uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) { TaskBaton *baton = (TaskBaton*)req->data; - baton->fn([baton](const EQ::Any& result) { + baton->fn([baton](const std::any& result) { baton->has_error = false; baton->has_result = true; baton->result = result; diff --git a/common/event/task_scheduler.h b/common/event/task_scheduler.h index 6cfe15f00..26f45cfe9 100644 --- a/common/event/task_scheduler.h +++ b/common/event/task_scheduler.h @@ -60,8 +60,8 @@ namespace EQ } template - auto Enqueue(Fn&& fn, Args&&... args) -> std::future::type> { - using return_type = typename std::result_of::type; + auto Enqueue(Fn&& fn, Args&&... args) -> std::future::type> { + using return_type = typename std::invoke_result::type; auto task = std::make_shared>( std::bind(std::forward(fn), std::forward(args)...) diff --git a/common/expedition_lockout_timer.cpp b/common/expedition_lockout_timer.cpp index dc4cb97c6..6422ad55a 100644 --- a/common/expedition_lockout_timer.cpp +++ b/common/expedition_lockout_timer.cpp @@ -19,7 +19,7 @@ */ #include "expedition_lockout_timer.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/rulesys.h" #include "../common/util/uuid.h" #include diff --git a/common/faction.cpp b/common/faction.cpp index 5f3fddacc..2b82f2bf6 100644 --- a/common/faction.cpp +++ b/common/faction.cpp @@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2) // TODO: add more values switch (r1) { case DARK_ELF: - if (r2 == 77) { + if (r2 == RACE_NERIAK_CITIZEN_77) { return true; } break; case BARBARIAN: - if (r2 == 90) { + if (r2 == RACE_HALAS_CITIZEN_90) { return true; } } diff --git a/common/faction.h b/common/faction.h index 907e393fc..04b40eb9c 100755 --- a/common/faction.h +++ b/common/faction.h @@ -75,6 +75,23 @@ struct NPCFaction uint8 temp; }; +// Faction Associations give a much more live like faction system +// Basically the primary faction and magnitude of a faction hit will generate the rest of them + +// Largest faction I could find quickly was Lord Inquisitor Seru with 9 total hits (8 associations) so 8 + 2 for max for now +#define MAX_FACTION_ASSOC 10 + +// this is the ID of a faction association and it's multiplier +struct FactionAssociationHit { + int id; + float multiplier; +}; + +struct FactionAssociations { + // maybe there should be more data here, fine for now + FactionAssociationHit hits[MAX_FACTION_ASSOC]; +}; + const char *FactionValueToString(FACTION_VALUE faction_value); FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value); #endif diff --git a/common/file_util.cpp b/common/file.cpp similarity index 56% rename from common/file_util.cpp rename to common/file.cpp index 7e2535512..2e478aa5b 100644 --- a/common/file_util.cpp +++ b/common/file.cpp @@ -19,7 +19,7 @@ */ #include -#include "file_util.h" +#include "file.h" #ifdef _WINDOWS #include @@ -35,38 +35,48 @@ #endif +#include +#include + +namespace fs = std::filesystem; + /** * @param name * @return */ -bool FileUtil::exists(const std::string &name) +bool File::Exists(const std::string &name) { - std::ifstream f(name.c_str()); - - return f.good(); + return fs::exists(fs::path{name}); } /** * @param directory_name */ -void FileUtil::mkdir(const std::string& directory_name) +void File::Makedir(const std::string &directory_name) { + fs::create_directory(directory_name); + fs::permissions(directory_name, fs::perms::owner_all); +} -#ifdef _WINDOWS - struct _stat st; - if (_stat(directory_name.c_str(), &st) == 0) // exists - return; - _mkdir(directory_name.c_str()); -#else - struct stat st{}; - if (stat(directory_name.c_str(), &st) == 0) { // exists - return; +std::string File::FindEqemuConfigPath() +{ + if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) { + return File::GetCwd(); } - ::mkdir(directory_name.c_str(), 0755); -#endif + else if (File::Exists(fs::path{File::GetCwd() + "/../eqemu_config.json"}.string())) { + return canonical(fs::path{File::GetCwd() + "/../"}).string(); + } + else if (File::Exists(fs::path{File::GetCwd() + "/login.json"}.string())) { + return File::GetCwd(); + } + else if (File::Exists(fs::path{File::GetCwd() + "/../login.json"}.string())) { + return canonical(fs::path{File::GetCwd() + "/../"}).string(); + } + + return {}; } -bool file_exists(const std::string& name) { - std::ifstream f(name.c_str()); - return f.good(); +std::string File::GetCwd() +{ + return fs::current_path().string(); } diff --git a/common/file_util.h b/common/file.h similarity index 73% rename from common/file_util.h rename to common/file.h index 02e47d198..c420b4c78 100644 --- a/common/file_util.h +++ b/common/file.h @@ -18,16 +18,21 @@ * */ -#ifndef EQEMU_FILE_UTIL_H -#define EQEMU_FILE_UTIL_H +#ifndef EQEMU_FILE_H +#define EQEMU_FILE_H +#include -class FileUtil { +namespace fs = std::filesystem; + +class File { public: - static bool exists(const std::string &name); - static void mkdir(const std::string& directory_name); + static bool Exists(const std::string &name); + static void Makedir(const std::string& directory_name); + static std::string FindEqemuConfigPath(); + static std::string GetCwd(); }; -bool file_exists(const std::string& name); +bool Exists(const std::string& name); -#endif //EQEMU_FILE_UTIL_H +#endif //EQEMU_FILE_H diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 07ba3b040..07322f9e1 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -20,7 +20,7 @@ #include "database.h" //#include "misc_functions.h" -#include "string_util.h" +#include "strings.h" #include #include @@ -63,7 +63,9 @@ bool BaseGuildManager::LoadGuilds() { for (auto row=results.begin();row!=results.end();++row) _CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]); - query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks"; + LogInfo("Loaded [{}] Guilds", Strings::Commify(std::to_string(results.RowCount()))); + + query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks"; results = m_db->QueryDatabase(query); if (!results.Success()) @@ -864,20 +866,11 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) { return(true); } -//factored out so I dont have to copy this crap. -#ifdef BOTS -#define GuildMemberBaseQuery \ -"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \ -" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \ -" g.`banker`, g.`public_note`, g.`alt`" \ -" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` " -#else #define GuildMemberBaseQuery \ "SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \ " g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \ " g.`banker`, g.`public_note`, g.`alt` " \ " FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` " -#endif static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) { //fields from `characer_` into.char_id = atoi(row[0]); @@ -967,13 +960,8 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) { } //load up the rank info for each guild. - std::string query; -#ifdef BOTS - query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C' AND c.deleted_at IS NULL", char_id); -#else - query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id); -#endif - auto results = m_db->QueryDatabase(query); + std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id); + auto results = m_db->QueryDatabase(query); if (!results.Success()) { return false; } @@ -1281,10 +1269,10 @@ bool BaseGuildManager::IsCharacterInGuild(uint32 character_id, uint32 guild_id) if (current_guild_id == GUILD_NONE) { return false; } - + if (guild_id && current_guild_id != guild_id) { return false; } return true; -} \ No newline at end of file +} diff --git a/common/http/httplib.h b/common/http/httplib.h index e697e106a..e0cae6b72 100644 --- a/common/http/httplib.h +++ b/common/http/httplib.h @@ -1,13 +1,15 @@ // // httplib.h // -// Copyright (c) 2021 Yuji Hirose. All rights reserved. +// Copyright (c) 2022 Yuji Hirose. All rights reserved. // MIT License // #ifndef CPPHTTPLIB_HTTPLIB_H #define CPPHTTPLIB_HTTPLIB_H +#define CPPHTTPLIB_VERSION "0.11.2" + /* * Configuration */ @@ -60,14 +62,26 @@ #define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192 #endif +#ifndef CPPHTTPLIB_HEADER_MAX_LENGTH +#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192 +#endif + #ifndef CPPHTTPLIB_REDIRECT_MAX_COUNT #define CPPHTTPLIB_REDIRECT_MAX_COUNT 20 #endif +#ifndef CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT +#define CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT 1024 +#endif + #ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH #define CPPHTTPLIB_PAYLOAD_MAX_LENGTH ((std::numeric_limits::max)()) #endif +#ifndef CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH +#define CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH 8192 +#endif + #ifndef CPPHTTPLIB_TCP_NODELAY #define CPPHTTPLIB_TCP_NODELAY false #endif @@ -95,6 +109,10 @@ #define CPPHTTPLIB_SEND_FLAGS 0 #endif +#ifndef CPPHTTPLIB_LISTEN_BACKLOG +#define CPPHTTPLIB_LISTEN_BACKLOG 5 +#endif + /* * Headers */ @@ -109,14 +127,16 @@ #endif //_CRT_NONSTDC_NO_DEPRECATE #if defined(_MSC_VER) +#if _MSC_VER < 1900 +#error Sorry, Visual Studio versions prior to 2015 are not supported +#endif + +#pragma comment(lib, "ws2_32.lib") + #ifdef _WIN64 using ssize_t = __int64; #else -using ssize_t = int; -#endif - -#if _MSC_VER < 1900 -#define snprintf _snprintf_s +using ssize_t = long; #endif #endif // _MSC_VER @@ -134,20 +154,12 @@ using ssize_t = int; #include #include - -#include #include #ifndef WSA_FLAG_NO_HANDLE_INHERIT #define WSA_FLAG_NO_HANDLE_INHERIT 0x80 #endif -#ifdef _MSC_VER -#pragma comment(lib, "ws2_32.lib") -#pragma comment(lib, "crypt32.lib") -#pragma comment(lib, "cryptui.lib") -#endif - #ifndef strcasecmp #define strcasecmp _stricmp #endif // strcasecmp @@ -160,8 +172,8 @@ using socket_t = SOCKET; #else // not _WIN32 #include -#include #include +#include #include #include #ifdef __linux__ @@ -175,10 +187,13 @@ using socket_t = SOCKET; #include #include #include +#include #include using socket_t = int; +#ifndef INVALID_SOCKET #define INVALID_SOCKET (-1) +#endif #endif //_WIN32 #include @@ -188,6 +203,7 @@ using socket_t = int; #include #include #include +#include #include #include #include @@ -207,8 +223,24 @@ using socket_t = int; #include #ifdef CPPHTTPLIB_OPENSSL_SUPPORT +#ifdef _WIN32 +#include + +// these are defined in wincrypt.h and it breaks compilation if BoringSSL is +// used +#undef X509_NAME +#undef X509_CERT_PAIR +#undef X509_EXTENSIONS +#undef PKCS7_SIGNER_INFO + +#ifdef _MSC_VER +#pragma comment(lib, "crypt32.lib") +#pragma comment(lib, "cryptui.lib") +#endif +#endif //_WIN32 + #include -#include +#include #include #include @@ -332,22 +364,22 @@ namespace httplib { }; using ContentProvider = - std::function; + std::function; using ContentProviderWithoutLength = - std::function; + std::function; using ContentProviderResourceReleaser = std::function; using ContentReceiverWithProgress = - std::function; + std::function; using ContentReceiver = - std::function; + std::function; using MultipartContentHeader = - std::function; + std::function; class ContentReader { public: @@ -400,22 +432,21 @@ namespace httplib { const SSL *ssl = nullptr; #endif - bool has_header(const char *key) const; - std::string get_header_value(const char *key, size_t id = 0) const; + bool has_header(const std::string &key) const; + std::string get_header_value(const std::string &key, size_t id = 0) const; template - T get_header_value(const char *key, size_t id = 0) const; - size_t get_header_value_count(const char *key) const; - void set_header(const char *key, const char *val); - void set_header(const char *key, const std::string &val); + T get_header_value(const std::string &key, size_t id = 0) const; + size_t get_header_value_count(const std::string &key) const; + void set_header(const std::string &key, const std::string &val); - bool has_param(const char *key) const; - std::string get_param_value(const char *key, size_t id = 0) const; - size_t get_param_value_count(const char *key) const; + bool has_param(const std::string &key) const; + std::string get_param_value(const std::string &key, size_t id = 0) const; + size_t get_param_value_count(const std::string &key) const; bool is_multipart_form_data() const; - bool has_file(const char *key) const; - MultipartFormData get_file_value(const char *key) const; + bool has_file(const std::string &key) const; + MultipartFormData get_file_value(const std::string &key) const; // private members... size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT; @@ -433,29 +464,27 @@ namespace httplib { std::string body; std::string location; // Redirect location - bool has_header(const char *key) const; - std::string get_header_value(const char *key, size_t id = 0) const; + bool has_header(const std::string &key) const; + std::string get_header_value(const std::string &key, size_t id = 0) const; template - T get_header_value(const char *key, size_t id = 0) const; - size_t get_header_value_count(const char *key) const; - void set_header(const char *key, const char *val); - void set_header(const char *key, const std::string &val); + T get_header_value(const std::string &key, size_t id = 0) const; + size_t get_header_value_count(const std::string &key) const; + void set_header(const std::string &key, const std::string &val); - void set_redirect(const char *url, int status = 302); void set_redirect(const std::string &url, int status = 302); - void set_content(const char *s, size_t n, const char *content_type); - void set_content(const std::string &s, const char *content_type); + void set_content(const char *s, size_t n, const std::string &content_type); + void set_content(const std::string &s, const std::string &content_type); void set_content_provider( - size_t length, const char *content_type, ContentProvider provider, + size_t length, const std::string &content_type, ContentProvider provider, ContentProviderResourceReleaser resource_releaser = nullptr); void set_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser = nullptr); void set_chunked_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser = nullptr); Response() = default; @@ -503,7 +532,7 @@ namespace httplib { virtual void enqueue(std::function fn) = 0; virtual void shutdown() = 0; - virtual void on_idle(){}; + virtual void on_idle() {} }; class ThreadPool : public TaskQueue { @@ -580,43 +609,27 @@ namespace httplib { using SocketOptions = std::function; - inline void default_socket_options(socket_t sock) { - int yes = 1; -#ifdef _WIN32 - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), - sizeof(yes)); - setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, - reinterpret_cast(&yes), sizeof(yes)); -#else -#ifdef SO_REUSEPORT - setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&yes), - sizeof(yes)); -#else - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), - sizeof(yes)); -#endif -#endif - } + void default_socket_options(socket_t sock); class Server { public: using Handler = std::function; using ExceptionHandler = - std::function; + std::function; enum class HandlerResponse { Handled, Unhandled, }; using HandlerWithResponse = - std::function; + std::function; using HandlerWithContentReader = std::function; using Expect100ContinueHandler = - std::function; + std::function; Server(); @@ -624,37 +637,24 @@ namespace httplib { virtual bool is_valid() const; - Server &Get(const char *pattern, Handler handler); - Server &Get(const char *pattern, size_t pattern_len, Handler handler); - Server &Post(const char *pattern, Handler handler); - Server &Post(const char *pattern, size_t pattern_len, Handler handler); - Server &Post(const char *pattern, HandlerWithContentReader handler); - Server &Post(const char *pattern, size_t pattern_len, - HandlerWithContentReader handler); - Server &Put(const char *pattern, Handler handler); - Server &Put(const char *pattern, size_t pattern_len, Handler handler); - Server &Put(const char *pattern, HandlerWithContentReader handler); - Server &Put(const char *pattern, size_t pattern_len, - HandlerWithContentReader handler); - Server &Patch(const char *pattern, Handler handler); - Server &Patch(const char *pattern, size_t pattern_len, Handler handler); - Server &Patch(const char *pattern, HandlerWithContentReader handler); - Server &Patch(const char *pattern, size_t pattern_len, - HandlerWithContentReader handler); - Server &Delete(const char *pattern, Handler handler); - Server &Delete(const char *pattern, size_t pattern_len, Handler handler); - Server &Delete(const char *pattern, HandlerWithContentReader handler); - Server &Delete(const char *pattern, size_t pattern_len, - HandlerWithContentReader handler); - Server &Options(const char *pattern, Handler handler); - Server &Options(const char *pattern, size_t pattern_len, Handler handler); + Server &Get(const std::string &pattern, Handler handler); + Server &Post(const std::string &pattern, Handler handler); + Server &Post(const std::string &pattern, HandlerWithContentReader handler); + Server &Put(const std::string &pattern, Handler handler); + Server &Put(const std::string &pattern, HandlerWithContentReader handler); + Server &Patch(const std::string &pattern, Handler handler); + Server &Patch(const std::string &pattern, HandlerWithContentReader handler); + Server &Delete(const std::string &pattern, Handler handler); + Server &Delete(const std::string &pattern, HandlerWithContentReader handler); + Server &Options(const std::string &pattern, Handler handler); - bool set_base_dir(const char *dir, const char *mount_point = nullptr); - bool set_mount_point(const char *mount_point, const char *dir, + bool set_base_dir(const std::string &dir, + const std::string &mount_point = std::string()); + bool set_mount_point(const std::string &mount_point, const std::string &dir, Headers headers = Headers()); - bool remove_mount_point(const char *mount_point); - Server &set_file_extension_and_mimetype_mapping(const char *ext, - const char *mime); + bool remove_mount_point(const std::string &mount_point); + Server &set_file_extension_and_mimetype_mapping(const std::string &ext, + const std::string &mime); Server &set_file_request_handler(Handler handler); Server &set_error_handler(HandlerWithResponse handler); @@ -689,11 +689,11 @@ namespace httplib { Server &set_payload_max_length(size_t length); - bool bind_to_port(const char *host, int port, int socket_flags = 0); - int bind_to_any_port(const char *host, int socket_flags = 0); + bool bind_to_port(const std::string &host, int port, int socket_flags = 0); + int bind_to_any_port(const std::string &host, int socket_flags = 0); bool listen_after_bind(); - bool listen(const char *host, int port, int socket_flags = 0); + bool listen(const std::string &host, int port, int socket_flags = 0); bool is_running() const; void stop(); @@ -719,11 +719,12 @@ namespace httplib { private: using Handlers = std::vector>; using HandlersForContentReader = - std::vector>; + std::vector>; - socket_t create_server_socket(const char *host, int port, int socket_flags, + socket_t create_server_socket(const std::string &host, int port, + int socket_flags, SocketOptions socket_options) const; - int bind_internal(const char *host, int port, int socket_flags); + int bind_internal(const std::string &host, int port, int socket_flags); bool listen_internal(); bool routing(Request &req, Response &res, Stream &strm); @@ -809,12 +810,12 @@ namespace httplib { SSLServerVerification, UnsupportedMultipartBoundaryChars, Compression, + ConnectionTimeout, }; - inline std::ostream &operator<<(std::ostream &os, const Error &obj) { - os << static_cast::type>(obj); - return os; - } + std::string to_string(const Error error); + + std::ostream &operator<<(std::ostream &os, const Error &obj); class Result { public: @@ -837,11 +838,12 @@ namespace httplib { Error error() const { return err_; } // Request Headers - bool has_request_header(const char *key) const; - std::string get_request_header_value(const char *key, size_t id = 0) const; + bool has_request_header(const std::string &key) const; + std::string get_request_header_value(const std::string &key, + size_t id = 0) const; template - T get_request_header_value(const char *key, size_t id = 0) const; - size_t get_request_header_value_count(const char *key) const; + T get_request_header_value(const std::string &key, size_t id = 0) const; + size_t get_request_header_value_count(const std::string &key) const; private: std::unique_ptr res_; @@ -863,126 +865,149 @@ namespace httplib { virtual bool is_valid() const; - Result Get(const char *path); - Result Get(const char *path, const Headers &headers); - Result Get(const char *path, Progress progress); - Result Get(const char *path, const Headers &headers, Progress progress); - Result Get(const char *path, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const char *path, ContentReceiver content_receiver, + Result Get(const std::string &path); + Result Get(const std::string &path, const Headers &headers); + Result Get(const std::string &path, Progress progress); + Result Get(const std::string &path, const Headers &headers, Progress progress); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, ContentReceiver content_receiver, + Progress progress); + Result Get(const std::string &path, const Headers &headers, + ContentReceiver content_receiver, Progress progress); + Result Get(const std::string &path, ResponseHandler response_handler, + ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, Progress progress = nullptr); + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Head(const char *path); - Result Head(const char *path, const Headers &headers); + Result Head(const std::string &path); + Result Head(const std::string &path, const Headers &headers); - Result Post(const char *path); - Result Post(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Post(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Post(const char *path, const std::string &body, - const char *content_type); - Result Post(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Post(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path); + Result Post(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Post(const std::string &path, const std::string &body, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Post(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Params ¶ms); - Result Post(const char *path, const Headers &headers, const Params ¶ms); - Result Post(const char *path, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Params ¶ms); + Result Post(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Post(const std::string &path, const MultipartFormDataItems &items); + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items, const std::string &boundary); - Result Put(const char *path); - Result Put(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Put(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Put(const char *path, const std::string &body, - const char *content_type); - Result Put(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Put(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, const Headers &headers, + Result Put(const std::string &path); + Result Put(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Put(const std::string &path, const std::string &body, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Put(const std::string &path, size_t content_length, + ContentProvider content_provider, const std::string &content_type); + Result Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Params ¶ms); - Result Put(const char *path, const Headers &headers, const Params ¶ms); + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Params ¶ms); + Result Put(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Put(const std::string &path, const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, const std::string &boundary); - Result Patch(const char *path); - Result Patch(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Patch(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Patch(const char *path, const std::string &body, - const char *content_type); - Result Patch(const char *path, const Headers &headers, - const std::string &body, const char *content_type); - Result Patch(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Patch(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, const Headers &headers, + Result Patch(const std::string &path); + Result Patch(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const std::string &body, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Patch(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); - Result Delete(const char *path); - Result Delete(const char *path, const Headers &headers); - Result Delete(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Delete(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Delete(const char *path, const std::string &body, - const char *content_type); - Result Delete(const char *path, const Headers &headers, - const std::string &body, const char *content_type); + Result Delete(const std::string &path); + Result Delete(const std::string &path, const Headers &headers); + Result Delete(const std::string &path, const char *body, + size_t content_length, const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Delete(const std::string &path, const std::string &body, + const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); - Result Options(const char *path); - Result Options(const char *path, const Headers &headers); + Result Options(const std::string &path); + Result Options(const std::string &path, const Headers &headers); bool send(Request &req, Response &res, Error &error); Result send(const Request &req); size_t is_socket_open() const; + socket_t socket() const; + void stop(); + void set_hostname_addr_map(std::map addr_map); + void set_default_headers(Headers headers); void set_address_family(int family); @@ -1002,10 +1027,11 @@ namespace httplib { template void set_write_timeout(const std::chrono::duration &duration); - void set_basic_auth(const char *username, const char *password); - void set_bearer_token_auth(const char *token); + void set_basic_auth(const std::string &username, const std::string &password); + void set_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const char *username, const char *password); + void set_digest_auth(const std::string &username, + const std::string &password); #endif void set_keep_alive(bool on); @@ -1017,13 +1043,21 @@ namespace httplib { void set_decompress(bool on); - void set_interface(const char *intf); + void set_interface(const std::string &intf); - void set_proxy(const char *host, int port); - void set_proxy_basic_auth(const char *username, const char *password); - void set_proxy_bearer_token_auth(const char *token); + void set_proxy(const std::string &host, int port); + void set_proxy_basic_auth(const std::string &username, + const std::string &password); + void set_proxy_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const char *username, const char *password); + void set_proxy_digest_auth(const std::string &username, + const std::string &password); +#endif + +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + void set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path = std::string()); + void set_ca_cert_store(X509_STORE *ca_cert_store); #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT @@ -1080,6 +1114,9 @@ namespace httplib { std::thread::id socket_requests_are_from_thread_ = std::thread::id(); bool socket_should_be_closed_when_request_is_done_ = false; + // Hostname-IP map + std::map addr_map_; + // Default headers Headers default_headers_; @@ -1099,7 +1136,7 @@ namespace httplib { std::string bearer_token_auth_token_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT std::string digest_auth_username_; - std::string digest_auth_password_; + std::string digest_auth_password_; #endif bool keep_alive_ = false; @@ -1124,7 +1161,14 @@ namespace httplib { std::string proxy_bearer_token_auth_token_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT std::string proxy_digest_auth_username_; - std::string proxy_digest_auth_password_; + std::string proxy_digest_auth_password_; +#endif + +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + std::string ca_cert_file_path_; + std::string ca_cert_dir_path_; + + X509_STORE *ca_cert_store_ = nullptr; #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT @@ -1142,16 +1186,18 @@ namespace httplib { bool handle_request(Stream &strm, Request &req, Response &res, bool close_connection, Error &error); std::unique_ptr send_with_content_provider( - Request &req, - // const char *method, const char *path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, + Request &req, const char *body, size_t content_length, + ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type, Error &error); + const std::string &content_type, Error &error); Result send_with_content_provider( - const char *method, const char *path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, + const std::string &method, const std::string &path, + const Headers &headers, const char *body, size_t content_length, + ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type); + const std::string &content_type); + + std::string adjust_host_string(const std::string &host) const; virtual bool process_socket(const Socket &socket, std::function callback); @@ -1161,9 +1207,9 @@ namespace httplib { class Client { public: // Universal interface - explicit Client(const char *scheme_host_port); + explicit Client(const std::string &scheme_host_port); - explicit Client(const char *scheme_host_port, + explicit Client(const std::string &scheme_host_port, const std::string &client_cert_path, const std::string &client_key_path); @@ -1174,128 +1220,153 @@ namespace httplib { const std::string &client_cert_path, const std::string &client_key_path); + Client(Client &&) = default; + ~Client(); bool is_valid() const; - Result Get(const char *path); - Result Get(const char *path, const Headers &headers); - Result Get(const char *path, Progress progress); - Result Get(const char *path, const Headers &headers, Progress progress); - Result Get(const char *path, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const char *path, ContentReceiver content_receiver, + Result Get(const std::string &path); + Result Get(const std::string &path, const Headers &headers); + Result Get(const std::string &path, Progress progress); + Result Get(const std::string &path, const Headers &headers, Progress progress); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, ContentReceiver content_receiver, + Progress progress); + Result Get(const std::string &path, const Headers &headers, + ContentReceiver content_receiver, Progress progress); + Result Get(const std::string &path, ResponseHandler response_handler, + ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, Progress progress = nullptr); + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Head(const char *path); - Result Head(const char *path, const Headers &headers); + Result Head(const std::string &path); + Result Head(const std::string &path, const Headers &headers); - Result Post(const char *path); - Result Post(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Post(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Post(const char *path, const std::string &body, - const char *content_type); - Result Post(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Post(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path); + Result Post(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Post(const std::string &path, const std::string &body, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Post(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Params ¶ms); - Result Post(const char *path, const Headers &headers, const Params ¶ms); - Result Post(const char *path, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Params ¶ms); + Result Post(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Post(const std::string &path, const MultipartFormDataItems &items); + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items, const std::string &boundary); - Result Put(const char *path); - Result Put(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Put(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Put(const char *path, const std::string &body, - const char *content_type); - Result Put(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Put(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, const Headers &headers, + Result Put(const std::string &path); + Result Put(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Put(const std::string &path, const std::string &body, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Put(const std::string &path, size_t content_length, + ContentProvider content_provider, const std::string &content_type); + Result Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Params ¶ms); - Result Put(const char *path, const Headers &headers, const Params ¶ms); - Result Patch(const char *path); - Result Patch(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Patch(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Patch(const char *path, const std::string &body, - const char *content_type); - Result Patch(const char *path, const Headers &headers, - const std::string &body, const char *content_type); - Result Patch(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Patch(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, const Headers &headers, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Params ¶ms); + Result Put(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Put(const std::string &path, const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, const std::string &boundary); + Result Patch(const std::string &path); + Result Patch(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const std::string &body, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Patch(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); - Result Delete(const char *path); - Result Delete(const char *path, const Headers &headers); - Result Delete(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Delete(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Delete(const char *path, const std::string &body, - const char *content_type); - Result Delete(const char *path, const Headers &headers, - const std::string &body, const char *content_type); + Result Delete(const std::string &path); + Result Delete(const std::string &path, const Headers &headers); + Result Delete(const std::string &path, const char *body, + size_t content_length, const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Delete(const std::string &path, const std::string &body, + const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); - Result Options(const char *path); - Result Options(const char *path, const Headers &headers); + Result Options(const std::string &path); + Result Options(const std::string &path, const Headers &headers); bool send(Request &req, Response &res, Error &error); Result send(const Request &req); size_t is_socket_open() const; + socket_t socket() const; + void stop(); + void set_hostname_addr_map(std::map addr_map); + void set_default_headers(Headers headers); void set_address_family(int family); @@ -1315,10 +1386,11 @@ namespace httplib { template void set_write_timeout(const std::chrono::duration &duration); - void set_basic_auth(const char *username, const char *password); - void set_bearer_token_auth(const char *token); + void set_basic_auth(const std::string &username, const std::string &password); + void set_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const char *username, const char *password); + void set_digest_auth(const std::string &username, + const std::string &password); #endif void set_keep_alive(bool on); @@ -1330,13 +1402,15 @@ namespace httplib { void set_decompress(bool on); - void set_interface(const char *intf); + void set_interface(const std::string &intf); - void set_proxy(const char *host, int port); - void set_proxy_basic_auth(const char *username, const char *password); - void set_proxy_bearer_token_auth(const char *token); + void set_proxy(const std::string &host, int port); + void set_proxy_basic_auth(const std::string &username, + const std::string &password); + void set_proxy_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const char *username, const char *password); + void set_proxy_digest_auth(const std::string &username, + const std::string &password); #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT @@ -1347,14 +1421,14 @@ namespace httplib { // SSL #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path = nullptr); + void set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path = std::string()); - void set_ca_cert_store(X509_STORE *ca_cert_store); + void set_ca_cert_store(X509_STORE *ca_cert_store); - long get_openssl_verify_result() const; + long get_openssl_verify_result() const; - SSL_CTX *ssl_context() const; + SSL_CTX *ssl_context() const; #endif private: @@ -1367,89 +1441,467 @@ namespace httplib { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT class SSLServer : public Server { + public: + SSLServer(const char *cert_path, const char *private_key_path, + const char *client_ca_cert_file_path = nullptr, + const char *client_ca_cert_dir_path = nullptr, + const char *private_key_password = nullptr); + + SSLServer(X509 *cert, EVP_PKEY *private_key, + X509_STORE *client_ca_cert_store = nullptr); + + SSLServer( + const std::function &setup_ssl_ctx_callback); + + ~SSLServer() override; + + bool is_valid() const override; + + SSL_CTX *ssl_context() const; + + private: + bool process_and_close_socket(socket_t sock) override; + + SSL_CTX *ctx_; + std::mutex ctx_mutex_; + }; + + class SSLClient : public ClientImpl { + public: + explicit SSLClient(const std::string &host); + + explicit SSLClient(const std::string &host, int port); + + explicit SSLClient(const std::string &host, int port, + const std::string &client_cert_path, + const std::string &client_key_path); + + explicit SSLClient(const std::string &host, int port, X509 *client_cert, + EVP_PKEY *client_key); + + ~SSLClient() override; + + bool is_valid() const override; + + void set_ca_cert_store(X509_STORE *ca_cert_store); + + long get_openssl_verify_result() const; + + SSL_CTX *ssl_context() const; + + private: + bool create_and_connect_socket(Socket &socket, Error &error) override; + void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override; + void shutdown_ssl_impl(Socket &socket, bool shutdown_socket); + + bool process_socket(const Socket &socket, + std::function callback) override; + bool is_ssl() const override; + + bool connect_with_proxy(Socket &sock, Response &res, bool &success, + Error &error); + bool initialize_ssl(Socket &socket, Error &error); + + bool load_certs(); + + bool verify_host(X509 *server_cert) const; + bool verify_host_with_subject_alt_name(X509 *server_cert) const; + bool verify_host_with_common_name(X509 *server_cert) const; + bool check_host_name(const char *pattern, size_t pattern_len) const; + + SSL_CTX *ctx_; + std::mutex ctx_mutex_; + std::once_flag initialize_cert_; + + std::vector host_components_; + + long verify_result_ = 0; + + friend class ClientImpl; + }; +#endif + +/* + * Implementation of template methods. + */ + + namespace detail { + + template + inline void duration_to_sec_and_usec(const T &duration, U callback) { + auto sec = std::chrono::duration_cast(duration).count(); + auto usec = std::chrono::duration_cast( + duration - std::chrono::seconds(sec)) + .count(); + callback(sec, usec); + } + + template + inline T get_header_value(const Headers & /*headers*/, + const std::string & /*key*/, size_t /*id*/ = 0, + uint64_t /*def*/ = 0) {} + + template <> + inline uint64_t get_header_value(const Headers &headers, + const std::string &key, size_t id, + uint64_t def) { + auto rng = headers.equal_range(key); + auto it = rng.first; + std::advance(it, static_cast(id)); + if (it != rng.second) { + return std::strtoull(it->second.data(), nullptr, 10); + } + return def; + } + + } // namespace detail + + template + inline T Request::get_header_value(const std::string &key, size_t id) const { + return detail::get_header_value(headers, key, id, 0); + } + + template + inline T Response::get_header_value(const std::string &key, size_t id) const { + return detail::get_header_value(headers, key, id, 0); + } + + template + inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { + const auto bufsiz = 2048; + std::array buf{}; + + auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...); + if (sn <= 0) { return sn; } + + auto n = static_cast(sn); + + if (n >= buf.size() - 1) { + std::vector glowable_buf(buf.size()); + + while (n >= glowable_buf.size() - 1) { + glowable_buf.resize(glowable_buf.size() * 2); + n = static_cast( + snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...)); + } + return write(&glowable_buf[0], n); + } else { + return write(buf.data(), n); + } + } + + inline void default_socket_options(socket_t sock) { + int yes = 1; +#ifdef _WIN32 + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), + sizeof(yes)); + setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, + reinterpret_cast(&yes), sizeof(yes)); +#else +#ifdef SO_REUSEPORT + setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&yes), + sizeof(yes)); +#else + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), + sizeof(yes)); +#endif +#endif + } + + template + inline Server & + Server::set_read_timeout(const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); + return *this; + } + + template + inline Server & + Server::set_write_timeout(const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); + return *this; + } + + template + inline Server & + Server::set_idle_interval(const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); }); + return *this; + } + + inline std::string to_string(const Error error) { + switch (error) { + case Error::Success: return "Success"; + case Error::Connection: return "Connection"; + case Error::BindIPAddress: return "BindIPAddress"; + case Error::Read: return "Read"; + case Error::Write: return "Write"; + case Error::ExceedRedirectCount: return "ExceedRedirectCount"; + case Error::Canceled: return "Canceled"; + case Error::SSLConnection: return "SSLConnection"; + case Error::SSLLoadingCerts: return "SSLLoadingCerts"; + case Error::SSLServerVerification: return "SSLServerVerification"; + case Error::UnsupportedMultipartBoundaryChars: + return "UnsupportedMultipartBoundaryChars"; + case Error::Compression: return "Compression"; + case Error::ConnectionTimeout: return "ConnectionTimeout"; + case Error::Unknown: return "Unknown"; + default: break; + } + + return "Invalid"; + } + + inline std::ostream &operator<<(std::ostream &os, const Error &obj) { + os << to_string(obj); + os << " (" << static_cast::type>(obj) << ')'; + return os; + } + + template + inline T Result::get_request_header_value(const std::string &key, + size_t id) const { + return detail::get_header_value(request_headers_, key, id, 0); + } + + template + inline void ClientImpl::set_connection_timeout( + const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) { + set_connection_timeout(sec, usec); + }); + } + + template + inline void ClientImpl::set_read_timeout( + const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); + } + + template + inline void ClientImpl::set_write_timeout( + const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); + } + + template + inline void Client::set_connection_timeout( + const std::chrono::duration &duration) { + cli_->set_connection_timeout(duration); + } + + template + inline void + Client::set_read_timeout(const std::chrono::duration &duration) { + cli_->set_read_timeout(duration); + } + + template + inline void + Client::set_write_timeout(const std::chrono::duration &duration) { + cli_->set_write_timeout(duration); + } + +/* + * Forward declarations and types that will be part of the .h file if split into + * .h + .cc. + */ + + std::string hosted_at(const std::string &hostname); + + void hosted_at(const std::string &hostname, std::vector &addrs); + + std::string append_query_params(const std::string &path, const Params ¶ms); + + std::pair make_range_header(Ranges ranges); + + std::pair + make_basic_authentication_header(const std::string &username, + const std::string &password, + bool is_proxy = false); + + namespace detail { + + std::string encode_query_param(const std::string &value); + + std::string decode_url(const std::string &s, bool convert_plus_to_space); + + void read_file(const std::string &path, std::string &out); + + std::string trim_copy(const std::string &s); + + void split(const char *b, const char *e, char d, + std::function fn); + + bool process_client_socket(socket_t sock, time_t read_timeout_sec, + time_t read_timeout_usec, time_t write_timeout_sec, + time_t write_timeout_usec, + std::function callback); + + socket_t create_client_socket( + const std::string &host, const std::string &ip, int port, + int address_family, bool tcp_nodelay, SocketOptions socket_options, + time_t connection_timeout_sec, time_t connection_timeout_usec, + time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, + time_t write_timeout_usec, const std::string &intf, Error &error); + + const char *get_header_value(const Headers &headers, const std::string &key, + size_t id = 0, const char *def = nullptr); + + std::string params_to_query_str(const Params ¶ms); + + void parse_query_text(const std::string &s, Params ¶ms); + + bool parse_range_header(const std::string &s, Ranges &ranges); + + int close_socket(socket_t sock); + + ssize_t send_socket(socket_t sock, const void *ptr, size_t size, int flags); + + ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags); + + enum class EncodingType { None = 0, Gzip, Brotli }; + + EncodingType encoding_type(const Request &req, const Response &res); + + class BufferStream : public Stream { + public: + BufferStream() = default; + ~BufferStream() override = default; + + bool is_readable() const override; + bool is_writable() const override; + ssize_t read(char *ptr, size_t size) override; + ssize_t write(const char *ptr, size_t size) override; + void get_remote_ip_and_port(std::string &ip, int &port) const override; + socket_t socket() const override; + + const std::string &get_buffer() const; + + private: + std::string buffer; + size_t position = 0; + }; + + class compressor { + public: + virtual ~compressor() = default; + + typedef std::function Callback; + virtual bool compress(const char *data, size_t data_length, bool last, + Callback callback) = 0; + }; + + class decompressor { + public: + virtual ~decompressor() = default; + + virtual bool is_valid() const = 0; + + typedef std::function Callback; + virtual bool decompress(const char *data, size_t data_length, + Callback callback) = 0; + }; + + class nocompressor : public compressor { + public: + virtual ~nocompressor() = default; + + bool compress(const char *data, size_t data_length, bool /*last*/, + Callback callback) override; + }; + +#ifdef CPPHTTPLIB_ZLIB_SUPPORT + class gzip_compressor : public compressor { public: - SSLServer(const char *cert_path, const char *private_key_path, - const char *client_ca_cert_file_path = nullptr, - const char *client_ca_cert_dir_path = nullptr); + gzip_compressor(); + ~gzip_compressor(); - SSLServer(X509 *cert, EVP_PKEY *private_key, - X509_STORE *client_ca_cert_store = nullptr); - - ~SSLServer() override; - - bool is_valid() const override; + bool compress(const char *data, size_t data_length, bool last, + Callback callback) override; private: - bool process_and_close_socket(socket_t sock) override; - - SSL_CTX *ctx_; - std::mutex ctx_mutex_; + bool is_valid_ = false; + z_stream strm_; }; -class SSLClient : public ClientImpl { +class gzip_decompressor : public decompressor { public: - explicit SSLClient(const std::string &host); - - explicit SSLClient(const std::string &host, int port); - - explicit SSLClient(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path); - - explicit SSLClient(const std::string &host, int port, X509 *client_cert, - EVP_PKEY *client_key); - - ~SSLClient() override; + gzip_decompressor(); + ~gzip_decompressor(); bool is_valid() const override; - void set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path = nullptr); - - void set_ca_cert_store(X509_STORE *ca_cert_store); - - long get_openssl_verify_result() const; - - SSL_CTX *ssl_context() const; + bool decompress(const char *data, size_t data_length, + Callback callback) override; private: - bool create_and_connect_socket(Socket &socket, Error &error) override; - void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override; - void shutdown_ssl_impl(Socket &socket, bool shutdown_socket); - - bool process_socket(const Socket &socket, - std::function callback) override; - bool is_ssl() const override; - - bool connect_with_proxy(Socket &sock, Response &res, bool &success, - Error &error); - bool initialize_ssl(Socket &socket, Error &error); - - bool load_certs(); - - bool verify_host(X509 *server_cert) const; - bool verify_host_with_subject_alt_name(X509 *server_cert) const; - bool verify_host_with_common_name(X509 *server_cert) const; - bool check_host_name(const char *pattern, size_t pattern_len) const; - - SSL_CTX *ctx_; - std::mutex ctx_mutex_; - std::once_flag initialize_cert_; - - std::vector host_components_; - - std::string ca_cert_file_path_; - std::string ca_cert_dir_path_; - long verify_result_ = 0; - - friend class ClientImpl; + bool is_valid_ = false; + z_stream strm_; }; #endif +#ifdef CPPHTTPLIB_BROTLI_SUPPORT + class brotli_compressor : public compressor { +public: + brotli_compressor(); + ~brotli_compressor(); + + bool compress(const char *data, size_t data_length, bool last, + Callback callback) override; + +private: + BrotliEncoderState *state_ = nullptr; +}; + +class brotli_decompressor : public decompressor { +public: + brotli_decompressor(); + ~brotli_decompressor(); + + bool is_valid() const override; + + bool decompress(const char *data, size_t data_length, + Callback callback) override; + +private: + BrotliDecoderResult decoder_r; + BrotliDecoderState *decoder_s = nullptr; +}; +#endif + +// NOTE: until the read size reaches `fixed_buffer_size`, use `fixed_buffer` +// to store data. The call can set memory on stack for performance. + class stream_line_reader { + public: + stream_line_reader(Stream &strm, char *fixed_buffer, + size_t fixed_buffer_size); + const char *ptr() const; + size_t size() const; + bool end_with_crlf() const; + bool getline(); + + private: + void append(char c); + + Stream &strm_; + char *fixed_buffer_; + const size_t fixed_buffer_size_; + size_t fixed_buffer_used_size_ = 0; + std::string glowable_buffer_; + }; + + } // namespace detail + // ---------------------------------------------------------------------------- /* - * Implementation + * Implementation that will be part of the .cc file if split into .h + .cc. */ namespace detail { @@ -1558,8 +2010,12 @@ private: } inline bool is_file(const std::string &path) { +#ifdef _WIN32 + return _access_s(path.c_str(), 0) == 0; +#else struct stat st; return stat(path.c_str(), &st) >= 0 && S_ISREG(st.st_mode); +#endif } inline bool is_dir(const std::string &path) { @@ -1728,7 +2184,8 @@ private: return s.substr(r.first, r.second - r.first); } - template void split(const char *b, const char *e, char d, Fn fn) { + inline void split(const char *b, const char *e, char d, + std::function fn) { size_t i = 0; size_t beg = 0; @@ -1747,81 +2204,70 @@ private: } } -// NOTE: until the read size reaches `fixed_buffer_size`, use `fixed_buffer` -// to store data. The call can set memory on stack for performance. - class stream_line_reader { - public: - stream_line_reader(Stream &strm, char *fixed_buffer, size_t fixed_buffer_size) - : strm_(strm), fixed_buffer_(fixed_buffer), - fixed_buffer_size_(fixed_buffer_size) {} + inline stream_line_reader::stream_line_reader(Stream &strm, char *fixed_buffer, + size_t fixed_buffer_size) + : strm_(strm), fixed_buffer_(fixed_buffer), + fixed_buffer_size_(fixed_buffer_size) {} - const char *ptr() const { - if (glowable_buffer_.empty()) { - return fixed_buffer_; - } else { - return glowable_buffer_.data(); - } + inline const char *stream_line_reader::ptr() const { + if (glowable_buffer_.empty()) { + return fixed_buffer_; + } else { + return glowable_buffer_.data(); } + } - size_t size() const { - if (glowable_buffer_.empty()) { - return fixed_buffer_used_size_; - } else { - return glowable_buffer_.size(); - } + inline size_t stream_line_reader::size() const { + if (glowable_buffer_.empty()) { + return fixed_buffer_used_size_; + } else { + return glowable_buffer_.size(); } + } - bool end_with_crlf() const { - auto end = ptr() + size(); - return size() >= 2 && end[-2] == '\r' && end[-1] == '\n'; - } + inline bool stream_line_reader::end_with_crlf() const { + auto end = ptr() + size(); + return size() >= 2 && end[-2] == '\r' && end[-1] == '\n'; + } - bool getline() { - fixed_buffer_used_size_ = 0; - glowable_buffer_.clear(); + inline bool stream_line_reader::getline() { + fixed_buffer_used_size_ = 0; + glowable_buffer_.clear(); - for (size_t i = 0;; i++) { - char byte; - auto n = strm_.read(&byte, 1); + for (size_t i = 0;; i++) { + char byte; + auto n = strm_.read(&byte, 1); - if (n < 0) { + if (n < 0) { + return false; + } else if (n == 0) { + if (i == 0) { return false; - } else if (n == 0) { - if (i == 0) { - return false; - } else { - break; - } + } else { + break; } - - append(byte); - - if (byte == '\n') { break; } } - return true; + append(byte); + + if (byte == '\n') { break; } } - private: - void append(char c) { - if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) { - fixed_buffer_[fixed_buffer_used_size_++] = c; - fixed_buffer_[fixed_buffer_used_size_] = '\0'; - } else { - if (glowable_buffer_.empty()) { - assert(fixed_buffer_[fixed_buffer_used_size_] == '\0'); - glowable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_); - } - glowable_buffer_ += c; + return true; + } + + inline void stream_line_reader::append(char c) { + if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) { + fixed_buffer_[fixed_buffer_used_size_++] = c; + fixed_buffer_[fixed_buffer_used_size_] = '\0'; + } else { + if (glowable_buffer_.empty()) { + assert(fixed_buffer_[fixed_buffer_used_size_] == '\0'); + glowable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_); } + glowable_buffer_ += c; } - - Stream &strm_; - char *fixed_buffer_; - const size_t fixed_buffer_size_; - size_t fixed_buffer_used_size_ = 0; - std::string glowable_buffer_; - }; + } inline int close_socket(socket_t sock) { #ifdef _WIN32 @@ -1841,6 +2287,31 @@ private: return res; } + inline ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags) { + return handle_EINTR([&]() { + return recv(sock, +#ifdef _WIN32 + static_cast(ptr), static_cast(size), +#else + ptr, size, +#endif + flags); + }); + } + + inline ssize_t send_socket(socket_t sock, const void *ptr, size_t size, + int flags) { + return handle_EINTR([&]() { + return send(sock, +#ifdef _WIN32 + static_cast(ptr), static_cast(size), +#else + ptr, size, +#endif + flags); + }); + } + inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) { #ifdef CPPHTTPLIB_USE_POLL struct pollfd pfd_read; @@ -1897,7 +2368,8 @@ private: #endif } - inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) { + inline Error wait_until_socket_is_ready(socket_t sock, time_t sec, + time_t usec) { #ifdef CPPHTTPLIB_USE_POLL struct pollfd pfd_read; pfd_read.fd = sock; @@ -1907,17 +2379,21 @@ private: auto poll_res = handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); + if (poll_res == 0) { return Error::ConnectionTimeout; } + if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) { int error = 0; socklen_t len = sizeof(error); auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, reinterpret_cast(&error), &len); - return res >= 0 && !error; + auto successful = res >= 0 && !error; + return successful ? Error::Success : Error::Connection; } - return false; + + return Error::Connection; #else #ifndef _WIN32 - if (sock >= FD_SETSIZE) { return false; } + if (sock >= FD_SETSIZE) { return Error::Connection; } #endif fd_set fdsr; @@ -1935,17 +2411,31 @@ private: return select(static_cast(sock + 1), &fdsr, &fdsw, &fdse, &tv); }); + if (ret == 0) { return Error::ConnectionTimeout; } + if (ret > 0 && (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) { int error = 0; socklen_t len = sizeof(error); - return getsockopt(sock, SOL_SOCKET, SO_ERROR, - reinterpret_cast(&error), &len) >= 0 && - !error; + auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, + reinterpret_cast(&error), &len); + auto successful = res >= 0 && !error; + return successful ? Error::Success : Error::Connection; } - return false; + return Error::Connection; #endif } + inline bool is_socket_alive(socket_t sock) { + const auto val = detail::select_read(sock, 0, 0); + if (val == 0) { + return true; + } else if (val < 0 && errno == EBADF) { + return false; + } + char buf[1]; + return detail::read_socket(sock, &buf[0], sizeof(buf), MSG_PEEK) > 0; + } + class SocketStream : public Stream { public: SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec, @@ -1965,37 +2455,21 @@ private: time_t read_timeout_usec_; time_t write_timeout_sec_; time_t write_timeout_usec_; + + std::vector read_buff_; + size_t read_buff_off_ = 0; + size_t read_buff_content_size_ = 0; + + static const size_t read_buff_size_ = 1024 * 4; }; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT class SSLSocketStream : public Stream { -public: - SSLSocketStream(socket_t sock, SSL *ssl, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec); - ~SSLSocketStream() override; - - bool is_readable() const override; - bool is_writable() const override; - ssize_t read(char *ptr, size_t size) override; - ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; - socket_t socket() const override; - -private: - socket_t sock_; - SSL *ssl_; - time_t read_timeout_sec_; - time_t read_timeout_usec_; - time_t write_timeout_sec_; - time_t write_timeout_usec_; -}; -#endif - - class BufferStream : public Stream { public: - BufferStream() = default; - ~BufferStream() override = default; + SSLSocketStream(socket_t sock, SSL *ssl, time_t read_timeout_sec, + time_t read_timeout_usec, time_t write_timeout_sec, + time_t write_timeout_usec); + ~SSLSocketStream() override; bool is_readable() const override; bool is_writable() const override; @@ -2004,12 +2478,15 @@ private: void get_remote_ip_and_port(std::string &ip, int &port) const override; socket_t socket() const override; - const std::string &get_buffer() const; - private: - std::string buffer; - size_t position = 0; + socket_t sock_; + SSL *ssl_; + time_t read_timeout_sec_; + time_t read_timeout_usec_; + time_t write_timeout_sec_; + time_t write_timeout_usec_; }; +#endif inline bool keep_alive(socket_t sock, time_t keep_alive_timeout_sec) { using namespace std::chrono; @@ -2032,12 +2509,14 @@ private: template inline bool - process_server_socket_core(socket_t sock, size_t keep_alive_max_count, + process_server_socket_core(const std::atomic &svr_sock, socket_t sock, + size_t keep_alive_max_count, time_t keep_alive_timeout_sec, T callback) { assert(keep_alive_max_count > 0); auto ret = false; auto count = keep_alive_max_count; - while (count > 0 && keep_alive(sock, keep_alive_timeout_sec)) { + while (svr_sock != INVALID_SOCKET && count > 0 && + keep_alive(sock, keep_alive_timeout_sec)) { auto close_connection = count == 1; auto connection_closed = false; ret = callback(close_connection, connection_closed); @@ -2049,12 +2528,13 @@ private: template inline bool - process_server_socket(socket_t sock, size_t keep_alive_max_count, + process_server_socket(const std::atomic &svr_sock, socket_t sock, + size_t keep_alive_max_count, time_t keep_alive_timeout_sec, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, time_t write_timeout_usec, T callback) { return process_server_socket_core( - sock, keep_alive_max_count, keep_alive_timeout_sec, + svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec, [&](bool close_connection, bool &connection_closed) { SocketStream strm(sock, read_timeout_sec, read_timeout_usec, write_timeout_sec, write_timeout_usec); @@ -2062,11 +2542,11 @@ private: }); } - template inline bool process_client_socket(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { + time_t write_timeout_usec, + std::function callback) { SocketStream strm(sock, read_timeout_sec, read_timeout_usec, write_timeout_sec, write_timeout_usec); return callback(strm); @@ -2081,24 +2561,58 @@ private: } template - socket_t create_socket(const char *host, int port, int address_family, - int socket_flags, bool tcp_nodelay, + socket_t create_socket(const std::string &host, const std::string &ip, int port, + int address_family, int socket_flags, bool tcp_nodelay, SocketOptions socket_options, BindOrConnect bind_or_connect) { // Get address info + const char *node = nullptr; struct addrinfo hints; struct addrinfo *result; memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = address_family; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = socket_flags; hints.ai_protocol = 0; + if (!ip.empty()) { + node = ip.c_str(); + // Ask getaddrinfo to convert IP in c-string to address + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + } else { + if (!host.empty()) { node = host.c_str(); } + hints.ai_family = address_family; + hints.ai_flags = socket_flags; + } + +#ifndef _WIN32 + if (hints.ai_family == AF_UNIX) { + const auto addrlen = host.length(); + if (addrlen > sizeof(sockaddr_un::sun_path)) return INVALID_SOCKET; + + auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); + if (sock != INVALID_SOCKET) { + sockaddr_un addr; + addr.sun_family = AF_UNIX; + std::copy(host.begin(), host.end(), addr.sun_path); + + hints.ai_addr = reinterpret_cast(&addr); + hints.ai_addrlen = static_cast( + sizeof(addr) - sizeof(addr.sun_path) + addrlen); + + if (!bind_or_connect(sock, hints)) { + close_socket(sock); + sock = INVALID_SOCKET; + } + } + return sock; + } +#endif + auto service = std::to_string(port); - if (getaddrinfo(host, service.c_str(), &hints, &result)) { -#ifdef __linux__ + if (getaddrinfo(node, service.c_str(), &hints, &result)) { +#if defined __linux__ && !defined __ANDROID__ res_init(); #endif return INVALID_SOCKET; @@ -2182,7 +2696,7 @@ private: #endif } - inline bool bind_ip_address(socket_t sock, const char *host) { + inline bool bind_ip_address(socket_t sock, const std::string &host) { struct addrinfo hints; struct addrinfo *result; @@ -2191,7 +2705,7 @@ private: hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; - if (getaddrinfo(host, "0", &hints, &result)) { return false; } + if (getaddrinfo(host.c_str(), "0", &hints, &result)) { return false; } auto ret = false; for (auto rp = result; rp; rp = rp->ai_next) { @@ -2211,11 +2725,14 @@ private: #endif #ifdef USE_IF2IP - inline std::string if2ip(const std::string &ifn) { + inline std::string if2ip(int address_family, const std::string &ifn) { struct ifaddrs *ifap; getifaddrs(&ifap); + std::string addr_candidate; for (auto ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr && ifn == ifa->ifa_name) { + if (ifa->ifa_addr && ifn == ifa->ifa_name && + (AF_UNSPEC == address_family || + ifa->ifa_addr->sa_family == address_family)) { if (ifa->ifa_addr->sa_family == AF_INET) { auto sa = reinterpret_cast(ifa->ifa_addr); char buf[INET_ADDRSTRLEN]; @@ -2223,28 +2740,43 @@ private: freeifaddrs(ifap); return std::string(buf, INET_ADDRSTRLEN); } + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + auto sa = reinterpret_cast(ifa->ifa_addr); + if (!IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) { + char buf[INET6_ADDRSTRLEN] = {}; + if (inet_ntop(AF_INET6, &sa->sin6_addr, buf, INET6_ADDRSTRLEN)) { + // equivalent to mac's IN6_IS_ADDR_UNIQUE_LOCAL + auto s6_addr_head = sa->sin6_addr.s6_addr[0]; + if (s6_addr_head == 0xfc || s6_addr_head == 0xfd) { + addr_candidate = std::string(buf, INET6_ADDRSTRLEN); + } else { + freeifaddrs(ifap); + return std::string(buf, INET6_ADDRSTRLEN); + } + } + } } } } freeifaddrs(ifap); - return std::string(); + return addr_candidate; } #endif inline socket_t create_client_socket( - const char *host, int port, int address_family, bool tcp_nodelay, - SocketOptions socket_options, time_t connection_timeout_sec, - time_t connection_timeout_usec, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, + const std::string &host, const std::string &ip, int port, + int address_family, bool tcp_nodelay, SocketOptions socket_options, + time_t connection_timeout_sec, time_t connection_timeout_usec, + time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, time_t write_timeout_usec, const std::string &intf, Error &error) { auto sock = create_socket( - host, port, address_family, 0, tcp_nodelay, std::move(socket_options), + host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options), [&](socket_t sock2, struct addrinfo &ai) -> bool { if (!intf.empty()) { #ifdef USE_IF2IP - auto ip = if2ip(intf); - if (ip.empty()) { ip = intf; } - if (!bind_ip_address(sock2, ip.c_str())) { + auto ip_from_if = if2ip(address_family, intf); + if (ip_from_if.empty()) { ip_from_if = intf; } + if (!bind_ip_address(sock2, ip_from_if.c_str())) { error = Error::BindIPAddress; return false; } @@ -2257,27 +2789,43 @@ private: ::connect(sock2, ai.ai_addr, static_cast(ai.ai_addrlen)); if (ret < 0) { - if (is_connection_error() || - !wait_until_socket_is_ready(sock2, connection_timeout_sec, - connection_timeout_usec)) { + if (is_connection_error()) { error = Error::Connection; return false; } + error = wait_until_socket_is_ready(sock2, connection_timeout_sec, + connection_timeout_usec); + if (error != Error::Success) { return false; } } set_nonblocking(sock2, false); { +#ifdef _WIN32 + auto timeout = static_cast(read_timeout_sec * 1000 + + read_timeout_usec / 1000); + setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, + sizeof(timeout)); +#else timeval tv; tv.tv_sec = static_cast(read_timeout_sec); tv.tv_usec = static_cast(read_timeout_usec); setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); +#endif } { + +#ifdef _WIN32 + auto timeout = static_cast(write_timeout_sec * 1000 + + write_timeout_usec / 1000); + setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, + sizeof(timeout)); +#else timeval tv; tv.tv_sec = static_cast(write_timeout_sec); tv.tv_usec = static_cast(write_timeout_usec); setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); +#endif } error = Error::Success; @@ -2293,7 +2841,7 @@ private: return sock; } - inline void get_remote_ip_and_port(const struct sockaddr_storage &addr, + inline bool get_remote_ip_and_port(const struct sockaddr_storage &addr, socklen_t addr_len, std::string &ip, int &port) { if (addr.ss_family == AF_INET) { @@ -2301,14 +2849,19 @@ private: } else if (addr.ss_family == AF_INET6) { port = ntohs(reinterpret_cast(&addr)->sin6_port); + } else { + return false; } std::array ipstr{}; - if (!getnameinfo(reinterpret_cast(&addr), addr_len, - ipstr.data(), static_cast(ipstr.size()), nullptr, - 0, NI_NUMERICHOST)) { - ip = ipstr.data(); + if (getnameinfo(reinterpret_cast(&addr), addr_len, + ipstr.data(), static_cast(ipstr.size()), nullptr, + 0, NI_NUMERICHOST)) { + return false; } + + ip = ipstr.data(); + return true; } inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) { @@ -2334,7 +2887,7 @@ private: namespace udl { - inline constexpr unsigned int operator"" _(const char *s, size_t l) { + inline constexpr unsigned int operator"" _t(const char *s, size_t l) { return str2tag_core(s, l, 0); } @@ -2348,59 +2901,59 @@ private: auto it = user_data.find(ext); if (it != user_data.end()) { return it->second.c_str(); } - using udl::operator""_; + using udl::operator""_t; switch (str2tag(ext)) { default: return nullptr; - case "css"_: return "text/css"; - case "csv"_: return "text/csv"; - case "txt"_: return "text/plain"; - case "vtt"_: return "text/vtt"; - case "htm"_: - case "html"_: return "text/html"; + case "css"_t: return "text/css"; + case "csv"_t: return "text/csv"; + case "htm"_t: + case "html"_t: return "text/html"; + case "js"_t: + case "mjs"_t: return "text/javascript"; + case "txt"_t: return "text/plain"; + case "vtt"_t: return "text/vtt"; - case "apng"_: return "image/apng"; - case "avif"_: return "image/avif"; - case "bmp"_: return "image/bmp"; - case "gif"_: return "image/gif"; - case "png"_: return "image/png"; - case "svg"_: return "image/svg+xml"; - case "webp"_: return "image/webp"; - case "ico"_: return "image/x-icon"; - case "tif"_: return "image/tiff"; - case "tiff"_: return "image/tiff"; - case "jpg"_: - case "jpeg"_: return "image/jpeg"; + case "apng"_t: return "image/apng"; + case "avif"_t: return "image/avif"; + case "bmp"_t: return "image/bmp"; + case "gif"_t: return "image/gif"; + case "png"_t: return "image/png"; + case "svg"_t: return "image/svg+xml"; + case "webp"_t: return "image/webp"; + case "ico"_t: return "image/x-icon"; + case "tif"_t: return "image/tiff"; + case "tiff"_t: return "image/tiff"; + case "jpg"_t: + case "jpeg"_t: return "image/jpeg"; - case "mp4"_: return "video/mp4"; - case "mpeg"_: return "video/mpeg"; - case "webm"_: return "video/webm"; + case "mp4"_t: return "video/mp4"; + case "mpeg"_t: return "video/mpeg"; + case "webm"_t: return "video/webm"; - case "mp3"_: return "audio/mp3"; - case "mpga"_: return "audio/mpeg"; - case "weba"_: return "audio/webm"; - case "wav"_: return "audio/wave"; + case "mp3"_t: return "audio/mp3"; + case "mpga"_t: return "audio/mpeg"; + case "weba"_t: return "audio/webm"; + case "wav"_t: return "audio/wave"; - case "otf"_: return "font/otf"; - case "ttf"_: return "font/ttf"; - case "woff"_: return "font/woff"; - case "woff2"_: return "font/woff2"; + case "otf"_t: return "font/otf"; + case "ttf"_t: return "font/ttf"; + case "woff"_t: return "font/woff"; + case "woff2"_t: return "font/woff2"; - case "7z"_: return "application/x-7z-compressed"; - case "atom"_: return "application/atom+xml"; - case "pdf"_: return "application/pdf"; - case "js"_: - case "mjs"_: return "application/javascript"; - case "json"_: return "application/json"; - case "rss"_: return "application/rss+xml"; - case "tar"_: return "application/x-tar"; - case "xht"_: - case "xhtml"_: return "application/xhtml+xml"; - case "xslt"_: return "application/xslt+xml"; - case "xml"_: return "application/xml"; - case "gz"_: return "application/gzip"; - case "zip"_: return "application/zip"; - case "wasm"_: return "application/wasm"; + case "7z"_t: return "application/x-7z-compressed"; + case "atom"_t: return "application/atom+xml"; + case "pdf"_t: return "application/pdf"; + case "json"_t: return "application/json"; + case "rss"_t: return "application/rss+xml"; + case "tar"_t: return "application/x-tar"; + case "xht"_t: + case "xhtml"_t: return "application/xhtml+xml"; + case "xslt"_t: return "application/xslt+xml"; + case "xml"_t: return "application/xml"; + case "gz"_t: return "application/gzip"; + case "zip"_t: return "application/zip"; + case "wasm"_t: return "application/wasm"; } } @@ -2475,15 +3028,22 @@ private: } inline bool can_compress_content_type(const std::string &content_type) { - return (!content_type.find("text/") && content_type != "text/event-stream") || - content_type == "image/svg+xml" || - content_type == "application/javascript" || - content_type == "application/json" || - content_type == "application/xml" || - content_type == "application/xhtml+xml"; - } + using udl::operator""_t; - enum class EncodingType { None = 0, Gzip, Brotli }; + auto tag = str2tag(content_type); + + switch (tag) { + case "image/svg+xml"_t: + case "application/javascript"_t: + case "application/json"_t: + case "application/xml"_t: + case "application/protobuf"_t: + case "application/xhtml+xml"_t: return true; + + default: + return !content_type.rfind("text/", 0) && tag != "text/event-stream"_t; + } + } inline EncodingType encoding_type(const Request &req, const Response &res) { auto ret = @@ -2508,61 +3068,41 @@ private: return EncodingType::None; } - class compressor { - public: - virtual ~compressor(){}; - - typedef std::function Callback; - virtual bool compress(const char *data, size_t data_length, bool last, - Callback callback) = 0; - }; - - class decompressor { - public: - virtual ~decompressor() {} - - virtual bool is_valid() const = 0; - - typedef std::function Callback; - virtual bool decompress(const char *data, size_t data_length, - Callback callback) = 0; - }; - - class nocompressor : public compressor { - public: - ~nocompressor(){}; - - bool compress(const char *data, size_t data_length, bool /*last*/, - Callback callback) override { - if (!data_length) { return true; } - return callback(data, data_length); - } - }; + inline bool nocompressor::compress(const char *data, size_t data_length, + bool /*last*/, Callback callback) { + if (!data_length) { return true; } + return callback(data, data_length); + } #ifdef CPPHTTPLIB_ZLIB_SUPPORT - class gzip_compressor : public compressor { -public: - gzip_compressor() { - std::memset(&strm_, 0, sizeof(strm_)); - strm_.zalloc = Z_NULL; - strm_.zfree = Z_NULL; - strm_.opaque = Z_NULL; + inline gzip_compressor::gzip_compressor() { + std::memset(&strm_, 0, sizeof(strm_)); + strm_.zalloc = Z_NULL; + strm_.zfree = Z_NULL; + strm_.opaque = Z_NULL; - is_valid_ = deflateInit2(&strm_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, - Z_DEFAULT_STRATEGY) == Z_OK; - } + is_valid_ = deflateInit2(&strm_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, + Z_DEFAULT_STRATEGY) == Z_OK; +} - ~gzip_compressor() { deflateEnd(&strm_); } +inline gzip_compressor::~gzip_compressor() { deflateEnd(&strm_); } - bool compress(const char *data, size_t data_length, bool last, - Callback callback) override { - assert(is_valid_); +inline bool gzip_compressor::compress(const char *data, size_t data_length, + bool last, Callback callback) { + assert(is_valid_); - auto flush = last ? Z_FINISH : Z_NO_FLUSH; + do { + constexpr size_t max_avail_in = + (std::numeric_limits::max)(); - strm_.avail_in = static_cast(data_length); + strm_.avail_in = static_cast( + (std::min)(data_length, max_avail_in)); strm_.next_in = const_cast(reinterpret_cast(data)); + data_length -= strm_.avail_in; + data += strm_.avail_in; + + auto flush = (last && data_length == 0) ? Z_FINISH : Z_NO_FLUSH; int ret = Z_OK; std::array buff{}; @@ -2578,50 +3118,59 @@ public: } } while (strm_.avail_out == 0); - assert((last && ret == Z_STREAM_END) || (!last && ret == Z_OK)); + assert((flush == Z_FINISH && ret == Z_STREAM_END) || + (flush == Z_NO_FLUSH && ret == Z_OK)); assert(strm_.avail_in == 0); - return true; - } + } while (data_length > 0); -private: - bool is_valid_ = false; - z_stream strm_; -}; + return true; +} -class gzip_decompressor : public decompressor { -public: - gzip_decompressor() { - std::memset(&strm_, 0, sizeof(strm_)); - strm_.zalloc = Z_NULL; - strm_.zfree = Z_NULL; - strm_.opaque = Z_NULL; +inline gzip_decompressor::gzip_decompressor() { + std::memset(&strm_, 0, sizeof(strm_)); + strm_.zalloc = Z_NULL; + strm_.zfree = Z_NULL; + strm_.opaque = Z_NULL; - // 15 is the value of wbits, which should be at the maximum possible value - // to ensure that any gzip stream can be decoded. The offset of 32 specifies - // that the stream type should be automatically detected either gzip or - // deflate. - is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK; - } + // 15 is the value of wbits, which should be at the maximum possible value + // to ensure that any gzip stream can be decoded. The offset of 32 specifies + // that the stream type should be automatically detected either gzip or + // deflate. + is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK; +} - ~gzip_decompressor() { inflateEnd(&strm_); } +inline gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); } - bool is_valid() const override { return is_valid_; } +inline bool gzip_decompressor::is_valid() const { return is_valid_; } - bool decompress(const char *data, size_t data_length, - Callback callback) override { - assert(is_valid_); +inline bool gzip_decompressor::decompress(const char *data, size_t data_length, + Callback callback) { + assert(is_valid_); - int ret = Z_OK; + int ret = Z_OK; - strm_.avail_in = static_cast(data_length); + do { + constexpr size_t max_avail_in = + (std::numeric_limits::max)(); + + strm_.avail_in = static_cast( + (std::min)(data_length, max_avail_in)); strm_.next_in = const_cast(reinterpret_cast(data)); + data_length -= strm_.avail_in; + data += strm_.avail_in; + std::array buff{}; while (strm_.avail_in > 0) { strm_.avail_out = static_cast(buff.size()); strm_.next_out = reinterpret_cast(buff.data()); + auto prev_avail_in = strm_.avail_in; + ret = inflate(&strm_, Z_NO_FLUSH); + + if (prev_avail_in - strm_.avail_in == 0) { return false; } + assert(ret != Z_STREAM_ERROR); switch (ret) { case Z_NEED_DICT: @@ -2634,118 +3183,107 @@ public: } } - return ret == Z_OK || ret == Z_STREAM_END; - } + if (ret != Z_OK && ret != Z_STREAM_END) return false; -private: - bool is_valid_ = false; - z_stream strm_; -}; + } while (data_length > 0); + + return true; +} #endif #ifdef CPPHTTPLIB_BROTLI_SUPPORT - class brotli_compressor : public compressor { -public: - brotli_compressor() { - state_ = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr); - } + inline brotli_compressor::brotli_compressor() { + state_ = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr); +} - ~brotli_compressor() { BrotliEncoderDestroyInstance(state_); } +inline brotli_compressor::~brotli_compressor() { + BrotliEncoderDestroyInstance(state_); +} - bool compress(const char *data, size_t data_length, bool last, - Callback callback) override { - std::array buff{}; +inline bool brotli_compressor::compress(const char *data, size_t data_length, + bool last, Callback callback) { + std::array buff{}; - auto operation = last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS; - auto available_in = data_length; - auto next_in = reinterpret_cast(data); + auto operation = last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS; + auto available_in = data_length; + auto next_in = reinterpret_cast(data); - for (;;) { - if (last) { - if (BrotliEncoderIsFinished(state_)) { break; } - } else { - if (!available_in) { break; } - } - - auto available_out = buff.size(); - auto next_out = buff.data(); - - if (!BrotliEncoderCompressStream(state_, operation, &available_in, - &next_in, &available_out, &next_out, - nullptr)) { - return false; - } - - auto output_bytes = buff.size() - available_out; - if (output_bytes) { - callback(reinterpret_cast(buff.data()), output_bytes); - } + for (;;) { + if (last) { + if (BrotliEncoderIsFinished(state_)) { break; } + } else { + if (!available_in) { break; } } - return true; - } + auto available_out = buff.size(); + auto next_out = buff.data(); -private: - BrotliEncoderState *state_ = nullptr; -}; - -class brotli_decompressor : public decompressor { -public: - brotli_decompressor() { - decoder_s = BrotliDecoderCreateInstance(0, 0, 0); - decoder_r = decoder_s ? BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT - : BROTLI_DECODER_RESULT_ERROR; - } - - ~brotli_decompressor() { - if (decoder_s) { BrotliDecoderDestroyInstance(decoder_s); } - } - - bool is_valid() const override { return decoder_s; } - - bool decompress(const char *data, size_t data_length, - Callback callback) override { - if (decoder_r == BROTLI_DECODER_RESULT_SUCCESS || - decoder_r == BROTLI_DECODER_RESULT_ERROR) { - return 0; + if (!BrotliEncoderCompressStream(state_, operation, &available_in, &next_in, + &available_out, &next_out, nullptr)) { + return false; } - const uint8_t *next_in = (const uint8_t *)data; - size_t avail_in = data_length; - size_t total_out; - - decoder_r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; - - std::array buff{}; - while (decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { - char *next_out = buff.data(); - size_t avail_out = buff.size(); - - decoder_r = BrotliDecoderDecompressStream( - decoder_s, &avail_in, &next_in, &avail_out, - reinterpret_cast(&next_out), &total_out); - - if (decoder_r == BROTLI_DECODER_RESULT_ERROR) { return false; } - - if (!callback(buff.data(), buff.size() - avail_out)) { return false; } + auto output_bytes = buff.size() - available_out; + if (output_bytes) { + callback(reinterpret_cast(buff.data()), output_bytes); } - - return decoder_r == BROTLI_DECODER_RESULT_SUCCESS || - decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; } -private: - BrotliDecoderResult decoder_r; - BrotliDecoderState *decoder_s = nullptr; -}; + return true; +} + +inline brotli_decompressor::brotli_decompressor() { + decoder_s = BrotliDecoderCreateInstance(0, 0, 0); + decoder_r = decoder_s ? BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT + : BROTLI_DECODER_RESULT_ERROR; +} + +inline brotli_decompressor::~brotli_decompressor() { + if (decoder_s) { BrotliDecoderDestroyInstance(decoder_s); } +} + +inline bool brotli_decompressor::is_valid() const { return decoder_s; } + +inline bool brotli_decompressor::decompress(const char *data, + size_t data_length, + Callback callback) { + if (decoder_r == BROTLI_DECODER_RESULT_SUCCESS || + decoder_r == BROTLI_DECODER_RESULT_ERROR) { + return 0; + } + + const uint8_t *next_in = (const uint8_t *)data; + size_t avail_in = data_length; + size_t total_out; + + decoder_r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + + std::array buff{}; + while (decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { + char *next_out = buff.data(); + size_t avail_out = buff.size(); + + decoder_r = BrotliDecoderDecompressStream( + decoder_s, &avail_in, &next_in, &avail_out, + reinterpret_cast(&next_out), &total_out); + + if (decoder_r == BROTLI_DECODER_RESULT_ERROR) { return false; } + + if (!callback(buff.data(), buff.size() - avail_out)) { return false; } + } + + return decoder_r == BROTLI_DECODER_RESULT_SUCCESS || + decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; +} #endif - inline bool has_header(const Headers &headers, const char *key) { + inline bool has_header(const Headers &headers, const std::string &key) { return headers.find(key) != headers.end(); } - inline const char *get_header_value(const Headers &headers, const char *key, - size_t id = 0, const char *def = nullptr) { + inline const char *get_header_value(const Headers &headers, + const std::string &key, size_t id, + const char *def) { auto rng = headers.equal_range(key); auto it = rng.first; std::advance(it, static_cast(id)); @@ -2753,23 +3291,6 @@ private: return def; } - template - inline T get_header_value(const Headers & /*headers*/, const char * /*key*/, - size_t /*id*/ = 0, uint64_t /*def*/ = 0) {} - - template <> - inline uint64_t get_header_value(const Headers &headers, - const char *key, size_t id, - uint64_t def) { - auto rng = headers.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { - return std::strtoull(it->second.data(), nullptr, 10); - } - return def; - } - template inline bool parse_header(const char *beg, const char *end, T fn) { // Skip trailing spaces and tabs. @@ -2809,15 +3330,26 @@ private: if (!line_reader.getline()) { return false; } // Check if the line ends with CRLF. + auto line_terminator_len = 2; if (line_reader.end_with_crlf()) { // Blank line indicates end of headers. if (line_reader.size() == 2) { break; } +#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR + } else { + // Blank line indicates end of headers. + if (line_reader.size() == 1) { break; } + line_terminator_len = 1; + } +#else } else { continue; // Skip invalid line. } +#endif - // Exclude CRLF - auto end = line_reader.ptr() + line_reader.size() - 2; + if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } + + // Exclude line terminator + auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; parse_header(line_reader.ptr(), end, [&](std::string &&key, std::string &&val) { @@ -2933,8 +3465,7 @@ private: std::string encoding = x.get_header_value("Content-Encoding"); std::unique_ptr decompressor; - if (encoding.find("gzip") != std::string::npos || - encoding.find("deflate") != std::string::npos) { + if (encoding == "gzip" || encoding == "deflate") { #ifdef CPPHTTPLIB_ZLIB_SUPPORT decompressor = detail::make_unique(); #else @@ -3002,7 +3533,7 @@ private: if (!ret) { status = exceed_payload_max_length ? 413 : 400; } return ret; }); - } + } // namespace detail inline ssize_t write_headers(Stream &strm, const Headers &headers) { ssize_t write_len = 0; @@ -3228,14 +3759,6 @@ private: return query; } - inline std::string append_query_params(const char *path, const Params ¶ms) { - std::string path_with_query = path; - const static std::regex re("[^?]+\\?.*"); - auto delm = std::regex_match(path, re) ? '&' : '?'; - path_with_query += delm + params_to_query_str(params); - return path_with_query; - } - inline void parse_query_text(const std::string &s, Params ¶ms) { std::set cache; split(s.data(), s.data() + s.size(), '&', [&](const char *b, const char *e) { @@ -3271,7 +3794,11 @@ private: return !boundary.empty(); } +#ifdef CPPHTTPLIB_NO_EXCEPTIONS + inline bool parse_range_header(const std::string &s, Ranges &ranges) { +#else inline bool parse_range_header(const std::string &s, Ranges &ranges) try { +#endif static auto re_first_range = std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))"); std::smatch m; if (std::regex_match(s, m, re_first_range)) { @@ -3303,37 +3830,41 @@ private: return all_valid_ranges; } return false; +#ifdef CPPHTTPLIB_NO_EXCEPTIONS + } +#else } catch (...) { return false; } +#endif class MultipartFormDataParser { public: MultipartFormDataParser() = default; - void set_boundary(std::string &&boundary) { boundary_ = boundary; } + void set_boundary(std::string &&boundary) { + boundary_ = boundary; + dash_boundary_crlf_ = dash_ + boundary_ + crlf_; + crlf_dash_boundary_ = crlf_ + dash_ + boundary_; + } bool is_valid() const { return is_valid_; } bool parse(const char *buf, size_t n, const ContentReceiver &content_callback, const MultipartContentHeader &header_callback) { + // TODO: support 'filename*' static const std::regex re_content_disposition( - "^Content-Disposition:\\s*form-data;\\s*name=\"(.*?)\"(?:;\\s*filename=" - "\"(.*?)\")?\\s*$", + R"~(^Content-Disposition:\s*form-data;\s*name="(.*?)"(?:;\s*filename="(.*?)")?(?:;\s*filename\*=\S+)?\s*$)~", std::regex_constants::icase); - static const std::string dash_ = "--"; - static const std::string crlf_ = "\r\n"; - buf_.append(buf, n); // TODO: performance improvement + buf_append(buf, n); - while (!buf_.empty()) { + while (buf_size() > 0) { switch (state_) { case 0: { // Initial boundary - auto pattern = dash_ + boundary_ + crlf_; - if (pattern.size() > buf_.size()) { return true; } - auto pos = buf_.find(pattern); - if (pos != 0) { return false; } - buf_.erase(0, pattern.size()); - off_ += pattern.size(); + buf_erase(buf_find(dash_boundary_crlf_)); + if (dash_boundary_crlf_.size() > buf_size()) { return true; } + if (!buf_start_with(dash_boundary_crlf_)) { return false; } + buf_erase(dash_boundary_crlf_.size()); state_ = 1; break; } @@ -3343,22 +3874,22 @@ private: break; } case 2: { // Headers - auto pos = buf_.find(crlf_); - while (pos != std::string::npos) { + auto pos = buf_find(crlf_); + if (pos > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } + while (pos < buf_size()) { // Empty line if (pos == 0) { if (!header_callback(file_)) { is_valid_ = false; return false; } - buf_.erase(0, crlf_.size()); - off_ += crlf_.size(); + buf_erase(crlf_.size()); state_ = 3; break; } static const std::string header_name = "content-type:"; - const auto header = buf_.substr(0, pos); + const auto header = buf_head(pos); if (start_with_case_ignore(header, header_name)) { file_.content_type = trim_copy(header.substr(header_name.size())); } else { @@ -3368,79 +3899,52 @@ private: file_.filename = m[2]; } } - - buf_.erase(0, pos + crlf_.size()); - off_ += pos + crlf_.size(); - pos = buf_.find(crlf_); + buf_erase(pos + crlf_.size()); + pos = buf_find(crlf_); } if (state_ != 3) { return true; } break; } case 3: { // Body - { - auto pattern = crlf_ + dash_; - if (pattern.size() > buf_.size()) { return true; } - - auto pos = find_string(buf_, pattern); - - if (!content_callback(buf_.data(), pos)) { + if (crlf_dash_boundary_.size() > buf_size()) { return true; } + auto pos = buf_find(crlf_dash_boundary_); + if (pos < buf_size()) { + if (!content_callback(buf_data(), pos)) { is_valid_ = false; return false; } - - off_ += pos; - buf_.erase(0, pos); - } - { - auto pattern = crlf_ + dash_ + boundary_; - if (pattern.size() > buf_.size()) { return true; } - - auto pos = buf_.find(pattern); - if (pos != std::string::npos) { - if (!content_callback(buf_.data(), pos)) { + buf_erase(pos + crlf_dash_boundary_.size()); + state_ = 4; + } else { + auto len = buf_size() - crlf_dash_boundary_.size(); + if (len > 0) { + if (!content_callback(buf_data(), len)) { is_valid_ = false; return false; } - - off_ += pos + pattern.size(); - buf_.erase(0, pos + pattern.size()); - state_ = 4; - } else { - if (!content_callback(buf_.data(), pattern.size())) { - is_valid_ = false; - return false; - } - - off_ += pattern.size(); - buf_.erase(0, pattern.size()); + buf_erase(len); } + return true; } break; } case 4: { // Boundary - if (crlf_.size() > buf_.size()) { return true; } - if (buf_.compare(0, crlf_.size(), crlf_) == 0) { - buf_.erase(0, crlf_.size()); - off_ += crlf_.size(); + if (crlf_.size() > buf_size()) { return true; } + if (buf_start_with(crlf_)) { + buf_erase(crlf_.size()); state_ = 1; } else { - auto pattern = dash_ + crlf_; - if (pattern.size() > buf_.size()) { return true; } - if (buf_.compare(0, pattern.size(), pattern) == 0) { - buf_.erase(0, pattern.size()); - off_ += pattern.size(); + if (dash_crlf_.size() > buf_size()) { return true; } + if (buf_start_with(dash_crlf_)) { + buf_erase(dash_crlf_.size()); is_valid_ = true; - state_ = 5; + buf_erase(buf_size()); // Remove epilogue } else { return true; } } break; } - case 5: { // Done - is_valid_ = false; - return false; - } } } @@ -3463,41 +3967,83 @@ private: return true; } - bool start_with(const std::string &a, size_t off, + const std::string dash_ = "--"; + const std::string crlf_ = "\r\n"; + const std::string dash_crlf_ = "--\r\n"; + std::string boundary_; + std::string dash_boundary_crlf_; + std::string crlf_dash_boundary_; + + size_t state_ = 0; + bool is_valid_ = false; + MultipartFormData file_; + + // Buffer + bool start_with(const std::string &a, size_t spos, size_t epos, const std::string &b) const { - if (a.size() - off < b.size()) { return false; } + if (epos - spos < b.size()) { return false; } for (size_t i = 0; i < b.size(); i++) { - if (a[i + off] != b[i]) { return false; } + if (a[i + spos] != b[i]) { return false; } } return true; } - size_t find_string(const std::string &s, const std::string &pattern) const { - auto c = pattern.front(); + size_t buf_size() const { return buf_epos_ - buf_spos_; } - size_t off = 0; - while (off < s.size()) { - auto pos = s.find(c, off); - if (pos == std::string::npos) { return s.size(); } + const char *buf_data() const { return &buf_[buf_spos_]; } - auto rem = s.size() - pos; - if (pattern.size() > rem) { return pos; } + std::string buf_head(size_t l) const { return buf_.substr(buf_spos_, l); } - if (start_with(s, pos, pattern)) { return pos; } + bool buf_start_with(const std::string &s) const { + return start_with(buf_, buf_spos_, buf_epos_, s); + } + + size_t buf_find(const std::string &s) const { + auto c = s.front(); + + size_t off = buf_spos_; + while (off < buf_epos_) { + auto pos = off; + while (true) { + if (pos == buf_epos_) { return buf_size(); } + if (buf_[pos] == c) { break; } + pos++; + } + + auto remaining_size = buf_epos_ - pos; + if (s.size() > remaining_size) { return buf_size(); } + + if (start_with(buf_, pos, buf_epos_, s)) { return pos - buf_spos_; } off = pos + 1; } - return s.size(); + return buf_size(); } - std::string boundary_; + void buf_append(const char *data, size_t n) { + auto remaining_size = buf_size(); + if (remaining_size > 0 && buf_spos_ > 0) { + for (size_t i = 0; i < remaining_size; i++) { + buf_[i] = buf_[buf_spos_ + i]; + } + } + buf_spos_ = 0; + buf_epos_ = remaining_size; + + if (remaining_size + n > buf_.size()) { buf_.resize(remaining_size + n); } + + for (size_t i = 0; i < n; i++) { + buf_[buf_epos_ + i] = data[i]; + } + buf_epos_ += n; + } + + void buf_erase(size_t size) { buf_spos_ += size; } std::string buf_; - size_t state_ = 0; - bool is_valid_ = false; - size_t off_ = 0; - MultipartFormData file_; + size_t buf_spos_ = 0; + size_t buf_epos_ = 0; }; inline std::string to_lower(const char *beg, const char *end) { @@ -3518,6 +4064,7 @@ private: // platforms, but due to lack of support in the c++ standard library, // doing better requires either some ugly hacks or breaking portability. std::random_device seed_gen; + // Request 128 bits of entropy for initialization std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), seed_gen()}; std::mt19937 engine(seed_sequence); @@ -3531,6 +4078,44 @@ private: return result; } + inline bool is_multipart_boundary_chars_valid(const std::string &boundary) { + auto valid = true; + for (size_t i = 0; i < boundary.size(); i++) { + auto c = boundary[i]; + if (!std::isalnum(c) && c != '-' && c != '_') { + valid = false; + break; + } + } + return valid; + } + + inline std::string + serialize_multipart_formdata(const MultipartFormDataItems &items, + const std::string &boundary, + std::string &content_type) { + std::string body; + + for (const auto &item : items) { + body += "--" + boundary + "\r\n"; + body += "Content-Disposition: form-data; name=\"" + item.name + "\""; + if (!item.filename.empty()) { + body += "; filename=\"" + item.filename + "\""; + } + body += "\r\n"; + if (!item.content_type.empty()) { + body += "Content-Type: " + item.content_type + "\r\n"; + } + body += "\r\n"; + body += item.content + "\r\n"; + } + + body += "--" + boundary + "--\r\n"; + + content_type = "multipart/form-data; boundary=" + boundary; + return body; + } + inline std::pair get_range_offset_and_length(const Request &req, size_t content_length, size_t index) { @@ -3604,7 +4189,7 @@ private: return process_multipart_ranges_data( req, res, boundary, content_type, [&](const std::string &token) { data += token; }, - [&](const char *token) { data += token; }, + [&](const std::string &token) { data += token; }, [&](size_t offset, size_t length) { if (offset < res.body.size()) { data += res.body.substr(offset, length); @@ -3623,7 +4208,7 @@ private: process_multipart_ranges_data( req, res, boundary, content_type, [&](const std::string &token) { data_length += token.size(); }, - [&](const char *token) { data_length += strlen(token); }, + [&](const std::string &token) { data_length += token.size(); }, [&](size_t /*offset*/, size_t length) { data_length += length; return true; @@ -3641,7 +4226,7 @@ private: return process_multipart_ranges_data( req, res, boundary, content_type, [&](const std::string &token) { strm.write(token); }, - [&](const char *token) { strm.write(token); }, + [&](const std::string &token) { strm.write(token); }, [&](size_t offset, size_t length) { return write_content(strm, res.content_provider_, offset, length, is_shutting_down); @@ -3669,8 +4254,8 @@ private: return false; } - inline bool has_crlf(const char *s) { - auto p = s; + inline bool has_crlf(const std::string &s) { + auto p = s.c_str(); while (*p) { if (*p == '\r' || *p == '\n') { return true; } p++; @@ -3679,39 +4264,37 @@ private: } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - template -inline std::string message_digest(const std::string &s, Init init, - Update update, Final final, - size_t digest_length) { - using namespace std; + inline std::string message_digest(const std::string &s, const EVP_MD *algo) { + auto context = std::unique_ptr( + EVP_MD_CTX_new(), EVP_MD_CTX_free); - std::vector md(digest_length, 0); - CTX ctx; - init(&ctx); - update(&ctx, s.data(), s.size()); - final(md.data(), &ctx); + unsigned int hash_length = 0; + unsigned char hash[EVP_MAX_MD_SIZE]; - stringstream ss; - for (auto c : md) { - ss << setfill('0') << setw(2) << hex << (unsigned int)c; - } - return ss.str(); -} + EVP_DigestInit_ex(context.get(), algo, nullptr); + EVP_DigestUpdate(context.get(), s.c_str(), s.size()); + EVP_DigestFinal_ex(context.get(), hash, &hash_length); -inline std::string MD5(const std::string &s) { - return message_digest(s, MD5_Init, MD5_Update, MD5_Final, - MD5_DIGEST_LENGTH); -} + std::stringstream ss; + for (auto i = 0u; i < hash_length; ++i) { + ss << std::hex << std::setw(2) << std::setfill('0') + << (unsigned int)hash[i]; + } -inline std::string SHA_256(const std::string &s) { - return message_digest(s, SHA256_Init, SHA256_Update, SHA256_Final, - SHA256_DIGEST_LENGTH); -} + return ss.str(); + } -inline std::string SHA_512(const std::string &s) { - return message_digest(s, SHA512_Init, SHA512_Update, SHA512_Final, - SHA512_DIGEST_LENGTH); -} + inline std::string MD5(const std::string &s) { + return message_digest(s, EVP_md5()); + } + + inline std::string SHA_256(const std::string &s) { + return message_digest(s, EVP_sha256()); + } + + inline std::string SHA_512(const std::string &s) { + return message_digest(s, EVP_sha512()); + } #endif #ifdef _WIN32 @@ -3747,10 +4330,14 @@ class WSInit { public: WSInit() { WSADATA wsaData; - WSAStartup(0x0002, &wsaData); + if (WSAStartup(0x0002, &wsaData) == 0) is_valid_ = true; } - ~WSInit() { WSACleanup(); } + ~WSInit() { + if (is_valid_) WSACleanup(); + } + + bool is_valid_ = false; }; static WSInit wsinit_; @@ -3758,52 +4345,64 @@ static WSInit wsinit_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT inline std::pair make_digest_authentication_header( - const Request &req, const std::map &auth, - size_t cnonce_count, const std::string &cnonce, const std::string &username, - const std::string &password, bool is_proxy = false) { - using namespace std; + const Request &req, const std::map &auth, + size_t cnonce_count, const std::string &cnonce, const std::string &username, + const std::string &password, bool is_proxy = false) { + std::string nc; + { + std::stringstream ss; + ss << std::setfill('0') << std::setw(8) << std::hex << cnonce_count; + nc = ss.str(); + } - string nc; - { - stringstream ss; - ss << setfill('0') << setw(8) << hex << cnonce_count; - nc = ss.str(); - } + std::string qop; + if (auth.find("qop") != auth.end()) { + qop = auth.at("qop"); + if (qop.find("auth-int") != std::string::npos) { + qop = "auth-int"; + } else if (qop.find("auth") != std::string::npos) { + qop = "auth"; + } else { + qop.clear(); + } + } - auto qop = auth.at("qop"); - if (qop.find("auth-int") != std::string::npos) { - qop = "auth-int"; - } else { - qop = "auth"; - } + std::string algo = "MD5"; + if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); } - std::string algo = "MD5"; - if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); } + std::string response; + { + auto H = algo == "SHA-256" ? detail::SHA_256 + : algo == "SHA-512" ? detail::SHA_512 + : detail::MD5; - string response; - { - auto H = algo == "SHA-256" ? detail::SHA_256 - : algo == "SHA-512" ? detail::SHA_512 - : detail::MD5; + auto A1 = username + ":" + auth.at("realm") + ":" + password; - auto A1 = username + ":" + auth.at("realm") + ":" + password; + auto A2 = req.method + ":" + req.path; + if (qop == "auth-int") { A2 += ":" + H(req.body); } - auto A2 = req.method + ":" + req.path; - if (qop == "auth-int") { A2 += ":" + H(req.body); } + if (qop.empty()) { + response = H(H(A1) + ":" + auth.at("nonce") + ":" + H(A2)); + } else { + response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce + + ":" + qop + ":" + H(A2)); + } + } - response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce + - ":" + qop + ":" + H(A2)); - } + auto opaque = (auth.find("opaque") != auth.end()) ? auth.at("opaque") : ""; - auto field = "Digest username=\"" + username + "\", realm=\"" + - auth.at("realm") + "\", nonce=\"" + auth.at("nonce") + - "\", uri=\"" + req.path + "\", algorithm=" + algo + - ", qop=" + qop + ", nc=\"" + nc + "\", cnonce=\"" + cnonce + - "\", response=\"" + response + "\""; + auto field = "Digest username=\"" + username + "\", realm=\"" + + auth.at("realm") + "\", nonce=\"" + auth.at("nonce") + + "\", uri=\"" + req.path + "\", algorithm=" + algo + + (qop.empty() ? ", response=\"" + : ", qop=" + qop + ", nc=" + nc + ", cnonce=\"" + + cnonce + "\", response=\"") + + response + "\"" + + (opaque.empty() ? "" : ", opaque=\"" + opaque + "\""); - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - return std::make_pair(key, field); -} + auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; + return std::make_pair(key, field); + } #endif inline bool parse_www_authenticate(const Response &res, @@ -3867,16 +4466,54 @@ static WSInit wsinit_; ContentProviderWithoutLength content_provider_; }; - template - inline void duration_to_sec_and_usec(const T &duration, U callback) { - auto sec = std::chrono::duration_cast(duration).count(); - auto usec = std::chrono::duration_cast( - duration - std::chrono::seconds(sec)) - .count(); - callback(sec, usec); + } // namespace detail + + inline std::string hosted_at(const std::string &hostname) { + std::vector addrs; + hosted_at(hostname, addrs); + if (addrs.empty()) { return std::string(); } + return addrs[0]; + } + + inline void hosted_at(const std::string &hostname, + std::vector &addrs) { + struct addrinfo hints; + struct addrinfo *result; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(hostname.c_str(), nullptr, &hints, &result)) { +#if defined __linux__ && !defined __ANDROID__ + res_init(); +#endif + return; } - } // namespace detail + for (auto rp = result; rp; rp = rp->ai_next) { + const auto &addr = + *reinterpret_cast(rp->ai_addr); + std::string ip; + int dummy = -1; + if (detail::get_remote_ip_and_port(addr, sizeof(struct sockaddr_storage), + ip, dummy)) { + addrs.push_back(ip); + } + } + + freeaddrinfo(result); + } + + inline std::string append_query_params(const std::string &path, + const Params ¶ms) { + std::string path_with_query = path; + const static std::regex re("[^?]+\\?.*"); + auto delm = std::regex_match(path, re) ? '&' : '?'; + path_with_query += delm + detail::params_to_query_str(params); + return path_with_query; + } // Header utilities inline std::pair make_range_header(Ranges ranges) { @@ -3894,8 +4531,7 @@ static WSInit wsinit_; inline std::pair make_basic_authentication_header(const std::string &username, - const std::string &password, - bool is_proxy = false) { + const std::string &password, bool is_proxy) { auto field = "Basic " + detail::base64_encode(username + ":" + password); auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; return std::make_pair(key, std::move(field)); @@ -3910,41 +4546,33 @@ static WSInit wsinit_; } // Request implementation - inline bool Request::has_header(const char *key) const { + inline bool Request::has_header(const std::string &key) const { return detail::has_header(headers, key); } - inline std::string Request::get_header_value(const char *key, size_t id) const { + inline std::string Request::get_header_value(const std::string &key, + size_t id) const { return detail::get_header_value(headers, key, id, ""); } - template - inline T Request::get_header_value(const char *key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); - } - - inline size_t Request::get_header_value_count(const char *key) const { + inline size_t Request::get_header_value_count(const std::string &key) const { auto r = headers.equal_range(key); return static_cast(std::distance(r.first, r.second)); } - inline void Request::set_header(const char *key, const char *val) { + inline void Request::set_header(const std::string &key, + const std::string &val) { if (!detail::has_crlf(key) && !detail::has_crlf(val)) { headers.emplace(key, val); } } - inline void Request::set_header(const char *key, const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val.c_str())) { - headers.emplace(key, val); - } - } - - inline bool Request::has_param(const char *key) const { + inline bool Request::has_param(const std::string &key) const { return params.find(key) != params.end(); } - inline std::string Request::get_param_value(const char *key, size_t id) const { + inline std::string Request::get_param_value(const std::string &key, + size_t id) const { auto rng = params.equal_range(key); auto it = rng.first; std::advance(it, static_cast(id)); @@ -3952,59 +4580,49 @@ static WSInit wsinit_; return std::string(); } - inline size_t Request::get_param_value_count(const char *key) const { + inline size_t Request::get_param_value_count(const std::string &key) const { auto r = params.equal_range(key); return static_cast(std::distance(r.first, r.second)); } inline bool Request::is_multipart_form_data() const { const auto &content_type = get_header_value("Content-Type"); - return !content_type.find("multipart/form-data"); + return !content_type.rfind("multipart/form-data", 0); } - inline bool Request::has_file(const char *key) const { + inline bool Request::has_file(const std::string &key) const { return files.find(key) != files.end(); } - inline MultipartFormData Request::get_file_value(const char *key) const { + inline MultipartFormData Request::get_file_value(const std::string &key) const { auto it = files.find(key); if (it != files.end()) { return it->second; } return MultipartFormData(); } // Response implementation - inline bool Response::has_header(const char *key) const { + inline bool Response::has_header(const std::string &key) const { return headers.find(key) != headers.end(); } - inline std::string Response::get_header_value(const char *key, + inline std::string Response::get_header_value(const std::string &key, size_t id) const { return detail::get_header_value(headers, key, id, ""); } - template - inline T Response::get_header_value(const char *key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); - } - - inline size_t Response::get_header_value_count(const char *key) const { + inline size_t Response::get_header_value_count(const std::string &key) const { auto r = headers.equal_range(key); return static_cast(std::distance(r.first, r.second)); } - inline void Response::set_header(const char *key, const char *val) { + inline void Response::set_header(const std::string &key, + const std::string &val) { if (!detail::has_crlf(key) && !detail::has_crlf(val)) { headers.emplace(key, val); } } - inline void Response::set_header(const char *key, const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val.c_str())) { - headers.emplace(key, val); - } - } - - inline void Response::set_redirect(const char *url, int stat) { + inline void Response::set_redirect(const std::string &url, int stat) { if (!detail::has_crlf(url)) { set_header("Location", url); if (300 <= stat && stat < 400) { @@ -4015,12 +4633,8 @@ static WSInit wsinit_; } } - inline void Response::set_redirect(const std::string &url, int stat) { - set_redirect(url.c_str(), stat); - } - inline void Response::set_content(const char *s, size_t n, - const char *content_type) { + const std::string &content_type) { body.assign(s, n); auto rng = headers.equal_range("Content-Type"); @@ -4029,12 +4643,12 @@ static WSInit wsinit_; } inline void Response::set_content(const std::string &s, - const char *content_type) { + const std::string &content_type) { set_content(s.data(), s.size(), content_type); } inline void Response::set_content_provider( - size_t in_length, const char *content_type, ContentProvider provider, + size_t in_length, const std::string &content_type, ContentProvider provider, ContentProviderResourceReleaser resource_releaser) { assert(in_length > 0); set_header("Content-Type", content_type); @@ -4045,7 +4659,7 @@ static WSInit wsinit_; } inline void Response::set_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser) { set_header("Content-Type", content_type); content_length_ = 0; @@ -4055,7 +4669,7 @@ static WSInit wsinit_; } inline void Response::set_chunked_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser) { set_header("Content-Type", content_type); content_length_ = 0; @@ -4065,21 +4679,17 @@ static WSInit wsinit_; } // Result implementation - inline bool Result::has_request_header(const char *key) const { + inline bool Result::has_request_header(const std::string &key) const { return request_headers_.find(key) != request_headers_.end(); } - inline std::string Result::get_request_header_value(const char *key, + inline std::string Result::get_request_header_value(const std::string &key, size_t id) const { return detail::get_header_value(request_headers_, key, id, ""); } - template - inline T Result::get_request_header_value(const char *key, size_t id) const { - return detail::get_header_value(request_headers_, key, id, 0); - } - - inline size_t Result::get_request_header_value_count(const char *key) const { + inline size_t + Result::get_request_header_value_count(const std::string &key) const { auto r = request_headers_.equal_range(key); return static_cast(std::distance(r.first, r.second)); } @@ -4093,40 +4703,6 @@ static WSInit wsinit_; return write(s.data(), s.size()); } - template - inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { - const auto bufsiz = 2048; - std::array buf; - -#if defined(_MSC_VER) && _MSC_VER < 1900 - auto sn = _snprintf_s(buf.data(), bufsiz - 1, buf.size() - 1, fmt, args...); -#else - auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...); -#endif - if (sn <= 0) { return sn; } - - auto n = static_cast(sn); - - if (n >= buf.size() - 1) { - std::vector glowable_buf(buf.size()); - - while (n >= glowable_buf.size() - 1) { - glowable_buf.resize(glowable_buf.size() * 2); -#if defined(_MSC_VER) && _MSC_VER < 1900 - n = static_cast(_snprintf_s(&glowable_buf[0], glowable_buf.size(), - glowable_buf.size() - 1, fmt, - args...)); -#else - n = static_cast( - snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...)); -#endif - } - return write(&glowable_buf[0], n); - } else { - return write(buf.data(), n); - } - } - namespace detail { // Socket stream implementation @@ -4137,7 +4713,7 @@ static WSInit wsinit_; : sock_(sock), read_timeout_sec_(read_timeout_sec), read_timeout_usec_(read_timeout_usec), write_timeout_sec_(write_timeout_sec), - write_timeout_usec_(write_timeout_usec) {} + write_timeout_usec_(write_timeout_usec), read_buff_(read_buff_size_, 0) {} inline SocketStream::~SocketStream() {} @@ -4146,35 +4722,65 @@ static WSInit wsinit_; } inline bool SocketStream::is_writable() const { - return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0; + return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && + is_socket_alive(sock_); } inline ssize_t SocketStream::read(char *ptr, size_t size) { +#ifdef _WIN32 + size = + (std::min)(size, static_cast((std::numeric_limits::max)())); +#else + size = (std::min)(size, + static_cast((std::numeric_limits::max)())); +#endif + + if (read_buff_off_ < read_buff_content_size_) { + auto remaining_size = read_buff_content_size_ - read_buff_off_; + if (size <= remaining_size) { + memcpy(ptr, read_buff_.data() + read_buff_off_, size); + read_buff_off_ += size; + return static_cast(size); + } else { + memcpy(ptr, read_buff_.data() + read_buff_off_, remaining_size); + read_buff_off_ += remaining_size; + return static_cast(remaining_size); + } + } + if (!is_readable()) { return -1; } -#ifdef _WIN32 - if (size > static_cast((std::numeric_limits::max)())) { - return -1; - } - return recv(sock_, ptr, static_cast(size), CPPHTTPLIB_RECV_FLAGS); -#else - return handle_EINTR( - [&]() { return recv(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS); }); -#endif + read_buff_off_ = 0; + read_buff_content_size_ = 0; + + if (size < read_buff_size_) { + auto n = read_socket(sock_, read_buff_.data(), read_buff_size_, + CPPHTTPLIB_RECV_FLAGS); + if (n <= 0) { + return n; + } else if (n <= static_cast(size)) { + memcpy(ptr, read_buff_.data(), static_cast(n)); + return n; + } else { + memcpy(ptr, read_buff_.data(), size); + read_buff_off_ = size; + read_buff_content_size_ = static_cast(n); + return static_cast(size); + } + } else { + return read_socket(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS); + } } inline ssize_t SocketStream::write(const char *ptr, size_t size) { if (!is_writable()) { return -1; } -#ifdef _WIN32 - if (size > static_cast((std::numeric_limits::max)())) { - return -1; - } - return send(sock_, ptr, static_cast(size), CPPHTTPLIB_SEND_FLAGS); -#else - return handle_EINTR( - [&]() { return send(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); }); +#if defined(_WIN32) && !defined(_WIN64) + size = + (std::min)(size, static_cast((std::numeric_limits::max)())); #endif + + return send_socket(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); } inline void SocketStream::get_remote_ip_and_port(std::string &ip, @@ -4190,7 +4796,7 @@ static WSInit wsinit_; inline bool BufferStream::is_writable() const { return true; } inline ssize_t BufferStream::read(char *ptr, size_t size) { -#if defined(_MSC_VER) && _MSC_VER <= 1900 +#if defined(_MSC_VER) && _MSC_VER < 1910 auto len_read = buffer._Copy_s(ptr, size, size, position); #else auto len_read = buffer.copy(ptr, size, position); @@ -4225,128 +4831,79 @@ static WSInit wsinit_; inline Server::~Server() {} - inline Server &Server::Get(const char *pattern, Handler handler) { - return Get(pattern, strlen(pattern), handler); - } - - inline Server &Server::Get(const char *pattern, size_t pattern_len, - Handler handler) { + inline Server &Server::Get(const std::string &pattern, Handler handler) { get_handlers_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Post(const char *pattern, Handler handler) { - return Post(pattern, strlen(pattern), handler); - } - - inline Server &Server::Post(const char *pattern, size_t pattern_len, - Handler handler) { + inline Server &Server::Post(const std::string &pattern, Handler handler) { post_handlers_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Post(const char *pattern, - HandlerWithContentReader handler) { - return Post(pattern, strlen(pattern), handler); - } - - inline Server &Server::Post(const char *pattern, size_t pattern_len, + inline Server &Server::Post(const std::string &pattern, HandlerWithContentReader handler) { post_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Put(const char *pattern, Handler handler) { - return Put(pattern, strlen(pattern), handler); - } - - inline Server &Server::Put(const char *pattern, size_t pattern_len, - Handler handler) { + inline Server &Server::Put(const std::string &pattern, Handler handler) { put_handlers_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Put(const char *pattern, - HandlerWithContentReader handler) { - return Put(pattern, strlen(pattern), handler); - } - - inline Server &Server::Put(const char *pattern, size_t pattern_len, + inline Server &Server::Put(const std::string &pattern, HandlerWithContentReader handler) { put_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Patch(const char *pattern, Handler handler) { - return Patch(pattern, strlen(pattern), handler); - } - - inline Server &Server::Patch(const char *pattern, size_t pattern_len, - Handler handler) { + inline Server &Server::Patch(const std::string &pattern, Handler handler) { patch_handlers_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Patch(const char *pattern, - HandlerWithContentReader handler) { - return Patch(pattern, strlen(pattern), handler); - } - - inline Server &Server::Patch(const char *pattern, size_t pattern_len, + inline Server &Server::Patch(const std::string &pattern, HandlerWithContentReader handler) { patch_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Delete(const char *pattern, Handler handler) { - return Delete(pattern, strlen(pattern), handler); - } - - inline Server &Server::Delete(const char *pattern, size_t pattern_len, - Handler handler) { + inline Server &Server::Delete(const std::string &pattern, Handler handler) { delete_handlers_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Delete(const char *pattern, - HandlerWithContentReader handler) { - return Delete(pattern, strlen(pattern), handler); - } - - inline Server &Server::Delete(const char *pattern, size_t pattern_len, + inline Server &Server::Delete(const std::string &pattern, HandlerWithContentReader handler) { delete_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline Server &Server::Options(const char *pattern, Handler handler) { - return Options(pattern, strlen(pattern), handler); - } - - inline Server &Server::Options(const char *pattern, size_t pattern_len, - Handler handler) { + inline Server &Server::Options(const std::string &pattern, Handler handler) { options_handlers_.push_back( - std::make_pair(std::regex(pattern, pattern_len), std::move(handler))); + std::make_pair(std::regex(pattern), std::move(handler))); return *this; } - inline bool Server::set_base_dir(const char *dir, const char *mount_point) { + inline bool Server::set_base_dir(const std::string &dir, + const std::string &mount_point) { return set_mount_point(mount_point, dir); } - inline bool Server::set_mount_point(const char *mount_point, const char *dir, - Headers headers) { + inline bool Server::set_mount_point(const std::string &mount_point, + const std::string &dir, Headers headers) { if (detail::is_dir(dir)) { - std::string mnt = mount_point ? mount_point : "/"; + std::string mnt = !mount_point.empty() ? mount_point : "/"; if (!mnt.empty() && mnt[0] == '/') { base_dirs_.push_back({mnt, dir, std::move(headers)}); return true; @@ -4355,7 +4912,7 @@ static WSInit wsinit_; return false; } - inline bool Server::remove_mount_point(const char *mount_point) { + inline bool Server::remove_mount_point(const std::string &mount_point) { for (auto it = base_dirs_.begin(); it != base_dirs_.end(); ++it) { if (it->mount_point == mount_point) { base_dirs_.erase(it); @@ -4366,8 +4923,8 @@ static WSInit wsinit_; } inline Server & - Server::set_file_extension_and_mimetype_mapping(const char *ext, - const char *mime) { + Server::set_file_extension_and_mimetype_mapping(const std::string &ext, + const std::string &mime) { file_extension_and_mimetype_map_[ext] = mime; return *this; } @@ -4453,58 +5010,36 @@ static WSInit wsinit_; return *this; } - template - inline Server & - Server::set_read_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); - return *this; - } - inline Server &Server::set_write_timeout(time_t sec, time_t usec) { write_timeout_sec_ = sec; write_timeout_usec_ = usec; return *this; } - template - inline Server & - Server::set_write_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); - return *this; - } - inline Server &Server::set_idle_interval(time_t sec, time_t usec) { idle_interval_sec_ = sec; idle_interval_usec_ = usec; return *this; } - template - inline Server & - Server::set_idle_interval(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); }); - return *this; - } - inline Server &Server::set_payload_max_length(size_t length) { payload_max_length_ = length; return *this; } - inline bool Server::bind_to_port(const char *host, int port, int socket_flags) { + inline bool Server::bind_to_port(const std::string &host, int port, + int socket_flags) { if (bind_internal(host, port, socket_flags) < 0) return false; return true; } - inline int Server::bind_to_any_port(const char *host, int socket_flags) { + inline int Server::bind_to_any_port(const std::string &host, int socket_flags) { return bind_internal(host, 0, socket_flags); } inline bool Server::listen_after_bind() { return listen_internal(); } - inline bool Server::listen(const char *host, int port, int socket_flags) { + inline bool Server::listen(const std::string &host, int port, + int socket_flags) { return bind_to_port(host, port, socket_flags) && listen_internal(); } @@ -4520,25 +5055,66 @@ static WSInit wsinit_; } inline bool Server::parse_request_line(const char *s, Request &req) { - const static std::regex re( - "(GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH|PRI) " - "(([^? ]+)(?:\\?([^ ]*?))?) (HTTP/1\\.[01])\r\n"); + auto len = strlen(s); + if (len < 2 || s[len - 2] != '\r' || s[len - 1] != '\n') { return false; } + len -= 2; - std::cmatch m; - if (std::regex_match(s, m, re)) { - req.version = std::string(m[5]); - req.method = std::string(m[1]); - req.target = std::string(m[2]); - req.path = detail::decode_url(m[3], false); + { + size_t count = 0; - // Parse query text - auto len = std::distance(m[4].first, m[4].second); - if (len > 0) { detail::parse_query_text(m[4], req.params); } + detail::split(s, s + len, ' ', [&](const char *b, const char *e) { + switch (count) { + case 0: req.method = std::string(b, e); break; + case 1: req.target = std::string(b, e); break; + case 2: req.version = std::string(b, e); break; + default: break; + } + count++; + }); - return true; + if (count != 3) { return false; } } - return false; + static const std::set methods{ + "GET", "HEAD", "POST", "PUT", "DELETE", + "CONNECT", "OPTIONS", "TRACE", "PATCH", "PRI"}; + + if (methods.find(req.method) == methods.end()) { return false; } + + if (req.version != "HTTP/1.1" && req.version != "HTTP/1.0") { return false; } + + { + // Skip URL fragment + for (size_t i = 0; i < req.target.size(); i++) { + if (req.target[i] == '#') { + req.target.erase(i); + break; + } + } + + size_t count = 0; + + detail::split(req.target.data(), req.target.data() + req.target.size(), '?', + [&](const char *b, const char *e) { + switch (count) { + case 0: + req.path = detail::decode_url(std::string(b, e), false); + break; + case 1: { + if (e - b > 0) { + detail::parse_query_text(std::string(b, e), req.params); + } + break; + } + default: break; + } + count++; + }); + + if (count > 2) { return false; } + } + + return true; } inline bool Server::write_response(Stream &strm, bool close_connection, @@ -4606,17 +5182,18 @@ static WSInit wsinit_; // Flush buffer auto &data = bstrm.get_buffer(); - strm.write(data.data(), data.size()); + detail::write_data(strm, data.data(), data.size()); } // Body auto ret = true; if (req.method != "HEAD") { if (!res.body.empty()) { - if (!strm.write(res.body)) { ret = false; } + if (!detail::write_data(strm, res.body.data(), res.body.size())) { + ret = false; + } } else if (res.content_provider_) { - if (write_content_with_provider(strm, req, res, boundary, - content_type)) { + if (write_content_with_provider(strm, req, res, boundary, content_type)) { res.content_provider_success_ = true; } else { res.content_provider_success_ = false; @@ -4683,6 +5260,7 @@ static WSInit wsinit_; inline bool Server::read_content(Stream &strm, Request &req, Response &res) { MultipartFormDataMap::iterator cur; + auto file_count = 0; if (read_content_core( strm, req, res, // Regular @@ -4693,6 +5271,9 @@ static WSInit wsinit_; }, // Multipart [&](const MultipartFormData &file) { + if (file_count++ == CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT) { + return false; + } cur = req.files.emplace(file.name, file); return true; }, @@ -4704,6 +5285,10 @@ static WSInit wsinit_; })) { const auto &content_type = req.get_header_value("Content-Type"); if (!content_type.find("application/x-www-form-urlencoded")) { + if (req.body.size() > CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH) { + res.status = 413; // NOTE: should be 414? + return false; + } detail::parse_query_text(req.body, req.params); } return true; @@ -4740,7 +5325,7 @@ static WSInit wsinit_; /* For debug size_t pos = 0; while (pos < n) { - auto read_size = std::min(1, n - pos); + auto read_size = (std::min)(1, n - pos); auto ret = multipart_form_data_parser.parse( buf + pos, read_size, multipart_receiver, mulitpart_header); if (!ret) { return false; } @@ -4806,23 +5391,23 @@ static WSInit wsinit_; } inline socket_t - Server::create_server_socket(const char *host, int port, int socket_flags, + Server::create_server_socket(const std::string &host, int port, + int socket_flags, SocketOptions socket_options) const { return detail::create_socket( - host, port, address_family_, socket_flags, tcp_nodelay_, + host, std::string(), port, address_family_, socket_flags, tcp_nodelay_, std::move(socket_options), [](socket_t sock, struct addrinfo &ai) -> bool { if (::bind(sock, ai.ai_addr, static_cast(ai.ai_addrlen))) { return false; } - if (::listen(sock, 5)) { // Listen through 5 channels - return false; - } + if (::listen(sock, CPPHTTPLIB_LISTEN_BACKLOG)) { return false; } return true; }); } - inline int Server::bind_internal(const char *host, int port, int socket_flags) { + inline int Server::bind_internal(const std::string &host, int port, + int socket_flags) { if (!is_valid()) { return -1; } svr_sock_ = create_server_socket(host, port, socket_flags, socket_options_); @@ -4886,16 +5471,31 @@ static WSInit wsinit_; } { +#ifdef _WIN32 + auto timeout = static_cast(read_timeout_sec_ * 1000 + + read_timeout_usec_ / 1000); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, + sizeof(timeout)); +#else timeval tv; tv.tv_sec = static_cast(read_timeout_sec_); tv.tv_usec = static_cast(read_timeout_usec_); setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); +#endif } { + +#ifdef _WIN32 + auto timeout = static_cast(write_timeout_sec_ * 1000 + + write_timeout_usec_ / 1000); + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, + sizeof(timeout)); +#else timeval tv; tv.tv_sec = static_cast(write_timeout_sec_); tv.tv_usec = static_cast(write_timeout_usec_); setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); +#endif } #if __cplusplus > 201703L @@ -5219,20 +5819,31 @@ static WSInit wsinit_; // Rounting bool routed = false; +#ifdef CPPHTTPLIB_NO_EXCEPTIONS + routed = routing(req, res, strm); +#else try { routed = routing(req, res, strm); } catch (std::exception &e) { if (exception_handler_) { - exception_handler_(req, res, e); + auto ep = std::current_exception(); + exception_handler_(req, res, ep); routed = true; } else { res.status = 500; res.set_header("EXCEPTION_WHAT", e.what()); } } catch (...) { - res.status = 500; - res.set_header("EXCEPTION_WHAT", "UNKNOWN"); + if (exception_handler_) { + auto ep = std::current_exception(); + exception_handler_(req, res, ep); + routed = true; + } else { + res.status = 500; + res.set_header("EXCEPTION_WHAT", "UNKNOWN"); + } } +#endif if (routed) { if (res.status == -1) { res.status = req.ranges.empty() ? 200 : 206; } @@ -5247,8 +5858,9 @@ static WSInit wsinit_; inline bool Server::process_and_close_socket(socket_t sock) { auto ret = detail::process_server_socket( - sock, keep_alive_max_count_, keep_alive_timeout_sec_, read_timeout_sec_, - read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, + svr_sock_, sock, keep_alive_max_count_, keep_alive_timeout_sec_, + read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, + write_timeout_usec_, [this](Stream &strm, bool close_connection, bool &connection_closed) { return process_request(strm, close_connection, connection_closed, nullptr); @@ -5269,9 +5881,8 @@ static WSInit wsinit_; inline ClientImpl::ClientImpl(const std::string &host, int port, const std::string &client_cert_path, const std::string &client_key_path) - // : (Error::Success), host_(host), port_(port), : host_(host), port_(port), - host_and_port_(host_ + ":" + std::to_string(port_)), + host_and_port_(adjust_host_string(host) + ":" + std::to_string(port)), client_cert_path_(client_cert_path), client_key_path_(client_key_path) {} inline ClientImpl::~ClientImpl() { @@ -5295,7 +5906,7 @@ static WSInit wsinit_; bearer_token_auth_token_ = rhs.bearer_token_auth_token_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT digest_auth_username_ = rhs.digest_auth_username_; - digest_auth_password_ = rhs.digest_auth_password_; + digest_auth_password_ = rhs.digest_auth_password_; #endif keep_alive_ = rhs.keep_alive_; follow_location_ = rhs.follow_location_; @@ -5313,7 +5924,12 @@ static WSInit wsinit_; proxy_bearer_token_auth_token_ = rhs.proxy_bearer_token_auth_token_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT proxy_digest_auth_username_ = rhs.proxy_digest_auth_username_; - proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_; + proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_; +#endif +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + ca_cert_file_path_ = rhs.ca_cert_file_path_; + ca_cert_dir_path_ = rhs.ca_cert_dir_path_; + ca_cert_store_ = rhs.ca_cert_store_; #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT server_certificate_verification_ = rhs.server_certificate_verification_; @@ -5324,13 +5940,19 @@ static WSInit wsinit_; inline socket_t ClientImpl::create_client_socket(Error &error) const { if (!proxy_host_.empty() && proxy_port_ != -1) { return detail::create_client_socket( - proxy_host_.c_str(), proxy_port_, address_family_, tcp_nodelay_, + proxy_host_, std::string(), proxy_port_, address_family_, tcp_nodelay_, socket_options_, connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_, error); } + + // Check is custom IP specified for host_ + std::string ip; + auto it = addr_map_.find(host_); + if (it != addr_map_.end()) ip = it->second; + return detail::create_client_socket( - host_.c_str(), port_, address_family_, tcp_nodelay_, socket_options_, + host_, ip, port_, address_family_, tcp_nodelay_, socket_options_, connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_, error); @@ -5378,13 +6000,17 @@ static WSInit wsinit_; inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, Response &res) { - std::array buf; + std::array buf{}; detail::stream_line_reader line_reader(strm, buf.data(), buf.size()); if (!line_reader.getline()) { return false; } +#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n"); +#else + const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n"); +#endif std::cmatch m; if (!std::regex_match(line_reader.ptr(), m, re)) { @@ -5413,13 +6039,14 @@ static WSInit wsinit_; { std::lock_guard guard(socket_mutex_); + // Set this to false immediately - if it ever gets set to true by the end of // the request, we know another thread instructed us to close the socket. socket_should_be_closed_when_request_is_done_ = false; auto is_alive = false; if (socket_.is_open()) { - is_alive = detail::select_write(socket_.sock, 0, 0) > 0; + is_alive = detail::is_socket_alive(socket_.sock); if (!is_alive) { // Attempt to avoid sigpipe by shutting down nongracefully if it seems // like the other side has already closed the connection Also, there @@ -5437,17 +6064,17 @@ static WSInit wsinit_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT // TODO: refactoring - if (is_ssl()) { - auto &scli = static_cast(*this); - if (!proxy_host_.empty() && proxy_port_ != -1) { - bool success = false; - if (!scli.connect_with_proxy(socket_, res, success, error)) { - return success; - } - } + if (is_ssl()) { + auto &scli = static_cast(*this); + if (!proxy_host_.empty() && proxy_port_ != -1) { + bool success = false; + if (!scli.connect_with_proxy(socket_, res, success, error)) { + return success; + } + } - if (!scli.initialize_ssl(socket_, error)) { return false; } - } + if (!scli.initialize_ssl(socket_, error)) { return false; } + } #endif } @@ -5539,31 +6166,31 @@ static WSInit wsinit_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT if ((res.status == 401 || res.status == 407) && - req.authorization_count_ < 5) { - auto is_proxy = res.status == 407; - const auto &username = - is_proxy ? proxy_digest_auth_username_ : digest_auth_username_; - const auto &password = - is_proxy ? proxy_digest_auth_password_ : digest_auth_password_; + req.authorization_count_ < 5) { + auto is_proxy = res.status == 407; + const auto &username = + is_proxy ? proxy_digest_auth_username_ : digest_auth_username_; + const auto &password = + is_proxy ? proxy_digest_auth_password_ : digest_auth_password_; - if (!username.empty() && !password.empty()) { - std::map auth; - if (detail::parse_www_authenticate(res, auth, is_proxy)) { - Request new_req = req; - new_req.authorization_count_ += 1; - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - new_req.headers.erase(key); - new_req.headers.insert(detail::make_digest_authentication_header( - req, auth, new_req.authorization_count_, detail::random_string(10), - username, password, is_proxy)); + if (!username.empty() && !password.empty()) { + std::map auth; + if (detail::parse_www_authenticate(res, auth, is_proxy)) { + Request new_req = req; + new_req.authorization_count_ += 1; + new_req.headers.erase(is_proxy ? "Proxy-Authorization" + : "Authorization"); + new_req.headers.insert(detail::make_digest_authentication_header( + req, auth, new_req.authorization_count_, detail::random_string(10), + username, password, is_proxy)); - Response new_res; + Response new_res; - ret = send(new_req, new_res, error); - if (ret) { res = new_res; } - } - } - } + ret = send(new_req, new_res, error); + if (ret) { res = new_res; } + } + } + } #endif return ret; @@ -5579,7 +6206,7 @@ static WSInit wsinit_; if (location.empty()) { return false; } const static std::regex re( - R"(^(?:(https?):)?(?://([^:/?#]*)(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)"); + R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)"); std::smatch m; if (!std::regex_match(location, m, re)) { return false; } @@ -5588,8 +6215,9 @@ static WSInit wsinit_; auto next_scheme = m[1].str(); auto next_host = m[2].str(); - auto port_str = m[3].str(); - auto next_path = m[4].str(); + if (next_host.empty()) { next_host = m[3].str(); } + auto port_str = m[4].str(); + auto next_path = m[5].str(); auto next_port = port_; if (!port_str.empty()) { @@ -5608,8 +6236,9 @@ static WSInit wsinit_; if (next_scheme == "https") { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT SSLClient cli(next_host.c_str(), next_port); - cli.copy_settings(*this); - return detail::redirect(cli, req, res, next_path, location, error); + cli.copy_settings(*this); + if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); } + return detail::redirect(cli, req, res, next_path, location, error); #else return false; #endif @@ -5649,7 +6278,11 @@ static WSInit wsinit_; inline bool ClientImpl::write_request(Stream &strm, Request &req, bool close_connection, Error &error) { // Prepare additional headers - if (close_connection) { req.headers.emplace("Connection", "close"); } + if (close_connection) { + if (!req.has_header("Connection")) { + req.headers.emplace("Connection", "close"); + } + } if (!req.has_header("Host")) { if (is_ssl()) { @@ -5669,15 +6302,20 @@ static WSInit wsinit_; if (!req.has_header("Accept")) { req.headers.emplace("Accept", "*/*"); } +#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT if (!req.has_header("User-Agent")) { - req.headers.emplace("User-Agent", "cpp-httplib/0.7"); + auto agent = std::string("cpp-httplib/") + CPPHTTPLIB_VERSION; + req.headers.emplace("User-Agent", agent); } +#endif if (req.body.empty()) { if (req.content_provider_) { if (!req.is_chunked_content_provider_) { - auto length = std::to_string(req.content_length_); - req.headers.emplace("Content-Length", length); + if (!req.has_header("Content-Length")) { + auto length = std::to_string(req.content_length_); + req.headers.emplace("Content-Length", length); + } } } else { if (req.method == "POST" || req.method == "PUT" || @@ -5697,24 +6335,32 @@ static WSInit wsinit_; } if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) { - req.headers.insert(make_basic_authentication_header( - basic_auth_username_, basic_auth_password_, false)); + if (!req.has_header("Authorization")) { + req.headers.insert(make_basic_authentication_header( + basic_auth_username_, basic_auth_password_, false)); + } } if (!proxy_basic_auth_username_.empty() && !proxy_basic_auth_password_.empty()) { - req.headers.insert(make_basic_authentication_header( - proxy_basic_auth_username_, proxy_basic_auth_password_, true)); + if (!req.has_header("Proxy-Authorization")) { + req.headers.insert(make_basic_authentication_header( + proxy_basic_auth_username_, proxy_basic_auth_password_, true)); + } } if (!bearer_token_auth_token_.empty()) { - req.headers.insert(make_bearer_token_authentication_header( - bearer_token_auth_token_, false)); + if (!req.has_header("Authorization")) { + req.headers.insert(make_bearer_token_authentication_header( + bearer_token_auth_token_, false)); + } } if (!proxy_bearer_token_auth_token_.empty()) { - req.headers.insert(make_bearer_token_authentication_header( - proxy_bearer_token_auth_token_, true)); + if (!req.has_header("Proxy-Authorization")) { + req.headers.insert(make_bearer_token_authentication_header( + proxy_bearer_token_auth_token_, true)); + } } // Request line and headers @@ -5737,26 +6383,24 @@ static WSInit wsinit_; // Body if (req.body.empty()) { return write_content_with_provider(strm, req, error); - } else { - return detail::write_data(strm, req.body.data(), req.body.size()); + } + + if (!detail::write_data(strm, req.body.data(), req.body.size())) { + error = Error::Write; + return false; } return true; } inline std::unique_ptr ClientImpl::send_with_content_provider( - Request &req, - // const char *method, const char *path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, + Request &req, const char *body, size_t content_length, + ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type, Error &error) { - - // Request req; - // req.method = method; - // req.headers = headers; - // req.path = path; - - if (content_type) { req.headers.emplace("Content-Type", content_type); } + const std::string &content_type, Error &error) { + if (!content_type.empty()) { + req.headers.emplace("Content-Type", content_type); + } #ifdef CPPHTTPLIB_ZLIB_SUPPORT if (compress_) { req.headers.emplace("Content-Encoding", "gzip"); } @@ -5777,8 +6421,9 @@ static WSInit wsinit_; auto last = offset + data_len == content_length; auto ret = compressor.compress( - data, data_len, last, [&](const char *data, size_t data_len) { - req.body.append(data, data_len); + data, data_len, last, + [&](const char *compressed_data, size_t compressed_data_len) { + req.body.append(compressed_data, compressed_data_len); return true; }); @@ -5833,10 +6478,10 @@ static WSInit wsinit_; } inline Result ClientImpl::send_with_content_provider( - const char *method, const char *path, const Headers &headers, + const std::string &method, const std::string &path, const Headers &headers, const char *body, size_t content_length, ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type) { + const std::string &content_type) { Request req; req.method = method; req.headers = headers; @@ -5845,14 +6490,18 @@ static WSInit wsinit_; auto error = Error::Success; auto res = send_with_content_provider( - req, - // method, path, headers, - body, content_length, std::move(content_provider), + req, body, content_length, std::move(content_provider), std::move(content_provider_without_length), content_type, error); return Result{std::move(res), error, std::move(req.headers)}; } + inline std::string + ClientImpl::adjust_host_string(const std::string &host) const { + if (host.find(':') != std::string::npos) { return "[" + host + "]"; } + return host; + } + inline bool ClientImpl::process_request(Stream &strm, Request &req, Response &res, bool close_connection, Error &error) { @@ -5946,19 +6595,19 @@ static WSInit wsinit_; inline bool ClientImpl::is_ssl() const { return false; } - inline Result ClientImpl::Get(const char *path) { + inline Result ClientImpl::Get(const std::string &path) { return Get(path, Headers(), Progress()); } - inline Result ClientImpl::Get(const char *path, Progress progress) { + inline Result ClientImpl::Get(const std::string &path, Progress progress) { return Get(path, Headers(), std::move(progress)); } - inline Result ClientImpl::Get(const char *path, const Headers &headers) { + inline Result ClientImpl::Get(const std::string &path, const Headers &headers) { return Get(path, headers, Progress()); } - inline Result ClientImpl::Get(const char *path, const Headers &headers, + inline Result ClientImpl::Get(const std::string &path, const Headers &headers, Progress progress) { Request req; req.method = "GET"; @@ -5969,45 +6618,45 @@ static WSInit wsinit_; return send_(std::move(req)); } - inline Result ClientImpl::Get(const char *path, + inline Result ClientImpl::Get(const std::string &path, ContentReceiver content_receiver) { return Get(path, Headers(), nullptr, std::move(content_receiver), nullptr); } - inline Result ClientImpl::Get(const char *path, + inline Result ClientImpl::Get(const std::string &path, ContentReceiver content_receiver, Progress progress) { return Get(path, Headers(), nullptr, std::move(content_receiver), std::move(progress)); } - inline Result ClientImpl::Get(const char *path, const Headers &headers, + inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver) { return Get(path, headers, nullptr, std::move(content_receiver), nullptr); } - inline Result ClientImpl::Get(const char *path, const Headers &headers, + inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, Progress progress) { return Get(path, headers, nullptr, std::move(content_receiver), std::move(progress)); } - inline Result ClientImpl::Get(const char *path, + inline Result ClientImpl::Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver) { return Get(path, Headers(), std::move(response_handler), std::move(content_receiver), nullptr); } - inline Result ClientImpl::Get(const char *path, const Headers &headers, + inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver) { return Get(path, headers, std::move(response_handler), std::move(content_receiver), nullptr); } - inline Result ClientImpl::Get(const char *path, + inline Result ClientImpl::Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { @@ -6015,7 +6664,7 @@ static WSInit wsinit_; std::move(content_receiver), std::move(progress)); } - inline Result ClientImpl::Get(const char *path, const Headers &headers, + inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { @@ -6034,22 +6683,22 @@ static WSInit wsinit_; return send_(std::move(req)); } - inline Result ClientImpl::Get(const char *path, const Params ¶ms, + inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, const Headers &headers, Progress progress) { if (params.empty()) { return Get(path, headers); } - std::string path_with_query = detail::append_query_params(path, params); + std::string path_with_query = append_query_params(path, params); return Get(path_with_query.c_str(), headers, progress); } - inline Result ClientImpl::Get(const char *path, const Params ¶ms, + inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, const Headers &headers, ContentReceiver content_receiver, Progress progress) { return Get(path, params, headers, nullptr, content_receiver, progress); } - inline Result ClientImpl::Get(const char *path, const Params ¶ms, + inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, @@ -6058,16 +6707,17 @@ static WSInit wsinit_; return Get(path, headers, response_handler, content_receiver, progress); } - std::string path_with_query = detail::append_query_params(path, params); + std::string path_with_query = append_query_params(path, params); return Get(path_with_query.c_str(), headers, response_handler, content_receiver, progress); } - inline Result ClientImpl::Head(const char *path) { + inline Result ClientImpl::Head(const std::string &path) { return Head(path, Headers()); } - inline Result ClientImpl::Head(const char *path, const Headers &headers) { + inline Result ClientImpl::Head(const std::string &path, + const Headers &headers) { Request req; req.method = "HEAD"; req.headers = headers; @@ -6076,288 +6726,308 @@ static WSInit wsinit_; return send_(std::move(req)); } - inline Result ClientImpl::Post(const char *path) { - return Post(path, std::string(), nullptr); + inline Result ClientImpl::Post(const std::string &path) { + return Post(path, std::string(), std::string()); } - inline Result ClientImpl::Post(const char *path, const char *body, + inline Result ClientImpl::Post(const std::string &path, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return Post(path, Headers(), body, content_length, content_type); } - inline Result ClientImpl::Post(const char *path, const Headers &headers, + inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("POST", path, headers, body, content_length, nullptr, nullptr, content_type); } - inline Result ClientImpl::Post(const char *path, const std::string &body, - const char *content_type) { + inline Result ClientImpl::Post(const std::string &path, const std::string &body, + const std::string &content_type) { return Post(path, Headers(), body, content_type); } - inline Result ClientImpl::Post(const char *path, const Headers &headers, + inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const std::string &body, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("POST", path, headers, body.data(), body.size(), nullptr, nullptr, content_type); } - inline Result ClientImpl::Post(const char *path, const Params ¶ms) { + inline Result ClientImpl::Post(const std::string &path, const Params ¶ms) { return Post(path, Headers(), params); } - inline Result ClientImpl::Post(const char *path, size_t content_length, + inline Result ClientImpl::Post(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return Post(path, Headers(), content_length, std::move(content_provider), content_type); } - inline Result ClientImpl::Post(const char *path, + inline Result ClientImpl::Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return Post(path, Headers(), std::move(content_provider), content_type); } - inline Result ClientImpl::Post(const char *path, const Headers &headers, + inline Result ClientImpl::Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("POST", path, headers, nullptr, content_length, std::move(content_provider), nullptr, content_type); } - inline Result ClientImpl::Post(const char *path, const Headers &headers, + inline Result ClientImpl::Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("POST", path, headers, nullptr, 0, nullptr, std::move(content_provider), content_type); } - inline Result ClientImpl::Post(const char *path, const Headers &headers, + inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const Params ¶ms) { auto query = detail::params_to_query_str(params); return Post(path, headers, query, "application/x-www-form-urlencoded"); } - inline Result ClientImpl::Post(const char *path, + inline Result ClientImpl::Post(const std::string &path, const MultipartFormDataItems &items) { return Post(path, Headers(), items); } - inline Result ClientImpl::Post(const char *path, const Headers &headers, + inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items) { - return Post(path, headers, items, detail::make_multipart_data_boundary()); - } - inline Result ClientImpl::Post(const char *path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - for (size_t i = 0; i < boundary.size(); i++) { - char c = boundary[i]; - if (!std::isalnum(c) && c != '-' && c != '_') { - return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; - } - } - - std::string body; - - for (const auto &item : items) { - body += "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"" + item.name + "\""; - if (!item.filename.empty()) { - body += "; filename=\"" + item.filename + "\""; - } - body += "\r\n"; - if (!item.content_type.empty()) { - body += "Content-Type: " + item.content_type + "\r\n"; - } - body += "\r\n"; - body += item.content + "\r\n"; - } - - body += "--" + boundary + "--\r\n"; - - std::string content_type = "multipart/form-data; boundary=" + boundary; + std::string content_type; + const auto &body = detail::serialize_multipart_formdata( + items, detail::make_multipart_data_boundary(), content_type); return Post(path, headers, body, content_type.c_str()); } - inline Result ClientImpl::Put(const char *path) { - return Put(path, std::string(), nullptr); + inline Result ClientImpl::Post(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const std::string &boundary) { + if (!detail::is_multipart_boundary_chars_valid(boundary)) { + return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; + } + + std::string content_type; + const auto &body = + detail::serialize_multipart_formdata(items, boundary, content_type); + return Post(path, headers, body, content_type.c_str()); } - inline Result ClientImpl::Put(const char *path, const char *body, - size_t content_length, const char *content_type) { + inline Result ClientImpl::Put(const std::string &path) { + return Put(path, std::string(), std::string()); + } + + inline Result ClientImpl::Put(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return Put(path, Headers(), body, content_length, content_type); } - inline Result ClientImpl::Put(const char *path, const Headers &headers, + inline Result ClientImpl::Put(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PUT", path, headers, body, content_length, nullptr, nullptr, content_type); } - inline Result ClientImpl::Put(const char *path, const std::string &body, - const char *content_type) { + inline Result ClientImpl::Put(const std::string &path, const std::string &body, + const std::string &content_type) { return Put(path, Headers(), body, content_type); } - inline Result ClientImpl::Put(const char *path, const Headers &headers, + inline Result ClientImpl::Put(const std::string &path, const Headers &headers, const std::string &body, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PUT", path, headers, body.data(), body.size(), nullptr, nullptr, content_type); } - inline Result ClientImpl::Put(const char *path, size_t content_length, + inline Result ClientImpl::Put(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return Put(path, Headers(), content_length, std::move(content_provider), content_type); } - inline Result ClientImpl::Put(const char *path, + inline Result ClientImpl::Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return Put(path, Headers(), std::move(content_provider), content_type); } - inline Result ClientImpl::Put(const char *path, const Headers &headers, + inline Result ClientImpl::Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PUT", path, headers, nullptr, content_length, std::move(content_provider), nullptr, content_type); } - inline Result ClientImpl::Put(const char *path, const Headers &headers, + inline Result ClientImpl::Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PUT", path, headers, nullptr, 0, nullptr, std::move(content_provider), content_type); } - inline Result ClientImpl::Put(const char *path, const Params ¶ms) { + inline Result ClientImpl::Put(const std::string &path, const Params ¶ms) { return Put(path, Headers(), params); } - inline Result ClientImpl::Put(const char *path, const Headers &headers, + inline Result ClientImpl::Put(const std::string &path, const Headers &headers, const Params ¶ms) { auto query = detail::params_to_query_str(params); return Put(path, headers, query, "application/x-www-form-urlencoded"); } - inline Result ClientImpl::Patch(const char *path) { - return Patch(path, std::string(), nullptr); + inline Result ClientImpl::Put(const std::string &path, + const MultipartFormDataItems &items) { + return Put(path, Headers(), items); } - inline Result ClientImpl::Patch(const char *path, const char *body, + inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items) { + std::string content_type; + const auto &body = detail::serialize_multipart_formdata( + items, detail::make_multipart_data_boundary(), content_type); + return Put(path, headers, body, content_type); + } + + inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const std::string &boundary) { + if (!detail::is_multipart_boundary_chars_valid(boundary)) { + return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; + } + + std::string content_type; + const auto &body = + detail::serialize_multipart_formdata(items, boundary, content_type); + return Put(path, headers, body, content_type); + } + + inline Result ClientImpl::Patch(const std::string &path) { + return Patch(path, std::string(), std::string()); + } + + inline Result ClientImpl::Patch(const std::string &path, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return Patch(path, Headers(), body, content_length, content_type); } - inline Result ClientImpl::Patch(const char *path, const Headers &headers, + inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PATCH", path, headers, body, content_length, nullptr, nullptr, content_type); } - inline Result ClientImpl::Patch(const char *path, const std::string &body, - const char *content_type) { + inline Result ClientImpl::Patch(const std::string &path, + const std::string &body, + const std::string &content_type) { return Patch(path, Headers(), body, content_type); } - inline Result ClientImpl::Patch(const char *path, const Headers &headers, + inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, const std::string &body, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PATCH", path, headers, body.data(), body.size(), nullptr, nullptr, content_type); } - inline Result ClientImpl::Patch(const char *path, size_t content_length, + inline Result ClientImpl::Patch(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return Patch(path, Headers(), content_length, std::move(content_provider), content_type); } - inline Result ClientImpl::Patch(const char *path, + inline Result ClientImpl::Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return Patch(path, Headers(), std::move(content_provider), content_type); } - inline Result ClientImpl::Patch(const char *path, const Headers &headers, + inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PATCH", path, headers, nullptr, content_length, std::move(content_provider), nullptr, content_type); } - inline Result ClientImpl::Patch(const char *path, const Headers &headers, + inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PATCH", path, headers, nullptr, 0, nullptr, std::move(content_provider), content_type); } - inline Result ClientImpl::Delete(const char *path) { - return Delete(path, Headers(), std::string(), nullptr); + inline Result ClientImpl::Delete(const std::string &path) { + return Delete(path, Headers(), std::string(), std::string()); } - inline Result ClientImpl::Delete(const char *path, const Headers &headers) { - return Delete(path, headers, std::string(), nullptr); + inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers) { + return Delete(path, headers, std::string(), std::string()); } - inline Result ClientImpl::Delete(const char *path, const char *body, + inline Result ClientImpl::Delete(const std::string &path, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return Delete(path, Headers(), body, content_length, content_type); } - inline Result ClientImpl::Delete(const char *path, const Headers &headers, - const char *body, size_t content_length, - const char *content_type) { + inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers, const char *body, + size_t content_length, + const std::string &content_type) { Request req; req.method = "DELETE"; req.headers = headers; req.path = path; - if (content_type) { req.headers.emplace("Content-Type", content_type); } + if (!content_type.empty()) { + req.headers.emplace("Content-Type", content_type); + } req.body.assign(body, content_length); return send_(std::move(req)); } - inline Result ClientImpl::Delete(const char *path, const std::string &body, - const char *content_type) { + inline Result ClientImpl::Delete(const std::string &path, + const std::string &body, + const std::string &content_type) { return Delete(path, Headers(), body.data(), body.size(), content_type); } - inline Result ClientImpl::Delete(const char *path, const Headers &headers, + inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers, const std::string &body, - const char *content_type) { + const std::string &content_type) { return Delete(path, headers, body.data(), body.size(), content_type); } - inline Result ClientImpl::Options(const char *path) { + inline Result ClientImpl::Options(const std::string &path) { return Options(path, Headers()); } - inline Result ClientImpl::Options(const char *path, const Headers &headers) { + inline Result ClientImpl::Options(const std::string &path, + const Headers &headers) { Request req; req.method = "OPTIONS"; req.headers = headers; @@ -6371,6 +7041,8 @@ static WSInit wsinit_; return socket_.is_open(); } + inline socket_t ClientImpl::socket() const { return socket_.sock; } + inline void ClientImpl::stop() { std::lock_guard guard(socket_mutex_); @@ -6399,54 +7071,32 @@ static WSInit wsinit_; connection_timeout_usec_ = usec; } - template - inline void ClientImpl::set_connection_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) { - set_connection_timeout(sec, usec); - }); - } - inline void ClientImpl::set_read_timeout(time_t sec, time_t usec) { read_timeout_sec_ = sec; read_timeout_usec_ = usec; } - template - inline void ClientImpl::set_read_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); - } - inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) { write_timeout_sec_ = sec; write_timeout_usec_ = usec; } - template - inline void ClientImpl::set_write_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); - } - - inline void ClientImpl::set_basic_auth(const char *username, - const char *password) { + inline void ClientImpl::set_basic_auth(const std::string &username, + const std::string &password) { basic_auth_username_ = username; basic_auth_password_ = password; } - inline void ClientImpl::set_bearer_token_auth(const char *token) { + inline void ClientImpl::set_bearer_token_auth(const std::string &token) { bearer_token_auth_token_ = token; } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - inline void ClientImpl::set_digest_auth(const char *username, - const char *password) { - digest_auth_username_ = username; - digest_auth_password_ = password; -} + inline void ClientImpl::set_digest_auth(const std::string &username, + const std::string &password) { + digest_auth_username_ = username; + digest_auth_password_ = password; + } #endif inline void ClientImpl::set_keep_alive(bool on) { keep_alive_ = on; } @@ -6455,6 +7105,11 @@ static WSInit wsinit_; inline void ClientImpl::set_url_encode(bool on) { url_encode_ = on; } + inline void + ClientImpl::set_hostname_addr_map(std::map addr_map) { + addr_map_ = std::move(addr_map); + } + inline void ClientImpl::set_default_headers(Headers headers) { default_headers_ = std::move(headers); } @@ -6473,35 +7128,51 @@ static WSInit wsinit_; inline void ClientImpl::set_decompress(bool on) { decompress_ = on; } - inline void ClientImpl::set_interface(const char *intf) { interface_ = intf; } + inline void ClientImpl::set_interface(const std::string &intf) { + interface_ = intf; + } - inline void ClientImpl::set_proxy(const char *host, int port) { + inline void ClientImpl::set_proxy(const std::string &host, int port) { proxy_host_ = host; proxy_port_ = port; } - inline void ClientImpl::set_proxy_basic_auth(const char *username, - const char *password) { + inline void ClientImpl::set_proxy_basic_auth(const std::string &username, + const std::string &password) { proxy_basic_auth_username_ = username; proxy_basic_auth_password_ = password; } - inline void ClientImpl::set_proxy_bearer_token_auth(const char *token) { + inline void ClientImpl::set_proxy_bearer_token_auth(const std::string &token) { proxy_bearer_token_auth_token_ = token; } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - inline void ClientImpl::set_proxy_digest_auth(const char *username, - const char *password) { - proxy_digest_auth_username_ = username; - proxy_digest_auth_password_ = password; -} + inline void ClientImpl::set_proxy_digest_auth(const std::string &username, + const std::string &password) { + proxy_digest_auth_username_ = username; + proxy_digest_auth_password_ = password; + } +#endif + +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + inline void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path) { + ca_cert_file_path_ = ca_cert_file_path; + ca_cert_dir_path_ = ca_cert_dir_path; + } + + inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) { + if (ca_cert_store && ca_cert_store != ca_cert_store_) { + ca_cert_store_ = ca_cert_store; + } + } #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT inline void ClientImpl::enable_server_certificate_verification(bool enabled) { - server_certificate_verification_ = enabled; -} + server_certificate_verification_ = enabled; + } #endif inline void ClientImpl::set_logger(Logger logger) { @@ -6514,99 +7185,98 @@ static WSInit wsinit_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT namespace detail { -template -inline SSL *ssl_new(socket_t sock, SSL_CTX *ctx, std::mutex &ctx_mutex, - U SSL_connect_or_accept, V setup) { - SSL *ssl = nullptr; - { - std::lock_guard guard(ctx_mutex); - ssl = SSL_new(ctx); - } + template + inline SSL *ssl_new(socket_t sock, SSL_CTX *ctx, std::mutex &ctx_mutex, + U SSL_connect_or_accept, V setup) { + SSL *ssl = nullptr; + { + std::lock_guard guard(ctx_mutex); + ssl = SSL_new(ctx); + } - if (ssl) { - set_nonblocking(sock, true); - auto bio = BIO_new_socket(static_cast(sock), BIO_NOCLOSE); - BIO_set_nbio(bio, 1); - SSL_set_bio(ssl, bio, bio); + if (ssl) { + set_nonblocking(sock, true); + auto bio = BIO_new_socket(static_cast(sock), BIO_NOCLOSE); + BIO_set_nbio(bio, 1); + SSL_set_bio(ssl, bio, bio); - if (!setup(ssl) || SSL_connect_or_accept(ssl) != 1) { - SSL_shutdown(ssl); - { - std::lock_guard guard(ctx_mutex); - SSL_free(ssl); - } - set_nonblocking(sock, false); - return nullptr; - } - BIO_set_nbio(bio, 0); - set_nonblocking(sock, false); - } + if (!setup(ssl) || SSL_connect_or_accept(ssl) != 1) { + SSL_shutdown(ssl); + { + std::lock_guard guard(ctx_mutex); + SSL_free(ssl); + } + set_nonblocking(sock, false); + return nullptr; + } + BIO_set_nbio(bio, 0); + set_nonblocking(sock, false); + } - return ssl; -} + return ssl; + } -inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, - bool shutdown_gracefully) { - // sometimes we may want to skip this to try to avoid SIGPIPE if we know - // the remote has closed the network connection - // Note that it is not always possible to avoid SIGPIPE, this is merely a - // best-efforts. - if (shutdown_gracefully) { SSL_shutdown(ssl); } + inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, + bool shutdown_gracefully) { + // sometimes we may want to skip this to try to avoid SIGPIPE if we know + // the remote has closed the network connection + // Note that it is not always possible to avoid SIGPIPE, this is merely a + // best-efforts. + if (shutdown_gracefully) { SSL_shutdown(ssl); } - std::lock_guard guard(ctx_mutex); - SSL_free(ssl); -} + std::lock_guard guard(ctx_mutex); + SSL_free(ssl); + } -template -bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl, - U ssl_connect_or_accept, - time_t timeout_sec, - time_t timeout_usec) { - int res = 0; - while ((res = ssl_connect_or_accept(ssl)) != 1) { - auto err = SSL_get_error(ssl, res); - switch (err) { - case SSL_ERROR_WANT_READ: - if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; } - break; - case SSL_ERROR_WANT_WRITE: - if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; } - break; - default: break; - } - return false; - } - return true; -} + template + bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl, + U ssl_connect_or_accept, + time_t timeout_sec, + time_t timeout_usec) { + int res = 0; + while ((res = ssl_connect_or_accept(ssl)) != 1) { + auto err = SSL_get_error(ssl, res); + switch (err) { + case SSL_ERROR_WANT_READ: + if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; } + break; + case SSL_ERROR_WANT_WRITE: + if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; } + break; + default: break; + } + return false; + } + return true; + } -template -inline bool -process_server_socket_ssl(SSL *ssl, socket_t sock, size_t keep_alive_max_count, - time_t keep_alive_timeout_sec, - time_t read_timeout_sec, time_t read_timeout_usec, - time_t write_timeout_sec, time_t write_timeout_usec, - T callback) { - return process_server_socket_core( - sock, keep_alive_max_count, keep_alive_timeout_sec, - [&](bool close_connection, bool &connection_closed) { - SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm, close_connection, connection_closed); - }); -} + template + inline bool process_server_socket_ssl( + const std::atomic &svr_sock, SSL *ssl, socket_t sock, + size_t keep_alive_max_count, time_t keep_alive_timeout_sec, + time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, + time_t write_timeout_usec, T callback) { + return process_server_socket_core( + svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec, + [&](bool close_connection, bool &connection_closed) { + SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, + write_timeout_sec, write_timeout_usec); + return callback(strm, close_connection, connection_closed); + }); + } -template -inline bool -process_client_socket_ssl(SSL *ssl, socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { - SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm); -} + template + inline bool + process_client_socket_ssl(SSL *ssl, socket_t sock, time_t read_timeout_sec, + time_t read_timeout_usec, time_t write_timeout_sec, + time_t write_timeout_usec, T callback) { + SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, + write_timeout_sec, write_timeout_usec); + return callback(strm); + } #if OPENSSL_VERSION_NUMBER < 0x10100000L -static std::shared_ptr> openSSL_locks_; + static std::shared_ptr> openSSL_locks_; class SSLThreadLocks { public: @@ -6632,462 +7302,493 @@ private: #endif -class SSLInit { -public: - SSLInit() { + class SSLInit { + public: + SSLInit() { #if OPENSSL_VERSION_NUMBER < 0x1010001fL - SSL_load_error_strings(); + SSL_load_error_strings(); SSL_library_init(); #else - OPENSSL_init_ssl( - OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + OPENSSL_init_ssl( + OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); #endif - } + } - ~SSLInit() { + ~SSLInit() { #if OPENSSL_VERSION_NUMBER < 0x1010001fL - ERR_free_strings(); + ERR_free_strings(); #endif - } + } -private: + private: #if OPENSSL_VERSION_NUMBER < 0x10100000L - SSLThreadLocks thread_init_; + SSLThreadLocks thread_init_; #endif -}; + }; // SSL socket stream implementation -inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl, - time_t read_timeout_sec, - time_t read_timeout_usec, - time_t write_timeout_sec, - time_t write_timeout_usec) - : sock_(sock), ssl_(ssl), read_timeout_sec_(read_timeout_sec), - read_timeout_usec_(read_timeout_usec), - write_timeout_sec_(write_timeout_sec), - write_timeout_usec_(write_timeout_usec) { - SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY); -} + inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl, + time_t read_timeout_sec, + time_t read_timeout_usec, + time_t write_timeout_sec, + time_t write_timeout_usec) + : sock_(sock), ssl_(ssl), read_timeout_sec_(read_timeout_sec), + read_timeout_usec_(read_timeout_usec), + write_timeout_sec_(write_timeout_sec), + write_timeout_usec_(write_timeout_usec) { + SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY); + } -inline SSLSocketStream::~SSLSocketStream() {} + inline SSLSocketStream::~SSLSocketStream() {} -inline bool SSLSocketStream::is_readable() const { - return detail::select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; -} + inline bool SSLSocketStream::is_readable() const { + return detail::select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; + } -inline bool SSLSocketStream::is_writable() const { - return detail::select_write(sock_, write_timeout_sec_, write_timeout_usec_) > - 0; -} + inline bool SSLSocketStream::is_writable() const { + return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && + is_socket_alive(sock_); + } -inline ssize_t SSLSocketStream::read(char *ptr, size_t size) { - if (SSL_pending(ssl_) > 0) { - return SSL_read(ssl_, ptr, static_cast(size)); - } else if (is_readable()) { - auto ret = SSL_read(ssl_, ptr, static_cast(size)); - if (ret < 0) { - auto err = SSL_get_error(ssl_, ret); + inline ssize_t SSLSocketStream::read(char *ptr, size_t size) { + if (SSL_pending(ssl_) > 0) { + return SSL_read(ssl_, ptr, static_cast(size)); + } else if (is_readable()) { + auto ret = SSL_read(ssl_, ptr, static_cast(size)); + if (ret < 0) { + auto err = SSL_get_error(ssl_, ret); + int n = 1000; #ifdef _WIN32 - while (err == SSL_ERROR_WANT_READ || - err == SSL_ERROR_SYSCALL && WSAGetLastError() == WSAETIMEDOUT) { + while (--n >= 0 && (err == SSL_ERROR_WANT_READ || + (err == SSL_ERROR_SYSCALL && + WSAGetLastError() == WSAETIMEDOUT))) { #else - while (err == SSL_ERROR_WANT_READ) { + while (--n >= 0 && err == SSL_ERROR_WANT_READ) { #endif - if (SSL_pending(ssl_) > 0) { - return SSL_read(ssl_, ptr, static_cast(size)); - } else if (is_readable()) { - ret = SSL_read(ssl_, ptr, static_cast(size)); - if (ret >= 0) { return ret; } - err = SSL_get_error(ssl_, ret); - } else { - return -1; - } - } - } - return ret; - } - return -1; -} + if (SSL_pending(ssl_) > 0) { + return SSL_read(ssl_, ptr, static_cast(size)); + } else if (is_readable()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + ret = SSL_read(ssl_, ptr, static_cast(size)); + if (ret >= 0) { return ret; } + err = SSL_get_error(ssl_, ret); + } else { + return -1; + } + } + } + return ret; + } + return -1; + } -inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) { - if (is_writable()) { return SSL_write(ssl_, ptr, static_cast(size)); } - return -1; -} + inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) { + if (is_writable()) { + auto handle_size = static_cast( + std::min(size, (std::numeric_limits::max)())); -inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, - int &port) const { - detail::get_remote_ip_and_port(sock_, ip, port); -} + auto ret = SSL_write(ssl_, ptr, static_cast(handle_size)); + if (ret < 0) { + auto err = SSL_get_error(ssl_, ret); + int n = 1000; +#ifdef _WIN32 + while (--n >= 0 && (err == SSL_ERROR_WANT_WRITE || + (err == SSL_ERROR_SYSCALL && + WSAGetLastError() == WSAETIMEDOUT))) { +#else + while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) { +#endif + if (is_writable()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + ret = SSL_write(ssl_, ptr, static_cast(handle_size)); + if (ret >= 0) { return ret; } + err = SSL_get_error(ssl_, ret); + } else { + return -1; + } + } + } + return ret; + } + return -1; + } -inline socket_t SSLSocketStream::socket() const { return sock_; } + inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, + int &port) const { + detail::get_remote_ip_and_port(sock_, ip, port); + } -static SSLInit sslinit_; + inline socket_t SSLSocketStream::socket() const { return sock_; } -} // namespace detail + static SSLInit sslinit_; + + } // namespace detail // SSL HTTP server implementation -inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path, - const char *client_ca_cert_file_path, - const char *client_ca_cert_dir_path) { - ctx_ = SSL_CTX_new(TLS_method()); + inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path, + const char *client_ca_cert_file_path, + const char *client_ca_cert_dir_path, + const char *private_key_password) { + ctx_ = SSL_CTX_new(TLS_server_method()); - if (ctx_) { - SSL_CTX_set_options(ctx_, - SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); + if (ctx_) { + SSL_CTX_set_options(ctx_, + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - // auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - // SSL_CTX_set_tmp_ecdh(ctx_, ecdh); - // EC_KEY_free(ecdh); + SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION); - if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 || - SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) != - 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } else if (client_ca_cert_file_path || client_ca_cert_dir_path) { - // if (client_ca_cert_file_path) { - // auto list = SSL_load_client_CA_file(client_ca_cert_file_path); - // SSL_CTX_set_client_CA_list(ctx_, list); - // } + // add default password callback before opening encrypted private key + if (private_key_password != nullptr && (private_key_password[0] != '\0')) { + SSL_CTX_set_default_passwd_cb_userdata(ctx_, + (char *)private_key_password); + } - SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path, - client_ca_cert_dir_path); + if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 || + SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) != + 1) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } else if (client_ca_cert_file_path || client_ca_cert_dir_path) { + SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path, + client_ca_cert_dir_path); - SSL_CTX_set_verify( - ctx_, - SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT, // SSL_VERIFY_CLIENT_ONCE, - nullptr); - } - } -} + SSL_CTX_set_verify( + ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); + } + } + } -inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key, - X509_STORE *client_ca_cert_store) { - ctx_ = SSL_CTX_new(SSLv23_server_method()); + inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key, + X509_STORE *client_ca_cert_store) { + ctx_ = SSL_CTX_new(TLS_server_method()); - if (ctx_) { - SSL_CTX_set_options(ctx_, - SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); + if (ctx_) { + SSL_CTX_set_options(ctx_, + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - if (SSL_CTX_use_certificate(ctx_, cert) != 1 || - SSL_CTX_use_PrivateKey(ctx_, private_key) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } else if (client_ca_cert_store) { + SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION); - SSL_CTX_set_cert_store(ctx_, client_ca_cert_store); + if (SSL_CTX_use_certificate(ctx_, cert) != 1 || + SSL_CTX_use_PrivateKey(ctx_, private_key) != 1) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } else if (client_ca_cert_store) { + SSL_CTX_set_cert_store(ctx_, client_ca_cert_store); - SSL_CTX_set_verify( - ctx_, - SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT, // SSL_VERIFY_CLIENT_ONCE, - nullptr); - } - } -} + SSL_CTX_set_verify( + ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); + } + } + } -inline SSLServer::~SSLServer() { - if (ctx_) { SSL_CTX_free(ctx_); } -} + inline SSLServer::SSLServer( + const std::function &setup_ssl_ctx_callback) { + ctx_ = SSL_CTX_new(TLS_method()); + if (ctx_) { + if (!setup_ssl_ctx_callback(*ctx_)) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } + } + } -inline bool SSLServer::is_valid() const { return ctx_; } + inline SSLServer::~SSLServer() { + if (ctx_) { SSL_CTX_free(ctx_); } + } -inline bool SSLServer::process_and_close_socket(socket_t sock) { - auto ssl = detail::ssl_new( - sock, ctx_, ctx_mutex_, - [&](SSL *ssl) { - return detail::ssl_connect_or_accept_nonblocking( - sock, ssl, SSL_accept, read_timeout_sec_, read_timeout_usec_); - }, - [](SSL * /*ssl*/) { return true; }); + inline bool SSLServer::is_valid() const { return ctx_; } - bool ret = false; - if (ssl) { - ret = detail::process_server_socket_ssl( - ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, - [this, ssl](Stream &strm, bool close_connection, - bool &connection_closed) { - return process_request(strm, close_connection, connection_closed, - [&](Request &req) { req.ssl = ssl; }); - }); + inline SSL_CTX *SSLServer::ssl_context() const { return ctx_; } - // Shutdown gracefully if the result seemed successful, non-gracefully if - // the connection appeared to be closed. - const bool shutdown_gracefully = ret; - detail::ssl_delete(ctx_mutex_, ssl, shutdown_gracefully); - } + inline bool SSLServer::process_and_close_socket(socket_t sock) { + auto ssl = detail::ssl_new( + sock, ctx_, ctx_mutex_, + [&](SSL *ssl2) { + return detail::ssl_connect_or_accept_nonblocking( + sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_); + }, + [](SSL * /*ssl2*/) { return true; }); - detail::shutdown_socket(sock); - detail::close_socket(sock); - return ret; -} + bool ret = false; + if (ssl) { + ret = detail::process_server_socket_ssl( + svr_sock_, ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_, + read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, + write_timeout_usec_, + [this, ssl](Stream &strm, bool close_connection, + bool &connection_closed) { + return process_request(strm, close_connection, connection_closed, + [&](Request &req) { req.ssl = ssl; }); + }); + + // Shutdown gracefully if the result seemed successful, non-gracefully if + // the connection appeared to be closed. + const bool shutdown_gracefully = ret; + detail::ssl_delete(ctx_mutex_, ssl, shutdown_gracefully); + } + + detail::shutdown_socket(sock); + detail::close_socket(sock); + return ret; + } // SSL HTTP client implementation -inline SSLClient::SSLClient(const std::string &host) - : SSLClient(host, 443, std::string(), std::string()) {} + inline SSLClient::SSLClient(const std::string &host) + : SSLClient(host, 443, std::string(), std::string()) {} -inline SSLClient::SSLClient(const std::string &host, int port) - : SSLClient(host, port, std::string(), std::string()) {} + inline SSLClient::SSLClient(const std::string &host, int port) + : SSLClient(host, port, std::string(), std::string()) {} -inline SSLClient::SSLClient(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path) - : ClientImpl(host, port, client_cert_path, client_key_path) { - ctx_ = SSL_CTX_new(SSLv23_client_method()); + inline SSLClient::SSLClient(const std::string &host, int port, + const std::string &client_cert_path, + const std::string &client_key_path) + : ClientImpl(host, port, client_cert_path, client_key_path) { + ctx_ = SSL_CTX_new(TLS_client_method()); - detail::split(&host_[0], &host_[host_.size()], '.', - [&](const char *b, const char *e) { - host_components_.emplace_back(std::string(b, e)); - }); - if (!client_cert_path.empty() && !client_key_path.empty()) { - if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(), - SSL_FILETYPE_PEM) != 1 || - SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(), - SSL_FILETYPE_PEM) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} + detail::split(&host_[0], &host_[host_.size()], '.', + [&](const char *b, const char *e) { + host_components_.emplace_back(std::string(b, e)); + }); -inline SSLClient::SSLClient(const std::string &host, int port, - X509 *client_cert, EVP_PKEY *client_key) - : ClientImpl(host, port) { - ctx_ = SSL_CTX_new(SSLv23_client_method()); + if (!client_cert_path.empty() && !client_key_path.empty()) { + if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(), + SSL_FILETYPE_PEM) != 1 || + SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(), + SSL_FILETYPE_PEM) != 1) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } + } + } - detail::split(&host_[0], &host_[host_.size()], '.', - [&](const char *b, const char *e) { - host_components_.emplace_back(std::string(b, e)); - }); - if (client_cert != nullptr && client_key != nullptr) { - if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 || - SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} + inline SSLClient::SSLClient(const std::string &host, int port, + X509 *client_cert, EVP_PKEY *client_key) + : ClientImpl(host, port) { + ctx_ = SSL_CTX_new(TLS_client_method()); -inline SSLClient::~SSLClient() { - if (ctx_) { SSL_CTX_free(ctx_); } - // Make sure to shut down SSL since shutdown_ssl will resolve to the - // base function rather than the derived function once we get to the - // base class destructor, and won't free the SSL (causing a leak). - shutdown_ssl_impl(socket_, true); -} + detail::split(&host_[0], &host_[host_.size()], '.', + [&](const char *b, const char *e) { + host_components_.emplace_back(std::string(b, e)); + }); -inline bool SSLClient::is_valid() const { return ctx_; } + if (client_cert != nullptr && client_key != nullptr) { + if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 || + SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } + } + } -inline void SSLClient::set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path) { - if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; } - if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; } -} + inline SSLClient::~SSLClient() { + if (ctx_) { SSL_CTX_free(ctx_); } + // Make sure to shut down SSL since shutdown_ssl will resolve to the + // base function rather than the derived function once we get to the + // base class destructor, and won't free the SSL (causing a leak). + shutdown_ssl_impl(socket_, true); + } -inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (ca_cert_store) { - if (ctx_) { - if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) { - // Free memory allocated for old cert and use new store `ca_cert_store` - SSL_CTX_set_cert_store(ctx_, ca_cert_store); - } - } else { - X509_STORE_free(ca_cert_store); - } - } -} + inline bool SSLClient::is_valid() const { return ctx_; } -inline long SSLClient::get_openssl_verify_result() const { - return verify_result_; -} + inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) { + if (ca_cert_store) { + if (ctx_) { + if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) { + // Free memory allocated for old cert and use new store `ca_cert_store` + SSL_CTX_set_cert_store(ctx_, ca_cert_store); + } + } else { + X509_STORE_free(ca_cert_store); + } + } + } -inline SSL_CTX *SSLClient::ssl_context() const { return ctx_; } + inline long SSLClient::get_openssl_verify_result() const { + return verify_result_; + } -inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) { - return is_valid() && ClientImpl::create_and_connect_socket(socket, error); -} + inline SSL_CTX *SSLClient::ssl_context() const { return ctx_; } + + inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) { + return is_valid() && ClientImpl::create_and_connect_socket(socket, error); + } // Assumes that socket_mutex_ is locked and that there are no requests in flight -inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, - bool &success, Error &error) { - success = true; - Response res2; - if (!detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { - Request req2; - req2.method = "CONNECT"; - req2.path = host_and_port_; - return process_request(strm, req2, res2, false, error); - })) { - // Thread-safe to close everything because we are assuming there are no - // requests in flight - shutdown_ssl(socket, true); - shutdown_socket(socket); - close_socket(socket); - success = false; - return false; - } + inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, + bool &success, Error &error) { + success = true; + Response res2; + if (!detail::process_client_socket( + socket.sock, read_timeout_sec_, read_timeout_usec_, + write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { + Request req2; + req2.method = "CONNECT"; + req2.path = host_and_port_; + return process_request(strm, req2, res2, false, error); + })) { + // Thread-safe to close everything because we are assuming there are no + // requests in flight + shutdown_ssl(socket, true); + shutdown_socket(socket); + close_socket(socket); + success = false; + return false; + } - if (res2.status == 407) { - if (!proxy_digest_auth_username_.empty() && - !proxy_digest_auth_password_.empty()) { - std::map auth; - if (detail::parse_www_authenticate(res2, auth, true)) { - Response res3; - if (!detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { - Request req3; - req3.method = "CONNECT"; - req3.path = host_and_port_; - req3.headers.insert(detail::make_digest_authentication_header( - req3, auth, 1, detail::random_string(10), - proxy_digest_auth_username_, proxy_digest_auth_password_, - true)); - return process_request(strm, req3, res3, false, error); - })) { - // Thread-safe to close everything because we are assuming there are - // no requests in flight - shutdown_ssl(socket, true); - shutdown_socket(socket); - close_socket(socket); - success = false; - return false; - } - } - } else { - res = res2; - return false; - } - } + if (res2.status == 407) { + if (!proxy_digest_auth_username_.empty() && + !proxy_digest_auth_password_.empty()) { + std::map auth; + if (detail::parse_www_authenticate(res2, auth, true)) { + Response res3; + if (!detail::process_client_socket( + socket.sock, read_timeout_sec_, read_timeout_usec_, + write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { + Request req3; + req3.method = "CONNECT"; + req3.path = host_and_port_; + req3.headers.insert(detail::make_digest_authentication_header( + req3, auth, 1, detail::random_string(10), + proxy_digest_auth_username_, proxy_digest_auth_password_, + true)); + return process_request(strm, req3, res3, false, error); + })) { + // Thread-safe to close everything because we are assuming there are + // no requests in flight + shutdown_ssl(socket, true); + shutdown_socket(socket); + close_socket(socket); + success = false; + return false; + } + } + } else { + res = res2; + return false; + } + } - return true; -} + return true; + } -inline bool SSLClient::load_certs() { - bool ret = true; + inline bool SSLClient::load_certs() { + bool ret = true; - std::call_once(initialize_cert_, [&]() { - std::lock_guard guard(ctx_mutex_); - if (!ca_cert_file_path_.empty()) { - if (!SSL_CTX_load_verify_locations(ctx_, ca_cert_file_path_.c_str(), - nullptr)) { - ret = false; - } - } else if (!ca_cert_dir_path_.empty()) { - if (!SSL_CTX_load_verify_locations(ctx_, nullptr, - ca_cert_dir_path_.c_str())) { - ret = false; - } - } else { + std::call_once(initialize_cert_, [&]() { + std::lock_guard guard(ctx_mutex_); + if (!ca_cert_file_path_.empty()) { + if (!SSL_CTX_load_verify_locations(ctx_, ca_cert_file_path_.c_str(), + nullptr)) { + ret = false; + } + } else if (!ca_cert_dir_path_.empty()) { + if (!SSL_CTX_load_verify_locations(ctx_, nullptr, + ca_cert_dir_path_.c_str())) { + ret = false; + } + } else { #ifdef _WIN32 - detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_)); + detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_)); #else - SSL_CTX_set_default_verify_paths(ctx_); + SSL_CTX_set_default_verify_paths(ctx_); #endif - } - }); + } + }); - return ret; -} + return ret; + } -inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) { - auto ssl = detail::ssl_new( - socket.sock, ctx_, ctx_mutex_, - [&](SSL *ssl) { - if (server_certificate_verification_) { - if (!load_certs()) { - error = Error::SSLLoadingCerts; - return false; - } - SSL_set_verify(ssl, SSL_VERIFY_NONE, nullptr); - } + inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) { + auto ssl = detail::ssl_new( + socket.sock, ctx_, ctx_mutex_, + [&](SSL *ssl2) { + if (server_certificate_verification_) { + if (!load_certs()) { + error = Error::SSLLoadingCerts; + return false; + } + SSL_set_verify(ssl2, SSL_VERIFY_NONE, nullptr); + } - if (!detail::ssl_connect_or_accept_nonblocking( - socket.sock, ssl, SSL_connect, connection_timeout_sec_, - connection_timeout_usec_)) { - error = Error::SSLConnection; - return false; - } + if (!detail::ssl_connect_or_accept_nonblocking( + socket.sock, ssl2, SSL_connect, connection_timeout_sec_, + connection_timeout_usec_)) { + error = Error::SSLConnection; + return false; + } - if (server_certificate_verification_) { - verify_result_ = SSL_get_verify_result(ssl); + if (server_certificate_verification_) { + verify_result_ = SSL_get_verify_result(ssl2); - if (verify_result_ != X509_V_OK) { - error = Error::SSLServerVerification; - return false; - } + if (verify_result_ != X509_V_OK) { + error = Error::SSLServerVerification; + return false; + } - auto server_cert = SSL_get_peer_certificate(ssl); + auto server_cert = SSL_get_peer_certificate(ssl2); - if (server_cert == nullptr) { - error = Error::SSLServerVerification; - return false; - } + if (server_cert == nullptr) { + error = Error::SSLServerVerification; + return false; + } - if (!verify_host(server_cert)) { - X509_free(server_cert); - error = Error::SSLServerVerification; - return false; - } - X509_free(server_cert); - } + if (!verify_host(server_cert)) { + X509_free(server_cert); + error = Error::SSLServerVerification; + return false; + } + X509_free(server_cert); + } - return true; - }, - [&](SSL *ssl) { - SSL_set_tlsext_host_name(ssl, host_.c_str()); - return true; - }); + return true; + }, + [&](SSL *ssl2) { + SSL_set_tlsext_host_name(ssl2, host_.c_str()); + return true; + }); - if (ssl) { - socket.ssl = ssl; - return true; - } + if (ssl) { + socket.ssl = ssl; + return true; + } - shutdown_socket(socket); - close_socket(socket); - return false; -} + shutdown_socket(socket); + close_socket(socket); + return false; + } -inline void SSLClient::shutdown_ssl(Socket &socket, bool shutdown_gracefully) { - shutdown_ssl_impl(socket, shutdown_gracefully); -} + inline void SSLClient::shutdown_ssl(Socket &socket, bool shutdown_gracefully) { + shutdown_ssl_impl(socket, shutdown_gracefully); + } -inline void SSLClient::shutdown_ssl_impl(Socket &socket, - bool shutdown_gracefully) { - if (socket.sock == INVALID_SOCKET) { - assert(socket.ssl == nullptr); - return; - } - if (socket.ssl) { - detail::ssl_delete(ctx_mutex_, socket.ssl, shutdown_gracefully); - socket.ssl = nullptr; - } - assert(socket.ssl == nullptr); -} + inline void SSLClient::shutdown_ssl_impl(Socket &socket, + bool shutdown_gracefully) { + if (socket.sock == INVALID_SOCKET) { + assert(socket.ssl == nullptr); + return; + } + if (socket.ssl) { + detail::ssl_delete(ctx_mutex_, socket.ssl, shutdown_gracefully); + socket.ssl = nullptr; + } + assert(socket.ssl == nullptr); + } -inline bool -SSLClient::process_socket(const Socket &socket, - std::function callback) { - assert(socket.ssl); - return detail::process_client_socket_ssl( - socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, std::move(callback)); -} + inline bool + SSLClient::process_socket(const Socket &socket, + std::function callback) { + assert(socket.ssl); + return detail::process_client_socket_ssl( + socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_, + write_timeout_sec_, write_timeout_usec_, std::move(callback)); + } -inline bool SSLClient::is_ssl() const { return true; } + inline bool SSLClient::is_ssl() const { return true; } -inline bool SSLClient::verify_host(X509 *server_cert) const { - /* Quote from RFC2818 section 3.1 "Server Identity" + inline bool SSLClient::verify_host(X509 *server_cert) const { + /* Quote from RFC2818 section 3.1 "Server Identity" If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name @@ -7108,149 +7809,153 @@ inline bool SSLClient::verify_host(X509 *server_cert) const { in the certificate and must exactly match the IP in the URI. */ - return verify_host_with_subject_alt_name(server_cert) || - verify_host_with_common_name(server_cert); -} + return verify_host_with_subject_alt_name(server_cert) || + verify_host_with_common_name(server_cert); + } -inline bool -SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { - auto ret = false; + inline bool + SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { + auto ret = false; - auto type = GEN_DNS; + auto type = GEN_DNS; - struct in6_addr addr6; - struct in_addr addr; - size_t addr_len = 0; + struct in6_addr addr6; + struct in_addr addr; + size_t addr_len = 0; #ifndef __MINGW32__ - if (inet_pton(AF_INET6, host_.c_str(), &addr6)) { - type = GEN_IPADD; - addr_len = sizeof(struct in6_addr); - } else if (inet_pton(AF_INET, host_.c_str(), &addr)) { - type = GEN_IPADD; - addr_len = sizeof(struct in_addr); - } + if (inet_pton(AF_INET6, host_.c_str(), &addr6)) { + type = GEN_IPADD; + addr_len = sizeof(struct in6_addr); + } else if (inet_pton(AF_INET, host_.c_str(), &addr)) { + type = GEN_IPADD; + addr_len = sizeof(struct in_addr); + } #endif - auto alt_names = static_cast( - X509_get_ext_d2i(server_cert, NID_subject_alt_name, nullptr, nullptr)); + auto alt_names = static_cast( + X509_get_ext_d2i(server_cert, NID_subject_alt_name, nullptr, nullptr)); - if (alt_names) { - auto dsn_matched = false; - auto ip_mached = false; + if (alt_names) { + auto dsn_matched = false; + auto ip_mached = false; - auto count = sk_GENERAL_NAME_num(alt_names); + auto count = sk_GENERAL_NAME_num(alt_names); - for (decltype(count) i = 0; i < count && !dsn_matched; i++) { - auto val = sk_GENERAL_NAME_value(alt_names, i); - if (val->type == type) { - auto name = (const char *)ASN1_STRING_get0_data(val->d.ia5); - auto name_len = (size_t)ASN1_STRING_length(val->d.ia5); + for (decltype(count) i = 0; i < count && !dsn_matched; i++) { + auto val = sk_GENERAL_NAME_value(alt_names, i); + if (val->type == type) { + auto name = (const char *)ASN1_STRING_get0_data(val->d.ia5); + auto name_len = (size_t)ASN1_STRING_length(val->d.ia5); - switch (type) { - case GEN_DNS: dsn_matched = check_host_name(name, name_len); break; + switch (type) { + case GEN_DNS: dsn_matched = check_host_name(name, name_len); break; - case GEN_IPADD: - if (!memcmp(&addr6, name, addr_len) || - !memcmp(&addr, name, addr_len)) { - ip_mached = true; - } - break; - } - } - } + case GEN_IPADD: + if (!memcmp(&addr6, name, addr_len) || + !memcmp(&addr, name, addr_len)) { + ip_mached = true; + } + break; + } + } + } - if (dsn_matched || ip_mached) { ret = true; } - } + if (dsn_matched || ip_mached) { ret = true; } + } - GENERAL_NAMES_free((STACK_OF(GENERAL_NAME) *)alt_names); - return ret; -} + GENERAL_NAMES_free((STACK_OF(GENERAL_NAME) *)alt_names); + return ret; + } -inline bool SSLClient::verify_host_with_common_name(X509 *server_cert) const { - const auto subject_name = X509_get_subject_name(server_cert); + inline bool SSLClient::verify_host_with_common_name(X509 *server_cert) const { + const auto subject_name = X509_get_subject_name(server_cert); - if (subject_name != nullptr) { - char name[BUFSIZ]; - auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName, - name, sizeof(name)); + if (subject_name != nullptr) { + char name[BUFSIZ]; + auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName, + name, sizeof(name)); - if (name_len != -1) { - return check_host_name(name, static_cast(name_len)); - } - } + if (name_len != -1) { + return check_host_name(name, static_cast(name_len)); + } + } - return false; -} + return false; + } -inline bool SSLClient::check_host_name(const char *pattern, - size_t pattern_len) const { - if (host_.size() == pattern_len && host_ == pattern) { return true; } + inline bool SSLClient::check_host_name(const char *pattern, + size_t pattern_len) const { + if (host_.size() == pattern_len && host_ == pattern) { return true; } - // Wildcard match - // https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/376484 - std::vector pattern_components; - detail::split(&pattern[0], &pattern[pattern_len], '.', - [&](const char *b, const char *e) { - pattern_components.emplace_back(std::string(b, e)); - }); + // Wildcard match + // https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/376484 + std::vector pattern_components; + detail::split(&pattern[0], &pattern[pattern_len], '.', + [&](const char *b, const char *e) { + pattern_components.emplace_back(std::string(b, e)); + }); - if (host_components_.size() != pattern_components.size()) { return false; } + if (host_components_.size() != pattern_components.size()) { return false; } - auto itr = pattern_components.begin(); - for (const auto &h : host_components_) { - auto &p = *itr; - if (p != h && p != "*") { - auto partial_match = (p.size() > 0 && p[p.size() - 1] == '*' && - !p.compare(0, p.size() - 1, h)); - if (!partial_match) { return false; } - } - ++itr; - } + auto itr = pattern_components.begin(); + for (const auto &h : host_components_) { + auto &p = *itr; + if (p != h && p != "*") { + auto partial_match = (p.size() > 0 && p[p.size() - 1] == '*' && + !p.compare(0, p.size() - 1, h)); + if (!partial_match) { return false; } + } + ++itr; + } - return true; -} + return true; + } #endif // Universal client implementation - inline Client::Client(const char *scheme_host_port) + inline Client::Client(const std::string &scheme_host_port) : Client(scheme_host_port, std::string(), std::string()) {} - inline Client::Client(const char *scheme_host_port, + inline Client::Client(const std::string &scheme_host_port, const std::string &client_cert_path, const std::string &client_key_path) { - const static std::regex re(R"(^(?:([a-z]+)://)?([^:/?#]+)(?::(\d+))?)"); + const static std::regex re( + R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)"); - std::cmatch m; + std::smatch m; if (std::regex_match(scheme_host_port, m, re)) { auto scheme = m[1].str(); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT if (!scheme.empty() && (scheme != "http" && scheme != "https")) { #else - if (!scheme.empty() && scheme != "http") { + if (!scheme.empty() && scheme != "http") { #endif +#ifndef CPPHTTPLIB_NO_EXCEPTIONS std::string msg = "'" + scheme + "' scheme is not supported."; throw std::invalid_argument(msg); +#endif return; } auto is_ssl = scheme == "https"; auto host = m[2].str(); + if (host.empty()) { host = m[3].str(); } - auto port_str = m[3].str(); + auto port_str = m[4].str(); auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80); if (is_ssl) { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - cli_ = detail::make_unique(host.c_str(), port, - client_cert_path, client_key_path); - is_ssl_ = is_ssl; + cli_ = detail::make_unique(host, port, client_cert_path, + client_key_path); + is_ssl_ = is_ssl; #endif } else { - cli_ = detail::make_unique(host.c_str(), port, - client_cert_path, client_key_path); + cli_ = detail::make_unique(host, port, client_cert_path, + client_key_path); } } else { cli_ = detail::make_unique(scheme_host_port, 80, @@ -7273,65 +7978,68 @@ inline bool SSLClient::check_host_name(const char *pattern, return cli_ != nullptr && cli_->is_valid(); } - inline Result Client::Get(const char *path) { return cli_->Get(path); } - inline Result Client::Get(const char *path, const Headers &headers) { + inline Result Client::Get(const std::string &path) { return cli_->Get(path); } + inline Result Client::Get(const std::string &path, const Headers &headers) { return cli_->Get(path, headers); } - inline Result Client::Get(const char *path, Progress progress) { + inline Result Client::Get(const std::string &path, Progress progress) { return cli_->Get(path, std::move(progress)); } - inline Result Client::Get(const char *path, const Headers &headers, + inline Result Client::Get(const std::string &path, const Headers &headers, Progress progress) { return cli_->Get(path, headers, std::move(progress)); } - inline Result Client::Get(const char *path, ContentReceiver content_receiver) { + inline Result Client::Get(const std::string &path, + ContentReceiver content_receiver) { return cli_->Get(path, std::move(content_receiver)); } - inline Result Client::Get(const char *path, const Headers &headers, + inline Result Client::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver) { return cli_->Get(path, headers, std::move(content_receiver)); } - inline Result Client::Get(const char *path, ContentReceiver content_receiver, - Progress progress) { + inline Result Client::Get(const std::string &path, + ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, std::move(content_receiver), std::move(progress)); } - inline Result Client::Get(const char *path, const Headers &headers, + inline Result Client::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, headers, std::move(content_receiver), std::move(progress)); } - inline Result Client::Get(const char *path, ResponseHandler response_handler, + inline Result Client::Get(const std::string &path, + ResponseHandler response_handler, ContentReceiver content_receiver) { return cli_->Get(path, std::move(response_handler), std::move(content_receiver)); } - inline Result Client::Get(const char *path, const Headers &headers, + inline Result Client::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver) { return cli_->Get(path, headers, std::move(response_handler), std::move(content_receiver)); } - inline Result Client::Get(const char *path, ResponseHandler response_handler, + inline Result Client::Get(const std::string &path, + ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, std::move(response_handler), std::move(content_receiver), std::move(progress)); } - inline Result Client::Get(const char *path, const Headers &headers, + inline Result Client::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, headers, std::move(response_handler), std::move(content_receiver), std::move(progress)); } - inline Result Client::Get(const char *path, const Params ¶ms, + inline Result Client::Get(const std::string &path, const Params ¶ms, const Headers &headers, Progress progress) { return cli_->Get(path, params, headers, progress); } - inline Result Client::Get(const char *path, const Params ¶ms, + inline Result Client::Get(const std::string &path, const Params ¶ms, const Headers &headers, ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, params, headers, content_receiver, progress); } - inline Result Client::Get(const char *path, const Params ¶ms, + inline Result Client::Get(const std::string &path, const Params ¶ms, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { @@ -7339,185 +8047,211 @@ inline bool SSLClient::check_host_name(const char *pattern, progress); } - inline Result Client::Head(const char *path) { return cli_->Head(path); } - inline Result Client::Head(const char *path, const Headers &headers) { + inline Result Client::Head(const std::string &path) { return cli_->Head(path); } + inline Result Client::Head(const std::string &path, const Headers &headers) { return cli_->Head(path, headers); } - inline Result Client::Post(const char *path) { return cli_->Post(path); } - inline Result Client::Post(const char *path, const char *body, - size_t content_length, const char *content_type) { + inline Result Client::Post(const std::string &path) { return cli_->Post(path); } + inline Result Client::Post(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Post(path, body, content_length, content_type); } - inline Result Client::Post(const char *path, const Headers &headers, + inline Result Client::Post(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, headers, body, content_length, content_type); } - inline Result Client::Post(const char *path, const std::string &body, - const char *content_type) { + inline Result Client::Post(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Post(path, body, content_type); } - inline Result Client::Post(const char *path, const Headers &headers, - const std::string &body, const char *content_type) { + inline Result Client::Post(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { return cli_->Post(path, headers, body, content_type); } - inline Result Client::Post(const char *path, size_t content_length, + inline Result Client::Post(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, content_length, std::move(content_provider), content_type); } - inline Result Client::Post(const char *path, + inline Result Client::Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, std::move(content_provider), content_type); } - inline Result Client::Post(const char *path, const Headers &headers, + inline Result Client::Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, headers, content_length, std::move(content_provider), content_type); } - inline Result Client::Post(const char *path, const Headers &headers, + inline Result Client::Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, headers, std::move(content_provider), content_type); } - inline Result Client::Post(const char *path, const Params ¶ms) { + inline Result Client::Post(const std::string &path, const Params ¶ms) { return cli_->Post(path, params); } - inline Result Client::Post(const char *path, const Headers &headers, + inline Result Client::Post(const std::string &path, const Headers &headers, const Params ¶ms) { return cli_->Post(path, headers, params); } - inline Result Client::Post(const char *path, + inline Result Client::Post(const std::string &path, const MultipartFormDataItems &items) { return cli_->Post(path, items); } - inline Result Client::Post(const char *path, const Headers &headers, + inline Result Client::Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items) { return cli_->Post(path, headers, items); } - inline Result Client::Post(const char *path, const Headers &headers, + inline Result Client::Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items, const std::string &boundary) { return cli_->Post(path, headers, items, boundary); } - inline Result Client::Put(const char *path) { return cli_->Put(path); } - inline Result Client::Put(const char *path, const char *body, - size_t content_length, const char *content_type) { + inline Result Client::Put(const std::string &path) { return cli_->Put(path); } + inline Result Client::Put(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Put(path, body, content_length, content_type); } - inline Result Client::Put(const char *path, const Headers &headers, + inline Result Client::Put(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, headers, body, content_length, content_type); } - inline Result Client::Put(const char *path, const std::string &body, - const char *content_type) { + inline Result Client::Put(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Put(path, body, content_type); } - inline Result Client::Put(const char *path, const Headers &headers, - const std::string &body, const char *content_type) { + inline Result Client::Put(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { return cli_->Put(path, headers, body, content_type); } - inline Result Client::Put(const char *path, size_t content_length, + inline Result Client::Put(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, content_length, std::move(content_provider), content_type); } - inline Result Client::Put(const char *path, + inline Result Client::Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, std::move(content_provider), content_type); } - inline Result Client::Put(const char *path, const Headers &headers, + inline Result Client::Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, headers, content_length, std::move(content_provider), content_type); } - inline Result Client::Put(const char *path, const Headers &headers, + inline Result Client::Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, headers, std::move(content_provider), content_type); } - inline Result Client::Put(const char *path, const Params ¶ms) { + inline Result Client::Put(const std::string &path, const Params ¶ms) { return cli_->Put(path, params); } - inline Result Client::Put(const char *path, const Headers &headers, + inline Result Client::Put(const std::string &path, const Headers &headers, const Params ¶ms) { return cli_->Put(path, headers, params); } - inline Result Client::Patch(const char *path) { return cli_->Patch(path); } - inline Result Client::Patch(const char *path, const char *body, - size_t content_length, const char *content_type) { + inline Result Client::Put(const std::string &path, + const MultipartFormDataItems &items) { + return cli_->Put(path, items); + } + inline Result Client::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items) { + return cli_->Put(path, headers, items); + } + inline Result Client::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const std::string &boundary) { + return cli_->Put(path, headers, items, boundary); + } + inline Result Client::Patch(const std::string &path) { + return cli_->Patch(path); + } + inline Result Client::Patch(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Patch(path, body, content_length, content_type); } - inline Result Client::Patch(const char *path, const Headers &headers, + inline Result Client::Patch(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, headers, body, content_length, content_type); } - inline Result Client::Patch(const char *path, const std::string &body, - const char *content_type) { + inline Result Client::Patch(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Patch(path, body, content_type); } - inline Result Client::Patch(const char *path, const Headers &headers, - const std::string &body, const char *content_type) { + inline Result Client::Patch(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { return cli_->Patch(path, headers, body, content_type); } - inline Result Client::Patch(const char *path, size_t content_length, + inline Result Client::Patch(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, content_length, std::move(content_provider), content_type); } - inline Result Client::Patch(const char *path, + inline Result Client::Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, std::move(content_provider), content_type); } - inline Result Client::Patch(const char *path, const Headers &headers, + inline Result Client::Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, headers, content_length, std::move(content_provider), content_type); } - inline Result Client::Patch(const char *path, const Headers &headers, + inline Result Client::Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, headers, std::move(content_provider), content_type); } - inline Result Client::Delete(const char *path) { return cli_->Delete(path); } - inline Result Client::Delete(const char *path, const Headers &headers) { + inline Result Client::Delete(const std::string &path) { + return cli_->Delete(path); + } + inline Result Client::Delete(const std::string &path, const Headers &headers) { return cli_->Delete(path, headers); } - inline Result Client::Delete(const char *path, const char *body, - size_t content_length, const char *content_type) { + inline Result Client::Delete(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Delete(path, body, content_length, content_type); } - inline Result Client::Delete(const char *path, const Headers &headers, + inline Result Client::Delete(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Delete(path, headers, body, content_length, content_type); } - inline Result Client::Delete(const char *path, const std::string &body, - const char *content_type) { + inline Result Client::Delete(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Delete(path, body, content_type); } - inline Result Client::Delete(const char *path, const Headers &headers, + inline Result Client::Delete(const std::string &path, const Headers &headers, const std::string &body, - const char *content_type) { + const std::string &content_type) { return cli_->Delete(path, headers, body, content_type); } - inline Result Client::Options(const char *path) { return cli_->Options(path); } - inline Result Client::Options(const char *path, const Headers &headers) { + inline Result Client::Options(const std::string &path) { + return cli_->Options(path); + } + inline Result Client::Options(const std::string &path, const Headers &headers) { return cli_->Options(path, headers); } @@ -7529,8 +8263,15 @@ inline bool SSLClient::check_host_name(const char *pattern, inline size_t Client::is_socket_open() const { return cli_->is_socket_open(); } + inline socket_t Client::socket() const { return cli_->socket(); } + inline void Client::stop() { cli_->stop(); } + inline void + Client::set_hostname_addr_map(std::map addr_map) { + cli_->set_hostname_addr_map(std::move(addr_map)); + } + inline void Client::set_default_headers(Headers headers) { cli_->set_default_headers(std::move(headers)); } @@ -7549,43 +8290,26 @@ inline bool SSLClient::check_host_name(const char *pattern, cli_->set_connection_timeout(sec, usec); } - template - inline void Client::set_connection_timeout( - const std::chrono::duration &duration) { - cli_->set_connection_timeout(duration); - } - inline void Client::set_read_timeout(time_t sec, time_t usec) { cli_->set_read_timeout(sec, usec); } - template - inline void - Client::set_read_timeout(const std::chrono::duration &duration) { - cli_->set_read_timeout(duration); - } - inline void Client::set_write_timeout(time_t sec, time_t usec) { cli_->set_write_timeout(sec, usec); } - template - inline void - Client::set_write_timeout(const std::chrono::duration &duration) { - cli_->set_write_timeout(duration); - } - - inline void Client::set_basic_auth(const char *username, const char *password) { + inline void Client::set_basic_auth(const std::string &username, + const std::string &password) { cli_->set_basic_auth(username, password); } - inline void Client::set_bearer_token_auth(const char *token) { + inline void Client::set_bearer_token_auth(const std::string &token) { cli_->set_bearer_token_auth(token); } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - inline void Client::set_digest_auth(const char *username, - const char *password) { - cli_->set_digest_auth(username, password); -} + inline void Client::set_digest_auth(const std::string &username, + const std::string &password) { + cli_->set_digest_auth(username, password); + } #endif inline void Client::set_keep_alive(bool on) { cli_->set_keep_alive(on); } @@ -7599,61 +8323,60 @@ inline bool SSLClient::check_host_name(const char *pattern, inline void Client::set_decompress(bool on) { cli_->set_decompress(on); } - inline void Client::set_interface(const char *intf) { + inline void Client::set_interface(const std::string &intf) { cli_->set_interface(intf); } - inline void Client::set_proxy(const char *host, int port) { + inline void Client::set_proxy(const std::string &host, int port) { cli_->set_proxy(host, port); } - inline void Client::set_proxy_basic_auth(const char *username, - const char *password) { + inline void Client::set_proxy_basic_auth(const std::string &username, + const std::string &password) { cli_->set_proxy_basic_auth(username, password); } - inline void Client::set_proxy_bearer_token_auth(const char *token) { + inline void Client::set_proxy_bearer_token_auth(const std::string &token) { cli_->set_proxy_bearer_token_auth(token); } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - inline void Client::set_proxy_digest_auth(const char *username, - const char *password) { - cli_->set_proxy_digest_auth(username, password); -} + inline void Client::set_proxy_digest_auth(const std::string &username, + const std::string &password) { + cli_->set_proxy_digest_auth(username, password); + } #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT inline void Client::enable_server_certificate_verification(bool enabled) { - cli_->enable_server_certificate_verification(enabled); -} + cli_->enable_server_certificate_verification(enabled); + } #endif inline void Client::set_logger(Logger logger) { cli_->set_logger(logger); } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - inline void Client::set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path) { - if (is_ssl_) { - static_cast(*cli_).set_ca_cert_path(ca_cert_file_path, - ca_cert_dir_path); - } -} + inline void Client::set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path) { + cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path); + } -inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (is_ssl_) { - static_cast(*cli_).set_ca_cert_store(ca_cert_store); - } -} + inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) { + if (is_ssl_) { + static_cast(*cli_).set_ca_cert_store(ca_cert_store); + } else { + cli_->set_ca_cert_store(ca_cert_store); + } + } -inline long Client::get_openssl_verify_result() const { - if (is_ssl_) { - return static_cast(*cli_).get_openssl_verify_result(); - } - return -1; // NOTE: -1 doesn't match any of X509_V_ERR_??? -} + inline long Client::get_openssl_verify_result() const { + if (is_ssl_) { + return static_cast(*cli_).get_openssl_verify_result(); + } + return -1; // NOTE: -1 doesn't match any of X509_V_ERR_??? + } -inline SSL_CTX *Client::ssl_context() const { - if (is_ssl_) { return static_cast(*cli_).ssl_context(); } - return nullptr; -} + inline SSL_CTX *Client::ssl_context() const { + if (is_ssl_) { return static_cast(*cli_).ssl_context(); } + return nullptr; + } #endif // ---------------------------------------------------------------------------- diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index fbc794351..eb1926304 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -25,7 +25,7 @@ //#include "races.h" //#include "rulesys.h" //#include "shareddb.h" -#include "string_util.h" +#include "strings.h" #include "../common/light_source.h" @@ -245,7 +245,7 @@ int16 EQ::InventoryProfile::PutItem(int16 slot_id, const ItemInstance& inst) if (temp_slot >= m_lookup->InventoryTypeSize.Bank) return EQ::invslot::SLOT_INVALID; } - + // Clean up item already in slot (if exists) DeleteItem(slot_id); @@ -617,7 +617,7 @@ int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id) quantity += item->CountAugmentByID(item_id); } } - + return quantity; } @@ -648,7 +648,7 @@ int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id) quantity += item->IsStackable() ? item->GetCharges() : 1; } } - + return quantity; } @@ -993,7 +993,7 @@ int16 EQ::InventoryProfile::CalcSlotId(int16 slot_id) { //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) - + if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) { parent_slot_id = invslot::GENERAL_BEGIN + (slot_id - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT; } @@ -1231,7 +1231,7 @@ uint8 EQ::InventoryProfile::FindBrightestLightType() for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { if ((iter->first < invslot::EQUIPMENT_BEGIN || iter->first > invslot::EQUIPMENT_END)) continue; - + if (iter->first == invslot::slotAmmo) continue; @@ -1369,7 +1369,7 @@ EQ::ItemInstance* EQ::InventoryProfile::_GetItem(const std::map= m_lookup->InventoryTypeSize.Bank) return nullptr; } - + auto it = bucket.find(slot_id); if (it != bucket.end()) { return it->second; @@ -1441,7 +1441,7 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst) result = slot_id; } } - + if (result == INVALID_INDEX) { LogError("InventoryProfile::_PutItem: Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot); InventoryProfile::MarkDirty(inst); // Slot not found, clean up @@ -1478,7 +1478,7 @@ int16 EQ::InventoryProfile::_HasItem(std::map& bucket, uin if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) return invslot::SLOT_AUGMENT_GENERIC_RETURN; } - + if (!inst->IsClassBag()) { continue; } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { @@ -1509,7 +1509,7 @@ int16 EQ::InventoryProfile::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint // is sufficient. However, in cases where referential criteria is considered, this can lead // to unintended results. Funtionality should be observed when referencing the return value // of this query - + uint32 quantity_found = 0; for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { @@ -1715,6 +1715,20 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 lo // We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo) break; } - + return EQ::invslot::SLOT_INVALID; } + +std::vector EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id) +{ + std::vector augments; + const auto* item = GetItem(slot_id); + + if (item) { + for (uint8 i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) { + augments.push_back(item->GetAugment(i) ? item->GetAugmentItemID(i) : 0); + } + } + + return augments; +} diff --git a/common/inventory_profile.h b/common/inventory_profile.h index c35f5679d..43f4a88f4 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -26,8 +26,11 @@ #include "item_instance.h" +#include "classes.h" +#include "races.h" #include +#include //FatherNitwit: location bits for searching specific @@ -129,7 +132,7 @@ namespace EQ // Swap items in inventory enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel }; - bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0); + bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = RACE_DOUG_0, uint8 class_id = NO_CLASS, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0); // Remove item from inventory bool DeleteItem(int16 slot_id, int16 quantity = 0); @@ -152,6 +155,9 @@ namespace EQ // Check how many of a specific augment the player has equipped by Item ID int CountAugmentEquippedByID(uint32 item_id); + // Get a list of augments from a specific slot ID + std::vector GetAugmentIDsBySlotID(int16 slot_id); + // Check whether there is space for the specified number of the specified item. bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity); @@ -202,7 +208,7 @@ namespace EQ void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); std::string GetCustomItemData(int16 slot_id, std::string identifier); - static int GetItemStatValue(uint32 item_id, const char* identifier); + static const int GetItemStatValue(uint32 item_id, std::string identifier); protected: /////////////////////////////// // Protected Methods diff --git a/common/inventory_slot.cpp b/common/inventory_slot.cpp index b86b5ca91..a63512ae2 100644 --- a/common/inventory_slot.cpp +++ b/common/inventory_slot.cpp @@ -19,7 +19,7 @@ #include "inventory_slot.h" #include "textures.h" -#include "string_util.h" +#include "strings.h" int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index) @@ -86,7 +86,7 @@ bool EQ::InventorySlot::IsValidSlot() const { if (_typeless) return false; - + int16 slot_count = invtype::GetInvTypeSize(_type_index); if (!slot_count || _slot_index < invslot::SLOT_BEGIN || _slot_index >= slot_count) return false; @@ -136,7 +136,7 @@ bool EQ::InventorySlot::IsWeaponIndex(int16 slot_index) { if (slot_index == invslot::slotPrimary || slot_index == invslot::slotSecondary || slot_index == invslot::slotRange) return true; - + return false; } @@ -364,7 +364,7 @@ bool EQ::InventorySlot::operator<(const InventorySlot& rhs) const { if (Typeless() || rhs.Typeless()) return inventory_slot_typeless_lessthan(*this, rhs); - + if (TypeIndex() < rhs.TypeIndex()) return true; @@ -384,6 +384,6 @@ bool EQ::operator==(const InventorySlot& lhs, const InventorySlot& rhs) { if (lhs.Typeless() || rhs.Typeless()) return ((lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex())); - + return ((lhs.TypeIndex() == rhs.TypeIndex()) && (lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex())); } diff --git a/common/ip_util.cpp b/common/ip_util.cpp index e1f5d0794..4bb906bb5 100644 --- a/common/ip_util.cpp +++ b/common/ip_util.cpp @@ -18,7 +18,17 @@ * */ +#include +#include +#include +#include #include "ip_util.h" +#include "http/httplib.h" +#include "http/uri.h" +#include "eqemu_logsys.h" +#include "event/event_loop.h" +#include "net/dns.h" +#include "event/task_scheduler.h" /** * @param ip @@ -70,3 +80,148 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip) IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0") ); } + +/** + * Gets local address - pings google to inspect what interface was used locally + * @return + */ +std::string IpUtil::GetLocalIPAddress() +{ + char my_ip_address[16]; + unsigned int my_port; + struct sockaddr_in server_address{}; + struct sockaddr_in my_address{}; + int sockfd; + + // Connect to server + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return ""; + } + + // Set server_addr + memset(&server_address, 0, sizeof(server_address)); + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = inet_addr("172.217.160.99"); + server_address.sin_port = htons(80); + + // Connect to server + if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) { + close(sockfd); + return ""; + } + + // Get my ip address and port + memset(&my_address, 0, sizeof(my_address)); + socklen_t len = sizeof(my_address); + getsockname(sockfd, (struct sockaddr *) &my_address, &len); + inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address)); + my_port = ntohs(my_address.sin_port); + + return fmt::format("{}", my_ip_address); +} + +/** + * Gets public address + * Uses various websites as options to return raw public IP back to the client + * @return + */ +std::string IpUtil::GetPublicIPAddress() +{ + std::vector endpoints = { + "http://ifconfig.me", + "http://api.ipify.org", + "http://ipinfo.io/ip", + "http://ipecho.net/plain", + }; + + for (auto &s: endpoints) { + // http get request + uri u(s); + + httplib::Client r( + fmt::format( + "{}://{}", + u.get_scheme(), + u.get_host() + ).c_str() + ); + + httplib::Headers headers = { + {"Content-type", "text/plain; charset=utf-8"}, + {"User-Agent", "curl/7.81.0"} + }; + + r.set_connection_timeout(1, 0); + r.set_read_timeout(1, 0); + r.set_write_timeout(1, 0); + + if (auto res = r.Get(fmt::format("/{}", u.get_path()).c_str(), headers)) { + if (res->status == 200) { + if (res->body.find('.') != std::string::npos) { + return res->body; + } + } + } + } + + return {}; +} + +std::string IpUtil::DNSLookupSync(const std::string &addr, int port) +{ + auto task_runner = new EQ::Event::TaskScheduler(); + auto res = task_runner->Enqueue( + [&]() -> std::string { + bool running = true; + std::string ret; + + EQ::Net::DNSLookup( + addr, port, false, [&](const std::string &addr) { + ret = addr; + if (addr.empty()) { + ret = ""; + running = false; + } + + return ret; + } + ); + + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + + auto &loop = EQ::EventLoop::Get(); + while (running) { + if (!ret.empty()) { + running = false; + } + + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(end - begin).count() > 1500) { + LogInfo( + "Deadline exceeded [{}]", + 1500 + ); + running = false; + } + + loop.Process(); + } + + return ret; + } + ); + + std::string result = res.get(); + safe_delete(task_runner); + + return result; +} + +bool IpUtil::IsIPAddress(const std::string &ip_address) +{ + struct sockaddr_in sa{}; + int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr)); + return result != 0; +} + + diff --git a/common/ip_util.h b/common/ip_util.h index 76ea33fdb..3f67492a4 100644 --- a/common/ip_util.h +++ b/common/ip_util.h @@ -30,7 +30,14 @@ public: static uint32_t IPToUInt(const std::string &ip); static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask); static bool IsIpInPrivateRfc1918(const std::string &ip); + static std::string GetLocalIPAddress(); + static std::string GetPublicIPAddress(); + static std::string DNSLookupSync( + const std::string &addr, + int port + ); + static bool IsIPAddress(const std::string &ip_address); }; -#endif //EQEMU_IP_UTIL_H \ No newline at end of file +#endif //EQEMU_IP_UTIL_H diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index 5eb4eedfc..e2c123f22 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -30,6 +30,7 @@ #include "types.h" #include "eqemu_exception.h" #include "eqemu_config.h" +#include "path_manager.h" namespace EQ { struct IPCMutex::Implementation { @@ -40,12 +41,11 @@ namespace EQ { #endif }; - IPCMutex::IPCMutex(std::string name) : locked_(false) { + IPCMutex::IPCMutex(const std::string& name) : locked_(false) { imp_ = new Implementation; #ifdef _WINDOWS auto Config = EQEmuConfig::get(); - std::string final_name = Config->SharedMemDir + "EQEmuMutex_"; - final_name += name; + std::string final_name = fmt::format("{}/EQEmuMutex_{}", Config->SharedMemDir, name); imp_->mut_ = CreateMutex(nullptr, FALSE, @@ -55,9 +55,7 @@ namespace EQ { EQ_EXCEPT("IPC Mutex", "Could not create mutex."); } #else - auto Config = EQEmuConfig::get(); - std::string final_name = Config->SharedMemDir + name; - final_name += ".lock"; + std::string final_name = fmt::format("{}/{}.lock", path.GetSharedMemoryPath(), name); #ifdef __DARWIN #if __DARWIN_C_LEVEL < 200809L diff --git a/common/ipc_mutex.h b/common/ipc_mutex.h index a8f2fd13c..4418f9189 100644 --- a/common/ipc_mutex.h +++ b/common/ipc_mutex.h @@ -37,7 +37,7 @@ namespace EQ { Creates a named binary semaphore, basically a semaphore that is init S <- 1 \param name The name of this mutex. */ - IPCMutex(std::string name); + IPCMutex(const std::string& name); //! Destructor ~IPCMutex(); diff --git a/common/item_data.cpp b/common/item_data.cpp index f3e13edf7..12e2f80a7 100644 --- a/common/item_data.cpp +++ b/common/item_data.cpp @@ -169,11 +169,33 @@ uint8 EQ::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit) bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const { - if (!(Races & GetPlayerRaceBit(race_id))) + if (!(Races & GetPlayerRaceBit(race_id))) { return false; + } - if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) + if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) { return false; + } + + return true; +} + +bool EQ::ItemData::IsClassEquipable(uint16 class_id) const +{ + + if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) { + return false; + } + + return true; +} + +bool EQ::ItemData::IsRaceEquipable(uint16 race_id) const +{ + + if (!(Races & GetPlayerRaceBit(race_id))) { + return false; + } return true; } diff --git a/common/item_data.h b/common/item_data.h index e3123e22f..9c66f87a8 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -370,7 +370,7 @@ namespace EQ uint32 Slots; // Bitfield for which slots this item can be used in uint32 Price; // Item cost (?) uint32 Icon; // Icon Number - uint32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295) + int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295) bool LoreFlag; // This will be true if LoreGroup is non-zero bool PendingLoreFlag; bool ArtifactFlag; @@ -473,14 +473,14 @@ namespace EQ uint32 LDoNSold; uint32 BaneDmgRaceAmt; uint32 AugRestrict; - uint32 Endur; - uint32 DotShielding; - uint32 Attack; - uint32 Regen; - uint32 ManaRegen; - uint32 EnduranceRegen; - uint32 Haste; - uint32 DamageShield; + int32 Endur; + int32 DotShielding; + int32 Attack; + int32 Regen; + int32 ManaRegen; + int32 EnduranceRegen; + int32 Haste; + int32 DamageShield; uint32 RecastDelay; int RecastType; uint32 AugDistiller; @@ -533,6 +533,8 @@ namespace EQ //BardName bool IsEquipable(uint16 Race, uint16 Class) const; + bool IsClassEquipable(uint16 Class) const; + bool IsRaceEquipable(uint16 Race) const; bool IsClassCommon() const; bool IsClassBag() const; bool IsClassBook() const; diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 185f2960b..0b940c8b2 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -23,7 +23,7 @@ //#include "races.h" #include "rulesys.h" #include "shareddb.h" -#include "string_util.h" +#include "strings.h" //#include "../common/light_source.h" @@ -263,20 +263,43 @@ bool EQ::ItemInstance::IsCharged() const // Can item be equipped? bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const { - if (!m_item || (m_item->Slots == 0)) + if (!m_item || !m_item->Slots) { return false; + } return m_item->IsEquipable(race, class_); } +// Can item be equipped by Class? +bool EQ::ItemInstance::IsClassEquipable(uint16 class_) const +{ + if (!m_item || !m_item->Slots) { + return false; + } + + return m_item->IsClassEquipable(class_); +} + +// Can item be equipped by Race? +bool EQ::ItemInstance::IsRaceEquipable(uint16 race) const +{ + if (!m_item || !m_item->Slots) { + return false; + } + + return m_item->IsRaceEquipable(race); +} + // Can equip at this slot? bool EQ::ItemInstance::IsEquipable(int16 slot_id) const { - if (!m_item) + if (!m_item || !m_item->Slots) { return false; + } - if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) + if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) { return false; + } return ((m_item->Slots & (1 << slot_id)) != 0); } @@ -309,19 +332,30 @@ bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const { return (index <= EQ::invslot::EQUIPMENT_END); } -int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augtype) const +int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const { - if (!m_item || !m_item->IsClassCommon()) + if (!m_item || !m_item->IsClassCommon()) { return INVALID_INDEX; - - int index = invaug::SOCKET_BEGIN; - for (; index <= invaug::SOCKET_END; ++index) { - if (GetItem(index)) { continue; } - if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype))) - break; } - return (index <= invaug::SOCKET_END) ? index : INVALID_INDEX; + auto i = invaug::SOCKET_BEGIN; + for (; i <= invaug::SOCKET_END; ++i) { + if (GetItem(i)) { + continue; + } + + if ( + augment_type == -1 || + ( + m_item->AugSlotType[i] && + ((1 << (m_item->AugSlotType[i] - 1)) & augment_type) + ) + ) { + break; + } + } + + return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX; } bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const @@ -500,10 +534,11 @@ bool EQ::ItemInstance::IsNoneEmptyContainer() } // Retrieve augment inside item -EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 slot) const +EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 augment_index) const { - if (m_item && m_item->IsClassCommon()) - return GetItem(slot); + if (m_item && m_item->IsClassCommon()) { + return GetItem(augment_index); + } return nullptr; } @@ -629,12 +664,13 @@ bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *C return false; } -uint32 EQ::ItemInstance::GetAugmentItemID(uint8 slot) const +uint32 EQ::ItemInstance::GetAugmentItemID(uint8 augment_index) const { - if (!m_item || !m_item->IsClassCommon()) + if (!m_item || !m_item->IsClassCommon()) { return 0; + } - return GetItemID(slot); + return GetItemID(augment_index); } // Add an augment to the item @@ -1215,7 +1251,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const { - int race = 0; + int race = RACE_DOUG_0; const auto item = GetItem(); if (item) { race = item->BaneDmgRace; @@ -1721,6 +1757,18 @@ int EQ::ItemInstance::GetItemHaste(bool augments) const return total; } +int EQ::ItemInstance::RemoveTaskDeliveredItems() +{ + int count = IsStackable() ? GetCharges() : 1; + count -= GetTaskDeliveredCount(); + if (IsStackable()) + { + SetCharges(count); + } + SetTaskDeliveredCount(0); + return count; +} + // // class EvolveInfo // diff --git a/common/item_instance.h b/common/item_instance.h index c6b97dd78..02832a6e5 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -92,6 +92,8 @@ namespace EQ // Can item be equipped by/at? bool IsEquipable(uint16 race, uint16 class_) const; + bool IsClassEquipable(uint16 class_) const; + bool IsRaceEquipable(uint16 race) const; bool IsEquipable(int16 slot_id) const; // @@ -125,8 +127,8 @@ namespace EQ // // Augments // - ItemInstance* GetAugment(uint8 slot) const; - uint32 GetAugmentItemID(uint8 slot) const; + ItemInstance* GetAugment(uint8 augment_index) const; + uint32 GetAugmentItemID(uint8 augment_index) const; void PutAugment(uint8 slot, const ItemInstance& inst); void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id); void DeleteAugment(uint8 slot); @@ -148,6 +150,8 @@ namespace EQ const ItemData* GetItem() const; const ItemData* GetUnscaledItem() const; + const uint8 GetItemType() const { return m_item ? m_item->ItemType : 255; } // Return 255 so you know there's no valid item + int16 GetCharges() const { return m_charges; } void SetCharges(int16 charges) { m_charges = charges; } @@ -229,6 +233,13 @@ namespace EQ void StopTimer(std::string name); void ClearTimers(); + int GetTaskDeliveredCount() const { return m_task_delivered_count; } + void SetTaskDeliveredCount(int count) { m_task_delivered_count = count; } + // This function should only be used by trade return apis + // Removes delivered task items from stack count and returns remaining count + // Return value should be used to determine if an item still exists (for stackable and non-stackable) + int RemoveTaskDeliveredItems(); + // Get a total of a stat, including augs // These functions should be used in place of other code manually totaling // to centralize where it is done to make future changes easier (ex. whenever powersources come around) @@ -313,6 +324,7 @@ namespace EQ uint32 m_new_id_file; uint32 m_ornament_hero_model; uint32 m_recast_timestamp; + int m_task_delivered_count = 0; // // Items inside of this item (augs or contents); diff --git a/common/md5.cpp b/common/md5.cpp index e3df1ff3c..ca2e38eb2 100644 --- a/common/md5.cpp +++ b/common/md5.cpp @@ -9,7 +9,7 @@ */ #include /* for memcpy() */ #include "../common/md5.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/seperator.h" MD5::MD5() { diff --git a/common/memory_buffer.h b/common/memory_buffer.h index b1019a232..a2e19d364 100644 --- a/common/memory_buffer.h +++ b/common/memory_buffer.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -41,7 +41,7 @@ namespace EQ MemoryBuffer& operator+=(const MemoryBuffer &rhs); friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; } ~MemoryBuffer(); - + uchar& operator[](size_t pos); const uchar& operator[](size_t pos) const; @@ -64,20 +64,20 @@ namespace EQ size_t Size() const; size_t Capacity(); size_t Capacity() const; - + void Resize(size_t sz); void Clear(); void Zero(); template void Write(T val) { - static_assert(std::is_pod::value, "MemoryBuffer::Write(T val) only works on pod and string types."); + static_assert(std::is_standard_layout::value, "MemoryBuffer::Write(T val) only works on pod and string types."); Write((const char*)&val, sizeof(T)); } template T Read() { - static_assert(std::is_pod::value, "MemoryBuffer::Read() only works on pod and string types."); + static_assert(std::is_standard_layout::value, "MemoryBuffer::Read() only works on pod and string types."); T temp; Read((uchar*)&temp, sizeof(T)); return temp; @@ -102,7 +102,7 @@ namespace EQ read_pos_ += len + 1; return ret; } - + void Write(const char *val, size_t len); void Read(uchar *buf, size_t len); void Read(char *str); @@ -113,7 +113,7 @@ namespace EQ inline size_t GetReadPosition() { return read_pos_; } inline void SetReadPosition(size_t rp) { read_pos_ = rp; } inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; } - + private: uchar *buffer_; size_t size_; diff --git a/common/memory_mapped_file.cpp b/common/memory_mapped_file.cpp index a11b3c5db..a1a16d5db 100644 --- a/common/memory_mapped_file.cpp +++ b/common/memory_mapped_file.cpp @@ -33,6 +33,9 @@ #include #endif +#include +namespace fs = std::filesystem; + namespace EQ { struct MemoryMappedFile::Implementation { diff --git a/common/mysql_request_row.h b/common/mysql_request_row.h index ddfbddee9..5f160ac63 100644 --- a/common/mysql_request_row.h +++ b/common/mysql_request_row.h @@ -10,8 +10,14 @@ #include #include "types.h" -class MySQLRequestRow : public std::iterator +class MySQLRequestRow { +public: + using iterator_category = std::input_iterator_tag; + using value_type = MYSQL_ROW; + using difference_type = std::ptrdiff_t; + using pointer = MYSQL_ROW*; + using reference = MYSQL_ROW&; private: MYSQL_RES* m_Result; diff --git a/common/net/console_server.cpp b/common/net/console_server.cpp index 31b597bfb..1b8e8af32 100644 --- a/common/net/console_server.cpp +++ b/common/net/console_server.cpp @@ -1,5 +1,5 @@ #include "console_server.h" -#include "../string_util.h" +#include "../strings.h" #include EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port) @@ -52,11 +52,11 @@ void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c) void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd) { - auto split = SplitString(cmd, ' '); - + auto split = Strings::Split(cmd, ' '); + if (split.size() > 0) { auto command = split[0]; - ToLowerString(command); + command = Strings::ToLower(command); if (command == "help" || command == "?") { c->SendLine("Commands:"); @@ -70,9 +70,9 @@ void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const st c->SendPrompt(); return; } - + split.erase(split.begin(), split.begin() + 1); - + auto cmd_def = m_commands.find(command); if (cmd_def != m_commands.end()) { if (c->Admin() >= cmd_def->second.status_required) { diff --git a/common/net/console_server_connection.cpp b/common/net/console_server_connection.cpp index 9e245a8f8..e53058f67 100644 --- a/common/net/console_server_connection.cpp +++ b/common/net/console_server_connection.cpp @@ -116,43 +116,42 @@ bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMes } switch (scm->chan_num) { - case 4: { - if (RuleB(Chat, ServerWideAuction)) { - QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message)); - break; - } else { // I think we want default action in this case? - return false; - } - } - - case 5: { - if (RuleB(Chat, ServerWideOOC)) { - QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message)); - break; - } else { // I think we want default action in this case? - return false; - } - } - - case 6: { - QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message)); + case ChatChannel_Guild: { + QueueMessage(fmt::format("{} tells the guild [{}], '{}'", scm->from, scm->guilddbid, scm->message)); break; } - - case 7: { - QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message)); + case ChatChannel_Auction: { + if (RuleB(Chat, ServerWideAuction)) { + QueueMessage(fmt::format("{} auctions, '{}'", scm->from, scm->message)); + break; + } else { // I think we want default action in this case? + return false; + } + } + case ChatChannel_OOC: { + if (RuleB(Chat, ServerWideOOC)) { + QueueMessage(fmt::format("{} says ooc, '{}'", scm->from, scm->message)); + break; + } else { // I think we want default action in this case? + return false; + } + } + case ChatChannel_Broadcast: { + QueueMessage(fmt::format("{} BROADCASTS, '{}'", scm->from, scm->message)); + break; + } + case ChatChannel_Tell: { + QueueMessage(fmt::format("[{}] tells {}, '{}'", scm->from, scm->to, scm->message)); if (onTell) { onTell(); } break; } - - case 11: { - QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message)); + case ChatChannel_GMSAY: { + QueueMessage(fmt::format("{} GMSAYS, '{}'", scm->from, scm->message)); break; } - default: { return false; } diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 125a240dd..7edb41244 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -3,6 +3,7 @@ #include "../event/task.h" #include "../data_verification.h" #include "crc32.h" +#include "../eqemu_logsys.h" #include #include #include @@ -308,6 +309,8 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); m_outgoing_budget = owner->m_options.outgoing_data_rate; + + LogNetcode("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key)); } //new connection made as client @@ -466,7 +469,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) for (int i = 1; i >= 0; --i) { switch (m_encode_passes[i]) { case EncodeXOR: - if (temp.GetInt8(0) == 0) + if (temp.GetInt8(0) == 0) Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); else Decode(temp, 1, temp.Length() - 1); @@ -630,6 +633,8 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) DynamicPacket p; p.PutSerialize(0, reply); InternalSend(p); + + LogNetcode("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key)); } break; @@ -647,6 +652,12 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2; m_max_packet_size = reply.max_packet_size; ChangeStatus(StatusConnected); + + LogNetcode( + "[OP_SessionResponse] Session [{}] refresh with encode key [{}]", + m_connect_code, + HostToNetwork(m_encode_key) + ); } } break; @@ -771,6 +782,12 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) SendDisconnect(); } + LogNetcode( + "[OP_SessionDisconnect] Session [{}] disconnect with encode key [{}]", + m_connect_code, + HostToNetwork(m_encode_key) + ); + ChangeStatus(StatusDisconnecting); break; } @@ -835,6 +852,7 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p) } if (p.Length() < (size_t)m_crc_bytes) { + LogNetcode("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code); return false; } @@ -1078,7 +1096,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) if (m_status == DbProtocolStatus::StatusDisconnected) { return; } - + auto resends = 0; auto now = Clock::now(); auto s = &m_streams[stream]; @@ -1113,7 +1131,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) Close(); return; } - + if ((size_t)time_since_last_send.count() > entry.second.resend_delay) { auto &p = entry.second.packet; if (p.Length() >= DaybreakHeader::size()) { @@ -1394,7 +1412,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length); size_t used = 0; - size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size(); + size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size() - 1; // -1 for compress flag DynamicPacket first_packet; first_packet.PutSerialize(0, first_header); first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen); @@ -1406,8 +1424,8 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, sent.first_sent = Clock::now(); sent.times_resent = 0; sent.resend_delay = EQ::Clamp( - static_cast((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms), - m_owner->m_options.resend_delay_min, + static_cast((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms), + m_owner->m_options.resend_delay_min, m_owner->m_options.resend_delay_max); stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); stream->sequence_out++; diff --git a/common/net/eqstream.cpp b/common/net/eqstream.cpp index 368a23931..c72ad1c4f 100644 --- a/common/net/eqstream.cpp +++ b/common/net/eqstream.cpp @@ -65,6 +65,15 @@ EQ::Net::EQStream::~EQStream() } void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) { + + LogPacketServerClient( + "[{}] [{:#06x}] Size [{}] {}", + OpcodeManager::EmuToName(p->GetOpcode()), + (*m_opcode_manager)->EmuToEQ(p->GetOpcode()), + p->Size(), + (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "") + ); + if (m_opcode_manager && *m_opcode_manager) { uint16 opcode = 0; if (p->GetOpcodeBypass() != 0) { diff --git a/common/net/eqstream.h b/common/net/eqstream.h index 86d7b9485..a87c6ec0b 100644 --- a/common/net/eqstream.h +++ b/common/net/eqstream.h @@ -57,6 +57,10 @@ namespace EQ virtual void SetOpcodeManager(OpcodeManager **opm) { m_opcode_manager = opm; } + virtual OpcodeManager * GetOpcodeManager() const + { + return (*m_opcode_manager); + }; virtual Stats GetStats() const; virtual void ResetStats(); diff --git a/common/net/servertalk_server_connection.cpp b/common/net/servertalk_server_connection.cpp index f3823cda6..405f85f73 100644 --- a/common/net/servertalk_server_connection.cpp +++ b/common/net/servertalk_server_connection.cpp @@ -135,7 +135,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer() auto leg_opcode = *(uint16_t*)&m_buffer[current]; auto leg_size = *(uint16_t*)&m_buffer[current + 2] - 4; - //this creates a small edge case where the exact size of a + //this creates a small edge case where the exact size of a //packet from the modern protocol can't be "43061256" //so in send we pad it one byte if that's the case if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) { @@ -319,6 +319,16 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p) size_t message_len = length; EQ::Net::StaticPacket packet(&data[0], message_len); + const auto is_detail_enabled = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer); + if (opcode != ServerOP_KeepAlive || is_detail_enabled) { + LogPacketServerToServer( + "[{:#06x}] Size [{}] {}", + opcode, + packet.Length(), + (is_detail_enabled ? "\n" + packet.ToString() : "") + ); + } + auto cb = m_message_callbacks.find(opcode); if (cb != m_message_callbacks.end()) { cb->second(opcode, packet); diff --git a/common/opcodemgr.cpp b/common/opcodemgr.cpp index 11d1b4811..70bcff702 100644 --- a/common/opcodemgr.cpp +++ b/common/opcodemgr.cpp @@ -184,6 +184,9 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) { MOpcodes.lock(); res = emu_to_eq[emu_op]; MOpcodes.unlock(); + + LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res); + #ifdef DEBUG_TRANSLATE fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res); #endif diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 908ecc26b..44a2ae606 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -11,7 +11,7 @@ are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -28,10 +28,12 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" -#include "../string_util.h" +#include "../strings.h" #include "../inventory_profile.h" #include "rof_structs.h" #include "../rulesys.h" +#include "../path_manager.h" +#include "../races.h" #include #include @@ -52,13 +54,13 @@ namespace RoF static inline structs::InventorySlot_Struct ServerToRoFCorpseSlot(uint32 server_corpse_slot); static inline uint32 ServerToRoFCorpseMainSlot(uint32 server_corpse_slot); static inline structs::TypelessInventorySlot_Struct ServerToRoFTypelessSlot(uint32 server_slot, int16 server_type); - + // client to server inventory location converters static inline uint32 RoFToServerSlot(structs::InventorySlot_Struct rof_slot); static inline uint32 RoFToServerCorpseSlot(structs::InventorySlot_Struct rof_corpse_slot); static inline uint32 RoFToServerCorpseMainSlot(uint32 rof_corpse_slot); static inline uint32 RoFToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof_slot, int16 rof_type); - + // server to client say link converter static inline void ServerToRoFSayLink(std::string& rofSayLink, const std::string& serverSayLink); @@ -75,12 +77,8 @@ namespace RoF { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); + //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -118,12 +116,7 @@ namespace RoF //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; @@ -672,7 +665,7 @@ namespace RoF ENCODE(OP_DeleteCharge) { - Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)"); + Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)"); ENCODE_FORWARD(OP_MoveItem); } @@ -736,30 +729,6 @@ namespace RoF FINISH_ENCODE(); } - ENCODE(OP_DzCompass) - { - SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); - ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, - sizeof(structs::DynamicZoneCompass_Struct) + - sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count - ); - - OUT(client_id); - OUT(count); - - for (uint32 i = 0; i < emu->count; ++i) - { - OUT(entries[i].dz_zone_id); - OUT(entries[i].dz_instance_id); - OUT(entries[i].dz_type); - OUT(entries[i].x); - OUT(entries[i].y); - OUT(entries[i].z); - } - - FINISH_ENCODE(); - } - ENCODE(OP_DzExpeditionEndsWarning) { ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); @@ -1558,7 +1527,7 @@ namespace RoF in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -1624,7 +1593,7 @@ namespace RoF ENCODE_LENGTH_EXACT(LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_LootItem)"); OUT(lootee); OUT(looter); @@ -1782,7 +1751,7 @@ namespace RoF ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)"); eq->from_slot = ServerToRoFSlot(emu->from_slot); eq->to_slot = ServerToRoFSlot(emu->to_slot); @@ -1838,10 +1807,10 @@ namespace RoF OUT_str(zone_short_name2); OUT(zone_id); OUT(zone_instance); - OUT(SuspendBuffs); - OUT(FastRegenHP); - OUT(FastRegenMana); - OUT(FastRegenEndurance); + OUT(suspend_buffs); + OUT(fast_regen_hp); + OUT(fast_regen_mana); + OUT(fast_regen_endurance); OUT(underworld_teleport_index); eq->FogDensity = emu->fog_density; @@ -1849,8 +1818,8 @@ namespace RoF /*fill in some unknowns with observed values, hopefully it will help */ eq->unknown800 = -1; eq->unknown844 = 600; - OUT(LavaDamage); - OUT(MinLavaDamage); + OUT(lava_damage); + OUT(min_lava_damage); eq->unknown888 = 1; eq->unknown889 = 0; eq->unknown890 = 1; @@ -3862,7 +3831,9 @@ namespace RoF } float SpawnSize = emu->size; - if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)) + ) { PacketSize += 60; @@ -3994,7 +3965,9 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 - if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522) + ) { for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) { @@ -4849,7 +4822,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_LootItem)"); IN(lootee); IN(looter); @@ -4864,7 +4837,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_MoveItem)"); emu->from_slot = RoFToServerSlot(eq->from_slot); emu->to_slot = RoFToServerSlot(eq->to_slot); @@ -5188,7 +5161,7 @@ namespace RoF void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { const EQ::ItemData *item = inst->GetUnscaledItem(); - + RoF::structs::ItemSerializationHeader hdr; //sprintf(hdr.unknown000, "06e0002Y1W00"); @@ -5207,7 +5180,7 @@ namespace RoF slot_id = ServerToRoFSlot(slot_id_in); break; } - + hdr.slot_type = (inst->GetMerchantSlot() ? invtype::typeMerchant : slot_id.Type); hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot); hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex); @@ -5295,7 +5268,7 @@ namespace RoF ob.write("\0", 1); ob.write("\0", 1); - + RoF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct)); @@ -5608,7 +5581,7 @@ namespace RoF iqbs.unknown28 = 0; iqbs.unknown30 = 0; iqbs.unknown39 = 1; - + ob.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); EQ::OutBuffer::pos_type count_pos = ob.tellp(); @@ -5776,7 +5749,7 @@ namespace RoF static inline uint32 ServerToRoFCorpseMainSlot(uint32 server_corpse_slot) { uint32 RoFSlot = invslot::SLOT_INVALID; - + if (server_corpse_slot <= EQ::invslot::CORPSE_END && server_corpse_slot >= EQ::invslot::CORPSE_BEGIN) { RoFSlot = server_corpse_slot; } @@ -6123,7 +6096,7 @@ namespace RoF return; } - auto segments = SplitString(serverSayLink, '\x12'); + auto segments = Strings::Split(serverSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -6162,7 +6135,7 @@ namespace RoF return; } - auto segments = SplitString(rofSayLink, '\x12'); + auto segments = Strings::Split(rofSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e6404a62a..c5facee0b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -28,10 +28,13 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" -#include "../string_util.h" +#include "../strings.h" #include "../inventory_profile.h" #include "rof2_structs.h" #include "../rulesys.h" +#include "../path_manager.h" +#include "../classes.h" +#include "../races.h" #include #include @@ -53,13 +56,13 @@ namespace RoF2 static inline structs::InventorySlot_Struct ServerToRoF2CorpseSlot(uint32 server_corpse_slot); static inline uint32 ServerToRoF2CorpseMainSlot(uint32 server_corpse_slot); static inline structs::TypelessInventorySlot_Struct ServerToRoF2TypelessSlot(uint32 server_slot, int16 server_type); - + // client to server inventory location converters static inline uint32 RoF2ToServerSlot(structs::InventorySlot_Struct rof2_slot); static inline uint32 RoF2ToServerCorpseSlot(structs::InventorySlot_Struct rof2_corpse_slot); static inline uint32 RoF2ToServerCorpseMainSlot(uint32 rof2_corpse_slot); static inline uint32 RoF2ToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof2_slot, int16 rof2_type); - + // server to client say link converter static inline void ServerToRoF2SayLink(std::string &rof2_saylink, const std::string &server_saylink); @@ -76,12 +79,9 @@ namespace RoF2 { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); + //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -122,12 +122,7 @@ namespace RoF2 //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; @@ -721,7 +716,7 @@ namespace RoF2 ENCODE(OP_DeleteCharge) { - Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)"); + Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)"); ENCODE_FORWARD(OP_MoveItem); } @@ -785,30 +780,6 @@ namespace RoF2 FINISH_ENCODE(); } - ENCODE(OP_DzCompass) - { - SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); - ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, - sizeof(structs::DynamicZoneCompass_Struct) + - sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count - ); - - OUT(client_id); - OUT(count); - - for (uint32 i = 0; i < emu->count; ++i) - { - OUT(entries[i].dz_zone_id); - OUT(entries[i].dz_instance_id); - OUT(entries[i].dz_type); - OUT(entries[i].x); - OUT(entries[i].y); - OUT(entries[i].z); - } - - FINISH_ENCODE(); - } - ENCODE(OP_DzExpeditionEndsWarning) { ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); @@ -1673,7 +1644,7 @@ namespace RoF2 ENCODE_LENGTH_EXACT(LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)"); OUT(lootee); OUT(looter); @@ -1831,7 +1802,7 @@ namespace RoF2 ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)"); eq->from_slot = ServerToRoF2Slot(emu->from_slot); eq->to_slot = ServerToRoF2Slot(emu->to_slot); @@ -1887,13 +1858,13 @@ namespace RoF2 OUT_str(zone_short_name2); OUT(zone_id); OUT(zone_instance); - OUT(SuspendBuffs); - OUT(FastRegenHP); - OUT(FastRegenMana); - OUT(FastRegenEndurance); + OUT(suspend_buffs); + OUT(fast_regen_hp); + OUT(fast_regen_mana); + OUT(fast_regen_endurance); OUT(underworld_teleport_index); - eq->FogDensity = emu->fog_density; + eq->fog_density = emu->fog_density; /*fill in some unknowns with observed values, hopefully it will help */ eq->ZoneTimeZone = 0; @@ -1905,22 +1876,22 @@ namespace RoF2 eq->SkyRelated2 = -1; eq->NPCAggroMaxDist = 600; eq->FilterID = 2008; // Guild Lobby observed value - OUT(LavaDamage); - OUT(MinLavaDamage); - eq->bDisallowManaStone = 1; - eq->bNoBind = 0; - eq->bNoAttack = 0; - eq->bNoCallOfHero = 0; - eq->bNoFlux = 0; - eq->bNoFear = 0; - eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off - eq->unknown895 = 0; - eq->CanPlaceCampsite = 2; - eq->CanPlaceGuildBanner = 2; - eq->FishingRelated = -1; // Set from PoK Example - eq->ForageRelated = -1; // Set from PoK Example - eq->bNoLevitate = 0; - eq->Blooming = 1.0; // Set from PoK Example + OUT(lava_damage); + OUT(min_lava_damage); + eq->bDisallowManaStone = 1; + eq->bNoBind = 0; + eq->bNoAttack = 0; + eq->bNoCallOfHero = 0; + eq->bNoFlux = 0; + eq->bNoFear = 0; + eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off + eq->unknown895 = 0; + eq->can_place_campsite = 2; + eq->can_place_guild_banner = 2; + eq->fishing_related = -1; // Set from PoK Example + eq->forage_related = -1; // Set from PoK Example + eq->b_no_levitate = 0; + eq->blooming = 1.0; // Set from PoK Example FINISH_ENCODE(); } @@ -2894,12 +2865,12 @@ namespace RoF2 EQApplicationPacket *inapp = *p; *p = nullptr; AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - + // the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0; auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size); inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct)); - + std::vector skill; std::vector points; @@ -2962,7 +2933,7 @@ namespace RoF2 outapp->WriteUInt32(inapp->ReadUInt32()); // base2 outapp->WriteUInt32(inapp->ReadUInt32()); // slot } - + dest->FastQueuePacket(&outapp); delete inapp; } @@ -3975,7 +3946,7 @@ namespace RoF2 if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; - if (emu->DestructibleObject || emu->class_ == 62) + if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) { if (emu->DestructibleObject) PacketSize = PacketSize - 4; // No bodytype @@ -3996,7 +3967,9 @@ namespace RoF2 } float SpawnSize = emu->size; - if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)) + ) { PacketSize += 60; @@ -4063,17 +4036,19 @@ namespace RoF2 // actually part of bitfields uint8 OtherData = 0; - if (emu->class_ == 62) //LDoN Chest + if (emu->class_ == LDON_TREASURE) //LDoN Chest + { OtherData = OtherData | 0x04; - - if (strlen(emu->title)) + } + if (strlen(emu->title)) { OtherData = OtherData | 16; - - if (strlen(emu->suffix)) + } + if (strlen(emu->suffix)) { OtherData = OtherData | 32; - - if (emu->DestructibleObject) + } + if (emu->DestructibleObject) { OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData + } VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); // float EmitterScalingRadius @@ -4089,7 +4064,7 @@ namespace RoF2 // int DefaultEmitterID VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - if (emu->DestructibleObject || emu->class_ == 62) + if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) { VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); @@ -4197,7 +4172,9 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^ - if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522) + ) { for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) { @@ -5046,7 +5023,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_LootItem)"); IN(lootee); IN(looter); @@ -5061,12 +5038,12 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)"); - + Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)"); + emu->from_slot = RoF2ToServerSlot(eq->from_slot); emu->to_slot = RoF2ToServerSlot(eq->to_slot); IN(number_in_stack); - + //LogNetcode("[RoF2] MoveItem Slot from [{}] to [{}], Number [{}]", emu->from_slot, emu->to_slot, emu->number_in_stack); FINISH_DIRECT_DECODE(); @@ -5443,7 +5420,7 @@ namespace RoF2 void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { const EQ::ItemData *item = inst->GetUnscaledItem(); - + RoF2::structs::ItemSerializationHeader hdr; //sprintf(hdr.unknown000, "06e0002Y1W00"); @@ -5462,7 +5439,7 @@ namespace RoF2 slot_id = ServerToRoF2Slot(slot_id_in); break; } - + hdr.slot_type = (inst->GetMerchantSlot() ? invtype::typeMerchant : slot_id.Type); hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot); hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex); @@ -5550,7 +5527,7 @@ namespace RoF2 ob.write("\0", 1); ob.write("\0", 1); - + RoF2::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); @@ -5873,7 +5850,7 @@ namespace RoF2 iqbs.unknown37a = 0; // (guessed position) New to RoF2 iqbs.unknown38 = 0; iqbs.unknown39 = 1; - + ob.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); EQ::OutBuffer::pos_type count_pos = ob.tellp(); @@ -6073,7 +6050,7 @@ namespace RoF2 uint32 server_slot = EQ::invslot::SLOT_INVALID; uint32 temp_slot = invslot::SLOT_INVALID; - + switch (rof2_slot.Type) { case invtype::typePossessions: { if (rof2_slot.Slot >= invslot::POSSESSIONS_BEGIN && rof2_slot.Slot <= invslot::POSSESSIONS_END) { @@ -6188,11 +6165,11 @@ namespace RoF2 static inline uint32 RoF2ToServerCorpseSlot(structs::InventorySlot_Struct rof2_corpse_slot) { uint32 ServerSlot = EQ::invslot::SLOT_INVALID; - + if (rof2_corpse_slot.Type != invtype::typeCorpse || rof2_corpse_slot.SubIndex != invbag::SLOT_INVALID || rof2_corpse_slot.AugIndex != invaug::SOCKET_INVALID) { ServerSlot = EQ::invslot::SLOT_INVALID; } - + else { ServerSlot = RoF2ToServerCorpseMainSlot(rof2_corpse_slot.Slot); } @@ -6346,7 +6323,7 @@ namespace RoF2 return; } - auto segments = SplitString(server_saylink, '\x12'); + auto segments = Strings::Split(server_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -6378,7 +6355,7 @@ namespace RoF2 return; } - auto segments = SplitString(rof2_saylink, '\x12'); + auto segments = Strings::Split(rof2_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp index c67ccf3ad..6df113f51 100644 --- a/common/patches/rof2_limits.cpp +++ b/common/patches/rof2_limits.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "rof2_limits.h" -#include "../string_util.h" +#include "../strings.h" int16 RoF2::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 130686cdf..4fa2e546a 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -59,7 +59,6 @@ E(OP_DeleteItem) E(OP_DeleteSpawn) E(OP_DisciplineUpdate) E(OP_DzChooseZone) -E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) E(OP_DzExpeditionInvite) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 42c1e5883..037574861 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -620,40 +620,40 @@ struct NewZone_Struct { /*0800*/ int32 SkyRelated2; //seen -1 -- maybe some default sky time? /*0804*/ char WeatherString2[32]; // /*0836*/ float WeatherChangeTime; // not sure :P - /*0840*/ uint32 Climate; - /*0844*/ int32 NPCAggroMaxDist; //seen 600 - /*0848*/ int32 FilterID; //seen 2008 -- maybe zone guide related? - /*0852*/ uint16 zone_id; // this might just be instance ID got 1736 for time - /*0854*/ uint16 zone_instance; - /*0856*/ uint32 scriptNPCReceivedanItem; - /*0860*/ uint32 bCheck; // padded bool - /*0864*/ uint32 scriptIDSomething; - /*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions - /*0872*/ uint32 scriptIDSomething3; - /*0876*/ uint32 SuspendBuffs; // padded bool - /*0880*/ uint32 LavaDamage; // LavaDamage value - /*0884*/ uint32 MinLavaDamage; // min cap after resist calcs - /*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone - /*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can! - /*0890*/ uint8 bNoAttack; // non-attack zone - /*0891*/ uint8 bNoCallOfHero; // coth line disabled - /*0892*/ uint8 bNoFlux; // gflux no worky - /*0893*/ uint8 bNoFear; // fear spells no worky - /*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber - /*0895*/ uint8 unknown895; // padding - /*0896*/ uint32 FastRegenHP; // percentage I think? - /*0900*/ uint32 FastRegenMana; // percentage I think? - /*0904*/ uint32 FastRegenEndurance; // percentage I think? - /*0908*/ uint32 CanPlaceCampsite; // 0 = no, 1 = can place, 2 = place and goto - /*0912*/ uint32 CanPlaceGuildBanner; // ^ - /*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16 - /*0920*/ uint32 bAdjustGamma; // padded bool - /*0924*/ uint32 TimeStringID; // Seen 0 - /*0928*/ uint32 bNoMercenaries; // padded bool - /*0932*/ int32 FishingRelated; // Seen -1 idk - /*0936*/ int32 ForageRelated; // Seen -1 idk - /*0940*/ uint32 bNoLevitate; // padded bool - /*0944*/ float Blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby + /*0840*/ uint32 Climate; + /*0844*/ int32 NPCAggroMaxDist; //seen 600 + /*0848*/ int32 FilterID; //seen 2008 -- maybe zone guide related? + /*0852*/ uint16 zone_id; // this might just be instance ID got 1736 for time + /*0854*/ uint16 zone_instance; + /*0856*/ uint32 scriptNPCReceivedanItem; + /*0860*/ uint32 bCheck; // padded bool + /*0864*/ uint32 scriptIDSomething; + /*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions + /*0872*/ uint32 scriptIDSomething3; + /*0876*/ uint32 suspend_buffs; // padded bool + /*0880*/ uint32 lava_damage; // lava_damage value + /*0884*/ uint32 min_lava_damage; // min cap after resist calcs + /*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone + /*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can! + /*0890*/ uint8 bNoAttack; // non-attack zone + /*0891*/ uint8 bNoCallOfHero; // coth line disabled + /*0892*/ uint8 bNoFlux; // gflux no worky + /*0893*/ uint8 bNoFear; // fear spells no worky + /*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber + /*0895*/ uint8 unknown895; // padding + /*0896*/ uint32 fast_regen_hp; // percentage I think? + /*0900*/ uint32 fast_regen_mana; // percentage I think? + /*0904*/ uint32 fast_regen_endurance; // percentage I think? + /*0908*/ uint32 can_place_campsite; // 0 = no, 1 = can place, 2 = place and goto + /*0912*/ uint32 can_place_guild_banner; // ^ + /*0916*/ float fog_density; // Most zones have this set to 0.33 Blightfire had 0.16 + /*0920*/ uint32 b_adjust_gamma; // padded bool + /*0924*/ uint32 time_string_id; // Seen 0 + /*0928*/ uint32 b_no_mercenaries; // padded bool + /*0932*/ int32 fishing_related; // Seen -1 idk + /*0936*/ int32 forage_related; // Seen -1 idk + /*0940*/ uint32 b_no_levitate; // padded bool + /*0944*/ float blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby /*0948*/ }; @@ -3476,7 +3476,7 @@ struct TraderClick_Struct{ /*000*/ uint32 Code; /*004*/ uint32 TraderID; /*008*/ uint32 Approval; - /*012*/ + /*012*/ }; struct FormattedMessage_Struct{ @@ -4989,7 +4989,7 @@ struct DynamicZoneCompassEntry_Struct /*000*/ uint16 dz_zone_id; // target dz id pair /*002*/ uint16 dz_instance_id; /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) -/*008*/ uint32 unknown008; +/*008*/ uint32 dz_switch_id; /*012*/ float y; /*016*/ float x; /*020*/ float z; diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp index 6c30b85f7..beb2bdbbc 100644 --- a/common/patches/rof_limits.cpp +++ b/common/patches/rof_limits.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "rof_limits.h" -#include "../string_util.h" +#include "../strings.h" int16 RoF::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 7cca08e61..98f20f431 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -45,7 +45,6 @@ E(OP_DeleteItem) E(OP_DeleteSpawn) E(OP_DisciplineUpdate) E(OP_DzChooseZone) -E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) E(OP_DzExpeditionInvite) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 662cc3872..3c81505d4 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -571,39 +571,39 @@ struct NewZone_Struct { /*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version. /*0800*/ int32 unknown800; //seen -1 /*0804*/ char unknown804[40]; // -/*0844*/ int32 unknown844; //seen 600 -/*0848*/ int32 unknown848; -/*0852*/ uint16 zone_id; -/*0854*/ uint16 zone_instance; -/*0856*/ uint32 scriptNPCReceivedanItem; -/*0860*/ uint32 bCheck; // padded bool -/*0864*/ uint32 scriptIDSomething; -/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions -/*0872*/ uint32 scriptIDSomething3; -/*0876*/ uint32 SuspendBuffs; -/*0880*/ uint32 LavaDamage; // Seen 50 -/*0884*/ uint32 MinLavaDamage; // Seen 10 -/*0888*/ uint8 unknown888; // Seen 1 -/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj) -/*0890*/ uint8 unknown890; // Seen 1 -/*0891*/ uint8 unknown891; // Seen 0 -/*0892*/ uint8 unknown892; // Seen 0 -/*0893*/ uint8 unknown893; // Seen 0 - 00 -/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off -/*0895*/ uint8 unknown895; // Seen 0 - 00 -/*0896*/ uint32 FastRegenHP; // Seen 180 -/*0900*/ uint32 FastRegenMana; // Seen 180 -/*0904*/ uint32 FastRegenEndurance; // Seen 180 -/*0908*/ uint32 unknown908; // Seen 2 -/*0912*/ uint32 unknown912; // Seen 2 -/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16 -/*0920*/ uint32 unknown920; // Seen 0 -/*0924*/ uint32 unknown924; // Seen 0 -/*0928*/ uint32 unknown928; // Seen 0 +/*0844*/ int32 unknown844; //seen 600 +/*0848*/ int32 unknown848; +/*0852*/ uint16 zone_id; +/*0854*/ uint16 zone_instance; +/*0856*/ uint32 scriptNPCReceivedanItem; +/*0860*/ uint32 bCheck; // padded bool +/*0864*/ uint32 scriptIDSomething; +/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions +/*0872*/ uint32 scriptIDSomething3; +/*0876*/ uint32 suspend_buffs; +/*0880*/ uint32 lava_damage; // Seen 50 +/*0884*/ uint32 min_lava_damage; // Seen 10 +/*0888*/ uint8 unknown888; // Seen 1 +/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj) +/*0890*/ uint8 unknown890; // Seen 1 +/*0891*/ uint8 unknown891; // Seen 0 +/*0892*/ uint8 unknown892; // Seen 0 +/*0893*/ uint8 unknown893; // Seen 0 - 00 +/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off +/*0895*/ uint8 unknown895; // Seen 0 - 00 +/*0896*/ uint32 fast_regen_hp; // Seen 180 +/*0900*/ uint32 fast_regen_mana; // Seen 180 +/*0904*/ uint32 fast_regen_endurance; // Seen 180 +/*0908*/ uint32 unknown908; // Seen 2 +/*0912*/ uint32 unknown912; // Seen 2 +/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16 +/*0920*/ uint32 unknown920; // Seen 0 +/*0924*/ uint32 unknown924; // Seen 0 +/*0928*/ uint32 unknown928; // Seen 0 /*0932*/ int32 unknown932; // Seen -1 /*0936*/ int32 unknown936; // Seen -1 -/*0940*/ uint32 unknown940; // Seen 0 -/*0944*/ float unknown944; // Seen 1.0 +/*0940*/ uint32 unknown940; // Seen 0 +/*0944*/ float unknown944; // Seen 1.0 /*0948*/ }; @@ -4921,7 +4921,7 @@ struct DynamicZoneCompassEntry_Struct /*000*/ uint16 dz_zone_id; // target dz id pair /*002*/ uint16 dz_instance_id; /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) -/*008*/ uint32 unknown008; +/*008*/ uint32 dz_switch_id; /*012*/ float y; /*016*/ float x; /*020*/ float z; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 32e58e432..98afcec62 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -28,10 +28,12 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" -#include "../string_util.h" +#include "../strings.h" #include "../item_instance.h" #include "sod_structs.h" #include "../rulesys.h" +#include "../path_manager.h" +#include "../races.h" #include #include @@ -69,12 +71,7 @@ namespace SoD { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -115,12 +112,7 @@ namespace SoD //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; @@ -407,7 +399,7 @@ namespace SoD in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -466,7 +458,7 @@ namespace SoD ENCODE(OP_DeleteCharge) { - Log(Logs::Moderate, Logs::Netcode, "SoD::ENCODE(OP_DeleteCharge)"); + Log(Logs::Detail, Logs::Netcode, "SoD::ENCODE(OP_DeleteCharge)"); ENCODE_FORWARD(OP_MoveItem); } @@ -509,30 +501,6 @@ namespace SoD FINISH_ENCODE(); } - ENCODE(OP_DzCompass) - { - SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); - ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, - sizeof(structs::DynamicZoneCompass_Struct) + - sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count - ); - - OUT(client_id); - OUT(count); - - for (uint32 i = 0; i < emu->count; ++i) - { - OUT(entries[i].dz_zone_id); - OUT(entries[i].dz_instance_id); - OUT(entries[i].dz_type); - OUT(entries[i].x); - OUT(entries[i].y); - OUT(entries[i].z); - } - - FINISH_ENCODE(); - } - ENCODE(OP_DzExpeditionEndsWarning) { ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); @@ -1089,7 +1057,7 @@ namespace SoD //store away the emu struct uchar* __emu_buffer = in->pBuffer; - + EQ::InternalSerializedItem_Struct* int_struct = (EQ::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQ::OutBuffer ob; @@ -1106,7 +1074,7 @@ namespace SoD in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -1160,7 +1128,7 @@ namespace SoD ENCODE_LENGTH_EXACT(LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoD::ENCODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "SoD::ENCODE(OP_LootItem)"); OUT(lootee); OUT(looter); @@ -1309,7 +1277,7 @@ namespace SoD ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoD::ENCODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "SoD::ENCODE(OP_MoveItem)"); eq->from_slot = ServerToSoDSlot(emu->from_slot); eq->to_slot = ServerToSoDSlot(emu->to_slot); @@ -1365,17 +1333,17 @@ namespace SoD OUT_str(zone_short_name2); OUT(zone_id); OUT(zone_instance); - OUT(SuspendBuffs); - OUT(FastRegenHP); - OUT(FastRegenMana); - OUT(FastRegenEndurance); + OUT(suspend_buffs); + OUT(fast_regen_hp); + OUT(fast_regen_mana); + OUT(fast_regen_endurance); OUT(underworld_teleport_index); /*fill in some unknowns with observed values, hopefully it will help */ eq->unknown800 = -1; eq->unknown844 = 600; - OUT(LavaDamage); - OUT(MinLavaDamage); + OUT(lava_damage); + OUT(min_lava_damage); eq->unknown888 = 1; eq->unknown889 = 0; eq->unknown890 = 1; @@ -1385,8 +1353,8 @@ namespace SoD eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off eq->unknown895 = 0; eq->unknown908 = 2; - eq->unknown912 = 2; - eq->FogDensity = emu->fog_density; + eq->unknown912 = 2; + eq->fog_density = emu->fog_density; FINISH_ENCODE(); } @@ -2499,7 +2467,9 @@ namespace SoD } float SpawnSize = emu->size; - if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)) + ) { PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount); @@ -2696,7 +2666,9 @@ namespace SoD Buffer += sizeof(structs::Spawn_Struct_Position); - if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522) + ) { for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) { @@ -2721,7 +2693,9 @@ namespace SoD } - if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522) + ) { structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; @@ -3252,7 +3226,7 @@ namespace SoD DECODE_LENGTH_EXACT(structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoD::DECODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "SoD::DECODE(OP_LootItem)"); IN(lootee); IN(looter); @@ -3267,7 +3241,7 @@ namespace SoD DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoD::DECODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "SoD::DECODE(OP_MoveItem)"); emu->from_slot = SoDToServerSlot(eq->from_slot); emu->to_slot = SoDToServerSlot(eq->to_slot); @@ -3538,7 +3512,7 @@ namespace SoD void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth) { const EQ::ItemData *item = inst->GetUnscaledItem(); - + SoD::structs::ItemSerializationHeader hdr; hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); @@ -3849,7 +3823,7 @@ namespace SoD iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; iqbs.Clairvoyance = item->Clairvoyance; - + ob.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); EQ::OutBuffer::pos_type count_pos = ob.tellp(); @@ -4061,7 +4035,7 @@ namespace SoD return; } - auto segments = SplitString(server_saylink, '\x12'); + auto segments = Strings::Split(server_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -4101,7 +4075,7 @@ namespace SoD return; } - auto segments = SplitString(sod_saylink, '\x12'); + auto segments = Strings::Split(sod_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp index dc1676d5a..87acff88a 100644 --- a/common/patches/sod_limits.cpp +++ b/common/patches/sod_limits.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "sod_limits.h" -#include "../string_util.h" +#include "../strings.h" int16 SoD::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/sod_ops.h b/common/patches/sod_ops.h index c98ab5ff0..d70807cce 100644 --- a/common/patches/sod_ops.h +++ b/common/patches/sod_ops.h @@ -36,7 +36,6 @@ E(OP_Damage) E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DzChooseZone) -E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) E(OP_DzExpeditionInvite) diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 7b0e45e46..fdfb42706 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -440,35 +440,35 @@ struct NewZone_Struct { /*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version. /*0800*/ int32 unknown800; //seen -1 /*0804*/ char unknown804[40]; // -/*0844*/ int32 unknown844; //seen 600 -/*0848*/ int32 unknown848; -/*0852*/ uint16 zone_id; -/*0854*/ uint16 zone_instance; -/*0856*/ uint32 scriptNPCReceivedanItem; -/*0860*/ uint32 bCheck; // padded bool -/*0864*/ uint32 scriptIDSomething; -/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions -/*0872*/ uint32 scriptIDSomething3; -/*0876*/ uint32 SuspendBuffs; -/*0880*/ uint32 LavaDamage; //seen 50 -/*0884*/ uint32 MinLavaDamage; //seen 10 -/*0888*/ uint8 unknown888; //seen 1 -/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj) -/*0890*/ uint8 unknown890; //seen 1 -/*0891*/ uint8 unknown891; //seen 0 -/*0892*/ uint8 unknown892; //seen 0 -/*0893*/ uint8 unknown893; //seen 0 - 00 -/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off -/*0895*/ uint8 unknown895; //seen 0 - 00 -/*0896*/ uint32 FastRegenHP; //seen 180 -/*0900*/ uint32 FastRegenMana; //seen 180 -/*0904*/ uint32 FastRegenEndurance; //seen 180 -/*0908*/ uint32 unknown908; //seen 2 -/*0912*/ uint32 unknown912; //seen 2 -/*0916*/ float FogDensity; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16 -/*0920*/ uint32 unknown920; //seen 0 -/*0924*/ uint32 unknown924; //seen 0 -/*0928*/ uint32 unknown928; //seen 0 +/*0844*/ int32 unknown844; //seen 600 +/*0848*/ int32 unknown848; +/*0852*/ uint16 zone_id; +/*0854*/ uint16 zone_instance; +/*0856*/ uint32 scriptNPCReceivedanItem; +/*0860*/ uint32 bCheck; // padded bool +/*0864*/ uint32 scriptIDSomething; +/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions +/*0872*/ uint32 scriptIDSomething3; +/*0876*/ uint32 suspend_buffs; +/*0880*/ uint32 lava_damage; //seen 50 +/*0884*/ uint32 min_lava_damage; //seen 10 +/*0888*/ uint8 unknown888; //seen 1 +/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj) +/*0890*/ uint8 unknown890; //seen 1 +/*0891*/ uint8 unknown891; //seen 0 +/*0892*/ uint8 unknown892; //seen 0 +/*0893*/ uint8 unknown893; //seen 0 - 00 +/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off +/*0895*/ uint8 unknown895; //seen 0 - 00 +/*0896*/ uint32 fast_regen_hp; //seen 180 +/*0900*/ uint32 fast_regen_mana; //seen 180 +/*0904*/ uint32 fast_regen_endurance; //seen 180 +/*0908*/ uint32 unknown908; //seen 2 +/*0912*/ uint32 unknown912; //seen 2 +/*0916*/ float fog_density; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16 +/*0920*/ uint32 unknown920; //seen 0 +/*0924*/ uint32 unknown924; //seen 0 +/*0928*/ uint32 unknown928; //seen 0 /*0932*/ }; @@ -4276,7 +4276,7 @@ struct DynamicZoneCompassEntry_Struct /*000*/ uint16 dz_zone_id; // target dz id pair /*002*/ uint16 dz_instance_id; /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) -/*008*/ uint32 unknown008; +/*008*/ uint32 dz_switch_id; /*012*/ float y; /*016*/ float x; /*020*/ float z; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index ff77e788b..a1ae18505 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -28,10 +28,11 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" -#include "../string_util.h" +#include "../strings.h" #include "../item_instance.h" #include "sof_structs.h" #include "../rulesys.h" +#include "../path_manager.h" #include #include @@ -69,12 +70,7 @@ namespace SoF { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -113,12 +109,7 @@ namespace SoF //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; @@ -387,7 +378,7 @@ namespace SoF in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -445,7 +436,7 @@ namespace SoF ENCODE(OP_DeleteCharge) { - Log(Logs::Moderate, Logs::Netcode, "SoF::ENCODE(OP_DeleteCharge)"); + Log(Logs::Detail, Logs::Netcode, "SoF::ENCODE(OP_DeleteCharge)"); ENCODE_FORWARD(OP_MoveItem); } @@ -497,30 +488,6 @@ namespace SoF FINISH_ENCODE(); } - ENCODE(OP_DzCompass) - { - SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); - ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, - sizeof(structs::DynamicZoneCompass_Struct) + - sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count - ); - - OUT(client_id); - OUT(count); - - for (uint32 i = 0; i < emu->count; ++i) - { - OUT(entries[i].dz_zone_id); - OUT(entries[i].dz_instance_id); - OUT(entries[i].dz_type); - OUT(entries[i].x); - OUT(entries[i].y); - OUT(entries[i].z); - } - - FINISH_ENCODE(); - } - ENCODE(OP_DzExpeditionEndsWarning) { ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); @@ -885,7 +852,7 @@ namespace SoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - + EQ::InternalSerializedItem_Struct* int_struct = (EQ::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQ::OutBuffer ob; @@ -902,7 +869,7 @@ namespace SoF in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -956,7 +923,7 @@ namespace SoF ENCODE_LENGTH_EXACT(LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoF::ENCODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "SoF::ENCODE(OP_LootItem)"); OUT(lootee); OUT(looter); @@ -987,7 +954,7 @@ namespace SoF ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoF::ENCODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "SoF::ENCODE(OP_MoveItem)"); eq->from_slot = ServerToSoFSlot(emu->from_slot); eq->to_slot = ServerToSoFSlot(emu->to_slot); @@ -1043,17 +1010,17 @@ namespace SoF OUT_str(zone_short_name2); OUT(zone_id); OUT(zone_instance); - OUT(SuspendBuffs); - OUT(FastRegenHP); - OUT(FastRegenMana); - OUT(FastRegenEndurance); + OUT(suspend_buffs); + OUT(fast_regen_hp); + OUT(fast_regen_mana); + OUT(fast_regen_endurance); OUT(underworld_teleport_index); /*fill in some unknowns with observed values, hopefully it will help */ eq->unknown796 = -1; eq->unknown840 = 600; - OUT(LavaDamage); - OUT(MinLavaDamage); + OUT(lava_damage); + OUT(min_lava_damage); eq->unknown884 = 1; eq->unknown885 = 0; eq->unknown886 = 1; @@ -2664,7 +2631,7 @@ namespace SoF DECODE_LENGTH_EXACT(structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoF::DECODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "SoF::DECODE(OP_LootItem)"); IN(lootee); IN(looter); @@ -2679,7 +2646,7 @@ namespace SoF DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "SoF::DECODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "SoF::DECODE(OP_MoveItem)"); emu->from_slot = SoFToServerSlot(eq->from_slot); emu->to_slot = SoFToServerSlot(eq->to_slot); @@ -2936,7 +2903,7 @@ namespace SoF void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth) { const EQ::ItemData *item = inst->GetUnscaledItem(); - + SoF::structs::ItemSerializationHeader hdr; hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); @@ -3245,7 +3212,7 @@ namespace SoF iqbs.HeroicSVCorrup = item->HeroicSVCorrup; iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - + ob.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); EQ::OutBuffer::pos_type count_pos = ob.tellp(); @@ -3354,7 +3321,7 @@ namespace SoF static inline uint32 ServerToSoFCorpseSlot(uint32 server_corpse_slot) { uint32 SoFSlot = invslot::SLOT_INVALID; - + if (server_corpse_slot <= EQ::invslot::slotGeneral8 && server_corpse_slot >= EQ::invslot::slotGeneral1) { SoFSlot = server_corpse_slot; } @@ -3465,7 +3432,7 @@ namespace SoF return; } - auto segments = SplitString(server_saylink, '\x12'); + auto segments = Strings::Split(server_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -3505,7 +3472,7 @@ namespace SoF return; } - auto segments = SplitString(sof_saylink, '\x12'); + auto segments = Strings::Split(sof_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp index aa42320c8..a646991da 100644 --- a/common/patches/sof_limits.cpp +++ b/common/patches/sof_limits.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "sof_limits.h" -#include "../string_util.h" +#include "../strings.h" int16 SoF::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index 0dd34e060..b68378996 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -37,7 +37,6 @@ E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) E(OP_DzChooseZone) -E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) E(OP_DzExpeditionInvite) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 05dfba0c5..bda416d73 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -444,31 +444,31 @@ struct NewZone_Struct { /*0700*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version. /*0796*/ int32 unknown796; //seen -1 /*0800*/ char unknown800[40]; // -/*0840*/ int32 unknown840; //seen 600 -/*0844*/ int32 unknown844; -/*0848*/ uint16 zone_id; -/*0850*/ uint16 zone_instance; -/*0852*/ uint32 scriptNPCReceivedanItem; -/*0856*/ uint32 bCheck; // padded bool -/*0860*/ uint32 scriptIDSomething; -/*0864*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions -/*0868*/ uint32 scriptIDSomething3; -/*0872*/ uint32 SuspendBuffs; -/*0876*/ uint32 LavaDamage; //seen 50 -/*0880*/ uint32 MinLavaDamage; //seen 10 -/*0884*/ uint8 unknown884; //seen 1 -/*0885*/ uint8 unknown885; //seen 0 (POK) or 1 (rujj) -/*0886*/ uint8 unknown886; //seen 1 -/*0887*/ uint8 unknown887; //seen 0 -/*0888*/ uint8 unknown888; //seen 0 -/*0893*/ uint8 unknown889; //seen 0 - 00 -/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off -/*0895*/ uint8 unknown891; //seen 0 - 00 -/*0892*/ uint32 FastRegenHP; //seen 180 -/*0896*/ uint32 FastRegenMana; //seen 180 -/*0900*/ uint32 FastRegenEndurance; //seen 180 -/*0904*/ uint32 unknown904; //seen 2 -/*0908*/ uint32 unknown908; //seen 2 +/*0840*/ int32 unknown840; //seen 600 +/*0844*/ int32 unknown844; +/*0848*/ uint16 zone_id; +/*0850*/ uint16 zone_instance; +/*0852*/ uint32 scriptNPCReceivedanItem; +/*0856*/ uint32 bCheck; // padded bool +/*0860*/ uint32 scriptIDSomething; +/*0864*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions +/*0868*/ uint32 scriptIDSomething3; +/*0872*/ uint32 suspend_buffs; +/*0876*/ uint32 lava_damage; //seen 50 +/*0880*/ uint32 min_lava_damage; //seen 10 +/*0884*/ uint8 unknown884; //seen 1 +/*0885*/ uint8 unknown885; //seen 0 (POK) or 1 (rujj) +/*0886*/ uint8 unknown886; //seen 1 +/*0887*/ uint8 unknown887; //seen 0 +/*0888*/ uint8 unknown888; //seen 0 +/*0893*/ uint8 unknown889; //seen 0 - 00 +/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off +/*0895*/ uint8 unknown891; //seen 0 - 00 +/*0892*/ uint32 fast_regen_hp; //seen 180 +/*0896*/ uint32 fast_regen_mana; //seen 180 +/*0900*/ uint32 fast_regen_endurance; //seen 180 +/*0904*/ uint32 unknown904; //seen 2 +/*0908*/ uint32 unknown908; //seen 2 /*0912*/ }; @@ -4186,7 +4186,7 @@ struct DynamicZoneCompassEntry_Struct /*000*/ uint16 dz_zone_id; // target dz id pair /*002*/ uint16 dz_instance_id; /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) -/*008*/ uint32 unknown008; +/*008*/ uint32 dz_switch_id; /*012*/ float y; /*016*/ float x; /*020*/ float z; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 4c9339854..7f7aa6326 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -29,9 +29,10 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" -#include "../string_util.h" +#include "../strings.h" #include "../item_instance.h" #include "titanium_structs.h" +#include "../path_manager.h" #include @@ -69,11 +70,7 @@ namespace Titanium auto Config = EQEmuConfig::get(); //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -114,12 +111,7 @@ namespace Titanium //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; @@ -338,13 +330,13 @@ namespace Titanium SerializeItem(ob, (const EQ::ItemInstance*)eq->inst, ServerToTitaniumSlot(eq->slot_id), 0); if (ob.tellp() == last_pos) LogNetcode("Titanium::ENCODE(OP_CharInventory) Serialization failed on item slot [{}] during OP_CharInventory. Item skipped", eq->slot_id); - + last_pos = ob.tellp(); } in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -388,7 +380,7 @@ namespace Titanium ENCODE(OP_DeleteCharge) { - Log(Logs::Moderate, Logs::Netcode, "Titanium::ENCODE(OP_DeleteCharge)"); + Log(Logs::Detail, Logs::Netcode, "Titanium::ENCODE(OP_DeleteCharge)"); ENCODE_FORWARD(OP_MoveItem); } @@ -440,30 +432,6 @@ namespace Titanium FINISH_ENCODE(); } - ENCODE(OP_DzCompass) - { - SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); - ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, - sizeof(structs::DynamicZoneCompass_Struct) + - sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count - ); - - OUT(client_id); - OUT(count); - - for (uint32 i = 0; i < emu->count; ++i) - { - OUT(entries[i].dz_zone_id); - OUT(entries[i].dz_instance_id); - OUT(entries[i].dz_type); - OUT(entries[i].x); - OUT(entries[i].y); - OUT(entries[i].z); - } - - FINISH_ENCODE(); - } - ENCODE(OP_DzExpeditionEndsWarning) { ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); @@ -861,7 +829,7 @@ namespace Titanium //store away the emu struct uchar* __emu_buffer = in->pBuffer; - + EQ::InternalSerializedItem_Struct* int_struct = (EQ::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQ::OutBuffer ob; @@ -878,7 +846,7 @@ namespace Titanium in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -922,7 +890,7 @@ namespace Titanium ENCODE_LENGTH_EXACT(LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "Titanium::ENCODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "Titanium::ENCODE(OP_LootItem)"); OUT(lootee); OUT(looter); @@ -966,7 +934,7 @@ namespace Titanium ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "Titanium::ENCODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "Titanium::ENCODE(OP_MoveItem)"); eq->from_slot = ServerToTitaniumSlot(emu->from_slot); eq->to_slot = ServerToTitaniumSlot(emu->to_slot); @@ -2210,7 +2178,7 @@ namespace Titanium DECODE_LENGTH_EXACT(structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "Titanium::DECODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "Titanium::DECODE(OP_LootItem)"); IN(lootee); IN(looter); @@ -2225,7 +2193,7 @@ namespace Titanium DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "Titanium::DECODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "Titanium::DECODE(OP_MoveItem)"); emu->from_slot = TitaniumToServerSlot(eq->from_slot); emu->to_slot = TitaniumToServerSlot(eq->to_slot); @@ -2845,7 +2813,7 @@ namespace Titanium return; } - auto segments = SplitString(server_saylink, '\x12'); + auto segments = Strings::Split(server_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -2885,7 +2853,7 @@ namespace Titanium return; } - auto segments = SplitString(titanium_saylink, '\x12'); + auto segments = Strings::Split(titanium_saylink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp index 2cab723f0..76da83b63 100644 --- a/common/patches/titanium_limits.cpp +++ b/common/patches/titanium_limits.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "titanium_limits.h" -#include "../string_util.h" +#include "../strings.h" int16 Titanium::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 6f11063be..c747233fd 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -33,7 +33,6 @@ E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) E(OP_DzChooseZone) -E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) E(OP_DzExpeditionInvite) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 1220877d5..6093af656 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3396,7 +3396,7 @@ struct DynamicZoneCompassEntry_Struct /*000*/ uint16 dz_zone_id; // target dz id pair /*002*/ uint16 dz_instance_id; /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) -/*008*/ uint32 unknown008; +/*008*/ uint32 dz_switch_id; /*012*/ float y; /*016*/ float x; /*020*/ float z; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 1e33ed307..b44524723 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -28,10 +28,13 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" -#include "../string_util.h" +#include "../strings.h" #include "../item_instance.h" #include "uf_structs.h" #include "../rulesys.h" +#include "../path_manager.h" +#include "../classes.h" +#include "../races.h" #include #include @@ -69,12 +72,7 @@ namespace UF { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -115,12 +113,7 @@ namespace UF //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; @@ -527,7 +520,7 @@ namespace UF in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -586,7 +579,7 @@ namespace UF ENCODE(OP_DeleteCharge) { - Log(Logs::Moderate, Logs::Netcode, "UF::ENCODE(OP_DeleteCharge)"); + Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_DeleteCharge)"); ENCODE_FORWARD(OP_MoveItem); } @@ -639,30 +632,6 @@ namespace UF FINISH_ENCODE(); } - ENCODE(OP_DzCompass) - { - SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); - ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, - sizeof(structs::DynamicZoneCompass_Struct) + - sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count - ); - - OUT(client_id); - OUT(count); - - for (uint32 i = 0; i < emu->count; ++i) - { - OUT(entries[i].dz_zone_id); - OUT(entries[i].dz_instance_id); - OUT(entries[i].dz_type); - OUT(entries[i].x); - OUT(entries[i].y); - OUT(entries[i].z); - } - - FINISH_ENCODE(); - } - ENCODE(OP_DzExpeditionEndsWarning) { ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); @@ -1314,7 +1283,7 @@ namespace UF in->size = ob.size(); in->pBuffer = ob.detach(); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -1380,7 +1349,7 @@ namespace UF ENCODE_LENGTH_EXACT(LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "UF::ENCODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_LootItem)"); OUT(lootee); OUT(looter); @@ -1533,7 +1502,7 @@ namespace UF ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "UF::ENCODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_MoveItem)"); eq->from_slot = ServerToUFSlot(emu->from_slot); eq->to_slot = ServerToUFSlot(emu->to_slot); @@ -1589,19 +1558,19 @@ namespace UF OUT_str(zone_short_name2); OUT(zone_id); OUT(zone_instance); - OUT(SuspendBuffs); - OUT(FastRegenHP); - OUT(FastRegenMana); - OUT(FastRegenEndurance); + OUT(suspend_buffs); + OUT(fast_regen_hp); + OUT(fast_regen_mana); + OUT(fast_regen_endurance); OUT(underworld_teleport_index); - eq->FogDensity = emu->fog_density; + eq->fog_density = emu->fog_density; /*fill in some unknowns with observed values, hopefully it will help */ eq->unknown800 = -1; eq->unknown844 = 600; - OUT(LavaDamage); - OUT(MinLavaDamage); + OUT(lava_damage); + OUT(min_lava_damage); eq->unknown888 = 1; eq->unknown889 = 0; eq->unknown890 = 1; @@ -1741,7 +1710,7 @@ namespace UF OUT(WIS); OUT(face); // OUT(unknown02264[47]); - + if (spells::SPELLBOOK_SIZE <= EQ::spells::SPELLBOOK_SIZE) { for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) { if (emu->spell_book[r] <= spells::SPELL_ID_MAX) @@ -2122,7 +2091,7 @@ namespace UF eq->aa_expansion = emu->expansion; eq->special_category = emu->category; eq->total_abilities = emu->total_effects; - + for(auto i = 0; i < eq->total_abilities; ++i) { eq->abilities[i].skill_id = inapp->ReadUInt32(); eq->abilities[i].base_value = inapp->ReadUInt32(); @@ -2749,7 +2718,7 @@ namespace UF if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; - if (emu->DestructibleObject || emu->class_ == 62) + if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) { if (emu->DestructibleObject) PacketSize = PacketSize - 4; // No bodytype @@ -2770,7 +2739,9 @@ namespace UF } float SpawnSize = emu->size; - if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)) + ) { PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount); @@ -2836,18 +2807,20 @@ namespace UF uint8 OtherData = 0; - if (emu->class_ == 62) //Ldon chest + if (emu->class_ == LDON_TREASURE) //Ldon chest + { OtherData = OtherData | 0x01; + } - if (strlen(emu->title)) + if (strlen(emu->title)) { OtherData = OtherData | 0x04; - - if (strlen(emu->suffix)) + } + if (strlen(emu->suffix)) { OtherData = OtherData | 0x08; - - if (emu->DestructibleObject) + } + if (emu->DestructibleObject) { OtherData = OtherData | 0xd1; // Live has 0xe1 for OtherData - + } VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); if (emu->DestructibleObject) @@ -2860,7 +2833,7 @@ namespace UF } VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - if (emu->DestructibleObject || emu->class_ == 62) + if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) { VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); @@ -2969,7 +2942,9 @@ namespace UF Buffer += sizeof(structs::Spawn_Struct_Position); - if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522) + ) { for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) { @@ -3003,7 +2978,9 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } - if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || + (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522) + ) { structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; @@ -3607,7 +3584,7 @@ namespace UF DECODE_LENGTH_EXACT(structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "UF::DECODE(OP_LootItem)"); + Log(Logs::Detail, Logs::Netcode, "UF::DECODE(OP_LootItem)"); IN(lootee); IN(looter); @@ -3622,7 +3599,7 @@ namespace UF DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log(Logs::Moderate, Logs::Netcode, "UF::DECODE(OP_MoveItem)"); + Log(Logs::Detail, Logs::Netcode, "UF::DECODE(OP_MoveItem)"); emu->from_slot = UFToServerSlot(eq->from_slot); emu->to_slot = UFToServerSlot(eq->to_slot); @@ -3835,7 +3812,7 @@ namespace UF void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth) { const EQ::ItemData *item = inst->GetUnscaledItem(); - + UF::structs::ItemSerializationHeader hdr; hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 1000) ? 0xFFFFFFFF : inst->GetCharges()) : 1); @@ -4420,7 +4397,7 @@ namespace UF return; } - auto segments = SplitString(serverSayLink, '\x12'); + auto segments = Strings::Split(serverSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -4460,7 +4437,7 @@ namespace UF return; } - auto segments = SplitString(ufSayLink, '\x12'); + auto segments = Strings::Split(ufSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp index 7cf5ec63e..f0083d086 100644 --- a/common/patches/uf_limits.cpp +++ b/common/patches/uf_limits.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "uf_limits.h" -#include "../string_util.h" +#include "../strings.h" int16 UF::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/uf_ops.h b/common/patches/uf_ops.h index 5d728f067..498b4f33d 100644 --- a/common/patches/uf_ops.h +++ b/common/patches/uf_ops.h @@ -39,7 +39,6 @@ E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DisciplineUpdate) E(OP_DzChooseZone) -E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) E(OP_DzExpeditionInvite) diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index a4b5b510c..86d6034f0 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -440,35 +440,35 @@ struct NewZone_Struct { /*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version. /*0800*/ int32 unknown800; //seen -1 /*0804*/ char unknown804[40]; // -/*0844*/ int32 unknown844; //seen 600 -/*0848*/ int32 unknown848; -/*0852*/ uint16 zone_id; -/*0854*/ uint16 zone_instance; -/*0856*/ uint32 scriptNPCReceivedanItem; -/*0860*/ uint32 bCheck; // padded bool -/*0864*/ uint32 scriptIDSomething; -/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions -/*0872*/ uint32 scriptIDSomething3; -/*0876*/ uint32 SuspendBuffs; -/*0880*/ uint32 LavaDamage; //seen 50 -/*0884*/ uint32 MinLavaDamage; //seen 10 -/*0888*/ uint8 unknown888; //seen 1 -/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj) -/*0890*/ uint8 unknown890; //seen 1 -/*0891*/ uint8 unknown891; //seen 0 -/*0892*/ uint8 unknown892; //seen 0 -/*0893*/ uint8 unknown893; //seen 0 - 00 -/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off -/*0895*/ uint8 unknown895; //seen 0 - 00 -/*0896*/ uint32 FastRegenHP; //seen 180 -/*0900*/ uint32 FastRegenMana; //seen 180 -/*0904*/ uint32 FastRegenEndurance; //seen 180 -/*0908*/ uint32 unknown908; //seen 2 -/*0912*/ uint32 unknown912; //seen 2 -/*0916*/ float FogDensity; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16 -/*0920*/ uint32 unknown920; //seen 0 -/*0924*/ uint32 unknown924; //seen 0 -/*0928*/ uint32 unknown928; //seen 0 +/*0844*/ int32 unknown844; //seen 600 +/*0848*/ int32 unknown848; +/*0852*/ uint16 zone_id; +/*0854*/ uint16 zone_instance; +/*0856*/ uint32 scriptNPCReceivedanItem; +/*0860*/ uint32 bCheck; // padded bool +/*0864*/ uint32 scriptIDSomething; +/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions +/*0872*/ uint32 scriptIDSomething3; +/*0876*/ uint32 suspend_buffs; +/*0880*/ uint32 lava_damage; //seen 50 +/*0884*/ uint32 min_lava_damage; //seen 10 +/*0888*/ uint8 unknown888; //seen 1 +/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj) +/*0890*/ uint8 unknown890; //seen 1 +/*0891*/ uint8 unknown891; //seen 0 +/*0892*/ uint8 unknown892; //seen 0 +/*0893*/ uint8 unknown893; //seen 0 - 00 +/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off +/*0895*/ uint8 unknown895; //seen 0 - 00 +/*0896*/ uint32 fast_regen_hp; //seen 180 +/*0900*/ uint32 fast_regen_mana; //seen 180 +/*0904*/ uint32 fast_regen_endurance; //seen 180 +/*0908*/ uint32 unknown908; //seen 2 +/*0912*/ uint32 unknown912; //seen 2 +/*0916*/ float fog_density; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16 +/*0920*/ uint32 unknown920; //seen 0 +/*0924*/ uint32 unknown924; //seen 0 +/*0928*/ uint32 unknown928; //seen 0 /*0932*/ uint8 unknown932[12]; }; @@ -3997,7 +3997,7 @@ struct ItemSerializationHeaderFinish { uint16 ornamentIcon; /*060*/ uint8 unknown060; //0 - /*061*/ uint8 unknown061; //0 - + /*061*/ uint8 unknown061; //0 - /*062*/ uint8 isCopied; // New to Underfoot // Copied flag on item /*063*/ uint8 ItemClass; //0, 1, or 2 }; @@ -4357,7 +4357,7 @@ struct DynamicZoneCompassEntry_Struct /*000*/ uint16 dz_zone_id; // target dz id pair /*002*/ uint16 dz_instance_id; /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) -/*008*/ uint32 unknown008; +/*008*/ uint32 dz_switch_id; /*012*/ float y; /*016*/ float x; /*020*/ float z; diff --git a/common/path_manager.cpp b/common/path_manager.cpp new file mode 100644 index 000000000..fba5f777a --- /dev/null +++ b/common/path_manager.cpp @@ -0,0 +1,140 @@ +#include "path_manager.h" +#include "file.h" +#include "eqemu_logsys.h" +#include "eqemu_config.h" +#include "strings.h" + +#include +namespace fs = std::filesystem; + +inline std::string striptrailingslash(const std::string &file_path) +{ + if (file_path.back() == '/' || file_path.back() == '\\') { + return file_path.substr(0, file_path.length() - 1); + } + + return file_path; +} + +void PathManager::LoadPaths() +{ + m_server_path = File::FindEqemuConfigPath(); + + if (!m_server_path.empty()) { + std::filesystem::current_path(m_server_path); + } + + if (m_server_path.empty()) { + LogInfo("Failed to load server path"); + return; + } + + LogInfo("server [{}]", m_server_path); + + if (!EQEmuConfig::LoadConfig()) { + LogError("Failed to load eqemu config"); + return; + } + + const auto c = EQEmuConfig::get(); + + // maps + if (File::Exists(fs::path{m_server_path + "/" + c->MapDir}.string())) { + m_maps_path = fs::relative(fs::path{m_server_path + "/" + c->MapDir}).string(); + } + else if (File::Exists(fs::path{m_server_path + "/maps"}.string())) { + m_maps_path = fs::relative(fs::path{m_server_path + "/maps"}).string(); + } + else if (File::Exists(fs::path{m_server_path + "/Maps"}.string())) { + m_maps_path = fs::relative(fs::path{m_server_path + "/Maps"}).string(); + } + + // quests + if (File::Exists(fs::path{m_server_path + "/" + c->QuestDir}.string())) { + m_quests_path = fs::relative(fs::path{m_server_path + "/" + c->QuestDir}).string(); + } + + // plugins + if (File::Exists(fs::path{m_server_path + "/" + c->PluginDir}.string())) { + m_plugins_path = fs::relative(fs::path{m_server_path + "/" + c->PluginDir}).string(); + } + + // lua_modules + if (File::Exists(fs::path{m_server_path + "/" + c->LuaModuleDir}.string())) { + m_lua_modules_path = fs::relative(fs::path{m_server_path + "/" + c->LuaModuleDir}).string(); + } + + // lua mods + if (File::Exists(fs::path{ m_server_path + "/mods" }.string())) { + m_lua_mods_path = fs::relative(fs::path{ m_server_path + "/mods" }).string(); + } + + // patches + if (File::Exists(fs::path{m_server_path + "/" + c->PatchDir}.string())) { + m_patch_path = fs::relative(fs::path{m_server_path + "/" + c->PatchDir}).string(); + } + + // shared_memory_path + if (File::Exists(fs::path{m_server_path + "/" + c->SharedMemDir}.string())) { + m_shared_memory_path = fs::relative(fs::path{ m_server_path + "/" + c->SharedMemDir }).string(); + } + + // logging path + if (File::Exists(fs::path{m_server_path + "/" + c->LogDir}.string())) { + m_log_path = fs::relative(fs::path{m_server_path + "/" + c->LogDir}).string(); + } + + LogInfo("logs path [{}]", m_log_path); + LogInfo("lua mods path [{}]", m_lua_mods_path); + LogInfo("lua_modules path [{}]", m_lua_modules_path); + LogInfo("maps path [{}]", m_maps_path); + LogInfo("patches path [{}]", m_patch_path); + LogInfo("plugins path [{}]", m_plugins_path); + LogInfo("quests path [{}]", m_quests_path); + LogInfo("shared_memory path [{}]", m_shared_memory_path); +} + +const std::string &PathManager::GetServerPath() const +{ + return m_server_path; +} + +const std::string &PathManager::GetMapsPath() const +{ + return m_maps_path; +} + +const std::string &PathManager::GetQuestsPath() const +{ + return m_quests_path; +} + +const std::string &PathManager::GetPluginsPath() const +{ + return m_plugins_path; +} + +const std::string &PathManager::GetSharedMemoryPath() const +{ + return m_shared_memory_path; +} + +const std::string &PathManager::GetLogPath() const +{ + return m_log_path; +} + +const std::string &PathManager::GetPatchPath() const +{ + return m_patch_path; +} + +const std::string &PathManager::GetLuaModulesPath() const +{ + return m_lua_modules_path; +} + +const std::string &PathManager::GetLuaModsPath() const +{ + return m_lua_mods_path; +} diff --git a/common/path_manager.h b/common/path_manager.h new file mode 100644 index 000000000..4283dbf64 --- /dev/null +++ b/common/path_manager.h @@ -0,0 +1,35 @@ +#ifndef EQEMU_PATH_MANAGER_H +#define EQEMU_PATH_MANAGER_H + + +#include + +class PathManager { +public: + void LoadPaths(); + + [[nodiscard]] const std::string &GetLogPath() const; + [[nodiscard]] const std::string &GetLuaModsPath() const; + [[nodiscard]] const std::string &GetLuaModulesPath() const; + [[nodiscard]] const std::string &GetMapsPath() const; + [[nodiscard]] const std::string &GetPatchPath() const; + [[nodiscard]] const std::string &GetPluginsPath() const; + [[nodiscard]] const std::string &GetQuestsPath() const; + [[nodiscard]] const std::string &GetServerPath() const; + [[nodiscard]] const std::string &GetSharedMemoryPath() const; + +private: + std::string m_log_path; + std::string m_lua_mods_path; + std::string m_lua_modules_path; + std::string m_maps_path; + std::string m_patch_path; + std::string m_plugins_path; + std::string m_quests_path; + std::string m_server_path; + std::string m_shared_memory_path; +}; + +extern PathManager path; + +#endif //EQEMU_PATH_MANAGER_H diff --git a/common/platform.cpp b/common/platform.cpp index e5481c339..b126e6d33 100644 --- a/common/platform.cpp +++ b/common/platform.cpp @@ -55,18 +55,18 @@ std::string GetPlatformName() return "UCS"; case EQEmuExePlatform::ExePlatformLogin: return "Login"; - case EQEmuExePlatform::ExePlatformSocket_Server: - return "SocketServer"; case EQEmuExePlatform::ExePlatformSharedMemory: - return "SharedMemory"; + return "SharedMem"; case EQEmuExePlatform::ExePlatformClientImport: - return "ClientImport"; + return "Import"; case EQEmuExePlatform::ExePlatformClientExport: - return "ClientExport"; + return "Export"; case EQEmuExePlatform::ExePlatformLaunch: return "Launch"; case EQEmuExePlatform::ExePlatformHC: return "HC"; + case EQEmuExePlatform::ExePlatformTests: + return "Tests"; default: return ""; } diff --git a/common/platform.h b/common/platform.h index bd24a1493..a69738ff6 100644 --- a/common/platform.h +++ b/common/platform.h @@ -36,7 +36,8 @@ enum EQEmuExePlatform ExePlatformSharedMemory, ExePlatformClientImport, ExePlatformClientExport, - ExePlatformHC + ExePlatformHC, + ExePlatformTests }; void RegisterExecutablePlatform(EQEmuExePlatform p); diff --git a/common/process/process.cpp b/common/process/process.cpp new file mode 100644 index 000000000..926c9700b --- /dev/null +++ b/common/process/process.cpp @@ -0,0 +1,18 @@ +#include +#include +#include "process.h" + +std::string Process::execute(const std::string &cmd) +{ + std::shared_ptr pipe(popen(cmd.c_str(), "r"), pclose); + if (!pipe) { return "ERROR"; } + char buffer[128]; + std::string result; + while (!feof(pipe.get())) { + if (fgets(buffer, 128, pipe.get()) != nullptr) { + result += buffer; + } + } + + return result; +} diff --git a/common/process/process.h b/common/process/process.h new file mode 100644 index 000000000..34dbb27c6 --- /dev/null +++ b/common/process/process.h @@ -0,0 +1,19 @@ +#ifndef EQEMU_PROCESS_H +#define EQEMU_PROCESS_H + +#include "../strings.h" + +#include + +#if _WIN32 +#define popen _popen +#define pclose _pclose +#endif + +class Process { +public: + static std::string execute(const std::string &cmd); +}; + + +#endif //EQEMU_PROCESS_H diff --git a/common/profanity_manager.cpp b/common/profanity_manager.cpp index 5b5cbea07..98a9cc73c 100644 --- a/common/profanity_manager.cpp +++ b/common/profanity_manager.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2019 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -11,15 +11,16 @@ are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "profanity_manager.h" +#include "eqemu_logsys.h" #include "dbcore.h" -#include "string_util.h" +#include "strings.h" #include #include @@ -66,7 +67,7 @@ bool EQ::ProfanityManager::AddProfanity(DBcore *db, std::string profanity) { return false; } - std::string entry = str_tolower(profanity); + std::string entry = Strings::ToLower(profanity); if (check_for_existing_entry(entry)) { return true; @@ -98,7 +99,7 @@ bool EQ::ProfanityManager::RemoveProfanity(DBcore *db, std::string profanity) { return false; } - std::string entry = str_tolower(profanity); + std::string entry = Strings::ToLower(profanity); if (!check_for_existing_entry(entry)) { return true; @@ -126,13 +127,13 @@ void EQ::ProfanityManager::RedactMessage(char *message) { return; } - std::string test_message = str_tolower(message); + std::string test_message = Strings::ToLower(message); // hard-coded max length based on channel message buffer size (4096 bytes).. // ..will need to change or remove if other sources are used for redaction if (test_message.length() < REDACTION_LENGTH_MIN || test_message.length() >= 4096) { return; } - + for (const auto &iter : profanity_list) { // consider adding textlink checks if it becomes an issue size_t pos = 0; size_t start_pos = 0; @@ -162,7 +163,7 @@ void EQ::ProfanityManager::RedactMessage(std::string &message) { return; } - std::string test_message = str_tolower(message); + std::string test_message = Strings::ToLower(message); for (const auto &iter : profanity_list) { size_t pos = 0; @@ -194,7 +195,7 @@ bool EQ::ProfanityManager::ContainsCensoredLanguage(const std::string &message) return false; } - std::string test_message = str_tolower(message); + std::string test_message = Strings::ToLower(message); for (const auto &iter : profanity_list) { if (test_message.find(iter) != std::string::npos) { @@ -227,14 +228,16 @@ bool EQ::ProfanityManager::load_database_entries(DBcore *db) { } for (auto row : results) { - std::string entry = str_tolower(row[0]); - if (entry.length() >= REDACTION_LENGTH_MIN) { + std::string entry = Strings::ToLower(row[0]); + if (entry.length() >= REDACTION_LENGTH_MIN) { if (!check_for_existing_entry(entry)) { profanity_list.push_back(entry); } } } + LogInfo("Loaded [{}] profanity entries", Strings::Commify(profanity_list.size())); + return true; } @@ -265,6 +268,6 @@ bool EQ::ProfanityManager::check_for_existing_entry(std::string profanity) { return true; } } - + return false; } diff --git a/common/ptimer.cpp b/common/ptimer.cpp index e6338bdf9..e5e5f438e 100644 --- a/common/ptimer.cpp +++ b/common/ptimer.cpp @@ -21,7 +21,7 @@ #include "timer.h" #include "ptimer.h" #include "database.h" -#include "string_util.h" +#include "strings.h" #ifdef _WINDOWS #include diff --git a/common/races.h b/common/races.h index 68e6fa061..3373c8353 100644 --- a/common/races.h +++ b/common/races.h @@ -1612,6 +1612,7 @@ namespace PlayerAppearance #define RACE_LUCLIN_731 731 #define RACE_PEGASUS_732 732 #define RACE_INTERACTIVE_OBJECT_2250 2250 +#define RACE_NODE_2254 2254 #endif diff --git a/common/repositories/aa_ability_repository.h b/common/repositories/aa_ability_repository.h index cf452a7d0..59bc165e4 100644 --- a/common/repositories/aa_ability_repository.h +++ b/common/repositories/aa_ability_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_AA_ABILITY_REPOSITORY_H #define EQEMU_AA_ABILITY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_aa_ability_repository.h" class AaAbilityRepository: public BaseAaAbilityRepository { diff --git a/common/repositories/aa_rank_effects_repository.h b/common/repositories/aa_rank_effects_repository.h index 7242e8f4a..ebec6814c 100644 --- a/common/repositories/aa_rank_effects_repository.h +++ b/common/repositories/aa_rank_effects_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_AA_RANK_EFFECTS_REPOSITORY_H #define EQEMU_AA_RANK_EFFECTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_aa_rank_effects_repository.h" class AaRankEffectsRepository: public BaseAaRankEffectsRepository { diff --git a/common/repositories/aa_rank_prereqs_repository.h b/common/repositories/aa_rank_prereqs_repository.h index cf0055870..76dbeea01 100644 --- a/common/repositories/aa_rank_prereqs_repository.h +++ b/common/repositories/aa_rank_prereqs_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_AA_RANK_PREREQS_REPOSITORY_H #define EQEMU_AA_RANK_PREREQS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_aa_rank_prereqs_repository.h" class AaRankPrereqsRepository: public BaseAaRankPrereqsRepository { diff --git a/common/repositories/aa_ranks_repository.h b/common/repositories/aa_ranks_repository.h index 64ac64c84..170548cad 100644 --- a/common/repositories/aa_ranks_repository.h +++ b/common/repositories/aa_ranks_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_AA_RANKS_REPOSITORY_H #define EQEMU_AA_RANKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_aa_ranks_repository.h" class AaRanksRepository: public BaseAaRanksRepository { diff --git a/common/repositories/account_flags_repository.h b/common/repositories/account_flags_repository.h index 12614e860..e1ebb32f4 100644 --- a/common/repositories/account_flags_repository.h +++ b/common/repositories/account_flags_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ACCOUNT_FLAGS_REPOSITORY_H #define EQEMU_ACCOUNT_FLAGS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_account_flags_repository.h" class AccountFlagsRepository: public BaseAccountFlagsRepository { diff --git a/common/repositories/account_ip_repository.h b/common/repositories/account_ip_repository.h index 50f10f168..d7278708b 100644 --- a/common/repositories/account_ip_repository.h +++ b/common/repositories/account_ip_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ACCOUNT_IP_REPOSITORY_H #define EQEMU_ACCOUNT_IP_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_account_ip_repository.h" class AccountIpRepository: public BaseAccountIpRepository { diff --git a/common/repositories/account_repository.h b/common/repositories/account_repository.h index 433be1b44..83d221911 100644 --- a/common/repositories/account_repository.h +++ b/common/repositories/account_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ACCOUNT_REPOSITORY_H #define EQEMU_ACCOUNT_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_account_repository.h" class AccountRepository: public BaseAccountRepository { diff --git a/common/repositories/account_rewards_repository.h b/common/repositories/account_rewards_repository.h index 16e1a1a19..3db8f653a 100644 --- a/common/repositories/account_rewards_repository.h +++ b/common/repositories/account_rewards_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ACCOUNT_REWARDS_REPOSITORY_H #define EQEMU_ACCOUNT_REWARDS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_account_rewards_repository.h" class AccountRewardsRepository: public BaseAccountRewardsRepository { diff --git a/common/repositories/adventure_details_repository.h b/common/repositories/adventure_details_repository.h index c616ccf0d..c81ac5cc3 100644 --- a/common/repositories/adventure_details_repository.h +++ b/common/repositories/adventure_details_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ADVENTURE_DETAILS_REPOSITORY_H #define EQEMU_ADVENTURE_DETAILS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_adventure_details_repository.h" class AdventureDetailsRepository: public BaseAdventureDetailsRepository { diff --git a/common/repositories/adventure_members_repository.h b/common/repositories/adventure_members_repository.h index 84a18c14a..d430d8eb2 100644 --- a/common/repositories/adventure_members_repository.h +++ b/common/repositories/adventure_members_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ADVENTURE_MEMBERS_REPOSITORY_H #define EQEMU_ADVENTURE_MEMBERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_adventure_members_repository.h" class AdventureMembersRepository: public BaseAdventureMembersRepository { diff --git a/common/repositories/adventure_stats_repository.h b/common/repositories/adventure_stats_repository.h index 6ad1c3fe6..6fe223e88 100644 --- a/common/repositories/adventure_stats_repository.h +++ b/common/repositories/adventure_stats_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ADVENTURE_STATS_REPOSITORY_H #define EQEMU_ADVENTURE_STATS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_adventure_stats_repository.h" class AdventureStatsRepository: public BaseAdventureStatsRepository { diff --git a/common/repositories/adventure_template_entry_flavor_repository.h b/common/repositories/adventure_template_entry_flavor_repository.h index 8d9ae5406..c0d1d63c9 100644 --- a/common/repositories/adventure_template_entry_flavor_repository.h +++ b/common/repositories/adventure_template_entry_flavor_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H #define EQEMU_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_adventure_template_entry_flavor_repository.h" class AdventureTemplateEntryFlavorRepository: public BaseAdventureTemplateEntryFlavorRepository { diff --git a/common/repositories/adventure_template_entry_repository.h b/common/repositories/adventure_template_entry_repository.h index 756ddf417..95db9f229 100644 --- a/common/repositories/adventure_template_entry_repository.h +++ b/common/repositories/adventure_template_entry_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H #define EQEMU_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_adventure_template_entry_repository.h" class AdventureTemplateEntryRepository: public BaseAdventureTemplateEntryRepository { diff --git a/common/repositories/adventure_template_repository.h b/common/repositories/adventure_template_repository.h index b284670ee..39c8699b7 100644 --- a/common/repositories/adventure_template_repository.h +++ b/common/repositories/adventure_template_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ADVENTURE_TEMPLATE_REPOSITORY_H #define EQEMU_ADVENTURE_TEMPLATE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_adventure_template_repository.h" class AdventureTemplateRepository: public BaseAdventureTemplateRepository { diff --git a/common/repositories/alternate_currency_repository.h b/common/repositories/alternate_currency_repository.h index 05b21a755..cd2a95f52 100644 --- a/common/repositories/alternate_currency_repository.h +++ b/common/repositories/alternate_currency_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ALTERNATE_CURRENCY_REPOSITORY_H #define EQEMU_ALTERNATE_CURRENCY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_alternate_currency_repository.h" class AlternateCurrencyRepository: public BaseAlternateCurrencyRepository { diff --git a/common/repositories/auras_repository.h b/common/repositories/auras_repository.h index bacfd0be9..7d97503fb 100644 --- a/common/repositories/auras_repository.h +++ b/common/repositories/auras_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_AURAS_REPOSITORY_H #define EQEMU_AURAS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_auras_repository.h" class AurasRepository: public BaseAurasRepository { diff --git a/common/repositories/base/base_aa_ability_repository.h b/common/repositories/base/base_aa_ability_repository.h index 40a8e2f18..293087871 100644 --- a/common/repositories/base/base_aa_ability_repository.h +++ b/common/repositories/base/base_aa_ability_repository.h @@ -13,26 +13,26 @@ #define EQEMU_BASE_AA_ABILITY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAaAbilityRepository { public: struct AaAbility { - int id; + uint32_t id; std::string name; - int category; - int classes; - int races; - int drakkin_heritage; - int deities; - int status; - int type; - int charges; - int grant_only; - int first_rank_id; - int enabled; - int reset_on_death; + int32_t category; + int32_t classes; + int32_t races; + int32_t drakkin_heritage; + int32_t deities; + int32_t status; + int32_t type; + int32_t charges; + int8_t grant_only; + int32_t first_rank_id; + uint8_t enabled; + int8_t reset_on_death; }; static std::string PrimaryKey() @@ -82,12 +82,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -115,27 +115,27 @@ public: static AaAbility NewEntity() { - AaAbility entry{}; + AaAbility e{}; - entry.id = 0; - entry.name = ""; - entry.category = -1; - entry.classes = 131070; - entry.races = 65535; - entry.drakkin_heritage = 127; - entry.deities = 131071; - entry.status = 0; - entry.type = 0; - entry.charges = 0; - entry.grant_only = 0; - entry.first_rank_id = -1; - entry.enabled = 1; - entry.reset_on_death = 0; + e.id = 0; + e.name = ""; + e.category = -1; + e.classes = 131070; + e.races = 65535; + e.drakkin_heritage = 127; + e.deities = 131071; + e.status = 0; + e.type = 0; + e.charges = 0; + e.grant_only = 0; + e.first_rank_id = -1; + e.enabled = 1; + e.reset_on_death = 0; - return entry; + return e; } - static AaAbility GetAaAbilityEntry( + static AaAbility GetAaAbility( const std::vector &aa_abilitys, int aa_ability_id ) @@ -164,24 +164,24 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AaAbility entry{}; + AaAbility e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.category = atoi(row[2]); - entry.classes = atoi(row[3]); - entry.races = atoi(row[4]); - entry.drakkin_heritage = atoi(row[5]); - entry.deities = atoi(row[6]); - entry.status = atoi(row[7]); - entry.type = atoi(row[8]); - entry.charges = atoi(row[9]); - entry.grant_only = atoi(row[10]); - entry.first_rank_id = atoi(row[11]); - entry.enabled = atoi(row[12]); - entry.reset_on_death = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.category = static_cast(atoi(row[2])); + e.classes = static_cast(atoi(row[3])); + e.races = static_cast(atoi(row[4])); + e.drakkin_heritage = static_cast(atoi(row[5])); + e.deities = static_cast(atoi(row[6])); + e.status = static_cast(atoi(row[7])); + e.type = static_cast(atoi(row[8])); + e.charges = static_cast(atoi(row[9])); + e.grant_only = static_cast(atoi(row[10])); + e.first_rank_id = static_cast(atoi(row[11])); + e.enabled = static_cast(strtoul(row[12], nullptr, 10)); + e.reset_on_death = static_cast(atoi(row[13])); - return entry; + return e; } return NewEntity(); @@ -206,35 +206,35 @@ public: static int UpdateOne( Database& db, - AaAbility aa_ability_entry + const AaAbility &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(aa_ability_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(aa_ability_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(aa_ability_entry.category)); - update_values.push_back(columns[3] + " = " + std::to_string(aa_ability_entry.classes)); - update_values.push_back(columns[4] + " = " + std::to_string(aa_ability_entry.races)); - update_values.push_back(columns[5] + " = " + std::to_string(aa_ability_entry.drakkin_heritage)); - update_values.push_back(columns[6] + " = " + std::to_string(aa_ability_entry.deities)); - update_values.push_back(columns[7] + " = " + std::to_string(aa_ability_entry.status)); - update_values.push_back(columns[8] + " = " + std::to_string(aa_ability_entry.type)); - update_values.push_back(columns[9] + " = " + std::to_string(aa_ability_entry.charges)); - update_values.push_back(columns[10] + " = " + std::to_string(aa_ability_entry.grant_only)); - update_values.push_back(columns[11] + " = " + std::to_string(aa_ability_entry.first_rank_id)); - update_values.push_back(columns[12] + " = " + std::to_string(aa_ability_entry.enabled)); - update_values.push_back(columns[13] + " = " + std::to_string(aa_ability_entry.reset_on_death)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.category)); + v.push_back(columns[3] + " = " + std::to_string(e.classes)); + v.push_back(columns[4] + " = " + std::to_string(e.races)); + v.push_back(columns[5] + " = " + std::to_string(e.drakkin_heritage)); + v.push_back(columns[6] + " = " + std::to_string(e.deities)); + v.push_back(columns[7] + " = " + std::to_string(e.status)); + v.push_back(columns[8] + " = " + std::to_string(e.type)); + v.push_back(columns[9] + " = " + std::to_string(e.charges)); + v.push_back(columns[10] + " = " + std::to_string(e.grant_only)); + v.push_back(columns[11] + " = " + std::to_string(e.first_rank_id)); + v.push_back(columns[12] + " = " + std::to_string(e.enabled)); + v.push_back(columns[13] + " = " + std::to_string(e.reset_on_death)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - aa_ability_entry.id + e.id ) ); @@ -243,79 +243,79 @@ public: static AaAbility InsertOne( Database& db, - AaAbility aa_ability_entry + AaAbility e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(aa_ability_entry.id)); - insert_values.push_back("'" + EscapeString(aa_ability_entry.name) + "'"); - insert_values.push_back(std::to_string(aa_ability_entry.category)); - insert_values.push_back(std::to_string(aa_ability_entry.classes)); - insert_values.push_back(std::to_string(aa_ability_entry.races)); - insert_values.push_back(std::to_string(aa_ability_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(aa_ability_entry.deities)); - insert_values.push_back(std::to_string(aa_ability_entry.status)); - insert_values.push_back(std::to_string(aa_ability_entry.type)); - insert_values.push_back(std::to_string(aa_ability_entry.charges)); - insert_values.push_back(std::to_string(aa_ability_entry.grant_only)); - insert_values.push_back(std::to_string(aa_ability_entry.first_rank_id)); - insert_values.push_back(std::to_string(aa_ability_entry.enabled)); - insert_values.push_back(std::to_string(aa_ability_entry.reset_on_death)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.category)); + v.push_back(std::to_string(e.classes)); + v.push_back(std::to_string(e.races)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.deities)); + v.push_back(std::to_string(e.status)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.grant_only)); + v.push_back(std::to_string(e.first_rank_id)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.reset_on_death)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - aa_ability_entry.id = results.LastInsertedID(); - return aa_ability_entry; + e.id = results.LastInsertedID(); + return e; } - aa_ability_entry = NewEntity(); + e = NewEntity(); - return aa_ability_entry; + return e; } static int InsertMany( Database& db, - std::vector aa_ability_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &aa_ability_entry: aa_ability_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(aa_ability_entry.id)); - insert_values.push_back("'" + EscapeString(aa_ability_entry.name) + "'"); - insert_values.push_back(std::to_string(aa_ability_entry.category)); - insert_values.push_back(std::to_string(aa_ability_entry.classes)); - insert_values.push_back(std::to_string(aa_ability_entry.races)); - insert_values.push_back(std::to_string(aa_ability_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(aa_ability_entry.deities)); - insert_values.push_back(std::to_string(aa_ability_entry.status)); - insert_values.push_back(std::to_string(aa_ability_entry.type)); - insert_values.push_back(std::to_string(aa_ability_entry.charges)); - insert_values.push_back(std::to_string(aa_ability_entry.grant_only)); - insert_values.push_back(std::to_string(aa_ability_entry.first_rank_id)); - insert_values.push_back(std::to_string(aa_ability_entry.enabled)); - insert_values.push_back(std::to_string(aa_ability_entry.reset_on_death)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.category)); + v.push_back(std::to_string(e.classes)); + v.push_back(std::to_string(e.races)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.deities)); + v.push_back(std::to_string(e.status)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.grant_only)); + v.push_back(std::to_string(e.first_rank_id)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.reset_on_death)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -336,30 +336,30 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaAbility entry{}; + AaAbility e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.category = atoi(row[2]); - entry.classes = atoi(row[3]); - entry.races = atoi(row[4]); - entry.drakkin_heritage = atoi(row[5]); - entry.deities = atoi(row[6]); - entry.status = atoi(row[7]); - entry.type = atoi(row[8]); - entry.charges = atoi(row[9]); - entry.grant_only = atoi(row[10]); - entry.first_rank_id = atoi(row[11]); - entry.enabled = atoi(row[12]); - entry.reset_on_death = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.category = static_cast(atoi(row[2])); + e.classes = static_cast(atoi(row[3])); + e.races = static_cast(atoi(row[4])); + e.drakkin_heritage = static_cast(atoi(row[5])); + e.deities = static_cast(atoi(row[6])); + e.status = static_cast(atoi(row[7])); + e.type = static_cast(atoi(row[8])); + e.charges = static_cast(atoi(row[9])); + e.grant_only = static_cast(atoi(row[10])); + e.first_rank_id = static_cast(atoi(row[11])); + e.enabled = static_cast(strtoul(row[12], nullptr, 10)); + e.reset_on_death = static_cast(atoi(row[13])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -374,30 +374,30 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaAbility entry{}; + AaAbility e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.category = atoi(row[2]); - entry.classes = atoi(row[3]); - entry.races = atoi(row[4]); - entry.drakkin_heritage = atoi(row[5]); - entry.deities = atoi(row[6]); - entry.status = atoi(row[7]); - entry.type = atoi(row[8]); - entry.charges = atoi(row[9]); - entry.grant_only = atoi(row[10]); - entry.first_rank_id = atoi(row[11]); - entry.enabled = atoi(row[12]); - entry.reset_on_death = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.category = static_cast(atoi(row[2])); + e.classes = static_cast(atoi(row[3])); + e.races = static_cast(atoi(row[4])); + e.drakkin_heritage = static_cast(atoi(row[5])); + e.deities = static_cast(atoi(row[6])); + e.status = static_cast(atoi(row[7])); + e.type = static_cast(atoi(row[8])); + e.charges = static_cast(atoi(row[9])); + e.grant_only = static_cast(atoi(row[10])); + e.first_rank_id = static_cast(atoi(row[11])); + e.enabled = static_cast(strtoul(row[12], nullptr, 10)); + e.reset_on_death = static_cast(atoi(row[13])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -422,6 +422,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_AA_ABILITY_REPOSITORY_H diff --git a/common/repositories/base/base_aa_rank_effects_repository.h b/common/repositories/base/base_aa_rank_effects_repository.h index 4d9c0684d..b2f3b70cf 100644 --- a/common/repositories/base/base_aa_rank_effects_repository.h +++ b/common/repositories/base/base_aa_rank_effects_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_AA_RANK_EFFECTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAaRankEffectsRepository { public: struct AaRankEffects { - int rank_id; - int slot; - int effect_id; - int base1; - int base2; + uint32_t rank_id; + uint32_t slot; + int32_t effect_id; + int32_t base1; + int32_t base2; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static AaRankEffects NewEntity() { - AaRankEffects entry{}; + AaRankEffects e{}; - entry.rank_id = 0; - entry.slot = 1; - entry.effect_id = 0; - entry.base1 = 0; - entry.base2 = 0; + e.rank_id = 0; + e.slot = 1; + e.effect_id = 0; + e.base1 = 0; + e.base2 = 0; - return entry; + return e; } - static AaRankEffects GetAaRankEffectsEntry( + static AaRankEffects GetAaRankEffects( const std::vector &aa_rank_effectss, int aa_rank_effects_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AaRankEffects entry{}; + AaRankEffects e{}; - entry.rank_id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.effect_id = atoi(row[2]); - entry.base1 = atoi(row[3]); - entry.base2 = atoi(row[4]); + e.rank_id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.effect_id = static_cast(atoi(row[2])); + e.base1 = static_cast(atoi(row[3])); + e.base2 = static_cast(atoi(row[4])); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - AaRankEffects aa_rank_effects_entry + const AaRankEffects &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(aa_rank_effects_entry.rank_id)); - update_values.push_back(columns[1] + " = " + std::to_string(aa_rank_effects_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(aa_rank_effects_entry.effect_id)); - update_values.push_back(columns[3] + " = " + std::to_string(aa_rank_effects_entry.base1)); - update_values.push_back(columns[4] + " = " + std::to_string(aa_rank_effects_entry.base2)); + v.push_back(columns[0] + " = " + std::to_string(e.rank_id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.effect_id)); + v.push_back(columns[3] + " = " + std::to_string(e.base1)); + v.push_back(columns[4] + " = " + std::to_string(e.base2)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - aa_rank_effects_entry.rank_id + e.rank_id ) ); @@ -189,61 +189,61 @@ public: static AaRankEffects InsertOne( Database& db, - AaRankEffects aa_rank_effects_entry + AaRankEffects e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(aa_rank_effects_entry.rank_id)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.slot)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.effect_id)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.base1)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.base2)); + v.push_back(std::to_string(e.rank_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.effect_id)); + v.push_back(std::to_string(e.base1)); + v.push_back(std::to_string(e.base2)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - aa_rank_effects_entry.rank_id = results.LastInsertedID(); - return aa_rank_effects_entry; + e.rank_id = results.LastInsertedID(); + return e; } - aa_rank_effects_entry = NewEntity(); + e = NewEntity(); - return aa_rank_effects_entry; + return e; } static int InsertMany( Database& db, - std::vector aa_rank_effects_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &aa_rank_effects_entry: aa_rank_effects_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(aa_rank_effects_entry.rank_id)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.slot)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.effect_id)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.base1)); - insert_values.push_back(std::to_string(aa_rank_effects_entry.base2)); + v.push_back(std::to_string(e.rank_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.effect_id)); + v.push_back(std::to_string(e.base1)); + v.push_back(std::to_string(e.base2)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaRankEffects entry{}; + AaRankEffects e{}; - entry.rank_id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.effect_id = atoi(row[2]); - entry.base1 = atoi(row[3]); - entry.base2 = atoi(row[4]); + e.rank_id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.effect_id = static_cast(atoi(row[2])); + e.base1 = static_cast(atoi(row[3])); + e.base2 = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaRankEffects entry{}; + AaRankEffects e{}; - entry.rank_id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.effect_id = atoi(row[2]); - entry.base1 = atoi(row[3]); - entry.base2 = atoi(row[4]); + e.rank_id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.effect_id = static_cast(atoi(row[2])); + e.base1 = static_cast(atoi(row[3])); + e.base2 = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_AA_RANK_EFFECTS_REPOSITORY_H diff --git a/common/repositories/base/base_aa_rank_prereqs_repository.h b/common/repositories/base/base_aa_rank_prereqs_repository.h index e6e76061c..0d00e2eea 100644 --- a/common/repositories/base/base_aa_rank_prereqs_repository.h +++ b/common/repositories/base/base_aa_rank_prereqs_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_AA_RANK_PREREQS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAaRankPrereqsRepository { public: struct AaRankPrereqs { - int rank_id; - int aa_id; - int points; + uint32_t rank_id; + int32_t aa_id; + int32_t points; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static AaRankPrereqs NewEntity() { - AaRankPrereqs entry{}; + AaRankPrereqs e{}; - entry.rank_id = 0; - entry.aa_id = 0; - entry.points = 0; + e.rank_id = 0; + e.aa_id = 0; + e.points = 0; - return entry; + return e; } - static AaRankPrereqs GetAaRankPrereqsEntry( + static AaRankPrereqs GetAaRankPrereqs( const std::vector &aa_rank_prereqss, int aa_rank_prereqs_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AaRankPrereqs entry{}; + AaRankPrereqs e{}; - entry.rank_id = atoi(row[0]); - entry.aa_id = atoi(row[1]); - entry.points = atoi(row[2]); + e.rank_id = static_cast(strtoul(row[0], nullptr, 10)); + e.aa_id = static_cast(atoi(row[1])); + e.points = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - AaRankPrereqs aa_rank_prereqs_entry + const AaRankPrereqs &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(aa_rank_prereqs_entry.rank_id)); - update_values.push_back(columns[1] + " = " + std::to_string(aa_rank_prereqs_entry.aa_id)); - update_values.push_back(columns[2] + " = " + std::to_string(aa_rank_prereqs_entry.points)); + v.push_back(columns[0] + " = " + std::to_string(e.rank_id)); + v.push_back(columns[1] + " = " + std::to_string(e.aa_id)); + v.push_back(columns[2] + " = " + std::to_string(e.points)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - aa_rank_prereqs_entry.rank_id + e.rank_id ) ); @@ -177,57 +177,57 @@ public: static AaRankPrereqs InsertOne( Database& db, - AaRankPrereqs aa_rank_prereqs_entry + AaRankPrereqs e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(aa_rank_prereqs_entry.rank_id)); - insert_values.push_back(std::to_string(aa_rank_prereqs_entry.aa_id)); - insert_values.push_back(std::to_string(aa_rank_prereqs_entry.points)); + v.push_back(std::to_string(e.rank_id)); + v.push_back(std::to_string(e.aa_id)); + v.push_back(std::to_string(e.points)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - aa_rank_prereqs_entry.rank_id = results.LastInsertedID(); - return aa_rank_prereqs_entry; + e.rank_id = results.LastInsertedID(); + return e; } - aa_rank_prereqs_entry = NewEntity(); + e = NewEntity(); - return aa_rank_prereqs_entry; + return e; } static int InsertMany( Database& db, - std::vector aa_rank_prereqs_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &aa_rank_prereqs_entry: aa_rank_prereqs_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(aa_rank_prereqs_entry.rank_id)); - insert_values.push_back(std::to_string(aa_rank_prereqs_entry.aa_id)); - insert_values.push_back(std::to_string(aa_rank_prereqs_entry.points)); + v.push_back(std::to_string(e.rank_id)); + v.push_back(std::to_string(e.aa_id)); + v.push_back(std::to_string(e.points)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaRankPrereqs entry{}; + AaRankPrereqs e{}; - entry.rank_id = atoi(row[0]); - entry.aa_id = atoi(row[1]); - entry.points = atoi(row[2]); + e.rank_id = static_cast(strtoul(row[0], nullptr, 10)); + e.aa_id = static_cast(atoi(row[1])); + e.points = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaRankPrereqs entry{}; + AaRankPrereqs e{}; - entry.rank_id = atoi(row[0]); - entry.aa_id = atoi(row[1]); - entry.points = atoi(row[2]); + e.rank_id = static_cast(strtoul(row[0], nullptr, 10)); + e.aa_id = static_cast(atoi(row[1])); + e.points = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_AA_RANK_PREREQS_REPOSITORY_H diff --git a/common/repositories/base/base_aa_ranks_repository.h b/common/repositories/base/base_aa_ranks_repository.h index 2f72f088f..d744fe731 100644 --- a/common/repositories/base/base_aa_ranks_repository.h +++ b/common/repositories/base/base_aa_ranks_repository.h @@ -13,25 +13,25 @@ #define EQEMU_BASE_AA_RANKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAaRanksRepository { public: struct AaRanks { - int id; - int upper_hotkey_sid; - int lower_hotkey_sid; - int title_sid; - int desc_sid; - int cost; - int level_req; - int spell; - int spell_type; - int recast_time; - int expansion; - int prev_id; - int next_id; + uint32_t id; + int32_t upper_hotkey_sid; + int32_t lower_hotkey_sid; + int32_t title_sid; + int32_t desc_sid; + int32_t cost; + int32_t level_req; + int32_t spell; + int32_t spell_type; + int32_t recast_time; + int32_t expansion; + int32_t prev_id; + int32_t next_id; }; static std::string PrimaryKey() @@ -79,12 +79,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -112,26 +112,26 @@ public: static AaRanks NewEntity() { - AaRanks entry{}; + AaRanks e{}; - entry.id = 0; - entry.upper_hotkey_sid = -1; - entry.lower_hotkey_sid = -1; - entry.title_sid = -1; - entry.desc_sid = -1; - entry.cost = 1; - entry.level_req = 51; - entry.spell = -1; - entry.spell_type = 0; - entry.recast_time = 0; - entry.expansion = 0; - entry.prev_id = -1; - entry.next_id = -1; + e.id = 0; + e.upper_hotkey_sid = -1; + e.lower_hotkey_sid = -1; + e.title_sid = -1; + e.desc_sid = -1; + e.cost = 1; + e.level_req = 51; + e.spell = -1; + e.spell_type = 0; + e.recast_time = 0; + e.expansion = 0; + e.prev_id = -1; + e.next_id = -1; - return entry; + return e; } - static AaRanks GetAaRanksEntry( + static AaRanks GetAaRanks( const std::vector &aa_rankss, int aa_ranks_id ) @@ -160,23 +160,23 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AaRanks entry{}; + AaRanks e{}; - entry.id = atoi(row[0]); - entry.upper_hotkey_sid = atoi(row[1]); - entry.lower_hotkey_sid = atoi(row[2]); - entry.title_sid = atoi(row[3]); - entry.desc_sid = atoi(row[4]); - entry.cost = atoi(row[5]); - entry.level_req = atoi(row[6]); - entry.spell = atoi(row[7]); - entry.spell_type = atoi(row[8]); - entry.recast_time = atoi(row[9]); - entry.expansion = atoi(row[10]); - entry.prev_id = atoi(row[11]); - entry.next_id = atoi(row[12]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.upper_hotkey_sid = static_cast(atoi(row[1])); + e.lower_hotkey_sid = static_cast(atoi(row[2])); + e.title_sid = static_cast(atoi(row[3])); + e.desc_sid = static_cast(atoi(row[4])); + e.cost = static_cast(atoi(row[5])); + e.level_req = static_cast(atoi(row[6])); + e.spell = static_cast(atoi(row[7])); + e.spell_type = static_cast(atoi(row[8])); + e.recast_time = static_cast(atoi(row[9])); + e.expansion = static_cast(atoi(row[10])); + e.prev_id = static_cast(atoi(row[11])); + e.next_id = static_cast(atoi(row[12])); - return entry; + return e; } return NewEntity(); @@ -201,34 +201,34 @@ public: static int UpdateOne( Database& db, - AaRanks aa_ranks_entry + const AaRanks &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(aa_ranks_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(aa_ranks_entry.upper_hotkey_sid)); - update_values.push_back(columns[2] + " = " + std::to_string(aa_ranks_entry.lower_hotkey_sid)); - update_values.push_back(columns[3] + " = " + std::to_string(aa_ranks_entry.title_sid)); - update_values.push_back(columns[4] + " = " + std::to_string(aa_ranks_entry.desc_sid)); - update_values.push_back(columns[5] + " = " + std::to_string(aa_ranks_entry.cost)); - update_values.push_back(columns[6] + " = " + std::to_string(aa_ranks_entry.level_req)); - update_values.push_back(columns[7] + " = " + std::to_string(aa_ranks_entry.spell)); - update_values.push_back(columns[8] + " = " + std::to_string(aa_ranks_entry.spell_type)); - update_values.push_back(columns[9] + " = " + std::to_string(aa_ranks_entry.recast_time)); - update_values.push_back(columns[10] + " = " + std::to_string(aa_ranks_entry.expansion)); - update_values.push_back(columns[11] + " = " + std::to_string(aa_ranks_entry.prev_id)); - update_values.push_back(columns[12] + " = " + std::to_string(aa_ranks_entry.next_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.upper_hotkey_sid)); + v.push_back(columns[2] + " = " + std::to_string(e.lower_hotkey_sid)); + v.push_back(columns[3] + " = " + std::to_string(e.title_sid)); + v.push_back(columns[4] + " = " + std::to_string(e.desc_sid)); + v.push_back(columns[5] + " = " + std::to_string(e.cost)); + v.push_back(columns[6] + " = " + std::to_string(e.level_req)); + v.push_back(columns[7] + " = " + std::to_string(e.spell)); + v.push_back(columns[8] + " = " + std::to_string(e.spell_type)); + v.push_back(columns[9] + " = " + std::to_string(e.recast_time)); + v.push_back(columns[10] + " = " + std::to_string(e.expansion)); + v.push_back(columns[11] + " = " + std::to_string(e.prev_id)); + v.push_back(columns[12] + " = " + std::to_string(e.next_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - aa_ranks_entry.id + e.id ) ); @@ -237,77 +237,77 @@ public: static AaRanks InsertOne( Database& db, - AaRanks aa_ranks_entry + AaRanks e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(aa_ranks_entry.id)); - insert_values.push_back(std::to_string(aa_ranks_entry.upper_hotkey_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.lower_hotkey_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.title_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.desc_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.cost)); - insert_values.push_back(std::to_string(aa_ranks_entry.level_req)); - insert_values.push_back(std::to_string(aa_ranks_entry.spell)); - insert_values.push_back(std::to_string(aa_ranks_entry.spell_type)); - insert_values.push_back(std::to_string(aa_ranks_entry.recast_time)); - insert_values.push_back(std::to_string(aa_ranks_entry.expansion)); - insert_values.push_back(std::to_string(aa_ranks_entry.prev_id)); - insert_values.push_back(std::to_string(aa_ranks_entry.next_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.upper_hotkey_sid)); + v.push_back(std::to_string(e.lower_hotkey_sid)); + v.push_back(std::to_string(e.title_sid)); + v.push_back(std::to_string(e.desc_sid)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.level_req)); + v.push_back(std::to_string(e.spell)); + v.push_back(std::to_string(e.spell_type)); + v.push_back(std::to_string(e.recast_time)); + v.push_back(std::to_string(e.expansion)); + v.push_back(std::to_string(e.prev_id)); + v.push_back(std::to_string(e.next_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - aa_ranks_entry.id = results.LastInsertedID(); - return aa_ranks_entry; + e.id = results.LastInsertedID(); + return e; } - aa_ranks_entry = NewEntity(); + e = NewEntity(); - return aa_ranks_entry; + return e; } static int InsertMany( Database& db, - std::vector aa_ranks_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &aa_ranks_entry: aa_ranks_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(aa_ranks_entry.id)); - insert_values.push_back(std::to_string(aa_ranks_entry.upper_hotkey_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.lower_hotkey_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.title_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.desc_sid)); - insert_values.push_back(std::to_string(aa_ranks_entry.cost)); - insert_values.push_back(std::to_string(aa_ranks_entry.level_req)); - insert_values.push_back(std::to_string(aa_ranks_entry.spell)); - insert_values.push_back(std::to_string(aa_ranks_entry.spell_type)); - insert_values.push_back(std::to_string(aa_ranks_entry.recast_time)); - insert_values.push_back(std::to_string(aa_ranks_entry.expansion)); - insert_values.push_back(std::to_string(aa_ranks_entry.prev_id)); - insert_values.push_back(std::to_string(aa_ranks_entry.next_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.upper_hotkey_sid)); + v.push_back(std::to_string(e.lower_hotkey_sid)); + v.push_back(std::to_string(e.title_sid)); + v.push_back(std::to_string(e.desc_sid)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.level_req)); + v.push_back(std::to_string(e.spell)); + v.push_back(std::to_string(e.spell_type)); + v.push_back(std::to_string(e.recast_time)); + v.push_back(std::to_string(e.expansion)); + v.push_back(std::to_string(e.prev_id)); + v.push_back(std::to_string(e.next_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -328,29 +328,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaRanks entry{}; + AaRanks e{}; - entry.id = atoi(row[0]); - entry.upper_hotkey_sid = atoi(row[1]); - entry.lower_hotkey_sid = atoi(row[2]); - entry.title_sid = atoi(row[3]); - entry.desc_sid = atoi(row[4]); - entry.cost = atoi(row[5]); - entry.level_req = atoi(row[6]); - entry.spell = atoi(row[7]); - entry.spell_type = atoi(row[8]); - entry.recast_time = atoi(row[9]); - entry.expansion = atoi(row[10]); - entry.prev_id = atoi(row[11]); - entry.next_id = atoi(row[12]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.upper_hotkey_sid = static_cast(atoi(row[1])); + e.lower_hotkey_sid = static_cast(atoi(row[2])); + e.title_sid = static_cast(atoi(row[3])); + e.desc_sid = static_cast(atoi(row[4])); + e.cost = static_cast(atoi(row[5])); + e.level_req = static_cast(atoi(row[6])); + e.spell = static_cast(atoi(row[7])); + e.spell_type = static_cast(atoi(row[8])); + e.recast_time = static_cast(atoi(row[9])); + e.expansion = static_cast(atoi(row[10])); + e.prev_id = static_cast(atoi(row[11])); + e.next_id = static_cast(atoi(row[12])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -365,29 +365,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AaRanks entry{}; + AaRanks e{}; - entry.id = atoi(row[0]); - entry.upper_hotkey_sid = atoi(row[1]); - entry.lower_hotkey_sid = atoi(row[2]); - entry.title_sid = atoi(row[3]); - entry.desc_sid = atoi(row[4]); - entry.cost = atoi(row[5]); - entry.level_req = atoi(row[6]); - entry.spell = atoi(row[7]); - entry.spell_type = atoi(row[8]); - entry.recast_time = atoi(row[9]); - entry.expansion = atoi(row[10]); - entry.prev_id = atoi(row[11]); - entry.next_id = atoi(row[12]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.upper_hotkey_sid = static_cast(atoi(row[1])); + e.lower_hotkey_sid = static_cast(atoi(row[2])); + e.title_sid = static_cast(atoi(row[3])); + e.desc_sid = static_cast(atoi(row[4])); + e.cost = static_cast(atoi(row[5])); + e.level_req = static_cast(atoi(row[6])); + e.spell = static_cast(atoi(row[7])); + e.spell_type = static_cast(atoi(row[8])); + e.recast_time = static_cast(atoi(row[9])); + e.expansion = static_cast(atoi(row[10])); + e.prev_id = static_cast(atoi(row[11])); + e.next_id = static_cast(atoi(row[12])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -412,6 +412,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_AA_RANKS_REPOSITORY_H diff --git a/common/repositories/base/base_account_flags_repository.h b/common/repositories/base/base_account_flags_repository.h index 00ba26713..52deedc55 100644 --- a/common/repositories/base/base_account_flags_repository.h +++ b/common/repositories/base/base_account_flags_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_ACCOUNT_FLAGS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAccountFlagsRepository { public: struct AccountFlags { - int p_accid; + uint32_t p_accid; std::string p_flag; std::string p_value; }; @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static AccountFlags NewEntity() { - AccountFlags entry{}; + AccountFlags e{}; - entry.p_accid = 0; - entry.p_flag = ""; - entry.p_value = ""; + e.p_accid = 0; + e.p_flag = ""; + e.p_value = ""; - return entry; + return e; } - static AccountFlags GetAccountFlagsEntry( + static AccountFlags GetAccountFlags( const std::vector &account_flagss, int account_flags_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AccountFlags entry{}; + AccountFlags e{}; - entry.p_accid = atoi(row[0]); - entry.p_flag = row[1] ? row[1] : ""; - entry.p_value = row[2] ? row[2] : ""; + e.p_accid = static_cast(strtoul(row[0], nullptr, 10)); + e.p_flag = row[1] ? row[1] : ""; + e.p_value = row[2] ? row[2] : ""; - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - AccountFlags account_flags_entry + const AccountFlags &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(account_flags_entry.p_accid)); - update_values.push_back(columns[1] + " = '" + EscapeString(account_flags_entry.p_flag) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(account_flags_entry.p_value) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.p_accid)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.p_flag) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.p_value) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - account_flags_entry.p_accid + e.p_accid ) ); @@ -177,57 +177,57 @@ public: static AccountFlags InsertOne( Database& db, - AccountFlags account_flags_entry + AccountFlags e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(account_flags_entry.p_accid)); - insert_values.push_back("'" + EscapeString(account_flags_entry.p_flag) + "'"); - insert_values.push_back("'" + EscapeString(account_flags_entry.p_value) + "'"); + v.push_back(std::to_string(e.p_accid)); + v.push_back("'" + Strings::Escape(e.p_flag) + "'"); + v.push_back("'" + Strings::Escape(e.p_value) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - account_flags_entry.p_accid = results.LastInsertedID(); - return account_flags_entry; + e.p_accid = results.LastInsertedID(); + return e; } - account_flags_entry = NewEntity(); + e = NewEntity(); - return account_flags_entry; + return e; } static int InsertMany( Database& db, - std::vector account_flags_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &account_flags_entry: account_flags_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(account_flags_entry.p_accid)); - insert_values.push_back("'" + EscapeString(account_flags_entry.p_flag) + "'"); - insert_values.push_back("'" + EscapeString(account_flags_entry.p_value) + "'"); + v.push_back(std::to_string(e.p_accid)); + v.push_back("'" + Strings::Escape(e.p_flag) + "'"); + v.push_back("'" + Strings::Escape(e.p_value) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AccountFlags entry{}; + AccountFlags e{}; - entry.p_accid = atoi(row[0]); - entry.p_flag = row[1] ? row[1] : ""; - entry.p_value = row[2] ? row[2] : ""; + e.p_accid = static_cast(strtoul(row[0], nullptr, 10)); + e.p_flag = row[1] ? row[1] : ""; + e.p_value = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AccountFlags entry{}; + AccountFlags e{}; - entry.p_accid = atoi(row[0]); - entry.p_flag = row[1] ? row[1] : ""; - entry.p_value = row[2] ? row[2] : ""; + e.p_accid = static_cast(strtoul(row[0], nullptr, 10)); + e.p_flag = row[1] ? row[1] : ""; + e.p_value = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ACCOUNT_FLAGS_REPOSITORY_H diff --git a/common/repositories/base/base_account_ip_repository.h b/common/repositories/base/base_account_ip_repository.h index e55a628c0..9b53cd5f2 100644 --- a/common/repositories/base/base_account_ip_repository.h +++ b/common/repositories/base/base_account_ip_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_ACCOUNT_IP_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAccountIpRepository { public: struct AccountIp { - int accid; + int32_t accid; std::string ip; - int count; + int32_t count; std::string lastused; }; @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static AccountIp NewEntity() { - AccountIp entry{}; + AccountIp e{}; - entry.accid = 0; - entry.ip = ""; - entry.count = 1; - entry.lastused = std::time(nullptr); + e.accid = 0; + e.ip = ""; + e.count = 1; + e.lastused = std::time(nullptr); - return entry; + return e; } - static AccountIp GetAccountIpEntry( + static AccountIp GetAccountIp( const std::vector &account_ips, int account_ip_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AccountIp entry{}; + AccountIp e{}; - entry.accid = atoi(row[0]); - entry.ip = row[1] ? row[1] : ""; - entry.count = atoi(row[2]); - entry.lastused = row[3] ? row[3] : ""; + e.accid = static_cast(atoi(row[0])); + e.ip = row[1] ? row[1] : ""; + e.count = static_cast(atoi(row[2])); + e.lastused = row[3] ? row[3] : ""; - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - AccountIp account_ip_entry + const AccountIp &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(account_ip_entry.accid)); - update_values.push_back(columns[1] + " = '" + EscapeString(account_ip_entry.ip) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(account_ip_entry.count)); - update_values.push_back(columns[3] + " = '" + EscapeString(account_ip_entry.lastused) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.accid)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.ip) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.count)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.lastused) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - account_ip_entry.accid + e.accid ) ); @@ -183,59 +183,59 @@ public: static AccountIp InsertOne( Database& db, - AccountIp account_ip_entry + AccountIp e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(account_ip_entry.accid)); - insert_values.push_back("'" + EscapeString(account_ip_entry.ip) + "'"); - insert_values.push_back(std::to_string(account_ip_entry.count)); - insert_values.push_back("'" + EscapeString(account_ip_entry.lastused) + "'"); + v.push_back(std::to_string(e.accid)); + v.push_back("'" + Strings::Escape(e.ip) + "'"); + v.push_back(std::to_string(e.count)); + v.push_back("'" + Strings::Escape(e.lastused) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - account_ip_entry.accid = results.LastInsertedID(); - return account_ip_entry; + e.accid = results.LastInsertedID(); + return e; } - account_ip_entry = NewEntity(); + e = NewEntity(); - return account_ip_entry; + return e; } static int InsertMany( Database& db, - std::vector account_ip_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &account_ip_entry: account_ip_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(account_ip_entry.accid)); - insert_values.push_back("'" + EscapeString(account_ip_entry.ip) + "'"); - insert_values.push_back(std::to_string(account_ip_entry.count)); - insert_values.push_back("'" + EscapeString(account_ip_entry.lastused) + "'"); + v.push_back(std::to_string(e.accid)); + v.push_back("'" + Strings::Escape(e.ip) + "'"); + v.push_back(std::to_string(e.count)); + v.push_back("'" + Strings::Escape(e.lastused) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AccountIp entry{}; + AccountIp e{}; - entry.accid = atoi(row[0]); - entry.ip = row[1] ? row[1] : ""; - entry.count = atoi(row[2]); - entry.lastused = row[3] ? row[3] : ""; + e.accid = static_cast(atoi(row[0])); + e.ip = row[1] ? row[1] : ""; + e.count = static_cast(atoi(row[2])); + e.lastused = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AccountIp entry{}; + AccountIp e{}; - entry.accid = atoi(row[0]); - entry.ip = row[1] ? row[1] : ""; - entry.count = atoi(row[2]); - entry.lastused = row[3] ? row[3] : ""; + e.accid = static_cast(atoi(row[0])); + e.ip = row[1] ? row[1] : ""; + e.count = static_cast(atoi(row[2])); + e.lastused = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ACCOUNT_IP_REPOSITORY_H diff --git a/common/repositories/base/base_account_repository.h b/common/repositories/base/base_account_repository.h index 5e8160085..92cf5b64a 100644 --- a/common/repositories/base/base_account_repository.h +++ b/common/repositories/base/base_account_repository.h @@ -13,29 +13,31 @@ #define EQEMU_BASE_ACCOUNT_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAccountRepository { public: struct Account { - int id; + int32_t id; std::string name; std::string charname; - int sharedplat; + uint32_t sharedplat; std::string password; - int status; + int32_t status; std::string ls_id; - int lsaccount_id; - int gmspeed; - int revoked; - int karma; + uint32_t lsaccount_id; + uint8_t gmspeed; + int8_t invulnerable; + int8_t flymode; + int8_t ignore_tells; + uint8_t revoked; + uint32_t karma; std::string minilogin_ip; - int hideme; - int rulesflag; + int8_t hideme; + uint8_t rulesflag; time_t suspendeduntil; - int time_creation; - int expansion; + uint32_t time_creation; std::string ban_reason; std::string suspend_reason; std::string crc_eqgame; @@ -60,6 +62,9 @@ public: "ls_id", "lsaccount_id", "gmspeed", + "invulnerable", + "flymode", + "ignore_tells", "revoked", "karma", "minilogin_ip", @@ -67,7 +72,6 @@ public: "rulesflag", "suspendeduntil", "time_creation", - "expansion", "ban_reason", "suspend_reason", "crc_eqgame", @@ -88,6 +92,9 @@ public: "ls_id", "lsaccount_id", "gmspeed", + "invulnerable", + "flymode", + "ignore_tells", "revoked", "karma", "minilogin_ip", @@ -95,7 +102,6 @@ public: "rulesflag", "UNIX_TIMESTAMP(suspendeduntil)", "time_creation", - "expansion", "ban_reason", "suspend_reason", "crc_eqgame", @@ -106,12 +112,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -139,35 +145,37 @@ public: static Account NewEntity() { - Account entry{}; + Account e{}; - entry.id = 0; - entry.name = ""; - entry.charname = ""; - entry.sharedplat = 0; - entry.password = ""; - entry.status = 0; - entry.ls_id = "eqemu"; - entry.lsaccount_id = 0; - entry.gmspeed = 0; - entry.revoked = 0; - entry.karma = 0; - entry.minilogin_ip = ""; - entry.hideme = 0; - entry.rulesflag = 0; - entry.suspendeduntil = 0; - entry.time_creation = 0; - entry.expansion = 0; - entry.ban_reason = ""; - entry.suspend_reason = ""; - entry.crc_eqgame = ""; - entry.crc_skillcaps = ""; - entry.crc_basedata = ""; + e.id = 0; + e.name = ""; + e.charname = ""; + e.sharedplat = 0; + e.password = ""; + e.status = 0; + e.ls_id = "eqemu"; + e.lsaccount_id = 0; + e.gmspeed = 0; + e.invulnerable = 0; + e.flymode = 0; + e.ignore_tells = 0; + e.revoked = 0; + e.karma = 0; + e.minilogin_ip = ""; + e.hideme = 0; + e.rulesflag = 0; + e.suspendeduntil = 0; + e.time_creation = 0; + e.ban_reason = ""; + e.suspend_reason = ""; + e.crc_eqgame = ""; + e.crc_skillcaps = ""; + e.crc_basedata = ""; - return entry; + return e; } - static Account GetAccountEntry( + static Account GetAccount( const std::vector &accounts, int account_id ) @@ -196,32 +204,34 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Account entry{}; + Account e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.charname = row[2] ? row[2] : ""; - entry.sharedplat = atoi(row[3]); - entry.password = row[4] ? row[4] : ""; - entry.status = atoi(row[5]); - entry.ls_id = row[6] ? row[6] : ""; - entry.lsaccount_id = atoi(row[7]); - entry.gmspeed = atoi(row[8]); - entry.revoked = atoi(row[9]); - entry.karma = atoi(row[10]); - entry.minilogin_ip = row[11] ? row[11] : ""; - entry.hideme = atoi(row[12]); - entry.rulesflag = atoi(row[13]); - entry.suspendeduntil = strtoll(row[14] ? row[14] : "-1", nullptr, 10); - entry.time_creation = atoi(row[15]); - entry.expansion = atoi(row[16]); - entry.ban_reason = row[17] ? row[17] : ""; - entry.suspend_reason = row[18] ? row[18] : ""; - entry.crc_eqgame = row[19] ? row[19] : ""; - entry.crc_skillcaps = row[20] ? row[20] : ""; - entry.crc_basedata = row[21] ? row[21] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.charname = row[2] ? row[2] : ""; + e.sharedplat = static_cast(strtoul(row[3], nullptr, 10)); + e.password = row[4] ? row[4] : ""; + e.status = static_cast(atoi(row[5])); + e.ls_id = row[6] ? row[6] : ""; + e.lsaccount_id = static_cast(strtoul(row[7], nullptr, 10)); + e.gmspeed = static_cast(strtoul(row[8], nullptr, 10)); + e.invulnerable = static_cast(atoi(row[9])); + e.flymode = static_cast(atoi(row[10])); + e.ignore_tells = static_cast(atoi(row[11])); + e.revoked = static_cast(strtoul(row[12], nullptr, 10)); + e.karma = static_cast(strtoul(row[13], nullptr, 10)); + e.minilogin_ip = row[14] ? row[14] : ""; + e.hideme = static_cast(atoi(row[15])); + e.rulesflag = static_cast(strtoul(row[16], nullptr, 10)); + e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10); + e.time_creation = static_cast(strtoul(row[18], nullptr, 10)); + e.ban_reason = row[19] ? row[19] : ""; + e.suspend_reason = row[20] ? row[20] : ""; + e.crc_eqgame = row[21] ? row[21] : ""; + e.crc_skillcaps = row[22] ? row[22] : ""; + e.crc_basedata = row[23] ? row[23] : ""; - return entry; + return e; } return NewEntity(); @@ -246,42 +256,44 @@ public: static int UpdateOne( Database& db, - Account account_entry + const Account &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(account_entry.name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(account_entry.charname) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(account_entry.sharedplat)); - update_values.push_back(columns[4] + " = '" + EscapeString(account_entry.password) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(account_entry.status)); - update_values.push_back(columns[6] + " = '" + EscapeString(account_entry.ls_id) + "'"); - update_values.push_back(columns[7] + " = " + std::to_string(account_entry.lsaccount_id)); - update_values.push_back(columns[8] + " = " + std::to_string(account_entry.gmspeed)); - update_values.push_back(columns[9] + " = " + std::to_string(account_entry.revoked)); - update_values.push_back(columns[10] + " = " + std::to_string(account_entry.karma)); - update_values.push_back(columns[11] + " = '" + EscapeString(account_entry.minilogin_ip) + "'"); - update_values.push_back(columns[12] + " = " + std::to_string(account_entry.hideme)); - update_values.push_back(columns[13] + " = " + std::to_string(account_entry.rulesflag)); - update_values.push_back(columns[14] + " = FROM_UNIXTIME(" + (account_entry.suspendeduntil > 0 ? std::to_string(account_entry.suspendeduntil) : "null") + ")"); - update_values.push_back(columns[15] + " = " + std::to_string(account_entry.time_creation)); - update_values.push_back(columns[16] + " = " + std::to_string(account_entry.expansion)); - update_values.push_back(columns[17] + " = '" + EscapeString(account_entry.ban_reason) + "'"); - update_values.push_back(columns[18] + " = '" + EscapeString(account_entry.suspend_reason) + "'"); - update_values.push_back(columns[19] + " = '" + EscapeString(account_entry.crc_eqgame) + "'"); - update_values.push_back(columns[20] + " = '" + EscapeString(account_entry.crc_skillcaps) + "'"); - update_values.push_back(columns[21] + " = '" + EscapeString(account_entry.crc_basedata) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.charname) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.sharedplat)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.password) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.status)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.ls_id) + "'"); + v.push_back(columns[7] + " = " + std::to_string(e.lsaccount_id)); + v.push_back(columns[8] + " = " + std::to_string(e.gmspeed)); + v.push_back(columns[9] + " = " + std::to_string(e.invulnerable)); + v.push_back(columns[10] + " = " + std::to_string(e.flymode)); + v.push_back(columns[11] + " = " + std::to_string(e.ignore_tells)); + v.push_back(columns[12] + " = " + std::to_string(e.revoked)); + v.push_back(columns[13] + " = " + std::to_string(e.karma)); + v.push_back(columns[14] + " = '" + Strings::Escape(e.minilogin_ip) + "'"); + v.push_back(columns[15] + " = " + std::to_string(e.hideme)); + v.push_back(columns[16] + " = " + std::to_string(e.rulesflag)); + v.push_back(columns[17] + " = FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")"); + v.push_back(columns[18] + " = " + std::to_string(e.time_creation)); + v.push_back(columns[19] + " = '" + Strings::Escape(e.ban_reason) + "'"); + v.push_back(columns[20] + " = '" + Strings::Escape(e.suspend_reason) + "'"); + v.push_back(columns[21] + " = '" + Strings::Escape(e.crc_eqgame) + "'"); + v.push_back(columns[22] + " = '" + Strings::Escape(e.crc_skillcaps) + "'"); + v.push_back(columns[23] + " = '" + Strings::Escape(e.crc_basedata) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - account_entry.id + e.id ) ); @@ -290,95 +302,99 @@ public: static Account InsertOne( Database& db, - Account account_entry + Account e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(account_entry.id)); - insert_values.push_back("'" + EscapeString(account_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.charname) + "'"); - insert_values.push_back(std::to_string(account_entry.sharedplat)); - insert_values.push_back("'" + EscapeString(account_entry.password) + "'"); - insert_values.push_back(std::to_string(account_entry.status)); - insert_values.push_back("'" + EscapeString(account_entry.ls_id) + "'"); - insert_values.push_back(std::to_string(account_entry.lsaccount_id)); - insert_values.push_back(std::to_string(account_entry.gmspeed)); - insert_values.push_back(std::to_string(account_entry.revoked)); - insert_values.push_back(std::to_string(account_entry.karma)); - insert_values.push_back("'" + EscapeString(account_entry.minilogin_ip) + "'"); - insert_values.push_back(std::to_string(account_entry.hideme)); - insert_values.push_back(std::to_string(account_entry.rulesflag)); - insert_values.push_back("FROM_UNIXTIME(" + (account_entry.suspendeduntil > 0 ? std::to_string(account_entry.suspendeduntil) : "null") + ")"); - insert_values.push_back(std::to_string(account_entry.time_creation)); - insert_values.push_back(std::to_string(account_entry.expansion)); - insert_values.push_back("'" + EscapeString(account_entry.ban_reason) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.suspend_reason) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.crc_eqgame) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.crc_skillcaps) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.crc_basedata) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back(std::to_string(e.sharedplat)); + v.push_back("'" + Strings::Escape(e.password) + "'"); + v.push_back(std::to_string(e.status)); + v.push_back("'" + Strings::Escape(e.ls_id) + "'"); + v.push_back(std::to_string(e.lsaccount_id)); + v.push_back(std::to_string(e.gmspeed)); + v.push_back(std::to_string(e.invulnerable)); + v.push_back(std::to_string(e.flymode)); + v.push_back(std::to_string(e.ignore_tells)); + v.push_back(std::to_string(e.revoked)); + v.push_back(std::to_string(e.karma)); + v.push_back("'" + Strings::Escape(e.minilogin_ip) + "'"); + v.push_back(std::to_string(e.hideme)); + v.push_back(std::to_string(e.rulesflag)); + v.push_back("FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")"); + v.push_back(std::to_string(e.time_creation)); + v.push_back("'" + Strings::Escape(e.ban_reason) + "'"); + v.push_back("'" + Strings::Escape(e.suspend_reason) + "'"); + v.push_back("'" + Strings::Escape(e.crc_eqgame) + "'"); + v.push_back("'" + Strings::Escape(e.crc_skillcaps) + "'"); + v.push_back("'" + Strings::Escape(e.crc_basedata) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - account_entry.id = results.LastInsertedID(); - return account_entry; + e.id = results.LastInsertedID(); + return e; } - account_entry = NewEntity(); + e = NewEntity(); - return account_entry; + return e; } static int InsertMany( Database& db, - std::vector account_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &account_entry: account_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(account_entry.id)); - insert_values.push_back("'" + EscapeString(account_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.charname) + "'"); - insert_values.push_back(std::to_string(account_entry.sharedplat)); - insert_values.push_back("'" + EscapeString(account_entry.password) + "'"); - insert_values.push_back(std::to_string(account_entry.status)); - insert_values.push_back("'" + EscapeString(account_entry.ls_id) + "'"); - insert_values.push_back(std::to_string(account_entry.lsaccount_id)); - insert_values.push_back(std::to_string(account_entry.gmspeed)); - insert_values.push_back(std::to_string(account_entry.revoked)); - insert_values.push_back(std::to_string(account_entry.karma)); - insert_values.push_back("'" + EscapeString(account_entry.minilogin_ip) + "'"); - insert_values.push_back(std::to_string(account_entry.hideme)); - insert_values.push_back(std::to_string(account_entry.rulesflag)); - insert_values.push_back("FROM_UNIXTIME(" + (account_entry.suspendeduntil > 0 ? std::to_string(account_entry.suspendeduntil) : "null") + ")"); - insert_values.push_back(std::to_string(account_entry.time_creation)); - insert_values.push_back(std::to_string(account_entry.expansion)); - insert_values.push_back("'" + EscapeString(account_entry.ban_reason) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.suspend_reason) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.crc_eqgame) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.crc_skillcaps) + "'"); - insert_values.push_back("'" + EscapeString(account_entry.crc_basedata) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back(std::to_string(e.sharedplat)); + v.push_back("'" + Strings::Escape(e.password) + "'"); + v.push_back(std::to_string(e.status)); + v.push_back("'" + Strings::Escape(e.ls_id) + "'"); + v.push_back(std::to_string(e.lsaccount_id)); + v.push_back(std::to_string(e.gmspeed)); + v.push_back(std::to_string(e.invulnerable)); + v.push_back(std::to_string(e.flymode)); + v.push_back(std::to_string(e.ignore_tells)); + v.push_back(std::to_string(e.revoked)); + v.push_back(std::to_string(e.karma)); + v.push_back("'" + Strings::Escape(e.minilogin_ip) + "'"); + v.push_back(std::to_string(e.hideme)); + v.push_back(std::to_string(e.rulesflag)); + v.push_back("FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")"); + v.push_back(std::to_string(e.time_creation)); + v.push_back("'" + Strings::Escape(e.ban_reason) + "'"); + v.push_back("'" + Strings::Escape(e.suspend_reason) + "'"); + v.push_back("'" + Strings::Escape(e.crc_eqgame) + "'"); + v.push_back("'" + Strings::Escape(e.crc_skillcaps) + "'"); + v.push_back("'" + Strings::Escape(e.crc_basedata) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -399,38 +415,40 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Account entry{}; + Account e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.charname = row[2] ? row[2] : ""; - entry.sharedplat = atoi(row[3]); - entry.password = row[4] ? row[4] : ""; - entry.status = atoi(row[5]); - entry.ls_id = row[6] ? row[6] : ""; - entry.lsaccount_id = atoi(row[7]); - entry.gmspeed = atoi(row[8]); - entry.revoked = atoi(row[9]); - entry.karma = atoi(row[10]); - entry.minilogin_ip = row[11] ? row[11] : ""; - entry.hideme = atoi(row[12]); - entry.rulesflag = atoi(row[13]); - entry.suspendeduntil = strtoll(row[14] ? row[14] : "-1", nullptr, 10); - entry.time_creation = atoi(row[15]); - entry.expansion = atoi(row[16]); - entry.ban_reason = row[17] ? row[17] : ""; - entry.suspend_reason = row[18] ? row[18] : ""; - entry.crc_eqgame = row[19] ? row[19] : ""; - entry.crc_skillcaps = row[20] ? row[20] : ""; - entry.crc_basedata = row[21] ? row[21] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.charname = row[2] ? row[2] : ""; + e.sharedplat = static_cast(strtoul(row[3], nullptr, 10)); + e.password = row[4] ? row[4] : ""; + e.status = static_cast(atoi(row[5])); + e.ls_id = row[6] ? row[6] : ""; + e.lsaccount_id = static_cast(strtoul(row[7], nullptr, 10)); + e.gmspeed = static_cast(strtoul(row[8], nullptr, 10)); + e.invulnerable = static_cast(atoi(row[9])); + e.flymode = static_cast(atoi(row[10])); + e.ignore_tells = static_cast(atoi(row[11])); + e.revoked = static_cast(strtoul(row[12], nullptr, 10)); + e.karma = static_cast(strtoul(row[13], nullptr, 10)); + e.minilogin_ip = row[14] ? row[14] : ""; + e.hideme = static_cast(atoi(row[15])); + e.rulesflag = static_cast(strtoul(row[16], nullptr, 10)); + e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10); + e.time_creation = static_cast(strtoul(row[18], nullptr, 10)); + e.ban_reason = row[19] ? row[19] : ""; + e.suspend_reason = row[20] ? row[20] : ""; + e.crc_eqgame = row[21] ? row[21] : ""; + e.crc_skillcaps = row[22] ? row[22] : ""; + e.crc_basedata = row[23] ? row[23] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -445,38 +463,40 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Account entry{}; + Account e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.charname = row[2] ? row[2] : ""; - entry.sharedplat = atoi(row[3]); - entry.password = row[4] ? row[4] : ""; - entry.status = atoi(row[5]); - entry.ls_id = row[6] ? row[6] : ""; - entry.lsaccount_id = atoi(row[7]); - entry.gmspeed = atoi(row[8]); - entry.revoked = atoi(row[9]); - entry.karma = atoi(row[10]); - entry.minilogin_ip = row[11] ? row[11] : ""; - entry.hideme = atoi(row[12]); - entry.rulesflag = atoi(row[13]); - entry.suspendeduntil = strtoll(row[14] ? row[14] : "-1", nullptr, 10); - entry.time_creation = atoi(row[15]); - entry.expansion = atoi(row[16]); - entry.ban_reason = row[17] ? row[17] : ""; - entry.suspend_reason = row[18] ? row[18] : ""; - entry.crc_eqgame = row[19] ? row[19] : ""; - entry.crc_skillcaps = row[20] ? row[20] : ""; - entry.crc_basedata = row[21] ? row[21] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.charname = row[2] ? row[2] : ""; + e.sharedplat = static_cast(strtoul(row[3], nullptr, 10)); + e.password = row[4] ? row[4] : ""; + e.status = static_cast(atoi(row[5])); + e.ls_id = row[6] ? row[6] : ""; + e.lsaccount_id = static_cast(strtoul(row[7], nullptr, 10)); + e.gmspeed = static_cast(strtoul(row[8], nullptr, 10)); + e.invulnerable = static_cast(atoi(row[9])); + e.flymode = static_cast(atoi(row[10])); + e.ignore_tells = static_cast(atoi(row[11])); + e.revoked = static_cast(strtoul(row[12], nullptr, 10)); + e.karma = static_cast(strtoul(row[13], nullptr, 10)); + e.minilogin_ip = row[14] ? row[14] : ""; + e.hideme = static_cast(atoi(row[15])); + e.rulesflag = static_cast(strtoul(row[16], nullptr, 10)); + e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10); + e.time_creation = static_cast(strtoul(row[18], nullptr, 10)); + e.ban_reason = row[19] ? row[19] : ""; + e.suspend_reason = row[20] ? row[20] : ""; + e.crc_eqgame = row[21] ? row[21] : ""; + e.crc_skillcaps = row[22] ? row[22] : ""; + e.crc_basedata = row[23] ? row[23] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -501,6 +521,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ACCOUNT_REPOSITORY_H diff --git a/common/repositories/base/base_account_rewards_repository.h b/common/repositories/base/base_account_rewards_repository.h index cc2fc52a2..008a2b165 100644 --- a/common/repositories/base/base_account_rewards_repository.h +++ b/common/repositories/base/base_account_rewards_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_ACCOUNT_REWARDS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAccountRewardsRepository { public: struct AccountRewards { - int account_id; - int reward_id; - int amount; + uint32_t account_id; + uint32_t reward_id; + uint32_t amount; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static AccountRewards NewEntity() { - AccountRewards entry{}; + AccountRewards e{}; - entry.account_id = 0; - entry.reward_id = 0; - entry.amount = 0; + e.account_id = 0; + e.reward_id = 0; + e.amount = 0; - return entry; + return e; } - static AccountRewards GetAccountRewardsEntry( + static AccountRewards GetAccountRewards( const std::vector &account_rewardss, int account_rewards_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AccountRewards entry{}; + AccountRewards e{}; - entry.account_id = atoi(row[0]); - entry.reward_id = atoi(row[1]); - entry.amount = atoi(row[2]); + e.account_id = static_cast(strtoul(row[0], nullptr, 10)); + e.reward_id = static_cast(strtoul(row[1], nullptr, 10)); + e.amount = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - AccountRewards account_rewards_entry + const AccountRewards &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(account_rewards_entry.account_id)); - update_values.push_back(columns[1] + " = " + std::to_string(account_rewards_entry.reward_id)); - update_values.push_back(columns[2] + " = " + std::to_string(account_rewards_entry.amount)); + v.push_back(columns[0] + " = " + std::to_string(e.account_id)); + v.push_back(columns[1] + " = " + std::to_string(e.reward_id)); + v.push_back(columns[2] + " = " + std::to_string(e.amount)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - account_rewards_entry.account_id + e.account_id ) ); @@ -177,57 +177,57 @@ public: static AccountRewards InsertOne( Database& db, - AccountRewards account_rewards_entry + AccountRewards e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(account_rewards_entry.account_id)); - insert_values.push_back(std::to_string(account_rewards_entry.reward_id)); - insert_values.push_back(std::to_string(account_rewards_entry.amount)); + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.reward_id)); + v.push_back(std::to_string(e.amount)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - account_rewards_entry.account_id = results.LastInsertedID(); - return account_rewards_entry; + e.account_id = results.LastInsertedID(); + return e; } - account_rewards_entry = NewEntity(); + e = NewEntity(); - return account_rewards_entry; + return e; } static int InsertMany( Database& db, - std::vector account_rewards_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &account_rewards_entry: account_rewards_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(account_rewards_entry.account_id)); - insert_values.push_back(std::to_string(account_rewards_entry.reward_id)); - insert_values.push_back(std::to_string(account_rewards_entry.amount)); + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.reward_id)); + v.push_back(std::to_string(e.amount)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AccountRewards entry{}; + AccountRewards e{}; - entry.account_id = atoi(row[0]); - entry.reward_id = atoi(row[1]); - entry.amount = atoi(row[2]); + e.account_id = static_cast(strtoul(row[0], nullptr, 10)); + e.reward_id = static_cast(strtoul(row[1], nullptr, 10)); + e.amount = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AccountRewards entry{}; + AccountRewards e{}; - entry.account_id = atoi(row[0]); - entry.reward_id = atoi(row[1]); - entry.amount = atoi(row[2]); + e.account_id = static_cast(strtoul(row[0], nullptr, 10)); + e.reward_id = static_cast(strtoul(row[1], nullptr, 10)); + e.amount = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ACCOUNT_REWARDS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_details_repository.h b/common/repositories/base/base_adventure_details_repository.h index 2eac688ab..e82accdef 100644 --- a/common/repositories/base/base_adventure_details_repository.h +++ b/common/repositories/base/base_adventure_details_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_ADVENTURE_DETAILS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAdventureDetailsRepository { public: struct AdventureDetails { - int id; - int adventure_id; - int instance_id; - int count; - int assassinate_count; - int status; - int time_created; - int time_zoned; - int time_completed; + uint32_t id; + uint16_t adventure_id; + int32_t instance_id; + uint16_t count; + uint16_t assassinate_count; + uint8_t status; + uint32_t time_created; + uint32_t time_zoned; + uint32_t time_completed; }; static std::string PrimaryKey() @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static AdventureDetails NewEntity() { - AdventureDetails entry{}; + AdventureDetails e{}; - entry.id = 0; - entry.adventure_id = 0; - entry.instance_id = -1; - entry.count = 0; - entry.assassinate_count = 0; - entry.status = 0; - entry.time_created = 0; - entry.time_zoned = 0; - entry.time_completed = 0; + e.id = 0; + e.adventure_id = 0; + e.instance_id = -1; + e.count = 0; + e.assassinate_count = 0; + e.status = 0; + e.time_created = 0; + e.time_zoned = 0; + e.time_completed = 0; - return entry; + return e; } - static AdventureDetails GetAdventureDetailsEntry( + static AdventureDetails GetAdventureDetails( const std::vector &adventure_detailss, int adventure_details_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AdventureDetails entry{}; + AdventureDetails e{}; - entry.id = atoi(row[0]); - entry.adventure_id = atoi(row[1]); - entry.instance_id = atoi(row[2]); - entry.count = atoi(row[3]); - entry.assassinate_count = atoi(row[4]); - entry.status = atoi(row[5]); - entry.time_created = atoi(row[6]); - entry.time_zoned = atoi(row[7]); - entry.time_completed = atoi(row[8]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.adventure_id = static_cast(strtoul(row[1], nullptr, 10)); + e.instance_id = static_cast(atoi(row[2])); + e.count = static_cast(strtoul(row[3], nullptr, 10)); + e.assassinate_count = static_cast(strtoul(row[4], nullptr, 10)); + e.status = static_cast(strtoul(row[5], nullptr, 10)); + e.time_created = static_cast(strtoul(row[6], nullptr, 10)); + e.time_zoned = static_cast(strtoul(row[7], nullptr, 10)); + e.time_completed = static_cast(strtoul(row[8], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -181,29 +181,29 @@ public: static int UpdateOne( Database& db, - AdventureDetails adventure_details_entry + const AdventureDetails &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(adventure_details_entry.adventure_id)); - update_values.push_back(columns[2] + " = " + std::to_string(adventure_details_entry.instance_id)); - update_values.push_back(columns[3] + " = " + std::to_string(adventure_details_entry.count)); - update_values.push_back(columns[4] + " = " + std::to_string(adventure_details_entry.assassinate_count)); - update_values.push_back(columns[5] + " = " + std::to_string(adventure_details_entry.status)); - update_values.push_back(columns[6] + " = " + std::to_string(adventure_details_entry.time_created)); - update_values.push_back(columns[7] + " = " + std::to_string(adventure_details_entry.time_zoned)); - update_values.push_back(columns[8] + " = " + std::to_string(adventure_details_entry.time_completed)); + v.push_back(columns[1] + " = " + std::to_string(e.adventure_id)); + v.push_back(columns[2] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[3] + " = " + std::to_string(e.count)); + v.push_back(columns[4] + " = " + std::to_string(e.assassinate_count)); + v.push_back(columns[5] + " = " + std::to_string(e.status)); + v.push_back(columns[6] + " = " + std::to_string(e.time_created)); + v.push_back(columns[7] + " = " + std::to_string(e.time_zoned)); + v.push_back(columns[8] + " = " + std::to_string(e.time_completed)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - adventure_details_entry.id + e.id ) ); @@ -212,69 +212,69 @@ public: static AdventureDetails InsertOne( Database& db, - AdventureDetails adventure_details_entry + AdventureDetails e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(adventure_details_entry.id)); - insert_values.push_back(std::to_string(adventure_details_entry.adventure_id)); - insert_values.push_back(std::to_string(adventure_details_entry.instance_id)); - insert_values.push_back(std::to_string(adventure_details_entry.count)); - insert_values.push_back(std::to_string(adventure_details_entry.assassinate_count)); - insert_values.push_back(std::to_string(adventure_details_entry.status)); - insert_values.push_back(std::to_string(adventure_details_entry.time_created)); - insert_values.push_back(std::to_string(adventure_details_entry.time_zoned)); - insert_values.push_back(std::to_string(adventure_details_entry.time_completed)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.adventure_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.count)); + v.push_back(std::to_string(e.assassinate_count)); + v.push_back(std::to_string(e.status)); + v.push_back(std::to_string(e.time_created)); + v.push_back(std::to_string(e.time_zoned)); + v.push_back(std::to_string(e.time_completed)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - adventure_details_entry.id = results.LastInsertedID(); - return adventure_details_entry; + e.id = results.LastInsertedID(); + return e; } - adventure_details_entry = NewEntity(); + e = NewEntity(); - return adventure_details_entry; + return e; } static int InsertMany( Database& db, - std::vector adventure_details_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &adventure_details_entry: adventure_details_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(adventure_details_entry.id)); - insert_values.push_back(std::to_string(adventure_details_entry.adventure_id)); - insert_values.push_back(std::to_string(adventure_details_entry.instance_id)); - insert_values.push_back(std::to_string(adventure_details_entry.count)); - insert_values.push_back(std::to_string(adventure_details_entry.assassinate_count)); - insert_values.push_back(std::to_string(adventure_details_entry.status)); - insert_values.push_back(std::to_string(adventure_details_entry.time_created)); - insert_values.push_back(std::to_string(adventure_details_entry.time_zoned)); - insert_values.push_back(std::to_string(adventure_details_entry.time_completed)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.adventure_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.count)); + v.push_back(std::to_string(e.assassinate_count)); + v.push_back(std::to_string(e.status)); + v.push_back(std::to_string(e.time_created)); + v.push_back(std::to_string(e.time_zoned)); + v.push_back(std::to_string(e.time_completed)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -295,25 +295,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureDetails entry{}; + AdventureDetails e{}; - entry.id = atoi(row[0]); - entry.adventure_id = atoi(row[1]); - entry.instance_id = atoi(row[2]); - entry.count = atoi(row[3]); - entry.assassinate_count = atoi(row[4]); - entry.status = atoi(row[5]); - entry.time_created = atoi(row[6]); - entry.time_zoned = atoi(row[7]); - entry.time_completed = atoi(row[8]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.adventure_id = static_cast(strtoul(row[1], nullptr, 10)); + e.instance_id = static_cast(atoi(row[2])); + e.count = static_cast(strtoul(row[3], nullptr, 10)); + e.assassinate_count = static_cast(strtoul(row[4], nullptr, 10)); + e.status = static_cast(strtoul(row[5], nullptr, 10)); + e.time_created = static_cast(strtoul(row[6], nullptr, 10)); + e.time_zoned = static_cast(strtoul(row[7], nullptr, 10)); + e.time_completed = static_cast(strtoul(row[8], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -328,25 +328,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureDetails entry{}; + AdventureDetails e{}; - entry.id = atoi(row[0]); - entry.adventure_id = atoi(row[1]); - entry.instance_id = atoi(row[2]); - entry.count = atoi(row[3]); - entry.assassinate_count = atoi(row[4]); - entry.status = atoi(row[5]); - entry.time_created = atoi(row[6]); - entry.time_zoned = atoi(row[7]); - entry.time_completed = atoi(row[8]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.adventure_id = static_cast(strtoul(row[1], nullptr, 10)); + e.instance_id = static_cast(atoi(row[2])); + e.count = static_cast(strtoul(row[3], nullptr, 10)); + e.assassinate_count = static_cast(strtoul(row[4], nullptr, 10)); + e.status = static_cast(strtoul(row[5], nullptr, 10)); + e.time_created = static_cast(strtoul(row[6], nullptr, 10)); + e.time_zoned = static_cast(strtoul(row[7], nullptr, 10)); + e.time_completed = static_cast(strtoul(row[8], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -371,6 +371,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ADVENTURE_DETAILS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_members_repository.h b/common/repositories/base/base_adventure_members_repository.h index 81102350c..1abf23b5b 100644 --- a/common/repositories/base/base_adventure_members_repository.h +++ b/common/repositories/base/base_adventure_members_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_ADVENTURE_MEMBERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAdventureMembersRepository { public: struct AdventureMembers { - int id; - int charid; + uint32_t id; + uint32_t charid; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static AdventureMembers NewEntity() { - AdventureMembers entry{}; + AdventureMembers e{}; - entry.id = 0; - entry.charid = 0; + e.id = 0; + e.charid = 0; - return entry; + return e; } - static AdventureMembers GetAdventureMembersEntry( + static AdventureMembers GetAdventureMembers( const std::vector &adventure_memberss, int adventure_members_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AdventureMembers entry{}; + AdventureMembers e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - AdventureMembers adventure_members_entry + const AdventureMembers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(adventure_members_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(adventure_members_entry.charid)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.charid)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - adventure_members_entry.charid + e.charid ) ); @@ -171,55 +171,55 @@ public: static AdventureMembers InsertOne( Database& db, - AdventureMembers adventure_members_entry + AdventureMembers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(adventure_members_entry.id)); - insert_values.push_back(std::to_string(adventure_members_entry.charid)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.charid)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - adventure_members_entry.charid = results.LastInsertedID(); - return adventure_members_entry; + e.charid = results.LastInsertedID(); + return e; } - adventure_members_entry = NewEntity(); + e = NewEntity(); - return adventure_members_entry; + return e; } static int InsertMany( Database& db, - std::vector adventure_members_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &adventure_members_entry: adventure_members_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(adventure_members_entry.id)); - insert_values.push_back(std::to_string(adventure_members_entry.charid)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.charid)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureMembers entry{}; + AdventureMembers e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureMembers entry{}; + AdventureMembers e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ADVENTURE_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_stats_repository.h b/common/repositories/base/base_adventure_stats_repository.h index 68d3ba20d..5a25d5126 100644 --- a/common/repositories/base/base_adventure_stats_repository.h +++ b/common/repositories/base/base_adventure_stats_repository.h @@ -13,23 +13,23 @@ #define EQEMU_BASE_ADVENTURE_STATS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAdventureStatsRepository { public: struct AdventureStats { - int player_id; - int guk_wins; - int mir_wins; - int mmc_wins; - int ruj_wins; - int tak_wins; - int guk_losses; - int mir_losses; - int mmc_losses; - int ruj_losses; - int tak_losses; + uint32_t player_id; + uint32_t guk_wins; + uint32_t mir_wins; + uint32_t mmc_wins; + uint32_t ruj_wins; + uint32_t tak_wins; + uint32_t guk_losses; + uint32_t mir_losses; + uint32_t mmc_losses; + uint32_t ruj_losses; + uint32_t tak_losses; }; static std::string PrimaryKey() @@ -73,12 +73,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -106,24 +106,24 @@ public: static AdventureStats NewEntity() { - AdventureStats entry{}; + AdventureStats e{}; - entry.player_id = 0; - entry.guk_wins = 0; - entry.mir_wins = 0; - entry.mmc_wins = 0; - entry.ruj_wins = 0; - entry.tak_wins = 0; - entry.guk_losses = 0; - entry.mir_losses = 0; - entry.mmc_losses = 0; - entry.ruj_losses = 0; - entry.tak_losses = 0; + e.player_id = 0; + e.guk_wins = 0; + e.mir_wins = 0; + e.mmc_wins = 0; + e.ruj_wins = 0; + e.tak_wins = 0; + e.guk_losses = 0; + e.mir_losses = 0; + e.mmc_losses = 0; + e.ruj_losses = 0; + e.tak_losses = 0; - return entry; + return e; } - static AdventureStats GetAdventureStatsEntry( + static AdventureStats GetAdventureStats( const std::vector &adventure_statss, int adventure_stats_id ) @@ -152,21 +152,21 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AdventureStats entry{}; + AdventureStats e{}; - entry.player_id = atoi(row[0]); - entry.guk_wins = atoi(row[1]); - entry.mir_wins = atoi(row[2]); - entry.mmc_wins = atoi(row[3]); - entry.ruj_wins = atoi(row[4]); - entry.tak_wins = atoi(row[5]); - entry.guk_losses = atoi(row[6]); - entry.mir_losses = atoi(row[7]); - entry.mmc_losses = atoi(row[8]); - entry.ruj_losses = atoi(row[9]); - entry.tak_losses = atoi(row[10]); + e.player_id = static_cast(strtoul(row[0], nullptr, 10)); + e.guk_wins = static_cast(strtoul(row[1], nullptr, 10)); + e.mir_wins = static_cast(strtoul(row[2], nullptr, 10)); + e.mmc_wins = static_cast(strtoul(row[3], nullptr, 10)); + e.ruj_wins = static_cast(strtoul(row[4], nullptr, 10)); + e.tak_wins = static_cast(strtoul(row[5], nullptr, 10)); + e.guk_losses = static_cast(strtoul(row[6], nullptr, 10)); + e.mir_losses = static_cast(strtoul(row[7], nullptr, 10)); + e.mmc_losses = static_cast(strtoul(row[8], nullptr, 10)); + e.ruj_losses = static_cast(strtoul(row[9], nullptr, 10)); + e.tak_losses = static_cast(strtoul(row[10], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -191,32 +191,32 @@ public: static int UpdateOne( Database& db, - AdventureStats adventure_stats_entry + const AdventureStats &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(adventure_stats_entry.player_id)); - update_values.push_back(columns[1] + " = " + std::to_string(adventure_stats_entry.guk_wins)); - update_values.push_back(columns[2] + " = " + std::to_string(adventure_stats_entry.mir_wins)); - update_values.push_back(columns[3] + " = " + std::to_string(adventure_stats_entry.mmc_wins)); - update_values.push_back(columns[4] + " = " + std::to_string(adventure_stats_entry.ruj_wins)); - update_values.push_back(columns[5] + " = " + std::to_string(adventure_stats_entry.tak_wins)); - update_values.push_back(columns[6] + " = " + std::to_string(adventure_stats_entry.guk_losses)); - update_values.push_back(columns[7] + " = " + std::to_string(adventure_stats_entry.mir_losses)); - update_values.push_back(columns[8] + " = " + std::to_string(adventure_stats_entry.mmc_losses)); - update_values.push_back(columns[9] + " = " + std::to_string(adventure_stats_entry.ruj_losses)); - update_values.push_back(columns[10] + " = " + std::to_string(adventure_stats_entry.tak_losses)); + v.push_back(columns[0] + " = " + std::to_string(e.player_id)); + v.push_back(columns[1] + " = " + std::to_string(e.guk_wins)); + v.push_back(columns[2] + " = " + std::to_string(e.mir_wins)); + v.push_back(columns[3] + " = " + std::to_string(e.mmc_wins)); + v.push_back(columns[4] + " = " + std::to_string(e.ruj_wins)); + v.push_back(columns[5] + " = " + std::to_string(e.tak_wins)); + v.push_back(columns[6] + " = " + std::to_string(e.guk_losses)); + v.push_back(columns[7] + " = " + std::to_string(e.mir_losses)); + v.push_back(columns[8] + " = " + std::to_string(e.mmc_losses)); + v.push_back(columns[9] + " = " + std::to_string(e.ruj_losses)); + v.push_back(columns[10] + " = " + std::to_string(e.tak_losses)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - adventure_stats_entry.player_id + e.player_id ) ); @@ -225,73 +225,73 @@ public: static AdventureStats InsertOne( Database& db, - AdventureStats adventure_stats_entry + AdventureStats e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(adventure_stats_entry.player_id)); - insert_values.push_back(std::to_string(adventure_stats_entry.guk_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.mir_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.mmc_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.ruj_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.tak_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.guk_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.mir_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.mmc_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.ruj_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.tak_losses)); + v.push_back(std::to_string(e.player_id)); + v.push_back(std::to_string(e.guk_wins)); + v.push_back(std::to_string(e.mir_wins)); + v.push_back(std::to_string(e.mmc_wins)); + v.push_back(std::to_string(e.ruj_wins)); + v.push_back(std::to_string(e.tak_wins)); + v.push_back(std::to_string(e.guk_losses)); + v.push_back(std::to_string(e.mir_losses)); + v.push_back(std::to_string(e.mmc_losses)); + v.push_back(std::to_string(e.ruj_losses)); + v.push_back(std::to_string(e.tak_losses)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - adventure_stats_entry.player_id = results.LastInsertedID(); - return adventure_stats_entry; + e.player_id = results.LastInsertedID(); + return e; } - adventure_stats_entry = NewEntity(); + e = NewEntity(); - return adventure_stats_entry; + return e; } static int InsertMany( Database& db, - std::vector adventure_stats_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &adventure_stats_entry: adventure_stats_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(adventure_stats_entry.player_id)); - insert_values.push_back(std::to_string(adventure_stats_entry.guk_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.mir_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.mmc_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.ruj_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.tak_wins)); - insert_values.push_back(std::to_string(adventure_stats_entry.guk_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.mir_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.mmc_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.ruj_losses)); - insert_values.push_back(std::to_string(adventure_stats_entry.tak_losses)); + v.push_back(std::to_string(e.player_id)); + v.push_back(std::to_string(e.guk_wins)); + v.push_back(std::to_string(e.mir_wins)); + v.push_back(std::to_string(e.mmc_wins)); + v.push_back(std::to_string(e.ruj_wins)); + v.push_back(std::to_string(e.tak_wins)); + v.push_back(std::to_string(e.guk_losses)); + v.push_back(std::to_string(e.mir_losses)); + v.push_back(std::to_string(e.mmc_losses)); + v.push_back(std::to_string(e.ruj_losses)); + v.push_back(std::to_string(e.tak_losses)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -312,27 +312,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureStats entry{}; + AdventureStats e{}; - entry.player_id = atoi(row[0]); - entry.guk_wins = atoi(row[1]); - entry.mir_wins = atoi(row[2]); - entry.mmc_wins = atoi(row[3]); - entry.ruj_wins = atoi(row[4]); - entry.tak_wins = atoi(row[5]); - entry.guk_losses = atoi(row[6]); - entry.mir_losses = atoi(row[7]); - entry.mmc_losses = atoi(row[8]); - entry.ruj_losses = atoi(row[9]); - entry.tak_losses = atoi(row[10]); + e.player_id = static_cast(strtoul(row[0], nullptr, 10)); + e.guk_wins = static_cast(strtoul(row[1], nullptr, 10)); + e.mir_wins = static_cast(strtoul(row[2], nullptr, 10)); + e.mmc_wins = static_cast(strtoul(row[3], nullptr, 10)); + e.ruj_wins = static_cast(strtoul(row[4], nullptr, 10)); + e.tak_wins = static_cast(strtoul(row[5], nullptr, 10)); + e.guk_losses = static_cast(strtoul(row[6], nullptr, 10)); + e.mir_losses = static_cast(strtoul(row[7], nullptr, 10)); + e.mmc_losses = static_cast(strtoul(row[8], nullptr, 10)); + e.ruj_losses = static_cast(strtoul(row[9], nullptr, 10)); + e.tak_losses = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -347,27 +347,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureStats entry{}; + AdventureStats e{}; - entry.player_id = atoi(row[0]); - entry.guk_wins = atoi(row[1]); - entry.mir_wins = atoi(row[2]); - entry.mmc_wins = atoi(row[3]); - entry.ruj_wins = atoi(row[4]); - entry.tak_wins = atoi(row[5]); - entry.guk_losses = atoi(row[6]); - entry.mir_losses = atoi(row[7]); - entry.mmc_losses = atoi(row[8]); - entry.ruj_losses = atoi(row[9]); - entry.tak_losses = atoi(row[10]); + e.player_id = static_cast(strtoul(row[0], nullptr, 10)); + e.guk_wins = static_cast(strtoul(row[1], nullptr, 10)); + e.mir_wins = static_cast(strtoul(row[2], nullptr, 10)); + e.mmc_wins = static_cast(strtoul(row[3], nullptr, 10)); + e.ruj_wins = static_cast(strtoul(row[4], nullptr, 10)); + e.tak_wins = static_cast(strtoul(row[5], nullptr, 10)); + e.guk_losses = static_cast(strtoul(row[6], nullptr, 10)); + e.mir_losses = static_cast(strtoul(row[7], nullptr, 10)); + e.mmc_losses = static_cast(strtoul(row[8], nullptr, 10)); + e.ruj_losses = static_cast(strtoul(row[9], nullptr, 10)); + e.tak_losses = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -392,6 +392,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ADVENTURE_STATS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_template_entry_flavor_repository.h b/common/repositories/base/base_adventure_template_entry_flavor_repository.h index 808c3e9d5..0507f7e85 100644 --- a/common/repositories/base/base_adventure_template_entry_flavor_repository.h +++ b/common/repositories/base/base_adventure_template_entry_flavor_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAdventureTemplateEntryFlavorRepository { public: struct AdventureTemplateEntryFlavor { - int id; + uint32_t id; std::string text; }; @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static AdventureTemplateEntryFlavor NewEntity() { - AdventureTemplateEntryFlavor entry{}; + AdventureTemplateEntryFlavor e{}; - entry.id = 0; - entry.text = ""; + e.id = 0; + e.text = ""; - return entry; + return e; } - static AdventureTemplateEntryFlavor GetAdventureTemplateEntryFlavorEntry( + static AdventureTemplateEntryFlavor GetAdventureTemplateEntryFlavor( const std::vector &adventure_template_entry_flavors, int adventure_template_entry_flavor_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AdventureTemplateEntryFlavor entry{}; + AdventureTemplateEntryFlavor e{}; - entry.id = atoi(row[0]); - entry.text = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.text = row[1] ? row[1] : ""; - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - AdventureTemplateEntryFlavor adventure_template_entry_flavor_entry + const AdventureTemplateEntryFlavor &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(adventure_template_entry_flavor_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(adventure_template_entry_flavor_entry.text) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.text) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - adventure_template_entry_flavor_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static AdventureTemplateEntryFlavor InsertOne( Database& db, - AdventureTemplateEntryFlavor adventure_template_entry_flavor_entry + AdventureTemplateEntryFlavor e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(adventure_template_entry_flavor_entry.id)); - insert_values.push_back("'" + EscapeString(adventure_template_entry_flavor_entry.text) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.text) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - adventure_template_entry_flavor_entry.id = results.LastInsertedID(); - return adventure_template_entry_flavor_entry; + e.id = results.LastInsertedID(); + return e; } - adventure_template_entry_flavor_entry = NewEntity(); + e = NewEntity(); - return adventure_template_entry_flavor_entry; + return e; } static int InsertMany( Database& db, - std::vector adventure_template_entry_flavor_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &adventure_template_entry_flavor_entry: adventure_template_entry_flavor_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(adventure_template_entry_flavor_entry.id)); - insert_values.push_back("'" + EscapeString(adventure_template_entry_flavor_entry.text) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.text) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureTemplateEntryFlavor entry{}; + AdventureTemplateEntryFlavor e{}; - entry.id = atoi(row[0]); - entry.text = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.text = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureTemplateEntryFlavor entry{}; + AdventureTemplateEntryFlavor e{}; - entry.id = atoi(row[0]); - entry.text = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.text = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_template_entry_repository.h b/common/repositories/base/base_adventure_template_entry_repository.h index 7ae32df88..aad89b1d3 100644 --- a/common/repositories/base/base_adventure_template_entry_repository.h +++ b/common/repositories/base/base_adventure_template_entry_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAdventureTemplateEntryRepository { public: struct AdventureTemplateEntry { - int id; - int template_id; + uint32_t id; + uint32_t template_id; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static AdventureTemplateEntry NewEntity() { - AdventureTemplateEntry entry{}; + AdventureTemplateEntry e{}; - entry.id = 0; - entry.template_id = 0; + e.id = 0; + e.template_id = 0; - return entry; + return e; } - static AdventureTemplateEntry GetAdventureTemplateEntryEntry( + static AdventureTemplateEntry GetAdventureTemplateEntry( const std::vector &adventure_template_entrys, int adventure_template_entry_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AdventureTemplateEntry entry{}; + AdventureTemplateEntry e{}; - entry.id = atoi(row[0]); - entry.template_id = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.template_id = static_cast(strtoul(row[1], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - AdventureTemplateEntry adventure_template_entry_entry + const AdventureTemplateEntry &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(adventure_template_entry_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(adventure_template_entry_entry.template_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.template_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - adventure_template_entry_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static AdventureTemplateEntry InsertOne( Database& db, - AdventureTemplateEntry adventure_template_entry_entry + AdventureTemplateEntry e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(adventure_template_entry_entry.id)); - insert_values.push_back(std::to_string(adventure_template_entry_entry.template_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.template_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - adventure_template_entry_entry.id = results.LastInsertedID(); - return adventure_template_entry_entry; + e.id = results.LastInsertedID(); + return e; } - adventure_template_entry_entry = NewEntity(); + e = NewEntity(); - return adventure_template_entry_entry; + return e; } static int InsertMany( Database& db, - std::vector adventure_template_entry_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &adventure_template_entry_entry: adventure_template_entry_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(adventure_template_entry_entry.id)); - insert_values.push_back(std::to_string(adventure_template_entry_entry.template_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.template_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureTemplateEntry entry{}; + AdventureTemplateEntry e{}; - entry.id = atoi(row[0]); - entry.template_id = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.template_id = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureTemplateEntry entry{}; + AdventureTemplateEntry e{}; - entry.id = atoi(row[0]); - entry.template_id = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.template_id = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_template_repository.h b/common/repositories/base/base_adventure_template_repository.h index f9d2e150e..ce6540ce2 100644 --- a/common/repositories/base/base_adventure_template_repository.h +++ b/common/repositories/base/base_adventure_template_repository.h @@ -13,45 +13,45 @@ #define EQEMU_BASE_ADVENTURE_TEMPLATE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAdventureTemplateRepository { public: struct AdventureTemplate { - int id; + uint32_t id; std::string zone; - int zone_version; - int is_hard; - int is_raid; - int min_level; - int max_level; - int type; - int type_data; - int type_count; + uint8_t zone_version; + uint8_t is_hard; + uint8_t is_raid; + uint8_t min_level; + uint8_t max_level; + uint8_t type; + uint32_t type_data; + uint16_t type_count; float assa_x; float assa_y; float assa_z; float assa_h; std::string text; - int duration; - int zone_in_time; - int win_points; - int lose_points; - int theme; - int zone_in_zone_id; + uint32_t duration; + uint32_t zone_in_time; + uint16_t win_points; + uint16_t lose_points; + uint8_t theme; + uint16_t zone_in_zone_id; float zone_in_x; float zone_in_y; - int zone_in_object_id; + int16_t zone_in_object_id; float dest_x; float dest_y; float dest_z; float dest_h; - int graveyard_zone_id; + uint32_t graveyard_zone_id; float graveyard_x; float graveyard_y; float graveyard_z; - float graveyard_radius; + std::string graveyard_radius; }; static std::string PrimaryKey() @@ -139,12 +139,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -172,46 +172,46 @@ public: static AdventureTemplate NewEntity() { - AdventureTemplate entry{}; + AdventureTemplate e{}; - entry.id = 0; - entry.zone = ""; - entry.zone_version = 0; - entry.is_hard = 0; - entry.is_raid = 0; - entry.min_level = 1; - entry.max_level = 65; - entry.type = 0; - entry.type_data = 0; - entry.type_count = 0; - entry.assa_x = 0; - entry.assa_y = 0; - entry.assa_z = 0; - entry.assa_h = 0; - entry.text = ""; - entry.duration = 7200; - entry.zone_in_time = 1800; - entry.win_points = 0; - entry.lose_points = 0; - entry.theme = 1; - entry.zone_in_zone_id = 0; - entry.zone_in_x = 0; - entry.zone_in_y = 0; - entry.zone_in_object_id = 0; - entry.dest_x = 0; - entry.dest_y = 0; - entry.dest_z = 0; - entry.dest_h = 0; - entry.graveyard_zone_id = 0; - entry.graveyard_x = 0; - entry.graveyard_y = 0; - entry.graveyard_z = 0; - entry.graveyard_radius = 0; + e.id = 0; + e.zone = ""; + e.zone_version = 0; + e.is_hard = 0; + e.is_raid = 0; + e.min_level = 1; + e.max_level = 65; + e.type = 0; + e.type_data = 0; + e.type_count = 0; + e.assa_x = 0; + e.assa_y = 0; + e.assa_z = 0; + e.assa_h = 0; + e.text = ""; + e.duration = 7200; + e.zone_in_time = 1800; + e.win_points = 0; + e.lose_points = 0; + e.theme = 1; + e.zone_in_zone_id = 0; + e.zone_in_x = 0; + e.zone_in_y = 0; + e.zone_in_object_id = 0; + e.dest_x = 0; + e.dest_y = 0; + e.dest_z = 0; + e.dest_h = 0; + e.graveyard_zone_id = 0; + e.graveyard_x = 0; + e.graveyard_y = 0; + e.graveyard_z = 0; + e.graveyard_radius = 0; - return entry; + return e; } - static AdventureTemplate GetAdventureTemplateEntry( + static AdventureTemplate GetAdventureTemplate( const std::vector &adventure_templates, int adventure_template_id ) @@ -240,43 +240,42 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AdventureTemplate entry{}; + AdventureTemplate e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.zone_version = atoi(row[2]); - entry.is_hard = atoi(row[3]); - entry.is_raid = atoi(row[4]); - entry.min_level = atoi(row[5]); - entry.max_level = atoi(row[6]); - entry.type = atoi(row[7]); - entry.type_data = atoi(row[8]); - entry.type_count = atoi(row[9]); - entry.assa_x = static_cast(atof(row[10])); - entry.assa_y = static_cast(atof(row[11])); - entry.assa_z = static_cast(atof(row[12])); - entry.assa_h = static_cast(atof(row[13])); - entry.text = row[14] ? row[14] : ""; - entry.duration = atoi(row[15]); - entry.zone_in_time = atoi(row[16]); - entry.win_points = atoi(row[17]); - entry.lose_points = atoi(row[18]); - entry.theme = atoi(row[19]); - entry.zone_in_zone_id = atoi(row[20]); - entry.zone_in_x = static_cast(atof(row[21])); - entry.zone_in_y = static_cast(atof(row[22])); - entry.zone_in_object_id = atoi(row[23]); - entry.dest_x = static_cast(atof(row[24])); - entry.dest_y = static_cast(atof(row[25])); - entry.dest_z = static_cast(atof(row[26])); - entry.dest_h = static_cast(atof(row[27])); - entry.graveyard_zone_id = atoi(row[28]); - entry.graveyard_x = static_cast(atof(row[29])); - entry.graveyard_y = static_cast(atof(row[30])); - entry.graveyard_z = static_cast(atof(row[31])); - entry.graveyard_radius = static_cast(atof(row[32])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.zone_version = static_cast(strtoul(row[2], nullptr, 10)); + e.is_hard = static_cast(strtoul(row[3], nullptr, 10)); + e.is_raid = static_cast(strtoul(row[4], nullptr, 10)); + e.min_level = static_cast(strtoul(row[5], nullptr, 10)); + e.max_level = static_cast(strtoul(row[6], nullptr, 10)); + e.type = static_cast(strtoul(row[7], nullptr, 10)); + e.type_data = static_cast(strtoul(row[8], nullptr, 10)); + e.type_count = static_cast(strtoul(row[9], nullptr, 10)); + e.assa_x = strtof(row[10], nullptr); + e.assa_y = strtof(row[11], nullptr); + e.assa_z = strtof(row[12], nullptr); + e.assa_h = strtof(row[13], nullptr); + e.text = row[14] ? row[14] : ""; + e.duration = static_cast(strtoul(row[15], nullptr, 10)); + e.zone_in_time = static_cast(strtoul(row[16], nullptr, 10)); + e.win_points = static_cast(strtoul(row[17], nullptr, 10)); + e.lose_points = static_cast(strtoul(row[18], nullptr, 10)); + e.theme = static_cast(strtoul(row[19], nullptr, 10)); + e.zone_in_zone_id = static_cast(strtoul(row[20], nullptr, 10)); + e.zone_in_x = strtof(row[21], nullptr); + e.zone_in_y = strtof(row[22], nullptr); + e.zone_in_object_id = static_cast(atoi(row[23])); + e.dest_x = strtof(row[24], nullptr); + e.dest_y = strtof(row[25], nullptr); + e.dest_z = strtof(row[26], nullptr); + e.dest_h = strtof(row[27], nullptr); + e.graveyard_zone_id = static_cast(strtoul(row[28], nullptr, 10)); + e.graveyard_x = strtof(row[29], nullptr); + e.graveyard_y = strtof(row[30], nullptr); + e.graveyard_z = strtof(row[31], nullptr); - return entry; + return e; } return NewEntity(); @@ -301,54 +300,54 @@ public: static int UpdateOne( Database& db, - AdventureTemplate adventure_template_entry + const AdventureTemplate &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(adventure_template_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(adventure_template_entry.zone) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(adventure_template_entry.zone_version)); - update_values.push_back(columns[3] + " = " + std::to_string(adventure_template_entry.is_hard)); - update_values.push_back(columns[4] + " = " + std::to_string(adventure_template_entry.is_raid)); - update_values.push_back(columns[5] + " = " + std::to_string(adventure_template_entry.min_level)); - update_values.push_back(columns[6] + " = " + std::to_string(adventure_template_entry.max_level)); - update_values.push_back(columns[7] + " = " + std::to_string(adventure_template_entry.type)); - update_values.push_back(columns[8] + " = " + std::to_string(adventure_template_entry.type_data)); - update_values.push_back(columns[9] + " = " + std::to_string(adventure_template_entry.type_count)); - update_values.push_back(columns[10] + " = " + std::to_string(adventure_template_entry.assa_x)); - update_values.push_back(columns[11] + " = " + std::to_string(adventure_template_entry.assa_y)); - update_values.push_back(columns[12] + " = " + std::to_string(adventure_template_entry.assa_z)); - update_values.push_back(columns[13] + " = " + std::to_string(adventure_template_entry.assa_h)); - update_values.push_back(columns[14] + " = '" + EscapeString(adventure_template_entry.text) + "'"); - update_values.push_back(columns[15] + " = " + std::to_string(adventure_template_entry.duration)); - update_values.push_back(columns[16] + " = " + std::to_string(adventure_template_entry.zone_in_time)); - update_values.push_back(columns[17] + " = " + std::to_string(adventure_template_entry.win_points)); - update_values.push_back(columns[18] + " = " + std::to_string(adventure_template_entry.lose_points)); - update_values.push_back(columns[19] + " = " + std::to_string(adventure_template_entry.theme)); - update_values.push_back(columns[20] + " = " + std::to_string(adventure_template_entry.zone_in_zone_id)); - update_values.push_back(columns[21] + " = " + std::to_string(adventure_template_entry.zone_in_x)); - update_values.push_back(columns[22] + " = " + std::to_string(adventure_template_entry.zone_in_y)); - update_values.push_back(columns[23] + " = " + std::to_string(adventure_template_entry.zone_in_object_id)); - update_values.push_back(columns[24] + " = " + std::to_string(adventure_template_entry.dest_x)); - update_values.push_back(columns[25] + " = " + std::to_string(adventure_template_entry.dest_y)); - update_values.push_back(columns[26] + " = " + std::to_string(adventure_template_entry.dest_z)); - update_values.push_back(columns[27] + " = " + std::to_string(adventure_template_entry.dest_h)); - update_values.push_back(columns[28] + " = " + std::to_string(adventure_template_entry.graveyard_zone_id)); - update_values.push_back(columns[29] + " = " + std::to_string(adventure_template_entry.graveyard_x)); - update_values.push_back(columns[30] + " = " + std::to_string(adventure_template_entry.graveyard_y)); - update_values.push_back(columns[31] + " = " + std::to_string(adventure_template_entry.graveyard_z)); - update_values.push_back(columns[32] + " = " + std::to_string(adventure_template_entry.graveyard_radius)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.zone_version)); + v.push_back(columns[3] + " = " + std::to_string(e.is_hard)); + v.push_back(columns[4] + " = " + std::to_string(e.is_raid)); + v.push_back(columns[5] + " = " + std::to_string(e.min_level)); + v.push_back(columns[6] + " = " + std::to_string(e.max_level)); + v.push_back(columns[7] + " = " + std::to_string(e.type)); + v.push_back(columns[8] + " = " + std::to_string(e.type_data)); + v.push_back(columns[9] + " = " + std::to_string(e.type_count)); + v.push_back(columns[10] + " = " + std::to_string(e.assa_x)); + v.push_back(columns[11] + " = " + std::to_string(e.assa_y)); + v.push_back(columns[12] + " = " + std::to_string(e.assa_z)); + v.push_back(columns[13] + " = " + std::to_string(e.assa_h)); + v.push_back(columns[14] + " = '" + Strings::Escape(e.text) + "'"); + v.push_back(columns[15] + " = " + std::to_string(e.duration)); + v.push_back(columns[16] + " = " + std::to_string(e.zone_in_time)); + v.push_back(columns[17] + " = " + std::to_string(e.win_points)); + v.push_back(columns[18] + " = " + std::to_string(e.lose_points)); + v.push_back(columns[19] + " = " + std::to_string(e.theme)); + v.push_back(columns[20] + " = " + std::to_string(e.zone_in_zone_id)); + v.push_back(columns[21] + " = " + std::to_string(e.zone_in_x)); + v.push_back(columns[22] + " = " + std::to_string(e.zone_in_y)); + v.push_back(columns[23] + " = " + std::to_string(e.zone_in_object_id)); + v.push_back(columns[24] + " = " + std::to_string(e.dest_x)); + v.push_back(columns[25] + " = " + std::to_string(e.dest_y)); + v.push_back(columns[26] + " = " + std::to_string(e.dest_z)); + v.push_back(columns[27] + " = " + std::to_string(e.dest_h)); + v.push_back(columns[28] + " = " + std::to_string(e.graveyard_zone_id)); + v.push_back(columns[29] + " = " + std::to_string(e.graveyard_x)); + v.push_back(columns[30] + " = " + std::to_string(e.graveyard_y)); + v.push_back(columns[31] + " = " + std::to_string(e.graveyard_z)); + v.push_back(columns[32] + " = " + std::to_string(e.graveyard_radius)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - adventure_template_entry.id + e.id ) ); @@ -357,117 +356,117 @@ public: static AdventureTemplate InsertOne( Database& db, - AdventureTemplate adventure_template_entry + AdventureTemplate e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(adventure_template_entry.id)); - insert_values.push_back("'" + EscapeString(adventure_template_entry.zone) + "'"); - insert_values.push_back(std::to_string(adventure_template_entry.zone_version)); - insert_values.push_back(std::to_string(adventure_template_entry.is_hard)); - insert_values.push_back(std::to_string(adventure_template_entry.is_raid)); - insert_values.push_back(std::to_string(adventure_template_entry.min_level)); - insert_values.push_back(std::to_string(adventure_template_entry.max_level)); - insert_values.push_back(std::to_string(adventure_template_entry.type)); - insert_values.push_back(std::to_string(adventure_template_entry.type_data)); - insert_values.push_back(std::to_string(adventure_template_entry.type_count)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_x)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_y)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_z)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_h)); - insert_values.push_back("'" + EscapeString(adventure_template_entry.text) + "'"); - insert_values.push_back(std::to_string(adventure_template_entry.duration)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_time)); - insert_values.push_back(std::to_string(adventure_template_entry.win_points)); - insert_values.push_back(std::to_string(adventure_template_entry.lose_points)); - insert_values.push_back(std::to_string(adventure_template_entry.theme)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_zone_id)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_x)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_y)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_object_id)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_x)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_y)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_z)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_h)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_zone_id)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_x)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_y)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_z)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_radius)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.zone_version)); + v.push_back(std::to_string(e.is_hard)); + v.push_back(std::to_string(e.is_raid)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.type_data)); + v.push_back(std::to_string(e.type_count)); + v.push_back(std::to_string(e.assa_x)); + v.push_back(std::to_string(e.assa_y)); + v.push_back(std::to_string(e.assa_z)); + v.push_back(std::to_string(e.assa_h)); + v.push_back("'" + Strings::Escape(e.text) + "'"); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.zone_in_time)); + v.push_back(std::to_string(e.win_points)); + v.push_back(std::to_string(e.lose_points)); + v.push_back(std::to_string(e.theme)); + v.push_back(std::to_string(e.zone_in_zone_id)); + v.push_back(std::to_string(e.zone_in_x)); + v.push_back(std::to_string(e.zone_in_y)); + v.push_back(std::to_string(e.zone_in_object_id)); + v.push_back(std::to_string(e.dest_x)); + v.push_back(std::to_string(e.dest_y)); + v.push_back(std::to_string(e.dest_z)); + v.push_back(std::to_string(e.dest_h)); + v.push_back(std::to_string(e.graveyard_zone_id)); + v.push_back(std::to_string(e.graveyard_x)); + v.push_back(std::to_string(e.graveyard_y)); + v.push_back(std::to_string(e.graveyard_z)); + v.push_back(std::to_string(e.graveyard_radius)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - adventure_template_entry.id = results.LastInsertedID(); - return adventure_template_entry; + e.id = results.LastInsertedID(); + return e; } - adventure_template_entry = NewEntity(); + e = NewEntity(); - return adventure_template_entry; + return e; } static int InsertMany( Database& db, - std::vector adventure_template_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &adventure_template_entry: adventure_template_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(adventure_template_entry.id)); - insert_values.push_back("'" + EscapeString(adventure_template_entry.zone) + "'"); - insert_values.push_back(std::to_string(adventure_template_entry.zone_version)); - insert_values.push_back(std::to_string(adventure_template_entry.is_hard)); - insert_values.push_back(std::to_string(adventure_template_entry.is_raid)); - insert_values.push_back(std::to_string(adventure_template_entry.min_level)); - insert_values.push_back(std::to_string(adventure_template_entry.max_level)); - insert_values.push_back(std::to_string(adventure_template_entry.type)); - insert_values.push_back(std::to_string(adventure_template_entry.type_data)); - insert_values.push_back(std::to_string(adventure_template_entry.type_count)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_x)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_y)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_z)); - insert_values.push_back(std::to_string(adventure_template_entry.assa_h)); - insert_values.push_back("'" + EscapeString(adventure_template_entry.text) + "'"); - insert_values.push_back(std::to_string(adventure_template_entry.duration)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_time)); - insert_values.push_back(std::to_string(adventure_template_entry.win_points)); - insert_values.push_back(std::to_string(adventure_template_entry.lose_points)); - insert_values.push_back(std::to_string(adventure_template_entry.theme)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_zone_id)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_x)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_y)); - insert_values.push_back(std::to_string(adventure_template_entry.zone_in_object_id)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_x)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_y)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_z)); - insert_values.push_back(std::to_string(adventure_template_entry.dest_h)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_zone_id)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_x)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_y)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_z)); - insert_values.push_back(std::to_string(adventure_template_entry.graveyard_radius)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.zone_version)); + v.push_back(std::to_string(e.is_hard)); + v.push_back(std::to_string(e.is_raid)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.type_data)); + v.push_back(std::to_string(e.type_count)); + v.push_back(std::to_string(e.assa_x)); + v.push_back(std::to_string(e.assa_y)); + v.push_back(std::to_string(e.assa_z)); + v.push_back(std::to_string(e.assa_h)); + v.push_back("'" + Strings::Escape(e.text) + "'"); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.zone_in_time)); + v.push_back(std::to_string(e.win_points)); + v.push_back(std::to_string(e.lose_points)); + v.push_back(std::to_string(e.theme)); + v.push_back(std::to_string(e.zone_in_zone_id)); + v.push_back(std::to_string(e.zone_in_x)); + v.push_back(std::to_string(e.zone_in_y)); + v.push_back(std::to_string(e.zone_in_object_id)); + v.push_back(std::to_string(e.dest_x)); + v.push_back(std::to_string(e.dest_y)); + v.push_back(std::to_string(e.dest_z)); + v.push_back(std::to_string(e.dest_h)); + v.push_back(std::to_string(e.graveyard_zone_id)); + v.push_back(std::to_string(e.graveyard_x)); + v.push_back(std::to_string(e.graveyard_y)); + v.push_back(std::to_string(e.graveyard_z)); + v.push_back(std::to_string(e.graveyard_radius)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -488,49 +487,48 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureTemplate entry{}; + AdventureTemplate e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.zone_version = atoi(row[2]); - entry.is_hard = atoi(row[3]); - entry.is_raid = atoi(row[4]); - entry.min_level = atoi(row[5]); - entry.max_level = atoi(row[6]); - entry.type = atoi(row[7]); - entry.type_data = atoi(row[8]); - entry.type_count = atoi(row[9]); - entry.assa_x = static_cast(atof(row[10])); - entry.assa_y = static_cast(atof(row[11])); - entry.assa_z = static_cast(atof(row[12])); - entry.assa_h = static_cast(atof(row[13])); - entry.text = row[14] ? row[14] : ""; - entry.duration = atoi(row[15]); - entry.zone_in_time = atoi(row[16]); - entry.win_points = atoi(row[17]); - entry.lose_points = atoi(row[18]); - entry.theme = atoi(row[19]); - entry.zone_in_zone_id = atoi(row[20]); - entry.zone_in_x = static_cast(atof(row[21])); - entry.zone_in_y = static_cast(atof(row[22])); - entry.zone_in_object_id = atoi(row[23]); - entry.dest_x = static_cast(atof(row[24])); - entry.dest_y = static_cast(atof(row[25])); - entry.dest_z = static_cast(atof(row[26])); - entry.dest_h = static_cast(atof(row[27])); - entry.graveyard_zone_id = atoi(row[28]); - entry.graveyard_x = static_cast(atof(row[29])); - entry.graveyard_y = static_cast(atof(row[30])); - entry.graveyard_z = static_cast(atof(row[31])); - entry.graveyard_radius = static_cast(atof(row[32])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.zone_version = static_cast(strtoul(row[2], nullptr, 10)); + e.is_hard = static_cast(strtoul(row[3], nullptr, 10)); + e.is_raid = static_cast(strtoul(row[4], nullptr, 10)); + e.min_level = static_cast(strtoul(row[5], nullptr, 10)); + e.max_level = static_cast(strtoul(row[6], nullptr, 10)); + e.type = static_cast(strtoul(row[7], nullptr, 10)); + e.type_data = static_cast(strtoul(row[8], nullptr, 10)); + e.type_count = static_cast(strtoul(row[9], nullptr, 10)); + e.assa_x = strtof(row[10], nullptr); + e.assa_y = strtof(row[11], nullptr); + e.assa_z = strtof(row[12], nullptr); + e.assa_h = strtof(row[13], nullptr); + e.text = row[14] ? row[14] : ""; + e.duration = static_cast(strtoul(row[15], nullptr, 10)); + e.zone_in_time = static_cast(strtoul(row[16], nullptr, 10)); + e.win_points = static_cast(strtoul(row[17], nullptr, 10)); + e.lose_points = static_cast(strtoul(row[18], nullptr, 10)); + e.theme = static_cast(strtoul(row[19], nullptr, 10)); + e.zone_in_zone_id = static_cast(strtoul(row[20], nullptr, 10)); + e.zone_in_x = strtof(row[21], nullptr); + e.zone_in_y = strtof(row[22], nullptr); + e.zone_in_object_id = static_cast(atoi(row[23])); + e.dest_x = strtof(row[24], nullptr); + e.dest_y = strtof(row[25], nullptr); + e.dest_z = strtof(row[26], nullptr); + e.dest_h = strtof(row[27], nullptr); + e.graveyard_zone_id = static_cast(strtoul(row[28], nullptr, 10)); + e.graveyard_x = strtof(row[29], nullptr); + e.graveyard_y = strtof(row[30], nullptr); + e.graveyard_z = strtof(row[31], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -545,49 +543,48 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AdventureTemplate entry{}; + AdventureTemplate e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.zone_version = atoi(row[2]); - entry.is_hard = atoi(row[3]); - entry.is_raid = atoi(row[4]); - entry.min_level = atoi(row[5]); - entry.max_level = atoi(row[6]); - entry.type = atoi(row[7]); - entry.type_data = atoi(row[8]); - entry.type_count = atoi(row[9]); - entry.assa_x = static_cast(atof(row[10])); - entry.assa_y = static_cast(atof(row[11])); - entry.assa_z = static_cast(atof(row[12])); - entry.assa_h = static_cast(atof(row[13])); - entry.text = row[14] ? row[14] : ""; - entry.duration = atoi(row[15]); - entry.zone_in_time = atoi(row[16]); - entry.win_points = atoi(row[17]); - entry.lose_points = atoi(row[18]); - entry.theme = atoi(row[19]); - entry.zone_in_zone_id = atoi(row[20]); - entry.zone_in_x = static_cast(atof(row[21])); - entry.zone_in_y = static_cast(atof(row[22])); - entry.zone_in_object_id = atoi(row[23]); - entry.dest_x = static_cast(atof(row[24])); - entry.dest_y = static_cast(atof(row[25])); - entry.dest_z = static_cast(atof(row[26])); - entry.dest_h = static_cast(atof(row[27])); - entry.graveyard_zone_id = atoi(row[28]); - entry.graveyard_x = static_cast(atof(row[29])); - entry.graveyard_y = static_cast(atof(row[30])); - entry.graveyard_z = static_cast(atof(row[31])); - entry.graveyard_radius = static_cast(atof(row[32])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.zone_version = static_cast(strtoul(row[2], nullptr, 10)); + e.is_hard = static_cast(strtoul(row[3], nullptr, 10)); + e.is_raid = static_cast(strtoul(row[4], nullptr, 10)); + e.min_level = static_cast(strtoul(row[5], nullptr, 10)); + e.max_level = static_cast(strtoul(row[6], nullptr, 10)); + e.type = static_cast(strtoul(row[7], nullptr, 10)); + e.type_data = static_cast(strtoul(row[8], nullptr, 10)); + e.type_count = static_cast(strtoul(row[9], nullptr, 10)); + e.assa_x = strtof(row[10], nullptr); + e.assa_y = strtof(row[11], nullptr); + e.assa_z = strtof(row[12], nullptr); + e.assa_h = strtof(row[13], nullptr); + e.text = row[14] ? row[14] : ""; + e.duration = static_cast(strtoul(row[15], nullptr, 10)); + e.zone_in_time = static_cast(strtoul(row[16], nullptr, 10)); + e.win_points = static_cast(strtoul(row[17], nullptr, 10)); + e.lose_points = static_cast(strtoul(row[18], nullptr, 10)); + e.theme = static_cast(strtoul(row[19], nullptr, 10)); + e.zone_in_zone_id = static_cast(strtoul(row[20], nullptr, 10)); + e.zone_in_x = strtof(row[21], nullptr); + e.zone_in_y = strtof(row[22], nullptr); + e.zone_in_object_id = static_cast(atoi(row[23])); + e.dest_x = strtof(row[24], nullptr); + e.dest_y = strtof(row[25], nullptr); + e.dest_z = strtof(row[26], nullptr); + e.dest_h = strtof(row[27], nullptr); + e.graveyard_zone_id = static_cast(strtoul(row[28], nullptr, 10)); + e.graveyard_x = strtof(row[29], nullptr); + e.graveyard_y = strtof(row[30], nullptr); + e.graveyard_z = strtof(row[31], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -612,6 +609,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ADVENTURE_TEMPLATE_REPOSITORY_H diff --git a/common/repositories/base/base_alternate_currency_repository.h b/common/repositories/base/base_alternate_currency_repository.h index 187309a05..10798b859 100644 --- a/common/repositories/base/base_alternate_currency_repository.h +++ b/common/repositories/base/base_alternate_currency_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_ALTERNATE_CURRENCY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAlternateCurrencyRepository { public: struct AlternateCurrency { - int id; - int item_id; + int32_t id; + int32_t item_id; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static AlternateCurrency NewEntity() { - AlternateCurrency entry{}; + AlternateCurrency e{}; - entry.id = 0; - entry.item_id = 0; + e.id = 0; + e.item_id = 0; - return entry; + return e; } - static AlternateCurrency GetAlternateCurrencyEntry( + static AlternateCurrency GetAlternateCurrency( const std::vector &alternate_currencys, int alternate_currency_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - AlternateCurrency entry{}; + AlternateCurrency e{}; - entry.id = atoi(row[0]); - entry.item_id = atoi(row[1]); + e.id = static_cast(atoi(row[0])); + e.item_id = static_cast(atoi(row[1])); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - AlternateCurrency alternate_currency_entry + const AlternateCurrency &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(alternate_currency_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(alternate_currency_entry.item_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - alternate_currency_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static AlternateCurrency InsertOne( Database& db, - AlternateCurrency alternate_currency_entry + AlternateCurrency e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(alternate_currency_entry.id)); - insert_values.push_back(std::to_string(alternate_currency_entry.item_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - alternate_currency_entry.id = results.LastInsertedID(); - return alternate_currency_entry; + e.id = results.LastInsertedID(); + return e; } - alternate_currency_entry = NewEntity(); + e = NewEntity(); - return alternate_currency_entry; + return e; } static int InsertMany( Database& db, - std::vector alternate_currency_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &alternate_currency_entry: alternate_currency_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(alternate_currency_entry.id)); - insert_values.push_back(std::to_string(alternate_currency_entry.item_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.item_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AlternateCurrency entry{}; + AlternateCurrency e{}; - entry.id = atoi(row[0]); - entry.item_id = atoi(row[1]); + e.id = static_cast(atoi(row[0])); + e.item_id = static_cast(atoi(row[1])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - AlternateCurrency entry{}; + AlternateCurrency e{}; - entry.id = atoi(row[0]); - entry.item_id = atoi(row[1]); + e.id = static_cast(atoi(row[0])); + e.item_id = static_cast(atoi(row[1])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ALTERNATE_CURRENCY_REPOSITORY_H diff --git a/common/repositories/base/base_auras_repository.h b/common/repositories/base/base_auras_repository.h index 98838bc51..e527fa8aa 100644 --- a/common/repositories/base/base_auras_repository.h +++ b/common/repositories/base/base_auras_repository.h @@ -13,23 +13,23 @@ #define EQEMU_BASE_AURAS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseAurasRepository { public: struct Auras { - int type; - int npc_type; + int32_t type; + int32_t npc_type; std::string name; - int spell_id; - int distance; - int aura_type; - int spawn_type; - int movement; - int duration; - int icon; - int cast_time; + int32_t spell_id; + int32_t distance; + int32_t aura_type; + int32_t spawn_type; + int32_t movement; + int32_t duration; + int32_t icon; + int32_t cast_time; }; static std::string PrimaryKey() @@ -73,12 +73,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -106,24 +106,24 @@ public: static Auras NewEntity() { - Auras entry{}; + Auras e{}; - entry.type = 0; - entry.npc_type = 0; - entry.name = ""; - entry.spell_id = 0; - entry.distance = 60; - entry.aura_type = 1; - entry.spawn_type = 0; - entry.movement = 0; - entry.duration = 5400; - entry.icon = -1; - entry.cast_time = 0; + e.type = 0; + e.npc_type = 0; + e.name = ""; + e.spell_id = 0; + e.distance = 60; + e.aura_type = 1; + e.spawn_type = 0; + e.movement = 0; + e.duration = 5400; + e.icon = -1; + e.cast_time = 0; - return entry; + return e; } - static Auras GetAurasEntry( + static Auras GetAuras( const std::vector &aurass, int auras_id ) @@ -152,21 +152,21 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Auras entry{}; + Auras e{}; - entry.type = atoi(row[0]); - entry.npc_type = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.spell_id = atoi(row[3]); - entry.distance = atoi(row[4]); - entry.aura_type = atoi(row[5]); - entry.spawn_type = atoi(row[6]); - entry.movement = atoi(row[7]); - entry.duration = atoi(row[8]); - entry.icon = atoi(row[9]); - entry.cast_time = atoi(row[10]); + e.type = static_cast(atoi(row[0])); + e.npc_type = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.spell_id = static_cast(atoi(row[3])); + e.distance = static_cast(atoi(row[4])); + e.aura_type = static_cast(atoi(row[5])); + e.spawn_type = static_cast(atoi(row[6])); + e.movement = static_cast(atoi(row[7])); + e.duration = static_cast(atoi(row[8])); + e.icon = static_cast(atoi(row[9])); + e.cast_time = static_cast(atoi(row[10])); - return entry; + return e; } return NewEntity(); @@ -191,32 +191,32 @@ public: static int UpdateOne( Database& db, - Auras auras_entry + const Auras &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(auras_entry.type)); - update_values.push_back(columns[1] + " = " + std::to_string(auras_entry.npc_type)); - update_values.push_back(columns[2] + " = '" + EscapeString(auras_entry.name) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(auras_entry.spell_id)); - update_values.push_back(columns[4] + " = " + std::to_string(auras_entry.distance)); - update_values.push_back(columns[5] + " = " + std::to_string(auras_entry.aura_type)); - update_values.push_back(columns[6] + " = " + std::to_string(auras_entry.spawn_type)); - update_values.push_back(columns[7] + " = " + std::to_string(auras_entry.movement)); - update_values.push_back(columns[8] + " = " + std::to_string(auras_entry.duration)); - update_values.push_back(columns[9] + " = " + std::to_string(auras_entry.icon)); - update_values.push_back(columns[10] + " = " + std::to_string(auras_entry.cast_time)); + v.push_back(columns[0] + " = " + std::to_string(e.type)); + v.push_back(columns[1] + " = " + std::to_string(e.npc_type)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[4] + " = " + std::to_string(e.distance)); + v.push_back(columns[5] + " = " + std::to_string(e.aura_type)); + v.push_back(columns[6] + " = " + std::to_string(e.spawn_type)); + v.push_back(columns[7] + " = " + std::to_string(e.movement)); + v.push_back(columns[8] + " = " + std::to_string(e.duration)); + v.push_back(columns[9] + " = " + std::to_string(e.icon)); + v.push_back(columns[10] + " = " + std::to_string(e.cast_time)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - auras_entry.type + e.type ) ); @@ -225,73 +225,73 @@ public: static Auras InsertOne( Database& db, - Auras auras_entry + Auras e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(auras_entry.type)); - insert_values.push_back(std::to_string(auras_entry.npc_type)); - insert_values.push_back("'" + EscapeString(auras_entry.name) + "'"); - insert_values.push_back(std::to_string(auras_entry.spell_id)); - insert_values.push_back(std::to_string(auras_entry.distance)); - insert_values.push_back(std::to_string(auras_entry.aura_type)); - insert_values.push_back(std::to_string(auras_entry.spawn_type)); - insert_values.push_back(std::to_string(auras_entry.movement)); - insert_values.push_back(std::to_string(auras_entry.duration)); - insert_values.push_back(std::to_string(auras_entry.icon)); - insert_values.push_back(std::to_string(auras_entry.cast_time)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.npc_type)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.distance)); + v.push_back(std::to_string(e.aura_type)); + v.push_back(std::to_string(e.spawn_type)); + v.push_back(std::to_string(e.movement)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.icon)); + v.push_back(std::to_string(e.cast_time)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - auras_entry.type = results.LastInsertedID(); - return auras_entry; + e.type = results.LastInsertedID(); + return e; } - auras_entry = NewEntity(); + e = NewEntity(); - return auras_entry; + return e; } static int InsertMany( Database& db, - std::vector auras_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &auras_entry: auras_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(auras_entry.type)); - insert_values.push_back(std::to_string(auras_entry.npc_type)); - insert_values.push_back("'" + EscapeString(auras_entry.name) + "'"); - insert_values.push_back(std::to_string(auras_entry.spell_id)); - insert_values.push_back(std::to_string(auras_entry.distance)); - insert_values.push_back(std::to_string(auras_entry.aura_type)); - insert_values.push_back(std::to_string(auras_entry.spawn_type)); - insert_values.push_back(std::to_string(auras_entry.movement)); - insert_values.push_back(std::to_string(auras_entry.duration)); - insert_values.push_back(std::to_string(auras_entry.icon)); - insert_values.push_back(std::to_string(auras_entry.cast_time)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.npc_type)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.distance)); + v.push_back(std::to_string(e.aura_type)); + v.push_back(std::to_string(e.spawn_type)); + v.push_back(std::to_string(e.movement)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.icon)); + v.push_back(std::to_string(e.cast_time)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -312,27 +312,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Auras entry{}; + Auras e{}; - entry.type = atoi(row[0]); - entry.npc_type = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.spell_id = atoi(row[3]); - entry.distance = atoi(row[4]); - entry.aura_type = atoi(row[5]); - entry.spawn_type = atoi(row[6]); - entry.movement = atoi(row[7]); - entry.duration = atoi(row[8]); - entry.icon = atoi(row[9]); - entry.cast_time = atoi(row[10]); + e.type = static_cast(atoi(row[0])); + e.npc_type = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.spell_id = static_cast(atoi(row[3])); + e.distance = static_cast(atoi(row[4])); + e.aura_type = static_cast(atoi(row[5])); + e.spawn_type = static_cast(atoi(row[6])); + e.movement = static_cast(atoi(row[7])); + e.duration = static_cast(atoi(row[8])); + e.icon = static_cast(atoi(row[9])); + e.cast_time = static_cast(atoi(row[10])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -347,27 +347,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Auras entry{}; + Auras e{}; - entry.type = atoi(row[0]); - entry.npc_type = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.spell_id = atoi(row[3]); - entry.distance = atoi(row[4]); - entry.aura_type = atoi(row[5]); - entry.spawn_type = atoi(row[6]); - entry.movement = atoi(row[7]); - entry.duration = atoi(row[8]); - entry.icon = atoi(row[9]); - entry.cast_time = atoi(row[10]); + e.type = static_cast(atoi(row[0])); + e.npc_type = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.spell_id = static_cast(atoi(row[3])); + e.distance = static_cast(atoi(row[4])); + e.aura_type = static_cast(atoi(row[5])); + e.spawn_type = static_cast(atoi(row[6])); + e.movement = static_cast(atoi(row[7])); + e.duration = static_cast(atoi(row[8])); + e.icon = static_cast(atoi(row[9])); + e.cast_time = static_cast(atoi(row[10])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -392,6 +392,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_AURAS_REPOSITORY_H diff --git a/common/repositories/base/base_base_data_repository.h b/common/repositories/base/base_base_data_repository.h index aa848aa75..8b41d99a8 100644 --- a/common/repositories/base/base_base_data_repository.h +++ b/common/repositories/base/base_base_data_repository.h @@ -13,22 +13,22 @@ #define EQEMU_BASE_BASE_DATA_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseBaseDataRepository { public: struct BaseData { - int level; - int class_; - float hp; - float mana; - float end; - float unk1; - float unk2; - float hp_fac; - float mana_fac; - float end_fac; + uint32_t level; + uint32_t class_; + double hp; + double mana; + double end; + double unk1; + double unk2; + double hp_fac; + double mana_fac; + double end_fac; }; static std::string PrimaryKey() @@ -70,12 +70,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -103,23 +103,23 @@ public: static BaseData NewEntity() { - BaseData entry{}; + BaseData e{}; - entry.level = 0; - entry.class_ = 0; - entry.hp = 0; - entry.mana = 0; - entry.end = 0; - entry.unk1 = 0; - entry.unk2 = 0; - entry.hp_fac = 0; - entry.mana_fac = 0; - entry.end_fac = 0; + e.level = 0; + e.class_ = 0; + e.hp = 0; + e.mana = 0; + e.end = 0; + e.unk1 = 0; + e.unk2 = 0; + e.hp_fac = 0; + e.mana_fac = 0; + e.end_fac = 0; - return entry; + return e; } - static BaseData GetBaseDataEntry( + static BaseData GetBaseData( const std::vector &base_datas, int base_data_id ) @@ -148,20 +148,20 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - BaseData entry{}; + BaseData e{}; - entry.level = atoi(row[0]); - entry.class_ = atoi(row[1]); - entry.hp = static_cast(atof(row[2])); - entry.mana = static_cast(atof(row[3])); - entry.end = static_cast(atof(row[4])); - entry.unk1 = static_cast(atof(row[5])); - entry.unk2 = static_cast(atof(row[6])); - entry.hp_fac = static_cast(atof(row[7])); - entry.mana_fac = static_cast(atof(row[8])); - entry.end_fac = static_cast(atof(row[9])); + e.level = static_cast(strtoul(row[0], nullptr, 10)); + e.class_ = static_cast(strtoul(row[1], nullptr, 10)); + e.hp = strtod(row[2], nullptr); + e.mana = strtod(row[3], nullptr); + e.end = strtod(row[4], nullptr); + e.unk1 = strtod(row[5], nullptr); + e.unk2 = strtod(row[6], nullptr); + e.hp_fac = strtod(row[7], nullptr); + e.mana_fac = strtod(row[8], nullptr); + e.end_fac = strtod(row[9], nullptr); - return entry; + return e; } return NewEntity(); @@ -186,31 +186,31 @@ public: static int UpdateOne( Database& db, - BaseData base_data_entry + const BaseData &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(base_data_entry.level)); - update_values.push_back(columns[1] + " = " + std::to_string(base_data_entry.class_)); - update_values.push_back(columns[2] + " = " + std::to_string(base_data_entry.hp)); - update_values.push_back(columns[3] + " = " + std::to_string(base_data_entry.mana)); - update_values.push_back(columns[4] + " = " + std::to_string(base_data_entry.end)); - update_values.push_back(columns[5] + " = " + std::to_string(base_data_entry.unk1)); - update_values.push_back(columns[6] + " = " + std::to_string(base_data_entry.unk2)); - update_values.push_back(columns[7] + " = " + std::to_string(base_data_entry.hp_fac)); - update_values.push_back(columns[8] + " = " + std::to_string(base_data_entry.mana_fac)); - update_values.push_back(columns[9] + " = " + std::to_string(base_data_entry.end_fac)); + v.push_back(columns[0] + " = " + std::to_string(e.level)); + v.push_back(columns[1] + " = " + std::to_string(e.class_)); + v.push_back(columns[2] + " = " + std::to_string(e.hp)); + v.push_back(columns[3] + " = " + std::to_string(e.mana)); + v.push_back(columns[4] + " = " + std::to_string(e.end)); + v.push_back(columns[5] + " = " + std::to_string(e.unk1)); + v.push_back(columns[6] + " = " + std::to_string(e.unk2)); + v.push_back(columns[7] + " = " + std::to_string(e.hp_fac)); + v.push_back(columns[8] + " = " + std::to_string(e.mana_fac)); + v.push_back(columns[9] + " = " + std::to_string(e.end_fac)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - base_data_entry.level + e.level ) ); @@ -219,71 +219,71 @@ public: static BaseData InsertOne( Database& db, - BaseData base_data_entry + BaseData e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(base_data_entry.level)); - insert_values.push_back(std::to_string(base_data_entry.class_)); - insert_values.push_back(std::to_string(base_data_entry.hp)); - insert_values.push_back(std::to_string(base_data_entry.mana)); - insert_values.push_back(std::to_string(base_data_entry.end)); - insert_values.push_back(std::to_string(base_data_entry.unk1)); - insert_values.push_back(std::to_string(base_data_entry.unk2)); - insert_values.push_back(std::to_string(base_data_entry.hp_fac)); - insert_values.push_back(std::to_string(base_data_entry.mana_fac)); - insert_values.push_back(std::to_string(base_data_entry.end_fac)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.end)); + v.push_back(std::to_string(e.unk1)); + v.push_back(std::to_string(e.unk2)); + v.push_back(std::to_string(e.hp_fac)); + v.push_back(std::to_string(e.mana_fac)); + v.push_back(std::to_string(e.end_fac)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - base_data_entry.level = results.LastInsertedID(); - return base_data_entry; + e.level = results.LastInsertedID(); + return e; } - base_data_entry = NewEntity(); + e = NewEntity(); - return base_data_entry; + return e; } static int InsertMany( Database& db, - std::vector base_data_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &base_data_entry: base_data_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(base_data_entry.level)); - insert_values.push_back(std::to_string(base_data_entry.class_)); - insert_values.push_back(std::to_string(base_data_entry.hp)); - insert_values.push_back(std::to_string(base_data_entry.mana)); - insert_values.push_back(std::to_string(base_data_entry.end)); - insert_values.push_back(std::to_string(base_data_entry.unk1)); - insert_values.push_back(std::to_string(base_data_entry.unk2)); - insert_values.push_back(std::to_string(base_data_entry.hp_fac)); - insert_values.push_back(std::to_string(base_data_entry.mana_fac)); - insert_values.push_back(std::to_string(base_data_entry.end_fac)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.end)); + v.push_back(std::to_string(e.unk1)); + v.push_back(std::to_string(e.unk2)); + v.push_back(std::to_string(e.hp_fac)); + v.push_back(std::to_string(e.mana_fac)); + v.push_back(std::to_string(e.end_fac)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -304,26 +304,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - BaseData entry{}; + BaseData e{}; - entry.level = atoi(row[0]); - entry.class_ = atoi(row[1]); - entry.hp = static_cast(atof(row[2])); - entry.mana = static_cast(atof(row[3])); - entry.end = static_cast(atof(row[4])); - entry.unk1 = static_cast(atof(row[5])); - entry.unk2 = static_cast(atof(row[6])); - entry.hp_fac = static_cast(atof(row[7])); - entry.mana_fac = static_cast(atof(row[8])); - entry.end_fac = static_cast(atof(row[9])); + e.level = static_cast(strtoul(row[0], nullptr, 10)); + e.class_ = static_cast(strtoul(row[1], nullptr, 10)); + e.hp = strtod(row[2], nullptr); + e.mana = strtod(row[3], nullptr); + e.end = strtod(row[4], nullptr); + e.unk1 = strtod(row[5], nullptr); + e.unk2 = strtod(row[6], nullptr); + e.hp_fac = strtod(row[7], nullptr); + e.mana_fac = strtod(row[8], nullptr); + e.end_fac = strtod(row[9], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -338,26 +338,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - BaseData entry{}; + BaseData e{}; - entry.level = atoi(row[0]); - entry.class_ = atoi(row[1]); - entry.hp = static_cast(atof(row[2])); - entry.mana = static_cast(atof(row[3])); - entry.end = static_cast(atof(row[4])); - entry.unk1 = static_cast(atof(row[5])); - entry.unk2 = static_cast(atof(row[6])); - entry.hp_fac = static_cast(atof(row[7])); - entry.mana_fac = static_cast(atof(row[8])); - entry.end_fac = static_cast(atof(row[9])); + e.level = static_cast(strtoul(row[0], nullptr, 10)); + e.class_ = static_cast(strtoul(row[1], nullptr, 10)); + e.hp = strtod(row[2], nullptr); + e.mana = strtod(row[3], nullptr); + e.end = strtod(row[4], nullptr); + e.unk1 = strtod(row[5], nullptr); + e.unk2 = strtod(row[6], nullptr); + e.hp_fac = strtod(row[7], nullptr); + e.mana_fac = strtod(row[8], nullptr); + e.end_fac = strtod(row[9], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -382,6 +382,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_BASE_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_blocked_spells_repository.h b/common/repositories/base/base_blocked_spells_repository.h index 31b47e448..822849d90 100644 --- a/common/repositories/base/base_blocked_spells_repository.h +++ b/common/repositories/base/base_blocked_spells_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_BLOCKED_SPELLS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseBlockedSpellsRepository { public: struct BlockedSpells { - int id; - int spellid; - int type; - int zoneid; + int32_t id; + uint32_t spellid; + int8_t type; + int32_t zoneid; float x; float y; float z; @@ -76,12 +76,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -109,25 +109,25 @@ public: static BlockedSpells NewEntity() { - BlockedSpells entry{}; + BlockedSpells e{}; - entry.id = 0; - entry.spellid = 0; - entry.type = 0; - entry.zoneid = 0; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.x_diff = 0; - entry.y_diff = 0; - entry.z_diff = 0; - entry.message = ""; - entry.description = ""; + e.id = 0; + e.spellid = 0; + e.type = 0; + e.zoneid = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.x_diff = 0; + e.y_diff = 0; + e.z_diff = 0; + e.message = ""; + e.description = ""; - return entry; + return e; } - static BlockedSpells GetBlockedSpellsEntry( + static BlockedSpells GetBlockedSpells( const std::vector &blocked_spellss, int blocked_spells_id ) @@ -156,22 +156,22 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - BlockedSpells entry{}; + BlockedSpells e{}; - entry.id = atoi(row[0]); - entry.spellid = atoi(row[1]); - entry.type = atoi(row[2]); - entry.zoneid = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.x_diff = static_cast(atof(row[7])); - entry.y_diff = static_cast(atof(row[8])); - entry.z_diff = static_cast(atof(row[9])); - entry.message = row[10] ? row[10] : ""; - entry.description = row[11] ? row[11] : ""; + e.id = static_cast(atoi(row[0])); + e.spellid = static_cast(strtoul(row[1], nullptr, 10)); + e.type = static_cast(atoi(row[2])); + e.zoneid = static_cast(atoi(row[3])); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.x_diff = strtof(row[7], nullptr); + e.y_diff = strtof(row[8], nullptr); + e.z_diff = strtof(row[9], nullptr); + e.message = row[10] ? row[10] : ""; + e.description = row[11] ? row[11] : ""; - return entry; + return e; } return NewEntity(); @@ -196,32 +196,32 @@ public: static int UpdateOne( Database& db, - BlockedSpells blocked_spells_entry + const BlockedSpells &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(blocked_spells_entry.spellid)); - update_values.push_back(columns[2] + " = " + std::to_string(blocked_spells_entry.type)); - update_values.push_back(columns[3] + " = " + std::to_string(blocked_spells_entry.zoneid)); - update_values.push_back(columns[4] + " = " + std::to_string(blocked_spells_entry.x)); - update_values.push_back(columns[5] + " = " + std::to_string(blocked_spells_entry.y)); - update_values.push_back(columns[6] + " = " + std::to_string(blocked_spells_entry.z)); - update_values.push_back(columns[7] + " = " + std::to_string(blocked_spells_entry.x_diff)); - update_values.push_back(columns[8] + " = " + std::to_string(blocked_spells_entry.y_diff)); - update_values.push_back(columns[9] + " = " + std::to_string(blocked_spells_entry.z_diff)); - update_values.push_back(columns[10] + " = '" + EscapeString(blocked_spells_entry.message) + "'"); - update_values.push_back(columns[11] + " = '" + EscapeString(blocked_spells_entry.description) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.spellid)); + v.push_back(columns[2] + " = " + std::to_string(e.type)); + v.push_back(columns[3] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[4] + " = " + std::to_string(e.x)); + v.push_back(columns[5] + " = " + std::to_string(e.y)); + v.push_back(columns[6] + " = " + std::to_string(e.z)); + v.push_back(columns[7] + " = " + std::to_string(e.x_diff)); + v.push_back(columns[8] + " = " + std::to_string(e.y_diff)); + v.push_back(columns[9] + " = " + std::to_string(e.z_diff)); + v.push_back(columns[10] + " = '" + Strings::Escape(e.message) + "'"); + v.push_back(columns[11] + " = '" + Strings::Escape(e.description) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - blocked_spells_entry.id + e.id ) ); @@ -230,75 +230,75 @@ public: static BlockedSpells InsertOne( Database& db, - BlockedSpells blocked_spells_entry + BlockedSpells e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(blocked_spells_entry.id)); - insert_values.push_back(std::to_string(blocked_spells_entry.spellid)); - insert_values.push_back(std::to_string(blocked_spells_entry.type)); - insert_values.push_back(std::to_string(blocked_spells_entry.zoneid)); - insert_values.push_back(std::to_string(blocked_spells_entry.x)); - insert_values.push_back(std::to_string(blocked_spells_entry.y)); - insert_values.push_back(std::to_string(blocked_spells_entry.z)); - insert_values.push_back(std::to_string(blocked_spells_entry.x_diff)); - insert_values.push_back(std::to_string(blocked_spells_entry.y_diff)); - insert_values.push_back(std::to_string(blocked_spells_entry.z_diff)); - insert_values.push_back("'" + EscapeString(blocked_spells_entry.message) + "'"); - insert_values.push_back("'" + EscapeString(blocked_spells_entry.description) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.x_diff)); + v.push_back(std::to_string(e.y_diff)); + v.push_back(std::to_string(e.z_diff)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("'" + Strings::Escape(e.description) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - blocked_spells_entry.id = results.LastInsertedID(); - return blocked_spells_entry; + e.id = results.LastInsertedID(); + return e; } - blocked_spells_entry = NewEntity(); + e = NewEntity(); - return blocked_spells_entry; + return e; } static int InsertMany( Database& db, - std::vector blocked_spells_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &blocked_spells_entry: blocked_spells_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(blocked_spells_entry.id)); - insert_values.push_back(std::to_string(blocked_spells_entry.spellid)); - insert_values.push_back(std::to_string(blocked_spells_entry.type)); - insert_values.push_back(std::to_string(blocked_spells_entry.zoneid)); - insert_values.push_back(std::to_string(blocked_spells_entry.x)); - insert_values.push_back(std::to_string(blocked_spells_entry.y)); - insert_values.push_back(std::to_string(blocked_spells_entry.z)); - insert_values.push_back(std::to_string(blocked_spells_entry.x_diff)); - insert_values.push_back(std::to_string(blocked_spells_entry.y_diff)); - insert_values.push_back(std::to_string(blocked_spells_entry.z_diff)); - insert_values.push_back("'" + EscapeString(blocked_spells_entry.message) + "'"); - insert_values.push_back("'" + EscapeString(blocked_spells_entry.description) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.x_diff)); + v.push_back(std::to_string(e.y_diff)); + v.push_back(std::to_string(e.z_diff)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("'" + Strings::Escape(e.description) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -319,28 +319,28 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - BlockedSpells entry{}; + BlockedSpells e{}; - entry.id = atoi(row[0]); - entry.spellid = atoi(row[1]); - entry.type = atoi(row[2]); - entry.zoneid = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.x_diff = static_cast(atof(row[7])); - entry.y_diff = static_cast(atof(row[8])); - entry.z_diff = static_cast(atof(row[9])); - entry.message = row[10] ? row[10] : ""; - entry.description = row[11] ? row[11] : ""; + e.id = static_cast(atoi(row[0])); + e.spellid = static_cast(strtoul(row[1], nullptr, 10)); + e.type = static_cast(atoi(row[2])); + e.zoneid = static_cast(atoi(row[3])); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.x_diff = strtof(row[7], nullptr); + e.y_diff = strtof(row[8], nullptr); + e.z_diff = strtof(row[9], nullptr); + e.message = row[10] ? row[10] : ""; + e.description = row[11] ? row[11] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -355,28 +355,28 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - BlockedSpells entry{}; + BlockedSpells e{}; - entry.id = atoi(row[0]); - entry.spellid = atoi(row[1]); - entry.type = atoi(row[2]); - entry.zoneid = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.x_diff = static_cast(atof(row[7])); - entry.y_diff = static_cast(atof(row[8])); - entry.z_diff = static_cast(atof(row[9])); - entry.message = row[10] ? row[10] : ""; - entry.description = row[11] ? row[11] : ""; + e.id = static_cast(atoi(row[0])); + e.spellid = static_cast(strtoul(row[1], nullptr, 10)); + e.type = static_cast(atoi(row[2])); + e.zoneid = static_cast(atoi(row[3])); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.x_diff = strtof(row[7], nullptr); + e.y_diff = strtof(row[8], nullptr); + e.z_diff = strtof(row[9], nullptr); + e.message = row[10] ? row[10] : ""; + e.description = row[11] ? row[11] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -401,6 +401,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_BLOCKED_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_books_repository.h b/common/repositories/base/base_books_repository.h index 11561eacc..badbb2e7b 100644 --- a/common/repositories/base/base_books_repository.h +++ b/common/repositories/base/base_books_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_BOOKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseBooksRepository { public: struct Books { - int id; + int32_t id; std::string name; std::string txtfile; - int language; + int32_t language; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static Books NewEntity() { - Books entry{}; + Books e{}; - entry.id = 0; - entry.name = ""; - entry.txtfile = ""; - entry.language = 0; + e.id = 0; + e.name = ""; + e.txtfile = ""; + e.language = 0; - return entry; + return e; } - static Books GetBooksEntry( + static Books GetBooks( const std::vector &bookss, int books_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Books entry{}; + Books e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.txtfile = row[2] ? row[2] : ""; - entry.language = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.txtfile = row[2] ? row[2] : ""; + e.language = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,24 +156,24 @@ public: static int UpdateOne( Database& db, - Books books_entry + const Books &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(books_entry.name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(books_entry.txtfile) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(books_entry.language)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.txtfile) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.language)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - books_entry.id + e.id ) ); @@ -182,59 +182,59 @@ public: static Books InsertOne( Database& db, - Books books_entry + Books e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(books_entry.id)); - insert_values.push_back("'" + EscapeString(books_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(books_entry.txtfile) + "'"); - insert_values.push_back(std::to_string(books_entry.language)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.txtfile) + "'"); + v.push_back(std::to_string(e.language)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - books_entry.id = results.LastInsertedID(); - return books_entry; + e.id = results.LastInsertedID(); + return e; } - books_entry = NewEntity(); + e = NewEntity(); - return books_entry; + return e; } static int InsertMany( Database& db, - std::vector books_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &books_entry: books_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(books_entry.id)); - insert_values.push_back("'" + EscapeString(books_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(books_entry.txtfile) + "'"); - insert_values.push_back(std::to_string(books_entry.language)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.txtfile) + "'"); + v.push_back(std::to_string(e.language)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -255,20 +255,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Books entry{}; + Books e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.txtfile = row[2] ? row[2] : ""; - entry.language = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.txtfile = row[2] ? row[2] : ""; + e.language = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -283,20 +283,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Books entry{}; + Books e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.txtfile = row[2] ? row[2] : ""; - entry.language = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.txtfile = row[2] ? row[2] : ""; + e.language = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -321,6 +321,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_BOOKS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_buffs_repository.h b/common/repositories/base/base_bot_buffs_repository.h new file mode 100644 index 000000000..729f4363c --- /dev/null +++ b/common/repositories/base/base_bot_buffs_repository.h @@ -0,0 +1,512 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_BUFFS_REPOSITORY_H +#define EQEMU_BASE_BOT_BUFFS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotBuffsRepository { +public: + struct BotBuffs { + uint32_t buffs_index; + uint32_t bot_id; + uint32_t spell_id; + uint8_t caster_level; + uint32_t duration_formula; + uint32_t tics_remaining; + uint32_t poison_counters; + uint32_t disease_counters; + uint32_t curse_counters; + uint32_t corruption_counters; + uint32_t numhits; + uint32_t melee_rune; + uint32_t magic_rune; + uint32_t dot_rune; + int8_t persistent; + int32_t caston_x; + int32_t caston_y; + int32_t caston_z; + uint32_t extra_di_chance; + int32_t instrument_mod; + }; + + static std::string PrimaryKey() + { + return std::string("buffs_index"); + } + + static std::vector Columns() + { + return { + "buffs_index", + "bot_id", + "spell_id", + "caster_level", + "duration_formula", + "tics_remaining", + "poison_counters", + "disease_counters", + "curse_counters", + "corruption_counters", + "numhits", + "melee_rune", + "magic_rune", + "dot_rune", + "persistent", + "caston_x", + "caston_y", + "caston_z", + "extra_di_chance", + "instrument_mod", + }; + } + + static std::vector SelectColumns() + { + return { + "buffs_index", + "bot_id", + "spell_id", + "caster_level", + "duration_formula", + "tics_remaining", + "poison_counters", + "disease_counters", + "curse_counters", + "corruption_counters", + "numhits", + "melee_rune", + "magic_rune", + "dot_rune", + "persistent", + "caston_x", + "caston_y", + "caston_z", + "extra_di_chance", + "instrument_mod", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_buffs"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotBuffs NewEntity() + { + BotBuffs e{}; + + e.buffs_index = 0; + e.bot_id = 0; + e.spell_id = 0; + e.caster_level = 0; + e.duration_formula = 0; + e.tics_remaining = 0; + e.poison_counters = 0; + e.disease_counters = 0; + e.curse_counters = 0; + e.corruption_counters = 0; + e.numhits = 0; + e.melee_rune = 0; + e.magic_rune = 0; + e.dot_rune = 0; + e.persistent = 0; + e.caston_x = 0; + e.caston_y = 0; + e.caston_z = 0; + e.extra_di_chance = 0; + e.instrument_mod = 10; + + return e; + } + + static BotBuffs GetBotBuffs( + const std::vector &bot_buffss, + int bot_buffs_id + ) + { + for (auto &bot_buffs : bot_buffss) { + if (bot_buffs.buffs_index == bot_buffs_id) { + return bot_buffs; + } + } + + return NewEntity(); + } + + static BotBuffs FindOne( + Database& db, + int bot_buffs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_buffs_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotBuffs e{}; + + e.buffs_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.duration_formula = static_cast(strtoul(row[4], nullptr, 10)); + e.tics_remaining = static_cast(strtoul(row[5], nullptr, 10)); + e.poison_counters = static_cast(strtoul(row[6], nullptr, 10)); + e.disease_counters = static_cast(strtoul(row[7], nullptr, 10)); + e.curse_counters = static_cast(strtoul(row[8], nullptr, 10)); + e.corruption_counters = static_cast(strtoul(row[9], nullptr, 10)); + e.numhits = static_cast(strtoul(row[10], nullptr, 10)); + e.melee_rune = static_cast(strtoul(row[11], nullptr, 10)); + e.magic_rune = static_cast(strtoul(row[12], nullptr, 10)); + e.dot_rune = static_cast(strtoul(row[13], nullptr, 10)); + e.persistent = static_cast(atoi(row[14])); + e.caston_x = static_cast(atoi(row[15])); + e.caston_y = static_cast(atoi(row[16])); + e.caston_z = static_cast(atoi(row[17])); + e.extra_di_chance = static_cast(strtoul(row[18], nullptr, 10)); + e.instrument_mod = static_cast(atoi(row[19])); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_buffs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_buffs_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotBuffs &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[3] + " = " + std::to_string(e.caster_level)); + v.push_back(columns[4] + " = " + std::to_string(e.duration_formula)); + v.push_back(columns[5] + " = " + std::to_string(e.tics_remaining)); + v.push_back(columns[6] + " = " + std::to_string(e.poison_counters)); + v.push_back(columns[7] + " = " + std::to_string(e.disease_counters)); + v.push_back(columns[8] + " = " + std::to_string(e.curse_counters)); + v.push_back(columns[9] + " = " + std::to_string(e.corruption_counters)); + v.push_back(columns[10] + " = " + std::to_string(e.numhits)); + v.push_back(columns[11] + " = " + std::to_string(e.melee_rune)); + v.push_back(columns[12] + " = " + std::to_string(e.magic_rune)); + v.push_back(columns[13] + " = " + std::to_string(e.dot_rune)); + v.push_back(columns[14] + " = " + std::to_string(e.persistent)); + v.push_back(columns[15] + " = " + std::to_string(e.caston_x)); + v.push_back(columns[16] + " = " + std::to_string(e.caston_y)); + v.push_back(columns[17] + " = " + std::to_string(e.caston_z)); + v.push_back(columns[18] + " = " + std::to_string(e.extra_di_chance)); + v.push_back(columns[19] + " = " + std::to_string(e.instrument_mod)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.buffs_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotBuffs InsertOne( + Database& db, + BotBuffs e + ) + { + std::vector v; + + v.push_back(std::to_string(e.buffs_index)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back(std::to_string(e.duration_formula)); + v.push_back(std::to_string(e.tics_remaining)); + v.push_back(std::to_string(e.poison_counters)); + v.push_back(std::to_string(e.disease_counters)); + v.push_back(std::to_string(e.curse_counters)); + v.push_back(std::to_string(e.corruption_counters)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.melee_rune)); + v.push_back(std::to_string(e.magic_rune)); + v.push_back(std::to_string(e.dot_rune)); + v.push_back(std::to_string(e.persistent)); + v.push_back(std::to_string(e.caston_x)); + v.push_back(std::to_string(e.caston_y)); + v.push_back(std::to_string(e.caston_z)); + v.push_back(std::to_string(e.extra_di_chance)); + v.push_back(std::to_string(e.instrument_mod)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.buffs_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.buffs_index)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back(std::to_string(e.duration_formula)); + v.push_back(std::to_string(e.tics_remaining)); + v.push_back(std::to_string(e.poison_counters)); + v.push_back(std::to_string(e.disease_counters)); + v.push_back(std::to_string(e.curse_counters)); + v.push_back(std::to_string(e.corruption_counters)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.melee_rune)); + v.push_back(std::to_string(e.magic_rune)); + v.push_back(std::to_string(e.dot_rune)); + v.push_back(std::to_string(e.persistent)); + v.push_back(std::to_string(e.caston_x)); + v.push_back(std::to_string(e.caston_y)); + v.push_back(std::to_string(e.caston_z)); + v.push_back(std::to_string(e.extra_di_chance)); + v.push_back(std::to_string(e.instrument_mod)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotBuffs e{}; + + e.buffs_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.duration_formula = static_cast(strtoul(row[4], nullptr, 10)); + e.tics_remaining = static_cast(strtoul(row[5], nullptr, 10)); + e.poison_counters = static_cast(strtoul(row[6], nullptr, 10)); + e.disease_counters = static_cast(strtoul(row[7], nullptr, 10)); + e.curse_counters = static_cast(strtoul(row[8], nullptr, 10)); + e.corruption_counters = static_cast(strtoul(row[9], nullptr, 10)); + e.numhits = static_cast(strtoul(row[10], nullptr, 10)); + e.melee_rune = static_cast(strtoul(row[11], nullptr, 10)); + e.magic_rune = static_cast(strtoul(row[12], nullptr, 10)); + e.dot_rune = static_cast(strtoul(row[13], nullptr, 10)); + e.persistent = static_cast(atoi(row[14])); + e.caston_x = static_cast(atoi(row[15])); + e.caston_y = static_cast(atoi(row[16])); + e.caston_z = static_cast(atoi(row[17])); + e.extra_di_chance = static_cast(strtoul(row[18], nullptr, 10)); + e.instrument_mod = static_cast(atoi(row[19])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotBuffs e{}; + + e.buffs_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.duration_formula = static_cast(strtoul(row[4], nullptr, 10)); + e.tics_remaining = static_cast(strtoul(row[5], nullptr, 10)); + e.poison_counters = static_cast(strtoul(row[6], nullptr, 10)); + e.disease_counters = static_cast(strtoul(row[7], nullptr, 10)); + e.curse_counters = static_cast(strtoul(row[8], nullptr, 10)); + e.corruption_counters = static_cast(strtoul(row[9], nullptr, 10)); + e.numhits = static_cast(strtoul(row[10], nullptr, 10)); + e.melee_rune = static_cast(strtoul(row[11], nullptr, 10)); + e.magic_rune = static_cast(strtoul(row[12], nullptr, 10)); + e.dot_rune = static_cast(strtoul(row[13], nullptr, 10)); + e.persistent = static_cast(atoi(row[14])); + e.caston_x = static_cast(atoi(row[15])); + e.caston_y = static_cast(atoi(row[16])); + e.caston_z = static_cast(atoi(row[17])); + e.extra_di_chance = static_cast(strtoul(row[18], nullptr, 10)); + e.instrument_mod = static_cast(atoi(row[19])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_create_combinations_repository.h b/common/repositories/base/base_bot_create_combinations_repository.h new file mode 100644 index 000000000..1f096db5b --- /dev/null +++ b/common/repositories/base/base_bot_create_combinations_repository.h @@ -0,0 +1,333 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H +#define EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotCreateCombinationsRepository { +public: + struct BotCreateCombinations { + uint32_t race; + uint32_t classes; + }; + + static std::string PrimaryKey() + { + return std::string("race"); + } + + static std::vector Columns() + { + return { + "race", + "classes", + }; + } + + static std::vector SelectColumns() + { + return { + "race", + "classes", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_create_combinations"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotCreateCombinations NewEntity() + { + BotCreateCombinations e{}; + + e.race = 0; + e.classes = 0; + + return e; + } + + static BotCreateCombinations GetBotCreateCombinations( + const std::vector &bot_create_combinationss, + int bot_create_combinations_id + ) + { + for (auto &bot_create_combinations : bot_create_combinationss) { + if (bot_create_combinations.race == bot_create_combinations_id) { + return bot_create_combinations; + } + } + + return NewEntity(); + } + + static BotCreateCombinations FindOne( + Database& db, + int bot_create_combinations_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_create_combinations_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotCreateCombinations e{}; + + e.race = static_cast(strtoul(row[0], nullptr, 10)); + e.classes = static_cast(strtoul(row[1], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_create_combinations_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_create_combinations_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotCreateCombinations &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.race)); + v.push_back(columns[1] + " = " + std::to_string(e.classes)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.race + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotCreateCombinations InsertOne( + Database& db, + BotCreateCombinations e + ) + { + std::vector v; + + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.classes)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.race = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.classes)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotCreateCombinations e{}; + + e.race = static_cast(strtoul(row[0], nullptr, 10)); + e.classes = static_cast(strtoul(row[1], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotCreateCombinations e{}; + + e.race = static_cast(strtoul(row[0], nullptr, 10)); + e.classes = static_cast(strtoul(row[1], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_data_repository.h b/common/repositories/base/base_bot_data_repository.h new file mode 100644 index 000000000..da0b67af7 --- /dev/null +++ b/common/repositories/base/base_bot_data_repository.h @@ -0,0 +1,813 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_DATA_REPOSITORY_H +#define EQEMU_BASE_BOT_DATA_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotDataRepository { +public: + struct BotData { + uint32_t bot_id; + uint32_t owner_id; + uint32_t spells_id; + std::string name; + std::string last_name; + std::string title; + std::string suffix; + int16_t zone_id; + int8_t gender; + int16_t race; + int8_t class_; + uint8_t level; + uint32_t deity; + uint32_t creation_day; + uint32_t last_spawn; + uint32_t time_spawned; + float size; + int32_t face; + int32_t hair_color; + int32_t hair_style; + int32_t beard; + int32_t beard_color; + int32_t eye_color_1; + int32_t eye_color_2; + int32_t drakkin_heritage; + int32_t drakkin_tattoo; + int32_t drakkin_details; + int16_t ac; + int32_t atk; + int32_t hp; + int32_t mana; + int32_t str; + int32_t sta; + int32_t cha; + int32_t dex; + int32_t int_; + int32_t agi; + int32_t wis; + int16_t fire; + int16_t cold; + int16_t magic; + int16_t poison; + int16_t disease; + int16_t corruption; + uint32_t show_helm; + uint32_t follow_distance; + uint8_t stop_melee_level; + int32_t expansion_bitmask; + uint8_t enforce_spell_settings; + uint8_t archery_setting; + }; + + static std::string PrimaryKey() + { + return std::string("bot_id"); + } + + static std::vector Columns() + { + return { + "bot_id", + "owner_id", + "spells_id", + "name", + "last_name", + "title", + "suffix", + "zone_id", + "gender", + "race", + "`class`", + "level", + "deity", + "creation_day", + "last_spawn", + "time_spawned", + "size", + "face", + "hair_color", + "hair_style", + "beard", + "beard_color", + "eye_color_1", + "eye_color_2", + "drakkin_heritage", + "drakkin_tattoo", + "drakkin_details", + "ac", + "atk", + "hp", + "mana", + "str", + "sta", + "cha", + "dex", + "`int`", + "agi", + "wis", + "fire", + "cold", + "magic", + "poison", + "disease", + "corruption", + "show_helm", + "follow_distance", + "stop_melee_level", + "expansion_bitmask", + "enforce_spell_settings", + "archery_setting", + }; + } + + static std::vector SelectColumns() + { + return { + "bot_id", + "owner_id", + "spells_id", + "name", + "last_name", + "title", + "suffix", + "zone_id", + "gender", + "race", + "`class`", + "level", + "deity", + "creation_day", + "last_spawn", + "time_spawned", + "size", + "face", + "hair_color", + "hair_style", + "beard", + "beard_color", + "eye_color_1", + "eye_color_2", + "drakkin_heritage", + "drakkin_tattoo", + "drakkin_details", + "ac", + "atk", + "hp", + "mana", + "str", + "sta", + "cha", + "dex", + "`int`", + "agi", + "wis", + "fire", + "cold", + "magic", + "poison", + "disease", + "corruption", + "show_helm", + "follow_distance", + "stop_melee_level", + "expansion_bitmask", + "enforce_spell_settings", + "archery_setting", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_data"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotData NewEntity() + { + BotData e{}; + + e.bot_id = 0; + e.owner_id = 0; + e.spells_id = 0; + e.name = ""; + e.last_name = ""; + e.title = ""; + e.suffix = ""; + e.zone_id = 0; + e.gender = 0; + e.race = 0; + e.class_ = 0; + e.level = 0; + e.deity = 0; + e.creation_day = 0; + e.last_spawn = 0; + e.time_spawned = 0; + e.size = 0; + e.face = 1; + e.hair_color = 1; + e.hair_style = 1; + e.beard = 0; + e.beard_color = 1; + e.eye_color_1 = 1; + e.eye_color_2 = 1; + e.drakkin_heritage = 0; + e.drakkin_tattoo = 0; + e.drakkin_details = 0; + e.ac = 0; + e.atk = 0; + e.hp = 0; + e.mana = 0; + e.str = 75; + e.sta = 75; + e.cha = 75; + e.dex = 75; + e.int_ = 75; + e.agi = 75; + e.wis = 75; + e.fire = 0; + e.cold = 0; + e.magic = 0; + e.poison = 0; + e.disease = 0; + e.corruption = 0; + e.show_helm = 0; + e.follow_distance = 200; + e.stop_melee_level = 255; + e.expansion_bitmask = -1; + e.enforce_spell_settings = 0; + e.archery_setting = 0; + + return e; + } + + static BotData GetBotData( + const std::vector &bot_datas, + int bot_data_id + ) + { + for (auto &bot_data : bot_datas) { + if (bot_data.bot_id == bot_data_id) { + return bot_data; + } + } + + return NewEntity(); + } + + static BotData FindOne( + Database& db, + int bot_data_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + bot_data_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotData e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.owner_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spells_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.title = row[5] ? row[5] : ""; + e.suffix = row[6] ? row[6] : ""; + e.zone_id = static_cast(atoi(row[7])); + e.gender = static_cast(atoi(row[8])); + e.race = static_cast(atoi(row[9])); + e.class_ = static_cast(atoi(row[10])); + e.level = static_cast(strtoul(row[11], nullptr, 10)); + e.deity = static_cast(strtoul(row[12], nullptr, 10)); + e.creation_day = static_cast(strtoul(row[13], nullptr, 10)); + e.last_spawn = static_cast(strtoul(row[14], nullptr, 10)); + e.time_spawned = static_cast(strtoul(row[15], nullptr, 10)); + e.size = strtof(row[16], nullptr); + e.face = static_cast(atoi(row[17])); + e.hair_color = static_cast(atoi(row[18])); + e.hair_style = static_cast(atoi(row[19])); + e.beard = static_cast(atoi(row[20])); + e.beard_color = static_cast(atoi(row[21])); + e.eye_color_1 = static_cast(atoi(row[22])); + e.eye_color_2 = static_cast(atoi(row[23])); + e.drakkin_heritage = static_cast(atoi(row[24])); + e.drakkin_tattoo = static_cast(atoi(row[25])); + e.drakkin_details = static_cast(atoi(row[26])); + e.ac = static_cast(atoi(row[27])); + e.atk = static_cast(atoi(row[28])); + e.hp = static_cast(atoi(row[29])); + e.mana = static_cast(atoi(row[30])); + e.str = static_cast(atoi(row[31])); + e.sta = static_cast(atoi(row[32])); + e.cha = static_cast(atoi(row[33])); + e.dex = static_cast(atoi(row[34])); + e.int_ = static_cast(atoi(row[35])); + e.agi = static_cast(atoi(row[36])); + e.wis = static_cast(atoi(row[37])); + e.fire = static_cast(atoi(row[38])); + e.cold = static_cast(atoi(row[39])); + e.magic = static_cast(atoi(row[40])); + e.poison = static_cast(atoi(row[41])); + e.disease = static_cast(atoi(row[42])); + e.corruption = static_cast(atoi(row[43])); + e.show_helm = static_cast(strtoul(row[44], nullptr, 10)); + e.follow_distance = static_cast(strtoul(row[45], nullptr, 10)); + e.stop_melee_level = static_cast(strtoul(row[46], nullptr, 10)); + e.expansion_bitmask = static_cast(atoi(row[47])); + e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); + e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_data_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_data_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotData &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.owner_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spells_id)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.last_name) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.title) + "'"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.suffix) + "'"); + v.push_back(columns[7] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[8] + " = " + std::to_string(e.gender)); + v.push_back(columns[9] + " = " + std::to_string(e.race)); + v.push_back(columns[10] + " = " + std::to_string(e.class_)); + v.push_back(columns[11] + " = " + std::to_string(e.level)); + v.push_back(columns[12] + " = " + std::to_string(e.deity)); + v.push_back(columns[13] + " = " + std::to_string(e.creation_day)); + v.push_back(columns[14] + " = " + std::to_string(e.last_spawn)); + v.push_back(columns[15] + " = " + std::to_string(e.time_spawned)); + v.push_back(columns[16] + " = " + std::to_string(e.size)); + v.push_back(columns[17] + " = " + std::to_string(e.face)); + v.push_back(columns[18] + " = " + std::to_string(e.hair_color)); + v.push_back(columns[19] + " = " + std::to_string(e.hair_style)); + v.push_back(columns[20] + " = " + std::to_string(e.beard)); + v.push_back(columns[21] + " = " + std::to_string(e.beard_color)); + v.push_back(columns[22] + " = " + std::to_string(e.eye_color_1)); + v.push_back(columns[23] + " = " + std::to_string(e.eye_color_2)); + v.push_back(columns[24] + " = " + std::to_string(e.drakkin_heritage)); + v.push_back(columns[25] + " = " + std::to_string(e.drakkin_tattoo)); + v.push_back(columns[26] + " = " + std::to_string(e.drakkin_details)); + v.push_back(columns[27] + " = " + std::to_string(e.ac)); + v.push_back(columns[28] + " = " + std::to_string(e.atk)); + v.push_back(columns[29] + " = " + std::to_string(e.hp)); + v.push_back(columns[30] + " = " + std::to_string(e.mana)); + v.push_back(columns[31] + " = " + std::to_string(e.str)); + v.push_back(columns[32] + " = " + std::to_string(e.sta)); + v.push_back(columns[33] + " = " + std::to_string(e.cha)); + v.push_back(columns[34] + " = " + std::to_string(e.dex)); + v.push_back(columns[35] + " = " + std::to_string(e.int_)); + v.push_back(columns[36] + " = " + std::to_string(e.agi)); + v.push_back(columns[37] + " = " + std::to_string(e.wis)); + v.push_back(columns[38] + " = " + std::to_string(e.fire)); + v.push_back(columns[39] + " = " + std::to_string(e.cold)); + v.push_back(columns[40] + " = " + std::to_string(e.magic)); + v.push_back(columns[41] + " = " + std::to_string(e.poison)); + v.push_back(columns[42] + " = " + std::to_string(e.disease)); + v.push_back(columns[43] + " = " + std::to_string(e.corruption)); + v.push_back(columns[44] + " = " + std::to_string(e.show_helm)); + v.push_back(columns[45] + " = " + std::to_string(e.follow_distance)); + v.push_back(columns[46] + " = " + std::to_string(e.stop_melee_level)); + v.push_back(columns[47] + " = " + std::to_string(e.expansion_bitmask)); + v.push_back(columns[48] + " = " + std::to_string(e.enforce_spell_settings)); + v.push_back(columns[49] + " = " + std::to_string(e.archery_setting)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.bot_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotData InsertOne( + Database& db, + BotData e + ) + { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.owner_id)); + v.push_back(std::to_string(e.spells_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.last_name) + "'"); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.creation_day)); + v.push_back(std::to_string(e.last_spawn)); + v.push_back(std::to_string(e.time_spawned)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.hair_color)); + v.push_back(std::to_string(e.hair_style)); + v.push_back(std::to_string(e.beard)); + v.push_back(std::to_string(e.beard_color)); + v.push_back(std::to_string(e.eye_color_1)); + v.push_back(std::to_string(e.eye_color_2)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.ac)); + v.push_back(std::to_string(e.atk)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.str)); + v.push_back(std::to_string(e.sta)); + v.push_back(std::to_string(e.cha)); + v.push_back(std::to_string(e.dex)); + v.push_back(std::to_string(e.int_)); + v.push_back(std::to_string(e.agi)); + v.push_back(std::to_string(e.wis)); + v.push_back(std::to_string(e.fire)); + v.push_back(std::to_string(e.cold)); + v.push_back(std::to_string(e.magic)); + v.push_back(std::to_string(e.poison)); + v.push_back(std::to_string(e.disease)); + v.push_back(std::to_string(e.corruption)); + v.push_back(std::to_string(e.show_helm)); + v.push_back(std::to_string(e.follow_distance)); + v.push_back(std::to_string(e.stop_melee_level)); + v.push_back(std::to_string(e.expansion_bitmask)); + v.push_back(std::to_string(e.enforce_spell_settings)); + v.push_back(std::to_string(e.archery_setting)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.bot_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.owner_id)); + v.push_back(std::to_string(e.spells_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.last_name) + "'"); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.creation_day)); + v.push_back(std::to_string(e.last_spawn)); + v.push_back(std::to_string(e.time_spawned)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.hair_color)); + v.push_back(std::to_string(e.hair_style)); + v.push_back(std::to_string(e.beard)); + v.push_back(std::to_string(e.beard_color)); + v.push_back(std::to_string(e.eye_color_1)); + v.push_back(std::to_string(e.eye_color_2)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.ac)); + v.push_back(std::to_string(e.atk)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.str)); + v.push_back(std::to_string(e.sta)); + v.push_back(std::to_string(e.cha)); + v.push_back(std::to_string(e.dex)); + v.push_back(std::to_string(e.int_)); + v.push_back(std::to_string(e.agi)); + v.push_back(std::to_string(e.wis)); + v.push_back(std::to_string(e.fire)); + v.push_back(std::to_string(e.cold)); + v.push_back(std::to_string(e.magic)); + v.push_back(std::to_string(e.poison)); + v.push_back(std::to_string(e.disease)); + v.push_back(std::to_string(e.corruption)); + v.push_back(std::to_string(e.show_helm)); + v.push_back(std::to_string(e.follow_distance)); + v.push_back(std::to_string(e.stop_melee_level)); + v.push_back(std::to_string(e.expansion_bitmask)); + v.push_back(std::to_string(e.enforce_spell_settings)); + v.push_back(std::to_string(e.archery_setting)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotData e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.owner_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spells_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.title = row[5] ? row[5] : ""; + e.suffix = row[6] ? row[6] : ""; + e.zone_id = static_cast(atoi(row[7])); + e.gender = static_cast(atoi(row[8])); + e.race = static_cast(atoi(row[9])); + e.class_ = static_cast(atoi(row[10])); + e.level = static_cast(strtoul(row[11], nullptr, 10)); + e.deity = static_cast(strtoul(row[12], nullptr, 10)); + e.creation_day = static_cast(strtoul(row[13], nullptr, 10)); + e.last_spawn = static_cast(strtoul(row[14], nullptr, 10)); + e.time_spawned = static_cast(strtoul(row[15], nullptr, 10)); + e.size = strtof(row[16], nullptr); + e.face = static_cast(atoi(row[17])); + e.hair_color = static_cast(atoi(row[18])); + e.hair_style = static_cast(atoi(row[19])); + e.beard = static_cast(atoi(row[20])); + e.beard_color = static_cast(atoi(row[21])); + e.eye_color_1 = static_cast(atoi(row[22])); + e.eye_color_2 = static_cast(atoi(row[23])); + e.drakkin_heritage = static_cast(atoi(row[24])); + e.drakkin_tattoo = static_cast(atoi(row[25])); + e.drakkin_details = static_cast(atoi(row[26])); + e.ac = static_cast(atoi(row[27])); + e.atk = static_cast(atoi(row[28])); + e.hp = static_cast(atoi(row[29])); + e.mana = static_cast(atoi(row[30])); + e.str = static_cast(atoi(row[31])); + e.sta = static_cast(atoi(row[32])); + e.cha = static_cast(atoi(row[33])); + e.dex = static_cast(atoi(row[34])); + e.int_ = static_cast(atoi(row[35])); + e.agi = static_cast(atoi(row[36])); + e.wis = static_cast(atoi(row[37])); + e.fire = static_cast(atoi(row[38])); + e.cold = static_cast(atoi(row[39])); + e.magic = static_cast(atoi(row[40])); + e.poison = static_cast(atoi(row[41])); + e.disease = static_cast(atoi(row[42])); + e.corruption = static_cast(atoi(row[43])); + e.show_helm = static_cast(strtoul(row[44], nullptr, 10)); + e.follow_distance = static_cast(strtoul(row[45], nullptr, 10)); + e.stop_melee_level = static_cast(strtoul(row[46], nullptr, 10)); + e.expansion_bitmask = static_cast(atoi(row[47])); + e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); + e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotData e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.owner_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spells_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.title = row[5] ? row[5] : ""; + e.suffix = row[6] ? row[6] : ""; + e.zone_id = static_cast(atoi(row[7])); + e.gender = static_cast(atoi(row[8])); + e.race = static_cast(atoi(row[9])); + e.class_ = static_cast(atoi(row[10])); + e.level = static_cast(strtoul(row[11], nullptr, 10)); + e.deity = static_cast(strtoul(row[12], nullptr, 10)); + e.creation_day = static_cast(strtoul(row[13], nullptr, 10)); + e.last_spawn = static_cast(strtoul(row[14], nullptr, 10)); + e.time_spawned = static_cast(strtoul(row[15], nullptr, 10)); + e.size = strtof(row[16], nullptr); + e.face = static_cast(atoi(row[17])); + e.hair_color = static_cast(atoi(row[18])); + e.hair_style = static_cast(atoi(row[19])); + e.beard = static_cast(atoi(row[20])); + e.beard_color = static_cast(atoi(row[21])); + e.eye_color_1 = static_cast(atoi(row[22])); + e.eye_color_2 = static_cast(atoi(row[23])); + e.drakkin_heritage = static_cast(atoi(row[24])); + e.drakkin_tattoo = static_cast(atoi(row[25])); + e.drakkin_details = static_cast(atoi(row[26])); + e.ac = static_cast(atoi(row[27])); + e.atk = static_cast(atoi(row[28])); + e.hp = static_cast(atoi(row[29])); + e.mana = static_cast(atoi(row[30])); + e.str = static_cast(atoi(row[31])); + e.sta = static_cast(atoi(row[32])); + e.cha = static_cast(atoi(row[33])); + e.dex = static_cast(atoi(row[34])); + e.int_ = static_cast(atoi(row[35])); + e.agi = static_cast(atoi(row[36])); + e.wis = static_cast(atoi(row[37])); + e.fire = static_cast(atoi(row[38])); + e.cold = static_cast(atoi(row[39])); + e.magic = static_cast(atoi(row[40])); + e.poison = static_cast(atoi(row[41])); + e.disease = static_cast(atoi(row[42])); + e.corruption = static_cast(atoi(row[43])); + e.show_helm = static_cast(strtoul(row[44], nullptr, 10)); + e.follow_distance = static_cast(strtoul(row[45], nullptr, 10)); + e.stop_melee_level = static_cast(strtoul(row[46], nullptr, 10)); + e.expansion_bitmask = static_cast(atoi(row[47])); + e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); + e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_bot_group_members_repository.h b/common/repositories/base/base_bot_group_members_repository.h new file mode 100644 index 000000000..2fbd9c0ca --- /dev/null +++ b/common/repositories/base/base_bot_group_members_repository.h @@ -0,0 +1,342 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H +#define EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotGroupMembersRepository { +public: + struct BotGroupMembers { + uint32_t group_members_index; + uint32_t groups_index; + uint32_t bot_id; + }; + + static std::string PrimaryKey() + { + return std::string("group_members_index"); + } + + static std::vector Columns() + { + return { + "group_members_index", + "groups_index", + "bot_id", + }; + } + + static std::vector SelectColumns() + { + return { + "group_members_index", + "groups_index", + "bot_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_group_members"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotGroupMembers NewEntity() + { + BotGroupMembers e{}; + + e.group_members_index = 0; + e.groups_index = 0; + e.bot_id = 0; + + return e; + } + + static BotGroupMembers GetBotGroupMembers( + const std::vector &bot_group_memberss, + int bot_group_members_id + ) + { + for (auto &bot_group_members : bot_group_memberss) { + if (bot_group_members.group_members_index == bot_group_members_id) { + return bot_group_members; + } + } + + return NewEntity(); + } + + static BotGroupMembers FindOne( + Database& db, + int bot_group_members_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_group_members_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotGroupMembers e{}; + + e.group_members_index = static_cast(strtoul(row[0], nullptr, 10)); + e.groups_index = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_group_members_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_group_members_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotGroupMembers &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.groups_index)); + v.push_back(columns[2] + " = " + std::to_string(e.bot_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.group_members_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotGroupMembers InsertOne( + Database& db, + BotGroupMembers e + ) + { + std::vector v; + + v.push_back(std::to_string(e.group_members_index)); + v.push_back(std::to_string(e.groups_index)); + v.push_back(std::to_string(e.bot_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.group_members_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.group_members_index)); + v.push_back(std::to_string(e.groups_index)); + v.push_back(std::to_string(e.bot_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotGroupMembers e{}; + + e.group_members_index = static_cast(strtoul(row[0], nullptr, 10)); + e.groups_index = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotGroupMembers e{}; + + e.group_members_index = static_cast(strtoul(row[0], nullptr, 10)); + e.groups_index = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_groups_repository.h b/common/repositories/base/base_bot_groups_repository.h new file mode 100644 index 000000000..ac86e329e --- /dev/null +++ b/common/repositories/base/base_bot_groups_repository.h @@ -0,0 +1,352 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_GROUPS_REPOSITORY_H +#define EQEMU_BASE_BOT_GROUPS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotGroupsRepository { +public: + struct BotGroups { + uint32_t groups_index; + uint32_t group_leader_id; + std::string group_name; + uint8_t auto_spawn; + }; + + static std::string PrimaryKey() + { + return std::string("groups_index"); + } + + static std::vector Columns() + { + return { + "groups_index", + "group_leader_id", + "group_name", + "auto_spawn", + }; + } + + static std::vector SelectColumns() + { + return { + "groups_index", + "group_leader_id", + "group_name", + "auto_spawn", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_groups"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotGroups NewEntity() + { + BotGroups e{}; + + e.groups_index = 0; + e.group_leader_id = 0; + e.group_name = ""; + e.auto_spawn = 0; + + return e; + } + + static BotGroups GetBotGroups( + const std::vector &bot_groupss, + int bot_groups_id + ) + { + for (auto &bot_groups : bot_groupss) { + if (bot_groups.groups_index == bot_groups_id) { + return bot_groups; + } + } + + return NewEntity(); + } + + static BotGroups FindOne( + Database& db, + int bot_groups_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_groups_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotGroups e{}; + + e.groups_index = static_cast(strtoul(row[0], nullptr, 10)); + e.group_leader_id = static_cast(strtoul(row[1], nullptr, 10)); + e.group_name = row[2] ? row[2] : ""; + e.auto_spawn = static_cast(strtoul(row[3], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_groups_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_groups_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotGroups &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.group_leader_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.group_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.auto_spawn)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.groups_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotGroups InsertOne( + Database& db, + BotGroups e + ) + { + std::vector v; + + v.push_back(std::to_string(e.groups_index)); + v.push_back(std::to_string(e.group_leader_id)); + v.push_back("'" + Strings::Escape(e.group_name) + "'"); + v.push_back(std::to_string(e.auto_spawn)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.groups_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.groups_index)); + v.push_back(std::to_string(e.group_leader_id)); + v.push_back("'" + Strings::Escape(e.group_name) + "'"); + v.push_back(std::to_string(e.auto_spawn)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotGroups e{}; + + e.groups_index = static_cast(strtoul(row[0], nullptr, 10)); + e.group_leader_id = static_cast(strtoul(row[1], nullptr, 10)); + e.group_name = row[2] ? row[2] : ""; + e.auto_spawn = static_cast(strtoul(row[3], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotGroups e{}; + + e.groups_index = static_cast(strtoul(row[0], nullptr, 10)); + e.group_leader_id = static_cast(strtoul(row[1], nullptr, 10)); + e.group_name = row[2] ? row[2] : ""; + e.auto_spawn = static_cast(strtoul(row[3], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_GROUPS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_guild_members_repository.h b/common/repositories/base/base_bot_guild_members_repository.h new file mode 100644 index 000000000..162938274 --- /dev/null +++ b/common/repositories/base/base_bot_guild_members_repository.h @@ -0,0 +1,403 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H +#define EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotGuildMembersRepository { +public: + struct BotGuildMembers { + int32_t bot_id; + uint32_t guild_id; + uint8_t rank; + uint8_t tribute_enable; + uint32_t total_tribute; + uint32_t last_tribute; + uint8_t banker; + std::string public_note; + uint8_t alt; + }; + + static std::string PrimaryKey() + { + return std::string("bot_id"); + } + + static std::vector Columns() + { + return { + "bot_id", + "guild_id", + "rank", + "tribute_enable", + "total_tribute", + "last_tribute", + "banker", + "public_note", + "alt", + }; + } + + static std::vector SelectColumns() + { + return { + "bot_id", + "guild_id", + "rank", + "tribute_enable", + "total_tribute", + "last_tribute", + "banker", + "public_note", + "alt", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_guild_members"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotGuildMembers NewEntity() + { + BotGuildMembers e{}; + + e.bot_id = 0; + e.guild_id = 0; + e.rank = 0; + e.tribute_enable = 0; + e.total_tribute = 0; + e.last_tribute = 0; + e.banker = 0; + e.public_note = ""; + e.alt = 0; + + return e; + } + + static BotGuildMembers GetBotGuildMembers( + const std::vector &bot_guild_memberss, + int bot_guild_members_id + ) + { + for (auto &bot_guild_members : bot_guild_memberss) { + if (bot_guild_members.bot_id == bot_guild_members_id) { + return bot_guild_members; + } + } + + return NewEntity(); + } + + static BotGuildMembers FindOne( + Database& db, + int bot_guild_members_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_guild_members_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotGuildMembers e{}; + + e.bot_id = static_cast(atoi(row[0])); + e.guild_id = static_cast(strtoul(row[1], nullptr, 10)); + e.rank = static_cast(strtoul(row[2], nullptr, 10)); + e.tribute_enable = static_cast(strtoul(row[3], nullptr, 10)); + e.total_tribute = static_cast(strtoul(row[4], nullptr, 10)); + e.last_tribute = static_cast(strtoul(row[5], nullptr, 10)); + e.banker = static_cast(strtoul(row[6], nullptr, 10)); + e.public_note = row[7] ? row[7] : ""; + e.alt = static_cast(strtoul(row[8], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_guild_members_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_guild_members_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotGuildMembers &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[1] + " = " + std::to_string(e.guild_id)); + v.push_back(columns[2] + " = " + std::to_string(e.rank)); + v.push_back(columns[3] + " = " + std::to_string(e.tribute_enable)); + v.push_back(columns[4] + " = " + std::to_string(e.total_tribute)); + v.push_back(columns[5] + " = " + std::to_string(e.last_tribute)); + v.push_back(columns[6] + " = " + std::to_string(e.banker)); + v.push_back(columns[7] + " = '" + Strings::Escape(e.public_note) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.alt)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.bot_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotGuildMembers InsertOne( + Database& db, + BotGuildMembers e + ) + { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.rank)); + v.push_back(std::to_string(e.tribute_enable)); + v.push_back(std::to_string(e.total_tribute)); + v.push_back(std::to_string(e.last_tribute)); + v.push_back(std::to_string(e.banker)); + v.push_back("'" + Strings::Escape(e.public_note) + "'"); + v.push_back(std::to_string(e.alt)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.bot_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.rank)); + v.push_back(std::to_string(e.tribute_enable)); + v.push_back(std::to_string(e.total_tribute)); + v.push_back(std::to_string(e.last_tribute)); + v.push_back(std::to_string(e.banker)); + v.push_back("'" + Strings::Escape(e.public_note) + "'"); + v.push_back(std::to_string(e.alt)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotGuildMembers e{}; + + e.bot_id = static_cast(atoi(row[0])); + e.guild_id = static_cast(strtoul(row[1], nullptr, 10)); + e.rank = static_cast(strtoul(row[2], nullptr, 10)); + e.tribute_enable = static_cast(strtoul(row[3], nullptr, 10)); + e.total_tribute = static_cast(strtoul(row[4], nullptr, 10)); + e.last_tribute = static_cast(strtoul(row[5], nullptr, 10)); + e.banker = static_cast(strtoul(row[6], nullptr, 10)); + e.public_note = row[7] ? row[7] : ""; + e.alt = static_cast(strtoul(row[8], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotGuildMembers e{}; + + e.bot_id = static_cast(atoi(row[0])); + e.guild_id = static_cast(strtoul(row[1], nullptr, 10)); + e.rank = static_cast(strtoul(row[2], nullptr, 10)); + e.tribute_enable = static_cast(strtoul(row[3], nullptr, 10)); + e.total_tribute = static_cast(strtoul(row[4], nullptr, 10)); + e.last_tribute = static_cast(strtoul(row[5], nullptr, 10)); + e.banker = static_cast(strtoul(row[6], nullptr, 10)); + e.public_note = row[7] ? row[7] : ""; + e.alt = static_cast(strtoul(row[8], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_heal_rotation_members_repository.h b/common/repositories/base/base_bot_heal_rotation_members_repository.h new file mode 100644 index 000000000..af89601d6 --- /dev/null +++ b/common/repositories/base/base_bot_heal_rotation_members_repository.h @@ -0,0 +1,342 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H +#define EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotHealRotationMembersRepository { +public: + struct BotHealRotationMembers { + uint32_t member_index; + uint32_t heal_rotation_index; + uint32_t bot_id; + }; + + static std::string PrimaryKey() + { + return std::string("member_index"); + } + + static std::vector Columns() + { + return { + "member_index", + "heal_rotation_index", + "bot_id", + }; + } + + static std::vector SelectColumns() + { + return { + "member_index", + "heal_rotation_index", + "bot_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_heal_rotation_members"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotHealRotationMembers NewEntity() + { + BotHealRotationMembers e{}; + + e.member_index = 0; + e.heal_rotation_index = 0; + e.bot_id = 0; + + return e; + } + + static BotHealRotationMembers GetBotHealRotationMembers( + const std::vector &bot_heal_rotation_memberss, + int bot_heal_rotation_members_id + ) + { + for (auto &bot_heal_rotation_members : bot_heal_rotation_memberss) { + if (bot_heal_rotation_members.member_index == bot_heal_rotation_members_id) { + return bot_heal_rotation_members; + } + } + + return NewEntity(); + } + + static BotHealRotationMembers FindOne( + Database& db, + int bot_heal_rotation_members_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_heal_rotation_members_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotHealRotationMembers e{}; + + e.member_index = static_cast(strtoul(row[0], nullptr, 10)); + e.heal_rotation_index = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_heal_rotation_members_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_heal_rotation_members_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotHealRotationMembers &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.heal_rotation_index)); + v.push_back(columns[2] + " = " + std::to_string(e.bot_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.member_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotHealRotationMembers InsertOne( + Database& db, + BotHealRotationMembers e + ) + { + std::vector v; + + v.push_back(std::to_string(e.member_index)); + v.push_back(std::to_string(e.heal_rotation_index)); + v.push_back(std::to_string(e.bot_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.member_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.member_index)); + v.push_back(std::to_string(e.heal_rotation_index)); + v.push_back(std::to_string(e.bot_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotHealRotationMembers e{}; + + e.member_index = static_cast(strtoul(row[0], nullptr, 10)); + e.heal_rotation_index = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotHealRotationMembers e{}; + + e.member_index = static_cast(strtoul(row[0], nullptr, 10)); + e.heal_rotation_index = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_heal_rotation_targets_repository.h b/common/repositories/base/base_bot_heal_rotation_targets_repository.h new file mode 100644 index 000000000..b5bef9c2b --- /dev/null +++ b/common/repositories/base/base_bot_heal_rotation_targets_repository.h @@ -0,0 +1,342 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H +#define EQEMU_BASE_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotHealRotationTargetsRepository { +public: + struct BotHealRotationTargets { + uint32_t target_index; + uint32_t heal_rotation_index; + std::string target_name; + }; + + static std::string PrimaryKey() + { + return std::string("target_index"); + } + + static std::vector Columns() + { + return { + "target_index", + "heal_rotation_index", + "target_name", + }; + } + + static std::vector SelectColumns() + { + return { + "target_index", + "heal_rotation_index", + "target_name", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_heal_rotation_targets"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotHealRotationTargets NewEntity() + { + BotHealRotationTargets e{}; + + e.target_index = 0; + e.heal_rotation_index = 0; + e.target_name = ""; + + return e; + } + + static BotHealRotationTargets GetBotHealRotationTargets( + const std::vector &bot_heal_rotation_targetss, + int bot_heal_rotation_targets_id + ) + { + for (auto &bot_heal_rotation_targets : bot_heal_rotation_targetss) { + if (bot_heal_rotation_targets.target_index == bot_heal_rotation_targets_id) { + return bot_heal_rotation_targets; + } + } + + return NewEntity(); + } + + static BotHealRotationTargets FindOne( + Database& db, + int bot_heal_rotation_targets_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_heal_rotation_targets_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotHealRotationTargets e{}; + + e.target_index = static_cast(strtoul(row[0], nullptr, 10)); + e.heal_rotation_index = static_cast(strtoul(row[1], nullptr, 10)); + e.target_name = row[2] ? row[2] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_heal_rotation_targets_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_heal_rotation_targets_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotHealRotationTargets &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.heal_rotation_index)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.target_name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.target_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotHealRotationTargets InsertOne( + Database& db, + BotHealRotationTargets e + ) + { + std::vector v; + + v.push_back(std::to_string(e.target_index)); + v.push_back(std::to_string(e.heal_rotation_index)); + v.push_back("'" + Strings::Escape(e.target_name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.target_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.target_index)); + v.push_back(std::to_string(e.heal_rotation_index)); + v.push_back("'" + Strings::Escape(e.target_name) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotHealRotationTargets e{}; + + e.target_index = static_cast(strtoul(row[0], nullptr, 10)); + e.heal_rotation_index = static_cast(strtoul(row[1], nullptr, 10)); + e.target_name = row[2] ? row[2] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotHealRotationTargets e{}; + + e.target_index = static_cast(strtoul(row[0], nullptr, 10)); + e.heal_rotation_index = static_cast(strtoul(row[1], nullptr, 10)); + e.target_name = row[2] ? row[2] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_heal_rotations_repository.h b/common/repositories/base/base_bot_heal_rotations_repository.h new file mode 100644 index 000000000..f39e0b403 --- /dev/null +++ b/common/repositories/base/base_bot_heal_rotations_repository.h @@ -0,0 +1,442 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H +#define EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotHealRotationsRepository { +public: + struct BotHealRotations { + uint32_t heal_rotation_index; + uint32_t bot_id; + uint32_t interval; + uint32_t fast_heals; + uint32_t adaptive_targeting; + uint32_t casting_override; + std::string safe_hp_base; + std::string safe_hp_cloth; + std::string safe_hp_leather; + std::string safe_hp_chain; + std::string safe_hp_plate; + std::string critical_hp_base; + std::string critical_hp_cloth; + std::string critical_hp_leather; + std::string critical_hp_chain; + std::string critical_hp_plate; + }; + + static std::string PrimaryKey() + { + return std::string("heal_rotation_index"); + } + + static std::vector Columns() + { + return { + "heal_rotation_index", + "bot_id", + "interval", + "fast_heals", + "adaptive_targeting", + "casting_override", + "safe_hp_base", + "safe_hp_cloth", + "safe_hp_leather", + "safe_hp_chain", + "safe_hp_plate", + "critical_hp_base", + "critical_hp_cloth", + "critical_hp_leather", + "critical_hp_chain", + "critical_hp_plate", + }; + } + + static std::vector SelectColumns() + { + return { + "heal_rotation_index", + "bot_id", + "interval", + "fast_heals", + "adaptive_targeting", + "casting_override", + "safe_hp_base", + "safe_hp_cloth", + "safe_hp_leather", + "safe_hp_chain", + "safe_hp_plate", + "critical_hp_base", + "critical_hp_cloth", + "critical_hp_leather", + "critical_hp_chain", + "critical_hp_plate", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_heal_rotations"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotHealRotations NewEntity() + { + BotHealRotations e{}; + + e.heal_rotation_index = 0; + e.bot_id = 0; + e.interval = 0; + e.fast_heals = 0; + e.adaptive_targeting = 0; + e.casting_override = 0; + e.safe_hp_base = 0; + e.safe_hp_cloth = 0; + e.safe_hp_leather = 0; + e.safe_hp_chain = 0; + e.safe_hp_plate = 0; + e.critical_hp_base = 0; + e.critical_hp_cloth = 0; + e.critical_hp_leather = 0; + e.critical_hp_chain = 0; + e.critical_hp_plate = 0; + + return e; + } + + static BotHealRotations GetBotHealRotations( + const std::vector &bot_heal_rotationss, + int bot_heal_rotations_id + ) + { + for (auto &bot_heal_rotations : bot_heal_rotationss) { + if (bot_heal_rotations.heal_rotation_index == bot_heal_rotations_id) { + return bot_heal_rotations; + } + } + + return NewEntity(); + } + + static BotHealRotations FindOne( + Database& db, + int bot_heal_rotations_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_heal_rotations_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotHealRotations e{}; + + e.heal_rotation_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.interval = static_cast(strtoul(row[2], nullptr, 10)); + e.fast_heals = static_cast(strtoul(row[3], nullptr, 10)); + e.adaptive_targeting = static_cast(strtoul(row[4], nullptr, 10)); + e.casting_override = static_cast(strtoul(row[5], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_heal_rotations_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_heal_rotations_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotHealRotations &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.interval)); + v.push_back(columns[3] + " = " + std::to_string(e.fast_heals)); + v.push_back(columns[4] + " = " + std::to_string(e.adaptive_targeting)); + v.push_back(columns[5] + " = " + std::to_string(e.casting_override)); + v.push_back(columns[6] + " = " + std::to_string(e.safe_hp_base)); + v.push_back(columns[7] + " = " + std::to_string(e.safe_hp_cloth)); + v.push_back(columns[8] + " = " + std::to_string(e.safe_hp_leather)); + v.push_back(columns[9] + " = " + std::to_string(e.safe_hp_chain)); + v.push_back(columns[10] + " = " + std::to_string(e.safe_hp_plate)); + v.push_back(columns[11] + " = " + std::to_string(e.critical_hp_base)); + v.push_back(columns[12] + " = " + std::to_string(e.critical_hp_cloth)); + v.push_back(columns[13] + " = " + std::to_string(e.critical_hp_leather)); + v.push_back(columns[14] + " = " + std::to_string(e.critical_hp_chain)); + v.push_back(columns[15] + " = " + std::to_string(e.critical_hp_plate)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.heal_rotation_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotHealRotations InsertOne( + Database& db, + BotHealRotations e + ) + { + std::vector v; + + v.push_back(std::to_string(e.heal_rotation_index)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.interval)); + v.push_back(std::to_string(e.fast_heals)); + v.push_back(std::to_string(e.adaptive_targeting)); + v.push_back(std::to_string(e.casting_override)); + v.push_back(std::to_string(e.safe_hp_base)); + v.push_back(std::to_string(e.safe_hp_cloth)); + v.push_back(std::to_string(e.safe_hp_leather)); + v.push_back(std::to_string(e.safe_hp_chain)); + v.push_back(std::to_string(e.safe_hp_plate)); + v.push_back(std::to_string(e.critical_hp_base)); + v.push_back(std::to_string(e.critical_hp_cloth)); + v.push_back(std::to_string(e.critical_hp_leather)); + v.push_back(std::to_string(e.critical_hp_chain)); + v.push_back(std::to_string(e.critical_hp_plate)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.heal_rotation_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.heal_rotation_index)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.interval)); + v.push_back(std::to_string(e.fast_heals)); + v.push_back(std::to_string(e.adaptive_targeting)); + v.push_back(std::to_string(e.casting_override)); + v.push_back(std::to_string(e.safe_hp_base)); + v.push_back(std::to_string(e.safe_hp_cloth)); + v.push_back(std::to_string(e.safe_hp_leather)); + v.push_back(std::to_string(e.safe_hp_chain)); + v.push_back(std::to_string(e.safe_hp_plate)); + v.push_back(std::to_string(e.critical_hp_base)); + v.push_back(std::to_string(e.critical_hp_cloth)); + v.push_back(std::to_string(e.critical_hp_leather)); + v.push_back(std::to_string(e.critical_hp_chain)); + v.push_back(std::to_string(e.critical_hp_plate)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotHealRotations e{}; + + e.heal_rotation_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.interval = static_cast(strtoul(row[2], nullptr, 10)); + e.fast_heals = static_cast(strtoul(row[3], nullptr, 10)); + e.adaptive_targeting = static_cast(strtoul(row[4], nullptr, 10)); + e.casting_override = static_cast(strtoul(row[5], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotHealRotations e{}; + + e.heal_rotation_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.interval = static_cast(strtoul(row[2], nullptr, 10)); + e.fast_heals = static_cast(strtoul(row[3], nullptr, 10)); + e.adaptive_targeting = static_cast(strtoul(row[4], nullptr, 10)); + e.casting_override = static_cast(strtoul(row[5], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_inspect_messages_repository.h b/common/repositories/base/base_bot_inspect_messages_repository.h new file mode 100644 index 000000000..bcf19437e --- /dev/null +++ b/common/repositories/base/base_bot_inspect_messages_repository.h @@ -0,0 +1,333 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_INSPECT_MESSAGES_REPOSITORY_H +#define EQEMU_BASE_BOT_INSPECT_MESSAGES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotInspectMessagesRepository { +public: + struct BotInspectMessages { + uint32_t bot_id; + std::string inspect_message; + }; + + static std::string PrimaryKey() + { + return std::string("bot_id"); + } + + static std::vector Columns() + { + return { + "bot_id", + "inspect_message", + }; + } + + static std::vector SelectColumns() + { + return { + "bot_id", + "inspect_message", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_inspect_messages"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotInspectMessages NewEntity() + { + BotInspectMessages e{}; + + e.bot_id = 0; + e.inspect_message = ""; + + return e; + } + + static BotInspectMessages GetBotInspectMessages( + const std::vector &bot_inspect_messagess, + int bot_inspect_messages_id + ) + { + for (auto &bot_inspect_messages : bot_inspect_messagess) { + if (bot_inspect_messages.bot_id == bot_inspect_messages_id) { + return bot_inspect_messages; + } + } + + return NewEntity(); + } + + static BotInspectMessages FindOne( + Database& db, + int bot_inspect_messages_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_inspect_messages_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotInspectMessages e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.inspect_message = row[1] ? row[1] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_inspect_messages_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_inspect_messages_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotInspectMessages &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.inspect_message) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.bot_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotInspectMessages InsertOne( + Database& db, + BotInspectMessages e + ) + { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back("'" + Strings::Escape(e.inspect_message) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.bot_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back("'" + Strings::Escape(e.inspect_message) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotInspectMessages e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.inspect_message = row[1] ? row[1] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotInspectMessages e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.inspect_message = row[1] ? row[1] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_INSPECT_MESSAGES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_inventories_repository.h b/common/repositories/base/base_bot_inventories_repository.h new file mode 100644 index 000000000..4f0545148 --- /dev/null +++ b/common/repositories/base/base_bot_inventories_repository.h @@ -0,0 +1,482 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H +#define EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotInventoriesRepository { +public: + struct BotInventories { + uint32_t inventories_index; + uint32_t bot_id; + uint32_t slot_id; + uint32_t item_id; + uint16_t inst_charges; + uint32_t inst_color; + uint8_t inst_no_drop; + std::string inst_custom_data; + uint32_t ornament_icon; + uint32_t ornament_id_file; + int32_t ornament_hero_model; + uint32_t augment_1; + uint32_t augment_2; + uint32_t augment_3; + uint32_t augment_4; + uint32_t augment_5; + uint32_t augment_6; + }; + + static std::string PrimaryKey() + { + return std::string("inventories_index"); + } + + static std::vector Columns() + { + return { + "inventories_index", + "bot_id", + "slot_id", + "item_id", + "inst_charges", + "inst_color", + "inst_no_drop", + "inst_custom_data", + "ornament_icon", + "ornament_id_file", + "ornament_hero_model", + "augment_1", + "augment_2", + "augment_3", + "augment_4", + "augment_5", + "augment_6", + }; + } + + static std::vector SelectColumns() + { + return { + "inventories_index", + "bot_id", + "slot_id", + "item_id", + "inst_charges", + "inst_color", + "inst_no_drop", + "inst_custom_data", + "ornament_icon", + "ornament_id_file", + "ornament_hero_model", + "augment_1", + "augment_2", + "augment_3", + "augment_4", + "augment_5", + "augment_6", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_inventories"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotInventories NewEntity() + { + BotInventories e{}; + + e.inventories_index = 0; + e.bot_id = 0; + e.slot_id = 0; + e.item_id = 0; + e.inst_charges = 0; + e.inst_color = 0; + e.inst_no_drop = 0; + e.inst_custom_data = ""; + e.ornament_icon = 0; + e.ornament_id_file = 0; + e.ornament_hero_model = 0; + e.augment_1 = 0; + e.augment_2 = 0; + e.augment_3 = 0; + e.augment_4 = 0; + e.augment_5 = 0; + e.augment_6 = 0; + + return e; + } + + static BotInventories GetBotInventories( + const std::vector &bot_inventoriess, + int bot_inventories_id + ) + { + for (auto &bot_inventories : bot_inventoriess) { + if (bot_inventories.inventories_index == bot_inventories_id) { + return bot_inventories; + } + } + + return NewEntity(); + } + + static BotInventories FindOne( + Database& db, + int bot_inventories_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_inventories_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotInventories e{}; + + e.inventories_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); + e.inst_charges = static_cast(strtoul(row[4], nullptr, 10)); + e.inst_color = static_cast(strtoul(row[5], nullptr, 10)); + e.inst_no_drop = static_cast(strtoul(row[6], nullptr, 10)); + e.inst_custom_data = row[7] ? row[7] : ""; + e.ornament_icon = static_cast(strtoul(row[8], nullptr, 10)); + e.ornament_id_file = static_cast(strtoul(row[9], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[10])); + e.augment_1 = static_cast(strtoul(row[11], nullptr, 10)); + e.augment_2 = static_cast(strtoul(row[12], nullptr, 10)); + e.augment_3 = static_cast(strtoul(row[13], nullptr, 10)); + e.augment_4 = static_cast(strtoul(row[14], nullptr, 10)); + e.augment_5 = static_cast(strtoul(row[15], nullptr, 10)); + e.augment_6 = static_cast(strtoul(row[16], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_inventories_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_inventories_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotInventories &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.slot_id)); + v.push_back(columns[3] + " = " + std::to_string(e.item_id)); + v.push_back(columns[4] + " = " + std::to_string(e.inst_charges)); + v.push_back(columns[5] + " = " + std::to_string(e.inst_color)); + v.push_back(columns[6] + " = " + std::to_string(e.inst_no_drop)); + v.push_back(columns[7] + " = '" + Strings::Escape(e.inst_custom_data) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.ornament_icon)); + v.push_back(columns[9] + " = " + std::to_string(e.ornament_id_file)); + v.push_back(columns[10] + " = " + std::to_string(e.ornament_hero_model)); + v.push_back(columns[11] + " = " + std::to_string(e.augment_1)); + v.push_back(columns[12] + " = " + std::to_string(e.augment_2)); + v.push_back(columns[13] + " = " + std::to_string(e.augment_3)); + v.push_back(columns[14] + " = " + std::to_string(e.augment_4)); + v.push_back(columns[15] + " = " + std::to_string(e.augment_5)); + v.push_back(columns[16] + " = " + std::to_string(e.augment_6)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.inventories_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotInventories InsertOne( + Database& db, + BotInventories e + ) + { + std::vector v; + + v.push_back(std::to_string(e.inventories_index)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.inst_charges)); + v.push_back(std::to_string(e.inst_color)); + v.push_back(std::to_string(e.inst_no_drop)); + v.push_back("'" + Strings::Escape(e.inst_custom_data) + "'"); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_id_file)); + v.push_back(std::to_string(e.ornament_hero_model)); + v.push_back(std::to_string(e.augment_1)); + v.push_back(std::to_string(e.augment_2)); + v.push_back(std::to_string(e.augment_3)); + v.push_back(std::to_string(e.augment_4)); + v.push_back(std::to_string(e.augment_5)); + v.push_back(std::to_string(e.augment_6)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.inventories_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.inventories_index)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.inst_charges)); + v.push_back(std::to_string(e.inst_color)); + v.push_back(std::to_string(e.inst_no_drop)); + v.push_back("'" + Strings::Escape(e.inst_custom_data) + "'"); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_id_file)); + v.push_back(std::to_string(e.ornament_hero_model)); + v.push_back(std::to_string(e.augment_1)); + v.push_back(std::to_string(e.augment_2)); + v.push_back(std::to_string(e.augment_3)); + v.push_back(std::to_string(e.augment_4)); + v.push_back(std::to_string(e.augment_5)); + v.push_back(std::to_string(e.augment_6)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotInventories e{}; + + e.inventories_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); + e.inst_charges = static_cast(strtoul(row[4], nullptr, 10)); + e.inst_color = static_cast(strtoul(row[5], nullptr, 10)); + e.inst_no_drop = static_cast(strtoul(row[6], nullptr, 10)); + e.inst_custom_data = row[7] ? row[7] : ""; + e.ornament_icon = static_cast(strtoul(row[8], nullptr, 10)); + e.ornament_id_file = static_cast(strtoul(row[9], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[10])); + e.augment_1 = static_cast(strtoul(row[11], nullptr, 10)); + e.augment_2 = static_cast(strtoul(row[12], nullptr, 10)); + e.augment_3 = static_cast(strtoul(row[13], nullptr, 10)); + e.augment_4 = static_cast(strtoul(row[14], nullptr, 10)); + e.augment_5 = static_cast(strtoul(row[15], nullptr, 10)); + e.augment_6 = static_cast(strtoul(row[16], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotInventories e{}; + + e.inventories_index = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); + e.inst_charges = static_cast(strtoul(row[4], nullptr, 10)); + e.inst_color = static_cast(strtoul(row[5], nullptr, 10)); + e.inst_no_drop = static_cast(strtoul(row[6], nullptr, 10)); + e.inst_custom_data = row[7] ? row[7] : ""; + e.ornament_icon = static_cast(strtoul(row[8], nullptr, 10)); + e.ornament_id_file = static_cast(strtoul(row[9], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[10])); + e.augment_1 = static_cast(strtoul(row[11], nullptr, 10)); + e.augment_2 = static_cast(strtoul(row[12], nullptr, 10)); + e.augment_3 = static_cast(strtoul(row[13], nullptr, 10)); + e.augment_4 = static_cast(strtoul(row[14], nullptr, 10)); + e.augment_5 = static_cast(strtoul(row[15], nullptr, 10)); + e.augment_6 = static_cast(strtoul(row[16], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_owner_options_repository.h b/common/repositories/base/base_bot_owner_options_repository.h new file mode 100644 index 000000000..3bc31c539 --- /dev/null +++ b/common/repositories/base/base_bot_owner_options_repository.h @@ -0,0 +1,343 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H +#define EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotOwnerOptionsRepository { +public: + struct BotOwnerOptions { + uint32_t owner_id; + uint16_t option_type; + uint16_t option_value; + }; + + static std::string PrimaryKey() + { + return std::string("owner_id"); + } + + static std::vector Columns() + { + return { + "owner_id", + "option_type", + "option_value", + }; + } + + static std::vector SelectColumns() + { + return { + "owner_id", + "option_type", + "option_value", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_owner_options"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotOwnerOptions NewEntity() + { + BotOwnerOptions e{}; + + e.owner_id = 0; + e.option_type = 0; + e.option_value = 0; + + return e; + } + + static BotOwnerOptions GetBotOwnerOptions( + const std::vector &bot_owner_optionss, + int bot_owner_options_id + ) + { + for (auto &bot_owner_options : bot_owner_optionss) { + if (bot_owner_options.owner_id == bot_owner_options_id) { + return bot_owner_options; + } + } + + return NewEntity(); + } + + static BotOwnerOptions FindOne( + Database& db, + int bot_owner_options_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_owner_options_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotOwnerOptions e{}; + + e.owner_id = static_cast(strtoul(row[0], nullptr, 10)); + e.option_type = static_cast(strtoul(row[1], nullptr, 10)); + e.option_value = static_cast(strtoul(row[2], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_owner_options_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_owner_options_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotOwnerOptions &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.owner_id)); + v.push_back(columns[1] + " = " + std::to_string(e.option_type)); + v.push_back(columns[2] + " = " + std::to_string(e.option_value)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.owner_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotOwnerOptions InsertOne( + Database& db, + BotOwnerOptions e + ) + { + std::vector v; + + v.push_back(std::to_string(e.owner_id)); + v.push_back(std::to_string(e.option_type)); + v.push_back(std::to_string(e.option_value)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.owner_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.owner_id)); + v.push_back(std::to_string(e.option_type)); + v.push_back(std::to_string(e.option_value)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotOwnerOptions e{}; + + e.owner_id = static_cast(strtoul(row[0], nullptr, 10)); + e.option_type = static_cast(strtoul(row[1], nullptr, 10)); + e.option_value = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotOwnerOptions e{}; + + e.owner_id = static_cast(strtoul(row[0], nullptr, 10)); + e.option_type = static_cast(strtoul(row[1], nullptr, 10)); + e.option_value = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_pet_buffs_repository.h b/common/repositories/base/base_bot_pet_buffs_repository.h new file mode 100644 index 000000000..e5b8fb92c --- /dev/null +++ b/common/repositories/base/base_bot_pet_buffs_repository.h @@ -0,0 +1,362 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H +#define EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotPetBuffsRepository { +public: + struct BotPetBuffs { + uint32_t pet_buffs_index; + uint32_t pets_index; + uint32_t spell_id; + uint32_t caster_level; + uint32_t duration; + }; + + static std::string PrimaryKey() + { + return std::string("pet_buffs_index"); + } + + static std::vector Columns() + { + return { + "pet_buffs_index", + "pets_index", + "spell_id", + "caster_level", + "duration", + }; + } + + static std::vector SelectColumns() + { + return { + "pet_buffs_index", + "pets_index", + "spell_id", + "caster_level", + "duration", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_pet_buffs"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotPetBuffs NewEntity() + { + BotPetBuffs e{}; + + e.pet_buffs_index = 0; + e.pets_index = 0; + e.spell_id = 0; + e.caster_level = 0; + e.duration = 0; + + return e; + } + + static BotPetBuffs GetBotPetBuffs( + const std::vector &bot_pet_buffss, + int bot_pet_buffs_id + ) + { + for (auto &bot_pet_buffs : bot_pet_buffss) { + if (bot_pet_buffs.pet_buffs_index == bot_pet_buffs_id) { + return bot_pet_buffs; + } + } + + return NewEntity(); + } + + static BotPetBuffs FindOne( + Database& db, + int bot_pet_buffs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_pet_buffs_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotPetBuffs e{}; + + e.pet_buffs_index = static_cast(strtoul(row[0], nullptr, 10)); + e.pets_index = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.duration = static_cast(strtoul(row[4], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_pet_buffs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_pet_buffs_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotPetBuffs &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.pets_index)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[3] + " = " + std::to_string(e.caster_level)); + v.push_back(columns[4] + " = " + std::to_string(e.duration)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.pet_buffs_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotPetBuffs InsertOne( + Database& db, + BotPetBuffs e + ) + { + std::vector v; + + v.push_back(std::to_string(e.pet_buffs_index)); + v.push_back(std::to_string(e.pets_index)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back(std::to_string(e.duration)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.pet_buffs_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.pet_buffs_index)); + v.push_back(std::to_string(e.pets_index)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back(std::to_string(e.duration)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotPetBuffs e{}; + + e.pet_buffs_index = static_cast(strtoul(row[0], nullptr, 10)); + e.pets_index = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.duration = static_cast(strtoul(row[4], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotPetBuffs e{}; + + e.pet_buffs_index = static_cast(strtoul(row[0], nullptr, 10)); + e.pets_index = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.duration = static_cast(strtoul(row[4], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_pet_inventories_repository.h b/common/repositories/base/base_bot_pet_inventories_repository.h new file mode 100644 index 000000000..f8c9e918f --- /dev/null +++ b/common/repositories/base/base_bot_pet_inventories_repository.h @@ -0,0 +1,342 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H +#define EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotPetInventoriesRepository { +public: + struct BotPetInventories { + uint32_t pet_inventories_index; + uint32_t pets_index; + uint32_t item_id; + }; + + static std::string PrimaryKey() + { + return std::string("pet_inventories_index"); + } + + static std::vector Columns() + { + return { + "pet_inventories_index", + "pets_index", + "item_id", + }; + } + + static std::vector SelectColumns() + { + return { + "pet_inventories_index", + "pets_index", + "item_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_pet_inventories"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotPetInventories NewEntity() + { + BotPetInventories e{}; + + e.pet_inventories_index = 0; + e.pets_index = 0; + e.item_id = 0; + + return e; + } + + static BotPetInventories GetBotPetInventories( + const std::vector &bot_pet_inventoriess, + int bot_pet_inventories_id + ) + { + for (auto &bot_pet_inventories : bot_pet_inventoriess) { + if (bot_pet_inventories.pet_inventories_index == bot_pet_inventories_id) { + return bot_pet_inventories; + } + } + + return NewEntity(); + } + + static BotPetInventories FindOne( + Database& db, + int bot_pet_inventories_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_pet_inventories_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotPetInventories e{}; + + e.pet_inventories_index = static_cast(strtoul(row[0], nullptr, 10)); + e.pets_index = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_pet_inventories_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_pet_inventories_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotPetInventories &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.pets_index)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.pet_inventories_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotPetInventories InsertOne( + Database& db, + BotPetInventories e + ) + { + std::vector v; + + v.push_back(std::to_string(e.pet_inventories_index)); + v.push_back(std::to_string(e.pets_index)); + v.push_back(std::to_string(e.item_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.pet_inventories_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.pet_inventories_index)); + v.push_back(std::to_string(e.pets_index)); + v.push_back(std::to_string(e.item_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotPetInventories e{}; + + e.pet_inventories_index = static_cast(strtoul(row[0], nullptr, 10)); + e.pets_index = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotPetInventories e{}; + + e.pet_inventories_index = static_cast(strtoul(row[0], nullptr, 10)); + e.pets_index = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_pets_repository.h b/common/repositories/base/base_bot_pets_repository.h new file mode 100644 index 000000000..59e43a6dc --- /dev/null +++ b/common/repositories/base/base_bot_pets_repository.h @@ -0,0 +1,372 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_PETS_REPOSITORY_H +#define EQEMU_BASE_BOT_PETS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotPetsRepository { +public: + struct BotPets { + uint32_t pets_index; + uint32_t spell_id; + uint32_t bot_id; + std::string name; + int32_t mana; + int32_t hp; + }; + + static std::string PrimaryKey() + { + return std::string("pets_index"); + } + + static std::vector Columns() + { + return { + "pets_index", + "spell_id", + "bot_id", + "name", + "mana", + "hp", + }; + } + + static std::vector SelectColumns() + { + return { + "pets_index", + "spell_id", + "bot_id", + "name", + "mana", + "hp", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_pets"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotPets NewEntity() + { + BotPets e{}; + + e.pets_index = 0; + e.spell_id = 0; + e.bot_id = 0; + e.name = ""; + e.mana = 0; + e.hp = 0; + + return e; + } + + static BotPets GetBotPets( + const std::vector &bot_petss, + int bot_pets_id + ) + { + for (auto &bot_pets : bot_petss) { + if (bot_pets.pets_index == bot_pets_id) { + return bot_pets; + } + } + + return NewEntity(); + } + + static BotPets FindOne( + Database& db, + int bot_pets_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_pets_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotPets e{}; + + e.pets_index = static_cast(strtoul(row[0], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.mana = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_pets_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_pets_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotPets &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[2] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.mana)); + v.push_back(columns[5] + " = " + std::to_string(e.hp)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.pets_index + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotPets InsertOne( + Database& db, + BotPets e + ) + { + std::vector v; + + v.push_back(std::to_string(e.pets_index)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.bot_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.hp)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.pets_index = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.pets_index)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.bot_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.hp)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotPets e{}; + + e.pets_index = static_cast(strtoul(row[0], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.mana = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotPets e{}; + + e.pets_index = static_cast(strtoul(row[0], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[1], nullptr, 10)); + e.bot_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.mana = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_PETS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_spell_casting_chances_repository.h b/common/repositories/base/base_bot_spell_casting_chances_repository.h new file mode 100644 index 000000000..544c08d29 --- /dev/null +++ b/common/repositories/base/base_bot_spell_casting_chances_repository.h @@ -0,0 +1,512 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H +#define EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotSpellCastingChancesRepository { +public: + struct BotSpellCastingChances { + int32_t id; + uint8_t spell_type_index; + uint8_t class_id; + uint8_t stance_index; + uint8_t nHSND_value; + uint8_t pH_value; + uint8_t pS_value; + uint8_t pHS_value; + uint8_t pN_value; + uint8_t pHN_value; + uint8_t pSN_value; + uint8_t pHSN_value; + uint8_t pD_value; + uint8_t pHD_value; + uint8_t pSD_value; + uint8_t pHSD_value; + uint8_t pND_value; + uint8_t pHND_value; + uint8_t pSND_value; + uint8_t pHSND_value; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "spell_type_index", + "class_id", + "stance_index", + "nHSND_value", + "pH_value", + "pS_value", + "pHS_value", + "pN_value", + "pHN_value", + "pSN_value", + "pHSN_value", + "pD_value", + "pHD_value", + "pSD_value", + "pHSD_value", + "pND_value", + "pHND_value", + "pSND_value", + "pHSND_value", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "spell_type_index", + "class_id", + "stance_index", + "nHSND_value", + "pH_value", + "pS_value", + "pHS_value", + "pN_value", + "pHN_value", + "pSN_value", + "pHSN_value", + "pD_value", + "pHD_value", + "pSD_value", + "pHSD_value", + "pND_value", + "pHND_value", + "pSND_value", + "pHSND_value", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_spell_casting_chances"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotSpellCastingChances NewEntity() + { + BotSpellCastingChances e{}; + + e.id = 0; + e.spell_type_index = 0; + e.class_id = 0; + e.stance_index = 0; + e.nHSND_value = 0; + e.pH_value = 0; + e.pS_value = 0; + e.pHS_value = 0; + e.pN_value = 0; + e.pHN_value = 0; + e.pSN_value = 0; + e.pHSN_value = 0; + e.pD_value = 0; + e.pHD_value = 0; + e.pSD_value = 0; + e.pHSD_value = 0; + e.pND_value = 0; + e.pHND_value = 0; + e.pSND_value = 0; + e.pHSND_value = 0; + + return e; + } + + static BotSpellCastingChances GetBotSpellCastingChances( + const std::vector &bot_spell_casting_chancess, + int bot_spell_casting_chances_id + ) + { + for (auto &bot_spell_casting_chances : bot_spell_casting_chancess) { + if (bot_spell_casting_chances.id == bot_spell_casting_chances_id) { + return bot_spell_casting_chances; + } + } + + return NewEntity(); + } + + static BotSpellCastingChances FindOne( + Database& db, + int bot_spell_casting_chances_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_spell_casting_chances_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotSpellCastingChances e{}; + + e.id = static_cast(atoi(row[0])); + e.spell_type_index = static_cast(strtoul(row[1], nullptr, 10)); + e.class_id = static_cast(strtoul(row[2], nullptr, 10)); + e.stance_index = static_cast(strtoul(row[3], nullptr, 10)); + e.nHSND_value = static_cast(strtoul(row[4], nullptr, 10)); + e.pH_value = static_cast(strtoul(row[5], nullptr, 10)); + e.pS_value = static_cast(strtoul(row[6], nullptr, 10)); + e.pHS_value = static_cast(strtoul(row[7], nullptr, 10)); + e.pN_value = static_cast(strtoul(row[8], nullptr, 10)); + e.pHN_value = static_cast(strtoul(row[9], nullptr, 10)); + e.pSN_value = static_cast(strtoul(row[10], nullptr, 10)); + e.pHSN_value = static_cast(strtoul(row[11], nullptr, 10)); + e.pD_value = static_cast(strtoul(row[12], nullptr, 10)); + e.pHD_value = static_cast(strtoul(row[13], nullptr, 10)); + e.pSD_value = static_cast(strtoul(row[14], nullptr, 10)); + e.pHSD_value = static_cast(strtoul(row[15], nullptr, 10)); + e.pND_value = static_cast(strtoul(row[16], nullptr, 10)); + e.pHND_value = static_cast(strtoul(row[17], nullptr, 10)); + e.pSND_value = static_cast(strtoul(row[18], nullptr, 10)); + e.pHSND_value = static_cast(strtoul(row[19], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_spell_casting_chances_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_spell_casting_chances_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotSpellCastingChances &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.spell_type_index)); + v.push_back(columns[2] + " = " + std::to_string(e.class_id)); + v.push_back(columns[3] + " = " + std::to_string(e.stance_index)); + v.push_back(columns[4] + " = " + std::to_string(e.nHSND_value)); + v.push_back(columns[5] + " = " + std::to_string(e.pH_value)); + v.push_back(columns[6] + " = " + std::to_string(e.pS_value)); + v.push_back(columns[7] + " = " + std::to_string(e.pHS_value)); + v.push_back(columns[8] + " = " + std::to_string(e.pN_value)); + v.push_back(columns[9] + " = " + std::to_string(e.pHN_value)); + v.push_back(columns[10] + " = " + std::to_string(e.pSN_value)); + v.push_back(columns[11] + " = " + std::to_string(e.pHSN_value)); + v.push_back(columns[12] + " = " + std::to_string(e.pD_value)); + v.push_back(columns[13] + " = " + std::to_string(e.pHD_value)); + v.push_back(columns[14] + " = " + std::to_string(e.pSD_value)); + v.push_back(columns[15] + " = " + std::to_string(e.pHSD_value)); + v.push_back(columns[16] + " = " + std::to_string(e.pND_value)); + v.push_back(columns[17] + " = " + std::to_string(e.pHND_value)); + v.push_back(columns[18] + " = " + std::to_string(e.pSND_value)); + v.push_back(columns[19] + " = " + std::to_string(e.pHSND_value)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotSpellCastingChances InsertOne( + Database& db, + BotSpellCastingChances e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.spell_type_index)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.stance_index)); + v.push_back(std::to_string(e.nHSND_value)); + v.push_back(std::to_string(e.pH_value)); + v.push_back(std::to_string(e.pS_value)); + v.push_back(std::to_string(e.pHS_value)); + v.push_back(std::to_string(e.pN_value)); + v.push_back(std::to_string(e.pHN_value)); + v.push_back(std::to_string(e.pSN_value)); + v.push_back(std::to_string(e.pHSN_value)); + v.push_back(std::to_string(e.pD_value)); + v.push_back(std::to_string(e.pHD_value)); + v.push_back(std::to_string(e.pSD_value)); + v.push_back(std::to_string(e.pHSD_value)); + v.push_back(std::to_string(e.pND_value)); + v.push_back(std::to_string(e.pHND_value)); + v.push_back(std::to_string(e.pSND_value)); + v.push_back(std::to_string(e.pHSND_value)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.spell_type_index)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.stance_index)); + v.push_back(std::to_string(e.nHSND_value)); + v.push_back(std::to_string(e.pH_value)); + v.push_back(std::to_string(e.pS_value)); + v.push_back(std::to_string(e.pHS_value)); + v.push_back(std::to_string(e.pN_value)); + v.push_back(std::to_string(e.pHN_value)); + v.push_back(std::to_string(e.pSN_value)); + v.push_back(std::to_string(e.pHSN_value)); + v.push_back(std::to_string(e.pD_value)); + v.push_back(std::to_string(e.pHD_value)); + v.push_back(std::to_string(e.pSD_value)); + v.push_back(std::to_string(e.pHSD_value)); + v.push_back(std::to_string(e.pND_value)); + v.push_back(std::to_string(e.pHND_value)); + v.push_back(std::to_string(e.pSND_value)); + v.push_back(std::to_string(e.pHSND_value)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotSpellCastingChances e{}; + + e.id = static_cast(atoi(row[0])); + e.spell_type_index = static_cast(strtoul(row[1], nullptr, 10)); + e.class_id = static_cast(strtoul(row[2], nullptr, 10)); + e.stance_index = static_cast(strtoul(row[3], nullptr, 10)); + e.nHSND_value = static_cast(strtoul(row[4], nullptr, 10)); + e.pH_value = static_cast(strtoul(row[5], nullptr, 10)); + e.pS_value = static_cast(strtoul(row[6], nullptr, 10)); + e.pHS_value = static_cast(strtoul(row[7], nullptr, 10)); + e.pN_value = static_cast(strtoul(row[8], nullptr, 10)); + e.pHN_value = static_cast(strtoul(row[9], nullptr, 10)); + e.pSN_value = static_cast(strtoul(row[10], nullptr, 10)); + e.pHSN_value = static_cast(strtoul(row[11], nullptr, 10)); + e.pD_value = static_cast(strtoul(row[12], nullptr, 10)); + e.pHD_value = static_cast(strtoul(row[13], nullptr, 10)); + e.pSD_value = static_cast(strtoul(row[14], nullptr, 10)); + e.pHSD_value = static_cast(strtoul(row[15], nullptr, 10)); + e.pND_value = static_cast(strtoul(row[16], nullptr, 10)); + e.pHND_value = static_cast(strtoul(row[17], nullptr, 10)); + e.pSND_value = static_cast(strtoul(row[18], nullptr, 10)); + e.pHSND_value = static_cast(strtoul(row[19], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotSpellCastingChances e{}; + + e.id = static_cast(atoi(row[0])); + e.spell_type_index = static_cast(strtoul(row[1], nullptr, 10)); + e.class_id = static_cast(strtoul(row[2], nullptr, 10)); + e.stance_index = static_cast(strtoul(row[3], nullptr, 10)); + e.nHSND_value = static_cast(strtoul(row[4], nullptr, 10)); + e.pH_value = static_cast(strtoul(row[5], nullptr, 10)); + e.pS_value = static_cast(strtoul(row[6], nullptr, 10)); + e.pHS_value = static_cast(strtoul(row[7], nullptr, 10)); + e.pN_value = static_cast(strtoul(row[8], nullptr, 10)); + e.pHN_value = static_cast(strtoul(row[9], nullptr, 10)); + e.pSN_value = static_cast(strtoul(row[10], nullptr, 10)); + e.pHSN_value = static_cast(strtoul(row[11], nullptr, 10)); + e.pD_value = static_cast(strtoul(row[12], nullptr, 10)); + e.pHD_value = static_cast(strtoul(row[13], nullptr, 10)); + e.pSD_value = static_cast(strtoul(row[14], nullptr, 10)); + e.pHSD_value = static_cast(strtoul(row[15], nullptr, 10)); + e.pND_value = static_cast(strtoul(row[16], nullptr, 10)); + e.pHND_value = static_cast(strtoul(row[17], nullptr, 10)); + e.pSND_value = static_cast(strtoul(row[18], nullptr, 10)); + e.pHSND_value = static_cast(strtoul(row[19], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_spell_settings_repository.h b/common/repositories/base/base_bot_spell_settings_repository.h new file mode 100644 index 000000000..91fbeabd1 --- /dev/null +++ b/common/repositories/base/base_bot_spell_settings_repository.h @@ -0,0 +1,382 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H +#define EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotSpellSettingsRepository { +public: + struct BotSpellSettings { + uint32_t id; + int32_t bot_id; + int16_t spell_id; + int16_t priority; + int16_t min_hp; + int16_t max_hp; + uint8_t is_enabled; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "bot_id", + "spell_id", + "priority", + "min_hp", + "max_hp", + "is_enabled", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "bot_id", + "spell_id", + "priority", + "min_hp", + "max_hp", + "is_enabled", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_spell_settings"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotSpellSettings NewEntity() + { + BotSpellSettings e{}; + + e.id = 0; + e.bot_id = 0; + e.spell_id = 0; + e.priority = 0; + e.min_hp = 0; + e.max_hp = 0; + e.is_enabled = 1; + + return e; + } + + static BotSpellSettings GetBotSpellSettings( + const std::vector &bot_spell_settingss, + int bot_spell_settings_id + ) + { + for (auto &bot_spell_settings : bot_spell_settingss) { + if (bot_spell_settings.id == bot_spell_settings_id) { + return bot_spell_settings; + } + } + + return NewEntity(); + } + + static BotSpellSettings FindOne( + Database& db, + int bot_spell_settings_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_spell_settings_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotSpellSettings e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(atoi(row[1])); + e.spell_id = static_cast(atoi(row[2])); + e.priority = static_cast(atoi(row[3])); + e.min_hp = static_cast(atoi(row[4])); + e.max_hp = static_cast(atoi(row[5])); + e.is_enabled = static_cast(strtoul(row[6], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_spell_settings_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_spell_settings_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotSpellSettings &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[3] + " = " + std::to_string(e.priority)); + v.push_back(columns[4] + " = " + std::to_string(e.min_hp)); + v.push_back(columns[5] + " = " + std::to_string(e.max_hp)); + v.push_back(columns[6] + " = " + std::to_string(e.is_enabled)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotSpellSettings InsertOne( + Database& db, + BotSpellSettings e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.priority)); + v.push_back(std::to_string(e.min_hp)); + v.push_back(std::to_string(e.max_hp)); + v.push_back(std::to_string(e.is_enabled)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.priority)); + v.push_back(std::to_string(e.min_hp)); + v.push_back(std::to_string(e.max_hp)); + v.push_back(std::to_string(e.is_enabled)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotSpellSettings e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(atoi(row[1])); + e.spell_id = static_cast(atoi(row[2])); + e.priority = static_cast(atoi(row[3])); + e.min_hp = static_cast(atoi(row[4])); + e.max_hp = static_cast(atoi(row[5])); + e.is_enabled = static_cast(strtoul(row[6], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotSpellSettings e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.bot_id = static_cast(atoi(row[1])); + e.spell_id = static_cast(atoi(row[2])); + e.priority = static_cast(atoi(row[3])); + e.min_hp = static_cast(atoi(row[4])); + e.max_hp = static_cast(atoi(row[5])); + e.is_enabled = static_cast(strtoul(row[6], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_spells_entries_repository.h b/common/repositories/base/base_bot_spells_entries_repository.h new file mode 100644 index 000000000..72a7d837a --- /dev/null +++ b/common/repositories/base/base_bot_spells_entries_repository.h @@ -0,0 +1,462 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotSpellsEntriesRepository { +public: + struct BotSpellsEntries { + uint32_t id; + int32_t npc_spells_id; + int16_t spellid; + uint32_t type; + uint8_t minlevel; + uint8_t maxlevel; + int16_t manacost; + int32_t recast_delay; + int16_t priority; + int32_t resist_adjust; + int16_t min_hp; + int16_t max_hp; + std::string bucket_name; + std::string bucket_value; + uint8_t bucket_comparison; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_spells_id", + "spellid", + "type", + "minlevel", + "maxlevel", + "manacost", + "recast_delay", + "priority", + "resist_adjust", + "min_hp", + "max_hp", + "bucket_name", + "bucket_value", + "bucket_comparison", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_spells_id", + "spellid", + "type", + "minlevel", + "maxlevel", + "manacost", + "recast_delay", + "priority", + "resist_adjust", + "min_hp", + "max_hp", + "bucket_name", + "bucket_value", + "bucket_comparison", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_spells_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotSpellsEntries NewEntity() + { + BotSpellsEntries e{}; + + e.id = 0; + e.npc_spells_id = 0; + e.spellid = 0; + e.type = 0; + e.minlevel = 0; + e.maxlevel = 255; + e.manacost = -1; + e.recast_delay = -1; + e.priority = 0; + e.resist_adjust = 0; + e.min_hp = 0; + e.max_hp = 0; + e.bucket_name = ""; + e.bucket_value = ""; + e.bucket_comparison = 0; + + return e; + } + + static BotSpellsEntries GetBotSpellsEntries( + const std::vector &bot_spells_entriess, + int bot_spells_entries_id + ) + { + for (auto &bot_spells_entries : bot_spells_entriess) { + if (bot_spells_entries.id == bot_spells_entries_id) { + return bot_spells_entries; + } + } + + return NewEntity(); + } + + static BotSpellsEntries FindOne( + Database& db, + int bot_spells_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_spells_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotSpellsEntries e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_id = static_cast(atoi(row[1])); + e.spellid = static_cast(atoi(row[2])); + e.type = static_cast(strtoul(row[3], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.manacost = static_cast(atoi(row[6])); + e.recast_delay = static_cast(atoi(row[7])); + e.priority = static_cast(atoi(row[8])); + e.resist_adjust = static_cast(atoi(row[9])); + e.min_hp = static_cast(atoi(row[10])); + e.max_hp = static_cast(atoi(row[11])); + e.bucket_name = row[12] ? row[12] : ""; + e.bucket_value = row[13] ? row[13] : ""; + e.bucket_comparison = static_cast(strtoul(row[14], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_spells_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_spells_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotSpellsEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spellid)); + v.push_back(columns[3] + " = " + std::to_string(e.type)); + v.push_back(columns[4] + " = " + std::to_string(e.minlevel)); + v.push_back(columns[5] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[6] + " = " + std::to_string(e.manacost)); + v.push_back(columns[7] + " = " + std::to_string(e.recast_delay)); + v.push_back(columns[8] + " = " + std::to_string(e.priority)); + v.push_back(columns[9] + " = " + std::to_string(e.resist_adjust)); + v.push_back(columns[10] + " = " + std::to_string(e.min_hp)); + v.push_back(columns[11] + " = " + std::to_string(e.max_hp)); + v.push_back(columns[12] + " = '" + Strings::Escape(e.bucket_name) + "'"); + v.push_back(columns[13] + " = '" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(columns[14] + " = " + std::to_string(e.bucket_comparison)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotSpellsEntries InsertOne( + Database& db, + BotSpellsEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_spells_id)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.manacost)); + v.push_back(std::to_string(e.recast_delay)); + v.push_back(std::to_string(e.priority)); + v.push_back(std::to_string(e.resist_adjust)); + v.push_back(std::to_string(e.min_hp)); + v.push_back(std::to_string(e.max_hp)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_spells_id)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.manacost)); + v.push_back(std::to_string(e.recast_delay)); + v.push_back(std::to_string(e.priority)); + v.push_back(std::to_string(e.resist_adjust)); + v.push_back(std::to_string(e.min_hp)); + v.push_back(std::to_string(e.max_hp)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotSpellsEntries e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_id = static_cast(atoi(row[1])); + e.spellid = static_cast(atoi(row[2])); + e.type = static_cast(strtoul(row[3], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.manacost = static_cast(atoi(row[6])); + e.recast_delay = static_cast(atoi(row[7])); + e.priority = static_cast(atoi(row[8])); + e.resist_adjust = static_cast(atoi(row[9])); + e.min_hp = static_cast(atoi(row[10])); + e.max_hp = static_cast(atoi(row[11])); + e.bucket_name = row[12] ? row[12] : ""; + e.bucket_value = row[13] ? row[13] : ""; + e.bucket_comparison = static_cast(strtoul(row[14], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotSpellsEntries e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_id = static_cast(atoi(row[1])); + e.spellid = static_cast(atoi(row[2])); + e.type = static_cast(strtoul(row[3], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.manacost = static_cast(atoi(row[6])); + e.recast_delay = static_cast(atoi(row[7])); + e.priority = static_cast(atoi(row[8])); + e.resist_adjust = static_cast(atoi(row[9])); + e.min_hp = static_cast(atoi(row[10])); + e.max_hp = static_cast(atoi(row[11])); + e.bucket_name = row[12] ? row[12] : ""; + e.bucket_value = row[13] ? row[13] : ""; + e.bucket_comparison = static_cast(strtoul(row[14], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_stances_repository.h b/common/repositories/base/base_bot_stances_repository.h new file mode 100644 index 000000000..045203d63 --- /dev/null +++ b/common/repositories/base/base_bot_stances_repository.h @@ -0,0 +1,333 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_STANCES_REPOSITORY_H +#define EQEMU_BASE_BOT_STANCES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotStancesRepository { +public: + struct BotStances { + uint32_t bot_id; + uint8_t stance_id; + }; + + static std::string PrimaryKey() + { + return std::string("bot_id"); + } + + static std::vector Columns() + { + return { + "bot_id", + "stance_id", + }; + } + + static std::vector SelectColumns() + { + return { + "bot_id", + "stance_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_stances"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotStances NewEntity() + { + BotStances e{}; + + e.bot_id = 0; + e.stance_id = 0; + + return e; + } + + static BotStances GetBotStances( + const std::vector &bot_stancess, + int bot_stances_id + ) + { + for (auto &bot_stances : bot_stancess) { + if (bot_stances.bot_id == bot_stances_id) { + return bot_stances; + } + } + + return NewEntity(); + } + + static BotStances FindOne( + Database& db, + int bot_stances_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_stances_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotStances e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[1], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_stances_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_stances_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotStances &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[1] + " = " + std::to_string(e.stance_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.bot_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotStances InsertOne( + Database& db, + BotStances e + ) + { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.stance_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.bot_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.stance_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotStances e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[1], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotStances e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[1], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_STANCES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_timers_repository.h b/common/repositories/base/base_bot_timers_repository.h new file mode 100644 index 000000000..16858859b --- /dev/null +++ b/common/repositories/base/base_bot_timers_repository.h @@ -0,0 +1,343 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_BOT_TIMERS_REPOSITORY_H +#define EQEMU_BASE_BOT_TIMERS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseBotTimersRepository { +public: + struct BotTimers { + uint32_t bot_id; + uint32_t timer_id; + uint32_t timer_value; + }; + + static std::string PrimaryKey() + { + return std::string("bot_id"); + } + + static std::vector Columns() + { + return { + "bot_id", + "timer_id", + "timer_value", + }; + } + + static std::vector SelectColumns() + { + return { + "bot_id", + "timer_id", + "timer_value", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("bot_timers"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static BotTimers NewEntity() + { + BotTimers e{}; + + e.bot_id = 0; + e.timer_id = 0; + e.timer_value = 0; + + return e; + } + + static BotTimers GetBotTimers( + const std::vector &bot_timerss, + int bot_timers_id + ) + { + for (auto &bot_timers : bot_timerss) { + if (bot_timers.bot_id == bot_timers_id) { + return bot_timers; + } + } + + return NewEntity(); + } + + static BotTimers FindOne( + Database& db, + int bot_timers_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + bot_timers_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + BotTimers e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.timer_id = static_cast(strtoul(row[1], nullptr, 10)); + e.timer_value = static_cast(strtoul(row[2], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int bot_timers_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + bot_timers_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const BotTimers &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[1] + " = " + std::to_string(e.timer_id)); + v.push_back(columns[2] + " = " + std::to_string(e.timer_value)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.bot_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static BotTimers InsertOne( + Database& db, + BotTimers e + ) + { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.timer_id)); + v.push_back(std::to_string(e.timer_value)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.bot_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.bot_id)); + v.push_back(std::to_string(e.timer_id)); + v.push_back(std::to_string(e.timer_value)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotTimers e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.timer_id = static_cast(strtoul(row[1], nullptr, 10)); + e.timer_value = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + BotTimers e{}; + + e.bot_id = static_cast(strtoul(row[0], nullptr, 10)); + e.timer_id = static_cast(strtoul(row[1], nullptr, 10)); + e.timer_value = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_BOT_TIMERS_REPOSITORY_H diff --git a/common/repositories/base/base_bug_reports_repository.h b/common/repositories/base/base_bug_reports_repository.h index db65d5e05..5e38742fa 100644 --- a/common/repositories/base/base_bug_reports_repository.h +++ b/common/repositories/base/base_bug_reports_repository.h @@ -13,41 +13,41 @@ #define EQEMU_BASE_BUG_REPORTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseBugReportsRepository { public: struct BugReports { - int id; + uint32_t id; std::string zone; - int client_version_id; + uint32_t client_version_id; std::string client_version_name; - int account_id; - int character_id; + uint32_t account_id; + uint32_t character_id; std::string character_name; - int reporter_spoof; - int category_id; + int8_t reporter_spoof; + uint32_t category_id; std::string category_name; std::string reporter_name; std::string ui_path; float pos_x; float pos_y; float pos_z; - int heading; - int time_played; - int target_id; + uint32_t heading; + uint32_t time_played; + uint32_t target_id; std::string target_name; - int optional_info_mask; - int _can_duplicate; - int _crash_bug; - int _target_info; - int _character_flags; - int _unknown_value; + uint32_t optional_info_mask; + int8_t _can_duplicate; + int8_t _crash_bug; + int8_t _target_info; + int8_t _character_flags; + int8_t _unknown_value; std::string bug_report; std::string system_info; time_t report_datetime; - int bug_status; + uint8_t bug_status; time_t last_review; std::string last_reviewer; std::string reviewer_notes; @@ -136,12 +136,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -169,45 +169,45 @@ public: static BugReports NewEntity() { - BugReports entry{}; + BugReports e{}; - entry.id = 0; - entry.zone = "Unknown"; - entry.client_version_id = 0; - entry.client_version_name = "Unknown"; - entry.account_id = 0; - entry.character_id = 0; - entry.character_name = "Unknown"; - entry.reporter_spoof = 1; - entry.category_id = 0; - entry.category_name = "Other"; - entry.reporter_name = "Unknown"; - entry.ui_path = "Unknown"; - entry.pos_x = 0; - entry.pos_y = 0; - entry.pos_z = 0; - entry.heading = 0; - entry.time_played = 0; - entry.target_id = 0; - entry.target_name = "Unknown"; - entry.optional_info_mask = 0; - entry._can_duplicate = 0; - entry._crash_bug = 0; - entry._target_info = 0; - entry._character_flags = 0; - entry._unknown_value = 0; - entry.bug_report = ""; - entry.system_info = ""; - entry.report_datetime = std::time(nullptr); - entry.bug_status = 0; - entry.last_review = std::time(nullptr); - entry.last_reviewer = "None"; - entry.reviewer_notes = ""; + e.id = 0; + e.zone = "Unknown"; + e.client_version_id = 0; + e.client_version_name = "Unknown"; + e.account_id = 0; + e.character_id = 0; + e.character_name = "Unknown"; + e.reporter_spoof = 1; + e.category_id = 0; + e.category_name = "Other"; + e.reporter_name = "Unknown"; + e.ui_path = "Unknown"; + e.pos_x = 0; + e.pos_y = 0; + e.pos_z = 0; + e.heading = 0; + e.time_played = 0; + e.target_id = 0; + e.target_name = "Unknown"; + e.optional_info_mask = 0; + e._can_duplicate = 0; + e._crash_bug = 0; + e._target_info = 0; + e._character_flags = 0; + e._unknown_value = 0; + e.bug_report = ""; + e.system_info = ""; + e.report_datetime = std::time(nullptr); + e.bug_status = 0; + e.last_review = std::time(nullptr); + e.last_reviewer = "None"; + e.reviewer_notes = ""; - return entry; + return e; } - static BugReports GetBugReportsEntry( + static BugReports GetBugReports( const std::vector &bug_reportss, int bug_reports_id ) @@ -236,42 +236,42 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - BugReports entry{}; + BugReports e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.client_version_id = atoi(row[2]); - entry.client_version_name = row[3] ? row[3] : ""; - entry.account_id = atoi(row[4]); - entry.character_id = atoi(row[5]); - entry.character_name = row[6] ? row[6] : ""; - entry.reporter_spoof = atoi(row[7]); - entry.category_id = atoi(row[8]); - entry.category_name = row[9] ? row[9] : ""; - entry.reporter_name = row[10] ? row[10] : ""; - entry.ui_path = row[11] ? row[11] : ""; - entry.pos_x = static_cast(atof(row[12])); - entry.pos_y = static_cast(atof(row[13])); - entry.pos_z = static_cast(atof(row[14])); - entry.heading = atoi(row[15]); - entry.time_played = atoi(row[16]); - entry.target_id = atoi(row[17]); - entry.target_name = row[18] ? row[18] : ""; - entry.optional_info_mask = atoi(row[19]); - entry._can_duplicate = atoi(row[20]); - entry._crash_bug = atoi(row[21]); - entry._target_info = atoi(row[22]); - entry._character_flags = atoi(row[23]); - entry._unknown_value = atoi(row[24]); - entry.bug_report = row[25] ? row[25] : ""; - entry.system_info = row[26] ? row[26] : ""; - entry.report_datetime = strtoll(row[27] ? row[27] : "-1", nullptr, 10); - entry.bug_status = atoi(row[28]); - entry.last_review = strtoll(row[29] ? row[29] : "-1", nullptr, 10); - entry.last_reviewer = row[30] ? row[30] : ""; - entry.reviewer_notes = row[31] ? row[31] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.client_version_id = static_cast(strtoul(row[2], nullptr, 10)); + e.client_version_name = row[3] ? row[3] : ""; + e.account_id = static_cast(strtoul(row[4], nullptr, 10)); + e.character_id = static_cast(strtoul(row[5], nullptr, 10)); + e.character_name = row[6] ? row[6] : ""; + e.reporter_spoof = static_cast(atoi(row[7])); + e.category_id = static_cast(strtoul(row[8], nullptr, 10)); + e.category_name = row[9] ? row[9] : ""; + e.reporter_name = row[10] ? row[10] : ""; + e.ui_path = row[11] ? row[11] : ""; + e.pos_x = strtof(row[12], nullptr); + e.pos_y = strtof(row[13], nullptr); + e.pos_z = strtof(row[14], nullptr); + e.heading = static_cast(strtoul(row[15], nullptr, 10)); + e.time_played = static_cast(strtoul(row[16], nullptr, 10)); + e.target_id = static_cast(strtoul(row[17], nullptr, 10)); + e.target_name = row[18] ? row[18] : ""; + e.optional_info_mask = static_cast(strtoul(row[19], nullptr, 10)); + e._can_duplicate = static_cast(atoi(row[20])); + e._crash_bug = static_cast(atoi(row[21])); + e._target_info = static_cast(atoi(row[22])); + e._character_flags = static_cast(atoi(row[23])); + e._unknown_value = static_cast(atoi(row[24])); + e.bug_report = row[25] ? row[25] : ""; + e.system_info = row[26] ? row[26] : ""; + e.report_datetime = strtoll(row[27] ? row[27] : "-1", nullptr, 10); + e.bug_status = static_cast(strtoul(row[28], nullptr, 10)); + e.last_review = strtoll(row[29] ? row[29] : "-1", nullptr, 10); + e.last_reviewer = row[30] ? row[30] : ""; + e.reviewer_notes = row[31] ? row[31] : ""; - return entry; + return e; } return NewEntity(); @@ -296,52 +296,52 @@ public: static int UpdateOne( Database& db, - BugReports bug_reports_entry + const BugReports &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(bug_reports_entry.zone) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(bug_reports_entry.client_version_id)); - update_values.push_back(columns[3] + " = '" + EscapeString(bug_reports_entry.client_version_name) + "'"); - update_values.push_back(columns[4] + " = " + std::to_string(bug_reports_entry.account_id)); - update_values.push_back(columns[5] + " = " + std::to_string(bug_reports_entry.character_id)); - update_values.push_back(columns[6] + " = '" + EscapeString(bug_reports_entry.character_name) + "'"); - update_values.push_back(columns[7] + " = " + std::to_string(bug_reports_entry.reporter_spoof)); - update_values.push_back(columns[8] + " = " + std::to_string(bug_reports_entry.category_id)); - update_values.push_back(columns[9] + " = '" + EscapeString(bug_reports_entry.category_name) + "'"); - update_values.push_back(columns[10] + " = '" + EscapeString(bug_reports_entry.reporter_name) + "'"); - update_values.push_back(columns[11] + " = '" + EscapeString(bug_reports_entry.ui_path) + "'"); - update_values.push_back(columns[12] + " = " + std::to_string(bug_reports_entry.pos_x)); - update_values.push_back(columns[13] + " = " + std::to_string(bug_reports_entry.pos_y)); - update_values.push_back(columns[14] + " = " + std::to_string(bug_reports_entry.pos_z)); - update_values.push_back(columns[15] + " = " + std::to_string(bug_reports_entry.heading)); - update_values.push_back(columns[16] + " = " + std::to_string(bug_reports_entry.time_played)); - update_values.push_back(columns[17] + " = " + std::to_string(bug_reports_entry.target_id)); - update_values.push_back(columns[18] + " = '" + EscapeString(bug_reports_entry.target_name) + "'"); - update_values.push_back(columns[19] + " = " + std::to_string(bug_reports_entry.optional_info_mask)); - update_values.push_back(columns[20] + " = " + std::to_string(bug_reports_entry._can_duplicate)); - update_values.push_back(columns[21] + " = " + std::to_string(bug_reports_entry._crash_bug)); - update_values.push_back(columns[22] + " = " + std::to_string(bug_reports_entry._target_info)); - update_values.push_back(columns[23] + " = " + std::to_string(bug_reports_entry._character_flags)); - update_values.push_back(columns[24] + " = " + std::to_string(bug_reports_entry._unknown_value)); - update_values.push_back(columns[25] + " = '" + EscapeString(bug_reports_entry.bug_report) + "'"); - update_values.push_back(columns[26] + " = '" + EscapeString(bug_reports_entry.system_info) + "'"); - update_values.push_back(columns[27] + " = FROM_UNIXTIME(" + (bug_reports_entry.report_datetime > 0 ? std::to_string(bug_reports_entry.report_datetime) : "null") + ")"); - update_values.push_back(columns[28] + " = " + std::to_string(bug_reports_entry.bug_status)); - update_values.push_back(columns[29] + " = FROM_UNIXTIME(" + (bug_reports_entry.last_review > 0 ? std::to_string(bug_reports_entry.last_review) : "null") + ")"); - update_values.push_back(columns[30] + " = '" + EscapeString(bug_reports_entry.last_reviewer) + "'"); - update_values.push_back(columns[31] + " = '" + EscapeString(bug_reports_entry.reviewer_notes) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.client_version_id)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.client_version_name) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.account_id)); + v.push_back(columns[5] + " = " + std::to_string(e.character_id)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.character_name) + "'"); + v.push_back(columns[7] + " = " + std::to_string(e.reporter_spoof)); + v.push_back(columns[8] + " = " + std::to_string(e.category_id)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.category_name) + "'"); + v.push_back(columns[10] + " = '" + Strings::Escape(e.reporter_name) + "'"); + v.push_back(columns[11] + " = '" + Strings::Escape(e.ui_path) + "'"); + v.push_back(columns[12] + " = " + std::to_string(e.pos_x)); + v.push_back(columns[13] + " = " + std::to_string(e.pos_y)); + v.push_back(columns[14] + " = " + std::to_string(e.pos_z)); + v.push_back(columns[15] + " = " + std::to_string(e.heading)); + v.push_back(columns[16] + " = " + std::to_string(e.time_played)); + v.push_back(columns[17] + " = " + std::to_string(e.target_id)); + v.push_back(columns[18] + " = '" + Strings::Escape(e.target_name) + "'"); + v.push_back(columns[19] + " = " + std::to_string(e.optional_info_mask)); + v.push_back(columns[20] + " = " + std::to_string(e._can_duplicate)); + v.push_back(columns[21] + " = " + std::to_string(e._crash_bug)); + v.push_back(columns[22] + " = " + std::to_string(e._target_info)); + v.push_back(columns[23] + " = " + std::to_string(e._character_flags)); + v.push_back(columns[24] + " = " + std::to_string(e._unknown_value)); + v.push_back(columns[25] + " = '" + Strings::Escape(e.bug_report) + "'"); + v.push_back(columns[26] + " = '" + Strings::Escape(e.system_info) + "'"); + v.push_back(columns[27] + " = FROM_UNIXTIME(" + (e.report_datetime > 0 ? std::to_string(e.report_datetime) : "null") + ")"); + v.push_back(columns[28] + " = " + std::to_string(e.bug_status)); + v.push_back(columns[29] + " = FROM_UNIXTIME(" + (e.last_review > 0 ? std::to_string(e.last_review) : "null") + ")"); + v.push_back(columns[30] + " = '" + Strings::Escape(e.last_reviewer) + "'"); + v.push_back(columns[31] + " = '" + Strings::Escape(e.reviewer_notes) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - bug_reports_entry.id + e.id ) ); @@ -350,115 +350,115 @@ public: static BugReports InsertOne( Database& db, - BugReports bug_reports_entry + BugReports e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(bug_reports_entry.id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.zone) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.client_version_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.client_version_name) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.account_id)); - insert_values.push_back(std::to_string(bug_reports_entry.character_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.character_name) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.reporter_spoof)); - insert_values.push_back(std::to_string(bug_reports_entry.category_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.category_name) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.reporter_name) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.ui_path) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.pos_x)); - insert_values.push_back(std::to_string(bug_reports_entry.pos_y)); - insert_values.push_back(std::to_string(bug_reports_entry.pos_z)); - insert_values.push_back(std::to_string(bug_reports_entry.heading)); - insert_values.push_back(std::to_string(bug_reports_entry.time_played)); - insert_values.push_back(std::to_string(bug_reports_entry.target_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.target_name) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.optional_info_mask)); - insert_values.push_back(std::to_string(bug_reports_entry._can_duplicate)); - insert_values.push_back(std::to_string(bug_reports_entry._crash_bug)); - insert_values.push_back(std::to_string(bug_reports_entry._target_info)); - insert_values.push_back(std::to_string(bug_reports_entry._character_flags)); - insert_values.push_back(std::to_string(bug_reports_entry._unknown_value)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.bug_report) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.system_info) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (bug_reports_entry.report_datetime > 0 ? std::to_string(bug_reports_entry.report_datetime) : "null") + ")"); - insert_values.push_back(std::to_string(bug_reports_entry.bug_status)); - insert_values.push_back("FROM_UNIXTIME(" + (bug_reports_entry.last_review > 0 ? std::to_string(bug_reports_entry.last_review) : "null") + ")"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.last_reviewer) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.reviewer_notes) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.client_version_id)); + v.push_back("'" + Strings::Escape(e.client_version_name) + "'"); + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back("'" + Strings::Escape(e.character_name) + "'"); + v.push_back(std::to_string(e.reporter_spoof)); + v.push_back(std::to_string(e.category_id)); + v.push_back("'" + Strings::Escape(e.category_name) + "'"); + v.push_back("'" + Strings::Escape(e.reporter_name) + "'"); + v.push_back("'" + Strings::Escape(e.ui_path) + "'"); + v.push_back(std::to_string(e.pos_x)); + v.push_back(std::to_string(e.pos_y)); + v.push_back(std::to_string(e.pos_z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.time_played)); + v.push_back(std::to_string(e.target_id)); + v.push_back("'" + Strings::Escape(e.target_name) + "'"); + v.push_back(std::to_string(e.optional_info_mask)); + v.push_back(std::to_string(e._can_duplicate)); + v.push_back(std::to_string(e._crash_bug)); + v.push_back(std::to_string(e._target_info)); + v.push_back(std::to_string(e._character_flags)); + v.push_back(std::to_string(e._unknown_value)); + v.push_back("'" + Strings::Escape(e.bug_report) + "'"); + v.push_back("'" + Strings::Escape(e.system_info) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.report_datetime > 0 ? std::to_string(e.report_datetime) : "null") + ")"); + v.push_back(std::to_string(e.bug_status)); + v.push_back("FROM_UNIXTIME(" + (e.last_review > 0 ? std::to_string(e.last_review) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.last_reviewer) + "'"); + v.push_back("'" + Strings::Escape(e.reviewer_notes) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - bug_reports_entry.id = results.LastInsertedID(); - return bug_reports_entry; + e.id = results.LastInsertedID(); + return e; } - bug_reports_entry = NewEntity(); + e = NewEntity(); - return bug_reports_entry; + return e; } static int InsertMany( Database& db, - std::vector bug_reports_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &bug_reports_entry: bug_reports_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(bug_reports_entry.id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.zone) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.client_version_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.client_version_name) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.account_id)); - insert_values.push_back(std::to_string(bug_reports_entry.character_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.character_name) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.reporter_spoof)); - insert_values.push_back(std::to_string(bug_reports_entry.category_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.category_name) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.reporter_name) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.ui_path) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.pos_x)); - insert_values.push_back(std::to_string(bug_reports_entry.pos_y)); - insert_values.push_back(std::to_string(bug_reports_entry.pos_z)); - insert_values.push_back(std::to_string(bug_reports_entry.heading)); - insert_values.push_back(std::to_string(bug_reports_entry.time_played)); - insert_values.push_back(std::to_string(bug_reports_entry.target_id)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.target_name) + "'"); - insert_values.push_back(std::to_string(bug_reports_entry.optional_info_mask)); - insert_values.push_back(std::to_string(bug_reports_entry._can_duplicate)); - insert_values.push_back(std::to_string(bug_reports_entry._crash_bug)); - insert_values.push_back(std::to_string(bug_reports_entry._target_info)); - insert_values.push_back(std::to_string(bug_reports_entry._character_flags)); - insert_values.push_back(std::to_string(bug_reports_entry._unknown_value)); - insert_values.push_back("'" + EscapeString(bug_reports_entry.bug_report) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.system_info) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (bug_reports_entry.report_datetime > 0 ? std::to_string(bug_reports_entry.report_datetime) : "null") + ")"); - insert_values.push_back(std::to_string(bug_reports_entry.bug_status)); - insert_values.push_back("FROM_UNIXTIME(" + (bug_reports_entry.last_review > 0 ? std::to_string(bug_reports_entry.last_review) : "null") + ")"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.last_reviewer) + "'"); - insert_values.push_back("'" + EscapeString(bug_reports_entry.reviewer_notes) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.client_version_id)); + v.push_back("'" + Strings::Escape(e.client_version_name) + "'"); + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back("'" + Strings::Escape(e.character_name) + "'"); + v.push_back(std::to_string(e.reporter_spoof)); + v.push_back(std::to_string(e.category_id)); + v.push_back("'" + Strings::Escape(e.category_name) + "'"); + v.push_back("'" + Strings::Escape(e.reporter_name) + "'"); + v.push_back("'" + Strings::Escape(e.ui_path) + "'"); + v.push_back(std::to_string(e.pos_x)); + v.push_back(std::to_string(e.pos_y)); + v.push_back(std::to_string(e.pos_z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.time_played)); + v.push_back(std::to_string(e.target_id)); + v.push_back("'" + Strings::Escape(e.target_name) + "'"); + v.push_back(std::to_string(e.optional_info_mask)); + v.push_back(std::to_string(e._can_duplicate)); + v.push_back(std::to_string(e._crash_bug)); + v.push_back(std::to_string(e._target_info)); + v.push_back(std::to_string(e._character_flags)); + v.push_back(std::to_string(e._unknown_value)); + v.push_back("'" + Strings::Escape(e.bug_report) + "'"); + v.push_back("'" + Strings::Escape(e.system_info) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.report_datetime > 0 ? std::to_string(e.report_datetime) : "null") + ")"); + v.push_back(std::to_string(e.bug_status)); + v.push_back("FROM_UNIXTIME(" + (e.last_review > 0 ? std::to_string(e.last_review) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.last_reviewer) + "'"); + v.push_back("'" + Strings::Escape(e.reviewer_notes) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -479,48 +479,48 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - BugReports entry{}; + BugReports e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.client_version_id = atoi(row[2]); - entry.client_version_name = row[3] ? row[3] : ""; - entry.account_id = atoi(row[4]); - entry.character_id = atoi(row[5]); - entry.character_name = row[6] ? row[6] : ""; - entry.reporter_spoof = atoi(row[7]); - entry.category_id = atoi(row[8]); - entry.category_name = row[9] ? row[9] : ""; - entry.reporter_name = row[10] ? row[10] : ""; - entry.ui_path = row[11] ? row[11] : ""; - entry.pos_x = static_cast(atof(row[12])); - entry.pos_y = static_cast(atof(row[13])); - entry.pos_z = static_cast(atof(row[14])); - entry.heading = atoi(row[15]); - entry.time_played = atoi(row[16]); - entry.target_id = atoi(row[17]); - entry.target_name = row[18] ? row[18] : ""; - entry.optional_info_mask = atoi(row[19]); - entry._can_duplicate = atoi(row[20]); - entry._crash_bug = atoi(row[21]); - entry._target_info = atoi(row[22]); - entry._character_flags = atoi(row[23]); - entry._unknown_value = atoi(row[24]); - entry.bug_report = row[25] ? row[25] : ""; - entry.system_info = row[26] ? row[26] : ""; - entry.report_datetime = strtoll(row[27] ? row[27] : "-1", nullptr, 10); - entry.bug_status = atoi(row[28]); - entry.last_review = strtoll(row[29] ? row[29] : "-1", nullptr, 10); - entry.last_reviewer = row[30] ? row[30] : ""; - entry.reviewer_notes = row[31] ? row[31] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.client_version_id = static_cast(strtoul(row[2], nullptr, 10)); + e.client_version_name = row[3] ? row[3] : ""; + e.account_id = static_cast(strtoul(row[4], nullptr, 10)); + e.character_id = static_cast(strtoul(row[5], nullptr, 10)); + e.character_name = row[6] ? row[6] : ""; + e.reporter_spoof = static_cast(atoi(row[7])); + e.category_id = static_cast(strtoul(row[8], nullptr, 10)); + e.category_name = row[9] ? row[9] : ""; + e.reporter_name = row[10] ? row[10] : ""; + e.ui_path = row[11] ? row[11] : ""; + e.pos_x = strtof(row[12], nullptr); + e.pos_y = strtof(row[13], nullptr); + e.pos_z = strtof(row[14], nullptr); + e.heading = static_cast(strtoul(row[15], nullptr, 10)); + e.time_played = static_cast(strtoul(row[16], nullptr, 10)); + e.target_id = static_cast(strtoul(row[17], nullptr, 10)); + e.target_name = row[18] ? row[18] : ""; + e.optional_info_mask = static_cast(strtoul(row[19], nullptr, 10)); + e._can_duplicate = static_cast(atoi(row[20])); + e._crash_bug = static_cast(atoi(row[21])); + e._target_info = static_cast(atoi(row[22])); + e._character_flags = static_cast(atoi(row[23])); + e._unknown_value = static_cast(atoi(row[24])); + e.bug_report = row[25] ? row[25] : ""; + e.system_info = row[26] ? row[26] : ""; + e.report_datetime = strtoll(row[27] ? row[27] : "-1", nullptr, 10); + e.bug_status = static_cast(strtoul(row[28], nullptr, 10)); + e.last_review = strtoll(row[29] ? row[29] : "-1", nullptr, 10); + e.last_reviewer = row[30] ? row[30] : ""; + e.reviewer_notes = row[31] ? row[31] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -535,48 +535,48 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - BugReports entry{}; + BugReports e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.client_version_id = atoi(row[2]); - entry.client_version_name = row[3] ? row[3] : ""; - entry.account_id = atoi(row[4]); - entry.character_id = atoi(row[5]); - entry.character_name = row[6] ? row[6] : ""; - entry.reporter_spoof = atoi(row[7]); - entry.category_id = atoi(row[8]); - entry.category_name = row[9] ? row[9] : ""; - entry.reporter_name = row[10] ? row[10] : ""; - entry.ui_path = row[11] ? row[11] : ""; - entry.pos_x = static_cast(atof(row[12])); - entry.pos_y = static_cast(atof(row[13])); - entry.pos_z = static_cast(atof(row[14])); - entry.heading = atoi(row[15]); - entry.time_played = atoi(row[16]); - entry.target_id = atoi(row[17]); - entry.target_name = row[18] ? row[18] : ""; - entry.optional_info_mask = atoi(row[19]); - entry._can_duplicate = atoi(row[20]); - entry._crash_bug = atoi(row[21]); - entry._target_info = atoi(row[22]); - entry._character_flags = atoi(row[23]); - entry._unknown_value = atoi(row[24]); - entry.bug_report = row[25] ? row[25] : ""; - entry.system_info = row[26] ? row[26] : ""; - entry.report_datetime = strtoll(row[27] ? row[27] : "-1", nullptr, 10); - entry.bug_status = atoi(row[28]); - entry.last_review = strtoll(row[29] ? row[29] : "-1", nullptr, 10); - entry.last_reviewer = row[30] ? row[30] : ""; - entry.reviewer_notes = row[31] ? row[31] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.client_version_id = static_cast(strtoul(row[2], nullptr, 10)); + e.client_version_name = row[3] ? row[3] : ""; + e.account_id = static_cast(strtoul(row[4], nullptr, 10)); + e.character_id = static_cast(strtoul(row[5], nullptr, 10)); + e.character_name = row[6] ? row[6] : ""; + e.reporter_spoof = static_cast(atoi(row[7])); + e.category_id = static_cast(strtoul(row[8], nullptr, 10)); + e.category_name = row[9] ? row[9] : ""; + e.reporter_name = row[10] ? row[10] : ""; + e.ui_path = row[11] ? row[11] : ""; + e.pos_x = strtof(row[12], nullptr); + e.pos_y = strtof(row[13], nullptr); + e.pos_z = strtof(row[14], nullptr); + e.heading = static_cast(strtoul(row[15], nullptr, 10)); + e.time_played = static_cast(strtoul(row[16], nullptr, 10)); + e.target_id = static_cast(strtoul(row[17], nullptr, 10)); + e.target_name = row[18] ? row[18] : ""; + e.optional_info_mask = static_cast(strtoul(row[19], nullptr, 10)); + e._can_duplicate = static_cast(atoi(row[20])); + e._crash_bug = static_cast(atoi(row[21])); + e._target_info = static_cast(atoi(row[22])); + e._character_flags = static_cast(atoi(row[23])); + e._unknown_value = static_cast(atoi(row[24])); + e.bug_report = row[25] ? row[25] : ""; + e.system_info = row[26] ? row[26] : ""; + e.report_datetime = strtoll(row[27] ? row[27] : "-1", nullptr, 10); + e.bug_status = static_cast(strtoul(row[28], nullptr, 10)); + e.last_review = strtoll(row[29] ? row[29] : "-1", nullptr, 10); + e.last_reviewer = row[30] ? row[30] : ""; + e.reviewer_notes = row[31] ? row[31] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -601,6 +601,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_BUG_REPORTS_REPOSITORY_H diff --git a/common/repositories/base/base_bugs_repository.h b/common/repositories/base/base_bugs_repository.h index 6fff42ed9..381fc4d01 100644 --- a/common/repositories/base/base_bugs_repository.h +++ b/common/repositories/base/base_bugs_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_BUGS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseBugsRepository { public: struct Bugs { - int id; + uint32_t id; std::string zone; std::string name; std::string ui; @@ -27,11 +27,11 @@ public: float y; float z; std::string type; - int flag; + uint8_t flag; std::string target; std::string bug; std::string date; - int status; + uint8_t status; }; static std::string PrimaryKey() @@ -79,12 +79,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -112,26 +112,26 @@ public: static Bugs NewEntity() { - Bugs entry{}; + Bugs e{}; - entry.id = 0; - entry.zone = ""; - entry.name = ""; - entry.ui = ""; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.type = ""; - entry.flag = 0; - entry.target = ""; - entry.bug = ""; - entry.date = 0; - entry.status = 0; + e.id = 0; + e.zone = ""; + e.name = ""; + e.ui = ""; + e.x = 0; + e.y = 0; + e.z = 0; + e.type = ""; + e.flag = 0; + e.target = ""; + e.bug = ""; + e.date = 0; + e.status = 0; - return entry; + return e; } - static Bugs GetBugsEntry( + static Bugs GetBugs( const std::vector &bugss, int bugs_id ) @@ -160,23 +160,23 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Bugs entry{}; + Bugs e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.name = row[2] ? row[2] : ""; - entry.ui = row[3] ? row[3] : ""; - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.type = row[7] ? row[7] : ""; - entry.flag = atoi(row[8]); - entry.target = row[9] ? row[9] : ""; - entry.bug = row[10] ? row[10] : ""; - entry.date = row[11] ? row[11] : ""; - entry.status = atoi(row[12]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.name = row[2] ? row[2] : ""; + e.ui = row[3] ? row[3] : ""; + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.type = row[7] ? row[7] : ""; + e.flag = static_cast(strtoul(row[8], nullptr, 10)); + e.target = row[9] ? row[9] : ""; + e.bug = row[10] ? row[10] : ""; + e.date = row[11] ? row[11] : ""; + e.status = static_cast(strtoul(row[12], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -201,33 +201,33 @@ public: static int UpdateOne( Database& db, - Bugs bugs_entry + const Bugs &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(bugs_entry.zone) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(bugs_entry.name) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(bugs_entry.ui) + "'"); - update_values.push_back(columns[4] + " = " + std::to_string(bugs_entry.x)); - update_values.push_back(columns[5] + " = " + std::to_string(bugs_entry.y)); - update_values.push_back(columns[6] + " = " + std::to_string(bugs_entry.z)); - update_values.push_back(columns[7] + " = '" + EscapeString(bugs_entry.type) + "'"); - update_values.push_back(columns[8] + " = " + std::to_string(bugs_entry.flag)); - update_values.push_back(columns[9] + " = '" + EscapeString(bugs_entry.target) + "'"); - update_values.push_back(columns[10] + " = '" + EscapeString(bugs_entry.bug) + "'"); - update_values.push_back(columns[11] + " = '" + EscapeString(bugs_entry.date) + "'"); - update_values.push_back(columns[12] + " = " + std::to_string(bugs_entry.status)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.ui) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.x)); + v.push_back(columns[5] + " = " + std::to_string(e.y)); + v.push_back(columns[6] + " = " + std::to_string(e.z)); + v.push_back(columns[7] + " = '" + Strings::Escape(e.type) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.flag)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.target) + "'"); + v.push_back(columns[10] + " = '" + Strings::Escape(e.bug) + "'"); + v.push_back(columns[11] + " = '" + Strings::Escape(e.date) + "'"); + v.push_back(columns[12] + " = " + std::to_string(e.status)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - bugs_entry.id + e.id ) ); @@ -236,77 +236,77 @@ public: static Bugs InsertOne( Database& db, - Bugs bugs_entry + Bugs e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(bugs_entry.id)); - insert_values.push_back("'" + EscapeString(bugs_entry.zone) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.ui) + "'"); - insert_values.push_back(std::to_string(bugs_entry.x)); - insert_values.push_back(std::to_string(bugs_entry.y)); - insert_values.push_back(std::to_string(bugs_entry.z)); - insert_values.push_back("'" + EscapeString(bugs_entry.type) + "'"); - insert_values.push_back(std::to_string(bugs_entry.flag)); - insert_values.push_back("'" + EscapeString(bugs_entry.target) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.bug) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.date) + "'"); - insert_values.push_back(std::to_string(bugs_entry.status)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.ui) + "'"); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back("'" + Strings::Escape(e.type) + "'"); + v.push_back(std::to_string(e.flag)); + v.push_back("'" + Strings::Escape(e.target) + "'"); + v.push_back("'" + Strings::Escape(e.bug) + "'"); + v.push_back("'" + Strings::Escape(e.date) + "'"); + v.push_back(std::to_string(e.status)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - bugs_entry.id = results.LastInsertedID(); - return bugs_entry; + e.id = results.LastInsertedID(); + return e; } - bugs_entry = NewEntity(); + e = NewEntity(); - return bugs_entry; + return e; } static int InsertMany( Database& db, - std::vector bugs_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &bugs_entry: bugs_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(bugs_entry.id)); - insert_values.push_back("'" + EscapeString(bugs_entry.zone) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.ui) + "'"); - insert_values.push_back(std::to_string(bugs_entry.x)); - insert_values.push_back(std::to_string(bugs_entry.y)); - insert_values.push_back(std::to_string(bugs_entry.z)); - insert_values.push_back("'" + EscapeString(bugs_entry.type) + "'"); - insert_values.push_back(std::to_string(bugs_entry.flag)); - insert_values.push_back("'" + EscapeString(bugs_entry.target) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.bug) + "'"); - insert_values.push_back("'" + EscapeString(bugs_entry.date) + "'"); - insert_values.push_back(std::to_string(bugs_entry.status)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.ui) + "'"); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back("'" + Strings::Escape(e.type) + "'"); + v.push_back(std::to_string(e.flag)); + v.push_back("'" + Strings::Escape(e.target) + "'"); + v.push_back("'" + Strings::Escape(e.bug) + "'"); + v.push_back("'" + Strings::Escape(e.date) + "'"); + v.push_back(std::to_string(e.status)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -327,29 +327,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Bugs entry{}; + Bugs e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.name = row[2] ? row[2] : ""; - entry.ui = row[3] ? row[3] : ""; - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.type = row[7] ? row[7] : ""; - entry.flag = atoi(row[8]); - entry.target = row[9] ? row[9] : ""; - entry.bug = row[10] ? row[10] : ""; - entry.date = row[11] ? row[11] : ""; - entry.status = atoi(row[12]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.name = row[2] ? row[2] : ""; + e.ui = row[3] ? row[3] : ""; + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.type = row[7] ? row[7] : ""; + e.flag = static_cast(strtoul(row[8], nullptr, 10)); + e.target = row[9] ? row[9] : ""; + e.bug = row[10] ? row[10] : ""; + e.date = row[11] ? row[11] : ""; + e.status = static_cast(strtoul(row[12], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -364,29 +364,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Bugs entry{}; + Bugs e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.name = row[2] ? row[2] : ""; - entry.ui = row[3] ? row[3] : ""; - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.type = row[7] ? row[7] : ""; - entry.flag = atoi(row[8]); - entry.target = row[9] ? row[9] : ""; - entry.bug = row[10] ? row[10] : ""; - entry.date = row[11] ? row[11] : ""; - entry.status = atoi(row[12]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.name = row[2] ? row[2] : ""; + e.ui = row[3] ? row[3] : ""; + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.type = row[7] ? row[7] : ""; + e.flag = static_cast(strtoul(row[8], nullptr, 10)); + e.target = row[9] ? row[9] : ""; + e.bug = row[10] ? row[10] : ""; + e.date = row[11] ? row[11] : ""; + e.status = static_cast(strtoul(row[12], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -411,6 +411,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_BUGS_REPOSITORY_H diff --git a/common/repositories/base/base_buyer_repository.h b/common/repositories/base/base_buyer_repository.h index 1299f203a..1e365481f 100644 --- a/common/repositories/base/base_buyer_repository.h +++ b/common/repositories/base/base_buyer_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_BUYER_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseBuyerRepository { public: struct Buyer { - int charid; - int buyslot; - int itemid; + int32_t charid; + int32_t buyslot; + int32_t itemid; std::string itemname; - int quantity; - int price; + int32_t quantity; + int32_t price; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static Buyer NewEntity() { - Buyer entry{}; + Buyer e{}; - entry.charid = 0; - entry.buyslot = 0; - entry.itemid = 0; - entry.itemname = ""; - entry.quantity = 0; - entry.price = 0; + e.charid = 0; + e.buyslot = 0; + e.itemid = 0; + e.itemname = ""; + e.quantity = 0; + e.price = 0; - return entry; + return e; } - static Buyer GetBuyerEntry( + static Buyer GetBuyer( const std::vector &buyers, int buyer_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Buyer entry{}; + Buyer e{}; - entry.charid = atoi(row[0]); - entry.buyslot = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.itemname = row[3] ? row[3] : ""; - entry.quantity = atoi(row[4]); - entry.price = atoi(row[5]); + e.charid = static_cast(atoi(row[0])); + e.buyslot = static_cast(atoi(row[1])); + e.itemid = static_cast(atoi(row[2])); + e.itemname = row[3] ? row[3] : ""; + e.quantity = static_cast(atoi(row[4])); + e.price = static_cast(atoi(row[5])); - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - Buyer buyer_entry + const Buyer &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(buyer_entry.charid)); - update_values.push_back(columns[1] + " = " + std::to_string(buyer_entry.buyslot)); - update_values.push_back(columns[2] + " = " + std::to_string(buyer_entry.itemid)); - update_values.push_back(columns[3] + " = '" + EscapeString(buyer_entry.itemname) + "'"); - update_values.push_back(columns[4] + " = " + std::to_string(buyer_entry.quantity)); - update_values.push_back(columns[5] + " = " + std::to_string(buyer_entry.price)); + v.push_back(columns[0] + " = " + std::to_string(e.charid)); + v.push_back(columns[1] + " = " + std::to_string(e.buyslot)); + v.push_back(columns[2] + " = " + std::to_string(e.itemid)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.itemname) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.quantity)); + v.push_back(columns[5] + " = " + std::to_string(e.price)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - buyer_entry.charid + e.charid ) ); @@ -195,63 +195,63 @@ public: static Buyer InsertOne( Database& db, - Buyer buyer_entry + Buyer e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(buyer_entry.charid)); - insert_values.push_back(std::to_string(buyer_entry.buyslot)); - insert_values.push_back(std::to_string(buyer_entry.itemid)); - insert_values.push_back("'" + EscapeString(buyer_entry.itemname) + "'"); - insert_values.push_back(std::to_string(buyer_entry.quantity)); - insert_values.push_back(std::to_string(buyer_entry.price)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.buyslot)); + v.push_back(std::to_string(e.itemid)); + v.push_back("'" + Strings::Escape(e.itemname) + "'"); + v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.price)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - buyer_entry.charid = results.LastInsertedID(); - return buyer_entry; + e.charid = results.LastInsertedID(); + return e; } - buyer_entry = NewEntity(); + e = NewEntity(); - return buyer_entry; + return e; } static int InsertMany( Database& db, - std::vector buyer_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &buyer_entry: buyer_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(buyer_entry.charid)); - insert_values.push_back(std::to_string(buyer_entry.buyslot)); - insert_values.push_back(std::to_string(buyer_entry.itemid)); - insert_values.push_back("'" + EscapeString(buyer_entry.itemname) + "'"); - insert_values.push_back(std::to_string(buyer_entry.quantity)); - insert_values.push_back(std::to_string(buyer_entry.price)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.buyslot)); + v.push_back(std::to_string(e.itemid)); + v.push_back("'" + Strings::Escape(e.itemname) + "'"); + v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.price)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Buyer entry{}; + Buyer e{}; - entry.charid = atoi(row[0]); - entry.buyslot = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.itemname = row[3] ? row[3] : ""; - entry.quantity = atoi(row[4]); - entry.price = atoi(row[5]); + e.charid = static_cast(atoi(row[0])); + e.buyslot = static_cast(atoi(row[1])); + e.itemid = static_cast(atoi(row[2])); + e.itemname = row[3] ? row[3] : ""; + e.quantity = static_cast(atoi(row[4])); + e.price = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Buyer entry{}; + Buyer e{}; - entry.charid = atoi(row[0]); - entry.buyslot = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.itemname = row[3] ? row[3] : ""; - entry.quantity = atoi(row[4]); - entry.price = atoi(row[5]); + e.charid = static_cast(atoi(row[0])); + e.buyslot = static_cast(atoi(row[1])); + e.itemid = static_cast(atoi(row[2])); + e.itemname = row[3] ? row[3] : ""; + e.quantity = static_cast(atoi(row[4])); + e.price = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_BUYER_REPOSITORY_H diff --git a/common/repositories/base/base_char_create_combinations_repository.h b/common/repositories/base/base_char_create_combinations_repository.h index 1548c96e3..98eae33a9 100644 --- a/common/repositories/base/base_char_create_combinations_repository.h +++ b/common/repositories/base/base_char_create_combinations_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_CHAR_CREATE_COMBINATIONS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharCreateCombinationsRepository { public: struct CharCreateCombinations { - int allocation_id; - int race; - int class_; - int deity; - int start_zone; - int expansions_req; + uint32_t allocation_id; + uint32_t race; + uint32_t class_; + uint32_t deity; + uint32_t start_zone; + uint32_t expansions_req; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static CharCreateCombinations NewEntity() { - CharCreateCombinations entry{}; + CharCreateCombinations e{}; - entry.allocation_id = 0; - entry.race = 0; - entry.class_ = 0; - entry.deity = 0; - entry.start_zone = 0; - entry.expansions_req = 0; + e.allocation_id = 0; + e.race = 0; + e.class_ = 0; + e.deity = 0; + e.start_zone = 0; + e.expansions_req = 0; - return entry; + return e; } - static CharCreateCombinations GetCharCreateCombinationsEntry( + static CharCreateCombinations GetCharCreateCombinations( const std::vector &char_create_combinationss, int char_create_combinations_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharCreateCombinations entry{}; + CharCreateCombinations e{}; - entry.allocation_id = atoi(row[0]); - entry.race = atoi(row[1]); - entry.class_ = atoi(row[2]); - entry.deity = atoi(row[3]); - entry.start_zone = atoi(row[4]); - entry.expansions_req = atoi(row[5]); + e.allocation_id = static_cast(strtoul(row[0], nullptr, 10)); + e.race = static_cast(strtoul(row[1], nullptr, 10)); + e.class_ = static_cast(strtoul(row[2], nullptr, 10)); + e.deity = static_cast(strtoul(row[3], nullptr, 10)); + e.start_zone = static_cast(strtoul(row[4], nullptr, 10)); + e.expansions_req = static_cast(strtoul(row[5], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - CharCreateCombinations char_create_combinations_entry + const CharCreateCombinations &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(char_create_combinations_entry.allocation_id)); - update_values.push_back(columns[1] + " = " + std::to_string(char_create_combinations_entry.race)); - update_values.push_back(columns[2] + " = " + std::to_string(char_create_combinations_entry.class_)); - update_values.push_back(columns[3] + " = " + std::to_string(char_create_combinations_entry.deity)); - update_values.push_back(columns[4] + " = " + std::to_string(char_create_combinations_entry.start_zone)); - update_values.push_back(columns[5] + " = " + std::to_string(char_create_combinations_entry.expansions_req)); + v.push_back(columns[0] + " = " + std::to_string(e.allocation_id)); + v.push_back(columns[1] + " = " + std::to_string(e.race)); + v.push_back(columns[2] + " = " + std::to_string(e.class_)); + v.push_back(columns[3] + " = " + std::to_string(e.deity)); + v.push_back(columns[4] + " = " + std::to_string(e.start_zone)); + v.push_back(columns[5] + " = " + std::to_string(e.expansions_req)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - char_create_combinations_entry.race + e.race ) ); @@ -195,63 +195,63 @@ public: static CharCreateCombinations InsertOne( Database& db, - CharCreateCombinations char_create_combinations_entry + CharCreateCombinations e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(char_create_combinations_entry.allocation_id)); - insert_values.push_back(std::to_string(char_create_combinations_entry.race)); - insert_values.push_back(std::to_string(char_create_combinations_entry.class_)); - insert_values.push_back(std::to_string(char_create_combinations_entry.deity)); - insert_values.push_back(std::to_string(char_create_combinations_entry.start_zone)); - insert_values.push_back(std::to_string(char_create_combinations_entry.expansions_req)); + v.push_back(std::to_string(e.allocation_id)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.start_zone)); + v.push_back(std::to_string(e.expansions_req)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - char_create_combinations_entry.race = results.LastInsertedID(); - return char_create_combinations_entry; + e.race = results.LastInsertedID(); + return e; } - char_create_combinations_entry = NewEntity(); + e = NewEntity(); - return char_create_combinations_entry; + return e; } static int InsertMany( Database& db, - std::vector char_create_combinations_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &char_create_combinations_entry: char_create_combinations_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(char_create_combinations_entry.allocation_id)); - insert_values.push_back(std::to_string(char_create_combinations_entry.race)); - insert_values.push_back(std::to_string(char_create_combinations_entry.class_)); - insert_values.push_back(std::to_string(char_create_combinations_entry.deity)); - insert_values.push_back(std::to_string(char_create_combinations_entry.start_zone)); - insert_values.push_back(std::to_string(char_create_combinations_entry.expansions_req)); + v.push_back(std::to_string(e.allocation_id)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.start_zone)); + v.push_back(std::to_string(e.expansions_req)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharCreateCombinations entry{}; + CharCreateCombinations e{}; - entry.allocation_id = atoi(row[0]); - entry.race = atoi(row[1]); - entry.class_ = atoi(row[2]); - entry.deity = atoi(row[3]); - entry.start_zone = atoi(row[4]); - entry.expansions_req = atoi(row[5]); + e.allocation_id = static_cast(strtoul(row[0], nullptr, 10)); + e.race = static_cast(strtoul(row[1], nullptr, 10)); + e.class_ = static_cast(strtoul(row[2], nullptr, 10)); + e.deity = static_cast(strtoul(row[3], nullptr, 10)); + e.start_zone = static_cast(strtoul(row[4], nullptr, 10)); + e.expansions_req = static_cast(strtoul(row[5], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharCreateCombinations entry{}; + CharCreateCombinations e{}; - entry.allocation_id = atoi(row[0]); - entry.race = atoi(row[1]); - entry.class_ = atoi(row[2]); - entry.deity = atoi(row[3]); - entry.start_zone = atoi(row[4]); - entry.expansions_req = atoi(row[5]); + e.allocation_id = static_cast(strtoul(row[0], nullptr, 10)); + e.race = static_cast(strtoul(row[1], nullptr, 10)); + e.class_ = static_cast(strtoul(row[2], nullptr, 10)); + e.deity = static_cast(strtoul(row[3], nullptr, 10)); + e.start_zone = static_cast(strtoul(row[4], nullptr, 10)); + e.expansions_req = static_cast(strtoul(row[5], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHAR_CREATE_COMBINATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_char_create_point_allocations_repository.h b/common/repositories/base/base_char_create_point_allocations_repository.h index 2ca6d2359..4573a025b 100644 --- a/common/repositories/base/base_char_create_point_allocations_repository.h +++ b/common/repositories/base/base_char_create_point_allocations_repository.h @@ -13,27 +13,27 @@ #define EQEMU_BASE_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharCreatePointAllocationsRepository { public: struct CharCreatePointAllocations { - int id; - int base_str; - int base_sta; - int base_dex; - int base_agi; - int base_int; - int base_wis; - int base_cha; - int alloc_str; - int alloc_sta; - int alloc_dex; - int alloc_agi; - int alloc_int; - int alloc_wis; - int alloc_cha; + uint32_t id; + uint32_t base_str; + uint32_t base_sta; + uint32_t base_dex; + uint32_t base_agi; + uint32_t base_int; + uint32_t base_wis; + uint32_t base_cha; + uint32_t alloc_str; + uint32_t alloc_sta; + uint32_t alloc_dex; + uint32_t alloc_agi; + uint32_t alloc_int; + uint32_t alloc_wis; + uint32_t alloc_cha; }; static std::string PrimaryKey() @@ -85,12 +85,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -118,28 +118,28 @@ public: static CharCreatePointAllocations NewEntity() { - CharCreatePointAllocations entry{}; + CharCreatePointAllocations e{}; - entry.id = 0; - entry.base_str = 0; - entry.base_sta = 0; - entry.base_dex = 0; - entry.base_agi = 0; - entry.base_int = 0; - entry.base_wis = 0; - entry.base_cha = 0; - entry.alloc_str = 0; - entry.alloc_sta = 0; - entry.alloc_dex = 0; - entry.alloc_agi = 0; - entry.alloc_int = 0; - entry.alloc_wis = 0; - entry.alloc_cha = 0; + e.id = 0; + e.base_str = 0; + e.base_sta = 0; + e.base_dex = 0; + e.base_agi = 0; + e.base_int = 0; + e.base_wis = 0; + e.base_cha = 0; + e.alloc_str = 0; + e.alloc_sta = 0; + e.alloc_dex = 0; + e.alloc_agi = 0; + e.alloc_int = 0; + e.alloc_wis = 0; + e.alloc_cha = 0; - return entry; + return e; } - static CharCreatePointAllocations GetCharCreatePointAllocationsEntry( + static CharCreatePointAllocations GetCharCreatePointAllocations( const std::vector &char_create_point_allocationss, int char_create_point_allocations_id ) @@ -168,25 +168,25 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharCreatePointAllocations entry{}; + CharCreatePointAllocations e{}; - entry.id = atoi(row[0]); - entry.base_str = atoi(row[1]); - entry.base_sta = atoi(row[2]); - entry.base_dex = atoi(row[3]); - entry.base_agi = atoi(row[4]); - entry.base_int = atoi(row[5]); - entry.base_wis = atoi(row[6]); - entry.base_cha = atoi(row[7]); - entry.alloc_str = atoi(row[8]); - entry.alloc_sta = atoi(row[9]); - entry.alloc_dex = atoi(row[10]); - entry.alloc_agi = atoi(row[11]); - entry.alloc_int = atoi(row[12]); - entry.alloc_wis = atoi(row[13]); - entry.alloc_cha = atoi(row[14]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.base_str = static_cast(strtoul(row[1], nullptr, 10)); + e.base_sta = static_cast(strtoul(row[2], nullptr, 10)); + e.base_dex = static_cast(strtoul(row[3], nullptr, 10)); + e.base_agi = static_cast(strtoul(row[4], nullptr, 10)); + e.base_int = static_cast(strtoul(row[5], nullptr, 10)); + e.base_wis = static_cast(strtoul(row[6], nullptr, 10)); + e.base_cha = static_cast(strtoul(row[7], nullptr, 10)); + e.alloc_str = static_cast(strtoul(row[8], nullptr, 10)); + e.alloc_sta = static_cast(strtoul(row[9], nullptr, 10)); + e.alloc_dex = static_cast(strtoul(row[10], nullptr, 10)); + e.alloc_agi = static_cast(strtoul(row[11], nullptr, 10)); + e.alloc_int = static_cast(strtoul(row[12], nullptr, 10)); + e.alloc_wis = static_cast(strtoul(row[13], nullptr, 10)); + e.alloc_cha = static_cast(strtoul(row[14], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -211,36 +211,36 @@ public: static int UpdateOne( Database& db, - CharCreatePointAllocations char_create_point_allocations_entry + const CharCreatePointAllocations &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(char_create_point_allocations_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(char_create_point_allocations_entry.base_str)); - update_values.push_back(columns[2] + " = " + std::to_string(char_create_point_allocations_entry.base_sta)); - update_values.push_back(columns[3] + " = " + std::to_string(char_create_point_allocations_entry.base_dex)); - update_values.push_back(columns[4] + " = " + std::to_string(char_create_point_allocations_entry.base_agi)); - update_values.push_back(columns[5] + " = " + std::to_string(char_create_point_allocations_entry.base_int)); - update_values.push_back(columns[6] + " = " + std::to_string(char_create_point_allocations_entry.base_wis)); - update_values.push_back(columns[7] + " = " + std::to_string(char_create_point_allocations_entry.base_cha)); - update_values.push_back(columns[8] + " = " + std::to_string(char_create_point_allocations_entry.alloc_str)); - update_values.push_back(columns[9] + " = " + std::to_string(char_create_point_allocations_entry.alloc_sta)); - update_values.push_back(columns[10] + " = " + std::to_string(char_create_point_allocations_entry.alloc_dex)); - update_values.push_back(columns[11] + " = " + std::to_string(char_create_point_allocations_entry.alloc_agi)); - update_values.push_back(columns[12] + " = " + std::to_string(char_create_point_allocations_entry.alloc_int)); - update_values.push_back(columns[13] + " = " + std::to_string(char_create_point_allocations_entry.alloc_wis)); - update_values.push_back(columns[14] + " = " + std::to_string(char_create_point_allocations_entry.alloc_cha)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.base_str)); + v.push_back(columns[2] + " = " + std::to_string(e.base_sta)); + v.push_back(columns[3] + " = " + std::to_string(e.base_dex)); + v.push_back(columns[4] + " = " + std::to_string(e.base_agi)); + v.push_back(columns[5] + " = " + std::to_string(e.base_int)); + v.push_back(columns[6] + " = " + std::to_string(e.base_wis)); + v.push_back(columns[7] + " = " + std::to_string(e.base_cha)); + v.push_back(columns[8] + " = " + std::to_string(e.alloc_str)); + v.push_back(columns[9] + " = " + std::to_string(e.alloc_sta)); + v.push_back(columns[10] + " = " + std::to_string(e.alloc_dex)); + v.push_back(columns[11] + " = " + std::to_string(e.alloc_agi)); + v.push_back(columns[12] + " = " + std::to_string(e.alloc_int)); + v.push_back(columns[13] + " = " + std::to_string(e.alloc_wis)); + v.push_back(columns[14] + " = " + std::to_string(e.alloc_cha)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - char_create_point_allocations_entry.id + e.id ) ); @@ -249,81 +249,81 @@ public: static CharCreatePointAllocations InsertOne( Database& db, - CharCreatePointAllocations char_create_point_allocations_entry + CharCreatePointAllocations e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(char_create_point_allocations_entry.id)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_str)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_sta)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_dex)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_agi)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_int)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_wis)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_cha)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_str)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_sta)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_dex)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_agi)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_int)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_wis)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_cha)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.base_str)); + v.push_back(std::to_string(e.base_sta)); + v.push_back(std::to_string(e.base_dex)); + v.push_back(std::to_string(e.base_agi)); + v.push_back(std::to_string(e.base_int)); + v.push_back(std::to_string(e.base_wis)); + v.push_back(std::to_string(e.base_cha)); + v.push_back(std::to_string(e.alloc_str)); + v.push_back(std::to_string(e.alloc_sta)); + v.push_back(std::to_string(e.alloc_dex)); + v.push_back(std::to_string(e.alloc_agi)); + v.push_back(std::to_string(e.alloc_int)); + v.push_back(std::to_string(e.alloc_wis)); + v.push_back(std::to_string(e.alloc_cha)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - char_create_point_allocations_entry.id = results.LastInsertedID(); - return char_create_point_allocations_entry; + e.id = results.LastInsertedID(); + return e; } - char_create_point_allocations_entry = NewEntity(); + e = NewEntity(); - return char_create_point_allocations_entry; + return e; } static int InsertMany( Database& db, - std::vector char_create_point_allocations_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &char_create_point_allocations_entry: char_create_point_allocations_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(char_create_point_allocations_entry.id)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_str)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_sta)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_dex)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_agi)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_int)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_wis)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.base_cha)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_str)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_sta)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_dex)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_agi)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_int)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_wis)); - insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_cha)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.base_str)); + v.push_back(std::to_string(e.base_sta)); + v.push_back(std::to_string(e.base_dex)); + v.push_back(std::to_string(e.base_agi)); + v.push_back(std::to_string(e.base_int)); + v.push_back(std::to_string(e.base_wis)); + v.push_back(std::to_string(e.base_cha)); + v.push_back(std::to_string(e.alloc_str)); + v.push_back(std::to_string(e.alloc_sta)); + v.push_back(std::to_string(e.alloc_dex)); + v.push_back(std::to_string(e.alloc_agi)); + v.push_back(std::to_string(e.alloc_int)); + v.push_back(std::to_string(e.alloc_wis)); + v.push_back(std::to_string(e.alloc_cha)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -344,31 +344,31 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharCreatePointAllocations entry{}; + CharCreatePointAllocations e{}; - entry.id = atoi(row[0]); - entry.base_str = atoi(row[1]); - entry.base_sta = atoi(row[2]); - entry.base_dex = atoi(row[3]); - entry.base_agi = atoi(row[4]); - entry.base_int = atoi(row[5]); - entry.base_wis = atoi(row[6]); - entry.base_cha = atoi(row[7]); - entry.alloc_str = atoi(row[8]); - entry.alloc_sta = atoi(row[9]); - entry.alloc_dex = atoi(row[10]); - entry.alloc_agi = atoi(row[11]); - entry.alloc_int = atoi(row[12]); - entry.alloc_wis = atoi(row[13]); - entry.alloc_cha = atoi(row[14]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.base_str = static_cast(strtoul(row[1], nullptr, 10)); + e.base_sta = static_cast(strtoul(row[2], nullptr, 10)); + e.base_dex = static_cast(strtoul(row[3], nullptr, 10)); + e.base_agi = static_cast(strtoul(row[4], nullptr, 10)); + e.base_int = static_cast(strtoul(row[5], nullptr, 10)); + e.base_wis = static_cast(strtoul(row[6], nullptr, 10)); + e.base_cha = static_cast(strtoul(row[7], nullptr, 10)); + e.alloc_str = static_cast(strtoul(row[8], nullptr, 10)); + e.alloc_sta = static_cast(strtoul(row[9], nullptr, 10)); + e.alloc_dex = static_cast(strtoul(row[10], nullptr, 10)); + e.alloc_agi = static_cast(strtoul(row[11], nullptr, 10)); + e.alloc_int = static_cast(strtoul(row[12], nullptr, 10)); + e.alloc_wis = static_cast(strtoul(row[13], nullptr, 10)); + e.alloc_cha = static_cast(strtoul(row[14], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -383,31 +383,31 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharCreatePointAllocations entry{}; + CharCreatePointAllocations e{}; - entry.id = atoi(row[0]); - entry.base_str = atoi(row[1]); - entry.base_sta = atoi(row[2]); - entry.base_dex = atoi(row[3]); - entry.base_agi = atoi(row[4]); - entry.base_int = atoi(row[5]); - entry.base_wis = atoi(row[6]); - entry.base_cha = atoi(row[7]); - entry.alloc_str = atoi(row[8]); - entry.alloc_sta = atoi(row[9]); - entry.alloc_dex = atoi(row[10]); - entry.alloc_agi = atoi(row[11]); - entry.alloc_int = atoi(row[12]); - entry.alloc_wis = atoi(row[13]); - entry.alloc_cha = atoi(row[14]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.base_str = static_cast(strtoul(row[1], nullptr, 10)); + e.base_sta = static_cast(strtoul(row[2], nullptr, 10)); + e.base_dex = static_cast(strtoul(row[3], nullptr, 10)); + e.base_agi = static_cast(strtoul(row[4], nullptr, 10)); + e.base_int = static_cast(strtoul(row[5], nullptr, 10)); + e.base_wis = static_cast(strtoul(row[6], nullptr, 10)); + e.base_cha = static_cast(strtoul(row[7], nullptr, 10)); + e.alloc_str = static_cast(strtoul(row[8], nullptr, 10)); + e.alloc_sta = static_cast(strtoul(row[9], nullptr, 10)); + e.alloc_dex = static_cast(strtoul(row[10], nullptr, 10)); + e.alloc_agi = static_cast(strtoul(row[11], nullptr, 10)); + e.alloc_int = static_cast(strtoul(row[12], nullptr, 10)); + e.alloc_wis = static_cast(strtoul(row[13], nullptr, 10)); + e.alloc_cha = static_cast(strtoul(row[14], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -432,6 +432,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_char_recipe_list_repository.h b/common/repositories/base/base_char_recipe_list_repository.h index 26b340f66..5ae76ef4f 100644 --- a/common/repositories/base/base_char_recipe_list_repository.h +++ b/common/repositories/base/base_char_recipe_list_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHAR_RECIPE_LIST_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharRecipeListRepository { public: struct CharRecipeList { - int char_id; - int recipe_id; - int madecount; + int32_t char_id; + int32_t recipe_id; + int32_t madecount; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharRecipeList NewEntity() { - CharRecipeList entry{}; + CharRecipeList e{}; - entry.char_id = 0; - entry.recipe_id = 0; - entry.madecount = 0; + e.char_id = 0; + e.recipe_id = 0; + e.madecount = 0; - return entry; + return e; } - static CharRecipeList GetCharRecipeListEntry( + static CharRecipeList GetCharRecipeList( const std::vector &char_recipe_lists, int char_recipe_list_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharRecipeList entry{}; + CharRecipeList e{}; - entry.char_id = atoi(row[0]); - entry.recipe_id = atoi(row[1]); - entry.madecount = atoi(row[2]); + e.char_id = static_cast(atoi(row[0])); + e.recipe_id = static_cast(atoi(row[1])); + e.madecount = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CharRecipeList char_recipe_list_entry + const CharRecipeList &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(char_recipe_list_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(char_recipe_list_entry.recipe_id)); - update_values.push_back(columns[2] + " = " + std::to_string(char_recipe_list_entry.madecount)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.recipe_id)); + v.push_back(columns[2] + " = " + std::to_string(e.madecount)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - char_recipe_list_entry.char_id + e.char_id ) ); @@ -177,57 +177,57 @@ public: static CharRecipeList InsertOne( Database& db, - CharRecipeList char_recipe_list_entry + CharRecipeList e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(char_recipe_list_entry.char_id)); - insert_values.push_back(std::to_string(char_recipe_list_entry.recipe_id)); - insert_values.push_back(std::to_string(char_recipe_list_entry.madecount)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.recipe_id)); + v.push_back(std::to_string(e.madecount)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - char_recipe_list_entry.char_id = results.LastInsertedID(); - return char_recipe_list_entry; + e.char_id = results.LastInsertedID(); + return e; } - char_recipe_list_entry = NewEntity(); + e = NewEntity(); - return char_recipe_list_entry; + return e; } static int InsertMany( Database& db, - std::vector char_recipe_list_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &char_recipe_list_entry: char_recipe_list_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(char_recipe_list_entry.char_id)); - insert_values.push_back(std::to_string(char_recipe_list_entry.recipe_id)); - insert_values.push_back(std::to_string(char_recipe_list_entry.madecount)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.recipe_id)); + v.push_back(std::to_string(e.madecount)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharRecipeList entry{}; + CharRecipeList e{}; - entry.char_id = atoi(row[0]); - entry.recipe_id = atoi(row[1]); - entry.madecount = atoi(row[2]); + e.char_id = static_cast(atoi(row[0])); + e.recipe_id = static_cast(atoi(row[1])); + e.madecount = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharRecipeList entry{}; + CharRecipeList e{}; - entry.char_id = atoi(row[0]); - entry.recipe_id = atoi(row[1]); - entry.madecount = atoi(row[2]); + e.char_id = static_cast(atoi(row[0])); + e.recipe_id = static_cast(atoi(row[1])); + e.madecount = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHAR_RECIPE_LIST_REPOSITORY_H diff --git a/common/repositories/base/base_character_activities_repository.h b/common/repositories/base/base_character_activities_repository.h index 2b3441055..b365bd81a 100644 --- a/common/repositories/base/base_character_activities_repository.h +++ b/common/repositories/base/base_character_activities_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_CHARACTER_ACTIVITIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterActivitiesRepository { public: struct CharacterActivities { - int charid; - int taskid; - int activityid; - int donecount; - int completed; + uint32_t charid; + uint32_t taskid; + uint32_t activityid; + uint32_t donecount; + int8_t completed; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static CharacterActivities NewEntity() { - CharacterActivities entry{}; + CharacterActivities e{}; - entry.charid = 0; - entry.taskid = 0; - entry.activityid = 0; - entry.donecount = 0; - entry.completed = 0; + e.charid = 0; + e.taskid = 0; + e.activityid = 0; + e.donecount = 0; + e.completed = 0; - return entry; + return e; } - static CharacterActivities GetCharacterActivitiesEntry( + static CharacterActivities GetCharacterActivities( const std::vector &character_activitiess, int character_activities_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterActivities entry{}; + CharacterActivities e{}; - entry.charid = atoi(row[0]); - entry.taskid = atoi(row[1]); - entry.activityid = atoi(row[2]); - entry.donecount = atoi(row[3]); - entry.completed = atoi(row[4]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); + e.activityid = static_cast(strtoul(row[2], nullptr, 10)); + e.donecount = static_cast(strtoul(row[3], nullptr, 10)); + e.completed = static_cast(atoi(row[4])); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - CharacterActivities character_activities_entry + const CharacterActivities &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_activities_entry.charid)); - update_values.push_back(columns[1] + " = " + std::to_string(character_activities_entry.taskid)); - update_values.push_back(columns[2] + " = " + std::to_string(character_activities_entry.activityid)); - update_values.push_back(columns[3] + " = " + std::to_string(character_activities_entry.donecount)); - update_values.push_back(columns[4] + " = " + std::to_string(character_activities_entry.completed)); + v.push_back(columns[0] + " = " + std::to_string(e.charid)); + v.push_back(columns[1] + " = " + std::to_string(e.taskid)); + v.push_back(columns[2] + " = " + std::to_string(e.activityid)); + v.push_back(columns[3] + " = " + std::to_string(e.donecount)); + v.push_back(columns[4] + " = " + std::to_string(e.completed)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_activities_entry.charid + e.charid ) ); @@ -189,61 +189,61 @@ public: static CharacterActivities InsertOne( Database& db, - CharacterActivities character_activities_entry + CharacterActivities e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_activities_entry.charid)); - insert_values.push_back(std::to_string(character_activities_entry.taskid)); - insert_values.push_back(std::to_string(character_activities_entry.activityid)); - insert_values.push_back(std::to_string(character_activities_entry.donecount)); - insert_values.push_back(std::to_string(character_activities_entry.completed)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.activityid)); + v.push_back(std::to_string(e.donecount)); + v.push_back(std::to_string(e.completed)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_activities_entry.charid = results.LastInsertedID(); - return character_activities_entry; + e.charid = results.LastInsertedID(); + return e; } - character_activities_entry = NewEntity(); + e = NewEntity(); - return character_activities_entry; + return e; } static int InsertMany( Database& db, - std::vector character_activities_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_activities_entry: character_activities_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_activities_entry.charid)); - insert_values.push_back(std::to_string(character_activities_entry.taskid)); - insert_values.push_back(std::to_string(character_activities_entry.activityid)); - insert_values.push_back(std::to_string(character_activities_entry.donecount)); - insert_values.push_back(std::to_string(character_activities_entry.completed)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.activityid)); + v.push_back(std::to_string(e.donecount)); + v.push_back(std::to_string(e.completed)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterActivities entry{}; + CharacterActivities e{}; - entry.charid = atoi(row[0]); - entry.taskid = atoi(row[1]); - entry.activityid = atoi(row[2]); - entry.donecount = atoi(row[3]); - entry.completed = atoi(row[4]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); + e.activityid = static_cast(strtoul(row[2], nullptr, 10)); + e.donecount = static_cast(strtoul(row[3], nullptr, 10)); + e.completed = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterActivities entry{}; + CharacterActivities e{}; - entry.charid = atoi(row[0]); - entry.taskid = atoi(row[1]); - entry.activityid = atoi(row[2]); - entry.donecount = atoi(row[3]); - entry.completed = atoi(row[4]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); + e.activityid = static_cast(strtoul(row[2], nullptr, 10)); + e.donecount = static_cast(strtoul(row[3], nullptr, 10)); + e.completed = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_ACTIVITIES_REPOSITORY_H diff --git a/common/repositories/base/base_character_alt_currency_repository.h b/common/repositories/base/base_character_alt_currency_repository.h index 3dad9cbbb..054bf0b01 100644 --- a/common/repositories/base/base_character_alt_currency_repository.h +++ b/common/repositories/base/base_character_alt_currency_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterAltCurrencyRepository { public: struct CharacterAltCurrency { - int char_id; - int currency_id; - int amount; + uint32_t char_id; + uint32_t currency_id; + uint32_t amount; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterAltCurrency NewEntity() { - CharacterAltCurrency entry{}; + CharacterAltCurrency e{}; - entry.char_id = 0; - entry.currency_id = 0; - entry.amount = 0; + e.char_id = 0; + e.currency_id = 0; + e.amount = 0; - return entry; + return e; } - static CharacterAltCurrency GetCharacterAltCurrencyEntry( + static CharacterAltCurrency GetCharacterAltCurrency( const std::vector &character_alt_currencys, int character_alt_currency_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterAltCurrency entry{}; + CharacterAltCurrency e{}; - entry.char_id = atoi(row[0]); - entry.currency_id = atoi(row[1]); - entry.amount = atoi(row[2]); + e.char_id = static_cast(strtoul(row[0], nullptr, 10)); + e.currency_id = static_cast(strtoul(row[1], nullptr, 10)); + e.amount = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CharacterAltCurrency character_alt_currency_entry + const CharacterAltCurrency &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_alt_currency_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_alt_currency_entry.currency_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_alt_currency_entry.amount)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.currency_id)); + v.push_back(columns[2] + " = " + std::to_string(e.amount)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_alt_currency_entry.char_id + e.char_id ) ); @@ -177,57 +177,57 @@ public: static CharacterAltCurrency InsertOne( Database& db, - CharacterAltCurrency character_alt_currency_entry + CharacterAltCurrency e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_alt_currency_entry.char_id)); - insert_values.push_back(std::to_string(character_alt_currency_entry.currency_id)); - insert_values.push_back(std::to_string(character_alt_currency_entry.amount)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.currency_id)); + v.push_back(std::to_string(e.amount)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_alt_currency_entry.char_id = results.LastInsertedID(); - return character_alt_currency_entry; + e.char_id = results.LastInsertedID(); + return e; } - character_alt_currency_entry = NewEntity(); + e = NewEntity(); - return character_alt_currency_entry; + return e; } static int InsertMany( Database& db, - std::vector character_alt_currency_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_alt_currency_entry: character_alt_currency_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_alt_currency_entry.char_id)); - insert_values.push_back(std::to_string(character_alt_currency_entry.currency_id)); - insert_values.push_back(std::to_string(character_alt_currency_entry.amount)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.currency_id)); + v.push_back(std::to_string(e.amount)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterAltCurrency entry{}; + CharacterAltCurrency e{}; - entry.char_id = atoi(row[0]); - entry.currency_id = atoi(row[1]); - entry.amount = atoi(row[2]); + e.char_id = static_cast(strtoul(row[0], nullptr, 10)); + e.currency_id = static_cast(strtoul(row[1], nullptr, 10)); + e.amount = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterAltCurrency entry{}; + CharacterAltCurrency e{}; - entry.char_id = atoi(row[0]); - entry.currency_id = atoi(row[1]); - entry.amount = atoi(row[2]); + e.char_id = static_cast(strtoul(row[0], nullptr, 10)); + e.currency_id = static_cast(strtoul(row[1], nullptr, 10)); + e.amount = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H diff --git a/common/repositories/base/base_character_alternate_abilities_repository.h b/common/repositories/base/base_character_alternate_abilities_repository.h index ae91d1274..c7009e487 100644 --- a/common/repositories/base/base_character_alternate_abilities_repository.h +++ b/common/repositories/base/base_character_alternate_abilities_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterAlternateAbilitiesRepository { public: struct CharacterAlternateAbilities { - int id; - int aa_id; - int aa_value; - int charges; + uint32_t id; + uint16_t aa_id; + uint16_t aa_value; + uint16_t charges; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static CharacterAlternateAbilities NewEntity() { - CharacterAlternateAbilities entry{}; + CharacterAlternateAbilities e{}; - entry.id = 0; - entry.aa_id = 0; - entry.aa_value = 0; - entry.charges = 0; + e.id = 0; + e.aa_id = 0; + e.aa_value = 0; + e.charges = 0; - return entry; + return e; } - static CharacterAlternateAbilities GetCharacterAlternateAbilitiesEntry( + static CharacterAlternateAbilities GetCharacterAlternateAbilities( const std::vector &character_alternate_abilitiess, int character_alternate_abilities_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterAlternateAbilities entry{}; + CharacterAlternateAbilities e{}; - entry.id = atoi(row[0]); - entry.aa_id = atoi(row[1]); - entry.aa_value = atoi(row[2]); - entry.charges = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.aa_id = static_cast(strtoul(row[1], nullptr, 10)); + e.aa_value = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - CharacterAlternateAbilities character_alternate_abilities_entry + const CharacterAlternateAbilities &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_alternate_abilities_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_alternate_abilities_entry.aa_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_alternate_abilities_entry.aa_value)); - update_values.push_back(columns[3] + " = " + std::to_string(character_alternate_abilities_entry.charges)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.aa_id)); + v.push_back(columns[2] + " = " + std::to_string(e.aa_value)); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_alternate_abilities_entry.id + e.id ) ); @@ -183,59 +183,59 @@ public: static CharacterAlternateAbilities InsertOne( Database& db, - CharacterAlternateAbilities character_alternate_abilities_entry + CharacterAlternateAbilities e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_alternate_abilities_entry.id)); - insert_values.push_back(std::to_string(character_alternate_abilities_entry.aa_id)); - insert_values.push_back(std::to_string(character_alternate_abilities_entry.aa_value)); - insert_values.push_back(std::to_string(character_alternate_abilities_entry.charges)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_id)); + v.push_back(std::to_string(e.aa_value)); + v.push_back(std::to_string(e.charges)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_alternate_abilities_entry.id = results.LastInsertedID(); - return character_alternate_abilities_entry; + e.id = results.LastInsertedID(); + return e; } - character_alternate_abilities_entry = NewEntity(); + e = NewEntity(); - return character_alternate_abilities_entry; + return e; } static int InsertMany( Database& db, - std::vector character_alternate_abilities_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_alternate_abilities_entry: character_alternate_abilities_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_alternate_abilities_entry.id)); - insert_values.push_back(std::to_string(character_alternate_abilities_entry.aa_id)); - insert_values.push_back(std::to_string(character_alternate_abilities_entry.aa_value)); - insert_values.push_back(std::to_string(character_alternate_abilities_entry.charges)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_id)); + v.push_back(std::to_string(e.aa_value)); + v.push_back(std::to_string(e.charges)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterAlternateAbilities entry{}; + CharacterAlternateAbilities e{}; - entry.id = atoi(row[0]); - entry.aa_id = atoi(row[1]); - entry.aa_value = atoi(row[2]); - entry.charges = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.aa_id = static_cast(strtoul(row[1], nullptr, 10)); + e.aa_value = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterAlternateAbilities entry{}; + CharacterAlternateAbilities e{}; - entry.id = atoi(row[0]); - entry.aa_id = atoi(row[1]); - entry.aa_value = atoi(row[2]); - entry.charges = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.aa_id = static_cast(strtoul(row[1], nullptr, 10)); + e.aa_value = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H diff --git a/common/repositories/base/base_character_auras_repository.h b/common/repositories/base/base_character_auras_repository.h index 84b165619..b2334e5ce 100644 --- a/common/repositories/base/base_character_auras_repository.h +++ b/common/repositories/base/base_character_auras_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterAurasRepository { public: struct CharacterAuras { - int id; - int slot; - int spell_id; + int32_t id; + int8_t slot; + int32_t spell_id; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterAuras NewEntity() { - CharacterAuras entry{}; + CharacterAuras e{}; - entry.id = 0; - entry.slot = 0; - entry.spell_id = 0; + e.id = 0; + e.slot = 0; + e.spell_id = 0; - return entry; + return e; } - static CharacterAuras GetCharacterAurasEntry( + static CharacterAuras GetCharacterAuras( const std::vector &character_aurass, int character_auras_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterAuras entry{}; + CharacterAuras e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.spell_id = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CharacterAuras character_auras_entry + const CharacterAuras &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_auras_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_auras_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(character_auras_entry.spell_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_auras_entry.id + e.id ) ); @@ -177,57 +177,57 @@ public: static CharacterAuras InsertOne( Database& db, - CharacterAuras character_auras_entry + CharacterAuras e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_auras_entry.id)); - insert_values.push_back(std::to_string(character_auras_entry.slot)); - insert_values.push_back(std::to_string(character_auras_entry.spell_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.spell_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_auras_entry.id = results.LastInsertedID(); - return character_auras_entry; + e.id = results.LastInsertedID(); + return e; } - character_auras_entry = NewEntity(); + e = NewEntity(); - return character_auras_entry; + return e; } static int InsertMany( Database& db, - std::vector character_auras_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_auras_entry: character_auras_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_auras_entry.id)); - insert_values.push_back(std::to_string(character_auras_entry.slot)); - insert_values.push_back(std::to_string(character_auras_entry.spell_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.spell_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterAuras entry{}; + CharacterAuras e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.spell_id = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterAuras entry{}; + CharacterAuras e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.spell_id = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H diff --git a/common/repositories/base/base_character_bandolier_repository.h b/common/repositories/base/base_character_bandolier_repository.h index be3adfb2d..2aca3aedf 100644 --- a/common/repositories/base/base_character_bandolier_repository.h +++ b/common/repositories/base/base_character_bandolier_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterBandolierRepository { public: struct CharacterBandolier { - int id; - int bandolier_id; - int bandolier_slot; - int item_id; - int icon; + uint32_t id; + uint8_t bandolier_id; + uint8_t bandolier_slot; + uint32_t item_id; + uint32_t icon; std::string bandolier_name; }; @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static CharacterBandolier NewEntity() { - CharacterBandolier entry{}; + CharacterBandolier e{}; - entry.id = 0; - entry.bandolier_id = 0; - entry.bandolier_slot = 0; - entry.item_id = 0; - entry.icon = 0; - entry.bandolier_name = "0"; + e.id = 0; + e.bandolier_id = 0; + e.bandolier_slot = 0; + e.item_id = 0; + e.icon = 0; + e.bandolier_name = "0"; - return entry; + return e; } - static CharacterBandolier GetCharacterBandolierEntry( + static CharacterBandolier GetCharacterBandolier( const std::vector &character_bandoliers, int character_bandolier_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterBandolier entry{}; + CharacterBandolier e{}; - entry.id = atoi(row[0]); - entry.bandolier_id = atoi(row[1]); - entry.bandolier_slot = atoi(row[2]); - entry.item_id = atoi(row[3]); - entry.icon = atoi(row[4]); - entry.bandolier_name = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.bandolier_id = static_cast(strtoul(row[1], nullptr, 10)); + e.bandolier_slot = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); + e.icon = static_cast(strtoul(row[4], nullptr, 10)); + e.bandolier_name = row[5] ? row[5] : ""; - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - CharacterBandolier character_bandolier_entry + const CharacterBandolier &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_bandolier_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_bandolier_entry.bandolier_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_bandolier_entry.bandolier_slot)); - update_values.push_back(columns[3] + " = " + std::to_string(character_bandolier_entry.item_id)); - update_values.push_back(columns[4] + " = " + std::to_string(character_bandolier_entry.icon)); - update_values.push_back(columns[5] + " = '" + EscapeString(character_bandolier_entry.bandolier_name) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.bandolier_id)); + v.push_back(columns[2] + " = " + std::to_string(e.bandolier_slot)); + v.push_back(columns[3] + " = " + std::to_string(e.item_id)); + v.push_back(columns[4] + " = " + std::to_string(e.icon)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.bandolier_name) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_bandolier_entry.id + e.id ) ); @@ -195,63 +195,63 @@ public: static CharacterBandolier InsertOne( Database& db, - CharacterBandolier character_bandolier_entry + CharacterBandolier e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_bandolier_entry.id)); - insert_values.push_back(std::to_string(character_bandolier_entry.bandolier_id)); - insert_values.push_back(std::to_string(character_bandolier_entry.bandolier_slot)); - insert_values.push_back(std::to_string(character_bandolier_entry.item_id)); - insert_values.push_back(std::to_string(character_bandolier_entry.icon)); - insert_values.push_back("'" + EscapeString(character_bandolier_entry.bandolier_name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.bandolier_id)); + v.push_back(std::to_string(e.bandolier_slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.icon)); + v.push_back("'" + Strings::Escape(e.bandolier_name) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_bandolier_entry.id = results.LastInsertedID(); - return character_bandolier_entry; + e.id = results.LastInsertedID(); + return e; } - character_bandolier_entry = NewEntity(); + e = NewEntity(); - return character_bandolier_entry; + return e; } static int InsertMany( Database& db, - std::vector character_bandolier_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_bandolier_entry: character_bandolier_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_bandolier_entry.id)); - insert_values.push_back(std::to_string(character_bandolier_entry.bandolier_id)); - insert_values.push_back(std::to_string(character_bandolier_entry.bandolier_slot)); - insert_values.push_back(std::to_string(character_bandolier_entry.item_id)); - insert_values.push_back(std::to_string(character_bandolier_entry.icon)); - insert_values.push_back("'" + EscapeString(character_bandolier_entry.bandolier_name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.bandolier_id)); + v.push_back(std::to_string(e.bandolier_slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.icon)); + v.push_back("'" + Strings::Escape(e.bandolier_name) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterBandolier entry{}; + CharacterBandolier e{}; - entry.id = atoi(row[0]); - entry.bandolier_id = atoi(row[1]); - entry.bandolier_slot = atoi(row[2]); - entry.item_id = atoi(row[3]); - entry.icon = atoi(row[4]); - entry.bandolier_name = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.bandolier_id = static_cast(strtoul(row[1], nullptr, 10)); + e.bandolier_slot = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); + e.icon = static_cast(strtoul(row[4], nullptr, 10)); + e.bandolier_name = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterBandolier entry{}; + CharacterBandolier e{}; - entry.id = atoi(row[0]); - entry.bandolier_id = atoi(row[1]); - entry.bandolier_slot = atoi(row[2]); - entry.item_id = atoi(row[3]); - entry.icon = atoi(row[4]); - entry.bandolier_name = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.bandolier_id = static_cast(strtoul(row[1], nullptr, 10)); + e.bandolier_slot = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); + e.icon = static_cast(strtoul(row[4], nullptr, 10)); + e.bandolier_name = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H diff --git a/common/repositories/base/base_character_bind_repository.h b/common/repositories/base/base_character_bind_repository.h index 4cc042596..12ce7d52e 100644 --- a/common/repositories/base/base_character_bind_repository.h +++ b/common/repositories/base/base_character_bind_repository.h @@ -13,20 +13,20 @@ #define EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterBindRepository { public: struct CharacterBind { - int id; - int slot; - int zone_id; - int instance_id; - float x; - float y; - float z; - float heading; + uint32_t id; + int32_t slot; + uint16_t zone_id; + uint32_t instance_id; + float x; + float y; + float z; + float heading; }; static std::string PrimaryKey() @@ -64,12 +64,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -97,21 +97,21 @@ public: static CharacterBind NewEntity() { - CharacterBind entry{}; + CharacterBind e{}; - entry.id = 0; - entry.slot = 0; - entry.zone_id = 0; - entry.instance_id = 0; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.heading = 0; + e.id = 0; + e.slot = 0; + e.zone_id = 0; + e.instance_id = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; - return entry; + return e; } - static CharacterBind GetCharacterBindEntry( + static CharacterBind GetCharacterBind( const std::vector &character_binds, int character_bind_id ) @@ -140,18 +140,18 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterBind entry{}; + CharacterBind e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.zone_id = atoi(row[2]); - entry.instance_id = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(atoi(row[1])); + e.zone_id = static_cast(strtoul(row[2], nullptr, 10)); + e.instance_id = static_cast(strtoul(row[3], nullptr, 10)); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); - return entry; + return e; } return NewEntity(); @@ -176,28 +176,28 @@ public: static int UpdateOne( Database& db, - CharacterBind character_bind_entry + const CharacterBind &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_bind_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(character_bind_entry.zone_id)); - update_values.push_back(columns[3] + " = " + std::to_string(character_bind_entry.instance_id)); - update_values.push_back(columns[4] + " = " + std::to_string(character_bind_entry.x)); - update_values.push_back(columns[5] + " = " + std::to_string(character_bind_entry.y)); - update_values.push_back(columns[6] + " = " + std::to_string(character_bind_entry.z)); - update_values.push_back(columns[7] + " = " + std::to_string(character_bind_entry.heading)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[3] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[4] + " = " + std::to_string(e.x)); + v.push_back(columns[5] + " = " + std::to_string(e.y)); + v.push_back(columns[6] + " = " + std::to_string(e.z)); + v.push_back(columns[7] + " = " + std::to_string(e.heading)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_bind_entry.id + e.id ) ); @@ -206,67 +206,67 @@ public: static CharacterBind InsertOne( Database& db, - CharacterBind character_bind_entry + CharacterBind e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_bind_entry.id)); - insert_values.push_back(std::to_string(character_bind_entry.slot)); - insert_values.push_back(std::to_string(character_bind_entry.zone_id)); - insert_values.push_back(std::to_string(character_bind_entry.instance_id)); - insert_values.push_back(std::to_string(character_bind_entry.x)); - insert_values.push_back(std::to_string(character_bind_entry.y)); - insert_values.push_back(std::to_string(character_bind_entry.z)); - insert_values.push_back(std::to_string(character_bind_entry.heading)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_bind_entry.id = results.LastInsertedID(); - return character_bind_entry; + e.id = results.LastInsertedID(); + return e; } - character_bind_entry = NewEntity(); + e = NewEntity(); - return character_bind_entry; + return e; } static int InsertMany( Database& db, - std::vector character_bind_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_bind_entry: character_bind_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_bind_entry.id)); - insert_values.push_back(std::to_string(character_bind_entry.slot)); - insert_values.push_back(std::to_string(character_bind_entry.zone_id)); - insert_values.push_back(std::to_string(character_bind_entry.instance_id)); - insert_values.push_back(std::to_string(character_bind_entry.x)); - insert_values.push_back(std::to_string(character_bind_entry.y)); - insert_values.push_back(std::to_string(character_bind_entry.z)); - insert_values.push_back(std::to_string(character_bind_entry.heading)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -287,24 +287,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterBind entry{}; + CharacterBind e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.zone_id = atoi(row[2]); - entry.instance_id = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(atoi(row[1])); + e.zone_id = static_cast(strtoul(row[2], nullptr, 10)); + e.instance_id = static_cast(strtoul(row[3], nullptr, 10)); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -319,24 +319,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterBind entry{}; + CharacterBind e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.zone_id = atoi(row[2]); - entry.instance_id = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(atoi(row[1])); + e.zone_id = static_cast(strtoul(row[2], nullptr, 10)); + e.instance_id = static_cast(strtoul(row[3], nullptr, 10)); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -361,6 +361,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H diff --git a/common/repositories/base/base_character_buffs_repository.h b/common/repositories/base/base_character_buffs_repository.h index 8205dac53..e4de463a3 100644 --- a/common/repositories/base/base_character_buffs_repository.h +++ b/common/repositories/base/base_character_buffs_repository.h @@ -13,29 +13,29 @@ #define EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterBuffsRepository { public: struct CharacterBuffs { - int character_id; - int slot_id; - int spell_id; - int caster_level; + uint32_t character_id; + uint8_t slot_id; + uint16_t spell_id; + uint8_t caster_level; std::string caster_name; - int ticsremaining; - int counters; - int numhits; - int melee_rune; - int magic_rune; - int persistent; - int dot_rune; - int caston_x; - int caston_y; - int caston_z; - int ExtraDIChance; - int instrument_mod; + int32_t ticsremaining; + uint32_t counters; + uint32_t numhits; + uint32_t melee_rune; + uint32_t magic_rune; + uint8_t persistent; + int32_t dot_rune; + int32_t caston_x; + int32_t caston_y; + int32_t caston_z; + int32_t ExtraDIChance; + int32_t instrument_mod; }; static std::string PrimaryKey() @@ -91,12 +91,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -124,30 +124,30 @@ public: static CharacterBuffs NewEntity() { - CharacterBuffs entry{}; + CharacterBuffs e{}; - entry.character_id = 0; - entry.slot_id = 0; - entry.spell_id = 0; - entry.caster_level = 0; - entry.caster_name = ""; - entry.ticsremaining = 0; - entry.counters = 0; - entry.numhits = 0; - entry.melee_rune = 0; - entry.magic_rune = 0; - entry.persistent = 0; - entry.dot_rune = 0; - entry.caston_x = 0; - entry.caston_y = 0; - entry.caston_z = 0; - entry.ExtraDIChance = 0; - entry.instrument_mod = 10; + e.character_id = 0; + e.slot_id = 0; + e.spell_id = 0; + e.caster_level = 0; + e.caster_name = ""; + e.ticsremaining = 0; + e.counters = 0; + e.numhits = 0; + e.melee_rune = 0; + e.magic_rune = 0; + e.persistent = 0; + e.dot_rune = 0; + e.caston_x = 0; + e.caston_y = 0; + e.caston_z = 0; + e.ExtraDIChance = 0; + e.instrument_mod = 10; - return entry; + return e; } - static CharacterBuffs GetCharacterBuffsEntry( + static CharacterBuffs GetCharacterBuffs( const std::vector &character_buffss, int character_buffs_id ) @@ -176,27 +176,27 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterBuffs entry{}; + CharacterBuffs e{}; - entry.character_id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); - entry.caster_level = atoi(row[3]); - entry.caster_name = row[4] ? row[4] : ""; - entry.ticsremaining = atoi(row[5]); - entry.counters = atoi(row[6]); - entry.numhits = atoi(row[7]); - entry.melee_rune = atoi(row[8]); - entry.magic_rune = atoi(row[9]); - entry.persistent = atoi(row[10]); - entry.dot_rune = atoi(row[11]); - entry.caston_x = atoi(row[12]); - entry.caston_y = atoi(row[13]); - entry.caston_z = atoi(row[14]); - entry.ExtraDIChance = atoi(row[15]); - entry.instrument_mod = atoi(row[16]); + e.character_id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.caster_name = row[4] ? row[4] : ""; + e.ticsremaining = static_cast(atoi(row[5])); + e.counters = static_cast(strtoul(row[6], nullptr, 10)); + e.numhits = static_cast(strtoul(row[7], nullptr, 10)); + e.melee_rune = static_cast(strtoul(row[8], nullptr, 10)); + e.magic_rune = static_cast(strtoul(row[9], nullptr, 10)); + e.persistent = static_cast(strtoul(row[10], nullptr, 10)); + e.dot_rune = static_cast(atoi(row[11])); + e.caston_x = static_cast(atoi(row[12])); + e.caston_y = static_cast(atoi(row[13])); + e.caston_z = static_cast(atoi(row[14])); + e.ExtraDIChance = static_cast(atoi(row[15])); + e.instrument_mod = static_cast(atoi(row[16])); - return entry; + return e; } return NewEntity(); @@ -221,38 +221,38 @@ public: static int UpdateOne( Database& db, - CharacterBuffs character_buffs_entry + const CharacterBuffs &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_buffs_entry.character_id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_buffs_entry.slot_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_buffs_entry.spell_id)); - update_values.push_back(columns[3] + " = " + std::to_string(character_buffs_entry.caster_level)); - update_values.push_back(columns[4] + " = '" + EscapeString(character_buffs_entry.caster_name) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(character_buffs_entry.ticsremaining)); - update_values.push_back(columns[6] + " = " + std::to_string(character_buffs_entry.counters)); - update_values.push_back(columns[7] + " = " + std::to_string(character_buffs_entry.numhits)); - update_values.push_back(columns[8] + " = " + std::to_string(character_buffs_entry.melee_rune)); - update_values.push_back(columns[9] + " = " + std::to_string(character_buffs_entry.magic_rune)); - update_values.push_back(columns[10] + " = " + std::to_string(character_buffs_entry.persistent)); - update_values.push_back(columns[11] + " = " + std::to_string(character_buffs_entry.dot_rune)); - update_values.push_back(columns[12] + " = " + std::to_string(character_buffs_entry.caston_x)); - update_values.push_back(columns[13] + " = " + std::to_string(character_buffs_entry.caston_y)); - update_values.push_back(columns[14] + " = " + std::to_string(character_buffs_entry.caston_z)); - update_values.push_back(columns[15] + " = " + std::to_string(character_buffs_entry.ExtraDIChance)); - update_values.push_back(columns[16] + " = " + std::to_string(character_buffs_entry.instrument_mod)); + v.push_back(columns[0] + " = " + std::to_string(e.character_id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[3] + " = " + std::to_string(e.caster_level)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.caster_name) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.ticsremaining)); + v.push_back(columns[6] + " = " + std::to_string(e.counters)); + v.push_back(columns[7] + " = " + std::to_string(e.numhits)); + v.push_back(columns[8] + " = " + std::to_string(e.melee_rune)); + v.push_back(columns[9] + " = " + std::to_string(e.magic_rune)); + v.push_back(columns[10] + " = " + std::to_string(e.persistent)); + v.push_back(columns[11] + " = " + std::to_string(e.dot_rune)); + v.push_back(columns[12] + " = " + std::to_string(e.caston_x)); + v.push_back(columns[13] + " = " + std::to_string(e.caston_y)); + v.push_back(columns[14] + " = " + std::to_string(e.caston_z)); + v.push_back(columns[15] + " = " + std::to_string(e.ExtraDIChance)); + v.push_back(columns[16] + " = " + std::to_string(e.instrument_mod)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_buffs_entry.character_id + e.character_id ) ); @@ -261,85 +261,85 @@ public: static CharacterBuffs InsertOne( Database& db, - CharacterBuffs character_buffs_entry + CharacterBuffs e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_buffs_entry.character_id)); - insert_values.push_back(std::to_string(character_buffs_entry.slot_id)); - insert_values.push_back(std::to_string(character_buffs_entry.spell_id)); - insert_values.push_back(std::to_string(character_buffs_entry.caster_level)); - insert_values.push_back("'" + EscapeString(character_buffs_entry.caster_name) + "'"); - insert_values.push_back(std::to_string(character_buffs_entry.ticsremaining)); - insert_values.push_back(std::to_string(character_buffs_entry.counters)); - insert_values.push_back(std::to_string(character_buffs_entry.numhits)); - insert_values.push_back(std::to_string(character_buffs_entry.melee_rune)); - insert_values.push_back(std::to_string(character_buffs_entry.magic_rune)); - insert_values.push_back(std::to_string(character_buffs_entry.persistent)); - insert_values.push_back(std::to_string(character_buffs_entry.dot_rune)); - insert_values.push_back(std::to_string(character_buffs_entry.caston_x)); - insert_values.push_back(std::to_string(character_buffs_entry.caston_y)); - insert_values.push_back(std::to_string(character_buffs_entry.caston_z)); - insert_values.push_back(std::to_string(character_buffs_entry.ExtraDIChance)); - insert_values.push_back(std::to_string(character_buffs_entry.instrument_mod)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back("'" + Strings::Escape(e.caster_name) + "'"); + v.push_back(std::to_string(e.ticsremaining)); + v.push_back(std::to_string(e.counters)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.melee_rune)); + v.push_back(std::to_string(e.magic_rune)); + v.push_back(std::to_string(e.persistent)); + v.push_back(std::to_string(e.dot_rune)); + v.push_back(std::to_string(e.caston_x)); + v.push_back(std::to_string(e.caston_y)); + v.push_back(std::to_string(e.caston_z)); + v.push_back(std::to_string(e.ExtraDIChance)); + v.push_back(std::to_string(e.instrument_mod)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_buffs_entry.character_id = results.LastInsertedID(); - return character_buffs_entry; + e.character_id = results.LastInsertedID(); + return e; } - character_buffs_entry = NewEntity(); + e = NewEntity(); - return character_buffs_entry; + return e; } static int InsertMany( Database& db, - std::vector character_buffs_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_buffs_entry: character_buffs_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_buffs_entry.character_id)); - insert_values.push_back(std::to_string(character_buffs_entry.slot_id)); - insert_values.push_back(std::to_string(character_buffs_entry.spell_id)); - insert_values.push_back(std::to_string(character_buffs_entry.caster_level)); - insert_values.push_back("'" + EscapeString(character_buffs_entry.caster_name) + "'"); - insert_values.push_back(std::to_string(character_buffs_entry.ticsremaining)); - insert_values.push_back(std::to_string(character_buffs_entry.counters)); - insert_values.push_back(std::to_string(character_buffs_entry.numhits)); - insert_values.push_back(std::to_string(character_buffs_entry.melee_rune)); - insert_values.push_back(std::to_string(character_buffs_entry.magic_rune)); - insert_values.push_back(std::to_string(character_buffs_entry.persistent)); - insert_values.push_back(std::to_string(character_buffs_entry.dot_rune)); - insert_values.push_back(std::to_string(character_buffs_entry.caston_x)); - insert_values.push_back(std::to_string(character_buffs_entry.caston_y)); - insert_values.push_back(std::to_string(character_buffs_entry.caston_z)); - insert_values.push_back(std::to_string(character_buffs_entry.ExtraDIChance)); - insert_values.push_back(std::to_string(character_buffs_entry.instrument_mod)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back("'" + Strings::Escape(e.caster_name) + "'"); + v.push_back(std::to_string(e.ticsremaining)); + v.push_back(std::to_string(e.counters)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.melee_rune)); + v.push_back(std::to_string(e.magic_rune)); + v.push_back(std::to_string(e.persistent)); + v.push_back(std::to_string(e.dot_rune)); + v.push_back(std::to_string(e.caston_x)); + v.push_back(std::to_string(e.caston_y)); + v.push_back(std::to_string(e.caston_z)); + v.push_back(std::to_string(e.ExtraDIChance)); + v.push_back(std::to_string(e.instrument_mod)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -360,33 +360,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterBuffs entry{}; + CharacterBuffs e{}; - entry.character_id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); - entry.caster_level = atoi(row[3]); - entry.caster_name = row[4] ? row[4] : ""; - entry.ticsremaining = atoi(row[5]); - entry.counters = atoi(row[6]); - entry.numhits = atoi(row[7]); - entry.melee_rune = atoi(row[8]); - entry.magic_rune = atoi(row[9]); - entry.persistent = atoi(row[10]); - entry.dot_rune = atoi(row[11]); - entry.caston_x = atoi(row[12]); - entry.caston_y = atoi(row[13]); - entry.caston_z = atoi(row[14]); - entry.ExtraDIChance = atoi(row[15]); - entry.instrument_mod = atoi(row[16]); + e.character_id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.caster_name = row[4] ? row[4] : ""; + e.ticsremaining = static_cast(atoi(row[5])); + e.counters = static_cast(strtoul(row[6], nullptr, 10)); + e.numhits = static_cast(strtoul(row[7], nullptr, 10)); + e.melee_rune = static_cast(strtoul(row[8], nullptr, 10)); + e.magic_rune = static_cast(strtoul(row[9], nullptr, 10)); + e.persistent = static_cast(strtoul(row[10], nullptr, 10)); + e.dot_rune = static_cast(atoi(row[11])); + e.caston_x = static_cast(atoi(row[12])); + e.caston_y = static_cast(atoi(row[13])); + e.caston_z = static_cast(atoi(row[14])); + e.ExtraDIChance = static_cast(atoi(row[15])); + e.instrument_mod = static_cast(atoi(row[16])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -401,33 +401,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterBuffs entry{}; + CharacterBuffs e{}; - entry.character_id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); - entry.caster_level = atoi(row[3]); - entry.caster_name = row[4] ? row[4] : ""; - entry.ticsremaining = atoi(row[5]); - entry.counters = atoi(row[6]); - entry.numhits = atoi(row[7]); - entry.melee_rune = atoi(row[8]); - entry.magic_rune = atoi(row[9]); - entry.persistent = atoi(row[10]); - entry.dot_rune = atoi(row[11]); - entry.caston_x = atoi(row[12]); - entry.caston_y = atoi(row[13]); - entry.caston_z = atoi(row[14]); - entry.ExtraDIChance = atoi(row[15]); - entry.instrument_mod = atoi(row[16]); + e.character_id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.caster_level = static_cast(strtoul(row[3], nullptr, 10)); + e.caster_name = row[4] ? row[4] : ""; + e.ticsremaining = static_cast(atoi(row[5])); + e.counters = static_cast(strtoul(row[6], nullptr, 10)); + e.numhits = static_cast(strtoul(row[7], nullptr, 10)); + e.melee_rune = static_cast(strtoul(row[8], nullptr, 10)); + e.magic_rune = static_cast(strtoul(row[9], nullptr, 10)); + e.persistent = static_cast(strtoul(row[10], nullptr, 10)); + e.dot_rune = static_cast(atoi(row[11])); + e.caston_x = static_cast(atoi(row[12])); + e.caston_y = static_cast(atoi(row[13])); + e.caston_z = static_cast(atoi(row[14])); + e.ExtraDIChance = static_cast(atoi(row[15])); + e.instrument_mod = static_cast(atoi(row[16])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -452,6 +452,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_character_corpse_items_repository.h b/common/repositories/base/base_character_corpse_items_repository.h index b12e4c95a..fbee91a78 100644 --- a/common/repositories/base/base_character_corpse_items_repository.h +++ b/common/repositories/base/base_character_corpse_items_repository.h @@ -13,23 +13,23 @@ #define EQEMU_BASE_CHARACTER_CORPSE_ITEMS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterCorpseItemsRepository { public: struct CharacterCorpseItems { - int corpse_id; - int equip_slot; - int item_id; - int charges; - int aug_1; - int aug_2; - int aug_3; - int aug_4; - int aug_5; - int aug_6; - int attuned; + uint32_t corpse_id; + uint32_t equip_slot; + uint32_t item_id; + uint32_t charges; + uint32_t aug_1; + uint32_t aug_2; + uint32_t aug_3; + uint32_t aug_4; + uint32_t aug_5; + int32_t aug_6; + int16_t attuned; }; static std::string PrimaryKey() @@ -73,12 +73,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -106,24 +106,24 @@ public: static CharacterCorpseItems NewEntity() { - CharacterCorpseItems entry{}; + CharacterCorpseItems e{}; - entry.corpse_id = 0; - entry.equip_slot = 0; - entry.item_id = 0; - entry.charges = 0; - entry.aug_1 = 0; - entry.aug_2 = 0; - entry.aug_3 = 0; - entry.aug_4 = 0; - entry.aug_5 = 0; - entry.aug_6 = 0; - entry.attuned = 0; + e.corpse_id = 0; + e.equip_slot = 0; + e.item_id = 0; + e.charges = 0; + e.aug_1 = 0; + e.aug_2 = 0; + e.aug_3 = 0; + e.aug_4 = 0; + e.aug_5 = 0; + e.aug_6 = 0; + e.attuned = 0; - return entry; + return e; } - static CharacterCorpseItems GetCharacterCorpseItemsEntry( + static CharacterCorpseItems GetCharacterCorpseItems( const std::vector &character_corpse_itemss, int character_corpse_items_id ) @@ -152,21 +152,21 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterCorpseItems entry{}; + CharacterCorpseItems e{}; - entry.corpse_id = atoi(row[0]); - entry.equip_slot = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.aug_1 = atoi(row[4]); - entry.aug_2 = atoi(row[5]); - entry.aug_3 = atoi(row[6]); - entry.aug_4 = atoi(row[7]); - entry.aug_5 = atoi(row[8]); - entry.aug_6 = atoi(row[9]); - entry.attuned = atoi(row[10]); + e.corpse_id = static_cast(strtoul(row[0], nullptr, 10)); + e.equip_slot = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.aug_1 = static_cast(strtoul(row[4], nullptr, 10)); + e.aug_2 = static_cast(strtoul(row[5], nullptr, 10)); + e.aug_3 = static_cast(strtoul(row[6], nullptr, 10)); + e.aug_4 = static_cast(strtoul(row[7], nullptr, 10)); + e.aug_5 = static_cast(strtoul(row[8], nullptr, 10)); + e.aug_6 = static_cast(atoi(row[9])); + e.attuned = static_cast(atoi(row[10])); - return entry; + return e; } return NewEntity(); @@ -191,32 +191,32 @@ public: static int UpdateOne( Database& db, - CharacterCorpseItems character_corpse_items_entry + const CharacterCorpseItems &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_corpse_items_entry.corpse_id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_corpse_items_entry.equip_slot)); - update_values.push_back(columns[2] + " = " + std::to_string(character_corpse_items_entry.item_id)); - update_values.push_back(columns[3] + " = " + std::to_string(character_corpse_items_entry.charges)); - update_values.push_back(columns[4] + " = " + std::to_string(character_corpse_items_entry.aug_1)); - update_values.push_back(columns[5] + " = " + std::to_string(character_corpse_items_entry.aug_2)); - update_values.push_back(columns[6] + " = " + std::to_string(character_corpse_items_entry.aug_3)); - update_values.push_back(columns[7] + " = " + std::to_string(character_corpse_items_entry.aug_4)); - update_values.push_back(columns[8] + " = " + std::to_string(character_corpse_items_entry.aug_5)); - update_values.push_back(columns[9] + " = " + std::to_string(character_corpse_items_entry.aug_6)); - update_values.push_back(columns[10] + " = " + std::to_string(character_corpse_items_entry.attuned)); + v.push_back(columns[0] + " = " + std::to_string(e.corpse_id)); + v.push_back(columns[1] + " = " + std::to_string(e.equip_slot)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); + v.push_back(columns[4] + " = " + std::to_string(e.aug_1)); + v.push_back(columns[5] + " = " + std::to_string(e.aug_2)); + v.push_back(columns[6] + " = " + std::to_string(e.aug_3)); + v.push_back(columns[7] + " = " + std::to_string(e.aug_4)); + v.push_back(columns[8] + " = " + std::to_string(e.aug_5)); + v.push_back(columns[9] + " = " + std::to_string(e.aug_6)); + v.push_back(columns[10] + " = " + std::to_string(e.attuned)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_corpse_items_entry.corpse_id + e.corpse_id ) ); @@ -225,73 +225,73 @@ public: static CharacterCorpseItems InsertOne( Database& db, - CharacterCorpseItems character_corpse_items_entry + CharacterCorpseItems e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_corpse_items_entry.corpse_id)); - insert_values.push_back(std::to_string(character_corpse_items_entry.equip_slot)); - insert_values.push_back(std::to_string(character_corpse_items_entry.item_id)); - insert_values.push_back(std::to_string(character_corpse_items_entry.charges)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_1)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_2)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_3)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_4)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_5)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_6)); - insert_values.push_back(std::to_string(character_corpse_items_entry.attuned)); + v.push_back(std::to_string(e.corpse_id)); + v.push_back(std::to_string(e.equip_slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.aug_1)); + v.push_back(std::to_string(e.aug_2)); + v.push_back(std::to_string(e.aug_3)); + v.push_back(std::to_string(e.aug_4)); + v.push_back(std::to_string(e.aug_5)); + v.push_back(std::to_string(e.aug_6)); + v.push_back(std::to_string(e.attuned)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_corpse_items_entry.corpse_id = results.LastInsertedID(); - return character_corpse_items_entry; + e.corpse_id = results.LastInsertedID(); + return e; } - character_corpse_items_entry = NewEntity(); + e = NewEntity(); - return character_corpse_items_entry; + return e; } static int InsertMany( Database& db, - std::vector character_corpse_items_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_corpse_items_entry: character_corpse_items_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_corpse_items_entry.corpse_id)); - insert_values.push_back(std::to_string(character_corpse_items_entry.equip_slot)); - insert_values.push_back(std::to_string(character_corpse_items_entry.item_id)); - insert_values.push_back(std::to_string(character_corpse_items_entry.charges)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_1)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_2)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_3)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_4)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_5)); - insert_values.push_back(std::to_string(character_corpse_items_entry.aug_6)); - insert_values.push_back(std::to_string(character_corpse_items_entry.attuned)); + v.push_back(std::to_string(e.corpse_id)); + v.push_back(std::to_string(e.equip_slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.aug_1)); + v.push_back(std::to_string(e.aug_2)); + v.push_back(std::to_string(e.aug_3)); + v.push_back(std::to_string(e.aug_4)); + v.push_back(std::to_string(e.aug_5)); + v.push_back(std::to_string(e.aug_6)); + v.push_back(std::to_string(e.attuned)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -312,27 +312,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterCorpseItems entry{}; + CharacterCorpseItems e{}; - entry.corpse_id = atoi(row[0]); - entry.equip_slot = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.aug_1 = atoi(row[4]); - entry.aug_2 = atoi(row[5]); - entry.aug_3 = atoi(row[6]); - entry.aug_4 = atoi(row[7]); - entry.aug_5 = atoi(row[8]); - entry.aug_6 = atoi(row[9]); - entry.attuned = atoi(row[10]); + e.corpse_id = static_cast(strtoul(row[0], nullptr, 10)); + e.equip_slot = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.aug_1 = static_cast(strtoul(row[4], nullptr, 10)); + e.aug_2 = static_cast(strtoul(row[5], nullptr, 10)); + e.aug_3 = static_cast(strtoul(row[6], nullptr, 10)); + e.aug_4 = static_cast(strtoul(row[7], nullptr, 10)); + e.aug_5 = static_cast(strtoul(row[8], nullptr, 10)); + e.aug_6 = static_cast(atoi(row[9])); + e.attuned = static_cast(atoi(row[10])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -347,27 +347,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterCorpseItems entry{}; + CharacterCorpseItems e{}; - entry.corpse_id = atoi(row[0]); - entry.equip_slot = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.aug_1 = atoi(row[4]); - entry.aug_2 = atoi(row[5]); - entry.aug_3 = atoi(row[6]); - entry.aug_4 = atoi(row[7]); - entry.aug_5 = atoi(row[8]); - entry.aug_6 = atoi(row[9]); - entry.attuned = atoi(row[10]); + e.corpse_id = static_cast(strtoul(row[0], nullptr, 10)); + e.equip_slot = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.aug_1 = static_cast(strtoul(row[4], nullptr, 10)); + e.aug_2 = static_cast(strtoul(row[5], nullptr, 10)); + e.aug_3 = static_cast(strtoul(row[6], nullptr, 10)); + e.aug_4 = static_cast(strtoul(row[7], nullptr, 10)); + e.aug_5 = static_cast(strtoul(row[8], nullptr, 10)); + e.aug_6 = static_cast(atoi(row[9])); + e.attuned = static_cast(atoi(row[10])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -392,6 +392,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_CORPSE_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_character_corpses_repository.h b/common/repositories/base/base_character_corpses_repository.h index e44604759..1e4de5d8d 100644 --- a/common/repositories/base/base_character_corpses_repository.h +++ b/common/repositories/base/base_character_corpses_repository.h @@ -13,59 +13,59 @@ #define EQEMU_BASE_CHARACTER_CORPSES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterCorpsesRepository { public: struct CharacterCorpses { - int id; - int charid; + uint32_t id; + uint32_t charid; std::string charname; - int zone_id; - int instance_id; + int16_t zone_id; + uint16_t instance_id; float x; float y; float z; float heading; time_t time_of_death; - int guild_consent_id; - int is_rezzed; - int is_buried; - int was_at_graveyard; - int is_locked; - int exp; - int size; - int level; - int race; - int gender; - int class_; - int deity; - int texture; - int helm_texture; - int copper; - int silver; - int gold; - int platinum; - int hair_color; - int beard_color; - int eye_color_1; - int eye_color_2; - int hair_style; - int face; - int beard; - int drakkin_heritage; - int drakkin_tattoo; - int drakkin_details; - int wc_1; - int wc_2; - int wc_3; - int wc_4; - int wc_5; - int wc_6; - int wc_7; - int wc_8; - int wc_9; + uint32_t guild_consent_id; + uint8_t is_rezzed; + int8_t is_buried; + int8_t was_at_graveyard; + int8_t is_locked; + uint32_t exp; + uint32_t size; + uint32_t level; + uint32_t race; + uint32_t gender; + uint32_t class_; + uint32_t deity; + uint32_t texture; + uint32_t helm_texture; + uint32_t copper; + uint32_t silver; + uint32_t gold; + uint32_t platinum; + uint32_t hair_color; + uint32_t beard_color; + uint32_t eye_color_1; + uint32_t eye_color_2; + uint32_t hair_style; + uint32_t face; + uint32_t beard; + uint32_t drakkin_heritage; + uint32_t drakkin_tattoo; + uint32_t drakkin_details; + uint32_t wc_1; + uint32_t wc_2; + uint32_t wc_3; + uint32_t wc_4; + uint32_t wc_5; + uint32_t wc_6; + uint32_t wc_7; + uint32_t wc_8; + uint32_t wc_9; }; static std::string PrimaryKey() @@ -181,12 +181,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -214,60 +214,60 @@ public: static CharacterCorpses NewEntity() { - CharacterCorpses entry{}; + CharacterCorpses e{}; - entry.id = 0; - entry.charid = 0; - entry.charname = ""; - entry.zone_id = 0; - entry.instance_id = 0; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.heading = 0; - entry.time_of_death = 0; - entry.guild_consent_id = 0; - entry.is_rezzed = 0; - entry.is_buried = 0; - entry.was_at_graveyard = 0; - entry.is_locked = 0; - entry.exp = 0; - entry.size = 0; - entry.level = 0; - entry.race = 0; - entry.gender = 0; - entry.class_ = 0; - entry.deity = 0; - entry.texture = 0; - entry.helm_texture = 0; - entry.copper = 0; - entry.silver = 0; - entry.gold = 0; - entry.platinum = 0; - entry.hair_color = 0; - entry.beard_color = 0; - entry.eye_color_1 = 0; - entry.eye_color_2 = 0; - entry.hair_style = 0; - entry.face = 0; - entry.beard = 0; - entry.drakkin_heritage = 0; - entry.drakkin_tattoo = 0; - entry.drakkin_details = 0; - entry.wc_1 = 0; - entry.wc_2 = 0; - entry.wc_3 = 0; - entry.wc_4 = 0; - entry.wc_5 = 0; - entry.wc_6 = 0; - entry.wc_7 = 0; - entry.wc_8 = 0; - entry.wc_9 = 0; + e.id = 0; + e.charid = 0; + e.charname = ""; + e.zone_id = 0; + e.instance_id = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; + e.time_of_death = 0; + e.guild_consent_id = 0; + e.is_rezzed = 0; + e.is_buried = 0; + e.was_at_graveyard = 0; + e.is_locked = 0; + e.exp = 0; + e.size = 0; + e.level = 0; + e.race = 0; + e.gender = 0; + e.class_ = 0; + e.deity = 0; + e.texture = 0; + e.helm_texture = 0; + e.copper = 0; + e.silver = 0; + e.gold = 0; + e.platinum = 0; + e.hair_color = 0; + e.beard_color = 0; + e.eye_color_1 = 0; + e.eye_color_2 = 0; + e.hair_style = 0; + e.face = 0; + e.beard = 0; + e.drakkin_heritage = 0; + e.drakkin_tattoo = 0; + e.drakkin_details = 0; + e.wc_1 = 0; + e.wc_2 = 0; + e.wc_3 = 0; + e.wc_4 = 0; + e.wc_5 = 0; + e.wc_6 = 0; + e.wc_7 = 0; + e.wc_8 = 0; + e.wc_9 = 0; - return entry; + return e; } - static CharacterCorpses GetCharacterCorpsesEntry( + static CharacterCorpses GetCharacterCorpses( const std::vector &character_corpsess, int character_corpses_id ) @@ -296,57 +296,57 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterCorpses entry{}; + CharacterCorpses e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.charname = row[2] ? row[2] : ""; - entry.zone_id = atoi(row[3]); - entry.instance_id = atoi(row[4]); - entry.x = static_cast(atof(row[5])); - entry.y = static_cast(atof(row[6])); - entry.z = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.time_of_death = strtoll(row[9] ? row[9] : "-1", nullptr, 10); - entry.guild_consent_id = atoi(row[10]); - entry.is_rezzed = atoi(row[11]); - entry.is_buried = atoi(row[12]); - entry.was_at_graveyard = atoi(row[13]); - entry.is_locked = atoi(row[14]); - entry.exp = atoi(row[15]); - entry.size = atoi(row[16]); - entry.level = atoi(row[17]); - entry.race = atoi(row[18]); - entry.gender = atoi(row[19]); - entry.class_ = atoi(row[20]); - entry.deity = atoi(row[21]); - entry.texture = atoi(row[22]); - entry.helm_texture = atoi(row[23]); - entry.copper = atoi(row[24]); - entry.silver = atoi(row[25]); - entry.gold = atoi(row[26]); - entry.platinum = atoi(row[27]); - entry.hair_color = atoi(row[28]); - entry.beard_color = atoi(row[29]); - entry.eye_color_1 = atoi(row[30]); - entry.eye_color_2 = atoi(row[31]); - entry.hair_style = atoi(row[32]); - entry.face = atoi(row[33]); - entry.beard = atoi(row[34]); - entry.drakkin_heritage = atoi(row[35]); - entry.drakkin_tattoo = atoi(row[36]); - entry.drakkin_details = atoi(row[37]); - entry.wc_1 = atoi(row[38]); - entry.wc_2 = atoi(row[39]); - entry.wc_3 = atoi(row[40]); - entry.wc_4 = atoi(row[41]); - entry.wc_5 = atoi(row[42]); - entry.wc_6 = atoi(row[43]); - entry.wc_7 = atoi(row[44]); - entry.wc_8 = atoi(row[45]); - entry.wc_9 = atoi(row[46]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.charname = row[2] ? row[2] : ""; + e.zone_id = static_cast(atoi(row[3])); + e.instance_id = static_cast(strtoul(row[4], nullptr, 10)); + e.x = strtof(row[5], nullptr); + e.y = strtof(row[6], nullptr); + e.z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.time_of_death = strtoll(row[9] ? row[9] : "-1", nullptr, 10); + e.guild_consent_id = static_cast(strtoul(row[10], nullptr, 10)); + e.is_rezzed = static_cast(strtoul(row[11], nullptr, 10)); + e.is_buried = static_cast(atoi(row[12])); + e.was_at_graveyard = static_cast(atoi(row[13])); + e.is_locked = static_cast(atoi(row[14])); + e.exp = static_cast(strtoul(row[15], nullptr, 10)); + e.size = static_cast(strtoul(row[16], nullptr, 10)); + e.level = static_cast(strtoul(row[17], nullptr, 10)); + e.race = static_cast(strtoul(row[18], nullptr, 10)); + e.gender = static_cast(strtoul(row[19], nullptr, 10)); + e.class_ = static_cast(strtoul(row[20], nullptr, 10)); + e.deity = static_cast(strtoul(row[21], nullptr, 10)); + e.texture = static_cast(strtoul(row[22], nullptr, 10)); + e.helm_texture = static_cast(strtoul(row[23], nullptr, 10)); + e.copper = static_cast(strtoul(row[24], nullptr, 10)); + e.silver = static_cast(strtoul(row[25], nullptr, 10)); + e.gold = static_cast(strtoul(row[26], nullptr, 10)); + e.platinum = static_cast(strtoul(row[27], nullptr, 10)); + e.hair_color = static_cast(strtoul(row[28], nullptr, 10)); + e.beard_color = static_cast(strtoul(row[29], nullptr, 10)); + e.eye_color_1 = static_cast(strtoul(row[30], nullptr, 10)); + e.eye_color_2 = static_cast(strtoul(row[31], nullptr, 10)); + e.hair_style = static_cast(strtoul(row[32], nullptr, 10)); + e.face = static_cast(strtoul(row[33], nullptr, 10)); + e.beard = static_cast(strtoul(row[34], nullptr, 10)); + e.drakkin_heritage = static_cast(strtoul(row[35], nullptr, 10)); + e.drakkin_tattoo = static_cast(strtoul(row[36], nullptr, 10)); + e.drakkin_details = static_cast(strtoul(row[37], nullptr, 10)); + e.wc_1 = static_cast(strtoul(row[38], nullptr, 10)); + e.wc_2 = static_cast(strtoul(row[39], nullptr, 10)); + e.wc_3 = static_cast(strtoul(row[40], nullptr, 10)); + e.wc_4 = static_cast(strtoul(row[41], nullptr, 10)); + e.wc_5 = static_cast(strtoul(row[42], nullptr, 10)); + e.wc_6 = static_cast(strtoul(row[43], nullptr, 10)); + e.wc_7 = static_cast(strtoul(row[44], nullptr, 10)); + e.wc_8 = static_cast(strtoul(row[45], nullptr, 10)); + e.wc_9 = static_cast(strtoul(row[46], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -371,67 +371,67 @@ public: static int UpdateOne( Database& db, - CharacterCorpses character_corpses_entry + const CharacterCorpses &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_corpses_entry.charid)); - update_values.push_back(columns[2] + " = '" + EscapeString(character_corpses_entry.charname) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(character_corpses_entry.zone_id)); - update_values.push_back(columns[4] + " = " + std::to_string(character_corpses_entry.instance_id)); - update_values.push_back(columns[5] + " = " + std::to_string(character_corpses_entry.x)); - update_values.push_back(columns[6] + " = " + std::to_string(character_corpses_entry.y)); - update_values.push_back(columns[7] + " = " + std::to_string(character_corpses_entry.z)); - update_values.push_back(columns[8] + " = " + std::to_string(character_corpses_entry.heading)); - update_values.push_back(columns[9] + " = FROM_UNIXTIME(" + (character_corpses_entry.time_of_death > 0 ? std::to_string(character_corpses_entry.time_of_death) : "null") + ")"); - update_values.push_back(columns[10] + " = " + std::to_string(character_corpses_entry.guild_consent_id)); - update_values.push_back(columns[11] + " = " + std::to_string(character_corpses_entry.is_rezzed)); - update_values.push_back(columns[12] + " = " + std::to_string(character_corpses_entry.is_buried)); - update_values.push_back(columns[13] + " = " + std::to_string(character_corpses_entry.was_at_graveyard)); - update_values.push_back(columns[14] + " = " + std::to_string(character_corpses_entry.is_locked)); - update_values.push_back(columns[15] + " = " + std::to_string(character_corpses_entry.exp)); - update_values.push_back(columns[16] + " = " + std::to_string(character_corpses_entry.size)); - update_values.push_back(columns[17] + " = " + std::to_string(character_corpses_entry.level)); - update_values.push_back(columns[18] + " = " + std::to_string(character_corpses_entry.race)); - update_values.push_back(columns[19] + " = " + std::to_string(character_corpses_entry.gender)); - update_values.push_back(columns[20] + " = " + std::to_string(character_corpses_entry.class_)); - update_values.push_back(columns[21] + " = " + std::to_string(character_corpses_entry.deity)); - update_values.push_back(columns[22] + " = " + std::to_string(character_corpses_entry.texture)); - update_values.push_back(columns[23] + " = " + std::to_string(character_corpses_entry.helm_texture)); - update_values.push_back(columns[24] + " = " + std::to_string(character_corpses_entry.copper)); - update_values.push_back(columns[25] + " = " + std::to_string(character_corpses_entry.silver)); - update_values.push_back(columns[26] + " = " + std::to_string(character_corpses_entry.gold)); - update_values.push_back(columns[27] + " = " + std::to_string(character_corpses_entry.platinum)); - update_values.push_back(columns[28] + " = " + std::to_string(character_corpses_entry.hair_color)); - update_values.push_back(columns[29] + " = " + std::to_string(character_corpses_entry.beard_color)); - update_values.push_back(columns[30] + " = " + std::to_string(character_corpses_entry.eye_color_1)); - update_values.push_back(columns[31] + " = " + std::to_string(character_corpses_entry.eye_color_2)); - update_values.push_back(columns[32] + " = " + std::to_string(character_corpses_entry.hair_style)); - update_values.push_back(columns[33] + " = " + std::to_string(character_corpses_entry.face)); - update_values.push_back(columns[34] + " = " + std::to_string(character_corpses_entry.beard)); - update_values.push_back(columns[35] + " = " + std::to_string(character_corpses_entry.drakkin_heritage)); - update_values.push_back(columns[36] + " = " + std::to_string(character_corpses_entry.drakkin_tattoo)); - update_values.push_back(columns[37] + " = " + std::to_string(character_corpses_entry.drakkin_details)); - update_values.push_back(columns[38] + " = " + std::to_string(character_corpses_entry.wc_1)); - update_values.push_back(columns[39] + " = " + std::to_string(character_corpses_entry.wc_2)); - update_values.push_back(columns[40] + " = " + std::to_string(character_corpses_entry.wc_3)); - update_values.push_back(columns[41] + " = " + std::to_string(character_corpses_entry.wc_4)); - update_values.push_back(columns[42] + " = " + std::to_string(character_corpses_entry.wc_5)); - update_values.push_back(columns[43] + " = " + std::to_string(character_corpses_entry.wc_6)); - update_values.push_back(columns[44] + " = " + std::to_string(character_corpses_entry.wc_7)); - update_values.push_back(columns[45] + " = " + std::to_string(character_corpses_entry.wc_8)); - update_values.push_back(columns[46] + " = " + std::to_string(character_corpses_entry.wc_9)); + v.push_back(columns[1] + " = " + std::to_string(e.charid)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.charname) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[4] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[5] + " = " + std::to_string(e.x)); + v.push_back(columns[6] + " = " + std::to_string(e.y)); + v.push_back(columns[7] + " = " + std::to_string(e.z)); + v.push_back(columns[8] + " = " + std::to_string(e.heading)); + v.push_back(columns[9] + " = FROM_UNIXTIME(" + (e.time_of_death > 0 ? std::to_string(e.time_of_death) : "null") + ")"); + v.push_back(columns[10] + " = " + std::to_string(e.guild_consent_id)); + v.push_back(columns[11] + " = " + std::to_string(e.is_rezzed)); + v.push_back(columns[12] + " = " + std::to_string(e.is_buried)); + v.push_back(columns[13] + " = " + std::to_string(e.was_at_graveyard)); + v.push_back(columns[14] + " = " + std::to_string(e.is_locked)); + v.push_back(columns[15] + " = " + std::to_string(e.exp)); + v.push_back(columns[16] + " = " + std::to_string(e.size)); + v.push_back(columns[17] + " = " + std::to_string(e.level)); + v.push_back(columns[18] + " = " + std::to_string(e.race)); + v.push_back(columns[19] + " = " + std::to_string(e.gender)); + v.push_back(columns[20] + " = " + std::to_string(e.class_)); + v.push_back(columns[21] + " = " + std::to_string(e.deity)); + v.push_back(columns[22] + " = " + std::to_string(e.texture)); + v.push_back(columns[23] + " = " + std::to_string(e.helm_texture)); + v.push_back(columns[24] + " = " + std::to_string(e.copper)); + v.push_back(columns[25] + " = " + std::to_string(e.silver)); + v.push_back(columns[26] + " = " + std::to_string(e.gold)); + v.push_back(columns[27] + " = " + std::to_string(e.platinum)); + v.push_back(columns[28] + " = " + std::to_string(e.hair_color)); + v.push_back(columns[29] + " = " + std::to_string(e.beard_color)); + v.push_back(columns[30] + " = " + std::to_string(e.eye_color_1)); + v.push_back(columns[31] + " = " + std::to_string(e.eye_color_2)); + v.push_back(columns[32] + " = " + std::to_string(e.hair_style)); + v.push_back(columns[33] + " = " + std::to_string(e.face)); + v.push_back(columns[34] + " = " + std::to_string(e.beard)); + v.push_back(columns[35] + " = " + std::to_string(e.drakkin_heritage)); + v.push_back(columns[36] + " = " + std::to_string(e.drakkin_tattoo)); + v.push_back(columns[37] + " = " + std::to_string(e.drakkin_details)); + v.push_back(columns[38] + " = " + std::to_string(e.wc_1)); + v.push_back(columns[39] + " = " + std::to_string(e.wc_2)); + v.push_back(columns[40] + " = " + std::to_string(e.wc_3)); + v.push_back(columns[41] + " = " + std::to_string(e.wc_4)); + v.push_back(columns[42] + " = " + std::to_string(e.wc_5)); + v.push_back(columns[43] + " = " + std::to_string(e.wc_6)); + v.push_back(columns[44] + " = " + std::to_string(e.wc_7)); + v.push_back(columns[45] + " = " + std::to_string(e.wc_8)); + v.push_back(columns[46] + " = " + std::to_string(e.wc_9)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_corpses_entry.id + e.id ) ); @@ -440,145 +440,145 @@ public: static CharacterCorpses InsertOne( Database& db, - CharacterCorpses character_corpses_entry + CharacterCorpses e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_corpses_entry.id)); - insert_values.push_back(std::to_string(character_corpses_entry.charid)); - insert_values.push_back("'" + EscapeString(character_corpses_entry.charname) + "'"); - insert_values.push_back(std::to_string(character_corpses_entry.zone_id)); - insert_values.push_back(std::to_string(character_corpses_entry.instance_id)); - insert_values.push_back(std::to_string(character_corpses_entry.x)); - insert_values.push_back(std::to_string(character_corpses_entry.y)); - insert_values.push_back(std::to_string(character_corpses_entry.z)); - insert_values.push_back(std::to_string(character_corpses_entry.heading)); - insert_values.push_back("FROM_UNIXTIME(" + (character_corpses_entry.time_of_death > 0 ? std::to_string(character_corpses_entry.time_of_death) : "null") + ")"); - insert_values.push_back(std::to_string(character_corpses_entry.guild_consent_id)); - insert_values.push_back(std::to_string(character_corpses_entry.is_rezzed)); - insert_values.push_back(std::to_string(character_corpses_entry.is_buried)); - insert_values.push_back(std::to_string(character_corpses_entry.was_at_graveyard)); - insert_values.push_back(std::to_string(character_corpses_entry.is_locked)); - insert_values.push_back(std::to_string(character_corpses_entry.exp)); - insert_values.push_back(std::to_string(character_corpses_entry.size)); - insert_values.push_back(std::to_string(character_corpses_entry.level)); - insert_values.push_back(std::to_string(character_corpses_entry.race)); - insert_values.push_back(std::to_string(character_corpses_entry.gender)); - insert_values.push_back(std::to_string(character_corpses_entry.class_)); - insert_values.push_back(std::to_string(character_corpses_entry.deity)); - insert_values.push_back(std::to_string(character_corpses_entry.texture)); - insert_values.push_back(std::to_string(character_corpses_entry.helm_texture)); - insert_values.push_back(std::to_string(character_corpses_entry.copper)); - insert_values.push_back(std::to_string(character_corpses_entry.silver)); - insert_values.push_back(std::to_string(character_corpses_entry.gold)); - insert_values.push_back(std::to_string(character_corpses_entry.platinum)); - insert_values.push_back(std::to_string(character_corpses_entry.hair_color)); - insert_values.push_back(std::to_string(character_corpses_entry.beard_color)); - insert_values.push_back(std::to_string(character_corpses_entry.eye_color_1)); - insert_values.push_back(std::to_string(character_corpses_entry.eye_color_2)); - insert_values.push_back(std::to_string(character_corpses_entry.hair_style)); - insert_values.push_back(std::to_string(character_corpses_entry.face)); - insert_values.push_back(std::to_string(character_corpses_entry.beard)); - insert_values.push_back(std::to_string(character_corpses_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(character_corpses_entry.drakkin_tattoo)); - insert_values.push_back(std::to_string(character_corpses_entry.drakkin_details)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_1)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_2)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_3)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_4)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_5)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_6)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_7)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_8)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_9)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.charid)); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back("FROM_UNIXTIME(" + (e.time_of_death > 0 ? std::to_string(e.time_of_death) : "null") + ")"); + v.push_back(std::to_string(e.guild_consent_id)); + v.push_back(std::to_string(e.is_rezzed)); + v.push_back(std::to_string(e.is_buried)); + v.push_back(std::to_string(e.was_at_graveyard)); + v.push_back(std::to_string(e.is_locked)); + v.push_back(std::to_string(e.exp)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helm_texture)); + v.push_back(std::to_string(e.copper)); + v.push_back(std::to_string(e.silver)); + v.push_back(std::to_string(e.gold)); + v.push_back(std::to_string(e.platinum)); + v.push_back(std::to_string(e.hair_color)); + v.push_back(std::to_string(e.beard_color)); + v.push_back(std::to_string(e.eye_color_1)); + v.push_back(std::to_string(e.eye_color_2)); + v.push_back(std::to_string(e.hair_style)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.beard)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.wc_1)); + v.push_back(std::to_string(e.wc_2)); + v.push_back(std::to_string(e.wc_3)); + v.push_back(std::to_string(e.wc_4)); + v.push_back(std::to_string(e.wc_5)); + v.push_back(std::to_string(e.wc_6)); + v.push_back(std::to_string(e.wc_7)); + v.push_back(std::to_string(e.wc_8)); + v.push_back(std::to_string(e.wc_9)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_corpses_entry.id = results.LastInsertedID(); - return character_corpses_entry; + e.id = results.LastInsertedID(); + return e; } - character_corpses_entry = NewEntity(); + e = NewEntity(); - return character_corpses_entry; + return e; } static int InsertMany( Database& db, - std::vector character_corpses_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_corpses_entry: character_corpses_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_corpses_entry.id)); - insert_values.push_back(std::to_string(character_corpses_entry.charid)); - insert_values.push_back("'" + EscapeString(character_corpses_entry.charname) + "'"); - insert_values.push_back(std::to_string(character_corpses_entry.zone_id)); - insert_values.push_back(std::to_string(character_corpses_entry.instance_id)); - insert_values.push_back(std::to_string(character_corpses_entry.x)); - insert_values.push_back(std::to_string(character_corpses_entry.y)); - insert_values.push_back(std::to_string(character_corpses_entry.z)); - insert_values.push_back(std::to_string(character_corpses_entry.heading)); - insert_values.push_back("FROM_UNIXTIME(" + (character_corpses_entry.time_of_death > 0 ? std::to_string(character_corpses_entry.time_of_death) : "null") + ")"); - insert_values.push_back(std::to_string(character_corpses_entry.guild_consent_id)); - insert_values.push_back(std::to_string(character_corpses_entry.is_rezzed)); - insert_values.push_back(std::to_string(character_corpses_entry.is_buried)); - insert_values.push_back(std::to_string(character_corpses_entry.was_at_graveyard)); - insert_values.push_back(std::to_string(character_corpses_entry.is_locked)); - insert_values.push_back(std::to_string(character_corpses_entry.exp)); - insert_values.push_back(std::to_string(character_corpses_entry.size)); - insert_values.push_back(std::to_string(character_corpses_entry.level)); - insert_values.push_back(std::to_string(character_corpses_entry.race)); - insert_values.push_back(std::to_string(character_corpses_entry.gender)); - insert_values.push_back(std::to_string(character_corpses_entry.class_)); - insert_values.push_back(std::to_string(character_corpses_entry.deity)); - insert_values.push_back(std::to_string(character_corpses_entry.texture)); - insert_values.push_back(std::to_string(character_corpses_entry.helm_texture)); - insert_values.push_back(std::to_string(character_corpses_entry.copper)); - insert_values.push_back(std::to_string(character_corpses_entry.silver)); - insert_values.push_back(std::to_string(character_corpses_entry.gold)); - insert_values.push_back(std::to_string(character_corpses_entry.platinum)); - insert_values.push_back(std::to_string(character_corpses_entry.hair_color)); - insert_values.push_back(std::to_string(character_corpses_entry.beard_color)); - insert_values.push_back(std::to_string(character_corpses_entry.eye_color_1)); - insert_values.push_back(std::to_string(character_corpses_entry.eye_color_2)); - insert_values.push_back(std::to_string(character_corpses_entry.hair_style)); - insert_values.push_back(std::to_string(character_corpses_entry.face)); - insert_values.push_back(std::to_string(character_corpses_entry.beard)); - insert_values.push_back(std::to_string(character_corpses_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(character_corpses_entry.drakkin_tattoo)); - insert_values.push_back(std::to_string(character_corpses_entry.drakkin_details)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_1)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_2)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_3)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_4)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_5)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_6)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_7)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_8)); - insert_values.push_back(std::to_string(character_corpses_entry.wc_9)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.charid)); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back("FROM_UNIXTIME(" + (e.time_of_death > 0 ? std::to_string(e.time_of_death) : "null") + ")"); + v.push_back(std::to_string(e.guild_consent_id)); + v.push_back(std::to_string(e.is_rezzed)); + v.push_back(std::to_string(e.is_buried)); + v.push_back(std::to_string(e.was_at_graveyard)); + v.push_back(std::to_string(e.is_locked)); + v.push_back(std::to_string(e.exp)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helm_texture)); + v.push_back(std::to_string(e.copper)); + v.push_back(std::to_string(e.silver)); + v.push_back(std::to_string(e.gold)); + v.push_back(std::to_string(e.platinum)); + v.push_back(std::to_string(e.hair_color)); + v.push_back(std::to_string(e.beard_color)); + v.push_back(std::to_string(e.eye_color_1)); + v.push_back(std::to_string(e.eye_color_2)); + v.push_back(std::to_string(e.hair_style)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.beard)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.wc_1)); + v.push_back(std::to_string(e.wc_2)); + v.push_back(std::to_string(e.wc_3)); + v.push_back(std::to_string(e.wc_4)); + v.push_back(std::to_string(e.wc_5)); + v.push_back(std::to_string(e.wc_6)); + v.push_back(std::to_string(e.wc_7)); + v.push_back(std::to_string(e.wc_8)); + v.push_back(std::to_string(e.wc_9)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -599,63 +599,63 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterCorpses entry{}; + CharacterCorpses e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.charname = row[2] ? row[2] : ""; - entry.zone_id = atoi(row[3]); - entry.instance_id = atoi(row[4]); - entry.x = static_cast(atof(row[5])); - entry.y = static_cast(atof(row[6])); - entry.z = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.time_of_death = strtoll(row[9] ? row[9] : "-1", nullptr, 10); - entry.guild_consent_id = atoi(row[10]); - entry.is_rezzed = atoi(row[11]); - entry.is_buried = atoi(row[12]); - entry.was_at_graveyard = atoi(row[13]); - entry.is_locked = atoi(row[14]); - entry.exp = atoi(row[15]); - entry.size = atoi(row[16]); - entry.level = atoi(row[17]); - entry.race = atoi(row[18]); - entry.gender = atoi(row[19]); - entry.class_ = atoi(row[20]); - entry.deity = atoi(row[21]); - entry.texture = atoi(row[22]); - entry.helm_texture = atoi(row[23]); - entry.copper = atoi(row[24]); - entry.silver = atoi(row[25]); - entry.gold = atoi(row[26]); - entry.platinum = atoi(row[27]); - entry.hair_color = atoi(row[28]); - entry.beard_color = atoi(row[29]); - entry.eye_color_1 = atoi(row[30]); - entry.eye_color_2 = atoi(row[31]); - entry.hair_style = atoi(row[32]); - entry.face = atoi(row[33]); - entry.beard = atoi(row[34]); - entry.drakkin_heritage = atoi(row[35]); - entry.drakkin_tattoo = atoi(row[36]); - entry.drakkin_details = atoi(row[37]); - entry.wc_1 = atoi(row[38]); - entry.wc_2 = atoi(row[39]); - entry.wc_3 = atoi(row[40]); - entry.wc_4 = atoi(row[41]); - entry.wc_5 = atoi(row[42]); - entry.wc_6 = atoi(row[43]); - entry.wc_7 = atoi(row[44]); - entry.wc_8 = atoi(row[45]); - entry.wc_9 = atoi(row[46]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.charname = row[2] ? row[2] : ""; + e.zone_id = static_cast(atoi(row[3])); + e.instance_id = static_cast(strtoul(row[4], nullptr, 10)); + e.x = strtof(row[5], nullptr); + e.y = strtof(row[6], nullptr); + e.z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.time_of_death = strtoll(row[9] ? row[9] : "-1", nullptr, 10); + e.guild_consent_id = static_cast(strtoul(row[10], nullptr, 10)); + e.is_rezzed = static_cast(strtoul(row[11], nullptr, 10)); + e.is_buried = static_cast(atoi(row[12])); + e.was_at_graveyard = static_cast(atoi(row[13])); + e.is_locked = static_cast(atoi(row[14])); + e.exp = static_cast(strtoul(row[15], nullptr, 10)); + e.size = static_cast(strtoul(row[16], nullptr, 10)); + e.level = static_cast(strtoul(row[17], nullptr, 10)); + e.race = static_cast(strtoul(row[18], nullptr, 10)); + e.gender = static_cast(strtoul(row[19], nullptr, 10)); + e.class_ = static_cast(strtoul(row[20], nullptr, 10)); + e.deity = static_cast(strtoul(row[21], nullptr, 10)); + e.texture = static_cast(strtoul(row[22], nullptr, 10)); + e.helm_texture = static_cast(strtoul(row[23], nullptr, 10)); + e.copper = static_cast(strtoul(row[24], nullptr, 10)); + e.silver = static_cast(strtoul(row[25], nullptr, 10)); + e.gold = static_cast(strtoul(row[26], nullptr, 10)); + e.platinum = static_cast(strtoul(row[27], nullptr, 10)); + e.hair_color = static_cast(strtoul(row[28], nullptr, 10)); + e.beard_color = static_cast(strtoul(row[29], nullptr, 10)); + e.eye_color_1 = static_cast(strtoul(row[30], nullptr, 10)); + e.eye_color_2 = static_cast(strtoul(row[31], nullptr, 10)); + e.hair_style = static_cast(strtoul(row[32], nullptr, 10)); + e.face = static_cast(strtoul(row[33], nullptr, 10)); + e.beard = static_cast(strtoul(row[34], nullptr, 10)); + e.drakkin_heritage = static_cast(strtoul(row[35], nullptr, 10)); + e.drakkin_tattoo = static_cast(strtoul(row[36], nullptr, 10)); + e.drakkin_details = static_cast(strtoul(row[37], nullptr, 10)); + e.wc_1 = static_cast(strtoul(row[38], nullptr, 10)); + e.wc_2 = static_cast(strtoul(row[39], nullptr, 10)); + e.wc_3 = static_cast(strtoul(row[40], nullptr, 10)); + e.wc_4 = static_cast(strtoul(row[41], nullptr, 10)); + e.wc_5 = static_cast(strtoul(row[42], nullptr, 10)); + e.wc_6 = static_cast(strtoul(row[43], nullptr, 10)); + e.wc_7 = static_cast(strtoul(row[44], nullptr, 10)); + e.wc_8 = static_cast(strtoul(row[45], nullptr, 10)); + e.wc_9 = static_cast(strtoul(row[46], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -670,63 +670,63 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterCorpses entry{}; + CharacterCorpses e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.charname = row[2] ? row[2] : ""; - entry.zone_id = atoi(row[3]); - entry.instance_id = atoi(row[4]); - entry.x = static_cast(atof(row[5])); - entry.y = static_cast(atof(row[6])); - entry.z = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.time_of_death = strtoll(row[9] ? row[9] : "-1", nullptr, 10); - entry.guild_consent_id = atoi(row[10]); - entry.is_rezzed = atoi(row[11]); - entry.is_buried = atoi(row[12]); - entry.was_at_graveyard = atoi(row[13]); - entry.is_locked = atoi(row[14]); - entry.exp = atoi(row[15]); - entry.size = atoi(row[16]); - entry.level = atoi(row[17]); - entry.race = atoi(row[18]); - entry.gender = atoi(row[19]); - entry.class_ = atoi(row[20]); - entry.deity = atoi(row[21]); - entry.texture = atoi(row[22]); - entry.helm_texture = atoi(row[23]); - entry.copper = atoi(row[24]); - entry.silver = atoi(row[25]); - entry.gold = atoi(row[26]); - entry.platinum = atoi(row[27]); - entry.hair_color = atoi(row[28]); - entry.beard_color = atoi(row[29]); - entry.eye_color_1 = atoi(row[30]); - entry.eye_color_2 = atoi(row[31]); - entry.hair_style = atoi(row[32]); - entry.face = atoi(row[33]); - entry.beard = atoi(row[34]); - entry.drakkin_heritage = atoi(row[35]); - entry.drakkin_tattoo = atoi(row[36]); - entry.drakkin_details = atoi(row[37]); - entry.wc_1 = atoi(row[38]); - entry.wc_2 = atoi(row[39]); - entry.wc_3 = atoi(row[40]); - entry.wc_4 = atoi(row[41]); - entry.wc_5 = atoi(row[42]); - entry.wc_6 = atoi(row[43]); - entry.wc_7 = atoi(row[44]); - entry.wc_8 = atoi(row[45]); - entry.wc_9 = atoi(row[46]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.charname = row[2] ? row[2] : ""; + e.zone_id = static_cast(atoi(row[3])); + e.instance_id = static_cast(strtoul(row[4], nullptr, 10)); + e.x = strtof(row[5], nullptr); + e.y = strtof(row[6], nullptr); + e.z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.time_of_death = strtoll(row[9] ? row[9] : "-1", nullptr, 10); + e.guild_consent_id = static_cast(strtoul(row[10], nullptr, 10)); + e.is_rezzed = static_cast(strtoul(row[11], nullptr, 10)); + e.is_buried = static_cast(atoi(row[12])); + e.was_at_graveyard = static_cast(atoi(row[13])); + e.is_locked = static_cast(atoi(row[14])); + e.exp = static_cast(strtoul(row[15], nullptr, 10)); + e.size = static_cast(strtoul(row[16], nullptr, 10)); + e.level = static_cast(strtoul(row[17], nullptr, 10)); + e.race = static_cast(strtoul(row[18], nullptr, 10)); + e.gender = static_cast(strtoul(row[19], nullptr, 10)); + e.class_ = static_cast(strtoul(row[20], nullptr, 10)); + e.deity = static_cast(strtoul(row[21], nullptr, 10)); + e.texture = static_cast(strtoul(row[22], nullptr, 10)); + e.helm_texture = static_cast(strtoul(row[23], nullptr, 10)); + e.copper = static_cast(strtoul(row[24], nullptr, 10)); + e.silver = static_cast(strtoul(row[25], nullptr, 10)); + e.gold = static_cast(strtoul(row[26], nullptr, 10)); + e.platinum = static_cast(strtoul(row[27], nullptr, 10)); + e.hair_color = static_cast(strtoul(row[28], nullptr, 10)); + e.beard_color = static_cast(strtoul(row[29], nullptr, 10)); + e.eye_color_1 = static_cast(strtoul(row[30], nullptr, 10)); + e.eye_color_2 = static_cast(strtoul(row[31], nullptr, 10)); + e.hair_style = static_cast(strtoul(row[32], nullptr, 10)); + e.face = static_cast(strtoul(row[33], nullptr, 10)); + e.beard = static_cast(strtoul(row[34], nullptr, 10)); + e.drakkin_heritage = static_cast(strtoul(row[35], nullptr, 10)); + e.drakkin_tattoo = static_cast(strtoul(row[36], nullptr, 10)); + e.drakkin_details = static_cast(strtoul(row[37], nullptr, 10)); + e.wc_1 = static_cast(strtoul(row[38], nullptr, 10)); + e.wc_2 = static_cast(strtoul(row[39], nullptr, 10)); + e.wc_3 = static_cast(strtoul(row[40], nullptr, 10)); + e.wc_4 = static_cast(strtoul(row[41], nullptr, 10)); + e.wc_5 = static_cast(strtoul(row[42], nullptr, 10)); + e.wc_6 = static_cast(strtoul(row[43], nullptr, 10)); + e.wc_7 = static_cast(strtoul(row[44], nullptr, 10)); + e.wc_8 = static_cast(strtoul(row[45], nullptr, 10)); + e.wc_9 = static_cast(strtoul(row[46], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -751,6 +751,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_CORPSES_REPOSITORY_H diff --git a/common/repositories/base/base_character_currency_repository.h b/common/repositories/base/base_character_currency_repository.h index b1e561608..5e83e4697 100644 --- a/common/repositories/base/base_character_currency_repository.h +++ b/common/repositories/base/base_character_currency_repository.h @@ -13,29 +13,29 @@ #define EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterCurrencyRepository { public: struct CharacterCurrency { - int id; - int platinum; - int gold; - int silver; - int copper; - int platinum_bank; - int gold_bank; - int silver_bank; - int copper_bank; - int platinum_cursor; - int gold_cursor; - int silver_cursor; - int copper_cursor; - int radiant_crystals; - int career_radiant_crystals; - int ebon_crystals; - int career_ebon_crystals; + uint32_t id; + uint32_t platinum; + uint32_t gold; + uint32_t silver; + uint32_t copper; + uint32_t platinum_bank; + uint32_t gold_bank; + uint32_t silver_bank; + uint32_t copper_bank; + uint32_t platinum_cursor; + uint32_t gold_cursor; + uint32_t silver_cursor; + uint32_t copper_cursor; + uint32_t radiant_crystals; + uint32_t career_radiant_crystals; + uint32_t ebon_crystals; + uint32_t career_ebon_crystals; }; static std::string PrimaryKey() @@ -91,12 +91,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -124,30 +124,30 @@ public: static CharacterCurrency NewEntity() { - CharacterCurrency entry{}; + CharacterCurrency e{}; - entry.id = 0; - entry.platinum = 0; - entry.gold = 0; - entry.silver = 0; - entry.copper = 0; - entry.platinum_bank = 0; - entry.gold_bank = 0; - entry.silver_bank = 0; - entry.copper_bank = 0; - entry.platinum_cursor = 0; - entry.gold_cursor = 0; - entry.silver_cursor = 0; - entry.copper_cursor = 0; - entry.radiant_crystals = 0; - entry.career_radiant_crystals = 0; - entry.ebon_crystals = 0; - entry.career_ebon_crystals = 0; + e.id = 0; + e.platinum = 0; + e.gold = 0; + e.silver = 0; + e.copper = 0; + e.platinum_bank = 0; + e.gold_bank = 0; + e.silver_bank = 0; + e.copper_bank = 0; + e.platinum_cursor = 0; + e.gold_cursor = 0; + e.silver_cursor = 0; + e.copper_cursor = 0; + e.radiant_crystals = 0; + e.career_radiant_crystals = 0; + e.ebon_crystals = 0; + e.career_ebon_crystals = 0; - return entry; + return e; } - static CharacterCurrency GetCharacterCurrencyEntry( + static CharacterCurrency GetCharacterCurrency( const std::vector &character_currencys, int character_currency_id ) @@ -176,27 +176,27 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterCurrency entry{}; + CharacterCurrency e{}; - entry.id = atoi(row[0]); - entry.platinum = atoi(row[1]); - entry.gold = atoi(row[2]); - entry.silver = atoi(row[3]); - entry.copper = atoi(row[4]); - entry.platinum_bank = atoi(row[5]); - entry.gold_bank = atoi(row[6]); - entry.silver_bank = atoi(row[7]); - entry.copper_bank = atoi(row[8]); - entry.platinum_cursor = atoi(row[9]); - entry.gold_cursor = atoi(row[10]); - entry.silver_cursor = atoi(row[11]); - entry.copper_cursor = atoi(row[12]); - entry.radiant_crystals = atoi(row[13]); - entry.career_radiant_crystals = atoi(row[14]); - entry.ebon_crystals = atoi(row[15]); - entry.career_ebon_crystals = atoi(row[16]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.platinum = static_cast(strtoul(row[1], nullptr, 10)); + e.gold = static_cast(strtoul(row[2], nullptr, 10)); + e.silver = static_cast(strtoul(row[3], nullptr, 10)); + e.copper = static_cast(strtoul(row[4], nullptr, 10)); + e.platinum_bank = static_cast(strtoul(row[5], nullptr, 10)); + e.gold_bank = static_cast(strtoul(row[6], nullptr, 10)); + e.silver_bank = static_cast(strtoul(row[7], nullptr, 10)); + e.copper_bank = static_cast(strtoul(row[8], nullptr, 10)); + e.platinum_cursor = static_cast(strtoul(row[9], nullptr, 10)); + e.gold_cursor = static_cast(strtoul(row[10], nullptr, 10)); + e.silver_cursor = static_cast(strtoul(row[11], nullptr, 10)); + e.copper_cursor = static_cast(strtoul(row[12], nullptr, 10)); + e.radiant_crystals = static_cast(strtoul(row[13], nullptr, 10)); + e.career_radiant_crystals = static_cast(strtoul(row[14], nullptr, 10)); + e.ebon_crystals = static_cast(strtoul(row[15], nullptr, 10)); + e.career_ebon_crystals = static_cast(strtoul(row[16], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -221,38 +221,38 @@ public: static int UpdateOne( Database& db, - CharacterCurrency character_currency_entry + const CharacterCurrency &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_currency_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_currency_entry.platinum)); - update_values.push_back(columns[2] + " = " + std::to_string(character_currency_entry.gold)); - update_values.push_back(columns[3] + " = " + std::to_string(character_currency_entry.silver)); - update_values.push_back(columns[4] + " = " + std::to_string(character_currency_entry.copper)); - update_values.push_back(columns[5] + " = " + std::to_string(character_currency_entry.platinum_bank)); - update_values.push_back(columns[6] + " = " + std::to_string(character_currency_entry.gold_bank)); - update_values.push_back(columns[7] + " = " + std::to_string(character_currency_entry.silver_bank)); - update_values.push_back(columns[8] + " = " + std::to_string(character_currency_entry.copper_bank)); - update_values.push_back(columns[9] + " = " + std::to_string(character_currency_entry.platinum_cursor)); - update_values.push_back(columns[10] + " = " + std::to_string(character_currency_entry.gold_cursor)); - update_values.push_back(columns[11] + " = " + std::to_string(character_currency_entry.silver_cursor)); - update_values.push_back(columns[12] + " = " + std::to_string(character_currency_entry.copper_cursor)); - update_values.push_back(columns[13] + " = " + std::to_string(character_currency_entry.radiant_crystals)); - update_values.push_back(columns[14] + " = " + std::to_string(character_currency_entry.career_radiant_crystals)); - update_values.push_back(columns[15] + " = " + std::to_string(character_currency_entry.ebon_crystals)); - update_values.push_back(columns[16] + " = " + std::to_string(character_currency_entry.career_ebon_crystals)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.platinum)); + v.push_back(columns[2] + " = " + std::to_string(e.gold)); + v.push_back(columns[3] + " = " + std::to_string(e.silver)); + v.push_back(columns[4] + " = " + std::to_string(e.copper)); + v.push_back(columns[5] + " = " + std::to_string(e.platinum_bank)); + v.push_back(columns[6] + " = " + std::to_string(e.gold_bank)); + v.push_back(columns[7] + " = " + std::to_string(e.silver_bank)); + v.push_back(columns[8] + " = " + std::to_string(e.copper_bank)); + v.push_back(columns[9] + " = " + std::to_string(e.platinum_cursor)); + v.push_back(columns[10] + " = " + std::to_string(e.gold_cursor)); + v.push_back(columns[11] + " = " + std::to_string(e.silver_cursor)); + v.push_back(columns[12] + " = " + std::to_string(e.copper_cursor)); + v.push_back(columns[13] + " = " + std::to_string(e.radiant_crystals)); + v.push_back(columns[14] + " = " + std::to_string(e.career_radiant_crystals)); + v.push_back(columns[15] + " = " + std::to_string(e.ebon_crystals)); + v.push_back(columns[16] + " = " + std::to_string(e.career_ebon_crystals)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_currency_entry.id + e.id ) ); @@ -261,85 +261,85 @@ public: static CharacterCurrency InsertOne( Database& db, - CharacterCurrency character_currency_entry + CharacterCurrency e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_currency_entry.id)); - insert_values.push_back(std::to_string(character_currency_entry.platinum)); - insert_values.push_back(std::to_string(character_currency_entry.gold)); - insert_values.push_back(std::to_string(character_currency_entry.silver)); - insert_values.push_back(std::to_string(character_currency_entry.copper)); - insert_values.push_back(std::to_string(character_currency_entry.platinum_bank)); - insert_values.push_back(std::to_string(character_currency_entry.gold_bank)); - insert_values.push_back(std::to_string(character_currency_entry.silver_bank)); - insert_values.push_back(std::to_string(character_currency_entry.copper_bank)); - insert_values.push_back(std::to_string(character_currency_entry.platinum_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.gold_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.silver_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.copper_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.radiant_crystals)); - insert_values.push_back(std::to_string(character_currency_entry.career_radiant_crystals)); - insert_values.push_back(std::to_string(character_currency_entry.ebon_crystals)); - insert_values.push_back(std::to_string(character_currency_entry.career_ebon_crystals)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.platinum)); + v.push_back(std::to_string(e.gold)); + v.push_back(std::to_string(e.silver)); + v.push_back(std::to_string(e.copper)); + v.push_back(std::to_string(e.platinum_bank)); + v.push_back(std::to_string(e.gold_bank)); + v.push_back(std::to_string(e.silver_bank)); + v.push_back(std::to_string(e.copper_bank)); + v.push_back(std::to_string(e.platinum_cursor)); + v.push_back(std::to_string(e.gold_cursor)); + v.push_back(std::to_string(e.silver_cursor)); + v.push_back(std::to_string(e.copper_cursor)); + v.push_back(std::to_string(e.radiant_crystals)); + v.push_back(std::to_string(e.career_radiant_crystals)); + v.push_back(std::to_string(e.ebon_crystals)); + v.push_back(std::to_string(e.career_ebon_crystals)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_currency_entry.id = results.LastInsertedID(); - return character_currency_entry; + e.id = results.LastInsertedID(); + return e; } - character_currency_entry = NewEntity(); + e = NewEntity(); - return character_currency_entry; + return e; } static int InsertMany( Database& db, - std::vector character_currency_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_currency_entry: character_currency_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_currency_entry.id)); - insert_values.push_back(std::to_string(character_currency_entry.platinum)); - insert_values.push_back(std::to_string(character_currency_entry.gold)); - insert_values.push_back(std::to_string(character_currency_entry.silver)); - insert_values.push_back(std::to_string(character_currency_entry.copper)); - insert_values.push_back(std::to_string(character_currency_entry.platinum_bank)); - insert_values.push_back(std::to_string(character_currency_entry.gold_bank)); - insert_values.push_back(std::to_string(character_currency_entry.silver_bank)); - insert_values.push_back(std::to_string(character_currency_entry.copper_bank)); - insert_values.push_back(std::to_string(character_currency_entry.platinum_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.gold_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.silver_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.copper_cursor)); - insert_values.push_back(std::to_string(character_currency_entry.radiant_crystals)); - insert_values.push_back(std::to_string(character_currency_entry.career_radiant_crystals)); - insert_values.push_back(std::to_string(character_currency_entry.ebon_crystals)); - insert_values.push_back(std::to_string(character_currency_entry.career_ebon_crystals)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.platinum)); + v.push_back(std::to_string(e.gold)); + v.push_back(std::to_string(e.silver)); + v.push_back(std::to_string(e.copper)); + v.push_back(std::to_string(e.platinum_bank)); + v.push_back(std::to_string(e.gold_bank)); + v.push_back(std::to_string(e.silver_bank)); + v.push_back(std::to_string(e.copper_bank)); + v.push_back(std::to_string(e.platinum_cursor)); + v.push_back(std::to_string(e.gold_cursor)); + v.push_back(std::to_string(e.silver_cursor)); + v.push_back(std::to_string(e.copper_cursor)); + v.push_back(std::to_string(e.radiant_crystals)); + v.push_back(std::to_string(e.career_radiant_crystals)); + v.push_back(std::to_string(e.ebon_crystals)); + v.push_back(std::to_string(e.career_ebon_crystals)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -360,33 +360,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterCurrency entry{}; + CharacterCurrency e{}; - entry.id = atoi(row[0]); - entry.platinum = atoi(row[1]); - entry.gold = atoi(row[2]); - entry.silver = atoi(row[3]); - entry.copper = atoi(row[4]); - entry.platinum_bank = atoi(row[5]); - entry.gold_bank = atoi(row[6]); - entry.silver_bank = atoi(row[7]); - entry.copper_bank = atoi(row[8]); - entry.platinum_cursor = atoi(row[9]); - entry.gold_cursor = atoi(row[10]); - entry.silver_cursor = atoi(row[11]); - entry.copper_cursor = atoi(row[12]); - entry.radiant_crystals = atoi(row[13]); - entry.career_radiant_crystals = atoi(row[14]); - entry.ebon_crystals = atoi(row[15]); - entry.career_ebon_crystals = atoi(row[16]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.platinum = static_cast(strtoul(row[1], nullptr, 10)); + e.gold = static_cast(strtoul(row[2], nullptr, 10)); + e.silver = static_cast(strtoul(row[3], nullptr, 10)); + e.copper = static_cast(strtoul(row[4], nullptr, 10)); + e.platinum_bank = static_cast(strtoul(row[5], nullptr, 10)); + e.gold_bank = static_cast(strtoul(row[6], nullptr, 10)); + e.silver_bank = static_cast(strtoul(row[7], nullptr, 10)); + e.copper_bank = static_cast(strtoul(row[8], nullptr, 10)); + e.platinum_cursor = static_cast(strtoul(row[9], nullptr, 10)); + e.gold_cursor = static_cast(strtoul(row[10], nullptr, 10)); + e.silver_cursor = static_cast(strtoul(row[11], nullptr, 10)); + e.copper_cursor = static_cast(strtoul(row[12], nullptr, 10)); + e.radiant_crystals = static_cast(strtoul(row[13], nullptr, 10)); + e.career_radiant_crystals = static_cast(strtoul(row[14], nullptr, 10)); + e.ebon_crystals = static_cast(strtoul(row[15], nullptr, 10)); + e.career_ebon_crystals = static_cast(strtoul(row[16], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -401,33 +401,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterCurrency entry{}; + CharacterCurrency e{}; - entry.id = atoi(row[0]); - entry.platinum = atoi(row[1]); - entry.gold = atoi(row[2]); - entry.silver = atoi(row[3]); - entry.copper = atoi(row[4]); - entry.platinum_bank = atoi(row[5]); - entry.gold_bank = atoi(row[6]); - entry.silver_bank = atoi(row[7]); - entry.copper_bank = atoi(row[8]); - entry.platinum_cursor = atoi(row[9]); - entry.gold_cursor = atoi(row[10]); - entry.silver_cursor = atoi(row[11]); - entry.copper_cursor = atoi(row[12]); - entry.radiant_crystals = atoi(row[13]); - entry.career_radiant_crystals = atoi(row[14]); - entry.ebon_crystals = atoi(row[15]); - entry.career_ebon_crystals = atoi(row[16]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.platinum = static_cast(strtoul(row[1], nullptr, 10)); + e.gold = static_cast(strtoul(row[2], nullptr, 10)); + e.silver = static_cast(strtoul(row[3], nullptr, 10)); + e.copper = static_cast(strtoul(row[4], nullptr, 10)); + e.platinum_bank = static_cast(strtoul(row[5], nullptr, 10)); + e.gold_bank = static_cast(strtoul(row[6], nullptr, 10)); + e.silver_bank = static_cast(strtoul(row[7], nullptr, 10)); + e.copper_bank = static_cast(strtoul(row[8], nullptr, 10)); + e.platinum_cursor = static_cast(strtoul(row[9], nullptr, 10)); + e.gold_cursor = static_cast(strtoul(row[10], nullptr, 10)); + e.silver_cursor = static_cast(strtoul(row[11], nullptr, 10)); + e.copper_cursor = static_cast(strtoul(row[12], nullptr, 10)); + e.radiant_crystals = static_cast(strtoul(row[13], nullptr, 10)); + e.career_radiant_crystals = static_cast(strtoul(row[14], nullptr, 10)); + e.ebon_crystals = static_cast(strtoul(row[15], nullptr, 10)); + e.career_ebon_crystals = static_cast(strtoul(row[16], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -452,6 +452,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H diff --git a/common/repositories/base/base_character_data_repository.h b/common/repositories/base/base_character_data_repository.h index d6c96e211..16a69da14 100644 --- a/common/repositories/base/base_character_data_repository.h +++ b/common/repositories/base/base_character_data_repository.h @@ -13,113 +13,115 @@ #define EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include + class BaseCharacterDataRepository { public: struct CharacterData { - int id; - int account_id; + uint32_t id; + int32_t account_id; std::string name; std::string last_name; std::string title; std::string suffix; - int zone_id; - int zone_instance; + uint32_t zone_id; + uint32_t zone_instance; float y; float x; float z; float heading; - int gender; - int race; - int class_; - int level; - int deity; - int birthday; - int last_login; - int time_played; - int level2; - int anon; - int gm; - int face; - int hair_color; - int hair_style; - int beard; - int beard_color; - int eye_color_1; - int eye_color_2; - int drakkin_heritage; - int drakkin_tattoo; - int drakkin_details; - int ability_time_seconds; - int ability_number; - int ability_time_minutes; - int ability_time_hours; - int exp; - int aa_points_spent; - int aa_exp; - int aa_points; - int group_leadership_exp; - int raid_leadership_exp; - int group_leadership_points; - int raid_leadership_points; - int points; - int cur_hp; - int mana; - int endurance; - int intoxication; - int str; - int sta; - int cha; - int dex; - int int_; - int agi; - int wis; - int zone_change_count; - int toxicity; - int hunger_level; - int thirst_level; - int ability_up; - int ldon_points_guk; - int ldon_points_mir; - int ldon_points_mmc; - int ldon_points_ruj; - int ldon_points_tak; - int ldon_points_available; - int tribute_time_remaining; - int career_tribute_points; - int tribute_points; - int tribute_active; - int pvp_status; - int pvp_kills; - int pvp_deaths; - int pvp_current_points; - int pvp_career_points; - int pvp_best_kill_streak; - int pvp_worst_death_streak; - int pvp_current_kill_streak; - int pvp2; - int pvp_type; - int show_helm; - int group_auto_consent; - int raid_auto_consent; - int guild_auto_consent; - int leadership_exp_on; - int RestTimer; - int air_remaining; - int autosplit_enabled; - int lfp; - int lfg; + uint8_t gender; + uint16_t race; + uint8_t class_; + uint32_t level; + uint32_t deity; + uint32_t birthday; + uint32_t last_login; + uint32_t time_played; + uint8_t level2; + uint8_t anon; + uint8_t gm; + uint32_t face; + uint8_t hair_color; + uint8_t hair_style; + uint8_t beard; + uint8_t beard_color; + uint8_t eye_color_1; + uint8_t eye_color_2; + uint32_t drakkin_heritage; + uint32_t drakkin_tattoo; + uint32_t drakkin_details; + uint8_t ability_time_seconds; + uint8_t ability_number; + uint8_t ability_time_minutes; + uint8_t ability_time_hours; + uint32_t exp; + uint8_t exp_enabled; + uint32_t aa_points_spent; + uint32_t aa_exp; + uint32_t aa_points; + uint32_t group_leadership_exp; + uint32_t raid_leadership_exp; + uint32_t group_leadership_points; + uint32_t raid_leadership_points; + uint32_t points; + uint32_t cur_hp; + uint32_t mana; + uint32_t endurance; + uint32_t intoxication; + uint32_t str; + uint32_t sta; + uint32_t cha; + uint32_t dex; + uint32_t int_; + uint32_t agi; + uint32_t wis; + uint32_t zone_change_count; + uint32_t toxicity; + uint32_t hunger_level; + uint32_t thirst_level; + uint32_t ability_up; + uint32_t ldon_points_guk; + uint32_t ldon_points_mir; + uint32_t ldon_points_mmc; + uint32_t ldon_points_ruj; + uint32_t ldon_points_tak; + uint32_t ldon_points_available; + uint32_t tribute_time_remaining; + uint32_t career_tribute_points; + uint32_t tribute_points; + uint32_t tribute_active; + uint8_t pvp_status; + uint32_t pvp_kills; + uint32_t pvp_deaths; + uint32_t pvp_current_points; + uint32_t pvp_career_points; + uint32_t pvp_best_kill_streak; + uint32_t pvp_worst_death_streak; + uint32_t pvp_current_kill_streak; + uint32_t pvp2; + uint32_t pvp_type; + uint32_t show_helm; + uint8_t group_auto_consent; + uint8_t raid_auto_consent; + uint8_t guild_auto_consent; + uint8_t leadership_exp_on; + uint32_t RestTimer; + uint32_t air_remaining; + uint32_t autosplit_enabled; + uint8_t lfp; + uint8_t lfg; std::string mailkey; - int xtargets; - int firstlogon; - int e_aa_effects; - int e_percent_to_aa; - int e_expended_aa_spent; - int aa_points_spent_old; - int aa_points_old; - int e_last_invsnapshot; + uint8_t xtargets; + int8_t firstlogon; + uint32_t e_aa_effects; + uint32_t e_percent_to_aa; + uint32_t e_expended_aa_spent; + uint32_t aa_points_spent_old; + uint32_t aa_points_old; + uint32_t e_last_invsnapshot; time_t deleted_at; }; @@ -169,6 +171,7 @@ public: "ability_time_minutes", "ability_time_hours", "exp", + "exp_enabled", "aa_points_spent", "aa_exp", "aa_points", @@ -277,6 +280,7 @@ public: "ability_time_minutes", "ability_time_hours", "exp", + "exp_enabled", "aa_points_spent", "aa_exp", "aa_points", @@ -346,12 +350,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -379,115 +383,116 @@ public: static CharacterData NewEntity() { - CharacterData entry{}; + CharacterData e{}; - entry.id = 0; - entry.account_id = 0; - entry.name = ""; - entry.last_name = ""; - entry.title = ""; - entry.suffix = ""; - entry.zone_id = 0; - entry.zone_instance = 0; - entry.y = 0; - entry.x = 0; - entry.z = 0; - entry.heading = 0; - entry.gender = 0; - entry.race = 0; - entry.class_ = 0; - entry.level = 0; - entry.deity = 0; - entry.birthday = 0; - entry.last_login = 0; - entry.time_played = 0; - entry.level2 = 0; - entry.anon = 0; - entry.gm = 0; - entry.face = 0; - entry.hair_color = 0; - entry.hair_style = 0; - entry.beard = 0; - entry.beard_color = 0; - entry.eye_color_1 = 0; - entry.eye_color_2 = 0; - entry.drakkin_heritage = 0; - entry.drakkin_tattoo = 0; - entry.drakkin_details = 0; - entry.ability_time_seconds = 0; - entry.ability_number = 0; - entry.ability_time_minutes = 0; - entry.ability_time_hours = 0; - entry.exp = 0; - entry.aa_points_spent = 0; - entry.aa_exp = 0; - entry.aa_points = 0; - entry.group_leadership_exp = 0; - entry.raid_leadership_exp = 0; - entry.group_leadership_points = 0; - entry.raid_leadership_points = 0; - entry.points = 0; - entry.cur_hp = 0; - entry.mana = 0; - entry.endurance = 0; - entry.intoxication = 0; - entry.str = 0; - entry.sta = 0; - entry.cha = 0; - entry.dex = 0; - entry.int_ = 0; - entry.agi = 0; - entry.wis = 0; - entry.zone_change_count = 0; - entry.toxicity = 0; - entry.hunger_level = 0; - entry.thirst_level = 0; - entry.ability_up = 0; - entry.ldon_points_guk = 0; - entry.ldon_points_mir = 0; - entry.ldon_points_mmc = 0; - entry.ldon_points_ruj = 0; - entry.ldon_points_tak = 0; - entry.ldon_points_available = 0; - entry.tribute_time_remaining = 0; - entry.career_tribute_points = 0; - entry.tribute_points = 0; - entry.tribute_active = 0; - entry.pvp_status = 0; - entry.pvp_kills = 0; - entry.pvp_deaths = 0; - entry.pvp_current_points = 0; - entry.pvp_career_points = 0; - entry.pvp_best_kill_streak = 0; - entry.pvp_worst_death_streak = 0; - entry.pvp_current_kill_streak = 0; - entry.pvp2 = 0; - entry.pvp_type = 0; - entry.show_helm = 0; - entry.group_auto_consent = 0; - entry.raid_auto_consent = 0; - entry.guild_auto_consent = 0; - entry.leadership_exp_on = 0; - entry.RestTimer = 0; - entry.air_remaining = 0; - entry.autosplit_enabled = 0; - entry.lfp = 0; - entry.lfg = 0; - entry.mailkey = ""; - entry.xtargets = 5; - entry.firstlogon = 0; - entry.e_aa_effects = 0; - entry.e_percent_to_aa = 0; - entry.e_expended_aa_spent = 0; - entry.aa_points_spent_old = 0; - entry.aa_points_old = 0; - entry.e_last_invsnapshot = 0; - entry.deleted_at = 0; + e.id = 0; + e.account_id = 0; + e.name = ""; + e.last_name = ""; + e.title = ""; + e.suffix = ""; + e.zone_id = 0; + e.zone_instance = 0; + e.y = 0; + e.x = 0; + e.z = 0; + e.heading = 0; + e.gender = 0; + e.race = 0; + e.class_ = 0; + e.level = 0; + e.deity = 0; + e.birthday = 0; + e.last_login = 0; + e.time_played = 0; + e.level2 = 0; + e.anon = 0; + e.gm = 0; + e.face = 0; + e.hair_color = 0; + e.hair_style = 0; + e.beard = 0; + e.beard_color = 0; + e.eye_color_1 = 0; + e.eye_color_2 = 0; + e.drakkin_heritage = 0; + e.drakkin_tattoo = 0; + e.drakkin_details = 0; + e.ability_time_seconds = 0; + e.ability_number = 0; + e.ability_time_minutes = 0; + e.ability_time_hours = 0; + e.exp = 0; + e.exp_enabled = 1; + e.aa_points_spent = 0; + e.aa_exp = 0; + e.aa_points = 0; + e.group_leadership_exp = 0; + e.raid_leadership_exp = 0; + e.group_leadership_points = 0; + e.raid_leadership_points = 0; + e.points = 0; + e.cur_hp = 0; + e.mana = 0; + e.endurance = 0; + e.intoxication = 0; + e.str = 0; + e.sta = 0; + e.cha = 0; + e.dex = 0; + e.int_ = 0; + e.agi = 0; + e.wis = 0; + e.zone_change_count = 0; + e.toxicity = 0; + e.hunger_level = 0; + e.thirst_level = 0; + e.ability_up = 0; + e.ldon_points_guk = 0; + e.ldon_points_mir = 0; + e.ldon_points_mmc = 0; + e.ldon_points_ruj = 0; + e.ldon_points_tak = 0; + e.ldon_points_available = 0; + e.tribute_time_remaining = 0; + e.career_tribute_points = 0; + e.tribute_points = 0; + e.tribute_active = 0; + e.pvp_status = 0; + e.pvp_kills = 0; + e.pvp_deaths = 0; + e.pvp_current_points = 0; + e.pvp_career_points = 0; + e.pvp_best_kill_streak = 0; + e.pvp_worst_death_streak = 0; + e.pvp_current_kill_streak = 0; + e.pvp2 = 0; + e.pvp_type = 0; + e.show_helm = 0; + e.group_auto_consent = 0; + e.raid_auto_consent = 0; + e.guild_auto_consent = 0; + e.leadership_exp_on = 0; + e.RestTimer = 0; + e.air_remaining = 0; + e.autosplit_enabled = 0; + e.lfp = 0; + e.lfg = 0; + e.mailkey = ""; + e.xtargets = 5; + e.firstlogon = 0; + e.e_aa_effects = 0; + e.e_percent_to_aa = 0; + e.e_expended_aa_spent = 0; + e.aa_points_spent_old = 0; + e.aa_points_old = 0; + e.e_last_invsnapshot = 0; + e.deleted_at = 0; - return entry; + return e; } - static CharacterData GetCharacterDataEntry( + static CharacterData GetCharacterData( const std::vector &character_datas, int character_data_id ) @@ -508,120 +513,122 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), character_data_id ) ); auto row = results.begin(); if (results.RowCount() == 1) { - CharacterData entry{}; + CharacterData e{}; - entry.id = atoi(row[0]); - entry.account_id = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.last_name = row[3] ? row[3] : ""; - entry.title = row[4] ? row[4] : ""; - entry.suffix = row[5] ? row[5] : ""; - entry.zone_id = atoi(row[6]); - entry.zone_instance = atoi(row[7]); - entry.y = static_cast(atof(row[8])); - entry.x = static_cast(atof(row[9])); - entry.z = static_cast(atof(row[10])); - entry.heading = static_cast(atof(row[11])); - entry.gender = atoi(row[12]); - entry.race = atoi(row[13]); - entry.class_ = atoi(row[14]); - entry.level = atoi(row[15]); - entry.deity = atoi(row[16]); - entry.birthday = atoi(row[17]); - entry.last_login = atoi(row[18]); - entry.time_played = atoi(row[19]); - entry.level2 = atoi(row[20]); - entry.anon = atoi(row[21]); - entry.gm = atoi(row[22]); - entry.face = atoi(row[23]); - entry.hair_color = atoi(row[24]); - entry.hair_style = atoi(row[25]); - entry.beard = atoi(row[26]); - entry.beard_color = atoi(row[27]); - entry.eye_color_1 = atoi(row[28]); - entry.eye_color_2 = atoi(row[29]); - entry.drakkin_heritage = atoi(row[30]); - entry.drakkin_tattoo = atoi(row[31]); - entry.drakkin_details = atoi(row[32]); - entry.ability_time_seconds = atoi(row[33]); - entry.ability_number = atoi(row[34]); - entry.ability_time_minutes = atoi(row[35]); - entry.ability_time_hours = atoi(row[36]); - entry.exp = atoi(row[37]); - entry.aa_points_spent = atoi(row[38]); - entry.aa_exp = atoi(row[39]); - entry.aa_points = atoi(row[40]); - entry.group_leadership_exp = atoi(row[41]); - entry.raid_leadership_exp = atoi(row[42]); - entry.group_leadership_points = atoi(row[43]); - entry.raid_leadership_points = atoi(row[44]); - entry.points = atoi(row[45]); - entry.cur_hp = atoi(row[46]); - entry.mana = atoi(row[47]); - entry.endurance = atoi(row[48]); - entry.intoxication = atoi(row[49]); - entry.str = atoi(row[50]); - entry.sta = atoi(row[51]); - entry.cha = atoi(row[52]); - entry.dex = atoi(row[53]); - entry.int_ = atoi(row[54]); - entry.agi = atoi(row[55]); - entry.wis = atoi(row[56]); - entry.zone_change_count = atoi(row[57]); - entry.toxicity = atoi(row[58]); - entry.hunger_level = atoi(row[59]); - entry.thirst_level = atoi(row[60]); - entry.ability_up = atoi(row[61]); - entry.ldon_points_guk = atoi(row[62]); - entry.ldon_points_mir = atoi(row[63]); - entry.ldon_points_mmc = atoi(row[64]); - entry.ldon_points_ruj = atoi(row[65]); - entry.ldon_points_tak = atoi(row[66]); - entry.ldon_points_available = atoi(row[67]); - entry.tribute_time_remaining = atoi(row[68]); - entry.career_tribute_points = atoi(row[69]); - entry.tribute_points = atoi(row[70]); - entry.tribute_active = atoi(row[71]); - entry.pvp_status = atoi(row[72]); - entry.pvp_kills = atoi(row[73]); - entry.pvp_deaths = atoi(row[74]); - entry.pvp_current_points = atoi(row[75]); - entry.pvp_career_points = atoi(row[76]); - entry.pvp_best_kill_streak = atoi(row[77]); - entry.pvp_worst_death_streak = atoi(row[78]); - entry.pvp_current_kill_streak = atoi(row[79]); - entry.pvp2 = atoi(row[80]); - entry.pvp_type = atoi(row[81]); - entry.show_helm = atoi(row[82]); - entry.group_auto_consent = atoi(row[83]); - entry.raid_auto_consent = atoi(row[84]); - entry.guild_auto_consent = atoi(row[85]); - entry.leadership_exp_on = atoi(row[86]); - entry.RestTimer = atoi(row[87]); - entry.air_remaining = atoi(row[88]); - entry.autosplit_enabled = atoi(row[89]); - entry.lfp = atoi(row[90]); - entry.lfg = atoi(row[91]); - entry.mailkey = row[92] ? row[92] : ""; - entry.xtargets = atoi(row[93]); - entry.firstlogon = atoi(row[94]); - entry.e_aa_effects = atoi(row[95]); - entry.e_percent_to_aa = atoi(row[96]); - entry.e_expended_aa_spent = atoi(row[97]); - entry.aa_points_spent_old = atoi(row[98]); - entry.aa_points_old = atoi(row[99]); - entry.e_last_invsnapshot = atoi(row[100]); - entry.deleted_at = strtoll(row[101] ? row[101] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_id = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.last_name = row[3] ? row[3] : ""; + e.title = row[4] ? row[4] : ""; + e.suffix = row[5] ? row[5] : ""; + e.zone_id = static_cast(strtoul(row[6], nullptr, 10)); + e.zone_instance = static_cast(strtoul(row[7], nullptr, 10)); + e.y = strtof(row[8], nullptr); + e.x = strtof(row[9], nullptr); + e.z = strtof(row[10], nullptr); + e.heading = strtof(row[11], nullptr); + e.gender = static_cast(strtoul(row[12], nullptr, 10)); + e.race = static_cast(strtoul(row[13], nullptr, 10)); + e.class_ = static_cast(strtoul(row[14], nullptr, 10)); + e.level = static_cast(strtoul(row[15], nullptr, 10)); + e.deity = static_cast(strtoul(row[16], nullptr, 10)); + e.birthday = static_cast(strtoul(row[17], nullptr, 10)); + e.last_login = static_cast(strtoul(row[18], nullptr, 10)); + e.time_played = static_cast(strtoul(row[19], nullptr, 10)); + e.level2 = static_cast(strtoul(row[20], nullptr, 10)); + e.anon = static_cast(strtoul(row[21], nullptr, 10)); + e.gm = static_cast(strtoul(row[22], nullptr, 10)); + e.face = static_cast(strtoul(row[23], nullptr, 10)); + e.hair_color = static_cast(strtoul(row[24], nullptr, 10)); + e.hair_style = static_cast(strtoul(row[25], nullptr, 10)); + e.beard = static_cast(strtoul(row[26], nullptr, 10)); + e.beard_color = static_cast(strtoul(row[27], nullptr, 10)); + e.eye_color_1 = static_cast(strtoul(row[28], nullptr, 10)); + e.eye_color_2 = static_cast(strtoul(row[29], nullptr, 10)); + e.drakkin_heritage = static_cast(strtoul(row[30], nullptr, 10)); + e.drakkin_tattoo = static_cast(strtoul(row[31], nullptr, 10)); + e.drakkin_details = static_cast(strtoul(row[32], nullptr, 10)); + e.ability_time_seconds = static_cast(strtoul(row[33], nullptr, 10)); + e.ability_number = static_cast(strtoul(row[34], nullptr, 10)); + e.ability_time_minutes = static_cast(strtoul(row[35], nullptr, 10)); + e.ability_time_hours = static_cast(strtoul(row[36], nullptr, 10)); + e.exp = static_cast(strtoul(row[37], nullptr, 10)); + e.exp_enabled = static_cast(strtoul(row[38], nullptr, 10)); + e.aa_points_spent = static_cast(strtoul(row[39], nullptr, 10)); + e.aa_exp = static_cast(strtoul(row[40], nullptr, 10)); + e.aa_points = static_cast(strtoul(row[41], nullptr, 10)); + e.group_leadership_exp = static_cast(strtoul(row[42], nullptr, 10)); + e.raid_leadership_exp = static_cast(strtoul(row[43], nullptr, 10)); + e.group_leadership_points = static_cast(strtoul(row[44], nullptr, 10)); + e.raid_leadership_points = static_cast(strtoul(row[45], nullptr, 10)); + e.points = static_cast(strtoul(row[46], nullptr, 10)); + e.cur_hp = static_cast(strtoul(row[47], nullptr, 10)); + e.mana = static_cast(strtoul(row[48], nullptr, 10)); + e.endurance = static_cast(strtoul(row[49], nullptr, 10)); + e.intoxication = static_cast(strtoul(row[50], nullptr, 10)); + e.str = static_cast(strtoul(row[51], nullptr, 10)); + e.sta = static_cast(strtoul(row[52], nullptr, 10)); + e.cha = static_cast(strtoul(row[53], nullptr, 10)); + e.dex = static_cast(strtoul(row[54], nullptr, 10)); + e.int_ = static_cast(strtoul(row[55], nullptr, 10)); + e.agi = static_cast(strtoul(row[56], nullptr, 10)); + e.wis = static_cast(strtoul(row[57], nullptr, 10)); + e.zone_change_count = static_cast(strtoul(row[58], nullptr, 10)); + e.toxicity = static_cast(strtoul(row[59], nullptr, 10)); + e.hunger_level = static_cast(strtoul(row[60], nullptr, 10)); + e.thirst_level = static_cast(strtoul(row[61], nullptr, 10)); + e.ability_up = static_cast(strtoul(row[62], nullptr, 10)); + e.ldon_points_guk = static_cast(strtoul(row[63], nullptr, 10)); + e.ldon_points_mir = static_cast(strtoul(row[64], nullptr, 10)); + e.ldon_points_mmc = static_cast(strtoul(row[65], nullptr, 10)); + e.ldon_points_ruj = static_cast(strtoul(row[66], nullptr, 10)); + e.ldon_points_tak = static_cast(strtoul(row[67], nullptr, 10)); + e.ldon_points_available = static_cast(strtoul(row[68], nullptr, 10)); + e.tribute_time_remaining = static_cast(strtoul(row[69], nullptr, 10)); + e.career_tribute_points = static_cast(strtoul(row[70], nullptr, 10)); + e.tribute_points = static_cast(strtoul(row[71], nullptr, 10)); + e.tribute_active = static_cast(strtoul(row[72], nullptr, 10)); + e.pvp_status = static_cast(strtoul(row[73], nullptr, 10)); + e.pvp_kills = static_cast(strtoul(row[74], nullptr, 10)); + e.pvp_deaths = static_cast(strtoul(row[75], nullptr, 10)); + e.pvp_current_points = static_cast(strtoul(row[76], nullptr, 10)); + e.pvp_career_points = static_cast(strtoul(row[77], nullptr, 10)); + e.pvp_best_kill_streak = static_cast(strtoul(row[78], nullptr, 10)); + e.pvp_worst_death_streak = static_cast(strtoul(row[79], nullptr, 10)); + e.pvp_current_kill_streak = static_cast(strtoul(row[80], nullptr, 10)); + e.pvp2 = static_cast(strtoul(row[81], nullptr, 10)); + e.pvp_type = static_cast(strtoul(row[82], nullptr, 10)); + e.show_helm = static_cast(strtoul(row[83], nullptr, 10)); + e.group_auto_consent = static_cast(strtoul(row[84], nullptr, 10)); + e.raid_auto_consent = static_cast(strtoul(row[85], nullptr, 10)); + e.guild_auto_consent = static_cast(strtoul(row[86], nullptr, 10)); + e.leadership_exp_on = static_cast(strtoul(row[87], nullptr, 10)); + e.RestTimer = static_cast(strtoul(row[88], nullptr, 10)); + e.air_remaining = static_cast(strtoul(row[89], nullptr, 10)); + e.autosplit_enabled = static_cast(strtoul(row[90], nullptr, 10)); + e.lfp = static_cast(strtoul(row[91], nullptr, 10)); + e.lfg = static_cast(strtoul(row[92], nullptr, 10)); + e.mailkey = row[93] ? row[93] : ""; + e.xtargets = static_cast(strtoul(row[94], nullptr, 10)); + e.firstlogon = static_cast(atoi(row[95])); + e.e_aa_effects = static_cast(strtoul(row[96], nullptr, 10)); + e.e_percent_to_aa = static_cast(strtoul(row[97], nullptr, 10)); + e.e_expended_aa_spent = static_cast(strtoul(row[98], nullptr, 10)); + e.aa_points_spent_old = static_cast(strtoul(row[99], nullptr, 10)); + e.aa_points_old = static_cast(strtoul(row[100], nullptr, 10)); + e.e_last_invsnapshot = static_cast(strtoul(row[101], nullptr, 10)); + e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -646,122 +653,123 @@ public: static int UpdateOne( Database& db, - CharacterData character_data_entry + const CharacterData &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_data_entry.account_id)); - update_values.push_back(columns[2] + " = '" + EscapeString(character_data_entry.name) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(character_data_entry.last_name) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(character_data_entry.title) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(character_data_entry.suffix) + "'"); - update_values.push_back(columns[6] + " = " + std::to_string(character_data_entry.zone_id)); - update_values.push_back(columns[7] + " = " + std::to_string(character_data_entry.zone_instance)); - update_values.push_back(columns[8] + " = " + std::to_string(character_data_entry.y)); - update_values.push_back(columns[9] + " = " + std::to_string(character_data_entry.x)); - update_values.push_back(columns[10] + " = " + std::to_string(character_data_entry.z)); - update_values.push_back(columns[11] + " = " + std::to_string(character_data_entry.heading)); - update_values.push_back(columns[12] + " = " + std::to_string(character_data_entry.gender)); - update_values.push_back(columns[13] + " = " + std::to_string(character_data_entry.race)); - update_values.push_back(columns[14] + " = " + std::to_string(character_data_entry.class_)); - update_values.push_back(columns[15] + " = " + std::to_string(character_data_entry.level)); - update_values.push_back(columns[16] + " = " + std::to_string(character_data_entry.deity)); - update_values.push_back(columns[17] + " = " + std::to_string(character_data_entry.birthday)); - update_values.push_back(columns[18] + " = " + std::to_string(character_data_entry.last_login)); - update_values.push_back(columns[19] + " = " + std::to_string(character_data_entry.time_played)); - update_values.push_back(columns[20] + " = " + std::to_string(character_data_entry.level2)); - update_values.push_back(columns[21] + " = " + std::to_string(character_data_entry.anon)); - update_values.push_back(columns[22] + " = " + std::to_string(character_data_entry.gm)); - update_values.push_back(columns[23] + " = " + std::to_string(character_data_entry.face)); - update_values.push_back(columns[24] + " = " + std::to_string(character_data_entry.hair_color)); - update_values.push_back(columns[25] + " = " + std::to_string(character_data_entry.hair_style)); - update_values.push_back(columns[26] + " = " + std::to_string(character_data_entry.beard)); - update_values.push_back(columns[27] + " = " + std::to_string(character_data_entry.beard_color)); - update_values.push_back(columns[28] + " = " + std::to_string(character_data_entry.eye_color_1)); - update_values.push_back(columns[29] + " = " + std::to_string(character_data_entry.eye_color_2)); - update_values.push_back(columns[30] + " = " + std::to_string(character_data_entry.drakkin_heritage)); - update_values.push_back(columns[31] + " = " + std::to_string(character_data_entry.drakkin_tattoo)); - update_values.push_back(columns[32] + " = " + std::to_string(character_data_entry.drakkin_details)); - update_values.push_back(columns[33] + " = " + std::to_string(character_data_entry.ability_time_seconds)); - update_values.push_back(columns[34] + " = " + std::to_string(character_data_entry.ability_number)); - update_values.push_back(columns[35] + " = " + std::to_string(character_data_entry.ability_time_minutes)); - update_values.push_back(columns[36] + " = " + std::to_string(character_data_entry.ability_time_hours)); - update_values.push_back(columns[37] + " = " + std::to_string(character_data_entry.exp)); - update_values.push_back(columns[38] + " = " + std::to_string(character_data_entry.aa_points_spent)); - update_values.push_back(columns[39] + " = " + std::to_string(character_data_entry.aa_exp)); - update_values.push_back(columns[40] + " = " + std::to_string(character_data_entry.aa_points)); - update_values.push_back(columns[41] + " = " + std::to_string(character_data_entry.group_leadership_exp)); - update_values.push_back(columns[42] + " = " + std::to_string(character_data_entry.raid_leadership_exp)); - update_values.push_back(columns[43] + " = " + std::to_string(character_data_entry.group_leadership_points)); - update_values.push_back(columns[44] + " = " + std::to_string(character_data_entry.raid_leadership_points)); - update_values.push_back(columns[45] + " = " + std::to_string(character_data_entry.points)); - update_values.push_back(columns[46] + " = " + std::to_string(character_data_entry.cur_hp)); - update_values.push_back(columns[47] + " = " + std::to_string(character_data_entry.mana)); - update_values.push_back(columns[48] + " = " + std::to_string(character_data_entry.endurance)); - update_values.push_back(columns[49] + " = " + std::to_string(character_data_entry.intoxication)); - update_values.push_back(columns[50] + " = " + std::to_string(character_data_entry.str)); - update_values.push_back(columns[51] + " = " + std::to_string(character_data_entry.sta)); - update_values.push_back(columns[52] + " = " + std::to_string(character_data_entry.cha)); - update_values.push_back(columns[53] + " = " + std::to_string(character_data_entry.dex)); - update_values.push_back(columns[54] + " = " + std::to_string(character_data_entry.int_)); - update_values.push_back(columns[55] + " = " + std::to_string(character_data_entry.agi)); - update_values.push_back(columns[56] + " = " + std::to_string(character_data_entry.wis)); - update_values.push_back(columns[57] + " = " + std::to_string(character_data_entry.zone_change_count)); - update_values.push_back(columns[58] + " = " + std::to_string(character_data_entry.toxicity)); - update_values.push_back(columns[59] + " = " + std::to_string(character_data_entry.hunger_level)); - update_values.push_back(columns[60] + " = " + std::to_string(character_data_entry.thirst_level)); - update_values.push_back(columns[61] + " = " + std::to_string(character_data_entry.ability_up)); - update_values.push_back(columns[62] + " = " + std::to_string(character_data_entry.ldon_points_guk)); - update_values.push_back(columns[63] + " = " + std::to_string(character_data_entry.ldon_points_mir)); - update_values.push_back(columns[64] + " = " + std::to_string(character_data_entry.ldon_points_mmc)); - update_values.push_back(columns[65] + " = " + std::to_string(character_data_entry.ldon_points_ruj)); - update_values.push_back(columns[66] + " = " + std::to_string(character_data_entry.ldon_points_tak)); - update_values.push_back(columns[67] + " = " + std::to_string(character_data_entry.ldon_points_available)); - update_values.push_back(columns[68] + " = " + std::to_string(character_data_entry.tribute_time_remaining)); - update_values.push_back(columns[69] + " = " + std::to_string(character_data_entry.career_tribute_points)); - update_values.push_back(columns[70] + " = " + std::to_string(character_data_entry.tribute_points)); - update_values.push_back(columns[71] + " = " + std::to_string(character_data_entry.tribute_active)); - update_values.push_back(columns[72] + " = " + std::to_string(character_data_entry.pvp_status)); - update_values.push_back(columns[73] + " = " + std::to_string(character_data_entry.pvp_kills)); - update_values.push_back(columns[74] + " = " + std::to_string(character_data_entry.pvp_deaths)); - update_values.push_back(columns[75] + " = " + std::to_string(character_data_entry.pvp_current_points)); - update_values.push_back(columns[76] + " = " + std::to_string(character_data_entry.pvp_career_points)); - update_values.push_back(columns[77] + " = " + std::to_string(character_data_entry.pvp_best_kill_streak)); - update_values.push_back(columns[78] + " = " + std::to_string(character_data_entry.pvp_worst_death_streak)); - update_values.push_back(columns[79] + " = " + std::to_string(character_data_entry.pvp_current_kill_streak)); - update_values.push_back(columns[80] + " = " + std::to_string(character_data_entry.pvp2)); - update_values.push_back(columns[81] + " = " + std::to_string(character_data_entry.pvp_type)); - update_values.push_back(columns[82] + " = " + std::to_string(character_data_entry.show_helm)); - update_values.push_back(columns[83] + " = " + std::to_string(character_data_entry.group_auto_consent)); - update_values.push_back(columns[84] + " = " + std::to_string(character_data_entry.raid_auto_consent)); - update_values.push_back(columns[85] + " = " + std::to_string(character_data_entry.guild_auto_consent)); - update_values.push_back(columns[86] + " = " + std::to_string(character_data_entry.leadership_exp_on)); - update_values.push_back(columns[87] + " = " + std::to_string(character_data_entry.RestTimer)); - update_values.push_back(columns[88] + " = " + std::to_string(character_data_entry.air_remaining)); - update_values.push_back(columns[89] + " = " + std::to_string(character_data_entry.autosplit_enabled)); - update_values.push_back(columns[90] + " = " + std::to_string(character_data_entry.lfp)); - update_values.push_back(columns[91] + " = " + std::to_string(character_data_entry.lfg)); - update_values.push_back(columns[92] + " = '" + EscapeString(character_data_entry.mailkey) + "'"); - update_values.push_back(columns[93] + " = " + std::to_string(character_data_entry.xtargets)); - update_values.push_back(columns[94] + " = " + std::to_string(character_data_entry.firstlogon)); - update_values.push_back(columns[95] + " = " + std::to_string(character_data_entry.e_aa_effects)); - update_values.push_back(columns[96] + " = " + std::to_string(character_data_entry.e_percent_to_aa)); - update_values.push_back(columns[97] + " = " + std::to_string(character_data_entry.e_expended_aa_spent)); - update_values.push_back(columns[98] + " = " + std::to_string(character_data_entry.aa_points_spent_old)); - update_values.push_back(columns[99] + " = " + std::to_string(character_data_entry.aa_points_old)); - update_values.push_back(columns[100] + " = " + std::to_string(character_data_entry.e_last_invsnapshot)); - update_values.push_back(columns[101] + " = FROM_UNIXTIME(" + (character_data_entry.deleted_at > 0 ? std::to_string(character_data_entry.deleted_at) : "null") + ")"); + v.push_back(columns[1] + " = " + std::to_string(e.account_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.last_name) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.title) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.suffix) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[7] + " = " + std::to_string(e.zone_instance)); + v.push_back(columns[8] + " = " + std::to_string(e.y)); + v.push_back(columns[9] + " = " + std::to_string(e.x)); + v.push_back(columns[10] + " = " + std::to_string(e.z)); + v.push_back(columns[11] + " = " + std::to_string(e.heading)); + v.push_back(columns[12] + " = " + std::to_string(e.gender)); + v.push_back(columns[13] + " = " + std::to_string(e.race)); + v.push_back(columns[14] + " = " + std::to_string(e.class_)); + v.push_back(columns[15] + " = " + std::to_string(e.level)); + v.push_back(columns[16] + " = " + std::to_string(e.deity)); + v.push_back(columns[17] + " = " + std::to_string(e.birthday)); + v.push_back(columns[18] + " = " + std::to_string(e.last_login)); + v.push_back(columns[19] + " = " + std::to_string(e.time_played)); + v.push_back(columns[20] + " = " + std::to_string(e.level2)); + v.push_back(columns[21] + " = " + std::to_string(e.anon)); + v.push_back(columns[22] + " = " + std::to_string(e.gm)); + v.push_back(columns[23] + " = " + std::to_string(e.face)); + v.push_back(columns[24] + " = " + std::to_string(e.hair_color)); + v.push_back(columns[25] + " = " + std::to_string(e.hair_style)); + v.push_back(columns[26] + " = " + std::to_string(e.beard)); + v.push_back(columns[27] + " = " + std::to_string(e.beard_color)); + v.push_back(columns[28] + " = " + std::to_string(e.eye_color_1)); + v.push_back(columns[29] + " = " + std::to_string(e.eye_color_2)); + v.push_back(columns[30] + " = " + std::to_string(e.drakkin_heritage)); + v.push_back(columns[31] + " = " + std::to_string(e.drakkin_tattoo)); + v.push_back(columns[32] + " = " + std::to_string(e.drakkin_details)); + v.push_back(columns[33] + " = " + std::to_string(e.ability_time_seconds)); + v.push_back(columns[34] + " = " + std::to_string(e.ability_number)); + v.push_back(columns[35] + " = " + std::to_string(e.ability_time_minutes)); + v.push_back(columns[36] + " = " + std::to_string(e.ability_time_hours)); + v.push_back(columns[37] + " = " + std::to_string(e.exp)); + v.push_back(columns[38] + " = " + std::to_string(e.exp_enabled)); + v.push_back(columns[39] + " = " + std::to_string(e.aa_points_spent)); + v.push_back(columns[40] + " = " + std::to_string(e.aa_exp)); + v.push_back(columns[41] + " = " + std::to_string(e.aa_points)); + v.push_back(columns[42] + " = " + std::to_string(e.group_leadership_exp)); + v.push_back(columns[43] + " = " + std::to_string(e.raid_leadership_exp)); + v.push_back(columns[44] + " = " + std::to_string(e.group_leadership_points)); + v.push_back(columns[45] + " = " + std::to_string(e.raid_leadership_points)); + v.push_back(columns[46] + " = " + std::to_string(e.points)); + v.push_back(columns[47] + " = " + std::to_string(e.cur_hp)); + v.push_back(columns[48] + " = " + std::to_string(e.mana)); + v.push_back(columns[49] + " = " + std::to_string(e.endurance)); + v.push_back(columns[50] + " = " + std::to_string(e.intoxication)); + v.push_back(columns[51] + " = " + std::to_string(e.str)); + v.push_back(columns[52] + " = " + std::to_string(e.sta)); + v.push_back(columns[53] + " = " + std::to_string(e.cha)); + v.push_back(columns[54] + " = " + std::to_string(e.dex)); + v.push_back(columns[55] + " = " + std::to_string(e.int_)); + v.push_back(columns[56] + " = " + std::to_string(e.agi)); + v.push_back(columns[57] + " = " + std::to_string(e.wis)); + v.push_back(columns[58] + " = " + std::to_string(e.zone_change_count)); + v.push_back(columns[59] + " = " + std::to_string(e.toxicity)); + v.push_back(columns[60] + " = " + std::to_string(e.hunger_level)); + v.push_back(columns[61] + " = " + std::to_string(e.thirst_level)); + v.push_back(columns[62] + " = " + std::to_string(e.ability_up)); + v.push_back(columns[63] + " = " + std::to_string(e.ldon_points_guk)); + v.push_back(columns[64] + " = " + std::to_string(e.ldon_points_mir)); + v.push_back(columns[65] + " = " + std::to_string(e.ldon_points_mmc)); + v.push_back(columns[66] + " = " + std::to_string(e.ldon_points_ruj)); + v.push_back(columns[67] + " = " + std::to_string(e.ldon_points_tak)); + v.push_back(columns[68] + " = " + std::to_string(e.ldon_points_available)); + v.push_back(columns[69] + " = " + std::to_string(e.tribute_time_remaining)); + v.push_back(columns[70] + " = " + std::to_string(e.career_tribute_points)); + v.push_back(columns[71] + " = " + std::to_string(e.tribute_points)); + v.push_back(columns[72] + " = " + std::to_string(e.tribute_active)); + v.push_back(columns[73] + " = " + std::to_string(e.pvp_status)); + v.push_back(columns[74] + " = " + std::to_string(e.pvp_kills)); + v.push_back(columns[75] + " = " + std::to_string(e.pvp_deaths)); + v.push_back(columns[76] + " = " + std::to_string(e.pvp_current_points)); + v.push_back(columns[77] + " = " + std::to_string(e.pvp_career_points)); + v.push_back(columns[78] + " = " + std::to_string(e.pvp_best_kill_streak)); + v.push_back(columns[79] + " = " + std::to_string(e.pvp_worst_death_streak)); + v.push_back(columns[80] + " = " + std::to_string(e.pvp_current_kill_streak)); + v.push_back(columns[81] + " = " + std::to_string(e.pvp2)); + v.push_back(columns[82] + " = " + std::to_string(e.pvp_type)); + v.push_back(columns[83] + " = " + std::to_string(e.show_helm)); + v.push_back(columns[84] + " = " + std::to_string(e.group_auto_consent)); + v.push_back(columns[85] + " = " + std::to_string(e.raid_auto_consent)); + v.push_back(columns[86] + " = " + std::to_string(e.guild_auto_consent)); + v.push_back(columns[87] + " = " + std::to_string(e.leadership_exp_on)); + v.push_back(columns[88] + " = " + std::to_string(e.RestTimer)); + v.push_back(columns[89] + " = " + std::to_string(e.air_remaining)); + v.push_back(columns[90] + " = " + std::to_string(e.autosplit_enabled)); + v.push_back(columns[91] + " = " + std::to_string(e.lfp)); + v.push_back(columns[92] + " = " + std::to_string(e.lfg)); + v.push_back(columns[93] + " = '" + Strings::Escape(e.mailkey) + "'"); + v.push_back(columns[94] + " = " + std::to_string(e.xtargets)); + v.push_back(columns[95] + " = " + std::to_string(e.firstlogon)); + v.push_back(columns[96] + " = " + std::to_string(e.e_aa_effects)); + v.push_back(columns[97] + " = " + std::to_string(e.e_percent_to_aa)); + v.push_back(columns[98] + " = " + std::to_string(e.e_expended_aa_spent)); + v.push_back(columns[99] + " = " + std::to_string(e.aa_points_spent_old)); + v.push_back(columns[100] + " = " + std::to_string(e.aa_points_old)); + v.push_back(columns[101] + " = " + std::to_string(e.e_last_invsnapshot)); + v.push_back(columns[102] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_data_entry.id + e.id ) ); @@ -770,255 +778,257 @@ public: static CharacterData InsertOne( Database& db, - CharacterData character_data_entry + CharacterData e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_data_entry.id)); - insert_values.push_back(std::to_string(character_data_entry.account_id)); - insert_values.push_back("'" + EscapeString(character_data_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(character_data_entry.last_name) + "'"); - insert_values.push_back("'" + EscapeString(character_data_entry.title) + "'"); - insert_values.push_back("'" + EscapeString(character_data_entry.suffix) + "'"); - insert_values.push_back(std::to_string(character_data_entry.zone_id)); - insert_values.push_back(std::to_string(character_data_entry.zone_instance)); - insert_values.push_back(std::to_string(character_data_entry.y)); - insert_values.push_back(std::to_string(character_data_entry.x)); - insert_values.push_back(std::to_string(character_data_entry.z)); - insert_values.push_back(std::to_string(character_data_entry.heading)); - insert_values.push_back(std::to_string(character_data_entry.gender)); - insert_values.push_back(std::to_string(character_data_entry.race)); - insert_values.push_back(std::to_string(character_data_entry.class_)); - insert_values.push_back(std::to_string(character_data_entry.level)); - insert_values.push_back(std::to_string(character_data_entry.deity)); - insert_values.push_back(std::to_string(character_data_entry.birthday)); - insert_values.push_back(std::to_string(character_data_entry.last_login)); - insert_values.push_back(std::to_string(character_data_entry.time_played)); - insert_values.push_back(std::to_string(character_data_entry.level2)); - insert_values.push_back(std::to_string(character_data_entry.anon)); - insert_values.push_back(std::to_string(character_data_entry.gm)); - insert_values.push_back(std::to_string(character_data_entry.face)); - insert_values.push_back(std::to_string(character_data_entry.hair_color)); - insert_values.push_back(std::to_string(character_data_entry.hair_style)); - insert_values.push_back(std::to_string(character_data_entry.beard)); - insert_values.push_back(std::to_string(character_data_entry.beard_color)); - insert_values.push_back(std::to_string(character_data_entry.eye_color_1)); - insert_values.push_back(std::to_string(character_data_entry.eye_color_2)); - insert_values.push_back(std::to_string(character_data_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(character_data_entry.drakkin_tattoo)); - insert_values.push_back(std::to_string(character_data_entry.drakkin_details)); - insert_values.push_back(std::to_string(character_data_entry.ability_time_seconds)); - insert_values.push_back(std::to_string(character_data_entry.ability_number)); - insert_values.push_back(std::to_string(character_data_entry.ability_time_minutes)); - insert_values.push_back(std::to_string(character_data_entry.ability_time_hours)); - insert_values.push_back(std::to_string(character_data_entry.exp)); - insert_values.push_back(std::to_string(character_data_entry.aa_points_spent)); - insert_values.push_back(std::to_string(character_data_entry.aa_exp)); - insert_values.push_back(std::to_string(character_data_entry.aa_points)); - insert_values.push_back(std::to_string(character_data_entry.group_leadership_exp)); - insert_values.push_back(std::to_string(character_data_entry.raid_leadership_exp)); - insert_values.push_back(std::to_string(character_data_entry.group_leadership_points)); - insert_values.push_back(std::to_string(character_data_entry.raid_leadership_points)); - insert_values.push_back(std::to_string(character_data_entry.points)); - insert_values.push_back(std::to_string(character_data_entry.cur_hp)); - insert_values.push_back(std::to_string(character_data_entry.mana)); - insert_values.push_back(std::to_string(character_data_entry.endurance)); - insert_values.push_back(std::to_string(character_data_entry.intoxication)); - insert_values.push_back(std::to_string(character_data_entry.str)); - insert_values.push_back(std::to_string(character_data_entry.sta)); - insert_values.push_back(std::to_string(character_data_entry.cha)); - insert_values.push_back(std::to_string(character_data_entry.dex)); - insert_values.push_back(std::to_string(character_data_entry.int_)); - insert_values.push_back(std::to_string(character_data_entry.agi)); - insert_values.push_back(std::to_string(character_data_entry.wis)); - insert_values.push_back(std::to_string(character_data_entry.zone_change_count)); - insert_values.push_back(std::to_string(character_data_entry.toxicity)); - insert_values.push_back(std::to_string(character_data_entry.hunger_level)); - insert_values.push_back(std::to_string(character_data_entry.thirst_level)); - insert_values.push_back(std::to_string(character_data_entry.ability_up)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_guk)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_mir)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_mmc)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_ruj)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_tak)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_available)); - insert_values.push_back(std::to_string(character_data_entry.tribute_time_remaining)); - insert_values.push_back(std::to_string(character_data_entry.career_tribute_points)); - insert_values.push_back(std::to_string(character_data_entry.tribute_points)); - insert_values.push_back(std::to_string(character_data_entry.tribute_active)); - insert_values.push_back(std::to_string(character_data_entry.pvp_status)); - insert_values.push_back(std::to_string(character_data_entry.pvp_kills)); - insert_values.push_back(std::to_string(character_data_entry.pvp_deaths)); - insert_values.push_back(std::to_string(character_data_entry.pvp_current_points)); - insert_values.push_back(std::to_string(character_data_entry.pvp_career_points)); - insert_values.push_back(std::to_string(character_data_entry.pvp_best_kill_streak)); - insert_values.push_back(std::to_string(character_data_entry.pvp_worst_death_streak)); - insert_values.push_back(std::to_string(character_data_entry.pvp_current_kill_streak)); - insert_values.push_back(std::to_string(character_data_entry.pvp2)); - insert_values.push_back(std::to_string(character_data_entry.pvp_type)); - insert_values.push_back(std::to_string(character_data_entry.show_helm)); - insert_values.push_back(std::to_string(character_data_entry.group_auto_consent)); - insert_values.push_back(std::to_string(character_data_entry.raid_auto_consent)); - insert_values.push_back(std::to_string(character_data_entry.guild_auto_consent)); - insert_values.push_back(std::to_string(character_data_entry.leadership_exp_on)); - insert_values.push_back(std::to_string(character_data_entry.RestTimer)); - insert_values.push_back(std::to_string(character_data_entry.air_remaining)); - insert_values.push_back(std::to_string(character_data_entry.autosplit_enabled)); - insert_values.push_back(std::to_string(character_data_entry.lfp)); - insert_values.push_back(std::to_string(character_data_entry.lfg)); - insert_values.push_back("'" + EscapeString(character_data_entry.mailkey) + "'"); - insert_values.push_back(std::to_string(character_data_entry.xtargets)); - insert_values.push_back(std::to_string(character_data_entry.firstlogon)); - insert_values.push_back(std::to_string(character_data_entry.e_aa_effects)); - insert_values.push_back(std::to_string(character_data_entry.e_percent_to_aa)); - insert_values.push_back(std::to_string(character_data_entry.e_expended_aa_spent)); - insert_values.push_back(std::to_string(character_data_entry.aa_points_spent_old)); - insert_values.push_back(std::to_string(character_data_entry.aa_points_old)); - insert_values.push_back(std::to_string(character_data_entry.e_last_invsnapshot)); - insert_values.push_back("FROM_UNIXTIME(" + (character_data_entry.deleted_at > 0 ? std::to_string(character_data_entry.deleted_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.account_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.last_name) + "'"); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.zone_instance)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.birthday)); + v.push_back(std::to_string(e.last_login)); + v.push_back(std::to_string(e.time_played)); + v.push_back(std::to_string(e.level2)); + v.push_back(std::to_string(e.anon)); + v.push_back(std::to_string(e.gm)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.hair_color)); + v.push_back(std::to_string(e.hair_style)); + v.push_back(std::to_string(e.beard)); + v.push_back(std::to_string(e.beard_color)); + v.push_back(std::to_string(e.eye_color_1)); + v.push_back(std::to_string(e.eye_color_2)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.ability_time_seconds)); + v.push_back(std::to_string(e.ability_number)); + v.push_back(std::to_string(e.ability_time_minutes)); + v.push_back(std::to_string(e.ability_time_hours)); + v.push_back(std::to_string(e.exp)); + v.push_back(std::to_string(e.exp_enabled)); + v.push_back(std::to_string(e.aa_points_spent)); + v.push_back(std::to_string(e.aa_exp)); + v.push_back(std::to_string(e.aa_points)); + v.push_back(std::to_string(e.group_leadership_exp)); + v.push_back(std::to_string(e.raid_leadership_exp)); + v.push_back(std::to_string(e.group_leadership_points)); + v.push_back(std::to_string(e.raid_leadership_points)); + v.push_back(std::to_string(e.points)); + v.push_back(std::to_string(e.cur_hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.endurance)); + v.push_back(std::to_string(e.intoxication)); + v.push_back(std::to_string(e.str)); + v.push_back(std::to_string(e.sta)); + v.push_back(std::to_string(e.cha)); + v.push_back(std::to_string(e.dex)); + v.push_back(std::to_string(e.int_)); + v.push_back(std::to_string(e.agi)); + v.push_back(std::to_string(e.wis)); + v.push_back(std::to_string(e.zone_change_count)); + v.push_back(std::to_string(e.toxicity)); + v.push_back(std::to_string(e.hunger_level)); + v.push_back(std::to_string(e.thirst_level)); + v.push_back(std::to_string(e.ability_up)); + v.push_back(std::to_string(e.ldon_points_guk)); + v.push_back(std::to_string(e.ldon_points_mir)); + v.push_back(std::to_string(e.ldon_points_mmc)); + v.push_back(std::to_string(e.ldon_points_ruj)); + v.push_back(std::to_string(e.ldon_points_tak)); + v.push_back(std::to_string(e.ldon_points_available)); + v.push_back(std::to_string(e.tribute_time_remaining)); + v.push_back(std::to_string(e.career_tribute_points)); + v.push_back(std::to_string(e.tribute_points)); + v.push_back(std::to_string(e.tribute_active)); + v.push_back(std::to_string(e.pvp_status)); + v.push_back(std::to_string(e.pvp_kills)); + v.push_back(std::to_string(e.pvp_deaths)); + v.push_back(std::to_string(e.pvp_current_points)); + v.push_back(std::to_string(e.pvp_career_points)); + v.push_back(std::to_string(e.pvp_best_kill_streak)); + v.push_back(std::to_string(e.pvp_worst_death_streak)); + v.push_back(std::to_string(e.pvp_current_kill_streak)); + v.push_back(std::to_string(e.pvp2)); + v.push_back(std::to_string(e.pvp_type)); + v.push_back(std::to_string(e.show_helm)); + v.push_back(std::to_string(e.group_auto_consent)); + v.push_back(std::to_string(e.raid_auto_consent)); + v.push_back(std::to_string(e.guild_auto_consent)); + v.push_back(std::to_string(e.leadership_exp_on)); + v.push_back(std::to_string(e.RestTimer)); + v.push_back(std::to_string(e.air_remaining)); + v.push_back(std::to_string(e.autosplit_enabled)); + v.push_back(std::to_string(e.lfp)); + v.push_back(std::to_string(e.lfg)); + v.push_back("'" + Strings::Escape(e.mailkey) + "'"); + v.push_back(std::to_string(e.xtargets)); + v.push_back(std::to_string(e.firstlogon)); + v.push_back(std::to_string(e.e_aa_effects)); + v.push_back(std::to_string(e.e_percent_to_aa)); + v.push_back(std::to_string(e.e_expended_aa_spent)); + v.push_back(std::to_string(e.aa_points_spent_old)); + v.push_back(std::to_string(e.aa_points_old)); + v.push_back(std::to_string(e.e_last_invsnapshot)); + v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_data_entry.id = results.LastInsertedID(); - return character_data_entry; + e.id = results.LastInsertedID(); + return e; } - character_data_entry = NewEntity(); + e = NewEntity(); - return character_data_entry; + return e; } static int InsertMany( Database& db, - std::vector character_data_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_data_entry: character_data_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_data_entry.id)); - insert_values.push_back(std::to_string(character_data_entry.account_id)); - insert_values.push_back("'" + EscapeString(character_data_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(character_data_entry.last_name) + "'"); - insert_values.push_back("'" + EscapeString(character_data_entry.title) + "'"); - insert_values.push_back("'" + EscapeString(character_data_entry.suffix) + "'"); - insert_values.push_back(std::to_string(character_data_entry.zone_id)); - insert_values.push_back(std::to_string(character_data_entry.zone_instance)); - insert_values.push_back(std::to_string(character_data_entry.y)); - insert_values.push_back(std::to_string(character_data_entry.x)); - insert_values.push_back(std::to_string(character_data_entry.z)); - insert_values.push_back(std::to_string(character_data_entry.heading)); - insert_values.push_back(std::to_string(character_data_entry.gender)); - insert_values.push_back(std::to_string(character_data_entry.race)); - insert_values.push_back(std::to_string(character_data_entry.class_)); - insert_values.push_back(std::to_string(character_data_entry.level)); - insert_values.push_back(std::to_string(character_data_entry.deity)); - insert_values.push_back(std::to_string(character_data_entry.birthday)); - insert_values.push_back(std::to_string(character_data_entry.last_login)); - insert_values.push_back(std::to_string(character_data_entry.time_played)); - insert_values.push_back(std::to_string(character_data_entry.level2)); - insert_values.push_back(std::to_string(character_data_entry.anon)); - insert_values.push_back(std::to_string(character_data_entry.gm)); - insert_values.push_back(std::to_string(character_data_entry.face)); - insert_values.push_back(std::to_string(character_data_entry.hair_color)); - insert_values.push_back(std::to_string(character_data_entry.hair_style)); - insert_values.push_back(std::to_string(character_data_entry.beard)); - insert_values.push_back(std::to_string(character_data_entry.beard_color)); - insert_values.push_back(std::to_string(character_data_entry.eye_color_1)); - insert_values.push_back(std::to_string(character_data_entry.eye_color_2)); - insert_values.push_back(std::to_string(character_data_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(character_data_entry.drakkin_tattoo)); - insert_values.push_back(std::to_string(character_data_entry.drakkin_details)); - insert_values.push_back(std::to_string(character_data_entry.ability_time_seconds)); - insert_values.push_back(std::to_string(character_data_entry.ability_number)); - insert_values.push_back(std::to_string(character_data_entry.ability_time_minutes)); - insert_values.push_back(std::to_string(character_data_entry.ability_time_hours)); - insert_values.push_back(std::to_string(character_data_entry.exp)); - insert_values.push_back(std::to_string(character_data_entry.aa_points_spent)); - insert_values.push_back(std::to_string(character_data_entry.aa_exp)); - insert_values.push_back(std::to_string(character_data_entry.aa_points)); - insert_values.push_back(std::to_string(character_data_entry.group_leadership_exp)); - insert_values.push_back(std::to_string(character_data_entry.raid_leadership_exp)); - insert_values.push_back(std::to_string(character_data_entry.group_leadership_points)); - insert_values.push_back(std::to_string(character_data_entry.raid_leadership_points)); - insert_values.push_back(std::to_string(character_data_entry.points)); - insert_values.push_back(std::to_string(character_data_entry.cur_hp)); - insert_values.push_back(std::to_string(character_data_entry.mana)); - insert_values.push_back(std::to_string(character_data_entry.endurance)); - insert_values.push_back(std::to_string(character_data_entry.intoxication)); - insert_values.push_back(std::to_string(character_data_entry.str)); - insert_values.push_back(std::to_string(character_data_entry.sta)); - insert_values.push_back(std::to_string(character_data_entry.cha)); - insert_values.push_back(std::to_string(character_data_entry.dex)); - insert_values.push_back(std::to_string(character_data_entry.int_)); - insert_values.push_back(std::to_string(character_data_entry.agi)); - insert_values.push_back(std::to_string(character_data_entry.wis)); - insert_values.push_back(std::to_string(character_data_entry.zone_change_count)); - insert_values.push_back(std::to_string(character_data_entry.toxicity)); - insert_values.push_back(std::to_string(character_data_entry.hunger_level)); - insert_values.push_back(std::to_string(character_data_entry.thirst_level)); - insert_values.push_back(std::to_string(character_data_entry.ability_up)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_guk)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_mir)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_mmc)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_ruj)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_tak)); - insert_values.push_back(std::to_string(character_data_entry.ldon_points_available)); - insert_values.push_back(std::to_string(character_data_entry.tribute_time_remaining)); - insert_values.push_back(std::to_string(character_data_entry.career_tribute_points)); - insert_values.push_back(std::to_string(character_data_entry.tribute_points)); - insert_values.push_back(std::to_string(character_data_entry.tribute_active)); - insert_values.push_back(std::to_string(character_data_entry.pvp_status)); - insert_values.push_back(std::to_string(character_data_entry.pvp_kills)); - insert_values.push_back(std::to_string(character_data_entry.pvp_deaths)); - insert_values.push_back(std::to_string(character_data_entry.pvp_current_points)); - insert_values.push_back(std::to_string(character_data_entry.pvp_career_points)); - insert_values.push_back(std::to_string(character_data_entry.pvp_best_kill_streak)); - insert_values.push_back(std::to_string(character_data_entry.pvp_worst_death_streak)); - insert_values.push_back(std::to_string(character_data_entry.pvp_current_kill_streak)); - insert_values.push_back(std::to_string(character_data_entry.pvp2)); - insert_values.push_back(std::to_string(character_data_entry.pvp_type)); - insert_values.push_back(std::to_string(character_data_entry.show_helm)); - insert_values.push_back(std::to_string(character_data_entry.group_auto_consent)); - insert_values.push_back(std::to_string(character_data_entry.raid_auto_consent)); - insert_values.push_back(std::to_string(character_data_entry.guild_auto_consent)); - insert_values.push_back(std::to_string(character_data_entry.leadership_exp_on)); - insert_values.push_back(std::to_string(character_data_entry.RestTimer)); - insert_values.push_back(std::to_string(character_data_entry.air_remaining)); - insert_values.push_back(std::to_string(character_data_entry.autosplit_enabled)); - insert_values.push_back(std::to_string(character_data_entry.lfp)); - insert_values.push_back(std::to_string(character_data_entry.lfg)); - insert_values.push_back("'" + EscapeString(character_data_entry.mailkey) + "'"); - insert_values.push_back(std::to_string(character_data_entry.xtargets)); - insert_values.push_back(std::to_string(character_data_entry.firstlogon)); - insert_values.push_back(std::to_string(character_data_entry.e_aa_effects)); - insert_values.push_back(std::to_string(character_data_entry.e_percent_to_aa)); - insert_values.push_back(std::to_string(character_data_entry.e_expended_aa_spent)); - insert_values.push_back(std::to_string(character_data_entry.aa_points_spent_old)); - insert_values.push_back(std::to_string(character_data_entry.aa_points_old)); - insert_values.push_back(std::to_string(character_data_entry.e_last_invsnapshot)); - insert_values.push_back("FROM_UNIXTIME(" + (character_data_entry.deleted_at > 0 ? std::to_string(character_data_entry.deleted_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.account_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.last_name) + "'"); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.zone_instance)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.birthday)); + v.push_back(std::to_string(e.last_login)); + v.push_back(std::to_string(e.time_played)); + v.push_back(std::to_string(e.level2)); + v.push_back(std::to_string(e.anon)); + v.push_back(std::to_string(e.gm)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.hair_color)); + v.push_back(std::to_string(e.hair_style)); + v.push_back(std::to_string(e.beard)); + v.push_back(std::to_string(e.beard_color)); + v.push_back(std::to_string(e.eye_color_1)); + v.push_back(std::to_string(e.eye_color_2)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.ability_time_seconds)); + v.push_back(std::to_string(e.ability_number)); + v.push_back(std::to_string(e.ability_time_minutes)); + v.push_back(std::to_string(e.ability_time_hours)); + v.push_back(std::to_string(e.exp)); + v.push_back(std::to_string(e.exp_enabled)); + v.push_back(std::to_string(e.aa_points_spent)); + v.push_back(std::to_string(e.aa_exp)); + v.push_back(std::to_string(e.aa_points)); + v.push_back(std::to_string(e.group_leadership_exp)); + v.push_back(std::to_string(e.raid_leadership_exp)); + v.push_back(std::to_string(e.group_leadership_points)); + v.push_back(std::to_string(e.raid_leadership_points)); + v.push_back(std::to_string(e.points)); + v.push_back(std::to_string(e.cur_hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.endurance)); + v.push_back(std::to_string(e.intoxication)); + v.push_back(std::to_string(e.str)); + v.push_back(std::to_string(e.sta)); + v.push_back(std::to_string(e.cha)); + v.push_back(std::to_string(e.dex)); + v.push_back(std::to_string(e.int_)); + v.push_back(std::to_string(e.agi)); + v.push_back(std::to_string(e.wis)); + v.push_back(std::to_string(e.zone_change_count)); + v.push_back(std::to_string(e.toxicity)); + v.push_back(std::to_string(e.hunger_level)); + v.push_back(std::to_string(e.thirst_level)); + v.push_back(std::to_string(e.ability_up)); + v.push_back(std::to_string(e.ldon_points_guk)); + v.push_back(std::to_string(e.ldon_points_mir)); + v.push_back(std::to_string(e.ldon_points_mmc)); + v.push_back(std::to_string(e.ldon_points_ruj)); + v.push_back(std::to_string(e.ldon_points_tak)); + v.push_back(std::to_string(e.ldon_points_available)); + v.push_back(std::to_string(e.tribute_time_remaining)); + v.push_back(std::to_string(e.career_tribute_points)); + v.push_back(std::to_string(e.tribute_points)); + v.push_back(std::to_string(e.tribute_active)); + v.push_back(std::to_string(e.pvp_status)); + v.push_back(std::to_string(e.pvp_kills)); + v.push_back(std::to_string(e.pvp_deaths)); + v.push_back(std::to_string(e.pvp_current_points)); + v.push_back(std::to_string(e.pvp_career_points)); + v.push_back(std::to_string(e.pvp_best_kill_streak)); + v.push_back(std::to_string(e.pvp_worst_death_streak)); + v.push_back(std::to_string(e.pvp_current_kill_streak)); + v.push_back(std::to_string(e.pvp2)); + v.push_back(std::to_string(e.pvp_type)); + v.push_back(std::to_string(e.show_helm)); + v.push_back(std::to_string(e.group_auto_consent)); + v.push_back(std::to_string(e.raid_auto_consent)); + v.push_back(std::to_string(e.guild_auto_consent)); + v.push_back(std::to_string(e.leadership_exp_on)); + v.push_back(std::to_string(e.RestTimer)); + v.push_back(std::to_string(e.air_remaining)); + v.push_back(std::to_string(e.autosplit_enabled)); + v.push_back(std::to_string(e.lfp)); + v.push_back(std::to_string(e.lfg)); + v.push_back("'" + Strings::Escape(e.mailkey) + "'"); + v.push_back(std::to_string(e.xtargets)); + v.push_back(std::to_string(e.firstlogon)); + v.push_back(std::to_string(e.e_aa_effects)); + v.push_back(std::to_string(e.e_percent_to_aa)); + v.push_back(std::to_string(e.e_expended_aa_spent)); + v.push_back(std::to_string(e.aa_points_spent_old)); + v.push_back(std::to_string(e.aa_points_old)); + v.push_back(std::to_string(e.e_last_invsnapshot)); + v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -1039,118 +1049,119 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterData entry{}; + CharacterData e{}; - entry.id = atoi(row[0]); - entry.account_id = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.last_name = row[3] ? row[3] : ""; - entry.title = row[4] ? row[4] : ""; - entry.suffix = row[5] ? row[5] : ""; - entry.zone_id = atoi(row[6]); - entry.zone_instance = atoi(row[7]); - entry.y = static_cast(atof(row[8])); - entry.x = static_cast(atof(row[9])); - entry.z = static_cast(atof(row[10])); - entry.heading = static_cast(atof(row[11])); - entry.gender = atoi(row[12]); - entry.race = atoi(row[13]); - entry.class_ = atoi(row[14]); - entry.level = atoi(row[15]); - entry.deity = atoi(row[16]); - entry.birthday = atoi(row[17]); - entry.last_login = atoi(row[18]); - entry.time_played = atoi(row[19]); - entry.level2 = atoi(row[20]); - entry.anon = atoi(row[21]); - entry.gm = atoi(row[22]); - entry.face = atoi(row[23]); - entry.hair_color = atoi(row[24]); - entry.hair_style = atoi(row[25]); - entry.beard = atoi(row[26]); - entry.beard_color = atoi(row[27]); - entry.eye_color_1 = atoi(row[28]); - entry.eye_color_2 = atoi(row[29]); - entry.drakkin_heritage = atoi(row[30]); - entry.drakkin_tattoo = atoi(row[31]); - entry.drakkin_details = atoi(row[32]); - entry.ability_time_seconds = atoi(row[33]); - entry.ability_number = atoi(row[34]); - entry.ability_time_minutes = atoi(row[35]); - entry.ability_time_hours = atoi(row[36]); - entry.exp = atoi(row[37]); - entry.aa_points_spent = atoi(row[38]); - entry.aa_exp = atoi(row[39]); - entry.aa_points = atoi(row[40]); - entry.group_leadership_exp = atoi(row[41]); - entry.raid_leadership_exp = atoi(row[42]); - entry.group_leadership_points = atoi(row[43]); - entry.raid_leadership_points = atoi(row[44]); - entry.points = atoi(row[45]); - entry.cur_hp = atoi(row[46]); - entry.mana = atoi(row[47]); - entry.endurance = atoi(row[48]); - entry.intoxication = atoi(row[49]); - entry.str = atoi(row[50]); - entry.sta = atoi(row[51]); - entry.cha = atoi(row[52]); - entry.dex = atoi(row[53]); - entry.int_ = atoi(row[54]); - entry.agi = atoi(row[55]); - entry.wis = atoi(row[56]); - entry.zone_change_count = atoi(row[57]); - entry.toxicity = atoi(row[58]); - entry.hunger_level = atoi(row[59]); - entry.thirst_level = atoi(row[60]); - entry.ability_up = atoi(row[61]); - entry.ldon_points_guk = atoi(row[62]); - entry.ldon_points_mir = atoi(row[63]); - entry.ldon_points_mmc = atoi(row[64]); - entry.ldon_points_ruj = atoi(row[65]); - entry.ldon_points_tak = atoi(row[66]); - entry.ldon_points_available = atoi(row[67]); - entry.tribute_time_remaining = atoi(row[68]); - entry.career_tribute_points = atoi(row[69]); - entry.tribute_points = atoi(row[70]); - entry.tribute_active = atoi(row[71]); - entry.pvp_status = atoi(row[72]); - entry.pvp_kills = atoi(row[73]); - entry.pvp_deaths = atoi(row[74]); - entry.pvp_current_points = atoi(row[75]); - entry.pvp_career_points = atoi(row[76]); - entry.pvp_best_kill_streak = atoi(row[77]); - entry.pvp_worst_death_streak = atoi(row[78]); - entry.pvp_current_kill_streak = atoi(row[79]); - entry.pvp2 = atoi(row[80]); - entry.pvp_type = atoi(row[81]); - entry.show_helm = atoi(row[82]); - entry.group_auto_consent = atoi(row[83]); - entry.raid_auto_consent = atoi(row[84]); - entry.guild_auto_consent = atoi(row[85]); - entry.leadership_exp_on = atoi(row[86]); - entry.RestTimer = atoi(row[87]); - entry.air_remaining = atoi(row[88]); - entry.autosplit_enabled = atoi(row[89]); - entry.lfp = atoi(row[90]); - entry.lfg = atoi(row[91]); - entry.mailkey = row[92] ? row[92] : ""; - entry.xtargets = atoi(row[93]); - entry.firstlogon = atoi(row[94]); - entry.e_aa_effects = atoi(row[95]); - entry.e_percent_to_aa = atoi(row[96]); - entry.e_expended_aa_spent = atoi(row[97]); - entry.aa_points_spent_old = atoi(row[98]); - entry.aa_points_old = atoi(row[99]); - entry.e_last_invsnapshot = atoi(row[100]); - entry.deleted_at = strtoll(row[101] ? row[101] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_id = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.last_name = row[3] ? row[3] : ""; + e.title = row[4] ? row[4] : ""; + e.suffix = row[5] ? row[5] : ""; + e.zone_id = static_cast(strtoul(row[6], nullptr, 10)); + e.zone_instance = static_cast(strtoul(row[7], nullptr, 10)); + e.y = strtof(row[8], nullptr); + e.x = strtof(row[9], nullptr); + e.z = strtof(row[10], nullptr); + e.heading = strtof(row[11], nullptr); + e.gender = static_cast(strtoul(row[12], nullptr, 10)); + e.race = static_cast(strtoul(row[13], nullptr, 10)); + e.class_ = static_cast(strtoul(row[14], nullptr, 10)); + e.level = static_cast(strtoul(row[15], nullptr, 10)); + e.deity = static_cast(strtoul(row[16], nullptr, 10)); + e.birthday = static_cast(strtoul(row[17], nullptr, 10)); + e.last_login = static_cast(strtoul(row[18], nullptr, 10)); + e.time_played = static_cast(strtoul(row[19], nullptr, 10)); + e.level2 = static_cast(strtoul(row[20], nullptr, 10)); + e.anon = static_cast(strtoul(row[21], nullptr, 10)); + e.gm = static_cast(strtoul(row[22], nullptr, 10)); + e.face = static_cast(strtoul(row[23], nullptr, 10)); + e.hair_color = static_cast(strtoul(row[24], nullptr, 10)); + e.hair_style = static_cast(strtoul(row[25], nullptr, 10)); + e.beard = static_cast(strtoul(row[26], nullptr, 10)); + e.beard_color = static_cast(strtoul(row[27], nullptr, 10)); + e.eye_color_1 = static_cast(strtoul(row[28], nullptr, 10)); + e.eye_color_2 = static_cast(strtoul(row[29], nullptr, 10)); + e.drakkin_heritage = static_cast(strtoul(row[30], nullptr, 10)); + e.drakkin_tattoo = static_cast(strtoul(row[31], nullptr, 10)); + e.drakkin_details = static_cast(strtoul(row[32], nullptr, 10)); + e.ability_time_seconds = static_cast(strtoul(row[33], nullptr, 10)); + e.ability_number = static_cast(strtoul(row[34], nullptr, 10)); + e.ability_time_minutes = static_cast(strtoul(row[35], nullptr, 10)); + e.ability_time_hours = static_cast(strtoul(row[36], nullptr, 10)); + e.exp = static_cast(strtoul(row[37], nullptr, 10)); + e.exp_enabled = static_cast(strtoul(row[38], nullptr, 10)); + e.aa_points_spent = static_cast(strtoul(row[39], nullptr, 10)); + e.aa_exp = static_cast(strtoul(row[40], nullptr, 10)); + e.aa_points = static_cast(strtoul(row[41], nullptr, 10)); + e.group_leadership_exp = static_cast(strtoul(row[42], nullptr, 10)); + e.raid_leadership_exp = static_cast(strtoul(row[43], nullptr, 10)); + e.group_leadership_points = static_cast(strtoul(row[44], nullptr, 10)); + e.raid_leadership_points = static_cast(strtoul(row[45], nullptr, 10)); + e.points = static_cast(strtoul(row[46], nullptr, 10)); + e.cur_hp = static_cast(strtoul(row[47], nullptr, 10)); + e.mana = static_cast(strtoul(row[48], nullptr, 10)); + e.endurance = static_cast(strtoul(row[49], nullptr, 10)); + e.intoxication = static_cast(strtoul(row[50], nullptr, 10)); + e.str = static_cast(strtoul(row[51], nullptr, 10)); + e.sta = static_cast(strtoul(row[52], nullptr, 10)); + e.cha = static_cast(strtoul(row[53], nullptr, 10)); + e.dex = static_cast(strtoul(row[54], nullptr, 10)); + e.int_ = static_cast(strtoul(row[55], nullptr, 10)); + e.agi = static_cast(strtoul(row[56], nullptr, 10)); + e.wis = static_cast(strtoul(row[57], nullptr, 10)); + e.zone_change_count = static_cast(strtoul(row[58], nullptr, 10)); + e.toxicity = static_cast(strtoul(row[59], nullptr, 10)); + e.hunger_level = static_cast(strtoul(row[60], nullptr, 10)); + e.thirst_level = static_cast(strtoul(row[61], nullptr, 10)); + e.ability_up = static_cast(strtoul(row[62], nullptr, 10)); + e.ldon_points_guk = static_cast(strtoul(row[63], nullptr, 10)); + e.ldon_points_mir = static_cast(strtoul(row[64], nullptr, 10)); + e.ldon_points_mmc = static_cast(strtoul(row[65], nullptr, 10)); + e.ldon_points_ruj = static_cast(strtoul(row[66], nullptr, 10)); + e.ldon_points_tak = static_cast(strtoul(row[67], nullptr, 10)); + e.ldon_points_available = static_cast(strtoul(row[68], nullptr, 10)); + e.tribute_time_remaining = static_cast(strtoul(row[69], nullptr, 10)); + e.career_tribute_points = static_cast(strtoul(row[70], nullptr, 10)); + e.tribute_points = static_cast(strtoul(row[71], nullptr, 10)); + e.tribute_active = static_cast(strtoul(row[72], nullptr, 10)); + e.pvp_status = static_cast(strtoul(row[73], nullptr, 10)); + e.pvp_kills = static_cast(strtoul(row[74], nullptr, 10)); + e.pvp_deaths = static_cast(strtoul(row[75], nullptr, 10)); + e.pvp_current_points = static_cast(strtoul(row[76], nullptr, 10)); + e.pvp_career_points = static_cast(strtoul(row[77], nullptr, 10)); + e.pvp_best_kill_streak = static_cast(strtoul(row[78], nullptr, 10)); + e.pvp_worst_death_streak = static_cast(strtoul(row[79], nullptr, 10)); + e.pvp_current_kill_streak = static_cast(strtoul(row[80], nullptr, 10)); + e.pvp2 = static_cast(strtoul(row[81], nullptr, 10)); + e.pvp_type = static_cast(strtoul(row[82], nullptr, 10)); + e.show_helm = static_cast(strtoul(row[83], nullptr, 10)); + e.group_auto_consent = static_cast(strtoul(row[84], nullptr, 10)); + e.raid_auto_consent = static_cast(strtoul(row[85], nullptr, 10)); + e.guild_auto_consent = static_cast(strtoul(row[86], nullptr, 10)); + e.leadership_exp_on = static_cast(strtoul(row[87], nullptr, 10)); + e.RestTimer = static_cast(strtoul(row[88], nullptr, 10)); + e.air_remaining = static_cast(strtoul(row[89], nullptr, 10)); + e.autosplit_enabled = static_cast(strtoul(row[90], nullptr, 10)); + e.lfp = static_cast(strtoul(row[91], nullptr, 10)); + e.lfg = static_cast(strtoul(row[92], nullptr, 10)); + e.mailkey = row[93] ? row[93] : ""; + e.xtargets = static_cast(strtoul(row[94], nullptr, 10)); + e.firstlogon = static_cast(atoi(row[95])); + e.e_aa_effects = static_cast(strtoul(row[96], nullptr, 10)); + e.e_percent_to_aa = static_cast(strtoul(row[97], nullptr, 10)); + e.e_expended_aa_spent = static_cast(strtoul(row[98], nullptr, 10)); + e.aa_points_spent_old = static_cast(strtoul(row[99], nullptr, 10)); + e.aa_points_old = static_cast(strtoul(row[100], nullptr, 10)); + e.e_last_invsnapshot = static_cast(strtoul(row[101], nullptr, 10)); + e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -1165,118 +1176,119 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterData entry{}; + CharacterData e{}; - entry.id = atoi(row[0]); - entry.account_id = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.last_name = row[3] ? row[3] : ""; - entry.title = row[4] ? row[4] : ""; - entry.suffix = row[5] ? row[5] : ""; - entry.zone_id = atoi(row[6]); - entry.zone_instance = atoi(row[7]); - entry.y = static_cast(atof(row[8])); - entry.x = static_cast(atof(row[9])); - entry.z = static_cast(atof(row[10])); - entry.heading = static_cast(atof(row[11])); - entry.gender = atoi(row[12]); - entry.race = atoi(row[13]); - entry.class_ = atoi(row[14]); - entry.level = atoi(row[15]); - entry.deity = atoi(row[16]); - entry.birthday = atoi(row[17]); - entry.last_login = atoi(row[18]); - entry.time_played = atoi(row[19]); - entry.level2 = atoi(row[20]); - entry.anon = atoi(row[21]); - entry.gm = atoi(row[22]); - entry.face = atoi(row[23]); - entry.hair_color = atoi(row[24]); - entry.hair_style = atoi(row[25]); - entry.beard = atoi(row[26]); - entry.beard_color = atoi(row[27]); - entry.eye_color_1 = atoi(row[28]); - entry.eye_color_2 = atoi(row[29]); - entry.drakkin_heritage = atoi(row[30]); - entry.drakkin_tattoo = atoi(row[31]); - entry.drakkin_details = atoi(row[32]); - entry.ability_time_seconds = atoi(row[33]); - entry.ability_number = atoi(row[34]); - entry.ability_time_minutes = atoi(row[35]); - entry.ability_time_hours = atoi(row[36]); - entry.exp = atoi(row[37]); - entry.aa_points_spent = atoi(row[38]); - entry.aa_exp = atoi(row[39]); - entry.aa_points = atoi(row[40]); - entry.group_leadership_exp = atoi(row[41]); - entry.raid_leadership_exp = atoi(row[42]); - entry.group_leadership_points = atoi(row[43]); - entry.raid_leadership_points = atoi(row[44]); - entry.points = atoi(row[45]); - entry.cur_hp = atoi(row[46]); - entry.mana = atoi(row[47]); - entry.endurance = atoi(row[48]); - entry.intoxication = atoi(row[49]); - entry.str = atoi(row[50]); - entry.sta = atoi(row[51]); - entry.cha = atoi(row[52]); - entry.dex = atoi(row[53]); - entry.int_ = atoi(row[54]); - entry.agi = atoi(row[55]); - entry.wis = atoi(row[56]); - entry.zone_change_count = atoi(row[57]); - entry.toxicity = atoi(row[58]); - entry.hunger_level = atoi(row[59]); - entry.thirst_level = atoi(row[60]); - entry.ability_up = atoi(row[61]); - entry.ldon_points_guk = atoi(row[62]); - entry.ldon_points_mir = atoi(row[63]); - entry.ldon_points_mmc = atoi(row[64]); - entry.ldon_points_ruj = atoi(row[65]); - entry.ldon_points_tak = atoi(row[66]); - entry.ldon_points_available = atoi(row[67]); - entry.tribute_time_remaining = atoi(row[68]); - entry.career_tribute_points = atoi(row[69]); - entry.tribute_points = atoi(row[70]); - entry.tribute_active = atoi(row[71]); - entry.pvp_status = atoi(row[72]); - entry.pvp_kills = atoi(row[73]); - entry.pvp_deaths = atoi(row[74]); - entry.pvp_current_points = atoi(row[75]); - entry.pvp_career_points = atoi(row[76]); - entry.pvp_best_kill_streak = atoi(row[77]); - entry.pvp_worst_death_streak = atoi(row[78]); - entry.pvp_current_kill_streak = atoi(row[79]); - entry.pvp2 = atoi(row[80]); - entry.pvp_type = atoi(row[81]); - entry.show_helm = atoi(row[82]); - entry.group_auto_consent = atoi(row[83]); - entry.raid_auto_consent = atoi(row[84]); - entry.guild_auto_consent = atoi(row[85]); - entry.leadership_exp_on = atoi(row[86]); - entry.RestTimer = atoi(row[87]); - entry.air_remaining = atoi(row[88]); - entry.autosplit_enabled = atoi(row[89]); - entry.lfp = atoi(row[90]); - entry.lfg = atoi(row[91]); - entry.mailkey = row[92] ? row[92] : ""; - entry.xtargets = atoi(row[93]); - entry.firstlogon = atoi(row[94]); - entry.e_aa_effects = atoi(row[95]); - entry.e_percent_to_aa = atoi(row[96]); - entry.e_expended_aa_spent = atoi(row[97]); - entry.aa_points_spent_old = atoi(row[98]); - entry.aa_points_old = atoi(row[99]); - entry.e_last_invsnapshot = atoi(row[100]); - entry.deleted_at = strtoll(row[101] ? row[101] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_id = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.last_name = row[3] ? row[3] : ""; + e.title = row[4] ? row[4] : ""; + e.suffix = row[5] ? row[5] : ""; + e.zone_id = static_cast(strtoul(row[6], nullptr, 10)); + e.zone_instance = static_cast(strtoul(row[7], nullptr, 10)); + e.y = strtof(row[8], nullptr); + e.x = strtof(row[9], nullptr); + e.z = strtof(row[10], nullptr); + e.heading = strtof(row[11], nullptr); + e.gender = static_cast(strtoul(row[12], nullptr, 10)); + e.race = static_cast(strtoul(row[13], nullptr, 10)); + e.class_ = static_cast(strtoul(row[14], nullptr, 10)); + e.level = static_cast(strtoul(row[15], nullptr, 10)); + e.deity = static_cast(strtoul(row[16], nullptr, 10)); + e.birthday = static_cast(strtoul(row[17], nullptr, 10)); + e.last_login = static_cast(strtoul(row[18], nullptr, 10)); + e.time_played = static_cast(strtoul(row[19], nullptr, 10)); + e.level2 = static_cast(strtoul(row[20], nullptr, 10)); + e.anon = static_cast(strtoul(row[21], nullptr, 10)); + e.gm = static_cast(strtoul(row[22], nullptr, 10)); + e.face = static_cast(strtoul(row[23], nullptr, 10)); + e.hair_color = static_cast(strtoul(row[24], nullptr, 10)); + e.hair_style = static_cast(strtoul(row[25], nullptr, 10)); + e.beard = static_cast(strtoul(row[26], nullptr, 10)); + e.beard_color = static_cast(strtoul(row[27], nullptr, 10)); + e.eye_color_1 = static_cast(strtoul(row[28], nullptr, 10)); + e.eye_color_2 = static_cast(strtoul(row[29], nullptr, 10)); + e.drakkin_heritage = static_cast(strtoul(row[30], nullptr, 10)); + e.drakkin_tattoo = static_cast(strtoul(row[31], nullptr, 10)); + e.drakkin_details = static_cast(strtoul(row[32], nullptr, 10)); + e.ability_time_seconds = static_cast(strtoul(row[33], nullptr, 10)); + e.ability_number = static_cast(strtoul(row[34], nullptr, 10)); + e.ability_time_minutes = static_cast(strtoul(row[35], nullptr, 10)); + e.ability_time_hours = static_cast(strtoul(row[36], nullptr, 10)); + e.exp = static_cast(strtoul(row[37], nullptr, 10)); + e.exp_enabled = static_cast(strtoul(row[38], nullptr, 10)); + e.aa_points_spent = static_cast(strtoul(row[39], nullptr, 10)); + e.aa_exp = static_cast(strtoul(row[40], nullptr, 10)); + e.aa_points = static_cast(strtoul(row[41], nullptr, 10)); + e.group_leadership_exp = static_cast(strtoul(row[42], nullptr, 10)); + e.raid_leadership_exp = static_cast(strtoul(row[43], nullptr, 10)); + e.group_leadership_points = static_cast(strtoul(row[44], nullptr, 10)); + e.raid_leadership_points = static_cast(strtoul(row[45], nullptr, 10)); + e.points = static_cast(strtoul(row[46], nullptr, 10)); + e.cur_hp = static_cast(strtoul(row[47], nullptr, 10)); + e.mana = static_cast(strtoul(row[48], nullptr, 10)); + e.endurance = static_cast(strtoul(row[49], nullptr, 10)); + e.intoxication = static_cast(strtoul(row[50], nullptr, 10)); + e.str = static_cast(strtoul(row[51], nullptr, 10)); + e.sta = static_cast(strtoul(row[52], nullptr, 10)); + e.cha = static_cast(strtoul(row[53], nullptr, 10)); + e.dex = static_cast(strtoul(row[54], nullptr, 10)); + e.int_ = static_cast(strtoul(row[55], nullptr, 10)); + e.agi = static_cast(strtoul(row[56], nullptr, 10)); + e.wis = static_cast(strtoul(row[57], nullptr, 10)); + e.zone_change_count = static_cast(strtoul(row[58], nullptr, 10)); + e.toxicity = static_cast(strtoul(row[59], nullptr, 10)); + e.hunger_level = static_cast(strtoul(row[60], nullptr, 10)); + e.thirst_level = static_cast(strtoul(row[61], nullptr, 10)); + e.ability_up = static_cast(strtoul(row[62], nullptr, 10)); + e.ldon_points_guk = static_cast(strtoul(row[63], nullptr, 10)); + e.ldon_points_mir = static_cast(strtoul(row[64], nullptr, 10)); + e.ldon_points_mmc = static_cast(strtoul(row[65], nullptr, 10)); + e.ldon_points_ruj = static_cast(strtoul(row[66], nullptr, 10)); + e.ldon_points_tak = static_cast(strtoul(row[67], nullptr, 10)); + e.ldon_points_available = static_cast(strtoul(row[68], nullptr, 10)); + e.tribute_time_remaining = static_cast(strtoul(row[69], nullptr, 10)); + e.career_tribute_points = static_cast(strtoul(row[70], nullptr, 10)); + e.tribute_points = static_cast(strtoul(row[71], nullptr, 10)); + e.tribute_active = static_cast(strtoul(row[72], nullptr, 10)); + e.pvp_status = static_cast(strtoul(row[73], nullptr, 10)); + e.pvp_kills = static_cast(strtoul(row[74], nullptr, 10)); + e.pvp_deaths = static_cast(strtoul(row[75], nullptr, 10)); + e.pvp_current_points = static_cast(strtoul(row[76], nullptr, 10)); + e.pvp_career_points = static_cast(strtoul(row[77], nullptr, 10)); + e.pvp_best_kill_streak = static_cast(strtoul(row[78], nullptr, 10)); + e.pvp_worst_death_streak = static_cast(strtoul(row[79], nullptr, 10)); + e.pvp_current_kill_streak = static_cast(strtoul(row[80], nullptr, 10)); + e.pvp2 = static_cast(strtoul(row[81], nullptr, 10)); + e.pvp_type = static_cast(strtoul(row[82], nullptr, 10)); + e.show_helm = static_cast(strtoul(row[83], nullptr, 10)); + e.group_auto_consent = static_cast(strtoul(row[84], nullptr, 10)); + e.raid_auto_consent = static_cast(strtoul(row[85], nullptr, 10)); + e.guild_auto_consent = static_cast(strtoul(row[86], nullptr, 10)); + e.leadership_exp_on = static_cast(strtoul(row[87], nullptr, 10)); + e.RestTimer = static_cast(strtoul(row[88], nullptr, 10)); + e.air_remaining = static_cast(strtoul(row[89], nullptr, 10)); + e.autosplit_enabled = static_cast(strtoul(row[90], nullptr, 10)); + e.lfp = static_cast(strtoul(row[91], nullptr, 10)); + e.lfg = static_cast(strtoul(row[92], nullptr, 10)); + e.mailkey = row[93] ? row[93] : ""; + e.xtargets = static_cast(strtoul(row[94], nullptr, 10)); + e.firstlogon = static_cast(atoi(row[95])); + e.e_aa_effects = static_cast(strtoul(row[96], nullptr, 10)); + e.e_percent_to_aa = static_cast(strtoul(row[97], nullptr, 10)); + e.e_expended_aa_spent = static_cast(strtoul(row[98], nullptr, 10)); + e.aa_points_spent_old = static_cast(strtoul(row[99], nullptr, 10)); + e.aa_points_old = static_cast(strtoul(row[100], nullptr, 10)); + e.e_last_invsnapshot = static_cast(strtoul(row[101], nullptr, 10)); + e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -1301,6 +1313,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_character_disciplines_repository.h b/common/repositories/base/base_character_disciplines_repository.h index 42ab05fbb..882c32165 100644 --- a/common/repositories/base/base_character_disciplines_repository.h +++ b/common/repositories/base/base_character_disciplines_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterDisciplinesRepository { public: struct CharacterDisciplines { - int id; - int slot_id; - int disc_id; + uint32_t id; + uint16_t slot_id; + uint16_t disc_id; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterDisciplines NewEntity() { - CharacterDisciplines entry{}; + CharacterDisciplines e{}; - entry.id = 0; - entry.slot_id = 0; - entry.disc_id = 0; + e.id = 0; + e.slot_id = 0; + e.disc_id = 0; - return entry; + return e; } - static CharacterDisciplines GetCharacterDisciplinesEntry( + static CharacterDisciplines GetCharacterDisciplines( const std::vector &character_discipliness, int character_disciplines_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterDisciplines entry{}; + CharacterDisciplines e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.disc_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.disc_id = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CharacterDisciplines character_disciplines_entry + const CharacterDisciplines &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_disciplines_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_disciplines_entry.slot_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_disciplines_entry.disc_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.disc_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_disciplines_entry.id + e.id ) ); @@ -177,57 +177,57 @@ public: static CharacterDisciplines InsertOne( Database& db, - CharacterDisciplines character_disciplines_entry + CharacterDisciplines e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_disciplines_entry.id)); - insert_values.push_back(std::to_string(character_disciplines_entry.slot_id)); - insert_values.push_back(std::to_string(character_disciplines_entry.disc_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.disc_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_disciplines_entry.id = results.LastInsertedID(); - return character_disciplines_entry; + e.id = results.LastInsertedID(); + return e; } - character_disciplines_entry = NewEntity(); + e = NewEntity(); - return character_disciplines_entry; + return e; } static int InsertMany( Database& db, - std::vector character_disciplines_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_disciplines_entry: character_disciplines_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_disciplines_entry.id)); - insert_values.push_back(std::to_string(character_disciplines_entry.slot_id)); - insert_values.push_back(std::to_string(character_disciplines_entry.disc_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.disc_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterDisciplines entry{}; + CharacterDisciplines e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.disc_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.disc_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterDisciplines entry{}; + CharacterDisciplines e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.disc_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.disc_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H diff --git a/common/repositories/base/base_character_exp_modifiers_repository.h b/common/repositories/base/base_character_exp_modifiers_repository.h index 51cf134ad..034316b19 100644 --- a/common/repositories/base/base_character_exp_modifiers_repository.h +++ b/common/repositories/base/base_character_exp_modifiers_repository.h @@ -13,16 +13,17 @@ #define EQEMU_BASE_CHARACTER_EXP_MODIFIERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterExpModifiersRepository { public: struct CharacterExpModifiers { - int character_id; - int zone_id; - float aa_modifier; - float exp_modifier; + int32_t character_id; + int32_t zone_id; + int32_t instance_version; + float aa_modifier; + float exp_modifier; }; static std::string PrimaryKey() @@ -35,6 +36,7 @@ public: return { "character_id", "zone_id", + "instance_version", "aa_modifier", "exp_modifier", }; @@ -45,6 +47,7 @@ public: return { "character_id", "zone_id", + "instance_version", "aa_modifier", "exp_modifier", }; @@ -52,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +88,18 @@ public: static CharacterExpModifiers NewEntity() { - CharacterExpModifiers entry{}; + CharacterExpModifiers e{}; - entry.character_id = 0; - entry.zone_id = 0; - entry.aa_modifier = 0; - entry.exp_modifier = 0; + e.character_id = 0; + e.zone_id = 0; + e.instance_version = -1; + e.aa_modifier = 0; + e.exp_modifier = 0; - return entry; + return e; } - static CharacterExpModifiers GetCharacterExpModifiersEntry( + static CharacterExpModifiers GetCharacterExpModifiers( const std::vector &character_exp_modifierss, int character_exp_modifiers_id ) @@ -124,14 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterExpModifiers entry{}; + CharacterExpModifiers e{}; - entry.character_id = atoi(row[0]); - entry.zone_id = atoi(row[1]); - entry.aa_modifier = static_cast(atof(row[2])); - entry.exp_modifier = static_cast(atof(row[3])); + e.character_id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + e.instance_version = static_cast(atoi(row[2])); + e.aa_modifier = strtof(row[3], nullptr); + e.exp_modifier = strtof(row[4], nullptr); - return entry; + return e; } return NewEntity(); @@ -156,25 +161,26 @@ public: static int UpdateOne( Database& db, - CharacterExpModifiers character_exp_modifiers_entry + const CharacterExpModifiers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_exp_modifiers_entry.character_id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_exp_modifiers_entry.zone_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_exp_modifiers_entry.aa_modifier)); - update_values.push_back(columns[3] + " = " + std::to_string(character_exp_modifiers_entry.exp_modifier)); + v.push_back(columns[0] + " = " + std::to_string(e.character_id)); + v.push_back(columns[1] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[2] + " = " + std::to_string(e.instance_version)); + v.push_back(columns[3] + " = " + std::to_string(e.aa_modifier)); + v.push_back(columns[4] + " = " + std::to_string(e.exp_modifier)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_exp_modifiers_entry.character_id + e.character_id ) ); @@ -183,59 +189,61 @@ public: static CharacterExpModifiers InsertOne( Database& db, - CharacterExpModifiers character_exp_modifiers_entry + CharacterExpModifiers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_exp_modifiers_entry.character_id)); - insert_values.push_back(std::to_string(character_exp_modifiers_entry.zone_id)); - insert_values.push_back(std::to_string(character_exp_modifiers_entry.aa_modifier)); - insert_values.push_back(std::to_string(character_exp_modifiers_entry.exp_modifier)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_version)); + v.push_back(std::to_string(e.aa_modifier)); + v.push_back(std::to_string(e.exp_modifier)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_exp_modifiers_entry.character_id = results.LastInsertedID(); - return character_exp_modifiers_entry; + e.character_id = results.LastInsertedID(); + return e; } - character_exp_modifiers_entry = NewEntity(); + e = NewEntity(); - return character_exp_modifiers_entry; + return e; } static int InsertMany( Database& db, - std::vector character_exp_modifiers_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_exp_modifiers_entry: character_exp_modifiers_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_exp_modifiers_entry.character_id)); - insert_values.push_back(std::to_string(character_exp_modifiers_entry.zone_id)); - insert_values.push_back(std::to_string(character_exp_modifiers_entry.aa_modifier)); - insert_values.push_back(std::to_string(character_exp_modifiers_entry.exp_modifier)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_version)); + v.push_back(std::to_string(e.aa_modifier)); + v.push_back(std::to_string(e.exp_modifier)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterExpModifiers entry{}; + CharacterExpModifiers e{}; - entry.character_id = atoi(row[0]); - entry.zone_id = atoi(row[1]); - entry.aa_modifier = static_cast(atof(row[2])); - entry.exp_modifier = static_cast(atof(row[3])); + e.character_id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + e.instance_version = static_cast(atoi(row[2])); + e.aa_modifier = strtof(row[3], nullptr); + e.exp_modifier = strtof(row[4], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterExpModifiers entry{}; + CharacterExpModifiers e{}; - entry.character_id = atoi(row[0]); - entry.zone_id = atoi(row[1]); - entry.aa_modifier = static_cast(atof(row[2])); - entry.exp_modifier = static_cast(atof(row[3])); + e.character_id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + e.instance_version = static_cast(atoi(row[2])); + e.aa_modifier = strtof(row[3], nullptr); + e.exp_modifier = strtof(row[4], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_EXP_MODIFIERS_REPOSITORY_H diff --git a/common/repositories/base/base_character_expedition_lockouts_repository.h b/common/repositories/base/base_character_expedition_lockouts_repository.h index a8c4e9fd8..1a5489b87 100644 --- a/common/repositories/base/base_character_expedition_lockouts_repository.h +++ b/common/repositories/base/base_character_expedition_lockouts_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterExpeditionLockoutsRepository { public: struct CharacterExpeditionLockouts { - int id; - int character_id; + uint32_t id; + uint32_t character_id; std::string expedition_name; std::string event_name; time_t expire_time; - int duration; + uint32_t duration; std::string from_expedition_uuid; }; @@ -61,12 +61,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -94,20 +94,20 @@ public: static CharacterExpeditionLockouts NewEntity() { - CharacterExpeditionLockouts entry{}; + CharacterExpeditionLockouts e{}; - entry.id = 0; - entry.character_id = 0; - entry.expedition_name = ""; - entry.event_name = ""; - entry.expire_time = std::time(nullptr); - entry.duration = 0; - entry.from_expedition_uuid = ""; + e.id = 0; + e.character_id = 0; + e.expedition_name = ""; + e.event_name = ""; + e.expire_time = std::time(nullptr); + e.duration = 0; + e.from_expedition_uuid = ""; - return entry; + return e; } - static CharacterExpeditionLockouts GetCharacterExpeditionLockoutsEntry( + static CharacterExpeditionLockouts GetCharacterExpeditionLockouts( const std::vector &character_expedition_lockoutss, int character_expedition_lockouts_id ) @@ -136,17 +136,17 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterExpeditionLockouts entry{}; + CharacterExpeditionLockouts e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.expedition_name = row[2] ? row[2] : ""; - entry.event_name = row[3] ? row[3] : ""; - entry.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.duration = atoi(row[5]); - entry.from_expedition_uuid = row[6] ? row[6] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.expedition_name = row[2] ? row[2] : ""; + e.event_name = row[3] ? row[3] : ""; + e.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.duration = static_cast(strtoul(row[5], nullptr, 10)); + e.from_expedition_uuid = row[6] ? row[6] : ""; - return entry; + return e; } return NewEntity(); @@ -171,27 +171,27 @@ public: static int UpdateOne( Database& db, - CharacterExpeditionLockouts character_expedition_lockouts_entry + const CharacterExpeditionLockouts &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_expedition_lockouts_entry.character_id)); - update_values.push_back(columns[2] + " = '" + EscapeString(character_expedition_lockouts_entry.expedition_name) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(character_expedition_lockouts_entry.event_name) + "'"); - update_values.push_back(columns[4] + " = FROM_UNIXTIME(" + (character_expedition_lockouts_entry.expire_time > 0 ? std::to_string(character_expedition_lockouts_entry.expire_time) : "null") + ")"); - update_values.push_back(columns[5] + " = " + std::to_string(character_expedition_lockouts_entry.duration)); - update_values.push_back(columns[6] + " = '" + EscapeString(character_expedition_lockouts_entry.from_expedition_uuid) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.character_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.expedition_name) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.event_name) + "'"); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(columns[5] + " = " + std::to_string(e.duration)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.from_expedition_uuid) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_expedition_lockouts_entry.id + e.id ) ); @@ -200,65 +200,65 @@ public: static CharacterExpeditionLockouts InsertOne( Database& db, - CharacterExpeditionLockouts character_expedition_lockouts_entry + CharacterExpeditionLockouts e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_expedition_lockouts_entry.id)); - insert_values.push_back(std::to_string(character_expedition_lockouts_entry.character_id)); - insert_values.push_back("'" + EscapeString(character_expedition_lockouts_entry.expedition_name) + "'"); - insert_values.push_back("'" + EscapeString(character_expedition_lockouts_entry.event_name) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (character_expedition_lockouts_entry.expire_time > 0 ? std::to_string(character_expedition_lockouts_entry.expire_time) : "null") + ")"); - insert_values.push_back(std::to_string(character_expedition_lockouts_entry.duration)); - insert_values.push_back("'" + EscapeString(character_expedition_lockouts_entry.from_expedition_uuid) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.character_id)); + v.push_back("'" + Strings::Escape(e.expedition_name) + "'"); + v.push_back("'" + Strings::Escape(e.event_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(std::to_string(e.duration)); + v.push_back("'" + Strings::Escape(e.from_expedition_uuid) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_expedition_lockouts_entry.id = results.LastInsertedID(); - return character_expedition_lockouts_entry; + e.id = results.LastInsertedID(); + return e; } - character_expedition_lockouts_entry = NewEntity(); + e = NewEntity(); - return character_expedition_lockouts_entry; + return e; } static int InsertMany( Database& db, - std::vector character_expedition_lockouts_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_expedition_lockouts_entry: character_expedition_lockouts_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_expedition_lockouts_entry.id)); - insert_values.push_back(std::to_string(character_expedition_lockouts_entry.character_id)); - insert_values.push_back("'" + EscapeString(character_expedition_lockouts_entry.expedition_name) + "'"); - insert_values.push_back("'" + EscapeString(character_expedition_lockouts_entry.event_name) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (character_expedition_lockouts_entry.expire_time > 0 ? std::to_string(character_expedition_lockouts_entry.expire_time) : "null") + ")"); - insert_values.push_back(std::to_string(character_expedition_lockouts_entry.duration)); - insert_values.push_back("'" + EscapeString(character_expedition_lockouts_entry.from_expedition_uuid) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.character_id)); + v.push_back("'" + Strings::Escape(e.expedition_name) + "'"); + v.push_back("'" + Strings::Escape(e.event_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(std::to_string(e.duration)); + v.push_back("'" + Strings::Escape(e.from_expedition_uuid) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -279,23 +279,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterExpeditionLockouts entry{}; + CharacterExpeditionLockouts e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.expedition_name = row[2] ? row[2] : ""; - entry.event_name = row[3] ? row[3] : ""; - entry.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.duration = atoi(row[5]); - entry.from_expedition_uuid = row[6] ? row[6] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.expedition_name = row[2] ? row[2] : ""; + e.event_name = row[3] ? row[3] : ""; + e.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.duration = static_cast(strtoul(row[5], nullptr, 10)); + e.from_expedition_uuid = row[6] ? row[6] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -310,23 +310,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterExpeditionLockouts entry{}; + CharacterExpeditionLockouts e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.expedition_name = row[2] ? row[2] : ""; - entry.event_name = row[3] ? row[3] : ""; - entry.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.duration = atoi(row[5]); - entry.from_expedition_uuid = row[6] ? row[6] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.expedition_name = row[2] ? row[2] : ""; + e.event_name = row[3] ? row[3] : ""; + e.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.duration = static_cast(strtoul(row[5], nullptr, 10)); + e.from_expedition_uuid = row[6] ? row[6] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -351,6 +351,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H diff --git a/common/repositories/base/base_character_inspect_messages_repository.h b/common/repositories/base/base_character_inspect_messages_repository.h index 70f381879..78d2ea904 100644 --- a/common/repositories/base/base_character_inspect_messages_repository.h +++ b/common/repositories/base/base_character_inspect_messages_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterInspectMessagesRepository { public: struct CharacterInspectMessages { - int id; + uint32_t id; std::string inspect_message; }; @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static CharacterInspectMessages NewEntity() { - CharacterInspectMessages entry{}; + CharacterInspectMessages e{}; - entry.id = 0; - entry.inspect_message = ""; + e.id = 0; + e.inspect_message = ""; - return entry; + return e; } - static CharacterInspectMessages GetCharacterInspectMessagesEntry( + static CharacterInspectMessages GetCharacterInspectMessages( const std::vector &character_inspect_messagess, int character_inspect_messages_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterInspectMessages entry{}; + CharacterInspectMessages e{}; - entry.id = atoi(row[0]); - entry.inspect_message = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.inspect_message = row[1] ? row[1] : ""; - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - CharacterInspectMessages character_inspect_messages_entry + const CharacterInspectMessages &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_inspect_messages_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(character_inspect_messages_entry.inspect_message) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.inspect_message) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_inspect_messages_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static CharacterInspectMessages InsertOne( Database& db, - CharacterInspectMessages character_inspect_messages_entry + CharacterInspectMessages e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_inspect_messages_entry.id)); - insert_values.push_back("'" + EscapeString(character_inspect_messages_entry.inspect_message) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.inspect_message) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_inspect_messages_entry.id = results.LastInsertedID(); - return character_inspect_messages_entry; + e.id = results.LastInsertedID(); + return e; } - character_inspect_messages_entry = NewEntity(); + e = NewEntity(); - return character_inspect_messages_entry; + return e; } static int InsertMany( Database& db, - std::vector character_inspect_messages_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_inspect_messages_entry: character_inspect_messages_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_inspect_messages_entry.id)); - insert_values.push_back("'" + EscapeString(character_inspect_messages_entry.inspect_message) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.inspect_message) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterInspectMessages entry{}; + CharacterInspectMessages e{}; - entry.id = atoi(row[0]); - entry.inspect_message = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.inspect_message = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterInspectMessages entry{}; + CharacterInspectMessages e{}; - entry.id = atoi(row[0]); - entry.inspect_message = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.inspect_message = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H diff --git a/common/repositories/base/base_character_instance_safereturns_repository.h b/common/repositories/base/base_character_instance_safereturns_repository.h index 780633f5f..e8f7faa4b 100644 --- a/common/repositories/base/base_character_instance_safereturns_repository.h +++ b/common/repositories/base/base_character_instance_safereturns_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterInstanceSafereturnsRepository { public: struct CharacterInstanceSafereturns { - int id; - int character_id; - int instance_zone_id; - int instance_id; - int safe_zone_id; - float safe_x; - float safe_y; - float safe_z; - float safe_heading; + uint32_t id; + uint32_t character_id; + int32_t instance_zone_id; + int32_t instance_id; + int32_t safe_zone_id; + float safe_x; + float safe_y; + float safe_z; + float safe_heading; }; static std::string PrimaryKey() @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static CharacterInstanceSafereturns NewEntity() { - CharacterInstanceSafereturns entry{}; + CharacterInstanceSafereturns e{}; - entry.id = 0; - entry.character_id = 0; - entry.instance_zone_id = 0; - entry.instance_id = 0; - entry.safe_zone_id = 0; - entry.safe_x = 0; - entry.safe_y = 0; - entry.safe_z = 0; - entry.safe_heading = 0; + e.id = 0; + e.character_id = 0; + e.instance_zone_id = 0; + e.instance_id = 0; + e.safe_zone_id = 0; + e.safe_x = 0; + e.safe_y = 0; + e.safe_z = 0; + e.safe_heading = 0; - return entry; + return e; } - static CharacterInstanceSafereturns GetCharacterInstanceSafereturnsEntry( + static CharacterInstanceSafereturns GetCharacterInstanceSafereturns( const std::vector &character_instance_safereturnss, int character_instance_safereturns_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterInstanceSafereturns entry{}; + CharacterInstanceSafereturns e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.instance_zone_id = atoi(row[2]); - entry.instance_id = atoi(row[3]); - entry.safe_zone_id = atoi(row[4]); - entry.safe_x = static_cast(atof(row[5])); - entry.safe_y = static_cast(atof(row[6])); - entry.safe_z = static_cast(atof(row[7])); - entry.safe_heading = static_cast(atof(row[8])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.instance_zone_id = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); + e.safe_zone_id = static_cast(atoi(row[4])); + e.safe_x = strtof(row[5], nullptr); + e.safe_y = strtof(row[6], nullptr); + e.safe_z = strtof(row[7], nullptr); + e.safe_heading = strtof(row[8], nullptr); - return entry; + return e; } return NewEntity(); @@ -181,29 +181,29 @@ public: static int UpdateOne( Database& db, - CharacterInstanceSafereturns character_instance_safereturns_entry + const CharacterInstanceSafereturns &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_instance_safereturns_entry.character_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_instance_safereturns_entry.instance_zone_id)); - update_values.push_back(columns[3] + " = " + std::to_string(character_instance_safereturns_entry.instance_id)); - update_values.push_back(columns[4] + " = " + std::to_string(character_instance_safereturns_entry.safe_zone_id)); - update_values.push_back(columns[5] + " = " + std::to_string(character_instance_safereturns_entry.safe_x)); - update_values.push_back(columns[6] + " = " + std::to_string(character_instance_safereturns_entry.safe_y)); - update_values.push_back(columns[7] + " = " + std::to_string(character_instance_safereturns_entry.safe_z)); - update_values.push_back(columns[8] + " = " + std::to_string(character_instance_safereturns_entry.safe_heading)); + v.push_back(columns[1] + " = " + std::to_string(e.character_id)); + v.push_back(columns[2] + " = " + std::to_string(e.instance_zone_id)); + v.push_back(columns[3] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[4] + " = " + std::to_string(e.safe_zone_id)); + v.push_back(columns[5] + " = " + std::to_string(e.safe_x)); + v.push_back(columns[6] + " = " + std::to_string(e.safe_y)); + v.push_back(columns[7] + " = " + std::to_string(e.safe_z)); + v.push_back(columns[8] + " = " + std::to_string(e.safe_heading)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_instance_safereturns_entry.id + e.id ) ); @@ -212,69 +212,69 @@ public: static CharacterInstanceSafereturns InsertOne( Database& db, - CharacterInstanceSafereturns character_instance_safereturns_entry + CharacterInstanceSafereturns e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_instance_safereturns_entry.id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.character_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.instance_zone_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.instance_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_zone_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_x)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_y)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_z)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_heading)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.instance_zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.safe_zone_id)); + v.push_back(std::to_string(e.safe_x)); + v.push_back(std::to_string(e.safe_y)); + v.push_back(std::to_string(e.safe_z)); + v.push_back(std::to_string(e.safe_heading)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_instance_safereturns_entry.id = results.LastInsertedID(); - return character_instance_safereturns_entry; + e.id = results.LastInsertedID(); + return e; } - character_instance_safereturns_entry = NewEntity(); + e = NewEntity(); - return character_instance_safereturns_entry; + return e; } static int InsertMany( Database& db, - std::vector character_instance_safereturns_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_instance_safereturns_entry: character_instance_safereturns_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_instance_safereturns_entry.id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.character_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.instance_zone_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.instance_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_zone_id)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_x)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_y)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_z)); - insert_values.push_back(std::to_string(character_instance_safereturns_entry.safe_heading)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.instance_zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.safe_zone_id)); + v.push_back(std::to_string(e.safe_x)); + v.push_back(std::to_string(e.safe_y)); + v.push_back(std::to_string(e.safe_z)); + v.push_back(std::to_string(e.safe_heading)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -295,25 +295,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterInstanceSafereturns entry{}; + CharacterInstanceSafereturns e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.instance_zone_id = atoi(row[2]); - entry.instance_id = atoi(row[3]); - entry.safe_zone_id = atoi(row[4]); - entry.safe_x = static_cast(atof(row[5])); - entry.safe_y = static_cast(atof(row[6])); - entry.safe_z = static_cast(atof(row[7])); - entry.safe_heading = static_cast(atof(row[8])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.instance_zone_id = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); + e.safe_zone_id = static_cast(atoi(row[4])); + e.safe_x = strtof(row[5], nullptr); + e.safe_y = strtof(row[6], nullptr); + e.safe_z = strtof(row[7], nullptr); + e.safe_heading = strtof(row[8], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -328,25 +328,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterInstanceSafereturns entry{}; + CharacterInstanceSafereturns e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.instance_zone_id = atoi(row[2]); - entry.instance_id = atoi(row[3]); - entry.safe_zone_id = atoi(row[4]); - entry.safe_x = static_cast(atof(row[5])); - entry.safe_y = static_cast(atof(row[6])); - entry.safe_z = static_cast(atof(row[7])); - entry.safe_heading = static_cast(atof(row[8])); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.instance_zone_id = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); + e.safe_zone_id = static_cast(atoi(row[4])); + e.safe_x = strtof(row[5], nullptr); + e.safe_y = strtof(row[6], nullptr); + e.safe_z = strtof(row[7], nullptr); + e.safe_heading = strtof(row[8], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -371,6 +371,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H diff --git a/common/repositories/base/base_character_item_recast_repository.h b/common/repositories/base/base_character_item_recast_repository.h index c38f1e1dc..929705ff8 100644 --- a/common/repositories/base/base_character_item_recast_repository.h +++ b/common/repositories/base/base_character_item_recast_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterItemRecastRepository { public: struct CharacterItemRecast { - int id; - int recast_type; - int timestamp; + uint32_t id; + uint16_t recast_type; + uint32_t timestamp; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterItemRecast NewEntity() { - CharacterItemRecast entry{}; + CharacterItemRecast e{}; - entry.id = 0; - entry.recast_type = 0; - entry.timestamp = 0; + e.id = 0; + e.recast_type = 0; + e.timestamp = 0; - return entry; + return e; } - static CharacterItemRecast GetCharacterItemRecastEntry( + static CharacterItemRecast GetCharacterItemRecast( const std::vector &character_item_recasts, int character_item_recast_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterItemRecast entry{}; + CharacterItemRecast e{}; - entry.id = atoi(row[0]); - entry.recast_type = atoi(row[1]); - entry.timestamp = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.recast_type = static_cast(strtoul(row[1], nullptr, 10)); + e.timestamp = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CharacterItemRecast character_item_recast_entry + const CharacterItemRecast &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_item_recast_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_item_recast_entry.recast_type)); - update_values.push_back(columns[2] + " = " + std::to_string(character_item_recast_entry.timestamp)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.recast_type)); + v.push_back(columns[2] + " = " + std::to_string(e.timestamp)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_item_recast_entry.id + e.id ) ); @@ -177,57 +177,57 @@ public: static CharacterItemRecast InsertOne( Database& db, - CharacterItemRecast character_item_recast_entry + CharacterItemRecast e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_item_recast_entry.id)); - insert_values.push_back(std::to_string(character_item_recast_entry.recast_type)); - insert_values.push_back(std::to_string(character_item_recast_entry.timestamp)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.recast_type)); + v.push_back(std::to_string(e.timestamp)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_item_recast_entry.id = results.LastInsertedID(); - return character_item_recast_entry; + e.id = results.LastInsertedID(); + return e; } - character_item_recast_entry = NewEntity(); + e = NewEntity(); - return character_item_recast_entry; + return e; } static int InsertMany( Database& db, - std::vector character_item_recast_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_item_recast_entry: character_item_recast_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_item_recast_entry.id)); - insert_values.push_back(std::to_string(character_item_recast_entry.recast_type)); - insert_values.push_back(std::to_string(character_item_recast_entry.timestamp)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.recast_type)); + v.push_back(std::to_string(e.timestamp)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterItemRecast entry{}; + CharacterItemRecast e{}; - entry.id = atoi(row[0]); - entry.recast_type = atoi(row[1]); - entry.timestamp = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.recast_type = static_cast(strtoul(row[1], nullptr, 10)); + e.timestamp = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterItemRecast entry{}; + CharacterItemRecast e{}; - entry.id = atoi(row[0]); - entry.recast_type = atoi(row[1]); - entry.timestamp = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.recast_type = static_cast(strtoul(row[1], nullptr, 10)); + e.timestamp = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H diff --git a/common/repositories/base/base_character_languages_repository.h b/common/repositories/base/base_character_languages_repository.h index 169dd6f6a..dc25de339 100644 --- a/common/repositories/base/base_character_languages_repository.h +++ b/common/repositories/base/base_character_languages_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_LANGUAGES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterLanguagesRepository { public: struct CharacterLanguages { - int id; - int lang_id; - int value; + uint32_t id; + uint16_t lang_id; + uint16_t value; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterLanguages NewEntity() { - CharacterLanguages entry{}; + CharacterLanguages e{}; - entry.id = 0; - entry.lang_id = 0; - entry.value = 0; + e.id = 0; + e.lang_id = 0; + e.value = 0; - return entry; + return e; } - static CharacterLanguages GetCharacterLanguagesEntry( + static CharacterLanguages GetCharacterLanguages( const std::vector &character_languagess, int character_languages_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterLanguages entry{}; + CharacterLanguages e{}; - entry.id = atoi(row[0]); - entry.lang_id = atoi(row[1]); - entry.value = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.lang_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,23 +151,23 @@ public: static int UpdateOne( Database& db, - CharacterLanguages character_languages_entry + const CharacterLanguages &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_languages_entry.lang_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_languages_entry.value)); + v.push_back(columns[1] + " = " + std::to_string(e.lang_id)); + v.push_back(columns[2] + " = " + std::to_string(e.value)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_languages_entry.id + e.id ) ); @@ -176,57 +176,57 @@ public: static CharacterLanguages InsertOne( Database& db, - CharacterLanguages character_languages_entry + CharacterLanguages e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_languages_entry.id)); - insert_values.push_back(std::to_string(character_languages_entry.lang_id)); - insert_values.push_back(std::to_string(character_languages_entry.value)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.lang_id)); + v.push_back(std::to_string(e.value)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_languages_entry.id = results.LastInsertedID(); - return character_languages_entry; + e.id = results.LastInsertedID(); + return e; } - character_languages_entry = NewEntity(); + e = NewEntity(); - return character_languages_entry; + return e; } static int InsertMany( Database& db, - std::vector character_languages_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_languages_entry: character_languages_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_languages_entry.id)); - insert_values.push_back(std::to_string(character_languages_entry.lang_id)); - insert_values.push_back(std::to_string(character_languages_entry.value)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.lang_id)); + v.push_back(std::to_string(e.value)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -247,19 +247,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterLanguages entry{}; + CharacterLanguages e{}; - entry.id = atoi(row[0]); - entry.lang_id = atoi(row[1]); - entry.value = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.lang_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -274,19 +274,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterLanguages entry{}; + CharacterLanguages e{}; - entry.id = atoi(row[0]); - entry.lang_id = atoi(row[1]); - entry.value = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.lang_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -311,6 +311,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_LANGUAGES_REPOSITORY_H diff --git a/common/repositories/base/base_character_leadership_abilities_repository.h b/common/repositories/base/base_character_leadership_abilities_repository.h index 0de0b5e8e..a58f0ba23 100644 --- a/common/repositories/base/base_character_leadership_abilities_repository.h +++ b/common/repositories/base/base_character_leadership_abilities_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterLeadershipAbilitiesRepository { public: struct CharacterLeadershipAbilities { - int id; - int slot; - int rank; + uint32_t id; + uint16_t slot; + uint16_t rank; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterLeadershipAbilities NewEntity() { - CharacterLeadershipAbilities entry{}; + CharacterLeadershipAbilities e{}; - entry.id = 0; - entry.slot = 0; - entry.rank = 0; + e.id = 0; + e.slot = 0; + e.rank = 0; - return entry; + return e; } - static CharacterLeadershipAbilities GetCharacterLeadershipAbilitiesEntry( + static CharacterLeadershipAbilities GetCharacterLeadershipAbilities( const std::vector &character_leadership_abilitiess, int character_leadership_abilities_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterLeadershipAbilities entry{}; + CharacterLeadershipAbilities e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.rank = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.rank = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CharacterLeadershipAbilities character_leadership_abilities_entry + const CharacterLeadershipAbilities &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_leadership_abilities_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_leadership_abilities_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(character_leadership_abilities_entry.rank)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.rank)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_leadership_abilities_entry.id + e.id ) ); @@ -177,57 +177,57 @@ public: static CharacterLeadershipAbilities InsertOne( Database& db, - CharacterLeadershipAbilities character_leadership_abilities_entry + CharacterLeadershipAbilities e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_leadership_abilities_entry.id)); - insert_values.push_back(std::to_string(character_leadership_abilities_entry.slot)); - insert_values.push_back(std::to_string(character_leadership_abilities_entry.rank)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.rank)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_leadership_abilities_entry.id = results.LastInsertedID(); - return character_leadership_abilities_entry; + e.id = results.LastInsertedID(); + return e; } - character_leadership_abilities_entry = NewEntity(); + e = NewEntity(); - return character_leadership_abilities_entry; + return e; } static int InsertMany( Database& db, - std::vector character_leadership_abilities_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_leadership_abilities_entry: character_leadership_abilities_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_leadership_abilities_entry.id)); - insert_values.push_back(std::to_string(character_leadership_abilities_entry.slot)); - insert_values.push_back(std::to_string(character_leadership_abilities_entry.rank)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.rank)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterLeadershipAbilities entry{}; + CharacterLeadershipAbilities e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.rank = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.rank = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterLeadershipAbilities entry{}; + CharacterLeadershipAbilities e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.rank = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.rank = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H diff --git a/common/repositories/base/base_character_material_repository.h b/common/repositories/base/base_character_material_repository.h index 7744aaa75..80506693c 100644 --- a/common/repositories/base/base_character_material_repository.h +++ b/common/repositories/base/base_character_material_repository.h @@ -13,19 +13,19 @@ #define EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterMaterialRepository { public: struct CharacterMaterial { - int id; - int slot; - int blue; - int green; - int red; - int use_tint; - int color; + uint32_t id; + uint8_t slot; + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t use_tint; + uint32_t color; }; static std::string PrimaryKey() @@ -61,12 +61,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -94,20 +94,20 @@ public: static CharacterMaterial NewEntity() { - CharacterMaterial entry{}; + CharacterMaterial e{}; - entry.id = 0; - entry.slot = 0; - entry.blue = 0; - entry.green = 0; - entry.red = 0; - entry.use_tint = 0; - entry.color = 0; + e.id = 0; + e.slot = 0; + e.blue = 0; + e.green = 0; + e.red = 0; + e.use_tint = 0; + e.color = 0; - return entry; + return e; } - static CharacterMaterial GetCharacterMaterialEntry( + static CharacterMaterial GetCharacterMaterial( const std::vector &character_materials, int character_material_id ) @@ -136,17 +136,17 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterMaterial entry{}; + CharacterMaterial e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.blue = atoi(row[2]); - entry.green = atoi(row[3]); - entry.red = atoi(row[4]); - entry.use_tint = atoi(row[5]); - entry.color = atoi(row[6]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.blue = static_cast(strtoul(row[2], nullptr, 10)); + e.green = static_cast(strtoul(row[3], nullptr, 10)); + e.red = static_cast(strtoul(row[4], nullptr, 10)); + e.use_tint = static_cast(strtoul(row[5], nullptr, 10)); + e.color = static_cast(strtoul(row[6], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -171,27 +171,27 @@ public: static int UpdateOne( Database& db, - CharacterMaterial character_material_entry + const CharacterMaterial &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_material_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(character_material_entry.blue)); - update_values.push_back(columns[3] + " = " + std::to_string(character_material_entry.green)); - update_values.push_back(columns[4] + " = " + std::to_string(character_material_entry.red)); - update_values.push_back(columns[5] + " = " + std::to_string(character_material_entry.use_tint)); - update_values.push_back(columns[6] + " = " + std::to_string(character_material_entry.color)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.blue)); + v.push_back(columns[3] + " = " + std::to_string(e.green)); + v.push_back(columns[4] + " = " + std::to_string(e.red)); + v.push_back(columns[5] + " = " + std::to_string(e.use_tint)); + v.push_back(columns[6] + " = " + std::to_string(e.color)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_material_entry.id + e.id ) ); @@ -200,65 +200,65 @@ public: static CharacterMaterial InsertOne( Database& db, - CharacterMaterial character_material_entry + CharacterMaterial e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_material_entry.id)); - insert_values.push_back(std::to_string(character_material_entry.slot)); - insert_values.push_back(std::to_string(character_material_entry.blue)); - insert_values.push_back(std::to_string(character_material_entry.green)); - insert_values.push_back(std::to_string(character_material_entry.red)); - insert_values.push_back(std::to_string(character_material_entry.use_tint)); - insert_values.push_back(std::to_string(character_material_entry.color)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.blue)); + v.push_back(std::to_string(e.green)); + v.push_back(std::to_string(e.red)); + v.push_back(std::to_string(e.use_tint)); + v.push_back(std::to_string(e.color)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_material_entry.id = results.LastInsertedID(); - return character_material_entry; + e.id = results.LastInsertedID(); + return e; } - character_material_entry = NewEntity(); + e = NewEntity(); - return character_material_entry; + return e; } static int InsertMany( Database& db, - std::vector character_material_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_material_entry: character_material_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_material_entry.id)); - insert_values.push_back(std::to_string(character_material_entry.slot)); - insert_values.push_back(std::to_string(character_material_entry.blue)); - insert_values.push_back(std::to_string(character_material_entry.green)); - insert_values.push_back(std::to_string(character_material_entry.red)); - insert_values.push_back(std::to_string(character_material_entry.use_tint)); - insert_values.push_back(std::to_string(character_material_entry.color)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.blue)); + v.push_back(std::to_string(e.green)); + v.push_back(std::to_string(e.red)); + v.push_back(std::to_string(e.use_tint)); + v.push_back(std::to_string(e.color)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -279,23 +279,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterMaterial entry{}; + CharacterMaterial e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.blue = atoi(row[2]); - entry.green = atoi(row[3]); - entry.red = atoi(row[4]); - entry.use_tint = atoi(row[5]); - entry.color = atoi(row[6]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.blue = static_cast(strtoul(row[2], nullptr, 10)); + e.green = static_cast(strtoul(row[3], nullptr, 10)); + e.red = static_cast(strtoul(row[4], nullptr, 10)); + e.use_tint = static_cast(strtoul(row[5], nullptr, 10)); + e.color = static_cast(strtoul(row[6], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -310,23 +310,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterMaterial entry{}; + CharacterMaterial e{}; - entry.id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.blue = atoi(row[2]); - entry.green = atoi(row[3]); - entry.red = atoi(row[4]); - entry.use_tint = atoi(row[5]); - entry.color = atoi(row[6]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.blue = static_cast(strtoul(row[2], nullptr, 10)); + e.green = static_cast(strtoul(row[3], nullptr, 10)); + e.red = static_cast(strtoul(row[4], nullptr, 10)); + e.use_tint = static_cast(strtoul(row[5], nullptr, 10)); + e.color = static_cast(strtoul(row[6], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -351,6 +351,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H diff --git a/common/repositories/base/base_character_memmed_spells_repository.h b/common/repositories/base/base_character_memmed_spells_repository.h index 7ee116cc7..4716e120f 100644 --- a/common/repositories/base/base_character_memmed_spells_repository.h +++ b/common/repositories/base/base_character_memmed_spells_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterMemmedSpellsRepository { public: struct CharacterMemmedSpells { - int id; - int slot_id; - int spell_id; + uint32_t id; + uint16_t slot_id; + uint16_t spell_id; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterMemmedSpells NewEntity() { - CharacterMemmedSpells entry{}; + CharacterMemmedSpells e{}; - entry.id = 0; - entry.slot_id = 0; - entry.spell_id = 0; + e.id = 0; + e.slot_id = 0; + e.spell_id = 0; - return entry; + return e; } - static CharacterMemmedSpells GetCharacterMemmedSpellsEntry( + static CharacterMemmedSpells GetCharacterMemmedSpells( const std::vector &character_memmed_spellss, int character_memmed_spells_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterMemmedSpells entry{}; + CharacterMemmedSpells e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CharacterMemmedSpells character_memmed_spells_entry + const CharacterMemmedSpells &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_memmed_spells_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_memmed_spells_entry.slot_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_memmed_spells_entry.spell_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_memmed_spells_entry.id + e.id ) ); @@ -177,57 +177,57 @@ public: static CharacterMemmedSpells InsertOne( Database& db, - CharacterMemmedSpells character_memmed_spells_entry + CharacterMemmedSpells e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_memmed_spells_entry.id)); - insert_values.push_back(std::to_string(character_memmed_spells_entry.slot_id)); - insert_values.push_back(std::to_string(character_memmed_spells_entry.spell_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.spell_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_memmed_spells_entry.id = results.LastInsertedID(); - return character_memmed_spells_entry; + e.id = results.LastInsertedID(); + return e; } - character_memmed_spells_entry = NewEntity(); + e = NewEntity(); - return character_memmed_spells_entry; + return e; } static int InsertMany( Database& db, - std::vector character_memmed_spells_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_memmed_spells_entry: character_memmed_spells_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_memmed_spells_entry.id)); - insert_values.push_back(std::to_string(character_memmed_spells_entry.slot_id)); - insert_values.push_back(std::to_string(character_memmed_spells_entry.spell_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.spell_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterMemmedSpells entry{}; + CharacterMemmedSpells e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterMemmedSpells entry{}; + CharacterMemmedSpells e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_character_peqzone_flags_repository.h b/common/repositories/base/base_character_peqzone_flags_repository.h new file mode 100644 index 000000000..fc83278b1 --- /dev/null +++ b/common/repositories/base/base_character_peqzone_flags_repository.h @@ -0,0 +1,333 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H +#define EQEMU_BASE_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseCharacterPeqzoneFlagsRepository { +public: + struct CharacterPeqzoneFlags { + int32_t id; + int32_t zone_id; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "zone_id", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "zone_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("character_peqzone_flags"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static CharacterPeqzoneFlags NewEntity() + { + CharacterPeqzoneFlags e{}; + + e.id = 0; + e.zone_id = 0; + + return e; + } + + static CharacterPeqzoneFlags GetCharacterPeqzoneFlags( + const std::vector &character_peqzone_flagss, + int character_peqzone_flags_id + ) + { + for (auto &character_peqzone_flags : character_peqzone_flagss) { + if (character_peqzone_flags.id == character_peqzone_flags_id) { + return character_peqzone_flags; + } + } + + return NewEntity(); + } + + static CharacterPeqzoneFlags FindOne( + Database& db, + int character_peqzone_flags_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + character_peqzone_flags_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + CharacterPeqzoneFlags e{}; + + e.id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int character_peqzone_flags_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + character_peqzone_flags_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const CharacterPeqzoneFlags &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.zone_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static CharacterPeqzoneFlags InsertOne( + Database& db, + CharacterPeqzoneFlags e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + CharacterPeqzoneFlags e{}; + + e.id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + CharacterPeqzoneFlags e{}; + + e.id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H diff --git a/common/repositories/base/base_character_pet_buffs_repository.h b/common/repositories/base/base_character_pet_buffs_repository.h index 1c0c23a9e..87fc3a286 100644 --- a/common/repositories/base/base_character_pet_buffs_repository.h +++ b/common/repositories/base/base_character_pet_buffs_repository.h @@ -13,23 +13,23 @@ #define EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterPetBuffsRepository { public: struct CharacterPetBuffs { - int char_id; - int pet; - int slot; - int spell_id; - int caster_level; + int32_t char_id; + int32_t pet; + int32_t slot; + int32_t spell_id; + int8_t caster_level; std::string castername; - int ticsremaining; - int counters; - int numhits; - int rune; - int instrument_mod; + int32_t ticsremaining; + int32_t counters; + int32_t numhits; + int32_t rune; + uint8_t instrument_mod; }; static std::string PrimaryKey() @@ -73,12 +73,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -106,24 +106,24 @@ public: static CharacterPetBuffs NewEntity() { - CharacterPetBuffs entry{}; + CharacterPetBuffs e{}; - entry.char_id = 0; - entry.pet = 0; - entry.slot = 0; - entry.spell_id = 0; - entry.caster_level = 0; - entry.castername = ""; - entry.ticsremaining = 0; - entry.counters = 0; - entry.numhits = 0; - entry.rune = 0; - entry.instrument_mod = 10; + e.char_id = 0; + e.pet = 0; + e.slot = 0; + e.spell_id = 0; + e.caster_level = 0; + e.castername = ""; + e.ticsremaining = 0; + e.counters = 0; + e.numhits = 0; + e.rune = 0; + e.instrument_mod = 10; - return entry; + return e; } - static CharacterPetBuffs GetCharacterPetBuffsEntry( + static CharacterPetBuffs GetCharacterPetBuffs( const std::vector &character_pet_buffss, int character_pet_buffs_id ) @@ -152,21 +152,21 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterPetBuffs entry{}; + CharacterPetBuffs e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.spell_id = atoi(row[3]); - entry.caster_level = atoi(row[4]); - entry.castername = row[5] ? row[5] : ""; - entry.ticsremaining = atoi(row[6]); - entry.counters = atoi(row[7]); - entry.numhits = atoi(row[8]); - entry.rune = atoi(row[9]); - entry.instrument_mod = atoi(row[10]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.slot = static_cast(atoi(row[2])); + e.spell_id = static_cast(atoi(row[3])); + e.caster_level = static_cast(atoi(row[4])); + e.castername = row[5] ? row[5] : ""; + e.ticsremaining = static_cast(atoi(row[6])); + e.counters = static_cast(atoi(row[7])); + e.numhits = static_cast(atoi(row[8])); + e.rune = static_cast(atoi(row[9])); + e.instrument_mod = static_cast(strtoul(row[10], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -191,32 +191,32 @@ public: static int UpdateOne( Database& db, - CharacterPetBuffs character_pet_buffs_entry + const CharacterPetBuffs &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_pet_buffs_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_pet_buffs_entry.pet)); - update_values.push_back(columns[2] + " = " + std::to_string(character_pet_buffs_entry.slot)); - update_values.push_back(columns[3] + " = " + std::to_string(character_pet_buffs_entry.spell_id)); - update_values.push_back(columns[4] + " = " + std::to_string(character_pet_buffs_entry.caster_level)); - update_values.push_back(columns[5] + " = '" + EscapeString(character_pet_buffs_entry.castername) + "'"); - update_values.push_back(columns[6] + " = " + std::to_string(character_pet_buffs_entry.ticsremaining)); - update_values.push_back(columns[7] + " = " + std::to_string(character_pet_buffs_entry.counters)); - update_values.push_back(columns[8] + " = " + std::to_string(character_pet_buffs_entry.numhits)); - update_values.push_back(columns[9] + " = " + std::to_string(character_pet_buffs_entry.rune)); - update_values.push_back(columns[10] + " = " + std::to_string(character_pet_buffs_entry.instrument_mod)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.pet)); + v.push_back(columns[2] + " = " + std::to_string(e.slot)); + v.push_back(columns[3] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[4] + " = " + std::to_string(e.caster_level)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.castername) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.ticsremaining)); + v.push_back(columns[7] + " = " + std::to_string(e.counters)); + v.push_back(columns[8] + " = " + std::to_string(e.numhits)); + v.push_back(columns[9] + " = " + std::to_string(e.rune)); + v.push_back(columns[10] + " = " + std::to_string(e.instrument_mod)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_pet_buffs_entry.char_id + e.char_id ) ); @@ -225,73 +225,73 @@ public: static CharacterPetBuffs InsertOne( Database& db, - CharacterPetBuffs character_pet_buffs_entry + CharacterPetBuffs e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_pet_buffs_entry.char_id)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.pet)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.slot)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.spell_id)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.caster_level)); - insert_values.push_back("'" + EscapeString(character_pet_buffs_entry.castername) + "'"); - insert_values.push_back(std::to_string(character_pet_buffs_entry.ticsremaining)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.counters)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.numhits)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.rune)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.instrument_mod)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.pet)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back("'" + Strings::Escape(e.castername) + "'"); + v.push_back(std::to_string(e.ticsremaining)); + v.push_back(std::to_string(e.counters)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.rune)); + v.push_back(std::to_string(e.instrument_mod)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_pet_buffs_entry.char_id = results.LastInsertedID(); - return character_pet_buffs_entry; + e.char_id = results.LastInsertedID(); + return e; } - character_pet_buffs_entry = NewEntity(); + e = NewEntity(); - return character_pet_buffs_entry; + return e; } static int InsertMany( Database& db, - std::vector character_pet_buffs_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_pet_buffs_entry: character_pet_buffs_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_pet_buffs_entry.char_id)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.pet)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.slot)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.spell_id)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.caster_level)); - insert_values.push_back("'" + EscapeString(character_pet_buffs_entry.castername) + "'"); - insert_values.push_back(std::to_string(character_pet_buffs_entry.ticsremaining)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.counters)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.numhits)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.rune)); - insert_values.push_back(std::to_string(character_pet_buffs_entry.instrument_mod)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.pet)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.caster_level)); + v.push_back("'" + Strings::Escape(e.castername) + "'"); + v.push_back(std::to_string(e.ticsremaining)); + v.push_back(std::to_string(e.counters)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.rune)); + v.push_back(std::to_string(e.instrument_mod)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -312,27 +312,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPetBuffs entry{}; + CharacterPetBuffs e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.spell_id = atoi(row[3]); - entry.caster_level = atoi(row[4]); - entry.castername = row[5] ? row[5] : ""; - entry.ticsremaining = atoi(row[6]); - entry.counters = atoi(row[7]); - entry.numhits = atoi(row[8]); - entry.rune = atoi(row[9]); - entry.instrument_mod = atoi(row[10]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.slot = static_cast(atoi(row[2])); + e.spell_id = static_cast(atoi(row[3])); + e.caster_level = static_cast(atoi(row[4])); + e.castername = row[5] ? row[5] : ""; + e.ticsremaining = static_cast(atoi(row[6])); + e.counters = static_cast(atoi(row[7])); + e.numhits = static_cast(atoi(row[8])); + e.rune = static_cast(atoi(row[9])); + e.instrument_mod = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -347,27 +347,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPetBuffs entry{}; + CharacterPetBuffs e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.spell_id = atoi(row[3]); - entry.caster_level = atoi(row[4]); - entry.castername = row[5] ? row[5] : ""; - entry.ticsremaining = atoi(row[6]); - entry.counters = atoi(row[7]); - entry.numhits = atoi(row[8]); - entry.rune = atoi(row[9]); - entry.instrument_mod = atoi(row[10]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.slot = static_cast(atoi(row[2])); + e.spell_id = static_cast(atoi(row[3])); + e.caster_level = static_cast(atoi(row[4])); + e.castername = row[5] ? row[5] : ""; + e.ticsremaining = static_cast(atoi(row[6])); + e.counters = static_cast(atoi(row[7])); + e.numhits = static_cast(atoi(row[8])); + e.rune = static_cast(atoi(row[9])); + e.instrument_mod = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -392,6 +392,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_character_pet_info_repository.h b/common/repositories/base/base_character_pet_info_repository.h index 63105d84f..dfb5c1ea2 100644 --- a/common/repositories/base/base_character_pet_info_repository.h +++ b/common/repositories/base/base_character_pet_info_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterPetInfoRepository { public: struct CharacterPetInfo { - int char_id; - int pet; + int32_t char_id; + int32_t pet; std::string petname; - int petpower; - int spell_id; - int hp; - int mana; + int32_t petpower; + int32_t spell_id; + int32_t hp; + int32_t mana; float size; - int taunting; + int8_t taunting; }; static std::string PrimaryKey() @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static CharacterPetInfo NewEntity() { - CharacterPetInfo entry{}; + CharacterPetInfo e{}; - entry.char_id = 0; - entry.pet = 0; - entry.petname = ""; - entry.petpower = 0; - entry.spell_id = 0; - entry.hp = 0; - entry.mana = 0; - entry.size = 0; - entry.taunting = 1; + e.char_id = 0; + e.pet = 0; + e.petname = ""; + e.petpower = 0; + e.spell_id = 0; + e.hp = 0; + e.mana = 0; + e.size = 0; + e.taunting = 1; - return entry; + return e; } - static CharacterPetInfo GetCharacterPetInfoEntry( + static CharacterPetInfo GetCharacterPetInfo( const std::vector &character_pet_infos, int character_pet_info_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterPetInfo entry{}; + CharacterPetInfo e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.petname = row[2] ? row[2] : ""; - entry.petpower = atoi(row[3]); - entry.spell_id = atoi(row[4]); - entry.hp = atoi(row[5]); - entry.mana = atoi(row[6]); - entry.size = static_cast(atof(row[7])); - entry.taunting = atoi(row[8]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.petname = row[2] ? row[2] : ""; + e.petpower = static_cast(atoi(row[3])); + e.spell_id = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + e.mana = static_cast(atoi(row[6])); + e.size = strtof(row[7], nullptr); + e.taunting = static_cast(atoi(row[8])); - return entry; + return e; } return NewEntity(); @@ -181,30 +181,30 @@ public: static int UpdateOne( Database& db, - CharacterPetInfo character_pet_info_entry + const CharacterPetInfo &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_pet_info_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_pet_info_entry.pet)); - update_values.push_back(columns[2] + " = '" + EscapeString(character_pet_info_entry.petname) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(character_pet_info_entry.petpower)); - update_values.push_back(columns[4] + " = " + std::to_string(character_pet_info_entry.spell_id)); - update_values.push_back(columns[5] + " = " + std::to_string(character_pet_info_entry.hp)); - update_values.push_back(columns[6] + " = " + std::to_string(character_pet_info_entry.mana)); - update_values.push_back(columns[7] + " = " + std::to_string(character_pet_info_entry.size)); - update_values.push_back(columns[8] + " = " + std::to_string(character_pet_info_entry.taunting)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.pet)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.petname) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.petpower)); + v.push_back(columns[4] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[5] + " = " + std::to_string(e.hp)); + v.push_back(columns[6] + " = " + std::to_string(e.mana)); + v.push_back(columns[7] + " = " + std::to_string(e.size)); + v.push_back(columns[8] + " = " + std::to_string(e.taunting)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_pet_info_entry.char_id + e.char_id ) ); @@ -213,69 +213,69 @@ public: static CharacterPetInfo InsertOne( Database& db, - CharacterPetInfo character_pet_info_entry + CharacterPetInfo e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_pet_info_entry.char_id)); - insert_values.push_back(std::to_string(character_pet_info_entry.pet)); - insert_values.push_back("'" + EscapeString(character_pet_info_entry.petname) + "'"); - insert_values.push_back(std::to_string(character_pet_info_entry.petpower)); - insert_values.push_back(std::to_string(character_pet_info_entry.spell_id)); - insert_values.push_back(std::to_string(character_pet_info_entry.hp)); - insert_values.push_back(std::to_string(character_pet_info_entry.mana)); - insert_values.push_back(std::to_string(character_pet_info_entry.size)); - insert_values.push_back(std::to_string(character_pet_info_entry.taunting)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.pet)); + v.push_back("'" + Strings::Escape(e.petname) + "'"); + v.push_back(std::to_string(e.petpower)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.taunting)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_pet_info_entry.char_id = results.LastInsertedID(); - return character_pet_info_entry; + e.char_id = results.LastInsertedID(); + return e; } - character_pet_info_entry = NewEntity(); + e = NewEntity(); - return character_pet_info_entry; + return e; } static int InsertMany( Database& db, - std::vector character_pet_info_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_pet_info_entry: character_pet_info_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_pet_info_entry.char_id)); - insert_values.push_back(std::to_string(character_pet_info_entry.pet)); - insert_values.push_back("'" + EscapeString(character_pet_info_entry.petname) + "'"); - insert_values.push_back(std::to_string(character_pet_info_entry.petpower)); - insert_values.push_back(std::to_string(character_pet_info_entry.spell_id)); - insert_values.push_back(std::to_string(character_pet_info_entry.hp)); - insert_values.push_back(std::to_string(character_pet_info_entry.mana)); - insert_values.push_back(std::to_string(character_pet_info_entry.size)); - insert_values.push_back(std::to_string(character_pet_info_entry.taunting)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.pet)); + v.push_back("'" + Strings::Escape(e.petname) + "'"); + v.push_back(std::to_string(e.petpower)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.taunting)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -296,25 +296,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPetInfo entry{}; + CharacterPetInfo e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.petname = row[2] ? row[2] : ""; - entry.petpower = atoi(row[3]); - entry.spell_id = atoi(row[4]); - entry.hp = atoi(row[5]); - entry.mana = atoi(row[6]); - entry.size = static_cast(atof(row[7])); - entry.taunting = atoi(row[8]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.petname = row[2] ? row[2] : ""; + e.petpower = static_cast(atoi(row[3])); + e.spell_id = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + e.mana = static_cast(atoi(row[6])); + e.size = strtof(row[7], nullptr); + e.taunting = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -329,25 +329,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPetInfo entry{}; + CharacterPetInfo e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.petname = row[2] ? row[2] : ""; - entry.petpower = atoi(row[3]); - entry.spell_id = atoi(row[4]); - entry.hp = atoi(row[5]); - entry.mana = atoi(row[6]); - entry.size = static_cast(atof(row[7])); - entry.taunting = atoi(row[8]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.petname = row[2] ? row[2] : ""; + e.petpower = static_cast(atoi(row[3])); + e.spell_id = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + e.mana = static_cast(atoi(row[6])); + e.size = strtof(row[7], nullptr); + e.taunting = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -372,6 +372,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H diff --git a/common/repositories/base/base_character_pet_inventory_repository.h b/common/repositories/base/base_character_pet_inventory_repository.h index 0f12b9704..cb364d97c 100644 --- a/common/repositories/base/base_character_pet_inventory_repository.h +++ b/common/repositories/base/base_character_pet_inventory_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterPetInventoryRepository { public: struct CharacterPetInventory { - int char_id; - int pet; - int slot; - int item_id; + int32_t char_id; + int32_t pet; + int32_t slot; + int32_t item_id; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static CharacterPetInventory NewEntity() { - CharacterPetInventory entry{}; + CharacterPetInventory e{}; - entry.char_id = 0; - entry.pet = 0; - entry.slot = 0; - entry.item_id = 0; + e.char_id = 0; + e.pet = 0; + e.slot = 0; + e.item_id = 0; - return entry; + return e; } - static CharacterPetInventory GetCharacterPetInventoryEntry( + static CharacterPetInventory GetCharacterPetInventory( const std::vector &character_pet_inventorys, int character_pet_inventory_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterPetInventory entry{}; + CharacterPetInventory e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.item_id = atoi(row[3]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.slot = static_cast(atoi(row[2])); + e.item_id = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - CharacterPetInventory character_pet_inventory_entry + const CharacterPetInventory &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_pet_inventory_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_pet_inventory_entry.pet)); - update_values.push_back(columns[2] + " = " + std::to_string(character_pet_inventory_entry.slot)); - update_values.push_back(columns[3] + " = " + std::to_string(character_pet_inventory_entry.item_id)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.pet)); + v.push_back(columns[2] + " = " + std::to_string(e.slot)); + v.push_back(columns[3] + " = " + std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_pet_inventory_entry.char_id + e.char_id ) ); @@ -183,59 +183,59 @@ public: static CharacterPetInventory InsertOne( Database& db, - CharacterPetInventory character_pet_inventory_entry + CharacterPetInventory e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_pet_inventory_entry.char_id)); - insert_values.push_back(std::to_string(character_pet_inventory_entry.pet)); - insert_values.push_back(std::to_string(character_pet_inventory_entry.slot)); - insert_values.push_back(std::to_string(character_pet_inventory_entry.item_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.pet)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_pet_inventory_entry.char_id = results.LastInsertedID(); - return character_pet_inventory_entry; + e.char_id = results.LastInsertedID(); + return e; } - character_pet_inventory_entry = NewEntity(); + e = NewEntity(); - return character_pet_inventory_entry; + return e; } static int InsertMany( Database& db, - std::vector character_pet_inventory_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_pet_inventory_entry: character_pet_inventory_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_pet_inventory_entry.char_id)); - insert_values.push_back(std::to_string(character_pet_inventory_entry.pet)); - insert_values.push_back(std::to_string(character_pet_inventory_entry.slot)); - insert_values.push_back(std::to_string(character_pet_inventory_entry.item_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.pet)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPetInventory entry{}; + CharacterPetInventory e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.item_id = atoi(row[3]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.slot = static_cast(atoi(row[2])); + e.item_id = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPetInventory entry{}; + CharacterPetInventory e{}; - entry.char_id = atoi(row[0]); - entry.pet = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.item_id = atoi(row[3]); + e.char_id = static_cast(atoi(row[0])); + e.pet = static_cast(atoi(row[1])); + e.slot = static_cast(atoi(row[2])); + e.item_id = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H diff --git a/common/repositories/base/base_character_potionbelt_repository.h b/common/repositories/base/base_character_potionbelt_repository.h index d8faca194..c31fef642 100644 --- a/common/repositories/base/base_character_potionbelt_repository.h +++ b/common/repositories/base/base_character_potionbelt_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterPotionbeltRepository { public: struct CharacterPotionbelt { - int id; - int potion_id; - int item_id; - int icon; + uint32_t id; + uint8_t potion_id; + uint32_t item_id; + uint32_t icon; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static CharacterPotionbelt NewEntity() { - CharacterPotionbelt entry{}; + CharacterPotionbelt e{}; - entry.id = 0; - entry.potion_id = 0; - entry.item_id = 0; - entry.icon = 0; + e.id = 0; + e.potion_id = 0; + e.item_id = 0; + e.icon = 0; - return entry; + return e; } - static CharacterPotionbelt GetCharacterPotionbeltEntry( + static CharacterPotionbelt GetCharacterPotionbelt( const std::vector &character_potionbelts, int character_potionbelt_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterPotionbelt entry{}; + CharacterPotionbelt e{}; - entry.id = atoi(row[0]); - entry.potion_id = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.icon = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.potion_id = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.icon = static_cast(strtoul(row[3], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - CharacterPotionbelt character_potionbelt_entry + const CharacterPotionbelt &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_potionbelt_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(character_potionbelt_entry.potion_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_potionbelt_entry.item_id)); - update_values.push_back(columns[3] + " = " + std::to_string(character_potionbelt_entry.icon)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.potion_id)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + v.push_back(columns[3] + " = " + std::to_string(e.icon)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_potionbelt_entry.id + e.id ) ); @@ -183,59 +183,59 @@ public: static CharacterPotionbelt InsertOne( Database& db, - CharacterPotionbelt character_potionbelt_entry + CharacterPotionbelt e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_potionbelt_entry.id)); - insert_values.push_back(std::to_string(character_potionbelt_entry.potion_id)); - insert_values.push_back(std::to_string(character_potionbelt_entry.item_id)); - insert_values.push_back(std::to_string(character_potionbelt_entry.icon)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.potion_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.icon)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_potionbelt_entry.id = results.LastInsertedID(); - return character_potionbelt_entry; + e.id = results.LastInsertedID(); + return e; } - character_potionbelt_entry = NewEntity(); + e = NewEntity(); - return character_potionbelt_entry; + return e; } static int InsertMany( Database& db, - std::vector character_potionbelt_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_potionbelt_entry: character_potionbelt_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_potionbelt_entry.id)); - insert_values.push_back(std::to_string(character_potionbelt_entry.potion_id)); - insert_values.push_back(std::to_string(character_potionbelt_entry.item_id)); - insert_values.push_back(std::to_string(character_potionbelt_entry.icon)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.potion_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.icon)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPotionbelt entry{}; + CharacterPotionbelt e{}; - entry.id = atoi(row[0]); - entry.potion_id = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.icon = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.potion_id = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.icon = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterPotionbelt entry{}; + CharacterPotionbelt e{}; - entry.id = atoi(row[0]); - entry.potion_id = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.icon = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.potion_id = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.icon = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H diff --git a/common/repositories/base/base_character_skills_repository.h b/common/repositories/base/base_character_skills_repository.h index 0bd5eac23..87c3c1778 100644 --- a/common/repositories/base/base_character_skills_repository.h +++ b/common/repositories/base/base_character_skills_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterSkillsRepository { public: struct CharacterSkills { - int id; - int skill_id; - int value; + uint32_t id; + uint16_t skill_id; + uint16_t value; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterSkills NewEntity() { - CharacterSkills entry{}; + CharacterSkills e{}; - entry.id = 0; - entry.skill_id = 0; - entry.value = 0; + e.id = 0; + e.skill_id = 0; + e.value = 0; - return entry; + return e; } - static CharacterSkills GetCharacterSkillsEntry( + static CharacterSkills GetCharacterSkills( const std::vector &character_skillss, int character_skills_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterSkills entry{}; + CharacterSkills e{}; - entry.id = atoi(row[0]); - entry.skill_id = atoi(row[1]); - entry.value = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.skill_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,23 +151,23 @@ public: static int UpdateOne( Database& db, - CharacterSkills character_skills_entry + const CharacterSkills &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_skills_entry.skill_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_skills_entry.value)); + v.push_back(columns[1] + " = " + std::to_string(e.skill_id)); + v.push_back(columns[2] + " = " + std::to_string(e.value)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_skills_entry.id + e.id ) ); @@ -176,57 +176,57 @@ public: static CharacterSkills InsertOne( Database& db, - CharacterSkills character_skills_entry + CharacterSkills e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_skills_entry.id)); - insert_values.push_back(std::to_string(character_skills_entry.skill_id)); - insert_values.push_back(std::to_string(character_skills_entry.value)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.skill_id)); + v.push_back(std::to_string(e.value)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_skills_entry.id = results.LastInsertedID(); - return character_skills_entry; + e.id = results.LastInsertedID(); + return e; } - character_skills_entry = NewEntity(); + e = NewEntity(); - return character_skills_entry; + return e; } static int InsertMany( Database& db, - std::vector character_skills_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_skills_entry: character_skills_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_skills_entry.id)); - insert_values.push_back(std::to_string(character_skills_entry.skill_id)); - insert_values.push_back(std::to_string(character_skills_entry.value)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.skill_id)); + v.push_back(std::to_string(e.value)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -247,19 +247,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterSkills entry{}; + CharacterSkills e{}; - entry.id = atoi(row[0]); - entry.skill_id = atoi(row[1]); - entry.value = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.skill_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -274,19 +274,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterSkills entry{}; + CharacterSkills e{}; - entry.id = atoi(row[0]); - entry.skill_id = atoi(row[1]); - entry.value = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.skill_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -311,6 +311,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H diff --git a/common/repositories/base/base_character_spells_repository.h b/common/repositories/base/base_character_spells_repository.h index f9465f3df..11514f84b 100644 --- a/common/repositories/base/base_character_spells_repository.h +++ b/common/repositories/base/base_character_spells_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterSpellsRepository { public: struct CharacterSpells { - int id; - int slot_id; - int spell_id; + uint32_t id; + uint16_t slot_id; + uint16_t spell_id; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CharacterSpells NewEntity() { - CharacterSpells entry{}; + CharacterSpells e{}; - entry.id = 0; - entry.slot_id = 0; - entry.spell_id = 0; + e.id = 0; + e.slot_id = 0; + e.spell_id = 0; - return entry; + return e; } - static CharacterSpells GetCharacterSpellsEntry( + static CharacterSpells GetCharacterSpells( const std::vector &character_spellss, int character_spells_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterSpells entry{}; + CharacterSpells e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,23 +151,23 @@ public: static int UpdateOne( Database& db, - CharacterSpells character_spells_entry + const CharacterSpells &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_spells_entry.slot_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_spells_entry.spell_id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_spells_entry.id + e.id ) ); @@ -176,57 +176,57 @@ public: static CharacterSpells InsertOne( Database& db, - CharacterSpells character_spells_entry + CharacterSpells e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_spells_entry.id)); - insert_values.push_back(std::to_string(character_spells_entry.slot_id)); - insert_values.push_back(std::to_string(character_spells_entry.spell_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.spell_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_spells_entry.id = results.LastInsertedID(); - return character_spells_entry; + e.id = results.LastInsertedID(); + return e; } - character_spells_entry = NewEntity(); + e = NewEntity(); - return character_spells_entry; + return e; } static int InsertMany( Database& db, - std::vector character_spells_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_spells_entry: character_spells_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_spells_entry.id)); - insert_values.push_back(std::to_string(character_spells_entry.slot_id)); - insert_values.push_back(std::to_string(character_spells_entry.spell_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.spell_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -247,19 +247,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterSpells entry{}; + CharacterSpells e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -274,19 +274,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterSpells entry{}; + CharacterSpells e{}; - entry.id = atoi(row[0]); - entry.slot_id = atoi(row[1]); - entry.spell_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -311,6 +311,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_character_task_timers_repository.h b/common/repositories/base/base_character_task_timers_repository.h index 73ea29182..6c9e76b19 100644 --- a/common/repositories/base/base_character_task_timers_repository.h +++ b/common/repositories/base/base_character_task_timers_repository.h @@ -13,17 +13,18 @@ #define EQEMU_BASE_CHARACTER_TASK_TIMERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterTaskTimersRepository { public: struct CharacterTaskTimers { - int id; - int character_id; - int task_id; - int timer_type; - time_t expire_time; + uint32_t id; + uint32_t character_id; + uint32_t task_id; + int32_t timer_type; + int32_t timer_group; + time_t expire_time; }; static std::string PrimaryKey() @@ -38,6 +39,7 @@ public: "character_id", "task_id", "timer_type", + "timer_group", "expire_time", }; } @@ -49,18 +51,19 @@ public: "character_id", "task_id", "timer_type", + "timer_group", "UNIX_TIMESTAMP(expire_time)", }; } static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +91,19 @@ public: static CharacterTaskTimers NewEntity() { - CharacterTaskTimers entry{}; + CharacterTaskTimers e{}; - entry.id = 0; - entry.character_id = 0; - entry.task_id = 0; - entry.timer_type = 0; - entry.expire_time = std::time(nullptr); + e.id = 0; + e.character_id = 0; + e.task_id = 0; + e.timer_type = 0; + e.timer_group = 0; + e.expire_time = std::time(nullptr); - return entry; + return e; } - static CharacterTaskTimers GetCharacterTaskTimersEntry( + static CharacterTaskTimers GetCharacterTaskTimers( const std::vector &character_task_timerss, int character_task_timers_id ) @@ -128,15 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterTaskTimers entry{}; + CharacterTaskTimers e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.task_id = atoi(row[2]); - entry.timer_type = atoi(row[3]); - entry.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.task_id = static_cast(strtoul(row[2], nullptr, 10)); + e.timer_type = static_cast(atoi(row[3])); + e.timer_group = static_cast(atoi(row[4])); + e.expire_time = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -161,25 +166,26 @@ public: static int UpdateOne( Database& db, - CharacterTaskTimers character_task_timers_entry + const CharacterTaskTimers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(character_task_timers_entry.character_id)); - update_values.push_back(columns[2] + " = " + std::to_string(character_task_timers_entry.task_id)); - update_values.push_back(columns[3] + " = " + std::to_string(character_task_timers_entry.timer_type)); - update_values.push_back(columns[4] + " = FROM_UNIXTIME(" + (character_task_timers_entry.expire_time > 0 ? std::to_string(character_task_timers_entry.expire_time) : "null") + ")"); + v.push_back(columns[1] + " = " + std::to_string(e.character_id)); + v.push_back(columns[2] + " = " + std::to_string(e.task_id)); + v.push_back(columns[3] + " = " + std::to_string(e.timer_type)); + v.push_back(columns[4] + " = " + std::to_string(e.timer_group)); + v.push_back(columns[5] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_task_timers_entry.id + e.id ) ); @@ -188,61 +194,63 @@ public: static CharacterTaskTimers InsertOne( Database& db, - CharacterTaskTimers character_task_timers_entry + CharacterTaskTimers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_task_timers_entry.id)); - insert_values.push_back(std::to_string(character_task_timers_entry.character_id)); - insert_values.push_back(std::to_string(character_task_timers_entry.task_id)); - insert_values.push_back(std::to_string(character_task_timers_entry.timer_type)); - insert_values.push_back("FROM_UNIXTIME(" + (character_task_timers_entry.expire_time > 0 ? std::to_string(character_task_timers_entry.expire_time) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.task_id)); + v.push_back(std::to_string(e.timer_type)); + v.push_back(std::to_string(e.timer_group)); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_task_timers_entry.id = results.LastInsertedID(); - return character_task_timers_entry; + e.id = results.LastInsertedID(); + return e; } - character_task_timers_entry = NewEntity(); + e = NewEntity(); - return character_task_timers_entry; + return e; } static int InsertMany( Database& db, - std::vector character_task_timers_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_task_timers_entry: character_task_timers_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_task_timers_entry.id)); - insert_values.push_back(std::to_string(character_task_timers_entry.character_id)); - insert_values.push_back(std::to_string(character_task_timers_entry.task_id)); - insert_values.push_back(std::to_string(character_task_timers_entry.timer_type)); - insert_values.push_back("FROM_UNIXTIME(" + (character_task_timers_entry.expire_time > 0 ? std::to_string(character_task_timers_entry.expire_time) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.task_id)); + v.push_back(std::to_string(e.timer_type)); + v.push_back(std::to_string(e.timer_group)); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -263,21 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterTaskTimers entry{}; + CharacterTaskTimers e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.task_id = atoi(row[2]); - entry.timer_type = atoi(row[3]); - entry.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.task_id = static_cast(strtoul(row[2], nullptr, 10)); + e.timer_type = static_cast(atoi(row[3])); + e.timer_group = static_cast(atoi(row[4])); + e.expire_time = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -292,21 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterTaskTimers entry{}; + CharacterTaskTimers e{}; - entry.id = atoi(row[0]); - entry.character_id = atoi(row[1]); - entry.task_id = atoi(row[2]); - entry.timer_type = atoi(row[3]); - entry.expire_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.character_id = static_cast(strtoul(row[1], nullptr, 10)); + e.task_id = static_cast(strtoul(row[2], nullptr, 10)); + e.timer_type = static_cast(atoi(row[3])); + e.timer_group = static_cast(atoi(row[4])); + e.expire_time = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -331,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_TASK_TIMERS_REPOSITORY_H diff --git a/common/repositories/base/base_character_tasks_repository.h b/common/repositories/base/base_character_tasks_repository.h index 251389557..070767ff0 100644 --- a/common/repositories/base/base_character_tasks_repository.h +++ b/common/repositories/base/base_character_tasks_repository.h @@ -13,17 +13,18 @@ #define EQEMU_BASE_CHARACTER_TASKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCharacterTasksRepository { public: struct CharacterTasks { - int charid; - int taskid; - int slot; - int type; - int acceptedtime; + uint32_t charid; + uint32_t taskid; + uint32_t slot; + int8_t type; + uint32_t acceptedtime; + int8_t was_rewarded; }; static std::string PrimaryKey() @@ -39,6 +40,7 @@ public: "slot", "type", "acceptedtime", + "was_rewarded", }; } @@ -50,17 +52,18 @@ public: "slot", "type", "acceptedtime", + "was_rewarded", }; } static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +91,19 @@ public: static CharacterTasks NewEntity() { - CharacterTasks entry{}; + CharacterTasks e{}; - entry.charid = 0; - entry.taskid = 0; - entry.slot = 0; - entry.type = 0; - entry.acceptedtime = 0; + e.charid = 0; + e.taskid = 0; + e.slot = 0; + e.type = 0; + e.acceptedtime = 0; + e.was_rewarded = 0; - return entry; + return e; } - static CharacterTasks GetCharacterTasksEntry( + static CharacterTasks GetCharacterTasks( const std::vector &character_taskss, int character_tasks_id ) @@ -128,15 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CharacterTasks entry{}; + CharacterTasks e{}; - entry.charid = atoi(row[0]); - entry.taskid = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.type = atoi(row[3]); - entry.acceptedtime = atoi(row[4]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); + e.slot = static_cast(strtoul(row[2], nullptr, 10)); + e.type = static_cast(atoi(row[3])); + e.acceptedtime = static_cast(strtoul(row[4], nullptr, 10)); + e.was_rewarded = static_cast(atoi(row[5])); - return entry; + return e; } return NewEntity(); @@ -161,26 +166,27 @@ public: static int UpdateOne( Database& db, - CharacterTasks character_tasks_entry + const CharacterTasks &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(character_tasks_entry.charid)); - update_values.push_back(columns[1] + " = " + std::to_string(character_tasks_entry.taskid)); - update_values.push_back(columns[2] + " = " + std::to_string(character_tasks_entry.slot)); - update_values.push_back(columns[3] + " = " + std::to_string(character_tasks_entry.type)); - update_values.push_back(columns[4] + " = " + std::to_string(character_tasks_entry.acceptedtime)); + v.push_back(columns[0] + " = " + std::to_string(e.charid)); + v.push_back(columns[1] + " = " + std::to_string(e.taskid)); + v.push_back(columns[2] + " = " + std::to_string(e.slot)); + v.push_back(columns[3] + " = " + std::to_string(e.type)); + v.push_back(columns[4] + " = " + std::to_string(e.acceptedtime)); + v.push_back(columns[5] + " = " + std::to_string(e.was_rewarded)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - character_tasks_entry.charid + e.charid ) ); @@ -189,61 +195,63 @@ public: static CharacterTasks InsertOne( Database& db, - CharacterTasks character_tasks_entry + CharacterTasks e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(character_tasks_entry.charid)); - insert_values.push_back(std::to_string(character_tasks_entry.taskid)); - insert_values.push_back(std::to_string(character_tasks_entry.slot)); - insert_values.push_back(std::to_string(character_tasks_entry.type)); - insert_values.push_back(std::to_string(character_tasks_entry.acceptedtime)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.acceptedtime)); + v.push_back(std::to_string(e.was_rewarded)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - character_tasks_entry.charid = results.LastInsertedID(); - return character_tasks_entry; + e.charid = results.LastInsertedID(); + return e; } - character_tasks_entry = NewEntity(); + e = NewEntity(); - return character_tasks_entry; + return e; } static int InsertMany( Database& db, - std::vector character_tasks_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &character_tasks_entry: character_tasks_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(character_tasks_entry.charid)); - insert_values.push_back(std::to_string(character_tasks_entry.taskid)); - insert_values.push_back(std::to_string(character_tasks_entry.slot)); - insert_values.push_back(std::to_string(character_tasks_entry.type)); - insert_values.push_back(std::to_string(character_tasks_entry.acceptedtime)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.acceptedtime)); + v.push_back(std::to_string(e.was_rewarded)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterTasks entry{}; + CharacterTasks e{}; - entry.charid = atoi(row[0]); - entry.taskid = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.type = atoi(row[3]); - entry.acceptedtime = atoi(row[4]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); + e.slot = static_cast(strtoul(row[2], nullptr, 10)); + e.type = static_cast(atoi(row[3])); + e.acceptedtime = static_cast(strtoul(row[4], nullptr, 10)); + e.was_rewarded = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CharacterTasks entry{}; + CharacterTasks e{}; - entry.charid = atoi(row[0]); - entry.taskid = atoi(row[1]); - entry.slot = atoi(row[2]); - entry.type = atoi(row[3]); - entry.acceptedtime = atoi(row[4]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); + e.slot = static_cast(strtoul(row[2], nullptr, 10)); + e.type = static_cast(atoi(row[3])); + e.acceptedtime = static_cast(strtoul(row[4], nullptr, 10)); + e.was_rewarded = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CHARACTER_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_chatchannel_reserved_names_repository.h b/common/repositories/base/base_chatchannel_reserved_names_repository.h new file mode 100644 index 000000000..df5cb9241 --- /dev/null +++ b/common/repositories/base/base_chatchannel_reserved_names_repository.h @@ -0,0 +1,334 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H +#define EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseChatchannelReservedNamesRepository { +public: + struct ChatchannelReservedNames { + int32_t id; + std::string name; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "name", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "name", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("chatchannel_reserved_names"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static ChatchannelReservedNames NewEntity() + { + ChatchannelReservedNames e{}; + + e.id = 0; + e.name = ""; + + return e; + } + + static ChatchannelReservedNames GetChatchannelReservedNames( + const std::vector &chatchannel_reserved_namess, + int chatchannel_reserved_names_id + ) + { + for (auto &chatchannel_reserved_names : chatchannel_reserved_namess) { + if (chatchannel_reserved_names.id == chatchannel_reserved_names_id) { + return chatchannel_reserved_names; + } + } + + return NewEntity(); + } + + static ChatchannelReservedNames FindOne( + Database& db, + int chatchannel_reserved_names_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + chatchannel_reserved_names_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + ChatchannelReservedNames e{}; + + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int chatchannel_reserved_names_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + chatchannel_reserved_names_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const ChatchannelReservedNames &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static ChatchannelReservedNames InsertOne( + Database& db, + ChatchannelReservedNames e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + ChatchannelReservedNames e{}; + + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + ChatchannelReservedNames e{}; + + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H diff --git a/common/repositories/base/base_chatchannels_repository.h b/common/repositories/base/base_chatchannels_repository.h new file mode 100644 index 000000000..a767d589a --- /dev/null +++ b/common/repositories/base/base_chatchannels_repository.h @@ -0,0 +1,364 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_CHATCHANNELS_REPOSITORY_H +#define EQEMU_BASE_CHATCHANNELS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseChatchannelsRepository { +public: + struct Chatchannels { + int32_t id; + std::string name; + std::string owner; + std::string password; + int32_t minstatus; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "name", + "owner", + "password", + "minstatus", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "name", + "owner", + "password", + "minstatus", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("chatchannels"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static Chatchannels NewEntity() + { + Chatchannels e{}; + + e.id = 0; + e.name = ""; + e.owner = ""; + e.password = ""; + e.minstatus = 0; + + return e; + } + + static Chatchannels GetChatchannels( + const std::vector &chatchannelss, + int chatchannels_id + ) + { + for (auto &chatchannels : chatchannelss) { + if (chatchannels.id == chatchannels_id) { + return chatchannels; + } + } + + return NewEntity(); + } + + static Chatchannels FindOne( + Database& db, + int chatchannels_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + chatchannels_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + Chatchannels e{}; + + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.owner = row[2] ? row[2] : ""; + e.password = row[3] ? row[3] : ""; + e.minstatus = static_cast(atoi(row[4])); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int chatchannels_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + chatchannels_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const Chatchannels &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.owner) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.password) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.minstatus)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static Chatchannels InsertOne( + Database& db, + Chatchannels e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.owner) + "'"); + v.push_back("'" + Strings::Escape(e.password) + "'"); + v.push_back(std::to_string(e.minstatus)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.owner) + "'"); + v.push_back("'" + Strings::Escape(e.password) + "'"); + v.push_back(std::to_string(e.minstatus)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + Chatchannels e{}; + + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.owner = row[2] ? row[2] : ""; + e.password = row[3] ? row[3] : ""; + e.minstatus = static_cast(atoi(row[4])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + Chatchannels e{}; + + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.owner = row[2] ? row[2] : ""; + e.password = row[3] ? row[3] : ""; + e.minstatus = static_cast(atoi(row[4])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_CHATCHANNELS_REPOSITORY_H diff --git a/common/repositories/base/base_completed_shared_task_activity_state_repository.h b/common/repositories/base/base_completed_shared_task_activity_state_repository.h index 83244b31d..e2225e8ea 100644 --- a/common/repositories/base/base_completed_shared_task_activity_state_repository.h +++ b/common/repositories/base/base_completed_shared_task_activity_state_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCompletedSharedTaskActivityStateRepository { public: struct CompletedSharedTaskActivityState { - int64 shared_task_id; - int activity_id; - int done_count; - time_t updated_time; - time_t completed_time; + int64_t shared_task_id; + int32_t activity_id; + int32_t done_count; + time_t updated_time; + time_t completed_time; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static CompletedSharedTaskActivityState NewEntity() { - CompletedSharedTaskActivityState entry{}; + CompletedSharedTaskActivityState e{}; - entry.shared_task_id = 0; - entry.activity_id = 0; - entry.done_count = 0; - entry.updated_time = 0; - entry.completed_time = 0; + e.shared_task_id = 0; + e.activity_id = 0; + e.done_count = 0; + e.updated_time = 0; + e.completed_time = 0; - return entry; + return e; } - static CompletedSharedTaskActivityState GetCompletedSharedTaskActivityStateEntry( + static CompletedSharedTaskActivityState GetCompletedSharedTaskActivityState( const std::vector &completed_shared_task_activity_states, int completed_shared_task_activity_state_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CompletedSharedTaskActivityState entry{}; + CompletedSharedTaskActivityState e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.activity_id = atoi(row[1]); - entry.done_count = atoi(row[2]); - entry.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.activity_id = static_cast(atoi(row[1])); + e.done_count = static_cast(atoi(row[2])); + e.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - CompletedSharedTaskActivityState completed_shared_task_activity_state_entry + const CompletedSharedTaskActivityState &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(completed_shared_task_activity_state_entry.shared_task_id)); - update_values.push_back(columns[1] + " = " + std::to_string(completed_shared_task_activity_state_entry.activity_id)); - update_values.push_back(columns[2] + " = " + std::to_string(completed_shared_task_activity_state_entry.done_count)); - update_values.push_back(columns[3] + " = FROM_UNIXTIME(" + (completed_shared_task_activity_state_entry.updated_time > 0 ? std::to_string(completed_shared_task_activity_state_entry.updated_time) : "null") + ")"); - update_values.push_back(columns[4] + " = FROM_UNIXTIME(" + (completed_shared_task_activity_state_entry.completed_time > 0 ? std::to_string(completed_shared_task_activity_state_entry.completed_time) : "null") + ")"); + v.push_back(columns[0] + " = " + std::to_string(e.shared_task_id)); + v.push_back(columns[1] + " = " + std::to_string(e.activity_id)); + v.push_back(columns[2] + " = " + std::to_string(e.done_count)); + v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.updated_time > 0 ? std::to_string(e.updated_time) : "null") + ")"); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.completed_time > 0 ? std::to_string(e.completed_time) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - completed_shared_task_activity_state_entry.shared_task_id + e.shared_task_id ) ); @@ -189,61 +189,61 @@ public: static CompletedSharedTaskActivityState InsertOne( Database& db, - CompletedSharedTaskActivityState completed_shared_task_activity_state_entry + CompletedSharedTaskActivityState e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(completed_shared_task_activity_state_entry.shared_task_id)); - insert_values.push_back(std::to_string(completed_shared_task_activity_state_entry.activity_id)); - insert_values.push_back(std::to_string(completed_shared_task_activity_state_entry.done_count)); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_task_activity_state_entry.updated_time > 0 ? std::to_string(completed_shared_task_activity_state_entry.updated_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_task_activity_state_entry.completed_time > 0 ? std::to_string(completed_shared_task_activity_state_entry.completed_time) : "null") + ")"); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.activity_id)); + v.push_back(std::to_string(e.done_count)); + v.push_back("FROM_UNIXTIME(" + (e.updated_time > 0 ? std::to_string(e.updated_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completed_time > 0 ? std::to_string(e.completed_time) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - completed_shared_task_activity_state_entry.shared_task_id = results.LastInsertedID(); - return completed_shared_task_activity_state_entry; + e.shared_task_id = results.LastInsertedID(); + return e; } - completed_shared_task_activity_state_entry = NewEntity(); + e = NewEntity(); - return completed_shared_task_activity_state_entry; + return e; } static int InsertMany( Database& db, - std::vector completed_shared_task_activity_state_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &completed_shared_task_activity_state_entry: completed_shared_task_activity_state_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(completed_shared_task_activity_state_entry.shared_task_id)); - insert_values.push_back(std::to_string(completed_shared_task_activity_state_entry.activity_id)); - insert_values.push_back(std::to_string(completed_shared_task_activity_state_entry.done_count)); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_task_activity_state_entry.updated_time > 0 ? std::to_string(completed_shared_task_activity_state_entry.updated_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_task_activity_state_entry.completed_time > 0 ? std::to_string(completed_shared_task_activity_state_entry.completed_time) : "null") + ")"); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.activity_id)); + v.push_back(std::to_string(e.done_count)); + v.push_back("FROM_UNIXTIME(" + (e.updated_time > 0 ? std::to_string(e.updated_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completed_time > 0 ? std::to_string(e.completed_time) : "null") + ")"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedSharedTaskActivityState entry{}; + CompletedSharedTaskActivityState e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.activity_id = atoi(row[1]); - entry.done_count = atoi(row[2]); - entry.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.activity_id = static_cast(atoi(row[1])); + e.done_count = static_cast(atoi(row[2])); + e.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedSharedTaskActivityState entry{}; + CompletedSharedTaskActivityState e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.activity_id = atoi(row[1]); - entry.done_count = atoi(row[2]); - entry.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.activity_id = static_cast(atoi(row[1])); + e.done_count = static_cast(atoi(row[2])); + e.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H diff --git a/common/repositories/base/base_completed_shared_task_members_repository.h b/common/repositories/base/base_completed_shared_task_members_repository.h index 05f72ce3a..a58dc0f00 100644 --- a/common/repositories/base/base_completed_shared_task_members_repository.h +++ b/common/repositories/base/base_completed_shared_task_members_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCompletedSharedTaskMembersRepository { public: struct CompletedSharedTaskMembers { - int64 shared_task_id; - int64 character_id; - int is_leader; + int64_t shared_task_id; + int64_t character_id; + int8_t is_leader; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static CompletedSharedTaskMembers NewEntity() { - CompletedSharedTaskMembers entry{}; + CompletedSharedTaskMembers e{}; - entry.shared_task_id = 0; - entry.character_id = 0; - entry.is_leader = 0; + e.shared_task_id = 0; + e.character_id = 0; + e.is_leader = 0; - return entry; + return e; } - static CompletedSharedTaskMembers GetCompletedSharedTaskMembersEntry( + static CompletedSharedTaskMembers GetCompletedSharedTaskMembers( const std::vector &completed_shared_task_memberss, int completed_shared_task_members_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CompletedSharedTaskMembers entry{}; + CompletedSharedTaskMembers e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.character_id = strtoll(row[1], nullptr, 10); - entry.is_leader = atoi(row[2]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.character_id = strtoll(row[1], nullptr, 10); + e.is_leader = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - CompletedSharedTaskMembers completed_shared_task_members_entry + const CompletedSharedTaskMembers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(completed_shared_task_members_entry.shared_task_id)); - update_values.push_back(columns[1] + " = " + std::to_string(completed_shared_task_members_entry.character_id)); - update_values.push_back(columns[2] + " = " + std::to_string(completed_shared_task_members_entry.is_leader)); + v.push_back(columns[0] + " = " + std::to_string(e.shared_task_id)); + v.push_back(columns[1] + " = " + std::to_string(e.character_id)); + v.push_back(columns[2] + " = " + std::to_string(e.is_leader)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - completed_shared_task_members_entry.shared_task_id + e.shared_task_id ) ); @@ -177,57 +177,57 @@ public: static CompletedSharedTaskMembers InsertOne( Database& db, - CompletedSharedTaskMembers completed_shared_task_members_entry + CompletedSharedTaskMembers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(completed_shared_task_members_entry.shared_task_id)); - insert_values.push_back(std::to_string(completed_shared_task_members_entry.character_id)); - insert_values.push_back(std::to_string(completed_shared_task_members_entry.is_leader)); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.is_leader)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - completed_shared_task_members_entry.shared_task_id = results.LastInsertedID(); - return completed_shared_task_members_entry; + e.shared_task_id = results.LastInsertedID(); + return e; } - completed_shared_task_members_entry = NewEntity(); + e = NewEntity(); - return completed_shared_task_members_entry; + return e; } static int InsertMany( Database& db, - std::vector completed_shared_task_members_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &completed_shared_task_members_entry: completed_shared_task_members_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(completed_shared_task_members_entry.shared_task_id)); - insert_values.push_back(std::to_string(completed_shared_task_members_entry.character_id)); - insert_values.push_back(std::to_string(completed_shared_task_members_entry.is_leader)); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.is_leader)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedSharedTaskMembers entry{}; + CompletedSharedTaskMembers e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.character_id = strtoll(row[1], nullptr, 10); - entry.is_leader = atoi(row[2]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.character_id = strtoll(row[1], nullptr, 10); + e.is_leader = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedSharedTaskMembers entry{}; + CompletedSharedTaskMembers e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.character_id = strtoll(row[1], nullptr, 10); - entry.is_leader = atoi(row[2]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.character_id = strtoll(row[1], nullptr, 10); + e.is_leader = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_completed_shared_tasks_repository.h b/common/repositories/base/base_completed_shared_tasks_repository.h index 9c1e3a87d..6ba398908 100644 --- a/common/repositories/base/base_completed_shared_tasks_repository.h +++ b/common/repositories/base/base_completed_shared_tasks_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_COMPLETED_SHARED_TASKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCompletedSharedTasksRepository { public: struct CompletedSharedTasks { - int64 id; - int task_id; - time_t accepted_time; - time_t expire_time; - time_t completion_time; - int is_locked; + int64_t id; + int32_t task_id; + time_t accepted_time; + time_t expire_time; + time_t completion_time; + int8_t is_locked; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static CompletedSharedTasks NewEntity() { - CompletedSharedTasks entry{}; + CompletedSharedTasks e{}; - entry.id = 0; - entry.task_id = 0; - entry.accepted_time = 0; - entry.expire_time = 0; - entry.completion_time = 0; - entry.is_locked = 0; + e.id = 0; + e.task_id = 0; + e.accepted_time = 0; + e.expire_time = 0; + e.completion_time = 0; + e.is_locked = 0; - return entry; + return e; } - static CompletedSharedTasks GetCompletedSharedTasksEntry( + static CompletedSharedTasks GetCompletedSharedTasks( const std::vector &completed_shared_taskss, int completed_shared_tasks_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CompletedSharedTasks entry{}; + CompletedSharedTasks e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.task_id = atoi(row[1]); - entry.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.is_locked = atoi(row[5]); + e.id = strtoll(row[0], nullptr, 10); + e.task_id = static_cast(atoi(row[1])); + e.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.is_locked = static_cast(atoi(row[5])); - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - CompletedSharedTasks completed_shared_tasks_entry + const CompletedSharedTasks &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(completed_shared_tasks_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(completed_shared_tasks_entry.task_id)); - update_values.push_back(columns[2] + " = FROM_UNIXTIME(" + (completed_shared_tasks_entry.accepted_time > 0 ? std::to_string(completed_shared_tasks_entry.accepted_time) : "null") + ")"); - update_values.push_back(columns[3] + " = FROM_UNIXTIME(" + (completed_shared_tasks_entry.expire_time > 0 ? std::to_string(completed_shared_tasks_entry.expire_time) : "null") + ")"); - update_values.push_back(columns[4] + " = FROM_UNIXTIME(" + (completed_shared_tasks_entry.completion_time > 0 ? std::to_string(completed_shared_tasks_entry.completion_time) : "null") + ")"); - update_values.push_back(columns[5] + " = " + std::to_string(completed_shared_tasks_entry.is_locked)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.task_id)); + v.push_back(columns[2] + " = FROM_UNIXTIME(" + (e.accepted_time > 0 ? std::to_string(e.accepted_time) : "null") + ")"); + v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.completion_time > 0 ? std::to_string(e.completion_time) : "null") + ")"); + v.push_back(columns[5] + " = " + std::to_string(e.is_locked)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - completed_shared_tasks_entry.id + e.id ) ); @@ -195,63 +195,63 @@ public: static CompletedSharedTasks InsertOne( Database& db, - CompletedSharedTasks completed_shared_tasks_entry + CompletedSharedTasks e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(completed_shared_tasks_entry.id)); - insert_values.push_back(std::to_string(completed_shared_tasks_entry.task_id)); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_tasks_entry.accepted_time > 0 ? std::to_string(completed_shared_tasks_entry.accepted_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_tasks_entry.expire_time > 0 ? std::to_string(completed_shared_tasks_entry.expire_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_tasks_entry.completion_time > 0 ? std::to_string(completed_shared_tasks_entry.completion_time) : "null") + ")"); - insert_values.push_back(std::to_string(completed_shared_tasks_entry.is_locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.task_id)); + v.push_back("FROM_UNIXTIME(" + (e.accepted_time > 0 ? std::to_string(e.accepted_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completion_time > 0 ? std::to_string(e.completion_time) : "null") + ")"); + v.push_back(std::to_string(e.is_locked)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - completed_shared_tasks_entry.id = results.LastInsertedID(); - return completed_shared_tasks_entry; + e.id = results.LastInsertedID(); + return e; } - completed_shared_tasks_entry = NewEntity(); + e = NewEntity(); - return completed_shared_tasks_entry; + return e; } static int InsertMany( Database& db, - std::vector completed_shared_tasks_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &completed_shared_tasks_entry: completed_shared_tasks_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(completed_shared_tasks_entry.id)); - insert_values.push_back(std::to_string(completed_shared_tasks_entry.task_id)); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_tasks_entry.accepted_time > 0 ? std::to_string(completed_shared_tasks_entry.accepted_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_tasks_entry.expire_time > 0 ? std::to_string(completed_shared_tasks_entry.expire_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (completed_shared_tasks_entry.completion_time > 0 ? std::to_string(completed_shared_tasks_entry.completion_time) : "null") + ")"); - insert_values.push_back(std::to_string(completed_shared_tasks_entry.is_locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.task_id)); + v.push_back("FROM_UNIXTIME(" + (e.accepted_time > 0 ? std::to_string(e.accepted_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completion_time > 0 ? std::to_string(e.completion_time) : "null") + ")"); + v.push_back(std::to_string(e.is_locked)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedSharedTasks entry{}; + CompletedSharedTasks e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.task_id = atoi(row[1]); - entry.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.is_locked = atoi(row[5]); + e.id = strtoll(row[0], nullptr, 10); + e.task_id = static_cast(atoi(row[1])); + e.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.is_locked = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedSharedTasks entry{}; + CompletedSharedTasks e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.task_id = atoi(row[1]); - entry.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.is_locked = atoi(row[5]); + e.id = strtoll(row[0], nullptr, 10); + e.task_id = static_cast(atoi(row[1])); + e.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.is_locked = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_COMPLETED_SHARED_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_completed_tasks_repository.h b/common/repositories/base/base_completed_tasks_repository.h index f6f84bfe9..e195da188 100644 --- a/common/repositories/base/base_completed_tasks_repository.h +++ b/common/repositories/base/base_completed_tasks_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_COMPLETED_TASKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseCompletedTasksRepository { public: struct CompletedTasks { - int charid; - int completedtime; - int taskid; - int activityid; + uint32_t charid; + uint32_t completedtime; + uint32_t taskid; + int32_t activityid; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static CompletedTasks NewEntity() { - CompletedTasks entry{}; + CompletedTasks e{}; - entry.charid = 0; - entry.completedtime = 0; - entry.taskid = 0; - entry.activityid = 0; + e.charid = 0; + e.completedtime = 0; + e.taskid = 0; + e.activityid = 0; - return entry; + return e; } - static CompletedTasks GetCompletedTasksEntry( + static CompletedTasks GetCompletedTasks( const std::vector &completed_taskss, int completed_tasks_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - CompletedTasks entry{}; + CompletedTasks e{}; - entry.charid = atoi(row[0]); - entry.completedtime = atoi(row[1]); - entry.taskid = atoi(row[2]); - entry.activityid = atoi(row[3]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.completedtime = static_cast(strtoul(row[1], nullptr, 10)); + e.taskid = static_cast(strtoul(row[2], nullptr, 10)); + e.activityid = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - CompletedTasks completed_tasks_entry + const CompletedTasks &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(completed_tasks_entry.charid)); - update_values.push_back(columns[1] + " = " + std::to_string(completed_tasks_entry.completedtime)); - update_values.push_back(columns[2] + " = " + std::to_string(completed_tasks_entry.taskid)); - update_values.push_back(columns[3] + " = " + std::to_string(completed_tasks_entry.activityid)); + v.push_back(columns[0] + " = " + std::to_string(e.charid)); + v.push_back(columns[1] + " = " + std::to_string(e.completedtime)); + v.push_back(columns[2] + " = " + std::to_string(e.taskid)); + v.push_back(columns[3] + " = " + std::to_string(e.activityid)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - completed_tasks_entry.charid + e.charid ) ); @@ -183,59 +183,59 @@ public: static CompletedTasks InsertOne( Database& db, - CompletedTasks completed_tasks_entry + CompletedTasks e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(completed_tasks_entry.charid)); - insert_values.push_back(std::to_string(completed_tasks_entry.completedtime)); - insert_values.push_back(std::to_string(completed_tasks_entry.taskid)); - insert_values.push_back(std::to_string(completed_tasks_entry.activityid)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.completedtime)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.activityid)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - completed_tasks_entry.charid = results.LastInsertedID(); - return completed_tasks_entry; + e.charid = results.LastInsertedID(); + return e; } - completed_tasks_entry = NewEntity(); + e = NewEntity(); - return completed_tasks_entry; + return e; } static int InsertMany( Database& db, - std::vector completed_tasks_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &completed_tasks_entry: completed_tasks_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(completed_tasks_entry.charid)); - insert_values.push_back(std::to_string(completed_tasks_entry.completedtime)); - insert_values.push_back(std::to_string(completed_tasks_entry.taskid)); - insert_values.push_back(std::to_string(completed_tasks_entry.activityid)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.completedtime)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.activityid)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedTasks entry{}; + CompletedTasks e{}; - entry.charid = atoi(row[0]); - entry.completedtime = atoi(row[1]); - entry.taskid = atoi(row[2]); - entry.activityid = atoi(row[3]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.completedtime = static_cast(strtoul(row[1], nullptr, 10)); + e.taskid = static_cast(strtoul(row[2], nullptr, 10)); + e.activityid = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - CompletedTasks entry{}; + CompletedTasks e{}; - entry.charid = atoi(row[0]); - entry.completedtime = atoi(row[1]); - entry.taskid = atoi(row[2]); - entry.activityid = atoi(row[3]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.completedtime = static_cast(strtoul(row[1], nullptr, 10)); + e.taskid = static_cast(strtoul(row[2], nullptr, 10)); + e.activityid = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_COMPLETED_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_content_flags_repository.h b/common/repositories/base/base_content_flags_repository.h index 79374fd37..f8e2bc4dc 100644 --- a/common/repositories/base/base_content_flags_repository.h +++ b/common/repositories/base/base_content_flags_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_CONTENT_FLAGS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseContentFlagsRepository { public: struct ContentFlags { - int id; + int32_t id; std::string flag_name; - int enabled; + int8_t enabled; std::string notes; }; @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static ContentFlags NewEntity() { - ContentFlags entry{}; + ContentFlags e{}; - entry.id = 0; - entry.flag_name = ""; - entry.enabled = 0; - entry.notes = ""; + e.id = 0; + e.flag_name = ""; + e.enabled = 0; + e.notes = ""; - return entry; + return e; } - static ContentFlags GetContentFlagsEntry( + static ContentFlags GetContentFlags( const std::vector &content_flagss, int content_flags_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - ContentFlags entry{}; + ContentFlags e{}; - entry.id = atoi(row[0]); - entry.flag_name = row[1] ? row[1] : ""; - entry.enabled = atoi(row[2]); - entry.notes = row[3] ? row[3] : ""; + e.id = static_cast(atoi(row[0])); + e.flag_name = row[1] ? row[1] : ""; + e.enabled = static_cast(atoi(row[2])); + e.notes = row[3] ? row[3] : ""; - return entry; + return e; } return NewEntity(); @@ -156,24 +156,24 @@ public: static int UpdateOne( Database& db, - ContentFlags content_flags_entry + const ContentFlags &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(content_flags_entry.flag_name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(content_flags_entry.enabled)); - update_values.push_back(columns[3] + " = '" + EscapeString(content_flags_entry.notes) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.flag_name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.enabled)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.notes) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - content_flags_entry.id + e.id ) ); @@ -182,59 +182,59 @@ public: static ContentFlags InsertOne( Database& db, - ContentFlags content_flags_entry + ContentFlags e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(content_flags_entry.id)); - insert_values.push_back("'" + EscapeString(content_flags_entry.flag_name) + "'"); - insert_values.push_back(std::to_string(content_flags_entry.enabled)); - insert_values.push_back("'" + EscapeString(content_flags_entry.notes) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.flag_name) + "'"); + v.push_back(std::to_string(e.enabled)); + v.push_back("'" + Strings::Escape(e.notes) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - content_flags_entry.id = results.LastInsertedID(); - return content_flags_entry; + e.id = results.LastInsertedID(); + return e; } - content_flags_entry = NewEntity(); + e = NewEntity(); - return content_flags_entry; + return e; } static int InsertMany( Database& db, - std::vector content_flags_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &content_flags_entry: content_flags_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(content_flags_entry.id)); - insert_values.push_back("'" + EscapeString(content_flags_entry.flag_name) + "'"); - insert_values.push_back(std::to_string(content_flags_entry.enabled)); - insert_values.push_back("'" + EscapeString(content_flags_entry.notes) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.flag_name) + "'"); + v.push_back(std::to_string(e.enabled)); + v.push_back("'" + Strings::Escape(e.notes) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -255,20 +255,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ContentFlags entry{}; + ContentFlags e{}; - entry.id = atoi(row[0]); - entry.flag_name = row[1] ? row[1] : ""; - entry.enabled = atoi(row[2]); - entry.notes = row[3] ? row[3] : ""; + e.id = static_cast(atoi(row[0])); + e.flag_name = row[1] ? row[1] : ""; + e.enabled = static_cast(atoi(row[2])); + e.notes = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -283,20 +283,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ContentFlags entry{}; + ContentFlags e{}; - entry.id = atoi(row[0]); - entry.flag_name = row[1] ? row[1] : ""; - entry.enabled = atoi(row[2]); - entry.notes = row[3] ? row[3] : ""; + e.id = static_cast(atoi(row[0])); + e.flag_name = row[1] ? row[1] : ""; + e.enabled = static_cast(atoi(row[2])); + e.notes = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -321,6 +321,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_CONTENT_FLAGS_REPOSITORY_H diff --git a/common/repositories/base/base_damageshieldtypes_repository.h b/common/repositories/base/base_damageshieldtypes_repository.h index 052b2e8e7..cc1ec4b8f 100644 --- a/common/repositories/base/base_damageshieldtypes_repository.h +++ b/common/repositories/base/base_damageshieldtypes_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_DAMAGESHIELDTYPES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseDamageshieldtypesRepository { public: struct Damageshieldtypes { - int spellid; - int type; + uint32_t spellid; + uint8_t type; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static Damageshieldtypes NewEntity() { - Damageshieldtypes entry{}; + Damageshieldtypes e{}; - entry.spellid = 0; - entry.type = 0; + e.spellid = 0; + e.type = 0; - return entry; + return e; } - static Damageshieldtypes GetDamageshieldtypesEntry( + static Damageshieldtypes GetDamageshieldtypes( const std::vector &damageshieldtypess, int damageshieldtypes_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Damageshieldtypes entry{}; + Damageshieldtypes e{}; - entry.spellid = atoi(row[0]); - entry.type = atoi(row[1]); + e.spellid = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - Damageshieldtypes damageshieldtypes_entry + const Damageshieldtypes &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(damageshieldtypes_entry.spellid)); - update_values.push_back(columns[1] + " = " + std::to_string(damageshieldtypes_entry.type)); + v.push_back(columns[0] + " = " + std::to_string(e.spellid)); + v.push_back(columns[1] + " = " + std::to_string(e.type)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - damageshieldtypes_entry.spellid + e.spellid ) ); @@ -171,55 +171,55 @@ public: static Damageshieldtypes InsertOne( Database& db, - Damageshieldtypes damageshieldtypes_entry + Damageshieldtypes e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(damageshieldtypes_entry.spellid)); - insert_values.push_back(std::to_string(damageshieldtypes_entry.type)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - damageshieldtypes_entry.spellid = results.LastInsertedID(); - return damageshieldtypes_entry; + e.spellid = results.LastInsertedID(); + return e; } - damageshieldtypes_entry = NewEntity(); + e = NewEntity(); - return damageshieldtypes_entry; + return e; } static int InsertMany( Database& db, - std::vector damageshieldtypes_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &damageshieldtypes_entry: damageshieldtypes_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(damageshieldtypes_entry.spellid)); - insert_values.push_back(std::to_string(damageshieldtypes_entry.type)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Damageshieldtypes entry{}; + Damageshieldtypes e{}; - entry.spellid = atoi(row[0]); - entry.type = atoi(row[1]); + e.spellid = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Damageshieldtypes entry{}; + Damageshieldtypes e{}; - entry.spellid = atoi(row[0]); - entry.type = atoi(row[1]); + e.spellid = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_DAMAGESHIELDTYPES_REPOSITORY_H diff --git a/common/repositories/base/base_data_buckets_repository.h b/common/repositories/base/base_data_buckets_repository.h index e144cc3db..3c7ad5a0a 100644 --- a/common/repositories/base/base_data_buckets_repository.h +++ b/common/repositories/base/base_data_buckets_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_DATA_BUCKETS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseDataBucketsRepository { public: struct DataBuckets { - int64 id; + uint64_t id; std::string key; std::string value; - int expires; + uint32_t expires; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static DataBuckets NewEntity() { - DataBuckets entry{}; + DataBuckets e{}; - entry.id = 0; - entry.key = ""; - entry.value = ""; - entry.expires = 0; + e.id = 0; + e.key = ""; + e.value = ""; + e.expires = 0; - return entry; + return e; } - static DataBuckets GetDataBucketsEntry( + static DataBuckets GetDataBuckets( const std::vector &data_bucketss, int data_buckets_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - DataBuckets entry{}; + DataBuckets e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.key = row[1] ? row[1] : ""; - entry.value = row[2] ? row[2] : ""; - entry.expires = atoi(row[3]); + e.id = strtoull(row[0], nullptr, 10); + e.key = row[1] ? row[1] : ""; + e.value = row[2] ? row[2] : ""; + e.expires = static_cast(strtoul(row[3], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -156,24 +156,24 @@ public: static int UpdateOne( Database& db, - DataBuckets data_buckets_entry + const DataBuckets &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(data_buckets_entry.key) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(data_buckets_entry.value) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(data_buckets_entry.expires)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.key) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.expires)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - data_buckets_entry.id + e.id ) ); @@ -182,59 +182,59 @@ public: static DataBuckets InsertOne( Database& db, - DataBuckets data_buckets_entry + DataBuckets e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(data_buckets_entry.id)); - insert_values.push_back("'" + EscapeString(data_buckets_entry.key) + "'"); - insert_values.push_back("'" + EscapeString(data_buckets_entry.value) + "'"); - insert_values.push_back(std::to_string(data_buckets_entry.expires)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.key) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.expires)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - data_buckets_entry.id = results.LastInsertedID(); - return data_buckets_entry; + e.id = results.LastInsertedID(); + return e; } - data_buckets_entry = NewEntity(); + e = NewEntity(); - return data_buckets_entry; + return e; } static int InsertMany( Database& db, - std::vector data_buckets_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &data_buckets_entry: data_buckets_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(data_buckets_entry.id)); - insert_values.push_back("'" + EscapeString(data_buckets_entry.key) + "'"); - insert_values.push_back("'" + EscapeString(data_buckets_entry.value) + "'"); - insert_values.push_back(std::to_string(data_buckets_entry.expires)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.key) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.expires)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -255,20 +255,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DataBuckets entry{}; + DataBuckets e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.key = row[1] ? row[1] : ""; - entry.value = row[2] ? row[2] : ""; - entry.expires = atoi(row[3]); + e.id = strtoull(row[0], nullptr, 10); + e.key = row[1] ? row[1] : ""; + e.value = row[2] ? row[2] : ""; + e.expires = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -283,20 +283,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DataBuckets entry{}; + DataBuckets e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.key = row[1] ? row[1] : ""; - entry.value = row[2] ? row[2] : ""; - entry.expires = atoi(row[3]); + e.id = strtoull(row[0], nullptr, 10); + e.key = row[1] ? row[1] : ""; + e.value = row[2] ? row[2] : ""; + e.expires = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -321,6 +321,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_DATA_BUCKETS_REPOSITORY_H diff --git a/common/repositories/base/base_db_str_repository.h b/common/repositories/base/base_db_str_repository.h index 0d84d757d..d79d65410 100644 --- a/common/repositories/base/base_db_str_repository.h +++ b/common/repositories/base/base_db_str_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_DB_STR_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseDbStrRepository { public: struct DbStr { - int id; - int type; + int32_t id; + int32_t type; std::string value; }; @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static DbStr NewEntity() { - DbStr entry{}; + DbStr e{}; - entry.id = 0; - entry.type = 0; - entry.value = ""; + e.id = 0; + e.type = 0; + e.value = ""; - return entry; + return e; } - static DbStr GetDbStrEntry( + static DbStr GetDbStr( const std::vector &db_strs, int db_str_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - DbStr entry{}; + DbStr e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.value = row[2] ? row[2] : ""; + e.id = static_cast(atoi(row[0])); + e.type = static_cast(atoi(row[1])); + e.value = row[2] ? row[2] : ""; - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - DbStr db_str_entry + const DbStr &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(db_str_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(db_str_entry.type)); - update_values.push_back(columns[2] + " = '" + EscapeString(db_str_entry.value) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.type)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - db_str_entry.id + e.id ) ); @@ -177,57 +177,57 @@ public: static DbStr InsertOne( Database& db, - DbStr db_str_entry + DbStr e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(db_str_entry.id)); - insert_values.push_back(std::to_string(db_str_entry.type)); - insert_values.push_back("'" + EscapeString(db_str_entry.value) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.value) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - db_str_entry.id = results.LastInsertedID(); - return db_str_entry; + e.id = results.LastInsertedID(); + return e; } - db_str_entry = NewEntity(); + e = NewEntity(); - return db_str_entry; + return e; } static int InsertMany( Database& db, - std::vector db_str_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &db_str_entry: db_str_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(db_str_entry.id)); - insert_values.push_back(std::to_string(db_str_entry.type)); - insert_values.push_back("'" + EscapeString(db_str_entry.value) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.value) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DbStr entry{}; + DbStr e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.value = row[2] ? row[2] : ""; + e.id = static_cast(atoi(row[0])); + e.type = static_cast(atoi(row[1])); + e.value = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DbStr entry{}; + DbStr e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.value = row[2] ? row[2] : ""; + e.id = static_cast(atoi(row[0])); + e.type = static_cast(atoi(row[1])); + e.value = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_DB_STR_REPOSITORY_H diff --git a/common/repositories/base/base_discord_webhooks_repository.h b/common/repositories/base/base_discord_webhooks_repository.h new file mode 100644 index 000000000..6967c1c28 --- /dev/null +++ b/common/repositories/base/base_discord_webhooks_repository.h @@ -0,0 +1,362 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_DISCORD_WEBHOOKS_REPOSITORY_H +#define EQEMU_BASE_DISCORD_WEBHOOKS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseDiscordWebhooksRepository { +public: + struct DiscordWebhooks { + int32_t id; + std::string webhook_name; + std::string webhook_url; + time_t created_at; + time_t deleted_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "webhook_name", + "webhook_url", + "created_at", + "deleted_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "webhook_name", + "webhook_url", + "UNIX_TIMESTAMP(created_at)", + "UNIX_TIMESTAMP(deleted_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("discord_webhooks"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static DiscordWebhooks NewEntity() + { + DiscordWebhooks e{}; + + e.id = 0; + e.webhook_name = ""; + e.webhook_url = ""; + e.created_at = 0; + e.deleted_at = 0; + + return e; + } + + static DiscordWebhooks GetDiscordWebhooks( + const std::vector &discord_webhookss, + int discord_webhooks_id + ) + { + for (auto &discord_webhooks : discord_webhookss) { + if (discord_webhooks.id == discord_webhooks_id) { + return discord_webhooks; + } + } + + return NewEntity(); + } + + static DiscordWebhooks FindOne( + Database& db, + int discord_webhooks_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + discord_webhooks_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + DiscordWebhooks e{}; + + e.id = static_cast(atoi(row[0])); + e.webhook_name = row[1] ? row[1] : ""; + e.webhook_url = row[2] ? row[2] : ""; + e.created_at = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.deleted_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int discord_webhooks_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + discord_webhooks_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const DiscordWebhooks &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = '" + Strings::Escape(e.webhook_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.webhook_url) + "'"); + v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static DiscordWebhooks InsertOne( + Database& db, + DiscordWebhooks e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.webhook_name) + "'"); + v.push_back("'" + Strings::Escape(e.webhook_url) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.webhook_name) + "'"); + v.push_back("'" + Strings::Escape(e.webhook_url) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + DiscordWebhooks e{}; + + e.id = static_cast(atoi(row[0])); + e.webhook_name = row[1] ? row[1] : ""; + e.webhook_url = row[2] ? row[2] : ""; + e.created_at = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.deleted_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + DiscordWebhooks e{}; + + e.id = static_cast(atoi(row[0])); + e.webhook_name = row[1] ? row[1] : ""; + e.webhook_url = row[2] ? row[2] : ""; + e.created_at = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.deleted_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_DISCORD_WEBHOOKS_REPOSITORY_H diff --git a/common/repositories/base/base_discovered_items_repository.h b/common/repositories/base/base_discovered_items_repository.h index 4ee1e2e77..5cef65213 100644 --- a/common/repositories/base/base_discovered_items_repository.h +++ b/common/repositories/base/base_discovered_items_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_DISCOVERED_ITEMS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseDiscoveredItemsRepository { public: struct DiscoveredItems { - int item_id; + uint32_t item_id; std::string char_name; - int discovered_date; - int account_status; + uint32_t discovered_date; + int32_t account_status; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static DiscoveredItems NewEntity() { - DiscoveredItems entry{}; + DiscoveredItems e{}; - entry.item_id = 0; - entry.char_name = ""; - entry.discovered_date = 0; - entry.account_status = 0; + e.item_id = 0; + e.char_name = ""; + e.discovered_date = 0; + e.account_status = 0; - return entry; + return e; } - static DiscoveredItems GetDiscoveredItemsEntry( + static DiscoveredItems GetDiscoveredItems( const std::vector &discovered_itemss, int discovered_items_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - DiscoveredItems entry{}; + DiscoveredItems e{}; - entry.item_id = atoi(row[0]); - entry.char_name = row[1] ? row[1] : ""; - entry.discovered_date = atoi(row[2]); - entry.account_status = atoi(row[3]); + e.item_id = static_cast(strtoul(row[0], nullptr, 10)); + e.char_name = row[1] ? row[1] : ""; + e.discovered_date = static_cast(strtoul(row[2], nullptr, 10)); + e.account_status = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - DiscoveredItems discovered_items_entry + const DiscoveredItems &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(discovered_items_entry.item_id)); - update_values.push_back(columns[1] + " = '" + EscapeString(discovered_items_entry.char_name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(discovered_items_entry.discovered_date)); - update_values.push_back(columns[3] + " = " + std::to_string(discovered_items_entry.account_status)); + v.push_back(columns[0] + " = " + std::to_string(e.item_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.char_name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.discovered_date)); + v.push_back(columns[3] + " = " + std::to_string(e.account_status)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - discovered_items_entry.item_id + e.item_id ) ); @@ -183,59 +183,59 @@ public: static DiscoveredItems InsertOne( Database& db, - DiscoveredItems discovered_items_entry + DiscoveredItems e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(discovered_items_entry.item_id)); - insert_values.push_back("'" + EscapeString(discovered_items_entry.char_name) + "'"); - insert_values.push_back(std::to_string(discovered_items_entry.discovered_date)); - insert_values.push_back(std::to_string(discovered_items_entry.account_status)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.char_name) + "'"); + v.push_back(std::to_string(e.discovered_date)); + v.push_back(std::to_string(e.account_status)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - discovered_items_entry.item_id = results.LastInsertedID(); - return discovered_items_entry; + e.item_id = results.LastInsertedID(); + return e; } - discovered_items_entry = NewEntity(); + e = NewEntity(); - return discovered_items_entry; + return e; } static int InsertMany( Database& db, - std::vector discovered_items_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &discovered_items_entry: discovered_items_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(discovered_items_entry.item_id)); - insert_values.push_back("'" + EscapeString(discovered_items_entry.char_name) + "'"); - insert_values.push_back(std::to_string(discovered_items_entry.discovered_date)); - insert_values.push_back(std::to_string(discovered_items_entry.account_status)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.char_name) + "'"); + v.push_back(std::to_string(e.discovered_date)); + v.push_back(std::to_string(e.account_status)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DiscoveredItems entry{}; + DiscoveredItems e{}; - entry.item_id = atoi(row[0]); - entry.char_name = row[1] ? row[1] : ""; - entry.discovered_date = atoi(row[2]); - entry.account_status = atoi(row[3]); + e.item_id = static_cast(strtoul(row[0], nullptr, 10)); + e.char_name = row[1] ? row[1] : ""; + e.discovered_date = static_cast(strtoul(row[2], nullptr, 10)); + e.account_status = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DiscoveredItems entry{}; + DiscoveredItems e{}; - entry.item_id = atoi(row[0]); - entry.char_name = row[1] ? row[1] : ""; - entry.discovered_date = atoi(row[2]); - entry.account_status = atoi(row[3]); + e.item_id = static_cast(strtoul(row[0], nullptr, 10)); + e.char_name = row[1] ? row[1] : ""; + e.discovered_date = static_cast(strtoul(row[2], nullptr, 10)); + e.account_status = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_DISCOVERED_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_doors_repository.h b/common/repositories/base/base_doors_repository.h index ff224387d..3711f192c 100644 --- a/common/repositories/base/base_doors_repository.h +++ b/common/repositories/base/base_doors_repository.h @@ -13,45 +13,46 @@ #define EQEMU_BASE_DOORS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseDoorsRepository { public: struct Doors { - int id; - int doorid; + int32_t id; + int16_t doorid; std::string zone; - int version; + int16_t version; std::string name; float pos_y; float pos_x; float pos_z; float heading; - int opentype; - int guild; - int lockpick; - int keyitem; - int nokeyring; - int triggerdoor; - int triggertype; - int disable_timer; - int doorisopen; - int door_param; + int16_t opentype; + int16_t guild; + int16_t lockpick; + int32_t keyitem; + uint8_t nokeyring; + int16_t triggerdoor; + int16_t triggertype; + int8_t disable_timer; + int16_t doorisopen; + int32_t door_param; std::string dest_zone; - int dest_instance; + uint32_t dest_instance; float dest_x; float dest_y; float dest_z; float dest_heading; - int invert_state; - int incline; - int size; + int32_t invert_state; + int32_t incline; + uint16_t size; float buffer; - int client_version_mask; - int is_ldon_door; - int min_expansion; - int max_expansion; + uint32_t client_version_mask; + int16_t is_ldon_door; + int32_t dz_switch_id; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -95,6 +96,7 @@ public: "buffer", "client_version_mask", "is_ldon_door", + "dz_switch_id", "min_expansion", "max_expansion", "content_flags", @@ -136,6 +138,7 @@ public: "buffer", "client_version_mask", "is_ldon_door", + "dz_switch_id", "min_expansion", "max_expansion", "content_flags", @@ -145,12 +148,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -178,48 +181,49 @@ public: static Doors NewEntity() { - Doors entry{}; + Doors e{}; - entry.id = 0; - entry.doorid = 0; - entry.zone = ""; - entry.version = 0; - entry.name = ""; - entry.pos_y = 0; - entry.pos_x = 0; - entry.pos_z = 0; - entry.heading = 0; - entry.opentype = 0; - entry.guild = 0; - entry.lockpick = 0; - entry.keyitem = 0; - entry.nokeyring = 0; - entry.triggerdoor = 0; - entry.triggertype = 0; - entry.disable_timer = 0; - entry.doorisopen = 0; - entry.door_param = 0; - entry.dest_zone = "NONE"; - entry.dest_instance = 0; - entry.dest_x = 0; - entry.dest_y = 0; - entry.dest_z = 0; - entry.dest_heading = 0; - entry.invert_state = 0; - entry.incline = 0; - entry.size = 100; - entry.buffer = 0; - entry.client_version_mask = 4294967295; - entry.is_ldon_door = 0; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.doorid = 0; + e.zone = ""; + e.version = 0; + e.name = ""; + e.pos_y = 0; + e.pos_x = 0; + e.pos_z = 0; + e.heading = 0; + e.opentype = 0; + e.guild = 0; + e.lockpick = 0; + e.keyitem = 0; + e.nokeyring = 0; + e.triggerdoor = 0; + e.triggertype = 0; + e.disable_timer = 0; + e.doorisopen = 0; + e.door_param = 0; + e.dest_zone = "NONE"; + e.dest_instance = 0; + e.dest_x = 0; + e.dest_y = 0; + e.dest_z = 0; + e.dest_heading = 0; + e.invert_state = 0; + e.incline = 0; + e.size = 100; + e.buffer = 0; + e.client_version_mask = 4294967295; + e.is_ldon_door = 0; + e.dz_switch_id = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Doors GetDoorsEntry( + static Doors GetDoors( const std::vector &doorss, int doors_id ) @@ -248,45 +252,46 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Doors entry{}; + Doors e{}; - entry.id = atoi(row[0]); - entry.doorid = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.version = atoi(row[3]); - entry.name = row[4] ? row[4] : ""; - entry.pos_y = static_cast(atof(row[5])); - entry.pos_x = static_cast(atof(row[6])); - entry.pos_z = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.opentype = atoi(row[9]); - entry.guild = atoi(row[10]); - entry.lockpick = atoi(row[11]); - entry.keyitem = atoi(row[12]); - entry.nokeyring = atoi(row[13]); - entry.triggerdoor = atoi(row[14]); - entry.triggertype = atoi(row[15]); - entry.disable_timer = atoi(row[16]); - entry.doorisopen = atoi(row[17]); - entry.door_param = atoi(row[18]); - entry.dest_zone = row[19] ? row[19] : ""; - entry.dest_instance = atoi(row[20]); - entry.dest_x = static_cast(atof(row[21])); - entry.dest_y = static_cast(atof(row[22])); - entry.dest_z = static_cast(atof(row[23])); - entry.dest_heading = static_cast(atof(row[24])); - entry.invert_state = atoi(row[25]); - entry.incline = atoi(row[26]); - entry.size = atoi(row[27]); - entry.buffer = static_cast(atof(row[28])); - entry.client_version_mask = atoi(row[29]); - entry.is_ldon_door = atoi(row[30]); - entry.min_expansion = atoi(row[31]); - entry.max_expansion = atoi(row[32]); - entry.content_flags = row[33] ? row[33] : ""; - entry.content_flags_disabled = row[34] ? row[34] : ""; + e.id = static_cast(atoi(row[0])); + e.doorid = static_cast(atoi(row[1])); + e.zone = row[2] ? row[2] : ""; + e.version = static_cast(atoi(row[3])); + e.name = row[4] ? row[4] : ""; + e.pos_y = strtof(row[5], nullptr); + e.pos_x = strtof(row[6], nullptr); + e.pos_z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.opentype = static_cast(atoi(row[9])); + e.guild = static_cast(atoi(row[10])); + e.lockpick = static_cast(atoi(row[11])); + e.keyitem = static_cast(atoi(row[12])); + e.nokeyring = static_cast(strtoul(row[13], nullptr, 10)); + e.triggerdoor = static_cast(atoi(row[14])); + e.triggertype = static_cast(atoi(row[15])); + e.disable_timer = static_cast(atoi(row[16])); + e.doorisopen = static_cast(atoi(row[17])); + e.door_param = static_cast(atoi(row[18])); + e.dest_zone = row[19] ? row[19] : ""; + e.dest_instance = static_cast(strtoul(row[20], nullptr, 10)); + e.dest_x = strtof(row[21], nullptr); + e.dest_y = strtof(row[22], nullptr); + e.dest_z = strtof(row[23], nullptr); + e.dest_heading = strtof(row[24], nullptr); + e.invert_state = static_cast(atoi(row[25])); + e.incline = static_cast(atoi(row[26])); + e.size = static_cast(strtoul(row[27], nullptr, 10)); + e.buffer = strtof(row[28], nullptr); + e.client_version_mask = static_cast(strtoul(row[29], nullptr, 10)); + e.is_ldon_door = static_cast(atoi(row[30])); + e.dz_switch_id = static_cast(atoi(row[31])); + e.min_expansion = static_cast(atoi(row[32])); + e.max_expansion = static_cast(atoi(row[33])); + e.content_flags = row[34] ? row[34] : ""; + e.content_flags_disabled = row[35] ? row[35] : ""; - return entry; + return e; } return NewEntity(); @@ -311,55 +316,56 @@ public: static int UpdateOne( Database& db, - Doors doors_entry + const Doors &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(doors_entry.doorid)); - update_values.push_back(columns[2] + " = '" + EscapeString(doors_entry.zone) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(doors_entry.version)); - update_values.push_back(columns[4] + " = '" + EscapeString(doors_entry.name) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(doors_entry.pos_y)); - update_values.push_back(columns[6] + " = " + std::to_string(doors_entry.pos_x)); - update_values.push_back(columns[7] + " = " + std::to_string(doors_entry.pos_z)); - update_values.push_back(columns[8] + " = " + std::to_string(doors_entry.heading)); - update_values.push_back(columns[9] + " = " + std::to_string(doors_entry.opentype)); - update_values.push_back(columns[10] + " = " + std::to_string(doors_entry.guild)); - update_values.push_back(columns[11] + " = " + std::to_string(doors_entry.lockpick)); - update_values.push_back(columns[12] + " = " + std::to_string(doors_entry.keyitem)); - update_values.push_back(columns[13] + " = " + std::to_string(doors_entry.nokeyring)); - update_values.push_back(columns[14] + " = " + std::to_string(doors_entry.triggerdoor)); - update_values.push_back(columns[15] + " = " + std::to_string(doors_entry.triggertype)); - update_values.push_back(columns[16] + " = " + std::to_string(doors_entry.disable_timer)); - update_values.push_back(columns[17] + " = " + std::to_string(doors_entry.doorisopen)); - update_values.push_back(columns[18] + " = " + std::to_string(doors_entry.door_param)); - update_values.push_back(columns[19] + " = '" + EscapeString(doors_entry.dest_zone) + "'"); - update_values.push_back(columns[20] + " = " + std::to_string(doors_entry.dest_instance)); - update_values.push_back(columns[21] + " = " + std::to_string(doors_entry.dest_x)); - update_values.push_back(columns[22] + " = " + std::to_string(doors_entry.dest_y)); - update_values.push_back(columns[23] + " = " + std::to_string(doors_entry.dest_z)); - update_values.push_back(columns[24] + " = " + std::to_string(doors_entry.dest_heading)); - update_values.push_back(columns[25] + " = " + std::to_string(doors_entry.invert_state)); - update_values.push_back(columns[26] + " = " + std::to_string(doors_entry.incline)); - update_values.push_back(columns[27] + " = " + std::to_string(doors_entry.size)); - update_values.push_back(columns[28] + " = " + std::to_string(doors_entry.buffer)); - update_values.push_back(columns[29] + " = " + std::to_string(doors_entry.client_version_mask)); - update_values.push_back(columns[30] + " = " + std::to_string(doors_entry.is_ldon_door)); - update_values.push_back(columns[31] + " = " + std::to_string(doors_entry.min_expansion)); - update_values.push_back(columns[32] + " = " + std::to_string(doors_entry.max_expansion)); - update_values.push_back(columns[33] + " = '" + EscapeString(doors_entry.content_flags) + "'"); - update_values.push_back(columns[34] + " = '" + EscapeString(doors_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.doorid)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.version)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.pos_y)); + v.push_back(columns[6] + " = " + std::to_string(e.pos_x)); + v.push_back(columns[7] + " = " + std::to_string(e.pos_z)); + v.push_back(columns[8] + " = " + std::to_string(e.heading)); + v.push_back(columns[9] + " = " + std::to_string(e.opentype)); + v.push_back(columns[10] + " = " + std::to_string(e.guild)); + v.push_back(columns[11] + " = " + std::to_string(e.lockpick)); + v.push_back(columns[12] + " = " + std::to_string(e.keyitem)); + v.push_back(columns[13] + " = " + std::to_string(e.nokeyring)); + v.push_back(columns[14] + " = " + std::to_string(e.triggerdoor)); + v.push_back(columns[15] + " = " + std::to_string(e.triggertype)); + v.push_back(columns[16] + " = " + std::to_string(e.disable_timer)); + v.push_back(columns[17] + " = " + std::to_string(e.doorisopen)); + v.push_back(columns[18] + " = " + std::to_string(e.door_param)); + v.push_back(columns[19] + " = '" + Strings::Escape(e.dest_zone) + "'"); + v.push_back(columns[20] + " = " + std::to_string(e.dest_instance)); + v.push_back(columns[21] + " = " + std::to_string(e.dest_x)); + v.push_back(columns[22] + " = " + std::to_string(e.dest_y)); + v.push_back(columns[23] + " = " + std::to_string(e.dest_z)); + v.push_back(columns[24] + " = " + std::to_string(e.dest_heading)); + v.push_back(columns[25] + " = " + std::to_string(e.invert_state)); + v.push_back(columns[26] + " = " + std::to_string(e.incline)); + v.push_back(columns[27] + " = " + std::to_string(e.size)); + v.push_back(columns[28] + " = " + std::to_string(e.buffer)); + v.push_back(columns[29] + " = " + std::to_string(e.client_version_mask)); + v.push_back(columns[30] + " = " + std::to_string(e.is_ldon_door)); + v.push_back(columns[31] + " = " + std::to_string(e.dz_switch_id)); + v.push_back(columns[32] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[33] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[34] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[35] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - doors_entry.id + e.id ) ); @@ -368,121 +374,123 @@ public: static Doors InsertOne( Database& db, - Doors doors_entry + Doors e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(doors_entry.id)); - insert_values.push_back(std::to_string(doors_entry.doorid)); - insert_values.push_back("'" + EscapeString(doors_entry.zone) + "'"); - insert_values.push_back(std::to_string(doors_entry.version)); - insert_values.push_back("'" + EscapeString(doors_entry.name) + "'"); - insert_values.push_back(std::to_string(doors_entry.pos_y)); - insert_values.push_back(std::to_string(doors_entry.pos_x)); - insert_values.push_back(std::to_string(doors_entry.pos_z)); - insert_values.push_back(std::to_string(doors_entry.heading)); - insert_values.push_back(std::to_string(doors_entry.opentype)); - insert_values.push_back(std::to_string(doors_entry.guild)); - insert_values.push_back(std::to_string(doors_entry.lockpick)); - insert_values.push_back(std::to_string(doors_entry.keyitem)); - insert_values.push_back(std::to_string(doors_entry.nokeyring)); - insert_values.push_back(std::to_string(doors_entry.triggerdoor)); - insert_values.push_back(std::to_string(doors_entry.triggertype)); - insert_values.push_back(std::to_string(doors_entry.disable_timer)); - insert_values.push_back(std::to_string(doors_entry.doorisopen)); - insert_values.push_back(std::to_string(doors_entry.door_param)); - insert_values.push_back("'" + EscapeString(doors_entry.dest_zone) + "'"); - insert_values.push_back(std::to_string(doors_entry.dest_instance)); - insert_values.push_back(std::to_string(doors_entry.dest_x)); - insert_values.push_back(std::to_string(doors_entry.dest_y)); - insert_values.push_back(std::to_string(doors_entry.dest_z)); - insert_values.push_back(std::to_string(doors_entry.dest_heading)); - insert_values.push_back(std::to_string(doors_entry.invert_state)); - insert_values.push_back(std::to_string(doors_entry.incline)); - insert_values.push_back(std::to_string(doors_entry.size)); - insert_values.push_back(std::to_string(doors_entry.buffer)); - insert_values.push_back(std::to_string(doors_entry.client_version_mask)); - insert_values.push_back(std::to_string(doors_entry.is_ldon_door)); - insert_values.push_back(std::to_string(doors_entry.min_expansion)); - insert_values.push_back(std::to_string(doors_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(doors_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(doors_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.doorid)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.pos_y)); + v.push_back(std::to_string(e.pos_x)); + v.push_back(std::to_string(e.pos_z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.opentype)); + v.push_back(std::to_string(e.guild)); + v.push_back(std::to_string(e.lockpick)); + v.push_back(std::to_string(e.keyitem)); + v.push_back(std::to_string(e.nokeyring)); + v.push_back(std::to_string(e.triggerdoor)); + v.push_back(std::to_string(e.triggertype)); + v.push_back(std::to_string(e.disable_timer)); + v.push_back(std::to_string(e.doorisopen)); + v.push_back(std::to_string(e.door_param)); + v.push_back("'" + Strings::Escape(e.dest_zone) + "'"); + v.push_back(std::to_string(e.dest_instance)); + v.push_back(std::to_string(e.dest_x)); + v.push_back(std::to_string(e.dest_y)); + v.push_back(std::to_string(e.dest_z)); + v.push_back(std::to_string(e.dest_heading)); + v.push_back(std::to_string(e.invert_state)); + v.push_back(std::to_string(e.incline)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.buffer)); + v.push_back(std::to_string(e.client_version_mask)); + v.push_back(std::to_string(e.is_ldon_door)); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - doors_entry.id = results.LastInsertedID(); - return doors_entry; + e.id = results.LastInsertedID(); + return e; } - doors_entry = NewEntity(); + e = NewEntity(); - return doors_entry; + return e; } static int InsertMany( Database& db, - std::vector doors_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &doors_entry: doors_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(doors_entry.id)); - insert_values.push_back(std::to_string(doors_entry.doorid)); - insert_values.push_back("'" + EscapeString(doors_entry.zone) + "'"); - insert_values.push_back(std::to_string(doors_entry.version)); - insert_values.push_back("'" + EscapeString(doors_entry.name) + "'"); - insert_values.push_back(std::to_string(doors_entry.pos_y)); - insert_values.push_back(std::to_string(doors_entry.pos_x)); - insert_values.push_back(std::to_string(doors_entry.pos_z)); - insert_values.push_back(std::to_string(doors_entry.heading)); - insert_values.push_back(std::to_string(doors_entry.opentype)); - insert_values.push_back(std::to_string(doors_entry.guild)); - insert_values.push_back(std::to_string(doors_entry.lockpick)); - insert_values.push_back(std::to_string(doors_entry.keyitem)); - insert_values.push_back(std::to_string(doors_entry.nokeyring)); - insert_values.push_back(std::to_string(doors_entry.triggerdoor)); - insert_values.push_back(std::to_string(doors_entry.triggertype)); - insert_values.push_back(std::to_string(doors_entry.disable_timer)); - insert_values.push_back(std::to_string(doors_entry.doorisopen)); - insert_values.push_back(std::to_string(doors_entry.door_param)); - insert_values.push_back("'" + EscapeString(doors_entry.dest_zone) + "'"); - insert_values.push_back(std::to_string(doors_entry.dest_instance)); - insert_values.push_back(std::to_string(doors_entry.dest_x)); - insert_values.push_back(std::to_string(doors_entry.dest_y)); - insert_values.push_back(std::to_string(doors_entry.dest_z)); - insert_values.push_back(std::to_string(doors_entry.dest_heading)); - insert_values.push_back(std::to_string(doors_entry.invert_state)); - insert_values.push_back(std::to_string(doors_entry.incline)); - insert_values.push_back(std::to_string(doors_entry.size)); - insert_values.push_back(std::to_string(doors_entry.buffer)); - insert_values.push_back(std::to_string(doors_entry.client_version_mask)); - insert_values.push_back(std::to_string(doors_entry.is_ldon_door)); - insert_values.push_back(std::to_string(doors_entry.min_expansion)); - insert_values.push_back(std::to_string(doors_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(doors_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(doors_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.doorid)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.pos_y)); + v.push_back(std::to_string(e.pos_x)); + v.push_back(std::to_string(e.pos_z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.opentype)); + v.push_back(std::to_string(e.guild)); + v.push_back(std::to_string(e.lockpick)); + v.push_back(std::to_string(e.keyitem)); + v.push_back(std::to_string(e.nokeyring)); + v.push_back(std::to_string(e.triggerdoor)); + v.push_back(std::to_string(e.triggertype)); + v.push_back(std::to_string(e.disable_timer)); + v.push_back(std::to_string(e.doorisopen)); + v.push_back(std::to_string(e.door_param)); + v.push_back("'" + Strings::Escape(e.dest_zone) + "'"); + v.push_back(std::to_string(e.dest_instance)); + v.push_back(std::to_string(e.dest_x)); + v.push_back(std::to_string(e.dest_y)); + v.push_back(std::to_string(e.dest_z)); + v.push_back(std::to_string(e.dest_heading)); + v.push_back(std::to_string(e.invert_state)); + v.push_back(std::to_string(e.incline)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.buffer)); + v.push_back(std::to_string(e.client_version_mask)); + v.push_back(std::to_string(e.is_ldon_door)); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -503,51 +511,52 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Doors entry{}; + Doors e{}; - entry.id = atoi(row[0]); - entry.doorid = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.version = atoi(row[3]); - entry.name = row[4] ? row[4] : ""; - entry.pos_y = static_cast(atof(row[5])); - entry.pos_x = static_cast(atof(row[6])); - entry.pos_z = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.opentype = atoi(row[9]); - entry.guild = atoi(row[10]); - entry.lockpick = atoi(row[11]); - entry.keyitem = atoi(row[12]); - entry.nokeyring = atoi(row[13]); - entry.triggerdoor = atoi(row[14]); - entry.triggertype = atoi(row[15]); - entry.disable_timer = atoi(row[16]); - entry.doorisopen = atoi(row[17]); - entry.door_param = atoi(row[18]); - entry.dest_zone = row[19] ? row[19] : ""; - entry.dest_instance = atoi(row[20]); - entry.dest_x = static_cast(atof(row[21])); - entry.dest_y = static_cast(atof(row[22])); - entry.dest_z = static_cast(atof(row[23])); - entry.dest_heading = static_cast(atof(row[24])); - entry.invert_state = atoi(row[25]); - entry.incline = atoi(row[26]); - entry.size = atoi(row[27]); - entry.buffer = static_cast(atof(row[28])); - entry.client_version_mask = atoi(row[29]); - entry.is_ldon_door = atoi(row[30]); - entry.min_expansion = atoi(row[31]); - entry.max_expansion = atoi(row[32]); - entry.content_flags = row[33] ? row[33] : ""; - entry.content_flags_disabled = row[34] ? row[34] : ""; + e.id = static_cast(atoi(row[0])); + e.doorid = static_cast(atoi(row[1])); + e.zone = row[2] ? row[2] : ""; + e.version = static_cast(atoi(row[3])); + e.name = row[4] ? row[4] : ""; + e.pos_y = strtof(row[5], nullptr); + e.pos_x = strtof(row[6], nullptr); + e.pos_z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.opentype = static_cast(atoi(row[9])); + e.guild = static_cast(atoi(row[10])); + e.lockpick = static_cast(atoi(row[11])); + e.keyitem = static_cast(atoi(row[12])); + e.nokeyring = static_cast(strtoul(row[13], nullptr, 10)); + e.triggerdoor = static_cast(atoi(row[14])); + e.triggertype = static_cast(atoi(row[15])); + e.disable_timer = static_cast(atoi(row[16])); + e.doorisopen = static_cast(atoi(row[17])); + e.door_param = static_cast(atoi(row[18])); + e.dest_zone = row[19] ? row[19] : ""; + e.dest_instance = static_cast(strtoul(row[20], nullptr, 10)); + e.dest_x = strtof(row[21], nullptr); + e.dest_y = strtof(row[22], nullptr); + e.dest_z = strtof(row[23], nullptr); + e.dest_heading = strtof(row[24], nullptr); + e.invert_state = static_cast(atoi(row[25])); + e.incline = static_cast(atoi(row[26])); + e.size = static_cast(strtoul(row[27], nullptr, 10)); + e.buffer = strtof(row[28], nullptr); + e.client_version_mask = static_cast(strtoul(row[29], nullptr, 10)); + e.is_ldon_door = static_cast(atoi(row[30])); + e.dz_switch_id = static_cast(atoi(row[31])); + e.min_expansion = static_cast(atoi(row[32])); + e.max_expansion = static_cast(atoi(row[33])); + e.content_flags = row[34] ? row[34] : ""; + e.content_flags_disabled = row[35] ? row[35] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -562,51 +571,52 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Doors entry{}; + Doors e{}; - entry.id = atoi(row[0]); - entry.doorid = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.version = atoi(row[3]); - entry.name = row[4] ? row[4] : ""; - entry.pos_y = static_cast(atof(row[5])); - entry.pos_x = static_cast(atof(row[6])); - entry.pos_z = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.opentype = atoi(row[9]); - entry.guild = atoi(row[10]); - entry.lockpick = atoi(row[11]); - entry.keyitem = atoi(row[12]); - entry.nokeyring = atoi(row[13]); - entry.triggerdoor = atoi(row[14]); - entry.triggertype = atoi(row[15]); - entry.disable_timer = atoi(row[16]); - entry.doorisopen = atoi(row[17]); - entry.door_param = atoi(row[18]); - entry.dest_zone = row[19] ? row[19] : ""; - entry.dest_instance = atoi(row[20]); - entry.dest_x = static_cast(atof(row[21])); - entry.dest_y = static_cast(atof(row[22])); - entry.dest_z = static_cast(atof(row[23])); - entry.dest_heading = static_cast(atof(row[24])); - entry.invert_state = atoi(row[25]); - entry.incline = atoi(row[26]); - entry.size = atoi(row[27]); - entry.buffer = static_cast(atof(row[28])); - entry.client_version_mask = atoi(row[29]); - entry.is_ldon_door = atoi(row[30]); - entry.min_expansion = atoi(row[31]); - entry.max_expansion = atoi(row[32]); - entry.content_flags = row[33] ? row[33] : ""; - entry.content_flags_disabled = row[34] ? row[34] : ""; + e.id = static_cast(atoi(row[0])); + e.doorid = static_cast(atoi(row[1])); + e.zone = row[2] ? row[2] : ""; + e.version = static_cast(atoi(row[3])); + e.name = row[4] ? row[4] : ""; + e.pos_y = strtof(row[5], nullptr); + e.pos_x = strtof(row[6], nullptr); + e.pos_z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.opentype = static_cast(atoi(row[9])); + e.guild = static_cast(atoi(row[10])); + e.lockpick = static_cast(atoi(row[11])); + e.keyitem = static_cast(atoi(row[12])); + e.nokeyring = static_cast(strtoul(row[13], nullptr, 10)); + e.triggerdoor = static_cast(atoi(row[14])); + e.triggertype = static_cast(atoi(row[15])); + e.disable_timer = static_cast(atoi(row[16])); + e.doorisopen = static_cast(atoi(row[17])); + e.door_param = static_cast(atoi(row[18])); + e.dest_zone = row[19] ? row[19] : ""; + e.dest_instance = static_cast(strtoul(row[20], nullptr, 10)); + e.dest_x = strtof(row[21], nullptr); + e.dest_y = strtof(row[22], nullptr); + e.dest_z = strtof(row[23], nullptr); + e.dest_heading = strtof(row[24], nullptr); + e.invert_state = static_cast(atoi(row[25])); + e.incline = static_cast(atoi(row[26])); + e.size = static_cast(strtoul(row[27], nullptr, 10)); + e.buffer = strtof(row[28], nullptr); + e.client_version_mask = static_cast(strtoul(row[29], nullptr, 10)); + e.is_ldon_door = static_cast(atoi(row[30])); + e.dz_switch_id = static_cast(atoi(row[31])); + e.min_expansion = static_cast(atoi(row[32])); + e.max_expansion = static_cast(atoi(row[33])); + e.content_flags = row[34] ? row[34] : ""; + e.content_flags_disabled = row[35] ? row[35] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -631,6 +641,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_DOORS_REPOSITORY_H diff --git a/common/repositories/base/base_dynamic_zone_members_repository.h b/common/repositories/base/base_dynamic_zone_members_repository.h index 4a9547140..7cd4fa68f 100644 --- a/common/repositories/base/base_dynamic_zone_members_repository.h +++ b/common/repositories/base/base_dynamic_zone_members_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseDynamicZoneMembersRepository { public: struct DynamicZoneMembers { - int id; - int dynamic_zone_id; - int character_id; + uint32_t id; + uint32_t dynamic_zone_id; + uint32_t character_id; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static DynamicZoneMembers NewEntity() { - DynamicZoneMembers entry{}; + DynamicZoneMembers e{}; - entry.id = 0; - entry.dynamic_zone_id = 0; - entry.character_id = 0; + e.id = 0; + e.dynamic_zone_id = 0; + e.character_id = 0; - return entry; + return e; } - static DynamicZoneMembers GetDynamicZoneMembersEntry( + static DynamicZoneMembers GetDynamicZoneMembers( const std::vector &dynamic_zone_memberss, int dynamic_zone_members_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - DynamicZoneMembers entry{}; + DynamicZoneMembers e{}; - entry.id = atoi(row[0]); - entry.dynamic_zone_id = atoi(row[1]); - entry.character_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); + e.character_id = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,23 +151,23 @@ public: static int UpdateOne( Database& db, - DynamicZoneMembers dynamic_zone_members_entry + const DynamicZoneMembers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(dynamic_zone_members_entry.dynamic_zone_id)); - update_values.push_back(columns[2] + " = " + std::to_string(dynamic_zone_members_entry.character_id)); + v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id)); + v.push_back(columns[2] + " = " + std::to_string(e.character_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - dynamic_zone_members_entry.id + e.id ) ); @@ -176,57 +176,57 @@ public: static DynamicZoneMembers InsertOne( Database& db, - DynamicZoneMembers dynamic_zone_members_entry + DynamicZoneMembers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(dynamic_zone_members_entry.id)); - insert_values.push_back(std::to_string(dynamic_zone_members_entry.dynamic_zone_id)); - insert_values.push_back(std::to_string(dynamic_zone_members_entry.character_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.dynamic_zone_id)); + v.push_back(std::to_string(e.character_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - dynamic_zone_members_entry.id = results.LastInsertedID(); - return dynamic_zone_members_entry; + e.id = results.LastInsertedID(); + return e; } - dynamic_zone_members_entry = NewEntity(); + e = NewEntity(); - return dynamic_zone_members_entry; + return e; } static int InsertMany( Database& db, - std::vector dynamic_zone_members_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &dynamic_zone_members_entry: dynamic_zone_members_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(dynamic_zone_members_entry.id)); - insert_values.push_back(std::to_string(dynamic_zone_members_entry.dynamic_zone_id)); - insert_values.push_back(std::to_string(dynamic_zone_members_entry.character_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.dynamic_zone_id)); + v.push_back(std::to_string(e.character_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -247,19 +247,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DynamicZoneMembers entry{}; + DynamicZoneMembers e{}; - entry.id = atoi(row[0]); - entry.dynamic_zone_id = atoi(row[1]); - entry.character_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); + e.character_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -274,19 +274,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DynamicZoneMembers entry{}; + DynamicZoneMembers e{}; - entry.id = atoi(row[0]); - entry.dynamic_zone_id = atoi(row[1]); - entry.character_id = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); + e.character_id = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -311,6 +311,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_dynamic_zone_templates_repository.h b/common/repositories/base/base_dynamic_zone_templates_repository.h new file mode 100644 index 000000000..40fa29397 --- /dev/null +++ b/common/repositories/base/base_dynamic_zone_templates_repository.h @@ -0,0 +1,532 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H +#define EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseDynamicZoneTemplatesRepository { +public: + struct DynamicZoneTemplates { + uint32_t id; + int32_t zone_id; + int32_t zone_version; + std::string name; + int32_t min_players; + int32_t max_players; + int32_t duration_seconds; + int32_t dz_switch_id; + int32_t compass_zone_id; + float compass_x; + float compass_y; + float compass_z; + int32_t return_zone_id; + float return_x; + float return_y; + float return_z; + float return_h; + int8_t override_zone_in; + float zone_in_x; + float zone_in_y; + float zone_in_z; + float zone_in_h; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "zone_id", + "zone_version", + "name", + "min_players", + "max_players", + "duration_seconds", + "dz_switch_id", + "compass_zone_id", + "compass_x", + "compass_y", + "compass_z", + "return_zone_id", + "return_x", + "return_y", + "return_z", + "return_h", + "override_zone_in", + "zone_in_x", + "zone_in_y", + "zone_in_z", + "zone_in_h", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "zone_id", + "zone_version", + "name", + "min_players", + "max_players", + "duration_seconds", + "dz_switch_id", + "compass_zone_id", + "compass_x", + "compass_y", + "compass_z", + "return_zone_id", + "return_x", + "return_y", + "return_z", + "return_h", + "override_zone_in", + "zone_in_x", + "zone_in_y", + "zone_in_z", + "zone_in_h", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("dynamic_zone_templates"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static DynamicZoneTemplates NewEntity() + { + DynamicZoneTemplates e{}; + + e.id = 0; + e.zone_id = 0; + e.zone_version = 0; + e.name = ""; + e.min_players = 0; + e.max_players = 0; + e.duration_seconds = 0; + e.dz_switch_id = 0; + e.compass_zone_id = 0; + e.compass_x = 0; + e.compass_y = 0; + e.compass_z = 0; + e.return_zone_id = 0; + e.return_x = 0; + e.return_y = 0; + e.return_z = 0; + e.return_h = 0; + e.override_zone_in = 0; + e.zone_in_x = 0; + e.zone_in_y = 0; + e.zone_in_z = 0; + e.zone_in_h = 0; + + return e; + } + + static DynamicZoneTemplates GetDynamicZoneTemplates( + const std::vector &dynamic_zone_templatess, + int dynamic_zone_templates_id + ) + { + for (auto &dynamic_zone_templates : dynamic_zone_templatess) { + if (dynamic_zone_templates.id == dynamic_zone_templates_id) { + return dynamic_zone_templates; + } + } + + return NewEntity(); + } + + static DynamicZoneTemplates FindOne( + Database& db, + int dynamic_zone_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + dynamic_zone_templates_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + DynamicZoneTemplates e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone_id = static_cast(atoi(row[1])); + e.zone_version = static_cast(atoi(row[2])); + e.name = row[3] ? row[3] : ""; + e.min_players = static_cast(atoi(row[4])); + e.max_players = static_cast(atoi(row[5])); + e.duration_seconds = static_cast(atoi(row[6])); + e.dz_switch_id = static_cast(atoi(row[7])); + e.compass_zone_id = static_cast(atoi(row[8])); + e.compass_x = strtof(row[9], nullptr); + e.compass_y = strtof(row[10], nullptr); + e.compass_z = strtof(row[11], nullptr); + e.return_zone_id = static_cast(atoi(row[12])); + e.return_x = strtof(row[13], nullptr); + e.return_y = strtof(row[14], nullptr); + e.return_z = strtof(row[15], nullptr); + e.return_h = strtof(row[16], nullptr); + e.override_zone_in = static_cast(atoi(row[17])); + e.zone_in_x = strtof(row[18], nullptr); + e.zone_in_y = strtof(row[19], nullptr); + e.zone_in_z = strtof(row[20], nullptr); + e.zone_in_h = strtof(row[21], nullptr); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int dynamic_zone_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + dynamic_zone_templates_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const DynamicZoneTemplates &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[2] + " = " + std::to_string(e.zone_version)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.min_players)); + v.push_back(columns[5] + " = " + std::to_string(e.max_players)); + v.push_back(columns[6] + " = " + std::to_string(e.duration_seconds)); + v.push_back(columns[7] + " = " + std::to_string(e.dz_switch_id)); + v.push_back(columns[8] + " = " + std::to_string(e.compass_zone_id)); + v.push_back(columns[9] + " = " + std::to_string(e.compass_x)); + v.push_back(columns[10] + " = " + std::to_string(e.compass_y)); + v.push_back(columns[11] + " = " + std::to_string(e.compass_z)); + v.push_back(columns[12] + " = " + std::to_string(e.return_zone_id)); + v.push_back(columns[13] + " = " + std::to_string(e.return_x)); + v.push_back(columns[14] + " = " + std::to_string(e.return_y)); + v.push_back(columns[15] + " = " + std::to_string(e.return_z)); + v.push_back(columns[16] + " = " + std::to_string(e.return_h)); + v.push_back(columns[17] + " = " + std::to_string(e.override_zone_in)); + v.push_back(columns[18] + " = " + std::to_string(e.zone_in_x)); + v.push_back(columns[19] + " = " + std::to_string(e.zone_in_y)); + v.push_back(columns[20] + " = " + std::to_string(e.zone_in_z)); + v.push_back(columns[21] + " = " + std::to_string(e.zone_in_h)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static DynamicZoneTemplates InsertOne( + Database& db, + DynamicZoneTemplates e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.zone_version)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.min_players)); + v.push_back(std::to_string(e.max_players)); + v.push_back(std::to_string(e.duration_seconds)); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.compass_zone_id)); + v.push_back(std::to_string(e.compass_x)); + v.push_back(std::to_string(e.compass_y)); + v.push_back(std::to_string(e.compass_z)); + v.push_back(std::to_string(e.return_zone_id)); + v.push_back(std::to_string(e.return_x)); + v.push_back(std::to_string(e.return_y)); + v.push_back(std::to_string(e.return_z)); + v.push_back(std::to_string(e.return_h)); + v.push_back(std::to_string(e.override_zone_in)); + v.push_back(std::to_string(e.zone_in_x)); + v.push_back(std::to_string(e.zone_in_y)); + v.push_back(std::to_string(e.zone_in_z)); + v.push_back(std::to_string(e.zone_in_h)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.zone_version)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.min_players)); + v.push_back(std::to_string(e.max_players)); + v.push_back(std::to_string(e.duration_seconds)); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.compass_zone_id)); + v.push_back(std::to_string(e.compass_x)); + v.push_back(std::to_string(e.compass_y)); + v.push_back(std::to_string(e.compass_z)); + v.push_back(std::to_string(e.return_zone_id)); + v.push_back(std::to_string(e.return_x)); + v.push_back(std::to_string(e.return_y)); + v.push_back(std::to_string(e.return_z)); + v.push_back(std::to_string(e.return_h)); + v.push_back(std::to_string(e.override_zone_in)); + v.push_back(std::to_string(e.zone_in_x)); + v.push_back(std::to_string(e.zone_in_y)); + v.push_back(std::to_string(e.zone_in_z)); + v.push_back(std::to_string(e.zone_in_h)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + DynamicZoneTemplates e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone_id = static_cast(atoi(row[1])); + e.zone_version = static_cast(atoi(row[2])); + e.name = row[3] ? row[3] : ""; + e.min_players = static_cast(atoi(row[4])); + e.max_players = static_cast(atoi(row[5])); + e.duration_seconds = static_cast(atoi(row[6])); + e.dz_switch_id = static_cast(atoi(row[7])); + e.compass_zone_id = static_cast(atoi(row[8])); + e.compass_x = strtof(row[9], nullptr); + e.compass_y = strtof(row[10], nullptr); + e.compass_z = strtof(row[11], nullptr); + e.return_zone_id = static_cast(atoi(row[12])); + e.return_x = strtof(row[13], nullptr); + e.return_y = strtof(row[14], nullptr); + e.return_z = strtof(row[15], nullptr); + e.return_h = strtof(row[16], nullptr); + e.override_zone_in = static_cast(atoi(row[17])); + e.zone_in_x = strtof(row[18], nullptr); + e.zone_in_y = strtof(row[19], nullptr); + e.zone_in_z = strtof(row[20], nullptr); + e.zone_in_h = strtof(row[21], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + DynamicZoneTemplates e{}; + + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone_id = static_cast(atoi(row[1])); + e.zone_version = static_cast(atoi(row[2])); + e.name = row[3] ? row[3] : ""; + e.min_players = static_cast(atoi(row[4])); + e.max_players = static_cast(atoi(row[5])); + e.duration_seconds = static_cast(atoi(row[6])); + e.dz_switch_id = static_cast(atoi(row[7])); + e.compass_zone_id = static_cast(atoi(row[8])); + e.compass_x = strtof(row[9], nullptr); + e.compass_y = strtof(row[10], nullptr); + e.compass_z = strtof(row[11], nullptr); + e.return_zone_id = static_cast(atoi(row[12])); + e.return_x = strtof(row[13], nullptr); + e.return_y = strtof(row[14], nullptr); + e.return_z = strtof(row[15], nullptr); + e.return_h = strtof(row[16], nullptr); + e.override_zone_in = static_cast(atoi(row[17])); + e.zone_in_x = strtof(row[18], nullptr); + e.zone_in_y = strtof(row[19], nullptr); + e.zone_in_z = strtof(row[20], nullptr); + e.zone_in_h = strtof(row[21], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_dynamic_zones_repository.h b/common/repositories/base/base_dynamic_zones_repository.h index 5cf186cf2..0def54ea1 100644 --- a/common/repositories/base/base_dynamic_zones_repository.h +++ b/common/repositories/base/base_dynamic_zones_repository.h @@ -13,25 +13,26 @@ #define EQEMU_BASE_DYNAMIC_ZONES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseDynamicZonesRepository { public: struct DynamicZones { - int id; - int instance_id; - int type; + uint32_t id; + int32_t instance_id; + uint8_t type; std::string uuid; std::string name; - int leader_id; - int min_players; - int max_players; - int compass_zone_id; + uint32_t leader_id; + uint32_t min_players; + uint32_t max_players; + int32_t dz_switch_id; + uint32_t compass_zone_id; float compass_x; float compass_y; float compass_z; - int safe_return_zone_id; + uint32_t safe_return_zone_id; float safe_return_x; float safe_return_y; float safe_return_z; @@ -40,7 +41,7 @@ public: float zone_in_y; float zone_in_z; float zone_in_heading; - int has_zone_in; + uint8_t has_zone_in; }; static std::string PrimaryKey() @@ -59,6 +60,7 @@ public: "leader_id", "min_players", "max_players", + "dz_switch_id", "compass_zone_id", "compass_x", "compass_y", @@ -87,6 +89,7 @@ public: "leader_id", "min_players", "max_players", + "dz_switch_id", "compass_zone_id", "compass_x", "compass_y", @@ -106,12 +109,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -139,35 +142,36 @@ public: static DynamicZones NewEntity() { - DynamicZones entry{}; + DynamicZones e{}; - entry.id = 0; - entry.instance_id = 0; - entry.type = 0; - entry.uuid = ""; - entry.name = ""; - entry.leader_id = 0; - entry.min_players = 0; - entry.max_players = 0; - entry.compass_zone_id = 0; - entry.compass_x = 0; - entry.compass_y = 0; - entry.compass_z = 0; - entry.safe_return_zone_id = 0; - entry.safe_return_x = 0; - entry.safe_return_y = 0; - entry.safe_return_z = 0; - entry.safe_return_heading = 0; - entry.zone_in_x = 0; - entry.zone_in_y = 0; - entry.zone_in_z = 0; - entry.zone_in_heading = 0; - entry.has_zone_in = 0; + e.id = 0; + e.instance_id = 0; + e.type = 0; + e.uuid = ""; + e.name = ""; + e.leader_id = 0; + e.min_players = 0; + e.max_players = 0; + e.dz_switch_id = 0; + e.compass_zone_id = 0; + e.compass_x = 0; + e.compass_y = 0; + e.compass_z = 0; + e.safe_return_zone_id = 0; + e.safe_return_x = 0; + e.safe_return_y = 0; + e.safe_return_z = 0; + e.safe_return_heading = 0; + e.zone_in_x = 0; + e.zone_in_y = 0; + e.zone_in_z = 0; + e.zone_in_heading = 0; + e.has_zone_in = 0; - return entry; + return e; } - static DynamicZones GetDynamicZonesEntry( + static DynamicZones GetDynamicZones( const std::vector &dynamic_zoness, int dynamic_zones_id ) @@ -196,32 +200,33 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - DynamicZones entry{}; + DynamicZones e{}; - entry.id = atoi(row[0]); - entry.instance_id = atoi(row[1]); - entry.type = atoi(row[2]); - entry.uuid = row[3] ? row[3] : ""; - entry.name = row[4] ? row[4] : ""; - entry.leader_id = atoi(row[5]); - entry.min_players = atoi(row[6]); - entry.max_players = atoi(row[7]); - entry.compass_zone_id = atoi(row[8]); - entry.compass_x = static_cast(atof(row[9])); - entry.compass_y = static_cast(atof(row[10])); - entry.compass_z = static_cast(atof(row[11])); - entry.safe_return_zone_id = atoi(row[12]); - entry.safe_return_x = static_cast(atof(row[13])); - entry.safe_return_y = static_cast(atof(row[14])); - entry.safe_return_z = static_cast(atof(row[15])); - entry.safe_return_heading = static_cast(atof(row[16])); - entry.zone_in_x = static_cast(atof(row[17])); - entry.zone_in_y = static_cast(atof(row[18])); - entry.zone_in_z = static_cast(atof(row[19])); - entry.zone_in_heading = static_cast(atof(row[20])); - entry.has_zone_in = atoi(row[21]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.instance_id = static_cast(atoi(row[1])); + e.type = static_cast(strtoul(row[2], nullptr, 10)); + e.uuid = row[3] ? row[3] : ""; + e.name = row[4] ? row[4] : ""; + e.leader_id = static_cast(strtoul(row[5], nullptr, 10)); + e.min_players = static_cast(strtoul(row[6], nullptr, 10)); + e.max_players = static_cast(strtoul(row[7], nullptr, 10)); + e.dz_switch_id = static_cast(atoi(row[8])); + e.compass_zone_id = static_cast(strtoul(row[9], nullptr, 10)); + e.compass_x = strtof(row[10], nullptr); + e.compass_y = strtof(row[11], nullptr); + e.compass_z = strtof(row[12], nullptr); + e.safe_return_zone_id = static_cast(strtoul(row[13], nullptr, 10)); + e.safe_return_x = strtof(row[14], nullptr); + e.safe_return_y = strtof(row[15], nullptr); + e.safe_return_z = strtof(row[16], nullptr); + e.safe_return_heading = strtof(row[17], nullptr); + e.zone_in_x = strtof(row[18], nullptr); + e.zone_in_y = strtof(row[19], nullptr); + e.zone_in_z = strtof(row[20], nullptr); + e.zone_in_heading = strtof(row[21], nullptr); + e.has_zone_in = static_cast(strtoul(row[22], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -246,42 +251,43 @@ public: static int UpdateOne( Database& db, - DynamicZones dynamic_zones_entry + const DynamicZones &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(dynamic_zones_entry.instance_id)); - update_values.push_back(columns[2] + " = " + std::to_string(dynamic_zones_entry.type)); - update_values.push_back(columns[3] + " = '" + EscapeString(dynamic_zones_entry.uuid) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(dynamic_zones_entry.name) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(dynamic_zones_entry.leader_id)); - update_values.push_back(columns[6] + " = " + std::to_string(dynamic_zones_entry.min_players)); - update_values.push_back(columns[7] + " = " + std::to_string(dynamic_zones_entry.max_players)); - update_values.push_back(columns[8] + " = " + std::to_string(dynamic_zones_entry.compass_zone_id)); - update_values.push_back(columns[9] + " = " + std::to_string(dynamic_zones_entry.compass_x)); - update_values.push_back(columns[10] + " = " + std::to_string(dynamic_zones_entry.compass_y)); - update_values.push_back(columns[11] + " = " + std::to_string(dynamic_zones_entry.compass_z)); - update_values.push_back(columns[12] + " = " + std::to_string(dynamic_zones_entry.safe_return_zone_id)); - update_values.push_back(columns[13] + " = " + std::to_string(dynamic_zones_entry.safe_return_x)); - update_values.push_back(columns[14] + " = " + std::to_string(dynamic_zones_entry.safe_return_y)); - update_values.push_back(columns[15] + " = " + std::to_string(dynamic_zones_entry.safe_return_z)); - update_values.push_back(columns[16] + " = " + std::to_string(dynamic_zones_entry.safe_return_heading)); - update_values.push_back(columns[17] + " = " + std::to_string(dynamic_zones_entry.zone_in_x)); - update_values.push_back(columns[18] + " = " + std::to_string(dynamic_zones_entry.zone_in_y)); - update_values.push_back(columns[19] + " = " + std::to_string(dynamic_zones_entry.zone_in_z)); - update_values.push_back(columns[20] + " = " + std::to_string(dynamic_zones_entry.zone_in_heading)); - update_values.push_back(columns[21] + " = " + std::to_string(dynamic_zones_entry.has_zone_in)); + v.push_back(columns[1] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[2] + " = " + std::to_string(e.type)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.uuid) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.leader_id)); + v.push_back(columns[6] + " = " + std::to_string(e.min_players)); + v.push_back(columns[7] + " = " + std::to_string(e.max_players)); + v.push_back(columns[8] + " = " + std::to_string(e.dz_switch_id)); + v.push_back(columns[9] + " = " + std::to_string(e.compass_zone_id)); + v.push_back(columns[10] + " = " + std::to_string(e.compass_x)); + v.push_back(columns[11] + " = " + std::to_string(e.compass_y)); + v.push_back(columns[12] + " = " + std::to_string(e.compass_z)); + v.push_back(columns[13] + " = " + std::to_string(e.safe_return_zone_id)); + v.push_back(columns[14] + " = " + std::to_string(e.safe_return_x)); + v.push_back(columns[15] + " = " + std::to_string(e.safe_return_y)); + v.push_back(columns[16] + " = " + std::to_string(e.safe_return_z)); + v.push_back(columns[17] + " = " + std::to_string(e.safe_return_heading)); + v.push_back(columns[18] + " = " + std::to_string(e.zone_in_x)); + v.push_back(columns[19] + " = " + std::to_string(e.zone_in_y)); + v.push_back(columns[20] + " = " + std::to_string(e.zone_in_z)); + v.push_back(columns[21] + " = " + std::to_string(e.zone_in_heading)); + v.push_back(columns[22] + " = " + std::to_string(e.has_zone_in)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - dynamic_zones_entry.id + e.id ) ); @@ -290,95 +296,97 @@ public: static DynamicZones InsertOne( Database& db, - DynamicZones dynamic_zones_entry + DynamicZones e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(dynamic_zones_entry.id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.instance_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.type)); - insert_values.push_back("'" + EscapeString(dynamic_zones_entry.uuid) + "'"); - insert_values.push_back("'" + EscapeString(dynamic_zones_entry.name) + "'"); - insert_values.push_back(std::to_string(dynamic_zones_entry.leader_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.min_players)); - insert_values.push_back(std::to_string(dynamic_zones_entry.max_players)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_zone_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_x)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_y)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_z)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_zone_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_x)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_y)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_z)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_heading)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_x)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_y)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_z)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_heading)); - insert_values.push_back(std::to_string(dynamic_zones_entry.has_zone_in)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.uuid) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.leader_id)); + v.push_back(std::to_string(e.min_players)); + v.push_back(std::to_string(e.max_players)); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.compass_zone_id)); + v.push_back(std::to_string(e.compass_x)); + v.push_back(std::to_string(e.compass_y)); + v.push_back(std::to_string(e.compass_z)); + v.push_back(std::to_string(e.safe_return_zone_id)); + v.push_back(std::to_string(e.safe_return_x)); + v.push_back(std::to_string(e.safe_return_y)); + v.push_back(std::to_string(e.safe_return_z)); + v.push_back(std::to_string(e.safe_return_heading)); + v.push_back(std::to_string(e.zone_in_x)); + v.push_back(std::to_string(e.zone_in_y)); + v.push_back(std::to_string(e.zone_in_z)); + v.push_back(std::to_string(e.zone_in_heading)); + v.push_back(std::to_string(e.has_zone_in)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - dynamic_zones_entry.id = results.LastInsertedID(); - return dynamic_zones_entry; + e.id = results.LastInsertedID(); + return e; } - dynamic_zones_entry = NewEntity(); + e = NewEntity(); - return dynamic_zones_entry; + return e; } static int InsertMany( Database& db, - std::vector dynamic_zones_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &dynamic_zones_entry: dynamic_zones_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(dynamic_zones_entry.id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.instance_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.type)); - insert_values.push_back("'" + EscapeString(dynamic_zones_entry.uuid) + "'"); - insert_values.push_back("'" + EscapeString(dynamic_zones_entry.name) + "'"); - insert_values.push_back(std::to_string(dynamic_zones_entry.leader_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.min_players)); - insert_values.push_back(std::to_string(dynamic_zones_entry.max_players)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_zone_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_x)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_y)); - insert_values.push_back(std::to_string(dynamic_zones_entry.compass_z)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_zone_id)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_x)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_y)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_z)); - insert_values.push_back(std::to_string(dynamic_zones_entry.safe_return_heading)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_x)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_y)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_z)); - insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_heading)); - insert_values.push_back(std::to_string(dynamic_zones_entry.has_zone_in)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.uuid) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.leader_id)); + v.push_back(std::to_string(e.min_players)); + v.push_back(std::to_string(e.max_players)); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.compass_zone_id)); + v.push_back(std::to_string(e.compass_x)); + v.push_back(std::to_string(e.compass_y)); + v.push_back(std::to_string(e.compass_z)); + v.push_back(std::to_string(e.safe_return_zone_id)); + v.push_back(std::to_string(e.safe_return_x)); + v.push_back(std::to_string(e.safe_return_y)); + v.push_back(std::to_string(e.safe_return_z)); + v.push_back(std::to_string(e.safe_return_heading)); + v.push_back(std::to_string(e.zone_in_x)); + v.push_back(std::to_string(e.zone_in_y)); + v.push_back(std::to_string(e.zone_in_z)); + v.push_back(std::to_string(e.zone_in_heading)); + v.push_back(std::to_string(e.has_zone_in)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -399,38 +407,39 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DynamicZones entry{}; + DynamicZones e{}; - entry.id = atoi(row[0]); - entry.instance_id = atoi(row[1]); - entry.type = atoi(row[2]); - entry.uuid = row[3] ? row[3] : ""; - entry.name = row[4] ? row[4] : ""; - entry.leader_id = atoi(row[5]); - entry.min_players = atoi(row[6]); - entry.max_players = atoi(row[7]); - entry.compass_zone_id = atoi(row[8]); - entry.compass_x = static_cast(atof(row[9])); - entry.compass_y = static_cast(atof(row[10])); - entry.compass_z = static_cast(atof(row[11])); - entry.safe_return_zone_id = atoi(row[12]); - entry.safe_return_x = static_cast(atof(row[13])); - entry.safe_return_y = static_cast(atof(row[14])); - entry.safe_return_z = static_cast(atof(row[15])); - entry.safe_return_heading = static_cast(atof(row[16])); - entry.zone_in_x = static_cast(atof(row[17])); - entry.zone_in_y = static_cast(atof(row[18])); - entry.zone_in_z = static_cast(atof(row[19])); - entry.zone_in_heading = static_cast(atof(row[20])); - entry.has_zone_in = atoi(row[21]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.instance_id = static_cast(atoi(row[1])); + e.type = static_cast(strtoul(row[2], nullptr, 10)); + e.uuid = row[3] ? row[3] : ""; + e.name = row[4] ? row[4] : ""; + e.leader_id = static_cast(strtoul(row[5], nullptr, 10)); + e.min_players = static_cast(strtoul(row[6], nullptr, 10)); + e.max_players = static_cast(strtoul(row[7], nullptr, 10)); + e.dz_switch_id = static_cast(atoi(row[8])); + e.compass_zone_id = static_cast(strtoul(row[9], nullptr, 10)); + e.compass_x = strtof(row[10], nullptr); + e.compass_y = strtof(row[11], nullptr); + e.compass_z = strtof(row[12], nullptr); + e.safe_return_zone_id = static_cast(strtoul(row[13], nullptr, 10)); + e.safe_return_x = strtof(row[14], nullptr); + e.safe_return_y = strtof(row[15], nullptr); + e.safe_return_z = strtof(row[16], nullptr); + e.safe_return_heading = strtof(row[17], nullptr); + e.zone_in_x = strtof(row[18], nullptr); + e.zone_in_y = strtof(row[19], nullptr); + e.zone_in_z = strtof(row[20], nullptr); + e.zone_in_heading = strtof(row[21], nullptr); + e.has_zone_in = static_cast(strtoul(row[22], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -445,38 +454,39 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - DynamicZones entry{}; + DynamicZones e{}; - entry.id = atoi(row[0]); - entry.instance_id = atoi(row[1]); - entry.type = atoi(row[2]); - entry.uuid = row[3] ? row[3] : ""; - entry.name = row[4] ? row[4] : ""; - entry.leader_id = atoi(row[5]); - entry.min_players = atoi(row[6]); - entry.max_players = atoi(row[7]); - entry.compass_zone_id = atoi(row[8]); - entry.compass_x = static_cast(atof(row[9])); - entry.compass_y = static_cast(atof(row[10])); - entry.compass_z = static_cast(atof(row[11])); - entry.safe_return_zone_id = atoi(row[12]); - entry.safe_return_x = static_cast(atof(row[13])); - entry.safe_return_y = static_cast(atof(row[14])); - entry.safe_return_z = static_cast(atof(row[15])); - entry.safe_return_heading = static_cast(atof(row[16])); - entry.zone_in_x = static_cast(atof(row[17])); - entry.zone_in_y = static_cast(atof(row[18])); - entry.zone_in_z = static_cast(atof(row[19])); - entry.zone_in_heading = static_cast(atof(row[20])); - entry.has_zone_in = atoi(row[21]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.instance_id = static_cast(atoi(row[1])); + e.type = static_cast(strtoul(row[2], nullptr, 10)); + e.uuid = row[3] ? row[3] : ""; + e.name = row[4] ? row[4] : ""; + e.leader_id = static_cast(strtoul(row[5], nullptr, 10)); + e.min_players = static_cast(strtoul(row[6], nullptr, 10)); + e.max_players = static_cast(strtoul(row[7], nullptr, 10)); + e.dz_switch_id = static_cast(atoi(row[8])); + e.compass_zone_id = static_cast(strtoul(row[9], nullptr, 10)); + e.compass_x = strtof(row[10], nullptr); + e.compass_y = strtof(row[11], nullptr); + e.compass_z = strtof(row[12], nullptr); + e.safe_return_zone_id = static_cast(strtoul(row[13], nullptr, 10)); + e.safe_return_x = strtof(row[14], nullptr); + e.safe_return_y = strtof(row[15], nullptr); + e.safe_return_z = strtof(row[16], nullptr); + e.safe_return_heading = strtof(row[17], nullptr); + e.zone_in_x = strtof(row[18], nullptr); + e.zone_in_y = strtof(row[19], nullptr); + e.zone_in_z = strtof(row[20], nullptr); + e.zone_in_heading = strtof(row[21], nullptr); + e.has_zone_in = static_cast(strtoul(row[22], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -501,6 +511,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_DYNAMIC_ZONES_REPOSITORY_H diff --git a/common/repositories/base/base_eventlog_repository.h b/common/repositories/base/base_eventlog_repository.h index 328c6ad4c..c2b008106 100644 --- a/common/repositories/base/base_eventlog_repository.h +++ b/common/repositories/base/base_eventlog_repository.h @@ -13,22 +13,22 @@ #define EQEMU_BASE_EVENTLOG_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseEventlogRepository { public: struct Eventlog { - int id; + uint32_t id; std::string accountname; - int accountid; - int status; + uint32_t accountid; + int32_t status; std::string charname; std::string target; std::string time; std::string descriptiontype; std::string description; - int event_nid; + int32_t event_nid; }; static std::string PrimaryKey() @@ -70,12 +70,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -103,23 +103,23 @@ public: static Eventlog NewEntity() { - Eventlog entry{}; + Eventlog e{}; - entry.id = 0; - entry.accountname = ""; - entry.accountid = 0; - entry.status = 0; - entry.charname = ""; - entry.target = "None"; - entry.time = std::time(nullptr); - entry.descriptiontype = ""; - entry.description = ""; - entry.event_nid = 0; + e.id = 0; + e.accountname = ""; + e.accountid = 0; + e.status = 0; + e.charname = ""; + e.target = "None"; + e.time = std::time(nullptr); + e.descriptiontype = ""; + e.description = ""; + e.event_nid = 0; - return entry; + return e; } - static Eventlog GetEventlogEntry( + static Eventlog GetEventlog( const std::vector &eventlogs, int eventlog_id ) @@ -148,20 +148,20 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Eventlog entry{}; + Eventlog e{}; - entry.id = atoi(row[0]); - entry.accountname = row[1] ? row[1] : ""; - entry.accountid = atoi(row[2]); - entry.status = atoi(row[3]); - entry.charname = row[4] ? row[4] : ""; - entry.target = row[5] ? row[5] : ""; - entry.time = row[6] ? row[6] : ""; - entry.descriptiontype = row[7] ? row[7] : ""; - entry.description = row[8] ? row[8] : ""; - entry.event_nid = atoi(row[9]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.accountname = row[1] ? row[1] : ""; + e.accountid = static_cast(strtoul(row[2], nullptr, 10)); + e.status = static_cast(atoi(row[3])); + e.charname = row[4] ? row[4] : ""; + e.target = row[5] ? row[5] : ""; + e.time = row[6] ? row[6] : ""; + e.descriptiontype = row[7] ? row[7] : ""; + e.description = row[8] ? row[8] : ""; + e.event_nid = static_cast(atoi(row[9])); - return entry; + return e; } return NewEntity(); @@ -186,30 +186,30 @@ public: static int UpdateOne( Database& db, - Eventlog eventlog_entry + const Eventlog &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(eventlog_entry.accountname) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(eventlog_entry.accountid)); - update_values.push_back(columns[3] + " = " + std::to_string(eventlog_entry.status)); - update_values.push_back(columns[4] + " = '" + EscapeString(eventlog_entry.charname) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(eventlog_entry.target) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(eventlog_entry.time) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(eventlog_entry.descriptiontype) + "'"); - update_values.push_back(columns[8] + " = '" + EscapeString(eventlog_entry.description) + "'"); - update_values.push_back(columns[9] + " = " + std::to_string(eventlog_entry.event_nid)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.accountname) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.accountid)); + v.push_back(columns[3] + " = " + std::to_string(e.status)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.charname) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.target) + "'"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.time) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.descriptiontype) + "'"); + v.push_back(columns[8] + " = '" + Strings::Escape(e.description) + "'"); + v.push_back(columns[9] + " = " + std::to_string(e.event_nid)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - eventlog_entry.id + e.id ) ); @@ -218,71 +218,71 @@ public: static Eventlog InsertOne( Database& db, - Eventlog eventlog_entry + Eventlog e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(eventlog_entry.id)); - insert_values.push_back("'" + EscapeString(eventlog_entry.accountname) + "'"); - insert_values.push_back(std::to_string(eventlog_entry.accountid)); - insert_values.push_back(std::to_string(eventlog_entry.status)); - insert_values.push_back("'" + EscapeString(eventlog_entry.charname) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.target) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.time) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.descriptiontype) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.description) + "'"); - insert_values.push_back(std::to_string(eventlog_entry.event_nid)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.accountname) + "'"); + v.push_back(std::to_string(e.accountid)); + v.push_back(std::to_string(e.status)); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.target) + "'"); + v.push_back("'" + Strings::Escape(e.time) + "'"); + v.push_back("'" + Strings::Escape(e.descriptiontype) + "'"); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back(std::to_string(e.event_nid)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - eventlog_entry.id = results.LastInsertedID(); - return eventlog_entry; + e.id = results.LastInsertedID(); + return e; } - eventlog_entry = NewEntity(); + e = NewEntity(); - return eventlog_entry; + return e; } static int InsertMany( Database& db, - std::vector eventlog_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &eventlog_entry: eventlog_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(eventlog_entry.id)); - insert_values.push_back("'" + EscapeString(eventlog_entry.accountname) + "'"); - insert_values.push_back(std::to_string(eventlog_entry.accountid)); - insert_values.push_back(std::to_string(eventlog_entry.status)); - insert_values.push_back("'" + EscapeString(eventlog_entry.charname) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.target) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.time) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.descriptiontype) + "'"); - insert_values.push_back("'" + EscapeString(eventlog_entry.description) + "'"); - insert_values.push_back(std::to_string(eventlog_entry.event_nid)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.accountname) + "'"); + v.push_back(std::to_string(e.accountid)); + v.push_back(std::to_string(e.status)); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.target) + "'"); + v.push_back("'" + Strings::Escape(e.time) + "'"); + v.push_back("'" + Strings::Escape(e.descriptiontype) + "'"); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back(std::to_string(e.event_nid)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -303,26 +303,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Eventlog entry{}; + Eventlog e{}; - entry.id = atoi(row[0]); - entry.accountname = row[1] ? row[1] : ""; - entry.accountid = atoi(row[2]); - entry.status = atoi(row[3]); - entry.charname = row[4] ? row[4] : ""; - entry.target = row[5] ? row[5] : ""; - entry.time = row[6] ? row[6] : ""; - entry.descriptiontype = row[7] ? row[7] : ""; - entry.description = row[8] ? row[8] : ""; - entry.event_nid = atoi(row[9]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.accountname = row[1] ? row[1] : ""; + e.accountid = static_cast(strtoul(row[2], nullptr, 10)); + e.status = static_cast(atoi(row[3])); + e.charname = row[4] ? row[4] : ""; + e.target = row[5] ? row[5] : ""; + e.time = row[6] ? row[6] : ""; + e.descriptiontype = row[7] ? row[7] : ""; + e.description = row[8] ? row[8] : ""; + e.event_nid = static_cast(atoi(row[9])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -337,26 +337,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Eventlog entry{}; + Eventlog e{}; - entry.id = atoi(row[0]); - entry.accountname = row[1] ? row[1] : ""; - entry.accountid = atoi(row[2]); - entry.status = atoi(row[3]); - entry.charname = row[4] ? row[4] : ""; - entry.target = row[5] ? row[5] : ""; - entry.time = row[6] ? row[6] : ""; - entry.descriptiontype = row[7] ? row[7] : ""; - entry.description = row[8] ? row[8] : ""; - entry.event_nid = atoi(row[9]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.accountname = row[1] ? row[1] : ""; + e.accountid = static_cast(strtoul(row[2], nullptr, 10)); + e.status = static_cast(atoi(row[3])); + e.charname = row[4] ? row[4] : ""; + e.target = row[5] ? row[5] : ""; + e.time = row[6] ? row[6] : ""; + e.descriptiontype = row[7] ? row[7] : ""; + e.description = row[8] ? row[8] : ""; + e.event_nid = static_cast(atoi(row[9])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -381,6 +381,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_EVENTLOG_REPOSITORY_H diff --git a/common/repositories/base/base_expedition_lockouts_repository.h b/common/repositories/base/base_expedition_lockouts_repository.h index b148b1b2d..e37dce650 100644 --- a/common/repositories/base/base_expedition_lockouts_repository.h +++ b/common/repositories/base/base_expedition_lockouts_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseExpeditionLockoutsRepository { public: struct ExpeditionLockouts { - int id; - int expedition_id; + uint32_t id; + uint32_t expedition_id; std::string event_name; time_t expire_time; - int duration; + uint32_t duration; std::string from_expedition_uuid; }; @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static ExpeditionLockouts NewEntity() { - ExpeditionLockouts entry{}; + ExpeditionLockouts e{}; - entry.id = 0; - entry.expedition_id = 0; - entry.event_name = ""; - entry.expire_time = std::time(nullptr); - entry.duration = 0; - entry.from_expedition_uuid = ""; + e.id = 0; + e.expedition_id = 0; + e.event_name = ""; + e.expire_time = std::time(nullptr); + e.duration = 0; + e.from_expedition_uuid = ""; - return entry; + return e; } - static ExpeditionLockouts GetExpeditionLockoutsEntry( + static ExpeditionLockouts GetExpeditionLockouts( const std::vector &expedition_lockoutss, int expedition_lockouts_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - ExpeditionLockouts entry{}; + ExpeditionLockouts e{}; - entry.id = atoi(row[0]); - entry.expedition_id = atoi(row[1]); - entry.event_name = row[2] ? row[2] : ""; - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.duration = atoi(row[4]); - entry.from_expedition_uuid = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.expedition_id = static_cast(strtoul(row[1], nullptr, 10)); + e.event_name = row[2] ? row[2] : ""; + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.duration = static_cast(strtoul(row[4], nullptr, 10)); + e.from_expedition_uuid = row[5] ? row[5] : ""; - return entry; + return e; } return NewEntity(); @@ -166,26 +166,26 @@ public: static int UpdateOne( Database& db, - ExpeditionLockouts expedition_lockouts_entry + const ExpeditionLockouts &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(expedition_lockouts_entry.expedition_id)); - update_values.push_back(columns[2] + " = '" + EscapeString(expedition_lockouts_entry.event_name) + "'"); - update_values.push_back(columns[3] + " = FROM_UNIXTIME(" + (expedition_lockouts_entry.expire_time > 0 ? std::to_string(expedition_lockouts_entry.expire_time) : "null") + ")"); - update_values.push_back(columns[4] + " = " + std::to_string(expedition_lockouts_entry.duration)); - update_values.push_back(columns[5] + " = '" + EscapeString(expedition_lockouts_entry.from_expedition_uuid) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.expedition_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.event_name) + "'"); + v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(columns[4] + " = " + std::to_string(e.duration)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.from_expedition_uuid) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - expedition_lockouts_entry.id + e.id ) ); @@ -194,63 +194,63 @@ public: static ExpeditionLockouts InsertOne( Database& db, - ExpeditionLockouts expedition_lockouts_entry + ExpeditionLockouts e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(expedition_lockouts_entry.id)); - insert_values.push_back(std::to_string(expedition_lockouts_entry.expedition_id)); - insert_values.push_back("'" + EscapeString(expedition_lockouts_entry.event_name) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (expedition_lockouts_entry.expire_time > 0 ? std::to_string(expedition_lockouts_entry.expire_time) : "null") + ")"); - insert_values.push_back(std::to_string(expedition_lockouts_entry.duration)); - insert_values.push_back("'" + EscapeString(expedition_lockouts_entry.from_expedition_uuid) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.expedition_id)); + v.push_back("'" + Strings::Escape(e.event_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(std::to_string(e.duration)); + v.push_back("'" + Strings::Escape(e.from_expedition_uuid) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - expedition_lockouts_entry.id = results.LastInsertedID(); - return expedition_lockouts_entry; + e.id = results.LastInsertedID(); + return e; } - expedition_lockouts_entry = NewEntity(); + e = NewEntity(); - return expedition_lockouts_entry; + return e; } static int InsertMany( Database& db, - std::vector expedition_lockouts_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &expedition_lockouts_entry: expedition_lockouts_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(expedition_lockouts_entry.id)); - insert_values.push_back(std::to_string(expedition_lockouts_entry.expedition_id)); - insert_values.push_back("'" + EscapeString(expedition_lockouts_entry.event_name) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (expedition_lockouts_entry.expire_time > 0 ? std::to_string(expedition_lockouts_entry.expire_time) : "null") + ")"); - insert_values.push_back(std::to_string(expedition_lockouts_entry.duration)); - insert_values.push_back("'" + EscapeString(expedition_lockouts_entry.from_expedition_uuid) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.expedition_id)); + v.push_back("'" + Strings::Escape(e.event_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(std::to_string(e.duration)); + v.push_back("'" + Strings::Escape(e.from_expedition_uuid) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -271,22 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ExpeditionLockouts entry{}; + ExpeditionLockouts e{}; - entry.id = atoi(row[0]); - entry.expedition_id = atoi(row[1]); - entry.event_name = row[2] ? row[2] : ""; - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.duration = atoi(row[4]); - entry.from_expedition_uuid = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.expedition_id = static_cast(strtoul(row[1], nullptr, 10)); + e.event_name = row[2] ? row[2] : ""; + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.duration = static_cast(strtoul(row[4], nullptr, 10)); + e.from_expedition_uuid = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -301,22 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ExpeditionLockouts entry{}; + ExpeditionLockouts e{}; - entry.id = atoi(row[0]); - entry.expedition_id = atoi(row[1]); - entry.event_name = row[2] ? row[2] : ""; - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.duration = atoi(row[4]); - entry.from_expedition_uuid = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.expedition_id = static_cast(strtoul(row[1], nullptr, 10)); + e.event_name = row[2] ? row[2] : ""; + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.duration = static_cast(strtoul(row[4], nullptr, 10)); + e.from_expedition_uuid = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -341,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H diff --git a/common/repositories/base/base_expeditions_repository.h b/common/repositories/base/base_expeditions_repository.h index 6e4cbdc0b..deaa3a01f 100644 --- a/common/repositories/base/base_expeditions_repository.h +++ b/common/repositories/base/base_expeditions_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_EXPEDITIONS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseExpeditionsRepository { public: struct Expeditions { - int id; - int dynamic_zone_id; - int add_replay_on_join; - int is_locked; + uint32_t id; + uint32_t dynamic_zone_id; + uint8_t add_replay_on_join; + uint8_t is_locked; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static Expeditions NewEntity() { - Expeditions entry{}; + Expeditions e{}; - entry.id = 0; - entry.dynamic_zone_id = 0; - entry.add_replay_on_join = 1; - entry.is_locked = 0; + e.id = 0; + e.dynamic_zone_id = 0; + e.add_replay_on_join = 1; + e.is_locked = 0; - return entry; + return e; } - static Expeditions GetExpeditionsEntry( + static Expeditions GetExpeditions( const std::vector &expeditionss, int expeditions_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Expeditions entry{}; + Expeditions e{}; - entry.id = atoi(row[0]); - entry.dynamic_zone_id = atoi(row[1]); - entry.add_replay_on_join = atoi(row[2]); - entry.is_locked = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); + e.add_replay_on_join = static_cast(strtoul(row[2], nullptr, 10)); + e.is_locked = static_cast(strtoul(row[3], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -156,24 +156,24 @@ public: static int UpdateOne( Database& db, - Expeditions expeditions_entry + const Expeditions &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(expeditions_entry.dynamic_zone_id)); - update_values.push_back(columns[2] + " = " + std::to_string(expeditions_entry.add_replay_on_join)); - update_values.push_back(columns[3] + " = " + std::to_string(expeditions_entry.is_locked)); + v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id)); + v.push_back(columns[2] + " = " + std::to_string(e.add_replay_on_join)); + v.push_back(columns[3] + " = " + std::to_string(e.is_locked)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - expeditions_entry.id + e.id ) ); @@ -182,59 +182,59 @@ public: static Expeditions InsertOne( Database& db, - Expeditions expeditions_entry + Expeditions e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(expeditions_entry.id)); - insert_values.push_back(std::to_string(expeditions_entry.dynamic_zone_id)); - insert_values.push_back(std::to_string(expeditions_entry.add_replay_on_join)); - insert_values.push_back(std::to_string(expeditions_entry.is_locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.dynamic_zone_id)); + v.push_back(std::to_string(e.add_replay_on_join)); + v.push_back(std::to_string(e.is_locked)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - expeditions_entry.id = results.LastInsertedID(); - return expeditions_entry; + e.id = results.LastInsertedID(); + return e; } - expeditions_entry = NewEntity(); + e = NewEntity(); - return expeditions_entry; + return e; } static int InsertMany( Database& db, - std::vector expeditions_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &expeditions_entry: expeditions_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(expeditions_entry.id)); - insert_values.push_back(std::to_string(expeditions_entry.dynamic_zone_id)); - insert_values.push_back(std::to_string(expeditions_entry.add_replay_on_join)); - insert_values.push_back(std::to_string(expeditions_entry.is_locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.dynamic_zone_id)); + v.push_back(std::to_string(e.add_replay_on_join)); + v.push_back(std::to_string(e.is_locked)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -255,20 +255,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Expeditions entry{}; + Expeditions e{}; - entry.id = atoi(row[0]); - entry.dynamic_zone_id = atoi(row[1]); - entry.add_replay_on_join = atoi(row[2]); - entry.is_locked = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); + e.add_replay_on_join = static_cast(strtoul(row[2], nullptr, 10)); + e.is_locked = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -283,20 +283,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Expeditions entry{}; + Expeditions e{}; - entry.id = atoi(row[0]); - entry.dynamic_zone_id = atoi(row[1]); - entry.add_replay_on_join = atoi(row[2]); - entry.is_locked = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); + e.add_replay_on_join = static_cast(strtoul(row[2], nullptr, 10)); + e.is_locked = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -321,6 +321,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_EXPEDITIONS_REPOSITORY_H diff --git a/common/repositories/base/base_faction_association_repository.h b/common/repositories/base/base_faction_association_repository.h new file mode 100644 index 000000000..029a355b6 --- /dev/null +++ b/common/repositories/base/base_faction_association_repository.h @@ -0,0 +1,523 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H +#define EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseFactionAssociationRepository { +public: + struct FactionAssociation { + int32_t id; + int32_t id_1; + float mod_1; + int32_t id_2; + float mod_2; + int32_t id_3; + float mod_3; + int32_t id_4; + float mod_4; + int32_t id_5; + float mod_5; + int32_t id_6; + float mod_6; + int32_t id_7; + float mod_7; + int32_t id_8; + float mod_8; + int32_t id_9; + float mod_9; + int32_t id_10; + float mod_10; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "id_1", + "mod_1", + "id_2", + "mod_2", + "id_3", + "mod_3", + "id_4", + "mod_4", + "id_5", + "mod_5", + "id_6", + "mod_6", + "id_7", + "mod_7", + "id_8", + "mod_8", + "id_9", + "mod_9", + "id_10", + "mod_10", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "id_1", + "mod_1", + "id_2", + "mod_2", + "id_3", + "mod_3", + "id_4", + "mod_4", + "id_5", + "mod_5", + "id_6", + "mod_6", + "id_7", + "mod_7", + "id_8", + "mod_8", + "id_9", + "mod_9", + "id_10", + "mod_10", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("faction_association"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static FactionAssociation NewEntity() + { + FactionAssociation e{}; + + e.id = 0; + e.id_1 = 0; + e.mod_1 = 0; + e.id_2 = 0; + e.mod_2 = 0; + e.id_3 = 0; + e.mod_3 = 0; + e.id_4 = 0; + e.mod_4 = 0; + e.id_5 = 0; + e.mod_5 = 0; + e.id_6 = 0; + e.mod_6 = 0; + e.id_7 = 0; + e.mod_7 = 0; + e.id_8 = 0; + e.mod_8 = 0; + e.id_9 = 0; + e.mod_9 = 0; + e.id_10 = 0; + e.mod_10 = 0; + + return e; + } + + static FactionAssociation GetFactionAssociation( + const std::vector &faction_associations, + int faction_association_id + ) + { + for (auto &faction_association : faction_associations) { + if (faction_association.id == faction_association_id) { + return faction_association; + } + } + + return NewEntity(); + } + + static FactionAssociation FindOne( + Database& db, + int faction_association_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + faction_association_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + FactionAssociation e{}; + + e.id = static_cast(atoi(row[0])); + e.id_1 = static_cast(atoi(row[1])); + e.mod_1 = strtof(row[2], nullptr); + e.id_2 = static_cast(atoi(row[3])); + e.mod_2 = strtof(row[4], nullptr); + e.id_3 = static_cast(atoi(row[5])); + e.mod_3 = strtof(row[6], nullptr); + e.id_4 = static_cast(atoi(row[7])); + e.mod_4 = strtof(row[8], nullptr); + e.id_5 = static_cast(atoi(row[9])); + e.mod_5 = strtof(row[10], nullptr); + e.id_6 = static_cast(atoi(row[11])); + e.mod_6 = strtof(row[12], nullptr); + e.id_7 = static_cast(atoi(row[13])); + e.mod_7 = strtof(row[14], nullptr); + e.id_8 = static_cast(atoi(row[15])); + e.mod_8 = strtof(row[16], nullptr); + e.id_9 = static_cast(atoi(row[17])); + e.mod_9 = strtof(row[18], nullptr); + e.id_10 = static_cast(atoi(row[19])); + e.mod_10 = strtof(row[20], nullptr); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int faction_association_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + faction_association_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const FactionAssociation &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.id_1)); + v.push_back(columns[2] + " = " + std::to_string(e.mod_1)); + v.push_back(columns[3] + " = " + std::to_string(e.id_2)); + v.push_back(columns[4] + " = " + std::to_string(e.mod_2)); + v.push_back(columns[5] + " = " + std::to_string(e.id_3)); + v.push_back(columns[6] + " = " + std::to_string(e.mod_3)); + v.push_back(columns[7] + " = " + std::to_string(e.id_4)); + v.push_back(columns[8] + " = " + std::to_string(e.mod_4)); + v.push_back(columns[9] + " = " + std::to_string(e.id_5)); + v.push_back(columns[10] + " = " + std::to_string(e.mod_5)); + v.push_back(columns[11] + " = " + std::to_string(e.id_6)); + v.push_back(columns[12] + " = " + std::to_string(e.mod_6)); + v.push_back(columns[13] + " = " + std::to_string(e.id_7)); + v.push_back(columns[14] + " = " + std::to_string(e.mod_7)); + v.push_back(columns[15] + " = " + std::to_string(e.id_8)); + v.push_back(columns[16] + " = " + std::to_string(e.mod_8)); + v.push_back(columns[17] + " = " + std::to_string(e.id_9)); + v.push_back(columns[18] + " = " + std::to_string(e.mod_9)); + v.push_back(columns[19] + " = " + std::to_string(e.id_10)); + v.push_back(columns[20] + " = " + std::to_string(e.mod_10)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static FactionAssociation InsertOne( + Database& db, + FactionAssociation e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.id_1)); + v.push_back(std::to_string(e.mod_1)); + v.push_back(std::to_string(e.id_2)); + v.push_back(std::to_string(e.mod_2)); + v.push_back(std::to_string(e.id_3)); + v.push_back(std::to_string(e.mod_3)); + v.push_back(std::to_string(e.id_4)); + v.push_back(std::to_string(e.mod_4)); + v.push_back(std::to_string(e.id_5)); + v.push_back(std::to_string(e.mod_5)); + v.push_back(std::to_string(e.id_6)); + v.push_back(std::to_string(e.mod_6)); + v.push_back(std::to_string(e.id_7)); + v.push_back(std::to_string(e.mod_7)); + v.push_back(std::to_string(e.id_8)); + v.push_back(std::to_string(e.mod_8)); + v.push_back(std::to_string(e.id_9)); + v.push_back(std::to_string(e.mod_9)); + v.push_back(std::to_string(e.id_10)); + v.push_back(std::to_string(e.mod_10)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.id_1)); + v.push_back(std::to_string(e.mod_1)); + v.push_back(std::to_string(e.id_2)); + v.push_back(std::to_string(e.mod_2)); + v.push_back(std::to_string(e.id_3)); + v.push_back(std::to_string(e.mod_3)); + v.push_back(std::to_string(e.id_4)); + v.push_back(std::to_string(e.mod_4)); + v.push_back(std::to_string(e.id_5)); + v.push_back(std::to_string(e.mod_5)); + v.push_back(std::to_string(e.id_6)); + v.push_back(std::to_string(e.mod_6)); + v.push_back(std::to_string(e.id_7)); + v.push_back(std::to_string(e.mod_7)); + v.push_back(std::to_string(e.id_8)); + v.push_back(std::to_string(e.mod_8)); + v.push_back(std::to_string(e.id_9)); + v.push_back(std::to_string(e.mod_9)); + v.push_back(std::to_string(e.id_10)); + v.push_back(std::to_string(e.mod_10)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + FactionAssociation e{}; + + e.id = static_cast(atoi(row[0])); + e.id_1 = static_cast(atoi(row[1])); + e.mod_1 = strtof(row[2], nullptr); + e.id_2 = static_cast(atoi(row[3])); + e.mod_2 = strtof(row[4], nullptr); + e.id_3 = static_cast(atoi(row[5])); + e.mod_3 = strtof(row[6], nullptr); + e.id_4 = static_cast(atoi(row[7])); + e.mod_4 = strtof(row[8], nullptr); + e.id_5 = static_cast(atoi(row[9])); + e.mod_5 = strtof(row[10], nullptr); + e.id_6 = static_cast(atoi(row[11])); + e.mod_6 = strtof(row[12], nullptr); + e.id_7 = static_cast(atoi(row[13])); + e.mod_7 = strtof(row[14], nullptr); + e.id_8 = static_cast(atoi(row[15])); + e.mod_8 = strtof(row[16], nullptr); + e.id_9 = static_cast(atoi(row[17])); + e.mod_9 = strtof(row[18], nullptr); + e.id_10 = static_cast(atoi(row[19])); + e.mod_10 = strtof(row[20], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + FactionAssociation e{}; + + e.id = static_cast(atoi(row[0])); + e.id_1 = static_cast(atoi(row[1])); + e.mod_1 = strtof(row[2], nullptr); + e.id_2 = static_cast(atoi(row[3])); + e.mod_2 = strtof(row[4], nullptr); + e.id_3 = static_cast(atoi(row[5])); + e.mod_3 = strtof(row[6], nullptr); + e.id_4 = static_cast(atoi(row[7])); + e.mod_4 = strtof(row[8], nullptr); + e.id_5 = static_cast(atoi(row[9])); + e.mod_5 = strtof(row[10], nullptr); + e.id_6 = static_cast(atoi(row[11])); + e.mod_6 = strtof(row[12], nullptr); + e.id_7 = static_cast(atoi(row[13])); + e.mod_7 = strtof(row[14], nullptr); + e.id_8 = static_cast(atoi(row[15])); + e.mod_8 = strtof(row[16], nullptr); + e.id_9 = static_cast(atoi(row[17])); + e.mod_9 = strtof(row[18], nullptr); + e.id_10 = static_cast(atoi(row[19])); + e.mod_10 = strtof(row[20], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H diff --git a/common/repositories/base/base_faction_base_data_repository.h b/common/repositories/base/base_faction_base_data_repository.h index cdf0f463d..3068d38bd 100644 --- a/common/repositories/base/base_faction_base_data_repository.h +++ b/common/repositories/base/base_faction_base_data_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_FACTION_BASE_DATA_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseFactionBaseDataRepository { public: struct FactionBaseData { - int client_faction_id; - int min; - int max; - int unk_hero1; - int unk_hero2; - int unk_hero3; + int16_t client_faction_id; + int16_t min; + int16_t max; + int16_t unk_hero1; + int16_t unk_hero2; + int16_t unk_hero3; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static FactionBaseData NewEntity() { - FactionBaseData entry{}; + FactionBaseData e{}; - entry.client_faction_id = 0; - entry.min = -2000; - entry.max = 2000; - entry.unk_hero1 = 0; - entry.unk_hero2 = 0; - entry.unk_hero3 = 0; + e.client_faction_id = 0; + e.min = -2000; + e.max = 2000; + e.unk_hero1 = 0; + e.unk_hero2 = 0; + e.unk_hero3 = 0; - return entry; + return e; } - static FactionBaseData GetFactionBaseDataEntry( + static FactionBaseData GetFactionBaseData( const std::vector &faction_base_datas, int faction_base_data_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - FactionBaseData entry{}; + FactionBaseData e{}; - entry.client_faction_id = atoi(row[0]); - entry.min = atoi(row[1]); - entry.max = atoi(row[2]); - entry.unk_hero1 = atoi(row[3]); - entry.unk_hero2 = atoi(row[4]); - entry.unk_hero3 = atoi(row[5]); + e.client_faction_id = static_cast(atoi(row[0])); + e.min = static_cast(atoi(row[1])); + e.max = static_cast(atoi(row[2])); + e.unk_hero1 = static_cast(atoi(row[3])); + e.unk_hero2 = static_cast(atoi(row[4])); + e.unk_hero3 = static_cast(atoi(row[5])); - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - FactionBaseData faction_base_data_entry + const FactionBaseData &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(faction_base_data_entry.client_faction_id)); - update_values.push_back(columns[1] + " = " + std::to_string(faction_base_data_entry.min)); - update_values.push_back(columns[2] + " = " + std::to_string(faction_base_data_entry.max)); - update_values.push_back(columns[3] + " = " + std::to_string(faction_base_data_entry.unk_hero1)); - update_values.push_back(columns[4] + " = " + std::to_string(faction_base_data_entry.unk_hero2)); - update_values.push_back(columns[5] + " = " + std::to_string(faction_base_data_entry.unk_hero3)); + v.push_back(columns[0] + " = " + std::to_string(e.client_faction_id)); + v.push_back(columns[1] + " = " + std::to_string(e.min)); + v.push_back(columns[2] + " = " + std::to_string(e.max)); + v.push_back(columns[3] + " = " + std::to_string(e.unk_hero1)); + v.push_back(columns[4] + " = " + std::to_string(e.unk_hero2)); + v.push_back(columns[5] + " = " + std::to_string(e.unk_hero3)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - faction_base_data_entry.client_faction_id + e.client_faction_id ) ); @@ -195,63 +195,63 @@ public: static FactionBaseData InsertOne( Database& db, - FactionBaseData faction_base_data_entry + FactionBaseData e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(faction_base_data_entry.client_faction_id)); - insert_values.push_back(std::to_string(faction_base_data_entry.min)); - insert_values.push_back(std::to_string(faction_base_data_entry.max)); - insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero1)); - insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero2)); - insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero3)); + v.push_back(std::to_string(e.client_faction_id)); + v.push_back(std::to_string(e.min)); + v.push_back(std::to_string(e.max)); + v.push_back(std::to_string(e.unk_hero1)); + v.push_back(std::to_string(e.unk_hero2)); + v.push_back(std::to_string(e.unk_hero3)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - faction_base_data_entry.client_faction_id = results.LastInsertedID(); - return faction_base_data_entry; + e.client_faction_id = results.LastInsertedID(); + return e; } - faction_base_data_entry = NewEntity(); + e = NewEntity(); - return faction_base_data_entry; + return e; } static int InsertMany( Database& db, - std::vector faction_base_data_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &faction_base_data_entry: faction_base_data_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(faction_base_data_entry.client_faction_id)); - insert_values.push_back(std::to_string(faction_base_data_entry.min)); - insert_values.push_back(std::to_string(faction_base_data_entry.max)); - insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero1)); - insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero2)); - insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero3)); + v.push_back(std::to_string(e.client_faction_id)); + v.push_back(std::to_string(e.min)); + v.push_back(std::to_string(e.max)); + v.push_back(std::to_string(e.unk_hero1)); + v.push_back(std::to_string(e.unk_hero2)); + v.push_back(std::to_string(e.unk_hero3)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionBaseData entry{}; + FactionBaseData e{}; - entry.client_faction_id = atoi(row[0]); - entry.min = atoi(row[1]); - entry.max = atoi(row[2]); - entry.unk_hero1 = atoi(row[3]); - entry.unk_hero2 = atoi(row[4]); - entry.unk_hero3 = atoi(row[5]); + e.client_faction_id = static_cast(atoi(row[0])); + e.min = static_cast(atoi(row[1])); + e.max = static_cast(atoi(row[2])); + e.unk_hero1 = static_cast(atoi(row[3])); + e.unk_hero2 = static_cast(atoi(row[4])); + e.unk_hero3 = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionBaseData entry{}; + FactionBaseData e{}; - entry.client_faction_id = atoi(row[0]); - entry.min = atoi(row[1]); - entry.max = atoi(row[2]); - entry.unk_hero1 = atoi(row[3]); - entry.unk_hero2 = atoi(row[4]); - entry.unk_hero3 = atoi(row[5]); + e.client_faction_id = static_cast(atoi(row[0])); + e.min = static_cast(atoi(row[1])); + e.max = static_cast(atoi(row[2])); + e.unk_hero1 = static_cast(atoi(row[3])); + e.unk_hero2 = static_cast(atoi(row[4])); + e.unk_hero3 = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_FACTION_BASE_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_faction_list_mod_repository.h b/common/repositories/base/base_faction_list_mod_repository.h index 2a03a0a02..26df4e6cb 100644 --- a/common/repositories/base/base_faction_list_mod_repository.h +++ b/common/repositories/base/base_faction_list_mod_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_FACTION_LIST_MOD_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseFactionListModRepository { public: struct FactionListMod { - int id; - int faction_id; - int mod; + uint32_t id; + uint32_t faction_id; + int16_t mod; std::string mod_name; }; @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static FactionListMod NewEntity() { - FactionListMod entry{}; + FactionListMod e{}; - entry.id = 0; - entry.faction_id = 0; - entry.mod = 0; - entry.mod_name = ""; + e.id = 0; + e.faction_id = 0; + e.mod = 0; + e.mod_name = ""; - return entry; + return e; } - static FactionListMod GetFactionListModEntry( + static FactionListMod GetFactionListMod( const std::vector &faction_list_mods, int faction_list_mod_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - FactionListMod entry{}; + FactionListMod e{}; - entry.id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.mod = atoi(row[2]); - entry.mod_name = row[3] ? row[3] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.faction_id = static_cast(strtoul(row[1], nullptr, 10)); + e.mod = static_cast(atoi(row[2])); + e.mod_name = row[3] ? row[3] : ""; - return entry; + return e; } return NewEntity(); @@ -156,24 +156,24 @@ public: static int UpdateOne( Database& db, - FactionListMod faction_list_mod_entry + const FactionListMod &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(faction_list_mod_entry.faction_id)); - update_values.push_back(columns[2] + " = " + std::to_string(faction_list_mod_entry.mod)); - update_values.push_back(columns[3] + " = '" + EscapeString(faction_list_mod_entry.mod_name) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.faction_id)); + v.push_back(columns[2] + " = " + std::to_string(e.mod)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.mod_name) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - faction_list_mod_entry.id + e.id ) ); @@ -182,59 +182,59 @@ public: static FactionListMod InsertOne( Database& db, - FactionListMod faction_list_mod_entry + FactionListMod e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(faction_list_mod_entry.id)); - insert_values.push_back(std::to_string(faction_list_mod_entry.faction_id)); - insert_values.push_back(std::to_string(faction_list_mod_entry.mod)); - insert_values.push_back("'" + EscapeString(faction_list_mod_entry.mod_name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.faction_id)); + v.push_back(std::to_string(e.mod)); + v.push_back("'" + Strings::Escape(e.mod_name) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - faction_list_mod_entry.id = results.LastInsertedID(); - return faction_list_mod_entry; + e.id = results.LastInsertedID(); + return e; } - faction_list_mod_entry = NewEntity(); + e = NewEntity(); - return faction_list_mod_entry; + return e; } static int InsertMany( Database& db, - std::vector faction_list_mod_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &faction_list_mod_entry: faction_list_mod_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(faction_list_mod_entry.id)); - insert_values.push_back(std::to_string(faction_list_mod_entry.faction_id)); - insert_values.push_back(std::to_string(faction_list_mod_entry.mod)); - insert_values.push_back("'" + EscapeString(faction_list_mod_entry.mod_name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.faction_id)); + v.push_back(std::to_string(e.mod)); + v.push_back("'" + Strings::Escape(e.mod_name) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -255,20 +255,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionListMod entry{}; + FactionListMod e{}; - entry.id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.mod = atoi(row[2]); - entry.mod_name = row[3] ? row[3] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.faction_id = static_cast(strtoul(row[1], nullptr, 10)); + e.mod = static_cast(atoi(row[2])); + e.mod_name = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -283,20 +283,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionListMod entry{}; + FactionListMod e{}; - entry.id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.mod = atoi(row[2]); - entry.mod_name = row[3] ? row[3] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.faction_id = static_cast(strtoul(row[1], nullptr, 10)); + e.mod = static_cast(atoi(row[2])); + e.mod_name = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -321,6 +321,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_FACTION_LIST_MOD_REPOSITORY_H diff --git a/common/repositories/base/base_faction_list_repository.h b/common/repositories/base/base_faction_list_repository.h index 51068b19b..6d2398187 100644 --- a/common/repositories/base/base_faction_list_repository.h +++ b/common/repositories/base/base_faction_list_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_FACTION_LIST_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseFactionListRepository { public: struct FactionList { - int id; + int32_t id; std::string name; - int base; + int16_t base; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static FactionList NewEntity() { - FactionList entry{}; + FactionList e{}; - entry.id = 0; - entry.name = ""; - entry.base = 0; + e.id = 0; + e.name = ""; + e.base = 0; - return entry; + return e; } - static FactionList GetFactionListEntry( + static FactionList GetFactionList( const std::vector &faction_lists, int faction_list_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - FactionList entry{}; + FactionList e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.base = atoi(row[2]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.base = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - FactionList faction_list_entry + const FactionList &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(faction_list_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(faction_list_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(faction_list_entry.base)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.base)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - faction_list_entry.id + e.id ) ); @@ -177,57 +177,57 @@ public: static FactionList InsertOne( Database& db, - FactionList faction_list_entry + FactionList e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(faction_list_entry.id)); - insert_values.push_back("'" + EscapeString(faction_list_entry.name) + "'"); - insert_values.push_back(std::to_string(faction_list_entry.base)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.base)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - faction_list_entry.id = results.LastInsertedID(); - return faction_list_entry; + e.id = results.LastInsertedID(); + return e; } - faction_list_entry = NewEntity(); + e = NewEntity(); - return faction_list_entry; + return e; } static int InsertMany( Database& db, - std::vector faction_list_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &faction_list_entry: faction_list_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(faction_list_entry.id)); - insert_values.push_back("'" + EscapeString(faction_list_entry.name) + "'"); - insert_values.push_back(std::to_string(faction_list_entry.base)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.base)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionList entry{}; + FactionList e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.base = atoi(row[2]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.base = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionList entry{}; + FactionList e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.base = atoi(row[2]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.base = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_FACTION_LIST_REPOSITORY_H diff --git a/common/repositories/base/base_faction_values_repository.h b/common/repositories/base/base_faction_values_repository.h index ef25a0147..5c2f134db 100644 --- a/common/repositories/base/base_faction_values_repository.h +++ b/common/repositories/base/base_faction_values_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_FACTION_VALUES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseFactionValuesRepository { public: struct FactionValues { - int char_id; - int faction_id; - int current_value; - int temp; + int32_t char_id; + int32_t faction_id; + int16_t current_value; + int8_t temp; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static FactionValues NewEntity() { - FactionValues entry{}; + FactionValues e{}; - entry.char_id = 0; - entry.faction_id = 0; - entry.current_value = 0; - entry.temp = 0; + e.char_id = 0; + e.faction_id = 0; + e.current_value = 0; + e.temp = 0; - return entry; + return e; } - static FactionValues GetFactionValuesEntry( + static FactionValues GetFactionValues( const std::vector &faction_valuess, int faction_values_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - FactionValues entry{}; + FactionValues e{}; - entry.char_id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.current_value = atoi(row[2]); - entry.temp = atoi(row[3]); + e.char_id = static_cast(atoi(row[0])); + e.faction_id = static_cast(atoi(row[1])); + e.current_value = static_cast(atoi(row[2])); + e.temp = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - FactionValues faction_values_entry + const FactionValues &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(faction_values_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(faction_values_entry.faction_id)); - update_values.push_back(columns[2] + " = " + std::to_string(faction_values_entry.current_value)); - update_values.push_back(columns[3] + " = " + std::to_string(faction_values_entry.temp)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.faction_id)); + v.push_back(columns[2] + " = " + std::to_string(e.current_value)); + v.push_back(columns[3] + " = " + std::to_string(e.temp)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - faction_values_entry.char_id + e.char_id ) ); @@ -183,59 +183,59 @@ public: static FactionValues InsertOne( Database& db, - FactionValues faction_values_entry + FactionValues e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(faction_values_entry.char_id)); - insert_values.push_back(std::to_string(faction_values_entry.faction_id)); - insert_values.push_back(std::to_string(faction_values_entry.current_value)); - insert_values.push_back(std::to_string(faction_values_entry.temp)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.faction_id)); + v.push_back(std::to_string(e.current_value)); + v.push_back(std::to_string(e.temp)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - faction_values_entry.char_id = results.LastInsertedID(); - return faction_values_entry; + e.char_id = results.LastInsertedID(); + return e; } - faction_values_entry = NewEntity(); + e = NewEntity(); - return faction_values_entry; + return e; } static int InsertMany( Database& db, - std::vector faction_values_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &faction_values_entry: faction_values_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(faction_values_entry.char_id)); - insert_values.push_back(std::to_string(faction_values_entry.faction_id)); - insert_values.push_back(std::to_string(faction_values_entry.current_value)); - insert_values.push_back(std::to_string(faction_values_entry.temp)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.faction_id)); + v.push_back(std::to_string(e.current_value)); + v.push_back(std::to_string(e.temp)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionValues entry{}; + FactionValues e{}; - entry.char_id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.current_value = atoi(row[2]); - entry.temp = atoi(row[3]); + e.char_id = static_cast(atoi(row[0])); + e.faction_id = static_cast(atoi(row[1])); + e.current_value = static_cast(atoi(row[2])); + e.temp = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - FactionValues entry{}; + FactionValues e{}; - entry.char_id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.current_value = atoi(row[2]); - entry.temp = atoi(row[3]); + e.char_id = static_cast(atoi(row[0])); + e.faction_id = static_cast(atoi(row[1])); + e.current_value = static_cast(atoi(row[2])); + e.temp = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_FACTION_VALUES_REPOSITORY_H diff --git a/common/repositories/base/base_fishing_repository.h b/common/repositories/base/base_fishing_repository.h index ba0f9eb11..c04886654 100644 --- a/common/repositories/base/base_fishing_repository.h +++ b/common/repositories/base/base_fishing_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_FISHING_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseFishingRepository { public: struct Fishing { - int id; - int zoneid; - int Itemid; - int skill_level; - int chance; - int npc_id; - int npc_chance; - int min_expansion; - int max_expansion; + int32_t id; + int32_t zoneid; + int32_t Itemid; + int16_t skill_level; + int16_t chance; + int32_t npc_id; + int32_t npc_chance; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -73,12 +73,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -106,24 +106,24 @@ public: static Fishing NewEntity() { - Fishing entry{}; + Fishing e{}; - entry.id = 0; - entry.zoneid = 0; - entry.Itemid = 0; - entry.skill_level = 0; - entry.chance = 0; - entry.npc_id = 0; - entry.npc_chance = 0; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.zoneid = 0; + e.Itemid = 0; + e.skill_level = 0; + e.chance = 0; + e.npc_id = 0; + e.npc_chance = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Fishing GetFishingEntry( + static Fishing GetFishing( const std::vector &fishings, int fishing_id ) @@ -152,21 +152,21 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Fishing entry{}; + Fishing e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.Itemid = atoi(row[2]); - entry.skill_level = atoi(row[3]); - entry.chance = atoi(row[4]); - entry.npc_id = atoi(row[5]); - entry.npc_chance = atoi(row[6]); - entry.min_expansion = atoi(row[7]); - entry.max_expansion = atoi(row[8]); - entry.content_flags = row[9] ? row[9] : ""; - entry.content_flags_disabled = row[10] ? row[10] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.Itemid = static_cast(atoi(row[2])); + e.skill_level = static_cast(atoi(row[3])); + e.chance = static_cast(atoi(row[4])); + e.npc_id = static_cast(atoi(row[5])); + e.npc_chance = static_cast(atoi(row[6])); + e.min_expansion = static_cast(atoi(row[7])); + e.max_expansion = static_cast(atoi(row[8])); + e.content_flags = row[9] ? row[9] : ""; + e.content_flags_disabled = row[10] ? row[10] : ""; - return entry; + return e; } return NewEntity(); @@ -191,31 +191,31 @@ public: static int UpdateOne( Database& db, - Fishing fishing_entry + const Fishing &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(fishing_entry.zoneid)); - update_values.push_back(columns[2] + " = " + std::to_string(fishing_entry.Itemid)); - update_values.push_back(columns[3] + " = " + std::to_string(fishing_entry.skill_level)); - update_values.push_back(columns[4] + " = " + std::to_string(fishing_entry.chance)); - update_values.push_back(columns[5] + " = " + std::to_string(fishing_entry.npc_id)); - update_values.push_back(columns[6] + " = " + std::to_string(fishing_entry.npc_chance)); - update_values.push_back(columns[7] + " = " + std::to_string(fishing_entry.min_expansion)); - update_values.push_back(columns[8] + " = " + std::to_string(fishing_entry.max_expansion)); - update_values.push_back(columns[9] + " = '" + EscapeString(fishing_entry.content_flags) + "'"); - update_values.push_back(columns[10] + " = '" + EscapeString(fishing_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[2] + " = " + std::to_string(e.Itemid)); + v.push_back(columns[3] + " = " + std::to_string(e.skill_level)); + v.push_back(columns[4] + " = " + std::to_string(e.chance)); + v.push_back(columns[5] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[6] + " = " + std::to_string(e.npc_chance)); + v.push_back(columns[7] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[8] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[10] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - fishing_entry.id + e.id ) ); @@ -224,73 +224,73 @@ public: static Fishing InsertOne( Database& db, - Fishing fishing_entry + Fishing e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(fishing_entry.id)); - insert_values.push_back(std::to_string(fishing_entry.zoneid)); - insert_values.push_back(std::to_string(fishing_entry.Itemid)); - insert_values.push_back(std::to_string(fishing_entry.skill_level)); - insert_values.push_back(std::to_string(fishing_entry.chance)); - insert_values.push_back(std::to_string(fishing_entry.npc_id)); - insert_values.push_back(std::to_string(fishing_entry.npc_chance)); - insert_values.push_back(std::to_string(fishing_entry.min_expansion)); - insert_values.push_back(std::to_string(fishing_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(fishing_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(fishing_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.Itemid)); + v.push_back(std::to_string(e.skill_level)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.npc_id)); + v.push_back(std::to_string(e.npc_chance)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - fishing_entry.id = results.LastInsertedID(); - return fishing_entry; + e.id = results.LastInsertedID(); + return e; } - fishing_entry = NewEntity(); + e = NewEntity(); - return fishing_entry; + return e; } static int InsertMany( Database& db, - std::vector fishing_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &fishing_entry: fishing_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(fishing_entry.id)); - insert_values.push_back(std::to_string(fishing_entry.zoneid)); - insert_values.push_back(std::to_string(fishing_entry.Itemid)); - insert_values.push_back(std::to_string(fishing_entry.skill_level)); - insert_values.push_back(std::to_string(fishing_entry.chance)); - insert_values.push_back(std::to_string(fishing_entry.npc_id)); - insert_values.push_back(std::to_string(fishing_entry.npc_chance)); - insert_values.push_back(std::to_string(fishing_entry.min_expansion)); - insert_values.push_back(std::to_string(fishing_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(fishing_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(fishing_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.Itemid)); + v.push_back(std::to_string(e.skill_level)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.npc_id)); + v.push_back(std::to_string(e.npc_chance)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -311,27 +311,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Fishing entry{}; + Fishing e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.Itemid = atoi(row[2]); - entry.skill_level = atoi(row[3]); - entry.chance = atoi(row[4]); - entry.npc_id = atoi(row[5]); - entry.npc_chance = atoi(row[6]); - entry.min_expansion = atoi(row[7]); - entry.max_expansion = atoi(row[8]); - entry.content_flags = row[9] ? row[9] : ""; - entry.content_flags_disabled = row[10] ? row[10] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.Itemid = static_cast(atoi(row[2])); + e.skill_level = static_cast(atoi(row[3])); + e.chance = static_cast(atoi(row[4])); + e.npc_id = static_cast(atoi(row[5])); + e.npc_chance = static_cast(atoi(row[6])); + e.min_expansion = static_cast(atoi(row[7])); + e.max_expansion = static_cast(atoi(row[8])); + e.content_flags = row[9] ? row[9] : ""; + e.content_flags_disabled = row[10] ? row[10] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -346,27 +346,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Fishing entry{}; + Fishing e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.Itemid = atoi(row[2]); - entry.skill_level = atoi(row[3]); - entry.chance = atoi(row[4]); - entry.npc_id = atoi(row[5]); - entry.npc_chance = atoi(row[6]); - entry.min_expansion = atoi(row[7]); - entry.max_expansion = atoi(row[8]); - entry.content_flags = row[9] ? row[9] : ""; - entry.content_flags_disabled = row[10] ? row[10] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.Itemid = static_cast(atoi(row[2])); + e.skill_level = static_cast(atoi(row[3])); + e.chance = static_cast(atoi(row[4])); + e.npc_id = static_cast(atoi(row[5])); + e.npc_chance = static_cast(atoi(row[6])); + e.min_expansion = static_cast(atoi(row[7])); + e.max_expansion = static_cast(atoi(row[8])); + e.content_flags = row[9] ? row[9] : ""; + e.content_flags_disabled = row[10] ? row[10] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -391,6 +391,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_FISHING_REPOSITORY_H diff --git a/common/repositories/base/base_forage_repository.h b/common/repositories/base/base_forage_repository.h index 166ee7cd4..609af148e 100644 --- a/common/repositories/base/base_forage_repository.h +++ b/common/repositories/base/base_forage_repository.h @@ -13,19 +13,19 @@ #define EQEMU_BASE_FORAGE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseForageRepository { public: struct Forage { - int id; - int zoneid; - int Itemid; - int level; - int chance; - int min_expansion; - int max_expansion; + int32_t id; + int32_t zoneid; + int32_t Itemid; + int16_t level; + int16_t chance; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static Forage NewEntity() { - Forage entry{}; + Forage e{}; - entry.id = 0; - entry.zoneid = 0; - entry.Itemid = 0; - entry.level = 0; - entry.chance = 0; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.zoneid = 0; + e.Itemid = 0; + e.level = 0; + e.chance = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Forage GetForageEntry( + static Forage GetForage( const std::vector &forages, int forage_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Forage entry{}; + Forage e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.Itemid = atoi(row[2]); - entry.level = atoi(row[3]); - entry.chance = atoi(row[4]); - entry.min_expansion = atoi(row[5]); - entry.max_expansion = atoi(row[6]); - entry.content_flags = row[7] ? row[7] : ""; - entry.content_flags_disabled = row[8] ? row[8] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.Itemid = static_cast(atoi(row[2])); + e.level = static_cast(atoi(row[3])); + e.chance = static_cast(atoi(row[4])); + e.min_expansion = static_cast(atoi(row[5])); + e.max_expansion = static_cast(atoi(row[6])); + e.content_flags = row[7] ? row[7] : ""; + e.content_flags_disabled = row[8] ? row[8] : ""; - return entry; + return e; } return NewEntity(); @@ -181,29 +181,29 @@ public: static int UpdateOne( Database& db, - Forage forage_entry + const Forage &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(forage_entry.zoneid)); - update_values.push_back(columns[2] + " = " + std::to_string(forage_entry.Itemid)); - update_values.push_back(columns[3] + " = " + std::to_string(forage_entry.level)); - update_values.push_back(columns[4] + " = " + std::to_string(forage_entry.chance)); - update_values.push_back(columns[5] + " = " + std::to_string(forage_entry.min_expansion)); - update_values.push_back(columns[6] + " = " + std::to_string(forage_entry.max_expansion)); - update_values.push_back(columns[7] + " = '" + EscapeString(forage_entry.content_flags) + "'"); - update_values.push_back(columns[8] + " = '" + EscapeString(forage_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[2] + " = " + std::to_string(e.Itemid)); + v.push_back(columns[3] + " = " + std::to_string(e.level)); + v.push_back(columns[4] + " = " + std::to_string(e.chance)); + v.push_back(columns[5] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[6] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[7] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - forage_entry.id + e.id ) ); @@ -212,69 +212,69 @@ public: static Forage InsertOne( Database& db, - Forage forage_entry + Forage e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(forage_entry.id)); - insert_values.push_back(std::to_string(forage_entry.zoneid)); - insert_values.push_back(std::to_string(forage_entry.Itemid)); - insert_values.push_back(std::to_string(forage_entry.level)); - insert_values.push_back(std::to_string(forage_entry.chance)); - insert_values.push_back(std::to_string(forage_entry.min_expansion)); - insert_values.push_back(std::to_string(forage_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(forage_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(forage_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.Itemid)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - forage_entry.id = results.LastInsertedID(); - return forage_entry; + e.id = results.LastInsertedID(); + return e; } - forage_entry = NewEntity(); + e = NewEntity(); - return forage_entry; + return e; } static int InsertMany( Database& db, - std::vector forage_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &forage_entry: forage_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(forage_entry.id)); - insert_values.push_back(std::to_string(forage_entry.zoneid)); - insert_values.push_back(std::to_string(forage_entry.Itemid)); - insert_values.push_back(std::to_string(forage_entry.level)); - insert_values.push_back(std::to_string(forage_entry.chance)); - insert_values.push_back(std::to_string(forage_entry.min_expansion)); - insert_values.push_back(std::to_string(forage_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(forage_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(forage_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.Itemid)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -295,25 +295,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Forage entry{}; + Forage e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.Itemid = atoi(row[2]); - entry.level = atoi(row[3]); - entry.chance = atoi(row[4]); - entry.min_expansion = atoi(row[5]); - entry.max_expansion = atoi(row[6]); - entry.content_flags = row[7] ? row[7] : ""; - entry.content_flags_disabled = row[8] ? row[8] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.Itemid = static_cast(atoi(row[2])); + e.level = static_cast(atoi(row[3])); + e.chance = static_cast(atoi(row[4])); + e.min_expansion = static_cast(atoi(row[5])); + e.max_expansion = static_cast(atoi(row[6])); + e.content_flags = row[7] ? row[7] : ""; + e.content_flags_disabled = row[8] ? row[8] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -328,25 +328,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Forage entry{}; + Forage e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.Itemid = atoi(row[2]); - entry.level = atoi(row[3]); - entry.chance = atoi(row[4]); - entry.min_expansion = atoi(row[5]); - entry.max_expansion = atoi(row[6]); - entry.content_flags = row[7] ? row[7] : ""; - entry.content_flags_disabled = row[8] ? row[8] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.Itemid = static_cast(atoi(row[2])); + e.level = static_cast(atoi(row[3])); + e.chance = static_cast(atoi(row[4])); + e.min_expansion = static_cast(atoi(row[5])); + e.max_expansion = static_cast(atoi(row[6])); + e.content_flags = row[7] ? row[7] : ""; + e.content_flags_disabled = row[8] ? row[8] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -371,6 +371,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_FORAGE_REPOSITORY_H diff --git a/common/repositories/base/base_friends_repository.h b/common/repositories/base/base_friends_repository.h index 27115b76d..1f9acf7be 100644 --- a/common/repositories/base/base_friends_repository.h +++ b/common/repositories/base/base_friends_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_FRIENDS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseFriendsRepository { public: struct Friends { - int charid; - int type; + uint32_t charid; + uint8_t type; std::string name; }; @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static Friends NewEntity() { - Friends entry{}; + Friends e{}; - entry.charid = 0; - entry.type = 1; - entry.name = ""; + e.charid = 0; + e.type = 1; + e.name = ""; - return entry; + return e; } - static Friends GetFriendsEntry( + static Friends GetFriends( const std::vector &friendss, int friends_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Friends entry{}; + Friends e{}; - entry.charid = atoi(row[0]); - entry.type = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.name = row[2] ? row[2] : ""; - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - Friends friends_entry + const Friends &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(friends_entry.charid)); - update_values.push_back(columns[1] + " = " + std::to_string(friends_entry.type)); - update_values.push_back(columns[2] + " = '" + EscapeString(friends_entry.name) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.charid)); + v.push_back(columns[1] + " = " + std::to_string(e.type)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - friends_entry.charid + e.charid ) ); @@ -177,57 +177,57 @@ public: static Friends InsertOne( Database& db, - Friends friends_entry + Friends e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(friends_entry.charid)); - insert_values.push_back(std::to_string(friends_entry.type)); - insert_values.push_back("'" + EscapeString(friends_entry.name) + "'"); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - friends_entry.charid = results.LastInsertedID(); - return friends_entry; + e.charid = results.LastInsertedID(); + return e; } - friends_entry = NewEntity(); + e = NewEntity(); - return friends_entry; + return e; } static int InsertMany( Database& db, - std::vector friends_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &friends_entry: friends_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(friends_entry.charid)); - insert_values.push_back(std::to_string(friends_entry.type)); - insert_values.push_back("'" + EscapeString(friends_entry.name) + "'"); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.name) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Friends entry{}; + Friends e{}; - entry.charid = atoi(row[0]); - entry.type = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.name = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Friends entry{}; + Friends e{}; - entry.charid = atoi(row[0]); - entry.type = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.name = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_FRIENDS_REPOSITORY_H diff --git a/common/repositories/base/base_global_loot_repository.h b/common/repositories/base/base_global_loot_repository.h index dbee15a9e..c8755d267 100644 --- a/common/repositories/base/base_global_loot_repository.h +++ b/common/repositories/base/base_global_loot_repository.h @@ -13,27 +13,27 @@ #define EQEMU_BASE_GLOBAL_LOOT_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGlobalLootRepository { public: struct GlobalLoot { - int id; + int32_t id; std::string description; - int loottable_id; - int enabled; - int min_level; - int max_level; - int rare; - int raid; + int32_t loottable_id; + int8_t enabled; + int32_t min_level; + int32_t max_level; + int8_t rare; + int8_t raid; std::string race; std::string class_; std::string bodytype; std::string zone; - int hot_zone; - int min_expansion; - int max_expansion; + int8_t hot_zone; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -91,12 +91,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -124,30 +124,30 @@ public: static GlobalLoot NewEntity() { - GlobalLoot entry{}; + GlobalLoot e{}; - entry.id = 0; - entry.description = ""; - entry.loottable_id = 0; - entry.enabled = 1; - entry.min_level = 0; - entry.max_level = 0; - entry.rare = 0; - entry.raid = 0; - entry.race = ""; - entry.class_ = ""; - entry.bodytype = ""; - entry.zone = ""; - entry.hot_zone = 0; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.description = ""; + e.loottable_id = 0; + e.enabled = 1; + e.min_level = 0; + e.max_level = 0; + e.rare = 0; + e.raid = 0; + e.race = ""; + e.class_ = ""; + e.bodytype = ""; + e.zone = ""; + e.hot_zone = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static GlobalLoot GetGlobalLootEntry( + static GlobalLoot GetGlobalLoot( const std::vector &global_loots, int global_loot_id ) @@ -176,27 +176,27 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GlobalLoot entry{}; + GlobalLoot e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; - entry.loottable_id = atoi(row[2]); - entry.enabled = atoi(row[3]); - entry.min_level = atoi(row[4]); - entry.max_level = atoi(row[5]); - entry.rare = atoi(row[6]); - entry.raid = atoi(row[7]); - entry.race = row[8] ? row[8] : ""; - entry.class_ = row[9] ? row[9] : ""; - entry.bodytype = row[10] ? row[10] : ""; - entry.zone = row[11] ? row[11] : ""; - entry.hot_zone = atoi(row[12]); - entry.min_expansion = atoi(row[13]); - entry.max_expansion = atoi(row[14]); - entry.content_flags = row[15] ? row[15] : ""; - entry.content_flags_disabled = row[16] ? row[16] : ""; + e.id = static_cast(atoi(row[0])); + e.description = row[1] ? row[1] : ""; + e.loottable_id = static_cast(atoi(row[2])); + e.enabled = static_cast(atoi(row[3])); + e.min_level = static_cast(atoi(row[4])); + e.max_level = static_cast(atoi(row[5])); + e.rare = static_cast(atoi(row[6])); + e.raid = static_cast(atoi(row[7])); + e.race = row[8] ? row[8] : ""; + e.class_ = row[9] ? row[9] : ""; + e.bodytype = row[10] ? row[10] : ""; + e.zone = row[11] ? row[11] : ""; + e.hot_zone = static_cast(atoi(row[12])); + e.min_expansion = static_cast(atoi(row[13])); + e.max_expansion = static_cast(atoi(row[14])); + e.content_flags = row[15] ? row[15] : ""; + e.content_flags_disabled = row[16] ? row[16] : ""; - return entry; + return e; } return NewEntity(); @@ -221,37 +221,37 @@ public: static int UpdateOne( Database& db, - GlobalLoot global_loot_entry + const GlobalLoot &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(global_loot_entry.description) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(global_loot_entry.loottable_id)); - update_values.push_back(columns[3] + " = " + std::to_string(global_loot_entry.enabled)); - update_values.push_back(columns[4] + " = " + std::to_string(global_loot_entry.min_level)); - update_values.push_back(columns[5] + " = " + std::to_string(global_loot_entry.max_level)); - update_values.push_back(columns[6] + " = " + std::to_string(global_loot_entry.rare)); - update_values.push_back(columns[7] + " = " + std::to_string(global_loot_entry.raid)); - update_values.push_back(columns[8] + " = '" + EscapeString(global_loot_entry.race) + "'"); - update_values.push_back(columns[9] + " = '" + EscapeString(global_loot_entry.class_) + "'"); - update_values.push_back(columns[10] + " = '" + EscapeString(global_loot_entry.bodytype) + "'"); - update_values.push_back(columns[11] + " = '" + EscapeString(global_loot_entry.zone) + "'"); - update_values.push_back(columns[12] + " = " + std::to_string(global_loot_entry.hot_zone)); - update_values.push_back(columns[13] + " = " + std::to_string(global_loot_entry.min_expansion)); - update_values.push_back(columns[14] + " = " + std::to_string(global_loot_entry.max_expansion)); - update_values.push_back(columns[15] + " = '" + EscapeString(global_loot_entry.content_flags) + "'"); - update_values.push_back(columns[16] + " = '" + EscapeString(global_loot_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.description) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.loottable_id)); + v.push_back(columns[3] + " = " + std::to_string(e.enabled)); + v.push_back(columns[4] + " = " + std::to_string(e.min_level)); + v.push_back(columns[5] + " = " + std::to_string(e.max_level)); + v.push_back(columns[6] + " = " + std::to_string(e.rare)); + v.push_back(columns[7] + " = " + std::to_string(e.raid)); + v.push_back(columns[8] + " = '" + Strings::Escape(e.race) + "'"); + v.push_back(columns[9] + " = '" + Strings::Escape(e.class_) + "'"); + v.push_back(columns[10] + " = '" + Strings::Escape(e.bodytype) + "'"); + v.push_back(columns[11] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[12] + " = " + std::to_string(e.hot_zone)); + v.push_back(columns[13] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[14] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[16] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - global_loot_entry.id + e.id ) ); @@ -260,85 +260,85 @@ public: static GlobalLoot InsertOne( Database& db, - GlobalLoot global_loot_entry + GlobalLoot e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(global_loot_entry.id)); - insert_values.push_back("'" + EscapeString(global_loot_entry.description) + "'"); - insert_values.push_back(std::to_string(global_loot_entry.loottable_id)); - insert_values.push_back(std::to_string(global_loot_entry.enabled)); - insert_values.push_back(std::to_string(global_loot_entry.min_level)); - insert_values.push_back(std::to_string(global_loot_entry.max_level)); - insert_values.push_back(std::to_string(global_loot_entry.rare)); - insert_values.push_back(std::to_string(global_loot_entry.raid)); - insert_values.push_back("'" + EscapeString(global_loot_entry.race) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.class_) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.bodytype) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.zone) + "'"); - insert_values.push_back(std::to_string(global_loot_entry.hot_zone)); - insert_values.push_back(std::to_string(global_loot_entry.min_expansion)); - insert_values.push_back(std::to_string(global_loot_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(global_loot_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back(std::to_string(e.loottable_id)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.rare)); + v.push_back(std::to_string(e.raid)); + v.push_back("'" + Strings::Escape(e.race) + "'"); + v.push_back("'" + Strings::Escape(e.class_) + "'"); + v.push_back("'" + Strings::Escape(e.bodytype) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.hot_zone)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - global_loot_entry.id = results.LastInsertedID(); - return global_loot_entry; + e.id = results.LastInsertedID(); + return e; } - global_loot_entry = NewEntity(); + e = NewEntity(); - return global_loot_entry; + return e; } static int InsertMany( Database& db, - std::vector global_loot_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &global_loot_entry: global_loot_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(global_loot_entry.id)); - insert_values.push_back("'" + EscapeString(global_loot_entry.description) + "'"); - insert_values.push_back(std::to_string(global_loot_entry.loottable_id)); - insert_values.push_back(std::to_string(global_loot_entry.enabled)); - insert_values.push_back(std::to_string(global_loot_entry.min_level)); - insert_values.push_back(std::to_string(global_loot_entry.max_level)); - insert_values.push_back(std::to_string(global_loot_entry.rare)); - insert_values.push_back(std::to_string(global_loot_entry.raid)); - insert_values.push_back("'" + EscapeString(global_loot_entry.race) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.class_) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.bodytype) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.zone) + "'"); - insert_values.push_back(std::to_string(global_loot_entry.hot_zone)); - insert_values.push_back(std::to_string(global_loot_entry.min_expansion)); - insert_values.push_back(std::to_string(global_loot_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(global_loot_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(global_loot_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back(std::to_string(e.loottable_id)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.rare)); + v.push_back(std::to_string(e.raid)); + v.push_back("'" + Strings::Escape(e.race) + "'"); + v.push_back("'" + Strings::Escape(e.class_) + "'"); + v.push_back("'" + Strings::Escape(e.bodytype) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.hot_zone)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -359,33 +359,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GlobalLoot entry{}; + GlobalLoot e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; - entry.loottable_id = atoi(row[2]); - entry.enabled = atoi(row[3]); - entry.min_level = atoi(row[4]); - entry.max_level = atoi(row[5]); - entry.rare = atoi(row[6]); - entry.raid = atoi(row[7]); - entry.race = row[8] ? row[8] : ""; - entry.class_ = row[9] ? row[9] : ""; - entry.bodytype = row[10] ? row[10] : ""; - entry.zone = row[11] ? row[11] : ""; - entry.hot_zone = atoi(row[12]); - entry.min_expansion = atoi(row[13]); - entry.max_expansion = atoi(row[14]); - entry.content_flags = row[15] ? row[15] : ""; - entry.content_flags_disabled = row[16] ? row[16] : ""; + e.id = static_cast(atoi(row[0])); + e.description = row[1] ? row[1] : ""; + e.loottable_id = static_cast(atoi(row[2])); + e.enabled = static_cast(atoi(row[3])); + e.min_level = static_cast(atoi(row[4])); + e.max_level = static_cast(atoi(row[5])); + e.rare = static_cast(atoi(row[6])); + e.raid = static_cast(atoi(row[7])); + e.race = row[8] ? row[8] : ""; + e.class_ = row[9] ? row[9] : ""; + e.bodytype = row[10] ? row[10] : ""; + e.zone = row[11] ? row[11] : ""; + e.hot_zone = static_cast(atoi(row[12])); + e.min_expansion = static_cast(atoi(row[13])); + e.max_expansion = static_cast(atoi(row[14])); + e.content_flags = row[15] ? row[15] : ""; + e.content_flags_disabled = row[16] ? row[16] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -400,33 +400,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GlobalLoot entry{}; + GlobalLoot e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; - entry.loottable_id = atoi(row[2]); - entry.enabled = atoi(row[3]); - entry.min_level = atoi(row[4]); - entry.max_level = atoi(row[5]); - entry.rare = atoi(row[6]); - entry.raid = atoi(row[7]); - entry.race = row[8] ? row[8] : ""; - entry.class_ = row[9] ? row[9] : ""; - entry.bodytype = row[10] ? row[10] : ""; - entry.zone = row[11] ? row[11] : ""; - entry.hot_zone = atoi(row[12]); - entry.min_expansion = atoi(row[13]); - entry.max_expansion = atoi(row[14]); - entry.content_flags = row[15] ? row[15] : ""; - entry.content_flags_disabled = row[16] ? row[16] : ""; + e.id = static_cast(atoi(row[0])); + e.description = row[1] ? row[1] : ""; + e.loottable_id = static_cast(atoi(row[2])); + e.enabled = static_cast(atoi(row[3])); + e.min_level = static_cast(atoi(row[4])); + e.max_level = static_cast(atoi(row[5])); + e.rare = static_cast(atoi(row[6])); + e.raid = static_cast(atoi(row[7])); + e.race = row[8] ? row[8] : ""; + e.class_ = row[9] ? row[9] : ""; + e.bodytype = row[10] ? row[10] : ""; + e.zone = row[11] ? row[11] : ""; + e.hot_zone = static_cast(atoi(row[12])); + e.min_expansion = static_cast(atoi(row[13])); + e.max_expansion = static_cast(atoi(row[14])); + e.content_flags = row[15] ? row[15] : ""; + e.content_flags_disabled = row[16] ? row[16] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -451,6 +451,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GLOBAL_LOOT_REPOSITORY_H diff --git a/common/repositories/base/base_gm_ips_repository.h b/common/repositories/base/base_gm_ips_repository.h index 84f18734d..ae1f52ef9 100644 --- a/common/repositories/base/base_gm_ips_repository.h +++ b/common/repositories/base/base_gm_ips_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_GM_IPS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGmIpsRepository { public: struct GmIps { std::string name; - int account_id; + int32_t account_id; std::string ip_address; }; @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static GmIps NewEntity() { - GmIps entry{}; + GmIps e{}; - entry.name = ""; - entry.account_id = 0; - entry.ip_address = ""; + e.name = ""; + e.account_id = 0; + e.ip_address = ""; - return entry; + return e; } - static GmIps GetGmIpsEntry( + static GmIps GetGmIps( const std::vector &gm_ipss, int gm_ips_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GmIps entry{}; + GmIps e{}; - entry.name = row[0] ? row[0] : ""; - entry.account_id = atoi(row[1]); - entry.ip_address = row[2] ? row[2] : ""; + e.name = row[0] ? row[0] : ""; + e.account_id = static_cast(atoi(row[1])); + e.ip_address = row[2] ? row[2] : ""; - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - GmIps gm_ips_entry + const GmIps &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = '" + EscapeString(gm_ips_entry.name) + "'"); - update_values.push_back(columns[1] + " = " + std::to_string(gm_ips_entry.account_id)); - update_values.push_back(columns[2] + " = '" + EscapeString(gm_ips_entry.ip_address) + "'"); + v.push_back(columns[0] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.account_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.ip_address) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - gm_ips_entry.account_id + e.account_id ) ); @@ -177,57 +177,57 @@ public: static GmIps InsertOne( Database& db, - GmIps gm_ips_entry + GmIps e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back("'" + EscapeString(gm_ips_entry.name) + "'"); - insert_values.push_back(std::to_string(gm_ips_entry.account_id)); - insert_values.push_back("'" + EscapeString(gm_ips_entry.ip_address) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.account_id)); + v.push_back("'" + Strings::Escape(e.ip_address) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - gm_ips_entry.account_id = results.LastInsertedID(); - return gm_ips_entry; + e.account_id = results.LastInsertedID(); + return e; } - gm_ips_entry = NewEntity(); + e = NewEntity(); - return gm_ips_entry; + return e; } static int InsertMany( Database& db, - std::vector gm_ips_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &gm_ips_entry: gm_ips_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back("'" + EscapeString(gm_ips_entry.name) + "'"); - insert_values.push_back(std::to_string(gm_ips_entry.account_id)); - insert_values.push_back("'" + EscapeString(gm_ips_entry.ip_address) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.account_id)); + v.push_back("'" + Strings::Escape(e.ip_address) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GmIps entry{}; + GmIps e{}; - entry.name = row[0] ? row[0] : ""; - entry.account_id = atoi(row[1]); - entry.ip_address = row[2] ? row[2] : ""; + e.name = row[0] ? row[0] : ""; + e.account_id = static_cast(atoi(row[1])); + e.ip_address = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GmIps entry{}; + GmIps e{}; - entry.name = row[0] ? row[0] : ""; - entry.account_id = atoi(row[1]); - entry.ip_address = row[2] ? row[2] : ""; + e.name = row[0] ? row[0] : ""; + e.account_id = static_cast(atoi(row[1])); + e.ip_address = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GM_IPS_REPOSITORY_H diff --git a/common/repositories/base/base_goallists_repository.h b/common/repositories/base/base_goallists_repository.h deleted file mode 100644 index 79e0919ca..000000000 --- a/common/repositories/base/base_goallists_repository.h +++ /dev/null @@ -1,307 +0,0 @@ -/** - * DO NOT MODIFY THIS FILE - * - * This repository was automatically generated and is NOT to be modified directly. - * Any repository modifications are meant to be made to the repository extending the base. - * Any modifications to base repositories are to be made by the generator only - * - * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories - */ - -#ifndef EQEMU_BASE_GOALLISTS_REPOSITORY_H -#define EQEMU_BASE_GOALLISTS_REPOSITORY_H - -#include "../../database.h" -#include "../../string_util.h" -#include - -class BaseGoallistsRepository { -public: - struct Goallists { - int listid; - int entry; - }; - - static std::string PrimaryKey() - { - return std::string("listid"); - } - - static std::vector Columns() - { - return { - "listid", - "entry", - }; - } - - static std::vector SelectColumns() - { - return { - "listid", - "entry", - }; - } - - static std::string ColumnsRaw() - { - return std::string(implode(", ", Columns())); - } - - static std::string SelectColumnsRaw() - { - return std::string(implode(", ", SelectColumns())); - } - - static std::string TableName() - { - return std::string("goallists"); - } - - static std::string BaseSelect() - { - return fmt::format( - "SELECT {} FROM {}", - SelectColumnsRaw(), - TableName() - ); - } - - static std::string BaseInsert() - { - return fmt::format( - "INSERT INTO {} ({}) ", - TableName(), - ColumnsRaw() - ); - } - - static Goallists NewEntity() - { - Goallists entry{}; - - entry.listid = 0; - entry.entry = 0; - - return entry; - } - - static Goallists GetGoallistsEntry( - const std::vector &goallistss, - int goallists_id - ) - { - for (auto &goallists : goallistss) { - if (goallists.listid == goallists_id) { - return goallists; - } - } - - return NewEntity(); - } - - static Goallists FindOne( - Database& db, - int goallists_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE id = {} LIMIT 1", - BaseSelect(), - goallists_id - ) - ); - - auto row = results.begin(); - if (results.RowCount() == 1) { - Goallists entry{}; - - entry.listid = atoi(row[0]); - entry.entry = atoi(row[1]); - - return entry; - } - - return NewEntity(); - } - - static int DeleteOne( - Database& db, - int goallists_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {} = {}", - TableName(), - PrimaryKey(), - goallists_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int UpdateOne( - Database& db, - Goallists goallists_entry - ) - { - std::vector update_values; - - auto columns = Columns(); - - update_values.push_back(columns[0] + " = " + std::to_string(goallists_entry.listid)); - update_values.push_back(columns[1] + " = " + std::to_string(goallists_entry.entry)); - - auto results = db.QueryDatabase( - fmt::format( - "UPDATE {} SET {} WHERE {} = {}", - TableName(), - implode(", ", update_values), - PrimaryKey(), - goallists_entry.listid - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static Goallists InsertOne( - Database& db, - Goallists goallists_entry - ) - { - std::vector insert_values; - - insert_values.push_back(std::to_string(goallists_entry.listid)); - insert_values.push_back(std::to_string(goallists_entry.entry)); - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES ({})", - BaseInsert(), - implode(",", insert_values) - ) - ); - - if (results.Success()) { - goallists_entry.listid = results.LastInsertedID(); - return goallists_entry; - } - - goallists_entry = NewEntity(); - - return goallists_entry; - } - - static int InsertMany( - Database& db, - std::vector goallists_entries - ) - { - std::vector insert_chunks; - - for (auto &goallists_entry: goallists_entries) { - std::vector insert_values; - - insert_values.push_back(std::to_string(goallists_entry.listid)); - insert_values.push_back(std::to_string(goallists_entry.entry)); - - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); - } - - std::vector insert_values; - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES {}", - BaseInsert(), - implode(",", insert_chunks) - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static std::vector All(Database& db) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{}", - BaseSelect() - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Goallists entry{}; - - entry.listid = atoi(row[0]); - entry.entry = atoi(row[1]); - - all_entries.push_back(entry); - } - - return all_entries; - } - - static std::vector GetWhere(Database& db, std::string where_filter) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE {}", - BaseSelect(), - where_filter - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Goallists entry{}; - - entry.listid = atoi(row[0]); - entry.entry = atoi(row[1]); - - all_entries.push_back(entry); - } - - return all_entries; - } - - static int DeleteWhere(Database& db, std::string where_filter) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {}", - TableName(), - where_filter - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int Truncate(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "TRUNCATE TABLE {}", - TableName() - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - -}; - -#endif //EQEMU_BASE_GOALLISTS_REPOSITORY_H diff --git a/common/repositories/base/base_graveyard_repository.h b/common/repositories/base/base_graveyard_repository.h index 2df4c292d..1cc7d5c1e 100644 --- a/common/repositories/base/base_graveyard_repository.h +++ b/common/repositories/base/base_graveyard_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_GRAVEYARD_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGraveyardRepository { public: struct Graveyard { - int id; - int zone_id; - float x; - float y; - float z; - float heading; + int32_t id; + int32_t zone_id; + float x; + float y; + float z; + float heading; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static Graveyard NewEntity() { - Graveyard entry{}; + Graveyard e{}; - entry.id = 0; - entry.zone_id = 0; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.heading = 0; + e.id = 0; + e.zone_id = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; - return entry; + return e; } - static Graveyard GetGraveyardEntry( + static Graveyard GetGraveyard( const std::vector &graveyards, int graveyard_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Graveyard entry{}; + Graveyard e{}; - entry.id = atoi(row[0]); - entry.zone_id = atoi(row[1]); - entry.x = static_cast(atof(row[2])); - entry.y = static_cast(atof(row[3])); - entry.z = static_cast(atof(row[4])); - entry.heading = static_cast(atof(row[5])); + e.id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + e.x = strtof(row[2], nullptr); + e.y = strtof(row[3], nullptr); + e.z = strtof(row[4], nullptr); + e.heading = strtof(row[5], nullptr); - return entry; + return e; } return NewEntity(); @@ -166,26 +166,26 @@ public: static int UpdateOne( Database& db, - Graveyard graveyard_entry + const Graveyard &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(graveyard_entry.zone_id)); - update_values.push_back(columns[2] + " = " + std::to_string(graveyard_entry.x)); - update_values.push_back(columns[3] + " = " + std::to_string(graveyard_entry.y)); - update_values.push_back(columns[4] + " = " + std::to_string(graveyard_entry.z)); - update_values.push_back(columns[5] + " = " + std::to_string(graveyard_entry.heading)); + v.push_back(columns[1] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[2] + " = " + std::to_string(e.x)); + v.push_back(columns[3] + " = " + std::to_string(e.y)); + v.push_back(columns[4] + " = " + std::to_string(e.z)); + v.push_back(columns[5] + " = " + std::to_string(e.heading)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - graveyard_entry.id + e.id ) ); @@ -194,63 +194,63 @@ public: static Graveyard InsertOne( Database& db, - Graveyard graveyard_entry + Graveyard e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(graveyard_entry.id)); - insert_values.push_back(std::to_string(graveyard_entry.zone_id)); - insert_values.push_back(std::to_string(graveyard_entry.x)); - insert_values.push_back(std::to_string(graveyard_entry.y)); - insert_values.push_back(std::to_string(graveyard_entry.z)); - insert_values.push_back(std::to_string(graveyard_entry.heading)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - graveyard_entry.id = results.LastInsertedID(); - return graveyard_entry; + e.id = results.LastInsertedID(); + return e; } - graveyard_entry = NewEntity(); + e = NewEntity(); - return graveyard_entry; + return e; } static int InsertMany( Database& db, - std::vector graveyard_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &graveyard_entry: graveyard_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(graveyard_entry.id)); - insert_values.push_back(std::to_string(graveyard_entry.zone_id)); - insert_values.push_back(std::to_string(graveyard_entry.x)); - insert_values.push_back(std::to_string(graveyard_entry.y)); - insert_values.push_back(std::to_string(graveyard_entry.z)); - insert_values.push_back(std::to_string(graveyard_entry.heading)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -271,22 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Graveyard entry{}; + Graveyard e{}; - entry.id = atoi(row[0]); - entry.zone_id = atoi(row[1]); - entry.x = static_cast(atof(row[2])); - entry.y = static_cast(atof(row[3])); - entry.z = static_cast(atof(row[4])); - entry.heading = static_cast(atof(row[5])); + e.id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + e.x = strtof(row[2], nullptr); + e.y = strtof(row[3], nullptr); + e.z = strtof(row[4], nullptr); + e.heading = strtof(row[5], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -301,22 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Graveyard entry{}; + Graveyard e{}; - entry.id = atoi(row[0]); - entry.zone_id = atoi(row[1]); - entry.x = static_cast(atof(row[2])); - entry.y = static_cast(atof(row[3])); - entry.z = static_cast(atof(row[4])); - entry.heading = static_cast(atof(row[5])); + e.id = static_cast(atoi(row[0])); + e.zone_id = static_cast(atoi(row[1])); + e.x = strtof(row[2], nullptr); + e.y = strtof(row[3], nullptr); + e.z = strtof(row[4], nullptr); + e.heading = strtof(row[5], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -341,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GRAVEYARD_REPOSITORY_H diff --git a/common/repositories/base/base_grid_entries_repository.h b/common/repositories/base/base_grid_entries_repository.h index 6b0f3fcd2..b4fafb192 100644 --- a/common/repositories/base/base_grid_entries_repository.h +++ b/common/repositories/base/base_grid_entries_repository.h @@ -1,54 +1,38 @@ /** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) + * DO NOT MODIFY THIS FILE * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - */ - -/** - * This repository was automatically generated on Apr 5, 2020 and is NOT - * to be modified directly. Any repository modifications are meant to be made to - * the repository extending the base. Any modifications to base repositories are to - * be made by the generator only + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories */ #ifndef EQEMU_BASE_GRID_ENTRIES_REPOSITORY_H #define EQEMU_BASE_GRID_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" +#include class BaseGridEntriesRepository { public: struct GridEntries { - int gridid; - int zoneid; - int number; - float x; - float y; - float z; - float heading; - int pause; - int8 centerpoint; + int32_t gridid; + int32_t zoneid; + int32_t number; + float x; + float y; + float z; + float heading; + int32_t pause; + int8_t centerpoint; }; static std::string PrimaryKey() { - return std::string("number"); + return std::string("gridid"); } static std::vector Columns() @@ -66,24 +50,29 @@ public: }; } - static std::string ColumnsRaw() + static std::vector SelectColumns() { - return std::string(implode(", ", Columns())); + return { + "gridid", + "zoneid", + "number", + "x", + "y", + "z", + "heading", + "pause", + "centerpoint", + }; } - static std::string InsertColumnsRaw() + static std::string ColumnsRaw() { - std::vector insert_columns; + return std::string(Strings::Implode(", ", Columns())); + } - for (auto &column : Columns()) { - if (column == PrimaryKey()) { - continue; - } - - insert_columns.push_back(column); - } - - return std::string(implode(", ", insert_columns)); + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -95,7 +84,7 @@ public: { return fmt::format( "SELECT {} FROM {}", - ColumnsRaw(), + SelectColumnsRaw(), TableName() ); } @@ -105,34 +94,34 @@ public: return fmt::format( "INSERT INTO {} ({}) ", TableName(), - InsertColumnsRaw() + ColumnsRaw() ); } static GridEntries NewEntity() { - GridEntries entry{}; + GridEntries e{}; - entry.gridid = 0; - entry.zoneid = 0; - entry.number = 0; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.heading = 0; - entry.pause = 0; - entry.centerpoint = 0; + e.gridid = 0; + e.zoneid = 0; + e.number = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; + e.pause = 0; + e.centerpoint = 0; - return entry; + return e; } - static GridEntries GetGridEntriesEntry( + static GridEntries GetGridEntries( const std::vector &grid_entriess, int grid_entries_id ) { for (auto &grid_entries : grid_entriess) { - if (grid_entries.number == grid_entries_id) { + if (grid_entries.gridid == grid_entries_id) { return grid_entries; } } @@ -141,10 +130,11 @@ public: } static GridEntries FindOne( + Database& db, int grid_entries_id ) { - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} WHERE id = {} LIMIT 1", BaseSelect(), @@ -154,29 +144,30 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GridEntries entry{}; + GridEntries e{}; - entry.gridid = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.number = atoi(row[2]); - entry.x = atof(row[3]); - entry.y = atof(row[4]); - entry.z = atof(row[5]); - entry.heading = atof(row[6]); - entry.pause = atoi(row[7]); - entry.centerpoint = atoi(row[8]); + e.gridid = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.number = static_cast(atoi(row[2])); + e.x = strtof(row[3], nullptr); + e.y = strtof(row[4], nullptr); + e.z = strtof(row[5], nullptr); + e.heading = strtof(row[6], nullptr); + e.pause = static_cast(atoi(row[7])); + e.centerpoint = static_cast(atoi(row[8])); - return entry; + return e; } return NewEntity(); } static int DeleteOne( + Database& db, int grid_entries_id ) { - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "DELETE FROM {} WHERE {} = {}", TableName(), @@ -189,27 +180,31 @@ public: } static int UpdateOne( - GridEntries grid_entries_entry + Database& db, + const GridEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[3] + " = " + std::to_string(grid_entries_entry.x)); - update_values.push_back(columns[4] + " = " + std::to_string(grid_entries_entry.y)); - update_values.push_back(columns[5] + " = " + std::to_string(grid_entries_entry.z)); - update_values.push_back(columns[6] + " = " + std::to_string(grid_entries_entry.heading)); - update_values.push_back(columns[7] + " = " + std::to_string(grid_entries_entry.pause)); - update_values.push_back(columns[8] + " = " + std::to_string(grid_entries_entry.centerpoint)); + v.push_back(columns[0] + " = " + std::to_string(e.gridid)); + v.push_back(columns[1] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[2] + " = " + std::to_string(e.number)); + v.push_back(columns[3] + " = " + std::to_string(e.x)); + v.push_back(columns[4] + " = " + std::to_string(e.y)); + v.push_back(columns[5] + " = " + std::to_string(e.z)); + v.push_back(columns[6] + " = " + std::to_string(e.heading)); + v.push_back(columns[7] + " = " + std::to_string(e.pause)); + v.push_back(columns[8] + " = " + std::to_string(e.centerpoint)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - grid_entries_entry.number + e.gridid ) ); @@ -217,73 +212,81 @@ public: } static GridEntries InsertOne( - GridEntries grid_entries_entry + Database& db, + GridEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(grid_entries_entry.x)); - insert_values.push_back(std::to_string(grid_entries_entry.y)); - insert_values.push_back(std::to_string(grid_entries_entry.z)); - insert_values.push_back(std::to_string(grid_entries_entry.heading)); - insert_values.push_back(std::to_string(grid_entries_entry.pause)); - insert_values.push_back(std::to_string(grid_entries_entry.centerpoint)); + v.push_back(std::to_string(e.gridid)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.number)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.pause)); + v.push_back(std::to_string(e.centerpoint)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - grid_entries_entry.id = results.LastInsertedID(); - return grid_entries_entry; + e.gridid = results.LastInsertedID(); + return e; } - grid_entries_entry = NewEntity(); + e = NewEntity(); - return grid_entries_entry; + return e; } static int InsertMany( - std::vector grid_entries_entries + Database& db, + const std::vector &entries ) { std::vector insert_chunks; - for (auto &grid_entries_entry: grid_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(grid_entries_entry.x)); - insert_values.push_back(std::to_string(grid_entries_entry.y)); - insert_values.push_back(std::to_string(grid_entries_entry.z)); - insert_values.push_back(std::to_string(grid_entries_entry.heading)); - insert_values.push_back(std::to_string(grid_entries_entry.pause)); - insert_values.push_back(std::to_string(grid_entries_entry.centerpoint)); + v.push_back(std::to_string(e.gridid)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.number)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.pause)); + v.push_back(std::to_string(e.centerpoint)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); return (results.Success() ? results.RowsAffected() : 0); } - static std::vector All() + static std::vector All(Database& db) { std::vector all_entries; - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{}", BaseSelect() @@ -293,29 +296,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GridEntries entry{}; + GridEntries e{}; - entry.gridid = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.number = atoi(row[2]); - entry.x = atof(row[3]); - entry.y = atof(row[4]); - entry.z = atof(row[5]); - entry.heading = atof(row[6]); - entry.pause = atoi(row[7]); - entry.centerpoint = atoi(row[8]); + e.gridid = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.number = static_cast(atoi(row[2])); + e.x = strtof(row[3], nullptr); + e.y = strtof(row[4], nullptr); + e.z = strtof(row[5], nullptr); + e.heading = strtof(row[6], nullptr); + e.pause = static_cast(atoi(row[7])); + e.centerpoint = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} WHERE {}", BaseSelect(), @@ -326,31 +329,30 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GridEntries entry{}; + GridEntries e{}; - entry.gridid = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.number = atoi(row[2]); - entry.x = atof(row[3]); - entry.y = atof(row[4]); - entry.z = atof(row[5]); - entry.heading = atof(row[6]); - entry.pause = atoi(row[7]); - entry.centerpoint = atoi(row[8]); + e.gridid = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.number = static_cast(atoi(row[2])); + e.x = strtof(row[3], nullptr); + e.y = strtof(row[4], nullptr); + e.z = strtof(row[5], nullptr); + e.heading = strtof(row[6], nullptr); + e.pause = static_cast(atoi(row[7])); + e.centerpoint = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "DELETE FROM {} WHERE {}", TableName(), - PrimaryKey(), where_filter ) ); @@ -358,6 +360,44 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GRID_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_grid_repository.h b/common/repositories/base/base_grid_repository.h index be0574fc0..e37e7971a 100644 --- a/common/repositories/base/base_grid_repository.h +++ b/common/repositories/base/base_grid_repository.h @@ -1,44 +1,28 @@ /** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) + * DO NOT MODIFY THIS FILE * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - */ - -/** * This repository was automatically generated and is NOT to be modified directly. - * Any repository modifications are meant to be made to - * the repository extending the base. Any modifications to base repositories are to - * be made by the generator only + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories */ #ifndef EQEMU_BASE_GRID_REPOSITORY_H #define EQEMU_BASE_GRID_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" +#include class BaseGridRepository { public: struct Grid { - int id; - int zoneid; - int type; - int type2; + int32_t id; + int32_t zoneid; + int32_t type; + int32_t type2; }; static std::string PrimaryKey() @@ -56,24 +40,24 @@ public: }; } - static std::string ColumnsRaw() + static std::vector SelectColumns() { - return std::string(implode(", ", Columns())); + return { + "id", + "zoneid", + "type", + "type2", + }; } - static std::string InsertColumnsRaw() + static std::string ColumnsRaw() { - std::vector insert_columns; + return std::string(Strings::Implode(", ", Columns())); + } - for (auto &column : Columns()) { - if (column == PrimaryKey()) { - continue; - } - - insert_columns.push_back(column); - } - - return std::string(implode(", ", insert_columns)); + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,7 +69,7 @@ public: { return fmt::format( "SELECT {} FROM {}", - ColumnsRaw(), + SelectColumnsRaw(), TableName() ); } @@ -95,23 +79,23 @@ public: return fmt::format( "INSERT INTO {} ({}) ", TableName(), - InsertColumnsRaw() + ColumnsRaw() ); } static Grid NewEntity() { - Grid entry{}; + Grid e{}; - entry.id = 0; - entry.zoneid = 0; - entry.type = 0; - entry.type2 = 0; + e.id = 0; + e.zoneid = 0; + e.type = 0; + e.type2 = 0; - return entry; + return e; } - static Grid GetGridEntry( + static Grid GetGrid( const std::vector &grids, int grid_id ) @@ -126,10 +110,11 @@ public: } static Grid FindOne( + Database& db, int grid_id ) { - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} WHERE id = {} LIMIT 1", BaseSelect(), @@ -139,24 +124,25 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Grid entry{}; + Grid e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.type = atoi(row[2]); - entry.type2 = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.type = static_cast(atoi(row[2])); + e.type2 = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); } static int DeleteOne( + Database& db, int grid_id ) { - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "DELETE FROM {} WHERE {} = {}", TableName(), @@ -169,25 +155,26 @@ public: } static int UpdateOne( - Grid grid_entry + Database& db, + const Grid &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(grid_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(grid_entry.zoneid)); - update_values.push_back(columns[2] + " = " + std::to_string(grid_entry.type)); - update_values.push_back(columns[3] + " = " + std::to_string(grid_entry.type2)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[2] + " = " + std::to_string(e.type)); + v.push_back(columns[3] + " = " + std::to_string(e.type2)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - grid_entry.id + e.id ) ); @@ -195,69 +182,71 @@ public: } static Grid InsertOne( - Grid grid_entry + Database& db, + Grid e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(grid_entry.id)); - insert_values.push_back(std::to_string(grid_entry.zoneid)); - insert_values.push_back(std::to_string(grid_entry.type)); - insert_values.push_back(std::to_string(grid_entry.type2)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.type2)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - grid_entry.id = results.LastInsertedID(); - return grid_entry; + e.id = results.LastInsertedID(); + return e; } - grid_entry = NewEntity(); + e = NewEntity(); - return grid_entry; + return e; } static int InsertMany( - std::vector grid_entries + Database& db, + const std::vector &entries ) { std::vector insert_chunks; - for (auto &grid_entry: grid_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(grid_entry.id)); - insert_values.push_back(std::to_string(grid_entry.zoneid)); - insert_values.push_back(std::to_string(grid_entry.type)); - insert_values.push_back(std::to_string(grid_entry.type2)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.type2)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); return (results.Success() ? results.RowsAffected() : 0); } - static std::vector All() + static std::vector All(Database& db) { std::vector all_entries; - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{}", BaseSelect() @@ -267,24 +256,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Grid entry{}; + Grid e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.type = atoi(row[2]); - entry.type2 = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.type = static_cast(atoi(row[2])); + e.type2 = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} WHERE {}", BaseSelect(), @@ -295,22 +284,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Grid entry{}; + Grid e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.type = atoi(row[2]); - entry.type2 = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(atoi(row[1])); + e.type = static_cast(atoi(row[2])); + e.type2 = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "DELETE FROM {} WHERE {}", TableName(), @@ -321,6 +310,44 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GRID_REPOSITORY_H diff --git a/common/repositories/base/base_ground_spawns_repository.h b/common/repositories/base/base_ground_spawns_repository.h index 715dfa14b..b9c534c13 100644 --- a/common/repositories/base/base_ground_spawns_repository.h +++ b/common/repositories/base/base_ground_spawns_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_GROUND_SPAWNS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGroundSpawnsRepository { public: struct GroundSpawns { - int id; - int zoneid; - int version; + uint32_t id; + uint32_t zoneid; + int16_t version; float max_x; float max_y; float max_z; @@ -29,12 +29,12 @@ public: float min_y; float heading; std::string name; - int item; - int max_allowed; + uint32_t item; + uint32_t max_allowed; std::string comment; - int respawn_timer; - int min_expansion; - int max_expansion; + uint32_t respawn_timer; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -94,12 +94,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -127,31 +127,31 @@ public: static GroundSpawns NewEntity() { - GroundSpawns entry{}; + GroundSpawns e{}; - entry.id = 0; - entry.zoneid = 0; - entry.version = 0; - entry.max_x = 2000; - entry.max_y = 2000; - entry.max_z = 10000; - entry.min_x = -2000; - entry.min_y = -2000; - entry.heading = 0; - entry.name = ""; - entry.item = 0; - entry.max_allowed = 1; - entry.comment = ""; - entry.respawn_timer = 300; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.zoneid = 0; + e.version = 0; + e.max_x = 2000; + e.max_y = 2000; + e.max_z = 10000; + e.min_x = -2000; + e.min_y = -2000; + e.heading = 0; + e.name = ""; + e.item = 0; + e.max_allowed = 1; + e.comment = ""; + e.respawn_timer = 300; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static GroundSpawns GetGroundSpawnsEntry( + static GroundSpawns GetGroundSpawns( const std::vector &ground_spawnss, int ground_spawns_id ) @@ -180,28 +180,28 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GroundSpawns entry{}; + GroundSpawns e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.version = atoi(row[2]); - entry.max_x = static_cast(atof(row[3])); - entry.max_y = static_cast(atof(row[4])); - entry.max_z = static_cast(atof(row[5])); - entry.min_x = static_cast(atof(row[6])); - entry.min_y = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.name = row[9] ? row[9] : ""; - entry.item = atoi(row[10]); - entry.max_allowed = atoi(row[11]); - entry.comment = row[12] ? row[12] : ""; - entry.respawn_timer = atoi(row[13]); - entry.min_expansion = atoi(row[14]); - entry.max_expansion = atoi(row[15]); - entry.content_flags = row[16] ? row[16] : ""; - entry.content_flags_disabled = row[17] ? row[17] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zoneid = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(atoi(row[2])); + e.max_x = strtof(row[3], nullptr); + e.max_y = strtof(row[4], nullptr); + e.max_z = strtof(row[5], nullptr); + e.min_x = strtof(row[6], nullptr); + e.min_y = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.name = row[9] ? row[9] : ""; + e.item = static_cast(strtoul(row[10], nullptr, 10)); + e.max_allowed = static_cast(strtoul(row[11], nullptr, 10)); + e.comment = row[12] ? row[12] : ""; + e.respawn_timer = static_cast(strtoul(row[13], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[14])); + e.max_expansion = static_cast(atoi(row[15])); + e.content_flags = row[16] ? row[16] : ""; + e.content_flags_disabled = row[17] ? row[17] : ""; - return entry; + return e; } return NewEntity(); @@ -226,38 +226,38 @@ public: static int UpdateOne( Database& db, - GroundSpawns ground_spawns_entry + const GroundSpawns &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(ground_spawns_entry.zoneid)); - update_values.push_back(columns[2] + " = " + std::to_string(ground_spawns_entry.version)); - update_values.push_back(columns[3] + " = " + std::to_string(ground_spawns_entry.max_x)); - update_values.push_back(columns[4] + " = " + std::to_string(ground_spawns_entry.max_y)); - update_values.push_back(columns[5] + " = " + std::to_string(ground_spawns_entry.max_z)); - update_values.push_back(columns[6] + " = " + std::to_string(ground_spawns_entry.min_x)); - update_values.push_back(columns[7] + " = " + std::to_string(ground_spawns_entry.min_y)); - update_values.push_back(columns[8] + " = " + std::to_string(ground_spawns_entry.heading)); - update_values.push_back(columns[9] + " = '" + EscapeString(ground_spawns_entry.name) + "'"); - update_values.push_back(columns[10] + " = " + std::to_string(ground_spawns_entry.item)); - update_values.push_back(columns[11] + " = " + std::to_string(ground_spawns_entry.max_allowed)); - update_values.push_back(columns[12] + " = '" + EscapeString(ground_spawns_entry.comment) + "'"); - update_values.push_back(columns[13] + " = " + std::to_string(ground_spawns_entry.respawn_timer)); - update_values.push_back(columns[14] + " = " + std::to_string(ground_spawns_entry.min_expansion)); - update_values.push_back(columns[15] + " = " + std::to_string(ground_spawns_entry.max_expansion)); - update_values.push_back(columns[16] + " = '" + EscapeString(ground_spawns_entry.content_flags) + "'"); - update_values.push_back(columns[17] + " = '" + EscapeString(ground_spawns_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[2] + " = " + std::to_string(e.version)); + v.push_back(columns[3] + " = " + std::to_string(e.max_x)); + v.push_back(columns[4] + " = " + std::to_string(e.max_y)); + v.push_back(columns[5] + " = " + std::to_string(e.max_z)); + v.push_back(columns[6] + " = " + std::to_string(e.min_x)); + v.push_back(columns[7] + " = " + std::to_string(e.min_y)); + v.push_back(columns[8] + " = " + std::to_string(e.heading)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[10] + " = " + std::to_string(e.item)); + v.push_back(columns[11] + " = " + std::to_string(e.max_allowed)); + v.push_back(columns[12] + " = '" + Strings::Escape(e.comment) + "'"); + v.push_back(columns[13] + " = " + std::to_string(e.respawn_timer)); + v.push_back(columns[14] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[15] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[16] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[17] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - ground_spawns_entry.id + e.id ) ); @@ -266,87 +266,87 @@ public: static GroundSpawns InsertOne( Database& db, - GroundSpawns ground_spawns_entry + GroundSpawns e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(ground_spawns_entry.id)); - insert_values.push_back(std::to_string(ground_spawns_entry.zoneid)); - insert_values.push_back(std::to_string(ground_spawns_entry.version)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_x)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_y)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_z)); - insert_values.push_back(std::to_string(ground_spawns_entry.min_x)); - insert_values.push_back(std::to_string(ground_spawns_entry.min_y)); - insert_values.push_back(std::to_string(ground_spawns_entry.heading)); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.name) + "'"); - insert_values.push_back(std::to_string(ground_spawns_entry.item)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_allowed)); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.comment) + "'"); - insert_values.push_back(std::to_string(ground_spawns_entry.respawn_timer)); - insert_values.push_back(std::to_string(ground_spawns_entry.min_expansion)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.max_x)); + v.push_back(std::to_string(e.max_y)); + v.push_back(std::to_string(e.max_z)); + v.push_back(std::to_string(e.min_x)); + v.push_back(std::to_string(e.min_y)); + v.push_back(std::to_string(e.heading)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.item)); + v.push_back(std::to_string(e.max_allowed)); + v.push_back("'" + Strings::Escape(e.comment) + "'"); + v.push_back(std::to_string(e.respawn_timer)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - ground_spawns_entry.id = results.LastInsertedID(); - return ground_spawns_entry; + e.id = results.LastInsertedID(); + return e; } - ground_spawns_entry = NewEntity(); + e = NewEntity(); - return ground_spawns_entry; + return e; } static int InsertMany( Database& db, - std::vector ground_spawns_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &ground_spawns_entry: ground_spawns_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(ground_spawns_entry.id)); - insert_values.push_back(std::to_string(ground_spawns_entry.zoneid)); - insert_values.push_back(std::to_string(ground_spawns_entry.version)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_x)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_y)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_z)); - insert_values.push_back(std::to_string(ground_spawns_entry.min_x)); - insert_values.push_back(std::to_string(ground_spawns_entry.min_y)); - insert_values.push_back(std::to_string(ground_spawns_entry.heading)); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.name) + "'"); - insert_values.push_back(std::to_string(ground_spawns_entry.item)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_allowed)); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.comment) + "'"); - insert_values.push_back(std::to_string(ground_spawns_entry.respawn_timer)); - insert_values.push_back(std::to_string(ground_spawns_entry.min_expansion)); - insert_values.push_back(std::to_string(ground_spawns_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(ground_spawns_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.max_x)); + v.push_back(std::to_string(e.max_y)); + v.push_back(std::to_string(e.max_z)); + v.push_back(std::to_string(e.min_x)); + v.push_back(std::to_string(e.min_y)); + v.push_back(std::to_string(e.heading)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.item)); + v.push_back(std::to_string(e.max_allowed)); + v.push_back("'" + Strings::Escape(e.comment) + "'"); + v.push_back(std::to_string(e.respawn_timer)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -367,34 +367,34 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GroundSpawns entry{}; + GroundSpawns e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.version = atoi(row[2]); - entry.max_x = static_cast(atof(row[3])); - entry.max_y = static_cast(atof(row[4])); - entry.max_z = static_cast(atof(row[5])); - entry.min_x = static_cast(atof(row[6])); - entry.min_y = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.name = row[9] ? row[9] : ""; - entry.item = atoi(row[10]); - entry.max_allowed = atoi(row[11]); - entry.comment = row[12] ? row[12] : ""; - entry.respawn_timer = atoi(row[13]); - entry.min_expansion = atoi(row[14]); - entry.max_expansion = atoi(row[15]); - entry.content_flags = row[16] ? row[16] : ""; - entry.content_flags_disabled = row[17] ? row[17] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zoneid = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(atoi(row[2])); + e.max_x = strtof(row[3], nullptr); + e.max_y = strtof(row[4], nullptr); + e.max_z = strtof(row[5], nullptr); + e.min_x = strtof(row[6], nullptr); + e.min_y = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.name = row[9] ? row[9] : ""; + e.item = static_cast(strtoul(row[10], nullptr, 10)); + e.max_allowed = static_cast(strtoul(row[11], nullptr, 10)); + e.comment = row[12] ? row[12] : ""; + e.respawn_timer = static_cast(strtoul(row[13], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[14])); + e.max_expansion = static_cast(atoi(row[15])); + e.content_flags = row[16] ? row[16] : ""; + e.content_flags_disabled = row[17] ? row[17] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -409,34 +409,34 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GroundSpawns entry{}; + GroundSpawns e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.version = atoi(row[2]); - entry.max_x = static_cast(atof(row[3])); - entry.max_y = static_cast(atof(row[4])); - entry.max_z = static_cast(atof(row[5])); - entry.min_x = static_cast(atof(row[6])); - entry.min_y = static_cast(atof(row[7])); - entry.heading = static_cast(atof(row[8])); - entry.name = row[9] ? row[9] : ""; - entry.item = atoi(row[10]); - entry.max_allowed = atoi(row[11]); - entry.comment = row[12] ? row[12] : ""; - entry.respawn_timer = atoi(row[13]); - entry.min_expansion = atoi(row[14]); - entry.max_expansion = atoi(row[15]); - entry.content_flags = row[16] ? row[16] : ""; - entry.content_flags_disabled = row[17] ? row[17] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zoneid = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(atoi(row[2])); + e.max_x = strtof(row[3], nullptr); + e.max_y = strtof(row[4], nullptr); + e.max_z = strtof(row[5], nullptr); + e.min_x = strtof(row[6], nullptr); + e.min_y = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.name = row[9] ? row[9] : ""; + e.item = static_cast(strtoul(row[10], nullptr, 10)); + e.max_allowed = static_cast(strtoul(row[11], nullptr, 10)); + e.comment = row[12] ? row[12] : ""; + e.respawn_timer = static_cast(strtoul(row[13], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[14])); + e.max_expansion = static_cast(atoi(row[15])); + e.content_flags = row[16] ? row[16] : ""; + e.content_flags_disabled = row[17] ? row[17] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -461,6 +461,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GROUND_SPAWNS_REPOSITORY_H diff --git a/common/repositories/base/base_group_id_repository.h b/common/repositories/base/base_group_id_repository.h index ce18b2298..628e814d4 100644 --- a/common/repositories/base/base_group_id_repository.h +++ b/common/repositories/base/base_group_id_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_GROUP_ID_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGroupIdRepository { public: struct GroupId { - int groupid; - int charid; + int32_t groupid; + int32_t charid; std::string name; - int ismerc; + int8_t ismerc; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static GroupId NewEntity() { - GroupId entry{}; + GroupId e{}; - entry.groupid = 0; - entry.charid = 0; - entry.name = ""; - entry.ismerc = 0; + e.groupid = 0; + e.charid = 0; + e.name = ""; + e.ismerc = 0; - return entry; + return e; } - static GroupId GetGroupIdEntry( + static GroupId GetGroupId( const std::vector &group_ids, int group_id_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GroupId entry{}; + GroupId e{}; - entry.groupid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.ismerc = atoi(row[3]); + e.groupid = static_cast(atoi(row[0])); + e.charid = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.ismerc = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - GroupId group_id_entry + const GroupId &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(group_id_entry.groupid)); - update_values.push_back(columns[1] + " = " + std::to_string(group_id_entry.charid)); - update_values.push_back(columns[2] + " = '" + EscapeString(group_id_entry.name) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(group_id_entry.ismerc)); + v.push_back(columns[0] + " = " + std::to_string(e.groupid)); + v.push_back(columns[1] + " = " + std::to_string(e.charid)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.ismerc)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - group_id_entry.groupid + e.groupid ) ); @@ -183,59 +183,59 @@ public: static GroupId InsertOne( Database& db, - GroupId group_id_entry + GroupId e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(group_id_entry.groupid)); - insert_values.push_back(std::to_string(group_id_entry.charid)); - insert_values.push_back("'" + EscapeString(group_id_entry.name) + "'"); - insert_values.push_back(std::to_string(group_id_entry.ismerc)); + v.push_back(std::to_string(e.groupid)); + v.push_back(std::to_string(e.charid)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.ismerc)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - group_id_entry.groupid = results.LastInsertedID(); - return group_id_entry; + e.groupid = results.LastInsertedID(); + return e; } - group_id_entry = NewEntity(); + e = NewEntity(); - return group_id_entry; + return e; } static int InsertMany( Database& db, - std::vector group_id_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &group_id_entry: group_id_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(group_id_entry.groupid)); - insert_values.push_back(std::to_string(group_id_entry.charid)); - insert_values.push_back("'" + EscapeString(group_id_entry.name) + "'"); - insert_values.push_back(std::to_string(group_id_entry.ismerc)); + v.push_back(std::to_string(e.groupid)); + v.push_back(std::to_string(e.charid)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.ismerc)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GroupId entry{}; + GroupId e{}; - entry.groupid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.ismerc = atoi(row[3]); + e.groupid = static_cast(atoi(row[0])); + e.charid = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.ismerc = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GroupId entry{}; + GroupId e{}; - entry.groupid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.ismerc = atoi(row[3]); + e.groupid = static_cast(atoi(row[0])); + e.charid = static_cast(atoi(row[1])); + e.name = row[2] ? row[2] : ""; + e.ismerc = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GROUP_ID_REPOSITORY_H diff --git a/common/repositories/base/base_group_leaders_repository.h b/common/repositories/base/base_group_leaders_repository.h index 15bd6af3b..5032bf65f 100644 --- a/common/repositories/base/base_group_leaders_repository.h +++ b/common/repositories/base/base_group_leaders_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_GROUP_LEADERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGroupLeadersRepository { public: struct GroupLeaders { - int gid; + int32_t gid; std::string leadername; std::string marknpc; std::string leadershipaa; @@ -27,7 +27,7 @@ public: std::string assist; std::string puller; std::string mentoree; - int mentor_percent; + int32_t mentor_percent; }; static std::string PrimaryKey() @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static GroupLeaders NewEntity() { - GroupLeaders entry{}; + GroupLeaders e{}; - entry.gid = 0; - entry.leadername = ""; - entry.marknpc = ""; - entry.leadershipaa = 0; - entry.maintank = ""; - entry.assist = ""; - entry.puller = ""; - entry.mentoree = ""; - entry.mentor_percent = 0; + e.gid = 0; + e.leadername = ""; + e.marknpc = ""; + e.leadershipaa = 0; + e.maintank = ""; + e.assist = ""; + e.puller = ""; + e.mentoree = ""; + e.mentor_percent = 0; - return entry; + return e; } - static GroupLeaders GetGroupLeadersEntry( + static GroupLeaders GetGroupLeaders( const std::vector &group_leaderss, int group_leaders_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GroupLeaders entry{}; + GroupLeaders e{}; - entry.gid = atoi(row[0]); - entry.leadername = row[1] ? row[1] : ""; - entry.marknpc = row[2] ? row[2] : ""; - entry.leadershipaa = row[3] ? row[3] : ""; - entry.maintank = row[4] ? row[4] : ""; - entry.assist = row[5] ? row[5] : ""; - entry.puller = row[6] ? row[6] : ""; - entry.mentoree = row[7] ? row[7] : ""; - entry.mentor_percent = atoi(row[8]); + e.gid = static_cast(atoi(row[0])); + e.leadername = row[1] ? row[1] : ""; + e.marknpc = row[2] ? row[2] : ""; + e.leadershipaa = row[3] ? row[3] : ""; + e.maintank = row[4] ? row[4] : ""; + e.assist = row[5] ? row[5] : ""; + e.puller = row[6] ? row[6] : ""; + e.mentoree = row[7] ? row[7] : ""; + e.mentor_percent = static_cast(atoi(row[8])); - return entry; + return e; } return NewEntity(); @@ -181,30 +181,30 @@ public: static int UpdateOne( Database& db, - GroupLeaders group_leaders_entry + const GroupLeaders &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(group_leaders_entry.gid)); - update_values.push_back(columns[1] + " = '" + EscapeString(group_leaders_entry.leadername) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(group_leaders_entry.marknpc) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(group_leaders_entry.leadershipaa) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(group_leaders_entry.maintank) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(group_leaders_entry.assist) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(group_leaders_entry.puller) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(group_leaders_entry.mentoree) + "'"); - update_values.push_back(columns[8] + " = " + std::to_string(group_leaders_entry.mentor_percent)); + v.push_back(columns[0] + " = " + std::to_string(e.gid)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.leadername) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.marknpc) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.leadershipaa) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.maintank) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.assist) + "'"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.puller) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.mentoree) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.mentor_percent)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - group_leaders_entry.gid + e.gid ) ); @@ -213,69 +213,69 @@ public: static GroupLeaders InsertOne( Database& db, - GroupLeaders group_leaders_entry + GroupLeaders e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(group_leaders_entry.gid)); - insert_values.push_back("'" + EscapeString(group_leaders_entry.leadername) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.marknpc) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.leadershipaa) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.maintank) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.assist) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.puller) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.mentoree) + "'"); - insert_values.push_back(std::to_string(group_leaders_entry.mentor_percent)); + v.push_back(std::to_string(e.gid)); + v.push_back("'" + Strings::Escape(e.leadername) + "'"); + v.push_back("'" + Strings::Escape(e.marknpc) + "'"); + v.push_back("'" + Strings::Escape(e.leadershipaa) + "'"); + v.push_back("'" + Strings::Escape(e.maintank) + "'"); + v.push_back("'" + Strings::Escape(e.assist) + "'"); + v.push_back("'" + Strings::Escape(e.puller) + "'"); + v.push_back("'" + Strings::Escape(e.mentoree) + "'"); + v.push_back(std::to_string(e.mentor_percent)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - group_leaders_entry.gid = results.LastInsertedID(); - return group_leaders_entry; + e.gid = results.LastInsertedID(); + return e; } - group_leaders_entry = NewEntity(); + e = NewEntity(); - return group_leaders_entry; + return e; } static int InsertMany( Database& db, - std::vector group_leaders_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &group_leaders_entry: group_leaders_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(group_leaders_entry.gid)); - insert_values.push_back("'" + EscapeString(group_leaders_entry.leadername) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.marknpc) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.leadershipaa) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.maintank) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.assist) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.puller) + "'"); - insert_values.push_back("'" + EscapeString(group_leaders_entry.mentoree) + "'"); - insert_values.push_back(std::to_string(group_leaders_entry.mentor_percent)); + v.push_back(std::to_string(e.gid)); + v.push_back("'" + Strings::Escape(e.leadername) + "'"); + v.push_back("'" + Strings::Escape(e.marknpc) + "'"); + v.push_back("'" + Strings::Escape(e.leadershipaa) + "'"); + v.push_back("'" + Strings::Escape(e.maintank) + "'"); + v.push_back("'" + Strings::Escape(e.assist) + "'"); + v.push_back("'" + Strings::Escape(e.puller) + "'"); + v.push_back("'" + Strings::Escape(e.mentoree) + "'"); + v.push_back(std::to_string(e.mentor_percent)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -296,25 +296,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GroupLeaders entry{}; + GroupLeaders e{}; - entry.gid = atoi(row[0]); - entry.leadername = row[1] ? row[1] : ""; - entry.marknpc = row[2] ? row[2] : ""; - entry.leadershipaa = row[3] ? row[3] : ""; - entry.maintank = row[4] ? row[4] : ""; - entry.assist = row[5] ? row[5] : ""; - entry.puller = row[6] ? row[6] : ""; - entry.mentoree = row[7] ? row[7] : ""; - entry.mentor_percent = atoi(row[8]); + e.gid = static_cast(atoi(row[0])); + e.leadername = row[1] ? row[1] : ""; + e.marknpc = row[2] ? row[2] : ""; + e.leadershipaa = row[3] ? row[3] : ""; + e.maintank = row[4] ? row[4] : ""; + e.assist = row[5] ? row[5] : ""; + e.puller = row[6] ? row[6] : ""; + e.mentoree = row[7] ? row[7] : ""; + e.mentor_percent = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -329,25 +329,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GroupLeaders entry{}; + GroupLeaders e{}; - entry.gid = atoi(row[0]); - entry.leadername = row[1] ? row[1] : ""; - entry.marknpc = row[2] ? row[2] : ""; - entry.leadershipaa = row[3] ? row[3] : ""; - entry.maintank = row[4] ? row[4] : ""; - entry.assist = row[5] ? row[5] : ""; - entry.puller = row[6] ? row[6] : ""; - entry.mentoree = row[7] ? row[7] : ""; - entry.mentor_percent = atoi(row[8]); + e.gid = static_cast(atoi(row[0])); + e.leadername = row[1] ? row[1] : ""; + e.marknpc = row[2] ? row[2] : ""; + e.leadershipaa = row[3] ? row[3] : ""; + e.maintank = row[4] ? row[4] : ""; + e.assist = row[5] ? row[5] : ""; + e.puller = row[6] ? row[6] : ""; + e.mentoree = row[7] ? row[7] : ""; + e.mentor_percent = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -372,6 +372,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GROUP_LEADERS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_members_repository.h b/common/repositories/base/base_guild_members_repository.h deleted file mode 100644 index df522d479..000000000 --- a/common/repositories/base/base_guild_members_repository.h +++ /dev/null @@ -1,377 +0,0 @@ -/** - * DO NOT MODIFY THIS FILE - * - * This repository was automatically generated and is NOT to be modified directly. - * Any repository modifications are meant to be made to the repository extending the base. - * Any modifications to base repositories are to be made by the generator only - * - * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories - */ - -#ifndef EQEMU_BASE_GUILD_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_GUILD_MEMBERS_REPOSITORY_H - -#include "../../database.h" -#include "../../string_util.h" -#include - -class BaseGuildMembersRepository { -public: - struct GuildMembers { - int char_id; - int guild_id; - int rank; - int tribute_enable; - int total_tribute; - int last_tribute; - int banker; - std::string public_note; - int alt; - }; - - static std::string PrimaryKey() - { - return std::string("char_id"); - } - - static std::vector Columns() - { - return { - "char_id", - "guild_id", - "rank", - "tribute_enable", - "total_tribute", - "last_tribute", - "banker", - "public_note", - "alt", - }; - } - - static std::vector SelectColumns() - { - return { - "char_id", - "guild_id", - "rank", - "tribute_enable", - "total_tribute", - "last_tribute", - "banker", - "public_note", - "alt", - }; - } - - static std::string ColumnsRaw() - { - return std::string(implode(", ", Columns())); - } - - static std::string SelectColumnsRaw() - { - return std::string(implode(", ", SelectColumns())); - } - - static std::string TableName() - { - return std::string("guild_members"); - } - - static std::string BaseSelect() - { - return fmt::format( - "SELECT {} FROM {}", - SelectColumnsRaw(), - TableName() - ); - } - - static std::string BaseInsert() - { - return fmt::format( - "INSERT INTO {} ({}) ", - TableName(), - ColumnsRaw() - ); - } - - static GuildMembers NewEntity() - { - GuildMembers entry{}; - - entry.char_id = 0; - entry.guild_id = 0; - entry.rank = 0; - entry.tribute_enable = 0; - entry.total_tribute = 0; - entry.last_tribute = 0; - entry.banker = 0; - entry.public_note = ""; - entry.alt = 0; - - return entry; - } - - static GuildMembers GetGuildMembersEntry( - const std::vector &guild_memberss, - int guild_members_id - ) - { - for (auto &guild_members : guild_memberss) { - if (guild_members.char_id == guild_members_id) { - return guild_members; - } - } - - return NewEntity(); - } - - static GuildMembers FindOne( - Database& db, - int guild_members_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE id = {} LIMIT 1", - BaseSelect(), - guild_members_id - ) - ); - - auto row = results.begin(); - if (results.RowCount() == 1) { - GuildMembers entry{}; - - entry.char_id = atoi(row[0]); - entry.guild_id = atoi(row[1]); - entry.rank = atoi(row[2]); - entry.tribute_enable = atoi(row[3]); - entry.total_tribute = atoi(row[4]); - entry.last_tribute = atoi(row[5]); - entry.banker = atoi(row[6]); - entry.public_note = row[7] ? row[7] : ""; - entry.alt = atoi(row[8]); - - return entry; - } - - return NewEntity(); - } - - static int DeleteOne( - Database& db, - int guild_members_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {} = {}", - TableName(), - PrimaryKey(), - guild_members_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int UpdateOne( - Database& db, - GuildMembers guild_members_entry - ) - { - std::vector update_values; - - auto columns = Columns(); - - update_values.push_back(columns[0] + " = " + std::to_string(guild_members_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(guild_members_entry.guild_id)); - update_values.push_back(columns[2] + " = " + std::to_string(guild_members_entry.rank)); - update_values.push_back(columns[3] + " = " + std::to_string(guild_members_entry.tribute_enable)); - update_values.push_back(columns[4] + " = " + std::to_string(guild_members_entry.total_tribute)); - update_values.push_back(columns[5] + " = " + std::to_string(guild_members_entry.last_tribute)); - update_values.push_back(columns[6] + " = " + std::to_string(guild_members_entry.banker)); - update_values.push_back(columns[7] + " = '" + EscapeString(guild_members_entry.public_note) + "'"); - update_values.push_back(columns[8] + " = " + std::to_string(guild_members_entry.alt)); - - auto results = db.QueryDatabase( - fmt::format( - "UPDATE {} SET {} WHERE {} = {}", - TableName(), - implode(", ", update_values), - PrimaryKey(), - guild_members_entry.char_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static GuildMembers InsertOne( - Database& db, - GuildMembers guild_members_entry - ) - { - std::vector insert_values; - - insert_values.push_back(std::to_string(guild_members_entry.char_id)); - insert_values.push_back(std::to_string(guild_members_entry.guild_id)); - insert_values.push_back(std::to_string(guild_members_entry.rank)); - insert_values.push_back(std::to_string(guild_members_entry.tribute_enable)); - insert_values.push_back(std::to_string(guild_members_entry.total_tribute)); - insert_values.push_back(std::to_string(guild_members_entry.last_tribute)); - insert_values.push_back(std::to_string(guild_members_entry.banker)); - insert_values.push_back("'" + EscapeString(guild_members_entry.public_note) + "'"); - insert_values.push_back(std::to_string(guild_members_entry.alt)); - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES ({})", - BaseInsert(), - implode(",", insert_values) - ) - ); - - if (results.Success()) { - guild_members_entry.char_id = results.LastInsertedID(); - return guild_members_entry; - } - - guild_members_entry = NewEntity(); - - return guild_members_entry; - } - - static int InsertMany( - Database& db, - std::vector guild_members_entries - ) - { - std::vector insert_chunks; - - for (auto &guild_members_entry: guild_members_entries) { - std::vector insert_values; - - insert_values.push_back(std::to_string(guild_members_entry.char_id)); - insert_values.push_back(std::to_string(guild_members_entry.guild_id)); - insert_values.push_back(std::to_string(guild_members_entry.rank)); - insert_values.push_back(std::to_string(guild_members_entry.tribute_enable)); - insert_values.push_back(std::to_string(guild_members_entry.total_tribute)); - insert_values.push_back(std::to_string(guild_members_entry.last_tribute)); - insert_values.push_back(std::to_string(guild_members_entry.banker)); - insert_values.push_back("'" + EscapeString(guild_members_entry.public_note) + "'"); - insert_values.push_back(std::to_string(guild_members_entry.alt)); - - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); - } - - std::vector insert_values; - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES {}", - BaseInsert(), - implode(",", insert_chunks) - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static std::vector All(Database& db) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{}", - BaseSelect() - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - GuildMembers entry{}; - - entry.char_id = atoi(row[0]); - entry.guild_id = atoi(row[1]); - entry.rank = atoi(row[2]); - entry.tribute_enable = atoi(row[3]); - entry.total_tribute = atoi(row[4]); - entry.last_tribute = atoi(row[5]); - entry.banker = atoi(row[6]); - entry.public_note = row[7] ? row[7] : ""; - entry.alt = atoi(row[8]); - - all_entries.push_back(entry); - } - - return all_entries; - } - - static std::vector GetWhere(Database& db, std::string where_filter) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE {}", - BaseSelect(), - where_filter - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - GuildMembers entry{}; - - entry.char_id = atoi(row[0]); - entry.guild_id = atoi(row[1]); - entry.rank = atoi(row[2]); - entry.tribute_enable = atoi(row[3]); - entry.total_tribute = atoi(row[4]); - entry.last_tribute = atoi(row[5]); - entry.banker = atoi(row[6]); - entry.public_note = row[7] ? row[7] : ""; - entry.alt = atoi(row[8]); - - all_entries.push_back(entry); - } - - return all_entries; - } - - static int DeleteWhere(Database& db, std::string where_filter) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {}", - TableName(), - where_filter - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int Truncate(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "TRUNCATE TABLE {}", - TableName() - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - -}; - -#endif //EQEMU_BASE_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_ranks_repository.h b/common/repositories/base/base_guild_ranks_repository.h index c777fd1e7..cbc4ddf64 100644 --- a/common/repositories/base/base_guild_ranks_repository.h +++ b/common/repositories/base/base_guild_ranks_repository.h @@ -13,23 +13,23 @@ #define EQEMU_BASE_GUILD_RANKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGuildRanksRepository { public: struct GuildRanks { - int guild_id; - int rank; + uint32_t guild_id; + uint8_t rank; std::string title; - int can_hear; - int can_speak; - int can_invite; - int can_remove; - int can_promote; - int can_demote; - int can_motd; - int can_warpeace; + uint8_t can_hear; + uint8_t can_speak; + uint8_t can_invite; + uint8_t can_remove; + uint8_t can_promote; + uint8_t can_demote; + uint8_t can_motd; + uint8_t can_warpeace; }; static std::string PrimaryKey() @@ -73,12 +73,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -106,24 +106,24 @@ public: static GuildRanks NewEntity() { - GuildRanks entry{}; + GuildRanks e{}; - entry.guild_id = 0; - entry.rank = 0; - entry.title = ""; - entry.can_hear = 0; - entry.can_speak = 0; - entry.can_invite = 0; - entry.can_remove = 0; - entry.can_promote = 0; - entry.can_demote = 0; - entry.can_motd = 0; - entry.can_warpeace = 0; + e.guild_id = 0; + e.rank = 0; + e.title = ""; + e.can_hear = 0; + e.can_speak = 0; + e.can_invite = 0; + e.can_remove = 0; + e.can_promote = 0; + e.can_demote = 0; + e.can_motd = 0; + e.can_warpeace = 0; - return entry; + return e; } - static GuildRanks GetGuildRanksEntry( + static GuildRanks GetGuildRanks( const std::vector &guild_rankss, int guild_ranks_id ) @@ -152,21 +152,21 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GuildRanks entry{}; + GuildRanks e{}; - entry.guild_id = atoi(row[0]); - entry.rank = atoi(row[1]); - entry.title = row[2] ? row[2] : ""; - entry.can_hear = atoi(row[3]); - entry.can_speak = atoi(row[4]); - entry.can_invite = atoi(row[5]); - entry.can_remove = atoi(row[6]); - entry.can_promote = atoi(row[7]); - entry.can_demote = atoi(row[8]); - entry.can_motd = atoi(row[9]); - entry.can_warpeace = atoi(row[10]); + e.guild_id = static_cast(strtoul(row[0], nullptr, 10)); + e.rank = static_cast(strtoul(row[1], nullptr, 10)); + e.title = row[2] ? row[2] : ""; + e.can_hear = static_cast(strtoul(row[3], nullptr, 10)); + e.can_speak = static_cast(strtoul(row[4], nullptr, 10)); + e.can_invite = static_cast(strtoul(row[5], nullptr, 10)); + e.can_remove = static_cast(strtoul(row[6], nullptr, 10)); + e.can_promote = static_cast(strtoul(row[7], nullptr, 10)); + e.can_demote = static_cast(strtoul(row[8], nullptr, 10)); + e.can_motd = static_cast(strtoul(row[9], nullptr, 10)); + e.can_warpeace = static_cast(strtoul(row[10], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -191,32 +191,32 @@ public: static int UpdateOne( Database& db, - GuildRanks guild_ranks_entry + const GuildRanks &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(guild_ranks_entry.guild_id)); - update_values.push_back(columns[1] + " = " + std::to_string(guild_ranks_entry.rank)); - update_values.push_back(columns[2] + " = '" + EscapeString(guild_ranks_entry.title) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(guild_ranks_entry.can_hear)); - update_values.push_back(columns[4] + " = " + std::to_string(guild_ranks_entry.can_speak)); - update_values.push_back(columns[5] + " = " + std::to_string(guild_ranks_entry.can_invite)); - update_values.push_back(columns[6] + " = " + std::to_string(guild_ranks_entry.can_remove)); - update_values.push_back(columns[7] + " = " + std::to_string(guild_ranks_entry.can_promote)); - update_values.push_back(columns[8] + " = " + std::to_string(guild_ranks_entry.can_demote)); - update_values.push_back(columns[9] + " = " + std::to_string(guild_ranks_entry.can_motd)); - update_values.push_back(columns[10] + " = " + std::to_string(guild_ranks_entry.can_warpeace)); + v.push_back(columns[0] + " = " + std::to_string(e.guild_id)); + v.push_back(columns[1] + " = " + std::to_string(e.rank)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.title) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.can_hear)); + v.push_back(columns[4] + " = " + std::to_string(e.can_speak)); + v.push_back(columns[5] + " = " + std::to_string(e.can_invite)); + v.push_back(columns[6] + " = " + std::to_string(e.can_remove)); + v.push_back(columns[7] + " = " + std::to_string(e.can_promote)); + v.push_back(columns[8] + " = " + std::to_string(e.can_demote)); + v.push_back(columns[9] + " = " + std::to_string(e.can_motd)); + v.push_back(columns[10] + " = " + std::to_string(e.can_warpeace)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - guild_ranks_entry.guild_id + e.guild_id ) ); @@ -225,73 +225,73 @@ public: static GuildRanks InsertOne( Database& db, - GuildRanks guild_ranks_entry + GuildRanks e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(guild_ranks_entry.guild_id)); - insert_values.push_back(std::to_string(guild_ranks_entry.rank)); - insert_values.push_back("'" + EscapeString(guild_ranks_entry.title) + "'"); - insert_values.push_back(std::to_string(guild_ranks_entry.can_hear)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_speak)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_invite)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_remove)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_promote)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_demote)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_motd)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_warpeace)); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.rank)); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back(std::to_string(e.can_hear)); + v.push_back(std::to_string(e.can_speak)); + v.push_back(std::to_string(e.can_invite)); + v.push_back(std::to_string(e.can_remove)); + v.push_back(std::to_string(e.can_promote)); + v.push_back(std::to_string(e.can_demote)); + v.push_back(std::to_string(e.can_motd)); + v.push_back(std::to_string(e.can_warpeace)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - guild_ranks_entry.guild_id = results.LastInsertedID(); - return guild_ranks_entry; + e.guild_id = results.LastInsertedID(); + return e; } - guild_ranks_entry = NewEntity(); + e = NewEntity(); - return guild_ranks_entry; + return e; } static int InsertMany( Database& db, - std::vector guild_ranks_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &guild_ranks_entry: guild_ranks_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(guild_ranks_entry.guild_id)); - insert_values.push_back(std::to_string(guild_ranks_entry.rank)); - insert_values.push_back("'" + EscapeString(guild_ranks_entry.title) + "'"); - insert_values.push_back(std::to_string(guild_ranks_entry.can_hear)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_speak)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_invite)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_remove)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_promote)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_demote)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_motd)); - insert_values.push_back(std::to_string(guild_ranks_entry.can_warpeace)); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.rank)); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back(std::to_string(e.can_hear)); + v.push_back(std::to_string(e.can_speak)); + v.push_back(std::to_string(e.can_invite)); + v.push_back(std::to_string(e.can_remove)); + v.push_back(std::to_string(e.can_promote)); + v.push_back(std::to_string(e.can_demote)); + v.push_back(std::to_string(e.can_motd)); + v.push_back(std::to_string(e.can_warpeace)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -312,27 +312,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GuildRanks entry{}; + GuildRanks e{}; - entry.guild_id = atoi(row[0]); - entry.rank = atoi(row[1]); - entry.title = row[2] ? row[2] : ""; - entry.can_hear = atoi(row[3]); - entry.can_speak = atoi(row[4]); - entry.can_invite = atoi(row[5]); - entry.can_remove = atoi(row[6]); - entry.can_promote = atoi(row[7]); - entry.can_demote = atoi(row[8]); - entry.can_motd = atoi(row[9]); - entry.can_warpeace = atoi(row[10]); + e.guild_id = static_cast(strtoul(row[0], nullptr, 10)); + e.rank = static_cast(strtoul(row[1], nullptr, 10)); + e.title = row[2] ? row[2] : ""; + e.can_hear = static_cast(strtoul(row[3], nullptr, 10)); + e.can_speak = static_cast(strtoul(row[4], nullptr, 10)); + e.can_invite = static_cast(strtoul(row[5], nullptr, 10)); + e.can_remove = static_cast(strtoul(row[6], nullptr, 10)); + e.can_promote = static_cast(strtoul(row[7], nullptr, 10)); + e.can_demote = static_cast(strtoul(row[8], nullptr, 10)); + e.can_motd = static_cast(strtoul(row[9], nullptr, 10)); + e.can_warpeace = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -347,27 +347,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GuildRanks entry{}; + GuildRanks e{}; - entry.guild_id = atoi(row[0]); - entry.rank = atoi(row[1]); - entry.title = row[2] ? row[2] : ""; - entry.can_hear = atoi(row[3]); - entry.can_speak = atoi(row[4]); - entry.can_invite = atoi(row[5]); - entry.can_remove = atoi(row[6]); - entry.can_promote = atoi(row[7]); - entry.can_demote = atoi(row[8]); - entry.can_motd = atoi(row[9]); - entry.can_warpeace = atoi(row[10]); + e.guild_id = static_cast(strtoul(row[0], nullptr, 10)); + e.rank = static_cast(strtoul(row[1], nullptr, 10)); + e.title = row[2] ? row[2] : ""; + e.can_hear = static_cast(strtoul(row[3], nullptr, 10)); + e.can_speak = static_cast(strtoul(row[4], nullptr, 10)); + e.can_invite = static_cast(strtoul(row[5], nullptr, 10)); + e.can_remove = static_cast(strtoul(row[6], nullptr, 10)); + e.can_promote = static_cast(strtoul(row[7], nullptr, 10)); + e.can_demote = static_cast(strtoul(row[8], nullptr, 10)); + e.can_motd = static_cast(strtoul(row[9], nullptr, 10)); + e.can_warpeace = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -392,6 +392,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GUILD_RANKS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_relations_repository.h b/common/repositories/base/base_guild_relations_repository.h index 869acc23e..6208edadc 100644 --- a/common/repositories/base/base_guild_relations_repository.h +++ b/common/repositories/base/base_guild_relations_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_GUILD_RELATIONS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGuildRelationsRepository { public: struct GuildRelations { - int guild1; - int guild2; - int relation; + uint32_t guild1; + uint32_t guild2; + int8_t relation; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static GuildRelations NewEntity() { - GuildRelations entry{}; + GuildRelations e{}; - entry.guild1 = 0; - entry.guild2 = 0; - entry.relation = 0; + e.guild1 = 0; + e.guild2 = 0; + e.relation = 0; - return entry; + return e; } - static GuildRelations GetGuildRelationsEntry( + static GuildRelations GetGuildRelations( const std::vector &guild_relationss, int guild_relations_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - GuildRelations entry{}; + GuildRelations e{}; - entry.guild1 = atoi(row[0]); - entry.guild2 = atoi(row[1]); - entry.relation = atoi(row[2]); + e.guild1 = static_cast(strtoul(row[0], nullptr, 10)); + e.guild2 = static_cast(strtoul(row[1], nullptr, 10)); + e.relation = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - GuildRelations guild_relations_entry + const GuildRelations &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(guild_relations_entry.guild1)); - update_values.push_back(columns[1] + " = " + std::to_string(guild_relations_entry.guild2)); - update_values.push_back(columns[2] + " = " + std::to_string(guild_relations_entry.relation)); + v.push_back(columns[0] + " = " + std::to_string(e.guild1)); + v.push_back(columns[1] + " = " + std::to_string(e.guild2)); + v.push_back(columns[2] + " = " + std::to_string(e.relation)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - guild_relations_entry.guild1 + e.guild1 ) ); @@ -177,57 +177,57 @@ public: static GuildRelations InsertOne( Database& db, - GuildRelations guild_relations_entry + GuildRelations e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(guild_relations_entry.guild1)); - insert_values.push_back(std::to_string(guild_relations_entry.guild2)); - insert_values.push_back(std::to_string(guild_relations_entry.relation)); + v.push_back(std::to_string(e.guild1)); + v.push_back(std::to_string(e.guild2)); + v.push_back(std::to_string(e.relation)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - guild_relations_entry.guild1 = results.LastInsertedID(); - return guild_relations_entry; + e.guild1 = results.LastInsertedID(); + return e; } - guild_relations_entry = NewEntity(); + e = NewEntity(); - return guild_relations_entry; + return e; } static int InsertMany( Database& db, - std::vector guild_relations_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &guild_relations_entry: guild_relations_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(guild_relations_entry.guild1)); - insert_values.push_back(std::to_string(guild_relations_entry.guild2)); - insert_values.push_back(std::to_string(guild_relations_entry.relation)); + v.push_back(std::to_string(e.guild1)); + v.push_back(std::to_string(e.guild2)); + v.push_back(std::to_string(e.relation)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GuildRelations entry{}; + GuildRelations e{}; - entry.guild1 = atoi(row[0]); - entry.guild2 = atoi(row[1]); - entry.relation = atoi(row[2]); + e.guild1 = static_cast(strtoul(row[0], nullptr, 10)); + e.guild2 = static_cast(strtoul(row[1], nullptr, 10)); + e.relation = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - GuildRelations entry{}; + GuildRelations e{}; - entry.guild1 = atoi(row[0]); - entry.guild2 = atoi(row[1]); - entry.relation = atoi(row[2]); + e.guild1 = static_cast(strtoul(row[0], nullptr, 10)); + e.guild2 = static_cast(strtoul(row[1], nullptr, 10)); + e.relation = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GUILD_RELATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_guilds_repository.h b/common/repositories/base/base_guilds_repository.h index e4f1a6700..a423eaaa7 100644 --- a/common/repositories/base/base_guilds_repository.h +++ b/common/repositories/base/base_guilds_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_GUILDS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseGuildsRepository { public: struct Guilds { - int id; + int32_t id; std::string name; - int leader; - int minstatus; + int32_t leader; + int16_t minstatus; std::string motd; - int tribute; + uint32_t tribute; std::string motd_setter; std::string channel; std::string url; @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static Guilds NewEntity() { - Guilds entry{}; + Guilds e{}; - entry.id = 0; - entry.name = ""; - entry.leader = 0; - entry.minstatus = 0; - entry.motd = ""; - entry.tribute = 0; - entry.motd_setter = ""; - entry.channel = ""; - entry.url = ""; + e.id = 0; + e.name = ""; + e.leader = 0; + e.minstatus = 0; + e.motd = ""; + e.tribute = 0; + e.motd_setter = ""; + e.channel = ""; + e.url = ""; - return entry; + return e; } - static Guilds GetGuildsEntry( + static Guilds GetGuilds( const std::vector &guildss, int guilds_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Guilds entry{}; + Guilds e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.leader = atoi(row[2]); - entry.minstatus = atoi(row[3]); - entry.motd = row[4] ? row[4] : ""; - entry.tribute = atoi(row[5]); - entry.motd_setter = row[6] ? row[6] : ""; - entry.channel = row[7] ? row[7] : ""; - entry.url = row[8] ? row[8] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.leader = static_cast(atoi(row[2])); + e.minstatus = static_cast(atoi(row[3])); + e.motd = row[4] ? row[4] : ""; + e.tribute = static_cast(strtoul(row[5], nullptr, 10)); + e.motd_setter = row[6] ? row[6] : ""; + e.channel = row[7] ? row[7] : ""; + e.url = row[8] ? row[8] : ""; - return entry; + return e; } return NewEntity(); @@ -181,29 +181,29 @@ public: static int UpdateOne( Database& db, - Guilds guilds_entry + const Guilds &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(guilds_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(guilds_entry.leader)); - update_values.push_back(columns[3] + " = " + std::to_string(guilds_entry.minstatus)); - update_values.push_back(columns[4] + " = '" + EscapeString(guilds_entry.motd) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(guilds_entry.tribute)); - update_values.push_back(columns[6] + " = '" + EscapeString(guilds_entry.motd_setter) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(guilds_entry.channel) + "'"); - update_values.push_back(columns[8] + " = '" + EscapeString(guilds_entry.url) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.leader)); + v.push_back(columns[3] + " = " + std::to_string(e.minstatus)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.motd) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.tribute)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.motd_setter) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.channel) + "'"); + v.push_back(columns[8] + " = '" + Strings::Escape(e.url) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - guilds_entry.id + e.id ) ); @@ -212,69 +212,69 @@ public: static Guilds InsertOne( Database& db, - Guilds guilds_entry + Guilds e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(guilds_entry.id)); - insert_values.push_back("'" + EscapeString(guilds_entry.name) + "'"); - insert_values.push_back(std::to_string(guilds_entry.leader)); - insert_values.push_back(std::to_string(guilds_entry.minstatus)); - insert_values.push_back("'" + EscapeString(guilds_entry.motd) + "'"); - insert_values.push_back(std::to_string(guilds_entry.tribute)); - insert_values.push_back("'" + EscapeString(guilds_entry.motd_setter) + "'"); - insert_values.push_back("'" + EscapeString(guilds_entry.channel) + "'"); - insert_values.push_back("'" + EscapeString(guilds_entry.url) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.leader)); + v.push_back(std::to_string(e.minstatus)); + v.push_back("'" + Strings::Escape(e.motd) + "'"); + v.push_back(std::to_string(e.tribute)); + v.push_back("'" + Strings::Escape(e.motd_setter) + "'"); + v.push_back("'" + Strings::Escape(e.channel) + "'"); + v.push_back("'" + Strings::Escape(e.url) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - guilds_entry.id = results.LastInsertedID(); - return guilds_entry; + e.id = results.LastInsertedID(); + return e; } - guilds_entry = NewEntity(); + e = NewEntity(); - return guilds_entry; + return e; } static int InsertMany( Database& db, - std::vector guilds_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &guilds_entry: guilds_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(guilds_entry.id)); - insert_values.push_back("'" + EscapeString(guilds_entry.name) + "'"); - insert_values.push_back(std::to_string(guilds_entry.leader)); - insert_values.push_back(std::to_string(guilds_entry.minstatus)); - insert_values.push_back("'" + EscapeString(guilds_entry.motd) + "'"); - insert_values.push_back(std::to_string(guilds_entry.tribute)); - insert_values.push_back("'" + EscapeString(guilds_entry.motd_setter) + "'"); - insert_values.push_back("'" + EscapeString(guilds_entry.channel) + "'"); - insert_values.push_back("'" + EscapeString(guilds_entry.url) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.leader)); + v.push_back(std::to_string(e.minstatus)); + v.push_back("'" + Strings::Escape(e.motd) + "'"); + v.push_back(std::to_string(e.tribute)); + v.push_back("'" + Strings::Escape(e.motd_setter) + "'"); + v.push_back("'" + Strings::Escape(e.channel) + "'"); + v.push_back("'" + Strings::Escape(e.url) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -295,25 +295,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Guilds entry{}; + Guilds e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.leader = atoi(row[2]); - entry.minstatus = atoi(row[3]); - entry.motd = row[4] ? row[4] : ""; - entry.tribute = atoi(row[5]); - entry.motd_setter = row[6] ? row[6] : ""; - entry.channel = row[7] ? row[7] : ""; - entry.url = row[8] ? row[8] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.leader = static_cast(atoi(row[2])); + e.minstatus = static_cast(atoi(row[3])); + e.motd = row[4] ? row[4] : ""; + e.tribute = static_cast(strtoul(row[5], nullptr, 10)); + e.motd_setter = row[6] ? row[6] : ""; + e.channel = row[7] ? row[7] : ""; + e.url = row[8] ? row[8] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -328,25 +328,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Guilds entry{}; + Guilds e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.leader = atoi(row[2]); - entry.minstatus = atoi(row[3]); - entry.motd = row[4] ? row[4] : ""; - entry.tribute = atoi(row[5]); - entry.motd_setter = row[6] ? row[6] : ""; - entry.channel = row[7] ? row[7] : ""; - entry.url = row[8] ? row[8] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.leader = static_cast(atoi(row[2])); + e.minstatus = static_cast(atoi(row[3])); + e.motd = row[4] ? row[4] : ""; + e.tribute = static_cast(strtoul(row[5], nullptr, 10)); + e.motd_setter = row[6] ? row[6] : ""; + e.channel = row[7] ? row[7] : ""; + e.url = row[8] ? row[8] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -371,6 +371,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_GUILDS_REPOSITORY_H diff --git a/common/repositories/base/base_hackers_repository.h b/common/repositories/base/base_hackers_repository.h index d8f01dced..329c370d8 100644 --- a/common/repositories/base/base_hackers_repository.h +++ b/common/repositories/base/base_hackers_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_HACKERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseHackersRepository { public: struct Hackers { - int id; + int32_t id; std::string account; std::string name; std::string hacked; @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static Hackers NewEntity() { - Hackers entry{}; + Hackers e{}; - entry.id = 0; - entry.account = ""; - entry.name = ""; - entry.hacked = ""; - entry.zone = ""; - entry.date = std::time(nullptr); + e.id = 0; + e.account = ""; + e.name = ""; + e.hacked = ""; + e.zone = ""; + e.date = std::time(nullptr); - return entry; + return e; } - static Hackers GetHackersEntry( + static Hackers GetHackers( const std::vector &hackerss, int hackers_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Hackers entry{}; + Hackers e{}; - entry.id = atoi(row[0]); - entry.account = row[1] ? row[1] : ""; - entry.name = row[2] ? row[2] : ""; - entry.hacked = row[3] ? row[3] : ""; - entry.zone = row[4] ? row[4] : ""; - entry.date = row[5] ? row[5] : ""; + e.id = static_cast(atoi(row[0])); + e.account = row[1] ? row[1] : ""; + e.name = row[2] ? row[2] : ""; + e.hacked = row[3] ? row[3] : ""; + e.zone = row[4] ? row[4] : ""; + e.date = row[5] ? row[5] : ""; - return entry; + return e; } return NewEntity(); @@ -166,26 +166,26 @@ public: static int UpdateOne( Database& db, - Hackers hackers_entry + const Hackers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(hackers_entry.account) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(hackers_entry.name) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(hackers_entry.hacked) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(hackers_entry.zone) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(hackers_entry.date) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.account) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.hacked) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.date) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - hackers_entry.id + e.id ) ); @@ -194,63 +194,63 @@ public: static Hackers InsertOne( Database& db, - Hackers hackers_entry + Hackers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(hackers_entry.id)); - insert_values.push_back("'" + EscapeString(hackers_entry.account) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.hacked) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.zone) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.date) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.account) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.hacked) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back("'" + Strings::Escape(e.date) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - hackers_entry.id = results.LastInsertedID(); - return hackers_entry; + e.id = results.LastInsertedID(); + return e; } - hackers_entry = NewEntity(); + e = NewEntity(); - return hackers_entry; + return e; } static int InsertMany( Database& db, - std::vector hackers_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &hackers_entry: hackers_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(hackers_entry.id)); - insert_values.push_back("'" + EscapeString(hackers_entry.account) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.hacked) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.zone) + "'"); - insert_values.push_back("'" + EscapeString(hackers_entry.date) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.account) + "'"); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.hacked) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back("'" + Strings::Escape(e.date) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -271,22 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Hackers entry{}; + Hackers e{}; - entry.id = atoi(row[0]); - entry.account = row[1] ? row[1] : ""; - entry.name = row[2] ? row[2] : ""; - entry.hacked = row[3] ? row[3] : ""; - entry.zone = row[4] ? row[4] : ""; - entry.date = row[5] ? row[5] : ""; + e.id = static_cast(atoi(row[0])); + e.account = row[1] ? row[1] : ""; + e.name = row[2] ? row[2] : ""; + e.hacked = row[3] ? row[3] : ""; + e.zone = row[4] ? row[4] : ""; + e.date = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -301,22 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Hackers entry{}; + Hackers e{}; - entry.id = atoi(row[0]); - entry.account = row[1] ? row[1] : ""; - entry.name = row[2] ? row[2] : ""; - entry.hacked = row[3] ? row[3] : ""; - entry.zone = row[4] ? row[4] : ""; - entry.date = row[5] ? row[5] : ""; + e.id = static_cast(atoi(row[0])); + e.account = row[1] ? row[1] : ""; + e.name = row[2] ? row[2] : ""; + e.hacked = row[3] ? row[3] : ""; + e.zone = row[4] ? row[4] : ""; + e.date = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -341,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_HACKERS_REPOSITORY_H diff --git a/common/repositories/base/base_horses_repository.h b/common/repositories/base/base_horses_repository.h index 5fdb0234c..a881720de 100644 --- a/common/repositories/base/base_horses_repository.h +++ b/common/repositories/base/base_horses_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_HORSES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseHorsesRepository { public: struct Horses { - int id; + int32_t id; std::string filename; - int race; - int gender; - int texture; + int16_t race; + int8_t gender; + int8_t texture; float mountspeed; std::string notes; }; @@ -61,12 +61,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -94,20 +94,20 @@ public: static Horses NewEntity() { - Horses entry{}; + Horses e{}; - entry.id = 0; - entry.filename = ""; - entry.race = 216; - entry.gender = 0; - entry.texture = 0; - entry.mountspeed = 0.75; - entry.notes = "Notes"; + e.id = 0; + e.filename = ""; + e.race = 216; + e.gender = 0; + e.texture = 0; + e.mountspeed = 0.75; + e.notes = "Notes"; - return entry; + return e; } - static Horses GetHorsesEntry( + static Horses GetHorses( const std::vector &horsess, int horses_id ) @@ -136,17 +136,17 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Horses entry{}; + Horses e{}; - entry.id = atoi(row[0]); - entry.filename = row[1] ? row[1] : ""; - entry.race = atoi(row[2]); - entry.gender = atoi(row[3]); - entry.texture = atoi(row[4]); - entry.mountspeed = static_cast(atof(row[5])); - entry.notes = row[6] ? row[6] : ""; + e.id = static_cast(atoi(row[0])); + e.filename = row[1] ? row[1] : ""; + e.race = static_cast(atoi(row[2])); + e.gender = static_cast(atoi(row[3])); + e.texture = static_cast(atoi(row[4])); + e.mountspeed = strtof(row[5], nullptr); + e.notes = row[6] ? row[6] : ""; - return entry; + return e; } return NewEntity(); @@ -171,27 +171,27 @@ public: static int UpdateOne( Database& db, - Horses horses_entry + const Horses &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(horses_entry.filename) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(horses_entry.race)); - update_values.push_back(columns[3] + " = " + std::to_string(horses_entry.gender)); - update_values.push_back(columns[4] + " = " + std::to_string(horses_entry.texture)); - update_values.push_back(columns[5] + " = " + std::to_string(horses_entry.mountspeed)); - update_values.push_back(columns[6] + " = '" + EscapeString(horses_entry.notes) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.filename) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.race)); + v.push_back(columns[3] + " = " + std::to_string(e.gender)); + v.push_back(columns[4] + " = " + std::to_string(e.texture)); + v.push_back(columns[5] + " = " + std::to_string(e.mountspeed)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.notes) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - horses_entry.id + e.id ) ); @@ -200,65 +200,65 @@ public: static Horses InsertOne( Database& db, - Horses horses_entry + Horses e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(horses_entry.id)); - insert_values.push_back("'" + EscapeString(horses_entry.filename) + "'"); - insert_values.push_back(std::to_string(horses_entry.race)); - insert_values.push_back(std::to_string(horses_entry.gender)); - insert_values.push_back(std::to_string(horses_entry.texture)); - insert_values.push_back(std::to_string(horses_entry.mountspeed)); - insert_values.push_back("'" + EscapeString(horses_entry.notes) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.filename) + "'"); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.mountspeed)); + v.push_back("'" + Strings::Escape(e.notes) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - horses_entry.id = results.LastInsertedID(); - return horses_entry; + e.id = results.LastInsertedID(); + return e; } - horses_entry = NewEntity(); + e = NewEntity(); - return horses_entry; + return e; } static int InsertMany( Database& db, - std::vector horses_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &horses_entry: horses_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(horses_entry.id)); - insert_values.push_back("'" + EscapeString(horses_entry.filename) + "'"); - insert_values.push_back(std::to_string(horses_entry.race)); - insert_values.push_back(std::to_string(horses_entry.gender)); - insert_values.push_back(std::to_string(horses_entry.texture)); - insert_values.push_back(std::to_string(horses_entry.mountspeed)); - insert_values.push_back("'" + EscapeString(horses_entry.notes) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.filename) + "'"); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.mountspeed)); + v.push_back("'" + Strings::Escape(e.notes) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -279,23 +279,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Horses entry{}; + Horses e{}; - entry.id = atoi(row[0]); - entry.filename = row[1] ? row[1] : ""; - entry.race = atoi(row[2]); - entry.gender = atoi(row[3]); - entry.texture = atoi(row[4]); - entry.mountspeed = static_cast(atof(row[5])); - entry.notes = row[6] ? row[6] : ""; + e.id = static_cast(atoi(row[0])); + e.filename = row[1] ? row[1] : ""; + e.race = static_cast(atoi(row[2])); + e.gender = static_cast(atoi(row[3])); + e.texture = static_cast(atoi(row[4])); + e.mountspeed = strtof(row[5], nullptr); + e.notes = row[6] ? row[6] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -310,23 +310,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Horses entry{}; + Horses e{}; - entry.id = atoi(row[0]); - entry.filename = row[1] ? row[1] : ""; - entry.race = atoi(row[2]); - entry.gender = atoi(row[3]); - entry.texture = atoi(row[4]); - entry.mountspeed = static_cast(atof(row[5])); - entry.notes = row[6] ? row[6] : ""; + e.id = static_cast(atoi(row[0])); + e.filename = row[1] ? row[1] : ""; + e.race = static_cast(atoi(row[2])); + e.gender = static_cast(atoi(row[3])); + e.texture = static_cast(atoi(row[4])); + e.mountspeed = strtof(row[5], nullptr); + e.notes = row[6] ? row[6] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -351,6 +351,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_HORSES_REPOSITORY_H diff --git a/common/repositories/base/base_instance_list_player_repository.h b/common/repositories/base/base_instance_list_player_repository.h index 4ef1123ec..85e6fe012 100644 --- a/common/repositories/base/base_instance_list_player_repository.h +++ b/common/repositories/base/base_instance_list_player_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_INSTANCE_LIST_PLAYER_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseInstanceListPlayerRepository { public: struct InstanceListPlayer { - int id; - int charid; + uint32_t id; + uint32_t charid; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static InstanceListPlayer NewEntity() { - InstanceListPlayer entry{}; + InstanceListPlayer e{}; - entry.id = 0; - entry.charid = 0; + e.id = 0; + e.charid = 0; - return entry; + return e; } - static InstanceListPlayer GetInstanceListPlayerEntry( + static InstanceListPlayer GetInstanceListPlayer( const std::vector &instance_list_players, int instance_list_player_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - InstanceListPlayer entry{}; + InstanceListPlayer e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - InstanceListPlayer instance_list_player_entry + const InstanceListPlayer &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(instance_list_player_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(instance_list_player_entry.charid)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.charid)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - instance_list_player_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static InstanceListPlayer InsertOne( Database& db, - InstanceListPlayer instance_list_player_entry + InstanceListPlayer e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(instance_list_player_entry.id)); - insert_values.push_back(std::to_string(instance_list_player_entry.charid)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.charid)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - instance_list_player_entry.id = results.LastInsertedID(); - return instance_list_player_entry; + e.id = results.LastInsertedID(); + return e; } - instance_list_player_entry = NewEntity(); + e = NewEntity(); - return instance_list_player_entry; + return e; } static int InsertMany( Database& db, - std::vector instance_list_player_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &instance_list_player_entry: instance_list_player_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(instance_list_player_entry.id)); - insert_values.push_back(std::to_string(instance_list_player_entry.charid)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.charid)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - InstanceListPlayer entry{}; + InstanceListPlayer e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - InstanceListPlayer entry{}; + InstanceListPlayer e{}; - entry.id = atoi(row[0]); - entry.charid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_INSTANCE_LIST_PLAYER_REPOSITORY_H diff --git a/common/repositories/base/base_instance_list_repository.h b/common/repositories/base/base_instance_list_repository.h index 9b23c50e6..dd82569ec 100644 --- a/common/repositories/base/base_instance_list_repository.h +++ b/common/repositories/base/base_instance_list_repository.h @@ -13,19 +13,19 @@ #define EQEMU_BASE_INSTANCE_LIST_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseInstanceListRepository { public: struct InstanceList { - int id; - int zone; - int version; - int is_global; - int start_time; - int duration; - int never_expires; + int32_t id; + uint32_t zone; + uint8_t version; + uint8_t is_global; + uint32_t start_time; + uint32_t duration; + uint8_t never_expires; }; static std::string PrimaryKey() @@ -61,12 +61,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -94,20 +94,20 @@ public: static InstanceList NewEntity() { - InstanceList entry{}; + InstanceList e{}; - entry.id = 0; - entry.zone = 0; - entry.version = 0; - entry.is_global = 0; - entry.start_time = 0; - entry.duration = 0; - entry.never_expires = 0; + e.id = 0; + e.zone = 0; + e.version = 0; + e.is_global = 0; + e.start_time = 0; + e.duration = 0; + e.never_expires = 0; - return entry; + return e; } - static InstanceList GetInstanceListEntry( + static InstanceList GetInstanceList( const std::vector &instance_lists, int instance_list_id ) @@ -136,17 +136,17 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - InstanceList entry{}; + InstanceList e{}; - entry.id = atoi(row[0]); - entry.zone = atoi(row[1]); - entry.version = atoi(row[2]); - entry.is_global = atoi(row[3]); - entry.start_time = atoi(row[4]); - entry.duration = atoi(row[5]); - entry.never_expires = atoi(row[6]); + e.id = static_cast(atoi(row[0])); + e.zone = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(strtoul(row[2], nullptr, 10)); + e.is_global = static_cast(strtoul(row[3], nullptr, 10)); + e.start_time = static_cast(strtoul(row[4], nullptr, 10)); + e.duration = static_cast(strtoul(row[5], nullptr, 10)); + e.never_expires = static_cast(strtoul(row[6], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -171,27 +171,27 @@ public: static int UpdateOne( Database& db, - InstanceList instance_list_entry + const InstanceList &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(instance_list_entry.zone)); - update_values.push_back(columns[2] + " = " + std::to_string(instance_list_entry.version)); - update_values.push_back(columns[3] + " = " + std::to_string(instance_list_entry.is_global)); - update_values.push_back(columns[4] + " = " + std::to_string(instance_list_entry.start_time)); - update_values.push_back(columns[5] + " = " + std::to_string(instance_list_entry.duration)); - update_values.push_back(columns[6] + " = " + std::to_string(instance_list_entry.never_expires)); + v.push_back(columns[1] + " = " + std::to_string(e.zone)); + v.push_back(columns[2] + " = " + std::to_string(e.version)); + v.push_back(columns[3] + " = " + std::to_string(e.is_global)); + v.push_back(columns[4] + " = " + std::to_string(e.start_time)); + v.push_back(columns[5] + " = " + std::to_string(e.duration)); + v.push_back(columns[6] + " = " + std::to_string(e.never_expires)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - instance_list_entry.id + e.id ) ); @@ -200,65 +200,65 @@ public: static InstanceList InsertOne( Database& db, - InstanceList instance_list_entry + InstanceList e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(instance_list_entry.id)); - insert_values.push_back(std::to_string(instance_list_entry.zone)); - insert_values.push_back(std::to_string(instance_list_entry.version)); - insert_values.push_back(std::to_string(instance_list_entry.is_global)); - insert_values.push_back(std::to_string(instance_list_entry.start_time)); - insert_values.push_back(std::to_string(instance_list_entry.duration)); - insert_values.push_back(std::to_string(instance_list_entry.never_expires)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.is_global)); + v.push_back(std::to_string(e.start_time)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.never_expires)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - instance_list_entry.id = results.LastInsertedID(); - return instance_list_entry; + e.id = results.LastInsertedID(); + return e; } - instance_list_entry = NewEntity(); + e = NewEntity(); - return instance_list_entry; + return e; } static int InsertMany( Database& db, - std::vector instance_list_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &instance_list_entry: instance_list_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(instance_list_entry.id)); - insert_values.push_back(std::to_string(instance_list_entry.zone)); - insert_values.push_back(std::to_string(instance_list_entry.version)); - insert_values.push_back(std::to_string(instance_list_entry.is_global)); - insert_values.push_back(std::to_string(instance_list_entry.start_time)); - insert_values.push_back(std::to_string(instance_list_entry.duration)); - insert_values.push_back(std::to_string(instance_list_entry.never_expires)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zone)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.is_global)); + v.push_back(std::to_string(e.start_time)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.never_expires)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -279,23 +279,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - InstanceList entry{}; + InstanceList e{}; - entry.id = atoi(row[0]); - entry.zone = atoi(row[1]); - entry.version = atoi(row[2]); - entry.is_global = atoi(row[3]); - entry.start_time = atoi(row[4]); - entry.duration = atoi(row[5]); - entry.never_expires = atoi(row[6]); + e.id = static_cast(atoi(row[0])); + e.zone = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(strtoul(row[2], nullptr, 10)); + e.is_global = static_cast(strtoul(row[3], nullptr, 10)); + e.start_time = static_cast(strtoul(row[4], nullptr, 10)); + e.duration = static_cast(strtoul(row[5], nullptr, 10)); + e.never_expires = static_cast(strtoul(row[6], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -310,23 +310,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - InstanceList entry{}; + InstanceList e{}; - entry.id = atoi(row[0]); - entry.zone = atoi(row[1]); - entry.version = atoi(row[2]); - entry.is_global = atoi(row[3]); - entry.start_time = atoi(row[4]); - entry.duration = atoi(row[5]); - entry.never_expires = atoi(row[6]); + e.id = static_cast(atoi(row[0])); + e.zone = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(strtoul(row[2], nullptr, 10)); + e.is_global = static_cast(strtoul(row[3], nullptr, 10)); + e.start_time = static_cast(strtoul(row[4], nullptr, 10)); + e.duration = static_cast(strtoul(row[5], nullptr, 10)); + e.never_expires = static_cast(strtoul(row[6], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -351,6 +351,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_INSTANCE_LIST_REPOSITORY_H diff --git a/common/repositories/base/base_inventory_repository.h b/common/repositories/base/base_inventory_repository.h index 07a4f282e..a3e0da3dd 100644 --- a/common/repositories/base/base_inventory_repository.h +++ b/common/repositories/base/base_inventory_repository.h @@ -13,28 +13,28 @@ #define EQEMU_BASE_INVENTORY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseInventoryRepository { public: struct Inventory { - int charid; - int slotid; - int itemid; - int charges; - int color; - int augslot1; - int augslot2; - int augslot3; - int augslot4; - int augslot5; - int augslot6; - int instnodrop; + uint32_t charid; + uint32_t slotid; + uint32_t itemid; + uint16_t charges; + uint32_t color; + uint32_t augslot1; + uint32_t augslot2; + uint32_t augslot3; + uint32_t augslot4; + uint32_t augslot5; + int32_t augslot6; + uint8_t instnodrop; std::string custom_data; - int ornamenticon; - int ornamentidfile; - int ornament_hero_model; + uint32_t ornamenticon; + uint32_t ornamentidfile; + int32_t ornament_hero_model; }; static std::string PrimaryKey() @@ -88,12 +88,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -121,29 +121,29 @@ public: static Inventory NewEntity() { - Inventory entry{}; + Inventory e{}; - entry.charid = 0; - entry.slotid = 0; - entry.itemid = 0; - entry.charges = 0; - entry.color = 0; - entry.augslot1 = 0; - entry.augslot2 = 0; - entry.augslot3 = 0; - entry.augslot4 = 0; - entry.augslot5 = 0; - entry.augslot6 = 0; - entry.instnodrop = 0; - entry.custom_data = ""; - entry.ornamenticon = 0; - entry.ornamentidfile = 0; - entry.ornament_hero_model = 0; + e.charid = 0; + e.slotid = 0; + e.itemid = 0; + e.charges = 0; + e.color = 0; + e.augslot1 = 0; + e.augslot2 = 0; + e.augslot3 = 0; + e.augslot4 = 0; + e.augslot5 = 0; + e.augslot6 = 0; + e.instnodrop = 0; + e.custom_data = ""; + e.ornamenticon = 0; + e.ornamentidfile = 0; + e.ornament_hero_model = 0; - return entry; + return e; } - static Inventory GetInventoryEntry( + static Inventory GetInventory( const std::vector &inventorys, int inventory_id ) @@ -172,26 +172,26 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Inventory entry{}; + Inventory e{}; - entry.charid = atoi(row[0]); - entry.slotid = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.color = atoi(row[4]); - entry.augslot1 = atoi(row[5]); - entry.augslot2 = atoi(row[6]); - entry.augslot3 = atoi(row[7]); - entry.augslot4 = atoi(row[8]); - entry.augslot5 = atoi(row[9]); - entry.augslot6 = atoi(row[10]); - entry.instnodrop = atoi(row[11]); - entry.custom_data = row[12] ? row[12] : ""; - entry.ornamenticon = atoi(row[13]); - entry.ornamentidfile = atoi(row[14]); - entry.ornament_hero_model = atoi(row[15]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.slotid = static_cast(strtoul(row[1], nullptr, 10)); + e.itemid = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.color = static_cast(strtoul(row[4], nullptr, 10)); + e.augslot1 = static_cast(strtoul(row[5], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[10])); + e.instnodrop = static_cast(strtoul(row[11], nullptr, 10)); + e.custom_data = row[12] ? row[12] : ""; + e.ornamenticon = static_cast(strtoul(row[13], nullptr, 10)); + e.ornamentidfile = static_cast(strtoul(row[14], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[15])); - return entry; + return e; } return NewEntity(); @@ -216,37 +216,37 @@ public: static int UpdateOne( Database& db, - Inventory inventory_entry + const Inventory &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(inventory_entry.charid)); - update_values.push_back(columns[1] + " = " + std::to_string(inventory_entry.slotid)); - update_values.push_back(columns[2] + " = " + std::to_string(inventory_entry.itemid)); - update_values.push_back(columns[3] + " = " + std::to_string(inventory_entry.charges)); - update_values.push_back(columns[4] + " = " + std::to_string(inventory_entry.color)); - update_values.push_back(columns[5] + " = " + std::to_string(inventory_entry.augslot1)); - update_values.push_back(columns[6] + " = " + std::to_string(inventory_entry.augslot2)); - update_values.push_back(columns[7] + " = " + std::to_string(inventory_entry.augslot3)); - update_values.push_back(columns[8] + " = " + std::to_string(inventory_entry.augslot4)); - update_values.push_back(columns[9] + " = " + std::to_string(inventory_entry.augslot5)); - update_values.push_back(columns[10] + " = " + std::to_string(inventory_entry.augslot6)); - update_values.push_back(columns[11] + " = " + std::to_string(inventory_entry.instnodrop)); - update_values.push_back(columns[12] + " = '" + EscapeString(inventory_entry.custom_data) + "'"); - update_values.push_back(columns[13] + " = " + std::to_string(inventory_entry.ornamenticon)); - update_values.push_back(columns[14] + " = " + std::to_string(inventory_entry.ornamentidfile)); - update_values.push_back(columns[15] + " = " + std::to_string(inventory_entry.ornament_hero_model)); + v.push_back(columns[0] + " = " + std::to_string(e.charid)); + v.push_back(columns[1] + " = " + std::to_string(e.slotid)); + v.push_back(columns[2] + " = " + std::to_string(e.itemid)); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); + v.push_back(columns[4] + " = " + std::to_string(e.color)); + v.push_back(columns[5] + " = " + std::to_string(e.augslot1)); + v.push_back(columns[6] + " = " + std::to_string(e.augslot2)); + v.push_back(columns[7] + " = " + std::to_string(e.augslot3)); + v.push_back(columns[8] + " = " + std::to_string(e.augslot4)); + v.push_back(columns[9] + " = " + std::to_string(e.augslot5)); + v.push_back(columns[10] + " = " + std::to_string(e.augslot6)); + v.push_back(columns[11] + " = " + std::to_string(e.instnodrop)); + v.push_back(columns[12] + " = '" + Strings::Escape(e.custom_data) + "'"); + v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon)); + v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile)); + v.push_back(columns[15] + " = " + std::to_string(e.ornament_hero_model)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - inventory_entry.charid + e.charid ) ); @@ -255,83 +255,83 @@ public: static Inventory InsertOne( Database& db, - Inventory inventory_entry + Inventory e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(inventory_entry.charid)); - insert_values.push_back(std::to_string(inventory_entry.slotid)); - insert_values.push_back(std::to_string(inventory_entry.itemid)); - insert_values.push_back(std::to_string(inventory_entry.charges)); - insert_values.push_back(std::to_string(inventory_entry.color)); - insert_values.push_back(std::to_string(inventory_entry.augslot1)); - insert_values.push_back(std::to_string(inventory_entry.augslot2)); - insert_values.push_back(std::to_string(inventory_entry.augslot3)); - insert_values.push_back(std::to_string(inventory_entry.augslot4)); - insert_values.push_back(std::to_string(inventory_entry.augslot5)); - insert_values.push_back(std::to_string(inventory_entry.augslot6)); - insert_values.push_back(std::to_string(inventory_entry.instnodrop)); - insert_values.push_back("'" + EscapeString(inventory_entry.custom_data) + "'"); - insert_values.push_back(std::to_string(inventory_entry.ornamenticon)); - insert_values.push_back(std::to_string(inventory_entry.ornamentidfile)); - insert_values.push_back(std::to_string(inventory_entry.ornament_hero_model)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.slotid)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augslot1)); + v.push_back(std::to_string(e.augslot2)); + v.push_back(std::to_string(e.augslot3)); + v.push_back(std::to_string(e.augslot4)); + v.push_back(std::to_string(e.augslot5)); + v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.instnodrop)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornamenticon)); + v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_hero_model)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - inventory_entry.charid = results.LastInsertedID(); - return inventory_entry; + e.charid = results.LastInsertedID(); + return e; } - inventory_entry = NewEntity(); + e = NewEntity(); - return inventory_entry; + return e; } static int InsertMany( Database& db, - std::vector inventory_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &inventory_entry: inventory_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(inventory_entry.charid)); - insert_values.push_back(std::to_string(inventory_entry.slotid)); - insert_values.push_back(std::to_string(inventory_entry.itemid)); - insert_values.push_back(std::to_string(inventory_entry.charges)); - insert_values.push_back(std::to_string(inventory_entry.color)); - insert_values.push_back(std::to_string(inventory_entry.augslot1)); - insert_values.push_back(std::to_string(inventory_entry.augslot2)); - insert_values.push_back(std::to_string(inventory_entry.augslot3)); - insert_values.push_back(std::to_string(inventory_entry.augslot4)); - insert_values.push_back(std::to_string(inventory_entry.augslot5)); - insert_values.push_back(std::to_string(inventory_entry.augslot6)); - insert_values.push_back(std::to_string(inventory_entry.instnodrop)); - insert_values.push_back("'" + EscapeString(inventory_entry.custom_data) + "'"); - insert_values.push_back(std::to_string(inventory_entry.ornamenticon)); - insert_values.push_back(std::to_string(inventory_entry.ornamentidfile)); - insert_values.push_back(std::to_string(inventory_entry.ornament_hero_model)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.slotid)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augslot1)); + v.push_back(std::to_string(e.augslot2)); + v.push_back(std::to_string(e.augslot3)); + v.push_back(std::to_string(e.augslot4)); + v.push_back(std::to_string(e.augslot5)); + v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.instnodrop)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornamenticon)); + v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_hero_model)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -352,32 +352,32 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Inventory entry{}; + Inventory e{}; - entry.charid = atoi(row[0]); - entry.slotid = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.color = atoi(row[4]); - entry.augslot1 = atoi(row[5]); - entry.augslot2 = atoi(row[6]); - entry.augslot3 = atoi(row[7]); - entry.augslot4 = atoi(row[8]); - entry.augslot5 = atoi(row[9]); - entry.augslot6 = atoi(row[10]); - entry.instnodrop = atoi(row[11]); - entry.custom_data = row[12] ? row[12] : ""; - entry.ornamenticon = atoi(row[13]); - entry.ornamentidfile = atoi(row[14]); - entry.ornament_hero_model = atoi(row[15]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.slotid = static_cast(strtoul(row[1], nullptr, 10)); + e.itemid = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.color = static_cast(strtoul(row[4], nullptr, 10)); + e.augslot1 = static_cast(strtoul(row[5], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[10])); + e.instnodrop = static_cast(strtoul(row[11], nullptr, 10)); + e.custom_data = row[12] ? row[12] : ""; + e.ornamenticon = static_cast(strtoul(row[13], nullptr, 10)); + e.ornamentidfile = static_cast(strtoul(row[14], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[15])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -392,32 +392,32 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Inventory entry{}; + Inventory e{}; - entry.charid = atoi(row[0]); - entry.slotid = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.color = atoi(row[4]); - entry.augslot1 = atoi(row[5]); - entry.augslot2 = atoi(row[6]); - entry.augslot3 = atoi(row[7]); - entry.augslot4 = atoi(row[8]); - entry.augslot5 = atoi(row[9]); - entry.augslot6 = atoi(row[10]); - entry.instnodrop = atoi(row[11]); - entry.custom_data = row[12] ? row[12] : ""; - entry.ornamenticon = atoi(row[13]); - entry.ornamentidfile = atoi(row[14]); - entry.ornament_hero_model = atoi(row[15]); + e.charid = static_cast(strtoul(row[0], nullptr, 10)); + e.slotid = static_cast(strtoul(row[1], nullptr, 10)); + e.itemid = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.color = static_cast(strtoul(row[4], nullptr, 10)); + e.augslot1 = static_cast(strtoul(row[5], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[10])); + e.instnodrop = static_cast(strtoul(row[11], nullptr, 10)); + e.custom_data = row[12] ? row[12] : ""; + e.ornamenticon = static_cast(strtoul(row[13], nullptr, 10)); + e.ornamentidfile = static_cast(strtoul(row[14], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[15])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -442,6 +442,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_INVENTORY_REPOSITORY_H diff --git a/common/repositories/base/base_inventory_snapshots_repository.h b/common/repositories/base/base_inventory_snapshots_repository.h index 58e2685ea..2ae90332f 100644 --- a/common/repositories/base/base_inventory_snapshots_repository.h +++ b/common/repositories/base/base_inventory_snapshots_repository.h @@ -13,29 +13,29 @@ #define EQEMU_BASE_INVENTORY_SNAPSHOTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseInventorySnapshotsRepository { public: struct InventorySnapshots { - int time_index; - int charid; - int slotid; - int itemid; - int charges; - int color; - int augslot1; - int augslot2; - int augslot3; - int augslot4; - int augslot5; - int augslot6; - int instnodrop; + uint32_t time_index; + uint32_t charid; + uint32_t slotid; + uint32_t itemid; + uint16_t charges; + uint32_t color; + uint32_t augslot1; + uint32_t augslot2; + uint32_t augslot3; + uint32_t augslot4; + uint32_t augslot5; + int32_t augslot6; + uint8_t instnodrop; std::string custom_data; - int ornamenticon; - int ornamentidfile; - int ornament_hero_model; + uint32_t ornamenticon; + uint32_t ornamentidfile; + int32_t ornament_hero_model; }; static std::string PrimaryKey() @@ -91,12 +91,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -124,30 +124,30 @@ public: static InventorySnapshots NewEntity() { - InventorySnapshots entry{}; + InventorySnapshots e{}; - entry.time_index = 0; - entry.charid = 0; - entry.slotid = 0; - entry.itemid = 0; - entry.charges = 0; - entry.color = 0; - entry.augslot1 = 0; - entry.augslot2 = 0; - entry.augslot3 = 0; - entry.augslot4 = 0; - entry.augslot5 = 0; - entry.augslot6 = 0; - entry.instnodrop = 0; - entry.custom_data = ""; - entry.ornamenticon = 0; - entry.ornamentidfile = 0; - entry.ornament_hero_model = 0; + e.time_index = 0; + e.charid = 0; + e.slotid = 0; + e.itemid = 0; + e.charges = 0; + e.color = 0; + e.augslot1 = 0; + e.augslot2 = 0; + e.augslot3 = 0; + e.augslot4 = 0; + e.augslot5 = 0; + e.augslot6 = 0; + e.instnodrop = 0; + e.custom_data = ""; + e.ornamenticon = 0; + e.ornamentidfile = 0; + e.ornament_hero_model = 0; - return entry; + return e; } - static InventorySnapshots GetInventorySnapshotsEntry( + static InventorySnapshots GetInventorySnapshots( const std::vector &inventory_snapshotss, int inventory_snapshots_id ) @@ -176,27 +176,27 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - InventorySnapshots entry{}; + InventorySnapshots e{}; - entry.time_index = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.slotid = atoi(row[2]); - entry.itemid = atoi(row[3]); - entry.charges = atoi(row[4]); - entry.color = atoi(row[5]); - entry.augslot1 = atoi(row[6]); - entry.augslot2 = atoi(row[7]); - entry.augslot3 = atoi(row[8]); - entry.augslot4 = atoi(row[9]); - entry.augslot5 = atoi(row[10]); - entry.augslot6 = atoi(row[11]); - entry.instnodrop = atoi(row[12]); - entry.custom_data = row[13] ? row[13] : ""; - entry.ornamenticon = atoi(row[14]); - entry.ornamentidfile = atoi(row[15]); - entry.ornament_hero_model = atoi(row[16]); + e.time_index = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.slotid = static_cast(strtoul(row[2], nullptr, 10)); + e.itemid = static_cast(strtoul(row[3], nullptr, 10)); + e.charges = static_cast(strtoul(row[4], nullptr, 10)); + e.color = static_cast(strtoul(row[5], nullptr, 10)); + e.augslot1 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[10], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[11])); + e.instnodrop = static_cast(strtoul(row[12], nullptr, 10)); + e.custom_data = row[13] ? row[13] : ""; + e.ornamenticon = static_cast(strtoul(row[14], nullptr, 10)); + e.ornamentidfile = static_cast(strtoul(row[15], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[16])); - return entry; + return e; } return NewEntity(); @@ -221,38 +221,38 @@ public: static int UpdateOne( Database& db, - InventorySnapshots inventory_snapshots_entry + const InventorySnapshots &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(inventory_snapshots_entry.time_index)); - update_values.push_back(columns[1] + " = " + std::to_string(inventory_snapshots_entry.charid)); - update_values.push_back(columns[2] + " = " + std::to_string(inventory_snapshots_entry.slotid)); - update_values.push_back(columns[3] + " = " + std::to_string(inventory_snapshots_entry.itemid)); - update_values.push_back(columns[4] + " = " + std::to_string(inventory_snapshots_entry.charges)); - update_values.push_back(columns[5] + " = " + std::to_string(inventory_snapshots_entry.color)); - update_values.push_back(columns[6] + " = " + std::to_string(inventory_snapshots_entry.augslot1)); - update_values.push_back(columns[7] + " = " + std::to_string(inventory_snapshots_entry.augslot2)); - update_values.push_back(columns[8] + " = " + std::to_string(inventory_snapshots_entry.augslot3)); - update_values.push_back(columns[9] + " = " + std::to_string(inventory_snapshots_entry.augslot4)); - update_values.push_back(columns[10] + " = " + std::to_string(inventory_snapshots_entry.augslot5)); - update_values.push_back(columns[11] + " = " + std::to_string(inventory_snapshots_entry.augslot6)); - update_values.push_back(columns[12] + " = " + std::to_string(inventory_snapshots_entry.instnodrop)); - update_values.push_back(columns[13] + " = '" + EscapeString(inventory_snapshots_entry.custom_data) + "'"); - update_values.push_back(columns[14] + " = " + std::to_string(inventory_snapshots_entry.ornamenticon)); - update_values.push_back(columns[15] + " = " + std::to_string(inventory_snapshots_entry.ornamentidfile)); - update_values.push_back(columns[16] + " = " + std::to_string(inventory_snapshots_entry.ornament_hero_model)); + v.push_back(columns[0] + " = " + std::to_string(e.time_index)); + v.push_back(columns[1] + " = " + std::to_string(e.charid)); + v.push_back(columns[2] + " = " + std::to_string(e.slotid)); + v.push_back(columns[3] + " = " + std::to_string(e.itemid)); + v.push_back(columns[4] + " = " + std::to_string(e.charges)); + v.push_back(columns[5] + " = " + std::to_string(e.color)); + v.push_back(columns[6] + " = " + std::to_string(e.augslot1)); + v.push_back(columns[7] + " = " + std::to_string(e.augslot2)); + v.push_back(columns[8] + " = " + std::to_string(e.augslot3)); + v.push_back(columns[9] + " = " + std::to_string(e.augslot4)); + v.push_back(columns[10] + " = " + std::to_string(e.augslot5)); + v.push_back(columns[11] + " = " + std::to_string(e.augslot6)); + v.push_back(columns[12] + " = " + std::to_string(e.instnodrop)); + v.push_back(columns[13] + " = '" + Strings::Escape(e.custom_data) + "'"); + v.push_back(columns[14] + " = " + std::to_string(e.ornamenticon)); + v.push_back(columns[15] + " = " + std::to_string(e.ornamentidfile)); + v.push_back(columns[16] + " = " + std::to_string(e.ornament_hero_model)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - inventory_snapshots_entry.time_index + e.time_index ) ); @@ -261,85 +261,85 @@ public: static InventorySnapshots InsertOne( Database& db, - InventorySnapshots inventory_snapshots_entry + InventorySnapshots e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(inventory_snapshots_entry.time_index)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.charid)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.slotid)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.itemid)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.charges)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.color)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot1)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot2)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot3)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot4)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot5)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot6)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.instnodrop)); - insert_values.push_back("'" + EscapeString(inventory_snapshots_entry.custom_data) + "'"); - insert_values.push_back(std::to_string(inventory_snapshots_entry.ornamenticon)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.ornamentidfile)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.ornament_hero_model)); + v.push_back(std::to_string(e.time_index)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.slotid)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augslot1)); + v.push_back(std::to_string(e.augslot2)); + v.push_back(std::to_string(e.augslot3)); + v.push_back(std::to_string(e.augslot4)); + v.push_back(std::to_string(e.augslot5)); + v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.instnodrop)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornamenticon)); + v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_hero_model)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - inventory_snapshots_entry.time_index = results.LastInsertedID(); - return inventory_snapshots_entry; + e.time_index = results.LastInsertedID(); + return e; } - inventory_snapshots_entry = NewEntity(); + e = NewEntity(); - return inventory_snapshots_entry; + return e; } static int InsertMany( Database& db, - std::vector inventory_snapshots_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &inventory_snapshots_entry: inventory_snapshots_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(inventory_snapshots_entry.time_index)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.charid)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.slotid)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.itemid)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.charges)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.color)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot1)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot2)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot3)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot4)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot5)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.augslot6)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.instnodrop)); - insert_values.push_back("'" + EscapeString(inventory_snapshots_entry.custom_data) + "'"); - insert_values.push_back(std::to_string(inventory_snapshots_entry.ornamenticon)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.ornamentidfile)); - insert_values.push_back(std::to_string(inventory_snapshots_entry.ornament_hero_model)); + v.push_back(std::to_string(e.time_index)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.slotid)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augslot1)); + v.push_back(std::to_string(e.augslot2)); + v.push_back(std::to_string(e.augslot3)); + v.push_back(std::to_string(e.augslot4)); + v.push_back(std::to_string(e.augslot5)); + v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.instnodrop)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornamenticon)); + v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_hero_model)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -360,33 +360,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - InventorySnapshots entry{}; + InventorySnapshots e{}; - entry.time_index = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.slotid = atoi(row[2]); - entry.itemid = atoi(row[3]); - entry.charges = atoi(row[4]); - entry.color = atoi(row[5]); - entry.augslot1 = atoi(row[6]); - entry.augslot2 = atoi(row[7]); - entry.augslot3 = atoi(row[8]); - entry.augslot4 = atoi(row[9]); - entry.augslot5 = atoi(row[10]); - entry.augslot6 = atoi(row[11]); - entry.instnodrop = atoi(row[12]); - entry.custom_data = row[13] ? row[13] : ""; - entry.ornamenticon = atoi(row[14]); - entry.ornamentidfile = atoi(row[15]); - entry.ornament_hero_model = atoi(row[16]); + e.time_index = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.slotid = static_cast(strtoul(row[2], nullptr, 10)); + e.itemid = static_cast(strtoul(row[3], nullptr, 10)); + e.charges = static_cast(strtoul(row[4], nullptr, 10)); + e.color = static_cast(strtoul(row[5], nullptr, 10)); + e.augslot1 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[10], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[11])); + e.instnodrop = static_cast(strtoul(row[12], nullptr, 10)); + e.custom_data = row[13] ? row[13] : ""; + e.ornamenticon = static_cast(strtoul(row[14], nullptr, 10)); + e.ornamentidfile = static_cast(strtoul(row[15], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[16])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -401,33 +401,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - InventorySnapshots entry{}; + InventorySnapshots e{}; - entry.time_index = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.slotid = atoi(row[2]); - entry.itemid = atoi(row[3]); - entry.charges = atoi(row[4]); - entry.color = atoi(row[5]); - entry.augslot1 = atoi(row[6]); - entry.augslot2 = atoi(row[7]); - entry.augslot3 = atoi(row[8]); - entry.augslot4 = atoi(row[9]); - entry.augslot5 = atoi(row[10]); - entry.augslot6 = atoi(row[11]); - entry.instnodrop = atoi(row[12]); - entry.custom_data = row[13] ? row[13] : ""; - entry.ornamenticon = atoi(row[14]); - entry.ornamentidfile = atoi(row[15]); - entry.ornament_hero_model = atoi(row[16]); + e.time_index = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.slotid = static_cast(strtoul(row[2], nullptr, 10)); + e.itemid = static_cast(strtoul(row[3], nullptr, 10)); + e.charges = static_cast(strtoul(row[4], nullptr, 10)); + e.color = static_cast(strtoul(row[5], nullptr, 10)); + e.augslot1 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[10], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[11])); + e.instnodrop = static_cast(strtoul(row[12], nullptr, 10)); + e.custom_data = row[13] ? row[13] : ""; + e.ornamenticon = static_cast(strtoul(row[14], nullptr, 10)); + e.ornamentidfile = static_cast(strtoul(row[15], nullptr, 10)); + e.ornament_hero_model = static_cast(atoi(row[16])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -452,6 +452,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_INVENTORY_SNAPSHOTS_REPOSITORY_H diff --git a/common/repositories/base/base_ip_exemptions_repository.h b/common/repositories/base/base_ip_exemptions_repository.h index 1cc185992..f76e8c7a4 100644 --- a/common/repositories/base/base_ip_exemptions_repository.h +++ b/common/repositories/base/base_ip_exemptions_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_IP_EXEMPTIONS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseIpExemptionsRepository { public: struct IpExemptions { - int exemption_id; + int32_t exemption_id; std::string exemption_ip; - int exemption_amount; + int32_t exemption_amount; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static IpExemptions NewEntity() { - IpExemptions entry{}; + IpExemptions e{}; - entry.exemption_id = 0; - entry.exemption_ip = ""; - entry.exemption_amount = 0; + e.exemption_id = 0; + e.exemption_ip = ""; + e.exemption_amount = 0; - return entry; + return e; } - static IpExemptions GetIpExemptionsEntry( + static IpExemptions GetIpExemptions( const std::vector &ip_exemptionss, int ip_exemptions_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - IpExemptions entry{}; + IpExemptions e{}; - entry.exemption_id = atoi(row[0]); - entry.exemption_ip = row[1] ? row[1] : ""; - entry.exemption_amount = atoi(row[2]); + e.exemption_id = static_cast(atoi(row[0])); + e.exemption_ip = row[1] ? row[1] : ""; + e.exemption_amount = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,23 +151,23 @@ public: static int UpdateOne( Database& db, - IpExemptions ip_exemptions_entry + const IpExemptions &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(ip_exemptions_entry.exemption_ip) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(ip_exemptions_entry.exemption_amount)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.exemption_ip) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.exemption_amount)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - ip_exemptions_entry.exemption_id + e.exemption_id ) ); @@ -176,57 +176,57 @@ public: static IpExemptions InsertOne( Database& db, - IpExemptions ip_exemptions_entry + IpExemptions e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(ip_exemptions_entry.exemption_id)); - insert_values.push_back("'" + EscapeString(ip_exemptions_entry.exemption_ip) + "'"); - insert_values.push_back(std::to_string(ip_exemptions_entry.exemption_amount)); + v.push_back(std::to_string(e.exemption_id)); + v.push_back("'" + Strings::Escape(e.exemption_ip) + "'"); + v.push_back(std::to_string(e.exemption_amount)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - ip_exemptions_entry.exemption_id = results.LastInsertedID(); - return ip_exemptions_entry; + e.exemption_id = results.LastInsertedID(); + return e; } - ip_exemptions_entry = NewEntity(); + e = NewEntity(); - return ip_exemptions_entry; + return e; } static int InsertMany( Database& db, - std::vector ip_exemptions_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &ip_exemptions_entry: ip_exemptions_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(ip_exemptions_entry.exemption_id)); - insert_values.push_back("'" + EscapeString(ip_exemptions_entry.exemption_ip) + "'"); - insert_values.push_back(std::to_string(ip_exemptions_entry.exemption_amount)); + v.push_back(std::to_string(e.exemption_id)); + v.push_back("'" + Strings::Escape(e.exemption_ip) + "'"); + v.push_back(std::to_string(e.exemption_amount)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -247,19 +247,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - IpExemptions entry{}; + IpExemptions e{}; - entry.exemption_id = atoi(row[0]); - entry.exemption_ip = row[1] ? row[1] : ""; - entry.exemption_amount = atoi(row[2]); + e.exemption_id = static_cast(atoi(row[0])); + e.exemption_ip = row[1] ? row[1] : ""; + e.exemption_amount = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -274,19 +274,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - IpExemptions entry{}; + IpExemptions e{}; - entry.exemption_id = atoi(row[0]); - entry.exemption_ip = row[1] ? row[1] : ""; - entry.exemption_amount = atoi(row[2]); + e.exemption_id = static_cast(atoi(row[0])); + e.exemption_ip = row[1] ? row[1] : ""; + e.exemption_amount = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -311,6 +311,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_IP_EXEMPTIONS_REPOSITORY_H diff --git a/common/repositories/base/base_item_tick_repository.h b/common/repositories/base/base_item_tick_repository.h index e70289fc4..08b9ded48 100644 --- a/common/repositories/base/base_item_tick_repository.h +++ b/common/repositories/base/base_item_tick_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_ITEM_TICK_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseItemTickRepository { public: struct ItemTick { - int it_itemid; - int it_chance; - int it_level; - int it_id; + int32_t it_itemid; + int32_t it_chance; + int32_t it_level; + int32_t it_id; std::string it_qglobal; - int it_bagslot; + int8_t it_bagslot; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static ItemTick NewEntity() { - ItemTick entry{}; + ItemTick e{}; - entry.it_itemid = 0; - entry.it_chance = 0; - entry.it_level = 0; - entry.it_id = 0; - entry.it_qglobal = ""; - entry.it_bagslot = 0; + e.it_itemid = 0; + e.it_chance = 0; + e.it_level = 0; + e.it_id = 0; + e.it_qglobal = ""; + e.it_bagslot = 0; - return entry; + return e; } - static ItemTick GetItemTickEntry( + static ItemTick GetItemTick( const std::vector &item_ticks, int item_tick_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - ItemTick entry{}; + ItemTick e{}; - entry.it_itemid = atoi(row[0]); - entry.it_chance = atoi(row[1]); - entry.it_level = atoi(row[2]); - entry.it_id = atoi(row[3]); - entry.it_qglobal = row[4] ? row[4] : ""; - entry.it_bagslot = atoi(row[5]); + e.it_itemid = static_cast(atoi(row[0])); + e.it_chance = static_cast(atoi(row[1])); + e.it_level = static_cast(atoi(row[2])); + e.it_id = static_cast(atoi(row[3])); + e.it_qglobal = row[4] ? row[4] : ""; + e.it_bagslot = static_cast(atoi(row[5])); - return entry; + return e; } return NewEntity(); @@ -166,26 +166,26 @@ public: static int UpdateOne( Database& db, - ItemTick item_tick_entry + const ItemTick &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(item_tick_entry.it_itemid)); - update_values.push_back(columns[1] + " = " + std::to_string(item_tick_entry.it_chance)); - update_values.push_back(columns[2] + " = " + std::to_string(item_tick_entry.it_level)); - update_values.push_back(columns[4] + " = '" + EscapeString(item_tick_entry.it_qglobal) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(item_tick_entry.it_bagslot)); + v.push_back(columns[0] + " = " + std::to_string(e.it_itemid)); + v.push_back(columns[1] + " = " + std::to_string(e.it_chance)); + v.push_back(columns[2] + " = " + std::to_string(e.it_level)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.it_qglobal) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.it_bagslot)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - item_tick_entry.it_id + e.it_id ) ); @@ -194,63 +194,63 @@ public: static ItemTick InsertOne( Database& db, - ItemTick item_tick_entry + ItemTick e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(item_tick_entry.it_itemid)); - insert_values.push_back(std::to_string(item_tick_entry.it_chance)); - insert_values.push_back(std::to_string(item_tick_entry.it_level)); - insert_values.push_back(std::to_string(item_tick_entry.it_id)); - insert_values.push_back("'" + EscapeString(item_tick_entry.it_qglobal) + "'"); - insert_values.push_back(std::to_string(item_tick_entry.it_bagslot)); + v.push_back(std::to_string(e.it_itemid)); + v.push_back(std::to_string(e.it_chance)); + v.push_back(std::to_string(e.it_level)); + v.push_back(std::to_string(e.it_id)); + v.push_back("'" + Strings::Escape(e.it_qglobal) + "'"); + v.push_back(std::to_string(e.it_bagslot)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - item_tick_entry.it_id = results.LastInsertedID(); - return item_tick_entry; + e.it_id = results.LastInsertedID(); + return e; } - item_tick_entry = NewEntity(); + e = NewEntity(); - return item_tick_entry; + return e; } static int InsertMany( Database& db, - std::vector item_tick_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &item_tick_entry: item_tick_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(item_tick_entry.it_itemid)); - insert_values.push_back(std::to_string(item_tick_entry.it_chance)); - insert_values.push_back(std::to_string(item_tick_entry.it_level)); - insert_values.push_back(std::to_string(item_tick_entry.it_id)); - insert_values.push_back("'" + EscapeString(item_tick_entry.it_qglobal) + "'"); - insert_values.push_back(std::to_string(item_tick_entry.it_bagslot)); + v.push_back(std::to_string(e.it_itemid)); + v.push_back(std::to_string(e.it_chance)); + v.push_back(std::to_string(e.it_level)); + v.push_back(std::to_string(e.it_id)); + v.push_back("'" + Strings::Escape(e.it_qglobal) + "'"); + v.push_back(std::to_string(e.it_bagslot)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -271,22 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ItemTick entry{}; + ItemTick e{}; - entry.it_itemid = atoi(row[0]); - entry.it_chance = atoi(row[1]); - entry.it_level = atoi(row[2]); - entry.it_id = atoi(row[3]); - entry.it_qglobal = row[4] ? row[4] : ""; - entry.it_bagslot = atoi(row[5]); + e.it_itemid = static_cast(atoi(row[0])); + e.it_chance = static_cast(atoi(row[1])); + e.it_level = static_cast(atoi(row[2])); + e.it_id = static_cast(atoi(row[3])); + e.it_qglobal = row[4] ? row[4] : ""; + e.it_bagslot = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -301,22 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ItemTick entry{}; + ItemTick e{}; - entry.it_itemid = atoi(row[0]); - entry.it_chance = atoi(row[1]); - entry.it_level = atoi(row[2]); - entry.it_id = atoi(row[3]); - entry.it_qglobal = row[4] ? row[4] : ""; - entry.it_bagslot = atoi(row[5]); + e.it_itemid = static_cast(atoi(row[0])); + e.it_chance = static_cast(atoi(row[1])); + e.it_level = static_cast(atoi(row[2])); + e.it_id = static_cast(atoi(row[3])); + e.it_qglobal = row[4] ? row[4] : ""; + e.it_bagslot = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -341,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ITEM_TICK_REPOSITORY_H diff --git a/common/repositories/base/base_items_repository.h b/common/repositories/base/base_items_repository.h index b89de9bae..ef908262e 100644 --- a/common/repositories/base/base_items_repository.h +++ b/common/repositories/base/base_items_repository.h @@ -13,297 +13,297 @@ #define EQEMU_BASE_ITEMS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseItemsRepository { public: struct Items { - int id; - int minstatus; + int32_t id; + int16_t minstatus; std::string Name; - int aagi; - int ac; - int accuracy; - int acha; - int adex; - int aint; - int artifactflag; - int asta; - int astr; - int attack; - int augrestrict; - int augslot1type; - int augslot1visible; - int augslot2type; - int augslot2visible; - int augslot3type; - int augslot3visible; - int augslot4type; - int augslot4visible; - int augslot5type; - int augslot5visible; - int augslot6type; - int augslot6visible; - int augtype; - int avoidance; - int awis; - int bagsize; - int bagslots; - int bagtype; - int bagwr; - int banedmgamt; - int banedmgraceamt; - int banedmgbody; - int banedmgrace; - int bardtype; - int bardvalue; - int book; - int casttime; - int casttime_; + int32_t aagi; + int32_t ac; + int32_t accuracy; + int32_t acha; + int32_t adex; + int32_t aint; + uint8_t artifactflag; + int32_t asta; + int32_t astr; + int32_t attack; + int32_t augrestrict; + int8_t augslot1type; + int8_t augslot1visible; + int8_t augslot2type; + int8_t augslot2visible; + int8_t augslot3type; + int8_t augslot3visible; + int8_t augslot4type; + int8_t augslot4visible; + int8_t augslot5type; + int8_t augslot5visible; + int8_t augslot6type; + int8_t augslot6visible; + int32_t augtype; + int32_t avoidance; + int32_t awis; + int32_t bagsize; + int32_t bagslots; + int32_t bagtype; + int32_t bagwr; + int32_t banedmgamt; + int32_t banedmgraceamt; + int32_t banedmgbody; + int32_t banedmgrace; + int32_t bardtype; + int32_t bardvalue; + int32_t book; + int32_t casttime; + int32_t casttime_; std::string charmfile; std::string charmfileid; - int classes; - int color; + int32_t classes; + uint32_t color; std::string combateffects; - int extradmgskill; - int extradmgamt; - int price; - int cr; - int damage; - int damageshield; - int deity; - int delay; - int augdistiller; - int dotshielding; - int dr; - int clicktype; - int clicklevel2; - int elemdmgtype; - int elemdmgamt; - int endur; - int factionamt1; - int factionamt2; - int factionamt3; - int factionamt4; - int factionmod1; - int factionmod2; - int factionmod3; - int factionmod4; + int32_t extradmgskill; + int32_t extradmgamt; + int32_t price; + int32_t cr; + int32_t damage; + int32_t damageshield; + int32_t deity; + int32_t delay; + int32_t augdistiller; + int32_t dotshielding; + int32_t dr; + int32_t clicktype; + int32_t clicklevel2; + int32_t elemdmgtype; + int32_t elemdmgamt; + int32_t endur; + int32_t factionamt1; + int32_t factionamt2; + int32_t factionamt3; + int32_t factionamt4; + int32_t factionmod1; + int32_t factionmod2; + int32_t factionmod3; + int32_t factionmod4; std::string filename; - int focuseffect; - int fr; - int fvnodrop; - int haste; - int clicklevel; - int hp; - int regen; - int icon; + int32_t focuseffect; + int32_t fr; + int32_t fvnodrop; + int32_t haste; + int32_t clicklevel; + int32_t hp; + int32_t regen; + int32_t icon; std::string idfile; - int itemclass; - int itemtype; - int ldonprice; - int ldontheme; - int ldonsold; - int light; + int32_t itemclass; + int32_t itemtype; + int32_t ldonprice; + int32_t ldontheme; + int32_t ldonsold; + int32_t light; std::string lore; - int loregroup; - int magic; - int mana; - int manaregen; - int enduranceregen; - int material; - int herosforgemodel; - int maxcharges; - int mr; - int nodrop; - int norent; - int pendingloreflag; - int pr; - int procrate; - int races; - int range; - int reclevel; - int recskill; - int reqlevel; + int32_t loregroup; + int32_t magic; + int32_t mana; + int32_t manaregen; + int32_t enduranceregen; + int32_t material; + int32_t herosforgemodel; + int32_t maxcharges; + int32_t mr; + int32_t nodrop; + int32_t norent; + uint8_t pendingloreflag; + int32_t pr; + int32_t procrate; + int32_t races; + int32_t range; + int32_t reclevel; + int32_t recskill; + int32_t reqlevel; float sellrate; - int shielding; - int size; - int skillmodtype; - int skillmodvalue; - int slots; - int clickeffect; - int spellshield; - int strikethrough; - int stunresist; - int summonedflag; - int tradeskills; - int favor; - int weight; - int UNK012; - int UNK013; - int benefitflag; - int UNK054; - int UNK059; - int booktype; - int recastdelay; - int recasttype; - int guildfavor; - int UNK123; - int UNK124; - int attuneable; - int nopet; + int32_t shielding; + int32_t size; + int32_t skillmodtype; + int32_t skillmodvalue; + int32_t slots; + int32_t clickeffect; + int32_t spellshield; + int32_t strikethrough; + int32_t stunresist; + uint8_t summonedflag; + int32_t tradeskills; + int32_t favor; + int32_t weight; + int32_t UNK012; + int32_t UNK013; + int32_t benefitflag; + int32_t UNK054; + int32_t UNK059; + int32_t booktype; + int32_t recastdelay; + int32_t recasttype; + int32_t guildfavor; + int32_t UNK123; + int32_t UNK124; + int32_t attuneable; + int32_t nopet; time_t updated; std::string comment; - int UNK127; - int pointtype; - int potionbelt; - int potionbeltslots; - int stacksize; - int notransfer; - int stackable; + int32_t UNK127; + int32_t pointtype; + int32_t potionbelt; + int32_t potionbeltslots; + int32_t stacksize; + int32_t notransfer; + int32_t stackable; std::string UNK134; - int UNK137; - int proceffect; - int proctype; - int proclevel2; - int proclevel; - int UNK142; - int worneffect; - int worntype; - int wornlevel2; - int wornlevel; - int UNK147; - int focustype; - int focuslevel2; - int focuslevel; - int UNK152; - int scrolleffect; - int scrolltype; - int scrolllevel2; - int scrolllevel; - int UNK157; + int32_t UNK137; + int32_t proceffect; + int32_t proctype; + int32_t proclevel2; + int32_t proclevel; + int32_t UNK142; + int32_t worneffect; + int32_t worntype; + int32_t wornlevel2; + int32_t wornlevel; + int32_t UNK147; + int32_t focustype; + int32_t focuslevel2; + int32_t focuslevel; + int32_t UNK152; + int32_t scrolleffect; + int32_t scrolltype; + int32_t scrolllevel2; + int32_t scrolllevel; + int32_t UNK157; time_t serialized; time_t verified; std::string serialization; std::string source; - int UNK033; + int32_t UNK033; std::string lorefile; - int UNK014; - int svcorruption; - int skillmodmax; - int UNK060; - int augslot1unk2; - int augslot2unk2; - int augslot3unk2; - int augslot4unk2; - int augslot5unk2; - int augslot6unk2; - int UNK120; - int UNK121; - int questitemflag; + int32_t UNK014; + int32_t svcorruption; + int32_t skillmodmax; + int32_t UNK060; + int32_t augslot1unk2; + int32_t augslot2unk2; + int32_t augslot3unk2; + int32_t augslot4unk2; + int32_t augslot5unk2; + int32_t augslot6unk2; + int32_t UNK120; + int32_t UNK121; + int32_t questitemflag; std::string UNK132; - int clickunk5; + int32_t clickunk5; std::string clickunk6; - int clickunk7; - int procunk1; - int procunk2; - int procunk3; - int procunk4; + int32_t clickunk7; + int32_t procunk1; + int32_t procunk2; + int32_t procunk3; + int32_t procunk4; std::string procunk6; - int procunk7; - int wornunk1; - int wornunk2; - int wornunk3; - int wornunk4; - int wornunk5; + int32_t procunk7; + int32_t wornunk1; + int32_t wornunk2; + int32_t wornunk3; + int32_t wornunk4; + int32_t wornunk5; std::string wornunk6; - int wornunk7; - int focusunk1; - int focusunk2; - int focusunk3; - int focusunk4; - int focusunk5; + int32_t wornunk7; + int32_t focusunk1; + int32_t focusunk2; + int32_t focusunk3; + int32_t focusunk4; + int32_t focusunk5; std::string focusunk6; - int focusunk7; - int scrollunk1; - int scrollunk2; - int scrollunk3; - int scrollunk4; - int scrollunk5; + int32_t focusunk7; + int32_t scrollunk1; + int32_t scrollunk2; + int32_t scrollunk3; + int32_t scrollunk4; + int32_t scrollunk5; std::string scrollunk6; - int scrollunk7; - int UNK193; - int purity; - int evoitem; - int evoid; - int evolvinglevel; - int evomax; + int32_t scrollunk7; + int32_t UNK193; + int32_t purity; + int32_t evoitem; + int32_t evoid; + int32_t evolvinglevel; + int32_t evomax; std::string clickname; std::string procname; std::string wornname; std::string focusname; std::string scrollname; - int dsmitigation; - int heroic_str; - int heroic_int; - int heroic_wis; - int heroic_agi; - int heroic_dex; - int heroic_sta; - int heroic_cha; - int heroic_pr; - int heroic_dr; - int heroic_fr; - int heroic_cr; - int heroic_mr; - int heroic_svcorrup; - int healamt; - int spelldmg; - int clairvoyance; - int backstabdmg; + int16_t dsmitigation; + int16_t heroic_str; + int16_t heroic_int; + int16_t heroic_wis; + int16_t heroic_agi; + int16_t heroic_dex; + int16_t heroic_sta; + int16_t heroic_cha; + int16_t heroic_pr; + int16_t heroic_dr; + int16_t heroic_fr; + int16_t heroic_cr; + int16_t heroic_mr; + int16_t heroic_svcorrup; + int16_t healamt; + int16_t spelldmg; + int16_t clairvoyance; + int16_t backstabdmg; std::string created; - int elitematerial; - int ldonsellbackrate; - int scriptfileid; - int expendablearrow; - int powersourcecapacity; - int bardeffect; - int bardeffecttype; - int bardlevel2; - int bardlevel; - int bardunk1; - int bardunk2; - int bardunk3; - int bardunk4; - int bardunk5; + int16_t elitematerial; + int16_t ldonsellbackrate; + int16_t scriptfileid; + int16_t expendablearrow; + int16_t powersourcecapacity; + int16_t bardeffect; + int16_t bardeffecttype; + int16_t bardlevel2; + int16_t bardlevel; + int16_t bardunk1; + int16_t bardunk2; + int16_t bardunk3; + int16_t bardunk4; + int16_t bardunk5; std::string bardname; - int bardunk7; - int UNK214; - int subtype; - int UNK220; - int UNK221; - int heirloom; - int UNK223; - int UNK224; - int UNK225; - int UNK226; - int UNK227; - int UNK228; - int UNK229; - int UNK230; - int UNK231; - int UNK232; - int UNK233; - int UNK234; - int placeable; - int UNK236; - int UNK237; - int UNK238; - int UNK239; - int UNK240; - int UNK241; - int epicitem; + int16_t bardunk7; + int16_t UNK214; + int32_t subtype; + int32_t UNK220; + int32_t UNK221; + int32_t heirloom; + int32_t UNK223; + int32_t UNK224; + int32_t UNK225; + int32_t UNK226; + int32_t UNK227; + int32_t UNK228; + int32_t UNK229; + int32_t UNK230; + int32_t UNK231; + int32_t UNK232; + int32_t UNK233; + int32_t UNK234; + int32_t placeable; + int32_t UNK236; + int32_t UNK237; + int32_t UNK238; + int32_t UNK239; + int32_t UNK240; + int32_t UNK241; + int32_t epicitem; }; static std::string PrimaryKey() @@ -895,12 +895,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -928,298 +928,298 @@ public: static Items NewEntity() { - Items entry{}; + Items e{}; - entry.id = 0; - entry.minstatus = 0; - entry.Name = ""; - entry.aagi = 0; - entry.ac = 0; - entry.accuracy = 0; - entry.acha = 0; - entry.adex = 0; - entry.aint = 0; - entry.artifactflag = 0; - entry.asta = 0; - entry.astr = 0; - entry.attack = 0; - entry.augrestrict = 0; - entry.augslot1type = 0; - entry.augslot1visible = 0; - entry.augslot2type = 0; - entry.augslot2visible = 0; - entry.augslot3type = 0; - entry.augslot3visible = 0; - entry.augslot4type = 0; - entry.augslot4visible = 0; - entry.augslot5type = 0; - entry.augslot5visible = 0; - entry.augslot6type = 0; - entry.augslot6visible = 0; - entry.augtype = 0; - entry.avoidance = 0; - entry.awis = 0; - entry.bagsize = 0; - entry.bagslots = 0; - entry.bagtype = 0; - entry.bagwr = 0; - entry.banedmgamt = 0; - entry.banedmgraceamt = 0; - entry.banedmgbody = 0; - entry.banedmgrace = 0; - entry.bardtype = 0; - entry.bardvalue = 0; - entry.book = 0; - entry.casttime = 0; - entry.casttime_ = 0; - entry.charmfile = ""; - entry.charmfileid = ""; - entry.classes = 0; - entry.color = 0; - entry.combateffects = ""; - entry.extradmgskill = 0; - entry.extradmgamt = 0; - entry.price = 0; - entry.cr = 0; - entry.damage = 0; - entry.damageshield = 0; - entry.deity = 0; - entry.delay = 0; - entry.augdistiller = 0; - entry.dotshielding = 0; - entry.dr = 0; - entry.clicktype = 0; - entry.clicklevel2 = 0; - entry.elemdmgtype = 0; - entry.elemdmgamt = 0; - entry.endur = 0; - entry.factionamt1 = 0; - entry.factionamt2 = 0; - entry.factionamt3 = 0; - entry.factionamt4 = 0; - entry.factionmod1 = 0; - entry.factionmod2 = 0; - entry.factionmod3 = 0; - entry.factionmod4 = 0; - entry.filename = ""; - entry.focuseffect = 0; - entry.fr = 0; - entry.fvnodrop = 0; - entry.haste = 0; - entry.clicklevel = 0; - entry.hp = 0; - entry.regen = 0; - entry.icon = 0; - entry.idfile = ""; - entry.itemclass = 0; - entry.itemtype = 0; - entry.ldonprice = 0; - entry.ldontheme = 0; - entry.ldonsold = 0; - entry.light = 0; - entry.lore = ""; - entry.loregroup = 0; - entry.magic = 0; - entry.mana = 0; - entry.manaregen = 0; - entry.enduranceregen = 0; - entry.material = 0; - entry.herosforgemodel = 0; - entry.maxcharges = 0; - entry.mr = 0; - entry.nodrop = 0; - entry.norent = 0; - entry.pendingloreflag = 0; - entry.pr = 0; - entry.procrate = 0; - entry.races = 0; - entry.range = 0; - entry.reclevel = 0; - entry.recskill = 0; - entry.reqlevel = 0; - entry.sellrate = 0; - entry.shielding = 0; - entry.size = 0; - entry.skillmodtype = 0; - entry.skillmodvalue = 0; - entry.slots = 0; - entry.clickeffect = 0; - entry.spellshield = 0; - entry.strikethrough = 0; - entry.stunresist = 0; - entry.summonedflag = 0; - entry.tradeskills = 0; - entry.favor = 0; - entry.weight = 0; - entry.UNK012 = 0; - entry.UNK013 = 0; - entry.benefitflag = 0; - entry.UNK054 = 0; - entry.UNK059 = 0; - entry.booktype = 0; - entry.recastdelay = 0; - entry.recasttype = 0; - entry.guildfavor = 0; - entry.UNK123 = 0; - entry.UNK124 = 0; - entry.attuneable = 0; - entry.nopet = 0; - entry.updated = 0; - entry.comment = ""; - entry.UNK127 = 0; - entry.pointtype = 0; - entry.potionbelt = 0; - entry.potionbeltslots = 0; - entry.stacksize = 0; - entry.notransfer = 0; - entry.stackable = 0; - entry.UNK134 = ""; - entry.UNK137 = 0; - entry.proceffect = 0; - entry.proctype = 0; - entry.proclevel2 = 0; - entry.proclevel = 0; - entry.UNK142 = 0; - entry.worneffect = 0; - entry.worntype = 0; - entry.wornlevel2 = 0; - entry.wornlevel = 0; - entry.UNK147 = 0; - entry.focustype = 0; - entry.focuslevel2 = 0; - entry.focuslevel = 0; - entry.UNK152 = 0; - entry.scrolleffect = 0; - entry.scrolltype = 0; - entry.scrolllevel2 = 0; - entry.scrolllevel = 0; - entry.UNK157 = 0; - entry.serialized = 0; - entry.verified = 0; - entry.serialization = ""; - entry.source = ""; - entry.UNK033 = 0; - entry.lorefile = ""; - entry.UNK014 = 0; - entry.svcorruption = 0; - entry.skillmodmax = 0; - entry.UNK060 = 0; - entry.augslot1unk2 = 0; - entry.augslot2unk2 = 0; - entry.augslot3unk2 = 0; - entry.augslot4unk2 = 0; - entry.augslot5unk2 = 0; - entry.augslot6unk2 = 0; - entry.UNK120 = 0; - entry.UNK121 = 0; - entry.questitemflag = 0; - entry.UNK132 = ""; - entry.clickunk5 = 0; - entry.clickunk6 = ""; - entry.clickunk7 = 0; - entry.procunk1 = 0; - entry.procunk2 = 0; - entry.procunk3 = 0; - entry.procunk4 = 0; - entry.procunk6 = ""; - entry.procunk7 = 0; - entry.wornunk1 = 0; - entry.wornunk2 = 0; - entry.wornunk3 = 0; - entry.wornunk4 = 0; - entry.wornunk5 = 0; - entry.wornunk6 = ""; - entry.wornunk7 = 0; - entry.focusunk1 = 0; - entry.focusunk2 = 0; - entry.focusunk3 = 0; - entry.focusunk4 = 0; - entry.focusunk5 = 0; - entry.focusunk6 = ""; - entry.focusunk7 = 0; - entry.scrollunk1 = 0; - entry.scrollunk2 = 0; - entry.scrollunk3 = 0; - entry.scrollunk4 = 0; - entry.scrollunk5 = 0; - entry.scrollunk6 = ""; - entry.scrollunk7 = 0; - entry.UNK193 = 0; - entry.purity = 0; - entry.evoitem = 0; - entry.evoid = 0; - entry.evolvinglevel = 0; - entry.evomax = 0; - entry.clickname = ""; - entry.procname = ""; - entry.wornname = ""; - entry.focusname = ""; - entry.scrollname = ""; - entry.dsmitigation = 0; - entry.heroic_str = 0; - entry.heroic_int = 0; - entry.heroic_wis = 0; - entry.heroic_agi = 0; - entry.heroic_dex = 0; - entry.heroic_sta = 0; - entry.heroic_cha = 0; - entry.heroic_pr = 0; - entry.heroic_dr = 0; - entry.heroic_fr = 0; - entry.heroic_cr = 0; - entry.heroic_mr = 0; - entry.heroic_svcorrup = 0; - entry.healamt = 0; - entry.spelldmg = 0; - entry.clairvoyance = 0; - entry.backstabdmg = 0; - entry.created = ""; - entry.elitematerial = 0; - entry.ldonsellbackrate = 0; - entry.scriptfileid = 0; - entry.expendablearrow = 0; - entry.powersourcecapacity = 0; - entry.bardeffect = 0; - entry.bardeffecttype = 0; - entry.bardlevel2 = 0; - entry.bardlevel = 0; - entry.bardunk1 = 0; - entry.bardunk2 = 0; - entry.bardunk3 = 0; - entry.bardunk4 = 0; - entry.bardunk5 = 0; - entry.bardname = ""; - entry.bardunk7 = 0; - entry.UNK214 = 0; - entry.subtype = 0; - entry.UNK220 = 0; - entry.UNK221 = 0; - entry.heirloom = 0; - entry.UNK223 = 0; - entry.UNK224 = 0; - entry.UNK225 = 0; - entry.UNK226 = 0; - entry.UNK227 = 0; - entry.UNK228 = 0; - entry.UNK229 = 0; - entry.UNK230 = 0; - entry.UNK231 = 0; - entry.UNK232 = 0; - entry.UNK233 = 0; - entry.UNK234 = 0; - entry.placeable = 0; - entry.UNK236 = 0; - entry.UNK237 = 0; - entry.UNK238 = 0; - entry.UNK239 = 0; - entry.UNK240 = 0; - entry.UNK241 = 0; - entry.epicitem = 0; + e.id = 0; + e.minstatus = 0; + e.Name = ""; + e.aagi = 0; + e.ac = 0; + e.accuracy = 0; + e.acha = 0; + e.adex = 0; + e.aint = 0; + e.artifactflag = 0; + e.asta = 0; + e.astr = 0; + e.attack = 0; + e.augrestrict = 0; + e.augslot1type = 0; + e.augslot1visible = 0; + e.augslot2type = 0; + e.augslot2visible = 0; + e.augslot3type = 0; + e.augslot3visible = 0; + e.augslot4type = 0; + e.augslot4visible = 0; + e.augslot5type = 0; + e.augslot5visible = 0; + e.augslot6type = 0; + e.augslot6visible = 0; + e.augtype = 0; + e.avoidance = 0; + e.awis = 0; + e.bagsize = 0; + e.bagslots = 0; + e.bagtype = 0; + e.bagwr = 0; + e.banedmgamt = 0; + e.banedmgraceamt = 0; + e.banedmgbody = 0; + e.banedmgrace = 0; + e.bardtype = 0; + e.bardvalue = 0; + e.book = 0; + e.casttime = 0; + e.casttime_ = 0; + e.charmfile = ""; + e.charmfileid = ""; + e.classes = 0; + e.color = 0; + e.combateffects = ""; + e.extradmgskill = 0; + e.extradmgamt = 0; + e.price = 0; + e.cr = 0; + e.damage = 0; + e.damageshield = 0; + e.deity = 0; + e.delay = 0; + e.augdistiller = 0; + e.dotshielding = 0; + e.dr = 0; + e.clicktype = 0; + e.clicklevel2 = 0; + e.elemdmgtype = 0; + e.elemdmgamt = 0; + e.endur = 0; + e.factionamt1 = 0; + e.factionamt2 = 0; + e.factionamt3 = 0; + e.factionamt4 = 0; + e.factionmod1 = 0; + e.factionmod2 = 0; + e.factionmod3 = 0; + e.factionmod4 = 0; + e.filename = ""; + e.focuseffect = 0; + e.fr = 0; + e.fvnodrop = 0; + e.haste = 0; + e.clicklevel = 0; + e.hp = 0; + e.regen = 0; + e.icon = 0; + e.idfile = ""; + e.itemclass = 0; + e.itemtype = 0; + e.ldonprice = 0; + e.ldontheme = 0; + e.ldonsold = 0; + e.light = 0; + e.lore = ""; + e.loregroup = 0; + e.magic = 0; + e.mana = 0; + e.manaregen = 0; + e.enduranceregen = 0; + e.material = 0; + e.herosforgemodel = 0; + e.maxcharges = 0; + e.mr = 0; + e.nodrop = 0; + e.norent = 0; + e.pendingloreflag = 0; + e.pr = 0; + e.procrate = 0; + e.races = 0; + e.range = 0; + e.reclevel = 0; + e.recskill = 0; + e.reqlevel = 0; + e.sellrate = 0; + e.shielding = 0; + e.size = 0; + e.skillmodtype = 0; + e.skillmodvalue = 0; + e.slots = 0; + e.clickeffect = 0; + e.spellshield = 0; + e.strikethrough = 0; + e.stunresist = 0; + e.summonedflag = 0; + e.tradeskills = 0; + e.favor = 0; + e.weight = 0; + e.UNK012 = 0; + e.UNK013 = 0; + e.benefitflag = 0; + e.UNK054 = 0; + e.UNK059 = 0; + e.booktype = 0; + e.recastdelay = 0; + e.recasttype = 0; + e.guildfavor = 0; + e.UNK123 = 0; + e.UNK124 = 0; + e.attuneable = 0; + e.nopet = 0; + e.updated = 0; + e.comment = ""; + e.UNK127 = 0; + e.pointtype = 0; + e.potionbelt = 0; + e.potionbeltslots = 0; + e.stacksize = 0; + e.notransfer = 0; + e.stackable = 0; + e.UNK134 = ""; + e.UNK137 = 0; + e.proceffect = 0; + e.proctype = 0; + e.proclevel2 = 0; + e.proclevel = 0; + e.UNK142 = 0; + e.worneffect = 0; + e.worntype = 0; + e.wornlevel2 = 0; + e.wornlevel = 0; + e.UNK147 = 0; + e.focustype = 0; + e.focuslevel2 = 0; + e.focuslevel = 0; + e.UNK152 = 0; + e.scrolleffect = 0; + e.scrolltype = 0; + e.scrolllevel2 = 0; + e.scrolllevel = 0; + e.UNK157 = 0; + e.serialized = 0; + e.verified = 0; + e.serialization = ""; + e.source = ""; + e.UNK033 = 0; + e.lorefile = ""; + e.UNK014 = 0; + e.svcorruption = 0; + e.skillmodmax = 0; + e.UNK060 = 0; + e.augslot1unk2 = 0; + e.augslot2unk2 = 0; + e.augslot3unk2 = 0; + e.augslot4unk2 = 0; + e.augslot5unk2 = 0; + e.augslot6unk2 = 0; + e.UNK120 = 0; + e.UNK121 = 0; + e.questitemflag = 0; + e.UNK132 = ""; + e.clickunk5 = 0; + e.clickunk6 = ""; + e.clickunk7 = 0; + e.procunk1 = 0; + e.procunk2 = 0; + e.procunk3 = 0; + e.procunk4 = 0; + e.procunk6 = ""; + e.procunk7 = 0; + e.wornunk1 = 0; + e.wornunk2 = 0; + e.wornunk3 = 0; + e.wornunk4 = 0; + e.wornunk5 = 0; + e.wornunk6 = ""; + e.wornunk7 = 0; + e.focusunk1 = 0; + e.focusunk2 = 0; + e.focusunk3 = 0; + e.focusunk4 = 0; + e.focusunk5 = 0; + e.focusunk6 = ""; + e.focusunk7 = 0; + e.scrollunk1 = 0; + e.scrollunk2 = 0; + e.scrollunk3 = 0; + e.scrollunk4 = 0; + e.scrollunk5 = 0; + e.scrollunk6 = ""; + e.scrollunk7 = 0; + e.UNK193 = 0; + e.purity = 0; + e.evoitem = 0; + e.evoid = 0; + e.evolvinglevel = 0; + e.evomax = 0; + e.clickname = ""; + e.procname = ""; + e.wornname = ""; + e.focusname = ""; + e.scrollname = ""; + e.dsmitigation = 0; + e.heroic_str = 0; + e.heroic_int = 0; + e.heroic_wis = 0; + e.heroic_agi = 0; + e.heroic_dex = 0; + e.heroic_sta = 0; + e.heroic_cha = 0; + e.heroic_pr = 0; + e.heroic_dr = 0; + e.heroic_fr = 0; + e.heroic_cr = 0; + e.heroic_mr = 0; + e.heroic_svcorrup = 0; + e.healamt = 0; + e.spelldmg = 0; + e.clairvoyance = 0; + e.backstabdmg = 0; + e.created = ""; + e.elitematerial = 0; + e.ldonsellbackrate = 0; + e.scriptfileid = 0; + e.expendablearrow = 0; + e.powersourcecapacity = 0; + e.bardeffect = 0; + e.bardeffecttype = 0; + e.bardlevel2 = 0; + e.bardlevel = 0; + e.bardunk1 = 0; + e.bardunk2 = 0; + e.bardunk3 = 0; + e.bardunk4 = 0; + e.bardunk5 = 0; + e.bardname = ""; + e.bardunk7 = 0; + e.UNK214 = 0; + e.subtype = 0; + e.UNK220 = 0; + e.UNK221 = 0; + e.heirloom = 0; + e.UNK223 = 0; + e.UNK224 = 0; + e.UNK225 = 0; + e.UNK226 = 0; + e.UNK227 = 0; + e.UNK228 = 0; + e.UNK229 = 0; + e.UNK230 = 0; + e.UNK231 = 0; + e.UNK232 = 0; + e.UNK233 = 0; + e.UNK234 = 0; + e.placeable = 0; + e.UNK236 = 0; + e.UNK237 = 0; + e.UNK238 = 0; + e.UNK239 = 0; + e.UNK240 = 0; + e.UNK241 = 0; + e.epicitem = 0; - return entry; + return e; } - static Items GetItemsEntry( + static Items GetItems( const std::vector &itemss, int items_id ) @@ -1248,295 +1248,295 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Items entry{}; + Items e{}; - entry.id = atoi(row[0]); - entry.minstatus = atoi(row[1]); - entry.Name = row[2] ? row[2] : ""; - entry.aagi = atoi(row[3]); - entry.ac = atoi(row[4]); - entry.accuracy = atoi(row[5]); - entry.acha = atoi(row[6]); - entry.adex = atoi(row[7]); - entry.aint = atoi(row[8]); - entry.artifactflag = atoi(row[9]); - entry.asta = atoi(row[10]); - entry.astr = atoi(row[11]); - entry.attack = atoi(row[12]); - entry.augrestrict = atoi(row[13]); - entry.augslot1type = atoi(row[14]); - entry.augslot1visible = atoi(row[15]); - entry.augslot2type = atoi(row[16]); - entry.augslot2visible = atoi(row[17]); - entry.augslot3type = atoi(row[18]); - entry.augslot3visible = atoi(row[19]); - entry.augslot4type = atoi(row[20]); - entry.augslot4visible = atoi(row[21]); - entry.augslot5type = atoi(row[22]); - entry.augslot5visible = atoi(row[23]); - entry.augslot6type = atoi(row[24]); - entry.augslot6visible = atoi(row[25]); - entry.augtype = atoi(row[26]); - entry.avoidance = atoi(row[27]); - entry.awis = atoi(row[28]); - entry.bagsize = atoi(row[29]); - entry.bagslots = atoi(row[30]); - entry.bagtype = atoi(row[31]); - entry.bagwr = atoi(row[32]); - entry.banedmgamt = atoi(row[33]); - entry.banedmgraceamt = atoi(row[34]); - entry.banedmgbody = atoi(row[35]); - entry.banedmgrace = atoi(row[36]); - entry.bardtype = atoi(row[37]); - entry.bardvalue = atoi(row[38]); - entry.book = atoi(row[39]); - entry.casttime = atoi(row[40]); - entry.casttime_ = atoi(row[41]); - entry.charmfile = row[42] ? row[42] : ""; - entry.charmfileid = row[43] ? row[43] : ""; - entry.classes = atoi(row[44]); - entry.color = atoi(row[45]); - entry.combateffects = row[46] ? row[46] : ""; - entry.extradmgskill = atoi(row[47]); - entry.extradmgamt = atoi(row[48]); - entry.price = atoi(row[49]); - entry.cr = atoi(row[50]); - entry.damage = atoi(row[51]); - entry.damageshield = atoi(row[52]); - entry.deity = atoi(row[53]); - entry.delay = atoi(row[54]); - entry.augdistiller = atoi(row[55]); - entry.dotshielding = atoi(row[56]); - entry.dr = atoi(row[57]); - entry.clicktype = atoi(row[58]); - entry.clicklevel2 = atoi(row[59]); - entry.elemdmgtype = atoi(row[60]); - entry.elemdmgamt = atoi(row[61]); - entry.endur = atoi(row[62]); - entry.factionamt1 = atoi(row[63]); - entry.factionamt2 = atoi(row[64]); - entry.factionamt3 = atoi(row[65]); - entry.factionamt4 = atoi(row[66]); - entry.factionmod1 = atoi(row[67]); - entry.factionmod2 = atoi(row[68]); - entry.factionmod3 = atoi(row[69]); - entry.factionmod4 = atoi(row[70]); - entry.filename = row[71] ? row[71] : ""; - entry.focuseffect = atoi(row[72]); - entry.fr = atoi(row[73]); - entry.fvnodrop = atoi(row[74]); - entry.haste = atoi(row[75]); - entry.clicklevel = atoi(row[76]); - entry.hp = atoi(row[77]); - entry.regen = atoi(row[78]); - entry.icon = atoi(row[79]); - entry.idfile = row[80] ? row[80] : ""; - entry.itemclass = atoi(row[81]); - entry.itemtype = atoi(row[82]); - entry.ldonprice = atoi(row[83]); - entry.ldontheme = atoi(row[84]); - entry.ldonsold = atoi(row[85]); - entry.light = atoi(row[86]); - entry.lore = row[87] ? row[87] : ""; - entry.loregroup = atoi(row[88]); - entry.magic = atoi(row[89]); - entry.mana = atoi(row[90]); - entry.manaregen = atoi(row[91]); - entry.enduranceregen = atoi(row[92]); - entry.material = atoi(row[93]); - entry.herosforgemodel = atoi(row[94]); - entry.maxcharges = atoi(row[95]); - entry.mr = atoi(row[96]); - entry.nodrop = atoi(row[97]); - entry.norent = atoi(row[98]); - entry.pendingloreflag = atoi(row[99]); - entry.pr = atoi(row[100]); - entry.procrate = atoi(row[101]); - entry.races = atoi(row[102]); - entry.range = atoi(row[103]); - entry.reclevel = atoi(row[104]); - entry.recskill = atoi(row[105]); - entry.reqlevel = atoi(row[106]); - entry.sellrate = static_cast(atof(row[107])); - entry.shielding = atoi(row[108]); - entry.size = atoi(row[109]); - entry.skillmodtype = atoi(row[110]); - entry.skillmodvalue = atoi(row[111]); - entry.slots = atoi(row[112]); - entry.clickeffect = atoi(row[113]); - entry.spellshield = atoi(row[114]); - entry.strikethrough = atoi(row[115]); - entry.stunresist = atoi(row[116]); - entry.summonedflag = atoi(row[117]); - entry.tradeskills = atoi(row[118]); - entry.favor = atoi(row[119]); - entry.weight = atoi(row[120]); - entry.UNK012 = atoi(row[121]); - entry.UNK013 = atoi(row[122]); - entry.benefitflag = atoi(row[123]); - entry.UNK054 = atoi(row[124]); - entry.UNK059 = atoi(row[125]); - entry.booktype = atoi(row[126]); - entry.recastdelay = atoi(row[127]); - entry.recasttype = atoi(row[128]); - entry.guildfavor = atoi(row[129]); - entry.UNK123 = atoi(row[130]); - entry.UNK124 = atoi(row[131]); - entry.attuneable = atoi(row[132]); - entry.nopet = atoi(row[133]); - entry.updated = strtoll(row[134] ? row[134] : "-1", nullptr, 10); - entry.comment = row[135] ? row[135] : ""; - entry.UNK127 = atoi(row[136]); - entry.pointtype = atoi(row[137]); - entry.potionbelt = atoi(row[138]); - entry.potionbeltslots = atoi(row[139]); - entry.stacksize = atoi(row[140]); - entry.notransfer = atoi(row[141]); - entry.stackable = atoi(row[142]); - entry.UNK134 = row[143] ? row[143] : ""; - entry.UNK137 = atoi(row[144]); - entry.proceffect = atoi(row[145]); - entry.proctype = atoi(row[146]); - entry.proclevel2 = atoi(row[147]); - entry.proclevel = atoi(row[148]); - entry.UNK142 = atoi(row[149]); - entry.worneffect = atoi(row[150]); - entry.worntype = atoi(row[151]); - entry.wornlevel2 = atoi(row[152]); - entry.wornlevel = atoi(row[153]); - entry.UNK147 = atoi(row[154]); - entry.focustype = atoi(row[155]); - entry.focuslevel2 = atoi(row[156]); - entry.focuslevel = atoi(row[157]); - entry.UNK152 = atoi(row[158]); - entry.scrolleffect = atoi(row[159]); - entry.scrolltype = atoi(row[160]); - entry.scrolllevel2 = atoi(row[161]); - entry.scrolllevel = atoi(row[162]); - entry.UNK157 = atoi(row[163]); - entry.serialized = strtoll(row[164] ? row[164] : "-1", nullptr, 10); - entry.verified = strtoll(row[165] ? row[165] : "-1", nullptr, 10); - entry.serialization = row[166] ? row[166] : ""; - entry.source = row[167] ? row[167] : ""; - entry.UNK033 = atoi(row[168]); - entry.lorefile = row[169] ? row[169] : ""; - entry.UNK014 = atoi(row[170]); - entry.svcorruption = atoi(row[171]); - entry.skillmodmax = atoi(row[172]); - entry.UNK060 = atoi(row[173]); - entry.augslot1unk2 = atoi(row[174]); - entry.augslot2unk2 = atoi(row[175]); - entry.augslot3unk2 = atoi(row[176]); - entry.augslot4unk2 = atoi(row[177]); - entry.augslot5unk2 = atoi(row[178]); - entry.augslot6unk2 = atoi(row[179]); - entry.UNK120 = atoi(row[180]); - entry.UNK121 = atoi(row[181]); - entry.questitemflag = atoi(row[182]); - entry.UNK132 = row[183] ? row[183] : ""; - entry.clickunk5 = atoi(row[184]); - entry.clickunk6 = row[185] ? row[185] : ""; - entry.clickunk7 = atoi(row[186]); - entry.procunk1 = atoi(row[187]); - entry.procunk2 = atoi(row[188]); - entry.procunk3 = atoi(row[189]); - entry.procunk4 = atoi(row[190]); - entry.procunk6 = row[191] ? row[191] : ""; - entry.procunk7 = atoi(row[192]); - entry.wornunk1 = atoi(row[193]); - entry.wornunk2 = atoi(row[194]); - entry.wornunk3 = atoi(row[195]); - entry.wornunk4 = atoi(row[196]); - entry.wornunk5 = atoi(row[197]); - entry.wornunk6 = row[198] ? row[198] : ""; - entry.wornunk7 = atoi(row[199]); - entry.focusunk1 = atoi(row[200]); - entry.focusunk2 = atoi(row[201]); - entry.focusunk3 = atoi(row[202]); - entry.focusunk4 = atoi(row[203]); - entry.focusunk5 = atoi(row[204]); - entry.focusunk6 = row[205] ? row[205] : ""; - entry.focusunk7 = atoi(row[206]); - entry.scrollunk1 = atoi(row[207]); - entry.scrollunk2 = atoi(row[208]); - entry.scrollunk3 = atoi(row[209]); - entry.scrollunk4 = atoi(row[210]); - entry.scrollunk5 = atoi(row[211]); - entry.scrollunk6 = row[212] ? row[212] : ""; - entry.scrollunk7 = atoi(row[213]); - entry.UNK193 = atoi(row[214]); - entry.purity = atoi(row[215]); - entry.evoitem = atoi(row[216]); - entry.evoid = atoi(row[217]); - entry.evolvinglevel = atoi(row[218]); - entry.evomax = atoi(row[219]); - entry.clickname = row[220] ? row[220] : ""; - entry.procname = row[221] ? row[221] : ""; - entry.wornname = row[222] ? row[222] : ""; - entry.focusname = row[223] ? row[223] : ""; - entry.scrollname = row[224] ? row[224] : ""; - entry.dsmitigation = atoi(row[225]); - entry.heroic_str = atoi(row[226]); - entry.heroic_int = atoi(row[227]); - entry.heroic_wis = atoi(row[228]); - entry.heroic_agi = atoi(row[229]); - entry.heroic_dex = atoi(row[230]); - entry.heroic_sta = atoi(row[231]); - entry.heroic_cha = atoi(row[232]); - entry.heroic_pr = atoi(row[233]); - entry.heroic_dr = atoi(row[234]); - entry.heroic_fr = atoi(row[235]); - entry.heroic_cr = atoi(row[236]); - entry.heroic_mr = atoi(row[237]); - entry.heroic_svcorrup = atoi(row[238]); - entry.healamt = atoi(row[239]); - entry.spelldmg = atoi(row[240]); - entry.clairvoyance = atoi(row[241]); - entry.backstabdmg = atoi(row[242]); - entry.created = row[243] ? row[243] : ""; - entry.elitematerial = atoi(row[244]); - entry.ldonsellbackrate = atoi(row[245]); - entry.scriptfileid = atoi(row[246]); - entry.expendablearrow = atoi(row[247]); - entry.powersourcecapacity = atoi(row[248]); - entry.bardeffect = atoi(row[249]); - entry.bardeffecttype = atoi(row[250]); - entry.bardlevel2 = atoi(row[251]); - entry.bardlevel = atoi(row[252]); - entry.bardunk1 = atoi(row[253]); - entry.bardunk2 = atoi(row[254]); - entry.bardunk3 = atoi(row[255]); - entry.bardunk4 = atoi(row[256]); - entry.bardunk5 = atoi(row[257]); - entry.bardname = row[258] ? row[258] : ""; - entry.bardunk7 = atoi(row[259]); - entry.UNK214 = atoi(row[260]); - entry.subtype = atoi(row[261]); - entry.UNK220 = atoi(row[262]); - entry.UNK221 = atoi(row[263]); - entry.heirloom = atoi(row[264]); - entry.UNK223 = atoi(row[265]); - entry.UNK224 = atoi(row[266]); - entry.UNK225 = atoi(row[267]); - entry.UNK226 = atoi(row[268]); - entry.UNK227 = atoi(row[269]); - entry.UNK228 = atoi(row[270]); - entry.UNK229 = atoi(row[271]); - entry.UNK230 = atoi(row[272]); - entry.UNK231 = atoi(row[273]); - entry.UNK232 = atoi(row[274]); - entry.UNK233 = atoi(row[275]); - entry.UNK234 = atoi(row[276]); - entry.placeable = atoi(row[277]); - entry.UNK236 = atoi(row[278]); - entry.UNK237 = atoi(row[279]); - entry.UNK238 = atoi(row[280]); - entry.UNK239 = atoi(row[281]); - entry.UNK240 = atoi(row[282]); - entry.UNK241 = atoi(row[283]); - entry.epicitem = atoi(row[284]); + e.id = static_cast(atoi(row[0])); + e.minstatus = static_cast(atoi(row[1])); + e.Name = row[2] ? row[2] : ""; + e.aagi = static_cast(atoi(row[3])); + e.ac = static_cast(atoi(row[4])); + e.accuracy = static_cast(atoi(row[5])); + e.acha = static_cast(atoi(row[6])); + e.adex = static_cast(atoi(row[7])); + e.aint = static_cast(atoi(row[8])); + e.artifactflag = static_cast(strtoul(row[9], nullptr, 10)); + e.asta = static_cast(atoi(row[10])); + e.astr = static_cast(atoi(row[11])); + e.attack = static_cast(atoi(row[12])); + e.augrestrict = static_cast(atoi(row[13])); + e.augslot1type = static_cast(atoi(row[14])); + e.augslot1visible = static_cast(atoi(row[15])); + e.augslot2type = static_cast(atoi(row[16])); + e.augslot2visible = static_cast(atoi(row[17])); + e.augslot3type = static_cast(atoi(row[18])); + e.augslot3visible = static_cast(atoi(row[19])); + e.augslot4type = static_cast(atoi(row[20])); + e.augslot4visible = static_cast(atoi(row[21])); + e.augslot5type = static_cast(atoi(row[22])); + e.augslot5visible = static_cast(atoi(row[23])); + e.augslot6type = static_cast(atoi(row[24])); + e.augslot6visible = static_cast(atoi(row[25])); + e.augtype = static_cast(atoi(row[26])); + e.avoidance = static_cast(atoi(row[27])); + e.awis = static_cast(atoi(row[28])); + e.bagsize = static_cast(atoi(row[29])); + e.bagslots = static_cast(atoi(row[30])); + e.bagtype = static_cast(atoi(row[31])); + e.bagwr = static_cast(atoi(row[32])); + e.banedmgamt = static_cast(atoi(row[33])); + e.banedmgraceamt = static_cast(atoi(row[34])); + e.banedmgbody = static_cast(atoi(row[35])); + e.banedmgrace = static_cast(atoi(row[36])); + e.bardtype = static_cast(atoi(row[37])); + e.bardvalue = static_cast(atoi(row[38])); + e.book = static_cast(atoi(row[39])); + e.casttime = static_cast(atoi(row[40])); + e.casttime_ = static_cast(atoi(row[41])); + e.charmfile = row[42] ? row[42] : ""; + e.charmfileid = row[43] ? row[43] : ""; + e.classes = static_cast(atoi(row[44])); + e.color = static_cast(strtoul(row[45], nullptr, 10)); + e.combateffects = row[46] ? row[46] : ""; + e.extradmgskill = static_cast(atoi(row[47])); + e.extradmgamt = static_cast(atoi(row[48])); + e.price = static_cast(atoi(row[49])); + e.cr = static_cast(atoi(row[50])); + e.damage = static_cast(atoi(row[51])); + e.damageshield = static_cast(atoi(row[52])); + e.deity = static_cast(atoi(row[53])); + e.delay = static_cast(atoi(row[54])); + e.augdistiller = static_cast(atoi(row[55])); + e.dotshielding = static_cast(atoi(row[56])); + e.dr = static_cast(atoi(row[57])); + e.clicktype = static_cast(atoi(row[58])); + e.clicklevel2 = static_cast(atoi(row[59])); + e.elemdmgtype = static_cast(atoi(row[60])); + e.elemdmgamt = static_cast(atoi(row[61])); + e.endur = static_cast(atoi(row[62])); + e.factionamt1 = static_cast(atoi(row[63])); + e.factionamt2 = static_cast(atoi(row[64])); + e.factionamt3 = static_cast(atoi(row[65])); + e.factionamt4 = static_cast(atoi(row[66])); + e.factionmod1 = static_cast(atoi(row[67])); + e.factionmod2 = static_cast(atoi(row[68])); + e.factionmod3 = static_cast(atoi(row[69])); + e.factionmod4 = static_cast(atoi(row[70])); + e.filename = row[71] ? row[71] : ""; + e.focuseffect = static_cast(atoi(row[72])); + e.fr = static_cast(atoi(row[73])); + e.fvnodrop = static_cast(atoi(row[74])); + e.haste = static_cast(atoi(row[75])); + e.clicklevel = static_cast(atoi(row[76])); + e.hp = static_cast(atoi(row[77])); + e.regen = static_cast(atoi(row[78])); + e.icon = static_cast(atoi(row[79])); + e.idfile = row[80] ? row[80] : ""; + e.itemclass = static_cast(atoi(row[81])); + e.itemtype = static_cast(atoi(row[82])); + e.ldonprice = static_cast(atoi(row[83])); + e.ldontheme = static_cast(atoi(row[84])); + e.ldonsold = static_cast(atoi(row[85])); + e.light = static_cast(atoi(row[86])); + e.lore = row[87] ? row[87] : ""; + e.loregroup = static_cast(atoi(row[88])); + e.magic = static_cast(atoi(row[89])); + e.mana = static_cast(atoi(row[90])); + e.manaregen = static_cast(atoi(row[91])); + e.enduranceregen = static_cast(atoi(row[92])); + e.material = static_cast(atoi(row[93])); + e.herosforgemodel = static_cast(atoi(row[94])); + e.maxcharges = static_cast(atoi(row[95])); + e.mr = static_cast(atoi(row[96])); + e.nodrop = static_cast(atoi(row[97])); + e.norent = static_cast(atoi(row[98])); + e.pendingloreflag = static_cast(strtoul(row[99], nullptr, 10)); + e.pr = static_cast(atoi(row[100])); + e.procrate = static_cast(atoi(row[101])); + e.races = static_cast(atoi(row[102])); + e.range = static_cast(atoi(row[103])); + e.reclevel = static_cast(atoi(row[104])); + e.recskill = static_cast(atoi(row[105])); + e.reqlevel = static_cast(atoi(row[106])); + e.sellrate = strtof(row[107], nullptr); + e.shielding = static_cast(atoi(row[108])); + e.size = static_cast(atoi(row[109])); + e.skillmodtype = static_cast(atoi(row[110])); + e.skillmodvalue = static_cast(atoi(row[111])); + e.slots = static_cast(atoi(row[112])); + e.clickeffect = static_cast(atoi(row[113])); + e.spellshield = static_cast(atoi(row[114])); + e.strikethrough = static_cast(atoi(row[115])); + e.stunresist = static_cast(atoi(row[116])); + e.summonedflag = static_cast(strtoul(row[117], nullptr, 10)); + e.tradeskills = static_cast(atoi(row[118])); + e.favor = static_cast(atoi(row[119])); + e.weight = static_cast(atoi(row[120])); + e.UNK012 = static_cast(atoi(row[121])); + e.UNK013 = static_cast(atoi(row[122])); + e.benefitflag = static_cast(atoi(row[123])); + e.UNK054 = static_cast(atoi(row[124])); + e.UNK059 = static_cast(atoi(row[125])); + e.booktype = static_cast(atoi(row[126])); + e.recastdelay = static_cast(atoi(row[127])); + e.recasttype = static_cast(atoi(row[128])); + e.guildfavor = static_cast(atoi(row[129])); + e.UNK123 = static_cast(atoi(row[130])); + e.UNK124 = static_cast(atoi(row[131])); + e.attuneable = static_cast(atoi(row[132])); + e.nopet = static_cast(atoi(row[133])); + e.updated = strtoll(row[134] ? row[134] : "-1", nullptr, 10); + e.comment = row[135] ? row[135] : ""; + e.UNK127 = static_cast(atoi(row[136])); + e.pointtype = static_cast(atoi(row[137])); + e.potionbelt = static_cast(atoi(row[138])); + e.potionbeltslots = static_cast(atoi(row[139])); + e.stacksize = static_cast(atoi(row[140])); + e.notransfer = static_cast(atoi(row[141])); + e.stackable = static_cast(atoi(row[142])); + e.UNK134 = row[143] ? row[143] : ""; + e.UNK137 = static_cast(atoi(row[144])); + e.proceffect = static_cast(atoi(row[145])); + e.proctype = static_cast(atoi(row[146])); + e.proclevel2 = static_cast(atoi(row[147])); + e.proclevel = static_cast(atoi(row[148])); + e.UNK142 = static_cast(atoi(row[149])); + e.worneffect = static_cast(atoi(row[150])); + e.worntype = static_cast(atoi(row[151])); + e.wornlevel2 = static_cast(atoi(row[152])); + e.wornlevel = static_cast(atoi(row[153])); + e.UNK147 = static_cast(atoi(row[154])); + e.focustype = static_cast(atoi(row[155])); + e.focuslevel2 = static_cast(atoi(row[156])); + e.focuslevel = static_cast(atoi(row[157])); + e.UNK152 = static_cast(atoi(row[158])); + e.scrolleffect = static_cast(atoi(row[159])); + e.scrolltype = static_cast(atoi(row[160])); + e.scrolllevel2 = static_cast(atoi(row[161])); + e.scrolllevel = static_cast(atoi(row[162])); + e.UNK157 = static_cast(atoi(row[163])); + e.serialized = strtoll(row[164] ? row[164] : "-1", nullptr, 10); + e.verified = strtoll(row[165] ? row[165] : "-1", nullptr, 10); + e.serialization = row[166] ? row[166] : ""; + e.source = row[167] ? row[167] : ""; + e.UNK033 = static_cast(atoi(row[168])); + e.lorefile = row[169] ? row[169] : ""; + e.UNK014 = static_cast(atoi(row[170])); + e.svcorruption = static_cast(atoi(row[171])); + e.skillmodmax = static_cast(atoi(row[172])); + e.UNK060 = static_cast(atoi(row[173])); + e.augslot1unk2 = static_cast(atoi(row[174])); + e.augslot2unk2 = static_cast(atoi(row[175])); + e.augslot3unk2 = static_cast(atoi(row[176])); + e.augslot4unk2 = static_cast(atoi(row[177])); + e.augslot5unk2 = static_cast(atoi(row[178])); + e.augslot6unk2 = static_cast(atoi(row[179])); + e.UNK120 = static_cast(atoi(row[180])); + e.UNK121 = static_cast(atoi(row[181])); + e.questitemflag = static_cast(atoi(row[182])); + e.UNK132 = row[183] ? row[183] : ""; + e.clickunk5 = static_cast(atoi(row[184])); + e.clickunk6 = row[185] ? row[185] : ""; + e.clickunk7 = static_cast(atoi(row[186])); + e.procunk1 = static_cast(atoi(row[187])); + e.procunk2 = static_cast(atoi(row[188])); + e.procunk3 = static_cast(atoi(row[189])); + e.procunk4 = static_cast(atoi(row[190])); + e.procunk6 = row[191] ? row[191] : ""; + e.procunk7 = static_cast(atoi(row[192])); + e.wornunk1 = static_cast(atoi(row[193])); + e.wornunk2 = static_cast(atoi(row[194])); + e.wornunk3 = static_cast(atoi(row[195])); + e.wornunk4 = static_cast(atoi(row[196])); + e.wornunk5 = static_cast(atoi(row[197])); + e.wornunk6 = row[198] ? row[198] : ""; + e.wornunk7 = static_cast(atoi(row[199])); + e.focusunk1 = static_cast(atoi(row[200])); + e.focusunk2 = static_cast(atoi(row[201])); + e.focusunk3 = static_cast(atoi(row[202])); + e.focusunk4 = static_cast(atoi(row[203])); + e.focusunk5 = static_cast(atoi(row[204])); + e.focusunk6 = row[205] ? row[205] : ""; + e.focusunk7 = static_cast(atoi(row[206])); + e.scrollunk1 = static_cast(atoi(row[207])); + e.scrollunk2 = static_cast(atoi(row[208])); + e.scrollunk3 = static_cast(atoi(row[209])); + e.scrollunk4 = static_cast(atoi(row[210])); + e.scrollunk5 = static_cast(atoi(row[211])); + e.scrollunk6 = row[212] ? row[212] : ""; + e.scrollunk7 = static_cast(atoi(row[213])); + e.UNK193 = static_cast(atoi(row[214])); + e.purity = static_cast(atoi(row[215])); + e.evoitem = static_cast(atoi(row[216])); + e.evoid = static_cast(atoi(row[217])); + e.evolvinglevel = static_cast(atoi(row[218])); + e.evomax = static_cast(atoi(row[219])); + e.clickname = row[220] ? row[220] : ""; + e.procname = row[221] ? row[221] : ""; + e.wornname = row[222] ? row[222] : ""; + e.focusname = row[223] ? row[223] : ""; + e.scrollname = row[224] ? row[224] : ""; + e.dsmitigation = static_cast(atoi(row[225])); + e.heroic_str = static_cast(atoi(row[226])); + e.heroic_int = static_cast(atoi(row[227])); + e.heroic_wis = static_cast(atoi(row[228])); + e.heroic_agi = static_cast(atoi(row[229])); + e.heroic_dex = static_cast(atoi(row[230])); + e.heroic_sta = static_cast(atoi(row[231])); + e.heroic_cha = static_cast(atoi(row[232])); + e.heroic_pr = static_cast(atoi(row[233])); + e.heroic_dr = static_cast(atoi(row[234])); + e.heroic_fr = static_cast(atoi(row[235])); + e.heroic_cr = static_cast(atoi(row[236])); + e.heroic_mr = static_cast(atoi(row[237])); + e.heroic_svcorrup = static_cast(atoi(row[238])); + e.healamt = static_cast(atoi(row[239])); + e.spelldmg = static_cast(atoi(row[240])); + e.clairvoyance = static_cast(atoi(row[241])); + e.backstabdmg = static_cast(atoi(row[242])); + e.created = row[243] ? row[243] : ""; + e.elitematerial = static_cast(atoi(row[244])); + e.ldonsellbackrate = static_cast(atoi(row[245])); + e.scriptfileid = static_cast(atoi(row[246])); + e.expendablearrow = static_cast(atoi(row[247])); + e.powersourcecapacity = static_cast(atoi(row[248])); + e.bardeffect = static_cast(atoi(row[249])); + e.bardeffecttype = static_cast(atoi(row[250])); + e.bardlevel2 = static_cast(atoi(row[251])); + e.bardlevel = static_cast(atoi(row[252])); + e.bardunk1 = static_cast(atoi(row[253])); + e.bardunk2 = static_cast(atoi(row[254])); + e.bardunk3 = static_cast(atoi(row[255])); + e.bardunk4 = static_cast(atoi(row[256])); + e.bardunk5 = static_cast(atoi(row[257])); + e.bardname = row[258] ? row[258] : ""; + e.bardunk7 = static_cast(atoi(row[259])); + e.UNK214 = static_cast(atoi(row[260])); + e.subtype = static_cast(atoi(row[261])); + e.UNK220 = static_cast(atoi(row[262])); + e.UNK221 = static_cast(atoi(row[263])); + e.heirloom = static_cast(atoi(row[264])); + e.UNK223 = static_cast(atoi(row[265])); + e.UNK224 = static_cast(atoi(row[266])); + e.UNK225 = static_cast(atoi(row[267])); + e.UNK226 = static_cast(atoi(row[268])); + e.UNK227 = static_cast(atoi(row[269])); + e.UNK228 = static_cast(atoi(row[270])); + e.UNK229 = static_cast(atoi(row[271])); + e.UNK230 = static_cast(atoi(row[272])); + e.UNK231 = static_cast(atoi(row[273])); + e.UNK232 = static_cast(atoi(row[274])); + e.UNK233 = static_cast(atoi(row[275])); + e.UNK234 = static_cast(atoi(row[276])); + e.placeable = static_cast(atoi(row[277])); + e.UNK236 = static_cast(atoi(row[278])); + e.UNK237 = static_cast(atoi(row[279])); + e.UNK238 = static_cast(atoi(row[280])); + e.UNK239 = static_cast(atoi(row[281])); + e.UNK240 = static_cast(atoi(row[282])); + e.UNK241 = static_cast(atoi(row[283])); + e.epicitem = static_cast(atoi(row[284])); - return entry; + return e; } return NewEntity(); @@ -1561,306 +1561,306 @@ public: static int UpdateOne( Database& db, - Items items_entry + const Items &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(items_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(items_entry.minstatus)); - update_values.push_back(columns[2] + " = '" + EscapeString(items_entry.Name) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(items_entry.aagi)); - update_values.push_back(columns[4] + " = " + std::to_string(items_entry.ac)); - update_values.push_back(columns[5] + " = " + std::to_string(items_entry.accuracy)); - update_values.push_back(columns[6] + " = " + std::to_string(items_entry.acha)); - update_values.push_back(columns[7] + " = " + std::to_string(items_entry.adex)); - update_values.push_back(columns[8] + " = " + std::to_string(items_entry.aint)); - update_values.push_back(columns[9] + " = " + std::to_string(items_entry.artifactflag)); - update_values.push_back(columns[10] + " = " + std::to_string(items_entry.asta)); - update_values.push_back(columns[11] + " = " + std::to_string(items_entry.astr)); - update_values.push_back(columns[12] + " = " + std::to_string(items_entry.attack)); - update_values.push_back(columns[13] + " = " + std::to_string(items_entry.augrestrict)); - update_values.push_back(columns[14] + " = " + std::to_string(items_entry.augslot1type)); - update_values.push_back(columns[15] + " = " + std::to_string(items_entry.augslot1visible)); - update_values.push_back(columns[16] + " = " + std::to_string(items_entry.augslot2type)); - update_values.push_back(columns[17] + " = " + std::to_string(items_entry.augslot2visible)); - update_values.push_back(columns[18] + " = " + std::to_string(items_entry.augslot3type)); - update_values.push_back(columns[19] + " = " + std::to_string(items_entry.augslot3visible)); - update_values.push_back(columns[20] + " = " + std::to_string(items_entry.augslot4type)); - update_values.push_back(columns[21] + " = " + std::to_string(items_entry.augslot4visible)); - update_values.push_back(columns[22] + " = " + std::to_string(items_entry.augslot5type)); - update_values.push_back(columns[23] + " = " + std::to_string(items_entry.augslot5visible)); - update_values.push_back(columns[24] + " = " + std::to_string(items_entry.augslot6type)); - update_values.push_back(columns[25] + " = " + std::to_string(items_entry.augslot6visible)); - update_values.push_back(columns[26] + " = " + std::to_string(items_entry.augtype)); - update_values.push_back(columns[27] + " = " + std::to_string(items_entry.avoidance)); - update_values.push_back(columns[28] + " = " + std::to_string(items_entry.awis)); - update_values.push_back(columns[29] + " = " + std::to_string(items_entry.bagsize)); - update_values.push_back(columns[30] + " = " + std::to_string(items_entry.bagslots)); - update_values.push_back(columns[31] + " = " + std::to_string(items_entry.bagtype)); - update_values.push_back(columns[32] + " = " + std::to_string(items_entry.bagwr)); - update_values.push_back(columns[33] + " = " + std::to_string(items_entry.banedmgamt)); - update_values.push_back(columns[34] + " = " + std::to_string(items_entry.banedmgraceamt)); - update_values.push_back(columns[35] + " = " + std::to_string(items_entry.banedmgbody)); - update_values.push_back(columns[36] + " = " + std::to_string(items_entry.banedmgrace)); - update_values.push_back(columns[37] + " = " + std::to_string(items_entry.bardtype)); - update_values.push_back(columns[38] + " = " + std::to_string(items_entry.bardvalue)); - update_values.push_back(columns[39] + " = " + std::to_string(items_entry.book)); - update_values.push_back(columns[40] + " = " + std::to_string(items_entry.casttime)); - update_values.push_back(columns[41] + " = " + std::to_string(items_entry.casttime_)); - update_values.push_back(columns[42] + " = '" + EscapeString(items_entry.charmfile) + "'"); - update_values.push_back(columns[43] + " = '" + EscapeString(items_entry.charmfileid) + "'"); - update_values.push_back(columns[44] + " = " + std::to_string(items_entry.classes)); - update_values.push_back(columns[45] + " = " + std::to_string(items_entry.color)); - update_values.push_back(columns[46] + " = '" + EscapeString(items_entry.combateffects) + "'"); - update_values.push_back(columns[47] + " = " + std::to_string(items_entry.extradmgskill)); - update_values.push_back(columns[48] + " = " + std::to_string(items_entry.extradmgamt)); - update_values.push_back(columns[49] + " = " + std::to_string(items_entry.price)); - update_values.push_back(columns[50] + " = " + std::to_string(items_entry.cr)); - update_values.push_back(columns[51] + " = " + std::to_string(items_entry.damage)); - update_values.push_back(columns[52] + " = " + std::to_string(items_entry.damageshield)); - update_values.push_back(columns[53] + " = " + std::to_string(items_entry.deity)); - update_values.push_back(columns[54] + " = " + std::to_string(items_entry.delay)); - update_values.push_back(columns[55] + " = " + std::to_string(items_entry.augdistiller)); - update_values.push_back(columns[56] + " = " + std::to_string(items_entry.dotshielding)); - update_values.push_back(columns[57] + " = " + std::to_string(items_entry.dr)); - update_values.push_back(columns[58] + " = " + std::to_string(items_entry.clicktype)); - update_values.push_back(columns[59] + " = " + std::to_string(items_entry.clicklevel2)); - update_values.push_back(columns[60] + " = " + std::to_string(items_entry.elemdmgtype)); - update_values.push_back(columns[61] + " = " + std::to_string(items_entry.elemdmgamt)); - update_values.push_back(columns[62] + " = " + std::to_string(items_entry.endur)); - update_values.push_back(columns[63] + " = " + std::to_string(items_entry.factionamt1)); - update_values.push_back(columns[64] + " = " + std::to_string(items_entry.factionamt2)); - update_values.push_back(columns[65] + " = " + std::to_string(items_entry.factionamt3)); - update_values.push_back(columns[66] + " = " + std::to_string(items_entry.factionamt4)); - update_values.push_back(columns[67] + " = " + std::to_string(items_entry.factionmod1)); - update_values.push_back(columns[68] + " = " + std::to_string(items_entry.factionmod2)); - update_values.push_back(columns[69] + " = " + std::to_string(items_entry.factionmod3)); - update_values.push_back(columns[70] + " = " + std::to_string(items_entry.factionmod4)); - update_values.push_back(columns[71] + " = '" + EscapeString(items_entry.filename) + "'"); - update_values.push_back(columns[72] + " = " + std::to_string(items_entry.focuseffect)); - update_values.push_back(columns[73] + " = " + std::to_string(items_entry.fr)); - update_values.push_back(columns[74] + " = " + std::to_string(items_entry.fvnodrop)); - update_values.push_back(columns[75] + " = " + std::to_string(items_entry.haste)); - update_values.push_back(columns[76] + " = " + std::to_string(items_entry.clicklevel)); - update_values.push_back(columns[77] + " = " + std::to_string(items_entry.hp)); - update_values.push_back(columns[78] + " = " + std::to_string(items_entry.regen)); - update_values.push_back(columns[79] + " = " + std::to_string(items_entry.icon)); - update_values.push_back(columns[80] + " = '" + EscapeString(items_entry.idfile) + "'"); - update_values.push_back(columns[81] + " = " + std::to_string(items_entry.itemclass)); - update_values.push_back(columns[82] + " = " + std::to_string(items_entry.itemtype)); - update_values.push_back(columns[83] + " = " + std::to_string(items_entry.ldonprice)); - update_values.push_back(columns[84] + " = " + std::to_string(items_entry.ldontheme)); - update_values.push_back(columns[85] + " = " + std::to_string(items_entry.ldonsold)); - update_values.push_back(columns[86] + " = " + std::to_string(items_entry.light)); - update_values.push_back(columns[87] + " = '" + EscapeString(items_entry.lore) + "'"); - update_values.push_back(columns[88] + " = " + std::to_string(items_entry.loregroup)); - update_values.push_back(columns[89] + " = " + std::to_string(items_entry.magic)); - update_values.push_back(columns[90] + " = " + std::to_string(items_entry.mana)); - update_values.push_back(columns[91] + " = " + std::to_string(items_entry.manaregen)); - update_values.push_back(columns[92] + " = " + std::to_string(items_entry.enduranceregen)); - update_values.push_back(columns[93] + " = " + std::to_string(items_entry.material)); - update_values.push_back(columns[94] + " = " + std::to_string(items_entry.herosforgemodel)); - update_values.push_back(columns[95] + " = " + std::to_string(items_entry.maxcharges)); - update_values.push_back(columns[96] + " = " + std::to_string(items_entry.mr)); - update_values.push_back(columns[97] + " = " + std::to_string(items_entry.nodrop)); - update_values.push_back(columns[98] + " = " + std::to_string(items_entry.norent)); - update_values.push_back(columns[99] + " = " + std::to_string(items_entry.pendingloreflag)); - update_values.push_back(columns[100] + " = " + std::to_string(items_entry.pr)); - update_values.push_back(columns[101] + " = " + std::to_string(items_entry.procrate)); - update_values.push_back(columns[102] + " = " + std::to_string(items_entry.races)); - update_values.push_back(columns[103] + " = " + std::to_string(items_entry.range)); - update_values.push_back(columns[104] + " = " + std::to_string(items_entry.reclevel)); - update_values.push_back(columns[105] + " = " + std::to_string(items_entry.recskill)); - update_values.push_back(columns[106] + " = " + std::to_string(items_entry.reqlevel)); - update_values.push_back(columns[107] + " = " + std::to_string(items_entry.sellrate)); - update_values.push_back(columns[108] + " = " + std::to_string(items_entry.shielding)); - update_values.push_back(columns[109] + " = " + std::to_string(items_entry.size)); - update_values.push_back(columns[110] + " = " + std::to_string(items_entry.skillmodtype)); - update_values.push_back(columns[111] + " = " + std::to_string(items_entry.skillmodvalue)); - update_values.push_back(columns[112] + " = " + std::to_string(items_entry.slots)); - update_values.push_back(columns[113] + " = " + std::to_string(items_entry.clickeffect)); - update_values.push_back(columns[114] + " = " + std::to_string(items_entry.spellshield)); - update_values.push_back(columns[115] + " = " + std::to_string(items_entry.strikethrough)); - update_values.push_back(columns[116] + " = " + std::to_string(items_entry.stunresist)); - update_values.push_back(columns[117] + " = " + std::to_string(items_entry.summonedflag)); - update_values.push_back(columns[118] + " = " + std::to_string(items_entry.tradeskills)); - update_values.push_back(columns[119] + " = " + std::to_string(items_entry.favor)); - update_values.push_back(columns[120] + " = " + std::to_string(items_entry.weight)); - update_values.push_back(columns[121] + " = " + std::to_string(items_entry.UNK012)); - update_values.push_back(columns[122] + " = " + std::to_string(items_entry.UNK013)); - update_values.push_back(columns[123] + " = " + std::to_string(items_entry.benefitflag)); - update_values.push_back(columns[124] + " = " + std::to_string(items_entry.UNK054)); - update_values.push_back(columns[125] + " = " + std::to_string(items_entry.UNK059)); - update_values.push_back(columns[126] + " = " + std::to_string(items_entry.booktype)); - update_values.push_back(columns[127] + " = " + std::to_string(items_entry.recastdelay)); - update_values.push_back(columns[128] + " = " + std::to_string(items_entry.recasttype)); - update_values.push_back(columns[129] + " = " + std::to_string(items_entry.guildfavor)); - update_values.push_back(columns[130] + " = " + std::to_string(items_entry.UNK123)); - update_values.push_back(columns[131] + " = " + std::to_string(items_entry.UNK124)); - update_values.push_back(columns[132] + " = " + std::to_string(items_entry.attuneable)); - update_values.push_back(columns[133] + " = " + std::to_string(items_entry.nopet)); - update_values.push_back(columns[134] + " = FROM_UNIXTIME(" + (items_entry.updated > 0 ? std::to_string(items_entry.updated) : "null") + ")"); - update_values.push_back(columns[135] + " = '" + EscapeString(items_entry.comment) + "'"); - update_values.push_back(columns[136] + " = " + std::to_string(items_entry.UNK127)); - update_values.push_back(columns[137] + " = " + std::to_string(items_entry.pointtype)); - update_values.push_back(columns[138] + " = " + std::to_string(items_entry.potionbelt)); - update_values.push_back(columns[139] + " = " + std::to_string(items_entry.potionbeltslots)); - update_values.push_back(columns[140] + " = " + std::to_string(items_entry.stacksize)); - update_values.push_back(columns[141] + " = " + std::to_string(items_entry.notransfer)); - update_values.push_back(columns[142] + " = " + std::to_string(items_entry.stackable)); - update_values.push_back(columns[143] + " = '" + EscapeString(items_entry.UNK134) + "'"); - update_values.push_back(columns[144] + " = " + std::to_string(items_entry.UNK137)); - update_values.push_back(columns[145] + " = " + std::to_string(items_entry.proceffect)); - update_values.push_back(columns[146] + " = " + std::to_string(items_entry.proctype)); - update_values.push_back(columns[147] + " = " + std::to_string(items_entry.proclevel2)); - update_values.push_back(columns[148] + " = " + std::to_string(items_entry.proclevel)); - update_values.push_back(columns[149] + " = " + std::to_string(items_entry.UNK142)); - update_values.push_back(columns[150] + " = " + std::to_string(items_entry.worneffect)); - update_values.push_back(columns[151] + " = " + std::to_string(items_entry.worntype)); - update_values.push_back(columns[152] + " = " + std::to_string(items_entry.wornlevel2)); - update_values.push_back(columns[153] + " = " + std::to_string(items_entry.wornlevel)); - update_values.push_back(columns[154] + " = " + std::to_string(items_entry.UNK147)); - update_values.push_back(columns[155] + " = " + std::to_string(items_entry.focustype)); - update_values.push_back(columns[156] + " = " + std::to_string(items_entry.focuslevel2)); - update_values.push_back(columns[157] + " = " + std::to_string(items_entry.focuslevel)); - update_values.push_back(columns[158] + " = " + std::to_string(items_entry.UNK152)); - update_values.push_back(columns[159] + " = " + std::to_string(items_entry.scrolleffect)); - update_values.push_back(columns[160] + " = " + std::to_string(items_entry.scrolltype)); - update_values.push_back(columns[161] + " = " + std::to_string(items_entry.scrolllevel2)); - update_values.push_back(columns[162] + " = " + std::to_string(items_entry.scrolllevel)); - update_values.push_back(columns[163] + " = " + std::to_string(items_entry.UNK157)); - update_values.push_back(columns[164] + " = FROM_UNIXTIME(" + (items_entry.serialized > 0 ? std::to_string(items_entry.serialized) : "null") + ")"); - update_values.push_back(columns[165] + " = FROM_UNIXTIME(" + (items_entry.verified > 0 ? std::to_string(items_entry.verified) : "null") + ")"); - update_values.push_back(columns[166] + " = '" + EscapeString(items_entry.serialization) + "'"); - update_values.push_back(columns[167] + " = '" + EscapeString(items_entry.source) + "'"); - update_values.push_back(columns[168] + " = " + std::to_string(items_entry.UNK033)); - update_values.push_back(columns[169] + " = '" + EscapeString(items_entry.lorefile) + "'"); - update_values.push_back(columns[170] + " = " + std::to_string(items_entry.UNK014)); - update_values.push_back(columns[171] + " = " + std::to_string(items_entry.svcorruption)); - update_values.push_back(columns[172] + " = " + std::to_string(items_entry.skillmodmax)); - update_values.push_back(columns[173] + " = " + std::to_string(items_entry.UNK060)); - update_values.push_back(columns[174] + " = " + std::to_string(items_entry.augslot1unk2)); - update_values.push_back(columns[175] + " = " + std::to_string(items_entry.augslot2unk2)); - update_values.push_back(columns[176] + " = " + std::to_string(items_entry.augslot3unk2)); - update_values.push_back(columns[177] + " = " + std::to_string(items_entry.augslot4unk2)); - update_values.push_back(columns[178] + " = " + std::to_string(items_entry.augslot5unk2)); - update_values.push_back(columns[179] + " = " + std::to_string(items_entry.augslot6unk2)); - update_values.push_back(columns[180] + " = " + std::to_string(items_entry.UNK120)); - update_values.push_back(columns[181] + " = " + std::to_string(items_entry.UNK121)); - update_values.push_back(columns[182] + " = " + std::to_string(items_entry.questitemflag)); - update_values.push_back(columns[183] + " = '" + EscapeString(items_entry.UNK132) + "'"); - update_values.push_back(columns[184] + " = " + std::to_string(items_entry.clickunk5)); - update_values.push_back(columns[185] + " = '" + EscapeString(items_entry.clickunk6) + "'"); - update_values.push_back(columns[186] + " = " + std::to_string(items_entry.clickunk7)); - update_values.push_back(columns[187] + " = " + std::to_string(items_entry.procunk1)); - update_values.push_back(columns[188] + " = " + std::to_string(items_entry.procunk2)); - update_values.push_back(columns[189] + " = " + std::to_string(items_entry.procunk3)); - update_values.push_back(columns[190] + " = " + std::to_string(items_entry.procunk4)); - update_values.push_back(columns[191] + " = '" + EscapeString(items_entry.procunk6) + "'"); - update_values.push_back(columns[192] + " = " + std::to_string(items_entry.procunk7)); - update_values.push_back(columns[193] + " = " + std::to_string(items_entry.wornunk1)); - update_values.push_back(columns[194] + " = " + std::to_string(items_entry.wornunk2)); - update_values.push_back(columns[195] + " = " + std::to_string(items_entry.wornunk3)); - update_values.push_back(columns[196] + " = " + std::to_string(items_entry.wornunk4)); - update_values.push_back(columns[197] + " = " + std::to_string(items_entry.wornunk5)); - update_values.push_back(columns[198] + " = '" + EscapeString(items_entry.wornunk6) + "'"); - update_values.push_back(columns[199] + " = " + std::to_string(items_entry.wornunk7)); - update_values.push_back(columns[200] + " = " + std::to_string(items_entry.focusunk1)); - update_values.push_back(columns[201] + " = " + std::to_string(items_entry.focusunk2)); - update_values.push_back(columns[202] + " = " + std::to_string(items_entry.focusunk3)); - update_values.push_back(columns[203] + " = " + std::to_string(items_entry.focusunk4)); - update_values.push_back(columns[204] + " = " + std::to_string(items_entry.focusunk5)); - update_values.push_back(columns[205] + " = '" + EscapeString(items_entry.focusunk6) + "'"); - update_values.push_back(columns[206] + " = " + std::to_string(items_entry.focusunk7)); - update_values.push_back(columns[207] + " = " + std::to_string(items_entry.scrollunk1)); - update_values.push_back(columns[208] + " = " + std::to_string(items_entry.scrollunk2)); - update_values.push_back(columns[209] + " = " + std::to_string(items_entry.scrollunk3)); - update_values.push_back(columns[210] + " = " + std::to_string(items_entry.scrollunk4)); - update_values.push_back(columns[211] + " = " + std::to_string(items_entry.scrollunk5)); - update_values.push_back(columns[212] + " = '" + EscapeString(items_entry.scrollunk6) + "'"); - update_values.push_back(columns[213] + " = " + std::to_string(items_entry.scrollunk7)); - update_values.push_back(columns[214] + " = " + std::to_string(items_entry.UNK193)); - update_values.push_back(columns[215] + " = " + std::to_string(items_entry.purity)); - update_values.push_back(columns[216] + " = " + std::to_string(items_entry.evoitem)); - update_values.push_back(columns[217] + " = " + std::to_string(items_entry.evoid)); - update_values.push_back(columns[218] + " = " + std::to_string(items_entry.evolvinglevel)); - update_values.push_back(columns[219] + " = " + std::to_string(items_entry.evomax)); - update_values.push_back(columns[220] + " = '" + EscapeString(items_entry.clickname) + "'"); - update_values.push_back(columns[221] + " = '" + EscapeString(items_entry.procname) + "'"); - update_values.push_back(columns[222] + " = '" + EscapeString(items_entry.wornname) + "'"); - update_values.push_back(columns[223] + " = '" + EscapeString(items_entry.focusname) + "'"); - update_values.push_back(columns[224] + " = '" + EscapeString(items_entry.scrollname) + "'"); - update_values.push_back(columns[225] + " = " + std::to_string(items_entry.dsmitigation)); - update_values.push_back(columns[226] + " = " + std::to_string(items_entry.heroic_str)); - update_values.push_back(columns[227] + " = " + std::to_string(items_entry.heroic_int)); - update_values.push_back(columns[228] + " = " + std::to_string(items_entry.heroic_wis)); - update_values.push_back(columns[229] + " = " + std::to_string(items_entry.heroic_agi)); - update_values.push_back(columns[230] + " = " + std::to_string(items_entry.heroic_dex)); - update_values.push_back(columns[231] + " = " + std::to_string(items_entry.heroic_sta)); - update_values.push_back(columns[232] + " = " + std::to_string(items_entry.heroic_cha)); - update_values.push_back(columns[233] + " = " + std::to_string(items_entry.heroic_pr)); - update_values.push_back(columns[234] + " = " + std::to_string(items_entry.heroic_dr)); - update_values.push_back(columns[235] + " = " + std::to_string(items_entry.heroic_fr)); - update_values.push_back(columns[236] + " = " + std::to_string(items_entry.heroic_cr)); - update_values.push_back(columns[237] + " = " + std::to_string(items_entry.heroic_mr)); - update_values.push_back(columns[238] + " = " + std::to_string(items_entry.heroic_svcorrup)); - update_values.push_back(columns[239] + " = " + std::to_string(items_entry.healamt)); - update_values.push_back(columns[240] + " = " + std::to_string(items_entry.spelldmg)); - update_values.push_back(columns[241] + " = " + std::to_string(items_entry.clairvoyance)); - update_values.push_back(columns[242] + " = " + std::to_string(items_entry.backstabdmg)); - update_values.push_back(columns[243] + " = '" + EscapeString(items_entry.created) + "'"); - update_values.push_back(columns[244] + " = " + std::to_string(items_entry.elitematerial)); - update_values.push_back(columns[245] + " = " + std::to_string(items_entry.ldonsellbackrate)); - update_values.push_back(columns[246] + " = " + std::to_string(items_entry.scriptfileid)); - update_values.push_back(columns[247] + " = " + std::to_string(items_entry.expendablearrow)); - update_values.push_back(columns[248] + " = " + std::to_string(items_entry.powersourcecapacity)); - update_values.push_back(columns[249] + " = " + std::to_string(items_entry.bardeffect)); - update_values.push_back(columns[250] + " = " + std::to_string(items_entry.bardeffecttype)); - update_values.push_back(columns[251] + " = " + std::to_string(items_entry.bardlevel2)); - update_values.push_back(columns[252] + " = " + std::to_string(items_entry.bardlevel)); - update_values.push_back(columns[253] + " = " + std::to_string(items_entry.bardunk1)); - update_values.push_back(columns[254] + " = " + std::to_string(items_entry.bardunk2)); - update_values.push_back(columns[255] + " = " + std::to_string(items_entry.bardunk3)); - update_values.push_back(columns[256] + " = " + std::to_string(items_entry.bardunk4)); - update_values.push_back(columns[257] + " = " + std::to_string(items_entry.bardunk5)); - update_values.push_back(columns[258] + " = '" + EscapeString(items_entry.bardname) + "'"); - update_values.push_back(columns[259] + " = " + std::to_string(items_entry.bardunk7)); - update_values.push_back(columns[260] + " = " + std::to_string(items_entry.UNK214)); - update_values.push_back(columns[261] + " = " + std::to_string(items_entry.subtype)); - update_values.push_back(columns[262] + " = " + std::to_string(items_entry.UNK220)); - update_values.push_back(columns[263] + " = " + std::to_string(items_entry.UNK221)); - update_values.push_back(columns[264] + " = " + std::to_string(items_entry.heirloom)); - update_values.push_back(columns[265] + " = " + std::to_string(items_entry.UNK223)); - update_values.push_back(columns[266] + " = " + std::to_string(items_entry.UNK224)); - update_values.push_back(columns[267] + " = " + std::to_string(items_entry.UNK225)); - update_values.push_back(columns[268] + " = " + std::to_string(items_entry.UNK226)); - update_values.push_back(columns[269] + " = " + std::to_string(items_entry.UNK227)); - update_values.push_back(columns[270] + " = " + std::to_string(items_entry.UNK228)); - update_values.push_back(columns[271] + " = " + std::to_string(items_entry.UNK229)); - update_values.push_back(columns[272] + " = " + std::to_string(items_entry.UNK230)); - update_values.push_back(columns[273] + " = " + std::to_string(items_entry.UNK231)); - update_values.push_back(columns[274] + " = " + std::to_string(items_entry.UNK232)); - update_values.push_back(columns[275] + " = " + std::to_string(items_entry.UNK233)); - update_values.push_back(columns[276] + " = " + std::to_string(items_entry.UNK234)); - update_values.push_back(columns[277] + " = " + std::to_string(items_entry.placeable)); - update_values.push_back(columns[278] + " = " + std::to_string(items_entry.UNK236)); - update_values.push_back(columns[279] + " = " + std::to_string(items_entry.UNK237)); - update_values.push_back(columns[280] + " = " + std::to_string(items_entry.UNK238)); - update_values.push_back(columns[281] + " = " + std::to_string(items_entry.UNK239)); - update_values.push_back(columns[282] + " = " + std::to_string(items_entry.UNK240)); - update_values.push_back(columns[283] + " = " + std::to_string(items_entry.UNK241)); - update_values.push_back(columns[284] + " = " + std::to_string(items_entry.epicitem)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.minstatus)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.Name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.aagi)); + v.push_back(columns[4] + " = " + std::to_string(e.ac)); + v.push_back(columns[5] + " = " + std::to_string(e.accuracy)); + v.push_back(columns[6] + " = " + std::to_string(e.acha)); + v.push_back(columns[7] + " = " + std::to_string(e.adex)); + v.push_back(columns[8] + " = " + std::to_string(e.aint)); + v.push_back(columns[9] + " = " + std::to_string(e.artifactflag)); + v.push_back(columns[10] + " = " + std::to_string(e.asta)); + v.push_back(columns[11] + " = " + std::to_string(e.astr)); + v.push_back(columns[12] + " = " + std::to_string(e.attack)); + v.push_back(columns[13] + " = " + std::to_string(e.augrestrict)); + v.push_back(columns[14] + " = " + std::to_string(e.augslot1type)); + v.push_back(columns[15] + " = " + std::to_string(e.augslot1visible)); + v.push_back(columns[16] + " = " + std::to_string(e.augslot2type)); + v.push_back(columns[17] + " = " + std::to_string(e.augslot2visible)); + v.push_back(columns[18] + " = " + std::to_string(e.augslot3type)); + v.push_back(columns[19] + " = " + std::to_string(e.augslot3visible)); + v.push_back(columns[20] + " = " + std::to_string(e.augslot4type)); + v.push_back(columns[21] + " = " + std::to_string(e.augslot4visible)); + v.push_back(columns[22] + " = " + std::to_string(e.augslot5type)); + v.push_back(columns[23] + " = " + std::to_string(e.augslot5visible)); + v.push_back(columns[24] + " = " + std::to_string(e.augslot6type)); + v.push_back(columns[25] + " = " + std::to_string(e.augslot6visible)); + v.push_back(columns[26] + " = " + std::to_string(e.augtype)); + v.push_back(columns[27] + " = " + std::to_string(e.avoidance)); + v.push_back(columns[28] + " = " + std::to_string(e.awis)); + v.push_back(columns[29] + " = " + std::to_string(e.bagsize)); + v.push_back(columns[30] + " = " + std::to_string(e.bagslots)); + v.push_back(columns[31] + " = " + std::to_string(e.bagtype)); + v.push_back(columns[32] + " = " + std::to_string(e.bagwr)); + v.push_back(columns[33] + " = " + std::to_string(e.banedmgamt)); + v.push_back(columns[34] + " = " + std::to_string(e.banedmgraceamt)); + v.push_back(columns[35] + " = " + std::to_string(e.banedmgbody)); + v.push_back(columns[36] + " = " + std::to_string(e.banedmgrace)); + v.push_back(columns[37] + " = " + std::to_string(e.bardtype)); + v.push_back(columns[38] + " = " + std::to_string(e.bardvalue)); + v.push_back(columns[39] + " = " + std::to_string(e.book)); + v.push_back(columns[40] + " = " + std::to_string(e.casttime)); + v.push_back(columns[41] + " = " + std::to_string(e.casttime_)); + v.push_back(columns[42] + " = '" + Strings::Escape(e.charmfile) + "'"); + v.push_back(columns[43] + " = '" + Strings::Escape(e.charmfileid) + "'"); + v.push_back(columns[44] + " = " + std::to_string(e.classes)); + v.push_back(columns[45] + " = " + std::to_string(e.color)); + v.push_back(columns[46] + " = '" + Strings::Escape(e.combateffects) + "'"); + v.push_back(columns[47] + " = " + std::to_string(e.extradmgskill)); + v.push_back(columns[48] + " = " + std::to_string(e.extradmgamt)); + v.push_back(columns[49] + " = " + std::to_string(e.price)); + v.push_back(columns[50] + " = " + std::to_string(e.cr)); + v.push_back(columns[51] + " = " + std::to_string(e.damage)); + v.push_back(columns[52] + " = " + std::to_string(e.damageshield)); + v.push_back(columns[53] + " = " + std::to_string(e.deity)); + v.push_back(columns[54] + " = " + std::to_string(e.delay)); + v.push_back(columns[55] + " = " + std::to_string(e.augdistiller)); + v.push_back(columns[56] + " = " + std::to_string(e.dotshielding)); + v.push_back(columns[57] + " = " + std::to_string(e.dr)); + v.push_back(columns[58] + " = " + std::to_string(e.clicktype)); + v.push_back(columns[59] + " = " + std::to_string(e.clicklevel2)); + v.push_back(columns[60] + " = " + std::to_string(e.elemdmgtype)); + v.push_back(columns[61] + " = " + std::to_string(e.elemdmgamt)); + v.push_back(columns[62] + " = " + std::to_string(e.endur)); + v.push_back(columns[63] + " = " + std::to_string(e.factionamt1)); + v.push_back(columns[64] + " = " + std::to_string(e.factionamt2)); + v.push_back(columns[65] + " = " + std::to_string(e.factionamt3)); + v.push_back(columns[66] + " = " + std::to_string(e.factionamt4)); + v.push_back(columns[67] + " = " + std::to_string(e.factionmod1)); + v.push_back(columns[68] + " = " + std::to_string(e.factionmod2)); + v.push_back(columns[69] + " = " + std::to_string(e.factionmod3)); + v.push_back(columns[70] + " = " + std::to_string(e.factionmod4)); + v.push_back(columns[71] + " = '" + Strings::Escape(e.filename) + "'"); + v.push_back(columns[72] + " = " + std::to_string(e.focuseffect)); + v.push_back(columns[73] + " = " + std::to_string(e.fr)); + v.push_back(columns[74] + " = " + std::to_string(e.fvnodrop)); + v.push_back(columns[75] + " = " + std::to_string(e.haste)); + v.push_back(columns[76] + " = " + std::to_string(e.clicklevel)); + v.push_back(columns[77] + " = " + std::to_string(e.hp)); + v.push_back(columns[78] + " = " + std::to_string(e.regen)); + v.push_back(columns[79] + " = " + std::to_string(e.icon)); + v.push_back(columns[80] + " = '" + Strings::Escape(e.idfile) + "'"); + v.push_back(columns[81] + " = " + std::to_string(e.itemclass)); + v.push_back(columns[82] + " = " + std::to_string(e.itemtype)); + v.push_back(columns[83] + " = " + std::to_string(e.ldonprice)); + v.push_back(columns[84] + " = " + std::to_string(e.ldontheme)); + v.push_back(columns[85] + " = " + std::to_string(e.ldonsold)); + v.push_back(columns[86] + " = " + std::to_string(e.light)); + v.push_back(columns[87] + " = '" + Strings::Escape(e.lore) + "'"); + v.push_back(columns[88] + " = " + std::to_string(e.loregroup)); + v.push_back(columns[89] + " = " + std::to_string(e.magic)); + v.push_back(columns[90] + " = " + std::to_string(e.mana)); + v.push_back(columns[91] + " = " + std::to_string(e.manaregen)); + v.push_back(columns[92] + " = " + std::to_string(e.enduranceregen)); + v.push_back(columns[93] + " = " + std::to_string(e.material)); + v.push_back(columns[94] + " = " + std::to_string(e.herosforgemodel)); + v.push_back(columns[95] + " = " + std::to_string(e.maxcharges)); + v.push_back(columns[96] + " = " + std::to_string(e.mr)); + v.push_back(columns[97] + " = " + std::to_string(e.nodrop)); + v.push_back(columns[98] + " = " + std::to_string(e.norent)); + v.push_back(columns[99] + " = " + std::to_string(e.pendingloreflag)); + v.push_back(columns[100] + " = " + std::to_string(e.pr)); + v.push_back(columns[101] + " = " + std::to_string(e.procrate)); + v.push_back(columns[102] + " = " + std::to_string(e.races)); + v.push_back(columns[103] + " = " + std::to_string(e.range)); + v.push_back(columns[104] + " = " + std::to_string(e.reclevel)); + v.push_back(columns[105] + " = " + std::to_string(e.recskill)); + v.push_back(columns[106] + " = " + std::to_string(e.reqlevel)); + v.push_back(columns[107] + " = " + std::to_string(e.sellrate)); + v.push_back(columns[108] + " = " + std::to_string(e.shielding)); + v.push_back(columns[109] + " = " + std::to_string(e.size)); + v.push_back(columns[110] + " = " + std::to_string(e.skillmodtype)); + v.push_back(columns[111] + " = " + std::to_string(e.skillmodvalue)); + v.push_back(columns[112] + " = " + std::to_string(e.slots)); + v.push_back(columns[113] + " = " + std::to_string(e.clickeffect)); + v.push_back(columns[114] + " = " + std::to_string(e.spellshield)); + v.push_back(columns[115] + " = " + std::to_string(e.strikethrough)); + v.push_back(columns[116] + " = " + std::to_string(e.stunresist)); + v.push_back(columns[117] + " = " + std::to_string(e.summonedflag)); + v.push_back(columns[118] + " = " + std::to_string(e.tradeskills)); + v.push_back(columns[119] + " = " + std::to_string(e.favor)); + v.push_back(columns[120] + " = " + std::to_string(e.weight)); + v.push_back(columns[121] + " = " + std::to_string(e.UNK012)); + v.push_back(columns[122] + " = " + std::to_string(e.UNK013)); + v.push_back(columns[123] + " = " + std::to_string(e.benefitflag)); + v.push_back(columns[124] + " = " + std::to_string(e.UNK054)); + v.push_back(columns[125] + " = " + std::to_string(e.UNK059)); + v.push_back(columns[126] + " = " + std::to_string(e.booktype)); + v.push_back(columns[127] + " = " + std::to_string(e.recastdelay)); + v.push_back(columns[128] + " = " + std::to_string(e.recasttype)); + v.push_back(columns[129] + " = " + std::to_string(e.guildfavor)); + v.push_back(columns[130] + " = " + std::to_string(e.UNK123)); + v.push_back(columns[131] + " = " + std::to_string(e.UNK124)); + v.push_back(columns[132] + " = " + std::to_string(e.attuneable)); + v.push_back(columns[133] + " = " + std::to_string(e.nopet)); + v.push_back(columns[134] + " = FROM_UNIXTIME(" + (e.updated > 0 ? std::to_string(e.updated) : "null") + ")"); + v.push_back(columns[135] + " = '" + Strings::Escape(e.comment) + "'"); + v.push_back(columns[136] + " = " + std::to_string(e.UNK127)); + v.push_back(columns[137] + " = " + std::to_string(e.pointtype)); + v.push_back(columns[138] + " = " + std::to_string(e.potionbelt)); + v.push_back(columns[139] + " = " + std::to_string(e.potionbeltslots)); + v.push_back(columns[140] + " = " + std::to_string(e.stacksize)); + v.push_back(columns[141] + " = " + std::to_string(e.notransfer)); + v.push_back(columns[142] + " = " + std::to_string(e.stackable)); + v.push_back(columns[143] + " = '" + Strings::Escape(e.UNK134) + "'"); + v.push_back(columns[144] + " = " + std::to_string(e.UNK137)); + v.push_back(columns[145] + " = " + std::to_string(e.proceffect)); + v.push_back(columns[146] + " = " + std::to_string(e.proctype)); + v.push_back(columns[147] + " = " + std::to_string(e.proclevel2)); + v.push_back(columns[148] + " = " + std::to_string(e.proclevel)); + v.push_back(columns[149] + " = " + std::to_string(e.UNK142)); + v.push_back(columns[150] + " = " + std::to_string(e.worneffect)); + v.push_back(columns[151] + " = " + std::to_string(e.worntype)); + v.push_back(columns[152] + " = " + std::to_string(e.wornlevel2)); + v.push_back(columns[153] + " = " + std::to_string(e.wornlevel)); + v.push_back(columns[154] + " = " + std::to_string(e.UNK147)); + v.push_back(columns[155] + " = " + std::to_string(e.focustype)); + v.push_back(columns[156] + " = " + std::to_string(e.focuslevel2)); + v.push_back(columns[157] + " = " + std::to_string(e.focuslevel)); + v.push_back(columns[158] + " = " + std::to_string(e.UNK152)); + v.push_back(columns[159] + " = " + std::to_string(e.scrolleffect)); + v.push_back(columns[160] + " = " + std::to_string(e.scrolltype)); + v.push_back(columns[161] + " = " + std::to_string(e.scrolllevel2)); + v.push_back(columns[162] + " = " + std::to_string(e.scrolllevel)); + v.push_back(columns[163] + " = " + std::to_string(e.UNK157)); + v.push_back(columns[164] + " = FROM_UNIXTIME(" + (e.serialized > 0 ? std::to_string(e.serialized) : "null") + ")"); + v.push_back(columns[165] + " = FROM_UNIXTIME(" + (e.verified > 0 ? std::to_string(e.verified) : "null") + ")"); + v.push_back(columns[166] + " = '" + Strings::Escape(e.serialization) + "'"); + v.push_back(columns[167] + " = '" + Strings::Escape(e.source) + "'"); + v.push_back(columns[168] + " = " + std::to_string(e.UNK033)); + v.push_back(columns[169] + " = '" + Strings::Escape(e.lorefile) + "'"); + v.push_back(columns[170] + " = " + std::to_string(e.UNK014)); + v.push_back(columns[171] + " = " + std::to_string(e.svcorruption)); + v.push_back(columns[172] + " = " + std::to_string(e.skillmodmax)); + v.push_back(columns[173] + " = " + std::to_string(e.UNK060)); + v.push_back(columns[174] + " = " + std::to_string(e.augslot1unk2)); + v.push_back(columns[175] + " = " + std::to_string(e.augslot2unk2)); + v.push_back(columns[176] + " = " + std::to_string(e.augslot3unk2)); + v.push_back(columns[177] + " = " + std::to_string(e.augslot4unk2)); + v.push_back(columns[178] + " = " + std::to_string(e.augslot5unk2)); + v.push_back(columns[179] + " = " + std::to_string(e.augslot6unk2)); + v.push_back(columns[180] + " = " + std::to_string(e.UNK120)); + v.push_back(columns[181] + " = " + std::to_string(e.UNK121)); + v.push_back(columns[182] + " = " + std::to_string(e.questitemflag)); + v.push_back(columns[183] + " = '" + Strings::Escape(e.UNK132) + "'"); + v.push_back(columns[184] + " = " + std::to_string(e.clickunk5)); + v.push_back(columns[185] + " = '" + Strings::Escape(e.clickunk6) + "'"); + v.push_back(columns[186] + " = " + std::to_string(e.clickunk7)); + v.push_back(columns[187] + " = " + std::to_string(e.procunk1)); + v.push_back(columns[188] + " = " + std::to_string(e.procunk2)); + v.push_back(columns[189] + " = " + std::to_string(e.procunk3)); + v.push_back(columns[190] + " = " + std::to_string(e.procunk4)); + v.push_back(columns[191] + " = '" + Strings::Escape(e.procunk6) + "'"); + v.push_back(columns[192] + " = " + std::to_string(e.procunk7)); + v.push_back(columns[193] + " = " + std::to_string(e.wornunk1)); + v.push_back(columns[194] + " = " + std::to_string(e.wornunk2)); + v.push_back(columns[195] + " = " + std::to_string(e.wornunk3)); + v.push_back(columns[196] + " = " + std::to_string(e.wornunk4)); + v.push_back(columns[197] + " = " + std::to_string(e.wornunk5)); + v.push_back(columns[198] + " = '" + Strings::Escape(e.wornunk6) + "'"); + v.push_back(columns[199] + " = " + std::to_string(e.wornunk7)); + v.push_back(columns[200] + " = " + std::to_string(e.focusunk1)); + v.push_back(columns[201] + " = " + std::to_string(e.focusunk2)); + v.push_back(columns[202] + " = " + std::to_string(e.focusunk3)); + v.push_back(columns[203] + " = " + std::to_string(e.focusunk4)); + v.push_back(columns[204] + " = " + std::to_string(e.focusunk5)); + v.push_back(columns[205] + " = '" + Strings::Escape(e.focusunk6) + "'"); + v.push_back(columns[206] + " = " + std::to_string(e.focusunk7)); + v.push_back(columns[207] + " = " + std::to_string(e.scrollunk1)); + v.push_back(columns[208] + " = " + std::to_string(e.scrollunk2)); + v.push_back(columns[209] + " = " + std::to_string(e.scrollunk3)); + v.push_back(columns[210] + " = " + std::to_string(e.scrollunk4)); + v.push_back(columns[211] + " = " + std::to_string(e.scrollunk5)); + v.push_back(columns[212] + " = '" + Strings::Escape(e.scrollunk6) + "'"); + v.push_back(columns[213] + " = " + std::to_string(e.scrollunk7)); + v.push_back(columns[214] + " = " + std::to_string(e.UNK193)); + v.push_back(columns[215] + " = " + std::to_string(e.purity)); + v.push_back(columns[216] + " = " + std::to_string(e.evoitem)); + v.push_back(columns[217] + " = " + std::to_string(e.evoid)); + v.push_back(columns[218] + " = " + std::to_string(e.evolvinglevel)); + v.push_back(columns[219] + " = " + std::to_string(e.evomax)); + v.push_back(columns[220] + " = '" + Strings::Escape(e.clickname) + "'"); + v.push_back(columns[221] + " = '" + Strings::Escape(e.procname) + "'"); + v.push_back(columns[222] + " = '" + Strings::Escape(e.wornname) + "'"); + v.push_back(columns[223] + " = '" + Strings::Escape(e.focusname) + "'"); + v.push_back(columns[224] + " = '" + Strings::Escape(e.scrollname) + "'"); + v.push_back(columns[225] + " = " + std::to_string(e.dsmitigation)); + v.push_back(columns[226] + " = " + std::to_string(e.heroic_str)); + v.push_back(columns[227] + " = " + std::to_string(e.heroic_int)); + v.push_back(columns[228] + " = " + std::to_string(e.heroic_wis)); + v.push_back(columns[229] + " = " + std::to_string(e.heroic_agi)); + v.push_back(columns[230] + " = " + std::to_string(e.heroic_dex)); + v.push_back(columns[231] + " = " + std::to_string(e.heroic_sta)); + v.push_back(columns[232] + " = " + std::to_string(e.heroic_cha)); + v.push_back(columns[233] + " = " + std::to_string(e.heroic_pr)); + v.push_back(columns[234] + " = " + std::to_string(e.heroic_dr)); + v.push_back(columns[235] + " = " + std::to_string(e.heroic_fr)); + v.push_back(columns[236] + " = " + std::to_string(e.heroic_cr)); + v.push_back(columns[237] + " = " + std::to_string(e.heroic_mr)); + v.push_back(columns[238] + " = " + std::to_string(e.heroic_svcorrup)); + v.push_back(columns[239] + " = " + std::to_string(e.healamt)); + v.push_back(columns[240] + " = " + std::to_string(e.spelldmg)); + v.push_back(columns[241] + " = " + std::to_string(e.clairvoyance)); + v.push_back(columns[242] + " = " + std::to_string(e.backstabdmg)); + v.push_back(columns[243] + " = '" + Strings::Escape(e.created) + "'"); + v.push_back(columns[244] + " = " + std::to_string(e.elitematerial)); + v.push_back(columns[245] + " = " + std::to_string(e.ldonsellbackrate)); + v.push_back(columns[246] + " = " + std::to_string(e.scriptfileid)); + v.push_back(columns[247] + " = " + std::to_string(e.expendablearrow)); + v.push_back(columns[248] + " = " + std::to_string(e.powersourcecapacity)); + v.push_back(columns[249] + " = " + std::to_string(e.bardeffect)); + v.push_back(columns[250] + " = " + std::to_string(e.bardeffecttype)); + v.push_back(columns[251] + " = " + std::to_string(e.bardlevel2)); + v.push_back(columns[252] + " = " + std::to_string(e.bardlevel)); + v.push_back(columns[253] + " = " + std::to_string(e.bardunk1)); + v.push_back(columns[254] + " = " + std::to_string(e.bardunk2)); + v.push_back(columns[255] + " = " + std::to_string(e.bardunk3)); + v.push_back(columns[256] + " = " + std::to_string(e.bardunk4)); + v.push_back(columns[257] + " = " + std::to_string(e.bardunk5)); + v.push_back(columns[258] + " = '" + Strings::Escape(e.bardname) + "'"); + v.push_back(columns[259] + " = " + std::to_string(e.bardunk7)); + v.push_back(columns[260] + " = " + std::to_string(e.UNK214)); + v.push_back(columns[261] + " = " + std::to_string(e.subtype)); + v.push_back(columns[262] + " = " + std::to_string(e.UNK220)); + v.push_back(columns[263] + " = " + std::to_string(e.UNK221)); + v.push_back(columns[264] + " = " + std::to_string(e.heirloom)); + v.push_back(columns[265] + " = " + std::to_string(e.UNK223)); + v.push_back(columns[266] + " = " + std::to_string(e.UNK224)); + v.push_back(columns[267] + " = " + std::to_string(e.UNK225)); + v.push_back(columns[268] + " = " + std::to_string(e.UNK226)); + v.push_back(columns[269] + " = " + std::to_string(e.UNK227)); + v.push_back(columns[270] + " = " + std::to_string(e.UNK228)); + v.push_back(columns[271] + " = " + std::to_string(e.UNK229)); + v.push_back(columns[272] + " = " + std::to_string(e.UNK230)); + v.push_back(columns[273] + " = " + std::to_string(e.UNK231)); + v.push_back(columns[274] + " = " + std::to_string(e.UNK232)); + v.push_back(columns[275] + " = " + std::to_string(e.UNK233)); + v.push_back(columns[276] + " = " + std::to_string(e.UNK234)); + v.push_back(columns[277] + " = " + std::to_string(e.placeable)); + v.push_back(columns[278] + " = " + std::to_string(e.UNK236)); + v.push_back(columns[279] + " = " + std::to_string(e.UNK237)); + v.push_back(columns[280] + " = " + std::to_string(e.UNK238)); + v.push_back(columns[281] + " = " + std::to_string(e.UNK239)); + v.push_back(columns[282] + " = " + std::to_string(e.UNK240)); + v.push_back(columns[283] + " = " + std::to_string(e.UNK241)); + v.push_back(columns[284] + " = " + std::to_string(e.epicitem)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - items_entry.id + e.id ) ); @@ -1869,621 +1869,621 @@ public: static Items InsertOne( Database& db, - Items items_entry + Items e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(items_entry.id)); - insert_values.push_back(std::to_string(items_entry.minstatus)); - insert_values.push_back("'" + EscapeString(items_entry.Name) + "'"); - insert_values.push_back(std::to_string(items_entry.aagi)); - insert_values.push_back(std::to_string(items_entry.ac)); - insert_values.push_back(std::to_string(items_entry.accuracy)); - insert_values.push_back(std::to_string(items_entry.acha)); - insert_values.push_back(std::to_string(items_entry.adex)); - insert_values.push_back(std::to_string(items_entry.aint)); - insert_values.push_back(std::to_string(items_entry.artifactflag)); - insert_values.push_back(std::to_string(items_entry.asta)); - insert_values.push_back(std::to_string(items_entry.astr)); - insert_values.push_back(std::to_string(items_entry.attack)); - insert_values.push_back(std::to_string(items_entry.augrestrict)); - insert_values.push_back(std::to_string(items_entry.augslot1type)); - insert_values.push_back(std::to_string(items_entry.augslot1visible)); - insert_values.push_back(std::to_string(items_entry.augslot2type)); - insert_values.push_back(std::to_string(items_entry.augslot2visible)); - insert_values.push_back(std::to_string(items_entry.augslot3type)); - insert_values.push_back(std::to_string(items_entry.augslot3visible)); - insert_values.push_back(std::to_string(items_entry.augslot4type)); - insert_values.push_back(std::to_string(items_entry.augslot4visible)); - insert_values.push_back(std::to_string(items_entry.augslot5type)); - insert_values.push_back(std::to_string(items_entry.augslot5visible)); - insert_values.push_back(std::to_string(items_entry.augslot6type)); - insert_values.push_back(std::to_string(items_entry.augslot6visible)); - insert_values.push_back(std::to_string(items_entry.augtype)); - insert_values.push_back(std::to_string(items_entry.avoidance)); - insert_values.push_back(std::to_string(items_entry.awis)); - insert_values.push_back(std::to_string(items_entry.bagsize)); - insert_values.push_back(std::to_string(items_entry.bagslots)); - insert_values.push_back(std::to_string(items_entry.bagtype)); - insert_values.push_back(std::to_string(items_entry.bagwr)); - insert_values.push_back(std::to_string(items_entry.banedmgamt)); - insert_values.push_back(std::to_string(items_entry.banedmgraceamt)); - insert_values.push_back(std::to_string(items_entry.banedmgbody)); - insert_values.push_back(std::to_string(items_entry.banedmgrace)); - insert_values.push_back(std::to_string(items_entry.bardtype)); - insert_values.push_back(std::to_string(items_entry.bardvalue)); - insert_values.push_back(std::to_string(items_entry.book)); - insert_values.push_back(std::to_string(items_entry.casttime)); - insert_values.push_back(std::to_string(items_entry.casttime_)); - insert_values.push_back("'" + EscapeString(items_entry.charmfile) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.charmfileid) + "'"); - insert_values.push_back(std::to_string(items_entry.classes)); - insert_values.push_back(std::to_string(items_entry.color)); - insert_values.push_back("'" + EscapeString(items_entry.combateffects) + "'"); - insert_values.push_back(std::to_string(items_entry.extradmgskill)); - insert_values.push_back(std::to_string(items_entry.extradmgamt)); - insert_values.push_back(std::to_string(items_entry.price)); - insert_values.push_back(std::to_string(items_entry.cr)); - insert_values.push_back(std::to_string(items_entry.damage)); - insert_values.push_back(std::to_string(items_entry.damageshield)); - insert_values.push_back(std::to_string(items_entry.deity)); - insert_values.push_back(std::to_string(items_entry.delay)); - insert_values.push_back(std::to_string(items_entry.augdistiller)); - insert_values.push_back(std::to_string(items_entry.dotshielding)); - insert_values.push_back(std::to_string(items_entry.dr)); - insert_values.push_back(std::to_string(items_entry.clicktype)); - insert_values.push_back(std::to_string(items_entry.clicklevel2)); - insert_values.push_back(std::to_string(items_entry.elemdmgtype)); - insert_values.push_back(std::to_string(items_entry.elemdmgamt)); - insert_values.push_back(std::to_string(items_entry.endur)); - insert_values.push_back(std::to_string(items_entry.factionamt1)); - insert_values.push_back(std::to_string(items_entry.factionamt2)); - insert_values.push_back(std::to_string(items_entry.factionamt3)); - insert_values.push_back(std::to_string(items_entry.factionamt4)); - insert_values.push_back(std::to_string(items_entry.factionmod1)); - insert_values.push_back(std::to_string(items_entry.factionmod2)); - insert_values.push_back(std::to_string(items_entry.factionmod3)); - insert_values.push_back(std::to_string(items_entry.factionmod4)); - insert_values.push_back("'" + EscapeString(items_entry.filename) + "'"); - insert_values.push_back(std::to_string(items_entry.focuseffect)); - insert_values.push_back(std::to_string(items_entry.fr)); - insert_values.push_back(std::to_string(items_entry.fvnodrop)); - insert_values.push_back(std::to_string(items_entry.haste)); - insert_values.push_back(std::to_string(items_entry.clicklevel)); - insert_values.push_back(std::to_string(items_entry.hp)); - insert_values.push_back(std::to_string(items_entry.regen)); - insert_values.push_back(std::to_string(items_entry.icon)); - insert_values.push_back("'" + EscapeString(items_entry.idfile) + "'"); - insert_values.push_back(std::to_string(items_entry.itemclass)); - insert_values.push_back(std::to_string(items_entry.itemtype)); - insert_values.push_back(std::to_string(items_entry.ldonprice)); - insert_values.push_back(std::to_string(items_entry.ldontheme)); - insert_values.push_back(std::to_string(items_entry.ldonsold)); - insert_values.push_back(std::to_string(items_entry.light)); - insert_values.push_back("'" + EscapeString(items_entry.lore) + "'"); - insert_values.push_back(std::to_string(items_entry.loregroup)); - insert_values.push_back(std::to_string(items_entry.magic)); - insert_values.push_back(std::to_string(items_entry.mana)); - insert_values.push_back(std::to_string(items_entry.manaregen)); - insert_values.push_back(std::to_string(items_entry.enduranceregen)); - insert_values.push_back(std::to_string(items_entry.material)); - insert_values.push_back(std::to_string(items_entry.herosforgemodel)); - insert_values.push_back(std::to_string(items_entry.maxcharges)); - insert_values.push_back(std::to_string(items_entry.mr)); - insert_values.push_back(std::to_string(items_entry.nodrop)); - insert_values.push_back(std::to_string(items_entry.norent)); - insert_values.push_back(std::to_string(items_entry.pendingloreflag)); - insert_values.push_back(std::to_string(items_entry.pr)); - insert_values.push_back(std::to_string(items_entry.procrate)); - insert_values.push_back(std::to_string(items_entry.races)); - insert_values.push_back(std::to_string(items_entry.range)); - insert_values.push_back(std::to_string(items_entry.reclevel)); - insert_values.push_back(std::to_string(items_entry.recskill)); - insert_values.push_back(std::to_string(items_entry.reqlevel)); - insert_values.push_back(std::to_string(items_entry.sellrate)); - insert_values.push_back(std::to_string(items_entry.shielding)); - insert_values.push_back(std::to_string(items_entry.size)); - insert_values.push_back(std::to_string(items_entry.skillmodtype)); - insert_values.push_back(std::to_string(items_entry.skillmodvalue)); - insert_values.push_back(std::to_string(items_entry.slots)); - insert_values.push_back(std::to_string(items_entry.clickeffect)); - insert_values.push_back(std::to_string(items_entry.spellshield)); - insert_values.push_back(std::to_string(items_entry.strikethrough)); - insert_values.push_back(std::to_string(items_entry.stunresist)); - insert_values.push_back(std::to_string(items_entry.summonedflag)); - insert_values.push_back(std::to_string(items_entry.tradeskills)); - insert_values.push_back(std::to_string(items_entry.favor)); - insert_values.push_back(std::to_string(items_entry.weight)); - insert_values.push_back(std::to_string(items_entry.UNK012)); - insert_values.push_back(std::to_string(items_entry.UNK013)); - insert_values.push_back(std::to_string(items_entry.benefitflag)); - insert_values.push_back(std::to_string(items_entry.UNK054)); - insert_values.push_back(std::to_string(items_entry.UNK059)); - insert_values.push_back(std::to_string(items_entry.booktype)); - insert_values.push_back(std::to_string(items_entry.recastdelay)); - insert_values.push_back(std::to_string(items_entry.recasttype)); - insert_values.push_back(std::to_string(items_entry.guildfavor)); - insert_values.push_back(std::to_string(items_entry.UNK123)); - insert_values.push_back(std::to_string(items_entry.UNK124)); - insert_values.push_back(std::to_string(items_entry.attuneable)); - insert_values.push_back(std::to_string(items_entry.nopet)); - insert_values.push_back("FROM_UNIXTIME(" + (items_entry.updated > 0 ? std::to_string(items_entry.updated) : "null") + ")"); - insert_values.push_back("'" + EscapeString(items_entry.comment) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK127)); - insert_values.push_back(std::to_string(items_entry.pointtype)); - insert_values.push_back(std::to_string(items_entry.potionbelt)); - insert_values.push_back(std::to_string(items_entry.potionbeltslots)); - insert_values.push_back(std::to_string(items_entry.stacksize)); - insert_values.push_back(std::to_string(items_entry.notransfer)); - insert_values.push_back(std::to_string(items_entry.stackable)); - insert_values.push_back("'" + EscapeString(items_entry.UNK134) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK137)); - insert_values.push_back(std::to_string(items_entry.proceffect)); - insert_values.push_back(std::to_string(items_entry.proctype)); - insert_values.push_back(std::to_string(items_entry.proclevel2)); - insert_values.push_back(std::to_string(items_entry.proclevel)); - insert_values.push_back(std::to_string(items_entry.UNK142)); - insert_values.push_back(std::to_string(items_entry.worneffect)); - insert_values.push_back(std::to_string(items_entry.worntype)); - insert_values.push_back(std::to_string(items_entry.wornlevel2)); - insert_values.push_back(std::to_string(items_entry.wornlevel)); - insert_values.push_back(std::to_string(items_entry.UNK147)); - insert_values.push_back(std::to_string(items_entry.focustype)); - insert_values.push_back(std::to_string(items_entry.focuslevel2)); - insert_values.push_back(std::to_string(items_entry.focuslevel)); - insert_values.push_back(std::to_string(items_entry.UNK152)); - insert_values.push_back(std::to_string(items_entry.scrolleffect)); - insert_values.push_back(std::to_string(items_entry.scrolltype)); - insert_values.push_back(std::to_string(items_entry.scrolllevel2)); - insert_values.push_back(std::to_string(items_entry.scrolllevel)); - insert_values.push_back(std::to_string(items_entry.UNK157)); - insert_values.push_back("FROM_UNIXTIME(" + (items_entry.serialized > 0 ? std::to_string(items_entry.serialized) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (items_entry.verified > 0 ? std::to_string(items_entry.verified) : "null") + ")"); - insert_values.push_back("'" + EscapeString(items_entry.serialization) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.source) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK033)); - insert_values.push_back("'" + EscapeString(items_entry.lorefile) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK014)); - insert_values.push_back(std::to_string(items_entry.svcorruption)); - insert_values.push_back(std::to_string(items_entry.skillmodmax)); - insert_values.push_back(std::to_string(items_entry.UNK060)); - insert_values.push_back(std::to_string(items_entry.augslot1unk2)); - insert_values.push_back(std::to_string(items_entry.augslot2unk2)); - insert_values.push_back(std::to_string(items_entry.augslot3unk2)); - insert_values.push_back(std::to_string(items_entry.augslot4unk2)); - insert_values.push_back(std::to_string(items_entry.augslot5unk2)); - insert_values.push_back(std::to_string(items_entry.augslot6unk2)); - insert_values.push_back(std::to_string(items_entry.UNK120)); - insert_values.push_back(std::to_string(items_entry.UNK121)); - insert_values.push_back(std::to_string(items_entry.questitemflag)); - insert_values.push_back("'" + EscapeString(items_entry.UNK132) + "'"); - insert_values.push_back(std::to_string(items_entry.clickunk5)); - insert_values.push_back("'" + EscapeString(items_entry.clickunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.clickunk7)); - insert_values.push_back(std::to_string(items_entry.procunk1)); - insert_values.push_back(std::to_string(items_entry.procunk2)); - insert_values.push_back(std::to_string(items_entry.procunk3)); - insert_values.push_back(std::to_string(items_entry.procunk4)); - insert_values.push_back("'" + EscapeString(items_entry.procunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.procunk7)); - insert_values.push_back(std::to_string(items_entry.wornunk1)); - insert_values.push_back(std::to_string(items_entry.wornunk2)); - insert_values.push_back(std::to_string(items_entry.wornunk3)); - insert_values.push_back(std::to_string(items_entry.wornunk4)); - insert_values.push_back(std::to_string(items_entry.wornunk5)); - insert_values.push_back("'" + EscapeString(items_entry.wornunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.wornunk7)); - insert_values.push_back(std::to_string(items_entry.focusunk1)); - insert_values.push_back(std::to_string(items_entry.focusunk2)); - insert_values.push_back(std::to_string(items_entry.focusunk3)); - insert_values.push_back(std::to_string(items_entry.focusunk4)); - insert_values.push_back(std::to_string(items_entry.focusunk5)); - insert_values.push_back("'" + EscapeString(items_entry.focusunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.focusunk7)); - insert_values.push_back(std::to_string(items_entry.scrollunk1)); - insert_values.push_back(std::to_string(items_entry.scrollunk2)); - insert_values.push_back(std::to_string(items_entry.scrollunk3)); - insert_values.push_back(std::to_string(items_entry.scrollunk4)); - insert_values.push_back(std::to_string(items_entry.scrollunk5)); - insert_values.push_back("'" + EscapeString(items_entry.scrollunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.scrollunk7)); - insert_values.push_back(std::to_string(items_entry.UNK193)); - insert_values.push_back(std::to_string(items_entry.purity)); - insert_values.push_back(std::to_string(items_entry.evoitem)); - insert_values.push_back(std::to_string(items_entry.evoid)); - insert_values.push_back(std::to_string(items_entry.evolvinglevel)); - insert_values.push_back(std::to_string(items_entry.evomax)); - insert_values.push_back("'" + EscapeString(items_entry.clickname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.procname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.wornname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.focusname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.scrollname) + "'"); - insert_values.push_back(std::to_string(items_entry.dsmitigation)); - insert_values.push_back(std::to_string(items_entry.heroic_str)); - insert_values.push_back(std::to_string(items_entry.heroic_int)); - insert_values.push_back(std::to_string(items_entry.heroic_wis)); - insert_values.push_back(std::to_string(items_entry.heroic_agi)); - insert_values.push_back(std::to_string(items_entry.heroic_dex)); - insert_values.push_back(std::to_string(items_entry.heroic_sta)); - insert_values.push_back(std::to_string(items_entry.heroic_cha)); - insert_values.push_back(std::to_string(items_entry.heroic_pr)); - insert_values.push_back(std::to_string(items_entry.heroic_dr)); - insert_values.push_back(std::to_string(items_entry.heroic_fr)); - insert_values.push_back(std::to_string(items_entry.heroic_cr)); - insert_values.push_back(std::to_string(items_entry.heroic_mr)); - insert_values.push_back(std::to_string(items_entry.heroic_svcorrup)); - insert_values.push_back(std::to_string(items_entry.healamt)); - insert_values.push_back(std::to_string(items_entry.spelldmg)); - insert_values.push_back(std::to_string(items_entry.clairvoyance)); - insert_values.push_back(std::to_string(items_entry.backstabdmg)); - insert_values.push_back("'" + EscapeString(items_entry.created) + "'"); - insert_values.push_back(std::to_string(items_entry.elitematerial)); - insert_values.push_back(std::to_string(items_entry.ldonsellbackrate)); - insert_values.push_back(std::to_string(items_entry.scriptfileid)); - insert_values.push_back(std::to_string(items_entry.expendablearrow)); - insert_values.push_back(std::to_string(items_entry.powersourcecapacity)); - insert_values.push_back(std::to_string(items_entry.bardeffect)); - insert_values.push_back(std::to_string(items_entry.bardeffecttype)); - insert_values.push_back(std::to_string(items_entry.bardlevel2)); - insert_values.push_back(std::to_string(items_entry.bardlevel)); - insert_values.push_back(std::to_string(items_entry.bardunk1)); - insert_values.push_back(std::to_string(items_entry.bardunk2)); - insert_values.push_back(std::to_string(items_entry.bardunk3)); - insert_values.push_back(std::to_string(items_entry.bardunk4)); - insert_values.push_back(std::to_string(items_entry.bardunk5)); - insert_values.push_back("'" + EscapeString(items_entry.bardname) + "'"); - insert_values.push_back(std::to_string(items_entry.bardunk7)); - insert_values.push_back(std::to_string(items_entry.UNK214)); - insert_values.push_back(std::to_string(items_entry.subtype)); - insert_values.push_back(std::to_string(items_entry.UNK220)); - insert_values.push_back(std::to_string(items_entry.UNK221)); - insert_values.push_back(std::to_string(items_entry.heirloom)); - insert_values.push_back(std::to_string(items_entry.UNK223)); - insert_values.push_back(std::to_string(items_entry.UNK224)); - insert_values.push_back(std::to_string(items_entry.UNK225)); - insert_values.push_back(std::to_string(items_entry.UNK226)); - insert_values.push_back(std::to_string(items_entry.UNK227)); - insert_values.push_back(std::to_string(items_entry.UNK228)); - insert_values.push_back(std::to_string(items_entry.UNK229)); - insert_values.push_back(std::to_string(items_entry.UNK230)); - insert_values.push_back(std::to_string(items_entry.UNK231)); - insert_values.push_back(std::to_string(items_entry.UNK232)); - insert_values.push_back(std::to_string(items_entry.UNK233)); - insert_values.push_back(std::to_string(items_entry.UNK234)); - insert_values.push_back(std::to_string(items_entry.placeable)); - insert_values.push_back(std::to_string(items_entry.UNK236)); - insert_values.push_back(std::to_string(items_entry.UNK237)); - insert_values.push_back(std::to_string(items_entry.UNK238)); - insert_values.push_back(std::to_string(items_entry.UNK239)); - insert_values.push_back(std::to_string(items_entry.UNK240)); - insert_values.push_back(std::to_string(items_entry.UNK241)); - insert_values.push_back(std::to_string(items_entry.epicitem)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.minstatus)); + v.push_back("'" + Strings::Escape(e.Name) + "'"); + v.push_back(std::to_string(e.aagi)); + v.push_back(std::to_string(e.ac)); + v.push_back(std::to_string(e.accuracy)); + v.push_back(std::to_string(e.acha)); + v.push_back(std::to_string(e.adex)); + v.push_back(std::to_string(e.aint)); + v.push_back(std::to_string(e.artifactflag)); + v.push_back(std::to_string(e.asta)); + v.push_back(std::to_string(e.astr)); + v.push_back(std::to_string(e.attack)); + v.push_back(std::to_string(e.augrestrict)); + v.push_back(std::to_string(e.augslot1type)); + v.push_back(std::to_string(e.augslot1visible)); + v.push_back(std::to_string(e.augslot2type)); + v.push_back(std::to_string(e.augslot2visible)); + v.push_back(std::to_string(e.augslot3type)); + v.push_back(std::to_string(e.augslot3visible)); + v.push_back(std::to_string(e.augslot4type)); + v.push_back(std::to_string(e.augslot4visible)); + v.push_back(std::to_string(e.augslot5type)); + v.push_back(std::to_string(e.augslot5visible)); + v.push_back(std::to_string(e.augslot6type)); + v.push_back(std::to_string(e.augslot6visible)); + v.push_back(std::to_string(e.augtype)); + v.push_back(std::to_string(e.avoidance)); + v.push_back(std::to_string(e.awis)); + v.push_back(std::to_string(e.bagsize)); + v.push_back(std::to_string(e.bagslots)); + v.push_back(std::to_string(e.bagtype)); + v.push_back(std::to_string(e.bagwr)); + v.push_back(std::to_string(e.banedmgamt)); + v.push_back(std::to_string(e.banedmgraceamt)); + v.push_back(std::to_string(e.banedmgbody)); + v.push_back(std::to_string(e.banedmgrace)); + v.push_back(std::to_string(e.bardtype)); + v.push_back(std::to_string(e.bardvalue)); + v.push_back(std::to_string(e.book)); + v.push_back(std::to_string(e.casttime)); + v.push_back(std::to_string(e.casttime_)); + v.push_back("'" + Strings::Escape(e.charmfile) + "'"); + v.push_back("'" + Strings::Escape(e.charmfileid) + "'"); + v.push_back(std::to_string(e.classes)); + v.push_back(std::to_string(e.color)); + v.push_back("'" + Strings::Escape(e.combateffects) + "'"); + v.push_back(std::to_string(e.extradmgskill)); + v.push_back(std::to_string(e.extradmgamt)); + v.push_back(std::to_string(e.price)); + v.push_back(std::to_string(e.cr)); + v.push_back(std::to_string(e.damage)); + v.push_back(std::to_string(e.damageshield)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.delay)); + v.push_back(std::to_string(e.augdistiller)); + v.push_back(std::to_string(e.dotshielding)); + v.push_back(std::to_string(e.dr)); + v.push_back(std::to_string(e.clicktype)); + v.push_back(std::to_string(e.clicklevel2)); + v.push_back(std::to_string(e.elemdmgtype)); + v.push_back(std::to_string(e.elemdmgamt)); + v.push_back(std::to_string(e.endur)); + v.push_back(std::to_string(e.factionamt1)); + v.push_back(std::to_string(e.factionamt2)); + v.push_back(std::to_string(e.factionamt3)); + v.push_back(std::to_string(e.factionamt4)); + v.push_back(std::to_string(e.factionmod1)); + v.push_back(std::to_string(e.factionmod2)); + v.push_back(std::to_string(e.factionmod3)); + v.push_back(std::to_string(e.factionmod4)); + v.push_back("'" + Strings::Escape(e.filename) + "'"); + v.push_back(std::to_string(e.focuseffect)); + v.push_back(std::to_string(e.fr)); + v.push_back(std::to_string(e.fvnodrop)); + v.push_back(std::to_string(e.haste)); + v.push_back(std::to_string(e.clicklevel)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.regen)); + v.push_back(std::to_string(e.icon)); + v.push_back("'" + Strings::Escape(e.idfile) + "'"); + v.push_back(std::to_string(e.itemclass)); + v.push_back(std::to_string(e.itemtype)); + v.push_back(std::to_string(e.ldonprice)); + v.push_back(std::to_string(e.ldontheme)); + v.push_back(std::to_string(e.ldonsold)); + v.push_back(std::to_string(e.light)); + v.push_back("'" + Strings::Escape(e.lore) + "'"); + v.push_back(std::to_string(e.loregroup)); + v.push_back(std::to_string(e.magic)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.manaregen)); + v.push_back(std::to_string(e.enduranceregen)); + v.push_back(std::to_string(e.material)); + v.push_back(std::to_string(e.herosforgemodel)); + v.push_back(std::to_string(e.maxcharges)); + v.push_back(std::to_string(e.mr)); + v.push_back(std::to_string(e.nodrop)); + v.push_back(std::to_string(e.norent)); + v.push_back(std::to_string(e.pendingloreflag)); + v.push_back(std::to_string(e.pr)); + v.push_back(std::to_string(e.procrate)); + v.push_back(std::to_string(e.races)); + v.push_back(std::to_string(e.range)); + v.push_back(std::to_string(e.reclevel)); + v.push_back(std::to_string(e.recskill)); + v.push_back(std::to_string(e.reqlevel)); + v.push_back(std::to_string(e.sellrate)); + v.push_back(std::to_string(e.shielding)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.skillmodtype)); + v.push_back(std::to_string(e.skillmodvalue)); + v.push_back(std::to_string(e.slots)); + v.push_back(std::to_string(e.clickeffect)); + v.push_back(std::to_string(e.spellshield)); + v.push_back(std::to_string(e.strikethrough)); + v.push_back(std::to_string(e.stunresist)); + v.push_back(std::to_string(e.summonedflag)); + v.push_back(std::to_string(e.tradeskills)); + v.push_back(std::to_string(e.favor)); + v.push_back(std::to_string(e.weight)); + v.push_back(std::to_string(e.UNK012)); + v.push_back(std::to_string(e.UNK013)); + v.push_back(std::to_string(e.benefitflag)); + v.push_back(std::to_string(e.UNK054)); + v.push_back(std::to_string(e.UNK059)); + v.push_back(std::to_string(e.booktype)); + v.push_back(std::to_string(e.recastdelay)); + v.push_back(std::to_string(e.recasttype)); + v.push_back(std::to_string(e.guildfavor)); + v.push_back(std::to_string(e.UNK123)); + v.push_back(std::to_string(e.UNK124)); + v.push_back(std::to_string(e.attuneable)); + v.push_back(std::to_string(e.nopet)); + v.push_back("FROM_UNIXTIME(" + (e.updated > 0 ? std::to_string(e.updated) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.comment) + "'"); + v.push_back(std::to_string(e.UNK127)); + v.push_back(std::to_string(e.pointtype)); + v.push_back(std::to_string(e.potionbelt)); + v.push_back(std::to_string(e.potionbeltslots)); + v.push_back(std::to_string(e.stacksize)); + v.push_back(std::to_string(e.notransfer)); + v.push_back(std::to_string(e.stackable)); + v.push_back("'" + Strings::Escape(e.UNK134) + "'"); + v.push_back(std::to_string(e.UNK137)); + v.push_back(std::to_string(e.proceffect)); + v.push_back(std::to_string(e.proctype)); + v.push_back(std::to_string(e.proclevel2)); + v.push_back(std::to_string(e.proclevel)); + v.push_back(std::to_string(e.UNK142)); + v.push_back(std::to_string(e.worneffect)); + v.push_back(std::to_string(e.worntype)); + v.push_back(std::to_string(e.wornlevel2)); + v.push_back(std::to_string(e.wornlevel)); + v.push_back(std::to_string(e.UNK147)); + v.push_back(std::to_string(e.focustype)); + v.push_back(std::to_string(e.focuslevel2)); + v.push_back(std::to_string(e.focuslevel)); + v.push_back(std::to_string(e.UNK152)); + v.push_back(std::to_string(e.scrolleffect)); + v.push_back(std::to_string(e.scrolltype)); + v.push_back(std::to_string(e.scrolllevel2)); + v.push_back(std::to_string(e.scrolllevel)); + v.push_back(std::to_string(e.UNK157)); + v.push_back("FROM_UNIXTIME(" + (e.serialized > 0 ? std::to_string(e.serialized) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.verified > 0 ? std::to_string(e.verified) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.serialization) + "'"); + v.push_back("'" + Strings::Escape(e.source) + "'"); + v.push_back(std::to_string(e.UNK033)); + v.push_back("'" + Strings::Escape(e.lorefile) + "'"); + v.push_back(std::to_string(e.UNK014)); + v.push_back(std::to_string(e.svcorruption)); + v.push_back(std::to_string(e.skillmodmax)); + v.push_back(std::to_string(e.UNK060)); + v.push_back(std::to_string(e.augslot1unk2)); + v.push_back(std::to_string(e.augslot2unk2)); + v.push_back(std::to_string(e.augslot3unk2)); + v.push_back(std::to_string(e.augslot4unk2)); + v.push_back(std::to_string(e.augslot5unk2)); + v.push_back(std::to_string(e.augslot6unk2)); + v.push_back(std::to_string(e.UNK120)); + v.push_back(std::to_string(e.UNK121)); + v.push_back(std::to_string(e.questitemflag)); + v.push_back("'" + Strings::Escape(e.UNK132) + "'"); + v.push_back(std::to_string(e.clickunk5)); + v.push_back("'" + Strings::Escape(e.clickunk6) + "'"); + v.push_back(std::to_string(e.clickunk7)); + v.push_back(std::to_string(e.procunk1)); + v.push_back(std::to_string(e.procunk2)); + v.push_back(std::to_string(e.procunk3)); + v.push_back(std::to_string(e.procunk4)); + v.push_back("'" + Strings::Escape(e.procunk6) + "'"); + v.push_back(std::to_string(e.procunk7)); + v.push_back(std::to_string(e.wornunk1)); + v.push_back(std::to_string(e.wornunk2)); + v.push_back(std::to_string(e.wornunk3)); + v.push_back(std::to_string(e.wornunk4)); + v.push_back(std::to_string(e.wornunk5)); + v.push_back("'" + Strings::Escape(e.wornunk6) + "'"); + v.push_back(std::to_string(e.wornunk7)); + v.push_back(std::to_string(e.focusunk1)); + v.push_back(std::to_string(e.focusunk2)); + v.push_back(std::to_string(e.focusunk3)); + v.push_back(std::to_string(e.focusunk4)); + v.push_back(std::to_string(e.focusunk5)); + v.push_back("'" + Strings::Escape(e.focusunk6) + "'"); + v.push_back(std::to_string(e.focusunk7)); + v.push_back(std::to_string(e.scrollunk1)); + v.push_back(std::to_string(e.scrollunk2)); + v.push_back(std::to_string(e.scrollunk3)); + v.push_back(std::to_string(e.scrollunk4)); + v.push_back(std::to_string(e.scrollunk5)); + v.push_back("'" + Strings::Escape(e.scrollunk6) + "'"); + v.push_back(std::to_string(e.scrollunk7)); + v.push_back(std::to_string(e.UNK193)); + v.push_back(std::to_string(e.purity)); + v.push_back(std::to_string(e.evoitem)); + v.push_back(std::to_string(e.evoid)); + v.push_back(std::to_string(e.evolvinglevel)); + v.push_back(std::to_string(e.evomax)); + v.push_back("'" + Strings::Escape(e.clickname) + "'"); + v.push_back("'" + Strings::Escape(e.procname) + "'"); + v.push_back("'" + Strings::Escape(e.wornname) + "'"); + v.push_back("'" + Strings::Escape(e.focusname) + "'"); + v.push_back("'" + Strings::Escape(e.scrollname) + "'"); + v.push_back(std::to_string(e.dsmitigation)); + v.push_back(std::to_string(e.heroic_str)); + v.push_back(std::to_string(e.heroic_int)); + v.push_back(std::to_string(e.heroic_wis)); + v.push_back(std::to_string(e.heroic_agi)); + v.push_back(std::to_string(e.heroic_dex)); + v.push_back(std::to_string(e.heroic_sta)); + v.push_back(std::to_string(e.heroic_cha)); + v.push_back(std::to_string(e.heroic_pr)); + v.push_back(std::to_string(e.heroic_dr)); + v.push_back(std::to_string(e.heroic_fr)); + v.push_back(std::to_string(e.heroic_cr)); + v.push_back(std::to_string(e.heroic_mr)); + v.push_back(std::to_string(e.heroic_svcorrup)); + v.push_back(std::to_string(e.healamt)); + v.push_back(std::to_string(e.spelldmg)); + v.push_back(std::to_string(e.clairvoyance)); + v.push_back(std::to_string(e.backstabdmg)); + v.push_back("'" + Strings::Escape(e.created) + "'"); + v.push_back(std::to_string(e.elitematerial)); + v.push_back(std::to_string(e.ldonsellbackrate)); + v.push_back(std::to_string(e.scriptfileid)); + v.push_back(std::to_string(e.expendablearrow)); + v.push_back(std::to_string(e.powersourcecapacity)); + v.push_back(std::to_string(e.bardeffect)); + v.push_back(std::to_string(e.bardeffecttype)); + v.push_back(std::to_string(e.bardlevel2)); + v.push_back(std::to_string(e.bardlevel)); + v.push_back(std::to_string(e.bardunk1)); + v.push_back(std::to_string(e.bardunk2)); + v.push_back(std::to_string(e.bardunk3)); + v.push_back(std::to_string(e.bardunk4)); + v.push_back(std::to_string(e.bardunk5)); + v.push_back("'" + Strings::Escape(e.bardname) + "'"); + v.push_back(std::to_string(e.bardunk7)); + v.push_back(std::to_string(e.UNK214)); + v.push_back(std::to_string(e.subtype)); + v.push_back(std::to_string(e.UNK220)); + v.push_back(std::to_string(e.UNK221)); + v.push_back(std::to_string(e.heirloom)); + v.push_back(std::to_string(e.UNK223)); + v.push_back(std::to_string(e.UNK224)); + v.push_back(std::to_string(e.UNK225)); + v.push_back(std::to_string(e.UNK226)); + v.push_back(std::to_string(e.UNK227)); + v.push_back(std::to_string(e.UNK228)); + v.push_back(std::to_string(e.UNK229)); + v.push_back(std::to_string(e.UNK230)); + v.push_back(std::to_string(e.UNK231)); + v.push_back(std::to_string(e.UNK232)); + v.push_back(std::to_string(e.UNK233)); + v.push_back(std::to_string(e.UNK234)); + v.push_back(std::to_string(e.placeable)); + v.push_back(std::to_string(e.UNK236)); + v.push_back(std::to_string(e.UNK237)); + v.push_back(std::to_string(e.UNK238)); + v.push_back(std::to_string(e.UNK239)); + v.push_back(std::to_string(e.UNK240)); + v.push_back(std::to_string(e.UNK241)); + v.push_back(std::to_string(e.epicitem)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - items_entry.id = results.LastInsertedID(); - return items_entry; + e.id = results.LastInsertedID(); + return e; } - items_entry = NewEntity(); + e = NewEntity(); - return items_entry; + return e; } static int InsertMany( Database& db, - std::vector items_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &items_entry: items_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(items_entry.id)); - insert_values.push_back(std::to_string(items_entry.minstatus)); - insert_values.push_back("'" + EscapeString(items_entry.Name) + "'"); - insert_values.push_back(std::to_string(items_entry.aagi)); - insert_values.push_back(std::to_string(items_entry.ac)); - insert_values.push_back(std::to_string(items_entry.accuracy)); - insert_values.push_back(std::to_string(items_entry.acha)); - insert_values.push_back(std::to_string(items_entry.adex)); - insert_values.push_back(std::to_string(items_entry.aint)); - insert_values.push_back(std::to_string(items_entry.artifactflag)); - insert_values.push_back(std::to_string(items_entry.asta)); - insert_values.push_back(std::to_string(items_entry.astr)); - insert_values.push_back(std::to_string(items_entry.attack)); - insert_values.push_back(std::to_string(items_entry.augrestrict)); - insert_values.push_back(std::to_string(items_entry.augslot1type)); - insert_values.push_back(std::to_string(items_entry.augslot1visible)); - insert_values.push_back(std::to_string(items_entry.augslot2type)); - insert_values.push_back(std::to_string(items_entry.augslot2visible)); - insert_values.push_back(std::to_string(items_entry.augslot3type)); - insert_values.push_back(std::to_string(items_entry.augslot3visible)); - insert_values.push_back(std::to_string(items_entry.augslot4type)); - insert_values.push_back(std::to_string(items_entry.augslot4visible)); - insert_values.push_back(std::to_string(items_entry.augslot5type)); - insert_values.push_back(std::to_string(items_entry.augslot5visible)); - insert_values.push_back(std::to_string(items_entry.augslot6type)); - insert_values.push_back(std::to_string(items_entry.augslot6visible)); - insert_values.push_back(std::to_string(items_entry.augtype)); - insert_values.push_back(std::to_string(items_entry.avoidance)); - insert_values.push_back(std::to_string(items_entry.awis)); - insert_values.push_back(std::to_string(items_entry.bagsize)); - insert_values.push_back(std::to_string(items_entry.bagslots)); - insert_values.push_back(std::to_string(items_entry.bagtype)); - insert_values.push_back(std::to_string(items_entry.bagwr)); - insert_values.push_back(std::to_string(items_entry.banedmgamt)); - insert_values.push_back(std::to_string(items_entry.banedmgraceamt)); - insert_values.push_back(std::to_string(items_entry.banedmgbody)); - insert_values.push_back(std::to_string(items_entry.banedmgrace)); - insert_values.push_back(std::to_string(items_entry.bardtype)); - insert_values.push_back(std::to_string(items_entry.bardvalue)); - insert_values.push_back(std::to_string(items_entry.book)); - insert_values.push_back(std::to_string(items_entry.casttime)); - insert_values.push_back(std::to_string(items_entry.casttime_)); - insert_values.push_back("'" + EscapeString(items_entry.charmfile) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.charmfileid) + "'"); - insert_values.push_back(std::to_string(items_entry.classes)); - insert_values.push_back(std::to_string(items_entry.color)); - insert_values.push_back("'" + EscapeString(items_entry.combateffects) + "'"); - insert_values.push_back(std::to_string(items_entry.extradmgskill)); - insert_values.push_back(std::to_string(items_entry.extradmgamt)); - insert_values.push_back(std::to_string(items_entry.price)); - insert_values.push_back(std::to_string(items_entry.cr)); - insert_values.push_back(std::to_string(items_entry.damage)); - insert_values.push_back(std::to_string(items_entry.damageshield)); - insert_values.push_back(std::to_string(items_entry.deity)); - insert_values.push_back(std::to_string(items_entry.delay)); - insert_values.push_back(std::to_string(items_entry.augdistiller)); - insert_values.push_back(std::to_string(items_entry.dotshielding)); - insert_values.push_back(std::to_string(items_entry.dr)); - insert_values.push_back(std::to_string(items_entry.clicktype)); - insert_values.push_back(std::to_string(items_entry.clicklevel2)); - insert_values.push_back(std::to_string(items_entry.elemdmgtype)); - insert_values.push_back(std::to_string(items_entry.elemdmgamt)); - insert_values.push_back(std::to_string(items_entry.endur)); - insert_values.push_back(std::to_string(items_entry.factionamt1)); - insert_values.push_back(std::to_string(items_entry.factionamt2)); - insert_values.push_back(std::to_string(items_entry.factionamt3)); - insert_values.push_back(std::to_string(items_entry.factionamt4)); - insert_values.push_back(std::to_string(items_entry.factionmod1)); - insert_values.push_back(std::to_string(items_entry.factionmod2)); - insert_values.push_back(std::to_string(items_entry.factionmod3)); - insert_values.push_back(std::to_string(items_entry.factionmod4)); - insert_values.push_back("'" + EscapeString(items_entry.filename) + "'"); - insert_values.push_back(std::to_string(items_entry.focuseffect)); - insert_values.push_back(std::to_string(items_entry.fr)); - insert_values.push_back(std::to_string(items_entry.fvnodrop)); - insert_values.push_back(std::to_string(items_entry.haste)); - insert_values.push_back(std::to_string(items_entry.clicklevel)); - insert_values.push_back(std::to_string(items_entry.hp)); - insert_values.push_back(std::to_string(items_entry.regen)); - insert_values.push_back(std::to_string(items_entry.icon)); - insert_values.push_back("'" + EscapeString(items_entry.idfile) + "'"); - insert_values.push_back(std::to_string(items_entry.itemclass)); - insert_values.push_back(std::to_string(items_entry.itemtype)); - insert_values.push_back(std::to_string(items_entry.ldonprice)); - insert_values.push_back(std::to_string(items_entry.ldontheme)); - insert_values.push_back(std::to_string(items_entry.ldonsold)); - insert_values.push_back(std::to_string(items_entry.light)); - insert_values.push_back("'" + EscapeString(items_entry.lore) + "'"); - insert_values.push_back(std::to_string(items_entry.loregroup)); - insert_values.push_back(std::to_string(items_entry.magic)); - insert_values.push_back(std::to_string(items_entry.mana)); - insert_values.push_back(std::to_string(items_entry.manaregen)); - insert_values.push_back(std::to_string(items_entry.enduranceregen)); - insert_values.push_back(std::to_string(items_entry.material)); - insert_values.push_back(std::to_string(items_entry.herosforgemodel)); - insert_values.push_back(std::to_string(items_entry.maxcharges)); - insert_values.push_back(std::to_string(items_entry.mr)); - insert_values.push_back(std::to_string(items_entry.nodrop)); - insert_values.push_back(std::to_string(items_entry.norent)); - insert_values.push_back(std::to_string(items_entry.pendingloreflag)); - insert_values.push_back(std::to_string(items_entry.pr)); - insert_values.push_back(std::to_string(items_entry.procrate)); - insert_values.push_back(std::to_string(items_entry.races)); - insert_values.push_back(std::to_string(items_entry.range)); - insert_values.push_back(std::to_string(items_entry.reclevel)); - insert_values.push_back(std::to_string(items_entry.recskill)); - insert_values.push_back(std::to_string(items_entry.reqlevel)); - insert_values.push_back(std::to_string(items_entry.sellrate)); - insert_values.push_back(std::to_string(items_entry.shielding)); - insert_values.push_back(std::to_string(items_entry.size)); - insert_values.push_back(std::to_string(items_entry.skillmodtype)); - insert_values.push_back(std::to_string(items_entry.skillmodvalue)); - insert_values.push_back(std::to_string(items_entry.slots)); - insert_values.push_back(std::to_string(items_entry.clickeffect)); - insert_values.push_back(std::to_string(items_entry.spellshield)); - insert_values.push_back(std::to_string(items_entry.strikethrough)); - insert_values.push_back(std::to_string(items_entry.stunresist)); - insert_values.push_back(std::to_string(items_entry.summonedflag)); - insert_values.push_back(std::to_string(items_entry.tradeskills)); - insert_values.push_back(std::to_string(items_entry.favor)); - insert_values.push_back(std::to_string(items_entry.weight)); - insert_values.push_back(std::to_string(items_entry.UNK012)); - insert_values.push_back(std::to_string(items_entry.UNK013)); - insert_values.push_back(std::to_string(items_entry.benefitflag)); - insert_values.push_back(std::to_string(items_entry.UNK054)); - insert_values.push_back(std::to_string(items_entry.UNK059)); - insert_values.push_back(std::to_string(items_entry.booktype)); - insert_values.push_back(std::to_string(items_entry.recastdelay)); - insert_values.push_back(std::to_string(items_entry.recasttype)); - insert_values.push_back(std::to_string(items_entry.guildfavor)); - insert_values.push_back(std::to_string(items_entry.UNK123)); - insert_values.push_back(std::to_string(items_entry.UNK124)); - insert_values.push_back(std::to_string(items_entry.attuneable)); - insert_values.push_back(std::to_string(items_entry.nopet)); - insert_values.push_back("FROM_UNIXTIME(" + (items_entry.updated > 0 ? std::to_string(items_entry.updated) : "null") + ")"); - insert_values.push_back("'" + EscapeString(items_entry.comment) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK127)); - insert_values.push_back(std::to_string(items_entry.pointtype)); - insert_values.push_back(std::to_string(items_entry.potionbelt)); - insert_values.push_back(std::to_string(items_entry.potionbeltslots)); - insert_values.push_back(std::to_string(items_entry.stacksize)); - insert_values.push_back(std::to_string(items_entry.notransfer)); - insert_values.push_back(std::to_string(items_entry.stackable)); - insert_values.push_back("'" + EscapeString(items_entry.UNK134) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK137)); - insert_values.push_back(std::to_string(items_entry.proceffect)); - insert_values.push_back(std::to_string(items_entry.proctype)); - insert_values.push_back(std::to_string(items_entry.proclevel2)); - insert_values.push_back(std::to_string(items_entry.proclevel)); - insert_values.push_back(std::to_string(items_entry.UNK142)); - insert_values.push_back(std::to_string(items_entry.worneffect)); - insert_values.push_back(std::to_string(items_entry.worntype)); - insert_values.push_back(std::to_string(items_entry.wornlevel2)); - insert_values.push_back(std::to_string(items_entry.wornlevel)); - insert_values.push_back(std::to_string(items_entry.UNK147)); - insert_values.push_back(std::to_string(items_entry.focustype)); - insert_values.push_back(std::to_string(items_entry.focuslevel2)); - insert_values.push_back(std::to_string(items_entry.focuslevel)); - insert_values.push_back(std::to_string(items_entry.UNK152)); - insert_values.push_back(std::to_string(items_entry.scrolleffect)); - insert_values.push_back(std::to_string(items_entry.scrolltype)); - insert_values.push_back(std::to_string(items_entry.scrolllevel2)); - insert_values.push_back(std::to_string(items_entry.scrolllevel)); - insert_values.push_back(std::to_string(items_entry.UNK157)); - insert_values.push_back("FROM_UNIXTIME(" + (items_entry.serialized > 0 ? std::to_string(items_entry.serialized) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (items_entry.verified > 0 ? std::to_string(items_entry.verified) : "null") + ")"); - insert_values.push_back("'" + EscapeString(items_entry.serialization) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.source) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK033)); - insert_values.push_back("'" + EscapeString(items_entry.lorefile) + "'"); - insert_values.push_back(std::to_string(items_entry.UNK014)); - insert_values.push_back(std::to_string(items_entry.svcorruption)); - insert_values.push_back(std::to_string(items_entry.skillmodmax)); - insert_values.push_back(std::to_string(items_entry.UNK060)); - insert_values.push_back(std::to_string(items_entry.augslot1unk2)); - insert_values.push_back(std::to_string(items_entry.augslot2unk2)); - insert_values.push_back(std::to_string(items_entry.augslot3unk2)); - insert_values.push_back(std::to_string(items_entry.augslot4unk2)); - insert_values.push_back(std::to_string(items_entry.augslot5unk2)); - insert_values.push_back(std::to_string(items_entry.augslot6unk2)); - insert_values.push_back(std::to_string(items_entry.UNK120)); - insert_values.push_back(std::to_string(items_entry.UNK121)); - insert_values.push_back(std::to_string(items_entry.questitemflag)); - insert_values.push_back("'" + EscapeString(items_entry.UNK132) + "'"); - insert_values.push_back(std::to_string(items_entry.clickunk5)); - insert_values.push_back("'" + EscapeString(items_entry.clickunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.clickunk7)); - insert_values.push_back(std::to_string(items_entry.procunk1)); - insert_values.push_back(std::to_string(items_entry.procunk2)); - insert_values.push_back(std::to_string(items_entry.procunk3)); - insert_values.push_back(std::to_string(items_entry.procunk4)); - insert_values.push_back("'" + EscapeString(items_entry.procunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.procunk7)); - insert_values.push_back(std::to_string(items_entry.wornunk1)); - insert_values.push_back(std::to_string(items_entry.wornunk2)); - insert_values.push_back(std::to_string(items_entry.wornunk3)); - insert_values.push_back(std::to_string(items_entry.wornunk4)); - insert_values.push_back(std::to_string(items_entry.wornunk5)); - insert_values.push_back("'" + EscapeString(items_entry.wornunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.wornunk7)); - insert_values.push_back(std::to_string(items_entry.focusunk1)); - insert_values.push_back(std::to_string(items_entry.focusunk2)); - insert_values.push_back(std::to_string(items_entry.focusunk3)); - insert_values.push_back(std::to_string(items_entry.focusunk4)); - insert_values.push_back(std::to_string(items_entry.focusunk5)); - insert_values.push_back("'" + EscapeString(items_entry.focusunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.focusunk7)); - insert_values.push_back(std::to_string(items_entry.scrollunk1)); - insert_values.push_back(std::to_string(items_entry.scrollunk2)); - insert_values.push_back(std::to_string(items_entry.scrollunk3)); - insert_values.push_back(std::to_string(items_entry.scrollunk4)); - insert_values.push_back(std::to_string(items_entry.scrollunk5)); - insert_values.push_back("'" + EscapeString(items_entry.scrollunk6) + "'"); - insert_values.push_back(std::to_string(items_entry.scrollunk7)); - insert_values.push_back(std::to_string(items_entry.UNK193)); - insert_values.push_back(std::to_string(items_entry.purity)); - insert_values.push_back(std::to_string(items_entry.evoitem)); - insert_values.push_back(std::to_string(items_entry.evoid)); - insert_values.push_back(std::to_string(items_entry.evolvinglevel)); - insert_values.push_back(std::to_string(items_entry.evomax)); - insert_values.push_back("'" + EscapeString(items_entry.clickname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.procname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.wornname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.focusname) + "'"); - insert_values.push_back("'" + EscapeString(items_entry.scrollname) + "'"); - insert_values.push_back(std::to_string(items_entry.dsmitigation)); - insert_values.push_back(std::to_string(items_entry.heroic_str)); - insert_values.push_back(std::to_string(items_entry.heroic_int)); - insert_values.push_back(std::to_string(items_entry.heroic_wis)); - insert_values.push_back(std::to_string(items_entry.heroic_agi)); - insert_values.push_back(std::to_string(items_entry.heroic_dex)); - insert_values.push_back(std::to_string(items_entry.heroic_sta)); - insert_values.push_back(std::to_string(items_entry.heroic_cha)); - insert_values.push_back(std::to_string(items_entry.heroic_pr)); - insert_values.push_back(std::to_string(items_entry.heroic_dr)); - insert_values.push_back(std::to_string(items_entry.heroic_fr)); - insert_values.push_back(std::to_string(items_entry.heroic_cr)); - insert_values.push_back(std::to_string(items_entry.heroic_mr)); - insert_values.push_back(std::to_string(items_entry.heroic_svcorrup)); - insert_values.push_back(std::to_string(items_entry.healamt)); - insert_values.push_back(std::to_string(items_entry.spelldmg)); - insert_values.push_back(std::to_string(items_entry.clairvoyance)); - insert_values.push_back(std::to_string(items_entry.backstabdmg)); - insert_values.push_back("'" + EscapeString(items_entry.created) + "'"); - insert_values.push_back(std::to_string(items_entry.elitematerial)); - insert_values.push_back(std::to_string(items_entry.ldonsellbackrate)); - insert_values.push_back(std::to_string(items_entry.scriptfileid)); - insert_values.push_back(std::to_string(items_entry.expendablearrow)); - insert_values.push_back(std::to_string(items_entry.powersourcecapacity)); - insert_values.push_back(std::to_string(items_entry.bardeffect)); - insert_values.push_back(std::to_string(items_entry.bardeffecttype)); - insert_values.push_back(std::to_string(items_entry.bardlevel2)); - insert_values.push_back(std::to_string(items_entry.bardlevel)); - insert_values.push_back(std::to_string(items_entry.bardunk1)); - insert_values.push_back(std::to_string(items_entry.bardunk2)); - insert_values.push_back(std::to_string(items_entry.bardunk3)); - insert_values.push_back(std::to_string(items_entry.bardunk4)); - insert_values.push_back(std::to_string(items_entry.bardunk5)); - insert_values.push_back("'" + EscapeString(items_entry.bardname) + "'"); - insert_values.push_back(std::to_string(items_entry.bardunk7)); - insert_values.push_back(std::to_string(items_entry.UNK214)); - insert_values.push_back(std::to_string(items_entry.subtype)); - insert_values.push_back(std::to_string(items_entry.UNK220)); - insert_values.push_back(std::to_string(items_entry.UNK221)); - insert_values.push_back(std::to_string(items_entry.heirloom)); - insert_values.push_back(std::to_string(items_entry.UNK223)); - insert_values.push_back(std::to_string(items_entry.UNK224)); - insert_values.push_back(std::to_string(items_entry.UNK225)); - insert_values.push_back(std::to_string(items_entry.UNK226)); - insert_values.push_back(std::to_string(items_entry.UNK227)); - insert_values.push_back(std::to_string(items_entry.UNK228)); - insert_values.push_back(std::to_string(items_entry.UNK229)); - insert_values.push_back(std::to_string(items_entry.UNK230)); - insert_values.push_back(std::to_string(items_entry.UNK231)); - insert_values.push_back(std::to_string(items_entry.UNK232)); - insert_values.push_back(std::to_string(items_entry.UNK233)); - insert_values.push_back(std::to_string(items_entry.UNK234)); - insert_values.push_back(std::to_string(items_entry.placeable)); - insert_values.push_back(std::to_string(items_entry.UNK236)); - insert_values.push_back(std::to_string(items_entry.UNK237)); - insert_values.push_back(std::to_string(items_entry.UNK238)); - insert_values.push_back(std::to_string(items_entry.UNK239)); - insert_values.push_back(std::to_string(items_entry.UNK240)); - insert_values.push_back(std::to_string(items_entry.UNK241)); - insert_values.push_back(std::to_string(items_entry.epicitem)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.minstatus)); + v.push_back("'" + Strings::Escape(e.Name) + "'"); + v.push_back(std::to_string(e.aagi)); + v.push_back(std::to_string(e.ac)); + v.push_back(std::to_string(e.accuracy)); + v.push_back(std::to_string(e.acha)); + v.push_back(std::to_string(e.adex)); + v.push_back(std::to_string(e.aint)); + v.push_back(std::to_string(e.artifactflag)); + v.push_back(std::to_string(e.asta)); + v.push_back(std::to_string(e.astr)); + v.push_back(std::to_string(e.attack)); + v.push_back(std::to_string(e.augrestrict)); + v.push_back(std::to_string(e.augslot1type)); + v.push_back(std::to_string(e.augslot1visible)); + v.push_back(std::to_string(e.augslot2type)); + v.push_back(std::to_string(e.augslot2visible)); + v.push_back(std::to_string(e.augslot3type)); + v.push_back(std::to_string(e.augslot3visible)); + v.push_back(std::to_string(e.augslot4type)); + v.push_back(std::to_string(e.augslot4visible)); + v.push_back(std::to_string(e.augslot5type)); + v.push_back(std::to_string(e.augslot5visible)); + v.push_back(std::to_string(e.augslot6type)); + v.push_back(std::to_string(e.augslot6visible)); + v.push_back(std::to_string(e.augtype)); + v.push_back(std::to_string(e.avoidance)); + v.push_back(std::to_string(e.awis)); + v.push_back(std::to_string(e.bagsize)); + v.push_back(std::to_string(e.bagslots)); + v.push_back(std::to_string(e.bagtype)); + v.push_back(std::to_string(e.bagwr)); + v.push_back(std::to_string(e.banedmgamt)); + v.push_back(std::to_string(e.banedmgraceamt)); + v.push_back(std::to_string(e.banedmgbody)); + v.push_back(std::to_string(e.banedmgrace)); + v.push_back(std::to_string(e.bardtype)); + v.push_back(std::to_string(e.bardvalue)); + v.push_back(std::to_string(e.book)); + v.push_back(std::to_string(e.casttime)); + v.push_back(std::to_string(e.casttime_)); + v.push_back("'" + Strings::Escape(e.charmfile) + "'"); + v.push_back("'" + Strings::Escape(e.charmfileid) + "'"); + v.push_back(std::to_string(e.classes)); + v.push_back(std::to_string(e.color)); + v.push_back("'" + Strings::Escape(e.combateffects) + "'"); + v.push_back(std::to_string(e.extradmgskill)); + v.push_back(std::to_string(e.extradmgamt)); + v.push_back(std::to_string(e.price)); + v.push_back(std::to_string(e.cr)); + v.push_back(std::to_string(e.damage)); + v.push_back(std::to_string(e.damageshield)); + v.push_back(std::to_string(e.deity)); + v.push_back(std::to_string(e.delay)); + v.push_back(std::to_string(e.augdistiller)); + v.push_back(std::to_string(e.dotshielding)); + v.push_back(std::to_string(e.dr)); + v.push_back(std::to_string(e.clicktype)); + v.push_back(std::to_string(e.clicklevel2)); + v.push_back(std::to_string(e.elemdmgtype)); + v.push_back(std::to_string(e.elemdmgamt)); + v.push_back(std::to_string(e.endur)); + v.push_back(std::to_string(e.factionamt1)); + v.push_back(std::to_string(e.factionamt2)); + v.push_back(std::to_string(e.factionamt3)); + v.push_back(std::to_string(e.factionamt4)); + v.push_back(std::to_string(e.factionmod1)); + v.push_back(std::to_string(e.factionmod2)); + v.push_back(std::to_string(e.factionmod3)); + v.push_back(std::to_string(e.factionmod4)); + v.push_back("'" + Strings::Escape(e.filename) + "'"); + v.push_back(std::to_string(e.focuseffect)); + v.push_back(std::to_string(e.fr)); + v.push_back(std::to_string(e.fvnodrop)); + v.push_back(std::to_string(e.haste)); + v.push_back(std::to_string(e.clicklevel)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.regen)); + v.push_back(std::to_string(e.icon)); + v.push_back("'" + Strings::Escape(e.idfile) + "'"); + v.push_back(std::to_string(e.itemclass)); + v.push_back(std::to_string(e.itemtype)); + v.push_back(std::to_string(e.ldonprice)); + v.push_back(std::to_string(e.ldontheme)); + v.push_back(std::to_string(e.ldonsold)); + v.push_back(std::to_string(e.light)); + v.push_back("'" + Strings::Escape(e.lore) + "'"); + v.push_back(std::to_string(e.loregroup)); + v.push_back(std::to_string(e.magic)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.manaregen)); + v.push_back(std::to_string(e.enduranceregen)); + v.push_back(std::to_string(e.material)); + v.push_back(std::to_string(e.herosforgemodel)); + v.push_back(std::to_string(e.maxcharges)); + v.push_back(std::to_string(e.mr)); + v.push_back(std::to_string(e.nodrop)); + v.push_back(std::to_string(e.norent)); + v.push_back(std::to_string(e.pendingloreflag)); + v.push_back(std::to_string(e.pr)); + v.push_back(std::to_string(e.procrate)); + v.push_back(std::to_string(e.races)); + v.push_back(std::to_string(e.range)); + v.push_back(std::to_string(e.reclevel)); + v.push_back(std::to_string(e.recskill)); + v.push_back(std::to_string(e.reqlevel)); + v.push_back(std::to_string(e.sellrate)); + v.push_back(std::to_string(e.shielding)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.skillmodtype)); + v.push_back(std::to_string(e.skillmodvalue)); + v.push_back(std::to_string(e.slots)); + v.push_back(std::to_string(e.clickeffect)); + v.push_back(std::to_string(e.spellshield)); + v.push_back(std::to_string(e.strikethrough)); + v.push_back(std::to_string(e.stunresist)); + v.push_back(std::to_string(e.summonedflag)); + v.push_back(std::to_string(e.tradeskills)); + v.push_back(std::to_string(e.favor)); + v.push_back(std::to_string(e.weight)); + v.push_back(std::to_string(e.UNK012)); + v.push_back(std::to_string(e.UNK013)); + v.push_back(std::to_string(e.benefitflag)); + v.push_back(std::to_string(e.UNK054)); + v.push_back(std::to_string(e.UNK059)); + v.push_back(std::to_string(e.booktype)); + v.push_back(std::to_string(e.recastdelay)); + v.push_back(std::to_string(e.recasttype)); + v.push_back(std::to_string(e.guildfavor)); + v.push_back(std::to_string(e.UNK123)); + v.push_back(std::to_string(e.UNK124)); + v.push_back(std::to_string(e.attuneable)); + v.push_back(std::to_string(e.nopet)); + v.push_back("FROM_UNIXTIME(" + (e.updated > 0 ? std::to_string(e.updated) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.comment) + "'"); + v.push_back(std::to_string(e.UNK127)); + v.push_back(std::to_string(e.pointtype)); + v.push_back(std::to_string(e.potionbelt)); + v.push_back(std::to_string(e.potionbeltslots)); + v.push_back(std::to_string(e.stacksize)); + v.push_back(std::to_string(e.notransfer)); + v.push_back(std::to_string(e.stackable)); + v.push_back("'" + Strings::Escape(e.UNK134) + "'"); + v.push_back(std::to_string(e.UNK137)); + v.push_back(std::to_string(e.proceffect)); + v.push_back(std::to_string(e.proctype)); + v.push_back(std::to_string(e.proclevel2)); + v.push_back(std::to_string(e.proclevel)); + v.push_back(std::to_string(e.UNK142)); + v.push_back(std::to_string(e.worneffect)); + v.push_back(std::to_string(e.worntype)); + v.push_back(std::to_string(e.wornlevel2)); + v.push_back(std::to_string(e.wornlevel)); + v.push_back(std::to_string(e.UNK147)); + v.push_back(std::to_string(e.focustype)); + v.push_back(std::to_string(e.focuslevel2)); + v.push_back(std::to_string(e.focuslevel)); + v.push_back(std::to_string(e.UNK152)); + v.push_back(std::to_string(e.scrolleffect)); + v.push_back(std::to_string(e.scrolltype)); + v.push_back(std::to_string(e.scrolllevel2)); + v.push_back(std::to_string(e.scrolllevel)); + v.push_back(std::to_string(e.UNK157)); + v.push_back("FROM_UNIXTIME(" + (e.serialized > 0 ? std::to_string(e.serialized) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.verified > 0 ? std::to_string(e.verified) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.serialization) + "'"); + v.push_back("'" + Strings::Escape(e.source) + "'"); + v.push_back(std::to_string(e.UNK033)); + v.push_back("'" + Strings::Escape(e.lorefile) + "'"); + v.push_back(std::to_string(e.UNK014)); + v.push_back(std::to_string(e.svcorruption)); + v.push_back(std::to_string(e.skillmodmax)); + v.push_back(std::to_string(e.UNK060)); + v.push_back(std::to_string(e.augslot1unk2)); + v.push_back(std::to_string(e.augslot2unk2)); + v.push_back(std::to_string(e.augslot3unk2)); + v.push_back(std::to_string(e.augslot4unk2)); + v.push_back(std::to_string(e.augslot5unk2)); + v.push_back(std::to_string(e.augslot6unk2)); + v.push_back(std::to_string(e.UNK120)); + v.push_back(std::to_string(e.UNK121)); + v.push_back(std::to_string(e.questitemflag)); + v.push_back("'" + Strings::Escape(e.UNK132) + "'"); + v.push_back(std::to_string(e.clickunk5)); + v.push_back("'" + Strings::Escape(e.clickunk6) + "'"); + v.push_back(std::to_string(e.clickunk7)); + v.push_back(std::to_string(e.procunk1)); + v.push_back(std::to_string(e.procunk2)); + v.push_back(std::to_string(e.procunk3)); + v.push_back(std::to_string(e.procunk4)); + v.push_back("'" + Strings::Escape(e.procunk6) + "'"); + v.push_back(std::to_string(e.procunk7)); + v.push_back(std::to_string(e.wornunk1)); + v.push_back(std::to_string(e.wornunk2)); + v.push_back(std::to_string(e.wornunk3)); + v.push_back(std::to_string(e.wornunk4)); + v.push_back(std::to_string(e.wornunk5)); + v.push_back("'" + Strings::Escape(e.wornunk6) + "'"); + v.push_back(std::to_string(e.wornunk7)); + v.push_back(std::to_string(e.focusunk1)); + v.push_back(std::to_string(e.focusunk2)); + v.push_back(std::to_string(e.focusunk3)); + v.push_back(std::to_string(e.focusunk4)); + v.push_back(std::to_string(e.focusunk5)); + v.push_back("'" + Strings::Escape(e.focusunk6) + "'"); + v.push_back(std::to_string(e.focusunk7)); + v.push_back(std::to_string(e.scrollunk1)); + v.push_back(std::to_string(e.scrollunk2)); + v.push_back(std::to_string(e.scrollunk3)); + v.push_back(std::to_string(e.scrollunk4)); + v.push_back(std::to_string(e.scrollunk5)); + v.push_back("'" + Strings::Escape(e.scrollunk6) + "'"); + v.push_back(std::to_string(e.scrollunk7)); + v.push_back(std::to_string(e.UNK193)); + v.push_back(std::to_string(e.purity)); + v.push_back(std::to_string(e.evoitem)); + v.push_back(std::to_string(e.evoid)); + v.push_back(std::to_string(e.evolvinglevel)); + v.push_back(std::to_string(e.evomax)); + v.push_back("'" + Strings::Escape(e.clickname) + "'"); + v.push_back("'" + Strings::Escape(e.procname) + "'"); + v.push_back("'" + Strings::Escape(e.wornname) + "'"); + v.push_back("'" + Strings::Escape(e.focusname) + "'"); + v.push_back("'" + Strings::Escape(e.scrollname) + "'"); + v.push_back(std::to_string(e.dsmitigation)); + v.push_back(std::to_string(e.heroic_str)); + v.push_back(std::to_string(e.heroic_int)); + v.push_back(std::to_string(e.heroic_wis)); + v.push_back(std::to_string(e.heroic_agi)); + v.push_back(std::to_string(e.heroic_dex)); + v.push_back(std::to_string(e.heroic_sta)); + v.push_back(std::to_string(e.heroic_cha)); + v.push_back(std::to_string(e.heroic_pr)); + v.push_back(std::to_string(e.heroic_dr)); + v.push_back(std::to_string(e.heroic_fr)); + v.push_back(std::to_string(e.heroic_cr)); + v.push_back(std::to_string(e.heroic_mr)); + v.push_back(std::to_string(e.heroic_svcorrup)); + v.push_back(std::to_string(e.healamt)); + v.push_back(std::to_string(e.spelldmg)); + v.push_back(std::to_string(e.clairvoyance)); + v.push_back(std::to_string(e.backstabdmg)); + v.push_back("'" + Strings::Escape(e.created) + "'"); + v.push_back(std::to_string(e.elitematerial)); + v.push_back(std::to_string(e.ldonsellbackrate)); + v.push_back(std::to_string(e.scriptfileid)); + v.push_back(std::to_string(e.expendablearrow)); + v.push_back(std::to_string(e.powersourcecapacity)); + v.push_back(std::to_string(e.bardeffect)); + v.push_back(std::to_string(e.bardeffecttype)); + v.push_back(std::to_string(e.bardlevel2)); + v.push_back(std::to_string(e.bardlevel)); + v.push_back(std::to_string(e.bardunk1)); + v.push_back(std::to_string(e.bardunk2)); + v.push_back(std::to_string(e.bardunk3)); + v.push_back(std::to_string(e.bardunk4)); + v.push_back(std::to_string(e.bardunk5)); + v.push_back("'" + Strings::Escape(e.bardname) + "'"); + v.push_back(std::to_string(e.bardunk7)); + v.push_back(std::to_string(e.UNK214)); + v.push_back(std::to_string(e.subtype)); + v.push_back(std::to_string(e.UNK220)); + v.push_back(std::to_string(e.UNK221)); + v.push_back(std::to_string(e.heirloom)); + v.push_back(std::to_string(e.UNK223)); + v.push_back(std::to_string(e.UNK224)); + v.push_back(std::to_string(e.UNK225)); + v.push_back(std::to_string(e.UNK226)); + v.push_back(std::to_string(e.UNK227)); + v.push_back(std::to_string(e.UNK228)); + v.push_back(std::to_string(e.UNK229)); + v.push_back(std::to_string(e.UNK230)); + v.push_back(std::to_string(e.UNK231)); + v.push_back(std::to_string(e.UNK232)); + v.push_back(std::to_string(e.UNK233)); + v.push_back(std::to_string(e.UNK234)); + v.push_back(std::to_string(e.placeable)); + v.push_back(std::to_string(e.UNK236)); + v.push_back(std::to_string(e.UNK237)); + v.push_back(std::to_string(e.UNK238)); + v.push_back(std::to_string(e.UNK239)); + v.push_back(std::to_string(e.UNK240)); + v.push_back(std::to_string(e.UNK241)); + v.push_back(std::to_string(e.epicitem)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -2504,301 +2504,301 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Items entry{}; + Items e{}; - entry.id = atoi(row[0]); - entry.minstatus = atoi(row[1]); - entry.Name = row[2] ? row[2] : ""; - entry.aagi = atoi(row[3]); - entry.ac = atoi(row[4]); - entry.accuracy = atoi(row[5]); - entry.acha = atoi(row[6]); - entry.adex = atoi(row[7]); - entry.aint = atoi(row[8]); - entry.artifactflag = atoi(row[9]); - entry.asta = atoi(row[10]); - entry.astr = atoi(row[11]); - entry.attack = atoi(row[12]); - entry.augrestrict = atoi(row[13]); - entry.augslot1type = atoi(row[14]); - entry.augslot1visible = atoi(row[15]); - entry.augslot2type = atoi(row[16]); - entry.augslot2visible = atoi(row[17]); - entry.augslot3type = atoi(row[18]); - entry.augslot3visible = atoi(row[19]); - entry.augslot4type = atoi(row[20]); - entry.augslot4visible = atoi(row[21]); - entry.augslot5type = atoi(row[22]); - entry.augslot5visible = atoi(row[23]); - entry.augslot6type = atoi(row[24]); - entry.augslot6visible = atoi(row[25]); - entry.augtype = atoi(row[26]); - entry.avoidance = atoi(row[27]); - entry.awis = atoi(row[28]); - entry.bagsize = atoi(row[29]); - entry.bagslots = atoi(row[30]); - entry.bagtype = atoi(row[31]); - entry.bagwr = atoi(row[32]); - entry.banedmgamt = atoi(row[33]); - entry.banedmgraceamt = atoi(row[34]); - entry.banedmgbody = atoi(row[35]); - entry.banedmgrace = atoi(row[36]); - entry.bardtype = atoi(row[37]); - entry.bardvalue = atoi(row[38]); - entry.book = atoi(row[39]); - entry.casttime = atoi(row[40]); - entry.casttime_ = atoi(row[41]); - entry.charmfile = row[42] ? row[42] : ""; - entry.charmfileid = row[43] ? row[43] : ""; - entry.classes = atoi(row[44]); - entry.color = atoi(row[45]); - entry.combateffects = row[46] ? row[46] : ""; - entry.extradmgskill = atoi(row[47]); - entry.extradmgamt = atoi(row[48]); - entry.price = atoi(row[49]); - entry.cr = atoi(row[50]); - entry.damage = atoi(row[51]); - entry.damageshield = atoi(row[52]); - entry.deity = atoi(row[53]); - entry.delay = atoi(row[54]); - entry.augdistiller = atoi(row[55]); - entry.dotshielding = atoi(row[56]); - entry.dr = atoi(row[57]); - entry.clicktype = atoi(row[58]); - entry.clicklevel2 = atoi(row[59]); - entry.elemdmgtype = atoi(row[60]); - entry.elemdmgamt = atoi(row[61]); - entry.endur = atoi(row[62]); - entry.factionamt1 = atoi(row[63]); - entry.factionamt2 = atoi(row[64]); - entry.factionamt3 = atoi(row[65]); - entry.factionamt4 = atoi(row[66]); - entry.factionmod1 = atoi(row[67]); - entry.factionmod2 = atoi(row[68]); - entry.factionmod3 = atoi(row[69]); - entry.factionmod4 = atoi(row[70]); - entry.filename = row[71] ? row[71] : ""; - entry.focuseffect = atoi(row[72]); - entry.fr = atoi(row[73]); - entry.fvnodrop = atoi(row[74]); - entry.haste = atoi(row[75]); - entry.clicklevel = atoi(row[76]); - entry.hp = atoi(row[77]); - entry.regen = atoi(row[78]); - entry.icon = atoi(row[79]); - entry.idfile = row[80] ? row[80] : ""; - entry.itemclass = atoi(row[81]); - entry.itemtype = atoi(row[82]); - entry.ldonprice = atoi(row[83]); - entry.ldontheme = atoi(row[84]); - entry.ldonsold = atoi(row[85]); - entry.light = atoi(row[86]); - entry.lore = row[87] ? row[87] : ""; - entry.loregroup = atoi(row[88]); - entry.magic = atoi(row[89]); - entry.mana = atoi(row[90]); - entry.manaregen = atoi(row[91]); - entry.enduranceregen = atoi(row[92]); - entry.material = atoi(row[93]); - entry.herosforgemodel = atoi(row[94]); - entry.maxcharges = atoi(row[95]); - entry.mr = atoi(row[96]); - entry.nodrop = atoi(row[97]); - entry.norent = atoi(row[98]); - entry.pendingloreflag = atoi(row[99]); - entry.pr = atoi(row[100]); - entry.procrate = atoi(row[101]); - entry.races = atoi(row[102]); - entry.range = atoi(row[103]); - entry.reclevel = atoi(row[104]); - entry.recskill = atoi(row[105]); - entry.reqlevel = atoi(row[106]); - entry.sellrate = static_cast(atof(row[107])); - entry.shielding = atoi(row[108]); - entry.size = atoi(row[109]); - entry.skillmodtype = atoi(row[110]); - entry.skillmodvalue = atoi(row[111]); - entry.slots = atoi(row[112]); - entry.clickeffect = atoi(row[113]); - entry.spellshield = atoi(row[114]); - entry.strikethrough = atoi(row[115]); - entry.stunresist = atoi(row[116]); - entry.summonedflag = atoi(row[117]); - entry.tradeskills = atoi(row[118]); - entry.favor = atoi(row[119]); - entry.weight = atoi(row[120]); - entry.UNK012 = atoi(row[121]); - entry.UNK013 = atoi(row[122]); - entry.benefitflag = atoi(row[123]); - entry.UNK054 = atoi(row[124]); - entry.UNK059 = atoi(row[125]); - entry.booktype = atoi(row[126]); - entry.recastdelay = atoi(row[127]); - entry.recasttype = atoi(row[128]); - entry.guildfavor = atoi(row[129]); - entry.UNK123 = atoi(row[130]); - entry.UNK124 = atoi(row[131]); - entry.attuneable = atoi(row[132]); - entry.nopet = atoi(row[133]); - entry.updated = strtoll(row[134] ? row[134] : "-1", nullptr, 10); - entry.comment = row[135] ? row[135] : ""; - entry.UNK127 = atoi(row[136]); - entry.pointtype = atoi(row[137]); - entry.potionbelt = atoi(row[138]); - entry.potionbeltslots = atoi(row[139]); - entry.stacksize = atoi(row[140]); - entry.notransfer = atoi(row[141]); - entry.stackable = atoi(row[142]); - entry.UNK134 = row[143] ? row[143] : ""; - entry.UNK137 = atoi(row[144]); - entry.proceffect = atoi(row[145]); - entry.proctype = atoi(row[146]); - entry.proclevel2 = atoi(row[147]); - entry.proclevel = atoi(row[148]); - entry.UNK142 = atoi(row[149]); - entry.worneffect = atoi(row[150]); - entry.worntype = atoi(row[151]); - entry.wornlevel2 = atoi(row[152]); - entry.wornlevel = atoi(row[153]); - entry.UNK147 = atoi(row[154]); - entry.focustype = atoi(row[155]); - entry.focuslevel2 = atoi(row[156]); - entry.focuslevel = atoi(row[157]); - entry.UNK152 = atoi(row[158]); - entry.scrolleffect = atoi(row[159]); - entry.scrolltype = atoi(row[160]); - entry.scrolllevel2 = atoi(row[161]); - entry.scrolllevel = atoi(row[162]); - entry.UNK157 = atoi(row[163]); - entry.serialized = strtoll(row[164] ? row[164] : "-1", nullptr, 10); - entry.verified = strtoll(row[165] ? row[165] : "-1", nullptr, 10); - entry.serialization = row[166] ? row[166] : ""; - entry.source = row[167] ? row[167] : ""; - entry.UNK033 = atoi(row[168]); - entry.lorefile = row[169] ? row[169] : ""; - entry.UNK014 = atoi(row[170]); - entry.svcorruption = atoi(row[171]); - entry.skillmodmax = atoi(row[172]); - entry.UNK060 = atoi(row[173]); - entry.augslot1unk2 = atoi(row[174]); - entry.augslot2unk2 = atoi(row[175]); - entry.augslot3unk2 = atoi(row[176]); - entry.augslot4unk2 = atoi(row[177]); - entry.augslot5unk2 = atoi(row[178]); - entry.augslot6unk2 = atoi(row[179]); - entry.UNK120 = atoi(row[180]); - entry.UNK121 = atoi(row[181]); - entry.questitemflag = atoi(row[182]); - entry.UNK132 = row[183] ? row[183] : ""; - entry.clickunk5 = atoi(row[184]); - entry.clickunk6 = row[185] ? row[185] : ""; - entry.clickunk7 = atoi(row[186]); - entry.procunk1 = atoi(row[187]); - entry.procunk2 = atoi(row[188]); - entry.procunk3 = atoi(row[189]); - entry.procunk4 = atoi(row[190]); - entry.procunk6 = row[191] ? row[191] : ""; - entry.procunk7 = atoi(row[192]); - entry.wornunk1 = atoi(row[193]); - entry.wornunk2 = atoi(row[194]); - entry.wornunk3 = atoi(row[195]); - entry.wornunk4 = atoi(row[196]); - entry.wornunk5 = atoi(row[197]); - entry.wornunk6 = row[198] ? row[198] : ""; - entry.wornunk7 = atoi(row[199]); - entry.focusunk1 = atoi(row[200]); - entry.focusunk2 = atoi(row[201]); - entry.focusunk3 = atoi(row[202]); - entry.focusunk4 = atoi(row[203]); - entry.focusunk5 = atoi(row[204]); - entry.focusunk6 = row[205] ? row[205] : ""; - entry.focusunk7 = atoi(row[206]); - entry.scrollunk1 = atoi(row[207]); - entry.scrollunk2 = atoi(row[208]); - entry.scrollunk3 = atoi(row[209]); - entry.scrollunk4 = atoi(row[210]); - entry.scrollunk5 = atoi(row[211]); - entry.scrollunk6 = row[212] ? row[212] : ""; - entry.scrollunk7 = atoi(row[213]); - entry.UNK193 = atoi(row[214]); - entry.purity = atoi(row[215]); - entry.evoitem = atoi(row[216]); - entry.evoid = atoi(row[217]); - entry.evolvinglevel = atoi(row[218]); - entry.evomax = atoi(row[219]); - entry.clickname = row[220] ? row[220] : ""; - entry.procname = row[221] ? row[221] : ""; - entry.wornname = row[222] ? row[222] : ""; - entry.focusname = row[223] ? row[223] : ""; - entry.scrollname = row[224] ? row[224] : ""; - entry.dsmitigation = atoi(row[225]); - entry.heroic_str = atoi(row[226]); - entry.heroic_int = atoi(row[227]); - entry.heroic_wis = atoi(row[228]); - entry.heroic_agi = atoi(row[229]); - entry.heroic_dex = atoi(row[230]); - entry.heroic_sta = atoi(row[231]); - entry.heroic_cha = atoi(row[232]); - entry.heroic_pr = atoi(row[233]); - entry.heroic_dr = atoi(row[234]); - entry.heroic_fr = atoi(row[235]); - entry.heroic_cr = atoi(row[236]); - entry.heroic_mr = atoi(row[237]); - entry.heroic_svcorrup = atoi(row[238]); - entry.healamt = atoi(row[239]); - entry.spelldmg = atoi(row[240]); - entry.clairvoyance = atoi(row[241]); - entry.backstabdmg = atoi(row[242]); - entry.created = row[243] ? row[243] : ""; - entry.elitematerial = atoi(row[244]); - entry.ldonsellbackrate = atoi(row[245]); - entry.scriptfileid = atoi(row[246]); - entry.expendablearrow = atoi(row[247]); - entry.powersourcecapacity = atoi(row[248]); - entry.bardeffect = atoi(row[249]); - entry.bardeffecttype = atoi(row[250]); - entry.bardlevel2 = atoi(row[251]); - entry.bardlevel = atoi(row[252]); - entry.bardunk1 = atoi(row[253]); - entry.bardunk2 = atoi(row[254]); - entry.bardunk3 = atoi(row[255]); - entry.bardunk4 = atoi(row[256]); - entry.bardunk5 = atoi(row[257]); - entry.bardname = row[258] ? row[258] : ""; - entry.bardunk7 = atoi(row[259]); - entry.UNK214 = atoi(row[260]); - entry.subtype = atoi(row[261]); - entry.UNK220 = atoi(row[262]); - entry.UNK221 = atoi(row[263]); - entry.heirloom = atoi(row[264]); - entry.UNK223 = atoi(row[265]); - entry.UNK224 = atoi(row[266]); - entry.UNK225 = atoi(row[267]); - entry.UNK226 = atoi(row[268]); - entry.UNK227 = atoi(row[269]); - entry.UNK228 = atoi(row[270]); - entry.UNK229 = atoi(row[271]); - entry.UNK230 = atoi(row[272]); - entry.UNK231 = atoi(row[273]); - entry.UNK232 = atoi(row[274]); - entry.UNK233 = atoi(row[275]); - entry.UNK234 = atoi(row[276]); - entry.placeable = atoi(row[277]); - entry.UNK236 = atoi(row[278]); - entry.UNK237 = atoi(row[279]); - entry.UNK238 = atoi(row[280]); - entry.UNK239 = atoi(row[281]); - entry.UNK240 = atoi(row[282]); - entry.UNK241 = atoi(row[283]); - entry.epicitem = atoi(row[284]); + e.id = static_cast(atoi(row[0])); + e.minstatus = static_cast(atoi(row[1])); + e.Name = row[2] ? row[2] : ""; + e.aagi = static_cast(atoi(row[3])); + e.ac = static_cast(atoi(row[4])); + e.accuracy = static_cast(atoi(row[5])); + e.acha = static_cast(atoi(row[6])); + e.adex = static_cast(atoi(row[7])); + e.aint = static_cast(atoi(row[8])); + e.artifactflag = static_cast(strtoul(row[9], nullptr, 10)); + e.asta = static_cast(atoi(row[10])); + e.astr = static_cast(atoi(row[11])); + e.attack = static_cast(atoi(row[12])); + e.augrestrict = static_cast(atoi(row[13])); + e.augslot1type = static_cast(atoi(row[14])); + e.augslot1visible = static_cast(atoi(row[15])); + e.augslot2type = static_cast(atoi(row[16])); + e.augslot2visible = static_cast(atoi(row[17])); + e.augslot3type = static_cast(atoi(row[18])); + e.augslot3visible = static_cast(atoi(row[19])); + e.augslot4type = static_cast(atoi(row[20])); + e.augslot4visible = static_cast(atoi(row[21])); + e.augslot5type = static_cast(atoi(row[22])); + e.augslot5visible = static_cast(atoi(row[23])); + e.augslot6type = static_cast(atoi(row[24])); + e.augslot6visible = static_cast(atoi(row[25])); + e.augtype = static_cast(atoi(row[26])); + e.avoidance = static_cast(atoi(row[27])); + e.awis = static_cast(atoi(row[28])); + e.bagsize = static_cast(atoi(row[29])); + e.bagslots = static_cast(atoi(row[30])); + e.bagtype = static_cast(atoi(row[31])); + e.bagwr = static_cast(atoi(row[32])); + e.banedmgamt = static_cast(atoi(row[33])); + e.banedmgraceamt = static_cast(atoi(row[34])); + e.banedmgbody = static_cast(atoi(row[35])); + e.banedmgrace = static_cast(atoi(row[36])); + e.bardtype = static_cast(atoi(row[37])); + e.bardvalue = static_cast(atoi(row[38])); + e.book = static_cast(atoi(row[39])); + e.casttime = static_cast(atoi(row[40])); + e.casttime_ = static_cast(atoi(row[41])); + e.charmfile = row[42] ? row[42] : ""; + e.charmfileid = row[43] ? row[43] : ""; + e.classes = static_cast(atoi(row[44])); + e.color = static_cast(strtoul(row[45], nullptr, 10)); + e.combateffects = row[46] ? row[46] : ""; + e.extradmgskill = static_cast(atoi(row[47])); + e.extradmgamt = static_cast(atoi(row[48])); + e.price = static_cast(atoi(row[49])); + e.cr = static_cast(atoi(row[50])); + e.damage = static_cast(atoi(row[51])); + e.damageshield = static_cast(atoi(row[52])); + e.deity = static_cast(atoi(row[53])); + e.delay = static_cast(atoi(row[54])); + e.augdistiller = static_cast(atoi(row[55])); + e.dotshielding = static_cast(atoi(row[56])); + e.dr = static_cast(atoi(row[57])); + e.clicktype = static_cast(atoi(row[58])); + e.clicklevel2 = static_cast(atoi(row[59])); + e.elemdmgtype = static_cast(atoi(row[60])); + e.elemdmgamt = static_cast(atoi(row[61])); + e.endur = static_cast(atoi(row[62])); + e.factionamt1 = static_cast(atoi(row[63])); + e.factionamt2 = static_cast(atoi(row[64])); + e.factionamt3 = static_cast(atoi(row[65])); + e.factionamt4 = static_cast(atoi(row[66])); + e.factionmod1 = static_cast(atoi(row[67])); + e.factionmod2 = static_cast(atoi(row[68])); + e.factionmod3 = static_cast(atoi(row[69])); + e.factionmod4 = static_cast(atoi(row[70])); + e.filename = row[71] ? row[71] : ""; + e.focuseffect = static_cast(atoi(row[72])); + e.fr = static_cast(atoi(row[73])); + e.fvnodrop = static_cast(atoi(row[74])); + e.haste = static_cast(atoi(row[75])); + e.clicklevel = static_cast(atoi(row[76])); + e.hp = static_cast(atoi(row[77])); + e.regen = static_cast(atoi(row[78])); + e.icon = static_cast(atoi(row[79])); + e.idfile = row[80] ? row[80] : ""; + e.itemclass = static_cast(atoi(row[81])); + e.itemtype = static_cast(atoi(row[82])); + e.ldonprice = static_cast(atoi(row[83])); + e.ldontheme = static_cast(atoi(row[84])); + e.ldonsold = static_cast(atoi(row[85])); + e.light = static_cast(atoi(row[86])); + e.lore = row[87] ? row[87] : ""; + e.loregroup = static_cast(atoi(row[88])); + e.magic = static_cast(atoi(row[89])); + e.mana = static_cast(atoi(row[90])); + e.manaregen = static_cast(atoi(row[91])); + e.enduranceregen = static_cast(atoi(row[92])); + e.material = static_cast(atoi(row[93])); + e.herosforgemodel = static_cast(atoi(row[94])); + e.maxcharges = static_cast(atoi(row[95])); + e.mr = static_cast(atoi(row[96])); + e.nodrop = static_cast(atoi(row[97])); + e.norent = static_cast(atoi(row[98])); + e.pendingloreflag = static_cast(strtoul(row[99], nullptr, 10)); + e.pr = static_cast(atoi(row[100])); + e.procrate = static_cast(atoi(row[101])); + e.races = static_cast(atoi(row[102])); + e.range = static_cast(atoi(row[103])); + e.reclevel = static_cast(atoi(row[104])); + e.recskill = static_cast(atoi(row[105])); + e.reqlevel = static_cast(atoi(row[106])); + e.sellrate = strtof(row[107], nullptr); + e.shielding = static_cast(atoi(row[108])); + e.size = static_cast(atoi(row[109])); + e.skillmodtype = static_cast(atoi(row[110])); + e.skillmodvalue = static_cast(atoi(row[111])); + e.slots = static_cast(atoi(row[112])); + e.clickeffect = static_cast(atoi(row[113])); + e.spellshield = static_cast(atoi(row[114])); + e.strikethrough = static_cast(atoi(row[115])); + e.stunresist = static_cast(atoi(row[116])); + e.summonedflag = static_cast(strtoul(row[117], nullptr, 10)); + e.tradeskills = static_cast(atoi(row[118])); + e.favor = static_cast(atoi(row[119])); + e.weight = static_cast(atoi(row[120])); + e.UNK012 = static_cast(atoi(row[121])); + e.UNK013 = static_cast(atoi(row[122])); + e.benefitflag = static_cast(atoi(row[123])); + e.UNK054 = static_cast(atoi(row[124])); + e.UNK059 = static_cast(atoi(row[125])); + e.booktype = static_cast(atoi(row[126])); + e.recastdelay = static_cast(atoi(row[127])); + e.recasttype = static_cast(atoi(row[128])); + e.guildfavor = static_cast(atoi(row[129])); + e.UNK123 = static_cast(atoi(row[130])); + e.UNK124 = static_cast(atoi(row[131])); + e.attuneable = static_cast(atoi(row[132])); + e.nopet = static_cast(atoi(row[133])); + e.updated = strtoll(row[134] ? row[134] : "-1", nullptr, 10); + e.comment = row[135] ? row[135] : ""; + e.UNK127 = static_cast(atoi(row[136])); + e.pointtype = static_cast(atoi(row[137])); + e.potionbelt = static_cast(atoi(row[138])); + e.potionbeltslots = static_cast(atoi(row[139])); + e.stacksize = static_cast(atoi(row[140])); + e.notransfer = static_cast(atoi(row[141])); + e.stackable = static_cast(atoi(row[142])); + e.UNK134 = row[143] ? row[143] : ""; + e.UNK137 = static_cast(atoi(row[144])); + e.proceffect = static_cast(atoi(row[145])); + e.proctype = static_cast(atoi(row[146])); + e.proclevel2 = static_cast(atoi(row[147])); + e.proclevel = static_cast(atoi(row[148])); + e.UNK142 = static_cast(atoi(row[149])); + e.worneffect = static_cast(atoi(row[150])); + e.worntype = static_cast(atoi(row[151])); + e.wornlevel2 = static_cast(atoi(row[152])); + e.wornlevel = static_cast(atoi(row[153])); + e.UNK147 = static_cast(atoi(row[154])); + e.focustype = static_cast(atoi(row[155])); + e.focuslevel2 = static_cast(atoi(row[156])); + e.focuslevel = static_cast(atoi(row[157])); + e.UNK152 = static_cast(atoi(row[158])); + e.scrolleffect = static_cast(atoi(row[159])); + e.scrolltype = static_cast(atoi(row[160])); + e.scrolllevel2 = static_cast(atoi(row[161])); + e.scrolllevel = static_cast(atoi(row[162])); + e.UNK157 = static_cast(atoi(row[163])); + e.serialized = strtoll(row[164] ? row[164] : "-1", nullptr, 10); + e.verified = strtoll(row[165] ? row[165] : "-1", nullptr, 10); + e.serialization = row[166] ? row[166] : ""; + e.source = row[167] ? row[167] : ""; + e.UNK033 = static_cast(atoi(row[168])); + e.lorefile = row[169] ? row[169] : ""; + e.UNK014 = static_cast(atoi(row[170])); + e.svcorruption = static_cast(atoi(row[171])); + e.skillmodmax = static_cast(atoi(row[172])); + e.UNK060 = static_cast(atoi(row[173])); + e.augslot1unk2 = static_cast(atoi(row[174])); + e.augslot2unk2 = static_cast(atoi(row[175])); + e.augslot3unk2 = static_cast(atoi(row[176])); + e.augslot4unk2 = static_cast(atoi(row[177])); + e.augslot5unk2 = static_cast(atoi(row[178])); + e.augslot6unk2 = static_cast(atoi(row[179])); + e.UNK120 = static_cast(atoi(row[180])); + e.UNK121 = static_cast(atoi(row[181])); + e.questitemflag = static_cast(atoi(row[182])); + e.UNK132 = row[183] ? row[183] : ""; + e.clickunk5 = static_cast(atoi(row[184])); + e.clickunk6 = row[185] ? row[185] : ""; + e.clickunk7 = static_cast(atoi(row[186])); + e.procunk1 = static_cast(atoi(row[187])); + e.procunk2 = static_cast(atoi(row[188])); + e.procunk3 = static_cast(atoi(row[189])); + e.procunk4 = static_cast(atoi(row[190])); + e.procunk6 = row[191] ? row[191] : ""; + e.procunk7 = static_cast(atoi(row[192])); + e.wornunk1 = static_cast(atoi(row[193])); + e.wornunk2 = static_cast(atoi(row[194])); + e.wornunk3 = static_cast(atoi(row[195])); + e.wornunk4 = static_cast(atoi(row[196])); + e.wornunk5 = static_cast(atoi(row[197])); + e.wornunk6 = row[198] ? row[198] : ""; + e.wornunk7 = static_cast(atoi(row[199])); + e.focusunk1 = static_cast(atoi(row[200])); + e.focusunk2 = static_cast(atoi(row[201])); + e.focusunk3 = static_cast(atoi(row[202])); + e.focusunk4 = static_cast(atoi(row[203])); + e.focusunk5 = static_cast(atoi(row[204])); + e.focusunk6 = row[205] ? row[205] : ""; + e.focusunk7 = static_cast(atoi(row[206])); + e.scrollunk1 = static_cast(atoi(row[207])); + e.scrollunk2 = static_cast(atoi(row[208])); + e.scrollunk3 = static_cast(atoi(row[209])); + e.scrollunk4 = static_cast(atoi(row[210])); + e.scrollunk5 = static_cast(atoi(row[211])); + e.scrollunk6 = row[212] ? row[212] : ""; + e.scrollunk7 = static_cast(atoi(row[213])); + e.UNK193 = static_cast(atoi(row[214])); + e.purity = static_cast(atoi(row[215])); + e.evoitem = static_cast(atoi(row[216])); + e.evoid = static_cast(atoi(row[217])); + e.evolvinglevel = static_cast(atoi(row[218])); + e.evomax = static_cast(atoi(row[219])); + e.clickname = row[220] ? row[220] : ""; + e.procname = row[221] ? row[221] : ""; + e.wornname = row[222] ? row[222] : ""; + e.focusname = row[223] ? row[223] : ""; + e.scrollname = row[224] ? row[224] : ""; + e.dsmitigation = static_cast(atoi(row[225])); + e.heroic_str = static_cast(atoi(row[226])); + e.heroic_int = static_cast(atoi(row[227])); + e.heroic_wis = static_cast(atoi(row[228])); + e.heroic_agi = static_cast(atoi(row[229])); + e.heroic_dex = static_cast(atoi(row[230])); + e.heroic_sta = static_cast(atoi(row[231])); + e.heroic_cha = static_cast(atoi(row[232])); + e.heroic_pr = static_cast(atoi(row[233])); + e.heroic_dr = static_cast(atoi(row[234])); + e.heroic_fr = static_cast(atoi(row[235])); + e.heroic_cr = static_cast(atoi(row[236])); + e.heroic_mr = static_cast(atoi(row[237])); + e.heroic_svcorrup = static_cast(atoi(row[238])); + e.healamt = static_cast(atoi(row[239])); + e.spelldmg = static_cast(atoi(row[240])); + e.clairvoyance = static_cast(atoi(row[241])); + e.backstabdmg = static_cast(atoi(row[242])); + e.created = row[243] ? row[243] : ""; + e.elitematerial = static_cast(atoi(row[244])); + e.ldonsellbackrate = static_cast(atoi(row[245])); + e.scriptfileid = static_cast(atoi(row[246])); + e.expendablearrow = static_cast(atoi(row[247])); + e.powersourcecapacity = static_cast(atoi(row[248])); + e.bardeffect = static_cast(atoi(row[249])); + e.bardeffecttype = static_cast(atoi(row[250])); + e.bardlevel2 = static_cast(atoi(row[251])); + e.bardlevel = static_cast(atoi(row[252])); + e.bardunk1 = static_cast(atoi(row[253])); + e.bardunk2 = static_cast(atoi(row[254])); + e.bardunk3 = static_cast(atoi(row[255])); + e.bardunk4 = static_cast(atoi(row[256])); + e.bardunk5 = static_cast(atoi(row[257])); + e.bardname = row[258] ? row[258] : ""; + e.bardunk7 = static_cast(atoi(row[259])); + e.UNK214 = static_cast(atoi(row[260])); + e.subtype = static_cast(atoi(row[261])); + e.UNK220 = static_cast(atoi(row[262])); + e.UNK221 = static_cast(atoi(row[263])); + e.heirloom = static_cast(atoi(row[264])); + e.UNK223 = static_cast(atoi(row[265])); + e.UNK224 = static_cast(atoi(row[266])); + e.UNK225 = static_cast(atoi(row[267])); + e.UNK226 = static_cast(atoi(row[268])); + e.UNK227 = static_cast(atoi(row[269])); + e.UNK228 = static_cast(atoi(row[270])); + e.UNK229 = static_cast(atoi(row[271])); + e.UNK230 = static_cast(atoi(row[272])); + e.UNK231 = static_cast(atoi(row[273])); + e.UNK232 = static_cast(atoi(row[274])); + e.UNK233 = static_cast(atoi(row[275])); + e.UNK234 = static_cast(atoi(row[276])); + e.placeable = static_cast(atoi(row[277])); + e.UNK236 = static_cast(atoi(row[278])); + e.UNK237 = static_cast(atoi(row[279])); + e.UNK238 = static_cast(atoi(row[280])); + e.UNK239 = static_cast(atoi(row[281])); + e.UNK240 = static_cast(atoi(row[282])); + e.UNK241 = static_cast(atoi(row[283])); + e.epicitem = static_cast(atoi(row[284])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -2813,301 +2813,301 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Items entry{}; + Items e{}; - entry.id = atoi(row[0]); - entry.minstatus = atoi(row[1]); - entry.Name = row[2] ? row[2] : ""; - entry.aagi = atoi(row[3]); - entry.ac = atoi(row[4]); - entry.accuracy = atoi(row[5]); - entry.acha = atoi(row[6]); - entry.adex = atoi(row[7]); - entry.aint = atoi(row[8]); - entry.artifactflag = atoi(row[9]); - entry.asta = atoi(row[10]); - entry.astr = atoi(row[11]); - entry.attack = atoi(row[12]); - entry.augrestrict = atoi(row[13]); - entry.augslot1type = atoi(row[14]); - entry.augslot1visible = atoi(row[15]); - entry.augslot2type = atoi(row[16]); - entry.augslot2visible = atoi(row[17]); - entry.augslot3type = atoi(row[18]); - entry.augslot3visible = atoi(row[19]); - entry.augslot4type = atoi(row[20]); - entry.augslot4visible = atoi(row[21]); - entry.augslot5type = atoi(row[22]); - entry.augslot5visible = atoi(row[23]); - entry.augslot6type = atoi(row[24]); - entry.augslot6visible = atoi(row[25]); - entry.augtype = atoi(row[26]); - entry.avoidance = atoi(row[27]); - entry.awis = atoi(row[28]); - entry.bagsize = atoi(row[29]); - entry.bagslots = atoi(row[30]); - entry.bagtype = atoi(row[31]); - entry.bagwr = atoi(row[32]); - entry.banedmgamt = atoi(row[33]); - entry.banedmgraceamt = atoi(row[34]); - entry.banedmgbody = atoi(row[35]); - entry.banedmgrace = atoi(row[36]); - entry.bardtype = atoi(row[37]); - entry.bardvalue = atoi(row[38]); - entry.book = atoi(row[39]); - entry.casttime = atoi(row[40]); - entry.casttime_ = atoi(row[41]); - entry.charmfile = row[42] ? row[42] : ""; - entry.charmfileid = row[43] ? row[43] : ""; - entry.classes = atoi(row[44]); - entry.color = atoi(row[45]); - entry.combateffects = row[46] ? row[46] : ""; - entry.extradmgskill = atoi(row[47]); - entry.extradmgamt = atoi(row[48]); - entry.price = atoi(row[49]); - entry.cr = atoi(row[50]); - entry.damage = atoi(row[51]); - entry.damageshield = atoi(row[52]); - entry.deity = atoi(row[53]); - entry.delay = atoi(row[54]); - entry.augdistiller = atoi(row[55]); - entry.dotshielding = atoi(row[56]); - entry.dr = atoi(row[57]); - entry.clicktype = atoi(row[58]); - entry.clicklevel2 = atoi(row[59]); - entry.elemdmgtype = atoi(row[60]); - entry.elemdmgamt = atoi(row[61]); - entry.endur = atoi(row[62]); - entry.factionamt1 = atoi(row[63]); - entry.factionamt2 = atoi(row[64]); - entry.factionamt3 = atoi(row[65]); - entry.factionamt4 = atoi(row[66]); - entry.factionmod1 = atoi(row[67]); - entry.factionmod2 = atoi(row[68]); - entry.factionmod3 = atoi(row[69]); - entry.factionmod4 = atoi(row[70]); - entry.filename = row[71] ? row[71] : ""; - entry.focuseffect = atoi(row[72]); - entry.fr = atoi(row[73]); - entry.fvnodrop = atoi(row[74]); - entry.haste = atoi(row[75]); - entry.clicklevel = atoi(row[76]); - entry.hp = atoi(row[77]); - entry.regen = atoi(row[78]); - entry.icon = atoi(row[79]); - entry.idfile = row[80] ? row[80] : ""; - entry.itemclass = atoi(row[81]); - entry.itemtype = atoi(row[82]); - entry.ldonprice = atoi(row[83]); - entry.ldontheme = atoi(row[84]); - entry.ldonsold = atoi(row[85]); - entry.light = atoi(row[86]); - entry.lore = row[87] ? row[87] : ""; - entry.loregroup = atoi(row[88]); - entry.magic = atoi(row[89]); - entry.mana = atoi(row[90]); - entry.manaregen = atoi(row[91]); - entry.enduranceregen = atoi(row[92]); - entry.material = atoi(row[93]); - entry.herosforgemodel = atoi(row[94]); - entry.maxcharges = atoi(row[95]); - entry.mr = atoi(row[96]); - entry.nodrop = atoi(row[97]); - entry.norent = atoi(row[98]); - entry.pendingloreflag = atoi(row[99]); - entry.pr = atoi(row[100]); - entry.procrate = atoi(row[101]); - entry.races = atoi(row[102]); - entry.range = atoi(row[103]); - entry.reclevel = atoi(row[104]); - entry.recskill = atoi(row[105]); - entry.reqlevel = atoi(row[106]); - entry.sellrate = static_cast(atof(row[107])); - entry.shielding = atoi(row[108]); - entry.size = atoi(row[109]); - entry.skillmodtype = atoi(row[110]); - entry.skillmodvalue = atoi(row[111]); - entry.slots = atoi(row[112]); - entry.clickeffect = atoi(row[113]); - entry.spellshield = atoi(row[114]); - entry.strikethrough = atoi(row[115]); - entry.stunresist = atoi(row[116]); - entry.summonedflag = atoi(row[117]); - entry.tradeskills = atoi(row[118]); - entry.favor = atoi(row[119]); - entry.weight = atoi(row[120]); - entry.UNK012 = atoi(row[121]); - entry.UNK013 = atoi(row[122]); - entry.benefitflag = atoi(row[123]); - entry.UNK054 = atoi(row[124]); - entry.UNK059 = atoi(row[125]); - entry.booktype = atoi(row[126]); - entry.recastdelay = atoi(row[127]); - entry.recasttype = atoi(row[128]); - entry.guildfavor = atoi(row[129]); - entry.UNK123 = atoi(row[130]); - entry.UNK124 = atoi(row[131]); - entry.attuneable = atoi(row[132]); - entry.nopet = atoi(row[133]); - entry.updated = strtoll(row[134] ? row[134] : "-1", nullptr, 10); - entry.comment = row[135] ? row[135] : ""; - entry.UNK127 = atoi(row[136]); - entry.pointtype = atoi(row[137]); - entry.potionbelt = atoi(row[138]); - entry.potionbeltslots = atoi(row[139]); - entry.stacksize = atoi(row[140]); - entry.notransfer = atoi(row[141]); - entry.stackable = atoi(row[142]); - entry.UNK134 = row[143] ? row[143] : ""; - entry.UNK137 = atoi(row[144]); - entry.proceffect = atoi(row[145]); - entry.proctype = atoi(row[146]); - entry.proclevel2 = atoi(row[147]); - entry.proclevel = atoi(row[148]); - entry.UNK142 = atoi(row[149]); - entry.worneffect = atoi(row[150]); - entry.worntype = atoi(row[151]); - entry.wornlevel2 = atoi(row[152]); - entry.wornlevel = atoi(row[153]); - entry.UNK147 = atoi(row[154]); - entry.focustype = atoi(row[155]); - entry.focuslevel2 = atoi(row[156]); - entry.focuslevel = atoi(row[157]); - entry.UNK152 = atoi(row[158]); - entry.scrolleffect = atoi(row[159]); - entry.scrolltype = atoi(row[160]); - entry.scrolllevel2 = atoi(row[161]); - entry.scrolllevel = atoi(row[162]); - entry.UNK157 = atoi(row[163]); - entry.serialized = strtoll(row[164] ? row[164] : "-1", nullptr, 10); - entry.verified = strtoll(row[165] ? row[165] : "-1", nullptr, 10); - entry.serialization = row[166] ? row[166] : ""; - entry.source = row[167] ? row[167] : ""; - entry.UNK033 = atoi(row[168]); - entry.lorefile = row[169] ? row[169] : ""; - entry.UNK014 = atoi(row[170]); - entry.svcorruption = atoi(row[171]); - entry.skillmodmax = atoi(row[172]); - entry.UNK060 = atoi(row[173]); - entry.augslot1unk2 = atoi(row[174]); - entry.augslot2unk2 = atoi(row[175]); - entry.augslot3unk2 = atoi(row[176]); - entry.augslot4unk2 = atoi(row[177]); - entry.augslot5unk2 = atoi(row[178]); - entry.augslot6unk2 = atoi(row[179]); - entry.UNK120 = atoi(row[180]); - entry.UNK121 = atoi(row[181]); - entry.questitemflag = atoi(row[182]); - entry.UNK132 = row[183] ? row[183] : ""; - entry.clickunk5 = atoi(row[184]); - entry.clickunk6 = row[185] ? row[185] : ""; - entry.clickunk7 = atoi(row[186]); - entry.procunk1 = atoi(row[187]); - entry.procunk2 = atoi(row[188]); - entry.procunk3 = atoi(row[189]); - entry.procunk4 = atoi(row[190]); - entry.procunk6 = row[191] ? row[191] : ""; - entry.procunk7 = atoi(row[192]); - entry.wornunk1 = atoi(row[193]); - entry.wornunk2 = atoi(row[194]); - entry.wornunk3 = atoi(row[195]); - entry.wornunk4 = atoi(row[196]); - entry.wornunk5 = atoi(row[197]); - entry.wornunk6 = row[198] ? row[198] : ""; - entry.wornunk7 = atoi(row[199]); - entry.focusunk1 = atoi(row[200]); - entry.focusunk2 = atoi(row[201]); - entry.focusunk3 = atoi(row[202]); - entry.focusunk4 = atoi(row[203]); - entry.focusunk5 = atoi(row[204]); - entry.focusunk6 = row[205] ? row[205] : ""; - entry.focusunk7 = atoi(row[206]); - entry.scrollunk1 = atoi(row[207]); - entry.scrollunk2 = atoi(row[208]); - entry.scrollunk3 = atoi(row[209]); - entry.scrollunk4 = atoi(row[210]); - entry.scrollunk5 = atoi(row[211]); - entry.scrollunk6 = row[212] ? row[212] : ""; - entry.scrollunk7 = atoi(row[213]); - entry.UNK193 = atoi(row[214]); - entry.purity = atoi(row[215]); - entry.evoitem = atoi(row[216]); - entry.evoid = atoi(row[217]); - entry.evolvinglevel = atoi(row[218]); - entry.evomax = atoi(row[219]); - entry.clickname = row[220] ? row[220] : ""; - entry.procname = row[221] ? row[221] : ""; - entry.wornname = row[222] ? row[222] : ""; - entry.focusname = row[223] ? row[223] : ""; - entry.scrollname = row[224] ? row[224] : ""; - entry.dsmitigation = atoi(row[225]); - entry.heroic_str = atoi(row[226]); - entry.heroic_int = atoi(row[227]); - entry.heroic_wis = atoi(row[228]); - entry.heroic_agi = atoi(row[229]); - entry.heroic_dex = atoi(row[230]); - entry.heroic_sta = atoi(row[231]); - entry.heroic_cha = atoi(row[232]); - entry.heroic_pr = atoi(row[233]); - entry.heroic_dr = atoi(row[234]); - entry.heroic_fr = atoi(row[235]); - entry.heroic_cr = atoi(row[236]); - entry.heroic_mr = atoi(row[237]); - entry.heroic_svcorrup = atoi(row[238]); - entry.healamt = atoi(row[239]); - entry.spelldmg = atoi(row[240]); - entry.clairvoyance = atoi(row[241]); - entry.backstabdmg = atoi(row[242]); - entry.created = row[243] ? row[243] : ""; - entry.elitematerial = atoi(row[244]); - entry.ldonsellbackrate = atoi(row[245]); - entry.scriptfileid = atoi(row[246]); - entry.expendablearrow = atoi(row[247]); - entry.powersourcecapacity = atoi(row[248]); - entry.bardeffect = atoi(row[249]); - entry.bardeffecttype = atoi(row[250]); - entry.bardlevel2 = atoi(row[251]); - entry.bardlevel = atoi(row[252]); - entry.bardunk1 = atoi(row[253]); - entry.bardunk2 = atoi(row[254]); - entry.bardunk3 = atoi(row[255]); - entry.bardunk4 = atoi(row[256]); - entry.bardunk5 = atoi(row[257]); - entry.bardname = row[258] ? row[258] : ""; - entry.bardunk7 = atoi(row[259]); - entry.UNK214 = atoi(row[260]); - entry.subtype = atoi(row[261]); - entry.UNK220 = atoi(row[262]); - entry.UNK221 = atoi(row[263]); - entry.heirloom = atoi(row[264]); - entry.UNK223 = atoi(row[265]); - entry.UNK224 = atoi(row[266]); - entry.UNK225 = atoi(row[267]); - entry.UNK226 = atoi(row[268]); - entry.UNK227 = atoi(row[269]); - entry.UNK228 = atoi(row[270]); - entry.UNK229 = atoi(row[271]); - entry.UNK230 = atoi(row[272]); - entry.UNK231 = atoi(row[273]); - entry.UNK232 = atoi(row[274]); - entry.UNK233 = atoi(row[275]); - entry.UNK234 = atoi(row[276]); - entry.placeable = atoi(row[277]); - entry.UNK236 = atoi(row[278]); - entry.UNK237 = atoi(row[279]); - entry.UNK238 = atoi(row[280]); - entry.UNK239 = atoi(row[281]); - entry.UNK240 = atoi(row[282]); - entry.UNK241 = atoi(row[283]); - entry.epicitem = atoi(row[284]); + e.id = static_cast(atoi(row[0])); + e.minstatus = static_cast(atoi(row[1])); + e.Name = row[2] ? row[2] : ""; + e.aagi = static_cast(atoi(row[3])); + e.ac = static_cast(atoi(row[4])); + e.accuracy = static_cast(atoi(row[5])); + e.acha = static_cast(atoi(row[6])); + e.adex = static_cast(atoi(row[7])); + e.aint = static_cast(atoi(row[8])); + e.artifactflag = static_cast(strtoul(row[9], nullptr, 10)); + e.asta = static_cast(atoi(row[10])); + e.astr = static_cast(atoi(row[11])); + e.attack = static_cast(atoi(row[12])); + e.augrestrict = static_cast(atoi(row[13])); + e.augslot1type = static_cast(atoi(row[14])); + e.augslot1visible = static_cast(atoi(row[15])); + e.augslot2type = static_cast(atoi(row[16])); + e.augslot2visible = static_cast(atoi(row[17])); + e.augslot3type = static_cast(atoi(row[18])); + e.augslot3visible = static_cast(atoi(row[19])); + e.augslot4type = static_cast(atoi(row[20])); + e.augslot4visible = static_cast(atoi(row[21])); + e.augslot5type = static_cast(atoi(row[22])); + e.augslot5visible = static_cast(atoi(row[23])); + e.augslot6type = static_cast(atoi(row[24])); + e.augslot6visible = static_cast(atoi(row[25])); + e.augtype = static_cast(atoi(row[26])); + e.avoidance = static_cast(atoi(row[27])); + e.awis = static_cast(atoi(row[28])); + e.bagsize = static_cast(atoi(row[29])); + e.bagslots = static_cast(atoi(row[30])); + e.bagtype = static_cast(atoi(row[31])); + e.bagwr = static_cast(atoi(row[32])); + e.banedmgamt = static_cast(atoi(row[33])); + e.banedmgraceamt = static_cast(atoi(row[34])); + e.banedmgbody = static_cast(atoi(row[35])); + e.banedmgrace = static_cast(atoi(row[36])); + e.bardtype = static_cast(atoi(row[37])); + e.bardvalue = static_cast(atoi(row[38])); + e.book = static_cast(atoi(row[39])); + e.casttime = static_cast(atoi(row[40])); + e.casttime_ = static_cast(atoi(row[41])); + e.charmfile = row[42] ? row[42] : ""; + e.charmfileid = row[43] ? row[43] : ""; + e.classes = static_cast(atoi(row[44])); + e.color = static_cast(strtoul(row[45], nullptr, 10)); + e.combateffects = row[46] ? row[46] : ""; + e.extradmgskill = static_cast(atoi(row[47])); + e.extradmgamt = static_cast(atoi(row[48])); + e.price = static_cast(atoi(row[49])); + e.cr = static_cast(atoi(row[50])); + e.damage = static_cast(atoi(row[51])); + e.damageshield = static_cast(atoi(row[52])); + e.deity = static_cast(atoi(row[53])); + e.delay = static_cast(atoi(row[54])); + e.augdistiller = static_cast(atoi(row[55])); + e.dotshielding = static_cast(atoi(row[56])); + e.dr = static_cast(atoi(row[57])); + e.clicktype = static_cast(atoi(row[58])); + e.clicklevel2 = static_cast(atoi(row[59])); + e.elemdmgtype = static_cast(atoi(row[60])); + e.elemdmgamt = static_cast(atoi(row[61])); + e.endur = static_cast(atoi(row[62])); + e.factionamt1 = static_cast(atoi(row[63])); + e.factionamt2 = static_cast(atoi(row[64])); + e.factionamt3 = static_cast(atoi(row[65])); + e.factionamt4 = static_cast(atoi(row[66])); + e.factionmod1 = static_cast(atoi(row[67])); + e.factionmod2 = static_cast(atoi(row[68])); + e.factionmod3 = static_cast(atoi(row[69])); + e.factionmod4 = static_cast(atoi(row[70])); + e.filename = row[71] ? row[71] : ""; + e.focuseffect = static_cast(atoi(row[72])); + e.fr = static_cast(atoi(row[73])); + e.fvnodrop = static_cast(atoi(row[74])); + e.haste = static_cast(atoi(row[75])); + e.clicklevel = static_cast(atoi(row[76])); + e.hp = static_cast(atoi(row[77])); + e.regen = static_cast(atoi(row[78])); + e.icon = static_cast(atoi(row[79])); + e.idfile = row[80] ? row[80] : ""; + e.itemclass = static_cast(atoi(row[81])); + e.itemtype = static_cast(atoi(row[82])); + e.ldonprice = static_cast(atoi(row[83])); + e.ldontheme = static_cast(atoi(row[84])); + e.ldonsold = static_cast(atoi(row[85])); + e.light = static_cast(atoi(row[86])); + e.lore = row[87] ? row[87] : ""; + e.loregroup = static_cast(atoi(row[88])); + e.magic = static_cast(atoi(row[89])); + e.mana = static_cast(atoi(row[90])); + e.manaregen = static_cast(atoi(row[91])); + e.enduranceregen = static_cast(atoi(row[92])); + e.material = static_cast(atoi(row[93])); + e.herosforgemodel = static_cast(atoi(row[94])); + e.maxcharges = static_cast(atoi(row[95])); + e.mr = static_cast(atoi(row[96])); + e.nodrop = static_cast(atoi(row[97])); + e.norent = static_cast(atoi(row[98])); + e.pendingloreflag = static_cast(strtoul(row[99], nullptr, 10)); + e.pr = static_cast(atoi(row[100])); + e.procrate = static_cast(atoi(row[101])); + e.races = static_cast(atoi(row[102])); + e.range = static_cast(atoi(row[103])); + e.reclevel = static_cast(atoi(row[104])); + e.recskill = static_cast(atoi(row[105])); + e.reqlevel = static_cast(atoi(row[106])); + e.sellrate = strtof(row[107], nullptr); + e.shielding = static_cast(atoi(row[108])); + e.size = static_cast(atoi(row[109])); + e.skillmodtype = static_cast(atoi(row[110])); + e.skillmodvalue = static_cast(atoi(row[111])); + e.slots = static_cast(atoi(row[112])); + e.clickeffect = static_cast(atoi(row[113])); + e.spellshield = static_cast(atoi(row[114])); + e.strikethrough = static_cast(atoi(row[115])); + e.stunresist = static_cast(atoi(row[116])); + e.summonedflag = static_cast(strtoul(row[117], nullptr, 10)); + e.tradeskills = static_cast(atoi(row[118])); + e.favor = static_cast(atoi(row[119])); + e.weight = static_cast(atoi(row[120])); + e.UNK012 = static_cast(atoi(row[121])); + e.UNK013 = static_cast(atoi(row[122])); + e.benefitflag = static_cast(atoi(row[123])); + e.UNK054 = static_cast(atoi(row[124])); + e.UNK059 = static_cast(atoi(row[125])); + e.booktype = static_cast(atoi(row[126])); + e.recastdelay = static_cast(atoi(row[127])); + e.recasttype = static_cast(atoi(row[128])); + e.guildfavor = static_cast(atoi(row[129])); + e.UNK123 = static_cast(atoi(row[130])); + e.UNK124 = static_cast(atoi(row[131])); + e.attuneable = static_cast(atoi(row[132])); + e.nopet = static_cast(atoi(row[133])); + e.updated = strtoll(row[134] ? row[134] : "-1", nullptr, 10); + e.comment = row[135] ? row[135] : ""; + e.UNK127 = static_cast(atoi(row[136])); + e.pointtype = static_cast(atoi(row[137])); + e.potionbelt = static_cast(atoi(row[138])); + e.potionbeltslots = static_cast(atoi(row[139])); + e.stacksize = static_cast(atoi(row[140])); + e.notransfer = static_cast(atoi(row[141])); + e.stackable = static_cast(atoi(row[142])); + e.UNK134 = row[143] ? row[143] : ""; + e.UNK137 = static_cast(atoi(row[144])); + e.proceffect = static_cast(atoi(row[145])); + e.proctype = static_cast(atoi(row[146])); + e.proclevel2 = static_cast(atoi(row[147])); + e.proclevel = static_cast(atoi(row[148])); + e.UNK142 = static_cast(atoi(row[149])); + e.worneffect = static_cast(atoi(row[150])); + e.worntype = static_cast(atoi(row[151])); + e.wornlevel2 = static_cast(atoi(row[152])); + e.wornlevel = static_cast(atoi(row[153])); + e.UNK147 = static_cast(atoi(row[154])); + e.focustype = static_cast(atoi(row[155])); + e.focuslevel2 = static_cast(atoi(row[156])); + e.focuslevel = static_cast(atoi(row[157])); + e.UNK152 = static_cast(atoi(row[158])); + e.scrolleffect = static_cast(atoi(row[159])); + e.scrolltype = static_cast(atoi(row[160])); + e.scrolllevel2 = static_cast(atoi(row[161])); + e.scrolllevel = static_cast(atoi(row[162])); + e.UNK157 = static_cast(atoi(row[163])); + e.serialized = strtoll(row[164] ? row[164] : "-1", nullptr, 10); + e.verified = strtoll(row[165] ? row[165] : "-1", nullptr, 10); + e.serialization = row[166] ? row[166] : ""; + e.source = row[167] ? row[167] : ""; + e.UNK033 = static_cast(atoi(row[168])); + e.lorefile = row[169] ? row[169] : ""; + e.UNK014 = static_cast(atoi(row[170])); + e.svcorruption = static_cast(atoi(row[171])); + e.skillmodmax = static_cast(atoi(row[172])); + e.UNK060 = static_cast(atoi(row[173])); + e.augslot1unk2 = static_cast(atoi(row[174])); + e.augslot2unk2 = static_cast(atoi(row[175])); + e.augslot3unk2 = static_cast(atoi(row[176])); + e.augslot4unk2 = static_cast(atoi(row[177])); + e.augslot5unk2 = static_cast(atoi(row[178])); + e.augslot6unk2 = static_cast(atoi(row[179])); + e.UNK120 = static_cast(atoi(row[180])); + e.UNK121 = static_cast(atoi(row[181])); + e.questitemflag = static_cast(atoi(row[182])); + e.UNK132 = row[183] ? row[183] : ""; + e.clickunk5 = static_cast(atoi(row[184])); + e.clickunk6 = row[185] ? row[185] : ""; + e.clickunk7 = static_cast(atoi(row[186])); + e.procunk1 = static_cast(atoi(row[187])); + e.procunk2 = static_cast(atoi(row[188])); + e.procunk3 = static_cast(atoi(row[189])); + e.procunk4 = static_cast(atoi(row[190])); + e.procunk6 = row[191] ? row[191] : ""; + e.procunk7 = static_cast(atoi(row[192])); + e.wornunk1 = static_cast(atoi(row[193])); + e.wornunk2 = static_cast(atoi(row[194])); + e.wornunk3 = static_cast(atoi(row[195])); + e.wornunk4 = static_cast(atoi(row[196])); + e.wornunk5 = static_cast(atoi(row[197])); + e.wornunk6 = row[198] ? row[198] : ""; + e.wornunk7 = static_cast(atoi(row[199])); + e.focusunk1 = static_cast(atoi(row[200])); + e.focusunk2 = static_cast(atoi(row[201])); + e.focusunk3 = static_cast(atoi(row[202])); + e.focusunk4 = static_cast(atoi(row[203])); + e.focusunk5 = static_cast(atoi(row[204])); + e.focusunk6 = row[205] ? row[205] : ""; + e.focusunk7 = static_cast(atoi(row[206])); + e.scrollunk1 = static_cast(atoi(row[207])); + e.scrollunk2 = static_cast(atoi(row[208])); + e.scrollunk3 = static_cast(atoi(row[209])); + e.scrollunk4 = static_cast(atoi(row[210])); + e.scrollunk5 = static_cast(atoi(row[211])); + e.scrollunk6 = row[212] ? row[212] : ""; + e.scrollunk7 = static_cast(atoi(row[213])); + e.UNK193 = static_cast(atoi(row[214])); + e.purity = static_cast(atoi(row[215])); + e.evoitem = static_cast(atoi(row[216])); + e.evoid = static_cast(atoi(row[217])); + e.evolvinglevel = static_cast(atoi(row[218])); + e.evomax = static_cast(atoi(row[219])); + e.clickname = row[220] ? row[220] : ""; + e.procname = row[221] ? row[221] : ""; + e.wornname = row[222] ? row[222] : ""; + e.focusname = row[223] ? row[223] : ""; + e.scrollname = row[224] ? row[224] : ""; + e.dsmitigation = static_cast(atoi(row[225])); + e.heroic_str = static_cast(atoi(row[226])); + e.heroic_int = static_cast(atoi(row[227])); + e.heroic_wis = static_cast(atoi(row[228])); + e.heroic_agi = static_cast(atoi(row[229])); + e.heroic_dex = static_cast(atoi(row[230])); + e.heroic_sta = static_cast(atoi(row[231])); + e.heroic_cha = static_cast(atoi(row[232])); + e.heroic_pr = static_cast(atoi(row[233])); + e.heroic_dr = static_cast(atoi(row[234])); + e.heroic_fr = static_cast(atoi(row[235])); + e.heroic_cr = static_cast(atoi(row[236])); + e.heroic_mr = static_cast(atoi(row[237])); + e.heroic_svcorrup = static_cast(atoi(row[238])); + e.healamt = static_cast(atoi(row[239])); + e.spelldmg = static_cast(atoi(row[240])); + e.clairvoyance = static_cast(atoi(row[241])); + e.backstabdmg = static_cast(atoi(row[242])); + e.created = row[243] ? row[243] : ""; + e.elitematerial = static_cast(atoi(row[244])); + e.ldonsellbackrate = static_cast(atoi(row[245])); + e.scriptfileid = static_cast(atoi(row[246])); + e.expendablearrow = static_cast(atoi(row[247])); + e.powersourcecapacity = static_cast(atoi(row[248])); + e.bardeffect = static_cast(atoi(row[249])); + e.bardeffecttype = static_cast(atoi(row[250])); + e.bardlevel2 = static_cast(atoi(row[251])); + e.bardlevel = static_cast(atoi(row[252])); + e.bardunk1 = static_cast(atoi(row[253])); + e.bardunk2 = static_cast(atoi(row[254])); + e.bardunk3 = static_cast(atoi(row[255])); + e.bardunk4 = static_cast(atoi(row[256])); + e.bardunk5 = static_cast(atoi(row[257])); + e.bardname = row[258] ? row[258] : ""; + e.bardunk7 = static_cast(atoi(row[259])); + e.UNK214 = static_cast(atoi(row[260])); + e.subtype = static_cast(atoi(row[261])); + e.UNK220 = static_cast(atoi(row[262])); + e.UNK221 = static_cast(atoi(row[263])); + e.heirloom = static_cast(atoi(row[264])); + e.UNK223 = static_cast(atoi(row[265])); + e.UNK224 = static_cast(atoi(row[266])); + e.UNK225 = static_cast(atoi(row[267])); + e.UNK226 = static_cast(atoi(row[268])); + e.UNK227 = static_cast(atoi(row[269])); + e.UNK228 = static_cast(atoi(row[270])); + e.UNK229 = static_cast(atoi(row[271])); + e.UNK230 = static_cast(atoi(row[272])); + e.UNK231 = static_cast(atoi(row[273])); + e.UNK232 = static_cast(atoi(row[274])); + e.UNK233 = static_cast(atoi(row[275])); + e.UNK234 = static_cast(atoi(row[276])); + e.placeable = static_cast(atoi(row[277])); + e.UNK236 = static_cast(atoi(row[278])); + e.UNK237 = static_cast(atoi(row[279])); + e.UNK238 = static_cast(atoi(row[280])); + e.UNK239 = static_cast(atoi(row[281])); + e.UNK240 = static_cast(atoi(row[282])); + e.UNK241 = static_cast(atoi(row[283])); + e.epicitem = static_cast(atoi(row[284])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -3132,6 +3132,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_launcher_repository.h b/common/repositories/base/base_launcher_repository.h index 047f027ce..15317105e 100644 --- a/common/repositories/base/base_launcher_repository.h +++ b/common/repositories/base/base_launcher_repository.h @@ -1,24 +1,3 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - */ - /** * This repository was automatically generated and is NOT to be modified directly. * Any repository modifications are meant to be made to @@ -30,7 +9,7 @@ #define EQEMU_BASE_LAUNCHER_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" class BaseLauncherRepository { public: @@ -54,7 +33,7 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string InsertColumnsRaw() @@ -69,7 +48,7 @@ public: insert_columns.push_back(column); } - return std::string(implode(", ", insert_columns)); + return std::string(Strings::Implode(", ", insert_columns)); } static std::string TableName() @@ -168,14 +147,14 @@ public: auto columns = Columns(); - update_values.push_back(columns[0] + " = '" + EscapeString(launcher_entry.name) + "'"); + update_values.push_back(columns[0] + " = '" + Strings::Escape(launcher_entry.name) + "'"); update_values.push_back(columns[1] + " = " + std::to_string(launcher_entry.dynamics)); auto results = database.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), launcher_entry.name ) @@ -190,14 +169,14 @@ public: { std::vector insert_values; - insert_values.push_back("'" + EscapeString(launcher_entry.name) + "'"); + insert_values.push_back("'" + Strings::Escape(launcher_entry.name) + "'"); insert_values.push_back(std::to_string(launcher_entry.dynamics)); auto results = database.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -220,10 +199,10 @@ public: for (auto &launcher_entry: launcher_entries) { std::vector insert_values; - insert_values.push_back("'" + EscapeString(launcher_entry.name) + "'"); + insert_values.push_back("'" + Strings::Escape(launcher_entry.name) + "'"); insert_values.push_back(std::to_string(launcher_entry.dynamics)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -232,7 +211,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/base/base_ldon_trap_entries_repository.h b/common/repositories/base/base_ldon_trap_entries_repository.h index ea1dd3c43..d47f815be 100644 --- a/common/repositories/base/base_ldon_trap_entries_repository.h +++ b/common/repositories/base/base_ldon_trap_entries_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_LDON_TRAP_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLdonTrapEntriesRepository { public: struct LdonTrapEntries { - int id; - int trap_id; + uint32_t id; + uint32_t trap_id; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static LdonTrapEntries NewEntity() { - LdonTrapEntries entry{}; + LdonTrapEntries e{}; - entry.id = 0; - entry.trap_id = 0; + e.id = 0; + e.trap_id = 0; - return entry; + return e; } - static LdonTrapEntries GetLdonTrapEntriesEntry( + static LdonTrapEntries GetLdonTrapEntries( const std::vector &ldon_trap_entriess, int ldon_trap_entries_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LdonTrapEntries entry{}; + LdonTrapEntries e{}; - entry.id = atoi(row[0]); - entry.trap_id = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.trap_id = static_cast(strtoul(row[1], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - LdonTrapEntries ldon_trap_entries_entry + const LdonTrapEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(ldon_trap_entries_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(ldon_trap_entries_entry.trap_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.trap_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - ldon_trap_entries_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static LdonTrapEntries InsertOne( Database& db, - LdonTrapEntries ldon_trap_entries_entry + LdonTrapEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(ldon_trap_entries_entry.id)); - insert_values.push_back(std::to_string(ldon_trap_entries_entry.trap_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.trap_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - ldon_trap_entries_entry.id = results.LastInsertedID(); - return ldon_trap_entries_entry; + e.id = results.LastInsertedID(); + return e; } - ldon_trap_entries_entry = NewEntity(); + e = NewEntity(); - return ldon_trap_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector ldon_trap_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &ldon_trap_entries_entry: ldon_trap_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(ldon_trap_entries_entry.id)); - insert_values.push_back(std::to_string(ldon_trap_entries_entry.trap_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.trap_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LdonTrapEntries entry{}; + LdonTrapEntries e{}; - entry.id = atoi(row[0]); - entry.trap_id = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.trap_id = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LdonTrapEntries entry{}; + LdonTrapEntries e{}; - entry.id = atoi(row[0]); - entry.trap_id = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.trap_id = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LDON_TRAP_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_ldon_trap_templates_repository.h b/common/repositories/base/base_ldon_trap_templates_repository.h index b4905a521..5a4281db6 100644 --- a/common/repositories/base/base_ldon_trap_templates_repository.h +++ b/common/repositories/base/base_ldon_trap_templates_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_LDON_TRAP_TEMPLATES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLdonTrapTemplatesRepository { public: struct LdonTrapTemplates { - int id; - int type; - int spell_id; - int skill; - int locked; + uint32_t id; + uint8_t type; + uint16_t spell_id; + uint16_t skill; + uint8_t locked; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static LdonTrapTemplates NewEntity() { - LdonTrapTemplates entry{}; + LdonTrapTemplates e{}; - entry.id = 0; - entry.type = 1; - entry.spell_id = 0; - entry.skill = 0; - entry.locked = 0; + e.id = 0; + e.type = 1; + e.spell_id = 0; + e.skill = 0; + e.locked = 0; - return entry; + return e; } - static LdonTrapTemplates GetLdonTrapTemplatesEntry( + static LdonTrapTemplates GetLdonTrapTemplates( const std::vector &ldon_trap_templatess, int ldon_trap_templates_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LdonTrapTemplates entry{}; + LdonTrapTemplates e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.spell_id = atoi(row[2]); - entry.skill = atoi(row[3]); - entry.locked = atoi(row[4]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.skill = static_cast(strtoul(row[3], nullptr, 10)); + e.locked = static_cast(strtoul(row[4], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - LdonTrapTemplates ldon_trap_templates_entry + const LdonTrapTemplates &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(ldon_trap_templates_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(ldon_trap_templates_entry.type)); - update_values.push_back(columns[2] + " = " + std::to_string(ldon_trap_templates_entry.spell_id)); - update_values.push_back(columns[3] + " = " + std::to_string(ldon_trap_templates_entry.skill)); - update_values.push_back(columns[4] + " = " + std::to_string(ldon_trap_templates_entry.locked)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.type)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[3] + " = " + std::to_string(e.skill)); + v.push_back(columns[4] + " = " + std::to_string(e.locked)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - ldon_trap_templates_entry.id + e.id ) ); @@ -189,61 +189,61 @@ public: static LdonTrapTemplates InsertOne( Database& db, - LdonTrapTemplates ldon_trap_templates_entry + LdonTrapTemplates e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(ldon_trap_templates_entry.id)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.type)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.spell_id)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.skill)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.skill)); + v.push_back(std::to_string(e.locked)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - ldon_trap_templates_entry.id = results.LastInsertedID(); - return ldon_trap_templates_entry; + e.id = results.LastInsertedID(); + return e; } - ldon_trap_templates_entry = NewEntity(); + e = NewEntity(); - return ldon_trap_templates_entry; + return e; } static int InsertMany( Database& db, - std::vector ldon_trap_templates_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &ldon_trap_templates_entry: ldon_trap_templates_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(ldon_trap_templates_entry.id)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.type)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.spell_id)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.skill)); - insert_values.push_back(std::to_string(ldon_trap_templates_entry.locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.skill)); + v.push_back(std::to_string(e.locked)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LdonTrapTemplates entry{}; + LdonTrapTemplates e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.spell_id = atoi(row[2]); - entry.skill = atoi(row[3]); - entry.locked = atoi(row[4]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.skill = static_cast(strtoul(row[3], nullptr, 10)); + e.locked = static_cast(strtoul(row[4], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LdonTrapTemplates entry{}; + LdonTrapTemplates e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.spell_id = atoi(row[2]); - entry.skill = atoi(row[3]); - entry.locked = atoi(row[4]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.skill = static_cast(strtoul(row[3], nullptr, 10)); + e.locked = static_cast(strtoul(row[4], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LDON_TRAP_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_level_exp_mods_repository.h b/common/repositories/base/base_level_exp_mods_repository.h index 3d1f57854..13dcb2cfd 100644 --- a/common/repositories/base/base_level_exp_mods_repository.h +++ b/common/repositories/base/base_level_exp_mods_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_LEVEL_EXP_MODS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLevelExpModsRepository { public: struct LevelExpMods { - int level; - float exp_mod; - float aa_exp_mod; + int32_t level; + float exp_mod; + float aa_exp_mod; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static LevelExpMods NewEntity() { - LevelExpMods entry{}; + LevelExpMods e{}; - entry.level = 0; - entry.exp_mod = 0; - entry.aa_exp_mod = 0; + e.level = 0; + e.exp_mod = 0; + e.aa_exp_mod = 0; - return entry; + return e; } - static LevelExpMods GetLevelExpModsEntry( + static LevelExpMods GetLevelExpMods( const std::vector &level_exp_modss, int level_exp_mods_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LevelExpMods entry{}; + LevelExpMods e{}; - entry.level = atoi(row[0]); - entry.exp_mod = static_cast(atof(row[1])); - entry.aa_exp_mod = static_cast(atof(row[2])); + e.level = static_cast(atoi(row[0])); + e.exp_mod = strtof(row[1], nullptr); + e.aa_exp_mod = strtof(row[2], nullptr); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - LevelExpMods level_exp_mods_entry + const LevelExpMods &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(level_exp_mods_entry.level)); - update_values.push_back(columns[1] + " = " + std::to_string(level_exp_mods_entry.exp_mod)); - update_values.push_back(columns[2] + " = " + std::to_string(level_exp_mods_entry.aa_exp_mod)); + v.push_back(columns[0] + " = " + std::to_string(e.level)); + v.push_back(columns[1] + " = " + std::to_string(e.exp_mod)); + v.push_back(columns[2] + " = " + std::to_string(e.aa_exp_mod)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - level_exp_mods_entry.level + e.level ) ); @@ -177,57 +177,57 @@ public: static LevelExpMods InsertOne( Database& db, - LevelExpMods level_exp_mods_entry + LevelExpMods e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(level_exp_mods_entry.level)); - insert_values.push_back(std::to_string(level_exp_mods_entry.exp_mod)); - insert_values.push_back(std::to_string(level_exp_mods_entry.aa_exp_mod)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.exp_mod)); + v.push_back(std::to_string(e.aa_exp_mod)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - level_exp_mods_entry.level = results.LastInsertedID(); - return level_exp_mods_entry; + e.level = results.LastInsertedID(); + return e; } - level_exp_mods_entry = NewEntity(); + e = NewEntity(); - return level_exp_mods_entry; + return e; } static int InsertMany( Database& db, - std::vector level_exp_mods_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &level_exp_mods_entry: level_exp_mods_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(level_exp_mods_entry.level)); - insert_values.push_back(std::to_string(level_exp_mods_entry.exp_mod)); - insert_values.push_back(std::to_string(level_exp_mods_entry.aa_exp_mod)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.exp_mod)); + v.push_back(std::to_string(e.aa_exp_mod)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LevelExpMods entry{}; + LevelExpMods e{}; - entry.level = atoi(row[0]); - entry.exp_mod = static_cast(atof(row[1])); - entry.aa_exp_mod = static_cast(atof(row[2])); + e.level = static_cast(atoi(row[0])); + e.exp_mod = strtof(row[1], nullptr); + e.aa_exp_mod = strtof(row[2], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LevelExpMods entry{}; + LevelExpMods e{}; - entry.level = atoi(row[0]); - entry.exp_mod = static_cast(atof(row[1])); - entry.aa_exp_mod = static_cast(atof(row[2])); + e.level = static_cast(atoi(row[0])); + e.exp_mod = strtof(row[1], nullptr); + e.aa_exp_mod = strtof(row[2], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LEVEL_EXP_MODS_REPOSITORY_H diff --git a/common/repositories/base/base_lfguild_repository.h b/common/repositories/base/base_lfguild_repository.h index 1ca4f0214..3fef33af2 100644 --- a/common/repositories/base/base_lfguild_repository.h +++ b/common/repositories/base/base_lfguild_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_LFGUILD_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLfguildRepository { public: struct Lfguild { - int type; + uint8_t type; std::string name; std::string comment; - int fromlevel; - int tolevel; - int classes; - int aacount; - int timezone; - int timeposted; + uint8_t fromlevel; + uint8_t tolevel; + uint32_t classes; + uint32_t aacount; + uint32_t timezone; + uint32_t timeposted; }; static std::string PrimaryKey() @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static Lfguild NewEntity() { - Lfguild entry{}; + Lfguild e{}; - entry.type = 0; - entry.name = ""; - entry.comment = ""; - entry.fromlevel = 0; - entry.tolevel = 0; - entry.classes = 0; - entry.aacount = 0; - entry.timezone = 0; - entry.timeposted = 0; + e.type = 0; + e.name = ""; + e.comment = ""; + e.fromlevel = 0; + e.tolevel = 0; + e.classes = 0; + e.aacount = 0; + e.timezone = 0; + e.timeposted = 0; - return entry; + return e; } - static Lfguild GetLfguildEntry( + static Lfguild GetLfguild( const std::vector &lfguilds, int lfguild_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Lfguild entry{}; + Lfguild e{}; - entry.type = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.comment = row[2] ? row[2] : ""; - entry.fromlevel = atoi(row[3]); - entry.tolevel = atoi(row[4]); - entry.classes = atoi(row[5]); - entry.aacount = atoi(row[6]); - entry.timezone = atoi(row[7]); - entry.timeposted = atoi(row[8]); + e.type = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.comment = row[2] ? row[2] : ""; + e.fromlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.tolevel = static_cast(strtoul(row[4], nullptr, 10)); + e.classes = static_cast(strtoul(row[5], nullptr, 10)); + e.aacount = static_cast(strtoul(row[6], nullptr, 10)); + e.timezone = static_cast(strtoul(row[7], nullptr, 10)); + e.timeposted = static_cast(strtoul(row[8], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -181,30 +181,30 @@ public: static int UpdateOne( Database& db, - Lfguild lfguild_entry + const Lfguild &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(lfguild_entry.type)); - update_values.push_back(columns[1] + " = '" + EscapeString(lfguild_entry.name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(lfguild_entry.comment) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(lfguild_entry.fromlevel)); - update_values.push_back(columns[4] + " = " + std::to_string(lfguild_entry.tolevel)); - update_values.push_back(columns[5] + " = " + std::to_string(lfguild_entry.classes)); - update_values.push_back(columns[6] + " = " + std::to_string(lfguild_entry.aacount)); - update_values.push_back(columns[7] + " = " + std::to_string(lfguild_entry.timezone)); - update_values.push_back(columns[8] + " = " + std::to_string(lfguild_entry.timeposted)); + v.push_back(columns[0] + " = " + std::to_string(e.type)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.comment) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.fromlevel)); + v.push_back(columns[4] + " = " + std::to_string(e.tolevel)); + v.push_back(columns[5] + " = " + std::to_string(e.classes)); + v.push_back(columns[6] + " = " + std::to_string(e.aacount)); + v.push_back(columns[7] + " = " + std::to_string(e.timezone)); + v.push_back(columns[8] + " = " + std::to_string(e.timeposted)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - lfguild_entry.type + e.type ) ); @@ -213,69 +213,69 @@ public: static Lfguild InsertOne( Database& db, - Lfguild lfguild_entry + Lfguild e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(lfguild_entry.type)); - insert_values.push_back("'" + EscapeString(lfguild_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(lfguild_entry.comment) + "'"); - insert_values.push_back(std::to_string(lfguild_entry.fromlevel)); - insert_values.push_back(std::to_string(lfguild_entry.tolevel)); - insert_values.push_back(std::to_string(lfguild_entry.classes)); - insert_values.push_back(std::to_string(lfguild_entry.aacount)); - insert_values.push_back(std::to_string(lfguild_entry.timezone)); - insert_values.push_back(std::to_string(lfguild_entry.timeposted)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.comment) + "'"); + v.push_back(std::to_string(e.fromlevel)); + v.push_back(std::to_string(e.tolevel)); + v.push_back(std::to_string(e.classes)); + v.push_back(std::to_string(e.aacount)); + v.push_back(std::to_string(e.timezone)); + v.push_back(std::to_string(e.timeposted)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - lfguild_entry.type = results.LastInsertedID(); - return lfguild_entry; + e.type = results.LastInsertedID(); + return e; } - lfguild_entry = NewEntity(); + e = NewEntity(); - return lfguild_entry; + return e; } static int InsertMany( Database& db, - std::vector lfguild_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &lfguild_entry: lfguild_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(lfguild_entry.type)); - insert_values.push_back("'" + EscapeString(lfguild_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(lfguild_entry.comment) + "'"); - insert_values.push_back(std::to_string(lfguild_entry.fromlevel)); - insert_values.push_back(std::to_string(lfguild_entry.tolevel)); - insert_values.push_back(std::to_string(lfguild_entry.classes)); - insert_values.push_back(std::to_string(lfguild_entry.aacount)); - insert_values.push_back(std::to_string(lfguild_entry.timezone)); - insert_values.push_back(std::to_string(lfguild_entry.timeposted)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.comment) + "'"); + v.push_back(std::to_string(e.fromlevel)); + v.push_back(std::to_string(e.tolevel)); + v.push_back(std::to_string(e.classes)); + v.push_back(std::to_string(e.aacount)); + v.push_back(std::to_string(e.timezone)); + v.push_back(std::to_string(e.timeposted)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -296,25 +296,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Lfguild entry{}; + Lfguild e{}; - entry.type = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.comment = row[2] ? row[2] : ""; - entry.fromlevel = atoi(row[3]); - entry.tolevel = atoi(row[4]); - entry.classes = atoi(row[5]); - entry.aacount = atoi(row[6]); - entry.timezone = atoi(row[7]); - entry.timeposted = atoi(row[8]); + e.type = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.comment = row[2] ? row[2] : ""; + e.fromlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.tolevel = static_cast(strtoul(row[4], nullptr, 10)); + e.classes = static_cast(strtoul(row[5], nullptr, 10)); + e.aacount = static_cast(strtoul(row[6], nullptr, 10)); + e.timezone = static_cast(strtoul(row[7], nullptr, 10)); + e.timeposted = static_cast(strtoul(row[8], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -329,25 +329,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Lfguild entry{}; + Lfguild e{}; - entry.type = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.comment = row[2] ? row[2] : ""; - entry.fromlevel = atoi(row[3]); - entry.tolevel = atoi(row[4]); - entry.classes = atoi(row[5]); - entry.aacount = atoi(row[6]); - entry.timezone = atoi(row[7]); - entry.timeposted = atoi(row[8]); + e.type = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.comment = row[2] ? row[2] : ""; + e.fromlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.tolevel = static_cast(strtoul(row[4], nullptr, 10)); + e.classes = static_cast(strtoul(row[5], nullptr, 10)); + e.aacount = static_cast(strtoul(row[6], nullptr, 10)); + e.timezone = static_cast(strtoul(row[7], nullptr, 10)); + e.timeposted = static_cast(strtoul(row[8], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -372,6 +372,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LFGUILD_REPOSITORY_H diff --git a/common/repositories/base/base_login_accounts_repository.h b/common/repositories/base/base_login_accounts_repository.h index b8c82d6be..4ac86f8d1 100644 --- a/common/repositories/base/base_login_accounts_repository.h +++ b/common/repositories/base/base_login_accounts_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_LOGIN_ACCOUNTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLoginAccountsRepository { public: struct LoginAccounts { - int id; + uint32_t id; std::string account_name; std::string account_password; std::string account_email; @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static LoginAccounts NewEntity() { - LoginAccounts entry{}; + LoginAccounts e{}; - entry.id = 0; - entry.account_name = ""; - entry.account_password = ""; - entry.account_email = ""; - entry.source_loginserver = ""; - entry.last_ip_address = ""; - entry.last_login_date = 0; - entry.created_at = 0; - entry.updated_at = std::time(nullptr); + e.id = 0; + e.account_name = ""; + e.account_password = ""; + e.account_email = ""; + e.source_loginserver = ""; + e.last_ip_address = ""; + e.last_login_date = 0; + e.created_at = 0; + e.updated_at = std::time(nullptr); - return entry; + return e; } - static LoginAccounts GetLoginAccountsEntry( + static LoginAccounts GetLoginAccounts( const std::vector &login_accountss, int login_accounts_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LoginAccounts entry{}; + LoginAccounts e{}; - entry.id = atoi(row[0]); - entry.account_name = row[1] ? row[1] : ""; - entry.account_password = row[2] ? row[2] : ""; - entry.account_email = row[3] ? row[3] : ""; - entry.source_loginserver = row[4] ? row[4] : ""; - entry.last_ip_address = row[5] ? row[5] : ""; - entry.last_login_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); - entry.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); - entry.updated_at = strtoll(row[8] ? row[8] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_name = row[1] ? row[1] : ""; + e.account_password = row[2] ? row[2] : ""; + e.account_email = row[3] ? row[3] : ""; + e.source_loginserver = row[4] ? row[4] : ""; + e.last_ip_address = row[5] ? row[5] : ""; + e.last_login_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + e.updated_at = strtoll(row[8] ? row[8] : "-1", nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -181,30 +181,30 @@ public: static int UpdateOne( Database& db, - LoginAccounts login_accounts_entry + const LoginAccounts &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(login_accounts_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(login_accounts_entry.account_name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(login_accounts_entry.account_password) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(login_accounts_entry.account_email) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(login_accounts_entry.source_loginserver) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(login_accounts_entry.last_ip_address) + "'"); - update_values.push_back(columns[6] + " = FROM_UNIXTIME(" + (login_accounts_entry.last_login_date > 0 ? std::to_string(login_accounts_entry.last_login_date) : "null") + ")"); - update_values.push_back(columns[7] + " = FROM_UNIXTIME(" + (login_accounts_entry.created_at > 0 ? std::to_string(login_accounts_entry.created_at) : "null") + ")"); - update_values.push_back(columns[8] + " = FROM_UNIXTIME(" + (login_accounts_entry.updated_at > 0 ? std::to_string(login_accounts_entry.updated_at) : "null") + ")"); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.account_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.account_password) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.account_email) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.source_loginserver) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.last_ip_address) + "'"); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.last_login_date > 0 ? std::to_string(e.last_login_date) : "null") + ")"); + v.push_back(columns[7] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[8] + " = FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - login_accounts_entry.id + e.id ) ); @@ -213,69 +213,69 @@ public: static LoginAccounts InsertOne( Database& db, - LoginAccounts login_accounts_entry + LoginAccounts e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(login_accounts_entry.id)); - insert_values.push_back("'" + EscapeString(login_accounts_entry.account_name) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.account_password) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.account_email) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.source_loginserver) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.last_ip_address) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (login_accounts_entry.last_login_date > 0 ? std::to_string(login_accounts_entry.last_login_date) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (login_accounts_entry.created_at > 0 ? std::to_string(login_accounts_entry.created_at) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (login_accounts_entry.updated_at > 0 ? std::to_string(login_accounts_entry.updated_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.account_name) + "'"); + v.push_back("'" + Strings::Escape(e.account_password) + "'"); + v.push_back("'" + Strings::Escape(e.account_email) + "'"); + v.push_back("'" + Strings::Escape(e.source_loginserver) + "'"); + v.push_back("'" + Strings::Escape(e.last_ip_address) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.last_login_date > 0 ? std::to_string(e.last_login_date) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - login_accounts_entry.id = results.LastInsertedID(); - return login_accounts_entry; + e.id = results.LastInsertedID(); + return e; } - login_accounts_entry = NewEntity(); + e = NewEntity(); - return login_accounts_entry; + return e; } static int InsertMany( Database& db, - std::vector login_accounts_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &login_accounts_entry: login_accounts_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(login_accounts_entry.id)); - insert_values.push_back("'" + EscapeString(login_accounts_entry.account_name) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.account_password) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.account_email) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.source_loginserver) + "'"); - insert_values.push_back("'" + EscapeString(login_accounts_entry.last_ip_address) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (login_accounts_entry.last_login_date > 0 ? std::to_string(login_accounts_entry.last_login_date) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (login_accounts_entry.created_at > 0 ? std::to_string(login_accounts_entry.created_at) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (login_accounts_entry.updated_at > 0 ? std::to_string(login_accounts_entry.updated_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.account_name) + "'"); + v.push_back("'" + Strings::Escape(e.account_password) + "'"); + v.push_back("'" + Strings::Escape(e.account_email) + "'"); + v.push_back("'" + Strings::Escape(e.source_loginserver) + "'"); + v.push_back("'" + Strings::Escape(e.last_ip_address) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.last_login_date > 0 ? std::to_string(e.last_login_date) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -296,25 +296,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginAccounts entry{}; + LoginAccounts e{}; - entry.id = atoi(row[0]); - entry.account_name = row[1] ? row[1] : ""; - entry.account_password = row[2] ? row[2] : ""; - entry.account_email = row[3] ? row[3] : ""; - entry.source_loginserver = row[4] ? row[4] : ""; - entry.last_ip_address = row[5] ? row[5] : ""; - entry.last_login_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); - entry.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); - entry.updated_at = strtoll(row[8] ? row[8] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_name = row[1] ? row[1] : ""; + e.account_password = row[2] ? row[2] : ""; + e.account_email = row[3] ? row[3] : ""; + e.source_loginserver = row[4] ? row[4] : ""; + e.last_ip_address = row[5] ? row[5] : ""; + e.last_login_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + e.updated_at = strtoll(row[8] ? row[8] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -329,25 +329,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginAccounts entry{}; + LoginAccounts e{}; - entry.id = atoi(row[0]); - entry.account_name = row[1] ? row[1] : ""; - entry.account_password = row[2] ? row[2] : ""; - entry.account_email = row[3] ? row[3] : ""; - entry.source_loginserver = row[4] ? row[4] : ""; - entry.last_ip_address = row[5] ? row[5] : ""; - entry.last_login_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); - entry.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); - entry.updated_at = strtoll(row[8] ? row[8] : "-1", nullptr, 10); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_name = row[1] ? row[1] : ""; + e.account_password = row[2] ? row[2] : ""; + e.account_email = row[3] ? row[3] : ""; + e.source_loginserver = row[4] ? row[4] : ""; + e.last_ip_address = row[5] ? row[5] : ""; + e.last_login_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + e.updated_at = strtoll(row[8] ? row[8] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -372,6 +372,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOGIN_ACCOUNTS_REPOSITORY_H diff --git a/common/repositories/base/base_login_api_tokens_repository.h b/common/repositories/base/base_login_api_tokens_repository.h index bfd8f9a74..3f5a107d3 100644 --- a/common/repositories/base/base_login_api_tokens_repository.h +++ b/common/repositories/base/base_login_api_tokens_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_LOGIN_API_TOKENS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLoginApiTokensRepository { public: struct LoginApiTokens { - int id; + int32_t id; std::string token; - int can_write; - int can_read; + int32_t can_write; + int32_t can_read; time_t created_at; time_t updated_at; }; @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static LoginApiTokens NewEntity() { - LoginApiTokens entry{}; + LoginApiTokens e{}; - entry.id = 0; - entry.token = ""; - entry.can_write = 0; - entry.can_read = 0; - entry.created_at = 0; - entry.updated_at = std::time(nullptr); + e.id = 0; + e.token = ""; + e.can_write = 0; + e.can_read = 0; + e.created_at = 0; + e.updated_at = std::time(nullptr); - return entry; + return e; } - static LoginApiTokens GetLoginApiTokensEntry( + static LoginApiTokens GetLoginApiTokens( const std::vector &login_api_tokenss, int login_api_tokens_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LoginApiTokens entry{}; + LoginApiTokens e{}; - entry.id = atoi(row[0]); - entry.token = row[1] ? row[1] : ""; - entry.can_write = atoi(row[2]); - entry.can_read = atoi(row[3]); - entry.created_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.updated_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.id = static_cast(atoi(row[0])); + e.token = row[1] ? row[1] : ""; + e.can_write = static_cast(atoi(row[2])); + e.can_read = static_cast(atoi(row[3])); + e.created_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.updated_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -166,26 +166,26 @@ public: static int UpdateOne( Database& db, - LoginApiTokens login_api_tokens_entry + const LoginApiTokens &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(login_api_tokens_entry.token) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(login_api_tokens_entry.can_write)); - update_values.push_back(columns[3] + " = " + std::to_string(login_api_tokens_entry.can_read)); - update_values.push_back(columns[4] + " = FROM_UNIXTIME(" + (login_api_tokens_entry.created_at > 0 ? std::to_string(login_api_tokens_entry.created_at) : "null") + ")"); - update_values.push_back(columns[5] + " = FROM_UNIXTIME(" + (login_api_tokens_entry.updated_at > 0 ? std::to_string(login_api_tokens_entry.updated_at) : "null") + ")"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.token) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.can_write)); + v.push_back(columns[3] + " = " + std::to_string(e.can_read)); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[5] + " = FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - login_api_tokens_entry.id + e.id ) ); @@ -194,63 +194,63 @@ public: static LoginApiTokens InsertOne( Database& db, - LoginApiTokens login_api_tokens_entry + LoginApiTokens e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(login_api_tokens_entry.id)); - insert_values.push_back("'" + EscapeString(login_api_tokens_entry.token) + "'"); - insert_values.push_back(std::to_string(login_api_tokens_entry.can_write)); - insert_values.push_back(std::to_string(login_api_tokens_entry.can_read)); - insert_values.push_back("FROM_UNIXTIME(" + (login_api_tokens_entry.created_at > 0 ? std::to_string(login_api_tokens_entry.created_at) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (login_api_tokens_entry.updated_at > 0 ? std::to_string(login_api_tokens_entry.updated_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.token) + "'"); + v.push_back(std::to_string(e.can_write)); + v.push_back(std::to_string(e.can_read)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - login_api_tokens_entry.id = results.LastInsertedID(); - return login_api_tokens_entry; + e.id = results.LastInsertedID(); + return e; } - login_api_tokens_entry = NewEntity(); + e = NewEntity(); - return login_api_tokens_entry; + return e; } static int InsertMany( Database& db, - std::vector login_api_tokens_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &login_api_tokens_entry: login_api_tokens_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(login_api_tokens_entry.id)); - insert_values.push_back("'" + EscapeString(login_api_tokens_entry.token) + "'"); - insert_values.push_back(std::to_string(login_api_tokens_entry.can_write)); - insert_values.push_back(std::to_string(login_api_tokens_entry.can_read)); - insert_values.push_back("FROM_UNIXTIME(" + (login_api_tokens_entry.created_at > 0 ? std::to_string(login_api_tokens_entry.created_at) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (login_api_tokens_entry.updated_at > 0 ? std::to_string(login_api_tokens_entry.updated_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.token) + "'"); + v.push_back(std::to_string(e.can_write)); + v.push_back(std::to_string(e.can_read)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -271,22 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginApiTokens entry{}; + LoginApiTokens e{}; - entry.id = atoi(row[0]); - entry.token = row[1] ? row[1] : ""; - entry.can_write = atoi(row[2]); - entry.can_read = atoi(row[3]); - entry.created_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.updated_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.id = static_cast(atoi(row[0])); + e.token = row[1] ? row[1] : ""; + e.can_write = static_cast(atoi(row[2])); + e.can_read = static_cast(atoi(row[3])); + e.created_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.updated_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -301,22 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginApiTokens entry{}; + LoginApiTokens e{}; - entry.id = atoi(row[0]); - entry.token = row[1] ? row[1] : ""; - entry.can_write = atoi(row[2]); - entry.can_read = atoi(row[3]); - entry.created_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.updated_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.id = static_cast(atoi(row[0])); + e.token = row[1] ? row[1] : ""; + e.can_write = static_cast(atoi(row[2])); + e.can_read = static_cast(atoi(row[3])); + e.created_at = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.updated_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -341,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOGIN_API_TOKENS_REPOSITORY_H diff --git a/common/repositories/base/base_login_server_admins_repository.h b/common/repositories/base/base_login_server_admins_repository.h index 901edc2f1..297dbd312 100644 --- a/common/repositories/base/base_login_server_admins_repository.h +++ b/common/repositories/base/base_login_server_admins_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_LOGIN_SERVER_ADMINS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLoginServerAdminsRepository { public: struct LoginServerAdmins { - int id; + uint32_t id; std::string account_name; std::string account_password; std::string first_name; @@ -64,12 +64,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -97,21 +97,21 @@ public: static LoginServerAdmins NewEntity() { - LoginServerAdmins entry{}; + LoginServerAdmins e{}; - entry.id = 0; - entry.account_name = ""; - entry.account_password = ""; - entry.first_name = ""; - entry.last_name = ""; - entry.email = ""; - entry.registration_date = 0; - entry.registration_ip_address = ""; + e.id = 0; + e.account_name = ""; + e.account_password = ""; + e.first_name = ""; + e.last_name = ""; + e.email = ""; + e.registration_date = 0; + e.registration_ip_address = ""; - return entry; + return e; } - static LoginServerAdmins GetLoginServerAdminsEntry( + static LoginServerAdmins GetLoginServerAdmins( const std::vector &login_server_adminss, int login_server_admins_id ) @@ -140,18 +140,18 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LoginServerAdmins entry{}; + LoginServerAdmins e{}; - entry.id = atoi(row[0]); - entry.account_name = row[1] ? row[1] : ""; - entry.account_password = row[2] ? row[2] : ""; - entry.first_name = row[3] ? row[3] : ""; - entry.last_name = row[4] ? row[4] : ""; - entry.email = row[5] ? row[5] : ""; - entry.registration_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); - entry.registration_ip_address = row[7] ? row[7] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_name = row[1] ? row[1] : ""; + e.account_password = row[2] ? row[2] : ""; + e.first_name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.email = row[5] ? row[5] : ""; + e.registration_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.registration_ip_address = row[7] ? row[7] : ""; - return entry; + return e; } return NewEntity(); @@ -176,28 +176,28 @@ public: static int UpdateOne( Database& db, - LoginServerAdmins login_server_admins_entry + const LoginServerAdmins &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(login_server_admins_entry.account_name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(login_server_admins_entry.account_password) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(login_server_admins_entry.first_name) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(login_server_admins_entry.last_name) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(login_server_admins_entry.email) + "'"); - update_values.push_back(columns[6] + " = FROM_UNIXTIME(" + (login_server_admins_entry.registration_date > 0 ? std::to_string(login_server_admins_entry.registration_date) : "null") + ")"); - update_values.push_back(columns[7] + " = '" + EscapeString(login_server_admins_entry.registration_ip_address) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.account_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.account_password) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.first_name) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.last_name) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.email) + "'"); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.registration_date > 0 ? std::to_string(e.registration_date) : "null") + ")"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.registration_ip_address) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - login_server_admins_entry.id + e.id ) ); @@ -206,67 +206,67 @@ public: static LoginServerAdmins InsertOne( Database& db, - LoginServerAdmins login_server_admins_entry + LoginServerAdmins e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(login_server_admins_entry.id)); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.account_name) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.account_password) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.first_name) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.last_name) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.email) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (login_server_admins_entry.registration_date > 0 ? std::to_string(login_server_admins_entry.registration_date) : "null") + ")"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.registration_ip_address) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.account_name) + "'"); + v.push_back("'" + Strings::Escape(e.account_password) + "'"); + v.push_back("'" + Strings::Escape(e.first_name) + "'"); + v.push_back("'" + Strings::Escape(e.last_name) + "'"); + v.push_back("'" + Strings::Escape(e.email) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.registration_date > 0 ? std::to_string(e.registration_date) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.registration_ip_address) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - login_server_admins_entry.id = results.LastInsertedID(); - return login_server_admins_entry; + e.id = results.LastInsertedID(); + return e; } - login_server_admins_entry = NewEntity(); + e = NewEntity(); - return login_server_admins_entry; + return e; } static int InsertMany( Database& db, - std::vector login_server_admins_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &login_server_admins_entry: login_server_admins_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(login_server_admins_entry.id)); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.account_name) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.account_password) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.first_name) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.last_name) + "'"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.email) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (login_server_admins_entry.registration_date > 0 ? std::to_string(login_server_admins_entry.registration_date) : "null") + ")"); - insert_values.push_back("'" + EscapeString(login_server_admins_entry.registration_ip_address) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.account_name) + "'"); + v.push_back("'" + Strings::Escape(e.account_password) + "'"); + v.push_back("'" + Strings::Escape(e.first_name) + "'"); + v.push_back("'" + Strings::Escape(e.last_name) + "'"); + v.push_back("'" + Strings::Escape(e.email) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.registration_date > 0 ? std::to_string(e.registration_date) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.registration_ip_address) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -287,24 +287,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginServerAdmins entry{}; + LoginServerAdmins e{}; - entry.id = atoi(row[0]); - entry.account_name = row[1] ? row[1] : ""; - entry.account_password = row[2] ? row[2] : ""; - entry.first_name = row[3] ? row[3] : ""; - entry.last_name = row[4] ? row[4] : ""; - entry.email = row[5] ? row[5] : ""; - entry.registration_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); - entry.registration_ip_address = row[7] ? row[7] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_name = row[1] ? row[1] : ""; + e.account_password = row[2] ? row[2] : ""; + e.first_name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.email = row[5] ? row[5] : ""; + e.registration_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.registration_ip_address = row[7] ? row[7] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -319,24 +319,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginServerAdmins entry{}; + LoginServerAdmins e{}; - entry.id = atoi(row[0]); - entry.account_name = row[1] ? row[1] : ""; - entry.account_password = row[2] ? row[2] : ""; - entry.first_name = row[3] ? row[3] : ""; - entry.last_name = row[4] ? row[4] : ""; - entry.email = row[5] ? row[5] : ""; - entry.registration_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); - entry.registration_ip_address = row[7] ? row[7] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.account_name = row[1] ? row[1] : ""; + e.account_password = row[2] ? row[2] : ""; + e.first_name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.email = row[5] ? row[5] : ""; + e.registration_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.registration_ip_address = row[7] ? row[7] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -361,6 +361,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOGIN_SERVER_ADMINS_REPOSITORY_H diff --git a/common/repositories/base/base_login_server_list_types_repository.h b/common/repositories/base/base_login_server_list_types_repository.h index 0f0483b54..9973d28aa 100644 --- a/common/repositories/base/base_login_server_list_types_repository.h +++ b/common/repositories/base/base_login_server_list_types_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLoginServerListTypesRepository { public: struct LoginServerListTypes { - int id; + uint32_t id; std::string description; }; @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static LoginServerListTypes NewEntity() { - LoginServerListTypes entry{}; + LoginServerListTypes e{}; - entry.id = 0; - entry.description = ""; + e.id = 0; + e.description = ""; - return entry; + return e; } - static LoginServerListTypes GetLoginServerListTypesEntry( + static LoginServerListTypes GetLoginServerListTypes( const std::vector &login_server_list_typess, int login_server_list_types_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LoginServerListTypes entry{}; + LoginServerListTypes e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.description = row[1] ? row[1] : ""; - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - LoginServerListTypes login_server_list_types_entry + const LoginServerListTypes &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(login_server_list_types_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(login_server_list_types_entry.description) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.description) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - login_server_list_types_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static LoginServerListTypes InsertOne( Database& db, - LoginServerListTypes login_server_list_types_entry + LoginServerListTypes e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(login_server_list_types_entry.id)); - insert_values.push_back("'" + EscapeString(login_server_list_types_entry.description) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.description) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - login_server_list_types_entry.id = results.LastInsertedID(); - return login_server_list_types_entry; + e.id = results.LastInsertedID(); + return e; } - login_server_list_types_entry = NewEntity(); + e = NewEntity(); - return login_server_list_types_entry; + return e; } static int InsertMany( Database& db, - std::vector login_server_list_types_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &login_server_list_types_entry: login_server_list_types_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(login_server_list_types_entry.id)); - insert_values.push_back("'" + EscapeString(login_server_list_types_entry.description) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.description) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginServerListTypes entry{}; + LoginServerListTypes e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.description = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginServerListTypes entry{}; + LoginServerListTypes e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.description = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_login_world_servers_repository.h b/common/repositories/base/base_login_world_servers_repository.h index 0c6616681..850f233a8 100644 --- a/common/repositories/base/base_login_world_servers_repository.h +++ b/common/repositories/base/base_login_world_servers_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_LOGIN_WORLD_SERVERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLoginWorldServersRepository { public: struct LoginWorldServers { - int id; + uint32_t id; std::string long_name; std::string short_name; std::string tag_description; - int login_server_list_type_id; + int32_t login_server_list_type_id; time_t last_login_date; std::string last_ip_address; - int login_server_admin_id; - int is_server_trusted; + int32_t login_server_admin_id; + int32_t is_server_trusted; std::string note; }; @@ -70,12 +70,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -103,23 +103,23 @@ public: static LoginWorldServers NewEntity() { - LoginWorldServers entry{}; + LoginWorldServers e{}; - entry.id = 0; - entry.long_name = ""; - entry.short_name = ""; - entry.tag_description = ""; - entry.login_server_list_type_id = 0; - entry.last_login_date = 0; - entry.last_ip_address = ""; - entry.login_server_admin_id = 0; - entry.is_server_trusted = 0; - entry.note = ""; + e.id = 0; + e.long_name = ""; + e.short_name = ""; + e.tag_description = ""; + e.login_server_list_type_id = 0; + e.last_login_date = 0; + e.last_ip_address = ""; + e.login_server_admin_id = 0; + e.is_server_trusted = 0; + e.note = ""; - return entry; + return e; } - static LoginWorldServers GetLoginWorldServersEntry( + static LoginWorldServers GetLoginWorldServers( const std::vector &login_world_serverss, int login_world_servers_id ) @@ -148,20 +148,20 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LoginWorldServers entry{}; + LoginWorldServers e{}; - entry.id = atoi(row[0]); - entry.long_name = row[1] ? row[1] : ""; - entry.short_name = row[2] ? row[2] : ""; - entry.tag_description = row[3] ? row[3] : ""; - entry.login_server_list_type_id = atoi(row[4]); - entry.last_login_date = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - entry.last_ip_address = row[6] ? row[6] : ""; - entry.login_server_admin_id = atoi(row[7]); - entry.is_server_trusted = atoi(row[8]); - entry.note = row[9] ? row[9] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.long_name = row[1] ? row[1] : ""; + e.short_name = row[2] ? row[2] : ""; + e.tag_description = row[3] ? row[3] : ""; + e.login_server_list_type_id = static_cast(atoi(row[4])); + e.last_login_date = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.last_ip_address = row[6] ? row[6] : ""; + e.login_server_admin_id = static_cast(atoi(row[7])); + e.is_server_trusted = static_cast(atoi(row[8])); + e.note = row[9] ? row[9] : ""; - return entry; + return e; } return NewEntity(); @@ -186,30 +186,30 @@ public: static int UpdateOne( Database& db, - LoginWorldServers login_world_servers_entry + const LoginWorldServers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(login_world_servers_entry.long_name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(login_world_servers_entry.short_name) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(login_world_servers_entry.tag_description) + "'"); - update_values.push_back(columns[4] + " = " + std::to_string(login_world_servers_entry.login_server_list_type_id)); - update_values.push_back(columns[5] + " = FROM_UNIXTIME(" + (login_world_servers_entry.last_login_date > 0 ? std::to_string(login_world_servers_entry.last_login_date) : "null") + ")"); - update_values.push_back(columns[6] + " = '" + EscapeString(login_world_servers_entry.last_ip_address) + "'"); - update_values.push_back(columns[7] + " = " + std::to_string(login_world_servers_entry.login_server_admin_id)); - update_values.push_back(columns[8] + " = " + std::to_string(login_world_servers_entry.is_server_trusted)); - update_values.push_back(columns[9] + " = '" + EscapeString(login_world_servers_entry.note) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.long_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.short_name) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.tag_description) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.login_server_list_type_id)); + v.push_back(columns[5] + " = FROM_UNIXTIME(" + (e.last_login_date > 0 ? std::to_string(e.last_login_date) : "null") + ")"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.last_ip_address) + "'"); + v.push_back(columns[7] + " = " + std::to_string(e.login_server_admin_id)); + v.push_back(columns[8] + " = " + std::to_string(e.is_server_trusted)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.note) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - login_world_servers_entry.id + e.id ) ); @@ -218,71 +218,71 @@ public: static LoginWorldServers InsertOne( Database& db, - LoginWorldServers login_world_servers_entry + LoginWorldServers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(login_world_servers_entry.id)); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.long_name) + "'"); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.short_name) + "'"); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.tag_description) + "'"); - insert_values.push_back(std::to_string(login_world_servers_entry.login_server_list_type_id)); - insert_values.push_back("FROM_UNIXTIME(" + (login_world_servers_entry.last_login_date > 0 ? std::to_string(login_world_servers_entry.last_login_date) : "null") + ")"); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.last_ip_address) + "'"); - insert_values.push_back(std::to_string(login_world_servers_entry.login_server_admin_id)); - insert_values.push_back(std::to_string(login_world_servers_entry.is_server_trusted)); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.note) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.long_name) + "'"); + v.push_back("'" + Strings::Escape(e.short_name) + "'"); + v.push_back("'" + Strings::Escape(e.tag_description) + "'"); + v.push_back(std::to_string(e.login_server_list_type_id)); + v.push_back("FROM_UNIXTIME(" + (e.last_login_date > 0 ? std::to_string(e.last_login_date) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.last_ip_address) + "'"); + v.push_back(std::to_string(e.login_server_admin_id)); + v.push_back(std::to_string(e.is_server_trusted)); + v.push_back("'" + Strings::Escape(e.note) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - login_world_servers_entry.id = results.LastInsertedID(); - return login_world_servers_entry; + e.id = results.LastInsertedID(); + return e; } - login_world_servers_entry = NewEntity(); + e = NewEntity(); - return login_world_servers_entry; + return e; } static int InsertMany( Database& db, - std::vector login_world_servers_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &login_world_servers_entry: login_world_servers_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(login_world_servers_entry.id)); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.long_name) + "'"); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.short_name) + "'"); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.tag_description) + "'"); - insert_values.push_back(std::to_string(login_world_servers_entry.login_server_list_type_id)); - insert_values.push_back("FROM_UNIXTIME(" + (login_world_servers_entry.last_login_date > 0 ? std::to_string(login_world_servers_entry.last_login_date) : "null") + ")"); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.last_ip_address) + "'"); - insert_values.push_back(std::to_string(login_world_servers_entry.login_server_admin_id)); - insert_values.push_back(std::to_string(login_world_servers_entry.is_server_trusted)); - insert_values.push_back("'" + EscapeString(login_world_servers_entry.note) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.long_name) + "'"); + v.push_back("'" + Strings::Escape(e.short_name) + "'"); + v.push_back("'" + Strings::Escape(e.tag_description) + "'"); + v.push_back(std::to_string(e.login_server_list_type_id)); + v.push_back("FROM_UNIXTIME(" + (e.last_login_date > 0 ? std::to_string(e.last_login_date) : "null") + ")"); + v.push_back("'" + Strings::Escape(e.last_ip_address) + "'"); + v.push_back(std::to_string(e.login_server_admin_id)); + v.push_back(std::to_string(e.is_server_trusted)); + v.push_back("'" + Strings::Escape(e.note) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -303,26 +303,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginWorldServers entry{}; + LoginWorldServers e{}; - entry.id = atoi(row[0]); - entry.long_name = row[1] ? row[1] : ""; - entry.short_name = row[2] ? row[2] : ""; - entry.tag_description = row[3] ? row[3] : ""; - entry.login_server_list_type_id = atoi(row[4]); - entry.last_login_date = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - entry.last_ip_address = row[6] ? row[6] : ""; - entry.login_server_admin_id = atoi(row[7]); - entry.is_server_trusted = atoi(row[8]); - entry.note = row[9] ? row[9] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.long_name = row[1] ? row[1] : ""; + e.short_name = row[2] ? row[2] : ""; + e.tag_description = row[3] ? row[3] : ""; + e.login_server_list_type_id = static_cast(atoi(row[4])); + e.last_login_date = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.last_ip_address = row[6] ? row[6] : ""; + e.login_server_admin_id = static_cast(atoi(row[7])); + e.is_server_trusted = static_cast(atoi(row[8])); + e.note = row[9] ? row[9] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -337,26 +337,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoginWorldServers entry{}; + LoginWorldServers e{}; - entry.id = atoi(row[0]); - entry.long_name = row[1] ? row[1] : ""; - entry.short_name = row[2] ? row[2] : ""; - entry.tag_description = row[3] ? row[3] : ""; - entry.login_server_list_type_id = atoi(row[4]); - entry.last_login_date = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - entry.last_ip_address = row[6] ? row[6] : ""; - entry.login_server_admin_id = atoi(row[7]); - entry.is_server_trusted = atoi(row[8]); - entry.note = row[9] ? row[9] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.long_name = row[1] ? row[1] : ""; + e.short_name = row[2] ? row[2] : ""; + e.tag_description = row[3] ? row[3] : ""; + e.login_server_list_type_id = static_cast(atoi(row[4])); + e.last_login_date = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.last_ip_address = row[6] ? row[6] : ""; + e.login_server_admin_id = static_cast(atoi(row[7])); + e.is_server_trusted = static_cast(atoi(row[8])); + e.note = row[9] ? row[9] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -381,6 +381,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOGIN_WORLD_SERVERS_REPOSITORY_H diff --git a/common/repositories/base/base_logsys_categories_repository.h b/common/repositories/base/base_logsys_categories_repository.h index f7ffb63bb..867ca894c 100644 --- a/common/repositories/base/base_logsys_categories_repository.h +++ b/common/repositories/base/base_logsys_categories_repository.h @@ -13,17 +13,19 @@ #define EQEMU_BASE_LOGSYS_CATEGORIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLogsysCategoriesRepository { public: struct LogsysCategories { - int log_category_id; + int32_t log_category_id; std::string log_category_description; - int log_to_console; - int log_to_file; - int log_to_gmsay; + int16_t log_to_console; + int16_t log_to_file; + int16_t log_to_gmsay; + int16_t log_to_discord; + int32_t discord_webhook_id; }; static std::string PrimaryKey() @@ -39,6 +41,8 @@ public: "log_to_console", "log_to_file", "log_to_gmsay", + "log_to_discord", + "discord_webhook_id", }; } @@ -50,17 +54,19 @@ public: "log_to_console", "log_to_file", "log_to_gmsay", + "log_to_discord", + "discord_webhook_id", }; } static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +94,20 @@ public: static LogsysCategories NewEntity() { - LogsysCategories entry{}; + LogsysCategories e{}; - entry.log_category_id = 0; - entry.log_category_description = ""; - entry.log_to_console = 0; - entry.log_to_file = 0; - entry.log_to_gmsay = 0; + e.log_category_id = 0; + e.log_category_description = ""; + e.log_to_console = 0; + e.log_to_file = 0; + e.log_to_gmsay = 0; + e.log_to_discord = 0; + e.discord_webhook_id = 0; - return entry; + return e; } - static LogsysCategories GetLogsysCategoriesEntry( + static LogsysCategories GetLogsysCategories( const std::vector &logsys_categoriess, int logsys_categories_id ) @@ -128,15 +136,17 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LogsysCategories entry{}; + LogsysCategories e{}; - entry.log_category_id = atoi(row[0]); - entry.log_category_description = row[1] ? row[1] : ""; - entry.log_to_console = atoi(row[2]); - entry.log_to_file = atoi(row[3]); - entry.log_to_gmsay = atoi(row[4]); + e.log_category_id = static_cast(atoi(row[0])); + e.log_category_description = row[1] ? row[1] : ""; + e.log_to_console = static_cast(atoi(row[2])); + e.log_to_file = static_cast(atoi(row[3])); + e.log_to_gmsay = static_cast(atoi(row[4])); + e.log_to_discord = static_cast(atoi(row[5])); + e.discord_webhook_id = static_cast(atoi(row[6])); - return entry; + return e; } return NewEntity(); @@ -161,26 +171,28 @@ public: static int UpdateOne( Database& db, - LogsysCategories logsys_categories_entry + const LogsysCategories &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(logsys_categories_entry.log_category_id)); - update_values.push_back(columns[1] + " = '" + EscapeString(logsys_categories_entry.log_category_description) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(logsys_categories_entry.log_to_console)); - update_values.push_back(columns[3] + " = " + std::to_string(logsys_categories_entry.log_to_file)); - update_values.push_back(columns[4] + " = " + std::to_string(logsys_categories_entry.log_to_gmsay)); + v.push_back(columns[0] + " = " + std::to_string(e.log_category_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.log_category_description) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.log_to_console)); + v.push_back(columns[3] + " = " + std::to_string(e.log_to_file)); + v.push_back(columns[4] + " = " + std::to_string(e.log_to_gmsay)); + v.push_back(columns[5] + " = " + std::to_string(e.log_to_discord)); + v.push_back(columns[6] + " = " + std::to_string(e.discord_webhook_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - logsys_categories_entry.log_category_id + e.log_category_id ) ); @@ -189,61 +201,65 @@ public: static LogsysCategories InsertOne( Database& db, - LogsysCategories logsys_categories_entry + LogsysCategories e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(logsys_categories_entry.log_category_id)); - insert_values.push_back("'" + EscapeString(logsys_categories_entry.log_category_description) + "'"); - insert_values.push_back(std::to_string(logsys_categories_entry.log_to_console)); - insert_values.push_back(std::to_string(logsys_categories_entry.log_to_file)); - insert_values.push_back(std::to_string(logsys_categories_entry.log_to_gmsay)); + v.push_back(std::to_string(e.log_category_id)); + v.push_back("'" + Strings::Escape(e.log_category_description) + "'"); + v.push_back(std::to_string(e.log_to_console)); + v.push_back(std::to_string(e.log_to_file)); + v.push_back(std::to_string(e.log_to_gmsay)); + v.push_back(std::to_string(e.log_to_discord)); + v.push_back(std::to_string(e.discord_webhook_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - logsys_categories_entry.log_category_id = results.LastInsertedID(); - return logsys_categories_entry; + e.log_category_id = results.LastInsertedID(); + return e; } - logsys_categories_entry = NewEntity(); + e = NewEntity(); - return logsys_categories_entry; + return e; } static int InsertMany( Database& db, - std::vector logsys_categories_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &logsys_categories_entry: logsys_categories_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(logsys_categories_entry.log_category_id)); - insert_values.push_back("'" + EscapeString(logsys_categories_entry.log_category_description) + "'"); - insert_values.push_back(std::to_string(logsys_categories_entry.log_to_console)); - insert_values.push_back(std::to_string(logsys_categories_entry.log_to_file)); - insert_values.push_back(std::to_string(logsys_categories_entry.log_to_gmsay)); + v.push_back(std::to_string(e.log_category_id)); + v.push_back("'" + Strings::Escape(e.log_category_description) + "'"); + v.push_back(std::to_string(e.log_to_console)); + v.push_back(std::to_string(e.log_to_file)); + v.push_back(std::to_string(e.log_to_gmsay)); + v.push_back(std::to_string(e.log_to_discord)); + v.push_back(std::to_string(e.discord_webhook_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +280,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LogsysCategories entry{}; + LogsysCategories e{}; - entry.log_category_id = atoi(row[0]); - entry.log_category_description = row[1] ? row[1] : ""; - entry.log_to_console = atoi(row[2]); - entry.log_to_file = atoi(row[3]); - entry.log_to_gmsay = atoi(row[4]); + e.log_category_id = static_cast(atoi(row[0])); + e.log_category_description = row[1] ? row[1] : ""; + e.log_to_console = static_cast(atoi(row[2])); + e.log_to_file = static_cast(atoi(row[3])); + e.log_to_gmsay = static_cast(atoi(row[4])); + e.log_to_discord = static_cast(atoi(row[5])); + e.discord_webhook_id = static_cast(atoi(row[6])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +311,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LogsysCategories entry{}; + LogsysCategories e{}; - entry.log_category_id = atoi(row[0]); - entry.log_category_description = row[1] ? row[1] : ""; - entry.log_to_console = atoi(row[2]); - entry.log_to_file = atoi(row[3]); - entry.log_to_gmsay = atoi(row[4]); + e.log_category_id = static_cast(atoi(row[0])); + e.log_category_description = row[1] ? row[1] : ""; + e.log_to_console = static_cast(atoi(row[2])); + e.log_to_file = static_cast(atoi(row[3])); + e.log_to_gmsay = static_cast(atoi(row[4])); + e.log_to_discord = static_cast(atoi(row[5])); + e.discord_webhook_id = static_cast(atoi(row[6])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +352,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOGSYS_CATEGORIES_REPOSITORY_H diff --git a/common/repositories/base/base_lootdrop_entries_repository.h b/common/repositories/base/base_lootdrop_entries_repository.h index d9bccef06..48a0cf337 100644 --- a/common/repositories/base/base_lootdrop_entries_repository.h +++ b/common/repositories/base/base_lootdrop_entries_repository.h @@ -13,23 +13,23 @@ #define EQEMU_BASE_LOOTDROP_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLootdropEntriesRepository { public: struct LootdropEntries { - int lootdrop_id; - int item_id; - int item_charges; - int equip_item; - float chance; - float disabled_chance; - int trivial_min_level; - int trivial_max_level; - int multiplier; - int npc_min_level; - int npc_max_level; + uint32_t lootdrop_id; + int32_t item_id; + uint16_t item_charges; + uint8_t equip_item; + float chance; + float disabled_chance; + uint16_t trivial_min_level; + uint16_t trivial_max_level; + uint8_t multiplier; + uint16_t npc_min_level; + uint16_t npc_max_level; }; static std::string PrimaryKey() @@ -73,12 +73,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -106,24 +106,24 @@ public: static LootdropEntries NewEntity() { - LootdropEntries entry{}; + LootdropEntries e{}; - entry.lootdrop_id = 0; - entry.item_id = 0; - entry.item_charges = 1; - entry.equip_item = 0; - entry.chance = 1; - entry.disabled_chance = 0; - entry.trivial_min_level = 0; - entry.trivial_max_level = 0; - entry.multiplier = 1; - entry.npc_min_level = 0; - entry.npc_max_level = 0; + e.lootdrop_id = 0; + e.item_id = 0; + e.item_charges = 1; + e.equip_item = 0; + e.chance = 1; + e.disabled_chance = 0; + e.trivial_min_level = 0; + e.trivial_max_level = 0; + e.multiplier = 1; + e.npc_min_level = 0; + e.npc_max_level = 0; - return entry; + return e; } - static LootdropEntries GetLootdropEntriesEntry( + static LootdropEntries GetLootdropEntries( const std::vector &lootdrop_entriess, int lootdrop_entries_id ) @@ -152,21 +152,21 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LootdropEntries entry{}; + LootdropEntries e{}; - entry.lootdrop_id = atoi(row[0]); - entry.item_id = atoi(row[1]); - entry.item_charges = atoi(row[2]); - entry.equip_item = atoi(row[3]); - entry.chance = static_cast(atof(row[4])); - entry.disabled_chance = static_cast(atof(row[5])); - entry.trivial_min_level = atoi(row[6]); - entry.trivial_max_level = atoi(row[7]); - entry.multiplier = atoi(row[8]); - entry.npc_min_level = atoi(row[9]); - entry.npc_max_level = atoi(row[10]); + e.lootdrop_id = static_cast(strtoul(row[0], nullptr, 10)); + e.item_id = static_cast(atoi(row[1])); + e.item_charges = static_cast(strtoul(row[2], nullptr, 10)); + e.equip_item = static_cast(strtoul(row[3], nullptr, 10)); + e.chance = strtof(row[4], nullptr); + e.disabled_chance = strtof(row[5], nullptr); + e.trivial_min_level = static_cast(strtoul(row[6], nullptr, 10)); + e.trivial_max_level = static_cast(strtoul(row[7], nullptr, 10)); + e.multiplier = static_cast(strtoul(row[8], nullptr, 10)); + e.npc_min_level = static_cast(strtoul(row[9], nullptr, 10)); + e.npc_max_level = static_cast(strtoul(row[10], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -191,32 +191,32 @@ public: static int UpdateOne( Database& db, - LootdropEntries lootdrop_entries_entry + const LootdropEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(lootdrop_entries_entry.lootdrop_id)); - update_values.push_back(columns[1] + " = " + std::to_string(lootdrop_entries_entry.item_id)); - update_values.push_back(columns[2] + " = " + std::to_string(lootdrop_entries_entry.item_charges)); - update_values.push_back(columns[3] + " = " + std::to_string(lootdrop_entries_entry.equip_item)); - update_values.push_back(columns[4] + " = " + std::to_string(lootdrop_entries_entry.chance)); - update_values.push_back(columns[5] + " = " + std::to_string(lootdrop_entries_entry.disabled_chance)); - update_values.push_back(columns[6] + " = " + std::to_string(lootdrop_entries_entry.trivial_min_level)); - update_values.push_back(columns[7] + " = " + std::to_string(lootdrop_entries_entry.trivial_max_level)); - update_values.push_back(columns[8] + " = " + std::to_string(lootdrop_entries_entry.multiplier)); - update_values.push_back(columns[9] + " = " + std::to_string(lootdrop_entries_entry.npc_min_level)); - update_values.push_back(columns[10] + " = " + std::to_string(lootdrop_entries_entry.npc_max_level)); + v.push_back(columns[0] + " = " + std::to_string(e.lootdrop_id)); + v.push_back(columns[1] + " = " + std::to_string(e.item_id)); + v.push_back(columns[2] + " = " + std::to_string(e.item_charges)); + v.push_back(columns[3] + " = " + std::to_string(e.equip_item)); + v.push_back(columns[4] + " = " + std::to_string(e.chance)); + v.push_back(columns[5] + " = " + std::to_string(e.disabled_chance)); + v.push_back(columns[6] + " = " + std::to_string(e.trivial_min_level)); + v.push_back(columns[7] + " = " + std::to_string(e.trivial_max_level)); + v.push_back(columns[8] + " = " + std::to_string(e.multiplier)); + v.push_back(columns[9] + " = " + std::to_string(e.npc_min_level)); + v.push_back(columns[10] + " = " + std::to_string(e.npc_max_level)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - lootdrop_entries_entry.lootdrop_id + e.lootdrop_id ) ); @@ -225,73 +225,73 @@ public: static LootdropEntries InsertOne( Database& db, - LootdropEntries lootdrop_entries_entry + LootdropEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(lootdrop_entries_entry.lootdrop_id)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.item_id)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.item_charges)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.equip_item)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.chance)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.disabled_chance)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.trivial_min_level)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.trivial_max_level)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.multiplier)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.npc_min_level)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.npc_max_level)); + v.push_back(std::to_string(e.lootdrop_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.item_charges)); + v.push_back(std::to_string(e.equip_item)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.disabled_chance)); + v.push_back(std::to_string(e.trivial_min_level)); + v.push_back(std::to_string(e.trivial_max_level)); + v.push_back(std::to_string(e.multiplier)); + v.push_back(std::to_string(e.npc_min_level)); + v.push_back(std::to_string(e.npc_max_level)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - lootdrop_entries_entry.lootdrop_id = results.LastInsertedID(); - return lootdrop_entries_entry; + e.lootdrop_id = results.LastInsertedID(); + return e; } - lootdrop_entries_entry = NewEntity(); + e = NewEntity(); - return lootdrop_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector lootdrop_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &lootdrop_entries_entry: lootdrop_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(lootdrop_entries_entry.lootdrop_id)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.item_id)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.item_charges)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.equip_item)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.chance)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.disabled_chance)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.trivial_min_level)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.trivial_max_level)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.multiplier)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.npc_min_level)); - insert_values.push_back(std::to_string(lootdrop_entries_entry.npc_max_level)); + v.push_back(std::to_string(e.lootdrop_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.item_charges)); + v.push_back(std::to_string(e.equip_item)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.disabled_chance)); + v.push_back(std::to_string(e.trivial_min_level)); + v.push_back(std::to_string(e.trivial_max_level)); + v.push_back(std::to_string(e.multiplier)); + v.push_back(std::to_string(e.npc_min_level)); + v.push_back(std::to_string(e.npc_max_level)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -312,27 +312,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LootdropEntries entry{}; + LootdropEntries e{}; - entry.lootdrop_id = atoi(row[0]); - entry.item_id = atoi(row[1]); - entry.item_charges = atoi(row[2]); - entry.equip_item = atoi(row[3]); - entry.chance = static_cast(atof(row[4])); - entry.disabled_chance = static_cast(atof(row[5])); - entry.trivial_min_level = atoi(row[6]); - entry.trivial_max_level = atoi(row[7]); - entry.multiplier = atoi(row[8]); - entry.npc_min_level = atoi(row[9]); - entry.npc_max_level = atoi(row[10]); + e.lootdrop_id = static_cast(strtoul(row[0], nullptr, 10)); + e.item_id = static_cast(atoi(row[1])); + e.item_charges = static_cast(strtoul(row[2], nullptr, 10)); + e.equip_item = static_cast(strtoul(row[3], nullptr, 10)); + e.chance = strtof(row[4], nullptr); + e.disabled_chance = strtof(row[5], nullptr); + e.trivial_min_level = static_cast(strtoul(row[6], nullptr, 10)); + e.trivial_max_level = static_cast(strtoul(row[7], nullptr, 10)); + e.multiplier = static_cast(strtoul(row[8], nullptr, 10)); + e.npc_min_level = static_cast(strtoul(row[9], nullptr, 10)); + e.npc_max_level = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -347,27 +347,27 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LootdropEntries entry{}; + LootdropEntries e{}; - entry.lootdrop_id = atoi(row[0]); - entry.item_id = atoi(row[1]); - entry.item_charges = atoi(row[2]); - entry.equip_item = atoi(row[3]); - entry.chance = static_cast(atof(row[4])); - entry.disabled_chance = static_cast(atof(row[5])); - entry.trivial_min_level = atoi(row[6]); - entry.trivial_max_level = atoi(row[7]); - entry.multiplier = atoi(row[8]); - entry.npc_min_level = atoi(row[9]); - entry.npc_max_level = atoi(row[10]); + e.lootdrop_id = static_cast(strtoul(row[0], nullptr, 10)); + e.item_id = static_cast(atoi(row[1])); + e.item_charges = static_cast(strtoul(row[2], nullptr, 10)); + e.equip_item = static_cast(strtoul(row[3], nullptr, 10)); + e.chance = strtof(row[4], nullptr); + e.disabled_chance = strtof(row[5], nullptr); + e.trivial_min_level = static_cast(strtoul(row[6], nullptr, 10)); + e.trivial_max_level = static_cast(strtoul(row[7], nullptr, 10)); + e.multiplier = static_cast(strtoul(row[8], nullptr, 10)); + e.npc_min_level = static_cast(strtoul(row[9], nullptr, 10)); + e.npc_max_level = static_cast(strtoul(row[10], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -392,6 +392,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOOTDROP_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_lootdrop_repository.h b/common/repositories/base/base_lootdrop_repository.h index aad7b5eef..6361dd6bf 100644 --- a/common/repositories/base/base_lootdrop_repository.h +++ b/common/repositories/base/base_lootdrop_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_LOOTDROP_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLootdropRepository { public: struct Lootdrop { - int id; + uint32_t id; std::string name; - int min_expansion; - int max_expansion; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static Lootdrop NewEntity() { - Lootdrop entry{}; + Lootdrop e{}; - entry.id = 0; - entry.name = ""; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.name = ""; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Lootdrop GetLootdropEntry( + static Lootdrop GetLootdrop( const std::vector &lootdrops, int lootdrop_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Lootdrop entry{}; + Lootdrop e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.min_expansion = atoi(row[2]); - entry.max_expansion = atoi(row[3]); - entry.content_flags = row[4] ? row[4] : ""; - entry.content_flags_disabled = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.min_expansion = static_cast(atoi(row[2])); + e.max_expansion = static_cast(atoi(row[3])); + e.content_flags = row[4] ? row[4] : ""; + e.content_flags_disabled = row[5] ? row[5] : ""; - return entry; + return e; } return NewEntity(); @@ -166,26 +166,26 @@ public: static int UpdateOne( Database& db, - Lootdrop lootdrop_entry + const Lootdrop &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(lootdrop_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(lootdrop_entry.min_expansion)); - update_values.push_back(columns[3] + " = " + std::to_string(lootdrop_entry.max_expansion)); - update_values.push_back(columns[4] + " = '" + EscapeString(lootdrop_entry.content_flags) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(lootdrop_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[3] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - lootdrop_entry.id + e.id ) ); @@ -194,63 +194,63 @@ public: static Lootdrop InsertOne( Database& db, - Lootdrop lootdrop_entry + Lootdrop e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(lootdrop_entry.id)); - insert_values.push_back("'" + EscapeString(lootdrop_entry.name) + "'"); - insert_values.push_back(std::to_string(lootdrop_entry.min_expansion)); - insert_values.push_back(std::to_string(lootdrop_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(lootdrop_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(lootdrop_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - lootdrop_entry.id = results.LastInsertedID(); - return lootdrop_entry; + e.id = results.LastInsertedID(); + return e; } - lootdrop_entry = NewEntity(); + e = NewEntity(); - return lootdrop_entry; + return e; } static int InsertMany( Database& db, - std::vector lootdrop_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &lootdrop_entry: lootdrop_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(lootdrop_entry.id)); - insert_values.push_back("'" + EscapeString(lootdrop_entry.name) + "'"); - insert_values.push_back(std::to_string(lootdrop_entry.min_expansion)); - insert_values.push_back(std::to_string(lootdrop_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(lootdrop_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(lootdrop_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -271,22 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Lootdrop entry{}; + Lootdrop e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.min_expansion = atoi(row[2]); - entry.max_expansion = atoi(row[3]); - entry.content_flags = row[4] ? row[4] : ""; - entry.content_flags_disabled = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.min_expansion = static_cast(atoi(row[2])); + e.max_expansion = static_cast(atoi(row[3])); + e.content_flags = row[4] ? row[4] : ""; + e.content_flags_disabled = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -301,22 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Lootdrop entry{}; + Lootdrop e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.min_expansion = atoi(row[2]); - entry.max_expansion = atoi(row[3]); - entry.content_flags = row[4] ? row[4] : ""; - entry.content_flags_disabled = row[5] ? row[5] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.min_expansion = static_cast(atoi(row[2])); + e.max_expansion = static_cast(atoi(row[3])); + e.content_flags = row[4] ? row[4] : ""; + e.content_flags_disabled = row[5] ? row[5] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -341,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOOTDROP_REPOSITORY_H diff --git a/common/repositories/base/base_loottable_entries_repository.h b/common/repositories/base/base_loottable_entries_repository.h index 371fa6f00..f36d8026a 100644 --- a/common/repositories/base/base_loottable_entries_repository.h +++ b/common/repositories/base/base_loottable_entries_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_LOOTTABLE_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLoottableEntriesRepository { public: struct LoottableEntries { - int loottable_id; - int lootdrop_id; - int multiplier; - int droplimit; - int mindrop; - float probability; + uint32_t loottable_id; + uint32_t lootdrop_id; + uint8_t multiplier; + uint8_t droplimit; + uint8_t mindrop; + float probability; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static LoottableEntries NewEntity() { - LoottableEntries entry{}; + LoottableEntries e{}; - entry.loottable_id = 0; - entry.lootdrop_id = 0; - entry.multiplier = 1; - entry.droplimit = 0; - entry.mindrop = 0; - entry.probability = 100; + e.loottable_id = 0; + e.lootdrop_id = 0; + e.multiplier = 1; + e.droplimit = 0; + e.mindrop = 0; + e.probability = 100; - return entry; + return e; } - static LoottableEntries GetLoottableEntriesEntry( + static LoottableEntries GetLoottableEntries( const std::vector &loottable_entriess, int loottable_entries_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - LoottableEntries entry{}; + LoottableEntries e{}; - entry.loottable_id = atoi(row[0]); - entry.lootdrop_id = atoi(row[1]); - entry.multiplier = atoi(row[2]); - entry.droplimit = atoi(row[3]); - entry.mindrop = atoi(row[4]); - entry.probability = static_cast(atof(row[5])); + e.loottable_id = static_cast(strtoul(row[0], nullptr, 10)); + e.lootdrop_id = static_cast(strtoul(row[1], nullptr, 10)); + e.multiplier = static_cast(strtoul(row[2], nullptr, 10)); + e.droplimit = static_cast(strtoul(row[3], nullptr, 10)); + e.mindrop = static_cast(strtoul(row[4], nullptr, 10)); + e.probability = strtof(row[5], nullptr); - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - LoottableEntries loottable_entries_entry + const LoottableEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(loottable_entries_entry.loottable_id)); - update_values.push_back(columns[1] + " = " + std::to_string(loottable_entries_entry.lootdrop_id)); - update_values.push_back(columns[2] + " = " + std::to_string(loottable_entries_entry.multiplier)); - update_values.push_back(columns[3] + " = " + std::to_string(loottable_entries_entry.droplimit)); - update_values.push_back(columns[4] + " = " + std::to_string(loottable_entries_entry.mindrop)); - update_values.push_back(columns[5] + " = " + std::to_string(loottable_entries_entry.probability)); + v.push_back(columns[0] + " = " + std::to_string(e.loottable_id)); + v.push_back(columns[1] + " = " + std::to_string(e.lootdrop_id)); + v.push_back(columns[2] + " = " + std::to_string(e.multiplier)); + v.push_back(columns[3] + " = " + std::to_string(e.droplimit)); + v.push_back(columns[4] + " = " + std::to_string(e.mindrop)); + v.push_back(columns[5] + " = " + std::to_string(e.probability)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - loottable_entries_entry.loottable_id + e.loottable_id ) ); @@ -195,63 +195,63 @@ public: static LoottableEntries InsertOne( Database& db, - LoottableEntries loottable_entries_entry + LoottableEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(loottable_entries_entry.loottable_id)); - insert_values.push_back(std::to_string(loottable_entries_entry.lootdrop_id)); - insert_values.push_back(std::to_string(loottable_entries_entry.multiplier)); - insert_values.push_back(std::to_string(loottable_entries_entry.droplimit)); - insert_values.push_back(std::to_string(loottable_entries_entry.mindrop)); - insert_values.push_back(std::to_string(loottable_entries_entry.probability)); + v.push_back(std::to_string(e.loottable_id)); + v.push_back(std::to_string(e.lootdrop_id)); + v.push_back(std::to_string(e.multiplier)); + v.push_back(std::to_string(e.droplimit)); + v.push_back(std::to_string(e.mindrop)); + v.push_back(std::to_string(e.probability)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - loottable_entries_entry.loottable_id = results.LastInsertedID(); - return loottable_entries_entry; + e.loottable_id = results.LastInsertedID(); + return e; } - loottable_entries_entry = NewEntity(); + e = NewEntity(); - return loottable_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector loottable_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &loottable_entries_entry: loottable_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(loottable_entries_entry.loottable_id)); - insert_values.push_back(std::to_string(loottable_entries_entry.lootdrop_id)); - insert_values.push_back(std::to_string(loottable_entries_entry.multiplier)); - insert_values.push_back(std::to_string(loottable_entries_entry.droplimit)); - insert_values.push_back(std::to_string(loottable_entries_entry.mindrop)); - insert_values.push_back(std::to_string(loottable_entries_entry.probability)); + v.push_back(std::to_string(e.loottable_id)); + v.push_back(std::to_string(e.lootdrop_id)); + v.push_back(std::to_string(e.multiplier)); + v.push_back(std::to_string(e.droplimit)); + v.push_back(std::to_string(e.mindrop)); + v.push_back(std::to_string(e.probability)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoottableEntries entry{}; + LoottableEntries e{}; - entry.loottable_id = atoi(row[0]); - entry.lootdrop_id = atoi(row[1]); - entry.multiplier = atoi(row[2]); - entry.droplimit = atoi(row[3]); - entry.mindrop = atoi(row[4]); - entry.probability = static_cast(atof(row[5])); + e.loottable_id = static_cast(strtoul(row[0], nullptr, 10)); + e.lootdrop_id = static_cast(strtoul(row[1], nullptr, 10)); + e.multiplier = static_cast(strtoul(row[2], nullptr, 10)); + e.droplimit = static_cast(strtoul(row[3], nullptr, 10)); + e.mindrop = static_cast(strtoul(row[4], nullptr, 10)); + e.probability = strtof(row[5], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - LoottableEntries entry{}; + LoottableEntries e{}; - entry.loottable_id = atoi(row[0]); - entry.lootdrop_id = atoi(row[1]); - entry.multiplier = atoi(row[2]); - entry.droplimit = atoi(row[3]); - entry.mindrop = atoi(row[4]); - entry.probability = static_cast(atof(row[5])); + e.loottable_id = static_cast(strtoul(row[0], nullptr, 10)); + e.lootdrop_id = static_cast(strtoul(row[1], nullptr, 10)); + e.multiplier = static_cast(strtoul(row[2], nullptr, 10)); + e.droplimit = static_cast(strtoul(row[3], nullptr, 10)); + e.mindrop = static_cast(strtoul(row[4], nullptr, 10)); + e.probability = strtof(row[5], nullptr); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOOTTABLE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_loottable_repository.h b/common/repositories/base/base_loottable_repository.h index 420b666b3..44d5156f0 100644 --- a/common/repositories/base/base_loottable_repository.h +++ b/common/repositories/base/base_loottable_repository.h @@ -13,20 +13,20 @@ #define EQEMU_BASE_LOOTTABLE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseLoottableRepository { public: struct Loottable { - int id; + uint32_t id; std::string name; - int mincash; - int maxcash; - int avgcoin; - int done; - int min_expansion; - int max_expansion; + uint32_t mincash; + uint32_t maxcash; + uint32_t avgcoin; + int8_t done; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -70,12 +70,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -103,23 +103,23 @@ public: static Loottable NewEntity() { - Loottable entry{}; + Loottable e{}; - entry.id = 0; - entry.name = ""; - entry.mincash = 0; - entry.maxcash = 0; - entry.avgcoin = 0; - entry.done = 0; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.name = ""; + e.mincash = 0; + e.maxcash = 0; + e.avgcoin = 0; + e.done = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Loottable GetLoottableEntry( + static Loottable GetLoottable( const std::vector &loottables, int loottable_id ) @@ -148,20 +148,20 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Loottable entry{}; + Loottable e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.mincash = atoi(row[2]); - entry.maxcash = atoi(row[3]); - entry.avgcoin = atoi(row[4]); - entry.done = atoi(row[5]); - entry.min_expansion = atoi(row[6]); - entry.max_expansion = atoi(row[7]); - entry.content_flags = row[8] ? row[8] : ""; - entry.content_flags_disabled = row[9] ? row[9] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.mincash = static_cast(strtoul(row[2], nullptr, 10)); + e.maxcash = static_cast(strtoul(row[3], nullptr, 10)); + e.avgcoin = static_cast(strtoul(row[4], nullptr, 10)); + e.done = static_cast(atoi(row[5])); + e.min_expansion = static_cast(atoi(row[6])); + e.max_expansion = static_cast(atoi(row[7])); + e.content_flags = row[8] ? row[8] : ""; + e.content_flags_disabled = row[9] ? row[9] : ""; - return entry; + return e; } return NewEntity(); @@ -186,30 +186,30 @@ public: static int UpdateOne( Database& db, - Loottable loottable_entry + const Loottable &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(loottable_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(loottable_entry.mincash)); - update_values.push_back(columns[3] + " = " + std::to_string(loottable_entry.maxcash)); - update_values.push_back(columns[4] + " = " + std::to_string(loottable_entry.avgcoin)); - update_values.push_back(columns[5] + " = " + std::to_string(loottable_entry.done)); - update_values.push_back(columns[6] + " = " + std::to_string(loottable_entry.min_expansion)); - update_values.push_back(columns[7] + " = " + std::to_string(loottable_entry.max_expansion)); - update_values.push_back(columns[8] + " = '" + EscapeString(loottable_entry.content_flags) + "'"); - update_values.push_back(columns[9] + " = '" + EscapeString(loottable_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.mincash)); + v.push_back(columns[3] + " = " + std::to_string(e.maxcash)); + v.push_back(columns[4] + " = " + std::to_string(e.avgcoin)); + v.push_back(columns[5] + " = " + std::to_string(e.done)); + v.push_back(columns[6] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[7] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - loottable_entry.id + e.id ) ); @@ -218,71 +218,71 @@ public: static Loottable InsertOne( Database& db, - Loottable loottable_entry + Loottable e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(loottable_entry.id)); - insert_values.push_back("'" + EscapeString(loottable_entry.name) + "'"); - insert_values.push_back(std::to_string(loottable_entry.mincash)); - insert_values.push_back(std::to_string(loottable_entry.maxcash)); - insert_values.push_back(std::to_string(loottable_entry.avgcoin)); - insert_values.push_back(std::to_string(loottable_entry.done)); - insert_values.push_back(std::to_string(loottable_entry.min_expansion)); - insert_values.push_back(std::to_string(loottable_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(loottable_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(loottable_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.mincash)); + v.push_back(std::to_string(e.maxcash)); + v.push_back(std::to_string(e.avgcoin)); + v.push_back(std::to_string(e.done)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - loottable_entry.id = results.LastInsertedID(); - return loottable_entry; + e.id = results.LastInsertedID(); + return e; } - loottable_entry = NewEntity(); + e = NewEntity(); - return loottable_entry; + return e; } static int InsertMany( Database& db, - std::vector loottable_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &loottable_entry: loottable_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(loottable_entry.id)); - insert_values.push_back("'" + EscapeString(loottable_entry.name) + "'"); - insert_values.push_back(std::to_string(loottable_entry.mincash)); - insert_values.push_back(std::to_string(loottable_entry.maxcash)); - insert_values.push_back(std::to_string(loottable_entry.avgcoin)); - insert_values.push_back(std::to_string(loottable_entry.done)); - insert_values.push_back(std::to_string(loottable_entry.min_expansion)); - insert_values.push_back(std::to_string(loottable_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(loottable_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(loottable_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.mincash)); + v.push_back(std::to_string(e.maxcash)); + v.push_back(std::to_string(e.avgcoin)); + v.push_back(std::to_string(e.done)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -303,26 +303,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Loottable entry{}; + Loottable e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.mincash = atoi(row[2]); - entry.maxcash = atoi(row[3]); - entry.avgcoin = atoi(row[4]); - entry.done = atoi(row[5]); - entry.min_expansion = atoi(row[6]); - entry.max_expansion = atoi(row[7]); - entry.content_flags = row[8] ? row[8] : ""; - entry.content_flags_disabled = row[9] ? row[9] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.mincash = static_cast(strtoul(row[2], nullptr, 10)); + e.maxcash = static_cast(strtoul(row[3], nullptr, 10)); + e.avgcoin = static_cast(strtoul(row[4], nullptr, 10)); + e.done = static_cast(atoi(row[5])); + e.min_expansion = static_cast(atoi(row[6])); + e.max_expansion = static_cast(atoi(row[7])); + e.content_flags = row[8] ? row[8] : ""; + e.content_flags_disabled = row[9] ? row[9] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -337,26 +337,26 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Loottable entry{}; + Loottable e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.mincash = atoi(row[2]); - entry.maxcash = atoi(row[3]); - entry.avgcoin = atoi(row[4]); - entry.done = atoi(row[5]); - entry.min_expansion = atoi(row[6]); - entry.max_expansion = atoi(row[7]); - entry.content_flags = row[8] ? row[8] : ""; - entry.content_flags_disabled = row[9] ? row[9] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.mincash = static_cast(strtoul(row[2], nullptr, 10)); + e.maxcash = static_cast(strtoul(row[3], nullptr, 10)); + e.avgcoin = static_cast(strtoul(row[4], nullptr, 10)); + e.done = static_cast(atoi(row[5])); + e.min_expansion = static_cast(atoi(row[6])); + e.max_expansion = static_cast(atoi(row[7])); + e.content_flags = row[8] ? row[8] : ""; + e.content_flags_disabled = row[9] ? row[9] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -381,6 +381,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_LOOTTABLE_REPOSITORY_H diff --git a/common/repositories/base/base_mail_repository.h b/common/repositories/base/base_mail_repository.h index 7b4da2cd7..11fcbce8d 100644 --- a/common/repositories/base/base_mail_repository.h +++ b/common/repositories/base/base_mail_repository.h @@ -13,20 +13,20 @@ #define EQEMU_BASE_MAIL_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseMailRepository { public: struct Mail { - int msgid; - int charid; - int timestamp; + uint32_t msgid; + uint32_t charid; + int32_t timestamp; std::string from; std::string subject; std::string body; std::string to; - int status; + int8_t status; }; static std::string PrimaryKey() @@ -64,12 +64,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -97,21 +97,21 @@ public: static Mail NewEntity() { - Mail entry{}; + Mail e{}; - entry.msgid = 0; - entry.charid = 0; - entry.timestamp = 0; - entry.from = ""; - entry.subject = ""; - entry.body = ""; - entry.to = ""; - entry.status = 0; + e.msgid = 0; + e.charid = 0; + e.timestamp = 0; + e.from = ""; + e.subject = ""; + e.body = ""; + e.to = ""; + e.status = 0; - return entry; + return e; } - static Mail GetMailEntry( + static Mail GetMail( const std::vector &mails, int mail_id ) @@ -140,18 +140,18 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Mail entry{}; + Mail e{}; - entry.msgid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.timestamp = atoi(row[2]); - entry.from = row[3] ? row[3] : ""; - entry.subject = row[4] ? row[4] : ""; - entry.body = row[5] ? row[5] : ""; - entry.to = row[6] ? row[6] : ""; - entry.status = atoi(row[7]); + e.msgid = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.timestamp = static_cast(atoi(row[2])); + e.from = row[3] ? row[3] : ""; + e.subject = row[4] ? row[4] : ""; + e.body = row[5] ? row[5] : ""; + e.to = row[6] ? row[6] : ""; + e.status = static_cast(atoi(row[7])); - return entry; + return e; } return NewEntity(); @@ -176,28 +176,28 @@ public: static int UpdateOne( Database& db, - Mail mail_entry + const Mail &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(mail_entry.charid)); - update_values.push_back(columns[2] + " = " + std::to_string(mail_entry.timestamp)); - update_values.push_back(columns[3] + " = '" + EscapeString(mail_entry.from) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(mail_entry.subject) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(mail_entry.body) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(mail_entry.to) + "'"); - update_values.push_back(columns[7] + " = " + std::to_string(mail_entry.status)); + v.push_back(columns[1] + " = " + std::to_string(e.charid)); + v.push_back(columns[2] + " = " + std::to_string(e.timestamp)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.from) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.subject) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.body) + "'"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.to) + "'"); + v.push_back(columns[7] + " = " + std::to_string(e.status)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - mail_entry.msgid + e.msgid ) ); @@ -206,67 +206,67 @@ public: static Mail InsertOne( Database& db, - Mail mail_entry + Mail e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(mail_entry.msgid)); - insert_values.push_back(std::to_string(mail_entry.charid)); - insert_values.push_back(std::to_string(mail_entry.timestamp)); - insert_values.push_back("'" + EscapeString(mail_entry.from) + "'"); - insert_values.push_back("'" + EscapeString(mail_entry.subject) + "'"); - insert_values.push_back("'" + EscapeString(mail_entry.body) + "'"); - insert_values.push_back("'" + EscapeString(mail_entry.to) + "'"); - insert_values.push_back(std::to_string(mail_entry.status)); + v.push_back(std::to_string(e.msgid)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.timestamp)); + v.push_back("'" + Strings::Escape(e.from) + "'"); + v.push_back("'" + Strings::Escape(e.subject) + "'"); + v.push_back("'" + Strings::Escape(e.body) + "'"); + v.push_back("'" + Strings::Escape(e.to) + "'"); + v.push_back(std::to_string(e.status)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - mail_entry.msgid = results.LastInsertedID(); - return mail_entry; + e.msgid = results.LastInsertedID(); + return e; } - mail_entry = NewEntity(); + e = NewEntity(); - return mail_entry; + return e; } static int InsertMany( Database& db, - std::vector mail_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &mail_entry: mail_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(mail_entry.msgid)); - insert_values.push_back(std::to_string(mail_entry.charid)); - insert_values.push_back(std::to_string(mail_entry.timestamp)); - insert_values.push_back("'" + EscapeString(mail_entry.from) + "'"); - insert_values.push_back("'" + EscapeString(mail_entry.subject) + "'"); - insert_values.push_back("'" + EscapeString(mail_entry.body) + "'"); - insert_values.push_back("'" + EscapeString(mail_entry.to) + "'"); - insert_values.push_back(std::to_string(mail_entry.status)); + v.push_back(std::to_string(e.msgid)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.timestamp)); + v.push_back("'" + Strings::Escape(e.from) + "'"); + v.push_back("'" + Strings::Escape(e.subject) + "'"); + v.push_back("'" + Strings::Escape(e.body) + "'"); + v.push_back("'" + Strings::Escape(e.to) + "'"); + v.push_back(std::to_string(e.status)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -287,24 +287,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Mail entry{}; + Mail e{}; - entry.msgid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.timestamp = atoi(row[2]); - entry.from = row[3] ? row[3] : ""; - entry.subject = row[4] ? row[4] : ""; - entry.body = row[5] ? row[5] : ""; - entry.to = row[6] ? row[6] : ""; - entry.status = atoi(row[7]); + e.msgid = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.timestamp = static_cast(atoi(row[2])); + e.from = row[3] ? row[3] : ""; + e.subject = row[4] ? row[4] : ""; + e.body = row[5] ? row[5] : ""; + e.to = row[6] ? row[6] : ""; + e.status = static_cast(atoi(row[7])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -319,24 +319,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Mail entry{}; + Mail e{}; - entry.msgid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.timestamp = atoi(row[2]); - entry.from = row[3] ? row[3] : ""; - entry.subject = row[4] ? row[4] : ""; - entry.body = row[5] ? row[5] : ""; - entry.to = row[6] ? row[6] : ""; - entry.status = atoi(row[7]); + e.msgid = static_cast(strtoul(row[0], nullptr, 10)); + e.charid = static_cast(strtoul(row[1], nullptr, 10)); + e.timestamp = static_cast(atoi(row[2])); + e.from = row[3] ? row[3] : ""; + e.subject = row[4] ? row[4] : ""; + e.body = row[5] ? row[5] : ""; + e.to = row[6] ? row[6] : ""; + e.status = static_cast(atoi(row[7])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -361,6 +361,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_MAIL_REPOSITORY_H diff --git a/common/repositories/base/base_merc_armorinfo_repository.h b/common/repositories/base/base_merc_armorinfo_repository.h new file mode 100644 index 000000000..99e57ae08 --- /dev/null +++ b/common/repositories/base/base_merc_armorinfo_repository.h @@ -0,0 +1,414 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H +#define EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercArmorinfoRepository { +public: + struct MercArmorinfo { + int32_t id; + uint32_t merc_npc_type_id; + uint8_t minlevel; + uint8_t maxlevel; + uint8_t texture; + uint8_t helmtexture; + uint32_t armortint_id; + uint8_t armortint_red; + uint8_t armortint_green; + uint8_t armortint_blue; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "merc_npc_type_id", + "minlevel", + "maxlevel", + "texture", + "helmtexture", + "armortint_id", + "armortint_red", + "armortint_green", + "armortint_blue", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "merc_npc_type_id", + "minlevel", + "maxlevel", + "texture", + "helmtexture", + "armortint_id", + "armortint_red", + "armortint_green", + "armortint_blue", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_armorinfo"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercArmorinfo NewEntity() + { + MercArmorinfo e{}; + + e.id = 0; + e.merc_npc_type_id = 0; + e.minlevel = 1; + e.maxlevel = 255; + e.texture = 0; + e.helmtexture = 0; + e.armortint_id = 0; + e.armortint_red = 0; + e.armortint_green = 0; + e.armortint_blue = 0; + + return e; + } + + static MercArmorinfo GetMercArmorinfo( + const std::vector &merc_armorinfos, + int merc_armorinfo_id + ) + { + for (auto &merc_armorinfo : merc_armorinfos) { + if (merc_armorinfo.id == merc_armorinfo_id) { + return merc_armorinfo; + } + } + + return NewEntity(); + } + + static MercArmorinfo FindOne( + Database& db, + int merc_armorinfo_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_armorinfo_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercArmorinfo e{}; + + e.id = static_cast(atoi(row[0])); + e.merc_npc_type_id = static_cast(strtoul(row[1], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[2], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.texture = static_cast(strtoul(row[4], nullptr, 10)); + e.helmtexture = static_cast(strtoul(row[5], nullptr, 10)); + e.armortint_id = static_cast(strtoul(row[6], nullptr, 10)); + e.armortint_red = static_cast(strtoul(row[7], nullptr, 10)); + e.armortint_green = static_cast(strtoul(row[8], nullptr, 10)); + e.armortint_blue = static_cast(strtoul(row[9], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_armorinfo_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_armorinfo_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercArmorinfo &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.merc_npc_type_id)); + v.push_back(columns[2] + " = " + std::to_string(e.minlevel)); + v.push_back(columns[3] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[4] + " = " + std::to_string(e.texture)); + v.push_back(columns[5] + " = " + std::to_string(e.helmtexture)); + v.push_back(columns[6] + " = " + std::to_string(e.armortint_id)); + v.push_back(columns[7] + " = " + std::to_string(e.armortint_red)); + v.push_back(columns[8] + " = " + std::to_string(e.armortint_green)); + v.push_back(columns[9] + " = " + std::to_string(e.armortint_blue)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercArmorinfo InsertOne( + Database& db, + MercArmorinfo e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helmtexture)); + v.push_back(std::to_string(e.armortint_id)); + v.push_back(std::to_string(e.armortint_red)); + v.push_back(std::to_string(e.armortint_green)); + v.push_back(std::to_string(e.armortint_blue)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helmtexture)); + v.push_back(std::to_string(e.armortint_id)); + v.push_back(std::to_string(e.armortint_red)); + v.push_back(std::to_string(e.armortint_green)); + v.push_back(std::to_string(e.armortint_blue)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercArmorinfo e{}; + + e.id = static_cast(atoi(row[0])); + e.merc_npc_type_id = static_cast(strtoul(row[1], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[2], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.texture = static_cast(strtoul(row[4], nullptr, 10)); + e.helmtexture = static_cast(strtoul(row[5], nullptr, 10)); + e.armortint_id = static_cast(strtoul(row[6], nullptr, 10)); + e.armortint_red = static_cast(strtoul(row[7], nullptr, 10)); + e.armortint_green = static_cast(strtoul(row[8], nullptr, 10)); + e.armortint_blue = static_cast(strtoul(row[9], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercArmorinfo e{}; + + e.id = static_cast(atoi(row[0])); + e.merc_npc_type_id = static_cast(strtoul(row[1], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[2], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.texture = static_cast(strtoul(row[4], nullptr, 10)); + e.helmtexture = static_cast(strtoul(row[5], nullptr, 10)); + e.armortint_id = static_cast(strtoul(row[6], nullptr, 10)); + e.armortint_red = static_cast(strtoul(row[7], nullptr, 10)); + e.armortint_green = static_cast(strtoul(row[8], nullptr, 10)); + e.armortint_blue = static_cast(strtoul(row[9], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H diff --git a/common/repositories/base/base_merc_buffs_repository.h b/common/repositories/base/base_merc_buffs_repository.h new file mode 100644 index 000000000..c210178cf --- /dev/null +++ b/common/repositories/base/base_merc_buffs_repository.h @@ -0,0 +1,504 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_BUFFS_REPOSITORY_H +#define EQEMU_BASE_MERC_BUFFS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercBuffsRepository { +public: + struct MercBuffs { + uint32_t MercBuffId; + uint32_t MercId; + uint32_t SpellId; + uint32_t CasterLevel; + uint32_t DurationFormula; + int32_t TicsRemaining; + uint32_t PoisonCounters; + uint32_t DiseaseCounters; + uint32_t CurseCounters; + uint32_t CorruptionCounters; + uint32_t HitCount; + uint32_t MeleeRune; + uint32_t MagicRune; + int32_t dot_rune; + int32_t caston_x; + int8_t Persistent; + int32_t caston_y; + int32_t caston_z; + int32_t ExtraDIChance; + }; + + static std::string PrimaryKey() + { + return std::string("MercBuffId"); + } + + static std::vector Columns() + { + return { + "MercBuffId", + "MercId", + "SpellId", + "CasterLevel", + "DurationFormula", + "TicsRemaining", + "PoisonCounters", + "DiseaseCounters", + "CurseCounters", + "CorruptionCounters", + "HitCount", + "MeleeRune", + "MagicRune", + "dot_rune", + "caston_x", + "Persistent", + "caston_y", + "caston_z", + "ExtraDIChance", + }; + } + + static std::vector SelectColumns() + { + return { + "MercBuffId", + "MercId", + "SpellId", + "CasterLevel", + "DurationFormula", + "TicsRemaining", + "PoisonCounters", + "DiseaseCounters", + "CurseCounters", + "CorruptionCounters", + "HitCount", + "MeleeRune", + "MagicRune", + "dot_rune", + "caston_x", + "Persistent", + "caston_y", + "caston_z", + "ExtraDIChance", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_buffs"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercBuffs NewEntity() + { + MercBuffs e{}; + + e.MercBuffId = 0; + e.MercId = 0; + e.SpellId = 0; + e.CasterLevel = 0; + e.DurationFormula = 0; + e.TicsRemaining = 0; + e.PoisonCounters = 0; + e.DiseaseCounters = 0; + e.CurseCounters = 0; + e.CorruptionCounters = 0; + e.HitCount = 0; + e.MeleeRune = 0; + e.MagicRune = 0; + e.dot_rune = 0; + e.caston_x = 0; + e.Persistent = 0; + e.caston_y = 0; + e.caston_z = 0; + e.ExtraDIChance = 0; + + return e; + } + + static MercBuffs GetMercBuffs( + const std::vector &merc_buffss, + int merc_buffs_id + ) + { + for (auto &merc_buffs : merc_buffss) { + if (merc_buffs.MercBuffId == merc_buffs_id) { + return merc_buffs; + } + } + + return NewEntity(); + } + + static MercBuffs FindOne( + Database& db, + int merc_buffs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_buffs_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercBuffs e{}; + + e.MercBuffId = static_cast(strtoul(row[0], nullptr, 10)); + e.MercId = static_cast(strtoul(row[1], nullptr, 10)); + e.SpellId = static_cast(strtoul(row[2], nullptr, 10)); + e.CasterLevel = static_cast(strtoul(row[3], nullptr, 10)); + e.DurationFormula = static_cast(strtoul(row[4], nullptr, 10)); + e.TicsRemaining = static_cast(atoi(row[5])); + e.PoisonCounters = static_cast(strtoul(row[6], nullptr, 10)); + e.DiseaseCounters = static_cast(strtoul(row[7], nullptr, 10)); + e.CurseCounters = static_cast(strtoul(row[8], nullptr, 10)); + e.CorruptionCounters = static_cast(strtoul(row[9], nullptr, 10)); + e.HitCount = static_cast(strtoul(row[10], nullptr, 10)); + e.MeleeRune = static_cast(strtoul(row[11], nullptr, 10)); + e.MagicRune = static_cast(strtoul(row[12], nullptr, 10)); + e.dot_rune = static_cast(atoi(row[13])); + e.caston_x = static_cast(atoi(row[14])); + e.Persistent = static_cast(atoi(row[15])); + e.caston_y = static_cast(atoi(row[16])); + e.caston_z = static_cast(atoi(row[17])); + e.ExtraDIChance = static_cast(atoi(row[18])); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_buffs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_buffs_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercBuffs &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.MercId)); + v.push_back(columns[2] + " = " + std::to_string(e.SpellId)); + v.push_back(columns[3] + " = " + std::to_string(e.CasterLevel)); + v.push_back(columns[4] + " = " + std::to_string(e.DurationFormula)); + v.push_back(columns[5] + " = " + std::to_string(e.TicsRemaining)); + v.push_back(columns[6] + " = " + std::to_string(e.PoisonCounters)); + v.push_back(columns[7] + " = " + std::to_string(e.DiseaseCounters)); + v.push_back(columns[8] + " = " + std::to_string(e.CurseCounters)); + v.push_back(columns[9] + " = " + std::to_string(e.CorruptionCounters)); + v.push_back(columns[10] + " = " + std::to_string(e.HitCount)); + v.push_back(columns[11] + " = " + std::to_string(e.MeleeRune)); + v.push_back(columns[12] + " = " + std::to_string(e.MagicRune)); + v.push_back(columns[13] + " = " + std::to_string(e.dot_rune)); + v.push_back(columns[14] + " = " + std::to_string(e.caston_x)); + v.push_back(columns[15] + " = " + std::to_string(e.Persistent)); + v.push_back(columns[16] + " = " + std::to_string(e.caston_y)); + v.push_back(columns[17] + " = " + std::to_string(e.caston_z)); + v.push_back(columns[18] + " = " + std::to_string(e.ExtraDIChance)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.MercBuffId + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercBuffs InsertOne( + Database& db, + MercBuffs e + ) + { + std::vector v; + + v.push_back(std::to_string(e.MercBuffId)); + v.push_back(std::to_string(e.MercId)); + v.push_back(std::to_string(e.SpellId)); + v.push_back(std::to_string(e.CasterLevel)); + v.push_back(std::to_string(e.DurationFormula)); + v.push_back(std::to_string(e.TicsRemaining)); + v.push_back(std::to_string(e.PoisonCounters)); + v.push_back(std::to_string(e.DiseaseCounters)); + v.push_back(std::to_string(e.CurseCounters)); + v.push_back(std::to_string(e.CorruptionCounters)); + v.push_back(std::to_string(e.HitCount)); + v.push_back(std::to_string(e.MeleeRune)); + v.push_back(std::to_string(e.MagicRune)); + v.push_back(std::to_string(e.dot_rune)); + v.push_back(std::to_string(e.caston_x)); + v.push_back(std::to_string(e.Persistent)); + v.push_back(std::to_string(e.caston_y)); + v.push_back(std::to_string(e.caston_z)); + v.push_back(std::to_string(e.ExtraDIChance)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.MercBuffId = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.MercBuffId)); + v.push_back(std::to_string(e.MercId)); + v.push_back(std::to_string(e.SpellId)); + v.push_back(std::to_string(e.CasterLevel)); + v.push_back(std::to_string(e.DurationFormula)); + v.push_back(std::to_string(e.TicsRemaining)); + v.push_back(std::to_string(e.PoisonCounters)); + v.push_back(std::to_string(e.DiseaseCounters)); + v.push_back(std::to_string(e.CurseCounters)); + v.push_back(std::to_string(e.CorruptionCounters)); + v.push_back(std::to_string(e.HitCount)); + v.push_back(std::to_string(e.MeleeRune)); + v.push_back(std::to_string(e.MagicRune)); + v.push_back(std::to_string(e.dot_rune)); + v.push_back(std::to_string(e.caston_x)); + v.push_back(std::to_string(e.Persistent)); + v.push_back(std::to_string(e.caston_y)); + v.push_back(std::to_string(e.caston_z)); + v.push_back(std::to_string(e.ExtraDIChance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercBuffs e{}; + + e.MercBuffId = static_cast(strtoul(row[0], nullptr, 10)); + e.MercId = static_cast(strtoul(row[1], nullptr, 10)); + e.SpellId = static_cast(strtoul(row[2], nullptr, 10)); + e.CasterLevel = static_cast(strtoul(row[3], nullptr, 10)); + e.DurationFormula = static_cast(strtoul(row[4], nullptr, 10)); + e.TicsRemaining = static_cast(atoi(row[5])); + e.PoisonCounters = static_cast(strtoul(row[6], nullptr, 10)); + e.DiseaseCounters = static_cast(strtoul(row[7], nullptr, 10)); + e.CurseCounters = static_cast(strtoul(row[8], nullptr, 10)); + e.CorruptionCounters = static_cast(strtoul(row[9], nullptr, 10)); + e.HitCount = static_cast(strtoul(row[10], nullptr, 10)); + e.MeleeRune = static_cast(strtoul(row[11], nullptr, 10)); + e.MagicRune = static_cast(strtoul(row[12], nullptr, 10)); + e.dot_rune = static_cast(atoi(row[13])); + e.caston_x = static_cast(atoi(row[14])); + e.Persistent = static_cast(atoi(row[15])); + e.caston_y = static_cast(atoi(row[16])); + e.caston_z = static_cast(atoi(row[17])); + e.ExtraDIChance = static_cast(atoi(row[18])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercBuffs e{}; + + e.MercBuffId = static_cast(strtoul(row[0], nullptr, 10)); + e.MercId = static_cast(strtoul(row[1], nullptr, 10)); + e.SpellId = static_cast(strtoul(row[2], nullptr, 10)); + e.CasterLevel = static_cast(strtoul(row[3], nullptr, 10)); + e.DurationFormula = static_cast(strtoul(row[4], nullptr, 10)); + e.TicsRemaining = static_cast(atoi(row[5])); + e.PoisonCounters = static_cast(strtoul(row[6], nullptr, 10)); + e.DiseaseCounters = static_cast(strtoul(row[7], nullptr, 10)); + e.CurseCounters = static_cast(strtoul(row[8], nullptr, 10)); + e.CorruptionCounters = static_cast(strtoul(row[9], nullptr, 10)); + e.HitCount = static_cast(strtoul(row[10], nullptr, 10)); + e.MeleeRune = static_cast(strtoul(row[11], nullptr, 10)); + e.MagicRune = static_cast(strtoul(row[12], nullptr, 10)); + e.dot_rune = static_cast(atoi(row[13])); + e.caston_x = static_cast(atoi(row[14])); + e.Persistent = static_cast(atoi(row[15])); + e.caston_y = static_cast(atoi(row[16])); + e.caston_z = static_cast(atoi(row[17])); + e.ExtraDIChance = static_cast(atoi(row[18])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_merc_inventory_repository.h b/common/repositories/base/base_merc_inventory_repository.h new file mode 100644 index 000000000..216d0c5d6 --- /dev/null +++ b/common/repositories/base/base_merc_inventory_repository.h @@ -0,0 +1,364 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_INVENTORY_REPOSITORY_H +#define EQEMU_BASE_MERC_INVENTORY_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercInventoryRepository { +public: + struct MercInventory { + uint32_t merc_inventory_id; + uint32_t merc_subtype_id; + uint32_t item_id; + uint32_t min_level; + uint32_t max_level; + }; + + static std::string PrimaryKey() + { + return std::string("merc_inventory_id"); + } + + static std::vector Columns() + { + return { + "merc_inventory_id", + "merc_subtype_id", + "item_id", + "min_level", + "max_level", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_inventory_id", + "merc_subtype_id", + "item_id", + "min_level", + "max_level", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_inventory"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercInventory NewEntity() + { + MercInventory e{}; + + e.merc_inventory_id = 0; + e.merc_subtype_id = 0; + e.item_id = 0; + e.min_level = 0; + e.max_level = 0; + + return e; + } + + static MercInventory GetMercInventory( + const std::vector &merc_inventorys, + int merc_inventory_id + ) + { + for (auto &merc_inventory : merc_inventorys) { + if (merc_inventory.merc_inventory_id == merc_inventory_id) { + return merc_inventory; + } + } + + return NewEntity(); + } + + static MercInventory FindOne( + Database& db, + int merc_inventory_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_inventory_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercInventory e{}; + + e.merc_inventory_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_subtype_id = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.min_level = static_cast(strtoul(row[3], nullptr, 10)); + e.max_level = static_cast(strtoul(row[4], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_inventory_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_inventory_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercInventory &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.merc_subtype_id)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + v.push_back(columns[3] + " = " + std::to_string(e.min_level)); + v.push_back(columns[4] + " = " + std::to_string(e.max_level)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_inventory_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercInventory InsertOne( + Database& db, + MercInventory e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_inventory_id)); + v.push_back(std::to_string(e.merc_subtype_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_inventory_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_inventory_id)); + v.push_back(std::to_string(e.merc_subtype_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercInventory e{}; + + e.merc_inventory_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_subtype_id = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.min_level = static_cast(strtoul(row[3], nullptr, 10)); + e.max_level = static_cast(strtoul(row[4], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercInventory e{}; + + e.merc_inventory_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_subtype_id = static_cast(strtoul(row[1], nullptr, 10)); + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.min_level = static_cast(strtoul(row[3], nullptr, 10)); + e.max_level = static_cast(strtoul(row[4], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_INVENTORY_REPOSITORY_H diff --git a/common/repositories/base/base_merc_merchant_entries_repository.h b/common/repositories/base/base_merc_merchant_entries_repository.h new file mode 100644 index 000000000..b6ba9ebcf --- /dev/null +++ b/common/repositories/base/base_merc_merchant_entries_repository.h @@ -0,0 +1,344 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_MERCHANT_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_MERC_MERCHANT_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercMerchantEntriesRepository { +public: + struct MercMerchantEntries { + uint32_t merc_merchant_entry_id; + uint32_t merc_merchant_template_id; + uint32_t merchant_id; + }; + + static std::string PrimaryKey() + { + return std::string("merc_merchant_entry_id"); + } + + static std::vector Columns() + { + return { + "merc_merchant_entry_id", + "merc_merchant_template_id", + "merchant_id", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_merchant_entry_id", + "merc_merchant_template_id", + "merchant_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_merchant_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercMerchantEntries NewEntity() + { + MercMerchantEntries e{}; + + e.merc_merchant_entry_id = 0; + e.merc_merchant_template_id = 0; + e.merchant_id = 0; + + return e; + } + + static MercMerchantEntries GetMercMerchantEntries( + const std::vector &merc_merchant_entriess, + int merc_merchant_entries_id + ) + { + for (auto &merc_merchant_entries : merc_merchant_entriess) { + if (merc_merchant_entries.merc_merchant_entry_id == merc_merchant_entries_id) { + return merc_merchant_entries; + } + } + + return NewEntity(); + } + + static MercMerchantEntries FindOne( + Database& db, + int merc_merchant_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_merchant_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercMerchantEntries e{}; + + e.merc_merchant_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_merchant_template_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merchant_id = static_cast(strtoul(row[2], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_merchant_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_merchant_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercMerchantEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.merc_merchant_template_id)); + v.push_back(columns[2] + " = " + std::to_string(e.merchant_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_merchant_entry_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercMerchantEntries InsertOne( + Database& db, + MercMerchantEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_merchant_entry_id)); + v.push_back(std::to_string(e.merc_merchant_template_id)); + v.push_back(std::to_string(e.merchant_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_merchant_entry_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_merchant_entry_id)); + v.push_back(std::to_string(e.merc_merchant_template_id)); + v.push_back(std::to_string(e.merchant_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercMerchantEntries e{}; + + e.merc_merchant_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_merchant_template_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merchant_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercMerchantEntries e{}; + + e.merc_merchant_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_merchant_template_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merchant_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_MERCHANT_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_merchant_template_entries_repository.h b/common/repositories/base/base_merc_merchant_template_entries_repository.h new file mode 100644 index 000000000..26ed3b9d6 --- /dev/null +++ b/common/repositories/base/base_merc_merchant_template_entries_repository.h @@ -0,0 +1,344 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercMerchantTemplateEntriesRepository { +public: + struct MercMerchantTemplateEntries { + uint32_t merc_merchant_template_entry_id; + uint32_t merc_merchant_template_id; + uint32_t merc_template_id; + }; + + static std::string PrimaryKey() + { + return std::string("merc_merchant_template_entry_id"); + } + + static std::vector Columns() + { + return { + "merc_merchant_template_entry_id", + "merc_merchant_template_id", + "merc_template_id", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_merchant_template_entry_id", + "merc_merchant_template_id", + "merc_template_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_merchant_template_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercMerchantTemplateEntries NewEntity() + { + MercMerchantTemplateEntries e{}; + + e.merc_merchant_template_entry_id = 0; + e.merc_merchant_template_id = 0; + e.merc_template_id = 0; + + return e; + } + + static MercMerchantTemplateEntries GetMercMerchantTemplateEntries( + const std::vector &merc_merchant_template_entriess, + int merc_merchant_template_entries_id + ) + { + for (auto &merc_merchant_template_entries : merc_merchant_template_entriess) { + if (merc_merchant_template_entries.merc_merchant_template_entry_id == merc_merchant_template_entries_id) { + return merc_merchant_template_entries; + } + } + + return NewEntity(); + } + + static MercMerchantTemplateEntries FindOne( + Database& db, + int merc_merchant_template_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_merchant_template_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercMerchantTemplateEntries e{}; + + e.merc_merchant_template_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_merchant_template_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merc_template_id = static_cast(strtoul(row[2], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_merchant_template_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_merchant_template_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercMerchantTemplateEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.merc_merchant_template_id)); + v.push_back(columns[2] + " = " + std::to_string(e.merc_template_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_merchant_template_entry_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercMerchantTemplateEntries InsertOne( + Database& db, + MercMerchantTemplateEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_merchant_template_entry_id)); + v.push_back(std::to_string(e.merc_merchant_template_id)); + v.push_back(std::to_string(e.merc_template_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_merchant_template_entry_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_merchant_template_entry_id)); + v.push_back(std::to_string(e.merc_merchant_template_id)); + v.push_back(std::to_string(e.merc_template_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercMerchantTemplateEntries e{}; + + e.merc_merchant_template_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_merchant_template_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merc_template_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercMerchantTemplateEntries e{}; + + e.merc_merchant_template_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_merchant_template_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merc_template_id = static_cast(strtoul(row[2], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_merchant_templates_repository.h b/common/repositories/base/base_merc_merchant_templates_repository.h new file mode 100644 index 000000000..84b61815f --- /dev/null +++ b/common/repositories/base/base_merc_merchant_templates_repository.h @@ -0,0 +1,344 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_MERCHANT_TEMPLATES_REPOSITORY_H +#define EQEMU_BASE_MERC_MERCHANT_TEMPLATES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercMerchantTemplatesRepository { +public: + struct MercMerchantTemplates { + uint32_t merc_merchant_template_id; + std::string name; + std::string qglobal; + }; + + static std::string PrimaryKey() + { + return std::string("merc_merchant_template_id"); + } + + static std::vector Columns() + { + return { + "merc_merchant_template_id", + "name", + "qglobal", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_merchant_template_id", + "name", + "qglobal", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_merchant_templates"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercMerchantTemplates NewEntity() + { + MercMerchantTemplates e{}; + + e.merc_merchant_template_id = 0; + e.name = ""; + e.qglobal = ""; + + return e; + } + + static MercMerchantTemplates GetMercMerchantTemplates( + const std::vector &merc_merchant_templatess, + int merc_merchant_templates_id + ) + { + for (auto &merc_merchant_templates : merc_merchant_templatess) { + if (merc_merchant_templates.merc_merchant_template_id == merc_merchant_templates_id) { + return merc_merchant_templates; + } + } + + return NewEntity(); + } + + static MercMerchantTemplates FindOne( + Database& db, + int merc_merchant_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_merchant_templates_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercMerchantTemplates e{}; + + e.merc_merchant_template_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.qglobal = row[2] ? row[2] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_merchant_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_merchant_templates_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercMerchantTemplates &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.qglobal) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_merchant_template_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercMerchantTemplates InsertOne( + Database& db, + MercMerchantTemplates e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_merchant_template_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.qglobal) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_merchant_template_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_merchant_template_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.qglobal) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercMerchantTemplates e{}; + + e.merc_merchant_template_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.qglobal = row[2] ? row[2] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercMerchantTemplates e{}; + + e.merc_merchant_template_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.qglobal = row[2] ? row[2] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_MERCHANT_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_name_types_repository.h b/common/repositories/base/base_merc_name_types_repository.h new file mode 100644 index 000000000..9ed66f376 --- /dev/null +++ b/common/repositories/base/base_merc_name_types_repository.h @@ -0,0 +1,355 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_NAME_TYPES_REPOSITORY_H +#define EQEMU_BASE_MERC_NAME_TYPES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercNameTypesRepository { +public: + struct MercNameTypes { + uint32_t name_type_id; + uint32_t class_id; + std::string prefix; + std::string suffix; + }; + + static std::string PrimaryKey() + { + return std::string("name_type_id"); + } + + static std::vector Columns() + { + return { + "name_type_id", + "class_id", + "prefix", + "suffix", + }; + } + + static std::vector SelectColumns() + { + return { + "name_type_id", + "class_id", + "prefix", + "suffix", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_name_types"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercNameTypes NewEntity() + { + MercNameTypes e{}; + + e.name_type_id = 0; + e.class_id = 0; + e.prefix = ""; + e.suffix = ""; + + return e; + } + + static MercNameTypes GetMercNameTypes( + const std::vector &merc_name_typess, + int merc_name_types_id + ) + { + for (auto &merc_name_types : merc_name_typess) { + if (merc_name_types.name_type_id == merc_name_types_id) { + return merc_name_types; + } + } + + return NewEntity(); + } + + static MercNameTypes FindOne( + Database& db, + int merc_name_types_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_name_types_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercNameTypes e{}; + + e.name_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.prefix = row[2] ? row[2] : ""; + e.suffix = row[3] ? row[3] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_name_types_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_name_types_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercNameTypes &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.name_type_id)); + v.push_back(columns[1] + " = " + std::to_string(e.class_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.prefix) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.suffix) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.name_type_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercNameTypes InsertOne( + Database& db, + MercNameTypes e + ) + { + std::vector v; + + v.push_back(std::to_string(e.name_type_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back("'" + Strings::Escape(e.prefix) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.name_type_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.name_type_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back("'" + Strings::Escape(e.prefix) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercNameTypes e{}; + + e.name_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.prefix = row[2] ? row[2] : ""; + e.suffix = row[3] ? row[3] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercNameTypes e{}; + + e.name_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.prefix = row[2] ? row[2] : ""; + e.suffix = row[3] ? row[3] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_NAME_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_npc_types_repository.h b/common/repositories/base/base_merc_npc_types_repository.h new file mode 100644 index 000000000..c224656dd --- /dev/null +++ b/common/repositories/base/base_merc_npc_types_repository.h @@ -0,0 +1,364 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_NPC_TYPES_REPOSITORY_H +#define EQEMU_BASE_MERC_NPC_TYPES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercNpcTypesRepository { +public: + struct MercNpcTypes { + uint32_t merc_npc_type_id; + uint8_t proficiency_id; + uint8_t tier_id; + uint32_t class_id; + std::string name; + }; + + static std::string PrimaryKey() + { + return std::string("merc_npc_type_id"); + } + + static std::vector Columns() + { + return { + "merc_npc_type_id", + "proficiency_id", + "tier_id", + "class_id", + "name", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_npc_type_id", + "proficiency_id", + "tier_id", + "class_id", + "name", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_npc_types"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercNpcTypes NewEntity() + { + MercNpcTypes e{}; + + e.merc_npc_type_id = 0; + e.proficiency_id = 0; + e.tier_id = 0; + e.class_id = 0; + e.name = ""; + + return e; + } + + static MercNpcTypes GetMercNpcTypes( + const std::vector &merc_npc_typess, + int merc_npc_types_id + ) + { + for (auto &merc_npc_types : merc_npc_typess) { + if (merc_npc_types.merc_npc_type_id == merc_npc_types_id) { + return merc_npc_types; + } + } + + return NewEntity(); + } + + static MercNpcTypes FindOne( + Database& db, + int merc_npc_types_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_npc_types_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercNpcTypes e{}; + + e.merc_npc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[1], nullptr, 10)); + e.tier_id = static_cast(strtoul(row[2], nullptr, 10)); + e.class_id = static_cast(strtoul(row[3], nullptr, 10)); + e.name = row[4] ? row[4] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_npc_types_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_npc_types_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercNpcTypes &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.proficiency_id)); + v.push_back(columns[2] + " = " + std::to_string(e.tier_id)); + v.push_back(columns[3] + " = " + std::to_string(e.class_id)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_npc_type_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercNpcTypes InsertOne( + Database& db, + MercNpcTypes e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back(std::to_string(e.tier_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_npc_type_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back(std::to_string(e.tier_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercNpcTypes e{}; + + e.merc_npc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[1], nullptr, 10)); + e.tier_id = static_cast(strtoul(row[2], nullptr, 10)); + e.class_id = static_cast(strtoul(row[3], nullptr, 10)); + e.name = row[4] ? row[4] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercNpcTypes e{}; + + e.merc_npc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[1], nullptr, 10)); + e.tier_id = static_cast(strtoul(row[2], nullptr, 10)); + e.class_id = static_cast(strtoul(row[3], nullptr, 10)); + e.name = row[4] ? row[4] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_NPC_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_spell_list_entries_repository.h b/common/repositories/base/base_merc_spell_list_entries_repository.h new file mode 100644 index 000000000..8c8e249ce --- /dev/null +++ b/common/repositories/base/base_merc_spell_list_entries_repository.h @@ -0,0 +1,404 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercSpellListEntriesRepository { +public: + struct MercSpellListEntries { + uint32_t merc_spell_list_entry_id; + uint32_t merc_spell_list_id; + uint32_t spell_id; + uint32_t spell_type; + uint8_t stance_id; + uint8_t minlevel; + uint8_t maxlevel; + int8_t slot; + uint8_t procChance; + }; + + static std::string PrimaryKey() + { + return std::string("merc_spell_list_entry_id"); + } + + static std::vector Columns() + { + return { + "merc_spell_list_entry_id", + "merc_spell_list_id", + "spell_id", + "spell_type", + "stance_id", + "minlevel", + "maxlevel", + "slot", + "procChance", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_spell_list_entry_id", + "merc_spell_list_id", + "spell_id", + "spell_type", + "stance_id", + "minlevel", + "maxlevel", + "slot", + "procChance", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_spell_list_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercSpellListEntries NewEntity() + { + MercSpellListEntries e{}; + + e.merc_spell_list_entry_id = 0; + e.merc_spell_list_id = 0; + e.spell_id = 0; + e.spell_type = 0; + e.stance_id = 0; + e.minlevel = 1; + e.maxlevel = 255; + e.slot = -1; + e.procChance = 0; + + return e; + } + + static MercSpellListEntries GetMercSpellListEntries( + const std::vector &merc_spell_list_entriess, + int merc_spell_list_entries_id + ) + { + for (auto &merc_spell_list_entries : merc_spell_list_entriess) { + if (merc_spell_list_entries.merc_spell_list_entry_id == merc_spell_list_entries_id) { + return merc_spell_list_entries; + } + } + + return NewEntity(); + } + + static MercSpellListEntries FindOne( + Database& db, + int merc_spell_list_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_spell_list_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercSpellListEntries e{}; + + e.merc_spell_list_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_spell_list_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.spell_type = static_cast(strtoul(row[3], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[4], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[6], nullptr, 10)); + e.slot = static_cast(atoi(row[7])); + e.procChance = static_cast(strtoul(row[8], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_spell_list_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_spell_list_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercSpellListEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.merc_spell_list_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[3] + " = " + std::to_string(e.spell_type)); + v.push_back(columns[4] + " = " + std::to_string(e.stance_id)); + v.push_back(columns[5] + " = " + std::to_string(e.minlevel)); + v.push_back(columns[6] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[7] + " = " + std::to_string(e.slot)); + v.push_back(columns[8] + " = " + std::to_string(e.procChance)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_spell_list_entry_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercSpellListEntries InsertOne( + Database& db, + MercSpellListEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_spell_list_entry_id)); + v.push_back(std::to_string(e.merc_spell_list_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.spell_type)); + v.push_back(std::to_string(e.stance_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.procChance)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_spell_list_entry_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_spell_list_entry_id)); + v.push_back(std::to_string(e.merc_spell_list_id)); + v.push_back(std::to_string(e.spell_id)); + v.push_back(std::to_string(e.spell_type)); + v.push_back(std::to_string(e.stance_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.procChance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercSpellListEntries e{}; + + e.merc_spell_list_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_spell_list_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.spell_type = static_cast(strtoul(row[3], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[4], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[6], nullptr, 10)); + e.slot = static_cast(atoi(row[7])); + e.procChance = static_cast(strtoul(row[8], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercSpellListEntries e{}; + + e.merc_spell_list_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_spell_list_id = static_cast(strtoul(row[1], nullptr, 10)); + e.spell_id = static_cast(strtoul(row[2], nullptr, 10)); + e.spell_type = static_cast(strtoul(row[3], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[4], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[6], nullptr, 10)); + e.slot = static_cast(atoi(row[7])); + e.procChance = static_cast(strtoul(row[8], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_spell_lists_repository.h b/common/repositories/base/base_merc_spell_lists_repository.h new file mode 100644 index 000000000..36b560d5d --- /dev/null +++ b/common/repositories/base/base_merc_spell_lists_repository.h @@ -0,0 +1,354 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_SPELL_LISTS_REPOSITORY_H +#define EQEMU_BASE_MERC_SPELL_LISTS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercSpellListsRepository { +public: + struct MercSpellLists { + uint32_t merc_spell_list_id; + uint32_t class_id; + uint8_t proficiency_id; + std::string name; + }; + + static std::string PrimaryKey() + { + return std::string("merc_spell_list_id"); + } + + static std::vector Columns() + { + return { + "merc_spell_list_id", + "class_id", + "proficiency_id", + "name", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_spell_list_id", + "class_id", + "proficiency_id", + "name", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_spell_lists"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercSpellLists NewEntity() + { + MercSpellLists e{}; + + e.merc_spell_list_id = 0; + e.class_id = 0; + e.proficiency_id = 0; + e.name = ""; + + return e; + } + + static MercSpellLists GetMercSpellLists( + const std::vector &merc_spell_listss, + int merc_spell_lists_id + ) + { + for (auto &merc_spell_lists : merc_spell_listss) { + if (merc_spell_lists.merc_spell_list_id == merc_spell_lists_id) { + return merc_spell_lists; + } + } + + return NewEntity(); + } + + static MercSpellLists FindOne( + Database& db, + int merc_spell_lists_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_spell_lists_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercSpellLists e{}; + + e.merc_spell_list_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_spell_lists_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_spell_lists_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercSpellLists &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.class_id)); + v.push_back(columns[2] + " = " + std::to_string(e.proficiency_id)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_spell_list_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercSpellLists InsertOne( + Database& db, + MercSpellLists e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_spell_list_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_spell_list_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_spell_list_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercSpellLists e{}; + + e.merc_spell_list_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercSpellLists e{}; + + e.merc_spell_list_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_SPELL_LISTS_REPOSITORY_H diff --git a/common/repositories/base/base_merc_stance_entries_repository.h b/common/repositories/base/base_merc_stance_entries_repository.h new file mode 100644 index 000000000..f2d96e7bd --- /dev/null +++ b/common/repositories/base/base_merc_stance_entries_repository.h @@ -0,0 +1,364 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_STANCE_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_MERC_STANCE_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercStanceEntriesRepository { +public: + struct MercStanceEntries { + uint32_t merc_stance_entry_id; + uint32_t class_id; + uint8_t proficiency_id; + uint8_t stance_id; + int8_t isdefault; + }; + + static std::string PrimaryKey() + { + return std::string("merc_stance_entry_id"); + } + + static std::vector Columns() + { + return { + "merc_stance_entry_id", + "class_id", + "proficiency_id", + "stance_id", + "isdefault", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_stance_entry_id", + "class_id", + "proficiency_id", + "stance_id", + "isdefault", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_stance_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercStanceEntries NewEntity() + { + MercStanceEntries e{}; + + e.merc_stance_entry_id = 0; + e.class_id = 0; + e.proficiency_id = 0; + e.stance_id = 0; + e.isdefault = 0; + + return e; + } + + static MercStanceEntries GetMercStanceEntries( + const std::vector &merc_stance_entriess, + int merc_stance_entries_id + ) + { + for (auto &merc_stance_entries : merc_stance_entriess) { + if (merc_stance_entries.merc_stance_entry_id == merc_stance_entries_id) { + return merc_stance_entries; + } + } + + return NewEntity(); + } + + static MercStanceEntries FindOne( + Database& db, + int merc_stance_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_stance_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercStanceEntries e{}; + + e.merc_stance_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[3], nullptr, 10)); + e.isdefault = static_cast(atoi(row[4])); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_stance_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_stance_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercStanceEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.class_id)); + v.push_back(columns[2] + " = " + std::to_string(e.proficiency_id)); + v.push_back(columns[3] + " = " + std::to_string(e.stance_id)); + v.push_back(columns[4] + " = " + std::to_string(e.isdefault)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_stance_entry_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercStanceEntries InsertOne( + Database& db, + MercStanceEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_stance_entry_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back(std::to_string(e.stance_id)); + v.push_back(std::to_string(e.isdefault)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_stance_entry_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_stance_entry_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back(std::to_string(e.stance_id)); + v.push_back(std::to_string(e.isdefault)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercStanceEntries e{}; + + e.merc_stance_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[3], nullptr, 10)); + e.isdefault = static_cast(atoi(row[4])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercStanceEntries e{}; + + e.merc_stance_entry_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.stance_id = static_cast(strtoul(row[3], nullptr, 10)); + e.isdefault = static_cast(atoi(row[4])); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_STANCE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_stats_repository.h b/common/repositories/base/base_merc_stats_repository.h new file mode 100644 index 000000000..55ada42e9 --- /dev/null +++ b/common/repositories/base/base_merc_stats_repository.h @@ -0,0 +1,645 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_STATS_REPOSITORY_H +#define EQEMU_BASE_MERC_STATS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercStatsRepository { +public: + struct MercStats { + uint32_t merc_npc_type_id; + uint8_t clientlevel; + uint8_t level; + int32_t hp; + int32_t mana; + int16_t AC; + int32_t ATK; + uint32_t STR; + uint32_t STA; + uint32_t DEX; + uint32_t AGI; + uint32_t _INT; + uint32_t WIS; + uint32_t CHA; + int16_t MR; + int16_t CR; + int16_t DR; + int16_t FR; + int16_t PR; + int16_t Corrup; + uint32_t mindmg; + uint32_t maxdmg; + int16_t attack_count; + int8_t attack_speed; + uint8_t attack_delay; + std::string special_abilities; + int32_t Accuracy; + uint32_t hp_regen_rate; + uint32_t mana_regen_rate; + float runspeed; + int32_t statscale; + float spellscale; + float healscale; + }; + + static std::string PrimaryKey() + { + return std::string("merc_npc_type_id"); + } + + static std::vector Columns() + { + return { + "merc_npc_type_id", + "clientlevel", + "level", + "hp", + "mana", + "AC", + "ATK", + "STR", + "STA", + "DEX", + "AGI", + "_INT", + "WIS", + "CHA", + "MR", + "CR", + "DR", + "FR", + "PR", + "Corrup", + "mindmg", + "maxdmg", + "attack_count", + "attack_speed", + "attack_delay", + "special_abilities", + "Accuracy", + "hp_regen_rate", + "mana_regen_rate", + "runspeed", + "statscale", + "spellscale", + "healscale", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_npc_type_id", + "clientlevel", + "level", + "hp", + "mana", + "AC", + "ATK", + "STR", + "STA", + "DEX", + "AGI", + "_INT", + "WIS", + "CHA", + "MR", + "CR", + "DR", + "FR", + "PR", + "Corrup", + "mindmg", + "maxdmg", + "attack_count", + "attack_speed", + "attack_delay", + "special_abilities", + "Accuracy", + "hp_regen_rate", + "mana_regen_rate", + "runspeed", + "statscale", + "spellscale", + "healscale", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_stats"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercStats NewEntity() + { + MercStats e{}; + + e.merc_npc_type_id = 0; + e.clientlevel = 1; + e.level = 1; + e.hp = 1; + e.mana = 0; + e.AC = 1; + e.ATK = 1; + e.STR = 75; + e.STA = 75; + e.DEX = 75; + e.AGI = 75; + e._INT = 80; + e.WIS = 80; + e.CHA = 75; + e.MR = 15; + e.CR = 15; + e.DR = 15; + e.FR = 15; + e.PR = 15; + e.Corrup = 15; + e.mindmg = 1; + e.maxdmg = 1; + e.attack_count = 0; + e.attack_speed = 0; + e.attack_delay = 30; + e.special_abilities = ""; + e.Accuracy = 0; + e.hp_regen_rate = 1; + e.mana_regen_rate = 1; + e.runspeed = 0; + e.statscale = 100; + e.spellscale = 100; + e.healscale = 100; + + return e; + } + + static MercStats GetMercStats( + const std::vector &merc_statss, + int merc_stats_id + ) + { + for (auto &merc_stats : merc_statss) { + if (merc_stats.merc_npc_type_id == merc_stats_id) { + return merc_stats; + } + } + + return NewEntity(); + } + + static MercStats FindOne( + Database& db, + int merc_stats_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_stats_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercStats e{}; + + e.merc_npc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.clientlevel = static_cast(strtoul(row[1], nullptr, 10)); + e.level = static_cast(strtoul(row[2], nullptr, 10)); + e.hp = static_cast(atoi(row[3])); + e.mana = static_cast(atoi(row[4])); + e.AC = static_cast(atoi(row[5])); + e.ATK = static_cast(atoi(row[6])); + e.STR = static_cast(strtoul(row[7], nullptr, 10)); + e.STA = static_cast(strtoul(row[8], nullptr, 10)); + e.DEX = static_cast(strtoul(row[9], nullptr, 10)); + e.AGI = static_cast(strtoul(row[10], nullptr, 10)); + e._INT = static_cast(strtoul(row[11], nullptr, 10)); + e.WIS = static_cast(strtoul(row[12], nullptr, 10)); + e.CHA = static_cast(strtoul(row[13], nullptr, 10)); + e.MR = static_cast(atoi(row[14])); + e.CR = static_cast(atoi(row[15])); + e.DR = static_cast(atoi(row[16])); + e.FR = static_cast(atoi(row[17])); + e.PR = static_cast(atoi(row[18])); + e.Corrup = static_cast(atoi(row[19])); + e.mindmg = static_cast(strtoul(row[20], nullptr, 10)); + e.maxdmg = static_cast(strtoul(row[21], nullptr, 10)); + e.attack_count = static_cast(atoi(row[22])); + e.attack_speed = static_cast(atoi(row[23])); + e.attack_delay = static_cast(strtoul(row[24], nullptr, 10)); + e.special_abilities = row[25] ? row[25] : ""; + e.Accuracy = static_cast(atoi(row[26])); + e.hp_regen_rate = static_cast(strtoul(row[27], nullptr, 10)); + e.mana_regen_rate = static_cast(strtoul(row[28], nullptr, 10)); + e.runspeed = strtof(row[29], nullptr); + e.statscale = static_cast(atoi(row[30])); + e.spellscale = strtof(row[31], nullptr); + e.healscale = strtof(row[32], nullptr); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_stats_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_stats_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercStats &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.merc_npc_type_id)); + v.push_back(columns[1] + " = " + std::to_string(e.clientlevel)); + v.push_back(columns[2] + " = " + std::to_string(e.level)); + v.push_back(columns[3] + " = " + std::to_string(e.hp)); + v.push_back(columns[4] + " = " + std::to_string(e.mana)); + v.push_back(columns[5] + " = " + std::to_string(e.AC)); + v.push_back(columns[6] + " = " + std::to_string(e.ATK)); + v.push_back(columns[7] + " = " + std::to_string(e.STR)); + v.push_back(columns[8] + " = " + std::to_string(e.STA)); + v.push_back(columns[9] + " = " + std::to_string(e.DEX)); + v.push_back(columns[10] + " = " + std::to_string(e.AGI)); + v.push_back(columns[11] + " = " + std::to_string(e._INT)); + v.push_back(columns[12] + " = " + std::to_string(e.WIS)); + v.push_back(columns[13] + " = " + std::to_string(e.CHA)); + v.push_back(columns[14] + " = " + std::to_string(e.MR)); + v.push_back(columns[15] + " = " + std::to_string(e.CR)); + v.push_back(columns[16] + " = " + std::to_string(e.DR)); + v.push_back(columns[17] + " = " + std::to_string(e.FR)); + v.push_back(columns[18] + " = " + std::to_string(e.PR)); + v.push_back(columns[19] + " = " + std::to_string(e.Corrup)); + v.push_back(columns[20] + " = " + std::to_string(e.mindmg)); + v.push_back(columns[21] + " = " + std::to_string(e.maxdmg)); + v.push_back(columns[22] + " = " + std::to_string(e.attack_count)); + v.push_back(columns[23] + " = " + std::to_string(e.attack_speed)); + v.push_back(columns[24] + " = " + std::to_string(e.attack_delay)); + v.push_back(columns[25] + " = '" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(columns[26] + " = " + std::to_string(e.Accuracy)); + v.push_back(columns[27] + " = " + std::to_string(e.hp_regen_rate)); + v.push_back(columns[28] + " = " + std::to_string(e.mana_regen_rate)); + v.push_back(columns[29] + " = " + std::to_string(e.runspeed)); + v.push_back(columns[30] + " = " + std::to_string(e.statscale)); + v.push_back(columns[31] + " = " + std::to_string(e.spellscale)); + v.push_back(columns[32] + " = " + std::to_string(e.healscale)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_npc_type_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercStats InsertOne( + Database& db, + MercStats e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.clientlevel)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.AC)); + v.push_back(std::to_string(e.ATK)); + v.push_back(std::to_string(e.STR)); + v.push_back(std::to_string(e.STA)); + v.push_back(std::to_string(e.DEX)); + v.push_back(std::to_string(e.AGI)); + v.push_back(std::to_string(e._INT)); + v.push_back(std::to_string(e.WIS)); + v.push_back(std::to_string(e.CHA)); + v.push_back(std::to_string(e.MR)); + v.push_back(std::to_string(e.CR)); + v.push_back(std::to_string(e.DR)); + v.push_back(std::to_string(e.FR)); + v.push_back(std::to_string(e.PR)); + v.push_back(std::to_string(e.Corrup)); + v.push_back(std::to_string(e.mindmg)); + v.push_back(std::to_string(e.maxdmg)); + v.push_back(std::to_string(e.attack_count)); + v.push_back(std::to_string(e.attack_speed)); + v.push_back(std::to_string(e.attack_delay)); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(std::to_string(e.Accuracy)); + v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.mana_regen_rate)); + v.push_back(std::to_string(e.runspeed)); + v.push_back(std::to_string(e.statscale)); + v.push_back(std::to_string(e.spellscale)); + v.push_back(std::to_string(e.healscale)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_npc_type_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.clientlevel)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.AC)); + v.push_back(std::to_string(e.ATK)); + v.push_back(std::to_string(e.STR)); + v.push_back(std::to_string(e.STA)); + v.push_back(std::to_string(e.DEX)); + v.push_back(std::to_string(e.AGI)); + v.push_back(std::to_string(e._INT)); + v.push_back(std::to_string(e.WIS)); + v.push_back(std::to_string(e.CHA)); + v.push_back(std::to_string(e.MR)); + v.push_back(std::to_string(e.CR)); + v.push_back(std::to_string(e.DR)); + v.push_back(std::to_string(e.FR)); + v.push_back(std::to_string(e.PR)); + v.push_back(std::to_string(e.Corrup)); + v.push_back(std::to_string(e.mindmg)); + v.push_back(std::to_string(e.maxdmg)); + v.push_back(std::to_string(e.attack_count)); + v.push_back(std::to_string(e.attack_speed)); + v.push_back(std::to_string(e.attack_delay)); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(std::to_string(e.Accuracy)); + v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.mana_regen_rate)); + v.push_back(std::to_string(e.runspeed)); + v.push_back(std::to_string(e.statscale)); + v.push_back(std::to_string(e.spellscale)); + v.push_back(std::to_string(e.healscale)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercStats e{}; + + e.merc_npc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.clientlevel = static_cast(strtoul(row[1], nullptr, 10)); + e.level = static_cast(strtoul(row[2], nullptr, 10)); + e.hp = static_cast(atoi(row[3])); + e.mana = static_cast(atoi(row[4])); + e.AC = static_cast(atoi(row[5])); + e.ATK = static_cast(atoi(row[6])); + e.STR = static_cast(strtoul(row[7], nullptr, 10)); + e.STA = static_cast(strtoul(row[8], nullptr, 10)); + e.DEX = static_cast(strtoul(row[9], nullptr, 10)); + e.AGI = static_cast(strtoul(row[10], nullptr, 10)); + e._INT = static_cast(strtoul(row[11], nullptr, 10)); + e.WIS = static_cast(strtoul(row[12], nullptr, 10)); + e.CHA = static_cast(strtoul(row[13], nullptr, 10)); + e.MR = static_cast(atoi(row[14])); + e.CR = static_cast(atoi(row[15])); + e.DR = static_cast(atoi(row[16])); + e.FR = static_cast(atoi(row[17])); + e.PR = static_cast(atoi(row[18])); + e.Corrup = static_cast(atoi(row[19])); + e.mindmg = static_cast(strtoul(row[20], nullptr, 10)); + e.maxdmg = static_cast(strtoul(row[21], nullptr, 10)); + e.attack_count = static_cast(atoi(row[22])); + e.attack_speed = static_cast(atoi(row[23])); + e.attack_delay = static_cast(strtoul(row[24], nullptr, 10)); + e.special_abilities = row[25] ? row[25] : ""; + e.Accuracy = static_cast(atoi(row[26])); + e.hp_regen_rate = static_cast(strtoul(row[27], nullptr, 10)); + e.mana_regen_rate = static_cast(strtoul(row[28], nullptr, 10)); + e.runspeed = strtof(row[29], nullptr); + e.statscale = static_cast(atoi(row[30])); + e.spellscale = strtof(row[31], nullptr); + e.healscale = strtof(row[32], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercStats e{}; + + e.merc_npc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.clientlevel = static_cast(strtoul(row[1], nullptr, 10)); + e.level = static_cast(strtoul(row[2], nullptr, 10)); + e.hp = static_cast(atoi(row[3])); + e.mana = static_cast(atoi(row[4])); + e.AC = static_cast(atoi(row[5])); + e.ATK = static_cast(atoi(row[6])); + e.STR = static_cast(strtoul(row[7], nullptr, 10)); + e.STA = static_cast(strtoul(row[8], nullptr, 10)); + e.DEX = static_cast(strtoul(row[9], nullptr, 10)); + e.AGI = static_cast(strtoul(row[10], nullptr, 10)); + e._INT = static_cast(strtoul(row[11], nullptr, 10)); + e.WIS = static_cast(strtoul(row[12], nullptr, 10)); + e.CHA = static_cast(strtoul(row[13], nullptr, 10)); + e.MR = static_cast(atoi(row[14])); + e.CR = static_cast(atoi(row[15])); + e.DR = static_cast(atoi(row[16])); + e.FR = static_cast(atoi(row[17])); + e.PR = static_cast(atoi(row[18])); + e.Corrup = static_cast(atoi(row[19])); + e.mindmg = static_cast(strtoul(row[20], nullptr, 10)); + e.maxdmg = static_cast(strtoul(row[21], nullptr, 10)); + e.attack_count = static_cast(atoi(row[22])); + e.attack_speed = static_cast(atoi(row[23])); + e.attack_delay = static_cast(strtoul(row[24], nullptr, 10)); + e.special_abilities = row[25] ? row[25] : ""; + e.Accuracy = static_cast(atoi(row[26])); + e.hp_regen_rate = static_cast(strtoul(row[27], nullptr, 10)); + e.mana_regen_rate = static_cast(strtoul(row[28], nullptr, 10)); + e.runspeed = strtof(row[29], nullptr); + e.statscale = static_cast(atoi(row[30])); + e.spellscale = strtof(row[31], nullptr); + e.healscale = strtof(row[32], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_STATS_REPOSITORY_H diff --git a/common/repositories/base/base_merc_subtypes_repository.h b/common/repositories/base/base_merc_subtypes_repository.h new file mode 100644 index 000000000..6dca32444 --- /dev/null +++ b/common/repositories/base/base_merc_subtypes_repository.h @@ -0,0 +1,354 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_SUBTYPES_REPOSITORY_H +#define EQEMU_BASE_MERC_SUBTYPES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercSubtypesRepository { +public: + struct MercSubtypes { + uint32_t merc_subtype_id; + uint32_t class_id; + uint8_t tier_id; + uint8_t confidence_id; + }; + + static std::string PrimaryKey() + { + return std::string("merc_subtype_id"); + } + + static std::vector Columns() + { + return { + "merc_subtype_id", + "class_id", + "tier_id", + "confidence_id", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_subtype_id", + "class_id", + "tier_id", + "confidence_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_subtypes"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercSubtypes NewEntity() + { + MercSubtypes e{}; + + e.merc_subtype_id = 0; + e.class_id = 0; + e.tier_id = 0; + e.confidence_id = 0; + + return e; + } + + static MercSubtypes GetMercSubtypes( + const std::vector &merc_subtypess, + int merc_subtypes_id + ) + { + for (auto &merc_subtypes : merc_subtypess) { + if (merc_subtypes.merc_subtype_id == merc_subtypes_id) { + return merc_subtypes; + } + } + + return NewEntity(); + } + + static MercSubtypes FindOne( + Database& db, + int merc_subtypes_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_subtypes_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercSubtypes e{}; + + e.merc_subtype_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.tier_id = static_cast(strtoul(row[2], nullptr, 10)); + e.confidence_id = static_cast(strtoul(row[3], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_subtypes_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_subtypes_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercSubtypes &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.class_id)); + v.push_back(columns[2] + " = " + std::to_string(e.tier_id)); + v.push_back(columns[3] + " = " + std::to_string(e.confidence_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_subtype_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercSubtypes InsertOne( + Database& db, + MercSubtypes e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_subtype_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.tier_id)); + v.push_back(std::to_string(e.confidence_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_subtype_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_subtype_id)); + v.push_back(std::to_string(e.class_id)); + v.push_back(std::to_string(e.tier_id)); + v.push_back(std::to_string(e.confidence_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercSubtypes e{}; + + e.merc_subtype_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.tier_id = static_cast(strtoul(row[2], nullptr, 10)); + e.confidence_id = static_cast(strtoul(row[3], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercSubtypes e{}; + + e.merc_subtype_id = static_cast(strtoul(row[0], nullptr, 10)); + e.class_id = static_cast(strtoul(row[1], nullptr, 10)); + e.tier_id = static_cast(strtoul(row[2], nullptr, 10)); + e.confidence_id = static_cast(strtoul(row[3], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_SUBTYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_templates_repository.h b/common/repositories/base/base_merc_templates_repository.h new file mode 100644 index 000000000..bf63c8554 --- /dev/null +++ b/common/repositories/base/base_merc_templates_repository.h @@ -0,0 +1,384 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_TEMPLATES_REPOSITORY_H +#define EQEMU_BASE_MERC_TEMPLATES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercTemplatesRepository { +public: + struct MercTemplates { + uint32_t merc_template_id; + uint32_t merc_type_id; + uint32_t merc_subtype_id; + uint32_t merc_npc_type_id; + std::string dbstring; + int8_t name_type_id; + uint32_t clientversion; + }; + + static std::string PrimaryKey() + { + return std::string("merc_template_id"); + } + + static std::vector Columns() + { + return { + "merc_template_id", + "merc_type_id", + "merc_subtype_id", + "merc_npc_type_id", + "dbstring", + "name_type_id", + "clientversion", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_template_id", + "merc_type_id", + "merc_subtype_id", + "merc_npc_type_id", + "dbstring", + "name_type_id", + "clientversion", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_templates"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercTemplates NewEntity() + { + MercTemplates e{}; + + e.merc_template_id = 0; + e.merc_type_id = 0; + e.merc_subtype_id = 0; + e.merc_npc_type_id = 0; + e.dbstring = ""; + e.name_type_id = 0; + e.clientversion = 0; + + return e; + } + + static MercTemplates GetMercTemplates( + const std::vector &merc_templatess, + int merc_templates_id + ) + { + for (auto &merc_templates : merc_templatess) { + if (merc_templates.merc_template_id == merc_templates_id) { + return merc_templates; + } + } + + return NewEntity(); + } + + static MercTemplates FindOne( + Database& db, + int merc_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_templates_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercTemplates e{}; + + e.merc_template_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_type_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merc_subtype_id = static_cast(strtoul(row[2], nullptr, 10)); + e.merc_npc_type_id = static_cast(strtoul(row[3], nullptr, 10)); + e.dbstring = row[4] ? row[4] : ""; + e.name_type_id = static_cast(atoi(row[5])); + e.clientversion = static_cast(strtoul(row[6], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_templates_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercTemplates &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.merc_type_id)); + v.push_back(columns[2] + " = " + std::to_string(e.merc_subtype_id)); + v.push_back(columns[3] + " = " + std::to_string(e.merc_npc_type_id)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.dbstring) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.name_type_id)); + v.push_back(columns[6] + " = " + std::to_string(e.clientversion)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_template_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercTemplates InsertOne( + Database& db, + MercTemplates e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_template_id)); + v.push_back(std::to_string(e.merc_type_id)); + v.push_back(std::to_string(e.merc_subtype_id)); + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back("'" + Strings::Escape(e.dbstring) + "'"); + v.push_back(std::to_string(e.name_type_id)); + v.push_back(std::to_string(e.clientversion)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_template_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_template_id)); + v.push_back(std::to_string(e.merc_type_id)); + v.push_back(std::to_string(e.merc_subtype_id)); + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back("'" + Strings::Escape(e.dbstring) + "'"); + v.push_back(std::to_string(e.name_type_id)); + v.push_back(std::to_string(e.clientversion)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercTemplates e{}; + + e.merc_template_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_type_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merc_subtype_id = static_cast(strtoul(row[2], nullptr, 10)); + e.merc_npc_type_id = static_cast(strtoul(row[3], nullptr, 10)); + e.dbstring = row[4] ? row[4] : ""; + e.name_type_id = static_cast(atoi(row[5])); + e.clientversion = static_cast(strtoul(row[6], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercTemplates e{}; + + e.merc_template_id = static_cast(strtoul(row[0], nullptr, 10)); + e.merc_type_id = static_cast(strtoul(row[1], nullptr, 10)); + e.merc_subtype_id = static_cast(strtoul(row[2], nullptr, 10)); + e.merc_npc_type_id = static_cast(strtoul(row[3], nullptr, 10)); + e.dbstring = row[4] ? row[4] : ""; + e.name_type_id = static_cast(atoi(row[5])); + e.clientversion = static_cast(strtoul(row[6], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_types_repository.h b/common/repositories/base/base_merc_types_repository.h new file mode 100644 index 000000000..35fa5735b --- /dev/null +++ b/common/repositories/base/base_merc_types_repository.h @@ -0,0 +1,364 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_TYPES_REPOSITORY_H +#define EQEMU_BASE_MERC_TYPES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercTypesRepository { +public: + struct MercTypes { + uint32_t merc_type_id; + uint32_t race_id; + uint8_t proficiency_id; + std::string dbstring; + uint32_t clientversion; + }; + + static std::string PrimaryKey() + { + return std::string("merc_type_id"); + } + + static std::vector Columns() + { + return { + "merc_type_id", + "race_id", + "proficiency_id", + "dbstring", + "clientversion", + }; + } + + static std::vector SelectColumns() + { + return { + "merc_type_id", + "race_id", + "proficiency_id", + "dbstring", + "clientversion", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_types"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercTypes NewEntity() + { + MercTypes e{}; + + e.merc_type_id = 0; + e.race_id = 0; + e.proficiency_id = 0; + e.dbstring = ""; + e.clientversion = 0; + + return e; + } + + static MercTypes GetMercTypes( + const std::vector &merc_typess, + int merc_types_id + ) + { + for (auto &merc_types : merc_typess) { + if (merc_types.merc_type_id == merc_types_id) { + return merc_types; + } + } + + return NewEntity(); + } + + static MercTypes FindOne( + Database& db, + int merc_types_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_types_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercTypes e{}; + + e.merc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.race_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.dbstring = row[3] ? row[3] : ""; + e.clientversion = static_cast(strtoul(row[4], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_types_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_types_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercTypes &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.race_id)); + v.push_back(columns[2] + " = " + std::to_string(e.proficiency_id)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.dbstring) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.clientversion)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.merc_type_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercTypes InsertOne( + Database& db, + MercTypes e + ) + { + std::vector v; + + v.push_back(std::to_string(e.merc_type_id)); + v.push_back(std::to_string(e.race_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back("'" + Strings::Escape(e.dbstring) + "'"); + v.push_back(std::to_string(e.clientversion)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.merc_type_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.merc_type_id)); + v.push_back(std::to_string(e.race_id)); + v.push_back(std::to_string(e.proficiency_id)); + v.push_back("'" + Strings::Escape(e.dbstring) + "'"); + v.push_back(std::to_string(e.clientversion)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercTypes e{}; + + e.merc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.race_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.dbstring = row[3] ? row[3] : ""; + e.clientversion = static_cast(strtoul(row[4], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercTypes e{}; + + e.merc_type_id = static_cast(strtoul(row[0], nullptr, 10)); + e.race_id = static_cast(strtoul(row[1], nullptr, 10)); + e.proficiency_id = static_cast(strtoul(row[2], nullptr, 10)); + e.dbstring = row[3] ? row[3] : ""; + e.clientversion = static_cast(strtoul(row[4], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_weaponinfo_repository.h b/common/repositories/base/base_merc_weaponinfo_repository.h new file mode 100644 index 000000000..6ebe444bc --- /dev/null +++ b/common/repositories/base/base_merc_weaponinfo_repository.h @@ -0,0 +1,394 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERC_WEAPONINFO_REPOSITORY_H +#define EQEMU_BASE_MERC_WEAPONINFO_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercWeaponinfoRepository { +public: + struct MercWeaponinfo { + int32_t id; + int32_t merc_npc_type_id; + uint8_t minlevel; + uint8_t maxlevel; + int32_t d_melee_texture1; + int32_t d_melee_texture2; + uint8_t prim_melee_type; + uint8_t sec_melee_type; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "merc_npc_type_id", + "minlevel", + "maxlevel", + "d_melee_texture1", + "d_melee_texture2", + "prim_melee_type", + "sec_melee_type", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "merc_npc_type_id", + "minlevel", + "maxlevel", + "d_melee_texture1", + "d_melee_texture2", + "prim_melee_type", + "sec_melee_type", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("merc_weaponinfo"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static MercWeaponinfo NewEntity() + { + MercWeaponinfo e{}; + + e.id = 0; + e.merc_npc_type_id = 0; + e.minlevel = 0; + e.maxlevel = 0; + e.d_melee_texture1 = 0; + e.d_melee_texture2 = 0; + e.prim_melee_type = 28; + e.sec_melee_type = 28; + + return e; + } + + static MercWeaponinfo GetMercWeaponinfo( + const std::vector &merc_weaponinfos, + int merc_weaponinfo_id + ) + { + for (auto &merc_weaponinfo : merc_weaponinfos) { + if (merc_weaponinfo.id == merc_weaponinfo_id) { + return merc_weaponinfo; + } + } + + return NewEntity(); + } + + static MercWeaponinfo FindOne( + Database& db, + int merc_weaponinfo_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + merc_weaponinfo_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + MercWeaponinfo e{}; + + e.id = static_cast(atoi(row[0])); + e.merc_npc_type_id = static_cast(atoi(row[1])); + e.minlevel = static_cast(strtoul(row[2], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.d_melee_texture1 = static_cast(atoi(row[4])); + e.d_melee_texture2 = static_cast(atoi(row[5])); + e.prim_melee_type = static_cast(strtoul(row[6], nullptr, 10)); + e.sec_melee_type = static_cast(strtoul(row[7], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int merc_weaponinfo_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + merc_weaponinfo_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const MercWeaponinfo &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.merc_npc_type_id)); + v.push_back(columns[2] + " = " + std::to_string(e.minlevel)); + v.push_back(columns[3] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[4] + " = " + std::to_string(e.d_melee_texture1)); + v.push_back(columns[5] + " = " + std::to_string(e.d_melee_texture2)); + v.push_back(columns[6] + " = " + std::to_string(e.prim_melee_type)); + v.push_back(columns[7] + " = " + std::to_string(e.sec_melee_type)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static MercWeaponinfo InsertOne( + Database& db, + MercWeaponinfo e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.d_melee_texture1)); + v.push_back(std::to_string(e.d_melee_texture2)); + v.push_back(std::to_string(e.prim_melee_type)); + v.push_back(std::to_string(e.sec_melee_type)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.merc_npc_type_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.d_melee_texture1)); + v.push_back(std::to_string(e.d_melee_texture2)); + v.push_back(std::to_string(e.prim_melee_type)); + v.push_back(std::to_string(e.sec_melee_type)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercWeaponinfo e{}; + + e.id = static_cast(atoi(row[0])); + e.merc_npc_type_id = static_cast(atoi(row[1])); + e.minlevel = static_cast(strtoul(row[2], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.d_melee_texture1 = static_cast(atoi(row[4])); + e.d_melee_texture2 = static_cast(atoi(row[5])); + e.prim_melee_type = static_cast(strtoul(row[6], nullptr, 10)); + e.sec_melee_type = static_cast(strtoul(row[7], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + MercWeaponinfo e{}; + + e.id = static_cast(atoi(row[0])); + e.merc_npc_type_id = static_cast(atoi(row[1])); + e.minlevel = static_cast(strtoul(row[2], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.d_melee_texture1 = static_cast(atoi(row[4])); + e.d_melee_texture2 = static_cast(atoi(row[5])); + e.prim_melee_type = static_cast(strtoul(row[6], nullptr, 10)); + e.sec_melee_type = static_cast(strtoul(row[7], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERC_WEAPONINFO_REPOSITORY_H diff --git a/common/repositories/base/base_merchantlist_repository.h b/common/repositories/base/base_merchantlist_repository.h index a447c3426..014a48919 100644 --- a/common/repositories/base/base_merchantlist_repository.h +++ b/common/repositories/base/base_merchantlist_repository.h @@ -13,22 +13,25 @@ #define EQEMU_BASE_MERCHANTLIST_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseMerchantlistRepository { public: struct Merchantlist { - int merchantid; - int slot; - int item; - int faction_required; - int level_required; - int alt_currency_cost; - int classes_required; - int probability; - int min_expansion; - int max_expansion; + int32_t merchantid; + int32_t slot; + int32_t item; + int16_t faction_required; + uint8_t level_required; + uint16_t alt_currency_cost; + int32_t classes_required; + int32_t probability; + std::string bucket_name; + std::string bucket_value; + uint8_t bucket_comparison; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -49,6 +52,9 @@ public: "alt_currency_cost", "classes_required", "probability", + "bucket_name", + "bucket_value", + "bucket_comparison", "min_expansion", "max_expansion", "content_flags", @@ -67,6 +73,9 @@ public: "alt_currency_cost", "classes_required", "probability", + "bucket_name", + "bucket_value", + "bucket_comparison", "min_expansion", "max_expansion", "content_flags", @@ -76,12 +85,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -109,25 +118,28 @@ public: static Merchantlist NewEntity() { - Merchantlist entry{}; + Merchantlist e{}; - entry.merchantid = 0; - entry.slot = 0; - entry.item = 0; - entry.faction_required = -100; - entry.level_required = 0; - entry.alt_currency_cost = 0; - entry.classes_required = 65535; - entry.probability = 100; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.merchantid = 0; + e.slot = 0; + e.item = 0; + e.faction_required = -100; + e.level_required = 0; + e.alt_currency_cost = 0; + e.classes_required = 65535; + e.probability = 100; + e.bucket_name = ""; + e.bucket_value = ""; + e.bucket_comparison = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Merchantlist GetMerchantlistEntry( + static Merchantlist GetMerchantlist( const std::vector &merchantlists, int merchantlist_id ) @@ -156,22 +168,25 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Merchantlist entry{}; + Merchantlist e{}; - entry.merchantid = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.item = atoi(row[2]); - entry.faction_required = atoi(row[3]); - entry.level_required = atoi(row[4]); - entry.alt_currency_cost = atoi(row[5]); - entry.classes_required = atoi(row[6]); - entry.probability = atoi(row[7]); - entry.min_expansion = atoi(row[8]); - entry.max_expansion = atoi(row[9]); - entry.content_flags = row[10] ? row[10] : ""; - entry.content_flags_disabled = row[11] ? row[11] : ""; + e.merchantid = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.item = static_cast(atoi(row[2])); + e.faction_required = static_cast(atoi(row[3])); + e.level_required = static_cast(strtoul(row[4], nullptr, 10)); + e.alt_currency_cost = static_cast(strtoul(row[5], nullptr, 10)); + e.classes_required = static_cast(atoi(row[6])); + e.probability = static_cast(atoi(row[7])); + e.bucket_name = row[8] ? row[8] : ""; + e.bucket_value = row[9] ? row[9] : ""; + e.bucket_comparison = static_cast(strtoul(row[10], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[11])); + e.max_expansion = static_cast(atoi(row[12])); + e.content_flags = row[13] ? row[13] : ""; + e.content_flags_disabled = row[14] ? row[14] : ""; - return entry; + return e; } return NewEntity(); @@ -196,33 +211,36 @@ public: static int UpdateOne( Database& db, - Merchantlist merchantlist_entry + const Merchantlist &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(merchantlist_entry.merchantid)); - update_values.push_back(columns[1] + " = " + std::to_string(merchantlist_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(merchantlist_entry.item)); - update_values.push_back(columns[3] + " = " + std::to_string(merchantlist_entry.faction_required)); - update_values.push_back(columns[4] + " = " + std::to_string(merchantlist_entry.level_required)); - update_values.push_back(columns[5] + " = " + std::to_string(merchantlist_entry.alt_currency_cost)); - update_values.push_back(columns[6] + " = " + std::to_string(merchantlist_entry.classes_required)); - update_values.push_back(columns[7] + " = " + std::to_string(merchantlist_entry.probability)); - update_values.push_back(columns[8] + " = " + std::to_string(merchantlist_entry.min_expansion)); - update_values.push_back(columns[9] + " = " + std::to_string(merchantlist_entry.max_expansion)); - update_values.push_back(columns[10] + " = '" + EscapeString(merchantlist_entry.content_flags) + "'"); - update_values.push_back(columns[11] + " = '" + EscapeString(merchantlist_entry.content_flags_disabled) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.merchantid)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.item)); + v.push_back(columns[3] + " = " + std::to_string(e.faction_required)); + v.push_back(columns[4] + " = " + std::to_string(e.level_required)); + v.push_back(columns[5] + " = " + std::to_string(e.alt_currency_cost)); + v.push_back(columns[6] + " = " + std::to_string(e.classes_required)); + v.push_back(columns[7] + " = " + std::to_string(e.probability)); + v.push_back(columns[8] + " = '" + Strings::Escape(e.bucket_name) + "'"); + v.push_back(columns[9] + " = '" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(columns[10] + " = " + std::to_string(e.bucket_comparison)); + v.push_back(columns[11] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[12] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[13] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - merchantlist_entry.merchantid + e.merchantid ) ); @@ -231,75 +249,81 @@ public: static Merchantlist InsertOne( Database& db, - Merchantlist merchantlist_entry + Merchantlist e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(merchantlist_entry.merchantid)); - insert_values.push_back(std::to_string(merchantlist_entry.slot)); - insert_values.push_back(std::to_string(merchantlist_entry.item)); - insert_values.push_back(std::to_string(merchantlist_entry.faction_required)); - insert_values.push_back(std::to_string(merchantlist_entry.level_required)); - insert_values.push_back(std::to_string(merchantlist_entry.alt_currency_cost)); - insert_values.push_back(std::to_string(merchantlist_entry.classes_required)); - insert_values.push_back(std::to_string(merchantlist_entry.probability)); - insert_values.push_back(std::to_string(merchantlist_entry.min_expansion)); - insert_values.push_back(std::to_string(merchantlist_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(merchantlist_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(merchantlist_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.merchantid)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item)); + v.push_back(std::to_string(e.faction_required)); + v.push_back(std::to_string(e.level_required)); + v.push_back(std::to_string(e.alt_currency_cost)); + v.push_back(std::to_string(e.classes_required)); + v.push_back(std::to_string(e.probability)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - merchantlist_entry.merchantid = results.LastInsertedID(); - return merchantlist_entry; + e.merchantid = results.LastInsertedID(); + return e; } - merchantlist_entry = NewEntity(); + e = NewEntity(); - return merchantlist_entry; + return e; } static int InsertMany( Database& db, - std::vector merchantlist_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &merchantlist_entry: merchantlist_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(merchantlist_entry.merchantid)); - insert_values.push_back(std::to_string(merchantlist_entry.slot)); - insert_values.push_back(std::to_string(merchantlist_entry.item)); - insert_values.push_back(std::to_string(merchantlist_entry.faction_required)); - insert_values.push_back(std::to_string(merchantlist_entry.level_required)); - insert_values.push_back(std::to_string(merchantlist_entry.alt_currency_cost)); - insert_values.push_back(std::to_string(merchantlist_entry.classes_required)); - insert_values.push_back(std::to_string(merchantlist_entry.probability)); - insert_values.push_back(std::to_string(merchantlist_entry.min_expansion)); - insert_values.push_back(std::to_string(merchantlist_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(merchantlist_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(merchantlist_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.merchantid)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item)); + v.push_back(std::to_string(e.faction_required)); + v.push_back(std::to_string(e.level_required)); + v.push_back(std::to_string(e.alt_currency_cost)); + v.push_back(std::to_string(e.classes_required)); + v.push_back(std::to_string(e.probability)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -320,28 +344,31 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Merchantlist entry{}; + Merchantlist e{}; - entry.merchantid = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.item = atoi(row[2]); - entry.faction_required = atoi(row[3]); - entry.level_required = atoi(row[4]); - entry.alt_currency_cost = atoi(row[5]); - entry.classes_required = atoi(row[6]); - entry.probability = atoi(row[7]); - entry.min_expansion = atoi(row[8]); - entry.max_expansion = atoi(row[9]); - entry.content_flags = row[10] ? row[10] : ""; - entry.content_flags_disabled = row[11] ? row[11] : ""; + e.merchantid = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.item = static_cast(atoi(row[2])); + e.faction_required = static_cast(atoi(row[3])); + e.level_required = static_cast(strtoul(row[4], nullptr, 10)); + e.alt_currency_cost = static_cast(strtoul(row[5], nullptr, 10)); + e.classes_required = static_cast(atoi(row[6])); + e.probability = static_cast(atoi(row[7])); + e.bucket_name = row[8] ? row[8] : ""; + e.bucket_value = row[9] ? row[9] : ""; + e.bucket_comparison = static_cast(strtoul(row[10], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[11])); + e.max_expansion = static_cast(atoi(row[12])); + e.content_flags = row[13] ? row[13] : ""; + e.content_flags_disabled = row[14] ? row[14] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -356,28 +383,31 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Merchantlist entry{}; + Merchantlist e{}; - entry.merchantid = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.item = atoi(row[2]); - entry.faction_required = atoi(row[3]); - entry.level_required = atoi(row[4]); - entry.alt_currency_cost = atoi(row[5]); - entry.classes_required = atoi(row[6]); - entry.probability = atoi(row[7]); - entry.min_expansion = atoi(row[8]); - entry.max_expansion = atoi(row[9]); - entry.content_flags = row[10] ? row[10] : ""; - entry.content_flags_disabled = row[11] ? row[11] : ""; + e.merchantid = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.item = static_cast(atoi(row[2])); + e.faction_required = static_cast(atoi(row[3])); + e.level_required = static_cast(strtoul(row[4], nullptr, 10)); + e.alt_currency_cost = static_cast(strtoul(row[5], nullptr, 10)); + e.classes_required = static_cast(atoi(row[6])); + e.probability = static_cast(atoi(row[7])); + e.bucket_name = row[8] ? row[8] : ""; + e.bucket_value = row[9] ? row[9] : ""; + e.bucket_comparison = static_cast(strtoul(row[10], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[11])); + e.max_expansion = static_cast(atoi(row[12])); + e.content_flags = row[13] ? row[13] : ""; + e.content_flags_disabled = row[14] ? row[14] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -402,6 +432,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_MERCHANTLIST_REPOSITORY_H diff --git a/common/repositories/base/base_merchantlist_temp_repository.h b/common/repositories/base/base_merchantlist_temp_repository.h index c31f886dd..99f25da49 100644 --- a/common/repositories/base/base_merchantlist_temp_repository.h +++ b/common/repositories/base/base_merchantlist_temp_repository.h @@ -13,16 +13,18 @@ #define EQEMU_BASE_MERCHANTLIST_TEMP_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseMerchantlistTempRepository { public: struct MerchantlistTemp { - int npcid; - int slot; - int itemid; - int charges; + uint32_t npcid; + uint8_t slot; + int32_t zone_id; + int32_t instance_id; + uint32_t itemid; + uint32_t charges; }; static std::string PrimaryKey() @@ -35,6 +37,8 @@ public: return { "npcid", "slot", + "zone_id", + "instance_id", "itemid", "charges", }; @@ -45,6 +49,8 @@ public: return { "npcid", "slot", + "zone_id", + "instance_id", "itemid", "charges", }; @@ -52,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +91,19 @@ public: static MerchantlistTemp NewEntity() { - MerchantlistTemp entry{}; + MerchantlistTemp e{}; - entry.npcid = 0; - entry.slot = 0; - entry.itemid = 0; - entry.charges = 1; + e.npcid = 0; + e.slot = 0; + e.zone_id = 0; + e.instance_id = 0; + e.itemid = 0; + e.charges = 1; - return entry; + return e; } - static MerchantlistTemp GetMerchantlistTempEntry( + static MerchantlistTemp GetMerchantlistTemp( const std::vector &merchantlist_temps, int merchantlist_temp_id ) @@ -124,14 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - MerchantlistTemp entry{}; + MerchantlistTemp e{}; - entry.npcid = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); + e.npcid = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.zone_id = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); + e.itemid = static_cast(strtoul(row[4], nullptr, 10)); + e.charges = static_cast(strtoul(row[5], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -156,25 +166,27 @@ public: static int UpdateOne( Database& db, - MerchantlistTemp merchantlist_temp_entry + const MerchantlistTemp &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(merchantlist_temp_entry.npcid)); - update_values.push_back(columns[1] + " = " + std::to_string(merchantlist_temp_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(merchantlist_temp_entry.itemid)); - update_values.push_back(columns[3] + " = " + std::to_string(merchantlist_temp_entry.charges)); + v.push_back(columns[0] + " = " + std::to_string(e.npcid)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[3] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[4] + " = " + std::to_string(e.itemid)); + v.push_back(columns[5] + " = " + std::to_string(e.charges)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - merchantlist_temp_entry.npcid + e.npcid ) ); @@ -183,59 +195,63 @@ public: static MerchantlistTemp InsertOne( Database& db, - MerchantlistTemp merchantlist_temp_entry + MerchantlistTemp e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(merchantlist_temp_entry.npcid)); - insert_values.push_back(std::to_string(merchantlist_temp_entry.slot)); - insert_values.push_back(std::to_string(merchantlist_temp_entry.itemid)); - insert_values.push_back(std::to_string(merchantlist_temp_entry.charges)); + v.push_back(std::to_string(e.npcid)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - merchantlist_temp_entry.npcid = results.LastInsertedID(); - return merchantlist_temp_entry; + e.npcid = results.LastInsertedID(); + return e; } - merchantlist_temp_entry = NewEntity(); + e = NewEntity(); - return merchantlist_temp_entry; + return e; } static int InsertMany( Database& db, - std::vector merchantlist_temp_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &merchantlist_temp_entry: merchantlist_temp_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(merchantlist_temp_entry.npcid)); - insert_values.push_back(std::to_string(merchantlist_temp_entry.slot)); - insert_values.push_back(std::to_string(merchantlist_temp_entry.itemid)); - insert_values.push_back(std::to_string(merchantlist_temp_entry.charges)); + v.push_back(std::to_string(e.npcid)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - MerchantlistTemp entry{}; + MerchantlistTemp e{}; - entry.npcid = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); + e.npcid = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.zone_id = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); + e.itemid = static_cast(strtoul(row[4], nullptr, 10)); + e.charges = static_cast(strtoul(row[5], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - MerchantlistTemp entry{}; + MerchantlistTemp e{}; - entry.npcid = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); + e.npcid = static_cast(strtoul(row[0], nullptr, 10)); + e.slot = static_cast(strtoul(row[1], nullptr, 10)); + e.zone_id = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); + e.itemid = static_cast(strtoul(row[4], nullptr, 10)); + e.charges = static_cast(strtoul(row[5], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_MERCHANTLIST_TEMP_REPOSITORY_H diff --git a/common/repositories/base/base_mercs_repository.h b/common/repositories/base/base_mercs_repository.h new file mode 100644 index 000000000..9ddb84bde --- /dev/null +++ b/common/repositories/base/base_mercs_repository.h @@ -0,0 +1,554 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_MERCS_REPOSITORY_H +#define EQEMU_BASE_MERCS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + + +class BaseMercsRepository { +public: + struct Mercs { + uint32_t MercID; + uint32_t OwnerCharacterID; + uint8_t Slot; + std::string Name; + uint32_t TemplateID; + uint32_t SuspendedTime; + uint8_t IsSuspended; + uint32_t TimerRemaining; + uint8_t Gender; + float MercSize; + uint8_t StanceID; + uint32_t HP; + uint32_t Mana; + uint32_t Endurance; + uint32_t Face; + uint32_t LuclinHairStyle; + uint32_t LuclinHairColor; + uint32_t LuclinEyeColor; + uint32_t LuclinEyeColor2; + uint32_t LuclinBeardColor; + uint32_t LuclinBeard; + uint32_t DrakkinHeritage; + uint32_t DrakkinTattoo; + uint32_t DrakkinDetails; + }; + + static std::string PrimaryKey() + { + return std::string("MercID"); + } + + static std::vector Columns() + { + return { + "MercID", + "OwnerCharacterID", + "Slot", + "Name", + "TemplateID", + "SuspendedTime", + "IsSuspended", + "TimerRemaining", + "Gender", + "MercSize", + "StanceID", + "HP", + "Mana", + "Endurance", + "Face", + "LuclinHairStyle", + "LuclinHairColor", + "LuclinEyeColor", + "LuclinEyeColor2", + "LuclinBeardColor", + "LuclinBeard", + "DrakkinHeritage", + "DrakkinTattoo", + "DrakkinDetails", + }; + } + + static std::vector SelectColumns() + { + return { + "MercID", + "OwnerCharacterID", + "Slot", + "Name", + "TemplateID", + "SuspendedTime", + "IsSuspended", + "TimerRemaining", + "Gender", + "MercSize", + "StanceID", + "HP", + "Mana", + "Endurance", + "Face", + "LuclinHairStyle", + "LuclinHairColor", + "LuclinEyeColor", + "LuclinEyeColor2", + "LuclinBeardColor", + "LuclinBeard", + "DrakkinHeritage", + "DrakkinTattoo", + "DrakkinDetails", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("mercs"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static Mercs NewEntity() + { + Mercs e{}; + + e.MercID = 0; + e.OwnerCharacterID = 0; + e.Slot = 0; + e.Name = ""; + e.TemplateID = 0; + e.SuspendedTime = 0; + e.IsSuspended = 0; + e.TimerRemaining = 0; + e.Gender = 0; + e.MercSize = 5; + e.StanceID = 0; + e.HP = 0; + e.Mana = 0; + e.Endurance = 0; + e.Face = 1; + e.LuclinHairStyle = 1; + e.LuclinHairColor = 1; + e.LuclinEyeColor = 1; + e.LuclinEyeColor2 = 1; + e.LuclinBeardColor = 1; + e.LuclinBeard = 0; + e.DrakkinHeritage = 0; + e.DrakkinTattoo = 0; + e.DrakkinDetails = 0; + + return e; + } + + static Mercs GetMercs( + const std::vector &mercss, + int mercs_id + ) + { + for (auto &mercs : mercss) { + if (mercs.MercID == mercs_id) { + return mercs; + } + } + + return NewEntity(); + } + + static Mercs FindOne( + Database& db, + int mercs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + mercs_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + Mercs e{}; + + e.MercID = static_cast(strtoul(row[0], nullptr, 10)); + e.OwnerCharacterID = static_cast(strtoul(row[1], nullptr, 10)); + e.Slot = static_cast(strtoul(row[2], nullptr, 10)); + e.Name = row[3] ? row[3] : ""; + e.TemplateID = static_cast(strtoul(row[4], nullptr, 10)); + e.SuspendedTime = static_cast(strtoul(row[5], nullptr, 10)); + e.IsSuspended = static_cast(strtoul(row[6], nullptr, 10)); + e.TimerRemaining = static_cast(strtoul(row[7], nullptr, 10)); + e.Gender = static_cast(strtoul(row[8], nullptr, 10)); + e.MercSize = strtof(row[9], nullptr); + e.StanceID = static_cast(strtoul(row[10], nullptr, 10)); + e.HP = static_cast(strtoul(row[11], nullptr, 10)); + e.Mana = static_cast(strtoul(row[12], nullptr, 10)); + e.Endurance = static_cast(strtoul(row[13], nullptr, 10)); + e.Face = static_cast(strtoul(row[14], nullptr, 10)); + e.LuclinHairStyle = static_cast(strtoul(row[15], nullptr, 10)); + e.LuclinHairColor = static_cast(strtoul(row[16], nullptr, 10)); + e.LuclinEyeColor = static_cast(strtoul(row[17], nullptr, 10)); + e.LuclinEyeColor2 = static_cast(strtoul(row[18], nullptr, 10)); + e.LuclinBeardColor = static_cast(strtoul(row[19], nullptr, 10)); + e.LuclinBeard = static_cast(strtoul(row[20], nullptr, 10)); + e.DrakkinHeritage = static_cast(strtoul(row[21], nullptr, 10)); + e.DrakkinTattoo = static_cast(strtoul(row[22], nullptr, 10)); + e.DrakkinDetails = static_cast(strtoul(row[23], nullptr, 10)); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int mercs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + mercs_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const Mercs &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.OwnerCharacterID)); + v.push_back(columns[2] + " = " + std::to_string(e.Slot)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.Name) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.TemplateID)); + v.push_back(columns[5] + " = " + std::to_string(e.SuspendedTime)); + v.push_back(columns[6] + " = " + std::to_string(e.IsSuspended)); + v.push_back(columns[7] + " = " + std::to_string(e.TimerRemaining)); + v.push_back(columns[8] + " = " + std::to_string(e.Gender)); + v.push_back(columns[9] + " = " + std::to_string(e.MercSize)); + v.push_back(columns[10] + " = " + std::to_string(e.StanceID)); + v.push_back(columns[11] + " = " + std::to_string(e.HP)); + v.push_back(columns[12] + " = " + std::to_string(e.Mana)); + v.push_back(columns[13] + " = " + std::to_string(e.Endurance)); + v.push_back(columns[14] + " = " + std::to_string(e.Face)); + v.push_back(columns[15] + " = " + std::to_string(e.LuclinHairStyle)); + v.push_back(columns[16] + " = " + std::to_string(e.LuclinHairColor)); + v.push_back(columns[17] + " = " + std::to_string(e.LuclinEyeColor)); + v.push_back(columns[18] + " = " + std::to_string(e.LuclinEyeColor2)); + v.push_back(columns[19] + " = " + std::to_string(e.LuclinBeardColor)); + v.push_back(columns[20] + " = " + std::to_string(e.LuclinBeard)); + v.push_back(columns[21] + " = " + std::to_string(e.DrakkinHeritage)); + v.push_back(columns[22] + " = " + std::to_string(e.DrakkinTattoo)); + v.push_back(columns[23] + " = " + std::to_string(e.DrakkinDetails)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.MercID + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static Mercs InsertOne( + Database& db, + Mercs e + ) + { + std::vector v; + + v.push_back(std::to_string(e.MercID)); + v.push_back(std::to_string(e.OwnerCharacterID)); + v.push_back(std::to_string(e.Slot)); + v.push_back("'" + Strings::Escape(e.Name) + "'"); + v.push_back(std::to_string(e.TemplateID)); + v.push_back(std::to_string(e.SuspendedTime)); + v.push_back(std::to_string(e.IsSuspended)); + v.push_back(std::to_string(e.TimerRemaining)); + v.push_back(std::to_string(e.Gender)); + v.push_back(std::to_string(e.MercSize)); + v.push_back(std::to_string(e.StanceID)); + v.push_back(std::to_string(e.HP)); + v.push_back(std::to_string(e.Mana)); + v.push_back(std::to_string(e.Endurance)); + v.push_back(std::to_string(e.Face)); + v.push_back(std::to_string(e.LuclinHairStyle)); + v.push_back(std::to_string(e.LuclinHairColor)); + v.push_back(std::to_string(e.LuclinEyeColor)); + v.push_back(std::to_string(e.LuclinEyeColor2)); + v.push_back(std::to_string(e.LuclinBeardColor)); + v.push_back(std::to_string(e.LuclinBeard)); + v.push_back(std::to_string(e.DrakkinHeritage)); + v.push_back(std::to_string(e.DrakkinTattoo)); + v.push_back(std::to_string(e.DrakkinDetails)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.MercID = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.MercID)); + v.push_back(std::to_string(e.OwnerCharacterID)); + v.push_back(std::to_string(e.Slot)); + v.push_back("'" + Strings::Escape(e.Name) + "'"); + v.push_back(std::to_string(e.TemplateID)); + v.push_back(std::to_string(e.SuspendedTime)); + v.push_back(std::to_string(e.IsSuspended)); + v.push_back(std::to_string(e.TimerRemaining)); + v.push_back(std::to_string(e.Gender)); + v.push_back(std::to_string(e.MercSize)); + v.push_back(std::to_string(e.StanceID)); + v.push_back(std::to_string(e.HP)); + v.push_back(std::to_string(e.Mana)); + v.push_back(std::to_string(e.Endurance)); + v.push_back(std::to_string(e.Face)); + v.push_back(std::to_string(e.LuclinHairStyle)); + v.push_back(std::to_string(e.LuclinHairColor)); + v.push_back(std::to_string(e.LuclinEyeColor)); + v.push_back(std::to_string(e.LuclinEyeColor2)); + v.push_back(std::to_string(e.LuclinBeardColor)); + v.push_back(std::to_string(e.LuclinBeard)); + v.push_back(std::to_string(e.DrakkinHeritage)); + v.push_back(std::to_string(e.DrakkinTattoo)); + v.push_back(std::to_string(e.DrakkinDetails)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + Mercs e{}; + + e.MercID = static_cast(strtoul(row[0], nullptr, 10)); + e.OwnerCharacterID = static_cast(strtoul(row[1], nullptr, 10)); + e.Slot = static_cast(strtoul(row[2], nullptr, 10)); + e.Name = row[3] ? row[3] : ""; + e.TemplateID = static_cast(strtoul(row[4], nullptr, 10)); + e.SuspendedTime = static_cast(strtoul(row[5], nullptr, 10)); + e.IsSuspended = static_cast(strtoul(row[6], nullptr, 10)); + e.TimerRemaining = static_cast(strtoul(row[7], nullptr, 10)); + e.Gender = static_cast(strtoul(row[8], nullptr, 10)); + e.MercSize = strtof(row[9], nullptr); + e.StanceID = static_cast(strtoul(row[10], nullptr, 10)); + e.HP = static_cast(strtoul(row[11], nullptr, 10)); + e.Mana = static_cast(strtoul(row[12], nullptr, 10)); + e.Endurance = static_cast(strtoul(row[13], nullptr, 10)); + e.Face = static_cast(strtoul(row[14], nullptr, 10)); + e.LuclinHairStyle = static_cast(strtoul(row[15], nullptr, 10)); + e.LuclinHairColor = static_cast(strtoul(row[16], nullptr, 10)); + e.LuclinEyeColor = static_cast(strtoul(row[17], nullptr, 10)); + e.LuclinEyeColor2 = static_cast(strtoul(row[18], nullptr, 10)); + e.LuclinBeardColor = static_cast(strtoul(row[19], nullptr, 10)); + e.LuclinBeard = static_cast(strtoul(row[20], nullptr, 10)); + e.DrakkinHeritage = static_cast(strtoul(row[21], nullptr, 10)); + e.DrakkinTattoo = static_cast(strtoul(row[22], nullptr, 10)); + e.DrakkinDetails = static_cast(strtoul(row[23], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + Mercs e{}; + + e.MercID = static_cast(strtoul(row[0], nullptr, 10)); + e.OwnerCharacterID = static_cast(strtoul(row[1], nullptr, 10)); + e.Slot = static_cast(strtoul(row[2], nullptr, 10)); + e.Name = row[3] ? row[3] : ""; + e.TemplateID = static_cast(strtoul(row[4], nullptr, 10)); + e.SuspendedTime = static_cast(strtoul(row[5], nullptr, 10)); + e.IsSuspended = static_cast(strtoul(row[6], nullptr, 10)); + e.TimerRemaining = static_cast(strtoul(row[7], nullptr, 10)); + e.Gender = static_cast(strtoul(row[8], nullptr, 10)); + e.MercSize = strtof(row[9], nullptr); + e.StanceID = static_cast(strtoul(row[10], nullptr, 10)); + e.HP = static_cast(strtoul(row[11], nullptr, 10)); + e.Mana = static_cast(strtoul(row[12], nullptr, 10)); + e.Endurance = static_cast(strtoul(row[13], nullptr, 10)); + e.Face = static_cast(strtoul(row[14], nullptr, 10)); + e.LuclinHairStyle = static_cast(strtoul(row[15], nullptr, 10)); + e.LuclinHairColor = static_cast(strtoul(row[16], nullptr, 10)); + e.LuclinEyeColor = static_cast(strtoul(row[17], nullptr, 10)); + e.LuclinEyeColor2 = static_cast(strtoul(row[18], nullptr, 10)); + e.LuclinBeardColor = static_cast(strtoul(row[19], nullptr, 10)); + e.LuclinBeard = static_cast(strtoul(row[20], nullptr, 10)); + e.DrakkinHeritage = static_cast(strtoul(row[21], nullptr, 10)); + e.DrakkinTattoo = static_cast(strtoul(row[22], nullptr, 10)); + e.DrakkinDetails = static_cast(strtoul(row[23], nullptr, 10)); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_MERCS_REPOSITORY_H diff --git a/common/repositories/base/base_name_filter_repository.h b/common/repositories/base/base_name_filter_repository.h index fbf9da8f3..24125c098 100644 --- a/common/repositories/base/base_name_filter_repository.h +++ b/common/repositories/base/base_name_filter_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_NAME_FILTER_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNameFilterRepository { public: struct NameFilter { - int id; + int32_t id; std::string name; }; @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static NameFilter NewEntity() { - NameFilter entry{}; + NameFilter e{}; - entry.id = 0; - entry.name = ""; + e.id = 0; + e.name = ""; - return entry; + return e; } - static NameFilter GetNameFilterEntry( + static NameFilter GetNameFilter( const std::vector &name_filters, int name_filter_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NameFilter entry{}; + NameFilter e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; - return entry; + return e; } return NewEntity(); @@ -146,22 +146,22 @@ public: static int UpdateOne( Database& db, - NameFilter name_filter_entry + const NameFilter &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(name_filter_entry.name) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - name_filter_entry.id + e.id ) ); @@ -170,55 +170,55 @@ public: static NameFilter InsertOne( Database& db, - NameFilter name_filter_entry + NameFilter e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(name_filter_entry.id)); - insert_values.push_back("'" + EscapeString(name_filter_entry.name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - name_filter_entry.id = results.LastInsertedID(); - return name_filter_entry; + e.id = results.LastInsertedID(); + return e; } - name_filter_entry = NewEntity(); + e = NewEntity(); - return name_filter_entry; + return e; } static int InsertMany( Database& db, - std::vector name_filter_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &name_filter_entry: name_filter_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(name_filter_entry.id)); - insert_values.push_back("'" + EscapeString(name_filter_entry.name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -239,18 +239,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NameFilter entry{}; + NameFilter e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -265,18 +265,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NameFilter entry{}; + NameFilter e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -301,6 +301,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NAME_FILTER_REPOSITORY_H diff --git a/common/repositories/base/base_npc_emotes_repository.h b/common/repositories/base/base_npc_emotes_repository.h index 86f3e418c..6e2e5b37d 100644 --- a/common/repositories/base/base_npc_emotes_repository.h +++ b/common/repositories/base/base_npc_emotes_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_NPC_EMOTES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcEmotesRepository { public: struct NpcEmotes { - int id; - int emoteid; - int event_; - int type; + int32_t id; + uint32_t emoteid; + int8_t event_; + int8_t type; std::string text; }; @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static NpcEmotes NewEntity() { - NpcEmotes entry{}; + NpcEmotes e{}; - entry.id = 0; - entry.emoteid = 0; - entry.event_ = 0; - entry.type = 0; - entry.text = ""; + e.id = 0; + e.emoteid = 0; + e.event_ = 0; + e.type = 0; + e.text = ""; - return entry; + return e; } - static NpcEmotes GetNpcEmotesEntry( + static NpcEmotes GetNpcEmotes( const std::vector &npc_emotess, int npc_emotes_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcEmotes entry{}; + NpcEmotes e{}; - entry.id = atoi(row[0]); - entry.emoteid = atoi(row[1]); - entry.event_ = atoi(row[2]); - entry.type = atoi(row[3]); - entry.text = row[4] ? row[4] : ""; + e.id = static_cast(atoi(row[0])); + e.emoteid = static_cast(strtoul(row[1], nullptr, 10)); + e.event_ = static_cast(atoi(row[2])); + e.type = static_cast(atoi(row[3])); + e.text = row[4] ? row[4] : ""; - return entry; + return e; } return NewEntity(); @@ -161,25 +161,25 @@ public: static int UpdateOne( Database& db, - NpcEmotes npc_emotes_entry + const NpcEmotes &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(npc_emotes_entry.emoteid)); - update_values.push_back(columns[2] + " = " + std::to_string(npc_emotes_entry.event_)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_emotes_entry.type)); - update_values.push_back(columns[4] + " = '" + EscapeString(npc_emotes_entry.text) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.emoteid)); + v.push_back(columns[2] + " = " + std::to_string(e.event_)); + v.push_back(columns[3] + " = " + std::to_string(e.type)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.text) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_emotes_entry.id + e.id ) ); @@ -188,61 +188,61 @@ public: static NpcEmotes InsertOne( Database& db, - NpcEmotes npc_emotes_entry + NpcEmotes e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_emotes_entry.id)); - insert_values.push_back(std::to_string(npc_emotes_entry.emoteid)); - insert_values.push_back(std::to_string(npc_emotes_entry.event_)); - insert_values.push_back(std::to_string(npc_emotes_entry.type)); - insert_values.push_back("'" + EscapeString(npc_emotes_entry.text) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.emoteid)); + v.push_back(std::to_string(e.event_)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.text) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_emotes_entry.id = results.LastInsertedID(); - return npc_emotes_entry; + e.id = results.LastInsertedID(); + return e; } - npc_emotes_entry = NewEntity(); + e = NewEntity(); - return npc_emotes_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_emotes_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_emotes_entry: npc_emotes_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_emotes_entry.id)); - insert_values.push_back(std::to_string(npc_emotes_entry.emoteid)); - insert_values.push_back(std::to_string(npc_emotes_entry.event_)); - insert_values.push_back(std::to_string(npc_emotes_entry.type)); - insert_values.push_back("'" + EscapeString(npc_emotes_entry.text) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.emoteid)); + v.push_back(std::to_string(e.event_)); + v.push_back(std::to_string(e.type)); + v.push_back("'" + Strings::Escape(e.text) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -263,21 +263,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcEmotes entry{}; + NpcEmotes e{}; - entry.id = atoi(row[0]); - entry.emoteid = atoi(row[1]); - entry.event_ = atoi(row[2]); - entry.type = atoi(row[3]); - entry.text = row[4] ? row[4] : ""; + e.id = static_cast(atoi(row[0])); + e.emoteid = static_cast(strtoul(row[1], nullptr, 10)); + e.event_ = static_cast(atoi(row[2])); + e.type = static_cast(atoi(row[3])); + e.text = row[4] ? row[4] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -292,21 +292,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcEmotes entry{}; + NpcEmotes e{}; - entry.id = atoi(row[0]); - entry.emoteid = atoi(row[1]); - entry.event_ = atoi(row[2]); - entry.type = atoi(row[3]); - entry.text = row[4] ? row[4] : ""; + e.id = static_cast(atoi(row[0])); + e.emoteid = static_cast(strtoul(row[1], nullptr, 10)); + e.event_ = static_cast(atoi(row[2])); + e.type = static_cast(atoi(row[3])); + e.text = row[4] ? row[4] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -331,6 +331,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_EMOTES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_faction_entries_repository.h b/common/repositories/base/base_npc_faction_entries_repository.h index d7a27f6a7..44a24a00e 100644 --- a/common/repositories/base/base_npc_faction_entries_repository.h +++ b/common/repositories/base/base_npc_faction_entries_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_NPC_FACTION_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcFactionEntriesRepository { public: struct NpcFactionEntries { - int npc_faction_id; - int faction_id; - int value; - int npc_value; - int temp; + uint32_t npc_faction_id; + uint32_t faction_id; + int32_t value; + int8_t npc_value; + int8_t temp; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static NpcFactionEntries NewEntity() { - NpcFactionEntries entry{}; + NpcFactionEntries e{}; - entry.npc_faction_id = 0; - entry.faction_id = 0; - entry.value = 0; - entry.npc_value = 0; - entry.temp = 0; + e.npc_faction_id = 0; + e.faction_id = 0; + e.value = 0; + e.npc_value = 0; + e.temp = 0; - return entry; + return e; } - static NpcFactionEntries GetNpcFactionEntriesEntry( + static NpcFactionEntries GetNpcFactionEntries( const std::vector &npc_faction_entriess, int npc_faction_entries_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcFactionEntries entry{}; + NpcFactionEntries e{}; - entry.npc_faction_id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.value = atoi(row[2]); - entry.npc_value = atoi(row[3]); - entry.temp = atoi(row[4]); + e.npc_faction_id = static_cast(strtoul(row[0], nullptr, 10)); + e.faction_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(atoi(row[2])); + e.npc_value = static_cast(atoi(row[3])); + e.temp = static_cast(atoi(row[4])); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - NpcFactionEntries npc_faction_entries_entry + const NpcFactionEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(npc_faction_entries_entry.npc_faction_id)); - update_values.push_back(columns[1] + " = " + std::to_string(npc_faction_entries_entry.faction_id)); - update_values.push_back(columns[2] + " = " + std::to_string(npc_faction_entries_entry.value)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_faction_entries_entry.npc_value)); - update_values.push_back(columns[4] + " = " + std::to_string(npc_faction_entries_entry.temp)); + v.push_back(columns[0] + " = " + std::to_string(e.npc_faction_id)); + v.push_back(columns[1] + " = " + std::to_string(e.faction_id)); + v.push_back(columns[2] + " = " + std::to_string(e.value)); + v.push_back(columns[3] + " = " + std::to_string(e.npc_value)); + v.push_back(columns[4] + " = " + std::to_string(e.temp)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_faction_entries_entry.npc_faction_id + e.npc_faction_id ) ); @@ -189,61 +189,61 @@ public: static NpcFactionEntries InsertOne( Database& db, - NpcFactionEntries npc_faction_entries_entry + NpcFactionEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_faction_entries_entry.npc_faction_id)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.faction_id)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.value)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.npc_value)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.temp)); + v.push_back(std::to_string(e.npc_faction_id)); + v.push_back(std::to_string(e.faction_id)); + v.push_back(std::to_string(e.value)); + v.push_back(std::to_string(e.npc_value)); + v.push_back(std::to_string(e.temp)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_faction_entries_entry.npc_faction_id = results.LastInsertedID(); - return npc_faction_entries_entry; + e.npc_faction_id = results.LastInsertedID(); + return e; } - npc_faction_entries_entry = NewEntity(); + e = NewEntity(); - return npc_faction_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_faction_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_faction_entries_entry: npc_faction_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_faction_entries_entry.npc_faction_id)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.faction_id)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.value)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.npc_value)); - insert_values.push_back(std::to_string(npc_faction_entries_entry.temp)); + v.push_back(std::to_string(e.npc_faction_id)); + v.push_back(std::to_string(e.faction_id)); + v.push_back(std::to_string(e.value)); + v.push_back(std::to_string(e.npc_value)); + v.push_back(std::to_string(e.temp)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcFactionEntries entry{}; + NpcFactionEntries e{}; - entry.npc_faction_id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.value = atoi(row[2]); - entry.npc_value = atoi(row[3]); - entry.temp = atoi(row[4]); + e.npc_faction_id = static_cast(strtoul(row[0], nullptr, 10)); + e.faction_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(atoi(row[2])); + e.npc_value = static_cast(atoi(row[3])); + e.temp = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcFactionEntries entry{}; + NpcFactionEntries e{}; - entry.npc_faction_id = atoi(row[0]); - entry.faction_id = atoi(row[1]); - entry.value = atoi(row[2]); - entry.npc_value = atoi(row[3]); - entry.temp = atoi(row[4]); + e.npc_faction_id = static_cast(strtoul(row[0], nullptr, 10)); + e.faction_id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(atoi(row[2])); + e.npc_value = static_cast(atoi(row[3])); + e.temp = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_FACTION_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_faction_repository.h b/common/repositories/base/base_npc_faction_repository.h index 02c124608..8c2f87f04 100644 --- a/common/repositories/base/base_npc_faction_repository.h +++ b/common/repositories/base/base_npc_faction_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_NPC_FACTION_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcFactionRepository { public: struct NpcFaction { - int id; + int32_t id; std::string name; - int primaryfaction; - int ignore_primary_assist; + int32_t primaryfaction; + int8_t ignore_primary_assist; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static NpcFaction NewEntity() { - NpcFaction entry{}; + NpcFaction e{}; - entry.id = 0; - entry.name = ""; - entry.primaryfaction = 0; - entry.ignore_primary_assist = 0; + e.id = 0; + e.name = ""; + e.primaryfaction = 0; + e.ignore_primary_assist = 0; - return entry; + return e; } - static NpcFaction GetNpcFactionEntry( + static NpcFaction GetNpcFaction( const std::vector &npc_factions, int npc_faction_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcFaction entry{}; + NpcFaction e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.primaryfaction = atoi(row[2]); - entry.ignore_primary_assist = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.primaryfaction = static_cast(atoi(row[2])); + e.ignore_primary_assist = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,24 +156,24 @@ public: static int UpdateOne( Database& db, - NpcFaction npc_faction_entry + const NpcFaction &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(npc_faction_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(npc_faction_entry.primaryfaction)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_faction_entry.ignore_primary_assist)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.primaryfaction)); + v.push_back(columns[3] + " = " + std::to_string(e.ignore_primary_assist)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_faction_entry.id + e.id ) ); @@ -182,59 +182,59 @@ public: static NpcFaction InsertOne( Database& db, - NpcFaction npc_faction_entry + NpcFaction e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_faction_entry.id)); - insert_values.push_back("'" + EscapeString(npc_faction_entry.name) + "'"); - insert_values.push_back(std::to_string(npc_faction_entry.primaryfaction)); - insert_values.push_back(std::to_string(npc_faction_entry.ignore_primary_assist)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.primaryfaction)); + v.push_back(std::to_string(e.ignore_primary_assist)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_faction_entry.id = results.LastInsertedID(); - return npc_faction_entry; + e.id = results.LastInsertedID(); + return e; } - npc_faction_entry = NewEntity(); + e = NewEntity(); - return npc_faction_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_faction_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_faction_entry: npc_faction_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_faction_entry.id)); - insert_values.push_back("'" + EscapeString(npc_faction_entry.name) + "'"); - insert_values.push_back(std::to_string(npc_faction_entry.primaryfaction)); - insert_values.push_back(std::to_string(npc_faction_entry.ignore_primary_assist)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.primaryfaction)); + v.push_back(std::to_string(e.ignore_primary_assist)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -255,20 +255,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcFaction entry{}; + NpcFaction e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.primaryfaction = atoi(row[2]); - entry.ignore_primary_assist = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.primaryfaction = static_cast(atoi(row[2])); + e.ignore_primary_assist = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -283,20 +283,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcFaction entry{}; + NpcFaction e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.primaryfaction = atoi(row[2]); - entry.ignore_primary_assist = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.primaryfaction = static_cast(atoi(row[2])); + e.ignore_primary_assist = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -321,6 +321,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_FACTION_REPOSITORY_H diff --git a/common/repositories/base/base_npc_scale_global_base_repository.h b/common/repositories/base/base_npc_scale_global_base_repository.h index 323123ecd..c8f6642c8 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -13,39 +13,39 @@ #define EQEMU_BASE_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcScaleGlobalBaseRepository { public: struct NpcScaleGlobalBase { - int type; - int level; - int ac; - int hp; - int accuracy; - int slow_mitigation; - int attack; - int strength; - int stamina; - int dexterity; - int agility; - int intelligence; - int wisdom; - int charisma; - int magic_resist; - int cold_resist; - int fire_resist; - int poison_resist; - int disease_resist; - int corruption_resist; - int physical_resist; - int min_dmg; - int max_dmg; - int hp_regen_rate; - int attack_delay; - int spell_scale; - int heal_scale; + int32_t type; + int32_t level; + int32_t ac; + int32_t hp; + int32_t accuracy; + int32_t slow_mitigation; + int32_t attack; + int32_t strength; + int32_t stamina; + int32_t dexterity; + int32_t agility; + int32_t intelligence; + int32_t wisdom; + int32_t charisma; + int32_t magic_resist; + int32_t cold_resist; + int32_t fire_resist; + int32_t poison_resist; + int32_t disease_resist; + int32_t corruption_resist; + int32_t physical_resist; + int32_t min_dmg; + int32_t max_dmg; + int32_t hp_regen_rate; + int32_t attack_delay; + int32_t spell_scale; + int32_t heal_scale; std::string special_abilities; }; @@ -124,12 +124,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -157,41 +157,41 @@ public: static NpcScaleGlobalBase NewEntity() { - NpcScaleGlobalBase entry{}; + NpcScaleGlobalBase e{}; - entry.type = 0; - entry.level = 0; - entry.ac = 0; - entry.hp = 0; - entry.accuracy = 0; - entry.slow_mitigation = 0; - entry.attack = 0; - entry.strength = 0; - entry.stamina = 0; - entry.dexterity = 0; - entry.agility = 0; - entry.intelligence = 0; - entry.wisdom = 0; - entry.charisma = 0; - entry.magic_resist = 0; - entry.cold_resist = 0; - entry.fire_resist = 0; - entry.poison_resist = 0; - entry.disease_resist = 0; - entry.corruption_resist = 0; - entry.physical_resist = 0; - entry.min_dmg = 0; - entry.max_dmg = 0; - entry.hp_regen_rate = 0; - entry.attack_delay = 0; - entry.spell_scale = 100; - entry.heal_scale = 100; - entry.special_abilities = ""; + e.type = 0; + e.level = 0; + e.ac = 0; + e.hp = 0; + e.accuracy = 0; + e.slow_mitigation = 0; + e.attack = 0; + e.strength = 0; + e.stamina = 0; + e.dexterity = 0; + e.agility = 0; + e.intelligence = 0; + e.wisdom = 0; + e.charisma = 0; + e.magic_resist = 0; + e.cold_resist = 0; + e.fire_resist = 0; + e.poison_resist = 0; + e.disease_resist = 0; + e.corruption_resist = 0; + e.physical_resist = 0; + e.min_dmg = 0; + e.max_dmg = 0; + e.hp_regen_rate = 0; + e.attack_delay = 0; + e.spell_scale = 100; + e.heal_scale = 100; + e.special_abilities = ""; - return entry; + return e; } - static NpcScaleGlobalBase GetNpcScaleGlobalBaseEntry( + static NpcScaleGlobalBase GetNpcScaleGlobalBase( const std::vector &npc_scale_global_bases, int npc_scale_global_base_id ) @@ -220,38 +220,38 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcScaleGlobalBase entry{}; + NpcScaleGlobalBase e{}; - entry.type = atoi(row[0]); - entry.level = atoi(row[1]); - entry.ac = atoi(row[2]); - entry.hp = atoi(row[3]); - entry.accuracy = atoi(row[4]); - entry.slow_mitigation = atoi(row[5]); - entry.attack = atoi(row[6]); - entry.strength = atoi(row[7]); - entry.stamina = atoi(row[8]); - entry.dexterity = atoi(row[9]); - entry.agility = atoi(row[10]); - entry.intelligence = atoi(row[11]); - entry.wisdom = atoi(row[12]); - entry.charisma = atoi(row[13]); - entry.magic_resist = atoi(row[14]); - entry.cold_resist = atoi(row[15]); - entry.fire_resist = atoi(row[16]); - entry.poison_resist = atoi(row[17]); - entry.disease_resist = atoi(row[18]); - entry.corruption_resist = atoi(row[19]); - entry.physical_resist = atoi(row[20]); - entry.min_dmg = atoi(row[21]); - entry.max_dmg = atoi(row[22]); - entry.hp_regen_rate = atoi(row[23]); - entry.attack_delay = atoi(row[24]); - entry.spell_scale = atoi(row[25]); - entry.heal_scale = atoi(row[26]); - entry.special_abilities = row[27] ? row[27] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.ac = static_cast(atoi(row[2])); + e.hp = static_cast(atoi(row[3])); + e.accuracy = static_cast(atoi(row[4])); + e.slow_mitigation = static_cast(atoi(row[5])); + e.attack = static_cast(atoi(row[6])); + e.strength = static_cast(atoi(row[7])); + e.stamina = static_cast(atoi(row[8])); + e.dexterity = static_cast(atoi(row[9])); + e.agility = static_cast(atoi(row[10])); + e.intelligence = static_cast(atoi(row[11])); + e.wisdom = static_cast(atoi(row[12])); + e.charisma = static_cast(atoi(row[13])); + e.magic_resist = static_cast(atoi(row[14])); + e.cold_resist = static_cast(atoi(row[15])); + e.fire_resist = static_cast(atoi(row[16])); + e.poison_resist = static_cast(atoi(row[17])); + e.disease_resist = static_cast(atoi(row[18])); + e.corruption_resist = static_cast(atoi(row[19])); + e.physical_resist = static_cast(atoi(row[20])); + e.min_dmg = static_cast(atoi(row[21])); + e.max_dmg = static_cast(atoi(row[22])); + e.hp_regen_rate = static_cast(atoi(row[23])); + e.attack_delay = static_cast(atoi(row[24])); + e.spell_scale = static_cast(atoi(row[25])); + e.heal_scale = static_cast(atoi(row[26])); + e.special_abilities = row[27] ? row[27] : ""; - return entry; + return e; } return NewEntity(); @@ -276,49 +276,49 @@ public: static int UpdateOne( Database& db, - NpcScaleGlobalBase npc_scale_global_base_entry + const NpcScaleGlobalBase &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(npc_scale_global_base_entry.type)); - update_values.push_back(columns[1] + " = " + std::to_string(npc_scale_global_base_entry.level)); - update_values.push_back(columns[2] + " = " + std::to_string(npc_scale_global_base_entry.ac)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_scale_global_base_entry.hp)); - update_values.push_back(columns[4] + " = " + std::to_string(npc_scale_global_base_entry.accuracy)); - update_values.push_back(columns[5] + " = " + std::to_string(npc_scale_global_base_entry.slow_mitigation)); - update_values.push_back(columns[6] + " = " + std::to_string(npc_scale_global_base_entry.attack)); - update_values.push_back(columns[7] + " = " + std::to_string(npc_scale_global_base_entry.strength)); - update_values.push_back(columns[8] + " = " + std::to_string(npc_scale_global_base_entry.stamina)); - update_values.push_back(columns[9] + " = " + std::to_string(npc_scale_global_base_entry.dexterity)); - update_values.push_back(columns[10] + " = " + std::to_string(npc_scale_global_base_entry.agility)); - update_values.push_back(columns[11] + " = " + std::to_string(npc_scale_global_base_entry.intelligence)); - update_values.push_back(columns[12] + " = " + std::to_string(npc_scale_global_base_entry.wisdom)); - update_values.push_back(columns[13] + " = " + std::to_string(npc_scale_global_base_entry.charisma)); - update_values.push_back(columns[14] + " = " + std::to_string(npc_scale_global_base_entry.magic_resist)); - update_values.push_back(columns[15] + " = " + std::to_string(npc_scale_global_base_entry.cold_resist)); - update_values.push_back(columns[16] + " = " + std::to_string(npc_scale_global_base_entry.fire_resist)); - update_values.push_back(columns[17] + " = " + std::to_string(npc_scale_global_base_entry.poison_resist)); - update_values.push_back(columns[18] + " = " + std::to_string(npc_scale_global_base_entry.disease_resist)); - update_values.push_back(columns[19] + " = " + std::to_string(npc_scale_global_base_entry.corruption_resist)); - update_values.push_back(columns[20] + " = " + std::to_string(npc_scale_global_base_entry.physical_resist)); - update_values.push_back(columns[21] + " = " + std::to_string(npc_scale_global_base_entry.min_dmg)); - update_values.push_back(columns[22] + " = " + std::to_string(npc_scale_global_base_entry.max_dmg)); - update_values.push_back(columns[23] + " = " + std::to_string(npc_scale_global_base_entry.hp_regen_rate)); - update_values.push_back(columns[24] + " = " + std::to_string(npc_scale_global_base_entry.attack_delay)); - update_values.push_back(columns[25] + " = " + std::to_string(npc_scale_global_base_entry.spell_scale)); - update_values.push_back(columns[26] + " = " + std::to_string(npc_scale_global_base_entry.heal_scale)); - update_values.push_back(columns[27] + " = '" + EscapeString(npc_scale_global_base_entry.special_abilities) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.type)); + v.push_back(columns[1] + " = " + std::to_string(e.level)); + v.push_back(columns[2] + " = " + std::to_string(e.ac)); + v.push_back(columns[3] + " = " + std::to_string(e.hp)); + v.push_back(columns[4] + " = " + std::to_string(e.accuracy)); + v.push_back(columns[5] + " = " + std::to_string(e.slow_mitigation)); + v.push_back(columns[6] + " = " + std::to_string(e.attack)); + v.push_back(columns[7] + " = " + std::to_string(e.strength)); + v.push_back(columns[8] + " = " + std::to_string(e.stamina)); + v.push_back(columns[9] + " = " + std::to_string(e.dexterity)); + v.push_back(columns[10] + " = " + std::to_string(e.agility)); + v.push_back(columns[11] + " = " + std::to_string(e.intelligence)); + v.push_back(columns[12] + " = " + std::to_string(e.wisdom)); + v.push_back(columns[13] + " = " + std::to_string(e.charisma)); + v.push_back(columns[14] + " = " + std::to_string(e.magic_resist)); + v.push_back(columns[15] + " = " + std::to_string(e.cold_resist)); + v.push_back(columns[16] + " = " + std::to_string(e.fire_resist)); + v.push_back(columns[17] + " = " + std::to_string(e.poison_resist)); + v.push_back(columns[18] + " = " + std::to_string(e.disease_resist)); + v.push_back(columns[19] + " = " + std::to_string(e.corruption_resist)); + v.push_back(columns[20] + " = " + std::to_string(e.physical_resist)); + v.push_back(columns[21] + " = " + std::to_string(e.min_dmg)); + v.push_back(columns[22] + " = " + std::to_string(e.max_dmg)); + v.push_back(columns[23] + " = " + std::to_string(e.hp_regen_rate)); + v.push_back(columns[24] + " = " + std::to_string(e.attack_delay)); + v.push_back(columns[25] + " = " + std::to_string(e.spell_scale)); + v.push_back(columns[26] + " = " + std::to_string(e.heal_scale)); + v.push_back(columns[27] + " = '" + Strings::Escape(e.special_abilities) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_scale_global_base_entry.type + e.type ) ); @@ -327,107 +327,107 @@ public: static NpcScaleGlobalBase InsertOne( Database& db, - NpcScaleGlobalBase npc_scale_global_base_entry + NpcScaleGlobalBase e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_scale_global_base_entry.type)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.level)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.ac)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.hp)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.accuracy)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.slow_mitigation)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.attack)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.strength)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.stamina)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.dexterity)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.agility)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.intelligence)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.wisdom)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.charisma)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.magic_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.cold_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.fire_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.poison_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.disease_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.corruption_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.physical_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.min_dmg)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.max_dmg)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.hp_regen_rate)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.attack_delay)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.spell_scale)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.heal_scale)); - insert_values.push_back("'" + EscapeString(npc_scale_global_base_entry.special_abilities) + "'"); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.ac)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.accuracy)); + v.push_back(std::to_string(e.slow_mitigation)); + v.push_back(std::to_string(e.attack)); + v.push_back(std::to_string(e.strength)); + v.push_back(std::to_string(e.stamina)); + v.push_back(std::to_string(e.dexterity)); + v.push_back(std::to_string(e.agility)); + v.push_back(std::to_string(e.intelligence)); + v.push_back(std::to_string(e.wisdom)); + v.push_back(std::to_string(e.charisma)); + v.push_back(std::to_string(e.magic_resist)); + v.push_back(std::to_string(e.cold_resist)); + v.push_back(std::to_string(e.fire_resist)); + v.push_back(std::to_string(e.poison_resist)); + v.push_back(std::to_string(e.disease_resist)); + v.push_back(std::to_string(e.corruption_resist)); + v.push_back(std::to_string(e.physical_resist)); + v.push_back(std::to_string(e.min_dmg)); + v.push_back(std::to_string(e.max_dmg)); + v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.attack_delay)); + v.push_back(std::to_string(e.spell_scale)); + v.push_back(std::to_string(e.heal_scale)); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_scale_global_base_entry.type = results.LastInsertedID(); - return npc_scale_global_base_entry; + e.type = results.LastInsertedID(); + return e; } - npc_scale_global_base_entry = NewEntity(); + e = NewEntity(); - return npc_scale_global_base_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_scale_global_base_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_scale_global_base_entry: npc_scale_global_base_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_scale_global_base_entry.type)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.level)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.ac)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.hp)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.accuracy)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.slow_mitigation)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.attack)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.strength)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.stamina)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.dexterity)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.agility)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.intelligence)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.wisdom)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.charisma)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.magic_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.cold_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.fire_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.poison_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.disease_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.corruption_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.physical_resist)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.min_dmg)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.max_dmg)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.hp_regen_rate)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.attack_delay)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.spell_scale)); - insert_values.push_back(std::to_string(npc_scale_global_base_entry.heal_scale)); - insert_values.push_back("'" + EscapeString(npc_scale_global_base_entry.special_abilities) + "'"); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.ac)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.accuracy)); + v.push_back(std::to_string(e.slow_mitigation)); + v.push_back(std::to_string(e.attack)); + v.push_back(std::to_string(e.strength)); + v.push_back(std::to_string(e.stamina)); + v.push_back(std::to_string(e.dexterity)); + v.push_back(std::to_string(e.agility)); + v.push_back(std::to_string(e.intelligence)); + v.push_back(std::to_string(e.wisdom)); + v.push_back(std::to_string(e.charisma)); + v.push_back(std::to_string(e.magic_resist)); + v.push_back(std::to_string(e.cold_resist)); + v.push_back(std::to_string(e.fire_resist)); + v.push_back(std::to_string(e.poison_resist)); + v.push_back(std::to_string(e.disease_resist)); + v.push_back(std::to_string(e.corruption_resist)); + v.push_back(std::to_string(e.physical_resist)); + v.push_back(std::to_string(e.min_dmg)); + v.push_back(std::to_string(e.max_dmg)); + v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.attack_delay)); + v.push_back(std::to_string(e.spell_scale)); + v.push_back(std::to_string(e.heal_scale)); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -448,44 +448,44 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcScaleGlobalBase entry{}; + NpcScaleGlobalBase e{}; - entry.type = atoi(row[0]); - entry.level = atoi(row[1]); - entry.ac = atoi(row[2]); - entry.hp = atoi(row[3]); - entry.accuracy = atoi(row[4]); - entry.slow_mitigation = atoi(row[5]); - entry.attack = atoi(row[6]); - entry.strength = atoi(row[7]); - entry.stamina = atoi(row[8]); - entry.dexterity = atoi(row[9]); - entry.agility = atoi(row[10]); - entry.intelligence = atoi(row[11]); - entry.wisdom = atoi(row[12]); - entry.charisma = atoi(row[13]); - entry.magic_resist = atoi(row[14]); - entry.cold_resist = atoi(row[15]); - entry.fire_resist = atoi(row[16]); - entry.poison_resist = atoi(row[17]); - entry.disease_resist = atoi(row[18]); - entry.corruption_resist = atoi(row[19]); - entry.physical_resist = atoi(row[20]); - entry.min_dmg = atoi(row[21]); - entry.max_dmg = atoi(row[22]); - entry.hp_regen_rate = atoi(row[23]); - entry.attack_delay = atoi(row[24]); - entry.spell_scale = atoi(row[25]); - entry.heal_scale = atoi(row[26]); - entry.special_abilities = row[27] ? row[27] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.ac = static_cast(atoi(row[2])); + e.hp = static_cast(atoi(row[3])); + e.accuracy = static_cast(atoi(row[4])); + e.slow_mitigation = static_cast(atoi(row[5])); + e.attack = static_cast(atoi(row[6])); + e.strength = static_cast(atoi(row[7])); + e.stamina = static_cast(atoi(row[8])); + e.dexterity = static_cast(atoi(row[9])); + e.agility = static_cast(atoi(row[10])); + e.intelligence = static_cast(atoi(row[11])); + e.wisdom = static_cast(atoi(row[12])); + e.charisma = static_cast(atoi(row[13])); + e.magic_resist = static_cast(atoi(row[14])); + e.cold_resist = static_cast(atoi(row[15])); + e.fire_resist = static_cast(atoi(row[16])); + e.poison_resist = static_cast(atoi(row[17])); + e.disease_resist = static_cast(atoi(row[18])); + e.corruption_resist = static_cast(atoi(row[19])); + e.physical_resist = static_cast(atoi(row[20])); + e.min_dmg = static_cast(atoi(row[21])); + e.max_dmg = static_cast(atoi(row[22])); + e.hp_regen_rate = static_cast(atoi(row[23])); + e.attack_delay = static_cast(atoi(row[24])); + e.spell_scale = static_cast(atoi(row[25])); + e.heal_scale = static_cast(atoi(row[26])); + e.special_abilities = row[27] ? row[27] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -500,44 +500,44 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcScaleGlobalBase entry{}; + NpcScaleGlobalBase e{}; - entry.type = atoi(row[0]); - entry.level = atoi(row[1]); - entry.ac = atoi(row[2]); - entry.hp = atoi(row[3]); - entry.accuracy = atoi(row[4]); - entry.slow_mitigation = atoi(row[5]); - entry.attack = atoi(row[6]); - entry.strength = atoi(row[7]); - entry.stamina = atoi(row[8]); - entry.dexterity = atoi(row[9]); - entry.agility = atoi(row[10]); - entry.intelligence = atoi(row[11]); - entry.wisdom = atoi(row[12]); - entry.charisma = atoi(row[13]); - entry.magic_resist = atoi(row[14]); - entry.cold_resist = atoi(row[15]); - entry.fire_resist = atoi(row[16]); - entry.poison_resist = atoi(row[17]); - entry.disease_resist = atoi(row[18]); - entry.corruption_resist = atoi(row[19]); - entry.physical_resist = atoi(row[20]); - entry.min_dmg = atoi(row[21]); - entry.max_dmg = atoi(row[22]); - entry.hp_regen_rate = atoi(row[23]); - entry.attack_delay = atoi(row[24]); - entry.spell_scale = atoi(row[25]); - entry.heal_scale = atoi(row[26]); - entry.special_abilities = row[27] ? row[27] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.ac = static_cast(atoi(row[2])); + e.hp = static_cast(atoi(row[3])); + e.accuracy = static_cast(atoi(row[4])); + e.slow_mitigation = static_cast(atoi(row[5])); + e.attack = static_cast(atoi(row[6])); + e.strength = static_cast(atoi(row[7])); + e.stamina = static_cast(atoi(row[8])); + e.dexterity = static_cast(atoi(row[9])); + e.agility = static_cast(atoi(row[10])); + e.intelligence = static_cast(atoi(row[11])); + e.wisdom = static_cast(atoi(row[12])); + e.charisma = static_cast(atoi(row[13])); + e.magic_resist = static_cast(atoi(row[14])); + e.cold_resist = static_cast(atoi(row[15])); + e.fire_resist = static_cast(atoi(row[16])); + e.poison_resist = static_cast(atoi(row[17])); + e.disease_resist = static_cast(atoi(row[18])); + e.corruption_resist = static_cast(atoi(row[19])); + e.physical_resist = static_cast(atoi(row[20])); + e.min_dmg = static_cast(atoi(row[21])); + e.max_dmg = static_cast(atoi(row[22])); + e.hp_regen_rate = static_cast(atoi(row[23])); + e.attack_delay = static_cast(atoi(row[24])); + e.spell_scale = static_cast(atoi(row[25])); + e.heal_scale = static_cast(atoi(row[26])); + e.special_abilities = row[27] ? row[27] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -562,6 +562,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_effects_entries_repository.h b/common/repositories/base/base_npc_spells_effects_entries_repository.h index 508ccc41e..257b5ffc7 100644 --- a/common/repositories/base/base_npc_spells_effects_entries_repository.h +++ b/common/repositories/base/base_npc_spells_effects_entries_repository.h @@ -13,20 +13,20 @@ #define EQEMU_BASE_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcSpellsEffectsEntriesRepository { public: struct NpcSpellsEffectsEntries { - int id; - int npc_spells_effects_id; - int spell_effect_id; - int minlevel; - int maxlevel; - int se_base; - int se_limit; - int se_max; + uint32_t id; + int32_t npc_spells_effects_id; + int16_t spell_effect_id; + uint8_t minlevel; + uint8_t maxlevel; + int32_t se_base; + int32_t se_limit; + int32_t se_max; }; static std::string PrimaryKey() @@ -64,12 +64,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -97,21 +97,21 @@ public: static NpcSpellsEffectsEntries NewEntity() { - NpcSpellsEffectsEntries entry{}; + NpcSpellsEffectsEntries e{}; - entry.id = 0; - entry.npc_spells_effects_id = 0; - entry.spell_effect_id = 0; - entry.minlevel = 0; - entry.maxlevel = 255; - entry.se_base = 0; - entry.se_limit = 0; - entry.se_max = 0; + e.id = 0; + e.npc_spells_effects_id = 0; + e.spell_effect_id = 0; + e.minlevel = 0; + e.maxlevel = 255; + e.se_base = 0; + e.se_limit = 0; + e.se_max = 0; - return entry; + return e; } - static NpcSpellsEffectsEntries GetNpcSpellsEffectsEntriesEntry( + static NpcSpellsEffectsEntries GetNpcSpellsEffectsEntries( const std::vector &npc_spells_effects_entriess, int npc_spells_effects_entries_id ) @@ -140,18 +140,18 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcSpellsEffectsEntries entry{}; + NpcSpellsEffectsEntries e{}; - entry.id = atoi(row[0]); - entry.npc_spells_effects_id = atoi(row[1]); - entry.spell_effect_id = atoi(row[2]); - entry.minlevel = atoi(row[3]); - entry.maxlevel = atoi(row[4]); - entry.se_base = atoi(row[5]); - entry.se_limit = atoi(row[6]); - entry.se_max = atoi(row[7]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_effects_id = static_cast(atoi(row[1])); + e.spell_effect_id = static_cast(atoi(row[2])); + e.minlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.se_base = static_cast(atoi(row[5])); + e.se_limit = static_cast(atoi(row[6])); + e.se_max = static_cast(atoi(row[7])); - return entry; + return e; } return NewEntity(); @@ -176,28 +176,28 @@ public: static int UpdateOne( Database& db, - NpcSpellsEffectsEntries npc_spells_effects_entries_entry + const NpcSpellsEffectsEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(npc_spells_effects_entries_entry.npc_spells_effects_id)); - update_values.push_back(columns[2] + " = " + std::to_string(npc_spells_effects_entries_entry.spell_effect_id)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_spells_effects_entries_entry.minlevel)); - update_values.push_back(columns[4] + " = " + std::to_string(npc_spells_effects_entries_entry.maxlevel)); - update_values.push_back(columns[5] + " = " + std::to_string(npc_spells_effects_entries_entry.se_base)); - update_values.push_back(columns[6] + " = " + std::to_string(npc_spells_effects_entries_entry.se_limit)); - update_values.push_back(columns[7] + " = " + std::to_string(npc_spells_effects_entries_entry.se_max)); + v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_effects_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spell_effect_id)); + v.push_back(columns[3] + " = " + std::to_string(e.minlevel)); + v.push_back(columns[4] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[5] + " = " + std::to_string(e.se_base)); + v.push_back(columns[6] + " = " + std::to_string(e.se_limit)); + v.push_back(columns[7] + " = " + std::to_string(e.se_max)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_spells_effects_entries_entry.id + e.id ) ); @@ -206,67 +206,67 @@ public: static NpcSpellsEffectsEntries InsertOne( Database& db, - NpcSpellsEffectsEntries npc_spells_effects_entries_entry + NpcSpellsEffectsEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.id)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.npc_spells_effects_id)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.spell_effect_id)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.minlevel)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.maxlevel)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_base)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_limit)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_max)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_spells_effects_id)); + v.push_back(std::to_string(e.spell_effect_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.se_base)); + v.push_back(std::to_string(e.se_limit)); + v.push_back(std::to_string(e.se_max)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_spells_effects_entries_entry.id = results.LastInsertedID(); - return npc_spells_effects_entries_entry; + e.id = results.LastInsertedID(); + return e; } - npc_spells_effects_entries_entry = NewEntity(); + e = NewEntity(); - return npc_spells_effects_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_spells_effects_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_spells_effects_entries_entry: npc_spells_effects_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.id)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.npc_spells_effects_id)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.spell_effect_id)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.minlevel)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.maxlevel)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_base)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_limit)); - insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_max)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_spells_effects_id)); + v.push_back(std::to_string(e.spell_effect_id)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.se_base)); + v.push_back(std::to_string(e.se_limit)); + v.push_back(std::to_string(e.se_max)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -287,24 +287,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpellsEffectsEntries entry{}; + NpcSpellsEffectsEntries e{}; - entry.id = atoi(row[0]); - entry.npc_spells_effects_id = atoi(row[1]); - entry.spell_effect_id = atoi(row[2]); - entry.minlevel = atoi(row[3]); - entry.maxlevel = atoi(row[4]); - entry.se_base = atoi(row[5]); - entry.se_limit = atoi(row[6]); - entry.se_max = atoi(row[7]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_effects_id = static_cast(atoi(row[1])); + e.spell_effect_id = static_cast(atoi(row[2])); + e.minlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.se_base = static_cast(atoi(row[5])); + e.se_limit = static_cast(atoi(row[6])); + e.se_max = static_cast(atoi(row[7])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -319,24 +319,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpellsEffectsEntries entry{}; + NpcSpellsEffectsEntries e{}; - entry.id = atoi(row[0]); - entry.npc_spells_effects_id = atoi(row[1]); - entry.spell_effect_id = atoi(row[2]); - entry.minlevel = atoi(row[3]); - entry.maxlevel = atoi(row[4]); - entry.se_base = atoi(row[5]); - entry.se_limit = atoi(row[6]); - entry.se_max = atoi(row[7]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_effects_id = static_cast(atoi(row[1])); + e.spell_effect_id = static_cast(atoi(row[2])); + e.minlevel = static_cast(strtoul(row[3], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.se_base = static_cast(atoi(row[5])); + e.se_limit = static_cast(atoi(row[6])); + e.se_max = static_cast(atoi(row[7])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -361,6 +361,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_effects_repository.h b/common/repositories/base/base_npc_spells_effects_repository.h index 23e16c2a0..333dc615c 100644 --- a/common/repositories/base/base_npc_spells_effects_repository.h +++ b/common/repositories/base/base_npc_spells_effects_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_NPC_SPELLS_EFFECTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcSpellsEffectsRepository { public: struct NpcSpellsEffects { - int id; + uint32_t id; std::string name; - int parent_list; + uint32_t parent_list; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static NpcSpellsEffects NewEntity() { - NpcSpellsEffects entry{}; + NpcSpellsEffects e{}; - entry.id = 0; - entry.name = ""; - entry.parent_list = 0; + e.id = 0; + e.name = ""; + e.parent_list = 0; - return entry; + return e; } - static NpcSpellsEffects GetNpcSpellsEffectsEntry( + static NpcSpellsEffects GetNpcSpellsEffects( const std::vector &npc_spells_effectss, int npc_spells_effects_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcSpellsEffects entry{}; + NpcSpellsEffects e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.parent_list = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.parent_list = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,23 +151,23 @@ public: static int UpdateOne( Database& db, - NpcSpellsEffects npc_spells_effects_entry + const NpcSpellsEffects &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(npc_spells_effects_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(npc_spells_effects_entry.parent_list)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.parent_list)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_spells_effects_entry.id + e.id ) ); @@ -176,57 +176,57 @@ public: static NpcSpellsEffects InsertOne( Database& db, - NpcSpellsEffects npc_spells_effects_entry + NpcSpellsEffects e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_spells_effects_entry.id)); - insert_values.push_back("'" + EscapeString(npc_spells_effects_entry.name) + "'"); - insert_values.push_back(std::to_string(npc_spells_effects_entry.parent_list)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.parent_list)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_spells_effects_entry.id = results.LastInsertedID(); - return npc_spells_effects_entry; + e.id = results.LastInsertedID(); + return e; } - npc_spells_effects_entry = NewEntity(); + e = NewEntity(); - return npc_spells_effects_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_spells_effects_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_spells_effects_entry: npc_spells_effects_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_spells_effects_entry.id)); - insert_values.push_back("'" + EscapeString(npc_spells_effects_entry.name) + "'"); - insert_values.push_back(std::to_string(npc_spells_effects_entry.parent_list)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.parent_list)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -247,19 +247,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpellsEffects entry{}; + NpcSpellsEffects e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.parent_list = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.parent_list = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -274,19 +274,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpellsEffects entry{}; + NpcSpellsEffects e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.parent_list = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.parent_list = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -311,6 +311,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_SPELLS_EFFECTS_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_entries_repository.h b/common/repositories/base/base_npc_spells_entries_repository.h index 72b39b108..1b946a24a 100644 --- a/common/repositories/base/base_npc_spells_entries_repository.h +++ b/common/repositories/base/base_npc_spells_entries_repository.h @@ -13,24 +13,24 @@ #define EQEMU_BASE_NPC_SPELLS_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcSpellsEntriesRepository { public: struct NpcSpellsEntries { - int id; - int npc_spells_id; - int spellid; - int type; - int minlevel; - int maxlevel; - int manacost; - int recast_delay; - int priority; - int resist_adjust; - int min_hp; - int max_hp; + uint32_t id; + int32_t npc_spells_id; + uint16_t spellid; + uint32_t type; + uint8_t minlevel; + uint8_t maxlevel; + int16_t manacost; + int32_t recast_delay; + int16_t priority; + int32_t resist_adjust; + int16_t min_hp; + int16_t max_hp; }; static std::string PrimaryKey() @@ -76,12 +76,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -109,25 +109,25 @@ public: static NpcSpellsEntries NewEntity() { - NpcSpellsEntries entry{}; + NpcSpellsEntries e{}; - entry.id = 0; - entry.npc_spells_id = 0; - entry.spellid = 0; - entry.type = 0; - entry.minlevel = 0; - entry.maxlevel = 255; - entry.manacost = -1; - entry.recast_delay = -1; - entry.priority = 0; - entry.resist_adjust = 0; - entry.min_hp = 0; - entry.max_hp = 0; + e.id = 0; + e.npc_spells_id = 0; + e.spellid = 0; + e.type = 0; + e.minlevel = 0; + e.maxlevel = 255; + e.manacost = -1; + e.recast_delay = -1; + e.priority = 0; + e.resist_adjust = 0; + e.min_hp = 0; + e.max_hp = 0; - return entry; + return e; } - static NpcSpellsEntries GetNpcSpellsEntriesEntry( + static NpcSpellsEntries GetNpcSpellsEntries( const std::vector &npc_spells_entriess, int npc_spells_entries_id ) @@ -156,22 +156,22 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcSpellsEntries entry{}; + NpcSpellsEntries e{}; - entry.id = atoi(row[0]); - entry.npc_spells_id = atoi(row[1]); - entry.spellid = atoi(row[2]); - entry.type = atoi(row[3]); - entry.minlevel = atoi(row[4]); - entry.maxlevel = atoi(row[5]); - entry.manacost = atoi(row[6]); - entry.recast_delay = atoi(row[7]); - entry.priority = atoi(row[8]); - entry.resist_adjust = atoi(row[9]); - entry.min_hp = atoi(row[10]); - entry.max_hp = atoi(row[11]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_id = static_cast(atoi(row[1])); + e.spellid = static_cast(strtoul(row[2], nullptr, 10)); + e.type = static_cast(strtoul(row[3], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.manacost = static_cast(atoi(row[6])); + e.recast_delay = static_cast(atoi(row[7])); + e.priority = static_cast(atoi(row[8])); + e.resist_adjust = static_cast(atoi(row[9])); + e.min_hp = static_cast(atoi(row[10])); + e.max_hp = static_cast(atoi(row[11])); - return entry; + return e; } return NewEntity(); @@ -196,32 +196,32 @@ public: static int UpdateOne( Database& db, - NpcSpellsEntries npc_spells_entries_entry + const NpcSpellsEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(npc_spells_entries_entry.npc_spells_id)); - update_values.push_back(columns[2] + " = " + std::to_string(npc_spells_entries_entry.spellid)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_spells_entries_entry.type)); - update_values.push_back(columns[4] + " = " + std::to_string(npc_spells_entries_entry.minlevel)); - update_values.push_back(columns[5] + " = " + std::to_string(npc_spells_entries_entry.maxlevel)); - update_values.push_back(columns[6] + " = " + std::to_string(npc_spells_entries_entry.manacost)); - update_values.push_back(columns[7] + " = " + std::to_string(npc_spells_entries_entry.recast_delay)); - update_values.push_back(columns[8] + " = " + std::to_string(npc_spells_entries_entry.priority)); - update_values.push_back(columns[9] + " = " + std::to_string(npc_spells_entries_entry.resist_adjust)); - update_values.push_back(columns[10] + " = " + std::to_string(npc_spells_entries_entry.min_hp)); - update_values.push_back(columns[11] + " = " + std::to_string(npc_spells_entries_entry.max_hp)); + v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_id)); + v.push_back(columns[2] + " = " + std::to_string(e.spellid)); + v.push_back(columns[3] + " = " + std::to_string(e.type)); + v.push_back(columns[4] + " = " + std::to_string(e.minlevel)); + v.push_back(columns[5] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[6] + " = " + std::to_string(e.manacost)); + v.push_back(columns[7] + " = " + std::to_string(e.recast_delay)); + v.push_back(columns[8] + " = " + std::to_string(e.priority)); + v.push_back(columns[9] + " = " + std::to_string(e.resist_adjust)); + v.push_back(columns[10] + " = " + std::to_string(e.min_hp)); + v.push_back(columns[11] + " = " + std::to_string(e.max_hp)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_spells_entries_entry.id + e.id ) ); @@ -230,75 +230,75 @@ public: static NpcSpellsEntries InsertOne( Database& db, - NpcSpellsEntries npc_spells_entries_entry + NpcSpellsEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_spells_entries_entry.id)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.npc_spells_id)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.spellid)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.type)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.minlevel)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.maxlevel)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.manacost)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.recast_delay)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.priority)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.resist_adjust)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.min_hp)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.max_hp)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_spells_id)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.manacost)); + v.push_back(std::to_string(e.recast_delay)); + v.push_back(std::to_string(e.priority)); + v.push_back(std::to_string(e.resist_adjust)); + v.push_back(std::to_string(e.min_hp)); + v.push_back(std::to_string(e.max_hp)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_spells_entries_entry.id = results.LastInsertedID(); - return npc_spells_entries_entry; + e.id = results.LastInsertedID(); + return e; } - npc_spells_entries_entry = NewEntity(); + e = NewEntity(); - return npc_spells_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_spells_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_spells_entries_entry: npc_spells_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_spells_entries_entry.id)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.npc_spells_id)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.spellid)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.type)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.minlevel)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.maxlevel)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.manacost)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.recast_delay)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.priority)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.resist_adjust)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.min_hp)); - insert_values.push_back(std::to_string(npc_spells_entries_entry.max_hp)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_spells_id)); + v.push_back(std::to_string(e.spellid)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.minlevel)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.manacost)); + v.push_back(std::to_string(e.recast_delay)); + v.push_back(std::to_string(e.priority)); + v.push_back(std::to_string(e.resist_adjust)); + v.push_back(std::to_string(e.min_hp)); + v.push_back(std::to_string(e.max_hp)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -319,28 +319,28 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpellsEntries entry{}; + NpcSpellsEntries e{}; - entry.id = atoi(row[0]); - entry.npc_spells_id = atoi(row[1]); - entry.spellid = atoi(row[2]); - entry.type = atoi(row[3]); - entry.minlevel = atoi(row[4]); - entry.maxlevel = atoi(row[5]); - entry.manacost = atoi(row[6]); - entry.recast_delay = atoi(row[7]); - entry.priority = atoi(row[8]); - entry.resist_adjust = atoi(row[9]); - entry.min_hp = atoi(row[10]); - entry.max_hp = atoi(row[11]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_id = static_cast(atoi(row[1])); + e.spellid = static_cast(strtoul(row[2], nullptr, 10)); + e.type = static_cast(strtoul(row[3], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.manacost = static_cast(atoi(row[6])); + e.recast_delay = static_cast(atoi(row[7])); + e.priority = static_cast(atoi(row[8])); + e.resist_adjust = static_cast(atoi(row[9])); + e.min_hp = static_cast(atoi(row[10])); + e.max_hp = static_cast(atoi(row[11])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -355,28 +355,28 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpellsEntries entry{}; + NpcSpellsEntries e{}; - entry.id = atoi(row[0]); - entry.npc_spells_id = atoi(row[1]); - entry.spellid = atoi(row[2]); - entry.type = atoi(row[3]); - entry.minlevel = atoi(row[4]); - entry.maxlevel = atoi(row[5]); - entry.manacost = atoi(row[6]); - entry.recast_delay = atoi(row[7]); - entry.priority = atoi(row[8]); - entry.resist_adjust = atoi(row[9]); - entry.min_hp = atoi(row[10]); - entry.max_hp = atoi(row[11]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.npc_spells_id = static_cast(atoi(row[1])); + e.spellid = static_cast(strtoul(row[2], nullptr, 10)); + e.type = static_cast(strtoul(row[3], nullptr, 10)); + e.minlevel = static_cast(strtoul(row[4], nullptr, 10)); + e.maxlevel = static_cast(strtoul(row[5], nullptr, 10)); + e.manacost = static_cast(atoi(row[6])); + e.recast_delay = static_cast(atoi(row[7])); + e.priority = static_cast(atoi(row[8])); + e.resist_adjust = static_cast(atoi(row[9])); + e.min_hp = static_cast(atoi(row[10])); + e.max_hp = static_cast(atoi(row[11])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -401,6 +401,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_SPELLS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_repository.h b/common/repositories/base/base_npc_spells_repository.h index 8433a208f..576333a1d 100644 --- a/common/repositories/base/base_npc_spells_repository.h +++ b/common/repositories/base/base_npc_spells_repository.h @@ -13,33 +13,33 @@ #define EQEMU_BASE_NPC_SPELLS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcSpellsRepository { public: struct NpcSpells { - int id; + uint32_t id; std::string name; - int parent_list; - int attack_proc; - int proc_chance; - int range_proc; - int rproc_chance; - int defensive_proc; - int dproc_chance; - int fail_recast; - int engaged_no_sp_recast_min; - int engaged_no_sp_recast_max; - int engaged_b_self_chance; - int engaged_b_other_chance; - int engaged_d_chance; - int pursue_no_sp_recast_min; - int pursue_no_sp_recast_max; - int pursue_d_chance; - int idle_no_sp_recast_min; - int idle_no_sp_recast_max; - int idle_b_chance; + uint32_t parent_list; + int16_t attack_proc; + int8_t proc_chance; + int16_t range_proc; + int16_t rproc_chance; + int16_t defensive_proc; + int16_t dproc_chance; + uint32_t fail_recast; + uint32_t engaged_no_sp_recast_min; + uint32_t engaged_no_sp_recast_max; + uint8_t engaged_b_self_chance; + uint8_t engaged_b_other_chance; + uint8_t engaged_d_chance; + uint32_t pursue_no_sp_recast_min; + uint32_t pursue_no_sp_recast_max; + uint8_t pursue_d_chance; + uint32_t idle_no_sp_recast_min; + uint32_t idle_no_sp_recast_max; + uint8_t idle_b_chance; }; static std::string PrimaryKey() @@ -103,12 +103,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -136,34 +136,34 @@ public: static NpcSpells NewEntity() { - NpcSpells entry{}; + NpcSpells e{}; - entry.id = 0; - entry.name = ""; - entry.parent_list = 0; - entry.attack_proc = -1; - entry.proc_chance = 3; - entry.range_proc = -1; - entry.rproc_chance = 0; - entry.defensive_proc = -1; - entry.dproc_chance = 0; - entry.fail_recast = 0; - entry.engaged_no_sp_recast_min = 0; - entry.engaged_no_sp_recast_max = 0; - entry.engaged_b_self_chance = 0; - entry.engaged_b_other_chance = 0; - entry.engaged_d_chance = 0; - entry.pursue_no_sp_recast_min = 0; - entry.pursue_no_sp_recast_max = 0; - entry.pursue_d_chance = 0; - entry.idle_no_sp_recast_min = 0; - entry.idle_no_sp_recast_max = 0; - entry.idle_b_chance = 0; + e.id = 0; + e.name = ""; + e.parent_list = 0; + e.attack_proc = -1; + e.proc_chance = 3; + e.range_proc = -1; + e.rproc_chance = 0; + e.defensive_proc = -1; + e.dproc_chance = 0; + e.fail_recast = 0; + e.engaged_no_sp_recast_min = 0; + e.engaged_no_sp_recast_max = 0; + e.engaged_b_self_chance = 0; + e.engaged_b_other_chance = 0; + e.engaged_d_chance = 0; + e.pursue_no_sp_recast_min = 0; + e.pursue_no_sp_recast_max = 0; + e.pursue_d_chance = 0; + e.idle_no_sp_recast_min = 0; + e.idle_no_sp_recast_max = 0; + e.idle_b_chance = 0; - return entry; + return e; } - static NpcSpells GetNpcSpellsEntry( + static NpcSpells GetNpcSpells( const std::vector &npc_spellss, int npc_spells_id ) @@ -192,31 +192,31 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcSpells entry{}; + NpcSpells e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.parent_list = atoi(row[2]); - entry.attack_proc = atoi(row[3]); - entry.proc_chance = atoi(row[4]); - entry.range_proc = atoi(row[5]); - entry.rproc_chance = atoi(row[6]); - entry.defensive_proc = atoi(row[7]); - entry.dproc_chance = atoi(row[8]); - entry.fail_recast = atoi(row[9]); - entry.engaged_no_sp_recast_min = atoi(row[10]); - entry.engaged_no_sp_recast_max = atoi(row[11]); - entry.engaged_b_self_chance = atoi(row[12]); - entry.engaged_b_other_chance = atoi(row[13]); - entry.engaged_d_chance = atoi(row[14]); - entry.pursue_no_sp_recast_min = atoi(row[15]); - entry.pursue_no_sp_recast_max = atoi(row[16]); - entry.pursue_d_chance = atoi(row[17]); - entry.idle_no_sp_recast_min = atoi(row[18]); - entry.idle_no_sp_recast_max = atoi(row[19]); - entry.idle_b_chance = atoi(row[20]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.parent_list = static_cast(strtoul(row[2], nullptr, 10)); + e.attack_proc = static_cast(atoi(row[3])); + e.proc_chance = static_cast(atoi(row[4])); + e.range_proc = static_cast(atoi(row[5])); + e.rproc_chance = static_cast(atoi(row[6])); + e.defensive_proc = static_cast(atoi(row[7])); + e.dproc_chance = static_cast(atoi(row[8])); + e.fail_recast = static_cast(strtoul(row[9], nullptr, 10)); + e.engaged_no_sp_recast_min = static_cast(strtoul(row[10], nullptr, 10)); + e.engaged_no_sp_recast_max = static_cast(strtoul(row[11], nullptr, 10)); + e.engaged_b_self_chance = static_cast(strtoul(row[12], nullptr, 10)); + e.engaged_b_other_chance = static_cast(strtoul(row[13], nullptr, 10)); + e.engaged_d_chance = static_cast(strtoul(row[14], nullptr, 10)); + e.pursue_no_sp_recast_min = static_cast(strtoul(row[15], nullptr, 10)); + e.pursue_no_sp_recast_max = static_cast(strtoul(row[16], nullptr, 10)); + e.pursue_d_chance = static_cast(strtoul(row[17], nullptr, 10)); + e.idle_no_sp_recast_min = static_cast(strtoul(row[18], nullptr, 10)); + e.idle_no_sp_recast_max = static_cast(strtoul(row[19], nullptr, 10)); + e.idle_b_chance = static_cast(strtoul(row[20], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -241,41 +241,41 @@ public: static int UpdateOne( Database& db, - NpcSpells npc_spells_entry + const NpcSpells &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(npc_spells_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(npc_spells_entry.parent_list)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_spells_entry.attack_proc)); - update_values.push_back(columns[4] + " = " + std::to_string(npc_spells_entry.proc_chance)); - update_values.push_back(columns[5] + " = " + std::to_string(npc_spells_entry.range_proc)); - update_values.push_back(columns[6] + " = " + std::to_string(npc_spells_entry.rproc_chance)); - update_values.push_back(columns[7] + " = " + std::to_string(npc_spells_entry.defensive_proc)); - update_values.push_back(columns[8] + " = " + std::to_string(npc_spells_entry.dproc_chance)); - update_values.push_back(columns[9] + " = " + std::to_string(npc_spells_entry.fail_recast)); - update_values.push_back(columns[10] + " = " + std::to_string(npc_spells_entry.engaged_no_sp_recast_min)); - update_values.push_back(columns[11] + " = " + std::to_string(npc_spells_entry.engaged_no_sp_recast_max)); - update_values.push_back(columns[12] + " = " + std::to_string(npc_spells_entry.engaged_b_self_chance)); - update_values.push_back(columns[13] + " = " + std::to_string(npc_spells_entry.engaged_b_other_chance)); - update_values.push_back(columns[14] + " = " + std::to_string(npc_spells_entry.engaged_d_chance)); - update_values.push_back(columns[15] + " = " + std::to_string(npc_spells_entry.pursue_no_sp_recast_min)); - update_values.push_back(columns[16] + " = " + std::to_string(npc_spells_entry.pursue_no_sp_recast_max)); - update_values.push_back(columns[17] + " = " + std::to_string(npc_spells_entry.pursue_d_chance)); - update_values.push_back(columns[18] + " = " + std::to_string(npc_spells_entry.idle_no_sp_recast_min)); - update_values.push_back(columns[19] + " = " + std::to_string(npc_spells_entry.idle_no_sp_recast_max)); - update_values.push_back(columns[20] + " = " + std::to_string(npc_spells_entry.idle_b_chance)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.parent_list)); + v.push_back(columns[3] + " = " + std::to_string(e.attack_proc)); + v.push_back(columns[4] + " = " + std::to_string(e.proc_chance)); + v.push_back(columns[5] + " = " + std::to_string(e.range_proc)); + v.push_back(columns[6] + " = " + std::to_string(e.rproc_chance)); + v.push_back(columns[7] + " = " + std::to_string(e.defensive_proc)); + v.push_back(columns[8] + " = " + std::to_string(e.dproc_chance)); + v.push_back(columns[9] + " = " + std::to_string(e.fail_recast)); + v.push_back(columns[10] + " = " + std::to_string(e.engaged_no_sp_recast_min)); + v.push_back(columns[11] + " = " + std::to_string(e.engaged_no_sp_recast_max)); + v.push_back(columns[12] + " = " + std::to_string(e.engaged_b_self_chance)); + v.push_back(columns[13] + " = " + std::to_string(e.engaged_b_other_chance)); + v.push_back(columns[14] + " = " + std::to_string(e.engaged_d_chance)); + v.push_back(columns[15] + " = " + std::to_string(e.pursue_no_sp_recast_min)); + v.push_back(columns[16] + " = " + std::to_string(e.pursue_no_sp_recast_max)); + v.push_back(columns[17] + " = " + std::to_string(e.pursue_d_chance)); + v.push_back(columns[18] + " = " + std::to_string(e.idle_no_sp_recast_min)); + v.push_back(columns[19] + " = " + std::to_string(e.idle_no_sp_recast_max)); + v.push_back(columns[20] + " = " + std::to_string(e.idle_b_chance)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_spells_entry.id + e.id ) ); @@ -284,93 +284,93 @@ public: static NpcSpells InsertOne( Database& db, - NpcSpells npc_spells_entry + NpcSpells e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_spells_entry.id)); - insert_values.push_back("'" + EscapeString(npc_spells_entry.name) + "'"); - insert_values.push_back(std::to_string(npc_spells_entry.parent_list)); - insert_values.push_back(std::to_string(npc_spells_entry.attack_proc)); - insert_values.push_back(std::to_string(npc_spells_entry.proc_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.range_proc)); - insert_values.push_back(std::to_string(npc_spells_entry.rproc_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.defensive_proc)); - insert_values.push_back(std::to_string(npc_spells_entry.dproc_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.fail_recast)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_no_sp_recast_min)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_no_sp_recast_max)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_b_self_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_b_other_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_d_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.pursue_no_sp_recast_min)); - insert_values.push_back(std::to_string(npc_spells_entry.pursue_no_sp_recast_max)); - insert_values.push_back(std::to_string(npc_spells_entry.pursue_d_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.idle_no_sp_recast_min)); - insert_values.push_back(std::to_string(npc_spells_entry.idle_no_sp_recast_max)); - insert_values.push_back(std::to_string(npc_spells_entry.idle_b_chance)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.parent_list)); + v.push_back(std::to_string(e.attack_proc)); + v.push_back(std::to_string(e.proc_chance)); + v.push_back(std::to_string(e.range_proc)); + v.push_back(std::to_string(e.rproc_chance)); + v.push_back(std::to_string(e.defensive_proc)); + v.push_back(std::to_string(e.dproc_chance)); + v.push_back(std::to_string(e.fail_recast)); + v.push_back(std::to_string(e.engaged_no_sp_recast_min)); + v.push_back(std::to_string(e.engaged_no_sp_recast_max)); + v.push_back(std::to_string(e.engaged_b_self_chance)); + v.push_back(std::to_string(e.engaged_b_other_chance)); + v.push_back(std::to_string(e.engaged_d_chance)); + v.push_back(std::to_string(e.pursue_no_sp_recast_min)); + v.push_back(std::to_string(e.pursue_no_sp_recast_max)); + v.push_back(std::to_string(e.pursue_d_chance)); + v.push_back(std::to_string(e.idle_no_sp_recast_min)); + v.push_back(std::to_string(e.idle_no_sp_recast_max)); + v.push_back(std::to_string(e.idle_b_chance)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_spells_entry.id = results.LastInsertedID(); - return npc_spells_entry; + e.id = results.LastInsertedID(); + return e; } - npc_spells_entry = NewEntity(); + e = NewEntity(); - return npc_spells_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_spells_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_spells_entry: npc_spells_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_spells_entry.id)); - insert_values.push_back("'" + EscapeString(npc_spells_entry.name) + "'"); - insert_values.push_back(std::to_string(npc_spells_entry.parent_list)); - insert_values.push_back(std::to_string(npc_spells_entry.attack_proc)); - insert_values.push_back(std::to_string(npc_spells_entry.proc_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.range_proc)); - insert_values.push_back(std::to_string(npc_spells_entry.rproc_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.defensive_proc)); - insert_values.push_back(std::to_string(npc_spells_entry.dproc_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.fail_recast)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_no_sp_recast_min)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_no_sp_recast_max)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_b_self_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_b_other_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.engaged_d_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.pursue_no_sp_recast_min)); - insert_values.push_back(std::to_string(npc_spells_entry.pursue_no_sp_recast_max)); - insert_values.push_back(std::to_string(npc_spells_entry.pursue_d_chance)); - insert_values.push_back(std::to_string(npc_spells_entry.idle_no_sp_recast_min)); - insert_values.push_back(std::to_string(npc_spells_entry.idle_no_sp_recast_max)); - insert_values.push_back(std::to_string(npc_spells_entry.idle_b_chance)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.parent_list)); + v.push_back(std::to_string(e.attack_proc)); + v.push_back(std::to_string(e.proc_chance)); + v.push_back(std::to_string(e.range_proc)); + v.push_back(std::to_string(e.rproc_chance)); + v.push_back(std::to_string(e.defensive_proc)); + v.push_back(std::to_string(e.dproc_chance)); + v.push_back(std::to_string(e.fail_recast)); + v.push_back(std::to_string(e.engaged_no_sp_recast_min)); + v.push_back(std::to_string(e.engaged_no_sp_recast_max)); + v.push_back(std::to_string(e.engaged_b_self_chance)); + v.push_back(std::to_string(e.engaged_b_other_chance)); + v.push_back(std::to_string(e.engaged_d_chance)); + v.push_back(std::to_string(e.pursue_no_sp_recast_min)); + v.push_back(std::to_string(e.pursue_no_sp_recast_max)); + v.push_back(std::to_string(e.pursue_d_chance)); + v.push_back(std::to_string(e.idle_no_sp_recast_min)); + v.push_back(std::to_string(e.idle_no_sp_recast_max)); + v.push_back(std::to_string(e.idle_b_chance)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -391,37 +391,37 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpells entry{}; + NpcSpells e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.parent_list = atoi(row[2]); - entry.attack_proc = atoi(row[3]); - entry.proc_chance = atoi(row[4]); - entry.range_proc = atoi(row[5]); - entry.rproc_chance = atoi(row[6]); - entry.defensive_proc = atoi(row[7]); - entry.dproc_chance = atoi(row[8]); - entry.fail_recast = atoi(row[9]); - entry.engaged_no_sp_recast_min = atoi(row[10]); - entry.engaged_no_sp_recast_max = atoi(row[11]); - entry.engaged_b_self_chance = atoi(row[12]); - entry.engaged_b_other_chance = atoi(row[13]); - entry.engaged_d_chance = atoi(row[14]); - entry.pursue_no_sp_recast_min = atoi(row[15]); - entry.pursue_no_sp_recast_max = atoi(row[16]); - entry.pursue_d_chance = atoi(row[17]); - entry.idle_no_sp_recast_min = atoi(row[18]); - entry.idle_no_sp_recast_max = atoi(row[19]); - entry.idle_b_chance = atoi(row[20]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.parent_list = static_cast(strtoul(row[2], nullptr, 10)); + e.attack_proc = static_cast(atoi(row[3])); + e.proc_chance = static_cast(atoi(row[4])); + e.range_proc = static_cast(atoi(row[5])); + e.rproc_chance = static_cast(atoi(row[6])); + e.defensive_proc = static_cast(atoi(row[7])); + e.dproc_chance = static_cast(atoi(row[8])); + e.fail_recast = static_cast(strtoul(row[9], nullptr, 10)); + e.engaged_no_sp_recast_min = static_cast(strtoul(row[10], nullptr, 10)); + e.engaged_no_sp_recast_max = static_cast(strtoul(row[11], nullptr, 10)); + e.engaged_b_self_chance = static_cast(strtoul(row[12], nullptr, 10)); + e.engaged_b_other_chance = static_cast(strtoul(row[13], nullptr, 10)); + e.engaged_d_chance = static_cast(strtoul(row[14], nullptr, 10)); + e.pursue_no_sp_recast_min = static_cast(strtoul(row[15], nullptr, 10)); + e.pursue_no_sp_recast_max = static_cast(strtoul(row[16], nullptr, 10)); + e.pursue_d_chance = static_cast(strtoul(row[17], nullptr, 10)); + e.idle_no_sp_recast_min = static_cast(strtoul(row[18], nullptr, 10)); + e.idle_no_sp_recast_max = static_cast(strtoul(row[19], nullptr, 10)); + e.idle_b_chance = static_cast(strtoul(row[20], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -436,37 +436,37 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcSpells entry{}; + NpcSpells e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.parent_list = atoi(row[2]); - entry.attack_proc = atoi(row[3]); - entry.proc_chance = atoi(row[4]); - entry.range_proc = atoi(row[5]); - entry.rproc_chance = atoi(row[6]); - entry.defensive_proc = atoi(row[7]); - entry.dproc_chance = atoi(row[8]); - entry.fail_recast = atoi(row[9]); - entry.engaged_no_sp_recast_min = atoi(row[10]); - entry.engaged_no_sp_recast_max = atoi(row[11]); - entry.engaged_b_self_chance = atoi(row[12]); - entry.engaged_b_other_chance = atoi(row[13]); - entry.engaged_d_chance = atoi(row[14]); - entry.pursue_no_sp_recast_min = atoi(row[15]); - entry.pursue_no_sp_recast_max = atoi(row[16]); - entry.pursue_d_chance = atoi(row[17]); - entry.idle_no_sp_recast_min = atoi(row[18]); - entry.idle_no_sp_recast_max = atoi(row[19]); - entry.idle_b_chance = atoi(row[20]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.parent_list = static_cast(strtoul(row[2], nullptr, 10)); + e.attack_proc = static_cast(atoi(row[3])); + e.proc_chance = static_cast(atoi(row[4])); + e.range_proc = static_cast(atoi(row[5])); + e.rproc_chance = static_cast(atoi(row[6])); + e.defensive_proc = static_cast(atoi(row[7])); + e.dproc_chance = static_cast(atoi(row[8])); + e.fail_recast = static_cast(strtoul(row[9], nullptr, 10)); + e.engaged_no_sp_recast_min = static_cast(strtoul(row[10], nullptr, 10)); + e.engaged_no_sp_recast_max = static_cast(strtoul(row[11], nullptr, 10)); + e.engaged_b_self_chance = static_cast(strtoul(row[12], nullptr, 10)); + e.engaged_b_other_chance = static_cast(strtoul(row[13], nullptr, 10)); + e.engaged_d_chance = static_cast(strtoul(row[14], nullptr, 10)); + e.pursue_no_sp_recast_min = static_cast(strtoul(row[15], nullptr, 10)); + e.pursue_no_sp_recast_max = static_cast(strtoul(row[16], nullptr, 10)); + e.pursue_d_chance = static_cast(strtoul(row[17], nullptr, 10)); + e.idle_no_sp_recast_min = static_cast(strtoul(row[18], nullptr, 10)); + e.idle_no_sp_recast_max = static_cast(strtoul(row[19], nullptr, 10)); + e.idle_b_chance = static_cast(strtoul(row[20], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -491,6 +491,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_npc_types_repository.h b/common/repositories/base/base_npc_types_repository.h index 535c4f9cb..4a6a0f688 100644 --- a/common/repositories/base/base_npc_types_repository.h +++ b/common/repositories/base/base_npc_types_repository.h @@ -13,136 +13,140 @@ #define EQEMU_BASE_NPC_TYPES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include + class BaseNpcTypesRepository { public: struct NpcTypes { - int id; + int32_t id; std::string name; std::string lastname; - int level; - int race; - int class_; - int bodytype; - int64 hp; - int64 mana; - int gender; - int texture; - int helmtexture; - int herosforgemodel; + uint8_t level; + uint16_t race; + uint8_t class_; + int32_t bodytype; + int64_t hp; + int64_t mana; + uint8_t gender; + uint8_t texture; + uint8_t helmtexture; + int32_t herosforgemodel; float size; - int64 hp_regen_rate; - int64 hp_regen_per_second; - int64 mana_regen_rate; - int loottable_id; - int merchant_id; - int alt_currency_id; - int npc_spells_id; - int npc_spells_effects_id; - int npc_faction_id; - int adventure_template_id; - int trap_template; - int mindmg; - int maxdmg; - int attack_count; + int64_t hp_regen_rate; + int64_t hp_regen_per_second; + int64_t mana_regen_rate; + uint32_t loottable_id; + uint32_t merchant_id; + uint32_t alt_currency_id; + uint32_t npc_spells_id; + uint32_t npc_spells_effects_id; + int32_t npc_faction_id; + uint32_t adventure_template_id; + uint32_t trap_template; + uint32_t mindmg; + uint32_t maxdmg; + int16_t attack_count; std::string npcspecialattks; std::string special_abilities; - int aggroradius; - int assistradius; - int face; - int luclin_hairstyle; - int luclin_haircolor; - int luclin_eyecolor; - int luclin_eyecolor2; - int luclin_beardcolor; - int luclin_beard; - int drakkin_heritage; - int drakkin_tattoo; - int drakkin_details; - int armortint_id; - int armortint_red; - int armortint_green; - int armortint_blue; - int d_melee_texture1; - int d_melee_texture2; + uint32_t aggroradius; + uint32_t assistradius; + uint32_t face; + uint32_t luclin_hairstyle; + uint32_t luclin_haircolor; + uint32_t luclin_eyecolor; + uint32_t luclin_eyecolor2; + uint32_t luclin_beardcolor; + uint32_t luclin_beard; + int32_t drakkin_heritage; + int32_t drakkin_tattoo; + int32_t drakkin_details; + uint32_t armortint_id; + uint8_t armortint_red; + uint8_t armortint_green; + uint8_t armortint_blue; + int32_t d_melee_texture1; + int32_t d_melee_texture2; std::string ammo_idfile; - int prim_melee_type; - int sec_melee_type; - int ranged_type; + uint8_t prim_melee_type; + uint8_t sec_melee_type; + uint8_t ranged_type; float runspeed; - int MR; - int CR; - int DR; - int FR; - int PR; - int Corrup; - int PhR; - int see_invis; - int see_invis_undead; - int qglobal; - int AC; - int npc_aggro; - int spawn_limit; + int16_t MR; + int16_t CR; + int16_t DR; + int16_t FR; + int16_t PR; + int16_t Corrup; + uint16_t PhR; + int16_t see_invis; + int16_t see_invis_undead; + uint32_t qglobal; + int16_t AC; + int8_t npc_aggro; + int8_t spawn_limit; float attack_speed; - int attack_delay; - int findable; - int STR; - int STA; - int DEX; - int AGI; - int _INT; - int WIS; - int CHA; - int see_hide; - int see_improved_hide; - int trackable; - int isbot; - int exclude; - int ATK; - int Accuracy; - int Avoidance; - int slow_mitigation; - int version; - int maxlevel; - int scalerate; - int private_corpse; - int unique_spawn_by_name; - int underwater; - int isquest; - int emoteid; + uint8_t attack_delay; + int8_t findable; + uint32_t STR; + uint32_t STA; + uint32_t DEX; + uint32_t AGI; + uint32_t _INT; + uint32_t WIS; + uint32_t CHA; + int8_t see_hide; + int8_t see_improved_hide; + int8_t trackable; + int8_t isbot; + int8_t exclude; + int32_t ATK; + int32_t Accuracy; + uint32_t Avoidance; + int16_t slow_mitigation; + uint16_t version; + int8_t maxlevel; + int32_t scalerate; + uint8_t private_corpse; + uint8_t unique_spawn_by_name; + uint8_t underwater; + int8_t isquest; + uint32_t emoteid; float spellscale; float healscale; - int no_target_hotkey; - int raid_target; - int armtexture; - int bracertexture; - int handtexture; - int legtexture; - int feettexture; - int light; - int walkspeed; - int peqid; - int unique_; - int fixed; - int ignore_despawn; - int show_name; - int untargetable; - int charm_ac; - int charm_min_dmg; - int charm_max_dmg; - int charm_attack_delay; - int charm_accuracy_rating; - int charm_avoidance_rating; - int charm_atk; - int skip_global_loot; - int rare_spawn; - int stuck_behavior; - int model; - int flymode; - int always_aggro; - int exp_mod; + uint8_t no_target_hotkey; + uint8_t raid_target; + int8_t armtexture; + int8_t bracertexture; + int8_t handtexture; + int8_t legtexture; + int8_t feettexture; + int8_t light; + int8_t walkspeed; + int32_t peqid; + int8_t unique_; + int8_t fixed; + int8_t ignore_despawn; + int8_t show_name; + int8_t untargetable; + int16_t charm_ac; + int32_t charm_min_dmg; + int32_t charm_max_dmg; + int8_t charm_attack_delay; + int32_t charm_accuracy_rating; + int32_t charm_avoidance_rating; + int32_t charm_atk; + int8_t skip_global_loot; + int8_t rare_spawn; + int8_t stuck_behavior; + int16_t model; + int8_t flymode; + int8_t always_aggro; + int32_t exp_mod; + int32_t heroic_strikethrough; + int32_t faction_amount; + uint8_t keeps_sold_items; }; static std::string PrimaryKey() @@ -277,6 +281,9 @@ public: "flymode", "always_aggro", "exp_mod", + "heroic_strikethrough", + "faction_amount", + "keeps_sold_items", }; } @@ -407,17 +414,20 @@ public: "flymode", "always_aggro", "exp_mod", + "heroic_strikethrough", + "faction_amount", + "keeps_sold_items", }; } static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -445,137 +455,140 @@ public: static NpcTypes NewEntity() { - NpcTypes entry{}; + NpcTypes e{}; - entry.id = 0; - entry.name = ""; - entry.lastname = ""; - entry.level = 0; - entry.race = 0; - entry.class_ = 0; - entry.bodytype = 1; - entry.hp = 0; - entry.mana = 0; - entry.gender = 0; - entry.texture = 0; - entry.helmtexture = 0; - entry.herosforgemodel = 0; - entry.size = 0; - entry.hp_regen_rate = 0; - entry.hp_regen_per_second = 0; - entry.mana_regen_rate = 0; - entry.loottable_id = 0; - entry.merchant_id = 0; - entry.alt_currency_id = 0; - entry.npc_spells_id = 0; - entry.npc_spells_effects_id = 0; - entry.npc_faction_id = 0; - entry.adventure_template_id = 0; - entry.trap_template = 0; - entry.mindmg = 0; - entry.maxdmg = 0; - entry.attack_count = -1; - entry.npcspecialattks = ""; - entry.special_abilities = ""; - entry.aggroradius = 0; - entry.assistradius = 0; - entry.face = 1; - entry.luclin_hairstyle = 1; - entry.luclin_haircolor = 1; - entry.luclin_eyecolor = 1; - entry.luclin_eyecolor2 = 1; - entry.luclin_beardcolor = 1; - entry.luclin_beard = 0; - entry.drakkin_heritage = 0; - entry.drakkin_tattoo = 0; - entry.drakkin_details = 0; - entry.armortint_id = 0; - entry.armortint_red = 0; - entry.armortint_green = 0; - entry.armortint_blue = 0; - entry.d_melee_texture1 = 0; - entry.d_melee_texture2 = 0; - entry.ammo_idfile = "IT10"; - entry.prim_melee_type = 28; - entry.sec_melee_type = 28; - entry.ranged_type = 7; - entry.runspeed = 0; - entry.MR = 0; - entry.CR = 0; - entry.DR = 0; - entry.FR = 0; - entry.PR = 0; - entry.Corrup = 0; - entry.PhR = 0; - entry.see_invis = 0; - entry.see_invis_undead = 0; - entry.qglobal = 0; - entry.AC = 0; - entry.npc_aggro = 0; - entry.spawn_limit = 0; - entry.attack_speed = 0; - entry.attack_delay = 30; - entry.findable = 0; - entry.STR = 75; - entry.STA = 75; - entry.DEX = 75; - entry.AGI = 75; - entry._INT = 80; - entry.WIS = 75; - entry.CHA = 75; - entry.see_hide = 0; - entry.see_improved_hide = 0; - entry.trackable = 1; - entry.isbot = 0; - entry.exclude = 1; - entry.ATK = 0; - entry.Accuracy = 0; - entry.Avoidance = 0; - entry.slow_mitigation = 0; - entry.version = 0; - entry.maxlevel = 0; - entry.scalerate = 100; - entry.private_corpse = 0; - entry.unique_spawn_by_name = 0; - entry.underwater = 0; - entry.isquest = 0; - entry.emoteid = 0; - entry.spellscale = 100; - entry.healscale = 100; - entry.no_target_hotkey = 0; - entry.raid_target = 0; - entry.armtexture = 0; - entry.bracertexture = 0; - entry.handtexture = 0; - entry.legtexture = 0; - entry.feettexture = 0; - entry.light = 0; - entry.walkspeed = 0; - entry.peqid = 0; - entry.unique_ = 0; - entry.fixed = 0; - entry.ignore_despawn = 0; - entry.show_name = 1; - entry.untargetable = 0; - entry.charm_ac = 0; - entry.charm_min_dmg = 0; - entry.charm_max_dmg = 0; - entry.charm_attack_delay = 0; - entry.charm_accuracy_rating = 0; - entry.charm_avoidance_rating = 0; - entry.charm_atk = 0; - entry.skip_global_loot = 0; - entry.rare_spawn = 0; - entry.stuck_behavior = 0; - entry.model = 0; - entry.flymode = -1; - entry.always_aggro = 0; - entry.exp_mod = 100; + e.id = 0; + e.name = ""; + e.lastname = ""; + e.level = 0; + e.race = 0; + e.class_ = 0; + e.bodytype = 1; + e.hp = 0; + e.mana = 0; + e.gender = 0; + e.texture = 0; + e.helmtexture = 0; + e.herosforgemodel = 0; + e.size = 0; + e.hp_regen_rate = 0; + e.hp_regen_per_second = 0; + e.mana_regen_rate = 0; + e.loottable_id = 0; + e.merchant_id = 0; + e.alt_currency_id = 0; + e.npc_spells_id = 0; + e.npc_spells_effects_id = 0; + e.npc_faction_id = 0; + e.adventure_template_id = 0; + e.trap_template = 0; + e.mindmg = 0; + e.maxdmg = 0; + e.attack_count = -1; + e.npcspecialattks = ""; + e.special_abilities = ""; + e.aggroradius = 0; + e.assistradius = 0; + e.face = 1; + e.luclin_hairstyle = 1; + e.luclin_haircolor = 1; + e.luclin_eyecolor = 1; + e.luclin_eyecolor2 = 1; + e.luclin_beardcolor = 1; + e.luclin_beard = 0; + e.drakkin_heritage = 0; + e.drakkin_tattoo = 0; + e.drakkin_details = 0; + e.armortint_id = 0; + e.armortint_red = 0; + e.armortint_green = 0; + e.armortint_blue = 0; + e.d_melee_texture1 = 0; + e.d_melee_texture2 = 0; + e.ammo_idfile = "IT10"; + e.prim_melee_type = 28; + e.sec_melee_type = 28; + e.ranged_type = 7; + e.runspeed = 0; + e.MR = 0; + e.CR = 0; + e.DR = 0; + e.FR = 0; + e.PR = 0; + e.Corrup = 0; + e.PhR = 0; + e.see_invis = 0; + e.see_invis_undead = 0; + e.qglobal = 0; + e.AC = 0; + e.npc_aggro = 0; + e.spawn_limit = 0; + e.attack_speed = 0; + e.attack_delay = 30; + e.findable = 0; + e.STR = 75; + e.STA = 75; + e.DEX = 75; + e.AGI = 75; + e._INT = 80; + e.WIS = 75; + e.CHA = 75; + e.see_hide = 0; + e.see_improved_hide = 0; + e.trackable = 1; + e.isbot = 0; + e.exclude = 1; + e.ATK = 0; + e.Accuracy = 0; + e.Avoidance = 0; + e.slow_mitigation = 0; + e.version = 0; + e.maxlevel = 0; + e.scalerate = 100; + e.private_corpse = 0; + e.unique_spawn_by_name = 0; + e.underwater = 0; + e.isquest = 0; + e.emoteid = 0; + e.spellscale = 100; + e.healscale = 100; + e.no_target_hotkey = 0; + e.raid_target = 0; + e.armtexture = 0; + e.bracertexture = 0; + e.handtexture = 0; + e.legtexture = 0; + e.feettexture = 0; + e.light = 0; + e.walkspeed = 0; + e.peqid = 0; + e.unique_ = 0; + e.fixed = 0; + e.ignore_despawn = 0; + e.show_name = 1; + e.untargetable = 0; + e.charm_ac = 0; + e.charm_min_dmg = 0; + e.charm_max_dmg = 0; + e.charm_attack_delay = 0; + e.charm_accuracy_rating = 0; + e.charm_avoidance_rating = 0; + e.charm_atk = 0; + e.skip_global_loot = 0; + e.rare_spawn = 0; + e.stuck_behavior = 0; + e.model = 0; + e.flymode = -1; + e.always_aggro = 0; + e.exp_mod = 100; + e.heroic_strikethrough = 0; + e.faction_amount = 0; + e.keeps_sold_items = 0; - return entry; + return e; } - static NpcTypes GetNpcTypesEntry( + static NpcTypes GetNpcTypes( const std::vector &npc_typess, int npc_types_id ) @@ -596,142 +609,146 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), npc_types_id ) ); auto row = results.begin(); if (results.RowCount() == 1) { - NpcTypes entry{}; + NpcTypes e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.lastname = row[2] ? row[2] : ""; - entry.level = atoi(row[3]); - entry.race = atoi(row[4]); - entry.class_ = atoi(row[5]); - entry.bodytype = atoi(row[6]); - entry.hp = strtoll(row[7], nullptr, 10); - entry.mana = strtoll(row[8], nullptr, 10); - entry.gender = atoi(row[9]); - entry.texture = atoi(row[10]); - entry.helmtexture = atoi(row[11]); - entry.herosforgemodel = atoi(row[12]); - entry.size = static_cast(atof(row[13])); - entry.hp_regen_rate = strtoll(row[14], nullptr, 10); - entry.hp_regen_per_second = strtoll(row[15], nullptr, 10); - entry.mana_regen_rate = strtoll(row[16], nullptr, 10); - entry.loottable_id = atoi(row[17]); - entry.merchant_id = atoi(row[18]); - entry.alt_currency_id = atoi(row[19]); - entry.npc_spells_id = atoi(row[20]); - entry.npc_spells_effects_id = atoi(row[21]); - entry.npc_faction_id = atoi(row[22]); - entry.adventure_template_id = atoi(row[23]); - entry.trap_template = atoi(row[24]); - entry.mindmg = atoi(row[25]); - entry.maxdmg = atoi(row[26]); - entry.attack_count = atoi(row[27]); - entry.npcspecialattks = row[28] ? row[28] : ""; - entry.special_abilities = row[29] ? row[29] : ""; - entry.aggroradius = atoi(row[30]); - entry.assistradius = atoi(row[31]); - entry.face = atoi(row[32]); - entry.luclin_hairstyle = atoi(row[33]); - entry.luclin_haircolor = atoi(row[34]); - entry.luclin_eyecolor = atoi(row[35]); - entry.luclin_eyecolor2 = atoi(row[36]); - entry.luclin_beardcolor = atoi(row[37]); - entry.luclin_beard = atoi(row[38]); - entry.drakkin_heritage = atoi(row[39]); - entry.drakkin_tattoo = atoi(row[40]); - entry.drakkin_details = atoi(row[41]); - entry.armortint_id = atoi(row[42]); - entry.armortint_red = atoi(row[43]); - entry.armortint_green = atoi(row[44]); - entry.armortint_blue = atoi(row[45]); - entry.d_melee_texture1 = atoi(row[46]); - entry.d_melee_texture2 = atoi(row[47]); - entry.ammo_idfile = row[48] ? row[48] : ""; - entry.prim_melee_type = atoi(row[49]); - entry.sec_melee_type = atoi(row[50]); - entry.ranged_type = atoi(row[51]); - entry.runspeed = static_cast(atof(row[52])); - entry.MR = atoi(row[53]); - entry.CR = atoi(row[54]); - entry.DR = atoi(row[55]); - entry.FR = atoi(row[56]); - entry.PR = atoi(row[57]); - entry.Corrup = atoi(row[58]); - entry.PhR = atoi(row[59]); - entry.see_invis = atoi(row[60]); - entry.see_invis_undead = atoi(row[61]); - entry.qglobal = atoi(row[62]); - entry.AC = atoi(row[63]); - entry.npc_aggro = atoi(row[64]); - entry.spawn_limit = atoi(row[65]); - entry.attack_speed = static_cast(atof(row[66])); - entry.attack_delay = atoi(row[67]); - entry.findable = atoi(row[68]); - entry.STR = atoi(row[69]); - entry.STA = atoi(row[70]); - entry.DEX = atoi(row[71]); - entry.AGI = atoi(row[72]); - entry._INT = atoi(row[73]); - entry.WIS = atoi(row[74]); - entry.CHA = atoi(row[75]); - entry.see_hide = atoi(row[76]); - entry.see_improved_hide = atoi(row[77]); - entry.trackable = atoi(row[78]); - entry.isbot = atoi(row[79]); - entry.exclude = atoi(row[80]); - entry.ATK = atoi(row[81]); - entry.Accuracy = atoi(row[82]); - entry.Avoidance = atoi(row[83]); - entry.slow_mitigation = atoi(row[84]); - entry.version = atoi(row[85]); - entry.maxlevel = atoi(row[86]); - entry.scalerate = atoi(row[87]); - entry.private_corpse = atoi(row[88]); - entry.unique_spawn_by_name = atoi(row[89]); - entry.underwater = atoi(row[90]); - entry.isquest = atoi(row[91]); - entry.emoteid = atoi(row[92]); - entry.spellscale = static_cast(atof(row[93])); - entry.healscale = static_cast(atof(row[94])); - entry.no_target_hotkey = atoi(row[95]); - entry.raid_target = atoi(row[96]); - entry.armtexture = atoi(row[97]); - entry.bracertexture = atoi(row[98]); - entry.handtexture = atoi(row[99]); - entry.legtexture = atoi(row[100]); - entry.feettexture = atoi(row[101]); - entry.light = atoi(row[102]); - entry.walkspeed = atoi(row[103]); - entry.peqid = atoi(row[104]); - entry.unique_ = atoi(row[105]); - entry.fixed = atoi(row[106]); - entry.ignore_despawn = atoi(row[107]); - entry.show_name = atoi(row[108]); - entry.untargetable = atoi(row[109]); - entry.charm_ac = atoi(row[110]); - entry.charm_min_dmg = atoi(row[111]); - entry.charm_max_dmg = atoi(row[112]); - entry.charm_attack_delay = atoi(row[113]); - entry.charm_accuracy_rating = atoi(row[114]); - entry.charm_avoidance_rating = atoi(row[115]); - entry.charm_atk = atoi(row[116]); - entry.skip_global_loot = atoi(row[117]); - entry.rare_spawn = atoi(row[118]); - entry.stuck_behavior = atoi(row[119]); - entry.model = atoi(row[120]); - entry.flymode = atoi(row[121]); - entry.always_aggro = atoi(row[122]); - entry.exp_mod = atoi(row[123]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.lastname = row[2] ? row[2] : ""; + e.level = static_cast(strtoul(row[3], nullptr, 10)); + e.race = static_cast(strtoul(row[4], nullptr, 10)); + e.class_ = static_cast(strtoul(row[5], nullptr, 10)); + e.bodytype = static_cast(atoi(row[6])); + e.hp = strtoll(row[7], nullptr, 10); + e.mana = strtoll(row[8], nullptr, 10); + e.gender = static_cast(strtoul(row[9], nullptr, 10)); + e.texture = static_cast(strtoul(row[10], nullptr, 10)); + e.helmtexture = static_cast(strtoul(row[11], nullptr, 10)); + e.herosforgemodel = static_cast(atoi(row[12])); + e.size = strtof(row[13], nullptr); + e.hp_regen_rate = strtoll(row[14], nullptr, 10); + e.hp_regen_per_second = strtoll(row[15], nullptr, 10); + e.mana_regen_rate = strtoll(row[16], nullptr, 10); + e.loottable_id = static_cast(strtoul(row[17], nullptr, 10)); + e.merchant_id = static_cast(strtoul(row[18], nullptr, 10)); + e.alt_currency_id = static_cast(strtoul(row[19], nullptr, 10)); + e.npc_spells_id = static_cast(strtoul(row[20], nullptr, 10)); + e.npc_spells_effects_id = static_cast(strtoul(row[21], nullptr, 10)); + e.npc_faction_id = static_cast(atoi(row[22])); + e.adventure_template_id = static_cast(strtoul(row[23], nullptr, 10)); + e.trap_template = static_cast(strtoul(row[24], nullptr, 10)); + e.mindmg = static_cast(strtoul(row[25], nullptr, 10)); + e.maxdmg = static_cast(strtoul(row[26], nullptr, 10)); + e.attack_count = static_cast(atoi(row[27])); + e.npcspecialattks = row[28] ? row[28] : ""; + e.special_abilities = row[29] ? row[29] : ""; + e.aggroradius = static_cast(strtoul(row[30], nullptr, 10)); + e.assistradius = static_cast(strtoul(row[31], nullptr, 10)); + e.face = static_cast(strtoul(row[32], nullptr, 10)); + e.luclin_hairstyle = static_cast(strtoul(row[33], nullptr, 10)); + e.luclin_haircolor = static_cast(strtoul(row[34], nullptr, 10)); + e.luclin_eyecolor = static_cast(strtoul(row[35], nullptr, 10)); + e.luclin_eyecolor2 = static_cast(strtoul(row[36], nullptr, 10)); + e.luclin_beardcolor = static_cast(strtoul(row[37], nullptr, 10)); + e.luclin_beard = static_cast(strtoul(row[38], nullptr, 10)); + e.drakkin_heritage = static_cast(atoi(row[39])); + e.drakkin_tattoo = static_cast(atoi(row[40])); + e.drakkin_details = static_cast(atoi(row[41])); + e.armortint_id = static_cast(strtoul(row[42], nullptr, 10)); + e.armortint_red = static_cast(strtoul(row[43], nullptr, 10)); + e.armortint_green = static_cast(strtoul(row[44], nullptr, 10)); + e.armortint_blue = static_cast(strtoul(row[45], nullptr, 10)); + e.d_melee_texture1 = static_cast(atoi(row[46])); + e.d_melee_texture2 = static_cast(atoi(row[47])); + e.ammo_idfile = row[48] ? row[48] : ""; + e.prim_melee_type = static_cast(strtoul(row[49], nullptr, 10)); + e.sec_melee_type = static_cast(strtoul(row[50], nullptr, 10)); + e.ranged_type = static_cast(strtoul(row[51], nullptr, 10)); + e.runspeed = strtof(row[52], nullptr); + e.MR = static_cast(atoi(row[53])); + e.CR = static_cast(atoi(row[54])); + e.DR = static_cast(atoi(row[55])); + e.FR = static_cast(atoi(row[56])); + e.PR = static_cast(atoi(row[57])); + e.Corrup = static_cast(atoi(row[58])); + e.PhR = static_cast(strtoul(row[59], nullptr, 10)); + e.see_invis = static_cast(atoi(row[60])); + e.see_invis_undead = static_cast(atoi(row[61])); + e.qglobal = static_cast(strtoul(row[62], nullptr, 10)); + e.AC = static_cast(atoi(row[63])); + e.npc_aggro = static_cast(atoi(row[64])); + e.spawn_limit = static_cast(atoi(row[65])); + e.attack_speed = strtof(row[66], nullptr); + e.attack_delay = static_cast(strtoul(row[67], nullptr, 10)); + e.findable = static_cast(atoi(row[68])); + e.STR = static_cast(strtoul(row[69], nullptr, 10)); + e.STA = static_cast(strtoul(row[70], nullptr, 10)); + e.DEX = static_cast(strtoul(row[71], nullptr, 10)); + e.AGI = static_cast(strtoul(row[72], nullptr, 10)); + e._INT = static_cast(strtoul(row[73], nullptr, 10)); + e.WIS = static_cast(strtoul(row[74], nullptr, 10)); + e.CHA = static_cast(strtoul(row[75], nullptr, 10)); + e.see_hide = static_cast(atoi(row[76])); + e.see_improved_hide = static_cast(atoi(row[77])); + e.trackable = static_cast(atoi(row[78])); + e.isbot = static_cast(atoi(row[79])); + e.exclude = static_cast(atoi(row[80])); + e.ATK = static_cast(atoi(row[81])); + e.Accuracy = static_cast(atoi(row[82])); + e.Avoidance = static_cast(strtoul(row[83], nullptr, 10)); + e.slow_mitigation = static_cast(atoi(row[84])); + e.version = static_cast(strtoul(row[85], nullptr, 10)); + e.maxlevel = static_cast(atoi(row[86])); + e.scalerate = static_cast(atoi(row[87])); + e.private_corpse = static_cast(strtoul(row[88], nullptr, 10)); + e.unique_spawn_by_name = static_cast(strtoul(row[89], nullptr, 10)); + e.underwater = static_cast(strtoul(row[90], nullptr, 10)); + e.isquest = static_cast(atoi(row[91])); + e.emoteid = static_cast(strtoul(row[92], nullptr, 10)); + e.spellscale = strtof(row[93], nullptr); + e.healscale = strtof(row[94], nullptr); + e.no_target_hotkey = static_cast(strtoul(row[95], nullptr, 10)); + e.raid_target = static_cast(strtoul(row[96], nullptr, 10)); + e.armtexture = static_cast(atoi(row[97])); + e.bracertexture = static_cast(atoi(row[98])); + e.handtexture = static_cast(atoi(row[99])); + e.legtexture = static_cast(atoi(row[100])); + e.feettexture = static_cast(atoi(row[101])); + e.light = static_cast(atoi(row[102])); + e.walkspeed = static_cast(atoi(row[103])); + e.peqid = static_cast(atoi(row[104])); + e.unique_ = static_cast(atoi(row[105])); + e.fixed = static_cast(atoi(row[106])); + e.ignore_despawn = static_cast(atoi(row[107])); + e.show_name = static_cast(atoi(row[108])); + e.untargetable = static_cast(atoi(row[109])); + e.charm_ac = static_cast(atoi(row[110])); + e.charm_min_dmg = static_cast(atoi(row[111])); + e.charm_max_dmg = static_cast(atoi(row[112])); + e.charm_attack_delay = static_cast(atoi(row[113])); + e.charm_accuracy_rating = static_cast(atoi(row[114])); + e.charm_avoidance_rating = static_cast(atoi(row[115])); + e.charm_atk = static_cast(atoi(row[116])); + e.skip_global_loot = static_cast(atoi(row[117])); + e.rare_spawn = static_cast(atoi(row[118])); + e.stuck_behavior = static_cast(atoi(row[119])); + e.model = static_cast(atoi(row[120])); + e.flymode = static_cast(atoi(row[121])); + e.always_aggro = static_cast(atoi(row[122])); + e.exp_mod = static_cast(atoi(row[123])); + e.heroic_strikethrough = static_cast(atoi(row[124])); + e.faction_amount = static_cast(atoi(row[125])); + e.keeps_sold_items = static_cast(strtoul(row[126], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -756,144 +773,147 @@ public: static int UpdateOne( Database& db, - NpcTypes npc_types_entry + const NpcTypes &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(npc_types_entry.name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(npc_types_entry.lastname) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(npc_types_entry.level)); - update_values.push_back(columns[4] + " = " + std::to_string(npc_types_entry.race)); - update_values.push_back(columns[5] + " = " + std::to_string(npc_types_entry.class_)); - update_values.push_back(columns[6] + " = " + std::to_string(npc_types_entry.bodytype)); - update_values.push_back(columns[7] + " = " + std::to_string(npc_types_entry.hp)); - update_values.push_back(columns[8] + " = " + std::to_string(npc_types_entry.mana)); - update_values.push_back(columns[9] + " = " + std::to_string(npc_types_entry.gender)); - update_values.push_back(columns[10] + " = " + std::to_string(npc_types_entry.texture)); - update_values.push_back(columns[11] + " = " + std::to_string(npc_types_entry.helmtexture)); - update_values.push_back(columns[12] + " = " + std::to_string(npc_types_entry.herosforgemodel)); - update_values.push_back(columns[13] + " = " + std::to_string(npc_types_entry.size)); - update_values.push_back(columns[14] + " = " + std::to_string(npc_types_entry.hp_regen_rate)); - update_values.push_back(columns[15] + " = " + std::to_string(npc_types_entry.hp_regen_per_second)); - update_values.push_back(columns[16] + " = " + std::to_string(npc_types_entry.mana_regen_rate)); - update_values.push_back(columns[17] + " = " + std::to_string(npc_types_entry.loottable_id)); - update_values.push_back(columns[18] + " = " + std::to_string(npc_types_entry.merchant_id)); - update_values.push_back(columns[19] + " = " + std::to_string(npc_types_entry.alt_currency_id)); - update_values.push_back(columns[20] + " = " + std::to_string(npc_types_entry.npc_spells_id)); - update_values.push_back(columns[21] + " = " + std::to_string(npc_types_entry.npc_spells_effects_id)); - update_values.push_back(columns[22] + " = " + std::to_string(npc_types_entry.npc_faction_id)); - update_values.push_back(columns[23] + " = " + std::to_string(npc_types_entry.adventure_template_id)); - update_values.push_back(columns[24] + " = " + std::to_string(npc_types_entry.trap_template)); - update_values.push_back(columns[25] + " = " + std::to_string(npc_types_entry.mindmg)); - update_values.push_back(columns[26] + " = " + std::to_string(npc_types_entry.maxdmg)); - update_values.push_back(columns[27] + " = " + std::to_string(npc_types_entry.attack_count)); - update_values.push_back(columns[28] + " = '" + EscapeString(npc_types_entry.npcspecialattks) + "'"); - update_values.push_back(columns[29] + " = '" + EscapeString(npc_types_entry.special_abilities) + "'"); - update_values.push_back(columns[30] + " = " + std::to_string(npc_types_entry.aggroradius)); - update_values.push_back(columns[31] + " = " + std::to_string(npc_types_entry.assistradius)); - update_values.push_back(columns[32] + " = " + std::to_string(npc_types_entry.face)); - update_values.push_back(columns[33] + " = " + std::to_string(npc_types_entry.luclin_hairstyle)); - update_values.push_back(columns[34] + " = " + std::to_string(npc_types_entry.luclin_haircolor)); - update_values.push_back(columns[35] + " = " + std::to_string(npc_types_entry.luclin_eyecolor)); - update_values.push_back(columns[36] + " = " + std::to_string(npc_types_entry.luclin_eyecolor2)); - update_values.push_back(columns[37] + " = " + std::to_string(npc_types_entry.luclin_beardcolor)); - update_values.push_back(columns[38] + " = " + std::to_string(npc_types_entry.luclin_beard)); - update_values.push_back(columns[39] + " = " + std::to_string(npc_types_entry.drakkin_heritage)); - update_values.push_back(columns[40] + " = " + std::to_string(npc_types_entry.drakkin_tattoo)); - update_values.push_back(columns[41] + " = " + std::to_string(npc_types_entry.drakkin_details)); - update_values.push_back(columns[42] + " = " + std::to_string(npc_types_entry.armortint_id)); - update_values.push_back(columns[43] + " = " + std::to_string(npc_types_entry.armortint_red)); - update_values.push_back(columns[44] + " = " + std::to_string(npc_types_entry.armortint_green)); - update_values.push_back(columns[45] + " = " + std::to_string(npc_types_entry.armortint_blue)); - update_values.push_back(columns[46] + " = " + std::to_string(npc_types_entry.d_melee_texture1)); - update_values.push_back(columns[47] + " = " + std::to_string(npc_types_entry.d_melee_texture2)); - update_values.push_back(columns[48] + " = '" + EscapeString(npc_types_entry.ammo_idfile) + "'"); - update_values.push_back(columns[49] + " = " + std::to_string(npc_types_entry.prim_melee_type)); - update_values.push_back(columns[50] + " = " + std::to_string(npc_types_entry.sec_melee_type)); - update_values.push_back(columns[51] + " = " + std::to_string(npc_types_entry.ranged_type)); - update_values.push_back(columns[52] + " = " + std::to_string(npc_types_entry.runspeed)); - update_values.push_back(columns[53] + " = " + std::to_string(npc_types_entry.MR)); - update_values.push_back(columns[54] + " = " + std::to_string(npc_types_entry.CR)); - update_values.push_back(columns[55] + " = " + std::to_string(npc_types_entry.DR)); - update_values.push_back(columns[56] + " = " + std::to_string(npc_types_entry.FR)); - update_values.push_back(columns[57] + " = " + std::to_string(npc_types_entry.PR)); - update_values.push_back(columns[58] + " = " + std::to_string(npc_types_entry.Corrup)); - update_values.push_back(columns[59] + " = " + std::to_string(npc_types_entry.PhR)); - update_values.push_back(columns[60] + " = " + std::to_string(npc_types_entry.see_invis)); - update_values.push_back(columns[61] + " = " + std::to_string(npc_types_entry.see_invis_undead)); - update_values.push_back(columns[62] + " = " + std::to_string(npc_types_entry.qglobal)); - update_values.push_back(columns[63] + " = " + std::to_string(npc_types_entry.AC)); - update_values.push_back(columns[64] + " = " + std::to_string(npc_types_entry.npc_aggro)); - update_values.push_back(columns[65] + " = " + std::to_string(npc_types_entry.spawn_limit)); - update_values.push_back(columns[66] + " = " + std::to_string(npc_types_entry.attack_speed)); - update_values.push_back(columns[67] + " = " + std::to_string(npc_types_entry.attack_delay)); - update_values.push_back(columns[68] + " = " + std::to_string(npc_types_entry.findable)); - update_values.push_back(columns[69] + " = " + std::to_string(npc_types_entry.STR)); - update_values.push_back(columns[70] + " = " + std::to_string(npc_types_entry.STA)); - update_values.push_back(columns[71] + " = " + std::to_string(npc_types_entry.DEX)); - update_values.push_back(columns[72] + " = " + std::to_string(npc_types_entry.AGI)); - update_values.push_back(columns[73] + " = " + std::to_string(npc_types_entry._INT)); - update_values.push_back(columns[74] + " = " + std::to_string(npc_types_entry.WIS)); - update_values.push_back(columns[75] + " = " + std::to_string(npc_types_entry.CHA)); - update_values.push_back(columns[76] + " = " + std::to_string(npc_types_entry.see_hide)); - update_values.push_back(columns[77] + " = " + std::to_string(npc_types_entry.see_improved_hide)); - update_values.push_back(columns[78] + " = " + std::to_string(npc_types_entry.trackable)); - update_values.push_back(columns[79] + " = " + std::to_string(npc_types_entry.isbot)); - update_values.push_back(columns[80] + " = " + std::to_string(npc_types_entry.exclude)); - update_values.push_back(columns[81] + " = " + std::to_string(npc_types_entry.ATK)); - update_values.push_back(columns[82] + " = " + std::to_string(npc_types_entry.Accuracy)); - update_values.push_back(columns[83] + " = " + std::to_string(npc_types_entry.Avoidance)); - update_values.push_back(columns[84] + " = " + std::to_string(npc_types_entry.slow_mitigation)); - update_values.push_back(columns[85] + " = " + std::to_string(npc_types_entry.version)); - update_values.push_back(columns[86] + " = " + std::to_string(npc_types_entry.maxlevel)); - update_values.push_back(columns[87] + " = " + std::to_string(npc_types_entry.scalerate)); - update_values.push_back(columns[88] + " = " + std::to_string(npc_types_entry.private_corpse)); - update_values.push_back(columns[89] + " = " + std::to_string(npc_types_entry.unique_spawn_by_name)); - update_values.push_back(columns[90] + " = " + std::to_string(npc_types_entry.underwater)); - update_values.push_back(columns[91] + " = " + std::to_string(npc_types_entry.isquest)); - update_values.push_back(columns[92] + " = " + std::to_string(npc_types_entry.emoteid)); - update_values.push_back(columns[93] + " = " + std::to_string(npc_types_entry.spellscale)); - update_values.push_back(columns[94] + " = " + std::to_string(npc_types_entry.healscale)); - update_values.push_back(columns[95] + " = " + std::to_string(npc_types_entry.no_target_hotkey)); - update_values.push_back(columns[96] + " = " + std::to_string(npc_types_entry.raid_target)); - update_values.push_back(columns[97] + " = " + std::to_string(npc_types_entry.armtexture)); - update_values.push_back(columns[98] + " = " + std::to_string(npc_types_entry.bracertexture)); - update_values.push_back(columns[99] + " = " + std::to_string(npc_types_entry.handtexture)); - update_values.push_back(columns[100] + " = " + std::to_string(npc_types_entry.legtexture)); - update_values.push_back(columns[101] + " = " + std::to_string(npc_types_entry.feettexture)); - update_values.push_back(columns[102] + " = " + std::to_string(npc_types_entry.light)); - update_values.push_back(columns[103] + " = " + std::to_string(npc_types_entry.walkspeed)); - update_values.push_back(columns[104] + " = " + std::to_string(npc_types_entry.peqid)); - update_values.push_back(columns[105] + " = " + std::to_string(npc_types_entry.unique_)); - update_values.push_back(columns[106] + " = " + std::to_string(npc_types_entry.fixed)); - update_values.push_back(columns[107] + " = " + std::to_string(npc_types_entry.ignore_despawn)); - update_values.push_back(columns[108] + " = " + std::to_string(npc_types_entry.show_name)); - update_values.push_back(columns[109] + " = " + std::to_string(npc_types_entry.untargetable)); - update_values.push_back(columns[110] + " = " + std::to_string(npc_types_entry.charm_ac)); - update_values.push_back(columns[111] + " = " + std::to_string(npc_types_entry.charm_min_dmg)); - update_values.push_back(columns[112] + " = " + std::to_string(npc_types_entry.charm_max_dmg)); - update_values.push_back(columns[113] + " = " + std::to_string(npc_types_entry.charm_attack_delay)); - update_values.push_back(columns[114] + " = " + std::to_string(npc_types_entry.charm_accuracy_rating)); - update_values.push_back(columns[115] + " = " + std::to_string(npc_types_entry.charm_avoidance_rating)); - update_values.push_back(columns[116] + " = " + std::to_string(npc_types_entry.charm_atk)); - update_values.push_back(columns[117] + " = " + std::to_string(npc_types_entry.skip_global_loot)); - update_values.push_back(columns[118] + " = " + std::to_string(npc_types_entry.rare_spawn)); - update_values.push_back(columns[119] + " = " + std::to_string(npc_types_entry.stuck_behavior)); - update_values.push_back(columns[120] + " = " + std::to_string(npc_types_entry.model)); - update_values.push_back(columns[121] + " = " + std::to_string(npc_types_entry.flymode)); - update_values.push_back(columns[122] + " = " + std::to_string(npc_types_entry.always_aggro)); - update_values.push_back(columns[123] + " = " + std::to_string(npc_types_entry.exp_mod)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.lastname) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.level)); + v.push_back(columns[4] + " = " + std::to_string(e.race)); + v.push_back(columns[5] + " = " + std::to_string(e.class_)); + v.push_back(columns[6] + " = " + std::to_string(e.bodytype)); + v.push_back(columns[7] + " = " + std::to_string(e.hp)); + v.push_back(columns[8] + " = " + std::to_string(e.mana)); + v.push_back(columns[9] + " = " + std::to_string(e.gender)); + v.push_back(columns[10] + " = " + std::to_string(e.texture)); + v.push_back(columns[11] + " = " + std::to_string(e.helmtexture)); + v.push_back(columns[12] + " = " + std::to_string(e.herosforgemodel)); + v.push_back(columns[13] + " = " + std::to_string(e.size)); + v.push_back(columns[14] + " = " + std::to_string(e.hp_regen_rate)); + v.push_back(columns[15] + " = " + std::to_string(e.hp_regen_per_second)); + v.push_back(columns[16] + " = " + std::to_string(e.mana_regen_rate)); + v.push_back(columns[17] + " = " + std::to_string(e.loottable_id)); + v.push_back(columns[18] + " = " + std::to_string(e.merchant_id)); + v.push_back(columns[19] + " = " + std::to_string(e.alt_currency_id)); + v.push_back(columns[20] + " = " + std::to_string(e.npc_spells_id)); + v.push_back(columns[21] + " = " + std::to_string(e.npc_spells_effects_id)); + v.push_back(columns[22] + " = " + std::to_string(e.npc_faction_id)); + v.push_back(columns[23] + " = " + std::to_string(e.adventure_template_id)); + v.push_back(columns[24] + " = " + std::to_string(e.trap_template)); + v.push_back(columns[25] + " = " + std::to_string(e.mindmg)); + v.push_back(columns[26] + " = " + std::to_string(e.maxdmg)); + v.push_back(columns[27] + " = " + std::to_string(e.attack_count)); + v.push_back(columns[28] + " = '" + Strings::Escape(e.npcspecialattks) + "'"); + v.push_back(columns[29] + " = '" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(columns[30] + " = " + std::to_string(e.aggroradius)); + v.push_back(columns[31] + " = " + std::to_string(e.assistradius)); + v.push_back(columns[32] + " = " + std::to_string(e.face)); + v.push_back(columns[33] + " = " + std::to_string(e.luclin_hairstyle)); + v.push_back(columns[34] + " = " + std::to_string(e.luclin_haircolor)); + v.push_back(columns[35] + " = " + std::to_string(e.luclin_eyecolor)); + v.push_back(columns[36] + " = " + std::to_string(e.luclin_eyecolor2)); + v.push_back(columns[37] + " = " + std::to_string(e.luclin_beardcolor)); + v.push_back(columns[38] + " = " + std::to_string(e.luclin_beard)); + v.push_back(columns[39] + " = " + std::to_string(e.drakkin_heritage)); + v.push_back(columns[40] + " = " + std::to_string(e.drakkin_tattoo)); + v.push_back(columns[41] + " = " + std::to_string(e.drakkin_details)); + v.push_back(columns[42] + " = " + std::to_string(e.armortint_id)); + v.push_back(columns[43] + " = " + std::to_string(e.armortint_red)); + v.push_back(columns[44] + " = " + std::to_string(e.armortint_green)); + v.push_back(columns[45] + " = " + std::to_string(e.armortint_blue)); + v.push_back(columns[46] + " = " + std::to_string(e.d_melee_texture1)); + v.push_back(columns[47] + " = " + std::to_string(e.d_melee_texture2)); + v.push_back(columns[48] + " = '" + Strings::Escape(e.ammo_idfile) + "'"); + v.push_back(columns[49] + " = " + std::to_string(e.prim_melee_type)); + v.push_back(columns[50] + " = " + std::to_string(e.sec_melee_type)); + v.push_back(columns[51] + " = " + std::to_string(e.ranged_type)); + v.push_back(columns[52] + " = " + std::to_string(e.runspeed)); + v.push_back(columns[53] + " = " + std::to_string(e.MR)); + v.push_back(columns[54] + " = " + std::to_string(e.CR)); + v.push_back(columns[55] + " = " + std::to_string(e.DR)); + v.push_back(columns[56] + " = " + std::to_string(e.FR)); + v.push_back(columns[57] + " = " + std::to_string(e.PR)); + v.push_back(columns[58] + " = " + std::to_string(e.Corrup)); + v.push_back(columns[59] + " = " + std::to_string(e.PhR)); + v.push_back(columns[60] + " = " + std::to_string(e.see_invis)); + v.push_back(columns[61] + " = " + std::to_string(e.see_invis_undead)); + v.push_back(columns[62] + " = " + std::to_string(e.qglobal)); + v.push_back(columns[63] + " = " + std::to_string(e.AC)); + v.push_back(columns[64] + " = " + std::to_string(e.npc_aggro)); + v.push_back(columns[65] + " = " + std::to_string(e.spawn_limit)); + v.push_back(columns[66] + " = " + std::to_string(e.attack_speed)); + v.push_back(columns[67] + " = " + std::to_string(e.attack_delay)); + v.push_back(columns[68] + " = " + std::to_string(e.findable)); + v.push_back(columns[69] + " = " + std::to_string(e.STR)); + v.push_back(columns[70] + " = " + std::to_string(e.STA)); + v.push_back(columns[71] + " = " + std::to_string(e.DEX)); + v.push_back(columns[72] + " = " + std::to_string(e.AGI)); + v.push_back(columns[73] + " = " + std::to_string(e._INT)); + v.push_back(columns[74] + " = " + std::to_string(e.WIS)); + v.push_back(columns[75] + " = " + std::to_string(e.CHA)); + v.push_back(columns[76] + " = " + std::to_string(e.see_hide)); + v.push_back(columns[77] + " = " + std::to_string(e.see_improved_hide)); + v.push_back(columns[78] + " = " + std::to_string(e.trackable)); + v.push_back(columns[79] + " = " + std::to_string(e.isbot)); + v.push_back(columns[80] + " = " + std::to_string(e.exclude)); + v.push_back(columns[81] + " = " + std::to_string(e.ATK)); + v.push_back(columns[82] + " = " + std::to_string(e.Accuracy)); + v.push_back(columns[83] + " = " + std::to_string(e.Avoidance)); + v.push_back(columns[84] + " = " + std::to_string(e.slow_mitigation)); + v.push_back(columns[85] + " = " + std::to_string(e.version)); + v.push_back(columns[86] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[87] + " = " + std::to_string(e.scalerate)); + v.push_back(columns[88] + " = " + std::to_string(e.private_corpse)); + v.push_back(columns[89] + " = " + std::to_string(e.unique_spawn_by_name)); + v.push_back(columns[90] + " = " + std::to_string(e.underwater)); + v.push_back(columns[91] + " = " + std::to_string(e.isquest)); + v.push_back(columns[92] + " = " + std::to_string(e.emoteid)); + v.push_back(columns[93] + " = " + std::to_string(e.spellscale)); + v.push_back(columns[94] + " = " + std::to_string(e.healscale)); + v.push_back(columns[95] + " = " + std::to_string(e.no_target_hotkey)); + v.push_back(columns[96] + " = " + std::to_string(e.raid_target)); + v.push_back(columns[97] + " = " + std::to_string(e.armtexture)); + v.push_back(columns[98] + " = " + std::to_string(e.bracertexture)); + v.push_back(columns[99] + " = " + std::to_string(e.handtexture)); + v.push_back(columns[100] + " = " + std::to_string(e.legtexture)); + v.push_back(columns[101] + " = " + std::to_string(e.feettexture)); + v.push_back(columns[102] + " = " + std::to_string(e.light)); + v.push_back(columns[103] + " = " + std::to_string(e.walkspeed)); + v.push_back(columns[104] + " = " + std::to_string(e.peqid)); + v.push_back(columns[105] + " = " + std::to_string(e.unique_)); + v.push_back(columns[106] + " = " + std::to_string(e.fixed)); + v.push_back(columns[107] + " = " + std::to_string(e.ignore_despawn)); + v.push_back(columns[108] + " = " + std::to_string(e.show_name)); + v.push_back(columns[109] + " = " + std::to_string(e.untargetable)); + v.push_back(columns[110] + " = " + std::to_string(e.charm_ac)); + v.push_back(columns[111] + " = " + std::to_string(e.charm_min_dmg)); + v.push_back(columns[112] + " = " + std::to_string(e.charm_max_dmg)); + v.push_back(columns[113] + " = " + std::to_string(e.charm_attack_delay)); + v.push_back(columns[114] + " = " + std::to_string(e.charm_accuracy_rating)); + v.push_back(columns[115] + " = " + std::to_string(e.charm_avoidance_rating)); + v.push_back(columns[116] + " = " + std::to_string(e.charm_atk)); + v.push_back(columns[117] + " = " + std::to_string(e.skip_global_loot)); + v.push_back(columns[118] + " = " + std::to_string(e.rare_spawn)); + v.push_back(columns[119] + " = " + std::to_string(e.stuck_behavior)); + v.push_back(columns[120] + " = " + std::to_string(e.model)); + v.push_back(columns[121] + " = " + std::to_string(e.flymode)); + v.push_back(columns[122] + " = " + std::to_string(e.always_aggro)); + v.push_back(columns[123] + " = " + std::to_string(e.exp_mod)); + v.push_back(columns[124] + " = " + std::to_string(e.heroic_strikethrough)); + v.push_back(columns[125] + " = " + std::to_string(e.faction_amount)); + v.push_back(columns[126] + " = " + std::to_string(e.keeps_sold_items)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_types_entry.id + e.id ) ); @@ -902,299 +922,305 @@ public: static NpcTypes InsertOne( Database& db, - NpcTypes npc_types_entry + NpcTypes e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_types_entry.id)); - insert_values.push_back("'" + EscapeString(npc_types_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(npc_types_entry.lastname) + "'"); - insert_values.push_back(std::to_string(npc_types_entry.level)); - insert_values.push_back(std::to_string(npc_types_entry.race)); - insert_values.push_back(std::to_string(npc_types_entry.class_)); - insert_values.push_back(std::to_string(npc_types_entry.bodytype)); - insert_values.push_back(std::to_string(npc_types_entry.hp)); - insert_values.push_back(std::to_string(npc_types_entry.mana)); - insert_values.push_back(std::to_string(npc_types_entry.gender)); - insert_values.push_back(std::to_string(npc_types_entry.texture)); - insert_values.push_back(std::to_string(npc_types_entry.helmtexture)); - insert_values.push_back(std::to_string(npc_types_entry.herosforgemodel)); - insert_values.push_back(std::to_string(npc_types_entry.size)); - insert_values.push_back(std::to_string(npc_types_entry.hp_regen_rate)); - insert_values.push_back(std::to_string(npc_types_entry.hp_regen_per_second)); - insert_values.push_back(std::to_string(npc_types_entry.mana_regen_rate)); - insert_values.push_back(std::to_string(npc_types_entry.loottable_id)); - insert_values.push_back(std::to_string(npc_types_entry.merchant_id)); - insert_values.push_back(std::to_string(npc_types_entry.alt_currency_id)); - insert_values.push_back(std::to_string(npc_types_entry.npc_spells_id)); - insert_values.push_back(std::to_string(npc_types_entry.npc_spells_effects_id)); - insert_values.push_back(std::to_string(npc_types_entry.npc_faction_id)); - insert_values.push_back(std::to_string(npc_types_entry.adventure_template_id)); - insert_values.push_back(std::to_string(npc_types_entry.trap_template)); - insert_values.push_back(std::to_string(npc_types_entry.mindmg)); - insert_values.push_back(std::to_string(npc_types_entry.maxdmg)); - insert_values.push_back(std::to_string(npc_types_entry.attack_count)); - insert_values.push_back("'" + EscapeString(npc_types_entry.npcspecialattks) + "'"); - insert_values.push_back("'" + EscapeString(npc_types_entry.special_abilities) + "'"); - insert_values.push_back(std::to_string(npc_types_entry.aggroradius)); - insert_values.push_back(std::to_string(npc_types_entry.assistradius)); - insert_values.push_back(std::to_string(npc_types_entry.face)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_hairstyle)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_haircolor)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_eyecolor)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_eyecolor2)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_beardcolor)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_beard)); - insert_values.push_back(std::to_string(npc_types_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(npc_types_entry.drakkin_tattoo)); - insert_values.push_back(std::to_string(npc_types_entry.drakkin_details)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_id)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_red)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_green)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_blue)); - insert_values.push_back(std::to_string(npc_types_entry.d_melee_texture1)); - insert_values.push_back(std::to_string(npc_types_entry.d_melee_texture2)); - insert_values.push_back("'" + EscapeString(npc_types_entry.ammo_idfile) + "'"); - insert_values.push_back(std::to_string(npc_types_entry.prim_melee_type)); - insert_values.push_back(std::to_string(npc_types_entry.sec_melee_type)); - insert_values.push_back(std::to_string(npc_types_entry.ranged_type)); - insert_values.push_back(std::to_string(npc_types_entry.runspeed)); - insert_values.push_back(std::to_string(npc_types_entry.MR)); - insert_values.push_back(std::to_string(npc_types_entry.CR)); - insert_values.push_back(std::to_string(npc_types_entry.DR)); - insert_values.push_back(std::to_string(npc_types_entry.FR)); - insert_values.push_back(std::to_string(npc_types_entry.PR)); - insert_values.push_back(std::to_string(npc_types_entry.Corrup)); - insert_values.push_back(std::to_string(npc_types_entry.PhR)); - insert_values.push_back(std::to_string(npc_types_entry.see_invis)); - insert_values.push_back(std::to_string(npc_types_entry.see_invis_undead)); - insert_values.push_back(std::to_string(npc_types_entry.qglobal)); - insert_values.push_back(std::to_string(npc_types_entry.AC)); - insert_values.push_back(std::to_string(npc_types_entry.npc_aggro)); - insert_values.push_back(std::to_string(npc_types_entry.spawn_limit)); - insert_values.push_back(std::to_string(npc_types_entry.attack_speed)); - insert_values.push_back(std::to_string(npc_types_entry.attack_delay)); - insert_values.push_back(std::to_string(npc_types_entry.findable)); - insert_values.push_back(std::to_string(npc_types_entry.STR)); - insert_values.push_back(std::to_string(npc_types_entry.STA)); - insert_values.push_back(std::to_string(npc_types_entry.DEX)); - insert_values.push_back(std::to_string(npc_types_entry.AGI)); - insert_values.push_back(std::to_string(npc_types_entry._INT)); - insert_values.push_back(std::to_string(npc_types_entry.WIS)); - insert_values.push_back(std::to_string(npc_types_entry.CHA)); - insert_values.push_back(std::to_string(npc_types_entry.see_hide)); - insert_values.push_back(std::to_string(npc_types_entry.see_improved_hide)); - insert_values.push_back(std::to_string(npc_types_entry.trackable)); - insert_values.push_back(std::to_string(npc_types_entry.isbot)); - insert_values.push_back(std::to_string(npc_types_entry.exclude)); - insert_values.push_back(std::to_string(npc_types_entry.ATK)); - insert_values.push_back(std::to_string(npc_types_entry.Accuracy)); - insert_values.push_back(std::to_string(npc_types_entry.Avoidance)); - insert_values.push_back(std::to_string(npc_types_entry.slow_mitigation)); - insert_values.push_back(std::to_string(npc_types_entry.version)); - insert_values.push_back(std::to_string(npc_types_entry.maxlevel)); - insert_values.push_back(std::to_string(npc_types_entry.scalerate)); - insert_values.push_back(std::to_string(npc_types_entry.private_corpse)); - insert_values.push_back(std::to_string(npc_types_entry.unique_spawn_by_name)); - insert_values.push_back(std::to_string(npc_types_entry.underwater)); - insert_values.push_back(std::to_string(npc_types_entry.isquest)); - insert_values.push_back(std::to_string(npc_types_entry.emoteid)); - insert_values.push_back(std::to_string(npc_types_entry.spellscale)); - insert_values.push_back(std::to_string(npc_types_entry.healscale)); - insert_values.push_back(std::to_string(npc_types_entry.no_target_hotkey)); - insert_values.push_back(std::to_string(npc_types_entry.raid_target)); - insert_values.push_back(std::to_string(npc_types_entry.armtexture)); - insert_values.push_back(std::to_string(npc_types_entry.bracertexture)); - insert_values.push_back(std::to_string(npc_types_entry.handtexture)); - insert_values.push_back(std::to_string(npc_types_entry.legtexture)); - insert_values.push_back(std::to_string(npc_types_entry.feettexture)); - insert_values.push_back(std::to_string(npc_types_entry.light)); - insert_values.push_back(std::to_string(npc_types_entry.walkspeed)); - insert_values.push_back(std::to_string(npc_types_entry.peqid)); - insert_values.push_back(std::to_string(npc_types_entry.unique_)); - insert_values.push_back(std::to_string(npc_types_entry.fixed)); - insert_values.push_back(std::to_string(npc_types_entry.ignore_despawn)); - insert_values.push_back(std::to_string(npc_types_entry.show_name)); - insert_values.push_back(std::to_string(npc_types_entry.untargetable)); - insert_values.push_back(std::to_string(npc_types_entry.charm_ac)); - insert_values.push_back(std::to_string(npc_types_entry.charm_min_dmg)); - insert_values.push_back(std::to_string(npc_types_entry.charm_max_dmg)); - insert_values.push_back(std::to_string(npc_types_entry.charm_attack_delay)); - insert_values.push_back(std::to_string(npc_types_entry.charm_accuracy_rating)); - insert_values.push_back(std::to_string(npc_types_entry.charm_avoidance_rating)); - insert_values.push_back(std::to_string(npc_types_entry.charm_atk)); - insert_values.push_back(std::to_string(npc_types_entry.skip_global_loot)); - insert_values.push_back(std::to_string(npc_types_entry.rare_spawn)); - insert_values.push_back(std::to_string(npc_types_entry.stuck_behavior)); - insert_values.push_back(std::to_string(npc_types_entry.model)); - insert_values.push_back(std::to_string(npc_types_entry.flymode)); - insert_values.push_back(std::to_string(npc_types_entry.always_aggro)); - insert_values.push_back(std::to_string(npc_types_entry.exp_mod)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.lastname) + "'"); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.bodytype)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helmtexture)); + v.push_back(std::to_string(e.herosforgemodel)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.hp_regen_per_second)); + v.push_back(std::to_string(e.mana_regen_rate)); + v.push_back(std::to_string(e.loottable_id)); + v.push_back(std::to_string(e.merchant_id)); + v.push_back(std::to_string(e.alt_currency_id)); + v.push_back(std::to_string(e.npc_spells_id)); + v.push_back(std::to_string(e.npc_spells_effects_id)); + v.push_back(std::to_string(e.npc_faction_id)); + v.push_back(std::to_string(e.adventure_template_id)); + v.push_back(std::to_string(e.trap_template)); + v.push_back(std::to_string(e.mindmg)); + v.push_back(std::to_string(e.maxdmg)); + v.push_back(std::to_string(e.attack_count)); + v.push_back("'" + Strings::Escape(e.npcspecialattks) + "'"); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(std::to_string(e.aggroradius)); + v.push_back(std::to_string(e.assistradius)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.luclin_hairstyle)); + v.push_back(std::to_string(e.luclin_haircolor)); + v.push_back(std::to_string(e.luclin_eyecolor)); + v.push_back(std::to_string(e.luclin_eyecolor2)); + v.push_back(std::to_string(e.luclin_beardcolor)); + v.push_back(std::to_string(e.luclin_beard)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.armortint_id)); + v.push_back(std::to_string(e.armortint_red)); + v.push_back(std::to_string(e.armortint_green)); + v.push_back(std::to_string(e.armortint_blue)); + v.push_back(std::to_string(e.d_melee_texture1)); + v.push_back(std::to_string(e.d_melee_texture2)); + v.push_back("'" + Strings::Escape(e.ammo_idfile) + "'"); + v.push_back(std::to_string(e.prim_melee_type)); + v.push_back(std::to_string(e.sec_melee_type)); + v.push_back(std::to_string(e.ranged_type)); + v.push_back(std::to_string(e.runspeed)); + v.push_back(std::to_string(e.MR)); + v.push_back(std::to_string(e.CR)); + v.push_back(std::to_string(e.DR)); + v.push_back(std::to_string(e.FR)); + v.push_back(std::to_string(e.PR)); + v.push_back(std::to_string(e.Corrup)); + v.push_back(std::to_string(e.PhR)); + v.push_back(std::to_string(e.see_invis)); + v.push_back(std::to_string(e.see_invis_undead)); + v.push_back(std::to_string(e.qglobal)); + v.push_back(std::to_string(e.AC)); + v.push_back(std::to_string(e.npc_aggro)); + v.push_back(std::to_string(e.spawn_limit)); + v.push_back(std::to_string(e.attack_speed)); + v.push_back(std::to_string(e.attack_delay)); + v.push_back(std::to_string(e.findable)); + v.push_back(std::to_string(e.STR)); + v.push_back(std::to_string(e.STA)); + v.push_back(std::to_string(e.DEX)); + v.push_back(std::to_string(e.AGI)); + v.push_back(std::to_string(e._INT)); + v.push_back(std::to_string(e.WIS)); + v.push_back(std::to_string(e.CHA)); + v.push_back(std::to_string(e.see_hide)); + v.push_back(std::to_string(e.see_improved_hide)); + v.push_back(std::to_string(e.trackable)); + v.push_back(std::to_string(e.isbot)); + v.push_back(std::to_string(e.exclude)); + v.push_back(std::to_string(e.ATK)); + v.push_back(std::to_string(e.Accuracy)); + v.push_back(std::to_string(e.Avoidance)); + v.push_back(std::to_string(e.slow_mitigation)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.scalerate)); + v.push_back(std::to_string(e.private_corpse)); + v.push_back(std::to_string(e.unique_spawn_by_name)); + v.push_back(std::to_string(e.underwater)); + v.push_back(std::to_string(e.isquest)); + v.push_back(std::to_string(e.emoteid)); + v.push_back(std::to_string(e.spellscale)); + v.push_back(std::to_string(e.healscale)); + v.push_back(std::to_string(e.no_target_hotkey)); + v.push_back(std::to_string(e.raid_target)); + v.push_back(std::to_string(e.armtexture)); + v.push_back(std::to_string(e.bracertexture)); + v.push_back(std::to_string(e.handtexture)); + v.push_back(std::to_string(e.legtexture)); + v.push_back(std::to_string(e.feettexture)); + v.push_back(std::to_string(e.light)); + v.push_back(std::to_string(e.walkspeed)); + v.push_back(std::to_string(e.peqid)); + v.push_back(std::to_string(e.unique_)); + v.push_back(std::to_string(e.fixed)); + v.push_back(std::to_string(e.ignore_despawn)); + v.push_back(std::to_string(e.show_name)); + v.push_back(std::to_string(e.untargetable)); + v.push_back(std::to_string(e.charm_ac)); + v.push_back(std::to_string(e.charm_min_dmg)); + v.push_back(std::to_string(e.charm_max_dmg)); + v.push_back(std::to_string(e.charm_attack_delay)); + v.push_back(std::to_string(e.charm_accuracy_rating)); + v.push_back(std::to_string(e.charm_avoidance_rating)); + v.push_back(std::to_string(e.charm_atk)); + v.push_back(std::to_string(e.skip_global_loot)); + v.push_back(std::to_string(e.rare_spawn)); + v.push_back(std::to_string(e.stuck_behavior)); + v.push_back(std::to_string(e.model)); + v.push_back(std::to_string(e.flymode)); + v.push_back(std::to_string(e.always_aggro)); + v.push_back(std::to_string(e.exp_mod)); + v.push_back(std::to_string(e.heroic_strikethrough)); + v.push_back(std::to_string(e.faction_amount)); + v.push_back(std::to_string(e.keeps_sold_items)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_types_entry.id = results.LastInsertedID(); - return npc_types_entry; + e.id = results.LastInsertedID(); + return e; } - npc_types_entry = NewEntity(); + e = NewEntity(); - return npc_types_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_types_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_types_entry: npc_types_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_types_entry.id)); - insert_values.push_back("'" + EscapeString(npc_types_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(npc_types_entry.lastname) + "'"); - insert_values.push_back(std::to_string(npc_types_entry.level)); - insert_values.push_back(std::to_string(npc_types_entry.race)); - insert_values.push_back(std::to_string(npc_types_entry.class_)); - insert_values.push_back(std::to_string(npc_types_entry.bodytype)); - insert_values.push_back(std::to_string(npc_types_entry.hp)); - insert_values.push_back(std::to_string(npc_types_entry.mana)); - insert_values.push_back(std::to_string(npc_types_entry.gender)); - insert_values.push_back(std::to_string(npc_types_entry.texture)); - insert_values.push_back(std::to_string(npc_types_entry.helmtexture)); - insert_values.push_back(std::to_string(npc_types_entry.herosforgemodel)); - insert_values.push_back(std::to_string(npc_types_entry.size)); - insert_values.push_back(std::to_string(npc_types_entry.hp_regen_rate)); - insert_values.push_back(std::to_string(npc_types_entry.hp_regen_per_second)); - insert_values.push_back(std::to_string(npc_types_entry.mana_regen_rate)); - insert_values.push_back(std::to_string(npc_types_entry.loottable_id)); - insert_values.push_back(std::to_string(npc_types_entry.merchant_id)); - insert_values.push_back(std::to_string(npc_types_entry.alt_currency_id)); - insert_values.push_back(std::to_string(npc_types_entry.npc_spells_id)); - insert_values.push_back(std::to_string(npc_types_entry.npc_spells_effects_id)); - insert_values.push_back(std::to_string(npc_types_entry.npc_faction_id)); - insert_values.push_back(std::to_string(npc_types_entry.adventure_template_id)); - insert_values.push_back(std::to_string(npc_types_entry.trap_template)); - insert_values.push_back(std::to_string(npc_types_entry.mindmg)); - insert_values.push_back(std::to_string(npc_types_entry.maxdmg)); - insert_values.push_back(std::to_string(npc_types_entry.attack_count)); - insert_values.push_back("'" + EscapeString(npc_types_entry.npcspecialattks) + "'"); - insert_values.push_back("'" + EscapeString(npc_types_entry.special_abilities) + "'"); - insert_values.push_back(std::to_string(npc_types_entry.aggroradius)); - insert_values.push_back(std::to_string(npc_types_entry.assistradius)); - insert_values.push_back(std::to_string(npc_types_entry.face)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_hairstyle)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_haircolor)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_eyecolor)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_eyecolor2)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_beardcolor)); - insert_values.push_back(std::to_string(npc_types_entry.luclin_beard)); - insert_values.push_back(std::to_string(npc_types_entry.drakkin_heritage)); - insert_values.push_back(std::to_string(npc_types_entry.drakkin_tattoo)); - insert_values.push_back(std::to_string(npc_types_entry.drakkin_details)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_id)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_red)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_green)); - insert_values.push_back(std::to_string(npc_types_entry.armortint_blue)); - insert_values.push_back(std::to_string(npc_types_entry.d_melee_texture1)); - insert_values.push_back(std::to_string(npc_types_entry.d_melee_texture2)); - insert_values.push_back("'" + EscapeString(npc_types_entry.ammo_idfile) + "'"); - insert_values.push_back(std::to_string(npc_types_entry.prim_melee_type)); - insert_values.push_back(std::to_string(npc_types_entry.sec_melee_type)); - insert_values.push_back(std::to_string(npc_types_entry.ranged_type)); - insert_values.push_back(std::to_string(npc_types_entry.runspeed)); - insert_values.push_back(std::to_string(npc_types_entry.MR)); - insert_values.push_back(std::to_string(npc_types_entry.CR)); - insert_values.push_back(std::to_string(npc_types_entry.DR)); - insert_values.push_back(std::to_string(npc_types_entry.FR)); - insert_values.push_back(std::to_string(npc_types_entry.PR)); - insert_values.push_back(std::to_string(npc_types_entry.Corrup)); - insert_values.push_back(std::to_string(npc_types_entry.PhR)); - insert_values.push_back(std::to_string(npc_types_entry.see_invis)); - insert_values.push_back(std::to_string(npc_types_entry.see_invis_undead)); - insert_values.push_back(std::to_string(npc_types_entry.qglobal)); - insert_values.push_back(std::to_string(npc_types_entry.AC)); - insert_values.push_back(std::to_string(npc_types_entry.npc_aggro)); - insert_values.push_back(std::to_string(npc_types_entry.spawn_limit)); - insert_values.push_back(std::to_string(npc_types_entry.attack_speed)); - insert_values.push_back(std::to_string(npc_types_entry.attack_delay)); - insert_values.push_back(std::to_string(npc_types_entry.findable)); - insert_values.push_back(std::to_string(npc_types_entry.STR)); - insert_values.push_back(std::to_string(npc_types_entry.STA)); - insert_values.push_back(std::to_string(npc_types_entry.DEX)); - insert_values.push_back(std::to_string(npc_types_entry.AGI)); - insert_values.push_back(std::to_string(npc_types_entry._INT)); - insert_values.push_back(std::to_string(npc_types_entry.WIS)); - insert_values.push_back(std::to_string(npc_types_entry.CHA)); - insert_values.push_back(std::to_string(npc_types_entry.see_hide)); - insert_values.push_back(std::to_string(npc_types_entry.see_improved_hide)); - insert_values.push_back(std::to_string(npc_types_entry.trackable)); - insert_values.push_back(std::to_string(npc_types_entry.isbot)); - insert_values.push_back(std::to_string(npc_types_entry.exclude)); - insert_values.push_back(std::to_string(npc_types_entry.ATK)); - insert_values.push_back(std::to_string(npc_types_entry.Accuracy)); - insert_values.push_back(std::to_string(npc_types_entry.Avoidance)); - insert_values.push_back(std::to_string(npc_types_entry.slow_mitigation)); - insert_values.push_back(std::to_string(npc_types_entry.version)); - insert_values.push_back(std::to_string(npc_types_entry.maxlevel)); - insert_values.push_back(std::to_string(npc_types_entry.scalerate)); - insert_values.push_back(std::to_string(npc_types_entry.private_corpse)); - insert_values.push_back(std::to_string(npc_types_entry.unique_spawn_by_name)); - insert_values.push_back(std::to_string(npc_types_entry.underwater)); - insert_values.push_back(std::to_string(npc_types_entry.isquest)); - insert_values.push_back(std::to_string(npc_types_entry.emoteid)); - insert_values.push_back(std::to_string(npc_types_entry.spellscale)); - insert_values.push_back(std::to_string(npc_types_entry.healscale)); - insert_values.push_back(std::to_string(npc_types_entry.no_target_hotkey)); - insert_values.push_back(std::to_string(npc_types_entry.raid_target)); - insert_values.push_back(std::to_string(npc_types_entry.armtexture)); - insert_values.push_back(std::to_string(npc_types_entry.bracertexture)); - insert_values.push_back(std::to_string(npc_types_entry.handtexture)); - insert_values.push_back(std::to_string(npc_types_entry.legtexture)); - insert_values.push_back(std::to_string(npc_types_entry.feettexture)); - insert_values.push_back(std::to_string(npc_types_entry.light)); - insert_values.push_back(std::to_string(npc_types_entry.walkspeed)); - insert_values.push_back(std::to_string(npc_types_entry.peqid)); - insert_values.push_back(std::to_string(npc_types_entry.unique_)); - insert_values.push_back(std::to_string(npc_types_entry.fixed)); - insert_values.push_back(std::to_string(npc_types_entry.ignore_despawn)); - insert_values.push_back(std::to_string(npc_types_entry.show_name)); - insert_values.push_back(std::to_string(npc_types_entry.untargetable)); - insert_values.push_back(std::to_string(npc_types_entry.charm_ac)); - insert_values.push_back(std::to_string(npc_types_entry.charm_min_dmg)); - insert_values.push_back(std::to_string(npc_types_entry.charm_max_dmg)); - insert_values.push_back(std::to_string(npc_types_entry.charm_attack_delay)); - insert_values.push_back(std::to_string(npc_types_entry.charm_accuracy_rating)); - insert_values.push_back(std::to_string(npc_types_entry.charm_avoidance_rating)); - insert_values.push_back(std::to_string(npc_types_entry.charm_atk)); - insert_values.push_back(std::to_string(npc_types_entry.skip_global_loot)); - insert_values.push_back(std::to_string(npc_types_entry.rare_spawn)); - insert_values.push_back(std::to_string(npc_types_entry.stuck_behavior)); - insert_values.push_back(std::to_string(npc_types_entry.model)); - insert_values.push_back(std::to_string(npc_types_entry.flymode)); - insert_values.push_back(std::to_string(npc_types_entry.always_aggro)); - insert_values.push_back(std::to_string(npc_types_entry.exp_mod)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.lastname) + "'"); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.bodytype)); + v.push_back(std::to_string(e.hp)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helmtexture)); + v.push_back(std::to_string(e.herosforgemodel)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.hp_regen_per_second)); + v.push_back(std::to_string(e.mana_regen_rate)); + v.push_back(std::to_string(e.loottable_id)); + v.push_back(std::to_string(e.merchant_id)); + v.push_back(std::to_string(e.alt_currency_id)); + v.push_back(std::to_string(e.npc_spells_id)); + v.push_back(std::to_string(e.npc_spells_effects_id)); + v.push_back(std::to_string(e.npc_faction_id)); + v.push_back(std::to_string(e.adventure_template_id)); + v.push_back(std::to_string(e.trap_template)); + v.push_back(std::to_string(e.mindmg)); + v.push_back(std::to_string(e.maxdmg)); + v.push_back(std::to_string(e.attack_count)); + v.push_back("'" + Strings::Escape(e.npcspecialattks) + "'"); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(std::to_string(e.aggroradius)); + v.push_back(std::to_string(e.assistradius)); + v.push_back(std::to_string(e.face)); + v.push_back(std::to_string(e.luclin_hairstyle)); + v.push_back(std::to_string(e.luclin_haircolor)); + v.push_back(std::to_string(e.luclin_eyecolor)); + v.push_back(std::to_string(e.luclin_eyecolor2)); + v.push_back(std::to_string(e.luclin_beardcolor)); + v.push_back(std::to_string(e.luclin_beard)); + v.push_back(std::to_string(e.drakkin_heritage)); + v.push_back(std::to_string(e.drakkin_tattoo)); + v.push_back(std::to_string(e.drakkin_details)); + v.push_back(std::to_string(e.armortint_id)); + v.push_back(std::to_string(e.armortint_red)); + v.push_back(std::to_string(e.armortint_green)); + v.push_back(std::to_string(e.armortint_blue)); + v.push_back(std::to_string(e.d_melee_texture1)); + v.push_back(std::to_string(e.d_melee_texture2)); + v.push_back("'" + Strings::Escape(e.ammo_idfile) + "'"); + v.push_back(std::to_string(e.prim_melee_type)); + v.push_back(std::to_string(e.sec_melee_type)); + v.push_back(std::to_string(e.ranged_type)); + v.push_back(std::to_string(e.runspeed)); + v.push_back(std::to_string(e.MR)); + v.push_back(std::to_string(e.CR)); + v.push_back(std::to_string(e.DR)); + v.push_back(std::to_string(e.FR)); + v.push_back(std::to_string(e.PR)); + v.push_back(std::to_string(e.Corrup)); + v.push_back(std::to_string(e.PhR)); + v.push_back(std::to_string(e.see_invis)); + v.push_back(std::to_string(e.see_invis_undead)); + v.push_back(std::to_string(e.qglobal)); + v.push_back(std::to_string(e.AC)); + v.push_back(std::to_string(e.npc_aggro)); + v.push_back(std::to_string(e.spawn_limit)); + v.push_back(std::to_string(e.attack_speed)); + v.push_back(std::to_string(e.attack_delay)); + v.push_back(std::to_string(e.findable)); + v.push_back(std::to_string(e.STR)); + v.push_back(std::to_string(e.STA)); + v.push_back(std::to_string(e.DEX)); + v.push_back(std::to_string(e.AGI)); + v.push_back(std::to_string(e._INT)); + v.push_back(std::to_string(e.WIS)); + v.push_back(std::to_string(e.CHA)); + v.push_back(std::to_string(e.see_hide)); + v.push_back(std::to_string(e.see_improved_hide)); + v.push_back(std::to_string(e.trackable)); + v.push_back(std::to_string(e.isbot)); + v.push_back(std::to_string(e.exclude)); + v.push_back(std::to_string(e.ATK)); + v.push_back(std::to_string(e.Accuracy)); + v.push_back(std::to_string(e.Avoidance)); + v.push_back(std::to_string(e.slow_mitigation)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.scalerate)); + v.push_back(std::to_string(e.private_corpse)); + v.push_back(std::to_string(e.unique_spawn_by_name)); + v.push_back(std::to_string(e.underwater)); + v.push_back(std::to_string(e.isquest)); + v.push_back(std::to_string(e.emoteid)); + v.push_back(std::to_string(e.spellscale)); + v.push_back(std::to_string(e.healscale)); + v.push_back(std::to_string(e.no_target_hotkey)); + v.push_back(std::to_string(e.raid_target)); + v.push_back(std::to_string(e.armtexture)); + v.push_back(std::to_string(e.bracertexture)); + v.push_back(std::to_string(e.handtexture)); + v.push_back(std::to_string(e.legtexture)); + v.push_back(std::to_string(e.feettexture)); + v.push_back(std::to_string(e.light)); + v.push_back(std::to_string(e.walkspeed)); + v.push_back(std::to_string(e.peqid)); + v.push_back(std::to_string(e.unique_)); + v.push_back(std::to_string(e.fixed)); + v.push_back(std::to_string(e.ignore_despawn)); + v.push_back(std::to_string(e.show_name)); + v.push_back(std::to_string(e.untargetable)); + v.push_back(std::to_string(e.charm_ac)); + v.push_back(std::to_string(e.charm_min_dmg)); + v.push_back(std::to_string(e.charm_max_dmg)); + v.push_back(std::to_string(e.charm_attack_delay)); + v.push_back(std::to_string(e.charm_accuracy_rating)); + v.push_back(std::to_string(e.charm_avoidance_rating)); + v.push_back(std::to_string(e.charm_atk)); + v.push_back(std::to_string(e.skip_global_loot)); + v.push_back(std::to_string(e.rare_spawn)); + v.push_back(std::to_string(e.stuck_behavior)); + v.push_back(std::to_string(e.model)); + v.push_back(std::to_string(e.flymode)); + v.push_back(std::to_string(e.always_aggro)); + v.push_back(std::to_string(e.exp_mod)); + v.push_back(std::to_string(e.heroic_strikethrough)); + v.push_back(std::to_string(e.faction_amount)); + v.push_back(std::to_string(e.keeps_sold_items)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -1215,140 +1241,143 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcTypes entry{}; + NpcTypes e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.lastname = row[2] ? row[2] : ""; - entry.level = atoi(row[3]); - entry.race = atoi(row[4]); - entry.class_ = atoi(row[5]); - entry.bodytype = atoi(row[6]); - entry.hp = strtoll(row[7], nullptr, 10); - entry.mana = strtoll(row[8], nullptr, 10); - entry.gender = atoi(row[9]); - entry.texture = atoi(row[10]); - entry.helmtexture = atoi(row[11]); - entry.herosforgemodel = atoi(row[12]); - entry.size = static_cast(atof(row[13])); - entry.hp_regen_rate = strtoll(row[14], nullptr, 10); - entry.hp_regen_per_second = strtoll(row[15], nullptr, 10); - entry.mana_regen_rate = strtoll(row[16], nullptr, 10); - entry.loottable_id = atoi(row[17]); - entry.merchant_id = atoi(row[18]); - entry.alt_currency_id = atoi(row[19]); - entry.npc_spells_id = atoi(row[20]); - entry.npc_spells_effects_id = atoi(row[21]); - entry.npc_faction_id = atoi(row[22]); - entry.adventure_template_id = atoi(row[23]); - entry.trap_template = atoi(row[24]); - entry.mindmg = atoi(row[25]); - entry.maxdmg = atoi(row[26]); - entry.attack_count = atoi(row[27]); - entry.npcspecialattks = row[28] ? row[28] : ""; - entry.special_abilities = row[29] ? row[29] : ""; - entry.aggroradius = atoi(row[30]); - entry.assistradius = atoi(row[31]); - entry.face = atoi(row[32]); - entry.luclin_hairstyle = atoi(row[33]); - entry.luclin_haircolor = atoi(row[34]); - entry.luclin_eyecolor = atoi(row[35]); - entry.luclin_eyecolor2 = atoi(row[36]); - entry.luclin_beardcolor = atoi(row[37]); - entry.luclin_beard = atoi(row[38]); - entry.drakkin_heritage = atoi(row[39]); - entry.drakkin_tattoo = atoi(row[40]); - entry.drakkin_details = atoi(row[41]); - entry.armortint_id = atoi(row[42]); - entry.armortint_red = atoi(row[43]); - entry.armortint_green = atoi(row[44]); - entry.armortint_blue = atoi(row[45]); - entry.d_melee_texture1 = atoi(row[46]); - entry.d_melee_texture2 = atoi(row[47]); - entry.ammo_idfile = row[48] ? row[48] : ""; - entry.prim_melee_type = atoi(row[49]); - entry.sec_melee_type = atoi(row[50]); - entry.ranged_type = atoi(row[51]); - entry.runspeed = static_cast(atof(row[52])); - entry.MR = atoi(row[53]); - entry.CR = atoi(row[54]); - entry.DR = atoi(row[55]); - entry.FR = atoi(row[56]); - entry.PR = atoi(row[57]); - entry.Corrup = atoi(row[58]); - entry.PhR = atoi(row[59]); - entry.see_invis = atoi(row[60]); - entry.see_invis_undead = atoi(row[61]); - entry.qglobal = atoi(row[62]); - entry.AC = atoi(row[63]); - entry.npc_aggro = atoi(row[64]); - entry.spawn_limit = atoi(row[65]); - entry.attack_speed = static_cast(atof(row[66])); - entry.attack_delay = atoi(row[67]); - entry.findable = atoi(row[68]); - entry.STR = atoi(row[69]); - entry.STA = atoi(row[70]); - entry.DEX = atoi(row[71]); - entry.AGI = atoi(row[72]); - entry._INT = atoi(row[73]); - entry.WIS = atoi(row[74]); - entry.CHA = atoi(row[75]); - entry.see_hide = atoi(row[76]); - entry.see_improved_hide = atoi(row[77]); - entry.trackable = atoi(row[78]); - entry.isbot = atoi(row[79]); - entry.exclude = atoi(row[80]); - entry.ATK = atoi(row[81]); - entry.Accuracy = atoi(row[82]); - entry.Avoidance = atoi(row[83]); - entry.slow_mitigation = atoi(row[84]); - entry.version = atoi(row[85]); - entry.maxlevel = atoi(row[86]); - entry.scalerate = atoi(row[87]); - entry.private_corpse = atoi(row[88]); - entry.unique_spawn_by_name = atoi(row[89]); - entry.underwater = atoi(row[90]); - entry.isquest = atoi(row[91]); - entry.emoteid = atoi(row[92]); - entry.spellscale = static_cast(atof(row[93])); - entry.healscale = static_cast(atof(row[94])); - entry.no_target_hotkey = atoi(row[95]); - entry.raid_target = atoi(row[96]); - entry.armtexture = atoi(row[97]); - entry.bracertexture = atoi(row[98]); - entry.handtexture = atoi(row[99]); - entry.legtexture = atoi(row[100]); - entry.feettexture = atoi(row[101]); - entry.light = atoi(row[102]); - entry.walkspeed = atoi(row[103]); - entry.peqid = atoi(row[104]); - entry.unique_ = atoi(row[105]); - entry.fixed = atoi(row[106]); - entry.ignore_despawn = atoi(row[107]); - entry.show_name = atoi(row[108]); - entry.untargetable = atoi(row[109]); - entry.charm_ac = atoi(row[110]); - entry.charm_min_dmg = atoi(row[111]); - entry.charm_max_dmg = atoi(row[112]); - entry.charm_attack_delay = atoi(row[113]); - entry.charm_accuracy_rating = atoi(row[114]); - entry.charm_avoidance_rating = atoi(row[115]); - entry.charm_atk = atoi(row[116]); - entry.skip_global_loot = atoi(row[117]); - entry.rare_spawn = atoi(row[118]); - entry.stuck_behavior = atoi(row[119]); - entry.model = atoi(row[120]); - entry.flymode = atoi(row[121]); - entry.always_aggro = atoi(row[122]); - entry.exp_mod = atoi(row[123]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.lastname = row[2] ? row[2] : ""; + e.level = static_cast(strtoul(row[3], nullptr, 10)); + e.race = static_cast(strtoul(row[4], nullptr, 10)); + e.class_ = static_cast(strtoul(row[5], nullptr, 10)); + e.bodytype = static_cast(atoi(row[6])); + e.hp = strtoll(row[7], nullptr, 10); + e.mana = strtoll(row[8], nullptr, 10); + e.gender = static_cast(strtoul(row[9], nullptr, 10)); + e.texture = static_cast(strtoul(row[10], nullptr, 10)); + e.helmtexture = static_cast(strtoul(row[11], nullptr, 10)); + e.herosforgemodel = static_cast(atoi(row[12])); + e.size = strtof(row[13], nullptr); + e.hp_regen_rate = strtoll(row[14], nullptr, 10); + e.hp_regen_per_second = strtoll(row[15], nullptr, 10); + e.mana_regen_rate = strtoll(row[16], nullptr, 10); + e.loottable_id = static_cast(strtoul(row[17], nullptr, 10)); + e.merchant_id = static_cast(strtoul(row[18], nullptr, 10)); + e.alt_currency_id = static_cast(strtoul(row[19], nullptr, 10)); + e.npc_spells_id = static_cast(strtoul(row[20], nullptr, 10)); + e.npc_spells_effects_id = static_cast(strtoul(row[21], nullptr, 10)); + e.npc_faction_id = static_cast(atoi(row[22])); + e.adventure_template_id = static_cast(strtoul(row[23], nullptr, 10)); + e.trap_template = static_cast(strtoul(row[24], nullptr, 10)); + e.mindmg = static_cast(strtoul(row[25], nullptr, 10)); + e.maxdmg = static_cast(strtoul(row[26], nullptr, 10)); + e.attack_count = static_cast(atoi(row[27])); + e.npcspecialattks = row[28] ? row[28] : ""; + e.special_abilities = row[29] ? row[29] : ""; + e.aggroradius = static_cast(strtoul(row[30], nullptr, 10)); + e.assistradius = static_cast(strtoul(row[31], nullptr, 10)); + e.face = static_cast(strtoul(row[32], nullptr, 10)); + e.luclin_hairstyle = static_cast(strtoul(row[33], nullptr, 10)); + e.luclin_haircolor = static_cast(strtoul(row[34], nullptr, 10)); + e.luclin_eyecolor = static_cast(strtoul(row[35], nullptr, 10)); + e.luclin_eyecolor2 = static_cast(strtoul(row[36], nullptr, 10)); + e.luclin_beardcolor = static_cast(strtoul(row[37], nullptr, 10)); + e.luclin_beard = static_cast(strtoul(row[38], nullptr, 10)); + e.drakkin_heritage = static_cast(atoi(row[39])); + e.drakkin_tattoo = static_cast(atoi(row[40])); + e.drakkin_details = static_cast(atoi(row[41])); + e.armortint_id = static_cast(strtoul(row[42], nullptr, 10)); + e.armortint_red = static_cast(strtoul(row[43], nullptr, 10)); + e.armortint_green = static_cast(strtoul(row[44], nullptr, 10)); + e.armortint_blue = static_cast(strtoul(row[45], nullptr, 10)); + e.d_melee_texture1 = static_cast(atoi(row[46])); + e.d_melee_texture2 = static_cast(atoi(row[47])); + e.ammo_idfile = row[48] ? row[48] : ""; + e.prim_melee_type = static_cast(strtoul(row[49], nullptr, 10)); + e.sec_melee_type = static_cast(strtoul(row[50], nullptr, 10)); + e.ranged_type = static_cast(strtoul(row[51], nullptr, 10)); + e.runspeed = strtof(row[52], nullptr); + e.MR = static_cast(atoi(row[53])); + e.CR = static_cast(atoi(row[54])); + e.DR = static_cast(atoi(row[55])); + e.FR = static_cast(atoi(row[56])); + e.PR = static_cast(atoi(row[57])); + e.Corrup = static_cast(atoi(row[58])); + e.PhR = static_cast(strtoul(row[59], nullptr, 10)); + e.see_invis = static_cast(atoi(row[60])); + e.see_invis_undead = static_cast(atoi(row[61])); + e.qglobal = static_cast(strtoul(row[62], nullptr, 10)); + e.AC = static_cast(atoi(row[63])); + e.npc_aggro = static_cast(atoi(row[64])); + e.spawn_limit = static_cast(atoi(row[65])); + e.attack_speed = strtof(row[66], nullptr); + e.attack_delay = static_cast(strtoul(row[67], nullptr, 10)); + e.findable = static_cast(atoi(row[68])); + e.STR = static_cast(strtoul(row[69], nullptr, 10)); + e.STA = static_cast(strtoul(row[70], nullptr, 10)); + e.DEX = static_cast(strtoul(row[71], nullptr, 10)); + e.AGI = static_cast(strtoul(row[72], nullptr, 10)); + e._INT = static_cast(strtoul(row[73], nullptr, 10)); + e.WIS = static_cast(strtoul(row[74], nullptr, 10)); + e.CHA = static_cast(strtoul(row[75], nullptr, 10)); + e.see_hide = static_cast(atoi(row[76])); + e.see_improved_hide = static_cast(atoi(row[77])); + e.trackable = static_cast(atoi(row[78])); + e.isbot = static_cast(atoi(row[79])); + e.exclude = static_cast(atoi(row[80])); + e.ATK = static_cast(atoi(row[81])); + e.Accuracy = static_cast(atoi(row[82])); + e.Avoidance = static_cast(strtoul(row[83], nullptr, 10)); + e.slow_mitigation = static_cast(atoi(row[84])); + e.version = static_cast(strtoul(row[85], nullptr, 10)); + e.maxlevel = static_cast(atoi(row[86])); + e.scalerate = static_cast(atoi(row[87])); + e.private_corpse = static_cast(strtoul(row[88], nullptr, 10)); + e.unique_spawn_by_name = static_cast(strtoul(row[89], nullptr, 10)); + e.underwater = static_cast(strtoul(row[90], nullptr, 10)); + e.isquest = static_cast(atoi(row[91])); + e.emoteid = static_cast(strtoul(row[92], nullptr, 10)); + e.spellscale = strtof(row[93], nullptr); + e.healscale = strtof(row[94], nullptr); + e.no_target_hotkey = static_cast(strtoul(row[95], nullptr, 10)); + e.raid_target = static_cast(strtoul(row[96], nullptr, 10)); + e.armtexture = static_cast(atoi(row[97])); + e.bracertexture = static_cast(atoi(row[98])); + e.handtexture = static_cast(atoi(row[99])); + e.legtexture = static_cast(atoi(row[100])); + e.feettexture = static_cast(atoi(row[101])); + e.light = static_cast(atoi(row[102])); + e.walkspeed = static_cast(atoi(row[103])); + e.peqid = static_cast(atoi(row[104])); + e.unique_ = static_cast(atoi(row[105])); + e.fixed = static_cast(atoi(row[106])); + e.ignore_despawn = static_cast(atoi(row[107])); + e.show_name = static_cast(atoi(row[108])); + e.untargetable = static_cast(atoi(row[109])); + e.charm_ac = static_cast(atoi(row[110])); + e.charm_min_dmg = static_cast(atoi(row[111])); + e.charm_max_dmg = static_cast(atoi(row[112])); + e.charm_attack_delay = static_cast(atoi(row[113])); + e.charm_accuracy_rating = static_cast(atoi(row[114])); + e.charm_avoidance_rating = static_cast(atoi(row[115])); + e.charm_atk = static_cast(atoi(row[116])); + e.skip_global_loot = static_cast(atoi(row[117])); + e.rare_spawn = static_cast(atoi(row[118])); + e.stuck_behavior = static_cast(atoi(row[119])); + e.model = static_cast(atoi(row[120])); + e.flymode = static_cast(atoi(row[121])); + e.always_aggro = static_cast(atoi(row[122])); + e.exp_mod = static_cast(atoi(row[123])); + e.heroic_strikethrough = static_cast(atoi(row[124])); + e.faction_amount = static_cast(atoi(row[125])); + e.keeps_sold_items = static_cast(strtoul(row[126], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -1363,140 +1392,143 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcTypes entry{}; + NpcTypes e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.lastname = row[2] ? row[2] : ""; - entry.level = atoi(row[3]); - entry.race = atoi(row[4]); - entry.class_ = atoi(row[5]); - entry.bodytype = atoi(row[6]); - entry.hp = strtoll(row[7], nullptr, 10); - entry.mana = strtoll(row[8], nullptr, 10); - entry.gender = atoi(row[9]); - entry.texture = atoi(row[10]); - entry.helmtexture = atoi(row[11]); - entry.herosforgemodel = atoi(row[12]); - entry.size = static_cast(atof(row[13])); - entry.hp_regen_rate = strtoll(row[14], nullptr, 10); - entry.hp_regen_per_second = strtoll(row[15], nullptr, 10); - entry.mana_regen_rate = strtoll(row[16], nullptr, 10); - entry.loottable_id = atoi(row[17]); - entry.merchant_id = atoi(row[18]); - entry.alt_currency_id = atoi(row[19]); - entry.npc_spells_id = atoi(row[20]); - entry.npc_spells_effects_id = atoi(row[21]); - entry.npc_faction_id = atoi(row[22]); - entry.adventure_template_id = atoi(row[23]); - entry.trap_template = atoi(row[24]); - entry.mindmg = atoi(row[25]); - entry.maxdmg = atoi(row[26]); - entry.attack_count = atoi(row[27]); - entry.npcspecialattks = row[28] ? row[28] : ""; - entry.special_abilities = row[29] ? row[29] : ""; - entry.aggroradius = atoi(row[30]); - entry.assistradius = atoi(row[31]); - entry.face = atoi(row[32]); - entry.luclin_hairstyle = atoi(row[33]); - entry.luclin_haircolor = atoi(row[34]); - entry.luclin_eyecolor = atoi(row[35]); - entry.luclin_eyecolor2 = atoi(row[36]); - entry.luclin_beardcolor = atoi(row[37]); - entry.luclin_beard = atoi(row[38]); - entry.drakkin_heritage = atoi(row[39]); - entry.drakkin_tattoo = atoi(row[40]); - entry.drakkin_details = atoi(row[41]); - entry.armortint_id = atoi(row[42]); - entry.armortint_red = atoi(row[43]); - entry.armortint_green = atoi(row[44]); - entry.armortint_blue = atoi(row[45]); - entry.d_melee_texture1 = atoi(row[46]); - entry.d_melee_texture2 = atoi(row[47]); - entry.ammo_idfile = row[48] ? row[48] : ""; - entry.prim_melee_type = atoi(row[49]); - entry.sec_melee_type = atoi(row[50]); - entry.ranged_type = atoi(row[51]); - entry.runspeed = static_cast(atof(row[52])); - entry.MR = atoi(row[53]); - entry.CR = atoi(row[54]); - entry.DR = atoi(row[55]); - entry.FR = atoi(row[56]); - entry.PR = atoi(row[57]); - entry.Corrup = atoi(row[58]); - entry.PhR = atoi(row[59]); - entry.see_invis = atoi(row[60]); - entry.see_invis_undead = atoi(row[61]); - entry.qglobal = atoi(row[62]); - entry.AC = atoi(row[63]); - entry.npc_aggro = atoi(row[64]); - entry.spawn_limit = atoi(row[65]); - entry.attack_speed = static_cast(atof(row[66])); - entry.attack_delay = atoi(row[67]); - entry.findable = atoi(row[68]); - entry.STR = atoi(row[69]); - entry.STA = atoi(row[70]); - entry.DEX = atoi(row[71]); - entry.AGI = atoi(row[72]); - entry._INT = atoi(row[73]); - entry.WIS = atoi(row[74]); - entry.CHA = atoi(row[75]); - entry.see_hide = atoi(row[76]); - entry.see_improved_hide = atoi(row[77]); - entry.trackable = atoi(row[78]); - entry.isbot = atoi(row[79]); - entry.exclude = atoi(row[80]); - entry.ATK = atoi(row[81]); - entry.Accuracy = atoi(row[82]); - entry.Avoidance = atoi(row[83]); - entry.slow_mitigation = atoi(row[84]); - entry.version = atoi(row[85]); - entry.maxlevel = atoi(row[86]); - entry.scalerate = atoi(row[87]); - entry.private_corpse = atoi(row[88]); - entry.unique_spawn_by_name = atoi(row[89]); - entry.underwater = atoi(row[90]); - entry.isquest = atoi(row[91]); - entry.emoteid = atoi(row[92]); - entry.spellscale = static_cast(atof(row[93])); - entry.healscale = static_cast(atof(row[94])); - entry.no_target_hotkey = atoi(row[95]); - entry.raid_target = atoi(row[96]); - entry.armtexture = atoi(row[97]); - entry.bracertexture = atoi(row[98]); - entry.handtexture = atoi(row[99]); - entry.legtexture = atoi(row[100]); - entry.feettexture = atoi(row[101]); - entry.light = atoi(row[102]); - entry.walkspeed = atoi(row[103]); - entry.peqid = atoi(row[104]); - entry.unique_ = atoi(row[105]); - entry.fixed = atoi(row[106]); - entry.ignore_despawn = atoi(row[107]); - entry.show_name = atoi(row[108]); - entry.untargetable = atoi(row[109]); - entry.charm_ac = atoi(row[110]); - entry.charm_min_dmg = atoi(row[111]); - entry.charm_max_dmg = atoi(row[112]); - entry.charm_attack_delay = atoi(row[113]); - entry.charm_accuracy_rating = atoi(row[114]); - entry.charm_avoidance_rating = atoi(row[115]); - entry.charm_atk = atoi(row[116]); - entry.skip_global_loot = atoi(row[117]); - entry.rare_spawn = atoi(row[118]); - entry.stuck_behavior = atoi(row[119]); - entry.model = atoi(row[120]); - entry.flymode = atoi(row[121]); - entry.always_aggro = atoi(row[122]); - entry.exp_mod = atoi(row[123]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.lastname = row[2] ? row[2] : ""; + e.level = static_cast(strtoul(row[3], nullptr, 10)); + e.race = static_cast(strtoul(row[4], nullptr, 10)); + e.class_ = static_cast(strtoul(row[5], nullptr, 10)); + e.bodytype = static_cast(atoi(row[6])); + e.hp = strtoll(row[7], nullptr, 10); + e.mana = strtoll(row[8], nullptr, 10); + e.gender = static_cast(strtoul(row[9], nullptr, 10)); + e.texture = static_cast(strtoul(row[10], nullptr, 10)); + e.helmtexture = static_cast(strtoul(row[11], nullptr, 10)); + e.herosforgemodel = static_cast(atoi(row[12])); + e.size = strtof(row[13], nullptr); + e.hp_regen_rate = strtoll(row[14], nullptr, 10); + e.hp_regen_per_second = strtoll(row[15], nullptr, 10); + e.mana_regen_rate = strtoll(row[16], nullptr, 10); + e.loottable_id = static_cast(strtoul(row[17], nullptr, 10)); + e.merchant_id = static_cast(strtoul(row[18], nullptr, 10)); + e.alt_currency_id = static_cast(strtoul(row[19], nullptr, 10)); + e.npc_spells_id = static_cast(strtoul(row[20], nullptr, 10)); + e.npc_spells_effects_id = static_cast(strtoul(row[21], nullptr, 10)); + e.npc_faction_id = static_cast(atoi(row[22])); + e.adventure_template_id = static_cast(strtoul(row[23], nullptr, 10)); + e.trap_template = static_cast(strtoul(row[24], nullptr, 10)); + e.mindmg = static_cast(strtoul(row[25], nullptr, 10)); + e.maxdmg = static_cast(strtoul(row[26], nullptr, 10)); + e.attack_count = static_cast(atoi(row[27])); + e.npcspecialattks = row[28] ? row[28] : ""; + e.special_abilities = row[29] ? row[29] : ""; + e.aggroradius = static_cast(strtoul(row[30], nullptr, 10)); + e.assistradius = static_cast(strtoul(row[31], nullptr, 10)); + e.face = static_cast(strtoul(row[32], nullptr, 10)); + e.luclin_hairstyle = static_cast(strtoul(row[33], nullptr, 10)); + e.luclin_haircolor = static_cast(strtoul(row[34], nullptr, 10)); + e.luclin_eyecolor = static_cast(strtoul(row[35], nullptr, 10)); + e.luclin_eyecolor2 = static_cast(strtoul(row[36], nullptr, 10)); + e.luclin_beardcolor = static_cast(strtoul(row[37], nullptr, 10)); + e.luclin_beard = static_cast(strtoul(row[38], nullptr, 10)); + e.drakkin_heritage = static_cast(atoi(row[39])); + e.drakkin_tattoo = static_cast(atoi(row[40])); + e.drakkin_details = static_cast(atoi(row[41])); + e.armortint_id = static_cast(strtoul(row[42], nullptr, 10)); + e.armortint_red = static_cast(strtoul(row[43], nullptr, 10)); + e.armortint_green = static_cast(strtoul(row[44], nullptr, 10)); + e.armortint_blue = static_cast(strtoul(row[45], nullptr, 10)); + e.d_melee_texture1 = static_cast(atoi(row[46])); + e.d_melee_texture2 = static_cast(atoi(row[47])); + e.ammo_idfile = row[48] ? row[48] : ""; + e.prim_melee_type = static_cast(strtoul(row[49], nullptr, 10)); + e.sec_melee_type = static_cast(strtoul(row[50], nullptr, 10)); + e.ranged_type = static_cast(strtoul(row[51], nullptr, 10)); + e.runspeed = strtof(row[52], nullptr); + e.MR = static_cast(atoi(row[53])); + e.CR = static_cast(atoi(row[54])); + e.DR = static_cast(atoi(row[55])); + e.FR = static_cast(atoi(row[56])); + e.PR = static_cast(atoi(row[57])); + e.Corrup = static_cast(atoi(row[58])); + e.PhR = static_cast(strtoul(row[59], nullptr, 10)); + e.see_invis = static_cast(atoi(row[60])); + e.see_invis_undead = static_cast(atoi(row[61])); + e.qglobal = static_cast(strtoul(row[62], nullptr, 10)); + e.AC = static_cast(atoi(row[63])); + e.npc_aggro = static_cast(atoi(row[64])); + e.spawn_limit = static_cast(atoi(row[65])); + e.attack_speed = strtof(row[66], nullptr); + e.attack_delay = static_cast(strtoul(row[67], nullptr, 10)); + e.findable = static_cast(atoi(row[68])); + e.STR = static_cast(strtoul(row[69], nullptr, 10)); + e.STA = static_cast(strtoul(row[70], nullptr, 10)); + e.DEX = static_cast(strtoul(row[71], nullptr, 10)); + e.AGI = static_cast(strtoul(row[72], nullptr, 10)); + e._INT = static_cast(strtoul(row[73], nullptr, 10)); + e.WIS = static_cast(strtoul(row[74], nullptr, 10)); + e.CHA = static_cast(strtoul(row[75], nullptr, 10)); + e.see_hide = static_cast(atoi(row[76])); + e.see_improved_hide = static_cast(atoi(row[77])); + e.trackable = static_cast(atoi(row[78])); + e.isbot = static_cast(atoi(row[79])); + e.exclude = static_cast(atoi(row[80])); + e.ATK = static_cast(atoi(row[81])); + e.Accuracy = static_cast(atoi(row[82])); + e.Avoidance = static_cast(strtoul(row[83], nullptr, 10)); + e.slow_mitigation = static_cast(atoi(row[84])); + e.version = static_cast(strtoul(row[85], nullptr, 10)); + e.maxlevel = static_cast(atoi(row[86])); + e.scalerate = static_cast(atoi(row[87])); + e.private_corpse = static_cast(strtoul(row[88], nullptr, 10)); + e.unique_spawn_by_name = static_cast(strtoul(row[89], nullptr, 10)); + e.underwater = static_cast(strtoul(row[90], nullptr, 10)); + e.isquest = static_cast(atoi(row[91])); + e.emoteid = static_cast(strtoul(row[92], nullptr, 10)); + e.spellscale = strtof(row[93], nullptr); + e.healscale = strtof(row[94], nullptr); + e.no_target_hotkey = static_cast(strtoul(row[95], nullptr, 10)); + e.raid_target = static_cast(strtoul(row[96], nullptr, 10)); + e.armtexture = static_cast(atoi(row[97])); + e.bracertexture = static_cast(atoi(row[98])); + e.handtexture = static_cast(atoi(row[99])); + e.legtexture = static_cast(atoi(row[100])); + e.feettexture = static_cast(atoi(row[101])); + e.light = static_cast(atoi(row[102])); + e.walkspeed = static_cast(atoi(row[103])); + e.peqid = static_cast(atoi(row[104])); + e.unique_ = static_cast(atoi(row[105])); + e.fixed = static_cast(atoi(row[106])); + e.ignore_despawn = static_cast(atoi(row[107])); + e.show_name = static_cast(atoi(row[108])); + e.untargetable = static_cast(atoi(row[109])); + e.charm_ac = static_cast(atoi(row[110])); + e.charm_min_dmg = static_cast(atoi(row[111])); + e.charm_max_dmg = static_cast(atoi(row[112])); + e.charm_attack_delay = static_cast(atoi(row[113])); + e.charm_accuracy_rating = static_cast(atoi(row[114])); + e.charm_avoidance_rating = static_cast(atoi(row[115])); + e.charm_atk = static_cast(atoi(row[116])); + e.skip_global_loot = static_cast(atoi(row[117])); + e.rare_spawn = static_cast(atoi(row[118])); + e.stuck_behavior = static_cast(atoi(row[119])); + e.model = static_cast(atoi(row[120])); + e.flymode = static_cast(atoi(row[121])); + e.always_aggro = static_cast(atoi(row[122])); + e.exp_mod = static_cast(atoi(row[123])); + e.heroic_strikethrough = static_cast(atoi(row[124])); + e.faction_amount = static_cast(atoi(row[125])); + e.keeps_sold_items = static_cast(strtoul(row[126], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -1521,6 +1553,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_types_tint_repository.h b/common/repositories/base/base_npc_types_tint_repository.h index 906bb08d0..3a4361fa1 100644 --- a/common/repositories/base/base_npc_types_tint_repository.h +++ b/common/repositories/base/base_npc_types_tint_repository.h @@ -13,41 +13,41 @@ #define EQEMU_BASE_NPC_TYPES_TINT_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseNpcTypesTintRepository { public: struct NpcTypesTint { - int id; + uint32_t id; std::string tint_set_name; - int red1h; - int grn1h; - int blu1h; - int red2c; - int grn2c; - int blu2c; - int red3a; - int grn3a; - int blu3a; - int red4b; - int grn4b; - int blu4b; - int red5g; - int grn5g; - int blu5g; - int red6l; - int grn6l; - int blu6l; - int red7f; - int grn7f; - int blu7f; - int red8x; - int grn8x; - int blu8x; - int red9x; - int grn9x; - int blu9x; + uint8_t red1h; + uint8_t grn1h; + uint8_t blu1h; + uint8_t red2c; + uint8_t grn2c; + uint8_t blu2c; + uint8_t red3a; + uint8_t grn3a; + uint8_t blu3a; + uint8_t red4b; + uint8_t grn4b; + uint8_t blu4b; + uint8_t red5g; + uint8_t grn5g; + uint8_t blu5g; + uint8_t red6l; + uint8_t grn6l; + uint8_t blu6l; + uint8_t red7f; + uint8_t grn7f; + uint8_t blu7f; + uint8_t red8x; + uint8_t grn8x; + uint8_t blu8x; + uint8_t red9x; + uint8_t grn9x; + uint8_t blu9x; }; static std::string PrimaryKey() @@ -127,12 +127,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -160,42 +160,42 @@ public: static NpcTypesTint NewEntity() { - NpcTypesTint entry{}; + NpcTypesTint e{}; - entry.id = 0; - entry.tint_set_name = ""; - entry.red1h = 0; - entry.grn1h = 0; - entry.blu1h = 0; - entry.red2c = 0; - entry.grn2c = 0; - entry.blu2c = 0; - entry.red3a = 0; - entry.grn3a = 0; - entry.blu3a = 0; - entry.red4b = 0; - entry.grn4b = 0; - entry.blu4b = 0; - entry.red5g = 0; - entry.grn5g = 0; - entry.blu5g = 0; - entry.red6l = 0; - entry.grn6l = 0; - entry.blu6l = 0; - entry.red7f = 0; - entry.grn7f = 0; - entry.blu7f = 0; - entry.red8x = 0; - entry.grn8x = 0; - entry.blu8x = 0; - entry.red9x = 0; - entry.grn9x = 0; - entry.blu9x = 0; + e.id = 0; + e.tint_set_name = ""; + e.red1h = 0; + e.grn1h = 0; + e.blu1h = 0; + e.red2c = 0; + e.grn2c = 0; + e.blu2c = 0; + e.red3a = 0; + e.grn3a = 0; + e.blu3a = 0; + e.red4b = 0; + e.grn4b = 0; + e.blu4b = 0; + e.red5g = 0; + e.grn5g = 0; + e.blu5g = 0; + e.red6l = 0; + e.grn6l = 0; + e.blu6l = 0; + e.red7f = 0; + e.grn7f = 0; + e.blu7f = 0; + e.red8x = 0; + e.grn8x = 0; + e.blu8x = 0; + e.red9x = 0; + e.grn9x = 0; + e.blu9x = 0; - return entry; + return e; } - static NpcTypesTint GetNpcTypesTintEntry( + static NpcTypesTint GetNpcTypesTint( const std::vector &npc_types_tints, int npc_types_tint_id ) @@ -224,39 +224,39 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - NpcTypesTint entry{}; + NpcTypesTint e{}; - entry.id = atoi(row[0]); - entry.tint_set_name = row[1] ? row[1] : ""; - entry.red1h = atoi(row[2]); - entry.grn1h = atoi(row[3]); - entry.blu1h = atoi(row[4]); - entry.red2c = atoi(row[5]); - entry.grn2c = atoi(row[6]); - entry.blu2c = atoi(row[7]); - entry.red3a = atoi(row[8]); - entry.grn3a = atoi(row[9]); - entry.blu3a = atoi(row[10]); - entry.red4b = atoi(row[11]); - entry.grn4b = atoi(row[12]); - entry.blu4b = atoi(row[13]); - entry.red5g = atoi(row[14]); - entry.grn5g = atoi(row[15]); - entry.blu5g = atoi(row[16]); - entry.red6l = atoi(row[17]); - entry.grn6l = atoi(row[18]); - entry.blu6l = atoi(row[19]); - entry.red7f = atoi(row[20]); - entry.grn7f = atoi(row[21]); - entry.blu7f = atoi(row[22]); - entry.red8x = atoi(row[23]); - entry.grn8x = atoi(row[24]); - entry.blu8x = atoi(row[25]); - entry.red9x = atoi(row[26]); - entry.grn9x = atoi(row[27]); - entry.blu9x = atoi(row[28]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.tint_set_name = row[1] ? row[1] : ""; + e.red1h = static_cast(strtoul(row[2], nullptr, 10)); + e.grn1h = static_cast(strtoul(row[3], nullptr, 10)); + e.blu1h = static_cast(strtoul(row[4], nullptr, 10)); + e.red2c = static_cast(strtoul(row[5], nullptr, 10)); + e.grn2c = static_cast(strtoul(row[6], nullptr, 10)); + e.blu2c = static_cast(strtoul(row[7], nullptr, 10)); + e.red3a = static_cast(strtoul(row[8], nullptr, 10)); + e.grn3a = static_cast(strtoul(row[9], nullptr, 10)); + e.blu3a = static_cast(strtoul(row[10], nullptr, 10)); + e.red4b = static_cast(strtoul(row[11], nullptr, 10)); + e.grn4b = static_cast(strtoul(row[12], nullptr, 10)); + e.blu4b = static_cast(strtoul(row[13], nullptr, 10)); + e.red5g = static_cast(strtoul(row[14], nullptr, 10)); + e.grn5g = static_cast(strtoul(row[15], nullptr, 10)); + e.blu5g = static_cast(strtoul(row[16], nullptr, 10)); + e.red6l = static_cast(strtoul(row[17], nullptr, 10)); + e.grn6l = static_cast(strtoul(row[18], nullptr, 10)); + e.blu6l = static_cast(strtoul(row[19], nullptr, 10)); + e.red7f = static_cast(strtoul(row[20], nullptr, 10)); + e.grn7f = static_cast(strtoul(row[21], nullptr, 10)); + e.blu7f = static_cast(strtoul(row[22], nullptr, 10)); + e.red8x = static_cast(strtoul(row[23], nullptr, 10)); + e.grn8x = static_cast(strtoul(row[24], nullptr, 10)); + e.blu8x = static_cast(strtoul(row[25], nullptr, 10)); + e.red9x = static_cast(strtoul(row[26], nullptr, 10)); + e.grn9x = static_cast(strtoul(row[27], nullptr, 10)); + e.blu9x = static_cast(strtoul(row[28], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -281,50 +281,50 @@ public: static int UpdateOne( Database& db, - NpcTypesTint npc_types_tint_entry + const NpcTypesTint &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(npc_types_tint_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(npc_types_tint_entry.tint_set_name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(npc_types_tint_entry.red1h)); - update_values.push_back(columns[3] + " = " + std::to_string(npc_types_tint_entry.grn1h)); - update_values.push_back(columns[4] + " = " + std::to_string(npc_types_tint_entry.blu1h)); - update_values.push_back(columns[5] + " = " + std::to_string(npc_types_tint_entry.red2c)); - update_values.push_back(columns[6] + " = " + std::to_string(npc_types_tint_entry.grn2c)); - update_values.push_back(columns[7] + " = " + std::to_string(npc_types_tint_entry.blu2c)); - update_values.push_back(columns[8] + " = " + std::to_string(npc_types_tint_entry.red3a)); - update_values.push_back(columns[9] + " = " + std::to_string(npc_types_tint_entry.grn3a)); - update_values.push_back(columns[10] + " = " + std::to_string(npc_types_tint_entry.blu3a)); - update_values.push_back(columns[11] + " = " + std::to_string(npc_types_tint_entry.red4b)); - update_values.push_back(columns[12] + " = " + std::to_string(npc_types_tint_entry.grn4b)); - update_values.push_back(columns[13] + " = " + std::to_string(npc_types_tint_entry.blu4b)); - update_values.push_back(columns[14] + " = " + std::to_string(npc_types_tint_entry.red5g)); - update_values.push_back(columns[15] + " = " + std::to_string(npc_types_tint_entry.grn5g)); - update_values.push_back(columns[16] + " = " + std::to_string(npc_types_tint_entry.blu5g)); - update_values.push_back(columns[17] + " = " + std::to_string(npc_types_tint_entry.red6l)); - update_values.push_back(columns[18] + " = " + std::to_string(npc_types_tint_entry.grn6l)); - update_values.push_back(columns[19] + " = " + std::to_string(npc_types_tint_entry.blu6l)); - update_values.push_back(columns[20] + " = " + std::to_string(npc_types_tint_entry.red7f)); - update_values.push_back(columns[21] + " = " + std::to_string(npc_types_tint_entry.grn7f)); - update_values.push_back(columns[22] + " = " + std::to_string(npc_types_tint_entry.blu7f)); - update_values.push_back(columns[23] + " = " + std::to_string(npc_types_tint_entry.red8x)); - update_values.push_back(columns[24] + " = " + std::to_string(npc_types_tint_entry.grn8x)); - update_values.push_back(columns[25] + " = " + std::to_string(npc_types_tint_entry.blu8x)); - update_values.push_back(columns[26] + " = " + std::to_string(npc_types_tint_entry.red9x)); - update_values.push_back(columns[27] + " = " + std::to_string(npc_types_tint_entry.grn9x)); - update_values.push_back(columns[28] + " = " + std::to_string(npc_types_tint_entry.blu9x)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.tint_set_name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.red1h)); + v.push_back(columns[3] + " = " + std::to_string(e.grn1h)); + v.push_back(columns[4] + " = " + std::to_string(e.blu1h)); + v.push_back(columns[5] + " = " + std::to_string(e.red2c)); + v.push_back(columns[6] + " = " + std::to_string(e.grn2c)); + v.push_back(columns[7] + " = " + std::to_string(e.blu2c)); + v.push_back(columns[8] + " = " + std::to_string(e.red3a)); + v.push_back(columns[9] + " = " + std::to_string(e.grn3a)); + v.push_back(columns[10] + " = " + std::to_string(e.blu3a)); + v.push_back(columns[11] + " = " + std::to_string(e.red4b)); + v.push_back(columns[12] + " = " + std::to_string(e.grn4b)); + v.push_back(columns[13] + " = " + std::to_string(e.blu4b)); + v.push_back(columns[14] + " = " + std::to_string(e.red5g)); + v.push_back(columns[15] + " = " + std::to_string(e.grn5g)); + v.push_back(columns[16] + " = " + std::to_string(e.blu5g)); + v.push_back(columns[17] + " = " + std::to_string(e.red6l)); + v.push_back(columns[18] + " = " + std::to_string(e.grn6l)); + v.push_back(columns[19] + " = " + std::to_string(e.blu6l)); + v.push_back(columns[20] + " = " + std::to_string(e.red7f)); + v.push_back(columns[21] + " = " + std::to_string(e.grn7f)); + v.push_back(columns[22] + " = " + std::to_string(e.blu7f)); + v.push_back(columns[23] + " = " + std::to_string(e.red8x)); + v.push_back(columns[24] + " = " + std::to_string(e.grn8x)); + v.push_back(columns[25] + " = " + std::to_string(e.blu8x)); + v.push_back(columns[26] + " = " + std::to_string(e.red9x)); + v.push_back(columns[27] + " = " + std::to_string(e.grn9x)); + v.push_back(columns[28] + " = " + std::to_string(e.blu9x)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - npc_types_tint_entry.id + e.id ) ); @@ -333,109 +333,109 @@ public: static NpcTypesTint InsertOne( Database& db, - NpcTypesTint npc_types_tint_entry + NpcTypesTint e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(npc_types_tint_entry.id)); - insert_values.push_back("'" + EscapeString(npc_types_tint_entry.tint_set_name) + "'"); - insert_values.push_back(std::to_string(npc_types_tint_entry.red1h)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn1h)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu1h)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red2c)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn2c)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu2c)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red3a)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn3a)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu3a)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red4b)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn4b)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu4b)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red5g)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn5g)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu5g)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red6l)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn6l)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu6l)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red7f)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn7f)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu7f)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red8x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn8x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu8x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red9x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn9x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu9x)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.tint_set_name) + "'"); + v.push_back(std::to_string(e.red1h)); + v.push_back(std::to_string(e.grn1h)); + v.push_back(std::to_string(e.blu1h)); + v.push_back(std::to_string(e.red2c)); + v.push_back(std::to_string(e.grn2c)); + v.push_back(std::to_string(e.blu2c)); + v.push_back(std::to_string(e.red3a)); + v.push_back(std::to_string(e.grn3a)); + v.push_back(std::to_string(e.blu3a)); + v.push_back(std::to_string(e.red4b)); + v.push_back(std::to_string(e.grn4b)); + v.push_back(std::to_string(e.blu4b)); + v.push_back(std::to_string(e.red5g)); + v.push_back(std::to_string(e.grn5g)); + v.push_back(std::to_string(e.blu5g)); + v.push_back(std::to_string(e.red6l)); + v.push_back(std::to_string(e.grn6l)); + v.push_back(std::to_string(e.blu6l)); + v.push_back(std::to_string(e.red7f)); + v.push_back(std::to_string(e.grn7f)); + v.push_back(std::to_string(e.blu7f)); + v.push_back(std::to_string(e.red8x)); + v.push_back(std::to_string(e.grn8x)); + v.push_back(std::to_string(e.blu8x)); + v.push_back(std::to_string(e.red9x)); + v.push_back(std::to_string(e.grn9x)); + v.push_back(std::to_string(e.blu9x)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - npc_types_tint_entry.id = results.LastInsertedID(); - return npc_types_tint_entry; + e.id = results.LastInsertedID(); + return e; } - npc_types_tint_entry = NewEntity(); + e = NewEntity(); - return npc_types_tint_entry; + return e; } static int InsertMany( Database& db, - std::vector npc_types_tint_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &npc_types_tint_entry: npc_types_tint_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(npc_types_tint_entry.id)); - insert_values.push_back("'" + EscapeString(npc_types_tint_entry.tint_set_name) + "'"); - insert_values.push_back(std::to_string(npc_types_tint_entry.red1h)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn1h)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu1h)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red2c)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn2c)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu2c)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red3a)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn3a)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu3a)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red4b)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn4b)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu4b)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red5g)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn5g)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu5g)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red6l)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn6l)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu6l)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red7f)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn7f)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu7f)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red8x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn8x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu8x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.red9x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.grn9x)); - insert_values.push_back(std::to_string(npc_types_tint_entry.blu9x)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.tint_set_name) + "'"); + v.push_back(std::to_string(e.red1h)); + v.push_back(std::to_string(e.grn1h)); + v.push_back(std::to_string(e.blu1h)); + v.push_back(std::to_string(e.red2c)); + v.push_back(std::to_string(e.grn2c)); + v.push_back(std::to_string(e.blu2c)); + v.push_back(std::to_string(e.red3a)); + v.push_back(std::to_string(e.grn3a)); + v.push_back(std::to_string(e.blu3a)); + v.push_back(std::to_string(e.red4b)); + v.push_back(std::to_string(e.grn4b)); + v.push_back(std::to_string(e.blu4b)); + v.push_back(std::to_string(e.red5g)); + v.push_back(std::to_string(e.grn5g)); + v.push_back(std::to_string(e.blu5g)); + v.push_back(std::to_string(e.red6l)); + v.push_back(std::to_string(e.grn6l)); + v.push_back(std::to_string(e.blu6l)); + v.push_back(std::to_string(e.red7f)); + v.push_back(std::to_string(e.grn7f)); + v.push_back(std::to_string(e.blu7f)); + v.push_back(std::to_string(e.red8x)); + v.push_back(std::to_string(e.grn8x)); + v.push_back(std::to_string(e.blu8x)); + v.push_back(std::to_string(e.red9x)); + v.push_back(std::to_string(e.grn9x)); + v.push_back(std::to_string(e.blu9x)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -456,45 +456,45 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcTypesTint entry{}; + NpcTypesTint e{}; - entry.id = atoi(row[0]); - entry.tint_set_name = row[1] ? row[1] : ""; - entry.red1h = atoi(row[2]); - entry.grn1h = atoi(row[3]); - entry.blu1h = atoi(row[4]); - entry.red2c = atoi(row[5]); - entry.grn2c = atoi(row[6]); - entry.blu2c = atoi(row[7]); - entry.red3a = atoi(row[8]); - entry.grn3a = atoi(row[9]); - entry.blu3a = atoi(row[10]); - entry.red4b = atoi(row[11]); - entry.grn4b = atoi(row[12]); - entry.blu4b = atoi(row[13]); - entry.red5g = atoi(row[14]); - entry.grn5g = atoi(row[15]); - entry.blu5g = atoi(row[16]); - entry.red6l = atoi(row[17]); - entry.grn6l = atoi(row[18]); - entry.blu6l = atoi(row[19]); - entry.red7f = atoi(row[20]); - entry.grn7f = atoi(row[21]); - entry.blu7f = atoi(row[22]); - entry.red8x = atoi(row[23]); - entry.grn8x = atoi(row[24]); - entry.blu8x = atoi(row[25]); - entry.red9x = atoi(row[26]); - entry.grn9x = atoi(row[27]); - entry.blu9x = atoi(row[28]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.tint_set_name = row[1] ? row[1] : ""; + e.red1h = static_cast(strtoul(row[2], nullptr, 10)); + e.grn1h = static_cast(strtoul(row[3], nullptr, 10)); + e.blu1h = static_cast(strtoul(row[4], nullptr, 10)); + e.red2c = static_cast(strtoul(row[5], nullptr, 10)); + e.grn2c = static_cast(strtoul(row[6], nullptr, 10)); + e.blu2c = static_cast(strtoul(row[7], nullptr, 10)); + e.red3a = static_cast(strtoul(row[8], nullptr, 10)); + e.grn3a = static_cast(strtoul(row[9], nullptr, 10)); + e.blu3a = static_cast(strtoul(row[10], nullptr, 10)); + e.red4b = static_cast(strtoul(row[11], nullptr, 10)); + e.grn4b = static_cast(strtoul(row[12], nullptr, 10)); + e.blu4b = static_cast(strtoul(row[13], nullptr, 10)); + e.red5g = static_cast(strtoul(row[14], nullptr, 10)); + e.grn5g = static_cast(strtoul(row[15], nullptr, 10)); + e.blu5g = static_cast(strtoul(row[16], nullptr, 10)); + e.red6l = static_cast(strtoul(row[17], nullptr, 10)); + e.grn6l = static_cast(strtoul(row[18], nullptr, 10)); + e.blu6l = static_cast(strtoul(row[19], nullptr, 10)); + e.red7f = static_cast(strtoul(row[20], nullptr, 10)); + e.grn7f = static_cast(strtoul(row[21], nullptr, 10)); + e.blu7f = static_cast(strtoul(row[22], nullptr, 10)); + e.red8x = static_cast(strtoul(row[23], nullptr, 10)); + e.grn8x = static_cast(strtoul(row[24], nullptr, 10)); + e.blu8x = static_cast(strtoul(row[25], nullptr, 10)); + e.red9x = static_cast(strtoul(row[26], nullptr, 10)); + e.grn9x = static_cast(strtoul(row[27], nullptr, 10)); + e.blu9x = static_cast(strtoul(row[28], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -509,45 +509,45 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - NpcTypesTint entry{}; + NpcTypesTint e{}; - entry.id = atoi(row[0]); - entry.tint_set_name = row[1] ? row[1] : ""; - entry.red1h = atoi(row[2]); - entry.grn1h = atoi(row[3]); - entry.blu1h = atoi(row[4]); - entry.red2c = atoi(row[5]); - entry.grn2c = atoi(row[6]); - entry.blu2c = atoi(row[7]); - entry.red3a = atoi(row[8]); - entry.grn3a = atoi(row[9]); - entry.blu3a = atoi(row[10]); - entry.red4b = atoi(row[11]); - entry.grn4b = atoi(row[12]); - entry.blu4b = atoi(row[13]); - entry.red5g = atoi(row[14]); - entry.grn5g = atoi(row[15]); - entry.blu5g = atoi(row[16]); - entry.red6l = atoi(row[17]); - entry.grn6l = atoi(row[18]); - entry.blu6l = atoi(row[19]); - entry.red7f = atoi(row[20]); - entry.grn7f = atoi(row[21]); - entry.blu7f = atoi(row[22]); - entry.red8x = atoi(row[23]); - entry.grn8x = atoi(row[24]); - entry.blu8x = atoi(row[25]); - entry.red9x = atoi(row[26]); - entry.grn9x = atoi(row[27]); - entry.blu9x = atoi(row[28]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.tint_set_name = row[1] ? row[1] : ""; + e.red1h = static_cast(strtoul(row[2], nullptr, 10)); + e.grn1h = static_cast(strtoul(row[3], nullptr, 10)); + e.blu1h = static_cast(strtoul(row[4], nullptr, 10)); + e.red2c = static_cast(strtoul(row[5], nullptr, 10)); + e.grn2c = static_cast(strtoul(row[6], nullptr, 10)); + e.blu2c = static_cast(strtoul(row[7], nullptr, 10)); + e.red3a = static_cast(strtoul(row[8], nullptr, 10)); + e.grn3a = static_cast(strtoul(row[9], nullptr, 10)); + e.blu3a = static_cast(strtoul(row[10], nullptr, 10)); + e.red4b = static_cast(strtoul(row[11], nullptr, 10)); + e.grn4b = static_cast(strtoul(row[12], nullptr, 10)); + e.blu4b = static_cast(strtoul(row[13], nullptr, 10)); + e.red5g = static_cast(strtoul(row[14], nullptr, 10)); + e.grn5g = static_cast(strtoul(row[15], nullptr, 10)); + e.blu5g = static_cast(strtoul(row[16], nullptr, 10)); + e.red6l = static_cast(strtoul(row[17], nullptr, 10)); + e.grn6l = static_cast(strtoul(row[18], nullptr, 10)); + e.blu6l = static_cast(strtoul(row[19], nullptr, 10)); + e.red7f = static_cast(strtoul(row[20], nullptr, 10)); + e.grn7f = static_cast(strtoul(row[21], nullptr, 10)); + e.blu7f = static_cast(strtoul(row[22], nullptr, 10)); + e.red8x = static_cast(strtoul(row[23], nullptr, 10)); + e.grn8x = static_cast(strtoul(row[24], nullptr, 10)); + e.blu8x = static_cast(strtoul(row[25], nullptr, 10)); + e.red9x = static_cast(strtoul(row[26], nullptr, 10)); + e.grn9x = static_cast(strtoul(row[27], nullptr, 10)); + e.blu9x = static_cast(strtoul(row[28], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -572,6 +572,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_NPC_TYPES_TINT_REPOSITORY_H diff --git a/common/repositories/base/base_object_contents_repository.h b/common/repositories/base/base_object_contents_repository.h index d45ff7cd7..f0cf358bb 100644 --- a/common/repositories/base/base_object_contents_repository.h +++ b/common/repositories/base/base_object_contents_repository.h @@ -13,24 +13,24 @@ #define EQEMU_BASE_OBJECT_CONTENTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseObjectContentsRepository { public: struct ObjectContents { - int zoneid; - int parentid; - int bagidx; - int itemid; - int charges; - time_t droptime; - int augslot1; - int augslot2; - int augslot3; - int augslot4; - int augslot5; - int augslot6; + uint32_t zoneid; + uint32_t parentid; + uint32_t bagidx; + uint32_t itemid; + int16_t charges; + time_t droptime; + uint32_t augslot1; + uint32_t augslot2; + uint32_t augslot3; + uint32_t augslot4; + uint32_t augslot5; + int32_t augslot6; }; static std::string PrimaryKey() @@ -76,12 +76,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -109,25 +109,25 @@ public: static ObjectContents NewEntity() { - ObjectContents entry{}; + ObjectContents e{}; - entry.zoneid = 0; - entry.parentid = 0; - entry.bagidx = 0; - entry.itemid = 0; - entry.charges = 0; - entry.droptime = 0; - entry.augslot1 = 0; - entry.augslot2 = 0; - entry.augslot3 = 0; - entry.augslot4 = 0; - entry.augslot5 = 0; - entry.augslot6 = 0; + e.zoneid = 0; + e.parentid = 0; + e.bagidx = 0; + e.itemid = 0; + e.charges = 0; + e.droptime = 0; + e.augslot1 = 0; + e.augslot2 = 0; + e.augslot3 = 0; + e.augslot4 = 0; + e.augslot5 = 0; + e.augslot6 = 0; - return entry; + return e; } - static ObjectContents GetObjectContentsEntry( + static ObjectContents GetObjectContents( const std::vector &object_contentss, int object_contents_id ) @@ -156,22 +156,22 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - ObjectContents entry{}; + ObjectContents e{}; - entry.zoneid = atoi(row[0]); - entry.parentid = atoi(row[1]); - entry.bagidx = atoi(row[2]); - entry.itemid = atoi(row[3]); - entry.charges = atoi(row[4]); - entry.droptime = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - entry.augslot1 = atoi(row[6]); - entry.augslot2 = atoi(row[7]); - entry.augslot3 = atoi(row[8]); - entry.augslot4 = atoi(row[9]); - entry.augslot5 = atoi(row[10]); - entry.augslot6 = atoi(row[11]); + e.zoneid = static_cast(strtoul(row[0], nullptr, 10)); + e.parentid = static_cast(strtoul(row[1], nullptr, 10)); + e.bagidx = static_cast(strtoul(row[2], nullptr, 10)); + e.itemid = static_cast(strtoul(row[3], nullptr, 10)); + e.charges = static_cast(atoi(row[4])); + e.droptime = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.augslot1 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[10], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[11])); - return entry; + return e; } return NewEntity(); @@ -196,33 +196,33 @@ public: static int UpdateOne( Database& db, - ObjectContents object_contents_entry + const ObjectContents &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(object_contents_entry.zoneid)); - update_values.push_back(columns[1] + " = " + std::to_string(object_contents_entry.parentid)); - update_values.push_back(columns[2] + " = " + std::to_string(object_contents_entry.bagidx)); - update_values.push_back(columns[3] + " = " + std::to_string(object_contents_entry.itemid)); - update_values.push_back(columns[4] + " = " + std::to_string(object_contents_entry.charges)); - update_values.push_back(columns[5] + " = FROM_UNIXTIME(" + (object_contents_entry.droptime > 0 ? std::to_string(object_contents_entry.droptime) : "null") + ")"); - update_values.push_back(columns[6] + " = " + std::to_string(object_contents_entry.augslot1)); - update_values.push_back(columns[7] + " = " + std::to_string(object_contents_entry.augslot2)); - update_values.push_back(columns[8] + " = " + std::to_string(object_contents_entry.augslot3)); - update_values.push_back(columns[9] + " = " + std::to_string(object_contents_entry.augslot4)); - update_values.push_back(columns[10] + " = " + std::to_string(object_contents_entry.augslot5)); - update_values.push_back(columns[11] + " = " + std::to_string(object_contents_entry.augslot6)); + v.push_back(columns[0] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[1] + " = " + std::to_string(e.parentid)); + v.push_back(columns[2] + " = " + std::to_string(e.bagidx)); + v.push_back(columns[3] + " = " + std::to_string(e.itemid)); + v.push_back(columns[4] + " = " + std::to_string(e.charges)); + v.push_back(columns[5] + " = FROM_UNIXTIME(" + (e.droptime > 0 ? std::to_string(e.droptime) : "null") + ")"); + v.push_back(columns[6] + " = " + std::to_string(e.augslot1)); + v.push_back(columns[7] + " = " + std::to_string(e.augslot2)); + v.push_back(columns[8] + " = " + std::to_string(e.augslot3)); + v.push_back(columns[9] + " = " + std::to_string(e.augslot4)); + v.push_back(columns[10] + " = " + std::to_string(e.augslot5)); + v.push_back(columns[11] + " = " + std::to_string(e.augslot6)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - object_contents_entry.parentid + e.parentid ) ); @@ -231,75 +231,75 @@ public: static ObjectContents InsertOne( Database& db, - ObjectContents object_contents_entry + ObjectContents e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(object_contents_entry.zoneid)); - insert_values.push_back(std::to_string(object_contents_entry.parentid)); - insert_values.push_back(std::to_string(object_contents_entry.bagidx)); - insert_values.push_back(std::to_string(object_contents_entry.itemid)); - insert_values.push_back(std::to_string(object_contents_entry.charges)); - insert_values.push_back("FROM_UNIXTIME(" + (object_contents_entry.droptime > 0 ? std::to_string(object_contents_entry.droptime) : "null") + ")"); - insert_values.push_back(std::to_string(object_contents_entry.augslot1)); - insert_values.push_back(std::to_string(object_contents_entry.augslot2)); - insert_values.push_back(std::to_string(object_contents_entry.augslot3)); - insert_values.push_back(std::to_string(object_contents_entry.augslot4)); - insert_values.push_back(std::to_string(object_contents_entry.augslot5)); - insert_values.push_back(std::to_string(object_contents_entry.augslot6)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.parentid)); + v.push_back(std::to_string(e.bagidx)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back("FROM_UNIXTIME(" + (e.droptime > 0 ? std::to_string(e.droptime) : "null") + ")"); + v.push_back(std::to_string(e.augslot1)); + v.push_back(std::to_string(e.augslot2)); + v.push_back(std::to_string(e.augslot3)); + v.push_back(std::to_string(e.augslot4)); + v.push_back(std::to_string(e.augslot5)); + v.push_back(std::to_string(e.augslot6)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - object_contents_entry.parentid = results.LastInsertedID(); - return object_contents_entry; + e.parentid = results.LastInsertedID(); + return e; } - object_contents_entry = NewEntity(); + e = NewEntity(); - return object_contents_entry; + return e; } static int InsertMany( Database& db, - std::vector object_contents_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &object_contents_entry: object_contents_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(object_contents_entry.zoneid)); - insert_values.push_back(std::to_string(object_contents_entry.parentid)); - insert_values.push_back(std::to_string(object_contents_entry.bagidx)); - insert_values.push_back(std::to_string(object_contents_entry.itemid)); - insert_values.push_back(std::to_string(object_contents_entry.charges)); - insert_values.push_back("FROM_UNIXTIME(" + (object_contents_entry.droptime > 0 ? std::to_string(object_contents_entry.droptime) : "null") + ")"); - insert_values.push_back(std::to_string(object_contents_entry.augslot1)); - insert_values.push_back(std::to_string(object_contents_entry.augslot2)); - insert_values.push_back(std::to_string(object_contents_entry.augslot3)); - insert_values.push_back(std::to_string(object_contents_entry.augslot4)); - insert_values.push_back(std::to_string(object_contents_entry.augslot5)); - insert_values.push_back(std::to_string(object_contents_entry.augslot6)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.parentid)); + v.push_back(std::to_string(e.bagidx)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back("FROM_UNIXTIME(" + (e.droptime > 0 ? std::to_string(e.droptime) : "null") + ")"); + v.push_back(std::to_string(e.augslot1)); + v.push_back(std::to_string(e.augslot2)); + v.push_back(std::to_string(e.augslot3)); + v.push_back(std::to_string(e.augslot4)); + v.push_back(std::to_string(e.augslot5)); + v.push_back(std::to_string(e.augslot6)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -320,28 +320,28 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ObjectContents entry{}; + ObjectContents e{}; - entry.zoneid = atoi(row[0]); - entry.parentid = atoi(row[1]); - entry.bagidx = atoi(row[2]); - entry.itemid = atoi(row[3]); - entry.charges = atoi(row[4]); - entry.droptime = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - entry.augslot1 = atoi(row[6]); - entry.augslot2 = atoi(row[7]); - entry.augslot3 = atoi(row[8]); - entry.augslot4 = atoi(row[9]); - entry.augslot5 = atoi(row[10]); - entry.augslot6 = atoi(row[11]); + e.zoneid = static_cast(strtoul(row[0], nullptr, 10)); + e.parentid = static_cast(strtoul(row[1], nullptr, 10)); + e.bagidx = static_cast(strtoul(row[2], nullptr, 10)); + e.itemid = static_cast(strtoul(row[3], nullptr, 10)); + e.charges = static_cast(atoi(row[4])); + e.droptime = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.augslot1 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[10], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[11])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -356,28 +356,28 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ObjectContents entry{}; + ObjectContents e{}; - entry.zoneid = atoi(row[0]); - entry.parentid = atoi(row[1]); - entry.bagidx = atoi(row[2]); - entry.itemid = atoi(row[3]); - entry.charges = atoi(row[4]); - entry.droptime = strtoll(row[5] ? row[5] : "-1", nullptr, 10); - entry.augslot1 = atoi(row[6]); - entry.augslot2 = atoi(row[7]); - entry.augslot3 = atoi(row[8]); - entry.augslot4 = atoi(row[9]); - entry.augslot5 = atoi(row[10]); - entry.augslot6 = atoi(row[11]); + e.zoneid = static_cast(strtoul(row[0], nullptr, 10)); + e.parentid = static_cast(strtoul(row[1], nullptr, 10)); + e.bagidx = static_cast(strtoul(row[2], nullptr, 10)); + e.itemid = static_cast(strtoul(row[3], nullptr, 10)); + e.charges = static_cast(atoi(row[4])); + e.droptime = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + e.augslot1 = static_cast(strtoul(row[6], nullptr, 10)); + e.augslot2 = static_cast(strtoul(row[7], nullptr, 10)); + e.augslot3 = static_cast(strtoul(row[8], nullptr, 10)); + e.augslot4 = static_cast(strtoul(row[9], nullptr, 10)); + e.augslot5 = static_cast(strtoul(row[10], nullptr, 10)); + e.augslot6 = static_cast(atoi(row[11])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -402,6 +402,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_OBJECT_CONTENTS_REPOSITORY_H diff --git a/common/repositories/base/base_object_repository.h b/common/repositories/base/base_object_repository.h index 9ab4cf577..34e42debf 100644 --- a/common/repositories/base/base_object_repository.h +++ b/common/repositories/base/base_object_repository.h @@ -13,40 +13,40 @@ #define EQEMU_BASE_OBJECT_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseObjectRepository { public: struct Object { - int id; - int zoneid; - int version; + int32_t id; + uint32_t zoneid; + int16_t version; float xpos; float ypos; float zpos; float heading; - int itemid; - int charges; + int32_t itemid; + uint16_t charges; std::string objectname; - int type; - int icon; - int unknown08; - int unknown10; - int unknown20; - int unknown24; - int unknown60; - int unknown64; - int unknown68; - int unknown72; - int unknown76; - int unknown84; + int32_t type; + int32_t icon; + int32_t unknown08; + int32_t unknown10; + int32_t unknown20; + int32_t unknown24; + int32_t unknown60; + int32_t unknown64; + int32_t unknown68; + int32_t unknown72; + int32_t unknown76; + int32_t unknown84; float size; float tilt_x; float tilt_y; std::string display_name; - int min_expansion; - int max_expansion; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -130,12 +130,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -163,43 +163,43 @@ public: static Object NewEntity() { - Object entry{}; + Object e{}; - entry.id = 0; - entry.zoneid = 0; - entry.version = 0; - entry.xpos = 0; - entry.ypos = 0; - entry.zpos = 0; - entry.heading = 0; - entry.itemid = 0; - entry.charges = 0; - entry.objectname = ""; - entry.type = 0; - entry.icon = 0; - entry.unknown08 = 0; - entry.unknown10 = 0; - entry.unknown20 = 0; - entry.unknown24 = 0; - entry.unknown60 = 0; - entry.unknown64 = 0; - entry.unknown68 = 0; - entry.unknown72 = 0; - entry.unknown76 = 0; - entry.unknown84 = 0; - entry.size = 100; - entry.tilt_x = 0; - entry.tilt_y = 0; - entry.display_name = ""; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.zoneid = 0; + e.version = 0; + e.xpos = 0; + e.ypos = 0; + e.zpos = 0; + e.heading = 0; + e.itemid = 0; + e.charges = 0; + e.objectname = ""; + e.type = 0; + e.icon = 0; + e.unknown08 = 0; + e.unknown10 = 0; + e.unknown20 = 0; + e.unknown24 = 0; + e.unknown60 = 0; + e.unknown64 = 0; + e.unknown68 = 0; + e.unknown72 = 0; + e.unknown76 = 0; + e.unknown84 = 0; + e.size = 100; + e.tilt_x = 0; + e.tilt_y = 0; + e.display_name = ""; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Object GetObjectEntry( + static Object GetObject( const std::vector &objects, int object_id ) @@ -228,40 +228,40 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Object entry{}; + Object e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.version = atoi(row[2]); - entry.xpos = static_cast(atof(row[3])); - entry.ypos = static_cast(atof(row[4])); - entry.zpos = static_cast(atof(row[5])); - entry.heading = static_cast(atof(row[6])); - entry.itemid = atoi(row[7]); - entry.charges = atoi(row[8]); - entry.objectname = row[9] ? row[9] : ""; - entry.type = atoi(row[10]); - entry.icon = atoi(row[11]); - entry.unknown08 = atoi(row[12]); - entry.unknown10 = atoi(row[13]); - entry.unknown20 = atoi(row[14]); - entry.unknown24 = atoi(row[15]); - entry.unknown60 = atoi(row[16]); - entry.unknown64 = atoi(row[17]); - entry.unknown68 = atoi(row[18]); - entry.unknown72 = atoi(row[19]); - entry.unknown76 = atoi(row[20]); - entry.unknown84 = atoi(row[21]); - entry.size = static_cast(atof(row[22])); - entry.tilt_x = static_cast(atof(row[23])); - entry.tilt_y = static_cast(atof(row[24])); - entry.display_name = row[25] ? row[25] : ""; - entry.min_expansion = atoi(row[26]); - entry.max_expansion = atoi(row[27]); - entry.content_flags = row[28] ? row[28] : ""; - entry.content_flags_disabled = row[29] ? row[29] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(atoi(row[2])); + e.xpos = strtof(row[3], nullptr); + e.ypos = strtof(row[4], nullptr); + e.zpos = strtof(row[5], nullptr); + e.heading = strtof(row[6], nullptr); + e.itemid = static_cast(atoi(row[7])); + e.charges = static_cast(strtoul(row[8], nullptr, 10)); + e.objectname = row[9] ? row[9] : ""; + e.type = static_cast(atoi(row[10])); + e.icon = static_cast(atoi(row[11])); + e.unknown08 = static_cast(atoi(row[12])); + e.unknown10 = static_cast(atoi(row[13])); + e.unknown20 = static_cast(atoi(row[14])); + e.unknown24 = static_cast(atoi(row[15])); + e.unknown60 = static_cast(atoi(row[16])); + e.unknown64 = static_cast(atoi(row[17])); + e.unknown68 = static_cast(atoi(row[18])); + e.unknown72 = static_cast(atoi(row[19])); + e.unknown76 = static_cast(atoi(row[20])); + e.unknown84 = static_cast(atoi(row[21])); + e.size = strtof(row[22], nullptr); + e.tilt_x = strtof(row[23], nullptr); + e.tilt_y = strtof(row[24], nullptr); + e.display_name = row[25] ? row[25] : ""; + e.min_expansion = static_cast(atoi(row[26])); + e.max_expansion = static_cast(atoi(row[27])); + e.content_flags = row[28] ? row[28] : ""; + e.content_flags_disabled = row[29] ? row[29] : ""; - return entry; + return e; } return NewEntity(); @@ -286,50 +286,50 @@ public: static int UpdateOne( Database& db, - Object object_entry + const Object &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(object_entry.zoneid)); - update_values.push_back(columns[2] + " = " + std::to_string(object_entry.version)); - update_values.push_back(columns[3] + " = " + std::to_string(object_entry.xpos)); - update_values.push_back(columns[4] + " = " + std::to_string(object_entry.ypos)); - update_values.push_back(columns[5] + " = " + std::to_string(object_entry.zpos)); - update_values.push_back(columns[6] + " = " + std::to_string(object_entry.heading)); - update_values.push_back(columns[7] + " = " + std::to_string(object_entry.itemid)); - update_values.push_back(columns[8] + " = " + std::to_string(object_entry.charges)); - update_values.push_back(columns[9] + " = '" + EscapeString(object_entry.objectname) + "'"); - update_values.push_back(columns[10] + " = " + std::to_string(object_entry.type)); - update_values.push_back(columns[11] + " = " + std::to_string(object_entry.icon)); - update_values.push_back(columns[12] + " = " + std::to_string(object_entry.unknown08)); - update_values.push_back(columns[13] + " = " + std::to_string(object_entry.unknown10)); - update_values.push_back(columns[14] + " = " + std::to_string(object_entry.unknown20)); - update_values.push_back(columns[15] + " = " + std::to_string(object_entry.unknown24)); - update_values.push_back(columns[16] + " = " + std::to_string(object_entry.unknown60)); - update_values.push_back(columns[17] + " = " + std::to_string(object_entry.unknown64)); - update_values.push_back(columns[18] + " = " + std::to_string(object_entry.unknown68)); - update_values.push_back(columns[19] + " = " + std::to_string(object_entry.unknown72)); - update_values.push_back(columns[20] + " = " + std::to_string(object_entry.unknown76)); - update_values.push_back(columns[21] + " = " + std::to_string(object_entry.unknown84)); - update_values.push_back(columns[22] + " = " + std::to_string(object_entry.size)); - update_values.push_back(columns[23] + " = " + std::to_string(object_entry.tilt_x)); - update_values.push_back(columns[24] + " = " + std::to_string(object_entry.tilt_y)); - update_values.push_back(columns[25] + " = '" + EscapeString(object_entry.display_name) + "'"); - update_values.push_back(columns[26] + " = " + std::to_string(object_entry.min_expansion)); - update_values.push_back(columns[27] + " = " + std::to_string(object_entry.max_expansion)); - update_values.push_back(columns[28] + " = '" + EscapeString(object_entry.content_flags) + "'"); - update_values.push_back(columns[29] + " = '" + EscapeString(object_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[2] + " = " + std::to_string(e.version)); + v.push_back(columns[3] + " = " + std::to_string(e.xpos)); + v.push_back(columns[4] + " = " + std::to_string(e.ypos)); + v.push_back(columns[5] + " = " + std::to_string(e.zpos)); + v.push_back(columns[6] + " = " + std::to_string(e.heading)); + v.push_back(columns[7] + " = " + std::to_string(e.itemid)); + v.push_back(columns[8] + " = " + std::to_string(e.charges)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.objectname) + "'"); + v.push_back(columns[10] + " = " + std::to_string(e.type)); + v.push_back(columns[11] + " = " + std::to_string(e.icon)); + v.push_back(columns[12] + " = " + std::to_string(e.unknown08)); + v.push_back(columns[13] + " = " + std::to_string(e.unknown10)); + v.push_back(columns[14] + " = " + std::to_string(e.unknown20)); + v.push_back(columns[15] + " = " + std::to_string(e.unknown24)); + v.push_back(columns[16] + " = " + std::to_string(e.unknown60)); + v.push_back(columns[17] + " = " + std::to_string(e.unknown64)); + v.push_back(columns[18] + " = " + std::to_string(e.unknown68)); + v.push_back(columns[19] + " = " + std::to_string(e.unknown72)); + v.push_back(columns[20] + " = " + std::to_string(e.unknown76)); + v.push_back(columns[21] + " = " + std::to_string(e.unknown84)); + v.push_back(columns[22] + " = " + std::to_string(e.size)); + v.push_back(columns[23] + " = " + std::to_string(e.tilt_x)); + v.push_back(columns[24] + " = " + std::to_string(e.tilt_y)); + v.push_back(columns[25] + " = '" + Strings::Escape(e.display_name) + "'"); + v.push_back(columns[26] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[27] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[28] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[29] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - object_entry.id + e.id ) ); @@ -338,111 +338,111 @@ public: static Object InsertOne( Database& db, - Object object_entry + Object e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(object_entry.id)); - insert_values.push_back(std::to_string(object_entry.zoneid)); - insert_values.push_back(std::to_string(object_entry.version)); - insert_values.push_back(std::to_string(object_entry.xpos)); - insert_values.push_back(std::to_string(object_entry.ypos)); - insert_values.push_back(std::to_string(object_entry.zpos)); - insert_values.push_back(std::to_string(object_entry.heading)); - insert_values.push_back(std::to_string(object_entry.itemid)); - insert_values.push_back(std::to_string(object_entry.charges)); - insert_values.push_back("'" + EscapeString(object_entry.objectname) + "'"); - insert_values.push_back(std::to_string(object_entry.type)); - insert_values.push_back(std::to_string(object_entry.icon)); - insert_values.push_back(std::to_string(object_entry.unknown08)); - insert_values.push_back(std::to_string(object_entry.unknown10)); - insert_values.push_back(std::to_string(object_entry.unknown20)); - insert_values.push_back(std::to_string(object_entry.unknown24)); - insert_values.push_back(std::to_string(object_entry.unknown60)); - insert_values.push_back(std::to_string(object_entry.unknown64)); - insert_values.push_back(std::to_string(object_entry.unknown68)); - insert_values.push_back(std::to_string(object_entry.unknown72)); - insert_values.push_back(std::to_string(object_entry.unknown76)); - insert_values.push_back(std::to_string(object_entry.unknown84)); - insert_values.push_back(std::to_string(object_entry.size)); - insert_values.push_back(std::to_string(object_entry.tilt_x)); - insert_values.push_back(std::to_string(object_entry.tilt_y)); - insert_values.push_back("'" + EscapeString(object_entry.display_name) + "'"); - insert_values.push_back(std::to_string(object_entry.min_expansion)); - insert_values.push_back(std::to_string(object_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(object_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(object_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.xpos)); + v.push_back(std::to_string(e.ypos)); + v.push_back(std::to_string(e.zpos)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back("'" + Strings::Escape(e.objectname) + "'"); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.icon)); + v.push_back(std::to_string(e.unknown08)); + v.push_back(std::to_string(e.unknown10)); + v.push_back(std::to_string(e.unknown20)); + v.push_back(std::to_string(e.unknown24)); + v.push_back(std::to_string(e.unknown60)); + v.push_back(std::to_string(e.unknown64)); + v.push_back(std::to_string(e.unknown68)); + v.push_back(std::to_string(e.unknown72)); + v.push_back(std::to_string(e.unknown76)); + v.push_back(std::to_string(e.unknown84)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.tilt_x)); + v.push_back(std::to_string(e.tilt_y)); + v.push_back("'" + Strings::Escape(e.display_name) + "'"); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - object_entry.id = results.LastInsertedID(); - return object_entry; + e.id = results.LastInsertedID(); + return e; } - object_entry = NewEntity(); + e = NewEntity(); - return object_entry; + return e; } static int InsertMany( Database& db, - std::vector object_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &object_entry: object_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(object_entry.id)); - insert_values.push_back(std::to_string(object_entry.zoneid)); - insert_values.push_back(std::to_string(object_entry.version)); - insert_values.push_back(std::to_string(object_entry.xpos)); - insert_values.push_back(std::to_string(object_entry.ypos)); - insert_values.push_back(std::to_string(object_entry.zpos)); - insert_values.push_back(std::to_string(object_entry.heading)); - insert_values.push_back(std::to_string(object_entry.itemid)); - insert_values.push_back(std::to_string(object_entry.charges)); - insert_values.push_back("'" + EscapeString(object_entry.objectname) + "'"); - insert_values.push_back(std::to_string(object_entry.type)); - insert_values.push_back(std::to_string(object_entry.icon)); - insert_values.push_back(std::to_string(object_entry.unknown08)); - insert_values.push_back(std::to_string(object_entry.unknown10)); - insert_values.push_back(std::to_string(object_entry.unknown20)); - insert_values.push_back(std::to_string(object_entry.unknown24)); - insert_values.push_back(std::to_string(object_entry.unknown60)); - insert_values.push_back(std::to_string(object_entry.unknown64)); - insert_values.push_back(std::to_string(object_entry.unknown68)); - insert_values.push_back(std::to_string(object_entry.unknown72)); - insert_values.push_back(std::to_string(object_entry.unknown76)); - insert_values.push_back(std::to_string(object_entry.unknown84)); - insert_values.push_back(std::to_string(object_entry.size)); - insert_values.push_back(std::to_string(object_entry.tilt_x)); - insert_values.push_back(std::to_string(object_entry.tilt_y)); - insert_values.push_back("'" + EscapeString(object_entry.display_name) + "'"); - insert_values.push_back(std::to_string(object_entry.min_expansion)); - insert_values.push_back(std::to_string(object_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(object_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(object_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.xpos)); + v.push_back(std::to_string(e.ypos)); + v.push_back(std::to_string(e.zpos)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.charges)); + v.push_back("'" + Strings::Escape(e.objectname) + "'"); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.icon)); + v.push_back(std::to_string(e.unknown08)); + v.push_back(std::to_string(e.unknown10)); + v.push_back(std::to_string(e.unknown20)); + v.push_back(std::to_string(e.unknown24)); + v.push_back(std::to_string(e.unknown60)); + v.push_back(std::to_string(e.unknown64)); + v.push_back(std::to_string(e.unknown68)); + v.push_back(std::to_string(e.unknown72)); + v.push_back(std::to_string(e.unknown76)); + v.push_back(std::to_string(e.unknown84)); + v.push_back(std::to_string(e.size)); + v.push_back(std::to_string(e.tilt_x)); + v.push_back(std::to_string(e.tilt_y)); + v.push_back("'" + Strings::Escape(e.display_name) + "'"); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -463,46 +463,46 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Object entry{}; + Object e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.version = atoi(row[2]); - entry.xpos = static_cast(atof(row[3])); - entry.ypos = static_cast(atof(row[4])); - entry.zpos = static_cast(atof(row[5])); - entry.heading = static_cast(atof(row[6])); - entry.itemid = atoi(row[7]); - entry.charges = atoi(row[8]); - entry.objectname = row[9] ? row[9] : ""; - entry.type = atoi(row[10]); - entry.icon = atoi(row[11]); - entry.unknown08 = atoi(row[12]); - entry.unknown10 = atoi(row[13]); - entry.unknown20 = atoi(row[14]); - entry.unknown24 = atoi(row[15]); - entry.unknown60 = atoi(row[16]); - entry.unknown64 = atoi(row[17]); - entry.unknown68 = atoi(row[18]); - entry.unknown72 = atoi(row[19]); - entry.unknown76 = atoi(row[20]); - entry.unknown84 = atoi(row[21]); - entry.size = static_cast(atof(row[22])); - entry.tilt_x = static_cast(atof(row[23])); - entry.tilt_y = static_cast(atof(row[24])); - entry.display_name = row[25] ? row[25] : ""; - entry.min_expansion = atoi(row[26]); - entry.max_expansion = atoi(row[27]); - entry.content_flags = row[28] ? row[28] : ""; - entry.content_flags_disabled = row[29] ? row[29] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(atoi(row[2])); + e.xpos = strtof(row[3], nullptr); + e.ypos = strtof(row[4], nullptr); + e.zpos = strtof(row[5], nullptr); + e.heading = strtof(row[6], nullptr); + e.itemid = static_cast(atoi(row[7])); + e.charges = static_cast(strtoul(row[8], nullptr, 10)); + e.objectname = row[9] ? row[9] : ""; + e.type = static_cast(atoi(row[10])); + e.icon = static_cast(atoi(row[11])); + e.unknown08 = static_cast(atoi(row[12])); + e.unknown10 = static_cast(atoi(row[13])); + e.unknown20 = static_cast(atoi(row[14])); + e.unknown24 = static_cast(atoi(row[15])); + e.unknown60 = static_cast(atoi(row[16])); + e.unknown64 = static_cast(atoi(row[17])); + e.unknown68 = static_cast(atoi(row[18])); + e.unknown72 = static_cast(atoi(row[19])); + e.unknown76 = static_cast(atoi(row[20])); + e.unknown84 = static_cast(atoi(row[21])); + e.size = strtof(row[22], nullptr); + e.tilt_x = strtof(row[23], nullptr); + e.tilt_y = strtof(row[24], nullptr); + e.display_name = row[25] ? row[25] : ""; + e.min_expansion = static_cast(atoi(row[26])); + e.max_expansion = static_cast(atoi(row[27])); + e.content_flags = row[28] ? row[28] : ""; + e.content_flags_disabled = row[29] ? row[29] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -517,46 +517,46 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Object entry{}; + Object e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.version = atoi(row[2]); - entry.xpos = static_cast(atof(row[3])); - entry.ypos = static_cast(atof(row[4])); - entry.zpos = static_cast(atof(row[5])); - entry.heading = static_cast(atof(row[6])); - entry.itemid = atoi(row[7]); - entry.charges = atoi(row[8]); - entry.objectname = row[9] ? row[9] : ""; - entry.type = atoi(row[10]); - entry.icon = atoi(row[11]); - entry.unknown08 = atoi(row[12]); - entry.unknown10 = atoi(row[13]); - entry.unknown20 = atoi(row[14]); - entry.unknown24 = atoi(row[15]); - entry.unknown60 = atoi(row[16]); - entry.unknown64 = atoi(row[17]); - entry.unknown68 = atoi(row[18]); - entry.unknown72 = atoi(row[19]); - entry.unknown76 = atoi(row[20]); - entry.unknown84 = atoi(row[21]); - entry.size = static_cast(atof(row[22])); - entry.tilt_x = static_cast(atof(row[23])); - entry.tilt_y = static_cast(atof(row[24])); - entry.display_name = row[25] ? row[25] : ""; - entry.min_expansion = atoi(row[26]); - entry.max_expansion = atoi(row[27]); - entry.content_flags = row[28] ? row[28] : ""; - entry.content_flags_disabled = row[29] ? row[29] : ""; + e.id = static_cast(atoi(row[0])); + e.zoneid = static_cast(strtoul(row[1], nullptr, 10)); + e.version = static_cast(atoi(row[2])); + e.xpos = strtof(row[3], nullptr); + e.ypos = strtof(row[4], nullptr); + e.zpos = strtof(row[5], nullptr); + e.heading = strtof(row[6], nullptr); + e.itemid = static_cast(atoi(row[7])); + e.charges = static_cast(strtoul(row[8], nullptr, 10)); + e.objectname = row[9] ? row[9] : ""; + e.type = static_cast(atoi(row[10])); + e.icon = static_cast(atoi(row[11])); + e.unknown08 = static_cast(atoi(row[12])); + e.unknown10 = static_cast(atoi(row[13])); + e.unknown20 = static_cast(atoi(row[14])); + e.unknown24 = static_cast(atoi(row[15])); + e.unknown60 = static_cast(atoi(row[16])); + e.unknown64 = static_cast(atoi(row[17])); + e.unknown68 = static_cast(atoi(row[18])); + e.unknown72 = static_cast(atoi(row[19])); + e.unknown76 = static_cast(atoi(row[20])); + e.unknown84 = static_cast(atoi(row[21])); + e.size = strtof(row[22], nullptr); + e.tilt_x = strtof(row[23], nullptr); + e.tilt_y = strtof(row[24], nullptr); + e.display_name = row[25] ? row[25] : ""; + e.min_expansion = static_cast(atoi(row[26])); + e.max_expansion = static_cast(atoi(row[27])); + e.content_flags = row[28] ? row[28] : ""; + e.content_flags_disabled = row[29] ? row[29] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -581,6 +581,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_OBJECT_REPOSITORY_H diff --git a/common/repositories/base/base_perl_event_export_settings_repository.h b/common/repositories/base/base_perl_event_export_settings_repository.h index 5221b7f77..d4e2fcafc 100644 --- a/common/repositories/base/base_perl_event_export_settings_repository.h +++ b/common/repositories/base/base_perl_event_export_settings_repository.h @@ -13,19 +13,19 @@ #define EQEMU_BASE_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BasePerlEventExportSettingsRepository { public: struct PerlEventExportSettings { - int event_id; + int32_t event_id; std::string event_description; - int export_qglobals; - int export_mob; - int export_zone; - int export_item; - int export_event; + int16_t export_qglobals; + int16_t export_mob; + int16_t export_zone; + int16_t export_item; + int16_t export_event; }; static std::string PrimaryKey() @@ -61,12 +61,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -94,20 +94,20 @@ public: static PerlEventExportSettings NewEntity() { - PerlEventExportSettings entry{}; + PerlEventExportSettings e{}; - entry.event_id = 0; - entry.event_description = ""; - entry.export_qglobals = 0; - entry.export_mob = 0; - entry.export_zone = 0; - entry.export_item = 0; - entry.export_event = 0; + e.event_id = 0; + e.event_description = ""; + e.export_qglobals = 0; + e.export_mob = 0; + e.export_zone = 0; + e.export_item = 0; + e.export_event = 0; - return entry; + return e; } - static PerlEventExportSettings GetPerlEventExportSettingsEntry( + static PerlEventExportSettings GetPerlEventExportSettings( const std::vector &perl_event_export_settingss, int perl_event_export_settings_id ) @@ -136,17 +136,17 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - PerlEventExportSettings entry{}; + PerlEventExportSettings e{}; - entry.event_id = atoi(row[0]); - entry.event_description = row[1] ? row[1] : ""; - entry.export_qglobals = atoi(row[2]); - entry.export_mob = atoi(row[3]); - entry.export_zone = atoi(row[4]); - entry.export_item = atoi(row[5]); - entry.export_event = atoi(row[6]); + e.event_id = static_cast(atoi(row[0])); + e.event_description = row[1] ? row[1] : ""; + e.export_qglobals = static_cast(atoi(row[2])); + e.export_mob = static_cast(atoi(row[3])); + e.export_zone = static_cast(atoi(row[4])); + e.export_item = static_cast(atoi(row[5])); + e.export_event = static_cast(atoi(row[6])); - return entry; + return e; } return NewEntity(); @@ -171,28 +171,28 @@ public: static int UpdateOne( Database& db, - PerlEventExportSettings perl_event_export_settings_entry + const PerlEventExportSettings &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(perl_event_export_settings_entry.event_id)); - update_values.push_back(columns[1] + " = '" + EscapeString(perl_event_export_settings_entry.event_description) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(perl_event_export_settings_entry.export_qglobals)); - update_values.push_back(columns[3] + " = " + std::to_string(perl_event_export_settings_entry.export_mob)); - update_values.push_back(columns[4] + " = " + std::to_string(perl_event_export_settings_entry.export_zone)); - update_values.push_back(columns[5] + " = " + std::to_string(perl_event_export_settings_entry.export_item)); - update_values.push_back(columns[6] + " = " + std::to_string(perl_event_export_settings_entry.export_event)); + v.push_back(columns[0] + " = " + std::to_string(e.event_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.event_description) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.export_qglobals)); + v.push_back(columns[3] + " = " + std::to_string(e.export_mob)); + v.push_back(columns[4] + " = " + std::to_string(e.export_zone)); + v.push_back(columns[5] + " = " + std::to_string(e.export_item)); + v.push_back(columns[6] + " = " + std::to_string(e.export_event)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - perl_event_export_settings_entry.event_id + e.event_id ) ); @@ -201,65 +201,65 @@ public: static PerlEventExportSettings InsertOne( Database& db, - PerlEventExportSettings perl_event_export_settings_entry + PerlEventExportSettings e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(perl_event_export_settings_entry.event_id)); - insert_values.push_back("'" + EscapeString(perl_event_export_settings_entry.event_description) + "'"); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_qglobals)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_mob)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_zone)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_item)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_event)); + v.push_back(std::to_string(e.event_id)); + v.push_back("'" + Strings::Escape(e.event_description) + "'"); + v.push_back(std::to_string(e.export_qglobals)); + v.push_back(std::to_string(e.export_mob)); + v.push_back(std::to_string(e.export_zone)); + v.push_back(std::to_string(e.export_item)); + v.push_back(std::to_string(e.export_event)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - perl_event_export_settings_entry.event_id = results.LastInsertedID(); - return perl_event_export_settings_entry; + e.event_id = results.LastInsertedID(); + return e; } - perl_event_export_settings_entry = NewEntity(); + e = NewEntity(); - return perl_event_export_settings_entry; + return e; } static int InsertMany( Database& db, - std::vector perl_event_export_settings_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &perl_event_export_settings_entry: perl_event_export_settings_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(perl_event_export_settings_entry.event_id)); - insert_values.push_back("'" + EscapeString(perl_event_export_settings_entry.event_description) + "'"); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_qglobals)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_mob)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_zone)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_item)); - insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_event)); + v.push_back(std::to_string(e.event_id)); + v.push_back("'" + Strings::Escape(e.event_description) + "'"); + v.push_back(std::to_string(e.export_qglobals)); + v.push_back(std::to_string(e.export_mob)); + v.push_back(std::to_string(e.export_zone)); + v.push_back(std::to_string(e.export_item)); + v.push_back(std::to_string(e.export_event)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -280,23 +280,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PerlEventExportSettings entry{}; + PerlEventExportSettings e{}; - entry.event_id = atoi(row[0]); - entry.event_description = row[1] ? row[1] : ""; - entry.export_qglobals = atoi(row[2]); - entry.export_mob = atoi(row[3]); - entry.export_zone = atoi(row[4]); - entry.export_item = atoi(row[5]); - entry.export_event = atoi(row[6]); + e.event_id = static_cast(atoi(row[0])); + e.event_description = row[1] ? row[1] : ""; + e.export_qglobals = static_cast(atoi(row[2])); + e.export_mob = static_cast(atoi(row[3])); + e.export_zone = static_cast(atoi(row[4])); + e.export_item = static_cast(atoi(row[5])); + e.export_event = static_cast(atoi(row[6])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -311,23 +311,23 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PerlEventExportSettings entry{}; + PerlEventExportSettings e{}; - entry.event_id = atoi(row[0]); - entry.event_description = row[1] ? row[1] : ""; - entry.export_qglobals = atoi(row[2]); - entry.export_mob = atoi(row[3]); - entry.export_zone = atoi(row[4]); - entry.export_item = atoi(row[5]); - entry.export_event = atoi(row[6]); + e.event_id = static_cast(atoi(row[0])); + e.event_description = row[1] ? row[1] : ""; + e.export_qglobals = static_cast(atoi(row[2])); + e.export_mob = static_cast(atoi(row[3])); + e.export_zone = static_cast(atoi(row[4])); + e.export_item = static_cast(atoi(row[5])); + e.export_event = static_cast(atoi(row[6])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -352,6 +352,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_petitions_repository.h b/common/repositories/base/base_petitions_repository.h index 9d62180e6..94706c16c 100644 --- a/common/repositories/base/base_petitions_repository.h +++ b/common/repositories/base/base_petitions_repository.h @@ -13,28 +13,28 @@ #define EQEMU_BASE_PETITIONS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BasePetitionsRepository { public: struct Petitions { - int dib; - int petid; + uint32_t dib; + uint32_t petid; std::string charname; std::string accountname; std::string lastgm; std::string petitiontext; std::string gmtext; std::string zone; - int urgency; - int charclass; - int charrace; - int charlevel; - int checkouts; - int unavailables; - int ischeckedout; - int64 senttime; + int32_t urgency; + int32_t charclass; + int32_t charrace; + int32_t charlevel; + int32_t checkouts; + int32_t unavailables; + int8_t ischeckedout; + int64_t senttime; }; static std::string PrimaryKey() @@ -88,12 +88,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -121,29 +121,29 @@ public: static Petitions NewEntity() { - Petitions entry{}; + Petitions e{}; - entry.dib = 0; - entry.petid = 0; - entry.charname = ""; - entry.accountname = ""; - entry.lastgm = ""; - entry.petitiontext = ""; - entry.gmtext = ""; - entry.zone = ""; - entry.urgency = 0; - entry.charclass = 0; - entry.charrace = 0; - entry.charlevel = 0; - entry.checkouts = 0; - entry.unavailables = 0; - entry.ischeckedout = 0; - entry.senttime = 0; + e.dib = 0; + e.petid = 0; + e.charname = ""; + e.accountname = ""; + e.lastgm = ""; + e.petitiontext = ""; + e.gmtext = ""; + e.zone = ""; + e.urgency = 0; + e.charclass = 0; + e.charrace = 0; + e.charlevel = 0; + e.checkouts = 0; + e.unavailables = 0; + e.ischeckedout = 0; + e.senttime = 0; - return entry; + return e; } - static Petitions GetPetitionsEntry( + static Petitions GetPetitions( const std::vector &petitionss, int petitions_id ) @@ -172,26 +172,26 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Petitions entry{}; + Petitions e{}; - entry.dib = atoi(row[0]); - entry.petid = atoi(row[1]); - entry.charname = row[2] ? row[2] : ""; - entry.accountname = row[3] ? row[3] : ""; - entry.lastgm = row[4] ? row[4] : ""; - entry.petitiontext = row[5] ? row[5] : ""; - entry.gmtext = row[6] ? row[6] : ""; - entry.zone = row[7] ? row[7] : ""; - entry.urgency = atoi(row[8]); - entry.charclass = atoi(row[9]); - entry.charrace = atoi(row[10]); - entry.charlevel = atoi(row[11]); - entry.checkouts = atoi(row[12]); - entry.unavailables = atoi(row[13]); - entry.ischeckedout = atoi(row[14]); - entry.senttime = strtoll(row[15], nullptr, 10); + e.dib = static_cast(strtoul(row[0], nullptr, 10)); + e.petid = static_cast(strtoul(row[1], nullptr, 10)); + e.charname = row[2] ? row[2] : ""; + e.accountname = row[3] ? row[3] : ""; + e.lastgm = row[4] ? row[4] : ""; + e.petitiontext = row[5] ? row[5] : ""; + e.gmtext = row[6] ? row[6] : ""; + e.zone = row[7] ? row[7] : ""; + e.urgency = static_cast(atoi(row[8])); + e.charclass = static_cast(atoi(row[9])); + e.charrace = static_cast(atoi(row[10])); + e.charlevel = static_cast(atoi(row[11])); + e.checkouts = static_cast(atoi(row[12])); + e.unavailables = static_cast(atoi(row[13])); + e.ischeckedout = static_cast(atoi(row[14])); + e.senttime = strtoll(row[15], nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -216,36 +216,36 @@ public: static int UpdateOne( Database& db, - Petitions petitions_entry + const Petitions &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(petitions_entry.petid)); - update_values.push_back(columns[2] + " = '" + EscapeString(petitions_entry.charname) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(petitions_entry.accountname) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(petitions_entry.lastgm) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(petitions_entry.petitiontext) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(petitions_entry.gmtext) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(petitions_entry.zone) + "'"); - update_values.push_back(columns[8] + " = " + std::to_string(petitions_entry.urgency)); - update_values.push_back(columns[9] + " = " + std::to_string(petitions_entry.charclass)); - update_values.push_back(columns[10] + " = " + std::to_string(petitions_entry.charrace)); - update_values.push_back(columns[11] + " = " + std::to_string(petitions_entry.charlevel)); - update_values.push_back(columns[12] + " = " + std::to_string(petitions_entry.checkouts)); - update_values.push_back(columns[13] + " = " + std::to_string(petitions_entry.unavailables)); - update_values.push_back(columns[14] + " = " + std::to_string(petitions_entry.ischeckedout)); - update_values.push_back(columns[15] + " = " + std::to_string(petitions_entry.senttime)); + v.push_back(columns[1] + " = " + std::to_string(e.petid)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.charname) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.accountname) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.lastgm) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.petitiontext) + "'"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.gmtext) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.urgency)); + v.push_back(columns[9] + " = " + std::to_string(e.charclass)); + v.push_back(columns[10] + " = " + std::to_string(e.charrace)); + v.push_back(columns[11] + " = " + std::to_string(e.charlevel)); + v.push_back(columns[12] + " = " + std::to_string(e.checkouts)); + v.push_back(columns[13] + " = " + std::to_string(e.unavailables)); + v.push_back(columns[14] + " = " + std::to_string(e.ischeckedout)); + v.push_back(columns[15] + " = " + std::to_string(e.senttime)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - petitions_entry.dib + e.dib ) ); @@ -254,83 +254,83 @@ public: static Petitions InsertOne( Database& db, - Petitions petitions_entry + Petitions e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(petitions_entry.dib)); - insert_values.push_back(std::to_string(petitions_entry.petid)); - insert_values.push_back("'" + EscapeString(petitions_entry.charname) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.accountname) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.lastgm) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.petitiontext) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.gmtext) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.zone) + "'"); - insert_values.push_back(std::to_string(petitions_entry.urgency)); - insert_values.push_back(std::to_string(petitions_entry.charclass)); - insert_values.push_back(std::to_string(petitions_entry.charrace)); - insert_values.push_back(std::to_string(petitions_entry.charlevel)); - insert_values.push_back(std::to_string(petitions_entry.checkouts)); - insert_values.push_back(std::to_string(petitions_entry.unavailables)); - insert_values.push_back(std::to_string(petitions_entry.ischeckedout)); - insert_values.push_back(std::to_string(petitions_entry.senttime)); + v.push_back(std::to_string(e.dib)); + v.push_back(std::to_string(e.petid)); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.accountname) + "'"); + v.push_back("'" + Strings::Escape(e.lastgm) + "'"); + v.push_back("'" + Strings::Escape(e.petitiontext) + "'"); + v.push_back("'" + Strings::Escape(e.gmtext) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.urgency)); + v.push_back(std::to_string(e.charclass)); + v.push_back(std::to_string(e.charrace)); + v.push_back(std::to_string(e.charlevel)); + v.push_back(std::to_string(e.checkouts)); + v.push_back(std::to_string(e.unavailables)); + v.push_back(std::to_string(e.ischeckedout)); + v.push_back(std::to_string(e.senttime)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - petitions_entry.dib = results.LastInsertedID(); - return petitions_entry; + e.dib = results.LastInsertedID(); + return e; } - petitions_entry = NewEntity(); + e = NewEntity(); - return petitions_entry; + return e; } static int InsertMany( Database& db, - std::vector petitions_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &petitions_entry: petitions_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(petitions_entry.dib)); - insert_values.push_back(std::to_string(petitions_entry.petid)); - insert_values.push_back("'" + EscapeString(petitions_entry.charname) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.accountname) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.lastgm) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.petitiontext) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.gmtext) + "'"); - insert_values.push_back("'" + EscapeString(petitions_entry.zone) + "'"); - insert_values.push_back(std::to_string(petitions_entry.urgency)); - insert_values.push_back(std::to_string(petitions_entry.charclass)); - insert_values.push_back(std::to_string(petitions_entry.charrace)); - insert_values.push_back(std::to_string(petitions_entry.charlevel)); - insert_values.push_back(std::to_string(petitions_entry.checkouts)); - insert_values.push_back(std::to_string(petitions_entry.unavailables)); - insert_values.push_back(std::to_string(petitions_entry.ischeckedout)); - insert_values.push_back(std::to_string(petitions_entry.senttime)); + v.push_back(std::to_string(e.dib)); + v.push_back(std::to_string(e.petid)); + v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.accountname) + "'"); + v.push_back("'" + Strings::Escape(e.lastgm) + "'"); + v.push_back("'" + Strings::Escape(e.petitiontext) + "'"); + v.push_back("'" + Strings::Escape(e.gmtext) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.urgency)); + v.push_back(std::to_string(e.charclass)); + v.push_back(std::to_string(e.charrace)); + v.push_back(std::to_string(e.charlevel)); + v.push_back(std::to_string(e.checkouts)); + v.push_back(std::to_string(e.unavailables)); + v.push_back(std::to_string(e.ischeckedout)); + v.push_back(std::to_string(e.senttime)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -351,32 +351,32 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Petitions entry{}; + Petitions e{}; - entry.dib = atoi(row[0]); - entry.petid = atoi(row[1]); - entry.charname = row[2] ? row[2] : ""; - entry.accountname = row[3] ? row[3] : ""; - entry.lastgm = row[4] ? row[4] : ""; - entry.petitiontext = row[5] ? row[5] : ""; - entry.gmtext = row[6] ? row[6] : ""; - entry.zone = row[7] ? row[7] : ""; - entry.urgency = atoi(row[8]); - entry.charclass = atoi(row[9]); - entry.charrace = atoi(row[10]); - entry.charlevel = atoi(row[11]); - entry.checkouts = atoi(row[12]); - entry.unavailables = atoi(row[13]); - entry.ischeckedout = atoi(row[14]); - entry.senttime = strtoll(row[15], nullptr, 10); + e.dib = static_cast(strtoul(row[0], nullptr, 10)); + e.petid = static_cast(strtoul(row[1], nullptr, 10)); + e.charname = row[2] ? row[2] : ""; + e.accountname = row[3] ? row[3] : ""; + e.lastgm = row[4] ? row[4] : ""; + e.petitiontext = row[5] ? row[5] : ""; + e.gmtext = row[6] ? row[6] : ""; + e.zone = row[7] ? row[7] : ""; + e.urgency = static_cast(atoi(row[8])); + e.charclass = static_cast(atoi(row[9])); + e.charrace = static_cast(atoi(row[10])); + e.charlevel = static_cast(atoi(row[11])); + e.checkouts = static_cast(atoi(row[12])); + e.unavailables = static_cast(atoi(row[13])); + e.ischeckedout = static_cast(atoi(row[14])); + e.senttime = strtoll(row[15], nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -391,32 +391,32 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Petitions entry{}; + Petitions e{}; - entry.dib = atoi(row[0]); - entry.petid = atoi(row[1]); - entry.charname = row[2] ? row[2] : ""; - entry.accountname = row[3] ? row[3] : ""; - entry.lastgm = row[4] ? row[4] : ""; - entry.petitiontext = row[5] ? row[5] : ""; - entry.gmtext = row[6] ? row[6] : ""; - entry.zone = row[7] ? row[7] : ""; - entry.urgency = atoi(row[8]); - entry.charclass = atoi(row[9]); - entry.charrace = atoi(row[10]); - entry.charlevel = atoi(row[11]); - entry.checkouts = atoi(row[12]); - entry.unavailables = atoi(row[13]); - entry.ischeckedout = atoi(row[14]); - entry.senttime = strtoll(row[15], nullptr, 10); + e.dib = static_cast(strtoul(row[0], nullptr, 10)); + e.petid = static_cast(strtoul(row[1], nullptr, 10)); + e.charname = row[2] ? row[2] : ""; + e.accountname = row[3] ? row[3] : ""; + e.lastgm = row[4] ? row[4] : ""; + e.petitiontext = row[5] ? row[5] : ""; + e.gmtext = row[6] ? row[6] : ""; + e.zone = row[7] ? row[7] : ""; + e.urgency = static_cast(atoi(row[8])); + e.charclass = static_cast(atoi(row[9])); + e.charrace = static_cast(atoi(row[10])); + e.charlevel = static_cast(atoi(row[11])); + e.checkouts = static_cast(atoi(row[12])); + e.unavailables = static_cast(atoi(row[13])); + e.ischeckedout = static_cast(atoi(row[14])); + e.senttime = strtoll(row[15], nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -441,6 +441,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_PETITIONS_REPOSITORY_H diff --git a/common/repositories/base/base_pets_beastlord_data_repository.h b/common/repositories/base/base_pets_beastlord_data_repository.h index 4b529f24c..fd0519f6e 100644 --- a/common/repositories/base/base_pets_beastlord_data_repository.h +++ b/common/repositories/base/base_pets_beastlord_data_repository.h @@ -13,19 +13,19 @@ #define EQEMU_BASE_PETS_BEASTLORD_DATA_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BasePetsBeastlordDataRepository { public: struct PetsBeastlordData { - int player_race; - int pet_race; - int texture; - int helm_texture; - int gender; - float size_modifier; - int face; + uint32_t player_race; + uint32_t pet_race; + uint8_t texture; + uint8_t helm_texture; + uint8_t gender; + std::string size_modifier; + uint8_t face; }; static std::string PrimaryKey() @@ -61,12 +61,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -94,20 +94,20 @@ public: static PetsBeastlordData NewEntity() { - PetsBeastlordData entry{}; + PetsBeastlordData e{}; - entry.player_race = 1; - entry.pet_race = 42; - entry.texture = 0; - entry.helm_texture = 0; - entry.gender = 2; - entry.size_modifier = 1; - entry.face = 0; + e.player_race = 1; + e.pet_race = 42; + e.texture = 0; + e.helm_texture = 0; + e.gender = 2; + e.size_modifier = 1; + e.face = 0; - return entry; + return e; } - static PetsBeastlordData GetPetsBeastlordDataEntry( + static PetsBeastlordData GetPetsBeastlordData( const std::vector &pets_beastlord_datas, int pets_beastlord_data_id ) @@ -136,17 +136,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - PetsBeastlordData entry{}; + PetsBeastlordData e{}; - entry.player_race = atoi(row[0]); - entry.pet_race = atoi(row[1]); - entry.texture = atoi(row[2]); - entry.helm_texture = atoi(row[3]); - entry.gender = atoi(row[4]); - entry.size_modifier = static_cast(atof(row[5])); - entry.face = atoi(row[6]); + e.player_race = static_cast(strtoul(row[0], nullptr, 10)); + e.pet_race = static_cast(strtoul(row[1], nullptr, 10)); + e.texture = static_cast(strtoul(row[2], nullptr, 10)); + e.helm_texture = static_cast(strtoul(row[3], nullptr, 10)); + e.gender = static_cast(strtoul(row[4], nullptr, 10)); + e.face = static_cast(strtoul(row[6], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -171,28 +170,28 @@ public: static int UpdateOne( Database& db, - PetsBeastlordData pets_beastlord_data_entry + const PetsBeastlordData &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(pets_beastlord_data_entry.player_race)); - update_values.push_back(columns[1] + " = " + std::to_string(pets_beastlord_data_entry.pet_race)); - update_values.push_back(columns[2] + " = " + std::to_string(pets_beastlord_data_entry.texture)); - update_values.push_back(columns[3] + " = " + std::to_string(pets_beastlord_data_entry.helm_texture)); - update_values.push_back(columns[4] + " = " + std::to_string(pets_beastlord_data_entry.gender)); - update_values.push_back(columns[5] + " = " + std::to_string(pets_beastlord_data_entry.size_modifier)); - update_values.push_back(columns[6] + " = " + std::to_string(pets_beastlord_data_entry.face)); + v.push_back(columns[0] + " = " + std::to_string(e.player_race)); + v.push_back(columns[1] + " = " + std::to_string(e.pet_race)); + v.push_back(columns[2] + " = " + std::to_string(e.texture)); + v.push_back(columns[3] + " = " + std::to_string(e.helm_texture)); + v.push_back(columns[4] + " = " + std::to_string(e.gender)); + v.push_back(columns[5] + " = " + std::to_string(e.size_modifier)); + v.push_back(columns[6] + " = " + std::to_string(e.face)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - pets_beastlord_data_entry.player_race + e.player_race ) ); @@ -201,65 +200,65 @@ public: static PetsBeastlordData InsertOne( Database& db, - PetsBeastlordData pets_beastlord_data_entry + PetsBeastlordData e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(pets_beastlord_data_entry.player_race)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.pet_race)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.texture)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.helm_texture)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.gender)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.size_modifier)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.face)); + v.push_back(std::to_string(e.player_race)); + v.push_back(std::to_string(e.pet_race)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helm_texture)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.size_modifier)); + v.push_back(std::to_string(e.face)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - pets_beastlord_data_entry.player_race = results.LastInsertedID(); - return pets_beastlord_data_entry; + e.player_race = results.LastInsertedID(); + return e; } - pets_beastlord_data_entry = NewEntity(); + e = NewEntity(); - return pets_beastlord_data_entry; + return e; } static int InsertMany( Database& db, - std::vector pets_beastlord_data_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &pets_beastlord_data_entry: pets_beastlord_data_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(pets_beastlord_data_entry.player_race)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.pet_race)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.texture)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.helm_texture)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.gender)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.size_modifier)); - insert_values.push_back(std::to_string(pets_beastlord_data_entry.face)); + v.push_back(std::to_string(e.player_race)); + v.push_back(std::to_string(e.pet_race)); + v.push_back(std::to_string(e.texture)); + v.push_back(std::to_string(e.helm_texture)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.size_modifier)); + v.push_back(std::to_string(e.face)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -280,23 +279,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PetsBeastlordData entry{}; + PetsBeastlordData e{}; - entry.player_race = atoi(row[0]); - entry.pet_race = atoi(row[1]); - entry.texture = atoi(row[2]); - entry.helm_texture = atoi(row[3]); - entry.gender = atoi(row[4]); - entry.size_modifier = static_cast(atof(row[5])); - entry.face = atoi(row[6]); + e.player_race = static_cast(strtoul(row[0], nullptr, 10)); + e.pet_race = static_cast(strtoul(row[1], nullptr, 10)); + e.texture = static_cast(strtoul(row[2], nullptr, 10)); + e.helm_texture = static_cast(strtoul(row[3], nullptr, 10)); + e.gender = static_cast(strtoul(row[4], nullptr, 10)); + e.face = static_cast(strtoul(row[6], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -311,23 +309,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PetsBeastlordData entry{}; + PetsBeastlordData e{}; - entry.player_race = atoi(row[0]); - entry.pet_race = atoi(row[1]); - entry.texture = atoi(row[2]); - entry.helm_texture = atoi(row[3]); - entry.gender = atoi(row[4]); - entry.size_modifier = static_cast(atof(row[5])); - entry.face = atoi(row[6]); + e.player_race = static_cast(strtoul(row[0], nullptr, 10)); + e.pet_race = static_cast(strtoul(row[1], nullptr, 10)); + e.texture = static_cast(strtoul(row[2], nullptr, 10)); + e.helm_texture = static_cast(strtoul(row[3], nullptr, 10)); + e.gender = static_cast(strtoul(row[4], nullptr, 10)); + e.face = static_cast(strtoul(row[6], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -352,6 +349,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_PETS_BEASTLORD_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_pets_equipmentset_entries_repository.h b/common/repositories/base/base_pets_equipmentset_entries_repository.h index 778b3f457..c6ba9b48a 100644 --- a/common/repositories/base/base_pets_equipmentset_entries_repository.h +++ b/common/repositories/base/base_pets_equipmentset_entries_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BasePetsEquipmentsetEntriesRepository { public: struct PetsEquipmentsetEntries { - int set_id; - int slot; - int item_id; + int32_t set_id; + int32_t slot; + int32_t item_id; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static PetsEquipmentsetEntries NewEntity() { - PetsEquipmentsetEntries entry{}; + PetsEquipmentsetEntries e{}; - entry.set_id = 0; - entry.slot = 0; - entry.item_id = 0; + e.set_id = 0; + e.slot = 0; + e.item_id = 0; - return entry; + return e; } - static PetsEquipmentsetEntries GetPetsEquipmentsetEntriesEntry( + static PetsEquipmentsetEntries GetPetsEquipmentsetEntries( const std::vector &pets_equipmentset_entriess, int pets_equipmentset_entries_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - PetsEquipmentsetEntries entry{}; + PetsEquipmentsetEntries e{}; - entry.set_id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.item_id = atoi(row[2]); + e.set_id = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.item_id = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - PetsEquipmentsetEntries pets_equipmentset_entries_entry + const PetsEquipmentsetEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(pets_equipmentset_entries_entry.set_id)); - update_values.push_back(columns[1] + " = " + std::to_string(pets_equipmentset_entries_entry.slot)); - update_values.push_back(columns[2] + " = " + std::to_string(pets_equipmentset_entries_entry.item_id)); + v.push_back(columns[0] + " = " + std::to_string(e.set_id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - pets_equipmentset_entries_entry.set_id + e.set_id ) ); @@ -177,57 +177,57 @@ public: static PetsEquipmentsetEntries InsertOne( Database& db, - PetsEquipmentsetEntries pets_equipmentset_entries_entry + PetsEquipmentsetEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.set_id)); - insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.slot)); - insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.item_id)); + v.push_back(std::to_string(e.set_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - pets_equipmentset_entries_entry.set_id = results.LastInsertedID(); - return pets_equipmentset_entries_entry; + e.set_id = results.LastInsertedID(); + return e; } - pets_equipmentset_entries_entry = NewEntity(); + e = NewEntity(); - return pets_equipmentset_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector pets_equipmentset_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &pets_equipmentset_entries_entry: pets_equipmentset_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.set_id)); - insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.slot)); - insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.item_id)); + v.push_back(std::to_string(e.set_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PetsEquipmentsetEntries entry{}; + PetsEquipmentsetEntries e{}; - entry.set_id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.item_id = atoi(row[2]); + e.set_id = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.item_id = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PetsEquipmentsetEntries entry{}; + PetsEquipmentsetEntries e{}; - entry.set_id = atoi(row[0]); - entry.slot = atoi(row[1]); - entry.item_id = atoi(row[2]); + e.set_id = static_cast(atoi(row[0])); + e.slot = static_cast(atoi(row[1])); + e.item_id = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_pets_equipmentset_repository.h b/common/repositories/base/base_pets_equipmentset_repository.h index 2c5c85afb..944df956f 100644 --- a/common/repositories/base/base_pets_equipmentset_repository.h +++ b/common/repositories/base/base_pets_equipmentset_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_PETS_EQUIPMENTSET_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BasePetsEquipmentsetRepository { public: struct PetsEquipmentset { - int set_id; + int32_t set_id; std::string setname; - int nested_set; + int32_t nested_set; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static PetsEquipmentset NewEntity() { - PetsEquipmentset entry{}; + PetsEquipmentset e{}; - entry.set_id = 0; - entry.setname = ""; - entry.nested_set = -1; + e.set_id = 0; + e.setname = ""; + e.nested_set = -1; - return entry; + return e; } - static PetsEquipmentset GetPetsEquipmentsetEntry( + static PetsEquipmentset GetPetsEquipmentset( const std::vector &pets_equipmentsets, int pets_equipmentset_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - PetsEquipmentset entry{}; + PetsEquipmentset e{}; - entry.set_id = atoi(row[0]); - entry.setname = row[1] ? row[1] : ""; - entry.nested_set = atoi(row[2]); + e.set_id = static_cast(atoi(row[0])); + e.setname = row[1] ? row[1] : ""; + e.nested_set = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - PetsEquipmentset pets_equipmentset_entry + const PetsEquipmentset &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(pets_equipmentset_entry.set_id)); - update_values.push_back(columns[1] + " = '" + EscapeString(pets_equipmentset_entry.setname) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(pets_equipmentset_entry.nested_set)); + v.push_back(columns[0] + " = " + std::to_string(e.set_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.setname) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.nested_set)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - pets_equipmentset_entry.set_id + e.set_id ) ); @@ -177,57 +177,57 @@ public: static PetsEquipmentset InsertOne( Database& db, - PetsEquipmentset pets_equipmentset_entry + PetsEquipmentset e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(pets_equipmentset_entry.set_id)); - insert_values.push_back("'" + EscapeString(pets_equipmentset_entry.setname) + "'"); - insert_values.push_back(std::to_string(pets_equipmentset_entry.nested_set)); + v.push_back(std::to_string(e.set_id)); + v.push_back("'" + Strings::Escape(e.setname) + "'"); + v.push_back(std::to_string(e.nested_set)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - pets_equipmentset_entry.set_id = results.LastInsertedID(); - return pets_equipmentset_entry; + e.set_id = results.LastInsertedID(); + return e; } - pets_equipmentset_entry = NewEntity(); + e = NewEntity(); - return pets_equipmentset_entry; + return e; } static int InsertMany( Database& db, - std::vector pets_equipmentset_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &pets_equipmentset_entry: pets_equipmentset_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(pets_equipmentset_entry.set_id)); - insert_values.push_back("'" + EscapeString(pets_equipmentset_entry.setname) + "'"); - insert_values.push_back(std::to_string(pets_equipmentset_entry.nested_set)); + v.push_back(std::to_string(e.set_id)); + v.push_back("'" + Strings::Escape(e.setname) + "'"); + v.push_back(std::to_string(e.nested_set)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PetsEquipmentset entry{}; + PetsEquipmentset e{}; - entry.set_id = atoi(row[0]); - entry.setname = row[1] ? row[1] : ""; - entry.nested_set = atoi(row[2]); + e.set_id = static_cast(atoi(row[0])); + e.setname = row[1] ? row[1] : ""; + e.nested_set = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PetsEquipmentset entry{}; + PetsEquipmentset e{}; - entry.set_id = atoi(row[0]); - entry.setname = row[1] ? row[1] : ""; - entry.nested_set = atoi(row[2]); + e.set_id = static_cast(atoi(row[0])); + e.setname = row[1] ? row[1] : ""; + e.nested_set = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_PETS_EQUIPMENTSET_REPOSITORY_H diff --git a/common/repositories/base/base_pets_repository.h b/common/repositories/base/base_pets_repository.h index 345b33ffb..dff44229f 100644 --- a/common/repositories/base/base_pets_repository.h +++ b/common/repositories/base/base_pets_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_PETS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BasePetsRepository { public: struct Pets { - int id; + int32_t id; std::string type; - int petpower; - int npcID; - int temp; - int petcontrol; - int petnaming; - int monsterflag; - int equipmentset; + int32_t petpower; + int32_t npcID; + int8_t temp; + int8_t petcontrol; + int8_t petnaming; + int8_t monsterflag; + int32_t equipmentset; }; static std::string PrimaryKey() @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static Pets NewEntity() { - Pets entry{}; + Pets e{}; - entry.id = 0; - entry.type = ""; - entry.petpower = 0; - entry.npcID = 0; - entry.temp = 0; - entry.petcontrol = 0; - entry.petnaming = 0; - entry.monsterflag = 0; - entry.equipmentset = -1; + e.id = 0; + e.type = ""; + e.petpower = 0; + e.npcID = 0; + e.temp = 0; + e.petcontrol = 0; + e.petnaming = 0; + e.monsterflag = 0; + e.equipmentset = -1; - return entry; + return e; } - static Pets GetPetsEntry( + static Pets GetPets( const std::vector &petss, int pets_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Pets entry{}; + Pets e{}; - entry.id = atoi(row[0]); - entry.type = row[1] ? row[1] : ""; - entry.petpower = atoi(row[2]); - entry.npcID = atoi(row[3]); - entry.temp = atoi(row[4]); - entry.petcontrol = atoi(row[5]); - entry.petnaming = atoi(row[6]); - entry.monsterflag = atoi(row[7]); - entry.equipmentset = atoi(row[8]); + e.id = static_cast(atoi(row[0])); + e.type = row[1] ? row[1] : ""; + e.petpower = static_cast(atoi(row[2])); + e.npcID = static_cast(atoi(row[3])); + e.temp = static_cast(atoi(row[4])); + e.petcontrol = static_cast(atoi(row[5])); + e.petnaming = static_cast(atoi(row[6])); + e.monsterflag = static_cast(atoi(row[7])); + e.equipmentset = static_cast(atoi(row[8])); - return entry; + return e; } return NewEntity(); @@ -181,29 +181,29 @@ public: static int UpdateOne( Database& db, - Pets pets_entry + const Pets &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(pets_entry.type) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(pets_entry.petpower)); - update_values.push_back(columns[3] + " = " + std::to_string(pets_entry.npcID)); - update_values.push_back(columns[4] + " = " + std::to_string(pets_entry.temp)); - update_values.push_back(columns[5] + " = " + std::to_string(pets_entry.petcontrol)); - update_values.push_back(columns[6] + " = " + std::to_string(pets_entry.petnaming)); - update_values.push_back(columns[7] + " = " + std::to_string(pets_entry.monsterflag)); - update_values.push_back(columns[8] + " = " + std::to_string(pets_entry.equipmentset)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.type) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.petpower)); + v.push_back(columns[3] + " = " + std::to_string(e.npcID)); + v.push_back(columns[4] + " = " + std::to_string(e.temp)); + v.push_back(columns[5] + " = " + std::to_string(e.petcontrol)); + v.push_back(columns[6] + " = " + std::to_string(e.petnaming)); + v.push_back(columns[7] + " = " + std::to_string(e.monsterflag)); + v.push_back(columns[8] + " = " + std::to_string(e.equipmentset)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - pets_entry.id + e.id ) ); @@ -212,69 +212,69 @@ public: static Pets InsertOne( Database& db, - Pets pets_entry + Pets e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(pets_entry.id)); - insert_values.push_back("'" + EscapeString(pets_entry.type) + "'"); - insert_values.push_back(std::to_string(pets_entry.petpower)); - insert_values.push_back(std::to_string(pets_entry.npcID)); - insert_values.push_back(std::to_string(pets_entry.temp)); - insert_values.push_back(std::to_string(pets_entry.petcontrol)); - insert_values.push_back(std::to_string(pets_entry.petnaming)); - insert_values.push_back(std::to_string(pets_entry.monsterflag)); - insert_values.push_back(std::to_string(pets_entry.equipmentset)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.type) + "'"); + v.push_back(std::to_string(e.petpower)); + v.push_back(std::to_string(e.npcID)); + v.push_back(std::to_string(e.temp)); + v.push_back(std::to_string(e.petcontrol)); + v.push_back(std::to_string(e.petnaming)); + v.push_back(std::to_string(e.monsterflag)); + v.push_back(std::to_string(e.equipmentset)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - pets_entry.id = results.LastInsertedID(); - return pets_entry; + e.id = results.LastInsertedID(); + return e; } - pets_entry = NewEntity(); + e = NewEntity(); - return pets_entry; + return e; } static int InsertMany( Database& db, - std::vector pets_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &pets_entry: pets_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(pets_entry.id)); - insert_values.push_back("'" + EscapeString(pets_entry.type) + "'"); - insert_values.push_back(std::to_string(pets_entry.petpower)); - insert_values.push_back(std::to_string(pets_entry.npcID)); - insert_values.push_back(std::to_string(pets_entry.temp)); - insert_values.push_back(std::to_string(pets_entry.petcontrol)); - insert_values.push_back(std::to_string(pets_entry.petnaming)); - insert_values.push_back(std::to_string(pets_entry.monsterflag)); - insert_values.push_back(std::to_string(pets_entry.equipmentset)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.type) + "'"); + v.push_back(std::to_string(e.petpower)); + v.push_back(std::to_string(e.npcID)); + v.push_back(std::to_string(e.temp)); + v.push_back(std::to_string(e.petcontrol)); + v.push_back(std::to_string(e.petnaming)); + v.push_back(std::to_string(e.monsterflag)); + v.push_back(std::to_string(e.equipmentset)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -295,25 +295,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Pets entry{}; + Pets e{}; - entry.id = atoi(row[0]); - entry.type = row[1] ? row[1] : ""; - entry.petpower = atoi(row[2]); - entry.npcID = atoi(row[3]); - entry.temp = atoi(row[4]); - entry.petcontrol = atoi(row[5]); - entry.petnaming = atoi(row[6]); - entry.monsterflag = atoi(row[7]); - entry.equipmentset = atoi(row[8]); + e.id = static_cast(atoi(row[0])); + e.type = row[1] ? row[1] : ""; + e.petpower = static_cast(atoi(row[2])); + e.npcID = static_cast(atoi(row[3])); + e.temp = static_cast(atoi(row[4])); + e.petcontrol = static_cast(atoi(row[5])); + e.petnaming = static_cast(atoi(row[6])); + e.monsterflag = static_cast(atoi(row[7])); + e.equipmentset = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -328,25 +328,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Pets entry{}; + Pets e{}; - entry.id = atoi(row[0]); - entry.type = row[1] ? row[1] : ""; - entry.petpower = atoi(row[2]); - entry.npcID = atoi(row[3]); - entry.temp = atoi(row[4]); - entry.petcontrol = atoi(row[5]); - entry.petnaming = atoi(row[6]); - entry.monsterflag = atoi(row[7]); - entry.equipmentset = atoi(row[8]); + e.id = static_cast(atoi(row[0])); + e.type = row[1] ? row[1] : ""; + e.petpower = static_cast(atoi(row[2])); + e.npcID = static_cast(atoi(row[3])); + e.temp = static_cast(atoi(row[4])); + e.petcontrol = static_cast(atoi(row[5])); + e.petnaming = static_cast(atoi(row[6])); + e.monsterflag = static_cast(atoi(row[7])); + e.equipmentset = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -371,6 +371,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_PETS_REPOSITORY_H diff --git a/common/repositories/base/base_player_titlesets_repository.h b/common/repositories/base/base_player_titlesets_repository.h index 1d7c2e031..2904ce0fb 100644 --- a/common/repositories/base/base_player_titlesets_repository.h +++ b/common/repositories/base/base_player_titlesets_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_PLAYER_TITLESETS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BasePlayerTitlesetsRepository { public: struct PlayerTitlesets { - int id; - int char_id; - int title_set; + uint32_t id; + uint32_t char_id; + uint32_t title_set; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static PlayerTitlesets NewEntity() { - PlayerTitlesets entry{}; + PlayerTitlesets e{}; - entry.id = 0; - entry.char_id = 0; - entry.title_set = 0; + e.id = 0; + e.char_id = 0; + e.title_set = 0; - return entry; + return e; } - static PlayerTitlesets GetPlayerTitlesetsEntry( + static PlayerTitlesets GetPlayerTitlesets( const std::vector &player_titlesetss, int player_titlesets_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - PlayerTitlesets entry{}; + PlayerTitlesets e{}; - entry.id = atoi(row[0]); - entry.char_id = atoi(row[1]); - entry.title_set = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.char_id = static_cast(strtoul(row[1], nullptr, 10)); + e.title_set = static_cast(strtoul(row[2], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -151,23 +151,23 @@ public: static int UpdateOne( Database& db, - PlayerTitlesets player_titlesets_entry + const PlayerTitlesets &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(player_titlesets_entry.char_id)); - update_values.push_back(columns[2] + " = " + std::to_string(player_titlesets_entry.title_set)); + v.push_back(columns[1] + " = " + std::to_string(e.char_id)); + v.push_back(columns[2] + " = " + std::to_string(e.title_set)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - player_titlesets_entry.id + e.id ) ); @@ -176,57 +176,57 @@ public: static PlayerTitlesets InsertOne( Database& db, - PlayerTitlesets player_titlesets_entry + PlayerTitlesets e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(player_titlesets_entry.id)); - insert_values.push_back(std::to_string(player_titlesets_entry.char_id)); - insert_values.push_back(std::to_string(player_titlesets_entry.title_set)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.title_set)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - player_titlesets_entry.id = results.LastInsertedID(); - return player_titlesets_entry; + e.id = results.LastInsertedID(); + return e; } - player_titlesets_entry = NewEntity(); + e = NewEntity(); - return player_titlesets_entry; + return e; } static int InsertMany( Database& db, - std::vector player_titlesets_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &player_titlesets_entry: player_titlesets_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(player_titlesets_entry.id)); - insert_values.push_back(std::to_string(player_titlesets_entry.char_id)); - insert_values.push_back(std::to_string(player_titlesets_entry.title_set)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.title_set)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -247,19 +247,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PlayerTitlesets entry{}; + PlayerTitlesets e{}; - entry.id = atoi(row[0]); - entry.char_id = atoi(row[1]); - entry.title_set = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.char_id = static_cast(strtoul(row[1], nullptr, 10)); + e.title_set = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -274,19 +274,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - PlayerTitlesets entry{}; + PlayerTitlesets e{}; - entry.id = atoi(row[0]); - entry.char_id = atoi(row[1]); - entry.title_set = atoi(row[2]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.char_id = static_cast(strtoul(row[1], nullptr, 10)); + e.title_set = static_cast(strtoul(row[2], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -311,6 +311,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_PLAYER_TITLESETS_REPOSITORY_H diff --git a/common/repositories/base/base_proximities_repository.h b/common/repositories/base/base_proximities_repository.h deleted file mode 100644 index 8126ac402..000000000 --- a/common/repositories/base/base_proximities_repository.h +++ /dev/null @@ -1,367 +0,0 @@ -/** - * DO NOT MODIFY THIS FILE - * - * This repository was automatically generated and is NOT to be modified directly. - * Any repository modifications are meant to be made to the repository extending the base. - * Any modifications to base repositories are to be made by the generator only - * - * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories - */ - -#ifndef EQEMU_BASE_PROXIMITIES_REPOSITORY_H -#define EQEMU_BASE_PROXIMITIES_REPOSITORY_H - -#include "../../database.h" -#include "../../string_util.h" -#include - -class BaseProximitiesRepository { -public: - struct Proximities { - int zoneid; - int exploreid; - float minx; - float maxx; - float miny; - float maxy; - float minz; - float maxz; - }; - - static std::string PrimaryKey() - { - return std::string("zoneid"); - } - - static std::vector Columns() - { - return { - "zoneid", - "exploreid", - "minx", - "maxx", - "miny", - "maxy", - "minz", - "maxz", - }; - } - - static std::vector SelectColumns() - { - return { - "zoneid", - "exploreid", - "minx", - "maxx", - "miny", - "maxy", - "minz", - "maxz", - }; - } - - static std::string ColumnsRaw() - { - return std::string(implode(", ", Columns())); - } - - static std::string SelectColumnsRaw() - { - return std::string(implode(", ", SelectColumns())); - } - - static std::string TableName() - { - return std::string("proximities"); - } - - static std::string BaseSelect() - { - return fmt::format( - "SELECT {} FROM {}", - SelectColumnsRaw(), - TableName() - ); - } - - static std::string BaseInsert() - { - return fmt::format( - "INSERT INTO {} ({}) ", - TableName(), - ColumnsRaw() - ); - } - - static Proximities NewEntity() - { - Proximities entry{}; - - entry.zoneid = 0; - entry.exploreid = 0; - entry.minx = 0.000000; - entry.maxx = 0.000000; - entry.miny = 0.000000; - entry.maxy = 0.000000; - entry.minz = 0.000000; - entry.maxz = 0.000000; - - return entry; - } - - static Proximities GetProximitiesEntry( - const std::vector &proximitiess, - int proximities_id - ) - { - for (auto &proximities : proximitiess) { - if (proximities.zoneid == proximities_id) { - return proximities; - } - } - - return NewEntity(); - } - - static Proximities FindOne( - Database& db, - int proximities_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE id = {} LIMIT 1", - BaseSelect(), - proximities_id - ) - ); - - auto row = results.begin(); - if (results.RowCount() == 1) { - Proximities entry{}; - - entry.zoneid = atoi(row[0]); - entry.exploreid = atoi(row[1]); - entry.minx = static_cast(atof(row[2])); - entry.maxx = static_cast(atof(row[3])); - entry.miny = static_cast(atof(row[4])); - entry.maxy = static_cast(atof(row[5])); - entry.minz = static_cast(atof(row[6])); - entry.maxz = static_cast(atof(row[7])); - - return entry; - } - - return NewEntity(); - } - - static int DeleteOne( - Database& db, - int proximities_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {} = {}", - TableName(), - PrimaryKey(), - proximities_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int UpdateOne( - Database& db, - Proximities proximities_entry - ) - { - std::vector update_values; - - auto columns = Columns(); - - update_values.push_back(columns[0] + " = " + std::to_string(proximities_entry.zoneid)); - update_values.push_back(columns[1] + " = " + std::to_string(proximities_entry.exploreid)); - update_values.push_back(columns[2] + " = " + std::to_string(proximities_entry.minx)); - update_values.push_back(columns[3] + " = " + std::to_string(proximities_entry.maxx)); - update_values.push_back(columns[4] + " = " + std::to_string(proximities_entry.miny)); - update_values.push_back(columns[5] + " = " + std::to_string(proximities_entry.maxy)); - update_values.push_back(columns[6] + " = " + std::to_string(proximities_entry.minz)); - update_values.push_back(columns[7] + " = " + std::to_string(proximities_entry.maxz)); - - auto results = db.QueryDatabase( - fmt::format( - "UPDATE {} SET {} WHERE {} = {}", - TableName(), - implode(", ", update_values), - PrimaryKey(), - proximities_entry.zoneid - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static Proximities InsertOne( - Database& db, - Proximities proximities_entry - ) - { - std::vector insert_values; - - insert_values.push_back(std::to_string(proximities_entry.zoneid)); - insert_values.push_back(std::to_string(proximities_entry.exploreid)); - insert_values.push_back(std::to_string(proximities_entry.minx)); - insert_values.push_back(std::to_string(proximities_entry.maxx)); - insert_values.push_back(std::to_string(proximities_entry.miny)); - insert_values.push_back(std::to_string(proximities_entry.maxy)); - insert_values.push_back(std::to_string(proximities_entry.minz)); - insert_values.push_back(std::to_string(proximities_entry.maxz)); - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES ({})", - BaseInsert(), - implode(",", insert_values) - ) - ); - - if (results.Success()) { - proximities_entry.zoneid = results.LastInsertedID(); - return proximities_entry; - } - - proximities_entry = NewEntity(); - - return proximities_entry; - } - - static int InsertMany( - Database& db, - std::vector proximities_entries - ) - { - std::vector insert_chunks; - - for (auto &proximities_entry: proximities_entries) { - std::vector insert_values; - - insert_values.push_back(std::to_string(proximities_entry.zoneid)); - insert_values.push_back(std::to_string(proximities_entry.exploreid)); - insert_values.push_back(std::to_string(proximities_entry.minx)); - insert_values.push_back(std::to_string(proximities_entry.maxx)); - insert_values.push_back(std::to_string(proximities_entry.miny)); - insert_values.push_back(std::to_string(proximities_entry.maxy)); - insert_values.push_back(std::to_string(proximities_entry.minz)); - insert_values.push_back(std::to_string(proximities_entry.maxz)); - - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); - } - - std::vector insert_values; - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES {}", - BaseInsert(), - implode(",", insert_chunks) - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static std::vector All(Database& db) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{}", - BaseSelect() - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Proximities entry{}; - - entry.zoneid = atoi(row[0]); - entry.exploreid = atoi(row[1]); - entry.minx = static_cast(atof(row[2])); - entry.maxx = static_cast(atof(row[3])); - entry.miny = static_cast(atof(row[4])); - entry.maxy = static_cast(atof(row[5])); - entry.minz = static_cast(atof(row[6])); - entry.maxz = static_cast(atof(row[7])); - - all_entries.push_back(entry); - } - - return all_entries; - } - - static std::vector GetWhere(Database& db, std::string where_filter) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE {}", - BaseSelect(), - where_filter - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Proximities entry{}; - - entry.zoneid = atoi(row[0]); - entry.exploreid = atoi(row[1]); - entry.minx = static_cast(atof(row[2])); - entry.maxx = static_cast(atof(row[3])); - entry.miny = static_cast(atof(row[4])); - entry.maxy = static_cast(atof(row[5])); - entry.minz = static_cast(atof(row[6])); - entry.maxz = static_cast(atof(row[7])); - - all_entries.push_back(entry); - } - - return all_entries; - } - - static int DeleteWhere(Database& db, std::string where_filter) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {}", - TableName(), - where_filter - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int Truncate(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "TRUNCATE TABLE {}", - TableName() - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - -}; - -#endif //EQEMU_BASE_PROXIMITIES_REPOSITORY_H diff --git a/common/repositories/base/base_quest_globals_repository.h b/common/repositories/base/base_quest_globals_repository.h index f6b751cfc..c09e955a7 100644 --- a/common/repositories/base/base_quest_globals_repository.h +++ b/common/repositories/base/base_quest_globals_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_QUEST_GLOBALS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseQuestGlobalsRepository { public: struct QuestGlobals { - int charid; - int npcid; - int zoneid; + int32_t charid; + int32_t npcid; + int32_t zoneid; std::string name; std::string value; - int expdate; + int32_t expdate; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static QuestGlobals NewEntity() { - QuestGlobals entry{}; + QuestGlobals e{}; - entry.charid = 0; - entry.npcid = 0; - entry.zoneid = 0; - entry.name = ""; - entry.value = "?"; - entry.expdate = 0; + e.charid = 0; + e.npcid = 0; + e.zoneid = 0; + e.name = ""; + e.value = "?"; + e.expdate = 0; - return entry; + return e; } - static QuestGlobals GetQuestGlobalsEntry( + static QuestGlobals GetQuestGlobals( const std::vector &quest_globalss, int quest_globals_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - QuestGlobals entry{}; + QuestGlobals e{}; - entry.charid = atoi(row[0]); - entry.npcid = atoi(row[1]); - entry.zoneid = atoi(row[2]); - entry.name = row[3] ? row[3] : ""; - entry.value = row[4] ? row[4] : ""; - entry.expdate = atoi(row[5]); + e.charid = static_cast(atoi(row[0])); + e.npcid = static_cast(atoi(row[1])); + e.zoneid = static_cast(atoi(row[2])); + e.name = row[3] ? row[3] : ""; + e.value = row[4] ? row[4] : ""; + e.expdate = static_cast(atoi(row[5])); - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - QuestGlobals quest_globals_entry + const QuestGlobals &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(quest_globals_entry.charid)); - update_values.push_back(columns[1] + " = " + std::to_string(quest_globals_entry.npcid)); - update_values.push_back(columns[2] + " = " + std::to_string(quest_globals_entry.zoneid)); - update_values.push_back(columns[3] + " = '" + EscapeString(quest_globals_entry.name) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(quest_globals_entry.value) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(quest_globals_entry.expdate)); + v.push_back(columns[0] + " = " + std::to_string(e.charid)); + v.push_back(columns[1] + " = " + std::to_string(e.npcid)); + v.push_back(columns[2] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.value) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.expdate)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - quest_globals_entry.charid + e.charid ) ); @@ -195,63 +195,63 @@ public: static QuestGlobals InsertOne( Database& db, - QuestGlobals quest_globals_entry + QuestGlobals e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(quest_globals_entry.charid)); - insert_values.push_back(std::to_string(quest_globals_entry.npcid)); - insert_values.push_back(std::to_string(quest_globals_entry.zoneid)); - insert_values.push_back("'" + EscapeString(quest_globals_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(quest_globals_entry.value) + "'"); - insert_values.push_back(std::to_string(quest_globals_entry.expdate)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.npcid)); + v.push_back(std::to_string(e.zoneid)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.expdate)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - quest_globals_entry.charid = results.LastInsertedID(); - return quest_globals_entry; + e.charid = results.LastInsertedID(); + return e; } - quest_globals_entry = NewEntity(); + e = NewEntity(); - return quest_globals_entry; + return e; } static int InsertMany( Database& db, - std::vector quest_globals_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &quest_globals_entry: quest_globals_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(quest_globals_entry.charid)); - insert_values.push_back(std::to_string(quest_globals_entry.npcid)); - insert_values.push_back(std::to_string(quest_globals_entry.zoneid)); - insert_values.push_back("'" + EscapeString(quest_globals_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(quest_globals_entry.value) + "'"); - insert_values.push_back(std::to_string(quest_globals_entry.expdate)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.npcid)); + v.push_back(std::to_string(e.zoneid)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.expdate)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - QuestGlobals entry{}; + QuestGlobals e{}; - entry.charid = atoi(row[0]); - entry.npcid = atoi(row[1]); - entry.zoneid = atoi(row[2]); - entry.name = row[3] ? row[3] : ""; - entry.value = row[4] ? row[4] : ""; - entry.expdate = atoi(row[5]); + e.charid = static_cast(atoi(row[0])); + e.npcid = static_cast(atoi(row[1])); + e.zoneid = static_cast(atoi(row[2])); + e.name = row[3] ? row[3] : ""; + e.value = row[4] ? row[4] : ""; + e.expdate = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - QuestGlobals entry{}; + QuestGlobals e{}; - entry.charid = atoi(row[0]); - entry.npcid = atoi(row[1]); - entry.zoneid = atoi(row[2]); - entry.name = row[3] ? row[3] : ""; - entry.value = row[4] ? row[4] : ""; - entry.expdate = atoi(row[5]); + e.charid = static_cast(atoi(row[0])); + e.npcid = static_cast(atoi(row[1])); + e.zoneid = static_cast(atoi(row[2])); + e.name = row[3] ? row[3] : ""; + e.value = row[4] ? row[4] : ""; + e.expdate = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_QUEST_GLOBALS_REPOSITORY_H diff --git a/common/repositories/base/base_raid_details_repository.h b/common/repositories/base/base_raid_details_repository.h index 075928853..7ce468c60 100644 --- a/common/repositories/base/base_raid_details_repository.h +++ b/common/repositories/base/base_raid_details_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_RAID_DETAILS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseRaidDetailsRepository { public: struct RaidDetails { - int raidid; - int loottype; - int locked; + int32_t raidid; + int32_t loottype; + int8_t locked; std::string motd; }; @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static RaidDetails NewEntity() { - RaidDetails entry{}; + RaidDetails e{}; - entry.raidid = 0; - entry.loottype = 0; - entry.locked = 0; - entry.motd = ""; + e.raidid = 0; + e.loottype = 0; + e.locked = 0; + e.motd = ""; - return entry; + return e; } - static RaidDetails GetRaidDetailsEntry( + static RaidDetails GetRaidDetails( const std::vector &raid_detailss, int raid_details_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - RaidDetails entry{}; + RaidDetails e{}; - entry.raidid = atoi(row[0]); - entry.loottype = atoi(row[1]); - entry.locked = atoi(row[2]); - entry.motd = row[3] ? row[3] : ""; + e.raidid = static_cast(atoi(row[0])); + e.loottype = static_cast(atoi(row[1])); + e.locked = static_cast(atoi(row[2])); + e.motd = row[3] ? row[3] : ""; - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - RaidDetails raid_details_entry + const RaidDetails &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(raid_details_entry.raidid)); - update_values.push_back(columns[1] + " = " + std::to_string(raid_details_entry.loottype)); - update_values.push_back(columns[2] + " = " + std::to_string(raid_details_entry.locked)); - update_values.push_back(columns[3] + " = '" + EscapeString(raid_details_entry.motd) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.raidid)); + v.push_back(columns[1] + " = " + std::to_string(e.loottype)); + v.push_back(columns[2] + " = " + std::to_string(e.locked)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.motd) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - raid_details_entry.raidid + e.raidid ) ); @@ -183,59 +183,59 @@ public: static RaidDetails InsertOne( Database& db, - RaidDetails raid_details_entry + RaidDetails e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(raid_details_entry.raidid)); - insert_values.push_back(std::to_string(raid_details_entry.loottype)); - insert_values.push_back(std::to_string(raid_details_entry.locked)); - insert_values.push_back("'" + EscapeString(raid_details_entry.motd) + "'"); + v.push_back(std::to_string(e.raidid)); + v.push_back(std::to_string(e.loottype)); + v.push_back(std::to_string(e.locked)); + v.push_back("'" + Strings::Escape(e.motd) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - raid_details_entry.raidid = results.LastInsertedID(); - return raid_details_entry; + e.raidid = results.LastInsertedID(); + return e; } - raid_details_entry = NewEntity(); + e = NewEntity(); - return raid_details_entry; + return e; } static int InsertMany( Database& db, - std::vector raid_details_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &raid_details_entry: raid_details_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(raid_details_entry.raidid)); - insert_values.push_back(std::to_string(raid_details_entry.loottype)); - insert_values.push_back(std::to_string(raid_details_entry.locked)); - insert_values.push_back("'" + EscapeString(raid_details_entry.motd) + "'"); + v.push_back(std::to_string(e.raidid)); + v.push_back(std::to_string(e.loottype)); + v.push_back(std::to_string(e.locked)); + v.push_back("'" + Strings::Escape(e.motd) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RaidDetails entry{}; + RaidDetails e{}; - entry.raidid = atoi(row[0]); - entry.loottype = atoi(row[1]); - entry.locked = atoi(row[2]); - entry.motd = row[3] ? row[3] : ""; + e.raidid = static_cast(atoi(row[0])); + e.loottype = static_cast(atoi(row[1])); + e.locked = static_cast(atoi(row[2])); + e.motd = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RaidDetails entry{}; + RaidDetails e{}; - entry.raidid = atoi(row[0]); - entry.loottype = atoi(row[1]); - entry.locked = atoi(row[2]); - entry.motd = row[3] ? row[3] : ""; + e.raidid = static_cast(atoi(row[0])); + e.loottype = static_cast(atoi(row[1])); + e.locked = static_cast(atoi(row[2])); + e.motd = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_RAID_DETAILS_REPOSITORY_H diff --git a/common/repositories/base/base_raid_members_repository.h b/common/repositories/base/base_raid_members_repository.h index ed90853f0..07defda40 100644 --- a/common/repositories/base/base_raid_members_repository.h +++ b/common/repositories/base/base_raid_members_repository.h @@ -13,21 +13,21 @@ #define EQEMU_BASE_RAID_MEMBERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseRaidMembersRepository { public: struct RaidMembers { - int raidid; - int charid; - int groupid; - int _class; - int level; + int32_t raidid; + int32_t charid; + uint32_t groupid; + int8_t _class; + int8_t level; std::string name; - int isgroupleader; - int israidleader; - int islooter; + int8_t isgroupleader; + int8_t israidleader; + int8_t islooter; }; static std::string PrimaryKey() @@ -67,12 +67,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -100,22 +100,22 @@ public: static RaidMembers NewEntity() { - RaidMembers entry{}; + RaidMembers e{}; - entry.raidid = 0; - entry.charid = 0; - entry.groupid = 0; - entry._class = 0; - entry.level = 0; - entry.name = ""; - entry.isgroupleader = 0; - entry.israidleader = 0; - entry.islooter = 0; + e.raidid = 0; + e.charid = 0; + e.groupid = 0; + e._class = 0; + e.level = 0; + e.name = ""; + e.isgroupleader = 0; + e.israidleader = 0; + e.islooter = 0; - return entry; + return e; } - static RaidMembers GetRaidMembersEntry( + static RaidMembers GetRaidMembers( const std::vector &raid_memberss, int raid_members_id ) @@ -144,19 +144,19 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - RaidMembers entry{}; + RaidMembers e{}; - entry.raidid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.groupid = atoi(row[2]); - entry._class = atoi(row[3]); - entry.level = atoi(row[4]); - entry.name = row[5] ? row[5] : ""; - entry.isgroupleader = atoi(row[6]); - entry.israidleader = atoi(row[7]); - entry.islooter = atoi(row[8]); + e.raidid = static_cast(atoi(row[0])); + e.charid = static_cast(atoi(row[1])); + e.groupid = static_cast(strtoul(row[2], nullptr, 10)); + e._class = static_cast(atoi(row[3])); + e.level = static_cast(atoi(row[4])); + e.name = row[5] ? row[5] : ""; + e.isgroupleader = static_cast(atoi(row[6])); + e.israidleader = static_cast(atoi(row[7])); + e.islooter = static_cast(atoi(row[8])); - return entry; + return e; } return NewEntity(); @@ -181,30 +181,30 @@ public: static int UpdateOne( Database& db, - RaidMembers raid_members_entry + const RaidMembers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(raid_members_entry.raidid)); - update_values.push_back(columns[1] + " = " + std::to_string(raid_members_entry.charid)); - update_values.push_back(columns[2] + " = " + std::to_string(raid_members_entry.groupid)); - update_values.push_back(columns[3] + " = " + std::to_string(raid_members_entry._class)); - update_values.push_back(columns[4] + " = " + std::to_string(raid_members_entry.level)); - update_values.push_back(columns[5] + " = '" + EscapeString(raid_members_entry.name) + "'"); - update_values.push_back(columns[6] + " = " + std::to_string(raid_members_entry.isgroupleader)); - update_values.push_back(columns[7] + " = " + std::to_string(raid_members_entry.israidleader)); - update_values.push_back(columns[8] + " = " + std::to_string(raid_members_entry.islooter)); + v.push_back(columns[0] + " = " + std::to_string(e.raidid)); + v.push_back(columns[1] + " = " + std::to_string(e.charid)); + v.push_back(columns[2] + " = " + std::to_string(e.groupid)); + v.push_back(columns[3] + " = " + std::to_string(e._class)); + v.push_back(columns[4] + " = " + std::to_string(e.level)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.isgroupleader)); + v.push_back(columns[7] + " = " + std::to_string(e.israidleader)); + v.push_back(columns[8] + " = " + std::to_string(e.islooter)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - raid_members_entry.charid + e.charid ) ); @@ -213,69 +213,69 @@ public: static RaidMembers InsertOne( Database& db, - RaidMembers raid_members_entry + RaidMembers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(raid_members_entry.raidid)); - insert_values.push_back(std::to_string(raid_members_entry.charid)); - insert_values.push_back(std::to_string(raid_members_entry.groupid)); - insert_values.push_back(std::to_string(raid_members_entry._class)); - insert_values.push_back(std::to_string(raid_members_entry.level)); - insert_values.push_back("'" + EscapeString(raid_members_entry.name) + "'"); - insert_values.push_back(std::to_string(raid_members_entry.isgroupleader)); - insert_values.push_back(std::to_string(raid_members_entry.israidleader)); - insert_values.push_back(std::to_string(raid_members_entry.islooter)); + v.push_back(std::to_string(e.raidid)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.groupid)); + v.push_back(std::to_string(e._class)); + v.push_back(std::to_string(e.level)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.isgroupleader)); + v.push_back(std::to_string(e.israidleader)); + v.push_back(std::to_string(e.islooter)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - raid_members_entry.charid = results.LastInsertedID(); - return raid_members_entry; + e.charid = results.LastInsertedID(); + return e; } - raid_members_entry = NewEntity(); + e = NewEntity(); - return raid_members_entry; + return e; } static int InsertMany( Database& db, - std::vector raid_members_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &raid_members_entry: raid_members_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(raid_members_entry.raidid)); - insert_values.push_back(std::to_string(raid_members_entry.charid)); - insert_values.push_back(std::to_string(raid_members_entry.groupid)); - insert_values.push_back(std::to_string(raid_members_entry._class)); - insert_values.push_back(std::to_string(raid_members_entry.level)); - insert_values.push_back("'" + EscapeString(raid_members_entry.name) + "'"); - insert_values.push_back(std::to_string(raid_members_entry.isgroupleader)); - insert_values.push_back(std::to_string(raid_members_entry.israidleader)); - insert_values.push_back(std::to_string(raid_members_entry.islooter)); + v.push_back(std::to_string(e.raidid)); + v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.groupid)); + v.push_back(std::to_string(e._class)); + v.push_back(std::to_string(e.level)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.isgroupleader)); + v.push_back(std::to_string(e.israidleader)); + v.push_back(std::to_string(e.islooter)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -296,25 +296,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RaidMembers entry{}; + RaidMembers e{}; - entry.raidid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.groupid = atoi(row[2]); - entry._class = atoi(row[3]); - entry.level = atoi(row[4]); - entry.name = row[5] ? row[5] : ""; - entry.isgroupleader = atoi(row[6]); - entry.israidleader = atoi(row[7]); - entry.islooter = atoi(row[8]); + e.raidid = static_cast(atoi(row[0])); + e.charid = static_cast(atoi(row[1])); + e.groupid = static_cast(strtoul(row[2], nullptr, 10)); + e._class = static_cast(atoi(row[3])); + e.level = static_cast(atoi(row[4])); + e.name = row[5] ? row[5] : ""; + e.isgroupleader = static_cast(atoi(row[6])); + e.israidleader = static_cast(atoi(row[7])); + e.islooter = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -329,25 +329,25 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RaidMembers entry{}; + RaidMembers e{}; - entry.raidid = atoi(row[0]); - entry.charid = atoi(row[1]); - entry.groupid = atoi(row[2]); - entry._class = atoi(row[3]); - entry.level = atoi(row[4]); - entry.name = row[5] ? row[5] : ""; - entry.isgroupleader = atoi(row[6]); - entry.israidleader = atoi(row[7]); - entry.islooter = atoi(row[8]); + e.raidid = static_cast(atoi(row[0])); + e.charid = static_cast(atoi(row[1])); + e.groupid = static_cast(strtoul(row[2], nullptr, 10)); + e._class = static_cast(atoi(row[3])); + e.level = static_cast(atoi(row[4])); + e.name = row[5] ? row[5] : ""; + e.isgroupleader = static_cast(atoi(row[6])); + e.israidleader = static_cast(atoi(row[7])); + e.islooter = static_cast(atoi(row[8])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -372,6 +372,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_RAID_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_reports_repository.h b/common/repositories/base/base_reports_repository.h index 46316917a..3a45fe730 100644 --- a/common/repositories/base/base_reports_repository.h +++ b/common/repositories/base/base_reports_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_REPORTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseReportsRepository { public: struct Reports { - int id; + uint32_t id; std::string name; std::string reported; std::string reported_text; @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static Reports NewEntity() { - Reports entry{}; + Reports e{}; - entry.id = 0; - entry.name = ""; - entry.reported = ""; - entry.reported_text = ""; + e.id = 0; + e.name = ""; + e.reported = ""; + e.reported_text = ""; - return entry; + return e; } - static Reports GetReportsEntry( + static Reports GetReports( const std::vector &reportss, int reports_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Reports entry{}; + Reports e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.reported = row[2] ? row[2] : ""; - entry.reported_text = row[3] ? row[3] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.reported = row[2] ? row[2] : ""; + e.reported_text = row[3] ? row[3] : ""; - return entry; + return e; } return NewEntity(); @@ -156,24 +156,24 @@ public: static int UpdateOne( Database& db, - Reports reports_entry + const Reports &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(reports_entry.name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(reports_entry.reported) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(reports_entry.reported_text) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.reported) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.reported_text) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - reports_entry.id + e.id ) ); @@ -182,59 +182,59 @@ public: static Reports InsertOne( Database& db, - Reports reports_entry + Reports e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(reports_entry.id)); - insert_values.push_back("'" + EscapeString(reports_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(reports_entry.reported) + "'"); - insert_values.push_back("'" + EscapeString(reports_entry.reported_text) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.reported) + "'"); + v.push_back("'" + Strings::Escape(e.reported_text) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - reports_entry.id = results.LastInsertedID(); - return reports_entry; + e.id = results.LastInsertedID(); + return e; } - reports_entry = NewEntity(); + e = NewEntity(); - return reports_entry; + return e; } static int InsertMany( Database& db, - std::vector reports_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &reports_entry: reports_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(reports_entry.id)); - insert_values.push_back("'" + EscapeString(reports_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(reports_entry.reported) + "'"); - insert_values.push_back("'" + EscapeString(reports_entry.reported_text) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.reported) + "'"); + v.push_back("'" + Strings::Escape(e.reported_text) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -255,20 +255,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Reports entry{}; + Reports e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.reported = row[2] ? row[2] : ""; - entry.reported_text = row[3] ? row[3] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.reported = row[2] ? row[2] : ""; + e.reported_text = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -283,20 +283,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Reports entry{}; + Reports e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.reported = row[2] ? row[2] : ""; - entry.reported_text = row[3] ? row[3] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.reported = row[2] ? row[2] : ""; + e.reported_text = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -321,6 +321,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_REPORTS_REPOSITORY_H diff --git a/common/repositories/base/base_respawn_times_repository.h b/common/repositories/base/base_respawn_times_repository.h index 27ed4b281..446a78216 100644 --- a/common/repositories/base/base_respawn_times_repository.h +++ b/common/repositories/base/base_respawn_times_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_RESPAWN_TIMES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseRespawnTimesRepository { public: struct RespawnTimes { - int id; - int start; - int duration; - int instance_id; + int32_t id; + int32_t start; + int32_t duration; + int16_t instance_id; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static RespawnTimes NewEntity() { - RespawnTimes entry{}; + RespawnTimes e{}; - entry.id = 0; - entry.start = 0; - entry.duration = 0; - entry.instance_id = 0; + e.id = 0; + e.start = 0; + e.duration = 0; + e.instance_id = 0; - return entry; + return e; } - static RespawnTimes GetRespawnTimesEntry( + static RespawnTimes GetRespawnTimes( const std::vector &respawn_timess, int respawn_times_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - RespawnTimes entry{}; + RespawnTimes e{}; - entry.id = atoi(row[0]); - entry.start = atoi(row[1]); - entry.duration = atoi(row[2]); - entry.instance_id = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.start = static_cast(atoi(row[1])); + e.duration = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - RespawnTimes respawn_times_entry + const RespawnTimes &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(respawn_times_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(respawn_times_entry.start)); - update_values.push_back(columns[2] + " = " + std::to_string(respawn_times_entry.duration)); - update_values.push_back(columns[3] + " = " + std::to_string(respawn_times_entry.instance_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.start)); + v.push_back(columns[2] + " = " + std::to_string(e.duration)); + v.push_back(columns[3] + " = " + std::to_string(e.instance_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - respawn_times_entry.id + e.id ) ); @@ -183,59 +183,59 @@ public: static RespawnTimes InsertOne( Database& db, - RespawnTimes respawn_times_entry + RespawnTimes e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(respawn_times_entry.id)); - insert_values.push_back(std::to_string(respawn_times_entry.start)); - insert_values.push_back(std::to_string(respawn_times_entry.duration)); - insert_values.push_back(std::to_string(respawn_times_entry.instance_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.start)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.instance_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - respawn_times_entry.id = results.LastInsertedID(); - return respawn_times_entry; + e.id = results.LastInsertedID(); + return e; } - respawn_times_entry = NewEntity(); + e = NewEntity(); - return respawn_times_entry; + return e; } static int InsertMany( Database& db, - std::vector respawn_times_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &respawn_times_entry: respawn_times_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(respawn_times_entry.id)); - insert_values.push_back(std::to_string(respawn_times_entry.start)); - insert_values.push_back(std::to_string(respawn_times_entry.duration)); - insert_values.push_back(std::to_string(respawn_times_entry.instance_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.start)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.instance_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RespawnTimes entry{}; + RespawnTimes e{}; - entry.id = atoi(row[0]); - entry.start = atoi(row[1]); - entry.duration = atoi(row[2]); - entry.instance_id = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.start = static_cast(atoi(row[1])); + e.duration = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RespawnTimes entry{}; + RespawnTimes e{}; - entry.id = atoi(row[0]); - entry.start = atoi(row[1]); - entry.duration = atoi(row[2]); - entry.instance_id = atoi(row[3]); + e.id = static_cast(atoi(row[0])); + e.start = static_cast(atoi(row[1])); + e.duration = static_cast(atoi(row[2])); + e.instance_id = static_cast(atoi(row[3])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_RESPAWN_TIMES_REPOSITORY_H diff --git a/common/repositories/base/base_rule_sets_repository.h b/common/repositories/base/base_rule_sets_repository.h index 5ca2361a8..461c6f1e6 100644 --- a/common/repositories/base/base_rule_sets_repository.h +++ b/common/repositories/base/base_rule_sets_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_RULE_SETS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseRuleSetsRepository { public: struct RuleSets { - int ruleset_id; + uint8_t ruleset_id; std::string name; }; @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static RuleSets NewEntity() { - RuleSets entry{}; + RuleSets e{}; - entry.ruleset_id = 0; - entry.name = ""; + e.ruleset_id = 0; + e.name = ""; - return entry; + return e; } - static RuleSets GetRuleSetsEntry( + static RuleSets GetRuleSets( const std::vector &rule_setss, int rule_sets_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - RuleSets entry{}; + RuleSets e{}; - entry.ruleset_id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; + e.ruleset_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; - return entry; + return e; } return NewEntity(); @@ -146,22 +146,22 @@ public: static int UpdateOne( Database& db, - RuleSets rule_sets_entry + const RuleSets &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(rule_sets_entry.name) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - rule_sets_entry.ruleset_id + e.ruleset_id ) ); @@ -170,55 +170,55 @@ public: static RuleSets InsertOne( Database& db, - RuleSets rule_sets_entry + RuleSets e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(rule_sets_entry.ruleset_id)); - insert_values.push_back("'" + EscapeString(rule_sets_entry.name) + "'"); + v.push_back(std::to_string(e.ruleset_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - rule_sets_entry.ruleset_id = results.LastInsertedID(); - return rule_sets_entry; + e.ruleset_id = results.LastInsertedID(); + return e; } - rule_sets_entry = NewEntity(); + e = NewEntity(); - return rule_sets_entry; + return e; } static int InsertMany( Database& db, - std::vector rule_sets_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &rule_sets_entry: rule_sets_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(rule_sets_entry.ruleset_id)); - insert_values.push_back("'" + EscapeString(rule_sets_entry.name) + "'"); + v.push_back(std::to_string(e.ruleset_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -239,18 +239,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RuleSets entry{}; + RuleSets e{}; - entry.ruleset_id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; + e.ruleset_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -265,18 +265,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RuleSets entry{}; + RuleSets e{}; - entry.ruleset_id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; + e.ruleset_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -301,6 +301,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_RULE_SETS_REPOSITORY_H diff --git a/common/repositories/base/base_rule_values_repository.h b/common/repositories/base/base_rule_values_repository.h index 418509d96..b98e3f7dc 100644 --- a/common/repositories/base/base_rule_values_repository.h +++ b/common/repositories/base/base_rule_values_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_RULE_VALUES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseRuleValuesRepository { public: struct RuleValues { - int ruleset_id; + uint8_t ruleset_id; std::string rule_name; std::string rule_value; std::string notes; @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static RuleValues NewEntity() { - RuleValues entry{}; + RuleValues e{}; - entry.ruleset_id = 0; - entry.rule_name = ""; - entry.rule_value = ""; - entry.notes = ""; + e.ruleset_id = 0; + e.rule_name = ""; + e.rule_value = ""; + e.notes = ""; - return entry; + return e; } - static RuleValues GetRuleValuesEntry( + static RuleValues GetRuleValues( const std::vector &rule_valuess, int rule_values_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - RuleValues entry{}; + RuleValues e{}; - entry.ruleset_id = atoi(row[0]); - entry.rule_name = row[1] ? row[1] : ""; - entry.rule_value = row[2] ? row[2] : ""; - entry.notes = row[3] ? row[3] : ""; + e.ruleset_id = static_cast(strtoul(row[0], nullptr, 10)); + e.rule_name = row[1] ? row[1] : ""; + e.rule_value = row[2] ? row[2] : ""; + e.notes = row[3] ? row[3] : ""; - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - RuleValues rule_values_entry + const RuleValues &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(rule_values_entry.ruleset_id)); - update_values.push_back(columns[1] + " = '" + EscapeString(rule_values_entry.rule_name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(rule_values_entry.rule_value) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(rule_values_entry.notes) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.ruleset_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.rule_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.rule_value) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.notes) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - rule_values_entry.ruleset_id + e.ruleset_id ) ); @@ -183,59 +183,59 @@ public: static RuleValues InsertOne( Database& db, - RuleValues rule_values_entry + RuleValues e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(rule_values_entry.ruleset_id)); - insert_values.push_back("'" + EscapeString(rule_values_entry.rule_name) + "'"); - insert_values.push_back("'" + EscapeString(rule_values_entry.rule_value) + "'"); - insert_values.push_back("'" + EscapeString(rule_values_entry.notes) + "'"); + v.push_back(std::to_string(e.ruleset_id)); + v.push_back("'" + Strings::Escape(e.rule_name) + "'"); + v.push_back("'" + Strings::Escape(e.rule_value) + "'"); + v.push_back("'" + Strings::Escape(e.notes) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - rule_values_entry.ruleset_id = results.LastInsertedID(); - return rule_values_entry; + e.ruleset_id = results.LastInsertedID(); + return e; } - rule_values_entry = NewEntity(); + e = NewEntity(); - return rule_values_entry; + return e; } static int InsertMany( Database& db, - std::vector rule_values_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &rule_values_entry: rule_values_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(rule_values_entry.ruleset_id)); - insert_values.push_back("'" + EscapeString(rule_values_entry.rule_name) + "'"); - insert_values.push_back("'" + EscapeString(rule_values_entry.rule_value) + "'"); - insert_values.push_back("'" + EscapeString(rule_values_entry.notes) + "'"); + v.push_back(std::to_string(e.ruleset_id)); + v.push_back("'" + Strings::Escape(e.rule_name) + "'"); + v.push_back("'" + Strings::Escape(e.rule_value) + "'"); + v.push_back("'" + Strings::Escape(e.notes) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RuleValues entry{}; + RuleValues e{}; - entry.ruleset_id = atoi(row[0]); - entry.rule_name = row[1] ? row[1] : ""; - entry.rule_value = row[2] ? row[2] : ""; - entry.notes = row[3] ? row[3] : ""; + e.ruleset_id = static_cast(strtoul(row[0], nullptr, 10)); + e.rule_name = row[1] ? row[1] : ""; + e.rule_value = row[2] ? row[2] : ""; + e.notes = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - RuleValues entry{}; + RuleValues e{}; - entry.ruleset_id = atoi(row[0]); - entry.rule_name = row[1] ? row[1] : ""; - entry.rule_value = row[2] ? row[2] : ""; - entry.notes = row[3] ? row[3] : ""; + e.ruleset_id = static_cast(strtoul(row[0], nullptr, 10)); + e.rule_name = row[1] ? row[1] : ""; + e.rule_value = row[2] ? row[2] : ""; + e.notes = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_RULE_VALUES_REPOSITORY_H diff --git a/common/repositories/base/base_saylink_repository.h b/common/repositories/base/base_saylink_repository.h index fac19e49e..5e35da29c 100644 --- a/common/repositories/base/base_saylink_repository.h +++ b/common/repositories/base/base_saylink_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_SAYLINK_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSaylinkRepository { public: struct Saylink { - int id; + int32_t id; std::string phrase; }; @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static Saylink NewEntity() { - Saylink entry{}; + Saylink e{}; - entry.id = 0; - entry.phrase = ""; + e.id = 0; + e.phrase = ""; - return entry; + return e; } - static Saylink GetSaylinkEntry( + static Saylink GetSaylink( const std::vector &saylinks, int saylink_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Saylink entry{}; + Saylink e{}; - entry.id = atoi(row[0]); - entry.phrase = row[1] ? row[1] : ""; + e.id = static_cast(atoi(row[0])); + e.phrase = row[1] ? row[1] : ""; - return entry; + return e; } return NewEntity(); @@ -146,22 +146,22 @@ public: static int UpdateOne( Database& db, - Saylink saylink_entry + const Saylink &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(saylink_entry.phrase) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.phrase) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - saylink_entry.id + e.id ) ); @@ -170,55 +170,55 @@ public: static Saylink InsertOne( Database& db, - Saylink saylink_entry + Saylink e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(saylink_entry.id)); - insert_values.push_back("'" + EscapeString(saylink_entry.phrase) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.phrase) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - saylink_entry.id = results.LastInsertedID(); - return saylink_entry; + e.id = results.LastInsertedID(); + return e; } - saylink_entry = NewEntity(); + e = NewEntity(); - return saylink_entry; + return e; } static int InsertMany( Database& db, - std::vector saylink_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &saylink_entry: saylink_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(saylink_entry.id)); - insert_values.push_back("'" + EscapeString(saylink_entry.phrase) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.phrase) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -239,18 +239,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Saylink entry{}; + Saylink e{}; - entry.id = atoi(row[0]); - entry.phrase = row[1] ? row[1] : ""; + e.id = static_cast(atoi(row[0])); + e.phrase = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -265,18 +265,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Saylink entry{}; + Saylink e{}; - entry.id = atoi(row[0]); - entry.phrase = row[1] ? row[1] : ""; + e.id = static_cast(atoi(row[0])); + e.phrase = row[1] ? row[1] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -301,6 +301,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SAYLINK_REPOSITORY_H diff --git a/common/repositories/base/base_server_scheduled_events_repository.h b/common/repositories/base/base_server_scheduled_events_repository.h index c47794b47..a1e32b40e 100644 --- a/common/repositories/base/base_server_scheduled_events_repository.h +++ b/common/repositories/base/base_server_scheduled_events_repository.h @@ -13,26 +13,26 @@ #define EQEMU_BASE_SERVER_SCHEDULED_EVENTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseServerScheduledEventsRepository { public: struct ServerScheduledEvents { - int id; + int32_t id; std::string description; std::string event_type; std::string event_data; - int minute_start; - int hour_start; - int day_start; - int month_start; - int year_start; - int minute_end; - int hour_end; - int day_end; - int month_end; - int year_end; + int32_t minute_start; + int32_t hour_start; + int32_t day_start; + int32_t month_start; + int32_t year_start; + int32_t minute_end; + int32_t hour_end; + int32_t day_end; + int32_t month_end; + int32_t year_end; std::string cron_expression; time_t created_at; time_t deleted_at; @@ -91,12 +91,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -124,30 +124,30 @@ public: static ServerScheduledEvents NewEntity() { - ServerScheduledEvents entry{}; + ServerScheduledEvents e{}; - entry.id = 0; - entry.description = ""; - entry.event_type = ""; - entry.event_data = ""; - entry.minute_start = 0; - entry.hour_start = 0; - entry.day_start = 0; - entry.month_start = 0; - entry.year_start = 0; - entry.minute_end = 0; - entry.hour_end = 0; - entry.day_end = 0; - entry.month_end = 0; - entry.year_end = 0; - entry.cron_expression = ""; - entry.created_at = 0; - entry.deleted_at = 0; + e.id = 0; + e.description = ""; + e.event_type = ""; + e.event_data = ""; + e.minute_start = 0; + e.hour_start = 0; + e.day_start = 0; + e.month_start = 0; + e.year_start = 0; + e.minute_end = 0; + e.hour_end = 0; + e.day_end = 0; + e.month_end = 0; + e.year_end = 0; + e.cron_expression = ""; + e.created_at = 0; + e.deleted_at = 0; - return entry; + return e; } - static ServerScheduledEvents GetServerScheduledEventsEntry( + static ServerScheduledEvents GetServerScheduledEvents( const std::vector &server_scheduled_eventss, int server_scheduled_events_id ) @@ -176,27 +176,27 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - ServerScheduledEvents entry{}; + ServerScheduledEvents e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; - entry.event_type = row[2] ? row[2] : ""; - entry.event_data = row[3] ? row[3] : ""; - entry.minute_start = atoi(row[4]); - entry.hour_start = atoi(row[5]); - entry.day_start = atoi(row[6]); - entry.month_start = atoi(row[7]); - entry.year_start = atoi(row[8]); - entry.minute_end = atoi(row[9]); - entry.hour_end = atoi(row[10]); - entry.day_end = atoi(row[11]); - entry.month_end = atoi(row[12]); - entry.year_end = atoi(row[13]); - entry.cron_expression = row[14] ? row[14] : ""; - entry.created_at = strtoll(row[15] ? row[15] : "-1", nullptr, 10); - entry.deleted_at = strtoll(row[16] ? row[16] : "-1", nullptr, 10); + e.id = static_cast(atoi(row[0])); + e.description = row[1] ? row[1] : ""; + e.event_type = row[2] ? row[2] : ""; + e.event_data = row[3] ? row[3] : ""; + e.minute_start = static_cast(atoi(row[4])); + e.hour_start = static_cast(atoi(row[5])); + e.day_start = static_cast(atoi(row[6])); + e.month_start = static_cast(atoi(row[7])); + e.year_start = static_cast(atoi(row[8])); + e.minute_end = static_cast(atoi(row[9])); + e.hour_end = static_cast(atoi(row[10])); + e.day_end = static_cast(atoi(row[11])); + e.month_end = static_cast(atoi(row[12])); + e.year_end = static_cast(atoi(row[13])); + e.cron_expression = row[14] ? row[14] : ""; + e.created_at = strtoll(row[15] ? row[15] : "-1", nullptr, 10); + e.deleted_at = strtoll(row[16] ? row[16] : "-1", nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -221,37 +221,37 @@ public: static int UpdateOne( Database& db, - ServerScheduledEvents server_scheduled_events_entry + const ServerScheduledEvents &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(server_scheduled_events_entry.description) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(server_scheduled_events_entry.event_type) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(server_scheduled_events_entry.event_data) + "'"); - update_values.push_back(columns[4] + " = " + std::to_string(server_scheduled_events_entry.minute_start)); - update_values.push_back(columns[5] + " = " + std::to_string(server_scheduled_events_entry.hour_start)); - update_values.push_back(columns[6] + " = " + std::to_string(server_scheduled_events_entry.day_start)); - update_values.push_back(columns[7] + " = " + std::to_string(server_scheduled_events_entry.month_start)); - update_values.push_back(columns[8] + " = " + std::to_string(server_scheduled_events_entry.year_start)); - update_values.push_back(columns[9] + " = " + std::to_string(server_scheduled_events_entry.minute_end)); - update_values.push_back(columns[10] + " = " + std::to_string(server_scheduled_events_entry.hour_end)); - update_values.push_back(columns[11] + " = " + std::to_string(server_scheduled_events_entry.day_end)); - update_values.push_back(columns[12] + " = " + std::to_string(server_scheduled_events_entry.month_end)); - update_values.push_back(columns[13] + " = " + std::to_string(server_scheduled_events_entry.year_end)); - update_values.push_back(columns[14] + " = '" + EscapeString(server_scheduled_events_entry.cron_expression) + "'"); - update_values.push_back(columns[15] + " = FROM_UNIXTIME(" + (server_scheduled_events_entry.created_at > 0 ? std::to_string(server_scheduled_events_entry.created_at) : "null") + ")"); - update_values.push_back(columns[16] + " = FROM_UNIXTIME(" + (server_scheduled_events_entry.deleted_at > 0 ? std::to_string(server_scheduled_events_entry.deleted_at) : "null") + ")"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.description) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.event_type) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.event_data) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.minute_start)); + v.push_back(columns[5] + " = " + std::to_string(e.hour_start)); + v.push_back(columns[6] + " = " + std::to_string(e.day_start)); + v.push_back(columns[7] + " = " + std::to_string(e.month_start)); + v.push_back(columns[8] + " = " + std::to_string(e.year_start)); + v.push_back(columns[9] + " = " + std::to_string(e.minute_end)); + v.push_back(columns[10] + " = " + std::to_string(e.hour_end)); + v.push_back(columns[11] + " = " + std::to_string(e.day_end)); + v.push_back(columns[12] + " = " + std::to_string(e.month_end)); + v.push_back(columns[13] + " = " + std::to_string(e.year_end)); + v.push_back(columns[14] + " = '" + Strings::Escape(e.cron_expression) + "'"); + v.push_back(columns[15] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[16] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - server_scheduled_events_entry.id + e.id ) ); @@ -260,85 +260,85 @@ public: static ServerScheduledEvents InsertOne( Database& db, - ServerScheduledEvents server_scheduled_events_entry + ServerScheduledEvents e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(server_scheduled_events_entry.id)); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.description) + "'"); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.event_type) + "'"); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.event_data) + "'"); - insert_values.push_back(std::to_string(server_scheduled_events_entry.minute_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.hour_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.day_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.month_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.year_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.minute_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.hour_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.day_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.month_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.year_end)); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.cron_expression) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (server_scheduled_events_entry.created_at > 0 ? std::to_string(server_scheduled_events_entry.created_at) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (server_scheduled_events_entry.deleted_at > 0 ? std::to_string(server_scheduled_events_entry.deleted_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back("'" + Strings::Escape(e.event_type) + "'"); + v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.minute_start)); + v.push_back(std::to_string(e.hour_start)); + v.push_back(std::to_string(e.day_start)); + v.push_back(std::to_string(e.month_start)); + v.push_back(std::to_string(e.year_start)); + v.push_back(std::to_string(e.minute_end)); + v.push_back(std::to_string(e.hour_end)); + v.push_back(std::to_string(e.day_end)); + v.push_back(std::to_string(e.month_end)); + v.push_back(std::to_string(e.year_end)); + v.push_back("'" + Strings::Escape(e.cron_expression) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - server_scheduled_events_entry.id = results.LastInsertedID(); - return server_scheduled_events_entry; + e.id = results.LastInsertedID(); + return e; } - server_scheduled_events_entry = NewEntity(); + e = NewEntity(); - return server_scheduled_events_entry; + return e; } static int InsertMany( Database& db, - std::vector server_scheduled_events_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &server_scheduled_events_entry: server_scheduled_events_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(server_scheduled_events_entry.id)); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.description) + "'"); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.event_type) + "'"); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.event_data) + "'"); - insert_values.push_back(std::to_string(server_scheduled_events_entry.minute_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.hour_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.day_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.month_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.year_start)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.minute_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.hour_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.day_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.month_end)); - insert_values.push_back(std::to_string(server_scheduled_events_entry.year_end)); - insert_values.push_back("'" + EscapeString(server_scheduled_events_entry.cron_expression) + "'"); - insert_values.push_back("FROM_UNIXTIME(" + (server_scheduled_events_entry.created_at > 0 ? std::to_string(server_scheduled_events_entry.created_at) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (server_scheduled_events_entry.deleted_at > 0 ? std::to_string(server_scheduled_events_entry.deleted_at) : "null") + ")"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back("'" + Strings::Escape(e.event_type) + "'"); + v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.minute_start)); + v.push_back(std::to_string(e.hour_start)); + v.push_back(std::to_string(e.day_start)); + v.push_back(std::to_string(e.month_start)); + v.push_back(std::to_string(e.year_start)); + v.push_back(std::to_string(e.minute_end)); + v.push_back(std::to_string(e.hour_end)); + v.push_back(std::to_string(e.day_end)); + v.push_back(std::to_string(e.month_end)); + v.push_back(std::to_string(e.year_end)); + v.push_back("'" + Strings::Escape(e.cron_expression) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -359,33 +359,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ServerScheduledEvents entry{}; + ServerScheduledEvents e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; - entry.event_type = row[2] ? row[2] : ""; - entry.event_data = row[3] ? row[3] : ""; - entry.minute_start = atoi(row[4]); - entry.hour_start = atoi(row[5]); - entry.day_start = atoi(row[6]); - entry.month_start = atoi(row[7]); - entry.year_start = atoi(row[8]); - entry.minute_end = atoi(row[9]); - entry.hour_end = atoi(row[10]); - entry.day_end = atoi(row[11]); - entry.month_end = atoi(row[12]); - entry.year_end = atoi(row[13]); - entry.cron_expression = row[14] ? row[14] : ""; - entry.created_at = strtoll(row[15] ? row[15] : "-1", nullptr, 10); - entry.deleted_at = strtoll(row[16] ? row[16] : "-1", nullptr, 10); + e.id = static_cast(atoi(row[0])); + e.description = row[1] ? row[1] : ""; + e.event_type = row[2] ? row[2] : ""; + e.event_data = row[3] ? row[3] : ""; + e.minute_start = static_cast(atoi(row[4])); + e.hour_start = static_cast(atoi(row[5])); + e.day_start = static_cast(atoi(row[6])); + e.month_start = static_cast(atoi(row[7])); + e.year_start = static_cast(atoi(row[8])); + e.minute_end = static_cast(atoi(row[9])); + e.hour_end = static_cast(atoi(row[10])); + e.day_end = static_cast(atoi(row[11])); + e.month_end = static_cast(atoi(row[12])); + e.year_end = static_cast(atoi(row[13])); + e.cron_expression = row[14] ? row[14] : ""; + e.created_at = strtoll(row[15] ? row[15] : "-1", nullptr, 10); + e.deleted_at = strtoll(row[16] ? row[16] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -400,33 +400,33 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ServerScheduledEvents entry{}; + ServerScheduledEvents e{}; - entry.id = atoi(row[0]); - entry.description = row[1] ? row[1] : ""; - entry.event_type = row[2] ? row[2] : ""; - entry.event_data = row[3] ? row[3] : ""; - entry.minute_start = atoi(row[4]); - entry.hour_start = atoi(row[5]); - entry.day_start = atoi(row[6]); - entry.month_start = atoi(row[7]); - entry.year_start = atoi(row[8]); - entry.minute_end = atoi(row[9]); - entry.hour_end = atoi(row[10]); - entry.day_end = atoi(row[11]); - entry.month_end = atoi(row[12]); - entry.year_end = atoi(row[13]); - entry.cron_expression = row[14] ? row[14] : ""; - entry.created_at = strtoll(row[15] ? row[15] : "-1", nullptr, 10); - entry.deleted_at = strtoll(row[16] ? row[16] : "-1", nullptr, 10); + e.id = static_cast(atoi(row[0])); + e.description = row[1] ? row[1] : ""; + e.event_type = row[2] ? row[2] : ""; + e.event_data = row[3] ? row[3] : ""; + e.minute_start = static_cast(atoi(row[4])); + e.hour_start = static_cast(atoi(row[5])); + e.day_start = static_cast(atoi(row[6])); + e.month_start = static_cast(atoi(row[7])); + e.year_start = static_cast(atoi(row[8])); + e.minute_end = static_cast(atoi(row[9])); + e.hour_end = static_cast(atoi(row[10])); + e.day_end = static_cast(atoi(row[11])); + e.month_end = static_cast(atoi(row[12])); + e.year_end = static_cast(atoi(row[13])); + e.cron_expression = row[14] ? row[14] : ""; + e.created_at = strtoll(row[15] ? row[15] : "-1", nullptr, 10); + e.deleted_at = strtoll(row[16] ? row[16] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -451,6 +451,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SERVER_SCHEDULED_EVENTS_REPOSITORY_H diff --git a/common/repositories/base/base_shared_task_activity_state_repository.h b/common/repositories/base/base_shared_task_activity_state_repository.h index e599f3cb7..fb6b56531 100644 --- a/common/repositories/base/base_shared_task_activity_state_repository.h +++ b/common/repositories/base/base_shared_task_activity_state_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSharedTaskActivityStateRepository { public: struct SharedTaskActivityState { - int64 shared_task_id; - int activity_id; - int done_count; - time_t updated_time; - time_t completed_time; + int64_t shared_task_id; + int32_t activity_id; + int32_t done_count; + time_t updated_time; + time_t completed_time; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static SharedTaskActivityState NewEntity() { - SharedTaskActivityState entry{}; + SharedTaskActivityState e{}; - entry.shared_task_id = 0; - entry.activity_id = 0; - entry.done_count = 0; - entry.updated_time = 0; - entry.completed_time = 0; + e.shared_task_id = 0; + e.activity_id = 0; + e.done_count = 0; + e.updated_time = 0; + e.completed_time = 0; - return entry; + return e; } - static SharedTaskActivityState GetSharedTaskActivityStateEntry( + static SharedTaskActivityState GetSharedTaskActivityState( const std::vector &shared_task_activity_states, int shared_task_activity_state_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SharedTaskActivityState entry{}; + SharedTaskActivityState e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.activity_id = atoi(row[1]); - entry.done_count = atoi(row[2]); - entry.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.activity_id = static_cast(atoi(row[1])); + e.done_count = static_cast(atoi(row[2])); + e.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - SharedTaskActivityState shared_task_activity_state_entry + const SharedTaskActivityState &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(shared_task_activity_state_entry.shared_task_id)); - update_values.push_back(columns[1] + " = " + std::to_string(shared_task_activity_state_entry.activity_id)); - update_values.push_back(columns[2] + " = " + std::to_string(shared_task_activity_state_entry.done_count)); - update_values.push_back(columns[3] + " = FROM_UNIXTIME(" + (shared_task_activity_state_entry.updated_time > 0 ? std::to_string(shared_task_activity_state_entry.updated_time) : "null") + ")"); - update_values.push_back(columns[4] + " = FROM_UNIXTIME(" + (shared_task_activity_state_entry.completed_time > 0 ? std::to_string(shared_task_activity_state_entry.completed_time) : "null") + ")"); + v.push_back(columns[0] + " = " + std::to_string(e.shared_task_id)); + v.push_back(columns[1] + " = " + std::to_string(e.activity_id)); + v.push_back(columns[2] + " = " + std::to_string(e.done_count)); + v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.updated_time > 0 ? std::to_string(e.updated_time) : "null") + ")"); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.completed_time > 0 ? std::to_string(e.completed_time) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - shared_task_activity_state_entry.shared_task_id + e.shared_task_id ) ); @@ -189,61 +189,61 @@ public: static SharedTaskActivityState InsertOne( Database& db, - SharedTaskActivityState shared_task_activity_state_entry + SharedTaskActivityState e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(shared_task_activity_state_entry.shared_task_id)); - insert_values.push_back(std::to_string(shared_task_activity_state_entry.activity_id)); - insert_values.push_back(std::to_string(shared_task_activity_state_entry.done_count)); - insert_values.push_back("FROM_UNIXTIME(" + (shared_task_activity_state_entry.updated_time > 0 ? std::to_string(shared_task_activity_state_entry.updated_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (shared_task_activity_state_entry.completed_time > 0 ? std::to_string(shared_task_activity_state_entry.completed_time) : "null") + ")"); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.activity_id)); + v.push_back(std::to_string(e.done_count)); + v.push_back("FROM_UNIXTIME(" + (e.updated_time > 0 ? std::to_string(e.updated_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completed_time > 0 ? std::to_string(e.completed_time) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - shared_task_activity_state_entry.shared_task_id = results.LastInsertedID(); - return shared_task_activity_state_entry; + e.shared_task_id = results.LastInsertedID(); + return e; } - shared_task_activity_state_entry = NewEntity(); + e = NewEntity(); - return shared_task_activity_state_entry; + return e; } static int InsertMany( Database& db, - std::vector shared_task_activity_state_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &shared_task_activity_state_entry: shared_task_activity_state_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(shared_task_activity_state_entry.shared_task_id)); - insert_values.push_back(std::to_string(shared_task_activity_state_entry.activity_id)); - insert_values.push_back(std::to_string(shared_task_activity_state_entry.done_count)); - insert_values.push_back("FROM_UNIXTIME(" + (shared_task_activity_state_entry.updated_time > 0 ? std::to_string(shared_task_activity_state_entry.updated_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (shared_task_activity_state_entry.completed_time > 0 ? std::to_string(shared_task_activity_state_entry.completed_time) : "null") + ")"); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.activity_id)); + v.push_back(std::to_string(e.done_count)); + v.push_back("FROM_UNIXTIME(" + (e.updated_time > 0 ? std::to_string(e.updated_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completed_time > 0 ? std::to_string(e.completed_time) : "null") + ")"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTaskActivityState entry{}; + SharedTaskActivityState e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.activity_id = atoi(row[1]); - entry.done_count = atoi(row[2]); - entry.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.activity_id = static_cast(atoi(row[1])); + e.done_count = static_cast(atoi(row[2])); + e.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTaskActivityState entry{}; + SharedTaskActivityState e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.activity_id = atoi(row[1]); - entry.done_count = atoi(row[2]); - entry.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.activity_id = static_cast(atoi(row[1])); + e.done_count = static_cast(atoi(row[2])); + e.updated_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completed_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H diff --git a/common/repositories/base/base_shared_task_dynamic_zones_repository.h b/common/repositories/base/base_shared_task_dynamic_zones_repository.h index 021e398cc..2bf92d75a 100644 --- a/common/repositories/base/base_shared_task_dynamic_zones_repository.h +++ b/common/repositories/base/base_shared_task_dynamic_zones_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSharedTaskDynamicZonesRepository { public: struct SharedTaskDynamicZones { - int64 shared_task_id; - int dynamic_zone_id; + int64_t shared_task_id; + uint32_t dynamic_zone_id; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static SharedTaskDynamicZones NewEntity() { - SharedTaskDynamicZones entry{}; + SharedTaskDynamicZones e{}; - entry.shared_task_id = 0; - entry.dynamic_zone_id = 0; + e.shared_task_id = 0; + e.dynamic_zone_id = 0; - return entry; + return e; } - static SharedTaskDynamicZones GetSharedTaskDynamicZonesEntry( + static SharedTaskDynamicZones GetSharedTaskDynamicZones( const std::vector &shared_task_dynamic_zoness, int shared_task_dynamic_zones_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SharedTaskDynamicZones entry{}; + SharedTaskDynamicZones e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.dynamic_zone_id = atoi(row[1]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - SharedTaskDynamicZones shared_task_dynamic_zones_entry + const SharedTaskDynamicZones &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(shared_task_dynamic_zones_entry.shared_task_id)); - update_values.push_back(columns[1] + " = " + std::to_string(shared_task_dynamic_zones_entry.dynamic_zone_id)); + v.push_back(columns[0] + " = " + std::to_string(e.shared_task_id)); + v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - shared_task_dynamic_zones_entry.shared_task_id + e.shared_task_id ) ); @@ -171,55 +171,55 @@ public: static SharedTaskDynamicZones InsertOne( Database& db, - SharedTaskDynamicZones shared_task_dynamic_zones_entry + SharedTaskDynamicZones e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(shared_task_dynamic_zones_entry.shared_task_id)); - insert_values.push_back(std::to_string(shared_task_dynamic_zones_entry.dynamic_zone_id)); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.dynamic_zone_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - shared_task_dynamic_zones_entry.shared_task_id = results.LastInsertedID(); - return shared_task_dynamic_zones_entry; + e.shared_task_id = results.LastInsertedID(); + return e; } - shared_task_dynamic_zones_entry = NewEntity(); + e = NewEntity(); - return shared_task_dynamic_zones_entry; + return e; } static int InsertMany( Database& db, - std::vector shared_task_dynamic_zones_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &shared_task_dynamic_zones_entry: shared_task_dynamic_zones_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(shared_task_dynamic_zones_entry.shared_task_id)); - insert_values.push_back(std::to_string(shared_task_dynamic_zones_entry.dynamic_zone_id)); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.dynamic_zone_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTaskDynamicZones entry{}; + SharedTaskDynamicZones e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.dynamic_zone_id = atoi(row[1]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTaskDynamicZones entry{}; + SharedTaskDynamicZones e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.dynamic_zone_id = atoi(row[1]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.dynamic_zone_id = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H diff --git a/common/repositories/base/base_shared_task_members_repository.h b/common/repositories/base/base_shared_task_members_repository.h index 0ab005888..b26e42c66 100644 --- a/common/repositories/base/base_shared_task_members_repository.h +++ b/common/repositories/base/base_shared_task_members_repository.h @@ -13,15 +13,15 @@ #define EQEMU_BASE_SHARED_TASK_MEMBERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSharedTaskMembersRepository { public: struct SharedTaskMembers { - int64 shared_task_id; - int64 character_id; - int is_leader; + int64_t shared_task_id; + int64_t character_id; + int8_t is_leader; }; static std::string PrimaryKey() @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static SharedTaskMembers NewEntity() { - SharedTaskMembers entry{}; + SharedTaskMembers e{}; - entry.shared_task_id = 0; - entry.character_id = 0; - entry.is_leader = 0; + e.shared_task_id = 0; + e.character_id = 0; + e.is_leader = 0; - return entry; + return e; } - static SharedTaskMembers GetSharedTaskMembersEntry( + static SharedTaskMembers GetSharedTaskMembers( const std::vector &shared_task_memberss, int shared_task_members_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SharedTaskMembers entry{}; + SharedTaskMembers e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.character_id = strtoll(row[1], nullptr, 10); - entry.is_leader = atoi(row[2]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.character_id = strtoll(row[1], nullptr, 10); + e.is_leader = static_cast(atoi(row[2])); - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - SharedTaskMembers shared_task_members_entry + const SharedTaskMembers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(shared_task_members_entry.shared_task_id)); - update_values.push_back(columns[1] + " = " + std::to_string(shared_task_members_entry.character_id)); - update_values.push_back(columns[2] + " = " + std::to_string(shared_task_members_entry.is_leader)); + v.push_back(columns[0] + " = " + std::to_string(e.shared_task_id)); + v.push_back(columns[1] + " = " + std::to_string(e.character_id)); + v.push_back(columns[2] + " = " + std::to_string(e.is_leader)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - shared_task_members_entry.shared_task_id + e.shared_task_id ) ); @@ -177,57 +177,57 @@ public: static SharedTaskMembers InsertOne( Database& db, - SharedTaskMembers shared_task_members_entry + SharedTaskMembers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(shared_task_members_entry.shared_task_id)); - insert_values.push_back(std::to_string(shared_task_members_entry.character_id)); - insert_values.push_back(std::to_string(shared_task_members_entry.is_leader)); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.is_leader)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - shared_task_members_entry.shared_task_id = results.LastInsertedID(); - return shared_task_members_entry; + e.shared_task_id = results.LastInsertedID(); + return e; } - shared_task_members_entry = NewEntity(); + e = NewEntity(); - return shared_task_members_entry; + return e; } static int InsertMany( Database& db, - std::vector shared_task_members_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &shared_task_members_entry: shared_task_members_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(shared_task_members_entry.shared_task_id)); - insert_values.push_back(std::to_string(shared_task_members_entry.character_id)); - insert_values.push_back(std::to_string(shared_task_members_entry.is_leader)); + v.push_back(std::to_string(e.shared_task_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.is_leader)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTaskMembers entry{}; + SharedTaskMembers e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.character_id = strtoll(row[1], nullptr, 10); - entry.is_leader = atoi(row[2]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.character_id = strtoll(row[1], nullptr, 10); + e.is_leader = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTaskMembers entry{}; + SharedTaskMembers e{}; - entry.shared_task_id = strtoll(row[0], nullptr, 10); - entry.character_id = strtoll(row[1], nullptr, 10); - entry.is_leader = atoi(row[2]); + e.shared_task_id = strtoll(row[0], nullptr, 10); + e.character_id = strtoll(row[1], nullptr, 10); + e.is_leader = static_cast(atoi(row[2])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SHARED_TASK_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_shared_tasks_repository.h b/common/repositories/base/base_shared_tasks_repository.h index 405bf09ed..82fee3608 100644 --- a/common/repositories/base/base_shared_tasks_repository.h +++ b/common/repositories/base/base_shared_tasks_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_SHARED_TASKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSharedTasksRepository { public: struct SharedTasks { - int64 id; - int task_id; - time_t accepted_time; - time_t expire_time; - time_t completion_time; - int is_locked; + int64_t id; + int32_t task_id; + time_t accepted_time; + time_t expire_time; + time_t completion_time; + int8_t is_locked; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static SharedTasks NewEntity() { - SharedTasks entry{}; + SharedTasks e{}; - entry.id = 0; - entry.task_id = 0; - entry.accepted_time = 0; - entry.expire_time = 0; - entry.completion_time = 0; - entry.is_locked = 0; + e.id = 0; + e.task_id = 0; + e.accepted_time = 0; + e.expire_time = 0; + e.completion_time = 0; + e.is_locked = 0; - return entry; + return e; } - static SharedTasks GetSharedTasksEntry( + static SharedTasks GetSharedTasks( const std::vector &shared_taskss, int shared_tasks_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SharedTasks entry{}; + SharedTasks e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.task_id = atoi(row[1]); - entry.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.is_locked = atoi(row[5]); + e.id = strtoll(row[0], nullptr, 10); + e.task_id = static_cast(atoi(row[1])); + e.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.is_locked = static_cast(atoi(row[5])); - return entry; + return e; } return NewEntity(); @@ -166,26 +166,26 @@ public: static int UpdateOne( Database& db, - SharedTasks shared_tasks_entry + const SharedTasks &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(shared_tasks_entry.task_id)); - update_values.push_back(columns[2] + " = FROM_UNIXTIME(" + (shared_tasks_entry.accepted_time > 0 ? std::to_string(shared_tasks_entry.accepted_time) : "null") + ")"); - update_values.push_back(columns[3] + " = FROM_UNIXTIME(" + (shared_tasks_entry.expire_time > 0 ? std::to_string(shared_tasks_entry.expire_time) : "null") + ")"); - update_values.push_back(columns[4] + " = FROM_UNIXTIME(" + (shared_tasks_entry.completion_time > 0 ? std::to_string(shared_tasks_entry.completion_time) : "null") + ")"); - update_values.push_back(columns[5] + " = " + std::to_string(shared_tasks_entry.is_locked)); + v.push_back(columns[1] + " = " + std::to_string(e.task_id)); + v.push_back(columns[2] + " = FROM_UNIXTIME(" + (e.accepted_time > 0 ? std::to_string(e.accepted_time) : "null") + ")"); + v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.completion_time > 0 ? std::to_string(e.completion_time) : "null") + ")"); + v.push_back(columns[5] + " = " + std::to_string(e.is_locked)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - shared_tasks_entry.id + e.id ) ); @@ -194,63 +194,63 @@ public: static SharedTasks InsertOne( Database& db, - SharedTasks shared_tasks_entry + SharedTasks e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(shared_tasks_entry.id)); - insert_values.push_back(std::to_string(shared_tasks_entry.task_id)); - insert_values.push_back("FROM_UNIXTIME(" + (shared_tasks_entry.accepted_time > 0 ? std::to_string(shared_tasks_entry.accepted_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (shared_tasks_entry.expire_time > 0 ? std::to_string(shared_tasks_entry.expire_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (shared_tasks_entry.completion_time > 0 ? std::to_string(shared_tasks_entry.completion_time) : "null") + ")"); - insert_values.push_back(std::to_string(shared_tasks_entry.is_locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.task_id)); + v.push_back("FROM_UNIXTIME(" + (e.accepted_time > 0 ? std::to_string(e.accepted_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completion_time > 0 ? std::to_string(e.completion_time) : "null") + ")"); + v.push_back(std::to_string(e.is_locked)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - shared_tasks_entry.id = results.LastInsertedID(); - return shared_tasks_entry; + e.id = results.LastInsertedID(); + return e; } - shared_tasks_entry = NewEntity(); + e = NewEntity(); - return shared_tasks_entry; + return e; } static int InsertMany( Database& db, - std::vector shared_tasks_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &shared_tasks_entry: shared_tasks_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(shared_tasks_entry.id)); - insert_values.push_back(std::to_string(shared_tasks_entry.task_id)); - insert_values.push_back("FROM_UNIXTIME(" + (shared_tasks_entry.accepted_time > 0 ? std::to_string(shared_tasks_entry.accepted_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (shared_tasks_entry.expire_time > 0 ? std::to_string(shared_tasks_entry.expire_time) : "null") + ")"); - insert_values.push_back("FROM_UNIXTIME(" + (shared_tasks_entry.completion_time > 0 ? std::to_string(shared_tasks_entry.completion_time) : "null") + ")"); - insert_values.push_back(std::to_string(shared_tasks_entry.is_locked)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.task_id)); + v.push_back("FROM_UNIXTIME(" + (e.accepted_time > 0 ? std::to_string(e.accepted_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); + v.push_back("FROM_UNIXTIME(" + (e.completion_time > 0 ? std::to_string(e.completion_time) : "null") + ")"); + v.push_back(std::to_string(e.is_locked)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -271,22 +271,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTasks entry{}; + SharedTasks e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.task_id = atoi(row[1]); - entry.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.is_locked = atoi(row[5]); + e.id = strtoll(row[0], nullptr, 10); + e.task_id = static_cast(atoi(row[1])); + e.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.is_locked = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -301,22 +301,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SharedTasks entry{}; + SharedTasks e{}; - entry.id = strtoll(row[0], nullptr, 10); - entry.task_id = atoi(row[1]); - entry.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); - entry.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); - entry.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); - entry.is_locked = atoi(row[5]); + e.id = strtoll(row[0], nullptr, 10); + e.task_id = static_cast(atoi(row[1])); + e.accepted_time = strtoll(row[2] ? row[2] : "-1", nullptr, 10); + e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); + e.completion_time = strtoll(row[4] ? row[4] : "-1", nullptr, 10); + e.is_locked = static_cast(atoi(row[5])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -341,6 +341,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SHARED_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_skill_caps_repository.h b/common/repositories/base/base_skill_caps_repository.h index 5e8efdfad..c1dc1c24f 100644 --- a/common/repositories/base/base_skill_caps_repository.h +++ b/common/repositories/base/base_skill_caps_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_SKILL_CAPS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSkillCapsRepository { public: struct SkillCaps { - int skillID; - int class_; - int level; - int cap; - int class_; + uint8_t skillID; + uint8_t class_; + uint8_t level; + uint32_t cap; + uint8_t class_; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static SkillCaps NewEntity() { - SkillCaps entry{}; + SkillCaps e{}; - entry.skillID = 0; - entry.class_ = 0; - entry.level = 0; - entry.cap = 0; - entry.class_ = 0; + e.skillID = 0; + e.class_ = 0; + e.level = 0; + e.cap = 0; + e.class_ = 0; - return entry; + return e; } - static SkillCaps GetSkillCapsEntry( + static SkillCaps GetSkillCaps( const std::vector &skill_capss, int skill_caps_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SkillCaps entry{}; + SkillCaps e{}; - entry.skillID = atoi(row[0]); - entry.class_ = atoi(row[1]); - entry.level = atoi(row[2]); - entry.cap = atoi(row[3]); - entry.class_ = atoi(row[4]); + e.skillID = static_cast(strtoul(row[0], nullptr, 10)); + e.class_ = static_cast(strtoul(row[1], nullptr, 10)); + e.level = static_cast(strtoul(row[2], nullptr, 10)); + e.cap = static_cast(strtoul(row[3], nullptr, 10)); + e.class_ = static_cast(strtoul(row[4], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - SkillCaps skill_caps_entry + const SkillCaps &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(skill_caps_entry.skillID)); - update_values.push_back(columns[1] + " = " + std::to_string(skill_caps_entry.class_)); - update_values.push_back(columns[2] + " = " + std::to_string(skill_caps_entry.level)); - update_values.push_back(columns[3] + " = " + std::to_string(skill_caps_entry.cap)); - update_values.push_back(columns[4] + " = " + std::to_string(skill_caps_entry.class_)); + v.push_back(columns[0] + " = " + std::to_string(e.skillID)); + v.push_back(columns[1] + " = " + std::to_string(e.class_)); + v.push_back(columns[2] + " = " + std::to_string(e.level)); + v.push_back(columns[3] + " = " + std::to_string(e.cap)); + v.push_back(columns[4] + " = " + std::to_string(e.class_)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - skill_caps_entry.skillID + e.skillID ) ); @@ -189,61 +189,61 @@ public: static SkillCaps InsertOne( Database& db, - SkillCaps skill_caps_entry + SkillCaps e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(skill_caps_entry.skillID)); - insert_values.push_back(std::to_string(skill_caps_entry.class_)); - insert_values.push_back(std::to_string(skill_caps_entry.level)); - insert_values.push_back(std::to_string(skill_caps_entry.cap)); - insert_values.push_back(std::to_string(skill_caps_entry.class_)); + v.push_back(std::to_string(e.skillID)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.cap)); + v.push_back(std::to_string(e.class_)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - skill_caps_entry.skillID = results.LastInsertedID(); - return skill_caps_entry; + e.skillID = results.LastInsertedID(); + return e; } - skill_caps_entry = NewEntity(); + e = NewEntity(); - return skill_caps_entry; + return e; } static int InsertMany( Database& db, - std::vector skill_caps_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &skill_caps_entry: skill_caps_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(skill_caps_entry.skillID)); - insert_values.push_back(std::to_string(skill_caps_entry.class_)); - insert_values.push_back(std::to_string(skill_caps_entry.level)); - insert_values.push_back(std::to_string(skill_caps_entry.cap)); - insert_values.push_back(std::to_string(skill_caps_entry.class_)); + v.push_back(std::to_string(e.skillID)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.cap)); + v.push_back(std::to_string(e.class_)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SkillCaps entry{}; + SkillCaps e{}; - entry.skillID = atoi(row[0]); - entry.class_ = atoi(row[1]); - entry.level = atoi(row[2]); - entry.cap = atoi(row[3]); - entry.class_ = atoi(row[4]); + e.skillID = static_cast(strtoul(row[0], nullptr, 10)); + e.class_ = static_cast(strtoul(row[1], nullptr, 10)); + e.level = static_cast(strtoul(row[2], nullptr, 10)); + e.cap = static_cast(strtoul(row[3], nullptr, 10)); + e.class_ = static_cast(strtoul(row[4], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SkillCaps entry{}; + SkillCaps e{}; - entry.skillID = atoi(row[0]); - entry.class_ = atoi(row[1]); - entry.level = atoi(row[2]); - entry.cap = atoi(row[3]); - entry.class_ = atoi(row[4]); + e.skillID = static_cast(strtoul(row[0], nullptr, 10)); + e.class_ = static_cast(strtoul(row[1], nullptr, 10)); + e.level = static_cast(strtoul(row[2], nullptr, 10)); + e.cap = static_cast(strtoul(row[3], nullptr, 10)); + e.class_ = static_cast(strtoul(row[4], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SKILL_CAPS_REPOSITORY_H diff --git a/common/repositories/base/base_spawn2_repository.h b/common/repositories/base/base_spawn2_repository.h index f771c12fe..bcfc8f0c9 100644 --- a/common/repositories/base/base_spawn2_repository.h +++ b/common/repositories/base/base_spawn2_repository.h @@ -13,30 +13,30 @@ #define EQEMU_BASE_SPAWN2_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpawn2Repository { public: struct Spawn2 { - int id; - int spawngroupID; + int32_t id; + int32_t spawngroupID; std::string zone; - int version; + int16_t version; float x; float y; float z; float heading; - int respawntime; - int variance; - int pathgrid; - int path_when_zone_idle; - int _condition; - int cond_value; - int enabled; - int animation; - int min_expansion; - int max_expansion; + int32_t respawntime; + int32_t variance; + int32_t pathgrid; + int8_t path_when_zone_idle; + uint32_t _condition; + int32_t cond_value; + uint8_t enabled; + uint8_t animation; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -100,12 +100,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -133,33 +133,33 @@ public: static Spawn2 NewEntity() { - Spawn2 entry{}; + Spawn2 e{}; - entry.id = 0; - entry.spawngroupID = 0; - entry.zone = ""; - entry.version = 0; - entry.x = 0.000000; - entry.y = 0.000000; - entry.z = 0.000000; - entry.heading = 0.000000; - entry.respawntime = 0; - entry.variance = 0; - entry.pathgrid = 0; - entry.path_when_zone_idle = 0; - entry._condition = 0; - entry.cond_value = 1; - entry.enabled = 1; - entry.animation = 0; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.spawngroupID = 0; + e.zone = ""; + e.version = 0; + e.x = 0.000000; + e.y = 0.000000; + e.z = 0.000000; + e.heading = 0.000000; + e.respawntime = 0; + e.variance = 0; + e.pathgrid = 0; + e.path_when_zone_idle = 0; + e._condition = 0; + e.cond_value = 1; + e.enabled = 1; + e.animation = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Spawn2 GetSpawn2Entry( + static Spawn2 GetSpawn2( const std::vector &spawn2s, int spawn2_id ) @@ -188,30 +188,30 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Spawn2 entry{}; + Spawn2 e{}; - entry.id = atoi(row[0]); - entry.spawngroupID = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.version = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); - entry.respawntime = atoi(row[8]); - entry.variance = atoi(row[9]); - entry.pathgrid = atoi(row[10]); - entry.path_when_zone_idle = atoi(row[11]); - entry._condition = atoi(row[12]); - entry.cond_value = atoi(row[13]); - entry.enabled = atoi(row[14]); - entry.animation = atoi(row[15]); - entry.min_expansion = atoi(row[16]); - entry.max_expansion = atoi(row[17]); - entry.content_flags = row[18] ? row[18] : ""; - entry.content_flags_disabled = row[19] ? row[19] : ""; + e.id = static_cast(atoi(row[0])); + e.spawngroupID = static_cast(atoi(row[1])); + e.zone = row[2] ? row[2] : ""; + e.version = static_cast(atoi(row[3])); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); + e.respawntime = static_cast(atoi(row[8])); + e.variance = static_cast(atoi(row[9])); + e.pathgrid = static_cast(atoi(row[10])); + e.path_when_zone_idle = static_cast(atoi(row[11])); + e._condition = static_cast(strtoul(row[12], nullptr, 10)); + e.cond_value = static_cast(atoi(row[13])); + e.enabled = static_cast(strtoul(row[14], nullptr, 10)); + e.animation = static_cast(strtoul(row[15], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[16])); + e.max_expansion = static_cast(atoi(row[17])); + e.content_flags = row[18] ? row[18] : ""; + e.content_flags_disabled = row[19] ? row[19] : ""; - return entry; + return e; } return NewEntity(); @@ -236,40 +236,40 @@ public: static int UpdateOne( Database& db, - Spawn2 spawn2_entry + const Spawn2 &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(spawn2_entry.spawngroupID)); - update_values.push_back(columns[2] + " = '" + EscapeString(spawn2_entry.zone) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(spawn2_entry.version)); - update_values.push_back(columns[4] + " = " + std::to_string(spawn2_entry.x)); - update_values.push_back(columns[5] + " = " + std::to_string(spawn2_entry.y)); - update_values.push_back(columns[6] + " = " + std::to_string(spawn2_entry.z)); - update_values.push_back(columns[7] + " = " + std::to_string(spawn2_entry.heading)); - update_values.push_back(columns[8] + " = " + std::to_string(spawn2_entry.respawntime)); - update_values.push_back(columns[9] + " = " + std::to_string(spawn2_entry.variance)); - update_values.push_back(columns[10] + " = " + std::to_string(spawn2_entry.pathgrid)); - update_values.push_back(columns[11] + " = " + std::to_string(spawn2_entry.path_when_zone_idle)); - update_values.push_back(columns[12] + " = " + std::to_string(spawn2_entry._condition)); - update_values.push_back(columns[13] + " = " + std::to_string(spawn2_entry.cond_value)); - update_values.push_back(columns[14] + " = " + std::to_string(spawn2_entry.enabled)); - update_values.push_back(columns[15] + " = " + std::to_string(spawn2_entry.animation)); - update_values.push_back(columns[16] + " = " + std::to_string(spawn2_entry.min_expansion)); - update_values.push_back(columns[17] + " = " + std::to_string(spawn2_entry.max_expansion)); - update_values.push_back(columns[18] + " = '" + EscapeString(spawn2_entry.content_flags) + "'"); - update_values.push_back(columns[19] + " = '" + EscapeString(spawn2_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.spawngroupID)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.version)); + v.push_back(columns[4] + " = " + std::to_string(e.x)); + v.push_back(columns[5] + " = " + std::to_string(e.y)); + v.push_back(columns[6] + " = " + std::to_string(e.z)); + v.push_back(columns[7] + " = " + std::to_string(e.heading)); + v.push_back(columns[8] + " = " + std::to_string(e.respawntime)); + v.push_back(columns[9] + " = " + std::to_string(e.variance)); + v.push_back(columns[10] + " = " + std::to_string(e.pathgrid)); + v.push_back(columns[11] + " = " + std::to_string(e.path_when_zone_idle)); + v.push_back(columns[12] + " = " + std::to_string(e._condition)); + v.push_back(columns[13] + " = " + std::to_string(e.cond_value)); + v.push_back(columns[14] + " = " + std::to_string(e.enabled)); + v.push_back(columns[15] + " = " + std::to_string(e.animation)); + v.push_back(columns[16] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[17] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[18] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[19] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spawn2_entry.id + e.id ) ); @@ -278,91 +278,91 @@ public: static Spawn2 InsertOne( Database& db, - Spawn2 spawn2_entry + Spawn2 e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spawn2_entry.id)); - insert_values.push_back(std::to_string(spawn2_entry.spawngroupID)); - insert_values.push_back("'" + EscapeString(spawn2_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn2_entry.version)); - insert_values.push_back(std::to_string(spawn2_entry.x)); - insert_values.push_back(std::to_string(spawn2_entry.y)); - insert_values.push_back(std::to_string(spawn2_entry.z)); - insert_values.push_back(std::to_string(spawn2_entry.heading)); - insert_values.push_back(std::to_string(spawn2_entry.respawntime)); - insert_values.push_back(std::to_string(spawn2_entry.variance)); - insert_values.push_back(std::to_string(spawn2_entry.pathgrid)); - insert_values.push_back(std::to_string(spawn2_entry.path_when_zone_idle)); - insert_values.push_back(std::to_string(spawn2_entry._condition)); - insert_values.push_back(std::to_string(spawn2_entry.cond_value)); - insert_values.push_back(std::to_string(spawn2_entry.enabled)); - insert_values.push_back(std::to_string(spawn2_entry.animation)); - insert_values.push_back(std::to_string(spawn2_entry.min_expansion)); - insert_values.push_back(std::to_string(spawn2_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(spawn2_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(spawn2_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.spawngroupID)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.respawntime)); + v.push_back(std::to_string(e.variance)); + v.push_back(std::to_string(e.pathgrid)); + v.push_back(std::to_string(e.path_when_zone_idle)); + v.push_back(std::to_string(e._condition)); + v.push_back(std::to_string(e.cond_value)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.animation)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spawn2_entry.id = results.LastInsertedID(); - return spawn2_entry; + e.id = results.LastInsertedID(); + return e; } - spawn2_entry = NewEntity(); + e = NewEntity(); - return spawn2_entry; + return e; } static int InsertMany( Database& db, - std::vector spawn2_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spawn2_entry: spawn2_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spawn2_entry.id)); - insert_values.push_back(std::to_string(spawn2_entry.spawngroupID)); - insert_values.push_back("'" + EscapeString(spawn2_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn2_entry.version)); - insert_values.push_back(std::to_string(spawn2_entry.x)); - insert_values.push_back(std::to_string(spawn2_entry.y)); - insert_values.push_back(std::to_string(spawn2_entry.z)); - insert_values.push_back(std::to_string(spawn2_entry.heading)); - insert_values.push_back(std::to_string(spawn2_entry.respawntime)); - insert_values.push_back(std::to_string(spawn2_entry.variance)); - insert_values.push_back(std::to_string(spawn2_entry.pathgrid)); - insert_values.push_back(std::to_string(spawn2_entry.path_when_zone_idle)); - insert_values.push_back(std::to_string(spawn2_entry._condition)); - insert_values.push_back(std::to_string(spawn2_entry.cond_value)); - insert_values.push_back(std::to_string(spawn2_entry.enabled)); - insert_values.push_back(std::to_string(spawn2_entry.animation)); - insert_values.push_back(std::to_string(spawn2_entry.min_expansion)); - insert_values.push_back(std::to_string(spawn2_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(spawn2_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(spawn2_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.spawngroupID)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.respawntime)); + v.push_back(std::to_string(e.variance)); + v.push_back(std::to_string(e.pathgrid)); + v.push_back(std::to_string(e.path_when_zone_idle)); + v.push_back(std::to_string(e._condition)); + v.push_back(std::to_string(e.cond_value)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.animation)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -383,36 +383,36 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Spawn2 entry{}; + Spawn2 e{}; - entry.id = atoi(row[0]); - entry.spawngroupID = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.version = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); - entry.respawntime = atoi(row[8]); - entry.variance = atoi(row[9]); - entry.pathgrid = atoi(row[10]); - entry.path_when_zone_idle = atoi(row[11]); - entry._condition = atoi(row[12]); - entry.cond_value = atoi(row[13]); - entry.enabled = atoi(row[14]); - entry.animation = atoi(row[15]); - entry.min_expansion = atoi(row[16]); - entry.max_expansion = atoi(row[17]); - entry.content_flags = row[18] ? row[18] : ""; - entry.content_flags_disabled = row[19] ? row[19] : ""; + e.id = static_cast(atoi(row[0])); + e.spawngroupID = static_cast(atoi(row[1])); + e.zone = row[2] ? row[2] : ""; + e.version = static_cast(atoi(row[3])); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); + e.respawntime = static_cast(atoi(row[8])); + e.variance = static_cast(atoi(row[9])); + e.pathgrid = static_cast(atoi(row[10])); + e.path_when_zone_idle = static_cast(atoi(row[11])); + e._condition = static_cast(strtoul(row[12], nullptr, 10)); + e.cond_value = static_cast(atoi(row[13])); + e.enabled = static_cast(strtoul(row[14], nullptr, 10)); + e.animation = static_cast(strtoul(row[15], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[16])); + e.max_expansion = static_cast(atoi(row[17])); + e.content_flags = row[18] ? row[18] : ""; + e.content_flags_disabled = row[19] ? row[19] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -427,36 +427,36 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Spawn2 entry{}; + Spawn2 e{}; - entry.id = atoi(row[0]); - entry.spawngroupID = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.version = atoi(row[3]); - entry.x = static_cast(atof(row[4])); - entry.y = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); - entry.respawntime = atoi(row[8]); - entry.variance = atoi(row[9]); - entry.pathgrid = atoi(row[10]); - entry.path_when_zone_idle = atoi(row[11]); - entry._condition = atoi(row[12]); - entry.cond_value = atoi(row[13]); - entry.enabled = atoi(row[14]); - entry.animation = atoi(row[15]); - entry.min_expansion = atoi(row[16]); - entry.max_expansion = atoi(row[17]); - entry.content_flags = row[18] ? row[18] : ""; - entry.content_flags_disabled = row[19] ? row[19] : ""; + e.id = static_cast(atoi(row[0])); + e.spawngroupID = static_cast(atoi(row[1])); + e.zone = row[2] ? row[2] : ""; + e.version = static_cast(atoi(row[3])); + e.x = strtof(row[4], nullptr); + e.y = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); + e.respawntime = static_cast(atoi(row[8])); + e.variance = static_cast(atoi(row[9])); + e.pathgrid = static_cast(atoi(row[10])); + e.path_when_zone_idle = static_cast(atoi(row[11])); + e._condition = static_cast(strtoul(row[12], nullptr, 10)); + e.cond_value = static_cast(atoi(row[13])); + e.enabled = static_cast(strtoul(row[14], nullptr, 10)); + e.animation = static_cast(strtoul(row[15], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[16])); + e.max_expansion = static_cast(atoi(row[17])); + e.content_flags = row[18] ? row[18] : ""; + e.content_flags_disabled = row[19] ? row[19] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -481,6 +481,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPAWN2_REPOSITORY_H diff --git a/common/repositories/base/base_spawn_condition_values_repository.h b/common/repositories/base/base_spawn_condition_values_repository.h index b778c7fbb..450572b0e 100644 --- a/common/repositories/base/base_spawn_condition_values_repository.h +++ b/common/repositories/base/base_spawn_condition_values_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_SPAWN_CONDITION_VALUES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpawnConditionValuesRepository { public: struct SpawnConditionValues { - int id; - int value; + uint32_t id; + uint8_t value; std::string zone; - int instance_id; + uint32_t instance_id; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static SpawnConditionValues NewEntity() { - SpawnConditionValues entry{}; + SpawnConditionValues e{}; - entry.id = 0; - entry.value = 0; - entry.zone = ""; - entry.instance_id = 0; + e.id = 0; + e.value = 0; + e.zone = ""; + e.instance_id = 0; - return entry; + return e; } - static SpawnConditionValues GetSpawnConditionValuesEntry( + static SpawnConditionValues GetSpawnConditionValues( const std::vector &spawn_condition_valuess, int spawn_condition_values_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SpawnConditionValues entry{}; + SpawnConditionValues e{}; - entry.id = atoi(row[0]); - entry.value = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.instance_id = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.value = static_cast(strtoul(row[1], nullptr, 10)); + e.zone = row[2] ? row[2] : ""; + e.instance_id = static_cast(strtoul(row[3], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - SpawnConditionValues spawn_condition_values_entry + const SpawnConditionValues &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(spawn_condition_values_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(spawn_condition_values_entry.value)); - update_values.push_back(columns[2] + " = '" + EscapeString(spawn_condition_values_entry.zone) + "'"); - update_values.push_back(columns[3] + " = " + std::to_string(spawn_condition_values_entry.instance_id)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.value)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.instance_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spawn_condition_values_entry.id + e.id ) ); @@ -183,59 +183,59 @@ public: static SpawnConditionValues InsertOne( Database& db, - SpawnConditionValues spawn_condition_values_entry + SpawnConditionValues e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spawn_condition_values_entry.id)); - insert_values.push_back(std::to_string(spawn_condition_values_entry.value)); - insert_values.push_back("'" + EscapeString(spawn_condition_values_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn_condition_values_entry.instance_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.value)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.instance_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spawn_condition_values_entry.id = results.LastInsertedID(); - return spawn_condition_values_entry; + e.id = results.LastInsertedID(); + return e; } - spawn_condition_values_entry = NewEntity(); + e = NewEntity(); - return spawn_condition_values_entry; + return e; } static int InsertMany( Database& db, - std::vector spawn_condition_values_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spawn_condition_values_entry: spawn_condition_values_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spawn_condition_values_entry.id)); - insert_values.push_back(std::to_string(spawn_condition_values_entry.value)); - insert_values.push_back("'" + EscapeString(spawn_condition_values_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn_condition_values_entry.instance_id)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.value)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.instance_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpawnConditionValues entry{}; + SpawnConditionValues e{}; - entry.id = atoi(row[0]); - entry.value = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.instance_id = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.value = static_cast(strtoul(row[1], nullptr, 10)); + e.zone = row[2] ? row[2] : ""; + e.instance_id = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpawnConditionValues entry{}; + SpawnConditionValues e{}; - entry.id = atoi(row[0]); - entry.value = atoi(row[1]); - entry.zone = row[2] ? row[2] : ""; - entry.instance_id = atoi(row[3]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.value = static_cast(strtoul(row[1], nullptr, 10)); + e.zone = row[2] ? row[2] : ""; + e.instance_id = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPAWN_CONDITION_VALUES_REPOSITORY_H diff --git a/common/repositories/base/base_spawn_conditions_repository.h b/common/repositories/base/base_spawn_conditions_repository.h index 11a6cd6ea..54d7a0ae1 100644 --- a/common/repositories/base/base_spawn_conditions_repository.h +++ b/common/repositories/base/base_spawn_conditions_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_SPAWN_CONDITIONS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpawnConditionsRepository { public: struct SpawnConditions { std::string zone; - int id; - int value; - int onchange; + uint32_t id; + int32_t value; + uint8_t onchange; std::string name; }; @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static SpawnConditions NewEntity() { - SpawnConditions entry{}; + SpawnConditions e{}; - entry.zone = ""; - entry.id = 1; - entry.value = 0; - entry.onchange = 0; - entry.name = ""; + e.zone = ""; + e.id = 1; + e.value = 0; + e.onchange = 0; + e.name = ""; - return entry; + return e; } - static SpawnConditions GetSpawnConditionsEntry( + static SpawnConditions GetSpawnConditions( const std::vector &spawn_conditionss, int spawn_conditions_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SpawnConditions entry{}; + SpawnConditions e{}; - entry.zone = row[0] ? row[0] : ""; - entry.id = atoi(row[1]); - entry.value = atoi(row[2]); - entry.onchange = atoi(row[3]); - entry.name = row[4] ? row[4] : ""; + e.zone = row[0] ? row[0] : ""; + e.id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(atoi(row[2])); + e.onchange = static_cast(strtoul(row[3], nullptr, 10)); + e.name = row[4] ? row[4] : ""; - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - SpawnConditions spawn_conditions_entry + const SpawnConditions &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = '" + EscapeString(spawn_conditions_entry.zone) + "'"); - update_values.push_back(columns[1] + " = " + std::to_string(spawn_conditions_entry.id)); - update_values.push_back(columns[2] + " = " + std::to_string(spawn_conditions_entry.value)); - update_values.push_back(columns[3] + " = " + std::to_string(spawn_conditions_entry.onchange)); - update_values.push_back(columns[4] + " = '" + EscapeString(spawn_conditions_entry.name) + "'"); + v.push_back(columns[0] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.id)); + v.push_back(columns[2] + " = " + std::to_string(e.value)); + v.push_back(columns[3] + " = " + std::to_string(e.onchange)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spawn_conditions_entry.id + e.id ) ); @@ -189,61 +189,61 @@ public: static SpawnConditions InsertOne( Database& db, - SpawnConditions spawn_conditions_entry + SpawnConditions e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back("'" + EscapeString(spawn_conditions_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn_conditions_entry.id)); - insert_values.push_back(std::to_string(spawn_conditions_entry.value)); - insert_values.push_back(std::to_string(spawn_conditions_entry.onchange)); - insert_values.push_back("'" + EscapeString(spawn_conditions_entry.name) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.value)); + v.push_back(std::to_string(e.onchange)); + v.push_back("'" + Strings::Escape(e.name) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spawn_conditions_entry.id = results.LastInsertedID(); - return spawn_conditions_entry; + e.id = results.LastInsertedID(); + return e; } - spawn_conditions_entry = NewEntity(); + e = NewEntity(); - return spawn_conditions_entry; + return e; } static int InsertMany( Database& db, - std::vector spawn_conditions_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spawn_conditions_entry: spawn_conditions_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back("'" + EscapeString(spawn_conditions_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn_conditions_entry.id)); - insert_values.push_back(std::to_string(spawn_conditions_entry.value)); - insert_values.push_back(std::to_string(spawn_conditions_entry.onchange)); - insert_values.push_back("'" + EscapeString(spawn_conditions_entry.name) + "'"); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.value)); + v.push_back(std::to_string(e.onchange)); + v.push_back("'" + Strings::Escape(e.name) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpawnConditions entry{}; + SpawnConditions e{}; - entry.zone = row[0] ? row[0] : ""; - entry.id = atoi(row[1]); - entry.value = atoi(row[2]); - entry.onchange = atoi(row[3]); - entry.name = row[4] ? row[4] : ""; + e.zone = row[0] ? row[0] : ""; + e.id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(atoi(row[2])); + e.onchange = static_cast(strtoul(row[3], nullptr, 10)); + e.name = row[4] ? row[4] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpawnConditions entry{}; + SpawnConditions e{}; - entry.zone = row[0] ? row[0] : ""; - entry.id = atoi(row[1]); - entry.value = atoi(row[2]); - entry.onchange = atoi(row[3]); - entry.name = row[4] ? row[4] : ""; + e.zone = row[0] ? row[0] : ""; + e.id = static_cast(strtoul(row[1], nullptr, 10)); + e.value = static_cast(atoi(row[2])); + e.onchange = static_cast(strtoul(row[3], nullptr, 10)); + e.name = row[4] ? row[4] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPAWN_CONDITIONS_REPOSITORY_H diff --git a/common/repositories/base/base_spawn_events_repository.h b/common/repositories/base/base_spawn_events_repository.h index e20f07fa7..d894ba1f7 100644 --- a/common/repositories/base/base_spawn_events_repository.h +++ b/common/repositories/base/base_spawn_events_repository.h @@ -13,26 +13,26 @@ #define EQEMU_BASE_SPAWN_EVENTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpawnEventsRepository { public: struct SpawnEvents { - int id; + uint32_t id; std::string zone; - int cond_id; + uint32_t cond_id; std::string name; - int period; - int next_minute; - int next_hour; - int next_day; - int next_month; - int next_year; - int enabled; - int action; - int argument; - int strict; + uint32_t period; + uint8_t next_minute; + uint8_t next_hour; + uint8_t next_day; + uint8_t next_month; + uint32_t next_year; + int8_t enabled; + uint8_t action; + int32_t argument; + int8_t strict; }; static std::string PrimaryKey() @@ -82,12 +82,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -115,27 +115,27 @@ public: static SpawnEvents NewEntity() { - SpawnEvents entry{}; + SpawnEvents e{}; - entry.id = 0; - entry.zone = ""; - entry.cond_id = 0; - entry.name = ""; - entry.period = 0; - entry.next_minute = 0; - entry.next_hour = 0; - entry.next_day = 0; - entry.next_month = 0; - entry.next_year = 0; - entry.enabled = 1; - entry.action = 0; - entry.argument = 0; - entry.strict = 0; + e.id = 0; + e.zone = ""; + e.cond_id = 0; + e.name = ""; + e.period = 0; + e.next_minute = 0; + e.next_hour = 0; + e.next_day = 0; + e.next_month = 0; + e.next_year = 0; + e.enabled = 1; + e.action = 0; + e.argument = 0; + e.strict = 0; - return entry; + return e; } - static SpawnEvents GetSpawnEventsEntry( + static SpawnEvents GetSpawnEvents( const std::vector &spawn_eventss, int spawn_events_id ) @@ -164,24 +164,24 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SpawnEvents entry{}; + SpawnEvents e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.cond_id = atoi(row[2]); - entry.name = row[3] ? row[3] : ""; - entry.period = atoi(row[4]); - entry.next_minute = atoi(row[5]); - entry.next_hour = atoi(row[6]); - entry.next_day = atoi(row[7]); - entry.next_month = atoi(row[8]); - entry.next_year = atoi(row[9]); - entry.enabled = atoi(row[10]); - entry.action = atoi(row[11]); - entry.argument = atoi(row[12]); - entry.strict = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.cond_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.period = static_cast(strtoul(row[4], nullptr, 10)); + e.next_minute = static_cast(strtoul(row[5], nullptr, 10)); + e.next_hour = static_cast(strtoul(row[6], nullptr, 10)); + e.next_day = static_cast(strtoul(row[7], nullptr, 10)); + e.next_month = static_cast(strtoul(row[8], nullptr, 10)); + e.next_year = static_cast(strtoul(row[9], nullptr, 10)); + e.enabled = static_cast(atoi(row[10])); + e.action = static_cast(strtoul(row[11], nullptr, 10)); + e.argument = static_cast(atoi(row[12])); + e.strict = static_cast(atoi(row[13])); - return entry; + return e; } return NewEntity(); @@ -206,34 +206,34 @@ public: static int UpdateOne( Database& db, - SpawnEvents spawn_events_entry + const SpawnEvents &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(spawn_events_entry.zone) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(spawn_events_entry.cond_id)); - update_values.push_back(columns[3] + " = '" + EscapeString(spawn_events_entry.name) + "'"); - update_values.push_back(columns[4] + " = " + std::to_string(spawn_events_entry.period)); - update_values.push_back(columns[5] + " = " + std::to_string(spawn_events_entry.next_minute)); - update_values.push_back(columns[6] + " = " + std::to_string(spawn_events_entry.next_hour)); - update_values.push_back(columns[7] + " = " + std::to_string(spawn_events_entry.next_day)); - update_values.push_back(columns[8] + " = " + std::to_string(spawn_events_entry.next_month)); - update_values.push_back(columns[9] + " = " + std::to_string(spawn_events_entry.next_year)); - update_values.push_back(columns[10] + " = " + std::to_string(spawn_events_entry.enabled)); - update_values.push_back(columns[11] + " = " + std::to_string(spawn_events_entry.action)); - update_values.push_back(columns[12] + " = " + std::to_string(spawn_events_entry.argument)); - update_values.push_back(columns[13] + " = " + std::to_string(spawn_events_entry.strict)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.cond_id)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.period)); + v.push_back(columns[5] + " = " + std::to_string(e.next_minute)); + v.push_back(columns[6] + " = " + std::to_string(e.next_hour)); + v.push_back(columns[7] + " = " + std::to_string(e.next_day)); + v.push_back(columns[8] + " = " + std::to_string(e.next_month)); + v.push_back(columns[9] + " = " + std::to_string(e.next_year)); + v.push_back(columns[10] + " = " + std::to_string(e.enabled)); + v.push_back(columns[11] + " = " + std::to_string(e.action)); + v.push_back(columns[12] + " = " + std::to_string(e.argument)); + v.push_back(columns[13] + " = " + std::to_string(e.strict)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spawn_events_entry.id + e.id ) ); @@ -242,79 +242,79 @@ public: static SpawnEvents InsertOne( Database& db, - SpawnEvents spawn_events_entry + SpawnEvents e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spawn_events_entry.id)); - insert_values.push_back("'" + EscapeString(spawn_events_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn_events_entry.cond_id)); - insert_values.push_back("'" + EscapeString(spawn_events_entry.name) + "'"); - insert_values.push_back(std::to_string(spawn_events_entry.period)); - insert_values.push_back(std::to_string(spawn_events_entry.next_minute)); - insert_values.push_back(std::to_string(spawn_events_entry.next_hour)); - insert_values.push_back(std::to_string(spawn_events_entry.next_day)); - insert_values.push_back(std::to_string(spawn_events_entry.next_month)); - insert_values.push_back(std::to_string(spawn_events_entry.next_year)); - insert_values.push_back(std::to_string(spawn_events_entry.enabled)); - insert_values.push_back(std::to_string(spawn_events_entry.action)); - insert_values.push_back(std::to_string(spawn_events_entry.argument)); - insert_values.push_back(std::to_string(spawn_events_entry.strict)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.cond_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.period)); + v.push_back(std::to_string(e.next_minute)); + v.push_back(std::to_string(e.next_hour)); + v.push_back(std::to_string(e.next_day)); + v.push_back(std::to_string(e.next_month)); + v.push_back(std::to_string(e.next_year)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.action)); + v.push_back(std::to_string(e.argument)); + v.push_back(std::to_string(e.strict)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spawn_events_entry.id = results.LastInsertedID(); - return spawn_events_entry; + e.id = results.LastInsertedID(); + return e; } - spawn_events_entry = NewEntity(); + e = NewEntity(); - return spawn_events_entry; + return e; } static int InsertMany( Database& db, - std::vector spawn_events_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spawn_events_entry: spawn_events_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spawn_events_entry.id)); - insert_values.push_back("'" + EscapeString(spawn_events_entry.zone) + "'"); - insert_values.push_back(std::to_string(spawn_events_entry.cond_id)); - insert_values.push_back("'" + EscapeString(spawn_events_entry.name) + "'"); - insert_values.push_back(std::to_string(spawn_events_entry.period)); - insert_values.push_back(std::to_string(spawn_events_entry.next_minute)); - insert_values.push_back(std::to_string(spawn_events_entry.next_hour)); - insert_values.push_back(std::to_string(spawn_events_entry.next_day)); - insert_values.push_back(std::to_string(spawn_events_entry.next_month)); - insert_values.push_back(std::to_string(spawn_events_entry.next_year)); - insert_values.push_back(std::to_string(spawn_events_entry.enabled)); - insert_values.push_back(std::to_string(spawn_events_entry.action)); - insert_values.push_back(std::to_string(spawn_events_entry.argument)); - insert_values.push_back(std::to_string(spawn_events_entry.strict)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.cond_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.period)); + v.push_back(std::to_string(e.next_minute)); + v.push_back(std::to_string(e.next_hour)); + v.push_back(std::to_string(e.next_day)); + v.push_back(std::to_string(e.next_month)); + v.push_back(std::to_string(e.next_year)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.action)); + v.push_back(std::to_string(e.argument)); + v.push_back(std::to_string(e.strict)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -335,30 +335,30 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpawnEvents entry{}; + SpawnEvents e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.cond_id = atoi(row[2]); - entry.name = row[3] ? row[3] : ""; - entry.period = atoi(row[4]); - entry.next_minute = atoi(row[5]); - entry.next_hour = atoi(row[6]); - entry.next_day = atoi(row[7]); - entry.next_month = atoi(row[8]); - entry.next_year = atoi(row[9]); - entry.enabled = atoi(row[10]); - entry.action = atoi(row[11]); - entry.argument = atoi(row[12]); - entry.strict = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.cond_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.period = static_cast(strtoul(row[4], nullptr, 10)); + e.next_minute = static_cast(strtoul(row[5], nullptr, 10)); + e.next_hour = static_cast(strtoul(row[6], nullptr, 10)); + e.next_day = static_cast(strtoul(row[7], nullptr, 10)); + e.next_month = static_cast(strtoul(row[8], nullptr, 10)); + e.next_year = static_cast(strtoul(row[9], nullptr, 10)); + e.enabled = static_cast(atoi(row[10])); + e.action = static_cast(strtoul(row[11], nullptr, 10)); + e.argument = static_cast(atoi(row[12])); + e.strict = static_cast(atoi(row[13])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -373,30 +373,30 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpawnEvents entry{}; + SpawnEvents e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.cond_id = atoi(row[2]); - entry.name = row[3] ? row[3] : ""; - entry.period = atoi(row[4]); - entry.next_minute = atoi(row[5]); - entry.next_hour = atoi(row[6]); - entry.next_day = atoi(row[7]); - entry.next_month = atoi(row[8]); - entry.next_year = atoi(row[9]); - entry.enabled = atoi(row[10]); - entry.action = atoi(row[11]); - entry.argument = atoi(row[12]); - entry.strict = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.zone = row[1] ? row[1] : ""; + e.cond_id = static_cast(strtoul(row[2], nullptr, 10)); + e.name = row[3] ? row[3] : ""; + e.period = static_cast(strtoul(row[4], nullptr, 10)); + e.next_minute = static_cast(strtoul(row[5], nullptr, 10)); + e.next_hour = static_cast(strtoul(row[6], nullptr, 10)); + e.next_day = static_cast(strtoul(row[7], nullptr, 10)); + e.next_month = static_cast(strtoul(row[8], nullptr, 10)); + e.next_year = static_cast(strtoul(row[9], nullptr, 10)); + e.enabled = static_cast(atoi(row[10])); + e.action = static_cast(strtoul(row[11], nullptr, 10)); + e.argument = static_cast(atoi(row[12])); + e.strict = static_cast(atoi(row[13])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -421,6 +421,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPAWN_EVENTS_REPOSITORY_H diff --git a/common/repositories/base/base_spawnentry_repository.h b/common/repositories/base/base_spawnentry_repository.h index e2500dae7..1632a4c79 100644 --- a/common/repositories/base/base_spawnentry_repository.h +++ b/common/repositories/base/base_spawnentry_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_SPAWNENTRY_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpawnentryRepository { public: struct Spawnentry { - int spawngroupID; - int npcID; - int chance; - int condition_value_filter; - int min_expansion; - int max_expansion; + int32_t spawngroupID; + int32_t npcID; + int16_t chance; + int32_t condition_value_filter; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -64,12 +64,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -97,21 +97,21 @@ public: static Spawnentry NewEntity() { - Spawnentry entry{}; + Spawnentry e{}; - entry.spawngroupID = 0; - entry.npcID = 0; - entry.chance = 0; - entry.condition_value_filter = 1; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.spawngroupID = 0; + e.npcID = 0; + e.chance = 0; + e.condition_value_filter = 1; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Spawnentry GetSpawnentryEntry( + static Spawnentry GetSpawnentry( const std::vector &spawnentrys, int spawnentry_id ) @@ -140,18 +140,18 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Spawnentry entry{}; + Spawnentry e{}; - entry.spawngroupID = atoi(row[0]); - entry.npcID = atoi(row[1]); - entry.chance = atoi(row[2]); - entry.condition_value_filter = atoi(row[3]); - entry.min_expansion = atoi(row[4]); - entry.max_expansion = atoi(row[5]); - entry.content_flags = row[6] ? row[6] : ""; - entry.content_flags_disabled = row[7] ? row[7] : ""; + e.spawngroupID = static_cast(atoi(row[0])); + e.npcID = static_cast(atoi(row[1])); + e.chance = static_cast(atoi(row[2])); + e.condition_value_filter = static_cast(atoi(row[3])); + e.min_expansion = static_cast(atoi(row[4])); + e.max_expansion = static_cast(atoi(row[5])); + e.content_flags = row[6] ? row[6] : ""; + e.content_flags_disabled = row[7] ? row[7] : ""; - return entry; + return e; } return NewEntity(); @@ -176,29 +176,29 @@ public: static int UpdateOne( Database& db, - Spawnentry spawnentry_entry + const Spawnentry &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(spawnentry_entry.spawngroupID)); - update_values.push_back(columns[1] + " = " + std::to_string(spawnentry_entry.npcID)); - update_values.push_back(columns[2] + " = " + std::to_string(spawnentry_entry.chance)); - update_values.push_back(columns[3] + " = " + std::to_string(spawnentry_entry.condition_value_filter)); - update_values.push_back(columns[4] + " = " + std::to_string(spawnentry_entry.min_expansion)); - update_values.push_back(columns[5] + " = " + std::to_string(spawnentry_entry.max_expansion)); - update_values.push_back(columns[6] + " = '" + EscapeString(spawnentry_entry.content_flags) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(spawnentry_entry.content_flags_disabled) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.spawngroupID)); + v.push_back(columns[1] + " = " + std::to_string(e.npcID)); + v.push_back(columns[2] + " = " + std::to_string(e.chance)); + v.push_back(columns[3] + " = " + std::to_string(e.condition_value_filter)); + v.push_back(columns[4] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[5] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spawnentry_entry.spawngroupID + e.spawngroupID ) ); @@ -207,67 +207,67 @@ public: static Spawnentry InsertOne( Database& db, - Spawnentry spawnentry_entry + Spawnentry e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spawnentry_entry.spawngroupID)); - insert_values.push_back(std::to_string(spawnentry_entry.npcID)); - insert_values.push_back(std::to_string(spawnentry_entry.chance)); - insert_values.push_back(std::to_string(spawnentry_entry.condition_value_filter)); - insert_values.push_back(std::to_string(spawnentry_entry.min_expansion)); - insert_values.push_back(std::to_string(spawnentry_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(spawnentry_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(spawnentry_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.spawngroupID)); + v.push_back(std::to_string(e.npcID)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.condition_value_filter)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spawnentry_entry.spawngroupID = results.LastInsertedID(); - return spawnentry_entry; + e.spawngroupID = results.LastInsertedID(); + return e; } - spawnentry_entry = NewEntity(); + e = NewEntity(); - return spawnentry_entry; + return e; } static int InsertMany( Database& db, - std::vector spawnentry_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spawnentry_entry: spawnentry_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spawnentry_entry.spawngroupID)); - insert_values.push_back(std::to_string(spawnentry_entry.npcID)); - insert_values.push_back(std::to_string(spawnentry_entry.chance)); - insert_values.push_back(std::to_string(spawnentry_entry.condition_value_filter)); - insert_values.push_back(std::to_string(spawnentry_entry.min_expansion)); - insert_values.push_back(std::to_string(spawnentry_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(spawnentry_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(spawnentry_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.spawngroupID)); + v.push_back(std::to_string(e.npcID)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.condition_value_filter)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -288,24 +288,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Spawnentry entry{}; + Spawnentry e{}; - entry.spawngroupID = atoi(row[0]); - entry.npcID = atoi(row[1]); - entry.chance = atoi(row[2]); - entry.condition_value_filter = atoi(row[3]); - entry.min_expansion = atoi(row[4]); - entry.max_expansion = atoi(row[5]); - entry.content_flags = row[6] ? row[6] : ""; - entry.content_flags_disabled = row[7] ? row[7] : ""; + e.spawngroupID = static_cast(atoi(row[0])); + e.npcID = static_cast(atoi(row[1])); + e.chance = static_cast(atoi(row[2])); + e.condition_value_filter = static_cast(atoi(row[3])); + e.min_expansion = static_cast(atoi(row[4])); + e.max_expansion = static_cast(atoi(row[5])); + e.content_flags = row[6] ? row[6] : ""; + e.content_flags_disabled = row[7] ? row[7] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -320,24 +320,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Spawnentry entry{}; + Spawnentry e{}; - entry.spawngroupID = atoi(row[0]); - entry.npcID = atoi(row[1]); - entry.chance = atoi(row[2]); - entry.condition_value_filter = atoi(row[3]); - entry.min_expansion = atoi(row[4]); - entry.max_expansion = atoi(row[5]); - entry.content_flags = row[6] ? row[6] : ""; - entry.content_flags_disabled = row[7] ? row[7] : ""; + e.spawngroupID = static_cast(atoi(row[0])); + e.npcID = static_cast(atoi(row[1])); + e.chance = static_cast(atoi(row[2])); + e.condition_value_filter = static_cast(atoi(row[3])); + e.min_expansion = static_cast(atoi(row[4])); + e.max_expansion = static_cast(atoi(row[5])); + e.content_flags = row[6] ? row[6] : ""; + e.content_flags_disabled = row[7] ? row[7] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -362,6 +362,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPAWNENTRY_REPOSITORY_H diff --git a/common/repositories/base/base_spawngroup_repository.h b/common/repositories/base/base_spawngroup_repository.h index 782c4c9df..16c1931b7 100644 --- a/common/repositories/base/base_spawngroup_repository.h +++ b/common/repositories/base/base_spawngroup_repository.h @@ -13,25 +13,25 @@ #define EQEMU_BASE_SPAWNGROUP_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpawngroupRepository { public: struct Spawngroup { - int id; + int32_t id; std::string name; - int spawn_limit; + int8_t spawn_limit; float dist; float max_x; float min_x; float max_y; float min_y; - int delay; - int mindelay; - int despawn; - int despawn_timer; - int wp_spawns; + int32_t delay; + int32_t mindelay; + int8_t despawn; + int32_t despawn_timer; + uint8_t wp_spawns; }; static std::string PrimaryKey() @@ -79,12 +79,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -112,26 +112,26 @@ public: static Spawngroup NewEntity() { - Spawngroup entry{}; + Spawngroup e{}; - entry.id = 0; - entry.name = ""; - entry.spawn_limit = 0; - entry.dist = 0; - entry.max_x = 0; - entry.min_x = 0; - entry.max_y = 0; - entry.min_y = 0; - entry.delay = 45000; - entry.mindelay = 15000; - entry.despawn = 0; - entry.despawn_timer = 100; - entry.wp_spawns = 0; + e.id = 0; + e.name = ""; + e.spawn_limit = 0; + e.dist = 0; + e.max_x = 0; + e.min_x = 0; + e.max_y = 0; + e.min_y = 0; + e.delay = 45000; + e.mindelay = 15000; + e.despawn = 0; + e.despawn_timer = 100; + e.wp_spawns = 0; - return entry; + return e; } - static Spawngroup GetSpawngroupEntry( + static Spawngroup GetSpawngroup( const std::vector &spawngroups, int spawngroup_id ) @@ -160,23 +160,23 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Spawngroup entry{}; + Spawngroup e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.spawn_limit = atoi(row[2]); - entry.dist = static_cast(atof(row[3])); - entry.max_x = static_cast(atof(row[4])); - entry.min_x = static_cast(atof(row[5])); - entry.max_y = static_cast(atof(row[6])); - entry.min_y = static_cast(atof(row[7])); - entry.delay = atoi(row[8]); - entry.mindelay = atoi(row[9]); - entry.despawn = atoi(row[10]); - entry.despawn_timer = atoi(row[11]); - entry.wp_spawns = atoi(row[12]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.spawn_limit = static_cast(atoi(row[2])); + e.dist = strtof(row[3], nullptr); + e.max_x = strtof(row[4], nullptr); + e.min_x = strtof(row[5], nullptr); + e.max_y = strtof(row[6], nullptr); + e.min_y = strtof(row[7], nullptr); + e.delay = static_cast(atoi(row[8])); + e.mindelay = static_cast(atoi(row[9])); + e.despawn = static_cast(atoi(row[10])); + e.despawn_timer = static_cast(atoi(row[11])); + e.wp_spawns = static_cast(strtoul(row[12], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -201,33 +201,33 @@ public: static int UpdateOne( Database& db, - Spawngroup spawngroup_entry + const Spawngroup &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(spawngroup_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(spawngroup_entry.spawn_limit)); - update_values.push_back(columns[3] + " = " + std::to_string(spawngroup_entry.dist)); - update_values.push_back(columns[4] + " = " + std::to_string(spawngroup_entry.max_x)); - update_values.push_back(columns[5] + " = " + std::to_string(spawngroup_entry.min_x)); - update_values.push_back(columns[6] + " = " + std::to_string(spawngroup_entry.max_y)); - update_values.push_back(columns[7] + " = " + std::to_string(spawngroup_entry.min_y)); - update_values.push_back(columns[8] + " = " + std::to_string(spawngroup_entry.delay)); - update_values.push_back(columns[9] + " = " + std::to_string(spawngroup_entry.mindelay)); - update_values.push_back(columns[10] + " = " + std::to_string(spawngroup_entry.despawn)); - update_values.push_back(columns[11] + " = " + std::to_string(spawngroup_entry.despawn_timer)); - update_values.push_back(columns[12] + " = " + std::to_string(spawngroup_entry.wp_spawns)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.spawn_limit)); + v.push_back(columns[3] + " = " + std::to_string(e.dist)); + v.push_back(columns[4] + " = " + std::to_string(e.max_x)); + v.push_back(columns[5] + " = " + std::to_string(e.min_x)); + v.push_back(columns[6] + " = " + std::to_string(e.max_y)); + v.push_back(columns[7] + " = " + std::to_string(e.min_y)); + v.push_back(columns[8] + " = " + std::to_string(e.delay)); + v.push_back(columns[9] + " = " + std::to_string(e.mindelay)); + v.push_back(columns[10] + " = " + std::to_string(e.despawn)); + v.push_back(columns[11] + " = " + std::to_string(e.despawn_timer)); + v.push_back(columns[12] + " = " + std::to_string(e.wp_spawns)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spawngroup_entry.id + e.id ) ); @@ -236,77 +236,77 @@ public: static Spawngroup InsertOne( Database& db, - Spawngroup spawngroup_entry + Spawngroup e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spawngroup_entry.id)); - insert_values.push_back("'" + EscapeString(spawngroup_entry.name) + "'"); - insert_values.push_back(std::to_string(spawngroup_entry.spawn_limit)); - insert_values.push_back(std::to_string(spawngroup_entry.dist)); - insert_values.push_back(std::to_string(spawngroup_entry.max_x)); - insert_values.push_back(std::to_string(spawngroup_entry.min_x)); - insert_values.push_back(std::to_string(spawngroup_entry.max_y)); - insert_values.push_back(std::to_string(spawngroup_entry.min_y)); - insert_values.push_back(std::to_string(spawngroup_entry.delay)); - insert_values.push_back(std::to_string(spawngroup_entry.mindelay)); - insert_values.push_back(std::to_string(spawngroup_entry.despawn)); - insert_values.push_back(std::to_string(spawngroup_entry.despawn_timer)); - insert_values.push_back(std::to_string(spawngroup_entry.wp_spawns)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.spawn_limit)); + v.push_back(std::to_string(e.dist)); + v.push_back(std::to_string(e.max_x)); + v.push_back(std::to_string(e.min_x)); + v.push_back(std::to_string(e.max_y)); + v.push_back(std::to_string(e.min_y)); + v.push_back(std::to_string(e.delay)); + v.push_back(std::to_string(e.mindelay)); + v.push_back(std::to_string(e.despawn)); + v.push_back(std::to_string(e.despawn_timer)); + v.push_back(std::to_string(e.wp_spawns)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spawngroup_entry.id = results.LastInsertedID(); - return spawngroup_entry; + e.id = results.LastInsertedID(); + return e; } - spawngroup_entry = NewEntity(); + e = NewEntity(); - return spawngroup_entry; + return e; } static int InsertMany( Database& db, - std::vector spawngroup_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spawngroup_entry: spawngroup_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spawngroup_entry.id)); - insert_values.push_back("'" + EscapeString(spawngroup_entry.name) + "'"); - insert_values.push_back(std::to_string(spawngroup_entry.spawn_limit)); - insert_values.push_back(std::to_string(spawngroup_entry.dist)); - insert_values.push_back(std::to_string(spawngroup_entry.max_x)); - insert_values.push_back(std::to_string(spawngroup_entry.min_x)); - insert_values.push_back(std::to_string(spawngroup_entry.max_y)); - insert_values.push_back(std::to_string(spawngroup_entry.min_y)); - insert_values.push_back(std::to_string(spawngroup_entry.delay)); - insert_values.push_back(std::to_string(spawngroup_entry.mindelay)); - insert_values.push_back(std::to_string(spawngroup_entry.despawn)); - insert_values.push_back(std::to_string(spawngroup_entry.despawn_timer)); - insert_values.push_back(std::to_string(spawngroup_entry.wp_spawns)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.spawn_limit)); + v.push_back(std::to_string(e.dist)); + v.push_back(std::to_string(e.max_x)); + v.push_back(std::to_string(e.min_x)); + v.push_back(std::to_string(e.max_y)); + v.push_back(std::to_string(e.min_y)); + v.push_back(std::to_string(e.delay)); + v.push_back(std::to_string(e.mindelay)); + v.push_back(std::to_string(e.despawn)); + v.push_back(std::to_string(e.despawn_timer)); + v.push_back(std::to_string(e.wp_spawns)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -327,29 +327,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Spawngroup entry{}; + Spawngroup e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.spawn_limit = atoi(row[2]); - entry.dist = static_cast(atof(row[3])); - entry.max_x = static_cast(atof(row[4])); - entry.min_x = static_cast(atof(row[5])); - entry.max_y = static_cast(atof(row[6])); - entry.min_y = static_cast(atof(row[7])); - entry.delay = atoi(row[8]); - entry.mindelay = atoi(row[9]); - entry.despawn = atoi(row[10]); - entry.despawn_timer = atoi(row[11]); - entry.wp_spawns = atoi(row[12]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.spawn_limit = static_cast(atoi(row[2])); + e.dist = strtof(row[3], nullptr); + e.max_x = strtof(row[4], nullptr); + e.min_x = strtof(row[5], nullptr); + e.max_y = strtof(row[6], nullptr); + e.min_y = strtof(row[7], nullptr); + e.delay = static_cast(atoi(row[8])); + e.mindelay = static_cast(atoi(row[9])); + e.despawn = static_cast(atoi(row[10])); + e.despawn_timer = static_cast(atoi(row[11])); + e.wp_spawns = static_cast(strtoul(row[12], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -364,29 +364,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Spawngroup entry{}; + Spawngroup e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.spawn_limit = atoi(row[2]); - entry.dist = static_cast(atof(row[3])); - entry.max_x = static_cast(atof(row[4])); - entry.min_x = static_cast(atof(row[5])); - entry.max_y = static_cast(atof(row[6])); - entry.min_y = static_cast(atof(row[7])); - entry.delay = atoi(row[8]); - entry.mindelay = atoi(row[9]); - entry.despawn = atoi(row[10]); - entry.despawn_timer = atoi(row[11]); - entry.wp_spawns = atoi(row[12]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.spawn_limit = static_cast(atoi(row[2])); + e.dist = strtof(row[3], nullptr); + e.max_x = strtof(row[4], nullptr); + e.min_x = strtof(row[5], nullptr); + e.max_y = strtof(row[6], nullptr); + e.min_y = strtof(row[7], nullptr); + e.delay = static_cast(atoi(row[8])); + e.mindelay = static_cast(atoi(row[9])); + e.despawn = static_cast(atoi(row[10])); + e.despawn_timer = static_cast(atoi(row[11])); + e.wp_spawns = static_cast(strtoul(row[12], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -411,6 +411,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPAWNGROUP_REPOSITORY_H diff --git a/common/repositories/base/base_spell_buckets_repository.h b/common/repositories/base/base_spell_buckets_repository.h index 69e5f3974..a9c78953a 100644 --- a/common/repositories/base/base_spell_buckets_repository.h +++ b/common/repositories/base/base_spell_buckets_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_SPELL_BUCKETS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpellBucketsRepository { public: struct SpellBuckets { - int64 spellid; + uint64_t spellid; std::string key; std::string value; }; @@ -49,12 +49,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -82,16 +82,16 @@ public: static SpellBuckets NewEntity() { - SpellBuckets entry{}; + SpellBuckets e{}; - entry.spellid = 0; - entry.key = ""; - entry.value = ""; + e.spellid = 0; + e.key = ""; + e.value = ""; - return entry; + return e; } - static SpellBuckets GetSpellBucketsEntry( + static SpellBuckets GetSpellBuckets( const std::vector &spell_bucketss, int spell_buckets_id ) @@ -120,13 +120,13 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SpellBuckets entry{}; + SpellBuckets e{}; - entry.spellid = strtoll(row[0], nullptr, 10); - entry.key = row[1] ? row[1] : ""; - entry.value = row[2] ? row[2] : ""; + e.spellid = strtoull(row[0], nullptr, 10); + e.key = row[1] ? row[1] : ""; + e.value = row[2] ? row[2] : ""; - return entry; + return e; } return NewEntity(); @@ -151,24 +151,24 @@ public: static int UpdateOne( Database& db, - SpellBuckets spell_buckets_entry + const SpellBuckets &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(spell_buckets_entry.spellid)); - update_values.push_back(columns[1] + " = '" + EscapeString(spell_buckets_entry.key) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(spell_buckets_entry.value) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.spellid)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.key) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spell_buckets_entry.spellid + e.spellid ) ); @@ -177,57 +177,57 @@ public: static SpellBuckets InsertOne( Database& db, - SpellBuckets spell_buckets_entry + SpellBuckets e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spell_buckets_entry.spellid)); - insert_values.push_back("'" + EscapeString(spell_buckets_entry.key) + "'"); - insert_values.push_back("'" + EscapeString(spell_buckets_entry.value) + "'"); + v.push_back(std::to_string(e.spellid)); + v.push_back("'" + Strings::Escape(e.key) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spell_buckets_entry.spellid = results.LastInsertedID(); - return spell_buckets_entry; + e.spellid = results.LastInsertedID(); + return e; } - spell_buckets_entry = NewEntity(); + e = NewEntity(); - return spell_buckets_entry; + return e; } static int InsertMany( Database& db, - std::vector spell_buckets_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spell_buckets_entry: spell_buckets_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spell_buckets_entry.spellid)); - insert_values.push_back("'" + EscapeString(spell_buckets_entry.key) + "'"); - insert_values.push_back("'" + EscapeString(spell_buckets_entry.value) + "'"); + v.push_back(std::to_string(e.spellid)); + v.push_back("'" + Strings::Escape(e.key) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -248,19 +248,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpellBuckets entry{}; + SpellBuckets e{}; - entry.spellid = strtoll(row[0], nullptr, 10); - entry.key = row[1] ? row[1] : ""; - entry.value = row[2] ? row[2] : ""; + e.spellid = strtoull(row[0], nullptr, 10); + e.key = row[1] ? row[1] : ""; + e.value = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -275,19 +275,19 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpellBuckets entry{}; + SpellBuckets e{}; - entry.spellid = strtoll(row[0], nullptr, 10); - entry.key = row[1] ? row[1] : ""; - entry.value = row[2] ? row[2] : ""; + e.spellid = strtoull(row[0], nullptr, 10); + e.key = row[1] ? row[1] : ""; + e.value = row[2] ? row[2] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -312,6 +312,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPELL_BUCKETS_REPOSITORY_H diff --git a/common/repositories/base/base_spell_globals_repository.h b/common/repositories/base/base_spell_globals_repository.h index 11323e9ce..a7a0541df 100644 --- a/common/repositories/base/base_spell_globals_repository.h +++ b/common/repositories/base/base_spell_globals_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_SPELL_GLOBALS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpellGlobalsRepository { public: struct SpellGlobals { - int spellid; + int32_t spellid; std::string spell_name; std::string qglobal; std::string value; @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static SpellGlobals NewEntity() { - SpellGlobals entry{}; + SpellGlobals e{}; - entry.spellid = 0; - entry.spell_name = ""; - entry.qglobal = ""; - entry.value = ""; + e.spellid = 0; + e.spell_name = ""; + e.qglobal = ""; + e.value = ""; - return entry; + return e; } - static SpellGlobals GetSpellGlobalsEntry( + static SpellGlobals GetSpellGlobals( const std::vector &spell_globalss, int spell_globals_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SpellGlobals entry{}; + SpellGlobals e{}; - entry.spellid = atoi(row[0]); - entry.spell_name = row[1] ? row[1] : ""; - entry.qglobal = row[2] ? row[2] : ""; - entry.value = row[3] ? row[3] : ""; + e.spellid = static_cast(atoi(row[0])); + e.spell_name = row[1] ? row[1] : ""; + e.qglobal = row[2] ? row[2] : ""; + e.value = row[3] ? row[3] : ""; - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - SpellGlobals spell_globals_entry + const SpellGlobals &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(spell_globals_entry.spellid)); - update_values.push_back(columns[1] + " = '" + EscapeString(spell_globals_entry.spell_name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(spell_globals_entry.qglobal) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(spell_globals_entry.value) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.spellid)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.spell_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.qglobal) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.value) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spell_globals_entry.spellid + e.spellid ) ); @@ -183,59 +183,59 @@ public: static SpellGlobals InsertOne( Database& db, - SpellGlobals spell_globals_entry + SpellGlobals e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spell_globals_entry.spellid)); - insert_values.push_back("'" + EscapeString(spell_globals_entry.spell_name) + "'"); - insert_values.push_back("'" + EscapeString(spell_globals_entry.qglobal) + "'"); - insert_values.push_back("'" + EscapeString(spell_globals_entry.value) + "'"); + v.push_back(std::to_string(e.spellid)); + v.push_back("'" + Strings::Escape(e.spell_name) + "'"); + v.push_back("'" + Strings::Escape(e.qglobal) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spell_globals_entry.spellid = results.LastInsertedID(); - return spell_globals_entry; + e.spellid = results.LastInsertedID(); + return e; } - spell_globals_entry = NewEntity(); + e = NewEntity(); - return spell_globals_entry; + return e; } static int InsertMany( Database& db, - std::vector spell_globals_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spell_globals_entry: spell_globals_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spell_globals_entry.spellid)); - insert_values.push_back("'" + EscapeString(spell_globals_entry.spell_name) + "'"); - insert_values.push_back("'" + EscapeString(spell_globals_entry.qglobal) + "'"); - insert_values.push_back("'" + EscapeString(spell_globals_entry.value) + "'"); + v.push_back(std::to_string(e.spellid)); + v.push_back("'" + Strings::Escape(e.spell_name) + "'"); + v.push_back("'" + Strings::Escape(e.qglobal) + "'"); + v.push_back("'" + Strings::Escape(e.value) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpellGlobals entry{}; + SpellGlobals e{}; - entry.spellid = atoi(row[0]); - entry.spell_name = row[1] ? row[1] : ""; - entry.qglobal = row[2] ? row[2] : ""; - entry.value = row[3] ? row[3] : ""; + e.spellid = static_cast(atoi(row[0])); + e.spell_name = row[1] ? row[1] : ""; + e.qglobal = row[2] ? row[2] : ""; + e.value = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpellGlobals entry{}; + SpellGlobals e{}; - entry.spellid = atoi(row[0]); - entry.spell_name = row[1] ? row[1] : ""; - entry.qglobal = row[2] ? row[2] : ""; - entry.value = row[3] ? row[3] : ""; + e.spellid = static_cast(atoi(row[0])); + e.spell_name = row[1] ? row[1] : ""; + e.qglobal = row[2] ? row[2] : ""; + e.value = row[3] ? row[3] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPELL_GLOBALS_REPOSITORY_H diff --git a/common/repositories/base/base_spells_new_repository.h b/common/repositories/base/base_spells_new_repository.h index 47b40ecba..1c61aab1f 100644 --- a/common/repositories/base/base_spells_new_repository.h +++ b/common/repositories/base/base_spells_new_repository.h @@ -13,13 +13,13 @@ #define EQEMU_BASE_SPELLS_NEW_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseSpellsNewRepository { public: struct SpellsNew { - int id; + int32_t id; std::string name; std::string player_1; std::string teleport_zone; @@ -28,234 +28,234 @@ public: std::string cast_on_you; std::string cast_on_other; std::string spell_fades; - int range; - int aoerange; - int pushback; - int pushup; - int cast_time; - int recovery_time; - int recast_time; - int buffdurationformula; - int buffduration; - int AEDuration; - int mana; - int effect_base_value1; - int effect_base_value2; - int effect_base_value3; - int effect_base_value4; - int effect_base_value5; - int effect_base_value6; - int effect_base_value7; - int effect_base_value8; - int effect_base_value9; - int effect_base_value10; - int effect_base_value11; - int effect_base_value12; - int effect_limit_value1; - int effect_limit_value2; - int effect_limit_value3; - int effect_limit_value4; - int effect_limit_value5; - int effect_limit_value6; - int effect_limit_value7; - int effect_limit_value8; - int effect_limit_value9; - int effect_limit_value10; - int effect_limit_value11; - int effect_limit_value12; - int max1; - int max2; - int max3; - int max4; - int max5; - int max6; - int max7; - int max8; - int max9; - int max10; - int max11; - int max12; - int icon; - int memicon; - int components1; - int components2; - int components3; - int components4; - int component_counts1; - int component_counts2; - int component_counts3; - int component_counts4; - int NoexpendReagent1; - int NoexpendReagent2; - int NoexpendReagent3; - int NoexpendReagent4; - int formula1; - int formula2; - int formula3; - int formula4; - int formula5; - int formula6; - int formula7; - int formula8; - int formula9; - int formula10; - int formula11; - int formula12; - int LightType; - int goodEffect; - int Activated; - int resisttype; - int effectid1; - int effectid2; - int effectid3; - int effectid4; - int effectid5; - int effectid6; - int effectid7; - int effectid8; - int effectid9; - int effectid10; - int effectid11; - int effectid12; - int targettype; - int basediff; - int skill; - int zonetype; - int EnvironmentType; - int TimeOfDay; - int classes1; - int classes2; - int classes3; - int classes4; - int classes5; - int classes6; - int classes7; - int classes8; - int classes9; - int classes10; - int classes11; - int classes12; - int classes13; - int classes14; - int classes15; - int classes16; - int CastingAnim; - int TargetAnim; - int TravelType; - int SpellAffectIndex; - int disallow_sit; - int deities0; - int deities1; - int deities2; - int deities3; - int deities4; - int deities5; - int deities6; - int deities7; - int deities8; - int deities9; - int deities10; - int deities11; - int deities12; - int deities13; - int deities14; - int deities15; - int deities16; - int field142; - int field143; - int new_icon; - int spellanim; - int uninterruptable; - int ResistDiff; - int dot_stacking_exempt; - int deleteable; - int RecourseLink; - int no_partial_resist; - int field152; - int field153; - int short_buff_box; - int descnum; - int typedescnum; - int effectdescnum; - int effectdescnum2; - int npc_no_los; - int field160; - int reflectable; - int bonushate; - int field163; - int field164; - int ldon_trap; - int EndurCost; - int EndurTimerIndex; - int IsDiscipline; - int field169; - int field170; - int field171; - int field172; - int HateAdded; - int EndurUpkeep; - int numhitstype; - int numhits; - int pvpresistbase; - int pvpresistcalc; - int pvpresistcap; - int spell_category; - int pvp_duration; - int pvp_duration_cap; - int pcnpc_only_flag; - int cast_not_standing; - int can_mgb; - int nodispell; - int npc_category; - int npc_usefulness; - int MinResist; - int MaxResist; - int viral_targets; - int viral_timer; - int nimbuseffect; - int ConeStartAngle; - int ConeStopAngle; - int sneaking; - int not_extendable; - int field198; - int field199; - int suspendable; - int viral_range; - int songcap; - int field203; - int field204; - int no_block; - int field206; - int spellgroup; - int rank; - int field209; - int field210; - int CastRestriction; - int allowrest; - int InCombat; - int OutofCombat; - int field215; - int field216; - int field217; - int aemaxtargets; - int maxtargets; - int field220; - int field221; - int field222; - int field223; - int persistdeath; - int field225; - int field226; + int32_t range; + int32_t aoerange; + int32_t pushback; + int32_t pushup; + int32_t cast_time; + int32_t recovery_time; + int32_t recast_time; + int32_t buffdurationformula; + int32_t buffduration; + int32_t AEDuration; + int32_t mana; + int32_t effect_base_value1; + int32_t effect_base_value2; + int32_t effect_base_value3; + int32_t effect_base_value4; + int32_t effect_base_value5; + int32_t effect_base_value6; + int32_t effect_base_value7; + int32_t effect_base_value8; + int32_t effect_base_value9; + int32_t effect_base_value10; + int32_t effect_base_value11; + int32_t effect_base_value12; + int32_t effect_limit_value1; + int32_t effect_limit_value2; + int32_t effect_limit_value3; + int32_t effect_limit_value4; + int32_t effect_limit_value5; + int32_t effect_limit_value6; + int32_t effect_limit_value7; + int32_t effect_limit_value8; + int32_t effect_limit_value9; + int32_t effect_limit_value10; + int32_t effect_limit_value11; + int32_t effect_limit_value12; + int32_t max1; + int32_t max2; + int32_t max3; + int32_t max4; + int32_t max5; + int32_t max6; + int32_t max7; + int32_t max8; + int32_t max9; + int32_t max10; + int32_t max11; + int32_t max12; + int32_t icon; + int32_t memicon; + int32_t components1; + int32_t components2; + int32_t components3; + int32_t components4; + int32_t component_counts1; + int32_t component_counts2; + int32_t component_counts3; + int32_t component_counts4; + int32_t NoexpendReagent1; + int32_t NoexpendReagent2; + int32_t NoexpendReagent3; + int32_t NoexpendReagent4; + int32_t formula1; + int32_t formula2; + int32_t formula3; + int32_t formula4; + int32_t formula5; + int32_t formula6; + int32_t formula7; + int32_t formula8; + int32_t formula9; + int32_t formula10; + int32_t formula11; + int32_t formula12; + int32_t LightType; + int32_t goodEffect; + int32_t Activated; + int32_t resisttype; + int32_t effectid1; + int32_t effectid2; + int32_t effectid3; + int32_t effectid4; + int32_t effectid5; + int32_t effectid6; + int32_t effectid7; + int32_t effectid8; + int32_t effectid9; + int32_t effectid10; + int32_t effectid11; + int32_t effectid12; + int32_t targettype; + int32_t basediff; + int32_t skill; + int32_t zonetype; + int32_t EnvironmentType; + int32_t TimeOfDay; + int32_t classes1; + int32_t classes2; + int32_t classes3; + int32_t classes4; + int32_t classes5; + int32_t classes6; + int32_t classes7; + int32_t classes8; + int32_t classes9; + int32_t classes10; + int32_t classes11; + int32_t classes12; + int32_t classes13; + int32_t classes14; + int32_t classes15; + int32_t classes16; + int32_t CastingAnim; + int32_t TargetAnim; + int32_t TravelType; + int32_t SpellAffectIndex; + int32_t disallow_sit; + int32_t deities0; + int32_t deities1; + int32_t deities2; + int32_t deities3; + int32_t deities4; + int32_t deities5; + int32_t deities6; + int32_t deities7; + int32_t deities8; + int32_t deities9; + int32_t deities10; + int32_t deities11; + int32_t deities12; + int32_t deities13; + int32_t deities14; + int32_t deities15; + int32_t deities16; + int32_t field142; + int32_t field143; + int32_t new_icon; + int32_t spellanim; + int32_t uninterruptable; + int32_t ResistDiff; + int32_t dot_stacking_exempt; + int32_t deleteable; + int32_t RecourseLink; + int32_t no_partial_resist; + int32_t field152; + int32_t field153; + int32_t short_buff_box; + int32_t descnum; + int32_t typedescnum; + int32_t effectdescnum; + int32_t effectdescnum2; + int32_t npc_no_los; + int32_t field160; + int32_t reflectable; + int32_t bonushate; + int32_t field163; + int32_t field164; + int32_t ldon_trap; + int32_t EndurCost; + int32_t EndurTimerIndex; + int32_t IsDiscipline; + int32_t field169; + int32_t field170; + int32_t field171; + int32_t field172; + int32_t HateAdded; + int32_t EndurUpkeep; + int32_t numhitstype; + int32_t numhits; + int32_t pvpresistbase; + int32_t pvpresistcalc; + int32_t pvpresistcap; + int32_t spell_category; + int32_t pvp_duration; + int32_t pvp_duration_cap; + int32_t pcnpc_only_flag; + int32_t cast_not_standing; + int32_t can_mgb; + int32_t nodispell; + int32_t npc_category; + int32_t npc_usefulness; + int32_t MinResist; + int32_t MaxResist; + int32_t viral_targets; + int32_t viral_timer; + int32_t nimbuseffect; + int32_t ConeStartAngle; + int32_t ConeStopAngle; + int32_t sneaking; + int32_t not_extendable; + int32_t field198; + int32_t field199; + int32_t suspendable; + int32_t viral_range; + int32_t songcap; + int32_t field203; + int32_t field204; + int32_t no_block; + int32_t field206; + int32_t spellgroup; + int32_t rank; + int32_t field209; + int32_t field210; + int32_t CastRestriction; + int32_t allowrest; + int32_t InCombat; + int32_t OutofCombat; + int32_t field215; + int32_t field216; + int32_t field217; + int32_t aemaxtargets; + int32_t maxtargets; + int32_t field220; + int32_t field221; + int32_t field222; + int32_t field223; + int32_t persistdeath; + int32_t field225; + int32_t field226; float min_dist; float min_dist_mod; float max_dist; float max_dist_mod; - int min_range; - int field232; - int field233; - int field234; - int field235; - int field236; + int32_t min_range; + int32_t field232; + int32_t field233; + int32_t field234; + int32_t field235; + int32_t field236; }; static std::string PrimaryKey() @@ -751,12 +751,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -784,250 +784,250 @@ public: static SpellsNew NewEntity() { - SpellsNew entry{}; + SpellsNew e{}; - entry.id = 0; - entry.name = ""; - entry.player_1 = "BLUE_TRAIL"; - entry.teleport_zone = ""; - entry.you_cast = ""; - entry.other_casts = ""; - entry.cast_on_you = ""; - entry.cast_on_other = ""; - entry.spell_fades = ""; - entry.range = 100; - entry.aoerange = 0; - entry.pushback = 0; - entry.pushup = 0; - entry.cast_time = 0; - entry.recovery_time = 0; - entry.recast_time = 0; - entry.buffdurationformula = 7; - entry.buffduration = 65; - entry.AEDuration = 0; - entry.mana = 0; - entry.effect_base_value1 = 100; - entry.effect_base_value2 = 0; - entry.effect_base_value3 = 0; - entry.effect_base_value4 = 0; - entry.effect_base_value5 = 0; - entry.effect_base_value6 = 0; - entry.effect_base_value7 = 0; - entry.effect_base_value8 = 0; - entry.effect_base_value9 = 0; - entry.effect_base_value10 = 0; - entry.effect_base_value11 = 0; - entry.effect_base_value12 = 0; - entry.effect_limit_value1 = 0; - entry.effect_limit_value2 = 0; - entry.effect_limit_value3 = 0; - entry.effect_limit_value4 = 0; - entry.effect_limit_value5 = 0; - entry.effect_limit_value6 = 0; - entry.effect_limit_value7 = 0; - entry.effect_limit_value8 = 0; - entry.effect_limit_value9 = 0; - entry.effect_limit_value10 = 0; - entry.effect_limit_value11 = 0; - entry.effect_limit_value12 = 0; - entry.max1 = 0; - entry.max2 = 0; - entry.max3 = 0; - entry.max4 = 0; - entry.max5 = 0; - entry.max6 = 0; - entry.max7 = 0; - entry.max8 = 0; - entry.max9 = 0; - entry.max10 = 0; - entry.max11 = 0; - entry.max12 = 0; - entry.icon = 0; - entry.memicon = 0; - entry.components1 = -1; - entry.components2 = -1; - entry.components3 = -1; - entry.components4 = -1; - entry.component_counts1 = 1; - entry.component_counts2 = 1; - entry.component_counts3 = 1; - entry.component_counts4 = 1; - entry.NoexpendReagent1 = -1; - entry.NoexpendReagent2 = -1; - entry.NoexpendReagent3 = -1; - entry.NoexpendReagent4 = -1; - entry.formula1 = 100; - entry.formula2 = 100; - entry.formula3 = 100; - entry.formula4 = 100; - entry.formula5 = 100; - entry.formula6 = 100; - entry.formula7 = 100; - entry.formula8 = 100; - entry.formula9 = 100; - entry.formula10 = 100; - entry.formula11 = 100; - entry.formula12 = 100; - entry.LightType = 0; - entry.goodEffect = 0; - entry.Activated = 0; - entry.resisttype = 0; - entry.effectid1 = 254; - entry.effectid2 = 254; - entry.effectid3 = 254; - entry.effectid4 = 254; - entry.effectid5 = 254; - entry.effectid6 = 254; - entry.effectid7 = 254; - entry.effectid8 = 254; - entry.effectid9 = 254; - entry.effectid10 = 254; - entry.effectid11 = 254; - entry.effectid12 = 254; - entry.targettype = 2; - entry.basediff = 0; - entry.skill = 98; - entry.zonetype = -1; - entry.EnvironmentType = 0; - entry.TimeOfDay = 0; - entry.classes1 = 255; - entry.classes2 = 255; - entry.classes3 = 255; - entry.classes4 = 255; - entry.classes5 = 255; - entry.classes6 = 255; - entry.classes7 = 255; - entry.classes8 = 255; - entry.classes9 = 255; - entry.classes10 = 255; - entry.classes11 = 255; - entry.classes12 = 255; - entry.classes13 = 255; - entry.classes14 = 255; - entry.classes15 = 255; - entry.classes16 = 255; - entry.CastingAnim = 44; - entry.TargetAnim = 13; - entry.TravelType = 0; - entry.SpellAffectIndex = -1; - entry.disallow_sit = 0; - entry.deities0 = 0; - entry.deities1 = 0; - entry.deities2 = 0; - entry.deities3 = 0; - entry.deities4 = 0; - entry.deities5 = 0; - entry.deities6 = 0; - entry.deities7 = 0; - entry.deities8 = 0; - entry.deities9 = 0; - entry.deities10 = 0; - entry.deities11 = 0; - entry.deities12 = 0; - entry.deities13 = 0; - entry.deities14 = 0; - entry.deities15 = 0; - entry.deities16 = 0; - entry.field142 = 100; - entry.field143 = 0; - entry.new_icon = 161; - entry.spellanim = 0; - entry.uninterruptable = 0; - entry.ResistDiff = -150; - entry.dot_stacking_exempt = 0; - entry.deleteable = 0; - entry.RecourseLink = 0; - entry.no_partial_resist = 0; - entry.field152 = 0; - entry.field153 = 0; - entry.short_buff_box = -1; - entry.descnum = 0; - entry.typedescnum = 0; - entry.effectdescnum = 0; - entry.effectdescnum2 = 0; - entry.npc_no_los = 0; - entry.field160 = 0; - entry.reflectable = 0; - entry.bonushate = 0; - entry.field163 = 100; - entry.field164 = -150; - entry.ldon_trap = 0; - entry.EndurCost = 0; - entry.EndurTimerIndex = 0; - entry.IsDiscipline = 0; - entry.field169 = 0; - entry.field170 = 0; - entry.field171 = 0; - entry.field172 = 0; - entry.HateAdded = 0; - entry.EndurUpkeep = 0; - entry.numhitstype = 0; - entry.numhits = 0; - entry.pvpresistbase = -150; - entry.pvpresistcalc = 100; - entry.pvpresistcap = -150; - entry.spell_category = -99; - entry.pvp_duration = 0; - entry.pvp_duration_cap = 0; - entry.pcnpc_only_flag = 0; - entry.cast_not_standing = 0; - entry.can_mgb = 0; - entry.nodispell = -1; - entry.npc_category = 0; - entry.npc_usefulness = 0; - entry.MinResist = 0; - entry.MaxResist = 0; - entry.viral_targets = 0; - entry.viral_timer = 0; - entry.nimbuseffect = 0; - entry.ConeStartAngle = 0; - entry.ConeStopAngle = 0; - entry.sneaking = 0; - entry.not_extendable = 0; - entry.field198 = 0; - entry.field199 = 1; - entry.suspendable = 0; - entry.viral_range = 0; - entry.songcap = 0; - entry.field203 = 0; - entry.field204 = 0; - entry.no_block = 0; - entry.field206 = -1; - entry.spellgroup = 0; - entry.rank = 0; - entry.field209 = 0; - entry.field210 = 1; - entry.CastRestriction = 0; - entry.allowrest = 0; - entry.InCombat = 0; - entry.OutofCombat = 0; - entry.field215 = 0; - entry.field216 = 0; - entry.field217 = 0; - entry.aemaxtargets = 0; - entry.maxtargets = 0; - entry.field220 = 0; - entry.field221 = 0; - entry.field222 = 0; - entry.field223 = 0; - entry.persistdeath = 0; - entry.field225 = 0; - entry.field226 = 0; - entry.min_dist = 0; - entry.min_dist_mod = 0; - entry.max_dist = 0; - entry.max_dist_mod = 0; - entry.min_range = 0; - entry.field232 = 0; - entry.field233 = 0; - entry.field234 = 0; - entry.field235 = 0; - entry.field236 = 0; + e.id = 0; + e.name = ""; + e.player_1 = "BLUE_TRAIL"; + e.teleport_zone = ""; + e.you_cast = ""; + e.other_casts = ""; + e.cast_on_you = ""; + e.cast_on_other = ""; + e.spell_fades = ""; + e.range = 100; + e.aoerange = 0; + e.pushback = 0; + e.pushup = 0; + e.cast_time = 0; + e.recovery_time = 0; + e.recast_time = 0; + e.buffdurationformula = 7; + e.buffduration = 65; + e.AEDuration = 0; + e.mana = 0; + e.effect_base_value1 = 100; + e.effect_base_value2 = 0; + e.effect_base_value3 = 0; + e.effect_base_value4 = 0; + e.effect_base_value5 = 0; + e.effect_base_value6 = 0; + e.effect_base_value7 = 0; + e.effect_base_value8 = 0; + e.effect_base_value9 = 0; + e.effect_base_value10 = 0; + e.effect_base_value11 = 0; + e.effect_base_value12 = 0; + e.effect_limit_value1 = 0; + e.effect_limit_value2 = 0; + e.effect_limit_value3 = 0; + e.effect_limit_value4 = 0; + e.effect_limit_value5 = 0; + e.effect_limit_value6 = 0; + e.effect_limit_value7 = 0; + e.effect_limit_value8 = 0; + e.effect_limit_value9 = 0; + e.effect_limit_value10 = 0; + e.effect_limit_value11 = 0; + e.effect_limit_value12 = 0; + e.max1 = 0; + e.max2 = 0; + e.max3 = 0; + e.max4 = 0; + e.max5 = 0; + e.max6 = 0; + e.max7 = 0; + e.max8 = 0; + e.max9 = 0; + e.max10 = 0; + e.max11 = 0; + e.max12 = 0; + e.icon = 0; + e.memicon = 0; + e.components1 = -1; + e.components2 = -1; + e.components3 = -1; + e.components4 = -1; + e.component_counts1 = 1; + e.component_counts2 = 1; + e.component_counts3 = 1; + e.component_counts4 = 1; + e.NoexpendReagent1 = -1; + e.NoexpendReagent2 = -1; + e.NoexpendReagent3 = -1; + e.NoexpendReagent4 = -1; + e.formula1 = 100; + e.formula2 = 100; + e.formula3 = 100; + e.formula4 = 100; + e.formula5 = 100; + e.formula6 = 100; + e.formula7 = 100; + e.formula8 = 100; + e.formula9 = 100; + e.formula10 = 100; + e.formula11 = 100; + e.formula12 = 100; + e.LightType = 0; + e.goodEffect = 0; + e.Activated = 0; + e.resisttype = 0; + e.effectid1 = 254; + e.effectid2 = 254; + e.effectid3 = 254; + e.effectid4 = 254; + e.effectid5 = 254; + e.effectid6 = 254; + e.effectid7 = 254; + e.effectid8 = 254; + e.effectid9 = 254; + e.effectid10 = 254; + e.effectid11 = 254; + e.effectid12 = 254; + e.targettype = 2; + e.basediff = 0; + e.skill = 98; + e.zonetype = -1; + e.EnvironmentType = 0; + e.TimeOfDay = 0; + e.classes1 = 255; + e.classes2 = 255; + e.classes3 = 255; + e.classes4 = 255; + e.classes5 = 255; + e.classes6 = 255; + e.classes7 = 255; + e.classes8 = 255; + e.classes9 = 255; + e.classes10 = 255; + e.classes11 = 255; + e.classes12 = 255; + e.classes13 = 255; + e.classes14 = 255; + e.classes15 = 255; + e.classes16 = 255; + e.CastingAnim = 44; + e.TargetAnim = 13; + e.TravelType = 0; + e.SpellAffectIndex = -1; + e.disallow_sit = 0; + e.deities0 = 0; + e.deities1 = 0; + e.deities2 = 0; + e.deities3 = 0; + e.deities4 = 0; + e.deities5 = 0; + e.deities6 = 0; + e.deities7 = 0; + e.deities8 = 0; + e.deities9 = 0; + e.deities10 = 0; + e.deities11 = 0; + e.deities12 = 0; + e.deities13 = 0; + e.deities14 = 0; + e.deities15 = 0; + e.deities16 = 0; + e.field142 = 100; + e.field143 = 0; + e.new_icon = 161; + e.spellanim = 0; + e.uninterruptable = 0; + e.ResistDiff = -150; + e.dot_stacking_exempt = 0; + e.deleteable = 0; + e.RecourseLink = 0; + e.no_partial_resist = 0; + e.field152 = 0; + e.field153 = 0; + e.short_buff_box = -1; + e.descnum = 0; + e.typedescnum = 0; + e.effectdescnum = 0; + e.effectdescnum2 = 0; + e.npc_no_los = 0; + e.field160 = 0; + e.reflectable = 0; + e.bonushate = 0; + e.field163 = 100; + e.field164 = -150; + e.ldon_trap = 0; + e.EndurCost = 0; + e.EndurTimerIndex = 0; + e.IsDiscipline = 0; + e.field169 = 0; + e.field170 = 0; + e.field171 = 0; + e.field172 = 0; + e.HateAdded = 0; + e.EndurUpkeep = 0; + e.numhitstype = 0; + e.numhits = 0; + e.pvpresistbase = -150; + e.pvpresistcalc = 100; + e.pvpresistcap = -150; + e.spell_category = -99; + e.pvp_duration = 0; + e.pvp_duration_cap = 0; + e.pcnpc_only_flag = 0; + e.cast_not_standing = 0; + e.can_mgb = 0; + e.nodispell = -1; + e.npc_category = 0; + e.npc_usefulness = 0; + e.MinResist = 0; + e.MaxResist = 0; + e.viral_targets = 0; + e.viral_timer = 0; + e.nimbuseffect = 0; + e.ConeStartAngle = 0; + e.ConeStopAngle = 0; + e.sneaking = 0; + e.not_extendable = 0; + e.field198 = 0; + e.field199 = 1; + e.suspendable = 0; + e.viral_range = 0; + e.songcap = 0; + e.field203 = 0; + e.field204 = 0; + e.no_block = 0; + e.field206 = -1; + e.spellgroup = 0; + e.rank = 0; + e.field209 = 0; + e.field210 = 1; + e.CastRestriction = 0; + e.allowrest = 0; + e.InCombat = 0; + e.OutofCombat = 0; + e.field215 = 0; + e.field216 = 0; + e.field217 = 0; + e.aemaxtargets = 0; + e.maxtargets = 0; + e.field220 = 0; + e.field221 = 0; + e.field222 = 0; + e.field223 = 0; + e.persistdeath = 0; + e.field225 = 0; + e.field226 = 0; + e.min_dist = 0; + e.min_dist_mod = 0; + e.max_dist = 0; + e.max_dist_mod = 0; + e.min_range = 0; + e.field232 = 0; + e.field233 = 0; + e.field234 = 0; + e.field235 = 0; + e.field236 = 0; - return entry; + return e; } - static SpellsNew GetSpellsNewEntry( + static SpellsNew GetSpellsNew( const std::vector &spells_news, int spells_new_id ) @@ -1056,247 +1056,247 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - SpellsNew entry{}; + SpellsNew e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.player_1 = row[2] ? row[2] : ""; - entry.teleport_zone = row[3] ? row[3] : ""; - entry.you_cast = row[4] ? row[4] : ""; - entry.other_casts = row[5] ? row[5] : ""; - entry.cast_on_you = row[6] ? row[6] : ""; - entry.cast_on_other = row[7] ? row[7] : ""; - entry.spell_fades = row[8] ? row[8] : ""; - entry.range = atoi(row[9]); - entry.aoerange = atoi(row[10]); - entry.pushback = atoi(row[11]); - entry.pushup = atoi(row[12]); - entry.cast_time = atoi(row[13]); - entry.recovery_time = atoi(row[14]); - entry.recast_time = atoi(row[15]); - entry.buffdurationformula = atoi(row[16]); - entry.buffduration = atoi(row[17]); - entry.AEDuration = atoi(row[18]); - entry.mana = atoi(row[19]); - entry.effect_base_value1 = atoi(row[20]); - entry.effect_base_value2 = atoi(row[21]); - entry.effect_base_value3 = atoi(row[22]); - entry.effect_base_value4 = atoi(row[23]); - entry.effect_base_value5 = atoi(row[24]); - entry.effect_base_value6 = atoi(row[25]); - entry.effect_base_value7 = atoi(row[26]); - entry.effect_base_value8 = atoi(row[27]); - entry.effect_base_value9 = atoi(row[28]); - entry.effect_base_value10 = atoi(row[29]); - entry.effect_base_value11 = atoi(row[30]); - entry.effect_base_value12 = atoi(row[31]); - entry.effect_limit_value1 = atoi(row[32]); - entry.effect_limit_value2 = atoi(row[33]); - entry.effect_limit_value3 = atoi(row[34]); - entry.effect_limit_value4 = atoi(row[35]); - entry.effect_limit_value5 = atoi(row[36]); - entry.effect_limit_value6 = atoi(row[37]); - entry.effect_limit_value7 = atoi(row[38]); - entry.effect_limit_value8 = atoi(row[39]); - entry.effect_limit_value9 = atoi(row[40]); - entry.effect_limit_value10 = atoi(row[41]); - entry.effect_limit_value11 = atoi(row[42]); - entry.effect_limit_value12 = atoi(row[43]); - entry.max1 = atoi(row[44]); - entry.max2 = atoi(row[45]); - entry.max3 = atoi(row[46]); - entry.max4 = atoi(row[47]); - entry.max5 = atoi(row[48]); - entry.max6 = atoi(row[49]); - entry.max7 = atoi(row[50]); - entry.max8 = atoi(row[51]); - entry.max9 = atoi(row[52]); - entry.max10 = atoi(row[53]); - entry.max11 = atoi(row[54]); - entry.max12 = atoi(row[55]); - entry.icon = atoi(row[56]); - entry.memicon = atoi(row[57]); - entry.components1 = atoi(row[58]); - entry.components2 = atoi(row[59]); - entry.components3 = atoi(row[60]); - entry.components4 = atoi(row[61]); - entry.component_counts1 = atoi(row[62]); - entry.component_counts2 = atoi(row[63]); - entry.component_counts3 = atoi(row[64]); - entry.component_counts4 = atoi(row[65]); - entry.NoexpendReagent1 = atoi(row[66]); - entry.NoexpendReagent2 = atoi(row[67]); - entry.NoexpendReagent3 = atoi(row[68]); - entry.NoexpendReagent4 = atoi(row[69]); - entry.formula1 = atoi(row[70]); - entry.formula2 = atoi(row[71]); - entry.formula3 = atoi(row[72]); - entry.formula4 = atoi(row[73]); - entry.formula5 = atoi(row[74]); - entry.formula6 = atoi(row[75]); - entry.formula7 = atoi(row[76]); - entry.formula8 = atoi(row[77]); - entry.formula9 = atoi(row[78]); - entry.formula10 = atoi(row[79]); - entry.formula11 = atoi(row[80]); - entry.formula12 = atoi(row[81]); - entry.LightType = atoi(row[82]); - entry.goodEffect = atoi(row[83]); - entry.Activated = atoi(row[84]); - entry.resisttype = atoi(row[85]); - entry.effectid1 = atoi(row[86]); - entry.effectid2 = atoi(row[87]); - entry.effectid3 = atoi(row[88]); - entry.effectid4 = atoi(row[89]); - entry.effectid5 = atoi(row[90]); - entry.effectid6 = atoi(row[91]); - entry.effectid7 = atoi(row[92]); - entry.effectid8 = atoi(row[93]); - entry.effectid9 = atoi(row[94]); - entry.effectid10 = atoi(row[95]); - entry.effectid11 = atoi(row[96]); - entry.effectid12 = atoi(row[97]); - entry.targettype = atoi(row[98]); - entry.basediff = atoi(row[99]); - entry.skill = atoi(row[100]); - entry.zonetype = atoi(row[101]); - entry.EnvironmentType = atoi(row[102]); - entry.TimeOfDay = atoi(row[103]); - entry.classes1 = atoi(row[104]); - entry.classes2 = atoi(row[105]); - entry.classes3 = atoi(row[106]); - entry.classes4 = atoi(row[107]); - entry.classes5 = atoi(row[108]); - entry.classes6 = atoi(row[109]); - entry.classes7 = atoi(row[110]); - entry.classes8 = atoi(row[111]); - entry.classes9 = atoi(row[112]); - entry.classes10 = atoi(row[113]); - entry.classes11 = atoi(row[114]); - entry.classes12 = atoi(row[115]); - entry.classes13 = atoi(row[116]); - entry.classes14 = atoi(row[117]); - entry.classes15 = atoi(row[118]); - entry.classes16 = atoi(row[119]); - entry.CastingAnim = atoi(row[120]); - entry.TargetAnim = atoi(row[121]); - entry.TravelType = atoi(row[122]); - entry.SpellAffectIndex = atoi(row[123]); - entry.disallow_sit = atoi(row[124]); - entry.deities0 = atoi(row[125]); - entry.deities1 = atoi(row[126]); - entry.deities2 = atoi(row[127]); - entry.deities3 = atoi(row[128]); - entry.deities4 = atoi(row[129]); - entry.deities5 = atoi(row[130]); - entry.deities6 = atoi(row[131]); - entry.deities7 = atoi(row[132]); - entry.deities8 = atoi(row[133]); - entry.deities9 = atoi(row[134]); - entry.deities10 = atoi(row[135]); - entry.deities11 = atoi(row[136]); - entry.deities12 = atoi(row[137]); - entry.deities13 = atoi(row[138]); - entry.deities14 = atoi(row[139]); - entry.deities15 = atoi(row[140]); - entry.deities16 = atoi(row[141]); - entry.field142 = atoi(row[142]); - entry.field143 = atoi(row[143]); - entry.new_icon = atoi(row[144]); - entry.spellanim = atoi(row[145]); - entry.uninterruptable = atoi(row[146]); - entry.ResistDiff = atoi(row[147]); - entry.dot_stacking_exempt = atoi(row[148]); - entry.deleteable = atoi(row[149]); - entry.RecourseLink = atoi(row[150]); - entry.no_partial_resist = atoi(row[151]); - entry.field152 = atoi(row[152]); - entry.field153 = atoi(row[153]); - entry.short_buff_box = atoi(row[154]); - entry.descnum = atoi(row[155]); - entry.typedescnum = atoi(row[156]); - entry.effectdescnum = atoi(row[157]); - entry.effectdescnum2 = atoi(row[158]); - entry.npc_no_los = atoi(row[159]); - entry.field160 = atoi(row[160]); - entry.reflectable = atoi(row[161]); - entry.bonushate = atoi(row[162]); - entry.field163 = atoi(row[163]); - entry.field164 = atoi(row[164]); - entry.ldon_trap = atoi(row[165]); - entry.EndurCost = atoi(row[166]); - entry.EndurTimerIndex = atoi(row[167]); - entry.IsDiscipline = atoi(row[168]); - entry.field169 = atoi(row[169]); - entry.field170 = atoi(row[170]); - entry.field171 = atoi(row[171]); - entry.field172 = atoi(row[172]); - entry.HateAdded = atoi(row[173]); - entry.EndurUpkeep = atoi(row[174]); - entry.numhitstype = atoi(row[175]); - entry.numhits = atoi(row[176]); - entry.pvpresistbase = atoi(row[177]); - entry.pvpresistcalc = atoi(row[178]); - entry.pvpresistcap = atoi(row[179]); - entry.spell_category = atoi(row[180]); - entry.pvp_duration = atoi(row[181]); - entry.pvp_duration_cap = atoi(row[182]); - entry.pcnpc_only_flag = atoi(row[183]); - entry.cast_not_standing = atoi(row[184]); - entry.can_mgb = atoi(row[185]); - entry.nodispell = atoi(row[186]); - entry.npc_category = atoi(row[187]); - entry.npc_usefulness = atoi(row[188]); - entry.MinResist = atoi(row[189]); - entry.MaxResist = atoi(row[190]); - entry.viral_targets = atoi(row[191]); - entry.viral_timer = atoi(row[192]); - entry.nimbuseffect = atoi(row[193]); - entry.ConeStartAngle = atoi(row[194]); - entry.ConeStopAngle = atoi(row[195]); - entry.sneaking = atoi(row[196]); - entry.not_extendable = atoi(row[197]); - entry.field198 = atoi(row[198]); - entry.field199 = atoi(row[199]); - entry.suspendable = atoi(row[200]); - entry.viral_range = atoi(row[201]); - entry.songcap = atoi(row[202]); - entry.field203 = atoi(row[203]); - entry.field204 = atoi(row[204]); - entry.no_block = atoi(row[205]); - entry.field206 = atoi(row[206]); - entry.spellgroup = atoi(row[207]); - entry.rank = atoi(row[208]); - entry.field209 = atoi(row[209]); - entry.field210 = atoi(row[210]); - entry.CastRestriction = atoi(row[211]); - entry.allowrest = atoi(row[212]); - entry.InCombat = atoi(row[213]); - entry.OutofCombat = atoi(row[214]); - entry.field215 = atoi(row[215]); - entry.field216 = atoi(row[216]); - entry.field217 = atoi(row[217]); - entry.aemaxtargets = atoi(row[218]); - entry.maxtargets = atoi(row[219]); - entry.field220 = atoi(row[220]); - entry.field221 = atoi(row[221]); - entry.field222 = atoi(row[222]); - entry.field223 = atoi(row[223]); - entry.persistdeath = atoi(row[224]); - entry.field225 = atoi(row[225]); - entry.field226 = atoi(row[226]); - entry.min_dist = static_cast(atof(row[227])); - entry.min_dist_mod = static_cast(atof(row[228])); - entry.max_dist = static_cast(atof(row[229])); - entry.max_dist_mod = static_cast(atof(row[230])); - entry.min_range = atoi(row[231]); - entry.field232 = atoi(row[232]); - entry.field233 = atoi(row[233]); - entry.field234 = atoi(row[234]); - entry.field235 = atoi(row[235]); - entry.field236 = atoi(row[236]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : ""; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range = static_cast(atoi(row[9])); + e.aoerange = static_cast(atoi(row[10])); + e.pushback = static_cast(atoi(row[11])); + e.pushup = static_cast(atoi(row[12])); + e.cast_time = static_cast(atoi(row[13])); + e.recovery_time = static_cast(atoi(row[14])); + e.recast_time = static_cast(atoi(row[15])); + e.buffdurationformula = static_cast(atoi(row[16])); + e.buffduration = static_cast(atoi(row[17])); + e.AEDuration = static_cast(atoi(row[18])); + e.mana = static_cast(atoi(row[19])); + e.effect_base_value1 = static_cast(atoi(row[20])); + e.effect_base_value2 = static_cast(atoi(row[21])); + e.effect_base_value3 = static_cast(atoi(row[22])); + e.effect_base_value4 = static_cast(atoi(row[23])); + e.effect_base_value5 = static_cast(atoi(row[24])); + e.effect_base_value6 = static_cast(atoi(row[25])); + e.effect_base_value7 = static_cast(atoi(row[26])); + e.effect_base_value8 = static_cast(atoi(row[27])); + e.effect_base_value9 = static_cast(atoi(row[28])); + e.effect_base_value10 = static_cast(atoi(row[29])); + e.effect_base_value11 = static_cast(atoi(row[30])); + e.effect_base_value12 = static_cast(atoi(row[31])); + e.effect_limit_value1 = static_cast(atoi(row[32])); + e.effect_limit_value2 = static_cast(atoi(row[33])); + e.effect_limit_value3 = static_cast(atoi(row[34])); + e.effect_limit_value4 = static_cast(atoi(row[35])); + e.effect_limit_value5 = static_cast(atoi(row[36])); + e.effect_limit_value6 = static_cast(atoi(row[37])); + e.effect_limit_value7 = static_cast(atoi(row[38])); + e.effect_limit_value8 = static_cast(atoi(row[39])); + e.effect_limit_value9 = static_cast(atoi(row[40])); + e.effect_limit_value10 = static_cast(atoi(row[41])); + e.effect_limit_value11 = static_cast(atoi(row[42])); + e.effect_limit_value12 = static_cast(atoi(row[43])); + e.max1 = static_cast(atoi(row[44])); + e.max2 = static_cast(atoi(row[45])); + e.max3 = static_cast(atoi(row[46])); + e.max4 = static_cast(atoi(row[47])); + e.max5 = static_cast(atoi(row[48])); + e.max6 = static_cast(atoi(row[49])); + e.max7 = static_cast(atoi(row[50])); + e.max8 = static_cast(atoi(row[51])); + e.max9 = static_cast(atoi(row[52])); + e.max10 = static_cast(atoi(row[53])); + e.max11 = static_cast(atoi(row[54])); + e.max12 = static_cast(atoi(row[55])); + e.icon = static_cast(atoi(row[56])); + e.memicon = static_cast(atoi(row[57])); + e.components1 = static_cast(atoi(row[58])); + e.components2 = static_cast(atoi(row[59])); + e.components3 = static_cast(atoi(row[60])); + e.components4 = static_cast(atoi(row[61])); + e.component_counts1 = static_cast(atoi(row[62])); + e.component_counts2 = static_cast(atoi(row[63])); + e.component_counts3 = static_cast(atoi(row[64])); + e.component_counts4 = static_cast(atoi(row[65])); + e.NoexpendReagent1 = static_cast(atoi(row[66])); + e.NoexpendReagent2 = static_cast(atoi(row[67])); + e.NoexpendReagent3 = static_cast(atoi(row[68])); + e.NoexpendReagent4 = static_cast(atoi(row[69])); + e.formula1 = static_cast(atoi(row[70])); + e.formula2 = static_cast(atoi(row[71])); + e.formula3 = static_cast(atoi(row[72])); + e.formula4 = static_cast(atoi(row[73])); + e.formula5 = static_cast(atoi(row[74])); + e.formula6 = static_cast(atoi(row[75])); + e.formula7 = static_cast(atoi(row[76])); + e.formula8 = static_cast(atoi(row[77])); + e.formula9 = static_cast(atoi(row[78])); + e.formula10 = static_cast(atoi(row[79])); + e.formula11 = static_cast(atoi(row[80])); + e.formula12 = static_cast(atoi(row[81])); + e.LightType = static_cast(atoi(row[82])); + e.goodEffect = static_cast(atoi(row[83])); + e.Activated = static_cast(atoi(row[84])); + e.resisttype = static_cast(atoi(row[85])); + e.effectid1 = static_cast(atoi(row[86])); + e.effectid2 = static_cast(atoi(row[87])); + e.effectid3 = static_cast(atoi(row[88])); + e.effectid4 = static_cast(atoi(row[89])); + e.effectid5 = static_cast(atoi(row[90])); + e.effectid6 = static_cast(atoi(row[91])); + e.effectid7 = static_cast(atoi(row[92])); + e.effectid8 = static_cast(atoi(row[93])); + e.effectid9 = static_cast(atoi(row[94])); + e.effectid10 = static_cast(atoi(row[95])); + e.effectid11 = static_cast(atoi(row[96])); + e.effectid12 = static_cast(atoi(row[97])); + e.targettype = static_cast(atoi(row[98])); + e.basediff = static_cast(atoi(row[99])); + e.skill = static_cast(atoi(row[100])); + e.zonetype = static_cast(atoi(row[101])); + e.EnvironmentType = static_cast(atoi(row[102])); + e.TimeOfDay = static_cast(atoi(row[103])); + e.classes1 = static_cast(atoi(row[104])); + e.classes2 = static_cast(atoi(row[105])); + e.classes3 = static_cast(atoi(row[106])); + e.classes4 = static_cast(atoi(row[107])); + e.classes5 = static_cast(atoi(row[108])); + e.classes6 = static_cast(atoi(row[109])); + e.classes7 = static_cast(atoi(row[110])); + e.classes8 = static_cast(atoi(row[111])); + e.classes9 = static_cast(atoi(row[112])); + e.classes10 = static_cast(atoi(row[113])); + e.classes11 = static_cast(atoi(row[114])); + e.classes12 = static_cast(atoi(row[115])); + e.classes13 = static_cast(atoi(row[116])); + e.classes14 = static_cast(atoi(row[117])); + e.classes15 = static_cast(atoi(row[118])); + e.classes16 = static_cast(atoi(row[119])); + e.CastingAnim = static_cast(atoi(row[120])); + e.TargetAnim = static_cast(atoi(row[121])); + e.TravelType = static_cast(atoi(row[122])); + e.SpellAffectIndex = static_cast(atoi(row[123])); + e.disallow_sit = static_cast(atoi(row[124])); + e.deities0 = static_cast(atoi(row[125])); + e.deities1 = static_cast(atoi(row[126])); + e.deities2 = static_cast(atoi(row[127])); + e.deities3 = static_cast(atoi(row[128])); + e.deities4 = static_cast(atoi(row[129])); + e.deities5 = static_cast(atoi(row[130])); + e.deities6 = static_cast(atoi(row[131])); + e.deities7 = static_cast(atoi(row[132])); + e.deities8 = static_cast(atoi(row[133])); + e.deities9 = static_cast(atoi(row[134])); + e.deities10 = static_cast(atoi(row[135])); + e.deities11 = static_cast(atoi(row[136])); + e.deities12 = static_cast(atoi(row[137])); + e.deities13 = static_cast(atoi(row[138])); + e.deities14 = static_cast(atoi(row[139])); + e.deities15 = static_cast(atoi(row[140])); + e.deities16 = static_cast(atoi(row[141])); + e.field142 = static_cast(atoi(row[142])); + e.field143 = static_cast(atoi(row[143])); + e.new_icon = static_cast(atoi(row[144])); + e.spellanim = static_cast(atoi(row[145])); + e.uninterruptable = static_cast(atoi(row[146])); + e.ResistDiff = static_cast(atoi(row[147])); + e.dot_stacking_exempt = static_cast(atoi(row[148])); + e.deleteable = static_cast(atoi(row[149])); + e.RecourseLink = static_cast(atoi(row[150])); + e.no_partial_resist = static_cast(atoi(row[151])); + e.field152 = static_cast(atoi(row[152])); + e.field153 = static_cast(atoi(row[153])); + e.short_buff_box = static_cast(atoi(row[154])); + e.descnum = static_cast(atoi(row[155])); + e.typedescnum = static_cast(atoi(row[156])); + e.effectdescnum = static_cast(atoi(row[157])); + e.effectdescnum2 = static_cast(atoi(row[158])); + e.npc_no_los = static_cast(atoi(row[159])); + e.field160 = static_cast(atoi(row[160])); + e.reflectable = static_cast(atoi(row[161])); + e.bonushate = static_cast(atoi(row[162])); + e.field163 = static_cast(atoi(row[163])); + e.field164 = static_cast(atoi(row[164])); + e.ldon_trap = static_cast(atoi(row[165])); + e.EndurCost = static_cast(atoi(row[166])); + e.EndurTimerIndex = static_cast(atoi(row[167])); + e.IsDiscipline = static_cast(atoi(row[168])); + e.field169 = static_cast(atoi(row[169])); + e.field170 = static_cast(atoi(row[170])); + e.field171 = static_cast(atoi(row[171])); + e.field172 = static_cast(atoi(row[172])); + e.HateAdded = static_cast(atoi(row[173])); + e.EndurUpkeep = static_cast(atoi(row[174])); + e.numhitstype = static_cast(atoi(row[175])); + e.numhits = static_cast(atoi(row[176])); + e.pvpresistbase = static_cast(atoi(row[177])); + e.pvpresistcalc = static_cast(atoi(row[178])); + e.pvpresistcap = static_cast(atoi(row[179])); + e.spell_category = static_cast(atoi(row[180])); + e.pvp_duration = static_cast(atoi(row[181])); + e.pvp_duration_cap = static_cast(atoi(row[182])); + e.pcnpc_only_flag = static_cast(atoi(row[183])); + e.cast_not_standing = static_cast(atoi(row[184])); + e.can_mgb = static_cast(atoi(row[185])); + e.nodispell = static_cast(atoi(row[186])); + e.npc_category = static_cast(atoi(row[187])); + e.npc_usefulness = static_cast(atoi(row[188])); + e.MinResist = static_cast(atoi(row[189])); + e.MaxResist = static_cast(atoi(row[190])); + e.viral_targets = static_cast(atoi(row[191])); + e.viral_timer = static_cast(atoi(row[192])); + e.nimbuseffect = static_cast(atoi(row[193])); + e.ConeStartAngle = static_cast(atoi(row[194])); + e.ConeStopAngle = static_cast(atoi(row[195])); + e.sneaking = static_cast(atoi(row[196])); + e.not_extendable = static_cast(atoi(row[197])); + e.field198 = static_cast(atoi(row[198])); + e.field199 = static_cast(atoi(row[199])); + e.suspendable = static_cast(atoi(row[200])); + e.viral_range = static_cast(atoi(row[201])); + e.songcap = static_cast(atoi(row[202])); + e.field203 = static_cast(atoi(row[203])); + e.field204 = static_cast(atoi(row[204])); + e.no_block = static_cast(atoi(row[205])); + e.field206 = static_cast(atoi(row[206])); + e.spellgroup = static_cast(atoi(row[207])); + e.rank = static_cast(atoi(row[208])); + e.field209 = static_cast(atoi(row[209])); + e.field210 = static_cast(atoi(row[210])); + e.CastRestriction = static_cast(atoi(row[211])); + e.allowrest = static_cast(atoi(row[212])); + e.InCombat = static_cast(atoi(row[213])); + e.OutofCombat = static_cast(atoi(row[214])); + e.field215 = static_cast(atoi(row[215])); + e.field216 = static_cast(atoi(row[216])); + e.field217 = static_cast(atoi(row[217])); + e.aemaxtargets = static_cast(atoi(row[218])); + e.maxtargets = static_cast(atoi(row[219])); + e.field220 = static_cast(atoi(row[220])); + e.field221 = static_cast(atoi(row[221])); + e.field222 = static_cast(atoi(row[222])); + e.field223 = static_cast(atoi(row[223])); + e.persistdeath = static_cast(atoi(row[224])); + e.field225 = static_cast(atoi(row[225])); + e.field226 = static_cast(atoi(row[226])); + e.min_dist = strtof(row[227], nullptr); + e.min_dist_mod = strtof(row[228], nullptr); + e.max_dist = strtof(row[229], nullptr); + e.max_dist_mod = strtof(row[230], nullptr); + e.min_range = static_cast(atoi(row[231])); + e.field232 = static_cast(atoi(row[232])); + e.field233 = static_cast(atoi(row[233])); + e.field234 = static_cast(atoi(row[234])); + e.field235 = static_cast(atoi(row[235])); + e.field236 = static_cast(atoi(row[236])); - return entry; + return e; } return NewEntity(); @@ -1321,258 +1321,258 @@ public: static int UpdateOne( Database& db, - SpellsNew spells_new_entry + const SpellsNew &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(spells_new_entry.id)); - update_values.push_back(columns[1] + " = '" + EscapeString(spells_new_entry.name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(spells_new_entry.player_1) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(spells_new_entry.teleport_zone) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(spells_new_entry.you_cast) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(spells_new_entry.other_casts) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(spells_new_entry.cast_on_you) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(spells_new_entry.cast_on_other) + "'"); - update_values.push_back(columns[8] + " = '" + EscapeString(spells_new_entry.spell_fades) + "'"); - update_values.push_back(columns[9] + " = " + std::to_string(spells_new_entry.range)); - update_values.push_back(columns[10] + " = " + std::to_string(spells_new_entry.aoerange)); - update_values.push_back(columns[11] + " = " + std::to_string(spells_new_entry.pushback)); - update_values.push_back(columns[12] + " = " + std::to_string(spells_new_entry.pushup)); - update_values.push_back(columns[13] + " = " + std::to_string(spells_new_entry.cast_time)); - update_values.push_back(columns[14] + " = " + std::to_string(spells_new_entry.recovery_time)); - update_values.push_back(columns[15] + " = " + std::to_string(spells_new_entry.recast_time)); - update_values.push_back(columns[16] + " = " + std::to_string(spells_new_entry.buffdurationformula)); - update_values.push_back(columns[17] + " = " + std::to_string(spells_new_entry.buffduration)); - update_values.push_back(columns[18] + " = " + std::to_string(spells_new_entry.AEDuration)); - update_values.push_back(columns[19] + " = " + std::to_string(spells_new_entry.mana)); - update_values.push_back(columns[20] + " = " + std::to_string(spells_new_entry.effect_base_value1)); - update_values.push_back(columns[21] + " = " + std::to_string(spells_new_entry.effect_base_value2)); - update_values.push_back(columns[22] + " = " + std::to_string(spells_new_entry.effect_base_value3)); - update_values.push_back(columns[23] + " = " + std::to_string(spells_new_entry.effect_base_value4)); - update_values.push_back(columns[24] + " = " + std::to_string(spells_new_entry.effect_base_value5)); - update_values.push_back(columns[25] + " = " + std::to_string(spells_new_entry.effect_base_value6)); - update_values.push_back(columns[26] + " = " + std::to_string(spells_new_entry.effect_base_value7)); - update_values.push_back(columns[27] + " = " + std::to_string(spells_new_entry.effect_base_value8)); - update_values.push_back(columns[28] + " = " + std::to_string(spells_new_entry.effect_base_value9)); - update_values.push_back(columns[29] + " = " + std::to_string(spells_new_entry.effect_base_value10)); - update_values.push_back(columns[30] + " = " + std::to_string(spells_new_entry.effect_base_value11)); - update_values.push_back(columns[31] + " = " + std::to_string(spells_new_entry.effect_base_value12)); - update_values.push_back(columns[32] + " = " + std::to_string(spells_new_entry.effect_limit_value1)); - update_values.push_back(columns[33] + " = " + std::to_string(spells_new_entry.effect_limit_value2)); - update_values.push_back(columns[34] + " = " + std::to_string(spells_new_entry.effect_limit_value3)); - update_values.push_back(columns[35] + " = " + std::to_string(spells_new_entry.effect_limit_value4)); - update_values.push_back(columns[36] + " = " + std::to_string(spells_new_entry.effect_limit_value5)); - update_values.push_back(columns[37] + " = " + std::to_string(spells_new_entry.effect_limit_value6)); - update_values.push_back(columns[38] + " = " + std::to_string(spells_new_entry.effect_limit_value7)); - update_values.push_back(columns[39] + " = " + std::to_string(spells_new_entry.effect_limit_value8)); - update_values.push_back(columns[40] + " = " + std::to_string(spells_new_entry.effect_limit_value9)); - update_values.push_back(columns[41] + " = " + std::to_string(spells_new_entry.effect_limit_value10)); - update_values.push_back(columns[42] + " = " + std::to_string(spells_new_entry.effect_limit_value11)); - update_values.push_back(columns[43] + " = " + std::to_string(spells_new_entry.effect_limit_value12)); - update_values.push_back(columns[44] + " = " + std::to_string(spells_new_entry.max1)); - update_values.push_back(columns[45] + " = " + std::to_string(spells_new_entry.max2)); - update_values.push_back(columns[46] + " = " + std::to_string(spells_new_entry.max3)); - update_values.push_back(columns[47] + " = " + std::to_string(spells_new_entry.max4)); - update_values.push_back(columns[48] + " = " + std::to_string(spells_new_entry.max5)); - update_values.push_back(columns[49] + " = " + std::to_string(spells_new_entry.max6)); - update_values.push_back(columns[50] + " = " + std::to_string(spells_new_entry.max7)); - update_values.push_back(columns[51] + " = " + std::to_string(spells_new_entry.max8)); - update_values.push_back(columns[52] + " = " + std::to_string(spells_new_entry.max9)); - update_values.push_back(columns[53] + " = " + std::to_string(spells_new_entry.max10)); - update_values.push_back(columns[54] + " = " + std::to_string(spells_new_entry.max11)); - update_values.push_back(columns[55] + " = " + std::to_string(spells_new_entry.max12)); - update_values.push_back(columns[56] + " = " + std::to_string(spells_new_entry.icon)); - update_values.push_back(columns[57] + " = " + std::to_string(spells_new_entry.memicon)); - update_values.push_back(columns[58] + " = " + std::to_string(spells_new_entry.components1)); - update_values.push_back(columns[59] + " = " + std::to_string(spells_new_entry.components2)); - update_values.push_back(columns[60] + " = " + std::to_string(spells_new_entry.components3)); - update_values.push_back(columns[61] + " = " + std::to_string(spells_new_entry.components4)); - update_values.push_back(columns[62] + " = " + std::to_string(spells_new_entry.component_counts1)); - update_values.push_back(columns[63] + " = " + std::to_string(spells_new_entry.component_counts2)); - update_values.push_back(columns[64] + " = " + std::to_string(spells_new_entry.component_counts3)); - update_values.push_back(columns[65] + " = " + std::to_string(spells_new_entry.component_counts4)); - update_values.push_back(columns[66] + " = " + std::to_string(spells_new_entry.NoexpendReagent1)); - update_values.push_back(columns[67] + " = " + std::to_string(spells_new_entry.NoexpendReagent2)); - update_values.push_back(columns[68] + " = " + std::to_string(spells_new_entry.NoexpendReagent3)); - update_values.push_back(columns[69] + " = " + std::to_string(spells_new_entry.NoexpendReagent4)); - update_values.push_back(columns[70] + " = " + std::to_string(spells_new_entry.formula1)); - update_values.push_back(columns[71] + " = " + std::to_string(spells_new_entry.formula2)); - update_values.push_back(columns[72] + " = " + std::to_string(spells_new_entry.formula3)); - update_values.push_back(columns[73] + " = " + std::to_string(spells_new_entry.formula4)); - update_values.push_back(columns[74] + " = " + std::to_string(spells_new_entry.formula5)); - update_values.push_back(columns[75] + " = " + std::to_string(spells_new_entry.formula6)); - update_values.push_back(columns[76] + " = " + std::to_string(spells_new_entry.formula7)); - update_values.push_back(columns[77] + " = " + std::to_string(spells_new_entry.formula8)); - update_values.push_back(columns[78] + " = " + std::to_string(spells_new_entry.formula9)); - update_values.push_back(columns[79] + " = " + std::to_string(spells_new_entry.formula10)); - update_values.push_back(columns[80] + " = " + std::to_string(spells_new_entry.formula11)); - update_values.push_back(columns[81] + " = " + std::to_string(spells_new_entry.formula12)); - update_values.push_back(columns[82] + " = " + std::to_string(spells_new_entry.LightType)); - update_values.push_back(columns[83] + " = " + std::to_string(spells_new_entry.goodEffect)); - update_values.push_back(columns[84] + " = " + std::to_string(spells_new_entry.Activated)); - update_values.push_back(columns[85] + " = " + std::to_string(spells_new_entry.resisttype)); - update_values.push_back(columns[86] + " = " + std::to_string(spells_new_entry.effectid1)); - update_values.push_back(columns[87] + " = " + std::to_string(spells_new_entry.effectid2)); - update_values.push_back(columns[88] + " = " + std::to_string(spells_new_entry.effectid3)); - update_values.push_back(columns[89] + " = " + std::to_string(spells_new_entry.effectid4)); - update_values.push_back(columns[90] + " = " + std::to_string(spells_new_entry.effectid5)); - update_values.push_back(columns[91] + " = " + std::to_string(spells_new_entry.effectid6)); - update_values.push_back(columns[92] + " = " + std::to_string(spells_new_entry.effectid7)); - update_values.push_back(columns[93] + " = " + std::to_string(spells_new_entry.effectid8)); - update_values.push_back(columns[94] + " = " + std::to_string(spells_new_entry.effectid9)); - update_values.push_back(columns[95] + " = " + std::to_string(spells_new_entry.effectid10)); - update_values.push_back(columns[96] + " = " + std::to_string(spells_new_entry.effectid11)); - update_values.push_back(columns[97] + " = " + std::to_string(spells_new_entry.effectid12)); - update_values.push_back(columns[98] + " = " + std::to_string(spells_new_entry.targettype)); - update_values.push_back(columns[99] + " = " + std::to_string(spells_new_entry.basediff)); - update_values.push_back(columns[100] + " = " + std::to_string(spells_new_entry.skill)); - update_values.push_back(columns[101] + " = " + std::to_string(spells_new_entry.zonetype)); - update_values.push_back(columns[102] + " = " + std::to_string(spells_new_entry.EnvironmentType)); - update_values.push_back(columns[103] + " = " + std::to_string(spells_new_entry.TimeOfDay)); - update_values.push_back(columns[104] + " = " + std::to_string(spells_new_entry.classes1)); - update_values.push_back(columns[105] + " = " + std::to_string(spells_new_entry.classes2)); - update_values.push_back(columns[106] + " = " + std::to_string(spells_new_entry.classes3)); - update_values.push_back(columns[107] + " = " + std::to_string(spells_new_entry.classes4)); - update_values.push_back(columns[108] + " = " + std::to_string(spells_new_entry.classes5)); - update_values.push_back(columns[109] + " = " + std::to_string(spells_new_entry.classes6)); - update_values.push_back(columns[110] + " = " + std::to_string(spells_new_entry.classes7)); - update_values.push_back(columns[111] + " = " + std::to_string(spells_new_entry.classes8)); - update_values.push_back(columns[112] + " = " + std::to_string(spells_new_entry.classes9)); - update_values.push_back(columns[113] + " = " + std::to_string(spells_new_entry.classes10)); - update_values.push_back(columns[114] + " = " + std::to_string(spells_new_entry.classes11)); - update_values.push_back(columns[115] + " = " + std::to_string(spells_new_entry.classes12)); - update_values.push_back(columns[116] + " = " + std::to_string(spells_new_entry.classes13)); - update_values.push_back(columns[117] + " = " + std::to_string(spells_new_entry.classes14)); - update_values.push_back(columns[118] + " = " + std::to_string(spells_new_entry.classes15)); - update_values.push_back(columns[119] + " = " + std::to_string(spells_new_entry.classes16)); - update_values.push_back(columns[120] + " = " + std::to_string(spells_new_entry.CastingAnim)); - update_values.push_back(columns[121] + " = " + std::to_string(spells_new_entry.TargetAnim)); - update_values.push_back(columns[122] + " = " + std::to_string(spells_new_entry.TravelType)); - update_values.push_back(columns[123] + " = " + std::to_string(spells_new_entry.SpellAffectIndex)); - update_values.push_back(columns[124] + " = " + std::to_string(spells_new_entry.disallow_sit)); - update_values.push_back(columns[125] + " = " + std::to_string(spells_new_entry.deities0)); - update_values.push_back(columns[126] + " = " + std::to_string(spells_new_entry.deities1)); - update_values.push_back(columns[127] + " = " + std::to_string(spells_new_entry.deities2)); - update_values.push_back(columns[128] + " = " + std::to_string(spells_new_entry.deities3)); - update_values.push_back(columns[129] + " = " + std::to_string(spells_new_entry.deities4)); - update_values.push_back(columns[130] + " = " + std::to_string(spells_new_entry.deities5)); - update_values.push_back(columns[131] + " = " + std::to_string(spells_new_entry.deities6)); - update_values.push_back(columns[132] + " = " + std::to_string(spells_new_entry.deities7)); - update_values.push_back(columns[133] + " = " + std::to_string(spells_new_entry.deities8)); - update_values.push_back(columns[134] + " = " + std::to_string(spells_new_entry.deities9)); - update_values.push_back(columns[135] + " = " + std::to_string(spells_new_entry.deities10)); - update_values.push_back(columns[136] + " = " + std::to_string(spells_new_entry.deities11)); - update_values.push_back(columns[137] + " = " + std::to_string(spells_new_entry.deities12)); - update_values.push_back(columns[138] + " = " + std::to_string(spells_new_entry.deities13)); - update_values.push_back(columns[139] + " = " + std::to_string(spells_new_entry.deities14)); - update_values.push_back(columns[140] + " = " + std::to_string(spells_new_entry.deities15)); - update_values.push_back(columns[141] + " = " + std::to_string(spells_new_entry.deities16)); - update_values.push_back(columns[142] + " = " + std::to_string(spells_new_entry.field142)); - update_values.push_back(columns[143] + " = " + std::to_string(spells_new_entry.field143)); - update_values.push_back(columns[144] + " = " + std::to_string(spells_new_entry.new_icon)); - update_values.push_back(columns[145] + " = " + std::to_string(spells_new_entry.spellanim)); - update_values.push_back(columns[146] + " = " + std::to_string(spells_new_entry.uninterruptable)); - update_values.push_back(columns[147] + " = " + std::to_string(spells_new_entry.ResistDiff)); - update_values.push_back(columns[148] + " = " + std::to_string(spells_new_entry.dot_stacking_exempt)); - update_values.push_back(columns[149] + " = " + std::to_string(spells_new_entry.deleteable)); - update_values.push_back(columns[150] + " = " + std::to_string(spells_new_entry.RecourseLink)); - update_values.push_back(columns[151] + " = " + std::to_string(spells_new_entry.no_partial_resist)); - update_values.push_back(columns[152] + " = " + std::to_string(spells_new_entry.field152)); - update_values.push_back(columns[153] + " = " + std::to_string(spells_new_entry.field153)); - update_values.push_back(columns[154] + " = " + std::to_string(spells_new_entry.short_buff_box)); - update_values.push_back(columns[155] + " = " + std::to_string(spells_new_entry.descnum)); - update_values.push_back(columns[156] + " = " + std::to_string(spells_new_entry.typedescnum)); - update_values.push_back(columns[157] + " = " + std::to_string(spells_new_entry.effectdescnum)); - update_values.push_back(columns[158] + " = " + std::to_string(spells_new_entry.effectdescnum2)); - update_values.push_back(columns[159] + " = " + std::to_string(spells_new_entry.npc_no_los)); - update_values.push_back(columns[160] + " = " + std::to_string(spells_new_entry.field160)); - update_values.push_back(columns[161] + " = " + std::to_string(spells_new_entry.reflectable)); - update_values.push_back(columns[162] + " = " + std::to_string(spells_new_entry.bonushate)); - update_values.push_back(columns[163] + " = " + std::to_string(spells_new_entry.field163)); - update_values.push_back(columns[164] + " = " + std::to_string(spells_new_entry.field164)); - update_values.push_back(columns[165] + " = " + std::to_string(spells_new_entry.ldon_trap)); - update_values.push_back(columns[166] + " = " + std::to_string(spells_new_entry.EndurCost)); - update_values.push_back(columns[167] + " = " + std::to_string(spells_new_entry.EndurTimerIndex)); - update_values.push_back(columns[168] + " = " + std::to_string(spells_new_entry.IsDiscipline)); - update_values.push_back(columns[169] + " = " + std::to_string(spells_new_entry.field169)); - update_values.push_back(columns[170] + " = " + std::to_string(spells_new_entry.field170)); - update_values.push_back(columns[171] + " = " + std::to_string(spells_new_entry.field171)); - update_values.push_back(columns[172] + " = " + std::to_string(spells_new_entry.field172)); - update_values.push_back(columns[173] + " = " + std::to_string(spells_new_entry.HateAdded)); - update_values.push_back(columns[174] + " = " + std::to_string(spells_new_entry.EndurUpkeep)); - update_values.push_back(columns[175] + " = " + std::to_string(spells_new_entry.numhitstype)); - update_values.push_back(columns[176] + " = " + std::to_string(spells_new_entry.numhits)); - update_values.push_back(columns[177] + " = " + std::to_string(spells_new_entry.pvpresistbase)); - update_values.push_back(columns[178] + " = " + std::to_string(spells_new_entry.pvpresistcalc)); - update_values.push_back(columns[179] + " = " + std::to_string(spells_new_entry.pvpresistcap)); - update_values.push_back(columns[180] + " = " + std::to_string(spells_new_entry.spell_category)); - update_values.push_back(columns[181] + " = " + std::to_string(spells_new_entry.pvp_duration)); - update_values.push_back(columns[182] + " = " + std::to_string(spells_new_entry.pvp_duration_cap)); - update_values.push_back(columns[183] + " = " + std::to_string(spells_new_entry.pcnpc_only_flag)); - update_values.push_back(columns[184] + " = " + std::to_string(spells_new_entry.cast_not_standing)); - update_values.push_back(columns[185] + " = " + std::to_string(spells_new_entry.can_mgb)); - update_values.push_back(columns[186] + " = " + std::to_string(spells_new_entry.nodispell)); - update_values.push_back(columns[187] + " = " + std::to_string(spells_new_entry.npc_category)); - update_values.push_back(columns[188] + " = " + std::to_string(spells_new_entry.npc_usefulness)); - update_values.push_back(columns[189] + " = " + std::to_string(spells_new_entry.MinResist)); - update_values.push_back(columns[190] + " = " + std::to_string(spells_new_entry.MaxResist)); - update_values.push_back(columns[191] + " = " + std::to_string(spells_new_entry.viral_targets)); - update_values.push_back(columns[192] + " = " + std::to_string(spells_new_entry.viral_timer)); - update_values.push_back(columns[193] + " = " + std::to_string(spells_new_entry.nimbuseffect)); - update_values.push_back(columns[194] + " = " + std::to_string(spells_new_entry.ConeStartAngle)); - update_values.push_back(columns[195] + " = " + std::to_string(spells_new_entry.ConeStopAngle)); - update_values.push_back(columns[196] + " = " + std::to_string(spells_new_entry.sneaking)); - update_values.push_back(columns[197] + " = " + std::to_string(spells_new_entry.not_extendable)); - update_values.push_back(columns[198] + " = " + std::to_string(spells_new_entry.field198)); - update_values.push_back(columns[199] + " = " + std::to_string(spells_new_entry.field199)); - update_values.push_back(columns[200] + " = " + std::to_string(spells_new_entry.suspendable)); - update_values.push_back(columns[201] + " = " + std::to_string(spells_new_entry.viral_range)); - update_values.push_back(columns[202] + " = " + std::to_string(spells_new_entry.songcap)); - update_values.push_back(columns[203] + " = " + std::to_string(spells_new_entry.field203)); - update_values.push_back(columns[204] + " = " + std::to_string(spells_new_entry.field204)); - update_values.push_back(columns[205] + " = " + std::to_string(spells_new_entry.no_block)); - update_values.push_back(columns[206] + " = " + std::to_string(spells_new_entry.field206)); - update_values.push_back(columns[207] + " = " + std::to_string(spells_new_entry.spellgroup)); - update_values.push_back(columns[208] + " = " + std::to_string(spells_new_entry.rank)); - update_values.push_back(columns[209] + " = " + std::to_string(spells_new_entry.field209)); - update_values.push_back(columns[210] + " = " + std::to_string(spells_new_entry.field210)); - update_values.push_back(columns[211] + " = " + std::to_string(spells_new_entry.CastRestriction)); - update_values.push_back(columns[212] + " = " + std::to_string(spells_new_entry.allowrest)); - update_values.push_back(columns[213] + " = " + std::to_string(spells_new_entry.InCombat)); - update_values.push_back(columns[214] + " = " + std::to_string(spells_new_entry.OutofCombat)); - update_values.push_back(columns[215] + " = " + std::to_string(spells_new_entry.field215)); - update_values.push_back(columns[216] + " = " + std::to_string(spells_new_entry.field216)); - update_values.push_back(columns[217] + " = " + std::to_string(spells_new_entry.field217)); - update_values.push_back(columns[218] + " = " + std::to_string(spells_new_entry.aemaxtargets)); - update_values.push_back(columns[219] + " = " + std::to_string(spells_new_entry.maxtargets)); - update_values.push_back(columns[220] + " = " + std::to_string(spells_new_entry.field220)); - update_values.push_back(columns[221] + " = " + std::to_string(spells_new_entry.field221)); - update_values.push_back(columns[222] + " = " + std::to_string(spells_new_entry.field222)); - update_values.push_back(columns[223] + " = " + std::to_string(spells_new_entry.field223)); - update_values.push_back(columns[224] + " = " + std::to_string(spells_new_entry.persistdeath)); - update_values.push_back(columns[225] + " = " + std::to_string(spells_new_entry.field225)); - update_values.push_back(columns[226] + " = " + std::to_string(spells_new_entry.field226)); - update_values.push_back(columns[227] + " = " + std::to_string(spells_new_entry.min_dist)); - update_values.push_back(columns[228] + " = " + std::to_string(spells_new_entry.min_dist_mod)); - update_values.push_back(columns[229] + " = " + std::to_string(spells_new_entry.max_dist)); - update_values.push_back(columns[230] + " = " + std::to_string(spells_new_entry.max_dist_mod)); - update_values.push_back(columns[231] + " = " + std::to_string(spells_new_entry.min_range)); - update_values.push_back(columns[232] + " = " + std::to_string(spells_new_entry.field232)); - update_values.push_back(columns[233] + " = " + std::to_string(spells_new_entry.field233)); - update_values.push_back(columns[234] + " = " + std::to_string(spells_new_entry.field234)); - update_values.push_back(columns[235] + " = " + std::to_string(spells_new_entry.field235)); - update_values.push_back(columns[236] + " = " + std::to_string(spells_new_entry.field236)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.player_1) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.teleport_zone) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.you_cast) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.other_casts) + "'"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.cast_on_you) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.cast_on_other) + "'"); + v.push_back(columns[8] + " = '" + Strings::Escape(e.spell_fades) + "'"); + v.push_back(columns[9] + " = " + std::to_string(e.range)); + v.push_back(columns[10] + " = " + std::to_string(e.aoerange)); + v.push_back(columns[11] + " = " + std::to_string(e.pushback)); + v.push_back(columns[12] + " = " + std::to_string(e.pushup)); + v.push_back(columns[13] + " = " + std::to_string(e.cast_time)); + v.push_back(columns[14] + " = " + std::to_string(e.recovery_time)); + v.push_back(columns[15] + " = " + std::to_string(e.recast_time)); + v.push_back(columns[16] + " = " + std::to_string(e.buffdurationformula)); + v.push_back(columns[17] + " = " + std::to_string(e.buffduration)); + v.push_back(columns[18] + " = " + std::to_string(e.AEDuration)); + v.push_back(columns[19] + " = " + std::to_string(e.mana)); + v.push_back(columns[20] + " = " + std::to_string(e.effect_base_value1)); + v.push_back(columns[21] + " = " + std::to_string(e.effect_base_value2)); + v.push_back(columns[22] + " = " + std::to_string(e.effect_base_value3)); + v.push_back(columns[23] + " = " + std::to_string(e.effect_base_value4)); + v.push_back(columns[24] + " = " + std::to_string(e.effect_base_value5)); + v.push_back(columns[25] + " = " + std::to_string(e.effect_base_value6)); + v.push_back(columns[26] + " = " + std::to_string(e.effect_base_value7)); + v.push_back(columns[27] + " = " + std::to_string(e.effect_base_value8)); + v.push_back(columns[28] + " = " + std::to_string(e.effect_base_value9)); + v.push_back(columns[29] + " = " + std::to_string(e.effect_base_value10)); + v.push_back(columns[30] + " = " + std::to_string(e.effect_base_value11)); + v.push_back(columns[31] + " = " + std::to_string(e.effect_base_value12)); + v.push_back(columns[32] + " = " + std::to_string(e.effect_limit_value1)); + v.push_back(columns[33] + " = " + std::to_string(e.effect_limit_value2)); + v.push_back(columns[34] + " = " + std::to_string(e.effect_limit_value3)); + v.push_back(columns[35] + " = " + std::to_string(e.effect_limit_value4)); + v.push_back(columns[36] + " = " + std::to_string(e.effect_limit_value5)); + v.push_back(columns[37] + " = " + std::to_string(e.effect_limit_value6)); + v.push_back(columns[38] + " = " + std::to_string(e.effect_limit_value7)); + v.push_back(columns[39] + " = " + std::to_string(e.effect_limit_value8)); + v.push_back(columns[40] + " = " + std::to_string(e.effect_limit_value9)); + v.push_back(columns[41] + " = " + std::to_string(e.effect_limit_value10)); + v.push_back(columns[42] + " = " + std::to_string(e.effect_limit_value11)); + v.push_back(columns[43] + " = " + std::to_string(e.effect_limit_value12)); + v.push_back(columns[44] + " = " + std::to_string(e.max1)); + v.push_back(columns[45] + " = " + std::to_string(e.max2)); + v.push_back(columns[46] + " = " + std::to_string(e.max3)); + v.push_back(columns[47] + " = " + std::to_string(e.max4)); + v.push_back(columns[48] + " = " + std::to_string(e.max5)); + v.push_back(columns[49] + " = " + std::to_string(e.max6)); + v.push_back(columns[50] + " = " + std::to_string(e.max7)); + v.push_back(columns[51] + " = " + std::to_string(e.max8)); + v.push_back(columns[52] + " = " + std::to_string(e.max9)); + v.push_back(columns[53] + " = " + std::to_string(e.max10)); + v.push_back(columns[54] + " = " + std::to_string(e.max11)); + v.push_back(columns[55] + " = " + std::to_string(e.max12)); + v.push_back(columns[56] + " = " + std::to_string(e.icon)); + v.push_back(columns[57] + " = " + std::to_string(e.memicon)); + v.push_back(columns[58] + " = " + std::to_string(e.components1)); + v.push_back(columns[59] + " = " + std::to_string(e.components2)); + v.push_back(columns[60] + " = " + std::to_string(e.components3)); + v.push_back(columns[61] + " = " + std::to_string(e.components4)); + v.push_back(columns[62] + " = " + std::to_string(e.component_counts1)); + v.push_back(columns[63] + " = " + std::to_string(e.component_counts2)); + v.push_back(columns[64] + " = " + std::to_string(e.component_counts3)); + v.push_back(columns[65] + " = " + std::to_string(e.component_counts4)); + v.push_back(columns[66] + " = " + std::to_string(e.NoexpendReagent1)); + v.push_back(columns[67] + " = " + std::to_string(e.NoexpendReagent2)); + v.push_back(columns[68] + " = " + std::to_string(e.NoexpendReagent3)); + v.push_back(columns[69] + " = " + std::to_string(e.NoexpendReagent4)); + v.push_back(columns[70] + " = " + std::to_string(e.formula1)); + v.push_back(columns[71] + " = " + std::to_string(e.formula2)); + v.push_back(columns[72] + " = " + std::to_string(e.formula3)); + v.push_back(columns[73] + " = " + std::to_string(e.formula4)); + v.push_back(columns[74] + " = " + std::to_string(e.formula5)); + v.push_back(columns[75] + " = " + std::to_string(e.formula6)); + v.push_back(columns[76] + " = " + std::to_string(e.formula7)); + v.push_back(columns[77] + " = " + std::to_string(e.formula8)); + v.push_back(columns[78] + " = " + std::to_string(e.formula9)); + v.push_back(columns[79] + " = " + std::to_string(e.formula10)); + v.push_back(columns[80] + " = " + std::to_string(e.formula11)); + v.push_back(columns[81] + " = " + std::to_string(e.formula12)); + v.push_back(columns[82] + " = " + std::to_string(e.LightType)); + v.push_back(columns[83] + " = " + std::to_string(e.goodEffect)); + v.push_back(columns[84] + " = " + std::to_string(e.Activated)); + v.push_back(columns[85] + " = " + std::to_string(e.resisttype)); + v.push_back(columns[86] + " = " + std::to_string(e.effectid1)); + v.push_back(columns[87] + " = " + std::to_string(e.effectid2)); + v.push_back(columns[88] + " = " + std::to_string(e.effectid3)); + v.push_back(columns[89] + " = " + std::to_string(e.effectid4)); + v.push_back(columns[90] + " = " + std::to_string(e.effectid5)); + v.push_back(columns[91] + " = " + std::to_string(e.effectid6)); + v.push_back(columns[92] + " = " + std::to_string(e.effectid7)); + v.push_back(columns[93] + " = " + std::to_string(e.effectid8)); + v.push_back(columns[94] + " = " + std::to_string(e.effectid9)); + v.push_back(columns[95] + " = " + std::to_string(e.effectid10)); + v.push_back(columns[96] + " = " + std::to_string(e.effectid11)); + v.push_back(columns[97] + " = " + std::to_string(e.effectid12)); + v.push_back(columns[98] + " = " + std::to_string(e.targettype)); + v.push_back(columns[99] + " = " + std::to_string(e.basediff)); + v.push_back(columns[100] + " = " + std::to_string(e.skill)); + v.push_back(columns[101] + " = " + std::to_string(e.zonetype)); + v.push_back(columns[102] + " = " + std::to_string(e.EnvironmentType)); + v.push_back(columns[103] + " = " + std::to_string(e.TimeOfDay)); + v.push_back(columns[104] + " = " + std::to_string(e.classes1)); + v.push_back(columns[105] + " = " + std::to_string(e.classes2)); + v.push_back(columns[106] + " = " + std::to_string(e.classes3)); + v.push_back(columns[107] + " = " + std::to_string(e.classes4)); + v.push_back(columns[108] + " = " + std::to_string(e.classes5)); + v.push_back(columns[109] + " = " + std::to_string(e.classes6)); + v.push_back(columns[110] + " = " + std::to_string(e.classes7)); + v.push_back(columns[111] + " = " + std::to_string(e.classes8)); + v.push_back(columns[112] + " = " + std::to_string(e.classes9)); + v.push_back(columns[113] + " = " + std::to_string(e.classes10)); + v.push_back(columns[114] + " = " + std::to_string(e.classes11)); + v.push_back(columns[115] + " = " + std::to_string(e.classes12)); + v.push_back(columns[116] + " = " + std::to_string(e.classes13)); + v.push_back(columns[117] + " = " + std::to_string(e.classes14)); + v.push_back(columns[118] + " = " + std::to_string(e.classes15)); + v.push_back(columns[119] + " = " + std::to_string(e.classes16)); + v.push_back(columns[120] + " = " + std::to_string(e.CastingAnim)); + v.push_back(columns[121] + " = " + std::to_string(e.TargetAnim)); + v.push_back(columns[122] + " = " + std::to_string(e.TravelType)); + v.push_back(columns[123] + " = " + std::to_string(e.SpellAffectIndex)); + v.push_back(columns[124] + " = " + std::to_string(e.disallow_sit)); + v.push_back(columns[125] + " = " + std::to_string(e.deities0)); + v.push_back(columns[126] + " = " + std::to_string(e.deities1)); + v.push_back(columns[127] + " = " + std::to_string(e.deities2)); + v.push_back(columns[128] + " = " + std::to_string(e.deities3)); + v.push_back(columns[129] + " = " + std::to_string(e.deities4)); + v.push_back(columns[130] + " = " + std::to_string(e.deities5)); + v.push_back(columns[131] + " = " + std::to_string(e.deities6)); + v.push_back(columns[132] + " = " + std::to_string(e.deities7)); + v.push_back(columns[133] + " = " + std::to_string(e.deities8)); + v.push_back(columns[134] + " = " + std::to_string(e.deities9)); + v.push_back(columns[135] + " = " + std::to_string(e.deities10)); + v.push_back(columns[136] + " = " + std::to_string(e.deities11)); + v.push_back(columns[137] + " = " + std::to_string(e.deities12)); + v.push_back(columns[138] + " = " + std::to_string(e.deities13)); + v.push_back(columns[139] + " = " + std::to_string(e.deities14)); + v.push_back(columns[140] + " = " + std::to_string(e.deities15)); + v.push_back(columns[141] + " = " + std::to_string(e.deities16)); + v.push_back(columns[142] + " = " + std::to_string(e.field142)); + v.push_back(columns[143] + " = " + std::to_string(e.field143)); + v.push_back(columns[144] + " = " + std::to_string(e.new_icon)); + v.push_back(columns[145] + " = " + std::to_string(e.spellanim)); + v.push_back(columns[146] + " = " + std::to_string(e.uninterruptable)); + v.push_back(columns[147] + " = " + std::to_string(e.ResistDiff)); + v.push_back(columns[148] + " = " + std::to_string(e.dot_stacking_exempt)); + v.push_back(columns[149] + " = " + std::to_string(e.deleteable)); + v.push_back(columns[150] + " = " + std::to_string(e.RecourseLink)); + v.push_back(columns[151] + " = " + std::to_string(e.no_partial_resist)); + v.push_back(columns[152] + " = " + std::to_string(e.field152)); + v.push_back(columns[153] + " = " + std::to_string(e.field153)); + v.push_back(columns[154] + " = " + std::to_string(e.short_buff_box)); + v.push_back(columns[155] + " = " + std::to_string(e.descnum)); + v.push_back(columns[156] + " = " + std::to_string(e.typedescnum)); + v.push_back(columns[157] + " = " + std::to_string(e.effectdescnum)); + v.push_back(columns[158] + " = " + std::to_string(e.effectdescnum2)); + v.push_back(columns[159] + " = " + std::to_string(e.npc_no_los)); + v.push_back(columns[160] + " = " + std::to_string(e.field160)); + v.push_back(columns[161] + " = " + std::to_string(e.reflectable)); + v.push_back(columns[162] + " = " + std::to_string(e.bonushate)); + v.push_back(columns[163] + " = " + std::to_string(e.field163)); + v.push_back(columns[164] + " = " + std::to_string(e.field164)); + v.push_back(columns[165] + " = " + std::to_string(e.ldon_trap)); + v.push_back(columns[166] + " = " + std::to_string(e.EndurCost)); + v.push_back(columns[167] + " = " + std::to_string(e.EndurTimerIndex)); + v.push_back(columns[168] + " = " + std::to_string(e.IsDiscipline)); + v.push_back(columns[169] + " = " + std::to_string(e.field169)); + v.push_back(columns[170] + " = " + std::to_string(e.field170)); + v.push_back(columns[171] + " = " + std::to_string(e.field171)); + v.push_back(columns[172] + " = " + std::to_string(e.field172)); + v.push_back(columns[173] + " = " + std::to_string(e.HateAdded)); + v.push_back(columns[174] + " = " + std::to_string(e.EndurUpkeep)); + v.push_back(columns[175] + " = " + std::to_string(e.numhitstype)); + v.push_back(columns[176] + " = " + std::to_string(e.numhits)); + v.push_back(columns[177] + " = " + std::to_string(e.pvpresistbase)); + v.push_back(columns[178] + " = " + std::to_string(e.pvpresistcalc)); + v.push_back(columns[179] + " = " + std::to_string(e.pvpresistcap)); + v.push_back(columns[180] + " = " + std::to_string(e.spell_category)); + v.push_back(columns[181] + " = " + std::to_string(e.pvp_duration)); + v.push_back(columns[182] + " = " + std::to_string(e.pvp_duration_cap)); + v.push_back(columns[183] + " = " + std::to_string(e.pcnpc_only_flag)); + v.push_back(columns[184] + " = " + std::to_string(e.cast_not_standing)); + v.push_back(columns[185] + " = " + std::to_string(e.can_mgb)); + v.push_back(columns[186] + " = " + std::to_string(e.nodispell)); + v.push_back(columns[187] + " = " + std::to_string(e.npc_category)); + v.push_back(columns[188] + " = " + std::to_string(e.npc_usefulness)); + v.push_back(columns[189] + " = " + std::to_string(e.MinResist)); + v.push_back(columns[190] + " = " + std::to_string(e.MaxResist)); + v.push_back(columns[191] + " = " + std::to_string(e.viral_targets)); + v.push_back(columns[192] + " = " + std::to_string(e.viral_timer)); + v.push_back(columns[193] + " = " + std::to_string(e.nimbuseffect)); + v.push_back(columns[194] + " = " + std::to_string(e.ConeStartAngle)); + v.push_back(columns[195] + " = " + std::to_string(e.ConeStopAngle)); + v.push_back(columns[196] + " = " + std::to_string(e.sneaking)); + v.push_back(columns[197] + " = " + std::to_string(e.not_extendable)); + v.push_back(columns[198] + " = " + std::to_string(e.field198)); + v.push_back(columns[199] + " = " + std::to_string(e.field199)); + v.push_back(columns[200] + " = " + std::to_string(e.suspendable)); + v.push_back(columns[201] + " = " + std::to_string(e.viral_range)); + v.push_back(columns[202] + " = " + std::to_string(e.songcap)); + v.push_back(columns[203] + " = " + std::to_string(e.field203)); + v.push_back(columns[204] + " = " + std::to_string(e.field204)); + v.push_back(columns[205] + " = " + std::to_string(e.no_block)); + v.push_back(columns[206] + " = " + std::to_string(e.field206)); + v.push_back(columns[207] + " = " + std::to_string(e.spellgroup)); + v.push_back(columns[208] + " = " + std::to_string(e.rank)); + v.push_back(columns[209] + " = " + std::to_string(e.field209)); + v.push_back(columns[210] + " = " + std::to_string(e.field210)); + v.push_back(columns[211] + " = " + std::to_string(e.CastRestriction)); + v.push_back(columns[212] + " = " + std::to_string(e.allowrest)); + v.push_back(columns[213] + " = " + std::to_string(e.InCombat)); + v.push_back(columns[214] + " = " + std::to_string(e.OutofCombat)); + v.push_back(columns[215] + " = " + std::to_string(e.field215)); + v.push_back(columns[216] + " = " + std::to_string(e.field216)); + v.push_back(columns[217] + " = " + std::to_string(e.field217)); + v.push_back(columns[218] + " = " + std::to_string(e.aemaxtargets)); + v.push_back(columns[219] + " = " + std::to_string(e.maxtargets)); + v.push_back(columns[220] + " = " + std::to_string(e.field220)); + v.push_back(columns[221] + " = " + std::to_string(e.field221)); + v.push_back(columns[222] + " = " + std::to_string(e.field222)); + v.push_back(columns[223] + " = " + std::to_string(e.field223)); + v.push_back(columns[224] + " = " + std::to_string(e.persistdeath)); + v.push_back(columns[225] + " = " + std::to_string(e.field225)); + v.push_back(columns[226] + " = " + std::to_string(e.field226)); + v.push_back(columns[227] + " = " + std::to_string(e.min_dist)); + v.push_back(columns[228] + " = " + std::to_string(e.min_dist_mod)); + v.push_back(columns[229] + " = " + std::to_string(e.max_dist)); + v.push_back(columns[230] + " = " + std::to_string(e.max_dist_mod)); + v.push_back(columns[231] + " = " + std::to_string(e.min_range)); + v.push_back(columns[232] + " = " + std::to_string(e.field232)); + v.push_back(columns[233] + " = " + std::to_string(e.field233)); + v.push_back(columns[234] + " = " + std::to_string(e.field234)); + v.push_back(columns[235] + " = " + std::to_string(e.field235)); + v.push_back(columns[236] + " = " + std::to_string(e.field236)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - spells_new_entry.id + e.id ) ); @@ -1581,525 +1581,525 @@ public: static SpellsNew InsertOne( Database& db, - SpellsNew spells_new_entry + SpellsNew e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(spells_new_entry.id)); - insert_values.push_back("'" + EscapeString(spells_new_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.player_1) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.teleport_zone) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.you_cast) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.other_casts) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.cast_on_you) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.cast_on_other) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.spell_fades) + "'"); - insert_values.push_back(std::to_string(spells_new_entry.range)); - insert_values.push_back(std::to_string(spells_new_entry.aoerange)); - insert_values.push_back(std::to_string(spells_new_entry.pushback)); - insert_values.push_back(std::to_string(spells_new_entry.pushup)); - insert_values.push_back(std::to_string(spells_new_entry.cast_time)); - insert_values.push_back(std::to_string(spells_new_entry.recovery_time)); - insert_values.push_back(std::to_string(spells_new_entry.recast_time)); - insert_values.push_back(std::to_string(spells_new_entry.buffdurationformula)); - insert_values.push_back(std::to_string(spells_new_entry.buffduration)); - insert_values.push_back(std::to_string(spells_new_entry.AEDuration)); - insert_values.push_back(std::to_string(spells_new_entry.mana)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value1)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value2)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value3)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value4)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value5)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value6)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value7)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value8)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value9)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value10)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value11)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value12)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value1)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value2)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value3)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value4)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value5)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value6)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value7)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value8)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value9)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value10)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value11)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value12)); - insert_values.push_back(std::to_string(spells_new_entry.max1)); - insert_values.push_back(std::to_string(spells_new_entry.max2)); - insert_values.push_back(std::to_string(spells_new_entry.max3)); - insert_values.push_back(std::to_string(spells_new_entry.max4)); - insert_values.push_back(std::to_string(spells_new_entry.max5)); - insert_values.push_back(std::to_string(spells_new_entry.max6)); - insert_values.push_back(std::to_string(spells_new_entry.max7)); - insert_values.push_back(std::to_string(spells_new_entry.max8)); - insert_values.push_back(std::to_string(spells_new_entry.max9)); - insert_values.push_back(std::to_string(spells_new_entry.max10)); - insert_values.push_back(std::to_string(spells_new_entry.max11)); - insert_values.push_back(std::to_string(spells_new_entry.max12)); - insert_values.push_back(std::to_string(spells_new_entry.icon)); - insert_values.push_back(std::to_string(spells_new_entry.memicon)); - insert_values.push_back(std::to_string(spells_new_entry.components1)); - insert_values.push_back(std::to_string(spells_new_entry.components2)); - insert_values.push_back(std::to_string(spells_new_entry.components3)); - insert_values.push_back(std::to_string(spells_new_entry.components4)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts1)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts2)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts3)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts4)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent1)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent2)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent3)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent4)); - insert_values.push_back(std::to_string(spells_new_entry.formula1)); - insert_values.push_back(std::to_string(spells_new_entry.formula2)); - insert_values.push_back(std::to_string(spells_new_entry.formula3)); - insert_values.push_back(std::to_string(spells_new_entry.formula4)); - insert_values.push_back(std::to_string(spells_new_entry.formula5)); - insert_values.push_back(std::to_string(spells_new_entry.formula6)); - insert_values.push_back(std::to_string(spells_new_entry.formula7)); - insert_values.push_back(std::to_string(spells_new_entry.formula8)); - insert_values.push_back(std::to_string(spells_new_entry.formula9)); - insert_values.push_back(std::to_string(spells_new_entry.formula10)); - insert_values.push_back(std::to_string(spells_new_entry.formula11)); - insert_values.push_back(std::to_string(spells_new_entry.formula12)); - insert_values.push_back(std::to_string(spells_new_entry.LightType)); - insert_values.push_back(std::to_string(spells_new_entry.goodEffect)); - insert_values.push_back(std::to_string(spells_new_entry.Activated)); - insert_values.push_back(std::to_string(spells_new_entry.resisttype)); - insert_values.push_back(std::to_string(spells_new_entry.effectid1)); - insert_values.push_back(std::to_string(spells_new_entry.effectid2)); - insert_values.push_back(std::to_string(spells_new_entry.effectid3)); - insert_values.push_back(std::to_string(spells_new_entry.effectid4)); - insert_values.push_back(std::to_string(spells_new_entry.effectid5)); - insert_values.push_back(std::to_string(spells_new_entry.effectid6)); - insert_values.push_back(std::to_string(spells_new_entry.effectid7)); - insert_values.push_back(std::to_string(spells_new_entry.effectid8)); - insert_values.push_back(std::to_string(spells_new_entry.effectid9)); - insert_values.push_back(std::to_string(spells_new_entry.effectid10)); - insert_values.push_back(std::to_string(spells_new_entry.effectid11)); - insert_values.push_back(std::to_string(spells_new_entry.effectid12)); - insert_values.push_back(std::to_string(spells_new_entry.targettype)); - insert_values.push_back(std::to_string(spells_new_entry.basediff)); - insert_values.push_back(std::to_string(spells_new_entry.skill)); - insert_values.push_back(std::to_string(spells_new_entry.zonetype)); - insert_values.push_back(std::to_string(spells_new_entry.EnvironmentType)); - insert_values.push_back(std::to_string(spells_new_entry.TimeOfDay)); - insert_values.push_back(std::to_string(spells_new_entry.classes1)); - insert_values.push_back(std::to_string(spells_new_entry.classes2)); - insert_values.push_back(std::to_string(spells_new_entry.classes3)); - insert_values.push_back(std::to_string(spells_new_entry.classes4)); - insert_values.push_back(std::to_string(spells_new_entry.classes5)); - insert_values.push_back(std::to_string(spells_new_entry.classes6)); - insert_values.push_back(std::to_string(spells_new_entry.classes7)); - insert_values.push_back(std::to_string(spells_new_entry.classes8)); - insert_values.push_back(std::to_string(spells_new_entry.classes9)); - insert_values.push_back(std::to_string(spells_new_entry.classes10)); - insert_values.push_back(std::to_string(spells_new_entry.classes11)); - insert_values.push_back(std::to_string(spells_new_entry.classes12)); - insert_values.push_back(std::to_string(spells_new_entry.classes13)); - insert_values.push_back(std::to_string(spells_new_entry.classes14)); - insert_values.push_back(std::to_string(spells_new_entry.classes15)); - insert_values.push_back(std::to_string(spells_new_entry.classes16)); - insert_values.push_back(std::to_string(spells_new_entry.CastingAnim)); - insert_values.push_back(std::to_string(spells_new_entry.TargetAnim)); - insert_values.push_back(std::to_string(spells_new_entry.TravelType)); - insert_values.push_back(std::to_string(spells_new_entry.SpellAffectIndex)); - insert_values.push_back(std::to_string(spells_new_entry.disallow_sit)); - insert_values.push_back(std::to_string(spells_new_entry.deities0)); - insert_values.push_back(std::to_string(spells_new_entry.deities1)); - insert_values.push_back(std::to_string(spells_new_entry.deities2)); - insert_values.push_back(std::to_string(spells_new_entry.deities3)); - insert_values.push_back(std::to_string(spells_new_entry.deities4)); - insert_values.push_back(std::to_string(spells_new_entry.deities5)); - insert_values.push_back(std::to_string(spells_new_entry.deities6)); - insert_values.push_back(std::to_string(spells_new_entry.deities7)); - insert_values.push_back(std::to_string(spells_new_entry.deities8)); - insert_values.push_back(std::to_string(spells_new_entry.deities9)); - insert_values.push_back(std::to_string(spells_new_entry.deities10)); - insert_values.push_back(std::to_string(spells_new_entry.deities11)); - insert_values.push_back(std::to_string(spells_new_entry.deities12)); - insert_values.push_back(std::to_string(spells_new_entry.deities13)); - insert_values.push_back(std::to_string(spells_new_entry.deities14)); - insert_values.push_back(std::to_string(spells_new_entry.deities15)); - insert_values.push_back(std::to_string(spells_new_entry.deities16)); - insert_values.push_back(std::to_string(spells_new_entry.field142)); - insert_values.push_back(std::to_string(spells_new_entry.field143)); - insert_values.push_back(std::to_string(spells_new_entry.new_icon)); - insert_values.push_back(std::to_string(spells_new_entry.spellanim)); - insert_values.push_back(std::to_string(spells_new_entry.uninterruptable)); - insert_values.push_back(std::to_string(spells_new_entry.ResistDiff)); - insert_values.push_back(std::to_string(spells_new_entry.dot_stacking_exempt)); - insert_values.push_back(std::to_string(spells_new_entry.deleteable)); - insert_values.push_back(std::to_string(spells_new_entry.RecourseLink)); - insert_values.push_back(std::to_string(spells_new_entry.no_partial_resist)); - insert_values.push_back(std::to_string(spells_new_entry.field152)); - insert_values.push_back(std::to_string(spells_new_entry.field153)); - insert_values.push_back(std::to_string(spells_new_entry.short_buff_box)); - insert_values.push_back(std::to_string(spells_new_entry.descnum)); - insert_values.push_back(std::to_string(spells_new_entry.typedescnum)); - insert_values.push_back(std::to_string(spells_new_entry.effectdescnum)); - insert_values.push_back(std::to_string(spells_new_entry.effectdescnum2)); - insert_values.push_back(std::to_string(spells_new_entry.npc_no_los)); - insert_values.push_back(std::to_string(spells_new_entry.field160)); - insert_values.push_back(std::to_string(spells_new_entry.reflectable)); - insert_values.push_back(std::to_string(spells_new_entry.bonushate)); - insert_values.push_back(std::to_string(spells_new_entry.field163)); - insert_values.push_back(std::to_string(spells_new_entry.field164)); - insert_values.push_back(std::to_string(spells_new_entry.ldon_trap)); - insert_values.push_back(std::to_string(spells_new_entry.EndurCost)); - insert_values.push_back(std::to_string(spells_new_entry.EndurTimerIndex)); - insert_values.push_back(std::to_string(spells_new_entry.IsDiscipline)); - insert_values.push_back(std::to_string(spells_new_entry.field169)); - insert_values.push_back(std::to_string(spells_new_entry.field170)); - insert_values.push_back(std::to_string(spells_new_entry.field171)); - insert_values.push_back(std::to_string(spells_new_entry.field172)); - insert_values.push_back(std::to_string(spells_new_entry.HateAdded)); - insert_values.push_back(std::to_string(spells_new_entry.EndurUpkeep)); - insert_values.push_back(std::to_string(spells_new_entry.numhitstype)); - insert_values.push_back(std::to_string(spells_new_entry.numhits)); - insert_values.push_back(std::to_string(spells_new_entry.pvpresistbase)); - insert_values.push_back(std::to_string(spells_new_entry.pvpresistcalc)); - insert_values.push_back(std::to_string(spells_new_entry.pvpresistcap)); - insert_values.push_back(std::to_string(spells_new_entry.spell_category)); - insert_values.push_back(std::to_string(spells_new_entry.pvp_duration)); - insert_values.push_back(std::to_string(spells_new_entry.pvp_duration_cap)); - insert_values.push_back(std::to_string(spells_new_entry.pcnpc_only_flag)); - insert_values.push_back(std::to_string(spells_new_entry.cast_not_standing)); - insert_values.push_back(std::to_string(spells_new_entry.can_mgb)); - insert_values.push_back(std::to_string(spells_new_entry.nodispell)); - insert_values.push_back(std::to_string(spells_new_entry.npc_category)); - insert_values.push_back(std::to_string(spells_new_entry.npc_usefulness)); - insert_values.push_back(std::to_string(spells_new_entry.MinResist)); - insert_values.push_back(std::to_string(spells_new_entry.MaxResist)); - insert_values.push_back(std::to_string(spells_new_entry.viral_targets)); - insert_values.push_back(std::to_string(spells_new_entry.viral_timer)); - insert_values.push_back(std::to_string(spells_new_entry.nimbuseffect)); - insert_values.push_back(std::to_string(spells_new_entry.ConeStartAngle)); - insert_values.push_back(std::to_string(spells_new_entry.ConeStopAngle)); - insert_values.push_back(std::to_string(spells_new_entry.sneaking)); - insert_values.push_back(std::to_string(spells_new_entry.not_extendable)); - insert_values.push_back(std::to_string(spells_new_entry.field198)); - insert_values.push_back(std::to_string(spells_new_entry.field199)); - insert_values.push_back(std::to_string(spells_new_entry.suspendable)); - insert_values.push_back(std::to_string(spells_new_entry.viral_range)); - insert_values.push_back(std::to_string(spells_new_entry.songcap)); - insert_values.push_back(std::to_string(spells_new_entry.field203)); - insert_values.push_back(std::to_string(spells_new_entry.field204)); - insert_values.push_back(std::to_string(spells_new_entry.no_block)); - insert_values.push_back(std::to_string(spells_new_entry.field206)); - insert_values.push_back(std::to_string(spells_new_entry.spellgroup)); - insert_values.push_back(std::to_string(spells_new_entry.rank)); - insert_values.push_back(std::to_string(spells_new_entry.field209)); - insert_values.push_back(std::to_string(spells_new_entry.field210)); - insert_values.push_back(std::to_string(spells_new_entry.CastRestriction)); - insert_values.push_back(std::to_string(spells_new_entry.allowrest)); - insert_values.push_back(std::to_string(spells_new_entry.InCombat)); - insert_values.push_back(std::to_string(spells_new_entry.OutofCombat)); - insert_values.push_back(std::to_string(spells_new_entry.field215)); - insert_values.push_back(std::to_string(spells_new_entry.field216)); - insert_values.push_back(std::to_string(spells_new_entry.field217)); - insert_values.push_back(std::to_string(spells_new_entry.aemaxtargets)); - insert_values.push_back(std::to_string(spells_new_entry.maxtargets)); - insert_values.push_back(std::to_string(spells_new_entry.field220)); - insert_values.push_back(std::to_string(spells_new_entry.field221)); - insert_values.push_back(std::to_string(spells_new_entry.field222)); - insert_values.push_back(std::to_string(spells_new_entry.field223)); - insert_values.push_back(std::to_string(spells_new_entry.persistdeath)); - insert_values.push_back(std::to_string(spells_new_entry.field225)); - insert_values.push_back(std::to_string(spells_new_entry.field226)); - insert_values.push_back(std::to_string(spells_new_entry.min_dist)); - insert_values.push_back(std::to_string(spells_new_entry.min_dist_mod)); - insert_values.push_back(std::to_string(spells_new_entry.max_dist)); - insert_values.push_back(std::to_string(spells_new_entry.max_dist_mod)); - insert_values.push_back(std::to_string(spells_new_entry.min_range)); - insert_values.push_back(std::to_string(spells_new_entry.field232)); - insert_values.push_back(std::to_string(spells_new_entry.field233)); - insert_values.push_back(std::to_string(spells_new_entry.field234)); - insert_values.push_back(std::to_string(spells_new_entry.field235)); - insert_values.push_back(std::to_string(spells_new_entry.field236)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.player_1) + "'"); + v.push_back("'" + Strings::Escape(e.teleport_zone) + "'"); + v.push_back("'" + Strings::Escape(e.you_cast) + "'"); + v.push_back("'" + Strings::Escape(e.other_casts) + "'"); + v.push_back("'" + Strings::Escape(e.cast_on_you) + "'"); + v.push_back("'" + Strings::Escape(e.cast_on_other) + "'"); + v.push_back("'" + Strings::Escape(e.spell_fades) + "'"); + v.push_back(std::to_string(e.range)); + v.push_back(std::to_string(e.aoerange)); + v.push_back(std::to_string(e.pushback)); + v.push_back(std::to_string(e.pushup)); + v.push_back(std::to_string(e.cast_time)); + v.push_back(std::to_string(e.recovery_time)); + v.push_back(std::to_string(e.recast_time)); + v.push_back(std::to_string(e.buffdurationformula)); + v.push_back(std::to_string(e.buffduration)); + v.push_back(std::to_string(e.AEDuration)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.effect_base_value1)); + v.push_back(std::to_string(e.effect_base_value2)); + v.push_back(std::to_string(e.effect_base_value3)); + v.push_back(std::to_string(e.effect_base_value4)); + v.push_back(std::to_string(e.effect_base_value5)); + v.push_back(std::to_string(e.effect_base_value6)); + v.push_back(std::to_string(e.effect_base_value7)); + v.push_back(std::to_string(e.effect_base_value8)); + v.push_back(std::to_string(e.effect_base_value9)); + v.push_back(std::to_string(e.effect_base_value10)); + v.push_back(std::to_string(e.effect_base_value11)); + v.push_back(std::to_string(e.effect_base_value12)); + v.push_back(std::to_string(e.effect_limit_value1)); + v.push_back(std::to_string(e.effect_limit_value2)); + v.push_back(std::to_string(e.effect_limit_value3)); + v.push_back(std::to_string(e.effect_limit_value4)); + v.push_back(std::to_string(e.effect_limit_value5)); + v.push_back(std::to_string(e.effect_limit_value6)); + v.push_back(std::to_string(e.effect_limit_value7)); + v.push_back(std::to_string(e.effect_limit_value8)); + v.push_back(std::to_string(e.effect_limit_value9)); + v.push_back(std::to_string(e.effect_limit_value10)); + v.push_back(std::to_string(e.effect_limit_value11)); + v.push_back(std::to_string(e.effect_limit_value12)); + v.push_back(std::to_string(e.max1)); + v.push_back(std::to_string(e.max2)); + v.push_back(std::to_string(e.max3)); + v.push_back(std::to_string(e.max4)); + v.push_back(std::to_string(e.max5)); + v.push_back(std::to_string(e.max6)); + v.push_back(std::to_string(e.max7)); + v.push_back(std::to_string(e.max8)); + v.push_back(std::to_string(e.max9)); + v.push_back(std::to_string(e.max10)); + v.push_back(std::to_string(e.max11)); + v.push_back(std::to_string(e.max12)); + v.push_back(std::to_string(e.icon)); + v.push_back(std::to_string(e.memicon)); + v.push_back(std::to_string(e.components1)); + v.push_back(std::to_string(e.components2)); + v.push_back(std::to_string(e.components3)); + v.push_back(std::to_string(e.components4)); + v.push_back(std::to_string(e.component_counts1)); + v.push_back(std::to_string(e.component_counts2)); + v.push_back(std::to_string(e.component_counts3)); + v.push_back(std::to_string(e.component_counts4)); + v.push_back(std::to_string(e.NoexpendReagent1)); + v.push_back(std::to_string(e.NoexpendReagent2)); + v.push_back(std::to_string(e.NoexpendReagent3)); + v.push_back(std::to_string(e.NoexpendReagent4)); + v.push_back(std::to_string(e.formula1)); + v.push_back(std::to_string(e.formula2)); + v.push_back(std::to_string(e.formula3)); + v.push_back(std::to_string(e.formula4)); + v.push_back(std::to_string(e.formula5)); + v.push_back(std::to_string(e.formula6)); + v.push_back(std::to_string(e.formula7)); + v.push_back(std::to_string(e.formula8)); + v.push_back(std::to_string(e.formula9)); + v.push_back(std::to_string(e.formula10)); + v.push_back(std::to_string(e.formula11)); + v.push_back(std::to_string(e.formula12)); + v.push_back(std::to_string(e.LightType)); + v.push_back(std::to_string(e.goodEffect)); + v.push_back(std::to_string(e.Activated)); + v.push_back(std::to_string(e.resisttype)); + v.push_back(std::to_string(e.effectid1)); + v.push_back(std::to_string(e.effectid2)); + v.push_back(std::to_string(e.effectid3)); + v.push_back(std::to_string(e.effectid4)); + v.push_back(std::to_string(e.effectid5)); + v.push_back(std::to_string(e.effectid6)); + v.push_back(std::to_string(e.effectid7)); + v.push_back(std::to_string(e.effectid8)); + v.push_back(std::to_string(e.effectid9)); + v.push_back(std::to_string(e.effectid10)); + v.push_back(std::to_string(e.effectid11)); + v.push_back(std::to_string(e.effectid12)); + v.push_back(std::to_string(e.targettype)); + v.push_back(std::to_string(e.basediff)); + v.push_back(std::to_string(e.skill)); + v.push_back(std::to_string(e.zonetype)); + v.push_back(std::to_string(e.EnvironmentType)); + v.push_back(std::to_string(e.TimeOfDay)); + v.push_back(std::to_string(e.classes1)); + v.push_back(std::to_string(e.classes2)); + v.push_back(std::to_string(e.classes3)); + v.push_back(std::to_string(e.classes4)); + v.push_back(std::to_string(e.classes5)); + v.push_back(std::to_string(e.classes6)); + v.push_back(std::to_string(e.classes7)); + v.push_back(std::to_string(e.classes8)); + v.push_back(std::to_string(e.classes9)); + v.push_back(std::to_string(e.classes10)); + v.push_back(std::to_string(e.classes11)); + v.push_back(std::to_string(e.classes12)); + v.push_back(std::to_string(e.classes13)); + v.push_back(std::to_string(e.classes14)); + v.push_back(std::to_string(e.classes15)); + v.push_back(std::to_string(e.classes16)); + v.push_back(std::to_string(e.CastingAnim)); + v.push_back(std::to_string(e.TargetAnim)); + v.push_back(std::to_string(e.TravelType)); + v.push_back(std::to_string(e.SpellAffectIndex)); + v.push_back(std::to_string(e.disallow_sit)); + v.push_back(std::to_string(e.deities0)); + v.push_back(std::to_string(e.deities1)); + v.push_back(std::to_string(e.deities2)); + v.push_back(std::to_string(e.deities3)); + v.push_back(std::to_string(e.deities4)); + v.push_back(std::to_string(e.deities5)); + v.push_back(std::to_string(e.deities6)); + v.push_back(std::to_string(e.deities7)); + v.push_back(std::to_string(e.deities8)); + v.push_back(std::to_string(e.deities9)); + v.push_back(std::to_string(e.deities10)); + v.push_back(std::to_string(e.deities11)); + v.push_back(std::to_string(e.deities12)); + v.push_back(std::to_string(e.deities13)); + v.push_back(std::to_string(e.deities14)); + v.push_back(std::to_string(e.deities15)); + v.push_back(std::to_string(e.deities16)); + v.push_back(std::to_string(e.field142)); + v.push_back(std::to_string(e.field143)); + v.push_back(std::to_string(e.new_icon)); + v.push_back(std::to_string(e.spellanim)); + v.push_back(std::to_string(e.uninterruptable)); + v.push_back(std::to_string(e.ResistDiff)); + v.push_back(std::to_string(e.dot_stacking_exempt)); + v.push_back(std::to_string(e.deleteable)); + v.push_back(std::to_string(e.RecourseLink)); + v.push_back(std::to_string(e.no_partial_resist)); + v.push_back(std::to_string(e.field152)); + v.push_back(std::to_string(e.field153)); + v.push_back(std::to_string(e.short_buff_box)); + v.push_back(std::to_string(e.descnum)); + v.push_back(std::to_string(e.typedescnum)); + v.push_back(std::to_string(e.effectdescnum)); + v.push_back(std::to_string(e.effectdescnum2)); + v.push_back(std::to_string(e.npc_no_los)); + v.push_back(std::to_string(e.field160)); + v.push_back(std::to_string(e.reflectable)); + v.push_back(std::to_string(e.bonushate)); + v.push_back(std::to_string(e.field163)); + v.push_back(std::to_string(e.field164)); + v.push_back(std::to_string(e.ldon_trap)); + v.push_back(std::to_string(e.EndurCost)); + v.push_back(std::to_string(e.EndurTimerIndex)); + v.push_back(std::to_string(e.IsDiscipline)); + v.push_back(std::to_string(e.field169)); + v.push_back(std::to_string(e.field170)); + v.push_back(std::to_string(e.field171)); + v.push_back(std::to_string(e.field172)); + v.push_back(std::to_string(e.HateAdded)); + v.push_back(std::to_string(e.EndurUpkeep)); + v.push_back(std::to_string(e.numhitstype)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.pvpresistbase)); + v.push_back(std::to_string(e.pvpresistcalc)); + v.push_back(std::to_string(e.pvpresistcap)); + v.push_back(std::to_string(e.spell_category)); + v.push_back(std::to_string(e.pvp_duration)); + v.push_back(std::to_string(e.pvp_duration_cap)); + v.push_back(std::to_string(e.pcnpc_only_flag)); + v.push_back(std::to_string(e.cast_not_standing)); + v.push_back(std::to_string(e.can_mgb)); + v.push_back(std::to_string(e.nodispell)); + v.push_back(std::to_string(e.npc_category)); + v.push_back(std::to_string(e.npc_usefulness)); + v.push_back(std::to_string(e.MinResist)); + v.push_back(std::to_string(e.MaxResist)); + v.push_back(std::to_string(e.viral_targets)); + v.push_back(std::to_string(e.viral_timer)); + v.push_back(std::to_string(e.nimbuseffect)); + v.push_back(std::to_string(e.ConeStartAngle)); + v.push_back(std::to_string(e.ConeStopAngle)); + v.push_back(std::to_string(e.sneaking)); + v.push_back(std::to_string(e.not_extendable)); + v.push_back(std::to_string(e.field198)); + v.push_back(std::to_string(e.field199)); + v.push_back(std::to_string(e.suspendable)); + v.push_back(std::to_string(e.viral_range)); + v.push_back(std::to_string(e.songcap)); + v.push_back(std::to_string(e.field203)); + v.push_back(std::to_string(e.field204)); + v.push_back(std::to_string(e.no_block)); + v.push_back(std::to_string(e.field206)); + v.push_back(std::to_string(e.spellgroup)); + v.push_back(std::to_string(e.rank)); + v.push_back(std::to_string(e.field209)); + v.push_back(std::to_string(e.field210)); + v.push_back(std::to_string(e.CastRestriction)); + v.push_back(std::to_string(e.allowrest)); + v.push_back(std::to_string(e.InCombat)); + v.push_back(std::to_string(e.OutofCombat)); + v.push_back(std::to_string(e.field215)); + v.push_back(std::to_string(e.field216)); + v.push_back(std::to_string(e.field217)); + v.push_back(std::to_string(e.aemaxtargets)); + v.push_back(std::to_string(e.maxtargets)); + v.push_back(std::to_string(e.field220)); + v.push_back(std::to_string(e.field221)); + v.push_back(std::to_string(e.field222)); + v.push_back(std::to_string(e.field223)); + v.push_back(std::to_string(e.persistdeath)); + v.push_back(std::to_string(e.field225)); + v.push_back(std::to_string(e.field226)); + v.push_back(std::to_string(e.min_dist)); + v.push_back(std::to_string(e.min_dist_mod)); + v.push_back(std::to_string(e.max_dist)); + v.push_back(std::to_string(e.max_dist_mod)); + v.push_back(std::to_string(e.min_range)); + v.push_back(std::to_string(e.field232)); + v.push_back(std::to_string(e.field233)); + v.push_back(std::to_string(e.field234)); + v.push_back(std::to_string(e.field235)); + v.push_back(std::to_string(e.field236)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - spells_new_entry.id = results.LastInsertedID(); - return spells_new_entry; + e.id = results.LastInsertedID(); + return e; } - spells_new_entry = NewEntity(); + e = NewEntity(); - return spells_new_entry; + return e; } static int InsertMany( Database& db, - std::vector spells_new_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &spells_new_entry: spells_new_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(spells_new_entry.id)); - insert_values.push_back("'" + EscapeString(spells_new_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.player_1) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.teleport_zone) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.you_cast) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.other_casts) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.cast_on_you) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.cast_on_other) + "'"); - insert_values.push_back("'" + EscapeString(spells_new_entry.spell_fades) + "'"); - insert_values.push_back(std::to_string(spells_new_entry.range)); - insert_values.push_back(std::to_string(spells_new_entry.aoerange)); - insert_values.push_back(std::to_string(spells_new_entry.pushback)); - insert_values.push_back(std::to_string(spells_new_entry.pushup)); - insert_values.push_back(std::to_string(spells_new_entry.cast_time)); - insert_values.push_back(std::to_string(spells_new_entry.recovery_time)); - insert_values.push_back(std::to_string(spells_new_entry.recast_time)); - insert_values.push_back(std::to_string(spells_new_entry.buffdurationformula)); - insert_values.push_back(std::to_string(spells_new_entry.buffduration)); - insert_values.push_back(std::to_string(spells_new_entry.AEDuration)); - insert_values.push_back(std::to_string(spells_new_entry.mana)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value1)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value2)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value3)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value4)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value5)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value6)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value7)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value8)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value9)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value10)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value11)); - insert_values.push_back(std::to_string(spells_new_entry.effect_base_value12)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value1)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value2)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value3)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value4)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value5)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value6)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value7)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value8)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value9)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value10)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value11)); - insert_values.push_back(std::to_string(spells_new_entry.effect_limit_value12)); - insert_values.push_back(std::to_string(spells_new_entry.max1)); - insert_values.push_back(std::to_string(spells_new_entry.max2)); - insert_values.push_back(std::to_string(spells_new_entry.max3)); - insert_values.push_back(std::to_string(spells_new_entry.max4)); - insert_values.push_back(std::to_string(spells_new_entry.max5)); - insert_values.push_back(std::to_string(spells_new_entry.max6)); - insert_values.push_back(std::to_string(spells_new_entry.max7)); - insert_values.push_back(std::to_string(spells_new_entry.max8)); - insert_values.push_back(std::to_string(spells_new_entry.max9)); - insert_values.push_back(std::to_string(spells_new_entry.max10)); - insert_values.push_back(std::to_string(spells_new_entry.max11)); - insert_values.push_back(std::to_string(spells_new_entry.max12)); - insert_values.push_back(std::to_string(spells_new_entry.icon)); - insert_values.push_back(std::to_string(spells_new_entry.memicon)); - insert_values.push_back(std::to_string(spells_new_entry.components1)); - insert_values.push_back(std::to_string(spells_new_entry.components2)); - insert_values.push_back(std::to_string(spells_new_entry.components3)); - insert_values.push_back(std::to_string(spells_new_entry.components4)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts1)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts2)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts3)); - insert_values.push_back(std::to_string(spells_new_entry.component_counts4)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent1)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent2)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent3)); - insert_values.push_back(std::to_string(spells_new_entry.NoexpendReagent4)); - insert_values.push_back(std::to_string(spells_new_entry.formula1)); - insert_values.push_back(std::to_string(spells_new_entry.formula2)); - insert_values.push_back(std::to_string(spells_new_entry.formula3)); - insert_values.push_back(std::to_string(spells_new_entry.formula4)); - insert_values.push_back(std::to_string(spells_new_entry.formula5)); - insert_values.push_back(std::to_string(spells_new_entry.formula6)); - insert_values.push_back(std::to_string(spells_new_entry.formula7)); - insert_values.push_back(std::to_string(spells_new_entry.formula8)); - insert_values.push_back(std::to_string(spells_new_entry.formula9)); - insert_values.push_back(std::to_string(spells_new_entry.formula10)); - insert_values.push_back(std::to_string(spells_new_entry.formula11)); - insert_values.push_back(std::to_string(spells_new_entry.formula12)); - insert_values.push_back(std::to_string(spells_new_entry.LightType)); - insert_values.push_back(std::to_string(spells_new_entry.goodEffect)); - insert_values.push_back(std::to_string(spells_new_entry.Activated)); - insert_values.push_back(std::to_string(spells_new_entry.resisttype)); - insert_values.push_back(std::to_string(spells_new_entry.effectid1)); - insert_values.push_back(std::to_string(spells_new_entry.effectid2)); - insert_values.push_back(std::to_string(spells_new_entry.effectid3)); - insert_values.push_back(std::to_string(spells_new_entry.effectid4)); - insert_values.push_back(std::to_string(spells_new_entry.effectid5)); - insert_values.push_back(std::to_string(spells_new_entry.effectid6)); - insert_values.push_back(std::to_string(spells_new_entry.effectid7)); - insert_values.push_back(std::to_string(spells_new_entry.effectid8)); - insert_values.push_back(std::to_string(spells_new_entry.effectid9)); - insert_values.push_back(std::to_string(spells_new_entry.effectid10)); - insert_values.push_back(std::to_string(spells_new_entry.effectid11)); - insert_values.push_back(std::to_string(spells_new_entry.effectid12)); - insert_values.push_back(std::to_string(spells_new_entry.targettype)); - insert_values.push_back(std::to_string(spells_new_entry.basediff)); - insert_values.push_back(std::to_string(spells_new_entry.skill)); - insert_values.push_back(std::to_string(spells_new_entry.zonetype)); - insert_values.push_back(std::to_string(spells_new_entry.EnvironmentType)); - insert_values.push_back(std::to_string(spells_new_entry.TimeOfDay)); - insert_values.push_back(std::to_string(spells_new_entry.classes1)); - insert_values.push_back(std::to_string(spells_new_entry.classes2)); - insert_values.push_back(std::to_string(spells_new_entry.classes3)); - insert_values.push_back(std::to_string(spells_new_entry.classes4)); - insert_values.push_back(std::to_string(spells_new_entry.classes5)); - insert_values.push_back(std::to_string(spells_new_entry.classes6)); - insert_values.push_back(std::to_string(spells_new_entry.classes7)); - insert_values.push_back(std::to_string(spells_new_entry.classes8)); - insert_values.push_back(std::to_string(spells_new_entry.classes9)); - insert_values.push_back(std::to_string(spells_new_entry.classes10)); - insert_values.push_back(std::to_string(spells_new_entry.classes11)); - insert_values.push_back(std::to_string(spells_new_entry.classes12)); - insert_values.push_back(std::to_string(spells_new_entry.classes13)); - insert_values.push_back(std::to_string(spells_new_entry.classes14)); - insert_values.push_back(std::to_string(spells_new_entry.classes15)); - insert_values.push_back(std::to_string(spells_new_entry.classes16)); - insert_values.push_back(std::to_string(spells_new_entry.CastingAnim)); - insert_values.push_back(std::to_string(spells_new_entry.TargetAnim)); - insert_values.push_back(std::to_string(spells_new_entry.TravelType)); - insert_values.push_back(std::to_string(spells_new_entry.SpellAffectIndex)); - insert_values.push_back(std::to_string(spells_new_entry.disallow_sit)); - insert_values.push_back(std::to_string(spells_new_entry.deities0)); - insert_values.push_back(std::to_string(spells_new_entry.deities1)); - insert_values.push_back(std::to_string(spells_new_entry.deities2)); - insert_values.push_back(std::to_string(spells_new_entry.deities3)); - insert_values.push_back(std::to_string(spells_new_entry.deities4)); - insert_values.push_back(std::to_string(spells_new_entry.deities5)); - insert_values.push_back(std::to_string(spells_new_entry.deities6)); - insert_values.push_back(std::to_string(spells_new_entry.deities7)); - insert_values.push_back(std::to_string(spells_new_entry.deities8)); - insert_values.push_back(std::to_string(spells_new_entry.deities9)); - insert_values.push_back(std::to_string(spells_new_entry.deities10)); - insert_values.push_back(std::to_string(spells_new_entry.deities11)); - insert_values.push_back(std::to_string(spells_new_entry.deities12)); - insert_values.push_back(std::to_string(spells_new_entry.deities13)); - insert_values.push_back(std::to_string(spells_new_entry.deities14)); - insert_values.push_back(std::to_string(spells_new_entry.deities15)); - insert_values.push_back(std::to_string(spells_new_entry.deities16)); - insert_values.push_back(std::to_string(spells_new_entry.field142)); - insert_values.push_back(std::to_string(spells_new_entry.field143)); - insert_values.push_back(std::to_string(spells_new_entry.new_icon)); - insert_values.push_back(std::to_string(spells_new_entry.spellanim)); - insert_values.push_back(std::to_string(spells_new_entry.uninterruptable)); - insert_values.push_back(std::to_string(spells_new_entry.ResistDiff)); - insert_values.push_back(std::to_string(spells_new_entry.dot_stacking_exempt)); - insert_values.push_back(std::to_string(spells_new_entry.deleteable)); - insert_values.push_back(std::to_string(spells_new_entry.RecourseLink)); - insert_values.push_back(std::to_string(spells_new_entry.no_partial_resist)); - insert_values.push_back(std::to_string(spells_new_entry.field152)); - insert_values.push_back(std::to_string(spells_new_entry.field153)); - insert_values.push_back(std::to_string(spells_new_entry.short_buff_box)); - insert_values.push_back(std::to_string(spells_new_entry.descnum)); - insert_values.push_back(std::to_string(spells_new_entry.typedescnum)); - insert_values.push_back(std::to_string(spells_new_entry.effectdescnum)); - insert_values.push_back(std::to_string(spells_new_entry.effectdescnum2)); - insert_values.push_back(std::to_string(spells_new_entry.npc_no_los)); - insert_values.push_back(std::to_string(spells_new_entry.field160)); - insert_values.push_back(std::to_string(spells_new_entry.reflectable)); - insert_values.push_back(std::to_string(spells_new_entry.bonushate)); - insert_values.push_back(std::to_string(spells_new_entry.field163)); - insert_values.push_back(std::to_string(spells_new_entry.field164)); - insert_values.push_back(std::to_string(spells_new_entry.ldon_trap)); - insert_values.push_back(std::to_string(spells_new_entry.EndurCost)); - insert_values.push_back(std::to_string(spells_new_entry.EndurTimerIndex)); - insert_values.push_back(std::to_string(spells_new_entry.IsDiscipline)); - insert_values.push_back(std::to_string(spells_new_entry.field169)); - insert_values.push_back(std::to_string(spells_new_entry.field170)); - insert_values.push_back(std::to_string(spells_new_entry.field171)); - insert_values.push_back(std::to_string(spells_new_entry.field172)); - insert_values.push_back(std::to_string(spells_new_entry.HateAdded)); - insert_values.push_back(std::to_string(spells_new_entry.EndurUpkeep)); - insert_values.push_back(std::to_string(spells_new_entry.numhitstype)); - insert_values.push_back(std::to_string(spells_new_entry.numhits)); - insert_values.push_back(std::to_string(spells_new_entry.pvpresistbase)); - insert_values.push_back(std::to_string(spells_new_entry.pvpresistcalc)); - insert_values.push_back(std::to_string(spells_new_entry.pvpresistcap)); - insert_values.push_back(std::to_string(spells_new_entry.spell_category)); - insert_values.push_back(std::to_string(spells_new_entry.pvp_duration)); - insert_values.push_back(std::to_string(spells_new_entry.pvp_duration_cap)); - insert_values.push_back(std::to_string(spells_new_entry.pcnpc_only_flag)); - insert_values.push_back(std::to_string(spells_new_entry.cast_not_standing)); - insert_values.push_back(std::to_string(spells_new_entry.can_mgb)); - insert_values.push_back(std::to_string(spells_new_entry.nodispell)); - insert_values.push_back(std::to_string(spells_new_entry.npc_category)); - insert_values.push_back(std::to_string(spells_new_entry.npc_usefulness)); - insert_values.push_back(std::to_string(spells_new_entry.MinResist)); - insert_values.push_back(std::to_string(spells_new_entry.MaxResist)); - insert_values.push_back(std::to_string(spells_new_entry.viral_targets)); - insert_values.push_back(std::to_string(spells_new_entry.viral_timer)); - insert_values.push_back(std::to_string(spells_new_entry.nimbuseffect)); - insert_values.push_back(std::to_string(spells_new_entry.ConeStartAngle)); - insert_values.push_back(std::to_string(spells_new_entry.ConeStopAngle)); - insert_values.push_back(std::to_string(spells_new_entry.sneaking)); - insert_values.push_back(std::to_string(spells_new_entry.not_extendable)); - insert_values.push_back(std::to_string(spells_new_entry.field198)); - insert_values.push_back(std::to_string(spells_new_entry.field199)); - insert_values.push_back(std::to_string(spells_new_entry.suspendable)); - insert_values.push_back(std::to_string(spells_new_entry.viral_range)); - insert_values.push_back(std::to_string(spells_new_entry.songcap)); - insert_values.push_back(std::to_string(spells_new_entry.field203)); - insert_values.push_back(std::to_string(spells_new_entry.field204)); - insert_values.push_back(std::to_string(spells_new_entry.no_block)); - insert_values.push_back(std::to_string(spells_new_entry.field206)); - insert_values.push_back(std::to_string(spells_new_entry.spellgroup)); - insert_values.push_back(std::to_string(spells_new_entry.rank)); - insert_values.push_back(std::to_string(spells_new_entry.field209)); - insert_values.push_back(std::to_string(spells_new_entry.field210)); - insert_values.push_back(std::to_string(spells_new_entry.CastRestriction)); - insert_values.push_back(std::to_string(spells_new_entry.allowrest)); - insert_values.push_back(std::to_string(spells_new_entry.InCombat)); - insert_values.push_back(std::to_string(spells_new_entry.OutofCombat)); - insert_values.push_back(std::to_string(spells_new_entry.field215)); - insert_values.push_back(std::to_string(spells_new_entry.field216)); - insert_values.push_back(std::to_string(spells_new_entry.field217)); - insert_values.push_back(std::to_string(spells_new_entry.aemaxtargets)); - insert_values.push_back(std::to_string(spells_new_entry.maxtargets)); - insert_values.push_back(std::to_string(spells_new_entry.field220)); - insert_values.push_back(std::to_string(spells_new_entry.field221)); - insert_values.push_back(std::to_string(spells_new_entry.field222)); - insert_values.push_back(std::to_string(spells_new_entry.field223)); - insert_values.push_back(std::to_string(spells_new_entry.persistdeath)); - insert_values.push_back(std::to_string(spells_new_entry.field225)); - insert_values.push_back(std::to_string(spells_new_entry.field226)); - insert_values.push_back(std::to_string(spells_new_entry.min_dist)); - insert_values.push_back(std::to_string(spells_new_entry.min_dist_mod)); - insert_values.push_back(std::to_string(spells_new_entry.max_dist)); - insert_values.push_back(std::to_string(spells_new_entry.max_dist_mod)); - insert_values.push_back(std::to_string(spells_new_entry.min_range)); - insert_values.push_back(std::to_string(spells_new_entry.field232)); - insert_values.push_back(std::to_string(spells_new_entry.field233)); - insert_values.push_back(std::to_string(spells_new_entry.field234)); - insert_values.push_back(std::to_string(spells_new_entry.field235)); - insert_values.push_back(std::to_string(spells_new_entry.field236)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.player_1) + "'"); + v.push_back("'" + Strings::Escape(e.teleport_zone) + "'"); + v.push_back("'" + Strings::Escape(e.you_cast) + "'"); + v.push_back("'" + Strings::Escape(e.other_casts) + "'"); + v.push_back("'" + Strings::Escape(e.cast_on_you) + "'"); + v.push_back("'" + Strings::Escape(e.cast_on_other) + "'"); + v.push_back("'" + Strings::Escape(e.spell_fades) + "'"); + v.push_back(std::to_string(e.range)); + v.push_back(std::to_string(e.aoerange)); + v.push_back(std::to_string(e.pushback)); + v.push_back(std::to_string(e.pushup)); + v.push_back(std::to_string(e.cast_time)); + v.push_back(std::to_string(e.recovery_time)); + v.push_back(std::to_string(e.recast_time)); + v.push_back(std::to_string(e.buffdurationformula)); + v.push_back(std::to_string(e.buffduration)); + v.push_back(std::to_string(e.AEDuration)); + v.push_back(std::to_string(e.mana)); + v.push_back(std::to_string(e.effect_base_value1)); + v.push_back(std::to_string(e.effect_base_value2)); + v.push_back(std::to_string(e.effect_base_value3)); + v.push_back(std::to_string(e.effect_base_value4)); + v.push_back(std::to_string(e.effect_base_value5)); + v.push_back(std::to_string(e.effect_base_value6)); + v.push_back(std::to_string(e.effect_base_value7)); + v.push_back(std::to_string(e.effect_base_value8)); + v.push_back(std::to_string(e.effect_base_value9)); + v.push_back(std::to_string(e.effect_base_value10)); + v.push_back(std::to_string(e.effect_base_value11)); + v.push_back(std::to_string(e.effect_base_value12)); + v.push_back(std::to_string(e.effect_limit_value1)); + v.push_back(std::to_string(e.effect_limit_value2)); + v.push_back(std::to_string(e.effect_limit_value3)); + v.push_back(std::to_string(e.effect_limit_value4)); + v.push_back(std::to_string(e.effect_limit_value5)); + v.push_back(std::to_string(e.effect_limit_value6)); + v.push_back(std::to_string(e.effect_limit_value7)); + v.push_back(std::to_string(e.effect_limit_value8)); + v.push_back(std::to_string(e.effect_limit_value9)); + v.push_back(std::to_string(e.effect_limit_value10)); + v.push_back(std::to_string(e.effect_limit_value11)); + v.push_back(std::to_string(e.effect_limit_value12)); + v.push_back(std::to_string(e.max1)); + v.push_back(std::to_string(e.max2)); + v.push_back(std::to_string(e.max3)); + v.push_back(std::to_string(e.max4)); + v.push_back(std::to_string(e.max5)); + v.push_back(std::to_string(e.max6)); + v.push_back(std::to_string(e.max7)); + v.push_back(std::to_string(e.max8)); + v.push_back(std::to_string(e.max9)); + v.push_back(std::to_string(e.max10)); + v.push_back(std::to_string(e.max11)); + v.push_back(std::to_string(e.max12)); + v.push_back(std::to_string(e.icon)); + v.push_back(std::to_string(e.memicon)); + v.push_back(std::to_string(e.components1)); + v.push_back(std::to_string(e.components2)); + v.push_back(std::to_string(e.components3)); + v.push_back(std::to_string(e.components4)); + v.push_back(std::to_string(e.component_counts1)); + v.push_back(std::to_string(e.component_counts2)); + v.push_back(std::to_string(e.component_counts3)); + v.push_back(std::to_string(e.component_counts4)); + v.push_back(std::to_string(e.NoexpendReagent1)); + v.push_back(std::to_string(e.NoexpendReagent2)); + v.push_back(std::to_string(e.NoexpendReagent3)); + v.push_back(std::to_string(e.NoexpendReagent4)); + v.push_back(std::to_string(e.formula1)); + v.push_back(std::to_string(e.formula2)); + v.push_back(std::to_string(e.formula3)); + v.push_back(std::to_string(e.formula4)); + v.push_back(std::to_string(e.formula5)); + v.push_back(std::to_string(e.formula6)); + v.push_back(std::to_string(e.formula7)); + v.push_back(std::to_string(e.formula8)); + v.push_back(std::to_string(e.formula9)); + v.push_back(std::to_string(e.formula10)); + v.push_back(std::to_string(e.formula11)); + v.push_back(std::to_string(e.formula12)); + v.push_back(std::to_string(e.LightType)); + v.push_back(std::to_string(e.goodEffect)); + v.push_back(std::to_string(e.Activated)); + v.push_back(std::to_string(e.resisttype)); + v.push_back(std::to_string(e.effectid1)); + v.push_back(std::to_string(e.effectid2)); + v.push_back(std::to_string(e.effectid3)); + v.push_back(std::to_string(e.effectid4)); + v.push_back(std::to_string(e.effectid5)); + v.push_back(std::to_string(e.effectid6)); + v.push_back(std::to_string(e.effectid7)); + v.push_back(std::to_string(e.effectid8)); + v.push_back(std::to_string(e.effectid9)); + v.push_back(std::to_string(e.effectid10)); + v.push_back(std::to_string(e.effectid11)); + v.push_back(std::to_string(e.effectid12)); + v.push_back(std::to_string(e.targettype)); + v.push_back(std::to_string(e.basediff)); + v.push_back(std::to_string(e.skill)); + v.push_back(std::to_string(e.zonetype)); + v.push_back(std::to_string(e.EnvironmentType)); + v.push_back(std::to_string(e.TimeOfDay)); + v.push_back(std::to_string(e.classes1)); + v.push_back(std::to_string(e.classes2)); + v.push_back(std::to_string(e.classes3)); + v.push_back(std::to_string(e.classes4)); + v.push_back(std::to_string(e.classes5)); + v.push_back(std::to_string(e.classes6)); + v.push_back(std::to_string(e.classes7)); + v.push_back(std::to_string(e.classes8)); + v.push_back(std::to_string(e.classes9)); + v.push_back(std::to_string(e.classes10)); + v.push_back(std::to_string(e.classes11)); + v.push_back(std::to_string(e.classes12)); + v.push_back(std::to_string(e.classes13)); + v.push_back(std::to_string(e.classes14)); + v.push_back(std::to_string(e.classes15)); + v.push_back(std::to_string(e.classes16)); + v.push_back(std::to_string(e.CastingAnim)); + v.push_back(std::to_string(e.TargetAnim)); + v.push_back(std::to_string(e.TravelType)); + v.push_back(std::to_string(e.SpellAffectIndex)); + v.push_back(std::to_string(e.disallow_sit)); + v.push_back(std::to_string(e.deities0)); + v.push_back(std::to_string(e.deities1)); + v.push_back(std::to_string(e.deities2)); + v.push_back(std::to_string(e.deities3)); + v.push_back(std::to_string(e.deities4)); + v.push_back(std::to_string(e.deities5)); + v.push_back(std::to_string(e.deities6)); + v.push_back(std::to_string(e.deities7)); + v.push_back(std::to_string(e.deities8)); + v.push_back(std::to_string(e.deities9)); + v.push_back(std::to_string(e.deities10)); + v.push_back(std::to_string(e.deities11)); + v.push_back(std::to_string(e.deities12)); + v.push_back(std::to_string(e.deities13)); + v.push_back(std::to_string(e.deities14)); + v.push_back(std::to_string(e.deities15)); + v.push_back(std::to_string(e.deities16)); + v.push_back(std::to_string(e.field142)); + v.push_back(std::to_string(e.field143)); + v.push_back(std::to_string(e.new_icon)); + v.push_back(std::to_string(e.spellanim)); + v.push_back(std::to_string(e.uninterruptable)); + v.push_back(std::to_string(e.ResistDiff)); + v.push_back(std::to_string(e.dot_stacking_exempt)); + v.push_back(std::to_string(e.deleteable)); + v.push_back(std::to_string(e.RecourseLink)); + v.push_back(std::to_string(e.no_partial_resist)); + v.push_back(std::to_string(e.field152)); + v.push_back(std::to_string(e.field153)); + v.push_back(std::to_string(e.short_buff_box)); + v.push_back(std::to_string(e.descnum)); + v.push_back(std::to_string(e.typedescnum)); + v.push_back(std::to_string(e.effectdescnum)); + v.push_back(std::to_string(e.effectdescnum2)); + v.push_back(std::to_string(e.npc_no_los)); + v.push_back(std::to_string(e.field160)); + v.push_back(std::to_string(e.reflectable)); + v.push_back(std::to_string(e.bonushate)); + v.push_back(std::to_string(e.field163)); + v.push_back(std::to_string(e.field164)); + v.push_back(std::to_string(e.ldon_trap)); + v.push_back(std::to_string(e.EndurCost)); + v.push_back(std::to_string(e.EndurTimerIndex)); + v.push_back(std::to_string(e.IsDiscipline)); + v.push_back(std::to_string(e.field169)); + v.push_back(std::to_string(e.field170)); + v.push_back(std::to_string(e.field171)); + v.push_back(std::to_string(e.field172)); + v.push_back(std::to_string(e.HateAdded)); + v.push_back(std::to_string(e.EndurUpkeep)); + v.push_back(std::to_string(e.numhitstype)); + v.push_back(std::to_string(e.numhits)); + v.push_back(std::to_string(e.pvpresistbase)); + v.push_back(std::to_string(e.pvpresistcalc)); + v.push_back(std::to_string(e.pvpresistcap)); + v.push_back(std::to_string(e.spell_category)); + v.push_back(std::to_string(e.pvp_duration)); + v.push_back(std::to_string(e.pvp_duration_cap)); + v.push_back(std::to_string(e.pcnpc_only_flag)); + v.push_back(std::to_string(e.cast_not_standing)); + v.push_back(std::to_string(e.can_mgb)); + v.push_back(std::to_string(e.nodispell)); + v.push_back(std::to_string(e.npc_category)); + v.push_back(std::to_string(e.npc_usefulness)); + v.push_back(std::to_string(e.MinResist)); + v.push_back(std::to_string(e.MaxResist)); + v.push_back(std::to_string(e.viral_targets)); + v.push_back(std::to_string(e.viral_timer)); + v.push_back(std::to_string(e.nimbuseffect)); + v.push_back(std::to_string(e.ConeStartAngle)); + v.push_back(std::to_string(e.ConeStopAngle)); + v.push_back(std::to_string(e.sneaking)); + v.push_back(std::to_string(e.not_extendable)); + v.push_back(std::to_string(e.field198)); + v.push_back(std::to_string(e.field199)); + v.push_back(std::to_string(e.suspendable)); + v.push_back(std::to_string(e.viral_range)); + v.push_back(std::to_string(e.songcap)); + v.push_back(std::to_string(e.field203)); + v.push_back(std::to_string(e.field204)); + v.push_back(std::to_string(e.no_block)); + v.push_back(std::to_string(e.field206)); + v.push_back(std::to_string(e.spellgroup)); + v.push_back(std::to_string(e.rank)); + v.push_back(std::to_string(e.field209)); + v.push_back(std::to_string(e.field210)); + v.push_back(std::to_string(e.CastRestriction)); + v.push_back(std::to_string(e.allowrest)); + v.push_back(std::to_string(e.InCombat)); + v.push_back(std::to_string(e.OutofCombat)); + v.push_back(std::to_string(e.field215)); + v.push_back(std::to_string(e.field216)); + v.push_back(std::to_string(e.field217)); + v.push_back(std::to_string(e.aemaxtargets)); + v.push_back(std::to_string(e.maxtargets)); + v.push_back(std::to_string(e.field220)); + v.push_back(std::to_string(e.field221)); + v.push_back(std::to_string(e.field222)); + v.push_back(std::to_string(e.field223)); + v.push_back(std::to_string(e.persistdeath)); + v.push_back(std::to_string(e.field225)); + v.push_back(std::to_string(e.field226)); + v.push_back(std::to_string(e.min_dist)); + v.push_back(std::to_string(e.min_dist_mod)); + v.push_back(std::to_string(e.max_dist)); + v.push_back(std::to_string(e.max_dist_mod)); + v.push_back(std::to_string(e.min_range)); + v.push_back(std::to_string(e.field232)); + v.push_back(std::to_string(e.field233)); + v.push_back(std::to_string(e.field234)); + v.push_back(std::to_string(e.field235)); + v.push_back(std::to_string(e.field236)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -2120,253 +2120,253 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpellsNew entry{}; + SpellsNew e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.player_1 = row[2] ? row[2] : ""; - entry.teleport_zone = row[3] ? row[3] : ""; - entry.you_cast = row[4] ? row[4] : ""; - entry.other_casts = row[5] ? row[5] : ""; - entry.cast_on_you = row[6] ? row[6] : ""; - entry.cast_on_other = row[7] ? row[7] : ""; - entry.spell_fades = row[8] ? row[8] : ""; - entry.range = atoi(row[9]); - entry.aoerange = atoi(row[10]); - entry.pushback = atoi(row[11]); - entry.pushup = atoi(row[12]); - entry.cast_time = atoi(row[13]); - entry.recovery_time = atoi(row[14]); - entry.recast_time = atoi(row[15]); - entry.buffdurationformula = atoi(row[16]); - entry.buffduration = atoi(row[17]); - entry.AEDuration = atoi(row[18]); - entry.mana = atoi(row[19]); - entry.effect_base_value1 = atoi(row[20]); - entry.effect_base_value2 = atoi(row[21]); - entry.effect_base_value3 = atoi(row[22]); - entry.effect_base_value4 = atoi(row[23]); - entry.effect_base_value5 = atoi(row[24]); - entry.effect_base_value6 = atoi(row[25]); - entry.effect_base_value7 = atoi(row[26]); - entry.effect_base_value8 = atoi(row[27]); - entry.effect_base_value9 = atoi(row[28]); - entry.effect_base_value10 = atoi(row[29]); - entry.effect_base_value11 = atoi(row[30]); - entry.effect_base_value12 = atoi(row[31]); - entry.effect_limit_value1 = atoi(row[32]); - entry.effect_limit_value2 = atoi(row[33]); - entry.effect_limit_value3 = atoi(row[34]); - entry.effect_limit_value4 = atoi(row[35]); - entry.effect_limit_value5 = atoi(row[36]); - entry.effect_limit_value6 = atoi(row[37]); - entry.effect_limit_value7 = atoi(row[38]); - entry.effect_limit_value8 = atoi(row[39]); - entry.effect_limit_value9 = atoi(row[40]); - entry.effect_limit_value10 = atoi(row[41]); - entry.effect_limit_value11 = atoi(row[42]); - entry.effect_limit_value12 = atoi(row[43]); - entry.max1 = atoi(row[44]); - entry.max2 = atoi(row[45]); - entry.max3 = atoi(row[46]); - entry.max4 = atoi(row[47]); - entry.max5 = atoi(row[48]); - entry.max6 = atoi(row[49]); - entry.max7 = atoi(row[50]); - entry.max8 = atoi(row[51]); - entry.max9 = atoi(row[52]); - entry.max10 = atoi(row[53]); - entry.max11 = atoi(row[54]); - entry.max12 = atoi(row[55]); - entry.icon = atoi(row[56]); - entry.memicon = atoi(row[57]); - entry.components1 = atoi(row[58]); - entry.components2 = atoi(row[59]); - entry.components3 = atoi(row[60]); - entry.components4 = atoi(row[61]); - entry.component_counts1 = atoi(row[62]); - entry.component_counts2 = atoi(row[63]); - entry.component_counts3 = atoi(row[64]); - entry.component_counts4 = atoi(row[65]); - entry.NoexpendReagent1 = atoi(row[66]); - entry.NoexpendReagent2 = atoi(row[67]); - entry.NoexpendReagent3 = atoi(row[68]); - entry.NoexpendReagent4 = atoi(row[69]); - entry.formula1 = atoi(row[70]); - entry.formula2 = atoi(row[71]); - entry.formula3 = atoi(row[72]); - entry.formula4 = atoi(row[73]); - entry.formula5 = atoi(row[74]); - entry.formula6 = atoi(row[75]); - entry.formula7 = atoi(row[76]); - entry.formula8 = atoi(row[77]); - entry.formula9 = atoi(row[78]); - entry.formula10 = atoi(row[79]); - entry.formula11 = atoi(row[80]); - entry.formula12 = atoi(row[81]); - entry.LightType = atoi(row[82]); - entry.goodEffect = atoi(row[83]); - entry.Activated = atoi(row[84]); - entry.resisttype = atoi(row[85]); - entry.effectid1 = atoi(row[86]); - entry.effectid2 = atoi(row[87]); - entry.effectid3 = atoi(row[88]); - entry.effectid4 = atoi(row[89]); - entry.effectid5 = atoi(row[90]); - entry.effectid6 = atoi(row[91]); - entry.effectid7 = atoi(row[92]); - entry.effectid8 = atoi(row[93]); - entry.effectid9 = atoi(row[94]); - entry.effectid10 = atoi(row[95]); - entry.effectid11 = atoi(row[96]); - entry.effectid12 = atoi(row[97]); - entry.targettype = atoi(row[98]); - entry.basediff = atoi(row[99]); - entry.skill = atoi(row[100]); - entry.zonetype = atoi(row[101]); - entry.EnvironmentType = atoi(row[102]); - entry.TimeOfDay = atoi(row[103]); - entry.classes1 = atoi(row[104]); - entry.classes2 = atoi(row[105]); - entry.classes3 = atoi(row[106]); - entry.classes4 = atoi(row[107]); - entry.classes5 = atoi(row[108]); - entry.classes6 = atoi(row[109]); - entry.classes7 = atoi(row[110]); - entry.classes8 = atoi(row[111]); - entry.classes9 = atoi(row[112]); - entry.classes10 = atoi(row[113]); - entry.classes11 = atoi(row[114]); - entry.classes12 = atoi(row[115]); - entry.classes13 = atoi(row[116]); - entry.classes14 = atoi(row[117]); - entry.classes15 = atoi(row[118]); - entry.classes16 = atoi(row[119]); - entry.CastingAnim = atoi(row[120]); - entry.TargetAnim = atoi(row[121]); - entry.TravelType = atoi(row[122]); - entry.SpellAffectIndex = atoi(row[123]); - entry.disallow_sit = atoi(row[124]); - entry.deities0 = atoi(row[125]); - entry.deities1 = atoi(row[126]); - entry.deities2 = atoi(row[127]); - entry.deities3 = atoi(row[128]); - entry.deities4 = atoi(row[129]); - entry.deities5 = atoi(row[130]); - entry.deities6 = atoi(row[131]); - entry.deities7 = atoi(row[132]); - entry.deities8 = atoi(row[133]); - entry.deities9 = atoi(row[134]); - entry.deities10 = atoi(row[135]); - entry.deities11 = atoi(row[136]); - entry.deities12 = atoi(row[137]); - entry.deities13 = atoi(row[138]); - entry.deities14 = atoi(row[139]); - entry.deities15 = atoi(row[140]); - entry.deities16 = atoi(row[141]); - entry.field142 = atoi(row[142]); - entry.field143 = atoi(row[143]); - entry.new_icon = atoi(row[144]); - entry.spellanim = atoi(row[145]); - entry.uninterruptable = atoi(row[146]); - entry.ResistDiff = atoi(row[147]); - entry.dot_stacking_exempt = atoi(row[148]); - entry.deleteable = atoi(row[149]); - entry.RecourseLink = atoi(row[150]); - entry.no_partial_resist = atoi(row[151]); - entry.field152 = atoi(row[152]); - entry.field153 = atoi(row[153]); - entry.short_buff_box = atoi(row[154]); - entry.descnum = atoi(row[155]); - entry.typedescnum = atoi(row[156]); - entry.effectdescnum = atoi(row[157]); - entry.effectdescnum2 = atoi(row[158]); - entry.npc_no_los = atoi(row[159]); - entry.field160 = atoi(row[160]); - entry.reflectable = atoi(row[161]); - entry.bonushate = atoi(row[162]); - entry.field163 = atoi(row[163]); - entry.field164 = atoi(row[164]); - entry.ldon_trap = atoi(row[165]); - entry.EndurCost = atoi(row[166]); - entry.EndurTimerIndex = atoi(row[167]); - entry.IsDiscipline = atoi(row[168]); - entry.field169 = atoi(row[169]); - entry.field170 = atoi(row[170]); - entry.field171 = atoi(row[171]); - entry.field172 = atoi(row[172]); - entry.HateAdded = atoi(row[173]); - entry.EndurUpkeep = atoi(row[174]); - entry.numhitstype = atoi(row[175]); - entry.numhits = atoi(row[176]); - entry.pvpresistbase = atoi(row[177]); - entry.pvpresistcalc = atoi(row[178]); - entry.pvpresistcap = atoi(row[179]); - entry.spell_category = atoi(row[180]); - entry.pvp_duration = atoi(row[181]); - entry.pvp_duration_cap = atoi(row[182]); - entry.pcnpc_only_flag = atoi(row[183]); - entry.cast_not_standing = atoi(row[184]); - entry.can_mgb = atoi(row[185]); - entry.nodispell = atoi(row[186]); - entry.npc_category = atoi(row[187]); - entry.npc_usefulness = atoi(row[188]); - entry.MinResist = atoi(row[189]); - entry.MaxResist = atoi(row[190]); - entry.viral_targets = atoi(row[191]); - entry.viral_timer = atoi(row[192]); - entry.nimbuseffect = atoi(row[193]); - entry.ConeStartAngle = atoi(row[194]); - entry.ConeStopAngle = atoi(row[195]); - entry.sneaking = atoi(row[196]); - entry.not_extendable = atoi(row[197]); - entry.field198 = atoi(row[198]); - entry.field199 = atoi(row[199]); - entry.suspendable = atoi(row[200]); - entry.viral_range = atoi(row[201]); - entry.songcap = atoi(row[202]); - entry.field203 = atoi(row[203]); - entry.field204 = atoi(row[204]); - entry.no_block = atoi(row[205]); - entry.field206 = atoi(row[206]); - entry.spellgroup = atoi(row[207]); - entry.rank = atoi(row[208]); - entry.field209 = atoi(row[209]); - entry.field210 = atoi(row[210]); - entry.CastRestriction = atoi(row[211]); - entry.allowrest = atoi(row[212]); - entry.InCombat = atoi(row[213]); - entry.OutofCombat = atoi(row[214]); - entry.field215 = atoi(row[215]); - entry.field216 = atoi(row[216]); - entry.field217 = atoi(row[217]); - entry.aemaxtargets = atoi(row[218]); - entry.maxtargets = atoi(row[219]); - entry.field220 = atoi(row[220]); - entry.field221 = atoi(row[221]); - entry.field222 = atoi(row[222]); - entry.field223 = atoi(row[223]); - entry.persistdeath = atoi(row[224]); - entry.field225 = atoi(row[225]); - entry.field226 = atoi(row[226]); - entry.min_dist = static_cast(atof(row[227])); - entry.min_dist_mod = static_cast(atof(row[228])); - entry.max_dist = static_cast(atof(row[229])); - entry.max_dist_mod = static_cast(atof(row[230])); - entry.min_range = atoi(row[231]); - entry.field232 = atoi(row[232]); - entry.field233 = atoi(row[233]); - entry.field234 = atoi(row[234]); - entry.field235 = atoi(row[235]); - entry.field236 = atoi(row[236]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : ""; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range = static_cast(atoi(row[9])); + e.aoerange = static_cast(atoi(row[10])); + e.pushback = static_cast(atoi(row[11])); + e.pushup = static_cast(atoi(row[12])); + e.cast_time = static_cast(atoi(row[13])); + e.recovery_time = static_cast(atoi(row[14])); + e.recast_time = static_cast(atoi(row[15])); + e.buffdurationformula = static_cast(atoi(row[16])); + e.buffduration = static_cast(atoi(row[17])); + e.AEDuration = static_cast(atoi(row[18])); + e.mana = static_cast(atoi(row[19])); + e.effect_base_value1 = static_cast(atoi(row[20])); + e.effect_base_value2 = static_cast(atoi(row[21])); + e.effect_base_value3 = static_cast(atoi(row[22])); + e.effect_base_value4 = static_cast(atoi(row[23])); + e.effect_base_value5 = static_cast(atoi(row[24])); + e.effect_base_value6 = static_cast(atoi(row[25])); + e.effect_base_value7 = static_cast(atoi(row[26])); + e.effect_base_value8 = static_cast(atoi(row[27])); + e.effect_base_value9 = static_cast(atoi(row[28])); + e.effect_base_value10 = static_cast(atoi(row[29])); + e.effect_base_value11 = static_cast(atoi(row[30])); + e.effect_base_value12 = static_cast(atoi(row[31])); + e.effect_limit_value1 = static_cast(atoi(row[32])); + e.effect_limit_value2 = static_cast(atoi(row[33])); + e.effect_limit_value3 = static_cast(atoi(row[34])); + e.effect_limit_value4 = static_cast(atoi(row[35])); + e.effect_limit_value5 = static_cast(atoi(row[36])); + e.effect_limit_value6 = static_cast(atoi(row[37])); + e.effect_limit_value7 = static_cast(atoi(row[38])); + e.effect_limit_value8 = static_cast(atoi(row[39])); + e.effect_limit_value9 = static_cast(atoi(row[40])); + e.effect_limit_value10 = static_cast(atoi(row[41])); + e.effect_limit_value11 = static_cast(atoi(row[42])); + e.effect_limit_value12 = static_cast(atoi(row[43])); + e.max1 = static_cast(atoi(row[44])); + e.max2 = static_cast(atoi(row[45])); + e.max3 = static_cast(atoi(row[46])); + e.max4 = static_cast(atoi(row[47])); + e.max5 = static_cast(atoi(row[48])); + e.max6 = static_cast(atoi(row[49])); + e.max7 = static_cast(atoi(row[50])); + e.max8 = static_cast(atoi(row[51])); + e.max9 = static_cast(atoi(row[52])); + e.max10 = static_cast(atoi(row[53])); + e.max11 = static_cast(atoi(row[54])); + e.max12 = static_cast(atoi(row[55])); + e.icon = static_cast(atoi(row[56])); + e.memicon = static_cast(atoi(row[57])); + e.components1 = static_cast(atoi(row[58])); + e.components2 = static_cast(atoi(row[59])); + e.components3 = static_cast(atoi(row[60])); + e.components4 = static_cast(atoi(row[61])); + e.component_counts1 = static_cast(atoi(row[62])); + e.component_counts2 = static_cast(atoi(row[63])); + e.component_counts3 = static_cast(atoi(row[64])); + e.component_counts4 = static_cast(atoi(row[65])); + e.NoexpendReagent1 = static_cast(atoi(row[66])); + e.NoexpendReagent2 = static_cast(atoi(row[67])); + e.NoexpendReagent3 = static_cast(atoi(row[68])); + e.NoexpendReagent4 = static_cast(atoi(row[69])); + e.formula1 = static_cast(atoi(row[70])); + e.formula2 = static_cast(atoi(row[71])); + e.formula3 = static_cast(atoi(row[72])); + e.formula4 = static_cast(atoi(row[73])); + e.formula5 = static_cast(atoi(row[74])); + e.formula6 = static_cast(atoi(row[75])); + e.formula7 = static_cast(atoi(row[76])); + e.formula8 = static_cast(atoi(row[77])); + e.formula9 = static_cast(atoi(row[78])); + e.formula10 = static_cast(atoi(row[79])); + e.formula11 = static_cast(atoi(row[80])); + e.formula12 = static_cast(atoi(row[81])); + e.LightType = static_cast(atoi(row[82])); + e.goodEffect = static_cast(atoi(row[83])); + e.Activated = static_cast(atoi(row[84])); + e.resisttype = static_cast(atoi(row[85])); + e.effectid1 = static_cast(atoi(row[86])); + e.effectid2 = static_cast(atoi(row[87])); + e.effectid3 = static_cast(atoi(row[88])); + e.effectid4 = static_cast(atoi(row[89])); + e.effectid5 = static_cast(atoi(row[90])); + e.effectid6 = static_cast(atoi(row[91])); + e.effectid7 = static_cast(atoi(row[92])); + e.effectid8 = static_cast(atoi(row[93])); + e.effectid9 = static_cast(atoi(row[94])); + e.effectid10 = static_cast(atoi(row[95])); + e.effectid11 = static_cast(atoi(row[96])); + e.effectid12 = static_cast(atoi(row[97])); + e.targettype = static_cast(atoi(row[98])); + e.basediff = static_cast(atoi(row[99])); + e.skill = static_cast(atoi(row[100])); + e.zonetype = static_cast(atoi(row[101])); + e.EnvironmentType = static_cast(atoi(row[102])); + e.TimeOfDay = static_cast(atoi(row[103])); + e.classes1 = static_cast(atoi(row[104])); + e.classes2 = static_cast(atoi(row[105])); + e.classes3 = static_cast(atoi(row[106])); + e.classes4 = static_cast(atoi(row[107])); + e.classes5 = static_cast(atoi(row[108])); + e.classes6 = static_cast(atoi(row[109])); + e.classes7 = static_cast(atoi(row[110])); + e.classes8 = static_cast(atoi(row[111])); + e.classes9 = static_cast(atoi(row[112])); + e.classes10 = static_cast(atoi(row[113])); + e.classes11 = static_cast(atoi(row[114])); + e.classes12 = static_cast(atoi(row[115])); + e.classes13 = static_cast(atoi(row[116])); + e.classes14 = static_cast(atoi(row[117])); + e.classes15 = static_cast(atoi(row[118])); + e.classes16 = static_cast(atoi(row[119])); + e.CastingAnim = static_cast(atoi(row[120])); + e.TargetAnim = static_cast(atoi(row[121])); + e.TravelType = static_cast(atoi(row[122])); + e.SpellAffectIndex = static_cast(atoi(row[123])); + e.disallow_sit = static_cast(atoi(row[124])); + e.deities0 = static_cast(atoi(row[125])); + e.deities1 = static_cast(atoi(row[126])); + e.deities2 = static_cast(atoi(row[127])); + e.deities3 = static_cast(atoi(row[128])); + e.deities4 = static_cast(atoi(row[129])); + e.deities5 = static_cast(atoi(row[130])); + e.deities6 = static_cast(atoi(row[131])); + e.deities7 = static_cast(atoi(row[132])); + e.deities8 = static_cast(atoi(row[133])); + e.deities9 = static_cast(atoi(row[134])); + e.deities10 = static_cast(atoi(row[135])); + e.deities11 = static_cast(atoi(row[136])); + e.deities12 = static_cast(atoi(row[137])); + e.deities13 = static_cast(atoi(row[138])); + e.deities14 = static_cast(atoi(row[139])); + e.deities15 = static_cast(atoi(row[140])); + e.deities16 = static_cast(atoi(row[141])); + e.field142 = static_cast(atoi(row[142])); + e.field143 = static_cast(atoi(row[143])); + e.new_icon = static_cast(atoi(row[144])); + e.spellanim = static_cast(atoi(row[145])); + e.uninterruptable = static_cast(atoi(row[146])); + e.ResistDiff = static_cast(atoi(row[147])); + e.dot_stacking_exempt = static_cast(atoi(row[148])); + e.deleteable = static_cast(atoi(row[149])); + e.RecourseLink = static_cast(atoi(row[150])); + e.no_partial_resist = static_cast(atoi(row[151])); + e.field152 = static_cast(atoi(row[152])); + e.field153 = static_cast(atoi(row[153])); + e.short_buff_box = static_cast(atoi(row[154])); + e.descnum = static_cast(atoi(row[155])); + e.typedescnum = static_cast(atoi(row[156])); + e.effectdescnum = static_cast(atoi(row[157])); + e.effectdescnum2 = static_cast(atoi(row[158])); + e.npc_no_los = static_cast(atoi(row[159])); + e.field160 = static_cast(atoi(row[160])); + e.reflectable = static_cast(atoi(row[161])); + e.bonushate = static_cast(atoi(row[162])); + e.field163 = static_cast(atoi(row[163])); + e.field164 = static_cast(atoi(row[164])); + e.ldon_trap = static_cast(atoi(row[165])); + e.EndurCost = static_cast(atoi(row[166])); + e.EndurTimerIndex = static_cast(atoi(row[167])); + e.IsDiscipline = static_cast(atoi(row[168])); + e.field169 = static_cast(atoi(row[169])); + e.field170 = static_cast(atoi(row[170])); + e.field171 = static_cast(atoi(row[171])); + e.field172 = static_cast(atoi(row[172])); + e.HateAdded = static_cast(atoi(row[173])); + e.EndurUpkeep = static_cast(atoi(row[174])); + e.numhitstype = static_cast(atoi(row[175])); + e.numhits = static_cast(atoi(row[176])); + e.pvpresistbase = static_cast(atoi(row[177])); + e.pvpresistcalc = static_cast(atoi(row[178])); + e.pvpresistcap = static_cast(atoi(row[179])); + e.spell_category = static_cast(atoi(row[180])); + e.pvp_duration = static_cast(atoi(row[181])); + e.pvp_duration_cap = static_cast(atoi(row[182])); + e.pcnpc_only_flag = static_cast(atoi(row[183])); + e.cast_not_standing = static_cast(atoi(row[184])); + e.can_mgb = static_cast(atoi(row[185])); + e.nodispell = static_cast(atoi(row[186])); + e.npc_category = static_cast(atoi(row[187])); + e.npc_usefulness = static_cast(atoi(row[188])); + e.MinResist = static_cast(atoi(row[189])); + e.MaxResist = static_cast(atoi(row[190])); + e.viral_targets = static_cast(atoi(row[191])); + e.viral_timer = static_cast(atoi(row[192])); + e.nimbuseffect = static_cast(atoi(row[193])); + e.ConeStartAngle = static_cast(atoi(row[194])); + e.ConeStopAngle = static_cast(atoi(row[195])); + e.sneaking = static_cast(atoi(row[196])); + e.not_extendable = static_cast(atoi(row[197])); + e.field198 = static_cast(atoi(row[198])); + e.field199 = static_cast(atoi(row[199])); + e.suspendable = static_cast(atoi(row[200])); + e.viral_range = static_cast(atoi(row[201])); + e.songcap = static_cast(atoi(row[202])); + e.field203 = static_cast(atoi(row[203])); + e.field204 = static_cast(atoi(row[204])); + e.no_block = static_cast(atoi(row[205])); + e.field206 = static_cast(atoi(row[206])); + e.spellgroup = static_cast(atoi(row[207])); + e.rank = static_cast(atoi(row[208])); + e.field209 = static_cast(atoi(row[209])); + e.field210 = static_cast(atoi(row[210])); + e.CastRestriction = static_cast(atoi(row[211])); + e.allowrest = static_cast(atoi(row[212])); + e.InCombat = static_cast(atoi(row[213])); + e.OutofCombat = static_cast(atoi(row[214])); + e.field215 = static_cast(atoi(row[215])); + e.field216 = static_cast(atoi(row[216])); + e.field217 = static_cast(atoi(row[217])); + e.aemaxtargets = static_cast(atoi(row[218])); + e.maxtargets = static_cast(atoi(row[219])); + e.field220 = static_cast(atoi(row[220])); + e.field221 = static_cast(atoi(row[221])); + e.field222 = static_cast(atoi(row[222])); + e.field223 = static_cast(atoi(row[223])); + e.persistdeath = static_cast(atoi(row[224])); + e.field225 = static_cast(atoi(row[225])); + e.field226 = static_cast(atoi(row[226])); + e.min_dist = strtof(row[227], nullptr); + e.min_dist_mod = strtof(row[228], nullptr); + e.max_dist = strtof(row[229], nullptr); + e.max_dist_mod = strtof(row[230], nullptr); + e.min_range = static_cast(atoi(row[231])); + e.field232 = static_cast(atoi(row[232])); + e.field233 = static_cast(atoi(row[233])); + e.field234 = static_cast(atoi(row[234])); + e.field235 = static_cast(atoi(row[235])); + e.field236 = static_cast(atoi(row[236])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -2381,253 +2381,253 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - SpellsNew entry{}; + SpellsNew e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.player_1 = row[2] ? row[2] : ""; - entry.teleport_zone = row[3] ? row[3] : ""; - entry.you_cast = row[4] ? row[4] : ""; - entry.other_casts = row[5] ? row[5] : ""; - entry.cast_on_you = row[6] ? row[6] : ""; - entry.cast_on_other = row[7] ? row[7] : ""; - entry.spell_fades = row[8] ? row[8] : ""; - entry.range = atoi(row[9]); - entry.aoerange = atoi(row[10]); - entry.pushback = atoi(row[11]); - entry.pushup = atoi(row[12]); - entry.cast_time = atoi(row[13]); - entry.recovery_time = atoi(row[14]); - entry.recast_time = atoi(row[15]); - entry.buffdurationformula = atoi(row[16]); - entry.buffduration = atoi(row[17]); - entry.AEDuration = atoi(row[18]); - entry.mana = atoi(row[19]); - entry.effect_base_value1 = atoi(row[20]); - entry.effect_base_value2 = atoi(row[21]); - entry.effect_base_value3 = atoi(row[22]); - entry.effect_base_value4 = atoi(row[23]); - entry.effect_base_value5 = atoi(row[24]); - entry.effect_base_value6 = atoi(row[25]); - entry.effect_base_value7 = atoi(row[26]); - entry.effect_base_value8 = atoi(row[27]); - entry.effect_base_value9 = atoi(row[28]); - entry.effect_base_value10 = atoi(row[29]); - entry.effect_base_value11 = atoi(row[30]); - entry.effect_base_value12 = atoi(row[31]); - entry.effect_limit_value1 = atoi(row[32]); - entry.effect_limit_value2 = atoi(row[33]); - entry.effect_limit_value3 = atoi(row[34]); - entry.effect_limit_value4 = atoi(row[35]); - entry.effect_limit_value5 = atoi(row[36]); - entry.effect_limit_value6 = atoi(row[37]); - entry.effect_limit_value7 = atoi(row[38]); - entry.effect_limit_value8 = atoi(row[39]); - entry.effect_limit_value9 = atoi(row[40]); - entry.effect_limit_value10 = atoi(row[41]); - entry.effect_limit_value11 = atoi(row[42]); - entry.effect_limit_value12 = atoi(row[43]); - entry.max1 = atoi(row[44]); - entry.max2 = atoi(row[45]); - entry.max3 = atoi(row[46]); - entry.max4 = atoi(row[47]); - entry.max5 = atoi(row[48]); - entry.max6 = atoi(row[49]); - entry.max7 = atoi(row[50]); - entry.max8 = atoi(row[51]); - entry.max9 = atoi(row[52]); - entry.max10 = atoi(row[53]); - entry.max11 = atoi(row[54]); - entry.max12 = atoi(row[55]); - entry.icon = atoi(row[56]); - entry.memicon = atoi(row[57]); - entry.components1 = atoi(row[58]); - entry.components2 = atoi(row[59]); - entry.components3 = atoi(row[60]); - entry.components4 = atoi(row[61]); - entry.component_counts1 = atoi(row[62]); - entry.component_counts2 = atoi(row[63]); - entry.component_counts3 = atoi(row[64]); - entry.component_counts4 = atoi(row[65]); - entry.NoexpendReagent1 = atoi(row[66]); - entry.NoexpendReagent2 = atoi(row[67]); - entry.NoexpendReagent3 = atoi(row[68]); - entry.NoexpendReagent4 = atoi(row[69]); - entry.formula1 = atoi(row[70]); - entry.formula2 = atoi(row[71]); - entry.formula3 = atoi(row[72]); - entry.formula4 = atoi(row[73]); - entry.formula5 = atoi(row[74]); - entry.formula6 = atoi(row[75]); - entry.formula7 = atoi(row[76]); - entry.formula8 = atoi(row[77]); - entry.formula9 = atoi(row[78]); - entry.formula10 = atoi(row[79]); - entry.formula11 = atoi(row[80]); - entry.formula12 = atoi(row[81]); - entry.LightType = atoi(row[82]); - entry.goodEffect = atoi(row[83]); - entry.Activated = atoi(row[84]); - entry.resisttype = atoi(row[85]); - entry.effectid1 = atoi(row[86]); - entry.effectid2 = atoi(row[87]); - entry.effectid3 = atoi(row[88]); - entry.effectid4 = atoi(row[89]); - entry.effectid5 = atoi(row[90]); - entry.effectid6 = atoi(row[91]); - entry.effectid7 = atoi(row[92]); - entry.effectid8 = atoi(row[93]); - entry.effectid9 = atoi(row[94]); - entry.effectid10 = atoi(row[95]); - entry.effectid11 = atoi(row[96]); - entry.effectid12 = atoi(row[97]); - entry.targettype = atoi(row[98]); - entry.basediff = atoi(row[99]); - entry.skill = atoi(row[100]); - entry.zonetype = atoi(row[101]); - entry.EnvironmentType = atoi(row[102]); - entry.TimeOfDay = atoi(row[103]); - entry.classes1 = atoi(row[104]); - entry.classes2 = atoi(row[105]); - entry.classes3 = atoi(row[106]); - entry.classes4 = atoi(row[107]); - entry.classes5 = atoi(row[108]); - entry.classes6 = atoi(row[109]); - entry.classes7 = atoi(row[110]); - entry.classes8 = atoi(row[111]); - entry.classes9 = atoi(row[112]); - entry.classes10 = atoi(row[113]); - entry.classes11 = atoi(row[114]); - entry.classes12 = atoi(row[115]); - entry.classes13 = atoi(row[116]); - entry.classes14 = atoi(row[117]); - entry.classes15 = atoi(row[118]); - entry.classes16 = atoi(row[119]); - entry.CastingAnim = atoi(row[120]); - entry.TargetAnim = atoi(row[121]); - entry.TravelType = atoi(row[122]); - entry.SpellAffectIndex = atoi(row[123]); - entry.disallow_sit = atoi(row[124]); - entry.deities0 = atoi(row[125]); - entry.deities1 = atoi(row[126]); - entry.deities2 = atoi(row[127]); - entry.deities3 = atoi(row[128]); - entry.deities4 = atoi(row[129]); - entry.deities5 = atoi(row[130]); - entry.deities6 = atoi(row[131]); - entry.deities7 = atoi(row[132]); - entry.deities8 = atoi(row[133]); - entry.deities9 = atoi(row[134]); - entry.deities10 = atoi(row[135]); - entry.deities11 = atoi(row[136]); - entry.deities12 = atoi(row[137]); - entry.deities13 = atoi(row[138]); - entry.deities14 = atoi(row[139]); - entry.deities15 = atoi(row[140]); - entry.deities16 = atoi(row[141]); - entry.field142 = atoi(row[142]); - entry.field143 = atoi(row[143]); - entry.new_icon = atoi(row[144]); - entry.spellanim = atoi(row[145]); - entry.uninterruptable = atoi(row[146]); - entry.ResistDiff = atoi(row[147]); - entry.dot_stacking_exempt = atoi(row[148]); - entry.deleteable = atoi(row[149]); - entry.RecourseLink = atoi(row[150]); - entry.no_partial_resist = atoi(row[151]); - entry.field152 = atoi(row[152]); - entry.field153 = atoi(row[153]); - entry.short_buff_box = atoi(row[154]); - entry.descnum = atoi(row[155]); - entry.typedescnum = atoi(row[156]); - entry.effectdescnum = atoi(row[157]); - entry.effectdescnum2 = atoi(row[158]); - entry.npc_no_los = atoi(row[159]); - entry.field160 = atoi(row[160]); - entry.reflectable = atoi(row[161]); - entry.bonushate = atoi(row[162]); - entry.field163 = atoi(row[163]); - entry.field164 = atoi(row[164]); - entry.ldon_trap = atoi(row[165]); - entry.EndurCost = atoi(row[166]); - entry.EndurTimerIndex = atoi(row[167]); - entry.IsDiscipline = atoi(row[168]); - entry.field169 = atoi(row[169]); - entry.field170 = atoi(row[170]); - entry.field171 = atoi(row[171]); - entry.field172 = atoi(row[172]); - entry.HateAdded = atoi(row[173]); - entry.EndurUpkeep = atoi(row[174]); - entry.numhitstype = atoi(row[175]); - entry.numhits = atoi(row[176]); - entry.pvpresistbase = atoi(row[177]); - entry.pvpresistcalc = atoi(row[178]); - entry.pvpresistcap = atoi(row[179]); - entry.spell_category = atoi(row[180]); - entry.pvp_duration = atoi(row[181]); - entry.pvp_duration_cap = atoi(row[182]); - entry.pcnpc_only_flag = atoi(row[183]); - entry.cast_not_standing = atoi(row[184]); - entry.can_mgb = atoi(row[185]); - entry.nodispell = atoi(row[186]); - entry.npc_category = atoi(row[187]); - entry.npc_usefulness = atoi(row[188]); - entry.MinResist = atoi(row[189]); - entry.MaxResist = atoi(row[190]); - entry.viral_targets = atoi(row[191]); - entry.viral_timer = atoi(row[192]); - entry.nimbuseffect = atoi(row[193]); - entry.ConeStartAngle = atoi(row[194]); - entry.ConeStopAngle = atoi(row[195]); - entry.sneaking = atoi(row[196]); - entry.not_extendable = atoi(row[197]); - entry.field198 = atoi(row[198]); - entry.field199 = atoi(row[199]); - entry.suspendable = atoi(row[200]); - entry.viral_range = atoi(row[201]); - entry.songcap = atoi(row[202]); - entry.field203 = atoi(row[203]); - entry.field204 = atoi(row[204]); - entry.no_block = atoi(row[205]); - entry.field206 = atoi(row[206]); - entry.spellgroup = atoi(row[207]); - entry.rank = atoi(row[208]); - entry.field209 = atoi(row[209]); - entry.field210 = atoi(row[210]); - entry.CastRestriction = atoi(row[211]); - entry.allowrest = atoi(row[212]); - entry.InCombat = atoi(row[213]); - entry.OutofCombat = atoi(row[214]); - entry.field215 = atoi(row[215]); - entry.field216 = atoi(row[216]); - entry.field217 = atoi(row[217]); - entry.aemaxtargets = atoi(row[218]); - entry.maxtargets = atoi(row[219]); - entry.field220 = atoi(row[220]); - entry.field221 = atoi(row[221]); - entry.field222 = atoi(row[222]); - entry.field223 = atoi(row[223]); - entry.persistdeath = atoi(row[224]); - entry.field225 = atoi(row[225]); - entry.field226 = atoi(row[226]); - entry.min_dist = static_cast(atof(row[227])); - entry.min_dist_mod = static_cast(atof(row[228])); - entry.max_dist = static_cast(atof(row[229])); - entry.max_dist_mod = static_cast(atof(row[230])); - entry.min_range = atoi(row[231]); - entry.field232 = atoi(row[232]); - entry.field233 = atoi(row[233]); - entry.field234 = atoi(row[234]); - entry.field235 = atoi(row[235]); - entry.field236 = atoi(row[236]); + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : ""; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range = static_cast(atoi(row[9])); + e.aoerange = static_cast(atoi(row[10])); + e.pushback = static_cast(atoi(row[11])); + e.pushup = static_cast(atoi(row[12])); + e.cast_time = static_cast(atoi(row[13])); + e.recovery_time = static_cast(atoi(row[14])); + e.recast_time = static_cast(atoi(row[15])); + e.buffdurationformula = static_cast(atoi(row[16])); + e.buffduration = static_cast(atoi(row[17])); + e.AEDuration = static_cast(atoi(row[18])); + e.mana = static_cast(atoi(row[19])); + e.effect_base_value1 = static_cast(atoi(row[20])); + e.effect_base_value2 = static_cast(atoi(row[21])); + e.effect_base_value3 = static_cast(atoi(row[22])); + e.effect_base_value4 = static_cast(atoi(row[23])); + e.effect_base_value5 = static_cast(atoi(row[24])); + e.effect_base_value6 = static_cast(atoi(row[25])); + e.effect_base_value7 = static_cast(atoi(row[26])); + e.effect_base_value8 = static_cast(atoi(row[27])); + e.effect_base_value9 = static_cast(atoi(row[28])); + e.effect_base_value10 = static_cast(atoi(row[29])); + e.effect_base_value11 = static_cast(atoi(row[30])); + e.effect_base_value12 = static_cast(atoi(row[31])); + e.effect_limit_value1 = static_cast(atoi(row[32])); + e.effect_limit_value2 = static_cast(atoi(row[33])); + e.effect_limit_value3 = static_cast(atoi(row[34])); + e.effect_limit_value4 = static_cast(atoi(row[35])); + e.effect_limit_value5 = static_cast(atoi(row[36])); + e.effect_limit_value6 = static_cast(atoi(row[37])); + e.effect_limit_value7 = static_cast(atoi(row[38])); + e.effect_limit_value8 = static_cast(atoi(row[39])); + e.effect_limit_value9 = static_cast(atoi(row[40])); + e.effect_limit_value10 = static_cast(atoi(row[41])); + e.effect_limit_value11 = static_cast(atoi(row[42])); + e.effect_limit_value12 = static_cast(atoi(row[43])); + e.max1 = static_cast(atoi(row[44])); + e.max2 = static_cast(atoi(row[45])); + e.max3 = static_cast(atoi(row[46])); + e.max4 = static_cast(atoi(row[47])); + e.max5 = static_cast(atoi(row[48])); + e.max6 = static_cast(atoi(row[49])); + e.max7 = static_cast(atoi(row[50])); + e.max8 = static_cast(atoi(row[51])); + e.max9 = static_cast(atoi(row[52])); + e.max10 = static_cast(atoi(row[53])); + e.max11 = static_cast(atoi(row[54])); + e.max12 = static_cast(atoi(row[55])); + e.icon = static_cast(atoi(row[56])); + e.memicon = static_cast(atoi(row[57])); + e.components1 = static_cast(atoi(row[58])); + e.components2 = static_cast(atoi(row[59])); + e.components3 = static_cast(atoi(row[60])); + e.components4 = static_cast(atoi(row[61])); + e.component_counts1 = static_cast(atoi(row[62])); + e.component_counts2 = static_cast(atoi(row[63])); + e.component_counts3 = static_cast(atoi(row[64])); + e.component_counts4 = static_cast(atoi(row[65])); + e.NoexpendReagent1 = static_cast(atoi(row[66])); + e.NoexpendReagent2 = static_cast(atoi(row[67])); + e.NoexpendReagent3 = static_cast(atoi(row[68])); + e.NoexpendReagent4 = static_cast(atoi(row[69])); + e.formula1 = static_cast(atoi(row[70])); + e.formula2 = static_cast(atoi(row[71])); + e.formula3 = static_cast(atoi(row[72])); + e.formula4 = static_cast(atoi(row[73])); + e.formula5 = static_cast(atoi(row[74])); + e.formula6 = static_cast(atoi(row[75])); + e.formula7 = static_cast(atoi(row[76])); + e.formula8 = static_cast(atoi(row[77])); + e.formula9 = static_cast(atoi(row[78])); + e.formula10 = static_cast(atoi(row[79])); + e.formula11 = static_cast(atoi(row[80])); + e.formula12 = static_cast(atoi(row[81])); + e.LightType = static_cast(atoi(row[82])); + e.goodEffect = static_cast(atoi(row[83])); + e.Activated = static_cast(atoi(row[84])); + e.resisttype = static_cast(atoi(row[85])); + e.effectid1 = static_cast(atoi(row[86])); + e.effectid2 = static_cast(atoi(row[87])); + e.effectid3 = static_cast(atoi(row[88])); + e.effectid4 = static_cast(atoi(row[89])); + e.effectid5 = static_cast(atoi(row[90])); + e.effectid6 = static_cast(atoi(row[91])); + e.effectid7 = static_cast(atoi(row[92])); + e.effectid8 = static_cast(atoi(row[93])); + e.effectid9 = static_cast(atoi(row[94])); + e.effectid10 = static_cast(atoi(row[95])); + e.effectid11 = static_cast(atoi(row[96])); + e.effectid12 = static_cast(atoi(row[97])); + e.targettype = static_cast(atoi(row[98])); + e.basediff = static_cast(atoi(row[99])); + e.skill = static_cast(atoi(row[100])); + e.zonetype = static_cast(atoi(row[101])); + e.EnvironmentType = static_cast(atoi(row[102])); + e.TimeOfDay = static_cast(atoi(row[103])); + e.classes1 = static_cast(atoi(row[104])); + e.classes2 = static_cast(atoi(row[105])); + e.classes3 = static_cast(atoi(row[106])); + e.classes4 = static_cast(atoi(row[107])); + e.classes5 = static_cast(atoi(row[108])); + e.classes6 = static_cast(atoi(row[109])); + e.classes7 = static_cast(atoi(row[110])); + e.classes8 = static_cast(atoi(row[111])); + e.classes9 = static_cast(atoi(row[112])); + e.classes10 = static_cast(atoi(row[113])); + e.classes11 = static_cast(atoi(row[114])); + e.classes12 = static_cast(atoi(row[115])); + e.classes13 = static_cast(atoi(row[116])); + e.classes14 = static_cast(atoi(row[117])); + e.classes15 = static_cast(atoi(row[118])); + e.classes16 = static_cast(atoi(row[119])); + e.CastingAnim = static_cast(atoi(row[120])); + e.TargetAnim = static_cast(atoi(row[121])); + e.TravelType = static_cast(atoi(row[122])); + e.SpellAffectIndex = static_cast(atoi(row[123])); + e.disallow_sit = static_cast(atoi(row[124])); + e.deities0 = static_cast(atoi(row[125])); + e.deities1 = static_cast(atoi(row[126])); + e.deities2 = static_cast(atoi(row[127])); + e.deities3 = static_cast(atoi(row[128])); + e.deities4 = static_cast(atoi(row[129])); + e.deities5 = static_cast(atoi(row[130])); + e.deities6 = static_cast(atoi(row[131])); + e.deities7 = static_cast(atoi(row[132])); + e.deities8 = static_cast(atoi(row[133])); + e.deities9 = static_cast(atoi(row[134])); + e.deities10 = static_cast(atoi(row[135])); + e.deities11 = static_cast(atoi(row[136])); + e.deities12 = static_cast(atoi(row[137])); + e.deities13 = static_cast(atoi(row[138])); + e.deities14 = static_cast(atoi(row[139])); + e.deities15 = static_cast(atoi(row[140])); + e.deities16 = static_cast(atoi(row[141])); + e.field142 = static_cast(atoi(row[142])); + e.field143 = static_cast(atoi(row[143])); + e.new_icon = static_cast(atoi(row[144])); + e.spellanim = static_cast(atoi(row[145])); + e.uninterruptable = static_cast(atoi(row[146])); + e.ResistDiff = static_cast(atoi(row[147])); + e.dot_stacking_exempt = static_cast(atoi(row[148])); + e.deleteable = static_cast(atoi(row[149])); + e.RecourseLink = static_cast(atoi(row[150])); + e.no_partial_resist = static_cast(atoi(row[151])); + e.field152 = static_cast(atoi(row[152])); + e.field153 = static_cast(atoi(row[153])); + e.short_buff_box = static_cast(atoi(row[154])); + e.descnum = static_cast(atoi(row[155])); + e.typedescnum = static_cast(atoi(row[156])); + e.effectdescnum = static_cast(atoi(row[157])); + e.effectdescnum2 = static_cast(atoi(row[158])); + e.npc_no_los = static_cast(atoi(row[159])); + e.field160 = static_cast(atoi(row[160])); + e.reflectable = static_cast(atoi(row[161])); + e.bonushate = static_cast(atoi(row[162])); + e.field163 = static_cast(atoi(row[163])); + e.field164 = static_cast(atoi(row[164])); + e.ldon_trap = static_cast(atoi(row[165])); + e.EndurCost = static_cast(atoi(row[166])); + e.EndurTimerIndex = static_cast(atoi(row[167])); + e.IsDiscipline = static_cast(atoi(row[168])); + e.field169 = static_cast(atoi(row[169])); + e.field170 = static_cast(atoi(row[170])); + e.field171 = static_cast(atoi(row[171])); + e.field172 = static_cast(atoi(row[172])); + e.HateAdded = static_cast(atoi(row[173])); + e.EndurUpkeep = static_cast(atoi(row[174])); + e.numhitstype = static_cast(atoi(row[175])); + e.numhits = static_cast(atoi(row[176])); + e.pvpresistbase = static_cast(atoi(row[177])); + e.pvpresistcalc = static_cast(atoi(row[178])); + e.pvpresistcap = static_cast(atoi(row[179])); + e.spell_category = static_cast(atoi(row[180])); + e.pvp_duration = static_cast(atoi(row[181])); + e.pvp_duration_cap = static_cast(atoi(row[182])); + e.pcnpc_only_flag = static_cast(atoi(row[183])); + e.cast_not_standing = static_cast(atoi(row[184])); + e.can_mgb = static_cast(atoi(row[185])); + e.nodispell = static_cast(atoi(row[186])); + e.npc_category = static_cast(atoi(row[187])); + e.npc_usefulness = static_cast(atoi(row[188])); + e.MinResist = static_cast(atoi(row[189])); + e.MaxResist = static_cast(atoi(row[190])); + e.viral_targets = static_cast(atoi(row[191])); + e.viral_timer = static_cast(atoi(row[192])); + e.nimbuseffect = static_cast(atoi(row[193])); + e.ConeStartAngle = static_cast(atoi(row[194])); + e.ConeStopAngle = static_cast(atoi(row[195])); + e.sneaking = static_cast(atoi(row[196])); + e.not_extendable = static_cast(atoi(row[197])); + e.field198 = static_cast(atoi(row[198])); + e.field199 = static_cast(atoi(row[199])); + e.suspendable = static_cast(atoi(row[200])); + e.viral_range = static_cast(atoi(row[201])); + e.songcap = static_cast(atoi(row[202])); + e.field203 = static_cast(atoi(row[203])); + e.field204 = static_cast(atoi(row[204])); + e.no_block = static_cast(atoi(row[205])); + e.field206 = static_cast(atoi(row[206])); + e.spellgroup = static_cast(atoi(row[207])); + e.rank = static_cast(atoi(row[208])); + e.field209 = static_cast(atoi(row[209])); + e.field210 = static_cast(atoi(row[210])); + e.CastRestriction = static_cast(atoi(row[211])); + e.allowrest = static_cast(atoi(row[212])); + e.InCombat = static_cast(atoi(row[213])); + e.OutofCombat = static_cast(atoi(row[214])); + e.field215 = static_cast(atoi(row[215])); + e.field216 = static_cast(atoi(row[216])); + e.field217 = static_cast(atoi(row[217])); + e.aemaxtargets = static_cast(atoi(row[218])); + e.maxtargets = static_cast(atoi(row[219])); + e.field220 = static_cast(atoi(row[220])); + e.field221 = static_cast(atoi(row[221])); + e.field222 = static_cast(atoi(row[222])); + e.field223 = static_cast(atoi(row[223])); + e.persistdeath = static_cast(atoi(row[224])); + e.field225 = static_cast(atoi(row[225])); + e.field226 = static_cast(atoi(row[226])); + e.min_dist = strtof(row[227], nullptr); + e.min_dist_mod = strtof(row[228], nullptr); + e.max_dist = strtof(row[229], nullptr); + e.max_dist_mod = strtof(row[230], nullptr); + e.min_range = static_cast(atoi(row[231])); + e.field232 = static_cast(atoi(row[232])); + e.field233 = static_cast(atoi(row[233])); + e.field234 = static_cast(atoi(row[234])); + e.field235 = static_cast(atoi(row[235])); + e.field236 = static_cast(atoi(row[236])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -2652,6 +2652,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_SPELLS_NEW_REPOSITORY_H diff --git a/common/repositories/base/base_start_zones_repository.h b/common/repositories/base/base_start_zones_repository.h index 5a970d4e3..124ff9ecb 100644 --- a/common/repositories/base/base_start_zones_repository.h +++ b/common/repositories/base/base_start_zones_repository.h @@ -13,7 +13,7 @@ #define EQEMU_BASE_START_ZONES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseStartZonesRepository { @@ -23,19 +23,19 @@ public: float y; float z; float heading; - int zone_id; - int bind_id; - int player_choice; - int player_class; - int player_deity; - int player_race; - int start_zone; + int32_t zone_id; + int32_t bind_id; + int32_t player_choice; + int32_t player_class; + int32_t player_deity; + int32_t player_race; + int32_t start_zone; float bind_x; float bind_y; float bind_z; - int select_rank; - int min_expansion; - int max_expansion; + uint8_t select_rank; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -97,12 +97,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -130,32 +130,32 @@ public: static StartZones NewEntity() { - StartZones entry{}; + StartZones e{}; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.heading = 0; - entry.zone_id = 0; - entry.bind_id = 0; - entry.player_choice = 0; - entry.player_class = 0; - entry.player_deity = 0; - entry.player_race = 0; - entry.start_zone = 0; - entry.bind_x = 0; - entry.bind_y = 0; - entry.bind_z = 0; - entry.select_rank = 50; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; + e.zone_id = 0; + e.bind_id = 0; + e.player_choice = 0; + e.player_class = 0; + e.player_deity = 0; + e.player_race = 0; + e.start_zone = 0; + e.bind_x = 0; + e.bind_y = 0; + e.bind_z = 0; + e.select_rank = 50; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static StartZones GetStartZonesEntry( + static StartZones GetStartZones( const std::vector &start_zoness, int start_zones_id ) @@ -184,29 +184,29 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - StartZones entry{}; + StartZones e{}; - entry.x = static_cast(atof(row[0])); - entry.y = static_cast(atof(row[1])); - entry.z = static_cast(atof(row[2])); - entry.heading = static_cast(atof(row[3])); - entry.zone_id = atoi(row[4]); - entry.bind_id = atoi(row[5]); - entry.player_choice = atoi(row[6]); - entry.player_class = atoi(row[7]); - entry.player_deity = atoi(row[8]); - entry.player_race = atoi(row[9]); - entry.start_zone = atoi(row[10]); - entry.bind_x = static_cast(atof(row[11])); - entry.bind_y = static_cast(atof(row[12])); - entry.bind_z = static_cast(atof(row[13])); - entry.select_rank = atoi(row[14]); - entry.min_expansion = atoi(row[15]); - entry.max_expansion = atoi(row[16]); - entry.content_flags = row[17] ? row[17] : ""; - entry.content_flags_disabled = row[18] ? row[18] : ""; + e.x = strtof(row[0], nullptr); + e.y = strtof(row[1], nullptr); + e.z = strtof(row[2], nullptr); + e.heading = strtof(row[3], nullptr); + e.zone_id = static_cast(atoi(row[4])); + e.bind_id = static_cast(atoi(row[5])); + e.player_choice = static_cast(atoi(row[6])); + e.player_class = static_cast(atoi(row[7])); + e.player_deity = static_cast(atoi(row[8])); + e.player_race = static_cast(atoi(row[9])); + e.start_zone = static_cast(atoi(row[10])); + e.bind_x = strtof(row[11], nullptr); + e.bind_y = strtof(row[12], nullptr); + e.bind_z = strtof(row[13], nullptr); + e.select_rank = static_cast(strtoul(row[14], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[15])); + e.max_expansion = static_cast(atoi(row[16])); + e.content_flags = row[17] ? row[17] : ""; + e.content_flags_disabled = row[18] ? row[18] : ""; - return entry; + return e; } return NewEntity(); @@ -231,40 +231,40 @@ public: static int UpdateOne( Database& db, - StartZones start_zones_entry + const StartZones &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(start_zones_entry.x)); - update_values.push_back(columns[1] + " = " + std::to_string(start_zones_entry.y)); - update_values.push_back(columns[2] + " = " + std::to_string(start_zones_entry.z)); - update_values.push_back(columns[3] + " = " + std::to_string(start_zones_entry.heading)); - update_values.push_back(columns[4] + " = " + std::to_string(start_zones_entry.zone_id)); - update_values.push_back(columns[5] + " = " + std::to_string(start_zones_entry.bind_id)); - update_values.push_back(columns[6] + " = " + std::to_string(start_zones_entry.player_choice)); - update_values.push_back(columns[7] + " = " + std::to_string(start_zones_entry.player_class)); - update_values.push_back(columns[8] + " = " + std::to_string(start_zones_entry.player_deity)); - update_values.push_back(columns[9] + " = " + std::to_string(start_zones_entry.player_race)); - update_values.push_back(columns[10] + " = " + std::to_string(start_zones_entry.start_zone)); - update_values.push_back(columns[11] + " = " + std::to_string(start_zones_entry.bind_x)); - update_values.push_back(columns[12] + " = " + std::to_string(start_zones_entry.bind_y)); - update_values.push_back(columns[13] + " = " + std::to_string(start_zones_entry.bind_z)); - update_values.push_back(columns[14] + " = " + std::to_string(start_zones_entry.select_rank)); - update_values.push_back(columns[15] + " = " + std::to_string(start_zones_entry.min_expansion)); - update_values.push_back(columns[16] + " = " + std::to_string(start_zones_entry.max_expansion)); - update_values.push_back(columns[17] + " = '" + EscapeString(start_zones_entry.content_flags) + "'"); - update_values.push_back(columns[18] + " = '" + EscapeString(start_zones_entry.content_flags_disabled) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.x)); + v.push_back(columns[1] + " = " + std::to_string(e.y)); + v.push_back(columns[2] + " = " + std::to_string(e.z)); + v.push_back(columns[3] + " = " + std::to_string(e.heading)); + v.push_back(columns[4] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[5] + " = " + std::to_string(e.bind_id)); + v.push_back(columns[6] + " = " + std::to_string(e.player_choice)); + v.push_back(columns[7] + " = " + std::to_string(e.player_class)); + v.push_back(columns[8] + " = " + std::to_string(e.player_deity)); + v.push_back(columns[9] + " = " + std::to_string(e.player_race)); + v.push_back(columns[10] + " = " + std::to_string(e.start_zone)); + v.push_back(columns[11] + " = " + std::to_string(e.bind_x)); + v.push_back(columns[12] + " = " + std::to_string(e.bind_y)); + v.push_back(columns[13] + " = " + std::to_string(e.bind_z)); + v.push_back(columns[14] + " = " + std::to_string(e.select_rank)); + v.push_back(columns[15] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[16] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[17] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[18] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - start_zones_entry.player_choice + e.player_choice ) ); @@ -273,89 +273,89 @@ public: static StartZones InsertOne( Database& db, - StartZones start_zones_entry + StartZones e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(start_zones_entry.x)); - insert_values.push_back(std::to_string(start_zones_entry.y)); - insert_values.push_back(std::to_string(start_zones_entry.z)); - insert_values.push_back(std::to_string(start_zones_entry.heading)); - insert_values.push_back(std::to_string(start_zones_entry.zone_id)); - insert_values.push_back(std::to_string(start_zones_entry.bind_id)); - insert_values.push_back(std::to_string(start_zones_entry.player_choice)); - insert_values.push_back(std::to_string(start_zones_entry.player_class)); - insert_values.push_back(std::to_string(start_zones_entry.player_deity)); - insert_values.push_back(std::to_string(start_zones_entry.player_race)); - insert_values.push_back(std::to_string(start_zones_entry.start_zone)); - insert_values.push_back(std::to_string(start_zones_entry.bind_x)); - insert_values.push_back(std::to_string(start_zones_entry.bind_y)); - insert_values.push_back(std::to_string(start_zones_entry.bind_z)); - insert_values.push_back(std::to_string(start_zones_entry.select_rank)); - insert_values.push_back(std::to_string(start_zones_entry.min_expansion)); - insert_values.push_back(std::to_string(start_zones_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(start_zones_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(start_zones_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.bind_id)); + v.push_back(std::to_string(e.player_choice)); + v.push_back(std::to_string(e.player_class)); + v.push_back(std::to_string(e.player_deity)); + v.push_back(std::to_string(e.player_race)); + v.push_back(std::to_string(e.start_zone)); + v.push_back(std::to_string(e.bind_x)); + v.push_back(std::to_string(e.bind_y)); + v.push_back(std::to_string(e.bind_z)); + v.push_back(std::to_string(e.select_rank)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - start_zones_entry.player_choice = results.LastInsertedID(); - return start_zones_entry; + e.player_choice = results.LastInsertedID(); + return e; } - start_zones_entry = NewEntity(); + e = NewEntity(); - return start_zones_entry; + return e; } static int InsertMany( Database& db, - std::vector start_zones_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &start_zones_entry: start_zones_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(start_zones_entry.x)); - insert_values.push_back(std::to_string(start_zones_entry.y)); - insert_values.push_back(std::to_string(start_zones_entry.z)); - insert_values.push_back(std::to_string(start_zones_entry.heading)); - insert_values.push_back(std::to_string(start_zones_entry.zone_id)); - insert_values.push_back(std::to_string(start_zones_entry.bind_id)); - insert_values.push_back(std::to_string(start_zones_entry.player_choice)); - insert_values.push_back(std::to_string(start_zones_entry.player_class)); - insert_values.push_back(std::to_string(start_zones_entry.player_deity)); - insert_values.push_back(std::to_string(start_zones_entry.player_race)); - insert_values.push_back(std::to_string(start_zones_entry.start_zone)); - insert_values.push_back(std::to_string(start_zones_entry.bind_x)); - insert_values.push_back(std::to_string(start_zones_entry.bind_y)); - insert_values.push_back(std::to_string(start_zones_entry.bind_z)); - insert_values.push_back(std::to_string(start_zones_entry.select_rank)); - insert_values.push_back(std::to_string(start_zones_entry.min_expansion)); - insert_values.push_back(std::to_string(start_zones_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(start_zones_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(start_zones_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.bind_id)); + v.push_back(std::to_string(e.player_choice)); + v.push_back(std::to_string(e.player_class)); + v.push_back(std::to_string(e.player_deity)); + v.push_back(std::to_string(e.player_race)); + v.push_back(std::to_string(e.start_zone)); + v.push_back(std::to_string(e.bind_x)); + v.push_back(std::to_string(e.bind_y)); + v.push_back(std::to_string(e.bind_z)); + v.push_back(std::to_string(e.select_rank)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -376,35 +376,35 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - StartZones entry{}; + StartZones e{}; - entry.x = static_cast(atof(row[0])); - entry.y = static_cast(atof(row[1])); - entry.z = static_cast(atof(row[2])); - entry.heading = static_cast(atof(row[3])); - entry.zone_id = atoi(row[4]); - entry.bind_id = atoi(row[5]); - entry.player_choice = atoi(row[6]); - entry.player_class = atoi(row[7]); - entry.player_deity = atoi(row[8]); - entry.player_race = atoi(row[9]); - entry.start_zone = atoi(row[10]); - entry.bind_x = static_cast(atof(row[11])); - entry.bind_y = static_cast(atof(row[12])); - entry.bind_z = static_cast(atof(row[13])); - entry.select_rank = atoi(row[14]); - entry.min_expansion = atoi(row[15]); - entry.max_expansion = atoi(row[16]); - entry.content_flags = row[17] ? row[17] : ""; - entry.content_flags_disabled = row[18] ? row[18] : ""; + e.x = strtof(row[0], nullptr); + e.y = strtof(row[1], nullptr); + e.z = strtof(row[2], nullptr); + e.heading = strtof(row[3], nullptr); + e.zone_id = static_cast(atoi(row[4])); + e.bind_id = static_cast(atoi(row[5])); + e.player_choice = static_cast(atoi(row[6])); + e.player_class = static_cast(atoi(row[7])); + e.player_deity = static_cast(atoi(row[8])); + e.player_race = static_cast(atoi(row[9])); + e.start_zone = static_cast(atoi(row[10])); + e.bind_x = strtof(row[11], nullptr); + e.bind_y = strtof(row[12], nullptr); + e.bind_z = strtof(row[13], nullptr); + e.select_rank = static_cast(strtoul(row[14], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[15])); + e.max_expansion = static_cast(atoi(row[16])); + e.content_flags = row[17] ? row[17] : ""; + e.content_flags_disabled = row[18] ? row[18] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -419,35 +419,35 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - StartZones entry{}; + StartZones e{}; - entry.x = static_cast(atof(row[0])); - entry.y = static_cast(atof(row[1])); - entry.z = static_cast(atof(row[2])); - entry.heading = static_cast(atof(row[3])); - entry.zone_id = atoi(row[4]); - entry.bind_id = atoi(row[5]); - entry.player_choice = atoi(row[6]); - entry.player_class = atoi(row[7]); - entry.player_deity = atoi(row[8]); - entry.player_race = atoi(row[9]); - entry.start_zone = atoi(row[10]); - entry.bind_x = static_cast(atof(row[11])); - entry.bind_y = static_cast(atof(row[12])); - entry.bind_z = static_cast(atof(row[13])); - entry.select_rank = atoi(row[14]); - entry.min_expansion = atoi(row[15]); - entry.max_expansion = atoi(row[16]); - entry.content_flags = row[17] ? row[17] : ""; - entry.content_flags_disabled = row[18] ? row[18] : ""; + e.x = strtof(row[0], nullptr); + e.y = strtof(row[1], nullptr); + e.z = strtof(row[2], nullptr); + e.heading = strtof(row[3], nullptr); + e.zone_id = static_cast(atoi(row[4])); + e.bind_id = static_cast(atoi(row[5])); + e.player_choice = static_cast(atoi(row[6])); + e.player_class = static_cast(atoi(row[7])); + e.player_deity = static_cast(atoi(row[8])); + e.player_race = static_cast(atoi(row[9])); + e.start_zone = static_cast(atoi(row[10])); + e.bind_x = strtof(row[11], nullptr); + e.bind_y = strtof(row[12], nullptr); + e.bind_z = strtof(row[13], nullptr); + e.select_rank = static_cast(strtoul(row[14], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[15])); + e.max_expansion = static_cast(atoi(row[16])); + e.content_flags = row[17] ? row[17] : ""; + e.content_flags_disabled = row[18] ? row[18] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -472,6 +472,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_START_ZONES_REPOSITORY_H diff --git a/common/repositories/base/base_starting_items_repository.h b/common/repositories/base/base_starting_items_repository.h index 0c17c503a..33711b462 100644 --- a/common/repositories/base/base_starting_items_repository.h +++ b/common/repositories/base/base_starting_items_repository.h @@ -13,23 +13,23 @@ #define EQEMU_BASE_STARTING_ITEMS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseStartingItemsRepository { public: struct StartingItems { - int id; - int race; - int class_; - int deityid; - int zoneid; - int itemid; - int item_charges; - int gm; - int slot; - int min_expansion; - int max_expansion; + uint32_t id; + int32_t race; + int32_t class_; + int32_t deityid; + int32_t zoneid; + int32_t itemid; + uint8_t item_charges; + int8_t gm; + int32_t slot; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -79,12 +79,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -112,26 +112,26 @@ public: static StartingItems NewEntity() { - StartingItems entry{}; + StartingItems e{}; - entry.id = 0; - entry.race = 0; - entry.class_ = 0; - entry.deityid = 0; - entry.zoneid = 0; - entry.itemid = 0; - entry.item_charges = 1; - entry.gm = 0; - entry.slot = -1; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.race = 0; + e.class_ = 0; + e.deityid = 0; + e.zoneid = 0; + e.itemid = 0; + e.item_charges = 1; + e.gm = 0; + e.slot = -1; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static StartingItems GetStartingItemsEntry( + static StartingItems GetStartingItems( const std::vector &starting_itemss, int starting_items_id ) @@ -160,23 +160,23 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - StartingItems entry{}; + StartingItems e{}; - entry.id = atoi(row[0]); - entry.race = atoi(row[1]); - entry.class_ = atoi(row[2]); - entry.deityid = atoi(row[3]); - entry.zoneid = atoi(row[4]); - entry.itemid = atoi(row[5]); - entry.item_charges = atoi(row[6]); - entry.gm = atoi(row[7]); - entry.slot = atoi(row[8]); - entry.min_expansion = atoi(row[9]); - entry.max_expansion = atoi(row[10]); - entry.content_flags = row[11] ? row[11] : ""; - entry.content_flags_disabled = row[12] ? row[12] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.race = static_cast(atoi(row[1])); + e.class_ = static_cast(atoi(row[2])); + e.deityid = static_cast(atoi(row[3])); + e.zoneid = static_cast(atoi(row[4])); + e.itemid = static_cast(atoi(row[5])); + e.item_charges = static_cast(strtoul(row[6], nullptr, 10)); + e.gm = static_cast(atoi(row[7])); + e.slot = static_cast(atoi(row[8])); + e.min_expansion = static_cast(atoi(row[9])); + e.max_expansion = static_cast(atoi(row[10])); + e.content_flags = row[11] ? row[11] : ""; + e.content_flags_disabled = row[12] ? row[12] : ""; - return entry; + return e; } return NewEntity(); @@ -201,33 +201,33 @@ public: static int UpdateOne( Database& db, - StartingItems starting_items_entry + const StartingItems &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(starting_items_entry.race)); - update_values.push_back(columns[2] + " = " + std::to_string(starting_items_entry.class_)); - update_values.push_back(columns[3] + " = " + std::to_string(starting_items_entry.deityid)); - update_values.push_back(columns[4] + " = " + std::to_string(starting_items_entry.zoneid)); - update_values.push_back(columns[5] + " = " + std::to_string(starting_items_entry.itemid)); - update_values.push_back(columns[6] + " = " + std::to_string(starting_items_entry.item_charges)); - update_values.push_back(columns[7] + " = " + std::to_string(starting_items_entry.gm)); - update_values.push_back(columns[8] + " = " + std::to_string(starting_items_entry.slot)); - update_values.push_back(columns[9] + " = " + std::to_string(starting_items_entry.min_expansion)); - update_values.push_back(columns[10] + " = " + std::to_string(starting_items_entry.max_expansion)); - update_values.push_back(columns[11] + " = '" + EscapeString(starting_items_entry.content_flags) + "'"); - update_values.push_back(columns[12] + " = '" + EscapeString(starting_items_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.race)); + v.push_back(columns[2] + " = " + std::to_string(e.class_)); + v.push_back(columns[3] + " = " + std::to_string(e.deityid)); + v.push_back(columns[4] + " = " + std::to_string(e.zoneid)); + v.push_back(columns[5] + " = " + std::to_string(e.itemid)); + v.push_back(columns[6] + " = " + std::to_string(e.item_charges)); + v.push_back(columns[7] + " = " + std::to_string(e.gm)); + v.push_back(columns[8] + " = " + std::to_string(e.slot)); + v.push_back(columns[9] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[10] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[11] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[12] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - starting_items_entry.id + e.id ) ); @@ -236,77 +236,77 @@ public: static StartingItems InsertOne( Database& db, - StartingItems starting_items_entry + StartingItems e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(starting_items_entry.id)); - insert_values.push_back(std::to_string(starting_items_entry.race)); - insert_values.push_back(std::to_string(starting_items_entry.class_)); - insert_values.push_back(std::to_string(starting_items_entry.deityid)); - insert_values.push_back(std::to_string(starting_items_entry.zoneid)); - insert_values.push_back(std::to_string(starting_items_entry.itemid)); - insert_values.push_back(std::to_string(starting_items_entry.item_charges)); - insert_values.push_back(std::to_string(starting_items_entry.gm)); - insert_values.push_back(std::to_string(starting_items_entry.slot)); - insert_values.push_back(std::to_string(starting_items_entry.min_expansion)); - insert_values.push_back(std::to_string(starting_items_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(starting_items_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(starting_items_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.deityid)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.item_charges)); + v.push_back(std::to_string(e.gm)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - starting_items_entry.id = results.LastInsertedID(); - return starting_items_entry; + e.id = results.LastInsertedID(); + return e; } - starting_items_entry = NewEntity(); + e = NewEntity(); - return starting_items_entry; + return e; } static int InsertMany( Database& db, - std::vector starting_items_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &starting_items_entry: starting_items_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(starting_items_entry.id)); - insert_values.push_back(std::to_string(starting_items_entry.race)); - insert_values.push_back(std::to_string(starting_items_entry.class_)); - insert_values.push_back(std::to_string(starting_items_entry.deityid)); - insert_values.push_back(std::to_string(starting_items_entry.zoneid)); - insert_values.push_back(std::to_string(starting_items_entry.itemid)); - insert_values.push_back(std::to_string(starting_items_entry.item_charges)); - insert_values.push_back(std::to_string(starting_items_entry.gm)); - insert_values.push_back(std::to_string(starting_items_entry.slot)); - insert_values.push_back(std::to_string(starting_items_entry.min_expansion)); - insert_values.push_back(std::to_string(starting_items_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(starting_items_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(starting_items_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.race)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.deityid)); + v.push_back(std::to_string(e.zoneid)); + v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.item_charges)); + v.push_back(std::to_string(e.gm)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -327,29 +327,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - StartingItems entry{}; + StartingItems e{}; - entry.id = atoi(row[0]); - entry.race = atoi(row[1]); - entry.class_ = atoi(row[2]); - entry.deityid = atoi(row[3]); - entry.zoneid = atoi(row[4]); - entry.itemid = atoi(row[5]); - entry.item_charges = atoi(row[6]); - entry.gm = atoi(row[7]); - entry.slot = atoi(row[8]); - entry.min_expansion = atoi(row[9]); - entry.max_expansion = atoi(row[10]); - entry.content_flags = row[11] ? row[11] : ""; - entry.content_flags_disabled = row[12] ? row[12] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.race = static_cast(atoi(row[1])); + e.class_ = static_cast(atoi(row[2])); + e.deityid = static_cast(atoi(row[3])); + e.zoneid = static_cast(atoi(row[4])); + e.itemid = static_cast(atoi(row[5])); + e.item_charges = static_cast(strtoul(row[6], nullptr, 10)); + e.gm = static_cast(atoi(row[7])); + e.slot = static_cast(atoi(row[8])); + e.min_expansion = static_cast(atoi(row[9])); + e.max_expansion = static_cast(atoi(row[10])); + e.content_flags = row[11] ? row[11] : ""; + e.content_flags_disabled = row[12] ? row[12] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -364,29 +364,29 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - StartingItems entry{}; + StartingItems e{}; - entry.id = atoi(row[0]); - entry.race = atoi(row[1]); - entry.class_ = atoi(row[2]); - entry.deityid = atoi(row[3]); - entry.zoneid = atoi(row[4]); - entry.itemid = atoi(row[5]); - entry.item_charges = atoi(row[6]); - entry.gm = atoi(row[7]); - entry.slot = atoi(row[8]); - entry.min_expansion = atoi(row[9]); - entry.max_expansion = atoi(row[10]); - entry.content_flags = row[11] ? row[11] : ""; - entry.content_flags_disabled = row[12] ? row[12] : ""; + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.race = static_cast(atoi(row[1])); + e.class_ = static_cast(atoi(row[2])); + e.deityid = static_cast(atoi(row[3])); + e.zoneid = static_cast(atoi(row[4])); + e.itemid = static_cast(atoi(row[5])); + e.item_charges = static_cast(strtoul(row[6], nullptr, 10)); + e.gm = static_cast(atoi(row[7])); + e.slot = static_cast(atoi(row[8])); + e.min_expansion = static_cast(atoi(row[9])); + e.max_expansion = static_cast(atoi(row[10])); + e.content_flags = row[11] ? row[11] : ""; + e.content_flags_disabled = row[12] ? row[12] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -411,6 +411,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_STARTING_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_task_activities_repository.h b/common/repositories/base/base_task_activities_repository.h index c1a9e1e4f..e0bb196a6 100644 --- a/common/repositories/base/base_task_activities_repository.h +++ b/common/repositories/base/base_task_activities_repository.h @@ -13,28 +13,36 @@ #define EQEMU_BASE_TASK_ACTIVITIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTaskActivitiesRepository { public: struct TaskActivities { - int taskid; - int activityid; - int step; - int activitytype; + uint32_t taskid; + uint32_t activityid; + int32_t req_activity_id; + int32_t step; + uint8_t activitytype; std::string target_name; + uint32_t goalmethod; + int32_t goalcount; + std::string description_override; + std::string npc_match_list; + std::string item_id_list; std::string item_list; + int32_t dz_switch_id; + float min_x; + float min_y; + float min_z; + float max_x; + float max_y; + float max_z; std::string skill_list; std::string spell_list; - std::string description_override; - int goalid; - std::string goal_match_list; - int goalmethod; - int goalcount; - int delivertonpc; std::string zones; - int optional; + int32_t zone_version; + int8_t optional; }; static std::string PrimaryKey() @@ -47,19 +55,27 @@ public: return { "taskid", "activityid", + "req_activity_id", "step", "activitytype", "target_name", - "item_list", - "skill_list", - "spell_list", - "description_override", - "goalid", - "goal_match_list", "goalmethod", "goalcount", - "delivertonpc", + "description_override", + "npc_match_list", + "item_id_list", + "item_list", + "dz_switch_id", + "min_x", + "min_y", + "min_z", + "max_x", + "max_y", + "max_z", + "skill_list", + "spell_list", "zones", + "zone_version", "optional", }; } @@ -69,31 +85,39 @@ public: return { "taskid", "activityid", + "req_activity_id", "step", "activitytype", "target_name", - "item_list", - "skill_list", - "spell_list", - "description_override", - "goalid", - "goal_match_list", "goalmethod", "goalcount", - "delivertonpc", + "description_override", + "npc_match_list", + "item_id_list", + "item_list", + "dz_switch_id", + "min_x", + "min_y", + "min_z", + "max_x", + "max_y", + "max_z", + "skill_list", + "spell_list", "zones", + "zone_version", "optional", }; } static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -121,29 +145,37 @@ public: static TaskActivities NewEntity() { - TaskActivities entry{}; + TaskActivities e{}; - entry.taskid = 0; - entry.activityid = 0; - entry.step = 0; - entry.activitytype = 0; - entry.target_name = ""; - entry.item_list = ""; - entry.skill_list = "-1"; - entry.spell_list = "0"; - entry.description_override = ""; - entry.goalid = 0; - entry.goal_match_list = ""; - entry.goalmethod = 0; - entry.goalcount = 1; - entry.delivertonpc = 0; - entry.zones = ""; - entry.optional = 0; + e.taskid = 0; + e.activityid = 0; + e.req_activity_id = -1; + e.step = 0; + e.activitytype = 0; + e.target_name = ""; + e.goalmethod = 0; + e.goalcount = 1; + e.description_override = ""; + e.npc_match_list = ""; + e.item_id_list = ""; + e.item_list = ""; + e.dz_switch_id = 0; + e.min_x = 0; + e.min_y = 0; + e.min_z = 0; + e.max_x = 0; + e.max_y = 0; + e.max_z = 0; + e.skill_list = "-1"; + e.spell_list = "0"; + e.zones = ""; + e.zone_version = -1; + e.optional = 0; - return entry; + return e; } - static TaskActivities GetTaskActivitiesEntry( + static TaskActivities GetTaskActivities( const std::vector &task_activitiess, int task_activities_id ) @@ -172,26 +204,34 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - TaskActivities entry{}; + TaskActivities e{}; - entry.taskid = atoi(row[0]); - entry.activityid = atoi(row[1]); - entry.step = atoi(row[2]); - entry.activitytype = atoi(row[3]); - entry.target_name = row[4] ? row[4] : ""; - entry.item_list = row[5] ? row[5] : ""; - entry.skill_list = row[6] ? row[6] : ""; - entry.spell_list = row[7] ? row[7] : ""; - entry.description_override = row[8] ? row[8] : ""; - entry.goalid = atoi(row[9]); - entry.goal_match_list = row[10] ? row[10] : ""; - entry.goalmethod = atoi(row[11]); - entry.goalcount = atoi(row[12]); - entry.delivertonpc = atoi(row[13]); - entry.zones = row[14] ? row[14] : ""; - entry.optional = atoi(row[15]); + e.taskid = static_cast(strtoul(row[0], nullptr, 10)); + e.activityid = static_cast(strtoul(row[1], nullptr, 10)); + e.req_activity_id = static_cast(atoi(row[2])); + e.step = static_cast(atoi(row[3])); + e.activitytype = static_cast(strtoul(row[4], nullptr, 10)); + e.target_name = row[5] ? row[5] : ""; + e.goalmethod = static_cast(strtoul(row[6], nullptr, 10)); + e.goalcount = static_cast(atoi(row[7])); + e.description_override = row[8] ? row[8] : ""; + e.npc_match_list = row[9] ? row[9] : ""; + e.item_id_list = row[10] ? row[10] : ""; + e.item_list = row[11] ? row[11] : ""; + e.dz_switch_id = static_cast(atoi(row[12])); + e.min_x = strtof(row[13], nullptr); + e.min_y = strtof(row[14], nullptr); + e.min_z = strtof(row[15], nullptr); + e.max_x = strtof(row[16], nullptr); + e.max_y = strtof(row[17], nullptr); + e.max_z = strtof(row[18], nullptr); + e.skill_list = row[19] ? row[19] : ""; + e.spell_list = row[20] ? row[20] : ""; + e.zones = row[21] ? row[21] : ""; + e.zone_version = static_cast(atoi(row[22])); + e.optional = static_cast(atoi(row[23])); - return entry; + return e; } return NewEntity(); @@ -216,37 +256,45 @@ public: static int UpdateOne( Database& db, - TaskActivities task_activities_entry + const TaskActivities &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(task_activities_entry.taskid)); - update_values.push_back(columns[1] + " = " + std::to_string(task_activities_entry.activityid)); - update_values.push_back(columns[2] + " = " + std::to_string(task_activities_entry.step)); - update_values.push_back(columns[3] + " = " + std::to_string(task_activities_entry.activitytype)); - update_values.push_back(columns[4] + " = '" + EscapeString(task_activities_entry.target_name) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(task_activities_entry.item_list) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(task_activities_entry.skill_list) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(task_activities_entry.spell_list) + "'"); - update_values.push_back(columns[8] + " = '" + EscapeString(task_activities_entry.description_override) + "'"); - update_values.push_back(columns[9] + " = " + std::to_string(task_activities_entry.goalid)); - update_values.push_back(columns[10] + " = '" + EscapeString(task_activities_entry.goal_match_list) + "'"); - update_values.push_back(columns[11] + " = " + std::to_string(task_activities_entry.goalmethod)); - update_values.push_back(columns[12] + " = " + std::to_string(task_activities_entry.goalcount)); - update_values.push_back(columns[13] + " = " + std::to_string(task_activities_entry.delivertonpc)); - update_values.push_back(columns[14] + " = '" + EscapeString(task_activities_entry.zones) + "'"); - update_values.push_back(columns[15] + " = " + std::to_string(task_activities_entry.optional)); + v.push_back(columns[0] + " = " + std::to_string(e.taskid)); + v.push_back(columns[1] + " = " + std::to_string(e.activityid)); + v.push_back(columns[2] + " = " + std::to_string(e.req_activity_id)); + v.push_back(columns[3] + " = " + std::to_string(e.step)); + v.push_back(columns[4] + " = " + std::to_string(e.activitytype)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.target_name) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.goalmethod)); + v.push_back(columns[7] + " = " + std::to_string(e.goalcount)); + v.push_back(columns[8] + " = '" + Strings::Escape(e.description_override) + "'"); + v.push_back(columns[9] + " = '" + Strings::Escape(e.npc_match_list) + "'"); + v.push_back(columns[10] + " = '" + Strings::Escape(e.item_id_list) + "'"); + v.push_back(columns[11] + " = '" + Strings::Escape(e.item_list) + "'"); + v.push_back(columns[12] + " = " + std::to_string(e.dz_switch_id)); + v.push_back(columns[13] + " = " + std::to_string(e.min_x)); + v.push_back(columns[14] + " = " + std::to_string(e.min_y)); + v.push_back(columns[15] + " = " + std::to_string(e.min_z)); + v.push_back(columns[16] + " = " + std::to_string(e.max_x)); + v.push_back(columns[17] + " = " + std::to_string(e.max_y)); + v.push_back(columns[18] + " = " + std::to_string(e.max_z)); + v.push_back(columns[19] + " = '" + Strings::Escape(e.skill_list) + "'"); + v.push_back(columns[20] + " = '" + Strings::Escape(e.spell_list) + "'"); + v.push_back(columns[21] + " = '" + Strings::Escape(e.zones) + "'"); + v.push_back(columns[22] + " = " + std::to_string(e.zone_version)); + v.push_back(columns[23] + " = " + std::to_string(e.optional)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - task_activities_entry.taskid + e.taskid ) ); @@ -255,83 +303,99 @@ public: static TaskActivities InsertOne( Database& db, - TaskActivities task_activities_entry + TaskActivities e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(task_activities_entry.taskid)); - insert_values.push_back(std::to_string(task_activities_entry.activityid)); - insert_values.push_back(std::to_string(task_activities_entry.step)); - insert_values.push_back(std::to_string(task_activities_entry.activitytype)); - insert_values.push_back("'" + EscapeString(task_activities_entry.target_name) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.item_list) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.skill_list) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.spell_list) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.description_override) + "'"); - insert_values.push_back(std::to_string(task_activities_entry.goalid)); - insert_values.push_back("'" + EscapeString(task_activities_entry.goal_match_list) + "'"); - insert_values.push_back(std::to_string(task_activities_entry.goalmethod)); - insert_values.push_back(std::to_string(task_activities_entry.goalcount)); - insert_values.push_back(std::to_string(task_activities_entry.delivertonpc)); - insert_values.push_back("'" + EscapeString(task_activities_entry.zones) + "'"); - insert_values.push_back(std::to_string(task_activities_entry.optional)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.activityid)); + v.push_back(std::to_string(e.req_activity_id)); + v.push_back(std::to_string(e.step)); + v.push_back(std::to_string(e.activitytype)); + v.push_back("'" + Strings::Escape(e.target_name) + "'"); + v.push_back(std::to_string(e.goalmethod)); + v.push_back(std::to_string(e.goalcount)); + v.push_back("'" + Strings::Escape(e.description_override) + "'"); + v.push_back("'" + Strings::Escape(e.npc_match_list) + "'"); + v.push_back("'" + Strings::Escape(e.item_id_list) + "'"); + v.push_back("'" + Strings::Escape(e.item_list) + "'"); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.min_x)); + v.push_back(std::to_string(e.min_y)); + v.push_back(std::to_string(e.min_z)); + v.push_back(std::to_string(e.max_x)); + v.push_back(std::to_string(e.max_y)); + v.push_back(std::to_string(e.max_z)); + v.push_back("'" + Strings::Escape(e.skill_list) + "'"); + v.push_back("'" + Strings::Escape(e.spell_list) + "'"); + v.push_back("'" + Strings::Escape(e.zones) + "'"); + v.push_back(std::to_string(e.zone_version)); + v.push_back(std::to_string(e.optional)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - task_activities_entry.taskid = results.LastInsertedID(); - return task_activities_entry; + e.taskid = results.LastInsertedID(); + return e; } - task_activities_entry = NewEntity(); + e = NewEntity(); - return task_activities_entry; + return e; } static int InsertMany( Database& db, - std::vector task_activities_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &task_activities_entry: task_activities_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(task_activities_entry.taskid)); - insert_values.push_back(std::to_string(task_activities_entry.activityid)); - insert_values.push_back(std::to_string(task_activities_entry.step)); - insert_values.push_back(std::to_string(task_activities_entry.activitytype)); - insert_values.push_back("'" + EscapeString(task_activities_entry.target_name) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.item_list) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.skill_list) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.spell_list) + "'"); - insert_values.push_back("'" + EscapeString(task_activities_entry.description_override) + "'"); - insert_values.push_back(std::to_string(task_activities_entry.goalid)); - insert_values.push_back("'" + EscapeString(task_activities_entry.goal_match_list) + "'"); - insert_values.push_back(std::to_string(task_activities_entry.goalmethod)); - insert_values.push_back(std::to_string(task_activities_entry.goalcount)); - insert_values.push_back(std::to_string(task_activities_entry.delivertonpc)); - insert_values.push_back("'" + EscapeString(task_activities_entry.zones) + "'"); - insert_values.push_back(std::to_string(task_activities_entry.optional)); + v.push_back(std::to_string(e.taskid)); + v.push_back(std::to_string(e.activityid)); + v.push_back(std::to_string(e.req_activity_id)); + v.push_back(std::to_string(e.step)); + v.push_back(std::to_string(e.activitytype)); + v.push_back("'" + Strings::Escape(e.target_name) + "'"); + v.push_back(std::to_string(e.goalmethod)); + v.push_back(std::to_string(e.goalcount)); + v.push_back("'" + Strings::Escape(e.description_override) + "'"); + v.push_back("'" + Strings::Escape(e.npc_match_list) + "'"); + v.push_back("'" + Strings::Escape(e.item_id_list) + "'"); + v.push_back("'" + Strings::Escape(e.item_list) + "'"); + v.push_back(std::to_string(e.dz_switch_id)); + v.push_back(std::to_string(e.min_x)); + v.push_back(std::to_string(e.min_y)); + v.push_back(std::to_string(e.min_z)); + v.push_back(std::to_string(e.max_x)); + v.push_back(std::to_string(e.max_y)); + v.push_back(std::to_string(e.max_z)); + v.push_back("'" + Strings::Escape(e.skill_list) + "'"); + v.push_back("'" + Strings::Escape(e.spell_list) + "'"); + v.push_back("'" + Strings::Escape(e.zones) + "'"); + v.push_back(std::to_string(e.zone_version)); + v.push_back(std::to_string(e.optional)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -352,32 +416,40 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TaskActivities entry{}; + TaskActivities e{}; - entry.taskid = atoi(row[0]); - entry.activityid = atoi(row[1]); - entry.step = atoi(row[2]); - entry.activitytype = atoi(row[3]); - entry.target_name = row[4] ? row[4] : ""; - entry.item_list = row[5] ? row[5] : ""; - entry.skill_list = row[6] ? row[6] : ""; - entry.spell_list = row[7] ? row[7] : ""; - entry.description_override = row[8] ? row[8] : ""; - entry.goalid = atoi(row[9]); - entry.goal_match_list = row[10] ? row[10] : ""; - entry.goalmethod = atoi(row[11]); - entry.goalcount = atoi(row[12]); - entry.delivertonpc = atoi(row[13]); - entry.zones = row[14] ? row[14] : ""; - entry.optional = atoi(row[15]); + e.taskid = static_cast(strtoul(row[0], nullptr, 10)); + e.activityid = static_cast(strtoul(row[1], nullptr, 10)); + e.req_activity_id = static_cast(atoi(row[2])); + e.step = static_cast(atoi(row[3])); + e.activitytype = static_cast(strtoul(row[4], nullptr, 10)); + e.target_name = row[5] ? row[5] : ""; + e.goalmethod = static_cast(strtoul(row[6], nullptr, 10)); + e.goalcount = static_cast(atoi(row[7])); + e.description_override = row[8] ? row[8] : ""; + e.npc_match_list = row[9] ? row[9] : ""; + e.item_id_list = row[10] ? row[10] : ""; + e.item_list = row[11] ? row[11] : ""; + e.dz_switch_id = static_cast(atoi(row[12])); + e.min_x = strtof(row[13], nullptr); + e.min_y = strtof(row[14], nullptr); + e.min_z = strtof(row[15], nullptr); + e.max_x = strtof(row[16], nullptr); + e.max_y = strtof(row[17], nullptr); + e.max_z = strtof(row[18], nullptr); + e.skill_list = row[19] ? row[19] : ""; + e.spell_list = row[20] ? row[20] : ""; + e.zones = row[21] ? row[21] : ""; + e.zone_version = static_cast(atoi(row[22])); + e.optional = static_cast(atoi(row[23])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -392,32 +464,40 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TaskActivities entry{}; + TaskActivities e{}; - entry.taskid = atoi(row[0]); - entry.activityid = atoi(row[1]); - entry.step = atoi(row[2]); - entry.activitytype = atoi(row[3]); - entry.target_name = row[4] ? row[4] : ""; - entry.item_list = row[5] ? row[5] : ""; - entry.skill_list = row[6] ? row[6] : ""; - entry.spell_list = row[7] ? row[7] : ""; - entry.description_override = row[8] ? row[8] : ""; - entry.goalid = atoi(row[9]); - entry.goal_match_list = row[10] ? row[10] : ""; - entry.goalmethod = atoi(row[11]); - entry.goalcount = atoi(row[12]); - entry.delivertonpc = atoi(row[13]); - entry.zones = row[14] ? row[14] : ""; - entry.optional = atoi(row[15]); + e.taskid = static_cast(strtoul(row[0], nullptr, 10)); + e.activityid = static_cast(strtoul(row[1], nullptr, 10)); + e.req_activity_id = static_cast(atoi(row[2])); + e.step = static_cast(atoi(row[3])); + e.activitytype = static_cast(strtoul(row[4], nullptr, 10)); + e.target_name = row[5] ? row[5] : ""; + e.goalmethod = static_cast(strtoul(row[6], nullptr, 10)); + e.goalcount = static_cast(atoi(row[7])); + e.description_override = row[8] ? row[8] : ""; + e.npc_match_list = row[9] ? row[9] : ""; + e.item_id_list = row[10] ? row[10] : ""; + e.item_list = row[11] ? row[11] : ""; + e.dz_switch_id = static_cast(atoi(row[12])); + e.min_x = strtof(row[13], nullptr); + e.min_y = strtof(row[14], nullptr); + e.min_z = strtof(row[15], nullptr); + e.max_x = strtof(row[16], nullptr); + e.max_y = strtof(row[17], nullptr); + e.max_z = strtof(row[18], nullptr); + e.skill_list = row[19] ? row[19] : ""; + e.spell_list = row[20] ? row[20] : ""; + e.zones = row[21] ? row[21] : ""; + e.zone_version = static_cast(atoi(row[22])); + e.optional = static_cast(atoi(row[23])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -442,6 +522,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TASK_ACTIVITIES_REPOSITORY_H diff --git a/common/repositories/base/base_tasks_repository.h b/common/repositories/base/base_tasks_repository.h index 23c76d788..de00cff57 100644 --- a/common/repositories/base/base_tasks_repository.h +++ b/common/repositories/base/base_tasks_repository.h @@ -13,35 +13,40 @@ #define EQEMU_BASE_TASKS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTasksRepository { public: struct Tasks { - int id; - int type; - int duration; - int duration_code; + uint32_t id; + int8_t type; + uint32_t duration; + int8_t duration_code; std::string title; std::string description; - std::string reward; - int rewardid; - int cashreward; - int xpreward; - int rewardmethod; - int reward_radiant_crystals; - int reward_ebon_crystals; - int minlevel; - int maxlevel; - int level_spread; - int min_players; - int max_players; - int repeatable; - int faction_reward; + std::string reward_text; + std::string reward_id_list; + uint32_t cash_reward; + int32_t exp_reward; + uint8_t reward_method; + int32_t reward_points; + int32_t reward_point_type; + uint8_t min_level; + uint8_t max_level; + uint32_t level_spread; + uint32_t min_players; + uint32_t max_players; + uint8_t repeatable; + int32_t faction_reward; std::string completion_emote; - int replay_timer_seconds; - int request_timer_seconds; + uint32_t replay_timer_group; + uint32_t replay_timer_seconds; + uint32_t request_timer_group; + uint32_t request_timer_seconds; + uint32_t dz_template_id; + int32_t lock_activity_id; + int32_t faction_amount; }; static std::string PrimaryKey() @@ -58,23 +63,28 @@ public: "duration_code", "title", "description", - "reward", - "rewardid", - "cashreward", - "xpreward", - "rewardmethod", - "reward_radiant_crystals", - "reward_ebon_crystals", - "minlevel", - "maxlevel", + "reward_text", + "reward_id_list", + "cash_reward", + "exp_reward", + "reward_method", + "reward_points", + "reward_point_type", + "min_level", + "max_level", "level_spread", "min_players", "max_players", "repeatable", "faction_reward", "completion_emote", + "replay_timer_group", "replay_timer_seconds", + "request_timer_group", "request_timer_seconds", + "dz_template_id", + "lock_activity_id", + "faction_amount", }; } @@ -87,34 +97,39 @@ public: "duration_code", "title", "description", - "reward", - "rewardid", - "cashreward", - "xpreward", - "rewardmethod", - "reward_radiant_crystals", - "reward_ebon_crystals", - "minlevel", - "maxlevel", + "reward_text", + "reward_id_list", + "cash_reward", + "exp_reward", + "reward_method", + "reward_points", + "reward_point_type", + "min_level", + "max_level", "level_spread", "min_players", "max_players", "repeatable", "faction_reward", "completion_emote", + "replay_timer_group", "replay_timer_seconds", + "request_timer_group", "request_timer_seconds", + "dz_template_id", + "lock_activity_id", + "faction_amount", }; } static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -142,36 +157,41 @@ public: static Tasks NewEntity() { - Tasks entry{}; + Tasks e{}; - entry.id = 0; - entry.type = 0; - entry.duration = 0; - entry.duration_code = 0; - entry.title = ""; - entry.description = ""; - entry.reward = ""; - entry.rewardid = 0; - entry.cashreward = 0; - entry.xpreward = 0; - entry.rewardmethod = 2; - entry.reward_radiant_crystals = 0; - entry.reward_ebon_crystals = 0; - entry.minlevel = 0; - entry.maxlevel = 0; - entry.level_spread = 0; - entry.min_players = 0; - entry.max_players = 0; - entry.repeatable = 1; - entry.faction_reward = 0; - entry.completion_emote = ""; - entry.replay_timer_seconds = 0; - entry.request_timer_seconds = 0; + e.id = 0; + e.type = 0; + e.duration = 0; + e.duration_code = 0; + e.title = ""; + e.description = ""; + e.reward_text = ""; + e.reward_id_list = ""; + e.cash_reward = 0; + e.exp_reward = 0; + e.reward_method = 0; + e.reward_points = 0; + e.reward_point_type = 0; + e.min_level = 0; + e.max_level = 0; + e.level_spread = 0; + e.min_players = 0; + e.max_players = 0; + e.repeatable = 1; + e.faction_reward = 0; + e.completion_emote = ""; + e.replay_timer_group = 0; + e.replay_timer_seconds = 0; + e.request_timer_group = 0; + e.request_timer_seconds = 0; + e.dz_template_id = 0; + e.lock_activity_id = -1; + e.faction_amount = 0; - return entry; + return e; } - static Tasks GetTasksEntry( + static Tasks GetTasks( const std::vector &taskss, int tasks_id ) @@ -200,33 +220,38 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Tasks entry{}; + Tasks e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.duration = atoi(row[2]); - entry.duration_code = atoi(row[3]); - entry.title = row[4] ? row[4] : ""; - entry.description = row[5] ? row[5] : ""; - entry.reward = row[6] ? row[6] : ""; - entry.rewardid = atoi(row[7]); - entry.cashreward = atoi(row[8]); - entry.xpreward = atoi(row[9]); - entry.rewardmethod = atoi(row[10]); - entry.reward_radiant_crystals = atoi(row[11]); - entry.reward_ebon_crystals = atoi(row[12]); - entry.minlevel = atoi(row[13]); - entry.maxlevel = atoi(row[14]); - entry.level_spread = atoi(row[15]); - entry.min_players = atoi(row[16]); - entry.max_players = atoi(row[17]); - entry.repeatable = atoi(row[18]); - entry.faction_reward = atoi(row[19]); - entry.completion_emote = row[20] ? row[20] : ""; - entry.replay_timer_seconds = atoi(row[21]); - entry.request_timer_seconds = atoi(row[22]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(atoi(row[1])); + e.duration = static_cast(strtoul(row[2], nullptr, 10)); + e.duration_code = static_cast(atoi(row[3])); + e.title = row[4] ? row[4] : ""; + e.description = row[5] ? row[5] : ""; + e.reward_text = row[6] ? row[6] : ""; + e.reward_id_list = row[7] ? row[7] : ""; + e.cash_reward = static_cast(strtoul(row[8], nullptr, 10)); + e.exp_reward = static_cast(atoi(row[9])); + e.reward_method = static_cast(strtoul(row[10], nullptr, 10)); + e.reward_points = static_cast(atoi(row[11])); + e.reward_point_type = static_cast(atoi(row[12])); + e.min_level = static_cast(strtoul(row[13], nullptr, 10)); + e.max_level = static_cast(strtoul(row[14], nullptr, 10)); + e.level_spread = static_cast(strtoul(row[15], nullptr, 10)); + e.min_players = static_cast(strtoul(row[16], nullptr, 10)); + e.max_players = static_cast(strtoul(row[17], nullptr, 10)); + e.repeatable = static_cast(strtoul(row[18], nullptr, 10)); + e.faction_reward = static_cast(atoi(row[19])); + e.completion_emote = row[20] ? row[20] : ""; + e.replay_timer_group = static_cast(strtoul(row[21], nullptr, 10)); + e.replay_timer_seconds = static_cast(strtoul(row[22], nullptr, 10)); + e.request_timer_group = static_cast(strtoul(row[23], nullptr, 10)); + e.request_timer_seconds = static_cast(strtoul(row[24], nullptr, 10)); + e.dz_template_id = static_cast(strtoul(row[25], nullptr, 10)); + e.lock_activity_id = static_cast(atoi(row[26])); + e.faction_amount = static_cast(atoi(row[27])); - return entry; + return e; } return NewEntity(); @@ -251,44 +276,49 @@ public: static int UpdateOne( Database& db, - Tasks tasks_entry + const Tasks &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(tasks_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(tasks_entry.type)); - update_values.push_back(columns[2] + " = " + std::to_string(tasks_entry.duration)); - update_values.push_back(columns[3] + " = " + std::to_string(tasks_entry.duration_code)); - update_values.push_back(columns[4] + " = '" + EscapeString(tasks_entry.title) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(tasks_entry.description) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(tasks_entry.reward) + "'"); - update_values.push_back(columns[7] + " = " + std::to_string(tasks_entry.rewardid)); - update_values.push_back(columns[8] + " = " + std::to_string(tasks_entry.cashreward)); - update_values.push_back(columns[9] + " = " + std::to_string(tasks_entry.xpreward)); - update_values.push_back(columns[10] + " = " + std::to_string(tasks_entry.rewardmethod)); - update_values.push_back(columns[11] + " = " + std::to_string(tasks_entry.reward_radiant_crystals)); - update_values.push_back(columns[12] + " = " + std::to_string(tasks_entry.reward_ebon_crystals)); - update_values.push_back(columns[13] + " = " + std::to_string(tasks_entry.minlevel)); - update_values.push_back(columns[14] + " = " + std::to_string(tasks_entry.maxlevel)); - update_values.push_back(columns[15] + " = " + std::to_string(tasks_entry.level_spread)); - update_values.push_back(columns[16] + " = " + std::to_string(tasks_entry.min_players)); - update_values.push_back(columns[17] + " = " + std::to_string(tasks_entry.max_players)); - update_values.push_back(columns[18] + " = " + std::to_string(tasks_entry.repeatable)); - update_values.push_back(columns[19] + " = " + std::to_string(tasks_entry.faction_reward)); - update_values.push_back(columns[20] + " = '" + EscapeString(tasks_entry.completion_emote) + "'"); - update_values.push_back(columns[21] + " = " + std::to_string(tasks_entry.replay_timer_seconds)); - update_values.push_back(columns[22] + " = " + std::to_string(tasks_entry.request_timer_seconds)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.type)); + v.push_back(columns[2] + " = " + std::to_string(e.duration)); + v.push_back(columns[3] + " = " + std::to_string(e.duration_code)); + v.push_back(columns[4] + " = '" + Strings::Escape(e.title) + "'"); + v.push_back(columns[5] + " = '" + Strings::Escape(e.description) + "'"); + v.push_back(columns[6] + " = '" + Strings::Escape(e.reward_text) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.reward_id_list) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.cash_reward)); + v.push_back(columns[9] + " = " + std::to_string(e.exp_reward)); + v.push_back(columns[10] + " = " + std::to_string(e.reward_method)); + v.push_back(columns[11] + " = " + std::to_string(e.reward_points)); + v.push_back(columns[12] + " = " + std::to_string(e.reward_point_type)); + v.push_back(columns[13] + " = " + std::to_string(e.min_level)); + v.push_back(columns[14] + " = " + std::to_string(e.max_level)); + v.push_back(columns[15] + " = " + std::to_string(e.level_spread)); + v.push_back(columns[16] + " = " + std::to_string(e.min_players)); + v.push_back(columns[17] + " = " + std::to_string(e.max_players)); + v.push_back(columns[18] + " = " + std::to_string(e.repeatable)); + v.push_back(columns[19] + " = " + std::to_string(e.faction_reward)); + v.push_back(columns[20] + " = '" + Strings::Escape(e.completion_emote) + "'"); + v.push_back(columns[21] + " = " + std::to_string(e.replay_timer_group)); + v.push_back(columns[22] + " = " + std::to_string(e.replay_timer_seconds)); + v.push_back(columns[23] + " = " + std::to_string(e.request_timer_group)); + v.push_back(columns[24] + " = " + std::to_string(e.request_timer_seconds)); + v.push_back(columns[25] + " = " + std::to_string(e.dz_template_id)); + v.push_back(columns[26] + " = " + std::to_string(e.lock_activity_id)); + v.push_back(columns[27] + " = " + std::to_string(e.faction_amount)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - tasks_entry.id + e.id ) ); @@ -297,97 +327,107 @@ public: static Tasks InsertOne( Database& db, - Tasks tasks_entry + Tasks e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(tasks_entry.id)); - insert_values.push_back(std::to_string(tasks_entry.type)); - insert_values.push_back(std::to_string(tasks_entry.duration)); - insert_values.push_back(std::to_string(tasks_entry.duration_code)); - insert_values.push_back("'" + EscapeString(tasks_entry.title) + "'"); - insert_values.push_back("'" + EscapeString(tasks_entry.description) + "'"); - insert_values.push_back("'" + EscapeString(tasks_entry.reward) + "'"); - insert_values.push_back(std::to_string(tasks_entry.rewardid)); - insert_values.push_back(std::to_string(tasks_entry.cashreward)); - insert_values.push_back(std::to_string(tasks_entry.xpreward)); - insert_values.push_back(std::to_string(tasks_entry.rewardmethod)); - insert_values.push_back(std::to_string(tasks_entry.reward_radiant_crystals)); - insert_values.push_back(std::to_string(tasks_entry.reward_ebon_crystals)); - insert_values.push_back(std::to_string(tasks_entry.minlevel)); - insert_values.push_back(std::to_string(tasks_entry.maxlevel)); - insert_values.push_back(std::to_string(tasks_entry.level_spread)); - insert_values.push_back(std::to_string(tasks_entry.min_players)); - insert_values.push_back(std::to_string(tasks_entry.max_players)); - insert_values.push_back(std::to_string(tasks_entry.repeatable)); - insert_values.push_back(std::to_string(tasks_entry.faction_reward)); - insert_values.push_back("'" + EscapeString(tasks_entry.completion_emote) + "'"); - insert_values.push_back(std::to_string(tasks_entry.replay_timer_seconds)); - insert_values.push_back(std::to_string(tasks_entry.request_timer_seconds)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.duration_code)); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back("'" + Strings::Escape(e.reward_text) + "'"); + v.push_back("'" + Strings::Escape(e.reward_id_list) + "'"); + v.push_back(std::to_string(e.cash_reward)); + v.push_back(std::to_string(e.exp_reward)); + v.push_back(std::to_string(e.reward_method)); + v.push_back(std::to_string(e.reward_points)); + v.push_back(std::to_string(e.reward_point_type)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.level_spread)); + v.push_back(std::to_string(e.min_players)); + v.push_back(std::to_string(e.max_players)); + v.push_back(std::to_string(e.repeatable)); + v.push_back(std::to_string(e.faction_reward)); + v.push_back("'" + Strings::Escape(e.completion_emote) + "'"); + v.push_back(std::to_string(e.replay_timer_group)); + v.push_back(std::to_string(e.replay_timer_seconds)); + v.push_back(std::to_string(e.request_timer_group)); + v.push_back(std::to_string(e.request_timer_seconds)); + v.push_back(std::to_string(e.dz_template_id)); + v.push_back(std::to_string(e.lock_activity_id)); + v.push_back(std::to_string(e.faction_amount)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - tasks_entry.id = results.LastInsertedID(); - return tasks_entry; + e.id = results.LastInsertedID(); + return e; } - tasks_entry = NewEntity(); + e = NewEntity(); - return tasks_entry; + return e; } static int InsertMany( Database& db, - std::vector tasks_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &tasks_entry: tasks_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(tasks_entry.id)); - insert_values.push_back(std::to_string(tasks_entry.type)); - insert_values.push_back(std::to_string(tasks_entry.duration)); - insert_values.push_back(std::to_string(tasks_entry.duration_code)); - insert_values.push_back("'" + EscapeString(tasks_entry.title) + "'"); - insert_values.push_back("'" + EscapeString(tasks_entry.description) + "'"); - insert_values.push_back("'" + EscapeString(tasks_entry.reward) + "'"); - insert_values.push_back(std::to_string(tasks_entry.rewardid)); - insert_values.push_back(std::to_string(tasks_entry.cashreward)); - insert_values.push_back(std::to_string(tasks_entry.xpreward)); - insert_values.push_back(std::to_string(tasks_entry.rewardmethod)); - insert_values.push_back(std::to_string(tasks_entry.reward_radiant_crystals)); - insert_values.push_back(std::to_string(tasks_entry.reward_ebon_crystals)); - insert_values.push_back(std::to_string(tasks_entry.minlevel)); - insert_values.push_back(std::to_string(tasks_entry.maxlevel)); - insert_values.push_back(std::to_string(tasks_entry.level_spread)); - insert_values.push_back(std::to_string(tasks_entry.min_players)); - insert_values.push_back(std::to_string(tasks_entry.max_players)); - insert_values.push_back(std::to_string(tasks_entry.repeatable)); - insert_values.push_back(std::to_string(tasks_entry.faction_reward)); - insert_values.push_back("'" + EscapeString(tasks_entry.completion_emote) + "'"); - insert_values.push_back(std::to_string(tasks_entry.replay_timer_seconds)); - insert_values.push_back(std::to_string(tasks_entry.request_timer_seconds)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.duration_code)); + v.push_back("'" + Strings::Escape(e.title) + "'"); + v.push_back("'" + Strings::Escape(e.description) + "'"); + v.push_back("'" + Strings::Escape(e.reward_text) + "'"); + v.push_back("'" + Strings::Escape(e.reward_id_list) + "'"); + v.push_back(std::to_string(e.cash_reward)); + v.push_back(std::to_string(e.exp_reward)); + v.push_back(std::to_string(e.reward_method)); + v.push_back(std::to_string(e.reward_points)); + v.push_back(std::to_string(e.reward_point_type)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.level_spread)); + v.push_back(std::to_string(e.min_players)); + v.push_back(std::to_string(e.max_players)); + v.push_back(std::to_string(e.repeatable)); + v.push_back(std::to_string(e.faction_reward)); + v.push_back("'" + Strings::Escape(e.completion_emote) + "'"); + v.push_back(std::to_string(e.replay_timer_group)); + v.push_back(std::to_string(e.replay_timer_seconds)); + v.push_back(std::to_string(e.request_timer_group)); + v.push_back(std::to_string(e.request_timer_seconds)); + v.push_back(std::to_string(e.dz_template_id)); + v.push_back(std::to_string(e.lock_activity_id)); + v.push_back(std::to_string(e.faction_amount)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -408,39 +448,44 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Tasks entry{}; + Tasks e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.duration = atoi(row[2]); - entry.duration_code = atoi(row[3]); - entry.title = row[4] ? row[4] : ""; - entry.description = row[5] ? row[5] : ""; - entry.reward = row[6] ? row[6] : ""; - entry.rewardid = atoi(row[7]); - entry.cashreward = atoi(row[8]); - entry.xpreward = atoi(row[9]); - entry.rewardmethod = atoi(row[10]); - entry.reward_radiant_crystals = atoi(row[11]); - entry.reward_ebon_crystals = atoi(row[12]); - entry.minlevel = atoi(row[13]); - entry.maxlevel = atoi(row[14]); - entry.level_spread = atoi(row[15]); - entry.min_players = atoi(row[16]); - entry.max_players = atoi(row[17]); - entry.repeatable = atoi(row[18]); - entry.faction_reward = atoi(row[19]); - entry.completion_emote = row[20] ? row[20] : ""; - entry.replay_timer_seconds = atoi(row[21]); - entry.request_timer_seconds = atoi(row[22]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(atoi(row[1])); + e.duration = static_cast(strtoul(row[2], nullptr, 10)); + e.duration_code = static_cast(atoi(row[3])); + e.title = row[4] ? row[4] : ""; + e.description = row[5] ? row[5] : ""; + e.reward_text = row[6] ? row[6] : ""; + e.reward_id_list = row[7] ? row[7] : ""; + e.cash_reward = static_cast(strtoul(row[8], nullptr, 10)); + e.exp_reward = static_cast(atoi(row[9])); + e.reward_method = static_cast(strtoul(row[10], nullptr, 10)); + e.reward_points = static_cast(atoi(row[11])); + e.reward_point_type = static_cast(atoi(row[12])); + e.min_level = static_cast(strtoul(row[13], nullptr, 10)); + e.max_level = static_cast(strtoul(row[14], nullptr, 10)); + e.level_spread = static_cast(strtoul(row[15], nullptr, 10)); + e.min_players = static_cast(strtoul(row[16], nullptr, 10)); + e.max_players = static_cast(strtoul(row[17], nullptr, 10)); + e.repeatable = static_cast(strtoul(row[18], nullptr, 10)); + e.faction_reward = static_cast(atoi(row[19])); + e.completion_emote = row[20] ? row[20] : ""; + e.replay_timer_group = static_cast(strtoul(row[21], nullptr, 10)); + e.replay_timer_seconds = static_cast(strtoul(row[22], nullptr, 10)); + e.request_timer_group = static_cast(strtoul(row[23], nullptr, 10)); + e.request_timer_seconds = static_cast(strtoul(row[24], nullptr, 10)); + e.dz_template_id = static_cast(strtoul(row[25], nullptr, 10)); + e.lock_activity_id = static_cast(atoi(row[26])); + e.faction_amount = static_cast(atoi(row[27])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -455,39 +500,44 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Tasks entry{}; + Tasks e{}; - entry.id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.duration = atoi(row[2]); - entry.duration_code = atoi(row[3]); - entry.title = row[4] ? row[4] : ""; - entry.description = row[5] ? row[5] : ""; - entry.reward = row[6] ? row[6] : ""; - entry.rewardid = atoi(row[7]); - entry.cashreward = atoi(row[8]); - entry.xpreward = atoi(row[9]); - entry.rewardmethod = atoi(row[10]); - entry.reward_radiant_crystals = atoi(row[11]); - entry.reward_ebon_crystals = atoi(row[12]); - entry.minlevel = atoi(row[13]); - entry.maxlevel = atoi(row[14]); - entry.level_spread = atoi(row[15]); - entry.min_players = atoi(row[16]); - entry.max_players = atoi(row[17]); - entry.repeatable = atoi(row[18]); - entry.faction_reward = atoi(row[19]); - entry.completion_emote = row[20] ? row[20] : ""; - entry.replay_timer_seconds = atoi(row[21]); - entry.request_timer_seconds = atoi(row[22]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.type = static_cast(atoi(row[1])); + e.duration = static_cast(strtoul(row[2], nullptr, 10)); + e.duration_code = static_cast(atoi(row[3])); + e.title = row[4] ? row[4] : ""; + e.description = row[5] ? row[5] : ""; + e.reward_text = row[6] ? row[6] : ""; + e.reward_id_list = row[7] ? row[7] : ""; + e.cash_reward = static_cast(strtoul(row[8], nullptr, 10)); + e.exp_reward = static_cast(atoi(row[9])); + e.reward_method = static_cast(strtoul(row[10], nullptr, 10)); + e.reward_points = static_cast(atoi(row[11])); + e.reward_point_type = static_cast(atoi(row[12])); + e.min_level = static_cast(strtoul(row[13], nullptr, 10)); + e.max_level = static_cast(strtoul(row[14], nullptr, 10)); + e.level_spread = static_cast(strtoul(row[15], nullptr, 10)); + e.min_players = static_cast(strtoul(row[16], nullptr, 10)); + e.max_players = static_cast(strtoul(row[17], nullptr, 10)); + e.repeatable = static_cast(strtoul(row[18], nullptr, 10)); + e.faction_reward = static_cast(atoi(row[19])); + e.completion_emote = row[20] ? row[20] : ""; + e.replay_timer_group = static_cast(strtoul(row[21], nullptr, 10)); + e.replay_timer_seconds = static_cast(strtoul(row[22], nullptr, 10)); + e.request_timer_group = static_cast(strtoul(row[23], nullptr, 10)); + e.request_timer_seconds = static_cast(strtoul(row[24], nullptr, 10)); + e.dz_template_id = static_cast(strtoul(row[25], nullptr, 10)); + e.lock_activity_id = static_cast(atoi(row[26])); + e.faction_amount = static_cast(atoi(row[27])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -512,6 +562,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_tasksets_repository.h b/common/repositories/base/base_tasksets_repository.h index 2dd53531f..396d5fdee 100644 --- a/common/repositories/base/base_tasksets_repository.h +++ b/common/repositories/base/base_tasksets_repository.h @@ -13,14 +13,14 @@ #define EQEMU_BASE_TASKSETS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTasksetsRepository { public: struct Tasksets { - int id; - int taskid; + uint32_t id; + uint32_t taskid; }; static std::string PrimaryKey() @@ -46,12 +46,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -79,15 +79,15 @@ public: static Tasksets NewEntity() { - Tasksets entry{}; + Tasksets e{}; - entry.id = 0; - entry.taskid = 0; + e.id = 0; + e.taskid = 0; - return entry; + return e; } - static Tasksets GetTasksetsEntry( + static Tasksets GetTasksets( const std::vector &tasksetss, int tasksets_id ) @@ -116,12 +116,12 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Tasksets entry{}; + Tasksets e{}; - entry.id = atoi(row[0]); - entry.taskid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -146,23 +146,23 @@ public: static int UpdateOne( Database& db, - Tasksets tasksets_entry + const Tasksets &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(tasksets_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(tasksets_entry.taskid)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.taskid)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - tasksets_entry.id + e.id ) ); @@ -171,55 +171,55 @@ public: static Tasksets InsertOne( Database& db, - Tasksets tasksets_entry + Tasksets e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(tasksets_entry.id)); - insert_values.push_back(std::to_string(tasksets_entry.taskid)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.taskid)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - tasksets_entry.id = results.LastInsertedID(); - return tasksets_entry; + e.id = results.LastInsertedID(); + return e; } - tasksets_entry = NewEntity(); + e = NewEntity(); - return tasksets_entry; + return e; } static int InsertMany( Database& db, - std::vector tasksets_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &tasksets_entry: tasksets_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(tasksets_entry.id)); - insert_values.push_back(std::to_string(tasksets_entry.taskid)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.taskid)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -240,18 +240,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Tasksets entry{}; + Tasksets e{}; - entry.id = atoi(row[0]); - entry.taskid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -266,18 +266,18 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Tasksets entry{}; + Tasksets e{}; - entry.id = atoi(row[0]); - entry.taskid = atoi(row[1]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.taskid = static_cast(strtoul(row[1], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -302,6 +302,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TASKSETS_REPOSITORY_H diff --git a/common/repositories/base/base_timers_repository.h b/common/repositories/base/base_timers_repository.h index 4be6e959d..cfe951099 100644 --- a/common/repositories/base/base_timers_repository.h +++ b/common/repositories/base/base_timers_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_TIMERS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTimersRepository { public: struct Timers { - int char_id; - int type; - int start; - int duration; - int enable; + int32_t char_id; + uint32_t type; + uint32_t start; + uint32_t duration; + int8_t enable; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static Timers NewEntity() { - Timers entry{}; + Timers e{}; - entry.char_id = 0; - entry.type = 0; - entry.start = 0; - entry.duration = 0; - entry.enable = 0; + e.char_id = 0; + e.type = 0; + e.start = 0; + e.duration = 0; + e.enable = 0; - return entry; + return e; } - static Timers GetTimersEntry( + static Timers GetTimers( const std::vector &timerss, int timers_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Timers entry{}; + Timers e{}; - entry.char_id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.start = atoi(row[2]); - entry.duration = atoi(row[3]); - entry.enable = atoi(row[4]); + e.char_id = static_cast(atoi(row[0])); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.start = static_cast(strtoul(row[2], nullptr, 10)); + e.duration = static_cast(strtoul(row[3], nullptr, 10)); + e.enable = static_cast(atoi(row[4])); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - Timers timers_entry + const Timers &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(timers_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(timers_entry.type)); - update_values.push_back(columns[2] + " = " + std::to_string(timers_entry.start)); - update_values.push_back(columns[3] + " = " + std::to_string(timers_entry.duration)); - update_values.push_back(columns[4] + " = " + std::to_string(timers_entry.enable)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.type)); + v.push_back(columns[2] + " = " + std::to_string(e.start)); + v.push_back(columns[3] + " = " + std::to_string(e.duration)); + v.push_back(columns[4] + " = " + std::to_string(e.enable)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - timers_entry.char_id + e.char_id ) ); @@ -189,61 +189,61 @@ public: static Timers InsertOne( Database& db, - Timers timers_entry + Timers e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(timers_entry.char_id)); - insert_values.push_back(std::to_string(timers_entry.type)); - insert_values.push_back(std::to_string(timers_entry.start)); - insert_values.push_back(std::to_string(timers_entry.duration)); - insert_values.push_back(std::to_string(timers_entry.enable)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.start)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.enable)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - timers_entry.char_id = results.LastInsertedID(); - return timers_entry; + e.char_id = results.LastInsertedID(); + return e; } - timers_entry = NewEntity(); + e = NewEntity(); - return timers_entry; + return e; } static int InsertMany( Database& db, - std::vector timers_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &timers_entry: timers_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(timers_entry.char_id)); - insert_values.push_back(std::to_string(timers_entry.type)); - insert_values.push_back(std::to_string(timers_entry.start)); - insert_values.push_back(std::to_string(timers_entry.duration)); - insert_values.push_back(std::to_string(timers_entry.enable)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.start)); + v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.enable)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Timers entry{}; + Timers e{}; - entry.char_id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.start = atoi(row[2]); - entry.duration = atoi(row[3]); - entry.enable = atoi(row[4]); + e.char_id = static_cast(atoi(row[0])); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.start = static_cast(strtoul(row[2], nullptr, 10)); + e.duration = static_cast(strtoul(row[3], nullptr, 10)); + e.enable = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Timers entry{}; + Timers e{}; - entry.char_id = atoi(row[0]); - entry.type = atoi(row[1]); - entry.start = atoi(row[2]); - entry.duration = atoi(row[3]); - entry.enable = atoi(row[4]); + e.char_id = static_cast(atoi(row[0])); + e.type = static_cast(strtoul(row[1], nullptr, 10)); + e.start = static_cast(strtoul(row[2], nullptr, 10)); + e.duration = static_cast(strtoul(row[3], nullptr, 10)); + e.enable = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TIMERS_REPOSITORY_H diff --git a/common/repositories/base/base_titles_repository.h b/common/repositories/base/base_titles_repository.h index fec2556d4..851f4729e 100644 --- a/common/repositories/base/base_titles_repository.h +++ b/common/repositories/base/base_titles_repository.h @@ -13,26 +13,26 @@ #define EQEMU_BASE_TITLES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTitlesRepository { public: struct Titles { - int id; - int skill_id; - int min_skill_value; - int max_skill_value; - int min_aa_points; - int max_aa_points; - int class_; - int gender; - int char_id; - int status; - int item_id; + uint32_t id; + int8_t skill_id; + int32_t min_skill_value; + int32_t max_skill_value; + int32_t min_aa_points; + int32_t max_aa_points; + int8_t class_; + int8_t gender; + int32_t char_id; + int32_t status; + int32_t item_id; std::string prefix; std::string suffix; - int title_set; + int32_t title_set; }; static std::string PrimaryKey() @@ -82,12 +82,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -115,27 +115,27 @@ public: static Titles NewEntity() { - Titles entry{}; + Titles e{}; - entry.id = 0; - entry.skill_id = -1; - entry.min_skill_value = -1; - entry.max_skill_value = -1; - entry.min_aa_points = -1; - entry.max_aa_points = -1; - entry.class_ = -1; - entry.gender = -1; - entry.char_id = -1; - entry.status = -1; - entry.item_id = -1; - entry.prefix = ""; - entry.suffix = ""; - entry.title_set = 0; + e.id = 0; + e.skill_id = -1; + e.min_skill_value = -1; + e.max_skill_value = -1; + e.min_aa_points = -1; + e.max_aa_points = -1; + e.class_ = -1; + e.gender = -1; + e.char_id = -1; + e.status = -1; + e.item_id = -1; + e.prefix = ""; + e.suffix = ""; + e.title_set = 0; - return entry; + return e; } - static Titles GetTitlesEntry( + static Titles GetTitles( const std::vector &titless, int titles_id ) @@ -164,24 +164,24 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Titles entry{}; + Titles e{}; - entry.id = atoi(row[0]); - entry.skill_id = atoi(row[1]); - entry.min_skill_value = atoi(row[2]); - entry.max_skill_value = atoi(row[3]); - entry.min_aa_points = atoi(row[4]); - entry.max_aa_points = atoi(row[5]); - entry.class_ = atoi(row[6]); - entry.gender = atoi(row[7]); - entry.char_id = atoi(row[8]); - entry.status = atoi(row[9]); - entry.item_id = atoi(row[10]); - entry.prefix = row[11] ? row[11] : ""; - entry.suffix = row[12] ? row[12] : ""; - entry.title_set = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.skill_id = static_cast(atoi(row[1])); + e.min_skill_value = static_cast(atoi(row[2])); + e.max_skill_value = static_cast(atoi(row[3])); + e.min_aa_points = static_cast(atoi(row[4])); + e.max_aa_points = static_cast(atoi(row[5])); + e.class_ = static_cast(atoi(row[6])); + e.gender = static_cast(atoi(row[7])); + e.char_id = static_cast(atoi(row[8])); + e.status = static_cast(atoi(row[9])); + e.item_id = static_cast(atoi(row[10])); + e.prefix = row[11] ? row[11] : ""; + e.suffix = row[12] ? row[12] : ""; + e.title_set = static_cast(atoi(row[13])); - return entry; + return e; } return NewEntity(); @@ -206,34 +206,34 @@ public: static int UpdateOne( Database& db, - Titles titles_entry + const Titles &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(titles_entry.skill_id)); - update_values.push_back(columns[2] + " = " + std::to_string(titles_entry.min_skill_value)); - update_values.push_back(columns[3] + " = " + std::to_string(titles_entry.max_skill_value)); - update_values.push_back(columns[4] + " = " + std::to_string(titles_entry.min_aa_points)); - update_values.push_back(columns[5] + " = " + std::to_string(titles_entry.max_aa_points)); - update_values.push_back(columns[6] + " = " + std::to_string(titles_entry.class_)); - update_values.push_back(columns[7] + " = " + std::to_string(titles_entry.gender)); - update_values.push_back(columns[8] + " = " + std::to_string(titles_entry.char_id)); - update_values.push_back(columns[9] + " = " + std::to_string(titles_entry.status)); - update_values.push_back(columns[10] + " = " + std::to_string(titles_entry.item_id)); - update_values.push_back(columns[11] + " = '" + EscapeString(titles_entry.prefix) + "'"); - update_values.push_back(columns[12] + " = '" + EscapeString(titles_entry.suffix) + "'"); - update_values.push_back(columns[13] + " = " + std::to_string(titles_entry.title_set)); + v.push_back(columns[1] + " = " + std::to_string(e.skill_id)); + v.push_back(columns[2] + " = " + std::to_string(e.min_skill_value)); + v.push_back(columns[3] + " = " + std::to_string(e.max_skill_value)); + v.push_back(columns[4] + " = " + std::to_string(e.min_aa_points)); + v.push_back(columns[5] + " = " + std::to_string(e.max_aa_points)); + v.push_back(columns[6] + " = " + std::to_string(e.class_)); + v.push_back(columns[7] + " = " + std::to_string(e.gender)); + v.push_back(columns[8] + " = " + std::to_string(e.char_id)); + v.push_back(columns[9] + " = " + std::to_string(e.status)); + v.push_back(columns[10] + " = " + std::to_string(e.item_id)); + v.push_back(columns[11] + " = '" + Strings::Escape(e.prefix) + "'"); + v.push_back(columns[12] + " = '" + Strings::Escape(e.suffix) + "'"); + v.push_back(columns[13] + " = " + std::to_string(e.title_set)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - titles_entry.id + e.id ) ); @@ -242,79 +242,79 @@ public: static Titles InsertOne( Database& db, - Titles titles_entry + Titles e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(titles_entry.id)); - insert_values.push_back(std::to_string(titles_entry.skill_id)); - insert_values.push_back(std::to_string(titles_entry.min_skill_value)); - insert_values.push_back(std::to_string(titles_entry.max_skill_value)); - insert_values.push_back(std::to_string(titles_entry.min_aa_points)); - insert_values.push_back(std::to_string(titles_entry.max_aa_points)); - insert_values.push_back(std::to_string(titles_entry.class_)); - insert_values.push_back(std::to_string(titles_entry.gender)); - insert_values.push_back(std::to_string(titles_entry.char_id)); - insert_values.push_back(std::to_string(titles_entry.status)); - insert_values.push_back(std::to_string(titles_entry.item_id)); - insert_values.push_back("'" + EscapeString(titles_entry.prefix) + "'"); - insert_values.push_back("'" + EscapeString(titles_entry.suffix) + "'"); - insert_values.push_back(std::to_string(titles_entry.title_set)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.skill_id)); + v.push_back(std::to_string(e.min_skill_value)); + v.push_back(std::to_string(e.max_skill_value)); + v.push_back(std::to_string(e.min_aa_points)); + v.push_back(std::to_string(e.max_aa_points)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.status)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.prefix) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + v.push_back(std::to_string(e.title_set)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - titles_entry.id = results.LastInsertedID(); - return titles_entry; + e.id = results.LastInsertedID(); + return e; } - titles_entry = NewEntity(); + e = NewEntity(); - return titles_entry; + return e; } static int InsertMany( Database& db, - std::vector titles_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &titles_entry: titles_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(titles_entry.id)); - insert_values.push_back(std::to_string(titles_entry.skill_id)); - insert_values.push_back(std::to_string(titles_entry.min_skill_value)); - insert_values.push_back(std::to_string(titles_entry.max_skill_value)); - insert_values.push_back(std::to_string(titles_entry.min_aa_points)); - insert_values.push_back(std::to_string(titles_entry.max_aa_points)); - insert_values.push_back(std::to_string(titles_entry.class_)); - insert_values.push_back(std::to_string(titles_entry.gender)); - insert_values.push_back(std::to_string(titles_entry.char_id)); - insert_values.push_back(std::to_string(titles_entry.status)); - insert_values.push_back(std::to_string(titles_entry.item_id)); - insert_values.push_back("'" + EscapeString(titles_entry.prefix) + "'"); - insert_values.push_back("'" + EscapeString(titles_entry.suffix) + "'"); - insert_values.push_back(std::to_string(titles_entry.title_set)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.skill_id)); + v.push_back(std::to_string(e.min_skill_value)); + v.push_back(std::to_string(e.max_skill_value)); + v.push_back(std::to_string(e.min_aa_points)); + v.push_back(std::to_string(e.max_aa_points)); + v.push_back(std::to_string(e.class_)); + v.push_back(std::to_string(e.gender)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.status)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.prefix) + "'"); + v.push_back("'" + Strings::Escape(e.suffix) + "'"); + v.push_back(std::to_string(e.title_set)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -335,30 +335,30 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Titles entry{}; + Titles e{}; - entry.id = atoi(row[0]); - entry.skill_id = atoi(row[1]); - entry.min_skill_value = atoi(row[2]); - entry.max_skill_value = atoi(row[3]); - entry.min_aa_points = atoi(row[4]); - entry.max_aa_points = atoi(row[5]); - entry.class_ = atoi(row[6]); - entry.gender = atoi(row[7]); - entry.char_id = atoi(row[8]); - entry.status = atoi(row[9]); - entry.item_id = atoi(row[10]); - entry.prefix = row[11] ? row[11] : ""; - entry.suffix = row[12] ? row[12] : ""; - entry.title_set = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.skill_id = static_cast(atoi(row[1])); + e.min_skill_value = static_cast(atoi(row[2])); + e.max_skill_value = static_cast(atoi(row[3])); + e.min_aa_points = static_cast(atoi(row[4])); + e.max_aa_points = static_cast(atoi(row[5])); + e.class_ = static_cast(atoi(row[6])); + e.gender = static_cast(atoi(row[7])); + e.char_id = static_cast(atoi(row[8])); + e.status = static_cast(atoi(row[9])); + e.item_id = static_cast(atoi(row[10])); + e.prefix = row[11] ? row[11] : ""; + e.suffix = row[12] ? row[12] : ""; + e.title_set = static_cast(atoi(row[13])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -373,30 +373,30 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Titles entry{}; + Titles e{}; - entry.id = atoi(row[0]); - entry.skill_id = atoi(row[1]); - entry.min_skill_value = atoi(row[2]); - entry.max_skill_value = atoi(row[3]); - entry.min_aa_points = atoi(row[4]); - entry.max_aa_points = atoi(row[5]); - entry.class_ = atoi(row[6]); - entry.gender = atoi(row[7]); - entry.char_id = atoi(row[8]); - entry.status = atoi(row[9]); - entry.item_id = atoi(row[10]); - entry.prefix = row[11] ? row[11] : ""; - entry.suffix = row[12] ? row[12] : ""; - entry.title_set = atoi(row[13]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.skill_id = static_cast(atoi(row[1])); + e.min_skill_value = static_cast(atoi(row[2])); + e.max_skill_value = static_cast(atoi(row[3])); + e.min_aa_points = static_cast(atoi(row[4])); + e.max_aa_points = static_cast(atoi(row[5])); + e.class_ = static_cast(atoi(row[6])); + e.gender = static_cast(atoi(row[7])); + e.char_id = static_cast(atoi(row[8])); + e.status = static_cast(atoi(row[9])); + e.item_id = static_cast(atoi(row[10])); + e.prefix = row[11] ? row[11] : ""; + e.suffix = row[12] ? row[12] : ""; + e.title_set = static_cast(atoi(row[13])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -421,6 +421,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TITLES_REPOSITORY_H diff --git a/common/repositories/base/base_tool_game_objects_repository.h b/common/repositories/base/base_tool_game_objects_repository.h index 3e1f8600f..908844df7 100644 --- a/common/repositories/base/base_tool_game_objects_repository.h +++ b/common/repositories/base/base_tool_game_objects_repository.h @@ -13,7 +13,7 @@ #define EQEMU_BASE_TOOL_GAME_OBJECTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseToolGameObjectsRepository { @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -174,16 +174,16 @@ public: auto columns = Columns(); update_values.push_back(columns[1] + " = " + std::to_string(tool_game_objects_entry.zoneid)); - update_values.push_back(columns[2] + " = '" + EscapeString(tool_game_objects_entry.zonesn) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(tool_game_objects_entry.object_name) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(tool_game_objects_entry.file_from) + "'"); + update_values.push_back(columns[2] + " = '" + Strings::Escape(tool_game_objects_entry.zonesn) + "'"); + update_values.push_back(columns[3] + " = '" + Strings::Escape(tool_game_objects_entry.object_name) + "'"); + update_values.push_back(columns[4] + " = '" + Strings::Escape(tool_game_objects_entry.file_from) + "'"); update_values.push_back(columns[5] + " = " + std::to_string(tool_game_objects_entry.is_global)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), tool_game_objects_entry.id ) @@ -201,16 +201,16 @@ public: insert_values.push_back(std::to_string(tool_game_objects_entry.id)); insert_values.push_back(std::to_string(tool_game_objects_entry.zoneid)); - insert_values.push_back("'" + EscapeString(tool_game_objects_entry.zonesn) + "'"); - insert_values.push_back("'" + EscapeString(tool_game_objects_entry.object_name) + "'"); - insert_values.push_back("'" + EscapeString(tool_game_objects_entry.file_from) + "'"); + insert_values.push_back("'" + Strings::Escape(tool_game_objects_entry.zonesn) + "'"); + insert_values.push_back("'" + Strings::Escape(tool_game_objects_entry.object_name) + "'"); + insert_values.push_back("'" + Strings::Escape(tool_game_objects_entry.file_from) + "'"); insert_values.push_back(std::to_string(tool_game_objects_entry.is_global)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -236,12 +236,12 @@ public: insert_values.push_back(std::to_string(tool_game_objects_entry.id)); insert_values.push_back(std::to_string(tool_game_objects_entry.zoneid)); - insert_values.push_back("'" + EscapeString(tool_game_objects_entry.zonesn) + "'"); - insert_values.push_back("'" + EscapeString(tool_game_objects_entry.object_name) + "'"); - insert_values.push_back("'" + EscapeString(tool_game_objects_entry.file_from) + "'"); + insert_values.push_back("'" + Strings::Escape(tool_game_objects_entry.zonesn) + "'"); + insert_values.push_back("'" + Strings::Escape(tool_game_objects_entry.object_name) + "'"); + insert_values.push_back("'" + Strings::Escape(tool_game_objects_entry.file_from) + "'"); insert_values.push_back(std::to_string(tool_game_objects_entry.is_global)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -250,7 +250,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/base/base_trader_repository.h b/common/repositories/base/base_trader_repository.h index 2fa33f862..a057b6bc6 100644 --- a/common/repositories/base/base_trader_repository.h +++ b/common/repositories/base/base_trader_repository.h @@ -13,18 +13,18 @@ #define EQEMU_BASE_TRADER_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTraderRepository { public: struct Trader { - int char_id; - int item_id; - int serialnumber; - int charges; - int item_cost; - int slot_id; + uint32_t char_id; + uint32_t item_id; + uint32_t serialnumber; + int32_t charges; + uint32_t item_cost; + uint8_t slot_id; }; static std::string PrimaryKey() @@ -58,12 +58,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -91,19 +91,19 @@ public: static Trader NewEntity() { - Trader entry{}; + Trader e{}; - entry.char_id = 0; - entry.item_id = 0; - entry.serialnumber = 0; - entry.charges = 0; - entry.item_cost = 0; - entry.slot_id = 0; + e.char_id = 0; + e.item_id = 0; + e.serialnumber = 0; + e.charges = 0; + e.item_cost = 0; + e.slot_id = 0; - return entry; + return e; } - static Trader GetTraderEntry( + static Trader GetTrader( const std::vector &traders, int trader_id ) @@ -132,16 +132,16 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Trader entry{}; + Trader e{}; - entry.char_id = atoi(row[0]); - entry.item_id = atoi(row[1]); - entry.serialnumber = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.item_cost = atoi(row[4]); - entry.slot_id = atoi(row[5]); + e.char_id = static_cast(strtoul(row[0], nullptr, 10)); + e.item_id = static_cast(strtoul(row[1], nullptr, 10)); + e.serialnumber = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(atoi(row[3])); + e.item_cost = static_cast(strtoul(row[4], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[5], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -166,27 +166,27 @@ public: static int UpdateOne( Database& db, - Trader trader_entry + const Trader &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(trader_entry.char_id)); - update_values.push_back(columns[1] + " = " + std::to_string(trader_entry.item_id)); - update_values.push_back(columns[2] + " = " + std::to_string(trader_entry.serialnumber)); - update_values.push_back(columns[3] + " = " + std::to_string(trader_entry.charges)); - update_values.push_back(columns[4] + " = " + std::to_string(trader_entry.item_cost)); - update_values.push_back(columns[5] + " = " + std::to_string(trader_entry.slot_id)); + v.push_back(columns[0] + " = " + std::to_string(e.char_id)); + v.push_back(columns[1] + " = " + std::to_string(e.item_id)); + v.push_back(columns[2] + " = " + std::to_string(e.serialnumber)); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); + v.push_back(columns[4] + " = " + std::to_string(e.item_cost)); + v.push_back(columns[5] + " = " + std::to_string(e.slot_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - trader_entry.char_id + e.char_id ) ); @@ -195,63 +195,63 @@ public: static Trader InsertOne( Database& db, - Trader trader_entry + Trader e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(trader_entry.char_id)); - insert_values.push_back(std::to_string(trader_entry.item_id)); - insert_values.push_back(std::to_string(trader_entry.serialnumber)); - insert_values.push_back(std::to_string(trader_entry.charges)); - insert_values.push_back(std::to_string(trader_entry.item_cost)); - insert_values.push_back(std::to_string(trader_entry.slot_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.serialnumber)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.item_cost)); + v.push_back(std::to_string(e.slot_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - trader_entry.char_id = results.LastInsertedID(); - return trader_entry; + e.char_id = results.LastInsertedID(); + return e; } - trader_entry = NewEntity(); + e = NewEntity(); - return trader_entry; + return e; } static int InsertMany( Database& db, - std::vector trader_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &trader_entry: trader_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(trader_entry.char_id)); - insert_values.push_back(std::to_string(trader_entry.item_id)); - insert_values.push_back(std::to_string(trader_entry.serialnumber)); - insert_values.push_back(std::to_string(trader_entry.charges)); - insert_values.push_back(std::to_string(trader_entry.item_cost)); - insert_values.push_back(std::to_string(trader_entry.slot_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.serialnumber)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.item_cost)); + v.push_back(std::to_string(e.slot_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -272,22 +272,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Trader entry{}; + Trader e{}; - entry.char_id = atoi(row[0]); - entry.item_id = atoi(row[1]); - entry.serialnumber = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.item_cost = atoi(row[4]); - entry.slot_id = atoi(row[5]); + e.char_id = static_cast(strtoul(row[0], nullptr, 10)); + e.item_id = static_cast(strtoul(row[1], nullptr, 10)); + e.serialnumber = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(atoi(row[3])); + e.item_cost = static_cast(strtoul(row[4], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[5], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -302,22 +302,22 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Trader entry{}; + Trader e{}; - entry.char_id = atoi(row[0]); - entry.item_id = atoi(row[1]); - entry.serialnumber = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.item_cost = atoi(row[4]); - entry.slot_id = atoi(row[5]); + e.char_id = static_cast(strtoul(row[0], nullptr, 10)); + e.item_id = static_cast(strtoul(row[1], nullptr, 10)); + e.serialnumber = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(atoi(row[3])); + e.item_cost = static_cast(strtoul(row[4], nullptr, 10)); + e.slot_id = static_cast(strtoul(row[5], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -342,6 +342,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TRADER_REPOSITORY_H diff --git a/common/repositories/base/base_tradeskill_recipe_entries_repository.h b/common/repositories/base/base_tradeskill_recipe_entries_repository.h index f33dea405..77a0f1942 100644 --- a/common/repositories/base/base_tradeskill_recipe_entries_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_entries_repository.h @@ -13,20 +13,20 @@ #define EQEMU_BASE_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTradeskillRecipeEntriesRepository { public: struct TradeskillRecipeEntries { - int id; - int recipe_id; - int item_id; - int successcount; - int failcount; - int componentcount; - int salvagecount; - int iscontainer; + int32_t id; + int32_t recipe_id; + int32_t item_id; + int8_t successcount; + int8_t failcount; + int8_t componentcount; + int8_t salvagecount; + int8_t iscontainer; }; static std::string PrimaryKey() @@ -64,12 +64,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -97,21 +97,21 @@ public: static TradeskillRecipeEntries NewEntity() { - TradeskillRecipeEntries entry{}; + TradeskillRecipeEntries e{}; - entry.id = 0; - entry.recipe_id = 0; - entry.item_id = 0; - entry.successcount = 0; - entry.failcount = 0; - entry.componentcount = 1; - entry.salvagecount = 0; - entry.iscontainer = 0; + e.id = 0; + e.recipe_id = 0; + e.item_id = 0; + e.successcount = 0; + e.failcount = 0; + e.componentcount = 1; + e.salvagecount = 0; + e.iscontainer = 0; - return entry; + return e; } - static TradeskillRecipeEntries GetTradeskillRecipeEntriesEntry( + static TradeskillRecipeEntries GetTradeskillRecipeEntries( const std::vector &tradeskill_recipe_entriess, int tradeskill_recipe_entries_id ) @@ -140,18 +140,18 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - TradeskillRecipeEntries entry{}; + TradeskillRecipeEntries e{}; - entry.id = atoi(row[0]); - entry.recipe_id = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.successcount = atoi(row[3]); - entry.failcount = atoi(row[4]); - entry.componentcount = atoi(row[5]); - entry.salvagecount = atoi(row[6]); - entry.iscontainer = atoi(row[7]); + e.id = static_cast(atoi(row[0])); + e.recipe_id = static_cast(atoi(row[1])); + e.item_id = static_cast(atoi(row[2])); + e.successcount = static_cast(atoi(row[3])); + e.failcount = static_cast(atoi(row[4])); + e.componentcount = static_cast(atoi(row[5])); + e.salvagecount = static_cast(atoi(row[6])); + e.iscontainer = static_cast(atoi(row[7])); - return entry; + return e; } return NewEntity(); @@ -176,28 +176,28 @@ public: static int UpdateOne( Database& db, - TradeskillRecipeEntries tradeskill_recipe_entries_entry + const TradeskillRecipeEntries &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = " + std::to_string(tradeskill_recipe_entries_entry.recipe_id)); - update_values.push_back(columns[2] + " = " + std::to_string(tradeskill_recipe_entries_entry.item_id)); - update_values.push_back(columns[3] + " = " + std::to_string(tradeskill_recipe_entries_entry.successcount)); - update_values.push_back(columns[4] + " = " + std::to_string(tradeskill_recipe_entries_entry.failcount)); - update_values.push_back(columns[5] + " = " + std::to_string(tradeskill_recipe_entries_entry.componentcount)); - update_values.push_back(columns[6] + " = " + std::to_string(tradeskill_recipe_entries_entry.salvagecount)); - update_values.push_back(columns[7] + " = " + std::to_string(tradeskill_recipe_entries_entry.iscontainer)); + v.push_back(columns[1] + " = " + std::to_string(e.recipe_id)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + v.push_back(columns[3] + " = " + std::to_string(e.successcount)); + v.push_back(columns[4] + " = " + std::to_string(e.failcount)); + v.push_back(columns[5] + " = " + std::to_string(e.componentcount)); + v.push_back(columns[6] + " = " + std::to_string(e.salvagecount)); + v.push_back(columns[7] + " = " + std::to_string(e.iscontainer)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - tradeskill_recipe_entries_entry.id + e.id ) ); @@ -206,67 +206,67 @@ public: static TradeskillRecipeEntries InsertOne( Database& db, - TradeskillRecipeEntries tradeskill_recipe_entries_entry + TradeskillRecipeEntries e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.id)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.recipe_id)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.item_id)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.successcount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.failcount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.componentcount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.salvagecount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.iscontainer)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.recipe_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.successcount)); + v.push_back(std::to_string(e.failcount)); + v.push_back(std::to_string(e.componentcount)); + v.push_back(std::to_string(e.salvagecount)); + v.push_back(std::to_string(e.iscontainer)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - tradeskill_recipe_entries_entry.id = results.LastInsertedID(); - return tradeskill_recipe_entries_entry; + e.id = results.LastInsertedID(); + return e; } - tradeskill_recipe_entries_entry = NewEntity(); + e = NewEntity(); - return tradeskill_recipe_entries_entry; + return e; } static int InsertMany( Database& db, - std::vector tradeskill_recipe_entries_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &tradeskill_recipe_entries_entry: tradeskill_recipe_entries_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.id)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.recipe_id)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.item_id)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.successcount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.failcount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.componentcount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.salvagecount)); - insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.iscontainer)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.recipe_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.successcount)); + v.push_back(std::to_string(e.failcount)); + v.push_back(std::to_string(e.componentcount)); + v.push_back(std::to_string(e.salvagecount)); + v.push_back(std::to_string(e.iscontainer)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -287,24 +287,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TradeskillRecipeEntries entry{}; + TradeskillRecipeEntries e{}; - entry.id = atoi(row[0]); - entry.recipe_id = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.successcount = atoi(row[3]); - entry.failcount = atoi(row[4]); - entry.componentcount = atoi(row[5]); - entry.salvagecount = atoi(row[6]); - entry.iscontainer = atoi(row[7]); + e.id = static_cast(atoi(row[0])); + e.recipe_id = static_cast(atoi(row[1])); + e.item_id = static_cast(atoi(row[2])); + e.successcount = static_cast(atoi(row[3])); + e.failcount = static_cast(atoi(row[4])); + e.componentcount = static_cast(atoi(row[5])); + e.salvagecount = static_cast(atoi(row[6])); + e.iscontainer = static_cast(atoi(row[7])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -319,24 +319,24 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TradeskillRecipeEntries entry{}; + TradeskillRecipeEntries e{}; - entry.id = atoi(row[0]); - entry.recipe_id = atoi(row[1]); - entry.item_id = atoi(row[2]); - entry.successcount = atoi(row[3]); - entry.failcount = atoi(row[4]); - entry.componentcount = atoi(row[5]); - entry.salvagecount = atoi(row[6]); - entry.iscontainer = atoi(row[7]); + e.id = static_cast(atoi(row[0])); + e.recipe_id = static_cast(atoi(row[1])); + e.item_id = static_cast(atoi(row[2])); + e.successcount = static_cast(atoi(row[3])); + e.failcount = static_cast(atoi(row[4])); + e.componentcount = static_cast(atoi(row[5])); + e.salvagecount = static_cast(atoi(row[6])); + e.iscontainer = static_cast(atoi(row[7])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -361,6 +361,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_tradeskill_recipe_repository.h b/common/repositories/base/base_tradeskill_recipe_repository.h index 2231a26dc..2abb76dc3 100644 --- a/common/repositories/base/base_tradeskill_recipe_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_repository.h @@ -13,25 +13,25 @@ #define EQEMU_BASE_TRADESKILL_RECIPE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTradeskillRecipeRepository { public: struct TradeskillRecipe { - int id; + int32_t id; std::string name; - int tradeskill; - int skillneeded; - int trivial; - int nofail; - int replace_container; + int16_t tradeskill; + int16_t skillneeded; + int16_t trivial; + int8_t nofail; + int8_t replace_container; std::string notes; - int must_learn; - int quest; - int enabled; - int min_expansion; - int max_expansion; + int8_t must_learn; + int8_t quest; + int8_t enabled; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -85,12 +85,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -118,28 +118,28 @@ public: static TradeskillRecipe NewEntity() { - TradeskillRecipe entry{}; + TradeskillRecipe e{}; - entry.id = 0; - entry.name = ""; - entry.tradeskill = 0; - entry.skillneeded = 0; - entry.trivial = 0; - entry.nofail = 0; - entry.replace_container = 0; - entry.notes = ""; - entry.must_learn = 0; - entry.quest = 0; - entry.enabled = 1; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.name = ""; + e.tradeskill = 0; + e.skillneeded = 0; + e.trivial = 0; + e.nofail = 0; + e.replace_container = 0; + e.notes = ""; + e.must_learn = 0; + e.quest = 0; + e.enabled = 1; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static TradeskillRecipe GetTradeskillRecipeEntry( + static TradeskillRecipe GetTradeskillRecipe( const std::vector &tradeskill_recipes, int tradeskill_recipe_id ) @@ -168,25 +168,25 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - TradeskillRecipe entry{}; + TradeskillRecipe e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.tradeskill = atoi(row[2]); - entry.skillneeded = atoi(row[3]); - entry.trivial = atoi(row[4]); - entry.nofail = atoi(row[5]); - entry.replace_container = atoi(row[6]); - entry.notes = row[7] ? row[7] : ""; - entry.must_learn = atoi(row[8]); - entry.quest = atoi(row[9]); - entry.enabled = atoi(row[10]); - entry.min_expansion = atoi(row[11]); - entry.max_expansion = atoi(row[12]); - entry.content_flags = row[13] ? row[13] : ""; - entry.content_flags_disabled = row[14] ? row[14] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.tradeskill = static_cast(atoi(row[2])); + e.skillneeded = static_cast(atoi(row[3])); + e.trivial = static_cast(atoi(row[4])); + e.nofail = static_cast(atoi(row[5])); + e.replace_container = static_cast(atoi(row[6])); + e.notes = row[7] ? row[7] : ""; + e.must_learn = static_cast(atoi(row[8])); + e.quest = static_cast(atoi(row[9])); + e.enabled = static_cast(atoi(row[10])); + e.min_expansion = static_cast(atoi(row[11])); + e.max_expansion = static_cast(atoi(row[12])); + e.content_flags = row[13] ? row[13] : ""; + e.content_flags_disabled = row[14] ? row[14] : ""; - return entry; + return e; } return NewEntity(); @@ -211,35 +211,35 @@ public: static int UpdateOne( Database& db, - TradeskillRecipe tradeskill_recipe_entry + const TradeskillRecipe &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(tradeskill_recipe_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(tradeskill_recipe_entry.tradeskill)); - update_values.push_back(columns[3] + " = " + std::to_string(tradeskill_recipe_entry.skillneeded)); - update_values.push_back(columns[4] + " = " + std::to_string(tradeskill_recipe_entry.trivial)); - update_values.push_back(columns[5] + " = " + std::to_string(tradeskill_recipe_entry.nofail)); - update_values.push_back(columns[6] + " = " + std::to_string(tradeskill_recipe_entry.replace_container)); - update_values.push_back(columns[7] + " = '" + EscapeString(tradeskill_recipe_entry.notes) + "'"); - update_values.push_back(columns[8] + " = " + std::to_string(tradeskill_recipe_entry.must_learn)); - update_values.push_back(columns[9] + " = " + std::to_string(tradeskill_recipe_entry.quest)); - update_values.push_back(columns[10] + " = " + std::to_string(tradeskill_recipe_entry.enabled)); - update_values.push_back(columns[11] + " = " + std::to_string(tradeskill_recipe_entry.min_expansion)); - update_values.push_back(columns[12] + " = " + std::to_string(tradeskill_recipe_entry.max_expansion)); - update_values.push_back(columns[13] + " = '" + EscapeString(tradeskill_recipe_entry.content_flags) + "'"); - update_values.push_back(columns[14] + " = '" + EscapeString(tradeskill_recipe_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.tradeskill)); + v.push_back(columns[3] + " = " + std::to_string(e.skillneeded)); + v.push_back(columns[4] + " = " + std::to_string(e.trivial)); + v.push_back(columns[5] + " = " + std::to_string(e.nofail)); + v.push_back(columns[6] + " = " + std::to_string(e.replace_container)); + v.push_back(columns[7] + " = '" + Strings::Escape(e.notes) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.must_learn)); + v.push_back(columns[9] + " = " + std::to_string(e.quest)); + v.push_back(columns[10] + " = " + std::to_string(e.enabled)); + v.push_back(columns[11] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[12] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[13] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - tradeskill_recipe_entry.id + e.id ) ); @@ -248,81 +248,81 @@ public: static TradeskillRecipe InsertOne( Database& db, - TradeskillRecipe tradeskill_recipe_entry + TradeskillRecipe e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(tradeskill_recipe_entry.id)); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.name) + "'"); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.tradeskill)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.skillneeded)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.trivial)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.nofail)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.replace_container)); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.notes) + "'"); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.must_learn)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.quest)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.enabled)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.min_expansion)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.tradeskill)); + v.push_back(std::to_string(e.skillneeded)); + v.push_back(std::to_string(e.trivial)); + v.push_back(std::to_string(e.nofail)); + v.push_back(std::to_string(e.replace_container)); + v.push_back("'" + Strings::Escape(e.notes) + "'"); + v.push_back(std::to_string(e.must_learn)); + v.push_back(std::to_string(e.quest)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - tradeskill_recipe_entry.id = results.LastInsertedID(); - return tradeskill_recipe_entry; + e.id = results.LastInsertedID(); + return e; } - tradeskill_recipe_entry = NewEntity(); + e = NewEntity(); - return tradeskill_recipe_entry; + return e; } static int InsertMany( Database& db, - std::vector tradeskill_recipe_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &tradeskill_recipe_entry: tradeskill_recipe_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(tradeskill_recipe_entry.id)); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.name) + "'"); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.tradeskill)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.skillneeded)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.trivial)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.nofail)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.replace_container)); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.notes) + "'"); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.must_learn)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.quest)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.enabled)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.min_expansion)); - insert_values.push_back(std::to_string(tradeskill_recipe_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.tradeskill)); + v.push_back(std::to_string(e.skillneeded)); + v.push_back(std::to_string(e.trivial)); + v.push_back(std::to_string(e.nofail)); + v.push_back(std::to_string(e.replace_container)); + v.push_back("'" + Strings::Escape(e.notes) + "'"); + v.push_back(std::to_string(e.must_learn)); + v.push_back(std::to_string(e.quest)); + v.push_back(std::to_string(e.enabled)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -343,31 +343,31 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TradeskillRecipe entry{}; + TradeskillRecipe e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.tradeskill = atoi(row[2]); - entry.skillneeded = atoi(row[3]); - entry.trivial = atoi(row[4]); - entry.nofail = atoi(row[5]); - entry.replace_container = atoi(row[6]); - entry.notes = row[7] ? row[7] : ""; - entry.must_learn = atoi(row[8]); - entry.quest = atoi(row[9]); - entry.enabled = atoi(row[10]); - entry.min_expansion = atoi(row[11]); - entry.max_expansion = atoi(row[12]); - entry.content_flags = row[13] ? row[13] : ""; - entry.content_flags_disabled = row[14] ? row[14] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.tradeskill = static_cast(atoi(row[2])); + e.skillneeded = static_cast(atoi(row[3])); + e.trivial = static_cast(atoi(row[4])); + e.nofail = static_cast(atoi(row[5])); + e.replace_container = static_cast(atoi(row[6])); + e.notes = row[7] ? row[7] : ""; + e.must_learn = static_cast(atoi(row[8])); + e.quest = static_cast(atoi(row[9])); + e.enabled = static_cast(atoi(row[10])); + e.min_expansion = static_cast(atoi(row[11])); + e.max_expansion = static_cast(atoi(row[12])); + e.content_flags = row[13] ? row[13] : ""; + e.content_flags_disabled = row[14] ? row[14] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -382,31 +382,31 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TradeskillRecipe entry{}; + TradeskillRecipe e{}; - entry.id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.tradeskill = atoi(row[2]); - entry.skillneeded = atoi(row[3]); - entry.trivial = atoi(row[4]); - entry.nofail = atoi(row[5]); - entry.replace_container = atoi(row[6]); - entry.notes = row[7] ? row[7] : ""; - entry.must_learn = atoi(row[8]); - entry.quest = atoi(row[9]); - entry.enabled = atoi(row[10]); - entry.min_expansion = atoi(row[11]); - entry.max_expansion = atoi(row[12]); - entry.content_flags = row[13] ? row[13] : ""; - entry.content_flags_disabled = row[14] ? row[14] : ""; + e.id = static_cast(atoi(row[0])); + e.name = row[1] ? row[1] : ""; + e.tradeskill = static_cast(atoi(row[2])); + e.skillneeded = static_cast(atoi(row[3])); + e.trivial = static_cast(atoi(row[4])); + e.nofail = static_cast(atoi(row[5])); + e.replace_container = static_cast(atoi(row[6])); + e.notes = row[7] ? row[7] : ""; + e.must_learn = static_cast(atoi(row[8])); + e.quest = static_cast(atoi(row[9])); + e.enabled = static_cast(atoi(row[10])); + e.min_expansion = static_cast(atoi(row[11])); + e.max_expansion = static_cast(atoi(row[12])); + e.content_flags = row[13] ? row[13] : ""; + e.content_flags_disabled = row[14] ? row[14] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -431,6 +431,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TRADESKILL_RECIPE_REPOSITORY_H diff --git a/common/repositories/base/base_traps_repository.h b/common/repositories/base/base_traps_repository.h index 71048760c..b40ad30b8 100644 --- a/common/repositories/base/base_traps_repository.h +++ b/common/repositories/base/base_traps_repository.h @@ -13,35 +13,35 @@ #define EQEMU_BASE_TRAPS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTrapsRepository { public: struct Traps { - int id; + int32_t id; std::string zone; - int version; - int x; - int y; - int z; - int chance; + uint16_t version; + int32_t x; + int32_t y; + int32_t z; + int8_t chance; float maxzdiff; float radius; - int effect; - int effectvalue; - int effectvalue2; + int32_t effect; + int32_t effectvalue; + int32_t effectvalue2; std::string message; - int skill; - int level; - int respawn_time; - int respawn_var; - int triggered_number; - int group; - int despawn_when_triggered; - int undetectable; - int min_expansion; - int max_expansion; + int32_t skill; + uint32_t level; + uint32_t respawn_time; + uint32_t respawn_var; + int8_t triggered_number; + int8_t group; + int8_t despawn_when_triggered; + int8_t undetectable; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; }; @@ -115,12 +115,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -148,38 +148,38 @@ public: static Traps NewEntity() { - Traps entry{}; + Traps e{}; - entry.id = 0; - entry.zone = ""; - entry.version = 0; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.chance = 0; - entry.maxzdiff = 0; - entry.radius = 0; - entry.effect = 0; - entry.effectvalue = 0; - entry.effectvalue2 = 0; - entry.message = ""; - entry.skill = 0; - entry.level = 1; - entry.respawn_time = 60; - entry.respawn_var = 0; - entry.triggered_number = 0; - entry.group = 0; - entry.despawn_when_triggered = 0; - entry.undetectable = 0; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; + e.id = 0; + e.zone = ""; + e.version = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.chance = 0; + e.maxzdiff = 0; + e.radius = 0; + e.effect = 0; + e.effectvalue = 0; + e.effectvalue2 = 0; + e.message = ""; + e.skill = 0; + e.level = 1; + e.respawn_time = 60; + e.respawn_var = 0; + e.triggered_number = 0; + e.group = 0; + e.despawn_when_triggered = 0; + e.undetectable = 0; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; - return entry; + return e; } - static Traps GetTrapsEntry( + static Traps GetTraps( const std::vector &trapss, int traps_id ) @@ -208,35 +208,35 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Traps entry{}; + Traps e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.version = atoi(row[2]); - entry.x = atoi(row[3]); - entry.y = atoi(row[4]); - entry.z = atoi(row[5]); - entry.chance = atoi(row[6]); - entry.maxzdiff = static_cast(atof(row[7])); - entry.radius = static_cast(atof(row[8])); - entry.effect = atoi(row[9]); - entry.effectvalue = atoi(row[10]); - entry.effectvalue2 = atoi(row[11]); - entry.message = row[12] ? row[12] : ""; - entry.skill = atoi(row[13]); - entry.level = atoi(row[14]); - entry.respawn_time = atoi(row[15]); - entry.respawn_var = atoi(row[16]); - entry.triggered_number = atoi(row[17]); - entry.group = atoi(row[18]); - entry.despawn_when_triggered = atoi(row[19]); - entry.undetectable = atoi(row[20]); - entry.min_expansion = atoi(row[21]); - entry.max_expansion = atoi(row[22]); - entry.content_flags = row[23] ? row[23] : ""; - entry.content_flags_disabled = row[24] ? row[24] : ""; + e.id = static_cast(atoi(row[0])); + e.zone = row[1] ? row[1] : ""; + e.version = static_cast(strtoul(row[2], nullptr, 10)); + e.x = static_cast(atoi(row[3])); + e.y = static_cast(atoi(row[4])); + e.z = static_cast(atoi(row[5])); + e.chance = static_cast(atoi(row[6])); + e.maxzdiff = strtof(row[7], nullptr); + e.radius = strtof(row[8], nullptr); + e.effect = static_cast(atoi(row[9])); + e.effectvalue = static_cast(atoi(row[10])); + e.effectvalue2 = static_cast(atoi(row[11])); + e.message = row[12] ? row[12] : ""; + e.skill = static_cast(atoi(row[13])); + e.level = static_cast(strtoul(row[14], nullptr, 10)); + e.respawn_time = static_cast(strtoul(row[15], nullptr, 10)); + e.respawn_var = static_cast(strtoul(row[16], nullptr, 10)); + e.triggered_number = static_cast(atoi(row[17])); + e.group = static_cast(atoi(row[18])); + e.despawn_when_triggered = static_cast(atoi(row[19])); + e.undetectable = static_cast(atoi(row[20])); + e.min_expansion = static_cast(atoi(row[21])); + e.max_expansion = static_cast(atoi(row[22])); + e.content_flags = row[23] ? row[23] : ""; + e.content_flags_disabled = row[24] ? row[24] : ""; - return entry; + return e; } return NewEntity(); @@ -261,45 +261,45 @@ public: static int UpdateOne( Database& db, - Traps traps_entry + const Traps &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(traps_entry.zone) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(traps_entry.version)); - update_values.push_back(columns[3] + " = " + std::to_string(traps_entry.x)); - update_values.push_back(columns[4] + " = " + std::to_string(traps_entry.y)); - update_values.push_back(columns[5] + " = " + std::to_string(traps_entry.z)); - update_values.push_back(columns[6] + " = " + std::to_string(traps_entry.chance)); - update_values.push_back(columns[7] + " = " + std::to_string(traps_entry.maxzdiff)); - update_values.push_back(columns[8] + " = " + std::to_string(traps_entry.radius)); - update_values.push_back(columns[9] + " = " + std::to_string(traps_entry.effect)); - update_values.push_back(columns[10] + " = " + std::to_string(traps_entry.effectvalue)); - update_values.push_back(columns[11] + " = " + std::to_string(traps_entry.effectvalue2)); - update_values.push_back(columns[12] + " = '" + EscapeString(traps_entry.message) + "'"); - update_values.push_back(columns[13] + " = " + std::to_string(traps_entry.skill)); - update_values.push_back(columns[14] + " = " + std::to_string(traps_entry.level)); - update_values.push_back(columns[15] + " = " + std::to_string(traps_entry.respawn_time)); - update_values.push_back(columns[16] + " = " + std::to_string(traps_entry.respawn_var)); - update_values.push_back(columns[17] + " = " + std::to_string(traps_entry.triggered_number)); - update_values.push_back(columns[18] + " = " + std::to_string(traps_entry.group)); - update_values.push_back(columns[19] + " = " + std::to_string(traps_entry.despawn_when_triggered)); - update_values.push_back(columns[20] + " = " + std::to_string(traps_entry.undetectable)); - update_values.push_back(columns[21] + " = " + std::to_string(traps_entry.min_expansion)); - update_values.push_back(columns[22] + " = " + std::to_string(traps_entry.max_expansion)); - update_values.push_back(columns[23] + " = '" + EscapeString(traps_entry.content_flags) + "'"); - update_values.push_back(columns[24] + " = '" + EscapeString(traps_entry.content_flags_disabled) + "'"); + v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.version)); + v.push_back(columns[3] + " = " + std::to_string(e.x)); + v.push_back(columns[4] + " = " + std::to_string(e.y)); + v.push_back(columns[5] + " = " + std::to_string(e.z)); + v.push_back(columns[6] + " = " + std::to_string(e.chance)); + v.push_back(columns[7] + " = " + std::to_string(e.maxzdiff)); + v.push_back(columns[8] + " = " + std::to_string(e.radius)); + v.push_back(columns[9] + " = " + std::to_string(e.effect)); + v.push_back(columns[10] + " = " + std::to_string(e.effectvalue)); + v.push_back(columns[11] + " = " + std::to_string(e.effectvalue2)); + v.push_back(columns[12] + " = '" + Strings::Escape(e.message) + "'"); + v.push_back(columns[13] + " = " + std::to_string(e.skill)); + v.push_back(columns[14] + " = " + std::to_string(e.level)); + v.push_back(columns[15] + " = " + std::to_string(e.respawn_time)); + v.push_back(columns[16] + " = " + std::to_string(e.respawn_var)); + v.push_back(columns[17] + " = " + std::to_string(e.triggered_number)); + v.push_back(columns[18] + " = " + std::to_string(e.group)); + v.push_back(columns[19] + " = " + std::to_string(e.despawn_when_triggered)); + v.push_back(columns[20] + " = " + std::to_string(e.undetectable)); + v.push_back(columns[21] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[22] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[23] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[24] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - traps_entry.id + e.id ) ); @@ -308,101 +308,101 @@ public: static Traps InsertOne( Database& db, - Traps traps_entry + Traps e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(traps_entry.id)); - insert_values.push_back("'" + EscapeString(traps_entry.zone) + "'"); - insert_values.push_back(std::to_string(traps_entry.version)); - insert_values.push_back(std::to_string(traps_entry.x)); - insert_values.push_back(std::to_string(traps_entry.y)); - insert_values.push_back(std::to_string(traps_entry.z)); - insert_values.push_back(std::to_string(traps_entry.chance)); - insert_values.push_back(std::to_string(traps_entry.maxzdiff)); - insert_values.push_back(std::to_string(traps_entry.radius)); - insert_values.push_back(std::to_string(traps_entry.effect)); - insert_values.push_back(std::to_string(traps_entry.effectvalue)); - insert_values.push_back(std::to_string(traps_entry.effectvalue2)); - insert_values.push_back("'" + EscapeString(traps_entry.message) + "'"); - insert_values.push_back(std::to_string(traps_entry.skill)); - insert_values.push_back(std::to_string(traps_entry.level)); - insert_values.push_back(std::to_string(traps_entry.respawn_time)); - insert_values.push_back(std::to_string(traps_entry.respawn_var)); - insert_values.push_back(std::to_string(traps_entry.triggered_number)); - insert_values.push_back(std::to_string(traps_entry.group)); - insert_values.push_back(std::to_string(traps_entry.despawn_when_triggered)); - insert_values.push_back(std::to_string(traps_entry.undetectable)); - insert_values.push_back(std::to_string(traps_entry.min_expansion)); - insert_values.push_back(std::to_string(traps_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(traps_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(traps_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.maxzdiff)); + v.push_back(std::to_string(e.radius)); + v.push_back(std::to_string(e.effect)); + v.push_back(std::to_string(e.effectvalue)); + v.push_back(std::to_string(e.effectvalue2)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back(std::to_string(e.skill)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.respawn_time)); + v.push_back(std::to_string(e.respawn_var)); + v.push_back(std::to_string(e.triggered_number)); + v.push_back(std::to_string(e.group)); + v.push_back(std::to_string(e.despawn_when_triggered)); + v.push_back(std::to_string(e.undetectable)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - traps_entry.id = results.LastInsertedID(); - return traps_entry; + e.id = results.LastInsertedID(); + return e; } - traps_entry = NewEntity(); + e = NewEntity(); - return traps_entry; + return e; } static int InsertMany( Database& db, - std::vector traps_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &traps_entry: traps_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(traps_entry.id)); - insert_values.push_back("'" + EscapeString(traps_entry.zone) + "'"); - insert_values.push_back(std::to_string(traps_entry.version)); - insert_values.push_back(std::to_string(traps_entry.x)); - insert_values.push_back(std::to_string(traps_entry.y)); - insert_values.push_back(std::to_string(traps_entry.z)); - insert_values.push_back(std::to_string(traps_entry.chance)); - insert_values.push_back(std::to_string(traps_entry.maxzdiff)); - insert_values.push_back(std::to_string(traps_entry.radius)); - insert_values.push_back(std::to_string(traps_entry.effect)); - insert_values.push_back(std::to_string(traps_entry.effectvalue)); - insert_values.push_back(std::to_string(traps_entry.effectvalue2)); - insert_values.push_back("'" + EscapeString(traps_entry.message) + "'"); - insert_values.push_back(std::to_string(traps_entry.skill)); - insert_values.push_back(std::to_string(traps_entry.level)); - insert_values.push_back(std::to_string(traps_entry.respawn_time)); - insert_values.push_back(std::to_string(traps_entry.respawn_var)); - insert_values.push_back(std::to_string(traps_entry.triggered_number)); - insert_values.push_back(std::to_string(traps_entry.group)); - insert_values.push_back(std::to_string(traps_entry.despawn_when_triggered)); - insert_values.push_back(std::to_string(traps_entry.undetectable)); - insert_values.push_back(std::to_string(traps_entry.min_expansion)); - insert_values.push_back(std::to_string(traps_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(traps_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(traps_entry.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.chance)); + v.push_back(std::to_string(e.maxzdiff)); + v.push_back(std::to_string(e.radius)); + v.push_back(std::to_string(e.effect)); + v.push_back(std::to_string(e.effectvalue)); + v.push_back(std::to_string(e.effectvalue2)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back(std::to_string(e.skill)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.respawn_time)); + v.push_back(std::to_string(e.respawn_var)); + v.push_back(std::to_string(e.triggered_number)); + v.push_back(std::to_string(e.group)); + v.push_back(std::to_string(e.despawn_when_triggered)); + v.push_back(std::to_string(e.undetectable)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -423,41 +423,41 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Traps entry{}; + Traps e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.version = atoi(row[2]); - entry.x = atoi(row[3]); - entry.y = atoi(row[4]); - entry.z = atoi(row[5]); - entry.chance = atoi(row[6]); - entry.maxzdiff = static_cast(atof(row[7])); - entry.radius = static_cast(atof(row[8])); - entry.effect = atoi(row[9]); - entry.effectvalue = atoi(row[10]); - entry.effectvalue2 = atoi(row[11]); - entry.message = row[12] ? row[12] : ""; - entry.skill = atoi(row[13]); - entry.level = atoi(row[14]); - entry.respawn_time = atoi(row[15]); - entry.respawn_var = atoi(row[16]); - entry.triggered_number = atoi(row[17]); - entry.group = atoi(row[18]); - entry.despawn_when_triggered = atoi(row[19]); - entry.undetectable = atoi(row[20]); - entry.min_expansion = atoi(row[21]); - entry.max_expansion = atoi(row[22]); - entry.content_flags = row[23] ? row[23] : ""; - entry.content_flags_disabled = row[24] ? row[24] : ""; + e.id = static_cast(atoi(row[0])); + e.zone = row[1] ? row[1] : ""; + e.version = static_cast(strtoul(row[2], nullptr, 10)); + e.x = static_cast(atoi(row[3])); + e.y = static_cast(atoi(row[4])); + e.z = static_cast(atoi(row[5])); + e.chance = static_cast(atoi(row[6])); + e.maxzdiff = strtof(row[7], nullptr); + e.radius = strtof(row[8], nullptr); + e.effect = static_cast(atoi(row[9])); + e.effectvalue = static_cast(atoi(row[10])); + e.effectvalue2 = static_cast(atoi(row[11])); + e.message = row[12] ? row[12] : ""; + e.skill = static_cast(atoi(row[13])); + e.level = static_cast(strtoul(row[14], nullptr, 10)); + e.respawn_time = static_cast(strtoul(row[15], nullptr, 10)); + e.respawn_var = static_cast(strtoul(row[16], nullptr, 10)); + e.triggered_number = static_cast(atoi(row[17])); + e.group = static_cast(atoi(row[18])); + e.despawn_when_triggered = static_cast(atoi(row[19])); + e.undetectable = static_cast(atoi(row[20])); + e.min_expansion = static_cast(atoi(row[21])); + e.max_expansion = static_cast(atoi(row[22])); + e.content_flags = row[23] ? row[23] : ""; + e.content_flags_disabled = row[24] ? row[24] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -472,41 +472,41 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Traps entry{}; + Traps e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.version = atoi(row[2]); - entry.x = atoi(row[3]); - entry.y = atoi(row[4]); - entry.z = atoi(row[5]); - entry.chance = atoi(row[6]); - entry.maxzdiff = static_cast(atof(row[7])); - entry.radius = static_cast(atof(row[8])); - entry.effect = atoi(row[9]); - entry.effectvalue = atoi(row[10]); - entry.effectvalue2 = atoi(row[11]); - entry.message = row[12] ? row[12] : ""; - entry.skill = atoi(row[13]); - entry.level = atoi(row[14]); - entry.respawn_time = atoi(row[15]); - entry.respawn_var = atoi(row[16]); - entry.triggered_number = atoi(row[17]); - entry.group = atoi(row[18]); - entry.despawn_when_triggered = atoi(row[19]); - entry.undetectable = atoi(row[20]); - entry.min_expansion = atoi(row[21]); - entry.max_expansion = atoi(row[22]); - entry.content_flags = row[23] ? row[23] : ""; - entry.content_flags_disabled = row[24] ? row[24] : ""; + e.id = static_cast(atoi(row[0])); + e.zone = row[1] ? row[1] : ""; + e.version = static_cast(strtoul(row[2], nullptr, 10)); + e.x = static_cast(atoi(row[3])); + e.y = static_cast(atoi(row[4])); + e.z = static_cast(atoi(row[5])); + e.chance = static_cast(atoi(row[6])); + e.maxzdiff = strtof(row[7], nullptr); + e.radius = strtof(row[8], nullptr); + e.effect = static_cast(atoi(row[9])); + e.effectvalue = static_cast(atoi(row[10])); + e.effectvalue2 = static_cast(atoi(row[11])); + e.message = row[12] ? row[12] : ""; + e.skill = static_cast(atoi(row[13])); + e.level = static_cast(strtoul(row[14], nullptr, 10)); + e.respawn_time = static_cast(strtoul(row[15], nullptr, 10)); + e.respawn_var = static_cast(strtoul(row[16], nullptr, 10)); + e.triggered_number = static_cast(atoi(row[17])); + e.group = static_cast(atoi(row[18])); + e.despawn_when_triggered = static_cast(atoi(row[19])); + e.undetectable = static_cast(atoi(row[20])); + e.min_expansion = static_cast(atoi(row[21])); + e.max_expansion = static_cast(atoi(row[22])); + e.content_flags = row[23] ? row[23] : ""; + e.content_flags_disabled = row[24] ? row[24] : ""; - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -531,6 +531,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TRAPS_REPOSITORY_H diff --git a/common/repositories/base/base_tribute_levels_repository.h b/common/repositories/base/base_tribute_levels_repository.h index 8ed65defc..52ab42899 100644 --- a/common/repositories/base/base_tribute_levels_repository.h +++ b/common/repositories/base/base_tribute_levels_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_TRIBUTE_LEVELS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTributeLevelsRepository { public: struct TributeLevels { - int tribute_id; - int level; - int cost; - int item_id; + uint32_t tribute_id; + uint32_t level; + uint32_t cost; + uint32_t item_id; }; static std::string PrimaryKey() @@ -52,12 +52,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -85,17 +85,17 @@ public: static TributeLevels NewEntity() { - TributeLevels entry{}; + TributeLevels e{}; - entry.tribute_id = 0; - entry.level = 0; - entry.cost = 0; - entry.item_id = 0; + e.tribute_id = 0; + e.level = 0; + e.cost = 0; + e.item_id = 0; - return entry; + return e; } - static TributeLevels GetTributeLevelsEntry( + static TributeLevels GetTributeLevels( const std::vector &tribute_levelss, int tribute_levels_id ) @@ -124,14 +124,14 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - TributeLevels entry{}; + TributeLevels e{}; - entry.tribute_id = atoi(row[0]); - entry.level = atoi(row[1]); - entry.cost = atoi(row[2]); - entry.item_id = atoi(row[3]); + e.tribute_id = static_cast(strtoul(row[0], nullptr, 10)); + e.level = static_cast(strtoul(row[1], nullptr, 10)); + e.cost = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -156,25 +156,25 @@ public: static int UpdateOne( Database& db, - TributeLevels tribute_levels_entry + const TributeLevels &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(tribute_levels_entry.tribute_id)); - update_values.push_back(columns[1] + " = " + std::to_string(tribute_levels_entry.level)); - update_values.push_back(columns[2] + " = " + std::to_string(tribute_levels_entry.cost)); - update_values.push_back(columns[3] + " = " + std::to_string(tribute_levels_entry.item_id)); + v.push_back(columns[0] + " = " + std::to_string(e.tribute_id)); + v.push_back(columns[1] + " = " + std::to_string(e.level)); + v.push_back(columns[2] + " = " + std::to_string(e.cost)); + v.push_back(columns[3] + " = " + std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - tribute_levels_entry.tribute_id + e.tribute_id ) ); @@ -183,59 +183,59 @@ public: static TributeLevels InsertOne( Database& db, - TributeLevels tribute_levels_entry + TributeLevels e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(tribute_levels_entry.tribute_id)); - insert_values.push_back(std::to_string(tribute_levels_entry.level)); - insert_values.push_back(std::to_string(tribute_levels_entry.cost)); - insert_values.push_back(std::to_string(tribute_levels_entry.item_id)); + v.push_back(std::to_string(e.tribute_id)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.item_id)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - tribute_levels_entry.tribute_id = results.LastInsertedID(); - return tribute_levels_entry; + e.tribute_id = results.LastInsertedID(); + return e; } - tribute_levels_entry = NewEntity(); + e = NewEntity(); - return tribute_levels_entry; + return e; } static int InsertMany( Database& db, - std::vector tribute_levels_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &tribute_levels_entry: tribute_levels_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(tribute_levels_entry.tribute_id)); - insert_values.push_back(std::to_string(tribute_levels_entry.level)); - insert_values.push_back(std::to_string(tribute_levels_entry.cost)); - insert_values.push_back(std::to_string(tribute_levels_entry.item_id)); + v.push_back(std::to_string(e.tribute_id)); + v.push_back(std::to_string(e.level)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.item_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -256,20 +256,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TributeLevels entry{}; + TributeLevels e{}; - entry.tribute_id = atoi(row[0]); - entry.level = atoi(row[1]); - entry.cost = atoi(row[2]); - entry.item_id = atoi(row[3]); + e.tribute_id = static_cast(strtoul(row[0], nullptr, 10)); + e.level = static_cast(strtoul(row[1], nullptr, 10)); + e.cost = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -284,20 +284,20 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - TributeLevels entry{}; + TributeLevels e{}; - entry.tribute_id = atoi(row[0]); - entry.level = atoi(row[1]); - entry.cost = atoi(row[2]); - entry.item_id = atoi(row[3]); + e.tribute_id = static_cast(strtoul(row[0], nullptr, 10)); + e.level = static_cast(strtoul(row[1], nullptr, 10)); + e.cost = static_cast(strtoul(row[2], nullptr, 10)); + e.item_id = static_cast(strtoul(row[3], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -322,6 +322,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TRIBUTE_LEVELS_REPOSITORY_H diff --git a/common/repositories/base/base_tributes_repository.h b/common/repositories/base/base_tributes_repository.h index a18729cd8..81d9e6489 100644 --- a/common/repositories/base/base_tributes_repository.h +++ b/common/repositories/base/base_tributes_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_TRIBUTES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseTributesRepository { public: struct Tributes { - int id; - int unknown; + uint32_t id; + uint32_t unknown; std::string name; std::string descr; - int isguild; + int8_t isguild; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static Tributes NewEntity() { - Tributes entry{}; + Tributes e{}; - entry.id = 0; - entry.unknown = 0; - entry.name = ""; - entry.descr = ""; - entry.isguild = 0; + e.id = 0; + e.unknown = 0; + e.name = ""; + e.descr = ""; + e.isguild = 0; - return entry; + return e; } - static Tributes GetTributesEntry( + static Tributes GetTributes( const std::vector &tributess, int tributes_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - Tributes entry{}; + Tributes e{}; - entry.id = atoi(row[0]); - entry.unknown = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.descr = row[3] ? row[3] : ""; - entry.isguild = atoi(row[4]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.unknown = static_cast(strtoul(row[1], nullptr, 10)); + e.name = row[2] ? row[2] : ""; + e.descr = row[3] ? row[3] : ""; + e.isguild = static_cast(atoi(row[4])); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - Tributes tributes_entry + const Tributes &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(tributes_entry.id)); - update_values.push_back(columns[1] + " = " + std::to_string(tributes_entry.unknown)); - update_values.push_back(columns[2] + " = '" + EscapeString(tributes_entry.name) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(tributes_entry.descr) + "'"); - update_values.push_back(columns[4] + " = " + std::to_string(tributes_entry.isguild)); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.unknown)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.descr) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.isguild)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - tributes_entry.id + e.id ) ); @@ -189,61 +189,61 @@ public: static Tributes InsertOne( Database& db, - Tributes tributes_entry + Tributes e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(tributes_entry.id)); - insert_values.push_back(std::to_string(tributes_entry.unknown)); - insert_values.push_back("'" + EscapeString(tributes_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(tributes_entry.descr) + "'"); - insert_values.push_back(std::to_string(tributes_entry.isguild)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.unknown)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.descr) + "'"); + v.push_back(std::to_string(e.isguild)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - tributes_entry.id = results.LastInsertedID(); - return tributes_entry; + e.id = results.LastInsertedID(); + return e; } - tributes_entry = NewEntity(); + e = NewEntity(); - return tributes_entry; + return e; } static int InsertMany( Database& db, - std::vector tributes_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &tributes_entry: tributes_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(tributes_entry.id)); - insert_values.push_back(std::to_string(tributes_entry.unknown)); - insert_values.push_back("'" + EscapeString(tributes_entry.name) + "'"); - insert_values.push_back("'" + EscapeString(tributes_entry.descr) + "'"); - insert_values.push_back(std::to_string(tributes_entry.isguild)); + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.unknown)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back("'" + Strings::Escape(e.descr) + "'"); + v.push_back(std::to_string(e.isguild)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Tributes entry{}; + Tributes e{}; - entry.id = atoi(row[0]); - entry.unknown = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.descr = row[3] ? row[3] : ""; - entry.isguild = atoi(row[4]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.unknown = static_cast(strtoul(row[1], nullptr, 10)); + e.name = row[2] ? row[2] : ""; + e.descr = row[3] ? row[3] : ""; + e.isguild = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Tributes entry{}; + Tributes e{}; - entry.id = atoi(row[0]); - entry.unknown = atoi(row[1]); - entry.name = row[2] ? row[2] : ""; - entry.descr = row[3] ? row[3] : ""; - entry.isguild = atoi(row[4]); + e.id = static_cast(strtoul(row[0], nullptr, 10)); + e.unknown = static_cast(strtoul(row[1], nullptr, 10)); + e.name = row[2] ? row[2] : ""; + e.descr = row[3] ? row[3] : ""; + e.isguild = static_cast(atoi(row[4])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_TRIBUTES_REPOSITORY_H diff --git a/common/repositories/base/base_variables_repository.h b/common/repositories/base/base_variables_repository.h index 8c18ded15..09facf31e 100644 --- a/common/repositories/base/base_variables_repository.h +++ b/common/repositories/base/base_variables_repository.h @@ -1,24 +1,3 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - */ - /** * This repository was automatically generated and is NOT to be modified directly. * Any repository modifications are meant to be made to @@ -30,7 +9,7 @@ #define EQEMU_BASE_VARIABLES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" class BaseVariablesRepository { public: @@ -58,7 +37,7 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string InsertColumnsRaw() @@ -73,7 +52,7 @@ public: insert_columns.push_back(column); } - return std::string(implode(", ", insert_columns)); + return std::string(Strings::Implode(", ", insert_columns)); } static std::string TableName() @@ -176,16 +155,16 @@ public: auto columns = Columns(); - update_values.push_back(columns[0] + " = '" + EscapeString(variables_entry.varname) + "'"); - update_values.push_back(columns[1] + " = '" + EscapeString(variables_entry.value) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(variables_entry.information) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(variables_entry.ts) + "'"); + update_values.push_back(columns[0] + " = '" + Strings::Escape(variables_entry.varname) + "'"); + update_values.push_back(columns[1] + " = '" + Strings::Escape(variables_entry.value) + "'"); + update_values.push_back(columns[2] + " = '" + Strings::Escape(variables_entry.information) + "'"); + update_values.push_back(columns[3] + " = '" + Strings::Escape(variables_entry.ts) + "'"); auto results = database.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), variables_entry.varname ) @@ -200,16 +179,16 @@ public: { std::vector insert_values; - insert_values.push_back("'" + EscapeString(variables_entry.varname) + "'"); - insert_values.push_back("'" + EscapeString(variables_entry.value) + "'"); - insert_values.push_back("'" + EscapeString(variables_entry.information) + "'"); - insert_values.push_back("'" + EscapeString(variables_entry.ts) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.varname) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.value) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.information) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.ts) + "'"); auto results = database.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -232,12 +211,12 @@ public: for (auto &variables_entry: variables_entries) { std::vector insert_values; - insert_values.push_back("'" + EscapeString(variables_entry.varname) + "'"); - insert_values.push_back("'" + EscapeString(variables_entry.value) + "'"); - insert_values.push_back("'" + EscapeString(variables_entry.information) + "'"); - insert_values.push_back("'" + EscapeString(variables_entry.ts) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.varname) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.value) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.information) + "'"); + insert_values.push_back("'" + Strings::Escape(variables_entry.ts) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -246,7 +225,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/base/base_veteran_reward_templates_repository.h b/common/repositories/base/base_veteran_reward_templates_repository.h index 9055b15d5..c3233a3d5 100644 --- a/common/repositories/base/base_veteran_reward_templates_repository.h +++ b/common/repositories/base/base_veteran_reward_templates_repository.h @@ -13,17 +13,17 @@ #define EQEMU_BASE_VETERAN_REWARD_TEMPLATES_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseVeteranRewardTemplatesRepository { public: struct VeteranRewardTemplates { - int claim_id; + uint32_t claim_id; std::string name; - int item_id; - int charges; - int reward_slot; + uint32_t item_id; + uint16_t charges; + uint8_t reward_slot; }; static std::string PrimaryKey() @@ -55,12 +55,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -88,18 +88,18 @@ public: static VeteranRewardTemplates NewEntity() { - VeteranRewardTemplates entry{}; + VeteranRewardTemplates e{}; - entry.claim_id = 0; - entry.name = ""; - entry.item_id = 0; - entry.charges = 0; - entry.reward_slot = 0; + e.claim_id = 0; + e.name = ""; + e.item_id = 0; + e.charges = 0; + e.reward_slot = 0; - return entry; + return e; } - static VeteranRewardTemplates GetVeteranRewardTemplatesEntry( + static VeteranRewardTemplates GetVeteranRewardTemplates( const std::vector &veteran_reward_templatess, int veteran_reward_templates_id ) @@ -128,15 +128,15 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - VeteranRewardTemplates entry{}; + VeteranRewardTemplates e{}; - entry.claim_id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.item_id = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.reward_slot = atoi(row[4]); + e.claim_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.reward_slot = static_cast(strtoul(row[4], nullptr, 10)); - return entry; + return e; } return NewEntity(); @@ -161,26 +161,26 @@ public: static int UpdateOne( Database& db, - VeteranRewardTemplates veteran_reward_templates_entry + const VeteranRewardTemplates &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = " + std::to_string(veteran_reward_templates_entry.claim_id)); - update_values.push_back(columns[1] + " = '" + EscapeString(veteran_reward_templates_entry.name) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(veteran_reward_templates_entry.item_id)); - update_values.push_back(columns[3] + " = " + std::to_string(veteran_reward_templates_entry.charges)); - update_values.push_back(columns[4] + " = " + std::to_string(veteran_reward_templates_entry.reward_slot)); + v.push_back(columns[0] + " = " + std::to_string(e.claim_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); + v.push_back(columns[4] + " = " + std::to_string(e.reward_slot)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - veteran_reward_templates_entry.claim_id + e.claim_id ) ); @@ -189,61 +189,61 @@ public: static VeteranRewardTemplates InsertOne( Database& db, - VeteranRewardTemplates veteran_reward_templates_entry + VeteranRewardTemplates e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(veteran_reward_templates_entry.claim_id)); - insert_values.push_back("'" + EscapeString(veteran_reward_templates_entry.name) + "'"); - insert_values.push_back(std::to_string(veteran_reward_templates_entry.item_id)); - insert_values.push_back(std::to_string(veteran_reward_templates_entry.charges)); - insert_values.push_back(std::to_string(veteran_reward_templates_entry.reward_slot)); + v.push_back(std::to_string(e.claim_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.reward_slot)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - veteran_reward_templates_entry.claim_id = results.LastInsertedID(); - return veteran_reward_templates_entry; + e.claim_id = results.LastInsertedID(); + return e; } - veteran_reward_templates_entry = NewEntity(); + e = NewEntity(); - return veteran_reward_templates_entry; + return e; } static int InsertMany( Database& db, - std::vector veteran_reward_templates_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &veteran_reward_templates_entry: veteran_reward_templates_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(veteran_reward_templates_entry.claim_id)); - insert_values.push_back("'" + EscapeString(veteran_reward_templates_entry.name) + "'"); - insert_values.push_back(std::to_string(veteran_reward_templates_entry.item_id)); - insert_values.push_back(std::to_string(veteran_reward_templates_entry.charges)); - insert_values.push_back(std::to_string(veteran_reward_templates_entry.reward_slot)); + v.push_back(std::to_string(e.claim_id)); + v.push_back("'" + Strings::Escape(e.name) + "'"); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.reward_slot)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -264,21 +264,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - VeteranRewardTemplates entry{}; + VeteranRewardTemplates e{}; - entry.claim_id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.item_id = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.reward_slot = atoi(row[4]); + e.claim_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.reward_slot = static_cast(strtoul(row[4], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -293,21 +293,21 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - VeteranRewardTemplates entry{}; + VeteranRewardTemplates e{}; - entry.claim_id = atoi(row[0]); - entry.name = row[1] ? row[1] : ""; - entry.item_id = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.reward_slot = atoi(row[4]); + e.claim_id = static_cast(strtoul(row[0], nullptr, 10)); + e.name = row[1] ? row[1] : ""; + e.item_id = static_cast(strtoul(row[2], nullptr, 10)); + e.charges = static_cast(strtoul(row[3], nullptr, 10)); + e.reward_slot = static_cast(strtoul(row[4], nullptr, 10)); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -332,6 +332,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_VETERAN_REWARD_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_zone_points_repository.h b/common/repositories/base/base_zone_points_repository.h index b1f288d75..286159d0c 100644 --- a/common/repositories/base/base_zone_points_repository.h +++ b/common/repositories/base/base_zone_points_repository.h @@ -13,16 +13,16 @@ #define EQEMU_BASE_ZONE_POINTS_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include class BaseZonePointsRepository { public: struct ZonePoints { - int id; + int32_t id; std::string zone; - int version; - int number; + int32_t version; + uint16_t number; float y; float x; float z; @@ -31,18 +31,18 @@ public: float target_x; float target_z; float target_heading; - int zoneinst; - int target_zone_id; - int target_instance; + uint16_t zoneinst; + uint32_t target_zone_id; + uint32_t target_instance; float buffer; - int client_version_mask; - int min_expansion; - int max_expansion; + uint32_t client_version_mask; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; - int is_virtual; - int height; - int width; + int8_t is_virtual; + int32_t height; + int32_t width; }; static std::string PrimaryKey() @@ -112,12 +112,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -145,37 +145,37 @@ public: static ZonePoints NewEntity() { - ZonePoints entry{}; + ZonePoints e{}; - entry.id = 0; - entry.zone = ""; - entry.version = 0; - entry.number = 1; - entry.y = 0; - entry.x = 0; - entry.z = 0; - entry.heading = 0; - entry.target_y = 0; - entry.target_x = 0; - entry.target_z = 0; - entry.target_heading = 0; - entry.zoneinst = 0; - entry.target_zone_id = 0; - entry.target_instance = 0; - entry.buffer = 0; - entry.client_version_mask = 4294967295; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; - entry.is_virtual = 0; - entry.height = 0; - entry.width = 0; + e.id = 0; + e.zone = ""; + e.version = 0; + e.number = 1; + e.y = 0; + e.x = 0; + e.z = 0; + e.heading = 0; + e.target_y = 0; + e.target_x = 0; + e.target_z = 0; + e.target_heading = 0; + e.zoneinst = 0; + e.target_zone_id = 0; + e.target_instance = 0; + e.buffer = 0; + e.client_version_mask = 4294967295; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; + e.is_virtual = 0; + e.height = 0; + e.width = 0; - return entry; + return e; } - static ZonePoints GetZonePointsEntry( + static ZonePoints GetZonePoints( const std::vector &zone_pointss, int zone_points_id ) @@ -204,34 +204,34 @@ public: auto row = results.begin(); if (results.RowCount() == 1) { - ZonePoints entry{}; + ZonePoints e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.version = atoi(row[2]); - entry.number = atoi(row[3]); - entry.y = static_cast(atof(row[4])); - entry.x = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); - entry.target_y = static_cast(atof(row[8])); - entry.target_x = static_cast(atof(row[9])); - entry.target_z = static_cast(atof(row[10])); - entry.target_heading = static_cast(atof(row[11])); - entry.zoneinst = atoi(row[12]); - entry.target_zone_id = atoi(row[13]); - entry.target_instance = atoi(row[14]); - entry.buffer = static_cast(atof(row[15])); - entry.client_version_mask = atoi(row[16]); - entry.min_expansion = atoi(row[17]); - entry.max_expansion = atoi(row[18]); - entry.content_flags = row[19] ? row[19] : ""; - entry.content_flags_disabled = row[20] ? row[20] : ""; - entry.is_virtual = atoi(row[21]); - entry.height = atoi(row[22]); - entry.width = atoi(row[23]); + e.id = static_cast(atoi(row[0])); + e.zone = row[1] ? row[1] : ""; + e.version = static_cast(atoi(row[2])); + e.number = static_cast(strtoul(row[3], nullptr, 10)); + e.y = strtof(row[4], nullptr); + e.x = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); + e.target_y = strtof(row[8], nullptr); + e.target_x = strtof(row[9], nullptr); + e.target_z = strtof(row[10], nullptr); + e.target_heading = strtof(row[11], nullptr); + e.zoneinst = static_cast(strtoul(row[12], nullptr, 10)); + e.target_zone_id = static_cast(strtoul(row[13], nullptr, 10)); + e.target_instance = static_cast(strtoul(row[14], nullptr, 10)); + e.buffer = strtof(row[15], nullptr); + e.client_version_mask = static_cast(strtoul(row[16], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[17])); + e.max_expansion = static_cast(atoi(row[18])); + e.content_flags = row[19] ? row[19] : ""; + e.content_flags_disabled = row[20] ? row[20] : ""; + e.is_virtual = static_cast(atoi(row[21])); + e.height = static_cast(atoi(row[22])); + e.width = static_cast(atoi(row[23])); - return entry; + return e; } return NewEntity(); @@ -256,44 +256,44 @@ public: static int UpdateOne( Database& db, - ZonePoints zone_points_entry + const ZonePoints &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[1] + " = '" + EscapeString(zone_points_entry.zone) + "'"); - update_values.push_back(columns[2] + " = " + std::to_string(zone_points_entry.version)); - update_values.push_back(columns[3] + " = " + std::to_string(zone_points_entry.number)); - update_values.push_back(columns[4] + " = " + std::to_string(zone_points_entry.y)); - update_values.push_back(columns[5] + " = " + std::to_string(zone_points_entry.x)); - update_values.push_back(columns[6] + " = " + std::to_string(zone_points_entry.z)); - update_values.push_back(columns[7] + " = " + std::to_string(zone_points_entry.heading)); - update_values.push_back(columns[8] + " = " + std::to_string(zone_points_entry.target_y)); - update_values.push_back(columns[9] + " = " + std::to_string(zone_points_entry.target_x)); - update_values.push_back(columns[10] + " = " + std::to_string(zone_points_entry.target_z)); - update_values.push_back(columns[11] + " = " + std::to_string(zone_points_entry.target_heading)); - update_values.push_back(columns[12] + " = " + std::to_string(zone_points_entry.zoneinst)); - update_values.push_back(columns[13] + " = " + std::to_string(zone_points_entry.target_zone_id)); - update_values.push_back(columns[14] + " = " + std::to_string(zone_points_entry.target_instance)); - update_values.push_back(columns[15] + " = " + std::to_string(zone_points_entry.buffer)); - update_values.push_back(columns[16] + " = " + std::to_string(zone_points_entry.client_version_mask)); - update_values.push_back(columns[17] + " = " + std::to_string(zone_points_entry.min_expansion)); - update_values.push_back(columns[18] + " = " + std::to_string(zone_points_entry.max_expansion)); - update_values.push_back(columns[19] + " = '" + EscapeString(zone_points_entry.content_flags) + "'"); - update_values.push_back(columns[20] + " = '" + EscapeString(zone_points_entry.content_flags_disabled) + "'"); - update_values.push_back(columns[21] + " = " + std::to_string(zone_points_entry.is_virtual)); - update_values.push_back(columns[22] + " = " + std::to_string(zone_points_entry.height)); - update_values.push_back(columns[23] + " = " + std::to_string(zone_points_entry.width)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.version)); + v.push_back(columns[3] + " = " + std::to_string(e.number)); + v.push_back(columns[4] + " = " + std::to_string(e.y)); + v.push_back(columns[5] + " = " + std::to_string(e.x)); + v.push_back(columns[6] + " = " + std::to_string(e.z)); + v.push_back(columns[7] + " = " + std::to_string(e.heading)); + v.push_back(columns[8] + " = " + std::to_string(e.target_y)); + v.push_back(columns[9] + " = " + std::to_string(e.target_x)); + v.push_back(columns[10] + " = " + std::to_string(e.target_z)); + v.push_back(columns[11] + " = " + std::to_string(e.target_heading)); + v.push_back(columns[12] + " = " + std::to_string(e.zoneinst)); + v.push_back(columns[13] + " = " + std::to_string(e.target_zone_id)); + v.push_back(columns[14] + " = " + std::to_string(e.target_instance)); + v.push_back(columns[15] + " = " + std::to_string(e.buffer)); + v.push_back(columns[16] + " = " + std::to_string(e.client_version_mask)); + v.push_back(columns[17] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[18] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[19] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[20] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(columns[21] + " = " + std::to_string(e.is_virtual)); + v.push_back(columns[22] + " = " + std::to_string(e.height)); + v.push_back(columns[23] + " = " + std::to_string(e.width)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - zone_points_entry.id + e.id ) ); @@ -302,99 +302,99 @@ public: static ZonePoints InsertOne( Database& db, - ZonePoints zone_points_entry + ZonePoints e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back(std::to_string(zone_points_entry.id)); - insert_values.push_back("'" + EscapeString(zone_points_entry.zone) + "'"); - insert_values.push_back(std::to_string(zone_points_entry.version)); - insert_values.push_back(std::to_string(zone_points_entry.number)); - insert_values.push_back(std::to_string(zone_points_entry.y)); - insert_values.push_back(std::to_string(zone_points_entry.x)); - insert_values.push_back(std::to_string(zone_points_entry.z)); - insert_values.push_back(std::to_string(zone_points_entry.heading)); - insert_values.push_back(std::to_string(zone_points_entry.target_y)); - insert_values.push_back(std::to_string(zone_points_entry.target_x)); - insert_values.push_back(std::to_string(zone_points_entry.target_z)); - insert_values.push_back(std::to_string(zone_points_entry.target_heading)); - insert_values.push_back(std::to_string(zone_points_entry.zoneinst)); - insert_values.push_back(std::to_string(zone_points_entry.target_zone_id)); - insert_values.push_back(std::to_string(zone_points_entry.target_instance)); - insert_values.push_back(std::to_string(zone_points_entry.buffer)); - insert_values.push_back(std::to_string(zone_points_entry.client_version_mask)); - insert_values.push_back(std::to_string(zone_points_entry.min_expansion)); - insert_values.push_back(std::to_string(zone_points_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags_disabled) + "'"); - insert_values.push_back(std::to_string(zone_points_entry.is_virtual)); - insert_values.push_back(std::to_string(zone_points_entry.height)); - insert_values.push_back(std::to_string(zone_points_entry.width)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.number)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.target_y)); + v.push_back(std::to_string(e.target_x)); + v.push_back(std::to_string(e.target_z)); + v.push_back(std::to_string(e.target_heading)); + v.push_back(std::to_string(e.zoneinst)); + v.push_back(std::to_string(e.target_zone_id)); + v.push_back(std::to_string(e.target_instance)); + v.push_back(std::to_string(e.buffer)); + v.push_back(std::to_string(e.client_version_mask)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.is_virtual)); + v.push_back(std::to_string(e.height)); + v.push_back(std::to_string(e.width)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - zone_points_entry.id = results.LastInsertedID(); - return zone_points_entry; + e.id = results.LastInsertedID(); + return e; } - zone_points_entry = NewEntity(); + e = NewEntity(); - return zone_points_entry; + return e; } static int InsertMany( Database& db, - std::vector zone_points_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &zone_points_entry: zone_points_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back(std::to_string(zone_points_entry.id)); - insert_values.push_back("'" + EscapeString(zone_points_entry.zone) + "'"); - insert_values.push_back(std::to_string(zone_points_entry.version)); - insert_values.push_back(std::to_string(zone_points_entry.number)); - insert_values.push_back(std::to_string(zone_points_entry.y)); - insert_values.push_back(std::to_string(zone_points_entry.x)); - insert_values.push_back(std::to_string(zone_points_entry.z)); - insert_values.push_back(std::to_string(zone_points_entry.heading)); - insert_values.push_back(std::to_string(zone_points_entry.target_y)); - insert_values.push_back(std::to_string(zone_points_entry.target_x)); - insert_values.push_back(std::to_string(zone_points_entry.target_z)); - insert_values.push_back(std::to_string(zone_points_entry.target_heading)); - insert_values.push_back(std::to_string(zone_points_entry.zoneinst)); - insert_values.push_back(std::to_string(zone_points_entry.target_zone_id)); - insert_values.push_back(std::to_string(zone_points_entry.target_instance)); - insert_values.push_back(std::to_string(zone_points_entry.buffer)); - insert_values.push_back(std::to_string(zone_points_entry.client_version_mask)); - insert_values.push_back(std::to_string(zone_points_entry.min_expansion)); - insert_values.push_back(std::to_string(zone_points_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags_disabled) + "'"); - insert_values.push_back(std::to_string(zone_points_entry.is_virtual)); - insert_values.push_back(std::to_string(zone_points_entry.height)); - insert_values.push_back(std::to_string(zone_points_entry.width)); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.zone) + "'"); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.number)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.target_y)); + v.push_back(std::to_string(e.target_x)); + v.push_back(std::to_string(e.target_z)); + v.push_back(std::to_string(e.target_heading)); + v.push_back(std::to_string(e.zoneinst)); + v.push_back(std::to_string(e.target_zone_id)); + v.push_back(std::to_string(e.target_instance)); + v.push_back(std::to_string(e.buffer)); + v.push_back(std::to_string(e.client_version_mask)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.is_virtual)); + v.push_back(std::to_string(e.height)); + v.push_back(std::to_string(e.width)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -415,40 +415,40 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ZonePoints entry{}; + ZonePoints e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.version = atoi(row[2]); - entry.number = atoi(row[3]); - entry.y = static_cast(atof(row[4])); - entry.x = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); - entry.target_y = static_cast(atof(row[8])); - entry.target_x = static_cast(atof(row[9])); - entry.target_z = static_cast(atof(row[10])); - entry.target_heading = static_cast(atof(row[11])); - entry.zoneinst = atoi(row[12]); - entry.target_zone_id = atoi(row[13]); - entry.target_instance = atoi(row[14]); - entry.buffer = static_cast(atof(row[15])); - entry.client_version_mask = atoi(row[16]); - entry.min_expansion = atoi(row[17]); - entry.max_expansion = atoi(row[18]); - entry.content_flags = row[19] ? row[19] : ""; - entry.content_flags_disabled = row[20] ? row[20] : ""; - entry.is_virtual = atoi(row[21]); - entry.height = atoi(row[22]); - entry.width = atoi(row[23]); + e.id = static_cast(atoi(row[0])); + e.zone = row[1] ? row[1] : ""; + e.version = static_cast(atoi(row[2])); + e.number = static_cast(strtoul(row[3], nullptr, 10)); + e.y = strtof(row[4], nullptr); + e.x = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); + e.target_y = strtof(row[8], nullptr); + e.target_x = strtof(row[9], nullptr); + e.target_z = strtof(row[10], nullptr); + e.target_heading = strtof(row[11], nullptr); + e.zoneinst = static_cast(strtoul(row[12], nullptr, 10)); + e.target_zone_id = static_cast(strtoul(row[13], nullptr, 10)); + e.target_instance = static_cast(strtoul(row[14], nullptr, 10)); + e.buffer = strtof(row[15], nullptr); + e.client_version_mask = static_cast(strtoul(row[16], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[17])); + e.max_expansion = static_cast(atoi(row[18])); + e.content_flags = row[19] ? row[19] : ""; + e.content_flags_disabled = row[20] ? row[20] : ""; + e.is_virtual = static_cast(atoi(row[21])); + e.height = static_cast(atoi(row[22])); + e.width = static_cast(atoi(row[23])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -463,40 +463,40 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - ZonePoints entry{}; + ZonePoints e{}; - entry.id = atoi(row[0]); - entry.zone = row[1] ? row[1] : ""; - entry.version = atoi(row[2]); - entry.number = atoi(row[3]); - entry.y = static_cast(atof(row[4])); - entry.x = static_cast(atof(row[5])); - entry.z = static_cast(atof(row[6])); - entry.heading = static_cast(atof(row[7])); - entry.target_y = static_cast(atof(row[8])); - entry.target_x = static_cast(atof(row[9])); - entry.target_z = static_cast(atof(row[10])); - entry.target_heading = static_cast(atof(row[11])); - entry.zoneinst = atoi(row[12]); - entry.target_zone_id = atoi(row[13]); - entry.target_instance = atoi(row[14]); - entry.buffer = static_cast(atof(row[15])); - entry.client_version_mask = atoi(row[16]); - entry.min_expansion = atoi(row[17]); - entry.max_expansion = atoi(row[18]); - entry.content_flags = row[19] ? row[19] : ""; - entry.content_flags_disabled = row[20] ? row[20] : ""; - entry.is_virtual = atoi(row[21]); - entry.height = atoi(row[22]); - entry.width = atoi(row[23]); + e.id = static_cast(atoi(row[0])); + e.zone = row[1] ? row[1] : ""; + e.version = static_cast(atoi(row[2])); + e.number = static_cast(strtoul(row[3], nullptr, 10)); + e.y = strtof(row[4], nullptr); + e.x = strtof(row[5], nullptr); + e.z = strtof(row[6], nullptr); + e.heading = strtof(row[7], nullptr); + e.target_y = strtof(row[8], nullptr); + e.target_x = strtof(row[9], nullptr); + e.target_z = strtof(row[10], nullptr); + e.target_heading = strtof(row[11], nullptr); + e.zoneinst = static_cast(strtoul(row[12], nullptr, 10)); + e.target_zone_id = static_cast(strtoul(row[13], nullptr, 10)); + e.target_instance = static_cast(strtoul(row[14], nullptr, 10)); + e.buffer = strtof(row[15], nullptr); + e.client_version_mask = static_cast(strtoul(row[16], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[17])); + e.max_expansion = static_cast(atoi(row[18])); + e.content_flags = row[19] ? row[19] : ""; + e.content_flags_disabled = row[20] ? row[20] : ""; + e.is_virtual = static_cast(atoi(row[21])); + e.height = static_cast(atoi(row[22])); + e.width = static_cast(atoi(row[23])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -521,6 +521,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ZONE_POINTS_REPOSITORY_H diff --git a/common/repositories/base/base_zone_repository.h b/common/repositories/base/base_zone_repository.h index c9db5510d..90f07fc86 100644 --- a/common/repositories/base/base_zone_repository.h +++ b/common/repositories/base/base_zone_repository.h @@ -13,14 +13,15 @@ #define EQEMU_BASE_ZONE_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include + class BaseZoneRepository { public: struct Zone { std::string short_name; - int id; + int32_t id; std::string file_name; std::string long_name; std::string map_file_name; @@ -29,90 +30,92 @@ public: float safe_z; float safe_heading; float graveyard_id; - int min_level; - int min_status; - int zoneidnumber; - int version; - int timezone; - int maxclients; - int ruleset; + uint8_t min_level; + uint8_t max_level; + uint8_t min_status; + int32_t zoneidnumber; + uint8_t version; + int32_t timezone; + int32_t maxclients; + uint32_t ruleset; std::string note; float underworld; float minclip; float maxclip; float fog_minclip; float fog_maxclip; - int fog_blue; - int fog_red; - int fog_green; - int sky; - int ztype; + uint8_t fog_blue; + uint8_t fog_red; + uint8_t fog_green; + uint8_t sky; + uint8_t ztype; float zone_exp_multiplier; float walkspeed; - int time_type; - int fog_red1; - int fog_green1; - int fog_blue1; + uint8_t time_type; + uint8_t fog_red1; + uint8_t fog_green1; + uint8_t fog_blue1; float fog_minclip1; float fog_maxclip1; - int fog_red2; - int fog_green2; - int fog_blue2; + uint8_t fog_red2; + uint8_t fog_green2; + uint8_t fog_blue2; float fog_minclip2; float fog_maxclip2; - int fog_red3; - int fog_green3; - int fog_blue3; + uint8_t fog_red3; + uint8_t fog_green3; + uint8_t fog_blue3; float fog_minclip3; float fog_maxclip3; - int fog_red4; - int fog_green4; - int fog_blue4; + uint8_t fog_red4; + uint8_t fog_green4; + uint8_t fog_blue4; float fog_minclip4; float fog_maxclip4; float fog_density; std::string flag_needed; - int canbind; - int cancombat; - int canlevitate; - int castoutdoor; - int hotzone; - int insttype; - int64 shutdowndelay; - int peqzone; - int expansion; - int suspendbuffs; - int rain_chance1; - int rain_chance2; - int rain_chance3; - int rain_chance4; - int rain_duration1; - int rain_duration2; - int rain_duration3; - int rain_duration4; - int snow_chance1; - int snow_chance2; - int snow_chance3; - int snow_chance4; - int snow_duration1; - int snow_duration2; - int snow_duration3; - int snow_duration4; + int8_t canbind; + int8_t cancombat; + int8_t canlevitate; + int8_t castoutdoor; + uint8_t hotzone; + uint8_t insttype; + uint64_t shutdowndelay; + int8_t peqzone; + int8_t expansion; + int8_t bypass_expansion_check; + uint8_t suspendbuffs; + int32_t rain_chance1; + int32_t rain_chance2; + int32_t rain_chance3; + int32_t rain_chance4; + int32_t rain_duration1; + int32_t rain_duration2; + int32_t rain_duration3; + int32_t rain_duration4; + int32_t snow_chance1; + int32_t snow_chance2; + int32_t snow_chance3; + int32_t snow_chance4; + int32_t snow_duration1; + int32_t snow_duration2; + int32_t snow_duration3; + int32_t snow_duration4; float gravity; - int type; - int skylock; - int fast_regen_hp; - int fast_regen_mana; - int fast_regen_endurance; - int npc_max_aggro_dist; - int max_movement_update_range; - int min_expansion; - int max_expansion; + int32_t type; + int8_t skylock; + int32_t fast_regen_hp; + int32_t fast_regen_mana; + int32_t fast_regen_endurance; + int32_t npc_max_aggro_dist; + uint32_t max_movement_update_range; + int8_t min_expansion; + int8_t max_expansion; std::string content_flags; std::string content_flags_disabled; - int underworld_teleport_index; - int lava_damage; - int min_lava_damage; + int32_t underworld_teleport_index; + int32_t lava_damage; + int32_t min_lava_damage; }; static std::string PrimaryKey() @@ -134,6 +137,7 @@ public: "safe_heading", "graveyard_id", "min_level", + "max_level", "min_status", "zoneidnumber", "version", @@ -185,6 +189,7 @@ public: "shutdowndelay", "peqzone", "expansion", + "bypass_expansion_check", "suspendbuffs", "rain_chance1", "rain_chance2", @@ -234,6 +239,7 @@ public: "safe_heading", "graveyard_id", "min_level", + "max_level", "min_status", "zoneidnumber", "version", @@ -285,6 +291,7 @@ public: "shutdowndelay", "peqzone", "expansion", + "bypass_expansion_check", "suspendbuffs", "rain_chance1", "rain_chance2", @@ -322,12 +329,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -355,107 +362,109 @@ public: static Zone NewEntity() { - Zone entry{}; + Zone e{}; - entry.short_name = ""; - entry.id = 0; - entry.file_name = ""; - entry.long_name = ""; - entry.map_file_name = ""; - entry.safe_x = 0; - entry.safe_y = 0; - entry.safe_z = 0; - entry.safe_heading = 0; - entry.graveyard_id = 0; - entry.min_level = 0; - entry.min_status = 0; - entry.zoneidnumber = 0; - entry.version = 0; - entry.timezone = 0; - entry.maxclients = 0; - entry.ruleset = 0; - entry.note = ""; - entry.underworld = 0; - entry.minclip = 450; - entry.maxclip = 450; - entry.fog_minclip = 450; - entry.fog_maxclip = 450; - entry.fog_blue = 0; - entry.fog_red = 0; - entry.fog_green = 0; - entry.sky = 1; - entry.ztype = 1; - entry.zone_exp_multiplier = 0.00; - entry.walkspeed = 0.4; - entry.time_type = 2; - entry.fog_red1 = 0; - entry.fog_green1 = 0; - entry.fog_blue1 = 0; - entry.fog_minclip1 = 450; - entry.fog_maxclip1 = 450; - entry.fog_red2 = 0; - entry.fog_green2 = 0; - entry.fog_blue2 = 0; - entry.fog_minclip2 = 450; - entry.fog_maxclip2 = 450; - entry.fog_red3 = 0; - entry.fog_green3 = 0; - entry.fog_blue3 = 0; - entry.fog_minclip3 = 450; - entry.fog_maxclip3 = 450; - entry.fog_red4 = 0; - entry.fog_green4 = 0; - entry.fog_blue4 = 0; - entry.fog_minclip4 = 450; - entry.fog_maxclip4 = 450; - entry.fog_density = 0; - entry.flag_needed = ""; - entry.canbind = 1; - entry.cancombat = 1; - entry.canlevitate = 1; - entry.castoutdoor = 1; - entry.hotzone = 0; - entry.insttype = 0; - entry.shutdowndelay = 5000; - entry.peqzone = 1; - entry.expansion = 0; - entry.suspendbuffs = 0; - entry.rain_chance1 = 0; - entry.rain_chance2 = 0; - entry.rain_chance3 = 0; - entry.rain_chance4 = 0; - entry.rain_duration1 = 0; - entry.rain_duration2 = 0; - entry.rain_duration3 = 0; - entry.rain_duration4 = 0; - entry.snow_chance1 = 0; - entry.snow_chance2 = 0; - entry.snow_chance3 = 0; - entry.snow_chance4 = 0; - entry.snow_duration1 = 0; - entry.snow_duration2 = 0; - entry.snow_duration3 = 0; - entry.snow_duration4 = 0; - entry.gravity = 0.4; - entry.type = 0; - entry.skylock = 0; - entry.fast_regen_hp = 180; - entry.fast_regen_mana = 180; - entry.fast_regen_endurance = 180; - entry.npc_max_aggro_dist = 600; - entry.max_movement_update_range = 600; - entry.min_expansion = -1; - entry.max_expansion = -1; - entry.content_flags = ""; - entry.content_flags_disabled = ""; - entry.underworld_teleport_index = 0; - entry.lava_damage = 50; - entry.min_lava_damage = 10; + e.short_name = ""; + e.id = 0; + e.file_name = ""; + e.long_name = ""; + e.map_file_name = ""; + e.safe_x = 0; + e.safe_y = 0; + e.safe_z = 0; + e.safe_heading = 0; + e.graveyard_id = 0; + e.min_level = 0; + e.max_level = 255; + e.min_status = 0; + e.zoneidnumber = 0; + e.version = 0; + e.timezone = 0; + e.maxclients = 0; + e.ruleset = 0; + e.note = ""; + e.underworld = 0; + e.minclip = 450; + e.maxclip = 450; + e.fog_minclip = 450; + e.fog_maxclip = 450; + e.fog_blue = 0; + e.fog_red = 0; + e.fog_green = 0; + e.sky = 1; + e.ztype = 1; + e.zone_exp_multiplier = 0.00; + e.walkspeed = 0.4; + e.time_type = 2; + e.fog_red1 = 0; + e.fog_green1 = 0; + e.fog_blue1 = 0; + e.fog_minclip1 = 450; + e.fog_maxclip1 = 450; + e.fog_red2 = 0; + e.fog_green2 = 0; + e.fog_blue2 = 0; + e.fog_minclip2 = 450; + e.fog_maxclip2 = 450; + e.fog_red3 = 0; + e.fog_green3 = 0; + e.fog_blue3 = 0; + e.fog_minclip3 = 450; + e.fog_maxclip3 = 450; + e.fog_red4 = 0; + e.fog_green4 = 0; + e.fog_blue4 = 0; + e.fog_minclip4 = 450; + e.fog_maxclip4 = 450; + e.fog_density = 0; + e.flag_needed = ""; + e.canbind = 1; + e.cancombat = 1; + e.canlevitate = 1; + e.castoutdoor = 1; + e.hotzone = 0; + e.insttype = 0; + e.shutdowndelay = 5000; + e.peqzone = 1; + e.expansion = 0; + e.bypass_expansion_check = 0; + e.suspendbuffs = 0; + e.rain_chance1 = 0; + e.rain_chance2 = 0; + e.rain_chance3 = 0; + e.rain_chance4 = 0; + e.rain_duration1 = 0; + e.rain_duration2 = 0; + e.rain_duration3 = 0; + e.rain_duration4 = 0; + e.snow_chance1 = 0; + e.snow_chance2 = 0; + e.snow_chance3 = 0; + e.snow_chance4 = 0; + e.snow_duration1 = 0; + e.snow_duration2 = 0; + e.snow_duration3 = 0; + e.snow_duration4 = 0; + e.gravity = 0.4; + e.type = 0; + e.skylock = 0; + e.fast_regen_hp = 180; + e.fast_regen_mana = 180; + e.fast_regen_endurance = 180; + e.npc_max_aggro_dist = 600; + e.max_movement_update_range = 600; + e.min_expansion = -1; + e.max_expansion = -1; + e.content_flags = ""; + e.content_flags_disabled = ""; + e.underworld_teleport_index = 0; + e.lava_damage = 50; + e.min_lava_damage = 10; - return entry; + return e; } - static Zone GetZoneEntry( + static Zone GetZone( const std::vector &zones, int zone_id ) @@ -476,112 +485,115 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), zone_id ) ); auto row = results.begin(); if (results.RowCount() == 1) { - Zone entry{}; + Zone e{}; - entry.short_name = row[0] ? row[0] : ""; - entry.id = atoi(row[1]); - entry.file_name = row[2] ? row[2] : ""; - entry.long_name = row[3] ? row[3] : ""; - entry.map_file_name = row[4] ? row[4] : ""; - entry.safe_x = static_cast(atof(row[5])); - entry.safe_y = static_cast(atof(row[6])); - entry.safe_z = static_cast(atof(row[7])); - entry.safe_heading = static_cast(atof(row[8])); - entry.graveyard_id = static_cast(atof(row[9])); - entry.min_level = atoi(row[10]); - entry.min_status = atoi(row[11]); - entry.zoneidnumber = atoi(row[12]); - entry.version = atoi(row[13]); - entry.timezone = atoi(row[14]); - entry.maxclients = atoi(row[15]); - entry.ruleset = atoi(row[16]); - entry.note = row[17] ? row[17] : ""; - entry.underworld = static_cast(atof(row[18])); - entry.minclip = static_cast(atof(row[19])); - entry.maxclip = static_cast(atof(row[20])); - entry.fog_minclip = static_cast(atof(row[21])); - entry.fog_maxclip = static_cast(atof(row[22])); - entry.fog_blue = atoi(row[23]); - entry.fog_red = atoi(row[24]); - entry.fog_green = atoi(row[25]); - entry.sky = atoi(row[26]); - entry.ztype = atoi(row[27]); - entry.zone_exp_multiplier = static_cast(atof(row[28])); - entry.walkspeed = static_cast(atof(row[29])); - entry.time_type = atoi(row[30]); - entry.fog_red1 = atoi(row[31]); - entry.fog_green1 = atoi(row[32]); - entry.fog_blue1 = atoi(row[33]); - entry.fog_minclip1 = static_cast(atof(row[34])); - entry.fog_maxclip1 = static_cast(atof(row[35])); - entry.fog_red2 = atoi(row[36]); - entry.fog_green2 = atoi(row[37]); - entry.fog_blue2 = atoi(row[38]); - entry.fog_minclip2 = static_cast(atof(row[39])); - entry.fog_maxclip2 = static_cast(atof(row[40])); - entry.fog_red3 = atoi(row[41]); - entry.fog_green3 = atoi(row[42]); - entry.fog_blue3 = atoi(row[43]); - entry.fog_minclip3 = static_cast(atof(row[44])); - entry.fog_maxclip3 = static_cast(atof(row[45])); - entry.fog_red4 = atoi(row[46]); - entry.fog_green4 = atoi(row[47]); - entry.fog_blue4 = atoi(row[48]); - entry.fog_minclip4 = static_cast(atof(row[49])); - entry.fog_maxclip4 = static_cast(atof(row[50])); - entry.fog_density = static_cast(atof(row[51])); - entry.flag_needed = row[52] ? row[52] : ""; - entry.canbind = atoi(row[53]); - entry.cancombat = atoi(row[54]); - entry.canlevitate = atoi(row[55]); - entry.castoutdoor = atoi(row[56]); - entry.hotzone = atoi(row[57]); - entry.insttype = atoi(row[58]); - entry.shutdowndelay = strtoll(row[59], nullptr, 10); - entry.peqzone = atoi(row[60]); - entry.expansion = atoi(row[61]); - entry.suspendbuffs = atoi(row[62]); - entry.rain_chance1 = atoi(row[63]); - entry.rain_chance2 = atoi(row[64]); - entry.rain_chance3 = atoi(row[65]); - entry.rain_chance4 = atoi(row[66]); - entry.rain_duration1 = atoi(row[67]); - entry.rain_duration2 = atoi(row[68]); - entry.rain_duration3 = atoi(row[69]); - entry.rain_duration4 = atoi(row[70]); - entry.snow_chance1 = atoi(row[71]); - entry.snow_chance2 = atoi(row[72]); - entry.snow_chance3 = atoi(row[73]); - entry.snow_chance4 = atoi(row[74]); - entry.snow_duration1 = atoi(row[75]); - entry.snow_duration2 = atoi(row[76]); - entry.snow_duration3 = atoi(row[77]); - entry.snow_duration4 = atoi(row[78]); - entry.gravity = static_cast(atof(row[79])); - entry.type = atoi(row[80]); - entry.skylock = atoi(row[81]); - entry.fast_regen_hp = atoi(row[82]); - entry.fast_regen_mana = atoi(row[83]); - entry.fast_regen_endurance = atoi(row[84]); - entry.npc_max_aggro_dist = atoi(row[85]); - entry.max_movement_update_range = atoi(row[86]); - entry.min_expansion = atoi(row[87]); - entry.max_expansion = atoi(row[88]); - entry.content_flags = row[89] ? row[89] : ""; - entry.content_flags_disabled = row[90] ? row[90] : ""; - entry.underworld_teleport_index = atoi(row[91]); - entry.lava_damage = atoi(row[92]); - entry.min_lava_damage = atoi(row[93]); + e.short_name = row[0] ? row[0] : ""; + e.id = static_cast(atoi(row[1])); + e.file_name = row[2] ? row[2] : ""; + e.long_name = row[3] ? row[3] : ""; + e.map_file_name = row[4] ? row[4] : ""; + e.safe_x = strtof(row[5], nullptr); + e.safe_y = strtof(row[6], nullptr); + e.safe_z = strtof(row[7], nullptr); + e.safe_heading = strtof(row[8], nullptr); + e.graveyard_id = strtof(row[9], nullptr); + e.min_level = static_cast(strtoul(row[10], nullptr, 10)); + e.max_level = static_cast(strtoul(row[11], nullptr, 10)); + e.min_status = static_cast(strtoul(row[12], nullptr, 10)); + e.zoneidnumber = static_cast(atoi(row[13])); + e.version = static_cast(strtoul(row[14], nullptr, 10)); + e.timezone = static_cast(atoi(row[15])); + e.maxclients = static_cast(atoi(row[16])); + e.ruleset = static_cast(strtoul(row[17], nullptr, 10)); + e.note = row[18] ? row[18] : ""; + e.underworld = strtof(row[19], nullptr); + e.minclip = strtof(row[20], nullptr); + e.maxclip = strtof(row[21], nullptr); + e.fog_minclip = strtof(row[22], nullptr); + e.fog_maxclip = strtof(row[23], nullptr); + e.fog_blue = static_cast(strtoul(row[24], nullptr, 10)); + e.fog_red = static_cast(strtoul(row[25], nullptr, 10)); + e.fog_green = static_cast(strtoul(row[26], nullptr, 10)); + e.sky = static_cast(strtoul(row[27], nullptr, 10)); + e.ztype = static_cast(strtoul(row[28], nullptr, 10)); + e.zone_exp_multiplier = strtof(row[29], nullptr); + e.walkspeed = strtof(row[30], nullptr); + e.time_type = static_cast(strtoul(row[31], nullptr, 10)); + e.fog_red1 = static_cast(strtoul(row[32], nullptr, 10)); + e.fog_green1 = static_cast(strtoul(row[33], nullptr, 10)); + e.fog_blue1 = static_cast(strtoul(row[34], nullptr, 10)); + e.fog_minclip1 = strtof(row[35], nullptr); + e.fog_maxclip1 = strtof(row[36], nullptr); + e.fog_red2 = static_cast(strtoul(row[37], nullptr, 10)); + e.fog_green2 = static_cast(strtoul(row[38], nullptr, 10)); + e.fog_blue2 = static_cast(strtoul(row[39], nullptr, 10)); + e.fog_minclip2 = strtof(row[40], nullptr); + e.fog_maxclip2 = strtof(row[41], nullptr); + e.fog_red3 = static_cast(strtoul(row[42], nullptr, 10)); + e.fog_green3 = static_cast(strtoul(row[43], nullptr, 10)); + e.fog_blue3 = static_cast(strtoul(row[44], nullptr, 10)); + e.fog_minclip3 = strtof(row[45], nullptr); + e.fog_maxclip3 = strtof(row[46], nullptr); + e.fog_red4 = static_cast(strtoul(row[47], nullptr, 10)); + e.fog_green4 = static_cast(strtoul(row[48], nullptr, 10)); + e.fog_blue4 = static_cast(strtoul(row[49], nullptr, 10)); + e.fog_minclip4 = strtof(row[50], nullptr); + e.fog_maxclip4 = strtof(row[51], nullptr); + e.fog_density = strtof(row[52], nullptr); + e.flag_needed = row[53] ? row[53] : ""; + e.canbind = static_cast(atoi(row[54])); + e.cancombat = static_cast(atoi(row[55])); + e.canlevitate = static_cast(atoi(row[56])); + e.castoutdoor = static_cast(atoi(row[57])); + e.hotzone = static_cast(strtoul(row[58], nullptr, 10)); + e.insttype = static_cast(strtoul(row[59], nullptr, 10)); + e.shutdowndelay = strtoull(row[60], nullptr, 10); + e.peqzone = static_cast(atoi(row[61])); + e.expansion = static_cast(atoi(row[62])); + e.bypass_expansion_check = static_cast(atoi(row[63])); + e.suspendbuffs = static_cast(strtoul(row[64], nullptr, 10)); + e.rain_chance1 = static_cast(atoi(row[65])); + e.rain_chance2 = static_cast(atoi(row[66])); + e.rain_chance3 = static_cast(atoi(row[67])); + e.rain_chance4 = static_cast(atoi(row[68])); + e.rain_duration1 = static_cast(atoi(row[69])); + e.rain_duration2 = static_cast(atoi(row[70])); + e.rain_duration3 = static_cast(atoi(row[71])); + e.rain_duration4 = static_cast(atoi(row[72])); + e.snow_chance1 = static_cast(atoi(row[73])); + e.snow_chance2 = static_cast(atoi(row[74])); + e.snow_chance3 = static_cast(atoi(row[75])); + e.snow_chance4 = static_cast(atoi(row[76])); + e.snow_duration1 = static_cast(atoi(row[77])); + e.snow_duration2 = static_cast(atoi(row[78])); + e.snow_duration3 = static_cast(atoi(row[79])); + e.snow_duration4 = static_cast(atoi(row[80])); + e.gravity = strtof(row[81], nullptr); + e.type = static_cast(atoi(row[82])); + e.skylock = static_cast(atoi(row[83])); + e.fast_regen_hp = static_cast(atoi(row[84])); + e.fast_regen_mana = static_cast(atoi(row[85])); + e.fast_regen_endurance = static_cast(atoi(row[86])); + e.npc_max_aggro_dist = static_cast(atoi(row[87])); + e.max_movement_update_range = static_cast(strtoul(row[88], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[89])); + e.max_expansion = static_cast(atoi(row[90])); + e.content_flags = row[91] ? row[91] : ""; + e.content_flags_disabled = row[92] ? row[92] : ""; + e.underworld_teleport_index = static_cast(atoi(row[93])); + e.lava_damage = static_cast(atoi(row[94])); + e.min_lava_damage = static_cast(atoi(row[95])); - return entry; + return e; } return NewEntity(); @@ -606,114 +618,116 @@ public: static int UpdateOne( Database& db, - Zone zone_entry + const Zone &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); - update_values.push_back(columns[0] + " = '" + EscapeString(zone_entry.short_name) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(zone_entry.file_name) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(zone_entry.long_name) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(zone_entry.map_file_name) + "'"); - update_values.push_back(columns[5] + " = " + std::to_string(zone_entry.safe_x)); - update_values.push_back(columns[6] + " = " + std::to_string(zone_entry.safe_y)); - update_values.push_back(columns[7] + " = " + std::to_string(zone_entry.safe_z)); - update_values.push_back(columns[8] + " = " + std::to_string(zone_entry.safe_heading)); - update_values.push_back(columns[9] + " = " + std::to_string(zone_entry.graveyard_id)); - update_values.push_back(columns[10] + " = " + std::to_string(zone_entry.min_level)); - update_values.push_back(columns[11] + " = " + std::to_string(zone_entry.min_status)); - update_values.push_back(columns[12] + " = " + std::to_string(zone_entry.zoneidnumber)); - update_values.push_back(columns[13] + " = " + std::to_string(zone_entry.version)); - update_values.push_back(columns[14] + " = " + std::to_string(zone_entry.timezone)); - update_values.push_back(columns[15] + " = " + std::to_string(zone_entry.maxclients)); - update_values.push_back(columns[16] + " = " + std::to_string(zone_entry.ruleset)); - update_values.push_back(columns[17] + " = '" + EscapeString(zone_entry.note) + "'"); - update_values.push_back(columns[18] + " = " + std::to_string(zone_entry.underworld)); - update_values.push_back(columns[19] + " = " + std::to_string(zone_entry.minclip)); - update_values.push_back(columns[20] + " = " + std::to_string(zone_entry.maxclip)); - update_values.push_back(columns[21] + " = " + std::to_string(zone_entry.fog_minclip)); - update_values.push_back(columns[22] + " = " + std::to_string(zone_entry.fog_maxclip)); - update_values.push_back(columns[23] + " = " + std::to_string(zone_entry.fog_blue)); - update_values.push_back(columns[24] + " = " + std::to_string(zone_entry.fog_red)); - update_values.push_back(columns[25] + " = " + std::to_string(zone_entry.fog_green)); - update_values.push_back(columns[26] + " = " + std::to_string(zone_entry.sky)); - update_values.push_back(columns[27] + " = " + std::to_string(zone_entry.ztype)); - update_values.push_back(columns[28] + " = " + std::to_string(zone_entry.zone_exp_multiplier)); - update_values.push_back(columns[29] + " = " + std::to_string(zone_entry.walkspeed)); - update_values.push_back(columns[30] + " = " + std::to_string(zone_entry.time_type)); - update_values.push_back(columns[31] + " = " + std::to_string(zone_entry.fog_red1)); - update_values.push_back(columns[32] + " = " + std::to_string(zone_entry.fog_green1)); - update_values.push_back(columns[33] + " = " + std::to_string(zone_entry.fog_blue1)); - update_values.push_back(columns[34] + " = " + std::to_string(zone_entry.fog_minclip1)); - update_values.push_back(columns[35] + " = " + std::to_string(zone_entry.fog_maxclip1)); - update_values.push_back(columns[36] + " = " + std::to_string(zone_entry.fog_red2)); - update_values.push_back(columns[37] + " = " + std::to_string(zone_entry.fog_green2)); - update_values.push_back(columns[38] + " = " + std::to_string(zone_entry.fog_blue2)); - update_values.push_back(columns[39] + " = " + std::to_string(zone_entry.fog_minclip2)); - update_values.push_back(columns[40] + " = " + std::to_string(zone_entry.fog_maxclip2)); - update_values.push_back(columns[41] + " = " + std::to_string(zone_entry.fog_red3)); - update_values.push_back(columns[42] + " = " + std::to_string(zone_entry.fog_green3)); - update_values.push_back(columns[43] + " = " + std::to_string(zone_entry.fog_blue3)); - update_values.push_back(columns[44] + " = " + std::to_string(zone_entry.fog_minclip3)); - update_values.push_back(columns[45] + " = " + std::to_string(zone_entry.fog_maxclip3)); - update_values.push_back(columns[46] + " = " + std::to_string(zone_entry.fog_red4)); - update_values.push_back(columns[47] + " = " + std::to_string(zone_entry.fog_green4)); - update_values.push_back(columns[48] + " = " + std::to_string(zone_entry.fog_blue4)); - update_values.push_back(columns[49] + " = " + std::to_string(zone_entry.fog_minclip4)); - update_values.push_back(columns[50] + " = " + std::to_string(zone_entry.fog_maxclip4)); - update_values.push_back(columns[51] + " = " + std::to_string(zone_entry.fog_density)); - update_values.push_back(columns[52] + " = '" + EscapeString(zone_entry.flag_needed) + "'"); - update_values.push_back(columns[53] + " = " + std::to_string(zone_entry.canbind)); - update_values.push_back(columns[54] + " = " + std::to_string(zone_entry.cancombat)); - update_values.push_back(columns[55] + " = " + std::to_string(zone_entry.canlevitate)); - update_values.push_back(columns[56] + " = " + std::to_string(zone_entry.castoutdoor)); - update_values.push_back(columns[57] + " = " + std::to_string(zone_entry.hotzone)); - update_values.push_back(columns[58] + " = " + std::to_string(zone_entry.insttype)); - update_values.push_back(columns[59] + " = " + std::to_string(zone_entry.shutdowndelay)); - update_values.push_back(columns[60] + " = " + std::to_string(zone_entry.peqzone)); - update_values.push_back(columns[61] + " = " + std::to_string(zone_entry.expansion)); - update_values.push_back(columns[62] + " = " + std::to_string(zone_entry.suspendbuffs)); - update_values.push_back(columns[63] + " = " + std::to_string(zone_entry.rain_chance1)); - update_values.push_back(columns[64] + " = " + std::to_string(zone_entry.rain_chance2)); - update_values.push_back(columns[65] + " = " + std::to_string(zone_entry.rain_chance3)); - update_values.push_back(columns[66] + " = " + std::to_string(zone_entry.rain_chance4)); - update_values.push_back(columns[67] + " = " + std::to_string(zone_entry.rain_duration1)); - update_values.push_back(columns[68] + " = " + std::to_string(zone_entry.rain_duration2)); - update_values.push_back(columns[69] + " = " + std::to_string(zone_entry.rain_duration3)); - update_values.push_back(columns[70] + " = " + std::to_string(zone_entry.rain_duration4)); - update_values.push_back(columns[71] + " = " + std::to_string(zone_entry.snow_chance1)); - update_values.push_back(columns[72] + " = " + std::to_string(zone_entry.snow_chance2)); - update_values.push_back(columns[73] + " = " + std::to_string(zone_entry.snow_chance3)); - update_values.push_back(columns[74] + " = " + std::to_string(zone_entry.snow_chance4)); - update_values.push_back(columns[75] + " = " + std::to_string(zone_entry.snow_duration1)); - update_values.push_back(columns[76] + " = " + std::to_string(zone_entry.snow_duration2)); - update_values.push_back(columns[77] + " = " + std::to_string(zone_entry.snow_duration3)); - update_values.push_back(columns[78] + " = " + std::to_string(zone_entry.snow_duration4)); - update_values.push_back(columns[79] + " = " + std::to_string(zone_entry.gravity)); - update_values.push_back(columns[80] + " = " + std::to_string(zone_entry.type)); - update_values.push_back(columns[81] + " = " + std::to_string(zone_entry.skylock)); - update_values.push_back(columns[82] + " = " + std::to_string(zone_entry.fast_regen_hp)); - update_values.push_back(columns[83] + " = " + std::to_string(zone_entry.fast_regen_mana)); - update_values.push_back(columns[84] + " = " + std::to_string(zone_entry.fast_regen_endurance)); - update_values.push_back(columns[85] + " = " + std::to_string(zone_entry.npc_max_aggro_dist)); - update_values.push_back(columns[86] + " = " + std::to_string(zone_entry.max_movement_update_range)); - update_values.push_back(columns[87] + " = " + std::to_string(zone_entry.min_expansion)); - update_values.push_back(columns[88] + " = " + std::to_string(zone_entry.max_expansion)); - update_values.push_back(columns[89] + " = '" + EscapeString(zone_entry.content_flags) + "'"); - update_values.push_back(columns[90] + " = '" + EscapeString(zone_entry.content_flags_disabled) + "'"); - update_values.push_back(columns[91] + " = " + std::to_string(zone_entry.underworld_teleport_index)); - update_values.push_back(columns[92] + " = " + std::to_string(zone_entry.lava_damage)); - update_values.push_back(columns[93] + " = " + std::to_string(zone_entry.min_lava_damage)); + v.push_back(columns[0] + " = '" + Strings::Escape(e.short_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.file_name) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.long_name) + "'"); + v.push_back(columns[4] + " = '" + Strings::Escape(e.map_file_name) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.safe_x)); + v.push_back(columns[6] + " = " + std::to_string(e.safe_y)); + v.push_back(columns[7] + " = " + std::to_string(e.safe_z)); + v.push_back(columns[8] + " = " + std::to_string(e.safe_heading)); + v.push_back(columns[9] + " = " + std::to_string(e.graveyard_id)); + v.push_back(columns[10] + " = " + std::to_string(e.min_level)); + v.push_back(columns[11] + " = " + std::to_string(e.max_level)); + v.push_back(columns[12] + " = " + std::to_string(e.min_status)); + v.push_back(columns[13] + " = " + std::to_string(e.zoneidnumber)); + v.push_back(columns[14] + " = " + std::to_string(e.version)); + v.push_back(columns[15] + " = " + std::to_string(e.timezone)); + v.push_back(columns[16] + " = " + std::to_string(e.maxclients)); + v.push_back(columns[17] + " = " + std::to_string(e.ruleset)); + v.push_back(columns[18] + " = '" + Strings::Escape(e.note) + "'"); + v.push_back(columns[19] + " = " + std::to_string(e.underworld)); + v.push_back(columns[20] + " = " + std::to_string(e.minclip)); + v.push_back(columns[21] + " = " + std::to_string(e.maxclip)); + v.push_back(columns[22] + " = " + std::to_string(e.fog_minclip)); + v.push_back(columns[23] + " = " + std::to_string(e.fog_maxclip)); + v.push_back(columns[24] + " = " + std::to_string(e.fog_blue)); + v.push_back(columns[25] + " = " + std::to_string(e.fog_red)); + v.push_back(columns[26] + " = " + std::to_string(e.fog_green)); + v.push_back(columns[27] + " = " + std::to_string(e.sky)); + v.push_back(columns[28] + " = " + std::to_string(e.ztype)); + v.push_back(columns[29] + " = " + std::to_string(e.zone_exp_multiplier)); + v.push_back(columns[30] + " = " + std::to_string(e.walkspeed)); + v.push_back(columns[31] + " = " + std::to_string(e.time_type)); + v.push_back(columns[32] + " = " + std::to_string(e.fog_red1)); + v.push_back(columns[33] + " = " + std::to_string(e.fog_green1)); + v.push_back(columns[34] + " = " + std::to_string(e.fog_blue1)); + v.push_back(columns[35] + " = " + std::to_string(e.fog_minclip1)); + v.push_back(columns[36] + " = " + std::to_string(e.fog_maxclip1)); + v.push_back(columns[37] + " = " + std::to_string(e.fog_red2)); + v.push_back(columns[38] + " = " + std::to_string(e.fog_green2)); + v.push_back(columns[39] + " = " + std::to_string(e.fog_blue2)); + v.push_back(columns[40] + " = " + std::to_string(e.fog_minclip2)); + v.push_back(columns[41] + " = " + std::to_string(e.fog_maxclip2)); + v.push_back(columns[42] + " = " + std::to_string(e.fog_red3)); + v.push_back(columns[43] + " = " + std::to_string(e.fog_green3)); + v.push_back(columns[44] + " = " + std::to_string(e.fog_blue3)); + v.push_back(columns[45] + " = " + std::to_string(e.fog_minclip3)); + v.push_back(columns[46] + " = " + std::to_string(e.fog_maxclip3)); + v.push_back(columns[47] + " = " + std::to_string(e.fog_red4)); + v.push_back(columns[48] + " = " + std::to_string(e.fog_green4)); + v.push_back(columns[49] + " = " + std::to_string(e.fog_blue4)); + v.push_back(columns[50] + " = " + std::to_string(e.fog_minclip4)); + v.push_back(columns[51] + " = " + std::to_string(e.fog_maxclip4)); + v.push_back(columns[52] + " = " + std::to_string(e.fog_density)); + v.push_back(columns[53] + " = '" + Strings::Escape(e.flag_needed) + "'"); + v.push_back(columns[54] + " = " + std::to_string(e.canbind)); + v.push_back(columns[55] + " = " + std::to_string(e.cancombat)); + v.push_back(columns[56] + " = " + std::to_string(e.canlevitate)); + v.push_back(columns[57] + " = " + std::to_string(e.castoutdoor)); + v.push_back(columns[58] + " = " + std::to_string(e.hotzone)); + v.push_back(columns[59] + " = " + std::to_string(e.insttype)); + v.push_back(columns[60] + " = " + std::to_string(e.shutdowndelay)); + v.push_back(columns[61] + " = " + std::to_string(e.peqzone)); + v.push_back(columns[62] + " = " + std::to_string(e.expansion)); + v.push_back(columns[63] + " = " + std::to_string(e.bypass_expansion_check)); + v.push_back(columns[64] + " = " + std::to_string(e.suspendbuffs)); + v.push_back(columns[65] + " = " + std::to_string(e.rain_chance1)); + v.push_back(columns[66] + " = " + std::to_string(e.rain_chance2)); + v.push_back(columns[67] + " = " + std::to_string(e.rain_chance3)); + v.push_back(columns[68] + " = " + std::to_string(e.rain_chance4)); + v.push_back(columns[69] + " = " + std::to_string(e.rain_duration1)); + v.push_back(columns[70] + " = " + std::to_string(e.rain_duration2)); + v.push_back(columns[71] + " = " + std::to_string(e.rain_duration3)); + v.push_back(columns[72] + " = " + std::to_string(e.rain_duration4)); + v.push_back(columns[73] + " = " + std::to_string(e.snow_chance1)); + v.push_back(columns[74] + " = " + std::to_string(e.snow_chance2)); + v.push_back(columns[75] + " = " + std::to_string(e.snow_chance3)); + v.push_back(columns[76] + " = " + std::to_string(e.snow_chance4)); + v.push_back(columns[77] + " = " + std::to_string(e.snow_duration1)); + v.push_back(columns[78] + " = " + std::to_string(e.snow_duration2)); + v.push_back(columns[79] + " = " + std::to_string(e.snow_duration3)); + v.push_back(columns[80] + " = " + std::to_string(e.snow_duration4)); + v.push_back(columns[81] + " = " + std::to_string(e.gravity)); + v.push_back(columns[82] + " = " + std::to_string(e.type)); + v.push_back(columns[83] + " = " + std::to_string(e.skylock)); + v.push_back(columns[84] + " = " + std::to_string(e.fast_regen_hp)); + v.push_back(columns[85] + " = " + std::to_string(e.fast_regen_mana)); + v.push_back(columns[86] + " = " + std::to_string(e.fast_regen_endurance)); + v.push_back(columns[87] + " = " + std::to_string(e.npc_max_aggro_dist)); + v.push_back(columns[88] + " = " + std::to_string(e.max_movement_update_range)); + v.push_back(columns[89] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[90] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[91] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[92] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(columns[93] + " = " + std::to_string(e.underworld_teleport_index)); + v.push_back(columns[94] + " = " + std::to_string(e.lava_damage)); + v.push_back(columns[95] + " = " + std::to_string(e.min_lava_damage)); auto results = db.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - zone_entry.id + e.id ) ); @@ -722,239 +736,243 @@ public: static Zone InsertOne( Database& db, - Zone zone_entry + Zone e ) { - std::vector insert_values; + std::vector v; - insert_values.push_back("'" + EscapeString(zone_entry.short_name) + "'"); - insert_values.push_back(std::to_string(zone_entry.id)); - insert_values.push_back("'" + EscapeString(zone_entry.file_name) + "'"); - insert_values.push_back("'" + EscapeString(zone_entry.long_name) + "'"); - insert_values.push_back("'" + EscapeString(zone_entry.map_file_name) + "'"); - insert_values.push_back(std::to_string(zone_entry.safe_x)); - insert_values.push_back(std::to_string(zone_entry.safe_y)); - insert_values.push_back(std::to_string(zone_entry.safe_z)); - insert_values.push_back(std::to_string(zone_entry.safe_heading)); - insert_values.push_back(std::to_string(zone_entry.graveyard_id)); - insert_values.push_back(std::to_string(zone_entry.min_level)); - insert_values.push_back(std::to_string(zone_entry.min_status)); - insert_values.push_back(std::to_string(zone_entry.zoneidnumber)); - insert_values.push_back(std::to_string(zone_entry.version)); - insert_values.push_back(std::to_string(zone_entry.timezone)); - insert_values.push_back(std::to_string(zone_entry.maxclients)); - insert_values.push_back(std::to_string(zone_entry.ruleset)); - insert_values.push_back("'" + EscapeString(zone_entry.note) + "'"); - insert_values.push_back(std::to_string(zone_entry.underworld)); - insert_values.push_back(std::to_string(zone_entry.minclip)); - insert_values.push_back(std::to_string(zone_entry.maxclip)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip)); - insert_values.push_back(std::to_string(zone_entry.fog_blue)); - insert_values.push_back(std::to_string(zone_entry.fog_red)); - insert_values.push_back(std::to_string(zone_entry.fog_green)); - insert_values.push_back(std::to_string(zone_entry.sky)); - insert_values.push_back(std::to_string(zone_entry.ztype)); - insert_values.push_back(std::to_string(zone_entry.zone_exp_multiplier)); - insert_values.push_back(std::to_string(zone_entry.walkspeed)); - insert_values.push_back(std::to_string(zone_entry.time_type)); - insert_values.push_back(std::to_string(zone_entry.fog_red1)); - insert_values.push_back(std::to_string(zone_entry.fog_green1)); - insert_values.push_back(std::to_string(zone_entry.fog_blue1)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip1)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip1)); - insert_values.push_back(std::to_string(zone_entry.fog_red2)); - insert_values.push_back(std::to_string(zone_entry.fog_green2)); - insert_values.push_back(std::to_string(zone_entry.fog_blue2)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip2)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip2)); - insert_values.push_back(std::to_string(zone_entry.fog_red3)); - insert_values.push_back(std::to_string(zone_entry.fog_green3)); - insert_values.push_back(std::to_string(zone_entry.fog_blue3)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip3)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip3)); - insert_values.push_back(std::to_string(zone_entry.fog_red4)); - insert_values.push_back(std::to_string(zone_entry.fog_green4)); - insert_values.push_back(std::to_string(zone_entry.fog_blue4)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip4)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip4)); - insert_values.push_back(std::to_string(zone_entry.fog_density)); - insert_values.push_back("'" + EscapeString(zone_entry.flag_needed) + "'"); - insert_values.push_back(std::to_string(zone_entry.canbind)); - insert_values.push_back(std::to_string(zone_entry.cancombat)); - insert_values.push_back(std::to_string(zone_entry.canlevitate)); - insert_values.push_back(std::to_string(zone_entry.castoutdoor)); - insert_values.push_back(std::to_string(zone_entry.hotzone)); - insert_values.push_back(std::to_string(zone_entry.insttype)); - insert_values.push_back(std::to_string(zone_entry.shutdowndelay)); - insert_values.push_back(std::to_string(zone_entry.peqzone)); - insert_values.push_back(std::to_string(zone_entry.expansion)); - insert_values.push_back(std::to_string(zone_entry.suspendbuffs)); - insert_values.push_back(std::to_string(zone_entry.rain_chance1)); - insert_values.push_back(std::to_string(zone_entry.rain_chance2)); - insert_values.push_back(std::to_string(zone_entry.rain_chance3)); - insert_values.push_back(std::to_string(zone_entry.rain_chance4)); - insert_values.push_back(std::to_string(zone_entry.rain_duration1)); - insert_values.push_back(std::to_string(zone_entry.rain_duration2)); - insert_values.push_back(std::to_string(zone_entry.rain_duration3)); - insert_values.push_back(std::to_string(zone_entry.rain_duration4)); - insert_values.push_back(std::to_string(zone_entry.snow_chance1)); - insert_values.push_back(std::to_string(zone_entry.snow_chance2)); - insert_values.push_back(std::to_string(zone_entry.snow_chance3)); - insert_values.push_back(std::to_string(zone_entry.snow_chance4)); - insert_values.push_back(std::to_string(zone_entry.snow_duration1)); - insert_values.push_back(std::to_string(zone_entry.snow_duration2)); - insert_values.push_back(std::to_string(zone_entry.snow_duration3)); - insert_values.push_back(std::to_string(zone_entry.snow_duration4)); - insert_values.push_back(std::to_string(zone_entry.gravity)); - insert_values.push_back(std::to_string(zone_entry.type)); - insert_values.push_back(std::to_string(zone_entry.skylock)); - insert_values.push_back(std::to_string(zone_entry.fast_regen_hp)); - insert_values.push_back(std::to_string(zone_entry.fast_regen_mana)); - insert_values.push_back(std::to_string(zone_entry.fast_regen_endurance)); - insert_values.push_back(std::to_string(zone_entry.npc_max_aggro_dist)); - insert_values.push_back(std::to_string(zone_entry.max_movement_update_range)); - insert_values.push_back(std::to_string(zone_entry.min_expansion)); - insert_values.push_back(std::to_string(zone_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(zone_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(zone_entry.content_flags_disabled) + "'"); - insert_values.push_back(std::to_string(zone_entry.underworld_teleport_index)); - insert_values.push_back(std::to_string(zone_entry.lava_damage)); - insert_values.push_back(std::to_string(zone_entry.min_lava_damage)); + v.push_back("'" + Strings::Escape(e.short_name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.file_name) + "'"); + v.push_back("'" + Strings::Escape(e.long_name) + "'"); + v.push_back("'" + Strings::Escape(e.map_file_name) + "'"); + v.push_back(std::to_string(e.safe_x)); + v.push_back(std::to_string(e.safe_y)); + v.push_back(std::to_string(e.safe_z)); + v.push_back(std::to_string(e.safe_heading)); + v.push_back(std::to_string(e.graveyard_id)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.min_status)); + v.push_back(std::to_string(e.zoneidnumber)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.timezone)); + v.push_back(std::to_string(e.maxclients)); + v.push_back(std::to_string(e.ruleset)); + v.push_back("'" + Strings::Escape(e.note) + "'"); + v.push_back(std::to_string(e.underworld)); + v.push_back(std::to_string(e.minclip)); + v.push_back(std::to_string(e.maxclip)); + v.push_back(std::to_string(e.fog_minclip)); + v.push_back(std::to_string(e.fog_maxclip)); + v.push_back(std::to_string(e.fog_blue)); + v.push_back(std::to_string(e.fog_red)); + v.push_back(std::to_string(e.fog_green)); + v.push_back(std::to_string(e.sky)); + v.push_back(std::to_string(e.ztype)); + v.push_back(std::to_string(e.zone_exp_multiplier)); + v.push_back(std::to_string(e.walkspeed)); + v.push_back(std::to_string(e.time_type)); + v.push_back(std::to_string(e.fog_red1)); + v.push_back(std::to_string(e.fog_green1)); + v.push_back(std::to_string(e.fog_blue1)); + v.push_back(std::to_string(e.fog_minclip1)); + v.push_back(std::to_string(e.fog_maxclip1)); + v.push_back(std::to_string(e.fog_red2)); + v.push_back(std::to_string(e.fog_green2)); + v.push_back(std::to_string(e.fog_blue2)); + v.push_back(std::to_string(e.fog_minclip2)); + v.push_back(std::to_string(e.fog_maxclip2)); + v.push_back(std::to_string(e.fog_red3)); + v.push_back(std::to_string(e.fog_green3)); + v.push_back(std::to_string(e.fog_blue3)); + v.push_back(std::to_string(e.fog_minclip3)); + v.push_back(std::to_string(e.fog_maxclip3)); + v.push_back(std::to_string(e.fog_red4)); + v.push_back(std::to_string(e.fog_green4)); + v.push_back(std::to_string(e.fog_blue4)); + v.push_back(std::to_string(e.fog_minclip4)); + v.push_back(std::to_string(e.fog_maxclip4)); + v.push_back(std::to_string(e.fog_density)); + v.push_back("'" + Strings::Escape(e.flag_needed) + "'"); + v.push_back(std::to_string(e.canbind)); + v.push_back(std::to_string(e.cancombat)); + v.push_back(std::to_string(e.canlevitate)); + v.push_back(std::to_string(e.castoutdoor)); + v.push_back(std::to_string(e.hotzone)); + v.push_back(std::to_string(e.insttype)); + v.push_back(std::to_string(e.shutdowndelay)); + v.push_back(std::to_string(e.peqzone)); + v.push_back(std::to_string(e.expansion)); + v.push_back(std::to_string(e.bypass_expansion_check)); + v.push_back(std::to_string(e.suspendbuffs)); + v.push_back(std::to_string(e.rain_chance1)); + v.push_back(std::to_string(e.rain_chance2)); + v.push_back(std::to_string(e.rain_chance3)); + v.push_back(std::to_string(e.rain_chance4)); + v.push_back(std::to_string(e.rain_duration1)); + v.push_back(std::to_string(e.rain_duration2)); + v.push_back(std::to_string(e.rain_duration3)); + v.push_back(std::to_string(e.rain_duration4)); + v.push_back(std::to_string(e.snow_chance1)); + v.push_back(std::to_string(e.snow_chance2)); + v.push_back(std::to_string(e.snow_chance3)); + v.push_back(std::to_string(e.snow_chance4)); + v.push_back(std::to_string(e.snow_duration1)); + v.push_back(std::to_string(e.snow_duration2)); + v.push_back(std::to_string(e.snow_duration3)); + v.push_back(std::to_string(e.snow_duration4)); + v.push_back(std::to_string(e.gravity)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.skylock)); + v.push_back(std::to_string(e.fast_regen_hp)); + v.push_back(std::to_string(e.fast_regen_mana)); + v.push_back(std::to_string(e.fast_regen_endurance)); + v.push_back(std::to_string(e.npc_max_aggro_dist)); + v.push_back(std::to_string(e.max_movement_update_range)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.underworld_teleport_index)); + v.push_back(std::to_string(e.lava_damage)); + v.push_back(std::to_string(e.min_lava_damage)); auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - zone_entry.id = results.LastInsertedID(); - return zone_entry; + e.id = results.LastInsertedID(); + return e; } - zone_entry = NewEntity(); + e = NewEntity(); - return zone_entry; + return e; } static int InsertMany( Database& db, - std::vector zone_entries + const std::vector &entries ) { std::vector insert_chunks; - for (auto &zone_entry: zone_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; - insert_values.push_back("'" + EscapeString(zone_entry.short_name) + "'"); - insert_values.push_back(std::to_string(zone_entry.id)); - insert_values.push_back("'" + EscapeString(zone_entry.file_name) + "'"); - insert_values.push_back("'" + EscapeString(zone_entry.long_name) + "'"); - insert_values.push_back("'" + EscapeString(zone_entry.map_file_name) + "'"); - insert_values.push_back(std::to_string(zone_entry.safe_x)); - insert_values.push_back(std::to_string(zone_entry.safe_y)); - insert_values.push_back(std::to_string(zone_entry.safe_z)); - insert_values.push_back(std::to_string(zone_entry.safe_heading)); - insert_values.push_back(std::to_string(zone_entry.graveyard_id)); - insert_values.push_back(std::to_string(zone_entry.min_level)); - insert_values.push_back(std::to_string(zone_entry.min_status)); - insert_values.push_back(std::to_string(zone_entry.zoneidnumber)); - insert_values.push_back(std::to_string(zone_entry.version)); - insert_values.push_back(std::to_string(zone_entry.timezone)); - insert_values.push_back(std::to_string(zone_entry.maxclients)); - insert_values.push_back(std::to_string(zone_entry.ruleset)); - insert_values.push_back("'" + EscapeString(zone_entry.note) + "'"); - insert_values.push_back(std::to_string(zone_entry.underworld)); - insert_values.push_back(std::to_string(zone_entry.minclip)); - insert_values.push_back(std::to_string(zone_entry.maxclip)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip)); - insert_values.push_back(std::to_string(zone_entry.fog_blue)); - insert_values.push_back(std::to_string(zone_entry.fog_red)); - insert_values.push_back(std::to_string(zone_entry.fog_green)); - insert_values.push_back(std::to_string(zone_entry.sky)); - insert_values.push_back(std::to_string(zone_entry.ztype)); - insert_values.push_back(std::to_string(zone_entry.zone_exp_multiplier)); - insert_values.push_back(std::to_string(zone_entry.walkspeed)); - insert_values.push_back(std::to_string(zone_entry.time_type)); - insert_values.push_back(std::to_string(zone_entry.fog_red1)); - insert_values.push_back(std::to_string(zone_entry.fog_green1)); - insert_values.push_back(std::to_string(zone_entry.fog_blue1)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip1)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip1)); - insert_values.push_back(std::to_string(zone_entry.fog_red2)); - insert_values.push_back(std::to_string(zone_entry.fog_green2)); - insert_values.push_back(std::to_string(zone_entry.fog_blue2)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip2)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip2)); - insert_values.push_back(std::to_string(zone_entry.fog_red3)); - insert_values.push_back(std::to_string(zone_entry.fog_green3)); - insert_values.push_back(std::to_string(zone_entry.fog_blue3)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip3)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip3)); - insert_values.push_back(std::to_string(zone_entry.fog_red4)); - insert_values.push_back(std::to_string(zone_entry.fog_green4)); - insert_values.push_back(std::to_string(zone_entry.fog_blue4)); - insert_values.push_back(std::to_string(zone_entry.fog_minclip4)); - insert_values.push_back(std::to_string(zone_entry.fog_maxclip4)); - insert_values.push_back(std::to_string(zone_entry.fog_density)); - insert_values.push_back("'" + EscapeString(zone_entry.flag_needed) + "'"); - insert_values.push_back(std::to_string(zone_entry.canbind)); - insert_values.push_back(std::to_string(zone_entry.cancombat)); - insert_values.push_back(std::to_string(zone_entry.canlevitate)); - insert_values.push_back(std::to_string(zone_entry.castoutdoor)); - insert_values.push_back(std::to_string(zone_entry.hotzone)); - insert_values.push_back(std::to_string(zone_entry.insttype)); - insert_values.push_back(std::to_string(zone_entry.shutdowndelay)); - insert_values.push_back(std::to_string(zone_entry.peqzone)); - insert_values.push_back(std::to_string(zone_entry.expansion)); - insert_values.push_back(std::to_string(zone_entry.suspendbuffs)); - insert_values.push_back(std::to_string(zone_entry.rain_chance1)); - insert_values.push_back(std::to_string(zone_entry.rain_chance2)); - insert_values.push_back(std::to_string(zone_entry.rain_chance3)); - insert_values.push_back(std::to_string(zone_entry.rain_chance4)); - insert_values.push_back(std::to_string(zone_entry.rain_duration1)); - insert_values.push_back(std::to_string(zone_entry.rain_duration2)); - insert_values.push_back(std::to_string(zone_entry.rain_duration3)); - insert_values.push_back(std::to_string(zone_entry.rain_duration4)); - insert_values.push_back(std::to_string(zone_entry.snow_chance1)); - insert_values.push_back(std::to_string(zone_entry.snow_chance2)); - insert_values.push_back(std::to_string(zone_entry.snow_chance3)); - insert_values.push_back(std::to_string(zone_entry.snow_chance4)); - insert_values.push_back(std::to_string(zone_entry.snow_duration1)); - insert_values.push_back(std::to_string(zone_entry.snow_duration2)); - insert_values.push_back(std::to_string(zone_entry.snow_duration3)); - insert_values.push_back(std::to_string(zone_entry.snow_duration4)); - insert_values.push_back(std::to_string(zone_entry.gravity)); - insert_values.push_back(std::to_string(zone_entry.type)); - insert_values.push_back(std::to_string(zone_entry.skylock)); - insert_values.push_back(std::to_string(zone_entry.fast_regen_hp)); - insert_values.push_back(std::to_string(zone_entry.fast_regen_mana)); - insert_values.push_back(std::to_string(zone_entry.fast_regen_endurance)); - insert_values.push_back(std::to_string(zone_entry.npc_max_aggro_dist)); - insert_values.push_back(std::to_string(zone_entry.max_movement_update_range)); - insert_values.push_back(std::to_string(zone_entry.min_expansion)); - insert_values.push_back(std::to_string(zone_entry.max_expansion)); - insert_values.push_back("'" + EscapeString(zone_entry.content_flags) + "'"); - insert_values.push_back("'" + EscapeString(zone_entry.content_flags_disabled) + "'"); - insert_values.push_back(std::to_string(zone_entry.underworld_teleport_index)); - insert_values.push_back(std::to_string(zone_entry.lava_damage)); - insert_values.push_back(std::to_string(zone_entry.min_lava_damage)); + v.push_back("'" + Strings::Escape(e.short_name) + "'"); + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.file_name) + "'"); + v.push_back("'" + Strings::Escape(e.long_name) + "'"); + v.push_back("'" + Strings::Escape(e.map_file_name) + "'"); + v.push_back(std::to_string(e.safe_x)); + v.push_back(std::to_string(e.safe_y)); + v.push_back(std::to_string(e.safe_z)); + v.push_back(std::to_string(e.safe_heading)); + v.push_back(std::to_string(e.graveyard_id)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); + v.push_back(std::to_string(e.min_status)); + v.push_back(std::to_string(e.zoneidnumber)); + v.push_back(std::to_string(e.version)); + v.push_back(std::to_string(e.timezone)); + v.push_back(std::to_string(e.maxclients)); + v.push_back(std::to_string(e.ruleset)); + v.push_back("'" + Strings::Escape(e.note) + "'"); + v.push_back(std::to_string(e.underworld)); + v.push_back(std::to_string(e.minclip)); + v.push_back(std::to_string(e.maxclip)); + v.push_back(std::to_string(e.fog_minclip)); + v.push_back(std::to_string(e.fog_maxclip)); + v.push_back(std::to_string(e.fog_blue)); + v.push_back(std::to_string(e.fog_red)); + v.push_back(std::to_string(e.fog_green)); + v.push_back(std::to_string(e.sky)); + v.push_back(std::to_string(e.ztype)); + v.push_back(std::to_string(e.zone_exp_multiplier)); + v.push_back(std::to_string(e.walkspeed)); + v.push_back(std::to_string(e.time_type)); + v.push_back(std::to_string(e.fog_red1)); + v.push_back(std::to_string(e.fog_green1)); + v.push_back(std::to_string(e.fog_blue1)); + v.push_back(std::to_string(e.fog_minclip1)); + v.push_back(std::to_string(e.fog_maxclip1)); + v.push_back(std::to_string(e.fog_red2)); + v.push_back(std::to_string(e.fog_green2)); + v.push_back(std::to_string(e.fog_blue2)); + v.push_back(std::to_string(e.fog_minclip2)); + v.push_back(std::to_string(e.fog_maxclip2)); + v.push_back(std::to_string(e.fog_red3)); + v.push_back(std::to_string(e.fog_green3)); + v.push_back(std::to_string(e.fog_blue3)); + v.push_back(std::to_string(e.fog_minclip3)); + v.push_back(std::to_string(e.fog_maxclip3)); + v.push_back(std::to_string(e.fog_red4)); + v.push_back(std::to_string(e.fog_green4)); + v.push_back(std::to_string(e.fog_blue4)); + v.push_back(std::to_string(e.fog_minclip4)); + v.push_back(std::to_string(e.fog_maxclip4)); + v.push_back(std::to_string(e.fog_density)); + v.push_back("'" + Strings::Escape(e.flag_needed) + "'"); + v.push_back(std::to_string(e.canbind)); + v.push_back(std::to_string(e.cancombat)); + v.push_back(std::to_string(e.canlevitate)); + v.push_back(std::to_string(e.castoutdoor)); + v.push_back(std::to_string(e.hotzone)); + v.push_back(std::to_string(e.insttype)); + v.push_back(std::to_string(e.shutdowndelay)); + v.push_back(std::to_string(e.peqzone)); + v.push_back(std::to_string(e.expansion)); + v.push_back(std::to_string(e.bypass_expansion_check)); + v.push_back(std::to_string(e.suspendbuffs)); + v.push_back(std::to_string(e.rain_chance1)); + v.push_back(std::to_string(e.rain_chance2)); + v.push_back(std::to_string(e.rain_chance3)); + v.push_back(std::to_string(e.rain_chance4)); + v.push_back(std::to_string(e.rain_duration1)); + v.push_back(std::to_string(e.rain_duration2)); + v.push_back(std::to_string(e.rain_duration3)); + v.push_back(std::to_string(e.rain_duration4)); + v.push_back(std::to_string(e.snow_chance1)); + v.push_back(std::to_string(e.snow_chance2)); + v.push_back(std::to_string(e.snow_chance3)); + v.push_back(std::to_string(e.snow_chance4)); + v.push_back(std::to_string(e.snow_duration1)); + v.push_back(std::to_string(e.snow_duration2)); + v.push_back(std::to_string(e.snow_duration3)); + v.push_back(std::to_string(e.snow_duration4)); + v.push_back(std::to_string(e.gravity)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.skylock)); + v.push_back(std::to_string(e.fast_regen_hp)); + v.push_back(std::to_string(e.fast_regen_mana)); + v.push_back(std::to_string(e.fast_regen_endurance)); + v.push_back(std::to_string(e.npc_max_aggro_dist)); + v.push_back(std::to_string(e.max_movement_update_range)); + v.push_back(std::to_string(e.min_expansion)); + v.push_back(std::to_string(e.max_expansion)); + v.push_back("'" + Strings::Escape(e.content_flags) + "'"); + v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(std::to_string(e.underworld_teleport_index)); + v.push_back(std::to_string(e.lava_damage)); + v.push_back(std::to_string(e.min_lava_damage)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -975,110 +993,112 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Zone entry{}; + Zone e{}; - entry.short_name = row[0] ? row[0] : ""; - entry.id = atoi(row[1]); - entry.file_name = row[2] ? row[2] : ""; - entry.long_name = row[3] ? row[3] : ""; - entry.map_file_name = row[4] ? row[4] : ""; - entry.safe_x = static_cast(atof(row[5])); - entry.safe_y = static_cast(atof(row[6])); - entry.safe_z = static_cast(atof(row[7])); - entry.safe_heading = static_cast(atof(row[8])); - entry.graveyard_id = static_cast(atof(row[9])); - entry.min_level = atoi(row[10]); - entry.min_status = atoi(row[11]); - entry.zoneidnumber = atoi(row[12]); - entry.version = atoi(row[13]); - entry.timezone = atoi(row[14]); - entry.maxclients = atoi(row[15]); - entry.ruleset = atoi(row[16]); - entry.note = row[17] ? row[17] : ""; - entry.underworld = static_cast(atof(row[18])); - entry.minclip = static_cast(atof(row[19])); - entry.maxclip = static_cast(atof(row[20])); - entry.fog_minclip = static_cast(atof(row[21])); - entry.fog_maxclip = static_cast(atof(row[22])); - entry.fog_blue = atoi(row[23]); - entry.fog_red = atoi(row[24]); - entry.fog_green = atoi(row[25]); - entry.sky = atoi(row[26]); - entry.ztype = atoi(row[27]); - entry.zone_exp_multiplier = static_cast(atof(row[28])); - entry.walkspeed = static_cast(atof(row[29])); - entry.time_type = atoi(row[30]); - entry.fog_red1 = atoi(row[31]); - entry.fog_green1 = atoi(row[32]); - entry.fog_blue1 = atoi(row[33]); - entry.fog_minclip1 = static_cast(atof(row[34])); - entry.fog_maxclip1 = static_cast(atof(row[35])); - entry.fog_red2 = atoi(row[36]); - entry.fog_green2 = atoi(row[37]); - entry.fog_blue2 = atoi(row[38]); - entry.fog_minclip2 = static_cast(atof(row[39])); - entry.fog_maxclip2 = static_cast(atof(row[40])); - entry.fog_red3 = atoi(row[41]); - entry.fog_green3 = atoi(row[42]); - entry.fog_blue3 = atoi(row[43]); - entry.fog_minclip3 = static_cast(atof(row[44])); - entry.fog_maxclip3 = static_cast(atof(row[45])); - entry.fog_red4 = atoi(row[46]); - entry.fog_green4 = atoi(row[47]); - entry.fog_blue4 = atoi(row[48]); - entry.fog_minclip4 = static_cast(atof(row[49])); - entry.fog_maxclip4 = static_cast(atof(row[50])); - entry.fog_density = static_cast(atof(row[51])); - entry.flag_needed = row[52] ? row[52] : ""; - entry.canbind = atoi(row[53]); - entry.cancombat = atoi(row[54]); - entry.canlevitate = atoi(row[55]); - entry.castoutdoor = atoi(row[56]); - entry.hotzone = atoi(row[57]); - entry.insttype = atoi(row[58]); - entry.shutdowndelay = strtoll(row[59], nullptr, 10); - entry.peqzone = atoi(row[60]); - entry.expansion = atoi(row[61]); - entry.suspendbuffs = atoi(row[62]); - entry.rain_chance1 = atoi(row[63]); - entry.rain_chance2 = atoi(row[64]); - entry.rain_chance3 = atoi(row[65]); - entry.rain_chance4 = atoi(row[66]); - entry.rain_duration1 = atoi(row[67]); - entry.rain_duration2 = atoi(row[68]); - entry.rain_duration3 = atoi(row[69]); - entry.rain_duration4 = atoi(row[70]); - entry.snow_chance1 = atoi(row[71]); - entry.snow_chance2 = atoi(row[72]); - entry.snow_chance3 = atoi(row[73]); - entry.snow_chance4 = atoi(row[74]); - entry.snow_duration1 = atoi(row[75]); - entry.snow_duration2 = atoi(row[76]); - entry.snow_duration3 = atoi(row[77]); - entry.snow_duration4 = atoi(row[78]); - entry.gravity = static_cast(atof(row[79])); - entry.type = atoi(row[80]); - entry.skylock = atoi(row[81]); - entry.fast_regen_hp = atoi(row[82]); - entry.fast_regen_mana = atoi(row[83]); - entry.fast_regen_endurance = atoi(row[84]); - entry.npc_max_aggro_dist = atoi(row[85]); - entry.max_movement_update_range = atoi(row[86]); - entry.min_expansion = atoi(row[87]); - entry.max_expansion = atoi(row[88]); - entry.content_flags = row[89] ? row[89] : ""; - entry.content_flags_disabled = row[90] ? row[90] : ""; - entry.underworld_teleport_index = atoi(row[91]); - entry.lava_damage = atoi(row[92]); - entry.min_lava_damage = atoi(row[93]); + e.short_name = row[0] ? row[0] : ""; + e.id = static_cast(atoi(row[1])); + e.file_name = row[2] ? row[2] : ""; + e.long_name = row[3] ? row[3] : ""; + e.map_file_name = row[4] ? row[4] : ""; + e.safe_x = strtof(row[5], nullptr); + e.safe_y = strtof(row[6], nullptr); + e.safe_z = strtof(row[7], nullptr); + e.safe_heading = strtof(row[8], nullptr); + e.graveyard_id = strtof(row[9], nullptr); + e.min_level = static_cast(strtoul(row[10], nullptr, 10)); + e.max_level = static_cast(strtoul(row[11], nullptr, 10)); + e.min_status = static_cast(strtoul(row[12], nullptr, 10)); + e.zoneidnumber = static_cast(atoi(row[13])); + e.version = static_cast(strtoul(row[14], nullptr, 10)); + e.timezone = static_cast(atoi(row[15])); + e.maxclients = static_cast(atoi(row[16])); + e.ruleset = static_cast(strtoul(row[17], nullptr, 10)); + e.note = row[18] ? row[18] : ""; + e.underworld = strtof(row[19], nullptr); + e.minclip = strtof(row[20], nullptr); + e.maxclip = strtof(row[21], nullptr); + e.fog_minclip = strtof(row[22], nullptr); + e.fog_maxclip = strtof(row[23], nullptr); + e.fog_blue = static_cast(strtoul(row[24], nullptr, 10)); + e.fog_red = static_cast(strtoul(row[25], nullptr, 10)); + e.fog_green = static_cast(strtoul(row[26], nullptr, 10)); + e.sky = static_cast(strtoul(row[27], nullptr, 10)); + e.ztype = static_cast(strtoul(row[28], nullptr, 10)); + e.zone_exp_multiplier = strtof(row[29], nullptr); + e.walkspeed = strtof(row[30], nullptr); + e.time_type = static_cast(strtoul(row[31], nullptr, 10)); + e.fog_red1 = static_cast(strtoul(row[32], nullptr, 10)); + e.fog_green1 = static_cast(strtoul(row[33], nullptr, 10)); + e.fog_blue1 = static_cast(strtoul(row[34], nullptr, 10)); + e.fog_minclip1 = strtof(row[35], nullptr); + e.fog_maxclip1 = strtof(row[36], nullptr); + e.fog_red2 = static_cast(strtoul(row[37], nullptr, 10)); + e.fog_green2 = static_cast(strtoul(row[38], nullptr, 10)); + e.fog_blue2 = static_cast(strtoul(row[39], nullptr, 10)); + e.fog_minclip2 = strtof(row[40], nullptr); + e.fog_maxclip2 = strtof(row[41], nullptr); + e.fog_red3 = static_cast(strtoul(row[42], nullptr, 10)); + e.fog_green3 = static_cast(strtoul(row[43], nullptr, 10)); + e.fog_blue3 = static_cast(strtoul(row[44], nullptr, 10)); + e.fog_minclip3 = strtof(row[45], nullptr); + e.fog_maxclip3 = strtof(row[46], nullptr); + e.fog_red4 = static_cast(strtoul(row[47], nullptr, 10)); + e.fog_green4 = static_cast(strtoul(row[48], nullptr, 10)); + e.fog_blue4 = static_cast(strtoul(row[49], nullptr, 10)); + e.fog_minclip4 = strtof(row[50], nullptr); + e.fog_maxclip4 = strtof(row[51], nullptr); + e.fog_density = strtof(row[52], nullptr); + e.flag_needed = row[53] ? row[53] : ""; + e.canbind = static_cast(atoi(row[54])); + e.cancombat = static_cast(atoi(row[55])); + e.canlevitate = static_cast(atoi(row[56])); + e.castoutdoor = static_cast(atoi(row[57])); + e.hotzone = static_cast(strtoul(row[58], nullptr, 10)); + e.insttype = static_cast(strtoul(row[59], nullptr, 10)); + e.shutdowndelay = strtoull(row[60], nullptr, 10); + e.peqzone = static_cast(atoi(row[61])); + e.expansion = static_cast(atoi(row[62])); + e.bypass_expansion_check = static_cast(atoi(row[63])); + e.suspendbuffs = static_cast(strtoul(row[64], nullptr, 10)); + e.rain_chance1 = static_cast(atoi(row[65])); + e.rain_chance2 = static_cast(atoi(row[66])); + e.rain_chance3 = static_cast(atoi(row[67])); + e.rain_chance4 = static_cast(atoi(row[68])); + e.rain_duration1 = static_cast(atoi(row[69])); + e.rain_duration2 = static_cast(atoi(row[70])); + e.rain_duration3 = static_cast(atoi(row[71])); + e.rain_duration4 = static_cast(atoi(row[72])); + e.snow_chance1 = static_cast(atoi(row[73])); + e.snow_chance2 = static_cast(atoi(row[74])); + e.snow_chance3 = static_cast(atoi(row[75])); + e.snow_chance4 = static_cast(atoi(row[76])); + e.snow_duration1 = static_cast(atoi(row[77])); + e.snow_duration2 = static_cast(atoi(row[78])); + e.snow_duration3 = static_cast(atoi(row[79])); + e.snow_duration4 = static_cast(atoi(row[80])); + e.gravity = strtof(row[81], nullptr); + e.type = static_cast(atoi(row[82])); + e.skylock = static_cast(atoi(row[83])); + e.fast_regen_hp = static_cast(atoi(row[84])); + e.fast_regen_mana = static_cast(atoi(row[85])); + e.fast_regen_endurance = static_cast(atoi(row[86])); + e.npc_max_aggro_dist = static_cast(atoi(row[87])); + e.max_movement_update_range = static_cast(strtoul(row[88], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[89])); + e.max_expansion = static_cast(atoi(row[90])); + e.content_flags = row[91] ? row[91] : ""; + e.content_flags_disabled = row[92] ? row[92] : ""; + e.underworld_teleport_index = static_cast(atoi(row[93])); + e.lava_damage = static_cast(atoi(row[94])); + e.min_lava_damage = static_cast(atoi(row[95])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector GetWhere(Database& db, std::string where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { std::vector all_entries; @@ -1093,110 +1113,112 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Zone entry{}; + Zone e{}; - entry.short_name = row[0] ? row[0] : ""; - entry.id = atoi(row[1]); - entry.file_name = row[2] ? row[2] : ""; - entry.long_name = row[3] ? row[3] : ""; - entry.map_file_name = row[4] ? row[4] : ""; - entry.safe_x = static_cast(atof(row[5])); - entry.safe_y = static_cast(atof(row[6])); - entry.safe_z = static_cast(atof(row[7])); - entry.safe_heading = static_cast(atof(row[8])); - entry.graveyard_id = static_cast(atof(row[9])); - entry.min_level = atoi(row[10]); - entry.min_status = atoi(row[11]); - entry.zoneidnumber = atoi(row[12]); - entry.version = atoi(row[13]); - entry.timezone = atoi(row[14]); - entry.maxclients = atoi(row[15]); - entry.ruleset = atoi(row[16]); - entry.note = row[17] ? row[17] : ""; - entry.underworld = static_cast(atof(row[18])); - entry.minclip = static_cast(atof(row[19])); - entry.maxclip = static_cast(atof(row[20])); - entry.fog_minclip = static_cast(atof(row[21])); - entry.fog_maxclip = static_cast(atof(row[22])); - entry.fog_blue = atoi(row[23]); - entry.fog_red = atoi(row[24]); - entry.fog_green = atoi(row[25]); - entry.sky = atoi(row[26]); - entry.ztype = atoi(row[27]); - entry.zone_exp_multiplier = static_cast(atof(row[28])); - entry.walkspeed = static_cast(atof(row[29])); - entry.time_type = atoi(row[30]); - entry.fog_red1 = atoi(row[31]); - entry.fog_green1 = atoi(row[32]); - entry.fog_blue1 = atoi(row[33]); - entry.fog_minclip1 = static_cast(atof(row[34])); - entry.fog_maxclip1 = static_cast(atof(row[35])); - entry.fog_red2 = atoi(row[36]); - entry.fog_green2 = atoi(row[37]); - entry.fog_blue2 = atoi(row[38]); - entry.fog_minclip2 = static_cast(atof(row[39])); - entry.fog_maxclip2 = static_cast(atof(row[40])); - entry.fog_red3 = atoi(row[41]); - entry.fog_green3 = atoi(row[42]); - entry.fog_blue3 = atoi(row[43]); - entry.fog_minclip3 = static_cast(atof(row[44])); - entry.fog_maxclip3 = static_cast(atof(row[45])); - entry.fog_red4 = atoi(row[46]); - entry.fog_green4 = atoi(row[47]); - entry.fog_blue4 = atoi(row[48]); - entry.fog_minclip4 = static_cast(atof(row[49])); - entry.fog_maxclip4 = static_cast(atof(row[50])); - entry.fog_density = static_cast(atof(row[51])); - entry.flag_needed = row[52] ? row[52] : ""; - entry.canbind = atoi(row[53]); - entry.cancombat = atoi(row[54]); - entry.canlevitate = atoi(row[55]); - entry.castoutdoor = atoi(row[56]); - entry.hotzone = atoi(row[57]); - entry.insttype = atoi(row[58]); - entry.shutdowndelay = strtoll(row[59], nullptr, 10); - entry.peqzone = atoi(row[60]); - entry.expansion = atoi(row[61]); - entry.suspendbuffs = atoi(row[62]); - entry.rain_chance1 = atoi(row[63]); - entry.rain_chance2 = atoi(row[64]); - entry.rain_chance3 = atoi(row[65]); - entry.rain_chance4 = atoi(row[66]); - entry.rain_duration1 = atoi(row[67]); - entry.rain_duration2 = atoi(row[68]); - entry.rain_duration3 = atoi(row[69]); - entry.rain_duration4 = atoi(row[70]); - entry.snow_chance1 = atoi(row[71]); - entry.snow_chance2 = atoi(row[72]); - entry.snow_chance3 = atoi(row[73]); - entry.snow_chance4 = atoi(row[74]); - entry.snow_duration1 = atoi(row[75]); - entry.snow_duration2 = atoi(row[76]); - entry.snow_duration3 = atoi(row[77]); - entry.snow_duration4 = atoi(row[78]); - entry.gravity = static_cast(atof(row[79])); - entry.type = atoi(row[80]); - entry.skylock = atoi(row[81]); - entry.fast_regen_hp = atoi(row[82]); - entry.fast_regen_mana = atoi(row[83]); - entry.fast_regen_endurance = atoi(row[84]); - entry.npc_max_aggro_dist = atoi(row[85]); - entry.max_movement_update_range = atoi(row[86]); - entry.min_expansion = atoi(row[87]); - entry.max_expansion = atoi(row[88]); - entry.content_flags = row[89] ? row[89] : ""; - entry.content_flags_disabled = row[90] ? row[90] : ""; - entry.underworld_teleport_index = atoi(row[91]); - entry.lava_damage = atoi(row[92]); - entry.min_lava_damage = atoi(row[93]); + e.short_name = row[0] ? row[0] : ""; + e.id = static_cast(atoi(row[1])); + e.file_name = row[2] ? row[2] : ""; + e.long_name = row[3] ? row[3] : ""; + e.map_file_name = row[4] ? row[4] : ""; + e.safe_x = strtof(row[5], nullptr); + e.safe_y = strtof(row[6], nullptr); + e.safe_z = strtof(row[7], nullptr); + e.safe_heading = strtof(row[8], nullptr); + e.graveyard_id = strtof(row[9], nullptr); + e.min_level = static_cast(strtoul(row[10], nullptr, 10)); + e.max_level = static_cast(strtoul(row[11], nullptr, 10)); + e.min_status = static_cast(strtoul(row[12], nullptr, 10)); + e.zoneidnumber = static_cast(atoi(row[13])); + e.version = static_cast(strtoul(row[14], nullptr, 10)); + e.timezone = static_cast(atoi(row[15])); + e.maxclients = static_cast(atoi(row[16])); + e.ruleset = static_cast(strtoul(row[17], nullptr, 10)); + e.note = row[18] ? row[18] : ""; + e.underworld = strtof(row[19], nullptr); + e.minclip = strtof(row[20], nullptr); + e.maxclip = strtof(row[21], nullptr); + e.fog_minclip = strtof(row[22], nullptr); + e.fog_maxclip = strtof(row[23], nullptr); + e.fog_blue = static_cast(strtoul(row[24], nullptr, 10)); + e.fog_red = static_cast(strtoul(row[25], nullptr, 10)); + e.fog_green = static_cast(strtoul(row[26], nullptr, 10)); + e.sky = static_cast(strtoul(row[27], nullptr, 10)); + e.ztype = static_cast(strtoul(row[28], nullptr, 10)); + e.zone_exp_multiplier = strtof(row[29], nullptr); + e.walkspeed = strtof(row[30], nullptr); + e.time_type = static_cast(strtoul(row[31], nullptr, 10)); + e.fog_red1 = static_cast(strtoul(row[32], nullptr, 10)); + e.fog_green1 = static_cast(strtoul(row[33], nullptr, 10)); + e.fog_blue1 = static_cast(strtoul(row[34], nullptr, 10)); + e.fog_minclip1 = strtof(row[35], nullptr); + e.fog_maxclip1 = strtof(row[36], nullptr); + e.fog_red2 = static_cast(strtoul(row[37], nullptr, 10)); + e.fog_green2 = static_cast(strtoul(row[38], nullptr, 10)); + e.fog_blue2 = static_cast(strtoul(row[39], nullptr, 10)); + e.fog_minclip2 = strtof(row[40], nullptr); + e.fog_maxclip2 = strtof(row[41], nullptr); + e.fog_red3 = static_cast(strtoul(row[42], nullptr, 10)); + e.fog_green3 = static_cast(strtoul(row[43], nullptr, 10)); + e.fog_blue3 = static_cast(strtoul(row[44], nullptr, 10)); + e.fog_minclip3 = strtof(row[45], nullptr); + e.fog_maxclip3 = strtof(row[46], nullptr); + e.fog_red4 = static_cast(strtoul(row[47], nullptr, 10)); + e.fog_green4 = static_cast(strtoul(row[48], nullptr, 10)); + e.fog_blue4 = static_cast(strtoul(row[49], nullptr, 10)); + e.fog_minclip4 = strtof(row[50], nullptr); + e.fog_maxclip4 = strtof(row[51], nullptr); + e.fog_density = strtof(row[52], nullptr); + e.flag_needed = row[53] ? row[53] : ""; + e.canbind = static_cast(atoi(row[54])); + e.cancombat = static_cast(atoi(row[55])); + e.canlevitate = static_cast(atoi(row[56])); + e.castoutdoor = static_cast(atoi(row[57])); + e.hotzone = static_cast(strtoul(row[58], nullptr, 10)); + e.insttype = static_cast(strtoul(row[59], nullptr, 10)); + e.shutdowndelay = strtoull(row[60], nullptr, 10); + e.peqzone = static_cast(atoi(row[61])); + e.expansion = static_cast(atoi(row[62])); + e.bypass_expansion_check = static_cast(atoi(row[63])); + e.suspendbuffs = static_cast(strtoul(row[64], nullptr, 10)); + e.rain_chance1 = static_cast(atoi(row[65])); + e.rain_chance2 = static_cast(atoi(row[66])); + e.rain_chance3 = static_cast(atoi(row[67])); + e.rain_chance4 = static_cast(atoi(row[68])); + e.rain_duration1 = static_cast(atoi(row[69])); + e.rain_duration2 = static_cast(atoi(row[70])); + e.rain_duration3 = static_cast(atoi(row[71])); + e.rain_duration4 = static_cast(atoi(row[72])); + e.snow_chance1 = static_cast(atoi(row[73])); + e.snow_chance2 = static_cast(atoi(row[74])); + e.snow_chance3 = static_cast(atoi(row[75])); + e.snow_chance4 = static_cast(atoi(row[76])); + e.snow_duration1 = static_cast(atoi(row[77])); + e.snow_duration2 = static_cast(atoi(row[78])); + e.snow_duration3 = static_cast(atoi(row[79])); + e.snow_duration4 = static_cast(atoi(row[80])); + e.gravity = strtof(row[81], nullptr); + e.type = static_cast(atoi(row[82])); + e.skylock = static_cast(atoi(row[83])); + e.fast_regen_hp = static_cast(atoi(row[84])); + e.fast_regen_mana = static_cast(atoi(row[85])); + e.fast_regen_endurance = static_cast(atoi(row[86])); + e.npc_max_aggro_dist = static_cast(atoi(row[87])); + e.max_movement_update_range = static_cast(strtoul(row[88], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[89])); + e.max_expansion = static_cast(atoi(row[90])); + e.content_flags = row[91] ? row[91] : ""; + e.content_flags_disabled = row[92] ? row[92] : ""; + e.underworld_teleport_index = static_cast(atoi(row[93])); + e.lava_damage = static_cast(atoi(row[94])); + e.min_lava_damage = static_cast(atoi(row[95])); - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -1221,6 +1243,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_ZONE_REPOSITORY_H diff --git a/common/repositories/base_data_repository.h b/common/repositories/base_data_repository.h index 55bbb781b..85e696b04 100644 --- a/common/repositories/base_data_repository.h +++ b/common/repositories/base_data_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_BASE_DATA_REPOSITORY_H #define EQEMU_BASE_DATA_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_base_data_repository.h" class BaseDataRepository: public BaseBaseDataRepository { diff --git a/common/repositories/blocked_spells_repository.h b/common/repositories/blocked_spells_repository.h index 54d66e493..b5d669df2 100644 --- a/common/repositories/blocked_spells_repository.h +++ b/common/repositories/blocked_spells_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_BLOCKED_SPELLS_REPOSITORY_H #define EQEMU_BLOCKED_SPELLS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_blocked_spells_repository.h" class BlockedSpellsRepository: public BaseBlockedSpellsRepository { diff --git a/common/repositories/books_repository.h b/common/repositories/books_repository.h index 6c2e3db91..d174e9194 100644 --- a/common/repositories/books_repository.h +++ b/common/repositories/books_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_BOOKS_REPOSITORY_H #define EQEMU_BOOKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_books_repository.h" class BooksRepository: public BaseBooksRepository { diff --git a/common/repositories/bot_buffs_repository.h b/common/repositories/bot_buffs_repository.h new file mode 100644 index 000000000..e7019601c --- /dev/null +++ b/common/repositories/bot_buffs_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_BUFFS_REPOSITORY_H +#define EQEMU_BOT_BUFFS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_buffs_repository.h" + +class BotBuffsRepository: public BaseBotBuffsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotBuffsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotBuffsRepository::GetWhereNeverExpires() + * BotBuffsRepository::GetWhereXAndY() + * BotBuffsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_BUFFS_REPOSITORY_H diff --git a/common/repositories/bot_create_combinations_repository.h b/common/repositories/bot_create_combinations_repository.h new file mode 100644 index 000000000..3955c9155 --- /dev/null +++ b/common/repositories/bot_create_combinations_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_CREATE_COMBINATIONS_REPOSITORY_H +#define EQEMU_BOT_CREATE_COMBINATIONS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_create_combinations_repository.h" + +class BotCreateCombinationsRepository: public BaseBotCreateCombinationsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotCreateCombinationsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotCreateCombinationsRepository::GetWhereNeverExpires() + * BotCreateCombinationsRepository::GetWhereXAndY() + * BotCreateCombinationsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_CREATE_COMBINATIONS_REPOSITORY_H diff --git a/common/repositories/bot_data_repository.h b/common/repositories/bot_data_repository.h new file mode 100644 index 000000000..e26781118 --- /dev/null +++ b/common/repositories/bot_data_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_DATA_REPOSITORY_H +#define EQEMU_BOT_DATA_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_data_repository.h" + +class BotDataRepository: public BaseBotDataRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotDataRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotDataRepository::GetWhereNeverExpires() + * BotDataRepository::GetWhereXAndY() + * BotDataRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_DATA_REPOSITORY_H diff --git a/common/repositories/bot_group_members_repository.h b/common/repositories/bot_group_members_repository.h new file mode 100644 index 000000000..837a5167e --- /dev/null +++ b/common/repositories/bot_group_members_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_GROUP_MEMBERS_REPOSITORY_H +#define EQEMU_BOT_GROUP_MEMBERS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_group_members_repository.h" + +class BotGroupMembersRepository: public BaseBotGroupMembersRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotGroupMembersRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotGroupMembersRepository::GetWhereNeverExpires() + * BotGroupMembersRepository::GetWhereXAndY() + * BotGroupMembersRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_GROUP_MEMBERS_REPOSITORY_H diff --git a/common/repositories/bot_groups_repository.h b/common/repositories/bot_groups_repository.h new file mode 100644 index 000000000..bd58f1356 --- /dev/null +++ b/common/repositories/bot_groups_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_GROUPS_REPOSITORY_H +#define EQEMU_BOT_GROUPS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_groups_repository.h" + +class BotGroupsRepository: public BaseBotGroupsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotGroupsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotGroupsRepository::GetWhereNeverExpires() + * BotGroupsRepository::GetWhereXAndY() + * BotGroupsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_GROUPS_REPOSITORY_H diff --git a/common/repositories/bot_guild_members_repository.h b/common/repositories/bot_guild_members_repository.h new file mode 100644 index 000000000..314a24b23 --- /dev/null +++ b/common/repositories/bot_guild_members_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_GUILD_MEMBERS_REPOSITORY_H +#define EQEMU_BOT_GUILD_MEMBERS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_guild_members_repository.h" + +class BotGuildMembersRepository: public BaseBotGuildMembersRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotGuildMembersRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotGuildMembersRepository::GetWhereNeverExpires() + * BotGuildMembersRepository::GetWhereXAndY() + * BotGuildMembersRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/bot_heal_rotation_members_repository.h b/common/repositories/bot_heal_rotation_members_repository.h new file mode 100644 index 000000000..4e0c1d057 --- /dev/null +++ b/common/repositories/bot_heal_rotation_members_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H +#define EQEMU_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_heal_rotation_members_repository.h" + +class BotHealRotationMembersRepository: public BaseBotHealRotationMembersRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotHealRotationMembersRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotHealRotationMembersRepository::GetWhereNeverExpires() + * BotHealRotationMembersRepository::GetWhereXAndY() + * BotHealRotationMembersRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H diff --git a/common/repositories/bot_heal_rotation_targets_repository.h b/common/repositories/bot_heal_rotation_targets_repository.h new file mode 100644 index 000000000..1faa29ac4 --- /dev/null +++ b/common/repositories/bot_heal_rotation_targets_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H +#define EQEMU_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_heal_rotation_targets_repository.h" + +class BotHealRotationTargetsRepository: public BaseBotHealRotationTargetsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotHealRotationTargetsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotHealRotationTargetsRepository::GetWhereNeverExpires() + * BotHealRotationTargetsRepository::GetWhereXAndY() + * BotHealRotationTargetsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H diff --git a/common/repositories/bot_heal_rotations_repository.h b/common/repositories/bot_heal_rotations_repository.h new file mode 100644 index 000000000..a5994fc5d --- /dev/null +++ b/common/repositories/bot_heal_rotations_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_HEAL_ROTATIONS_REPOSITORY_H +#define EQEMU_BOT_HEAL_ROTATIONS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_heal_rotations_repository.h" + +class BotHealRotationsRepository: public BaseBotHealRotationsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotHealRotationsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotHealRotationsRepository::GetWhereNeverExpires() + * BotHealRotationsRepository::GetWhereXAndY() + * BotHealRotationsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_HEAL_ROTATIONS_REPOSITORY_H diff --git a/common/repositories/bot_inspect_messages_repository.h b/common/repositories/bot_inspect_messages_repository.h new file mode 100644 index 000000000..27d486a57 --- /dev/null +++ b/common/repositories/bot_inspect_messages_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_INSPECT_MESSAGES_REPOSITORY_H +#define EQEMU_BOT_INSPECT_MESSAGES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_inspect_messages_repository.h" + +class BotInspectMessagesRepository: public BaseBotInspectMessagesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotInspectMessagesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotInspectMessagesRepository::GetWhereNeverExpires() + * BotInspectMessagesRepository::GetWhereXAndY() + * BotInspectMessagesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_INSPECT_MESSAGES_REPOSITORY_H diff --git a/common/repositories/bot_inventories_repository.h b/common/repositories/bot_inventories_repository.h new file mode 100644 index 000000000..84123fc22 --- /dev/null +++ b/common/repositories/bot_inventories_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_INVENTORIES_REPOSITORY_H +#define EQEMU_BOT_INVENTORIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_inventories_repository.h" + +class BotInventoriesRepository: public BaseBotInventoriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotInventoriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotInventoriesRepository::GetWhereNeverExpires() + * BotInventoriesRepository::GetWhereXAndY() + * BotInventoriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/bot_owner_options_repository.h b/common/repositories/bot_owner_options_repository.h new file mode 100644 index 000000000..ecc698e7d --- /dev/null +++ b/common/repositories/bot_owner_options_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_OWNER_OPTIONS_REPOSITORY_H +#define EQEMU_BOT_OWNER_OPTIONS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_owner_options_repository.h" + +class BotOwnerOptionsRepository: public BaseBotOwnerOptionsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotOwnerOptionsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotOwnerOptionsRepository::GetWhereNeverExpires() + * BotOwnerOptionsRepository::GetWhereXAndY() + * BotOwnerOptionsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_OWNER_OPTIONS_REPOSITORY_H diff --git a/common/repositories/bot_pet_buffs_repository.h b/common/repositories/bot_pet_buffs_repository.h new file mode 100644 index 000000000..546b94f8b --- /dev/null +++ b/common/repositories/bot_pet_buffs_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_PET_BUFFS_REPOSITORY_H +#define EQEMU_BOT_PET_BUFFS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_pet_buffs_repository.h" + +class BotPetBuffsRepository: public BaseBotPetBuffsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotPetBuffsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotPetBuffsRepository::GetWhereNeverExpires() + * BotPetBuffsRepository::GetWhereXAndY() + * BotPetBuffsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_PET_BUFFS_REPOSITORY_H diff --git a/common/repositories/bot_pet_inventories_repository.h b/common/repositories/bot_pet_inventories_repository.h new file mode 100644 index 000000000..0ad1c7460 --- /dev/null +++ b/common/repositories/bot_pet_inventories_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_PET_INVENTORIES_REPOSITORY_H +#define EQEMU_BOT_PET_INVENTORIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_pet_inventories_repository.h" + +class BotPetInventoriesRepository: public BaseBotPetInventoriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotPetInventoriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotPetInventoriesRepository::GetWhereNeverExpires() + * BotPetInventoriesRepository::GetWhereXAndY() + * BotPetInventoriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_PET_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/bot_pets_repository.h b/common/repositories/bot_pets_repository.h new file mode 100644 index 000000000..808d52bc2 --- /dev/null +++ b/common/repositories/bot_pets_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_PETS_REPOSITORY_H +#define EQEMU_BOT_PETS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_pets_repository.h" + +class BotPetsRepository: public BaseBotPetsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotPetsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotPetsRepository::GetWhereNeverExpires() + * BotPetsRepository::GetWhereXAndY() + * BotPetsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_PETS_REPOSITORY_H diff --git a/common/repositories/bot_spell_casting_chances_repository.h b/common/repositories/bot_spell_casting_chances_repository.h new file mode 100644 index 000000000..b8c2ac921 --- /dev/null +++ b/common/repositories/bot_spell_casting_chances_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H +#define EQEMU_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_spell_casting_chances_repository.h" + +class BotSpellCastingChancesRepository: public BaseBotSpellCastingChancesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotSpellCastingChancesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotSpellCastingChancesRepository::GetWhereNeverExpires() + * BotSpellCastingChancesRepository::GetWhereXAndY() + * BotSpellCastingChancesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H diff --git a/common/repositories/bot_spell_settings_repository.h b/common/repositories/bot_spell_settings_repository.h new file mode 100644 index 000000000..595e08525 --- /dev/null +++ b/common/repositories/bot_spell_settings_repository.h @@ -0,0 +1,75 @@ +#ifndef EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H +#define EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_spell_settings_repository.h" + +class BotSpellSettingsRepository: public BaseBotSpellSettingsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotSpellSettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotSpellSettingsRepository::GetWhereNeverExpires() + * BotSpellSettingsRepository::GetWhereXAndY() + * BotSpellSettingsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + + static bool UpdateSpellSetting( + Database& db, + const BotSpellSettings &e + ) { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[3] + " = " + std::to_string(e.priority)); + v.push_back(columns[4] + " = " + std::to_string(e.min_hp)); + v.push_back(columns[5] + " = " + std::to_string(e.max_hp)); + v.push_back(columns[6] + " = " + std::to_string(e.is_enabled)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE `bot_id` = {} AND `spell_id` = {}", + TableName(), + Strings::Implode(", ", v), + e.bot_id, + e.spell_id + ) + ); + + return (results.Success() ? true : false); + } +}; + +#endif //EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H diff --git a/common/repositories/bot_spells_entries_repository.h b/common/repositories/bot_spells_entries_repository.h new file mode 100644 index 000000000..5901df341 --- /dev/null +++ b/common/repositories/bot_spells_entries_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_SPELLS_ENTRIES_REPOSITORY_H +#define EQEMU_BOT_SPELLS_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_spells_entries_repository.h" + +class BotSpellsEntriesRepository: public BaseBotSpellsEntriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotSpellsEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotSpellsEntriesRepository::GetWhereNeverExpires() + * BotSpellsEntriesRepository::GetWhereXAndY() + * BotSpellsEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_SPELLS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/bot_stances_repository.h b/common/repositories/bot_stances_repository.h new file mode 100644 index 000000000..a9a0e49e0 --- /dev/null +++ b/common/repositories/bot_stances_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_STANCES_REPOSITORY_H +#define EQEMU_BOT_STANCES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_stances_repository.h" + +class BotStancesRepository: public BaseBotStancesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotStancesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotStancesRepository::GetWhereNeverExpires() + * BotStancesRepository::GetWhereXAndY() + * BotStancesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_STANCES_REPOSITORY_H diff --git a/common/repositories/bot_timers_repository.h b/common/repositories/bot_timers_repository.h new file mode 100644 index 000000000..19cf9269e --- /dev/null +++ b/common/repositories/bot_timers_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_BOT_TIMERS_REPOSITORY_H +#define EQEMU_BOT_TIMERS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_bot_timers_repository.h" + +class BotTimersRepository: public BaseBotTimersRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * BotTimersRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * BotTimersRepository::GetWhereNeverExpires() + * BotTimersRepository::GetWhereXAndY() + * BotTimersRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_BOT_TIMERS_REPOSITORY_H diff --git a/common/repositories/bug_reports_repository.h b/common/repositories/bug_reports_repository.h index 36b2258d2..a6f622d28 100644 --- a/common/repositories/bug_reports_repository.h +++ b/common/repositories/bug_reports_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_BUG_REPORTS_REPOSITORY_H #define EQEMU_BUG_REPORTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_bug_reports_repository.h" class BugReportsRepository: public BaseBugReportsRepository { diff --git a/common/repositories/bugs_repository.h b/common/repositories/bugs_repository.h index 8ca1ac25c..f55d88658 100644 --- a/common/repositories/bugs_repository.h +++ b/common/repositories/bugs_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_BUGS_REPOSITORY_H #define EQEMU_BUGS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_bugs_repository.h" class BugsRepository: public BaseBugsRepository { diff --git a/common/repositories/buyer_repository.h b/common/repositories/buyer_repository.h index d3ecb7585..7c3b39840 100644 --- a/common/repositories/buyer_repository.h +++ b/common/repositories/buyer_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_BUYER_REPOSITORY_H #define EQEMU_BUYER_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_buyer_repository.h" class BuyerRepository: public BaseBuyerRepository { diff --git a/common/repositories/char_create_combinations_repository.h b/common/repositories/char_create_combinations_repository.h index 1d0260958..42baebb02 100644 --- a/common/repositories/char_create_combinations_repository.h +++ b/common/repositories/char_create_combinations_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHAR_CREATE_COMBINATIONS_REPOSITORY_H #define EQEMU_CHAR_CREATE_COMBINATIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_char_create_combinations_repository.h" class CharCreateCombinationsRepository: public BaseCharCreateCombinationsRepository { diff --git a/common/repositories/char_create_point_allocations_repository.h b/common/repositories/char_create_point_allocations_repository.h index 1fd6cdcb9..8828d2521 100644 --- a/common/repositories/char_create_point_allocations_repository.h +++ b/common/repositories/char_create_point_allocations_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H #define EQEMU_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_char_create_point_allocations_repository.h" class CharCreatePointAllocationsRepository: public BaseCharCreatePointAllocationsRepository { diff --git a/common/repositories/char_recipe_list_repository.h b/common/repositories/char_recipe_list_repository.h index f8ff81f01..9435da6cc 100644 --- a/common/repositories/char_recipe_list_repository.h +++ b/common/repositories/char_recipe_list_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H #define EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_char_recipe_list_repository.h" class CharRecipeListRepository: public BaseCharRecipeListRepository { @@ -65,6 +45,20 @@ public: // Custom extended repository methods here + static CharRecipeList GetCharRecipeListEntry( + const std::vector &recipe_list, + uint32 recipe_id + ) + { + for (auto &e : recipe_list) { + if (e.recipe_id == recipe_id) { + return e; + } + } + + return NewEntity(); + } + }; #endif //EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H diff --git a/common/repositories/character_activities_repository.h b/common/repositories/character_activities_repository.h index 9b442958c..420548887 100644 --- a/common/repositories/character_activities_repository.h +++ b/common/repositories/character_activities_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_ACTIVITIES_REPOSITORY_H #define EQEMU_CHARACTER_ACTIVITIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_activities_repository.h" class CharacterActivitiesRepository: public BaseCharacterActivitiesRepository { diff --git a/common/repositories/character_alt_currency_repository.h b/common/repositories/character_alt_currency_repository.h index 3f657b817..1ef74dd58 100644 --- a/common/repositories/character_alt_currency_repository.h +++ b/common/repositories/character_alt_currency_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_ALT_CURRENCY_REPOSITORY_H #define EQEMU_CHARACTER_ALT_CURRENCY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_alt_currency_repository.h" class CharacterAltCurrencyRepository: public BaseCharacterAltCurrencyRepository { diff --git a/common/repositories/character_alternate_abilities_repository.h b/common/repositories/character_alternate_abilities_repository.h index 6c4bb6f16..d3514c91f 100644 --- a/common/repositories/character_alternate_abilities_repository.h +++ b/common/repositories/character_alternate_abilities_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H #define EQEMU_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_alternate_abilities_repository.h" class CharacterAlternateAbilitiesRepository: public BaseCharacterAlternateAbilitiesRepository { diff --git a/common/repositories/character_auras_repository.h b/common/repositories/character_auras_repository.h index 5f2669c2a..f03154a3b 100644 --- a/common/repositories/character_auras_repository.h +++ b/common/repositories/character_auras_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_AURAS_REPOSITORY_H #define EQEMU_CHARACTER_AURAS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_auras_repository.h" class CharacterAurasRepository: public BaseCharacterAurasRepository { diff --git a/common/repositories/character_bandolier_repository.h b/common/repositories/character_bandolier_repository.h index aacaf042d..ff2a6dcc0 100644 --- a/common/repositories/character_bandolier_repository.h +++ b/common/repositories/character_bandolier_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_BANDOLIER_REPOSITORY_H #define EQEMU_CHARACTER_BANDOLIER_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_bandolier_repository.h" class CharacterBandolierRepository: public BaseCharacterBandolierRepository { diff --git a/common/repositories/character_bind_repository.h b/common/repositories/character_bind_repository.h index 28556c296..a78bef415 100644 --- a/common/repositories/character_bind_repository.h +++ b/common/repositories/character_bind_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_BIND_REPOSITORY_H #define EQEMU_CHARACTER_BIND_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_bind_repository.h" class CharacterBindRepository: public BaseCharacterBindRepository { diff --git a/common/repositories/character_buffs_repository.h b/common/repositories/character_buffs_repository.h index d5a05dc3e..92a81fe05 100644 --- a/common/repositories/character_buffs_repository.h +++ b/common/repositories/character_buffs_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_BUFFS_REPOSITORY_H #define EQEMU_CHARACTER_BUFFS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_buffs_repository.h" class CharacterBuffsRepository: public BaseCharacterBuffsRepository { diff --git a/common/repositories/character_corpse_items_repository.h b/common/repositories/character_corpse_items_repository.h index 44ff0c7e2..1a0352d8f 100644 --- a/common/repositories/character_corpse_items_repository.h +++ b/common/repositories/character_corpse_items_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_CORPSE_ITEMS_REPOSITORY_H #define EQEMU_CHARACTER_CORPSE_ITEMS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_corpse_items_repository.h" class CharacterCorpseItemsRepository: public BaseCharacterCorpseItemsRepository { diff --git a/common/repositories/character_corpses_repository.h b/common/repositories/character_corpses_repository.h index 7a0d5af55..c228b15e1 100644 --- a/common/repositories/character_corpses_repository.h +++ b/common/repositories/character_corpses_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_CORPSES_REPOSITORY_H #define EQEMU_CHARACTER_CORPSES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_corpses_repository.h" class CharacterCorpsesRepository: public BaseCharacterCorpsesRepository { @@ -64,7 +44,30 @@ public: */ // Custom extended repository methods here + static int BuryInstance(Database& db, uint16 instance_id) { + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET is_buried = 1, instance_id = 0 WHERE instance_id = {}", + TableName(), + instance_id + ) + ); + return (results.Success() ? results.RowsAffected() : 0); + } + + static int BuryInstances(Database& db, const std::string& joined_instance_ids) + { + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", + TableName(), + joined_instance_ids + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } }; #endif //EQEMU_CHARACTER_CORPSES_REPOSITORY_H diff --git a/common/repositories/character_currency_repository.h b/common/repositories/character_currency_repository.h index 661e4e7fa..833e6cbf2 100644 --- a/common/repositories/character_currency_repository.h +++ b/common/repositories/character_currency_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_CURRENCY_REPOSITORY_H #define EQEMU_CHARACTER_CURRENCY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_currency_repository.h" class CharacterCurrencyRepository: public BaseCharacterCurrencyRepository { diff --git a/common/repositories/character_data_repository.h b/common/repositories/character_data_repository.h index e8ec2d21d..f527e5537 100644 --- a/common/repositories/character_data_repository.h +++ b/common/repositories/character_data_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_DATA_REPOSITORY_H #define EQEMU_CHARACTER_DATA_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_data_repository.h" class CharacterDataRepository: public BaseCharacterDataRepository { diff --git a/common/repositories/character_disciplines_repository.h b/common/repositories/character_disciplines_repository.h index dd8dd029b..a6a0ff225 100644 --- a/common/repositories/character_disciplines_repository.h +++ b/common/repositories/character_disciplines_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_DISCIPLINES_REPOSITORY_H #define EQEMU_CHARACTER_DISCIPLINES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_disciplines_repository.h" class CharacterDisciplinesRepository: public BaseCharacterDisciplinesRepository { diff --git a/common/repositories/character_exp_modifiers_repository.h b/common/repositories/character_exp_modifiers_repository.h index fa8dfe158..d94fe79ff 100644 --- a/common/repositories/character_exp_modifiers_repository.h +++ b/common/repositories/character_exp_modifiers_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_EXP_MODIFIERS_REPOSITORY_H #define EQEMU_CHARACTER_EXP_MODIFIERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_exp_modifiers_repository.h" class CharacterExpModifiersRepository: public BaseCharacterExpModifiersRepository { diff --git a/common/repositories/character_expedition_lockouts_repository.h b/common/repositories/character_expedition_lockouts_repository.h index 006bacae1..bf16e49a4 100644 --- a/common/repositories/character_expedition_lockouts_repository.h +++ b/common/repositories/character_expedition_lockouts_repository.h @@ -1,29 +1,9 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H #define EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H #include "../database.h" #include "../expedition_lockout_timer.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_expedition_lockouts_repository.h" #include @@ -95,8 +75,6 @@ public: Database& db, const std::vector& character_ids, const std::string& expedition_name, const std::string& ordered_event_name) { - auto joined_character_ids = fmt::join(character_ids, ","); - auto results = db.QueryDatabase(fmt::format(SQL( SELECT character_id, @@ -113,10 +91,10 @@ public: FIELD(character_id, {}), FIELD(event_name, '{}') DESC ), - joined_character_ids, - EscapeString(expedition_name), - joined_character_ids, - EscapeString(ordered_event_name) + fmt::join(character_ids, ","), + Strings::Escape(expedition_name), + fmt::join(character_ids, ","), + Strings::Escape(ordered_event_name) )); std::unordered_map> lockouts; diff --git a/common/repositories/character_inspect_messages_repository.h b/common/repositories/character_inspect_messages_repository.h index e916fd6e3..b3c8b5cbc 100644 --- a/common/repositories/character_inspect_messages_repository.h +++ b/common/repositories/character_inspect_messages_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H #define EQEMU_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_inspect_messages_repository.h" class CharacterInspectMessagesRepository: public BaseCharacterInspectMessagesRepository { diff --git a/common/repositories/character_instance_safereturns_repository.h b/common/repositories/character_instance_safereturns_repository.h index 89bfddead..681f4f6ad 100644 --- a/common/repositories/character_instance_safereturns_repository.h +++ b/common/repositories/character_instance_safereturns_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H #define EQEMU_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_instance_safereturns_repository.h" class CharacterInstanceSafereturnsRepository: public BaseCharacterInstanceSafereturnsRepository { @@ -92,7 +72,7 @@ public: safe_heading = VALUES(safe_heading) ), BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) )); if (results.Success()) diff --git a/common/repositories/character_item_recast_repository.h b/common/repositories/character_item_recast_repository.h index 00814ad63..35a36559d 100644 --- a/common/repositories/character_item_recast_repository.h +++ b/common/repositories/character_item_recast_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_ITEM_RECAST_REPOSITORY_H #define EQEMU_CHARACTER_ITEM_RECAST_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_item_recast_repository.h" class CharacterItemRecastRepository: public BaseCharacterItemRecastRepository { diff --git a/common/repositories/character_languages_repository.h b/common/repositories/character_languages_repository.h index de53ea979..b4b866666 100644 --- a/common/repositories/character_languages_repository.h +++ b/common/repositories/character_languages_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_LANGUAGES_REPOSITORY_H #define EQEMU_CHARACTER_LANGUAGES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_languages_repository.h" class CharacterLanguagesRepository: public BaseCharacterLanguagesRepository { diff --git a/common/repositories/character_leadership_abilities_repository.h b/common/repositories/character_leadership_abilities_repository.h index a2d496001..5f688d9d5 100644 --- a/common/repositories/character_leadership_abilities_repository.h +++ b/common/repositories/character_leadership_abilities_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H #define EQEMU_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_leadership_abilities_repository.h" class CharacterLeadershipAbilitiesRepository: public BaseCharacterLeadershipAbilitiesRepository { diff --git a/common/repositories/character_material_repository.h b/common/repositories/character_material_repository.h index c80f5b050..eb5989025 100644 --- a/common/repositories/character_material_repository.h +++ b/common/repositories/character_material_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_MATERIAL_REPOSITORY_H #define EQEMU_CHARACTER_MATERIAL_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_material_repository.h" class CharacterMaterialRepository: public BaseCharacterMaterialRepository { diff --git a/common/repositories/character_memmed_spells_repository.h b/common/repositories/character_memmed_spells_repository.h index 8e4ac4be7..cdf5cc5f0 100644 --- a/common/repositories/character_memmed_spells_repository.h +++ b/common/repositories/character_memmed_spells_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_MEMMED_SPELLS_REPOSITORY_H #define EQEMU_CHARACTER_MEMMED_SPELLS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_memmed_spells_repository.h" class CharacterMemmedSpellsRepository: public BaseCharacterMemmedSpellsRepository { diff --git a/common/repositories/character_peqzone_flags_repository.h b/common/repositories/character_peqzone_flags_repository.h new file mode 100644 index 000000000..3295a6c8c --- /dev/null +++ b/common/repositories/character_peqzone_flags_repository.h @@ -0,0 +1,62 @@ +#ifndef EQEMU_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H +#define EQEMU_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_character_peqzone_flags_repository.h" + +class CharacterPeqzoneFlagsRepository: public BaseCharacterPeqzoneFlagsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * CharacterPeqzoneFlagsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * CharacterPeqzoneFlagsRepository::GetWhereNeverExpires() + * CharacterPeqzoneFlagsRepository::GetWhereXAndY() + * CharacterPeqzoneFlagsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + static int DeleteFlag(Database& db, uint32 character_id, uint32 zone_id) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE id = {} AND zone_id = {}", + TableName(), + character_id, + zone_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H diff --git a/common/repositories/character_pet_buffs_repository.h b/common/repositories/character_pet_buffs_repository.h index 1667e86df..b5ed82c63 100644 --- a/common/repositories/character_pet_buffs_repository.h +++ b/common/repositories/character_pet_buffs_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_PET_BUFFS_REPOSITORY_H #define EQEMU_CHARACTER_PET_BUFFS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_pet_buffs_repository.h" class CharacterPetBuffsRepository: public BaseCharacterPetBuffsRepository { diff --git a/common/repositories/character_pet_info_repository.h b/common/repositories/character_pet_info_repository.h index fcbf2a8d3..45c4f2854 100644 --- a/common/repositories/character_pet_info_repository.h +++ b/common/repositories/character_pet_info_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_PET_INFO_REPOSITORY_H #define EQEMU_CHARACTER_PET_INFO_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_pet_info_repository.h" class CharacterPetInfoRepository: public BaseCharacterPetInfoRepository { diff --git a/common/repositories/character_pet_inventory_repository.h b/common/repositories/character_pet_inventory_repository.h index ab0570ab2..21fb5c362 100644 --- a/common/repositories/character_pet_inventory_repository.h +++ b/common/repositories/character_pet_inventory_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_PET_INVENTORY_REPOSITORY_H #define EQEMU_CHARACTER_PET_INVENTORY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_pet_inventory_repository.h" class CharacterPetInventoryRepository: public BaseCharacterPetInventoryRepository { diff --git a/common/repositories/character_potionbelt_repository.h b/common/repositories/character_potionbelt_repository.h index 8ce1bb71b..1a69e6711 100644 --- a/common/repositories/character_potionbelt_repository.h +++ b/common/repositories/character_potionbelt_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_POTIONBELT_REPOSITORY_H #define EQEMU_CHARACTER_POTIONBELT_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_potionbelt_repository.h" class CharacterPotionbeltRepository: public BaseCharacterPotionbeltRepository { diff --git a/common/repositories/character_recipe_list_repository.h b/common/repositories/character_recipe_list_repository.h deleted file mode 100644 index f0a53f099..000000000 --- a/common/repositories/character_recipe_list_repository.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef EQEMU_CHARACTER_RECIPE_LIST_REPOSITORY_H -#define EQEMU_CHARACTER_RECIPE_LIST_REPOSITORY_H - -#include "../database.h" -#include "../string_util.h" - -class CharacterRecipeListRepository { -public: - struct CharacterRecipeList { - int character_id; - int recipe_id; - int made_count; - }; - - static std::vector Columns() - { - return { - "char_id", - "recipe_id", - "madecount", - }; - } - - static std::string ColumnsRaw() - { - return std::string(implode(", ", Columns())); - } - - static std::string TableName() - { - return std::string("char_recipe_list"); - } - - static std::string BaseSelect() - { - return std::string( - fmt::format( - "SELECT {} FROM {}", - ColumnsRaw(), - TableName() - ) - ); - } - - static CharacterRecipeList NewEntity() - { - CharacterRecipeList character_recipe_list_entry; - - character_recipe_list_entry.character_id = 0; - character_recipe_list_entry.made_count = 0; - character_recipe_list_entry.recipe_id = 0; - - return character_recipe_list_entry; - } - - static std::vector GetLearnedRecipeList(int character_id) - { - std::vector character_recipe_list; - - auto results = database.QueryDatabase( - fmt::format( - "{} WHERE char_id = {}", - BaseSelect(), - character_id - ) - ); - - for (auto row = results.begin(); row != results.end(); ++row) { - CharacterRecipeList character_recipe_list_entry; - - character_recipe_list_entry.character_id = character_id; - character_recipe_list_entry.recipe_id = atoi(row[1]); - character_recipe_list_entry.made_count = atoi(row[2]); - - character_recipe_list.push_back(character_recipe_list_entry); - } - - return character_recipe_list; - } - - static CharacterRecipeList GetRecipe( - std::vector character_recipe_list, - int recipe_id - ) - { - for (auto &row : character_recipe_list) { - if (row.recipe_id == recipe_id) { - return row; - } - } - - return NewEntity(); - } - -}; - -#endif //EQEMU_CHARACTER_RECIPE_LIST_REPOSITORY_H diff --git a/common/repositories/character_skills_repository.h b/common/repositories/character_skills_repository.h index de2f40f90..c8c60e104 100644 --- a/common/repositories/character_skills_repository.h +++ b/common/repositories/character_skills_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_SKILLS_REPOSITORY_H #define EQEMU_CHARACTER_SKILLS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_skills_repository.h" class CharacterSkillsRepository: public BaseCharacterSkillsRepository { diff --git a/common/repositories/character_spells_repository.h b/common/repositories/character_spells_repository.h index 982956ce3..81c3f9697 100644 --- a/common/repositories/character_spells_repository.h +++ b/common/repositories/character_spells_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_SPELLS_REPOSITORY_H #define EQEMU_CHARACTER_SPELLS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_spells_repository.h" class CharacterSpellsRepository: public BaseCharacterSpellsRepository { diff --git a/common/repositories/character_task_timers_repository.h b/common/repositories/character_task_timers_repository.h index 7f0b07962..4b153cd01 100644 --- a/common/repositories/character_task_timers_repository.h +++ b/common/repositories/character_task_timers_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_TASK_TIMERS_REPOSITORY_H #define EQEMU_CHARACTER_TASK_TIMERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_task_timers_repository.h" class CharacterTaskTimersRepository: public BaseCharacterTaskTimersRepository { diff --git a/common/repositories/character_tasks_repository.h b/common/repositories/character_tasks_repository.h index 71ead2aeb..15b44ccff 100644 --- a/common/repositories/character_tasks_repository.h +++ b/common/repositories/character_tasks_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CHARACTER_TASKS_REPOSITORY_H #define EQEMU_CHARACTER_TASKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_character_tasks_repository.h" class CharacterTasksRepository: public BaseCharacterTasksRepository { diff --git a/common/repositories/chatchannel_reserved_names_repository.h b/common/repositories/chatchannel_reserved_names_repository.h new file mode 100644 index 000000000..44fa80621 --- /dev/null +++ b/common/repositories/chatchannel_reserved_names_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H +#define EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_chatchannel_reserved_names_repository.h" + +class ChatchannelReservedNamesRepository: public BaseChatchannelReservedNamesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * ChatchannelReservedNamesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * ChatchannelReservedNamesRepository::GetWhereNeverExpires() + * ChatchannelReservedNamesRepository::GetWhereXAndY() + * ChatchannelReservedNamesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H diff --git a/common/repositories/chatchannels_repository.h b/common/repositories/chatchannels_repository.h new file mode 100644 index 000000000..0b388d301 --- /dev/null +++ b/common/repositories/chatchannels_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_CHATCHANNELS_REPOSITORY_H +#define EQEMU_CHATCHANNELS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_chatchannels_repository.h" + +class ChatchannelsRepository: public BaseChatchannelsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * ChatchannelsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * ChatchannelsRepository::GetWhereNeverExpires() + * ChatchannelsRepository::GetWhereXAndY() + * ChatchannelsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_CHATCHANNELS_REPOSITORY_H diff --git a/common/repositories/completed_shared_task_activity_state_repository.h b/common/repositories/completed_shared_task_activity_state_repository.h index afb0ef3fd..144bb124c 100644 --- a/common/repositories/completed_shared_task_activity_state_repository.h +++ b/common/repositories/completed_shared_task_activity_state_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H #define EQEMU_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_completed_shared_task_activity_state_repository.h" class CompletedSharedTaskActivityStateRepository: public BaseCompletedSharedTaskActivityStateRepository { diff --git a/common/repositories/completed_shared_task_members_repository.h b/common/repositories/completed_shared_task_members_repository.h index 6c0cf609a..5e456f3c5 100644 --- a/common/repositories/completed_shared_task_members_repository.h +++ b/common/repositories/completed_shared_task_members_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H #define EQEMU_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_completed_shared_task_members_repository.h" class CompletedSharedTaskMembersRepository: public BaseCompletedSharedTaskMembersRepository { diff --git a/common/repositories/completed_shared_tasks_repository.h b/common/repositories/completed_shared_tasks_repository.h index bbf46f16c..555a5775a 100644 --- a/common/repositories/completed_shared_tasks_repository.h +++ b/common/repositories/completed_shared_tasks_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_COMPLETED_SHARED_TASKS_REPOSITORY_H #define EQEMU_COMPLETED_SHARED_TASKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_completed_shared_tasks_repository.h" class CompletedSharedTasksRepository: public BaseCompletedSharedTasksRepository { diff --git a/common/repositories/completed_tasks_repository.h b/common/repositories/completed_tasks_repository.h index 65a9a2c5c..8bb00017e 100644 --- a/common/repositories/completed_tasks_repository.h +++ b/common/repositories/completed_tasks_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_COMPLETED_TASKS_REPOSITORY_H #define EQEMU_COMPLETED_TASKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_completed_tasks_repository.h" class CompletedTasksRepository: public BaseCompletedTasksRepository { diff --git a/common/repositories/content_flags_repository.h b/common/repositories/content_flags_repository.h index d9bf0098c..b777155cd 100644 --- a/common/repositories/content_flags_repository.h +++ b/common/repositories/content_flags_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CONTENT_FLAGS_REPOSITORY_H #define EQEMU_CONTENT_FLAGS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_content_flags_repository.h" class ContentFlagsRepository: public BaseContentFlagsRepository { diff --git a/common/repositories/criteria/content_filter_criteria.h b/common/repositories/criteria/content_filter_criteria.h index 8d73eefe4..0883097d4 100644 --- a/common/repositories/criteria/content_filter_criteria.h +++ b/common/repositories/criteria/content_filter_criteria.h @@ -1,29 +1,9 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_CONTENT_FILTER_CRITERIA_H #define EQEMU_CONTENT_FILTER_CRITERIA_H #include #include "../../content/world_content_service.h" -#include "../../string_util.h" +#include "../../strings.h" namespace ContentFilterCriteria { static std::string apply(std::string table_prefix = "") @@ -61,14 +41,14 @@ namespace ContentFilterCriteria { flags_in_filter_enabled = fmt::format( " OR CONCAT(',', {}content_flags, ',') REGEXP ',({}),' ", table_prefix, - implode("|", flags_enabled) + Strings::Implode("|", flags_enabled) ); } if (!flags_disabled.empty()) { flags_in_filter_disabled = fmt::format( " OR CONCAT(',', {}content_flags_disabled, ',') REGEXP ',({}),' ", table_prefix, - implode("|", flags_disabled) + Strings::Implode("|", flags_disabled) ); } diff --git a/common/repositories/damageshieldtypes_repository.h b/common/repositories/damageshieldtypes_repository.h index 3bb4b4fd2..ec7c829f0 100644 --- a/common/repositories/damageshieldtypes_repository.h +++ b/common/repositories/damageshieldtypes_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_DAMAGESHIELDTYPES_REPOSITORY_H #define EQEMU_DAMAGESHIELDTYPES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_damageshieldtypes_repository.h" class DamageshieldtypesRepository: public BaseDamageshieldtypesRepository { diff --git a/common/repositories/data_buckets_repository.h b/common/repositories/data_buckets_repository.h index d33a56304..606dbdfaa 100644 --- a/common/repositories/data_buckets_repository.h +++ b/common/repositories/data_buckets_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_DATA_BUCKETS_REPOSITORY_H #define EQEMU_DATA_BUCKETS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_data_buckets_repository.h" class DataBucketsRepository: public BaseDataBucketsRepository { diff --git a/common/repositories/db_str_repository.h b/common/repositories/db_str_repository.h index 95662cdfa..1ea5550ac 100644 --- a/common/repositories/db_str_repository.h +++ b/common/repositories/db_str_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_DB_STR_REPOSITORY_H #define EQEMU_DB_STR_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_db_str_repository.h" class DbStrRepository: public BaseDbStrRepository { diff --git a/common/repositories/discord_webhooks_repository.h b/common/repositories/discord_webhooks_repository.h new file mode 100644 index 000000000..064fadfbf --- /dev/null +++ b/common/repositories/discord_webhooks_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_DISCORD_WEBHOOKS_REPOSITORY_H +#define EQEMU_DISCORD_WEBHOOKS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_discord_webhooks_repository.h" + +class DiscordWebhooksRepository: public BaseDiscordWebhooksRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * DiscordWebhooksRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * DiscordWebhooksRepository::GetWhereNeverExpires() + * DiscordWebhooksRepository::GetWhereXAndY() + * DiscordWebhooksRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_DISCORD_WEBHOOKS_REPOSITORY_H diff --git a/common/repositories/discovered_items_repository.h b/common/repositories/discovered_items_repository.h index 512ebbbd7..6fcd7968e 100644 --- a/common/repositories/discovered_items_repository.h +++ b/common/repositories/discovered_items_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_DISCOVERED_ITEMS_REPOSITORY_H #define EQEMU_DISCOVERED_ITEMS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_discovered_items_repository.h" class DiscoveredItemsRepository: public BaseDiscoveredItemsRepository { diff --git a/common/repositories/doors_repository.h b/common/repositories/doors_repository.h index aa67d8e20..f0e46fdee 100644 --- a/common/repositories/doors_repository.h +++ b/common/repositories/doors_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_DOORS_REPOSITORY_H #define EQEMU_DOORS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_doors_repository.h" class DoorsRepository: public BaseDoorsRepository { diff --git a/common/repositories/dynamic_zone_members_repository.h b/common/repositories/dynamic_zone_members_repository.h index 3ccdd17b8..1e25fc950 100644 --- a/common/repositories/dynamic_zone_members_repository.h +++ b/common/repositories/dynamic_zone_members_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H #define EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_dynamic_zone_members_repository.h" class DynamicZoneMembersRepository: public BaseDynamicZoneMembersRepository { @@ -210,7 +190,7 @@ public: insert_values.push_back(std::to_string(dynamic_zone_members_entry.dynamic_zone_id)); insert_values.push_back(std::to_string(dynamic_zone_members_entry.character_id)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -220,7 +200,7 @@ public: "INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = id;", TableName(), ColumnsRaw(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/dynamic_zone_templates_repository.h b/common/repositories/dynamic_zone_templates_repository.h new file mode 100644 index 000000000..0dfe1183e --- /dev/null +++ b/common/repositories/dynamic_zone_templates_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H +#define EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_dynamic_zone_templates_repository.h" + +class DynamicZoneTemplatesRepository: public BaseDynamicZoneTemplatesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * DynamicZoneTemplatesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * DynamicZoneTemplatesRepository::GetWhereNeverExpires() + * DynamicZoneTemplatesRepository::GetWhereXAndY() + * DynamicZoneTemplatesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/dynamic_zones_repository.h b/common/repositories/dynamic_zones_repository.h index 677fcc2f8..a64aef8cc 100644 --- a/common/repositories/dynamic_zones_repository.h +++ b/common/repositories/dynamic_zones_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_DYNAMIC_ZONES_REPOSITORY_H #define EQEMU_DYNAMIC_ZONES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_dynamic_zones_repository.h" class DynamicZonesRepository: public BaseDynamicZonesRepository { @@ -75,6 +55,7 @@ public: int max_players; int instance_id; int type; + int dz_switch_id; int compass_zone_id; float compass_x; float compass_y; @@ -109,6 +90,7 @@ public: dynamic_zones.max_players, dynamic_zones.instance_id, dynamic_zones.type, + dynamic_zones.dz_switch_id, dynamic_zones.compass_zone_id, dynamic_zones.compass_x, dynamic_zones.compass_y, @@ -147,6 +129,7 @@ public: entry.max_players = strtol(row[col++], nullptr, 10); entry.instance_id = strtol(row[col++], nullptr, 10); entry.type = strtol(row[col++], nullptr, 10); + entry.dz_switch_id = strtol(row[col++], nullptr, 10); entry.compass_zone_id = strtol(row[col++], nullptr, 10); entry.compass_x = strtof(row[col++], nullptr); entry.compass_y = strtof(row[col++], nullptr); @@ -261,6 +244,18 @@ public: } } + static void UpdateSwitchID(Database& db, uint32_t dz_id, int dz_switch_id) + { + if (dz_id != 0) + { + std::string query = fmt::format(SQL( + UPDATE {} SET dz_switch_id = {} WHERE {} = {}; + ), TableName(), dz_switch_id, PrimaryKey(), dz_id); + + db.QueryDatabase(query); + } + } + struct DynamicZoneInstancePlayerCount { uint32_t id; diff --git a/common/repositories/eventlog_repository.h b/common/repositories/eventlog_repository.h index f2d7ba369..83f21fb1a 100644 --- a/common/repositories/eventlog_repository.h +++ b/common/repositories/eventlog_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_EVENTLOG_REPOSITORY_H #define EQEMU_EVENTLOG_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_eventlog_repository.h" class EventlogRepository: public BaseEventlogRepository { diff --git a/common/repositories/expedition_lockouts_repository.h b/common/repositories/expedition_lockouts_repository.h index 5eab18915..94dbe155d 100644 --- a/common/repositories/expedition_lockouts_repository.h +++ b/common/repositories/expedition_lockouts_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H #define EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_expedition_lockouts_repository.h" class ExpeditionLockoutsRepository: public BaseExpeditionLockoutsRepository { diff --git a/common/repositories/expeditions_repository.h b/common/repositories/expeditions_repository.h index 1470cbad0..502b9bc04 100644 --- a/common/repositories/expeditions_repository.h +++ b/common/repositories/expeditions_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_EXPEDITIONS_REPOSITORY_H #define EQEMU_EXPEDITIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_expeditions_repository.h" class ExpeditionsRepository: public BaseExpeditionsRepository { diff --git a/common/repositories/faction_association_repository.h b/common/repositories/faction_association_repository.h new file mode 100644 index 000000000..18cb67729 --- /dev/null +++ b/common/repositories/faction_association_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_FACTION_ASSOCIATION_REPOSITORY_H +#define EQEMU_FACTION_ASSOCIATION_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_faction_association_repository.h" + +class FactionAssociationRepository: public BaseFactionAssociationRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * FactionAssociationRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * FactionAssociationRepository::GetWhereNeverExpires() + * FactionAssociationRepository::GetWhereXAndY() + * FactionAssociationRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_FACTION_ASSOCIATION_REPOSITORY_H diff --git a/common/repositories/faction_base_data_repository.h b/common/repositories/faction_base_data_repository.h index f62890768..0cabe09cf 100644 --- a/common/repositories/faction_base_data_repository.h +++ b/common/repositories/faction_base_data_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_FACTION_BASE_DATA_REPOSITORY_H #define EQEMU_FACTION_BASE_DATA_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_faction_base_data_repository.h" class FactionBaseDataRepository: public BaseFactionBaseDataRepository { diff --git a/common/repositories/faction_list_mod_repository.h b/common/repositories/faction_list_mod_repository.h index 2999a273b..029abb2cb 100644 --- a/common/repositories/faction_list_mod_repository.h +++ b/common/repositories/faction_list_mod_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_FACTION_LIST_MOD_REPOSITORY_H #define EQEMU_FACTION_LIST_MOD_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_faction_list_mod_repository.h" class FactionListModRepository: public BaseFactionListModRepository { diff --git a/common/repositories/faction_list_repository.h b/common/repositories/faction_list_repository.h index ef14bac7f..f37e47a3b 100644 --- a/common/repositories/faction_list_repository.h +++ b/common/repositories/faction_list_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_FACTION_LIST_REPOSITORY_H #define EQEMU_FACTION_LIST_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_faction_list_repository.h" class FactionListRepository: public BaseFactionListRepository { diff --git a/common/repositories/faction_values_repository.h b/common/repositories/faction_values_repository.h index 5c8ca4fe6..9ab862045 100644 --- a/common/repositories/faction_values_repository.h +++ b/common/repositories/faction_values_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_FACTION_VALUES_REPOSITORY_H #define EQEMU_FACTION_VALUES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_faction_values_repository.h" class FactionValuesRepository: public BaseFactionValuesRepository { diff --git a/common/repositories/fishing_repository.h b/common/repositories/fishing_repository.h index d5cd78cb7..90e8aa82b 100644 --- a/common/repositories/fishing_repository.h +++ b/common/repositories/fishing_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_FISHING_REPOSITORY_H #define EQEMU_FISHING_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_fishing_repository.h" class FishingRepository: public BaseFishingRepository { diff --git a/common/repositories/forage_repository.h b/common/repositories/forage_repository.h index 7f8e67c19..5f158e69d 100644 --- a/common/repositories/forage_repository.h +++ b/common/repositories/forage_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_FORAGE_REPOSITORY_H #define EQEMU_FORAGE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_forage_repository.h" class ForageRepository: public BaseForageRepository { diff --git a/common/repositories/friends_repository.h b/common/repositories/friends_repository.h index 0e0d0469a..3917f9f02 100644 --- a/common/repositories/friends_repository.h +++ b/common/repositories/friends_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_FRIENDS_REPOSITORY_H #define EQEMU_FRIENDS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_friends_repository.h" class FriendsRepository: public BaseFriendsRepository { diff --git a/common/repositories/global_loot_repository.h b/common/repositories/global_loot_repository.h index 519fee2d4..ca1783d21 100644 --- a/common/repositories/global_loot_repository.h +++ b/common/repositories/global_loot_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GLOBAL_LOOT_REPOSITORY_H #define EQEMU_GLOBAL_LOOT_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_global_loot_repository.h" class GlobalLootRepository: public BaseGlobalLootRepository { diff --git a/common/repositories/gm_ips_repository.h b/common/repositories/gm_ips_repository.h index 94289a519..bf62bbd1b 100644 --- a/common/repositories/gm_ips_repository.h +++ b/common/repositories/gm_ips_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GM_IPS_REPOSITORY_H #define EQEMU_GM_IPS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_gm_ips_repository.h" class GmIpsRepository: public BaseGmIpsRepository { diff --git a/common/repositories/goallists_repository.h b/common/repositories/goallists_repository.h deleted file mode 100644 index 781fd6200..000000000 --- a/common/repositories/goallists_repository.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef EQEMU_GOALLISTS_REPOSITORY_H -#define EQEMU_GOALLISTS_REPOSITORY_H - -#include "../database.h" -#include "../string_util.h" -#include "base/base_goallists_repository.h" - -class GoallistsRepository: public BaseGoallistsRepository { -public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * GoallistsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * GoallistsRepository::GetWhereNeverExpires() - * GoallistsRepository::GetWhereXAndY() - * GoallistsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - - // Custom extended repository methods here - -}; - -#endif //EQEMU_GOALLISTS_REPOSITORY_H diff --git a/common/repositories/graveyard_repository.h b/common/repositories/graveyard_repository.h index b427587a4..12bf4c565 100644 --- a/common/repositories/graveyard_repository.h +++ b/common/repositories/graveyard_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GRAVEYARD_REPOSITORY_H #define EQEMU_GRAVEYARD_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_graveyard_repository.h" class GraveyardRepository: public BaseGraveyardRepository { diff --git a/common/repositories/grid_entries_repository.h b/common/repositories/grid_entries_repository.h index bbdd2c321..7a9712d64 100644 --- a/common/repositories/grid_entries_repository.h +++ b/common/repositories/grid_entries_repository.h @@ -1,101 +1,55 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GRID_ENTRIES_REPOSITORY_H #define EQEMU_GRID_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" +#include "base/base_grid_entries_repository.h" -class GridEntriesRepository { +class GridEntriesRepository: public BaseGridEntriesRepository { public: - struct GridEntry { - int gridid; - int zoneid; - int number; - float x; - float y; - float z; - float heading; - int pause; - int8 centerpoint; - }; - static std::vector Columns() + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * GridEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * GridEntriesRepository::GetWhereNeverExpires() + * GridEntriesRepository::GetWhereXAndY() + * GridEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + + static std::vector GetZoneGridEntries(Database& db, int zone_id) { - return { - "gridid", - "zoneid", - "number", - "x", - "y", - "z", - "heading", - "pause", - "centerpoint", - }; - } + std::vector grid_entries; - static std::string ColumnsRaw() - { - return std::string(implode(", ", Columns())); - } - - static std::string TableName() - { - return std::string("grid_entries"); - } - - static std::string BaseSelect() - { - return std::string( - fmt::format( - "SELECT {} FROM {}", - ColumnsRaw(), - TableName() - ) - ); - } - - static GridEntry NewEntity() - { - GridEntry entry{}; - - entry.gridid = 0; - entry.zoneid = 0; - entry.number = 0; - entry.x = 0; - entry.y = 0; - entry.z = 0; - entry.heading = 0; - entry.pause = 0; - entry.centerpoint = 0; - - return entry; - } - - static std::vector GetZoneGridEntries(int zone_id) - { - std::vector grid_entries; - - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} WHERE zoneid = {} ORDER BY gridid, number", BaseSelect(), @@ -104,7 +58,7 @@ public: ); for (auto row = results.begin(); row != results.end(); ++row) { - GridEntry entry{}; + GridEntries entry{}; entry.gridid = atoi(row[0]); entry.zoneid = atoi(row[1]); @@ -121,6 +75,7 @@ public: return grid_entries; } + }; -#endif +#endif //EQEMU_GRID_ENTRIES_REPOSITORY_H diff --git a/common/repositories/grid_repository.h b/common/repositories/grid_repository.h index ea965546e..df6968209 100644 --- a/common/repositories/grid_repository.h +++ b/common/repositories/grid_repository.h @@ -1,73 +1,55 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GRID_REPOSITORY_H #define EQEMU_GRID_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_grid_repository.h" -class GridRepository : public BaseGridRepository { +class GridRepository: public BaseGridRepository { public: - /** - * This file was auto generated on Apr 5, 2020 and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators - * - * Base Methods (Subject to be expanded upon in time) - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * GridRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * GridRepository::GetWhereNeverExpires() - * GridRepository::GetWhereXAndY() - * GridRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * GridRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * GridRepository::GetWhereNeverExpires() + * GridRepository::GetWhereXAndY() + * GridRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ // Custom extended repository methods here - static std::vector GetZoneGrids(int zone_id) + static std::vector GetZoneGrids(Database& db, int zone_id) { std::vector grids; - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} WHERE zoneid = {}", BaseSelect(), @@ -76,33 +58,19 @@ public: ); for (auto row = results.begin(); row != results.end(); ++row) { - Grid entry{}; + Grid e{}; - entry.id = atoi(row[0]); - entry.zoneid = atoi(row[1]); - entry.type = atoi(row[2]); - entry.type2 = atoi(row[3]); + e.id = atoi(row[0]); + e.zoneid = atoi(row[1]); + e.type = atoi(row[2]); + e.type2 = atoi(row[3]); - grids.push_back(entry); + grids.push_back(e); } return grids; } - static Grid GetGrid( - const std::vector &grids, - int grid_id - ) - { - for (auto &row : grids) { - if (row.id == grid_id) { - return row; - } - } - - return NewEntity(); - } - }; #endif //EQEMU_GRID_REPOSITORY_H diff --git a/common/repositories/ground_spawns_repository.h b/common/repositories/ground_spawns_repository.h index 79d0e9454..800dd0b3a 100644 --- a/common/repositories/ground_spawns_repository.h +++ b/common/repositories/ground_spawns_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GROUND_SPAWNS_REPOSITORY_H #define EQEMU_GROUND_SPAWNS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_ground_spawns_repository.h" class GroundSpawnsRepository: public BaseGroundSpawnsRepository { diff --git a/common/repositories/group_id_repository.h b/common/repositories/group_id_repository.h index 403dec551..d2717acfc 100644 --- a/common/repositories/group_id_repository.h +++ b/common/repositories/group_id_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GROUP_ID_REPOSITORY_H #define EQEMU_GROUP_ID_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_group_id_repository.h" class GroupIdRepository: public BaseGroupIdRepository { diff --git a/common/repositories/group_leaders_repository.h b/common/repositories/group_leaders_repository.h index 811a6757e..9dcef525e 100644 --- a/common/repositories/group_leaders_repository.h +++ b/common/repositories/group_leaders_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GROUP_LEADERS_REPOSITORY_H #define EQEMU_GROUP_LEADERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_group_leaders_repository.h" class GroupLeadersRepository: public BaseGroupLeadersRepository { diff --git a/common/repositories/guild_bank_repository.h b/common/repositories/guild_bank_repository.h index d23b66653..502844804 100644 --- a/common/repositories/guild_bank_repository.h +++ b/common/repositories/guild_bank_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GUILD_BANK_REPOSITORY_H #define EQEMU_GUILD_BANK_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" class GuildBankRepository { public: @@ -58,7 +38,7 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string InsertColumnsRaw() @@ -73,7 +53,7 @@ public: insert_columns.push_back(column); } - return std::string(implode(", ", insert_columns)); + return std::string(Strings::Implode(", ", insert_columns)); } static std::string TableName() @@ -189,15 +169,15 @@ public: update_values.push_back(columns[2] + " = " + std::to_string(guild_bank_entry.slot)); update_values.push_back(columns[3] + " = " + std::to_string(guild_bank_entry.itemid)); update_values.push_back(columns[4] + " = " + std::to_string(guild_bank_entry.qty)); - update_values.push_back(columns[5] + " = '" + EscapeString(guild_bank_entry.donator) + "'"); + update_values.push_back(columns[5] + " = '" + Strings::Escape(guild_bank_entry.donator) + "'"); update_values.push_back(columns[6] + " = " + std::to_string(guild_bank_entry.permissions)); - update_values.push_back(columns[7] + " = '" + EscapeString(guild_bank_entry.whofor) + "'"); + update_values.push_back(columns[7] + " = '" + Strings::Escape(guild_bank_entry.whofor) + "'"); auto results = database.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), guild_bank_entry. ) @@ -217,15 +197,15 @@ public: insert_values.push_back(std::to_string(guild_bank_entry.slot)); insert_values.push_back(std::to_string(guild_bank_entry.itemid)); insert_values.push_back(std::to_string(guild_bank_entry.qty)); - insert_values.push_back("'" + EscapeString(guild_bank_entry.donator) + "'"); + insert_values.push_back("'" + Strings::Escape(guild_bank_entry.donator) + "'"); insert_values.push_back(std::to_string(guild_bank_entry.permissions)); - insert_values.push_back("'" + EscapeString(guild_bank_entry.whofor) + "'"); + insert_values.push_back("'" + Strings::Escape(guild_bank_entry.whofor) + "'"); auto results = database.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -253,11 +233,11 @@ public: insert_values.push_back(std::to_string(guild_bank_entry.slot)); insert_values.push_back(std::to_string(guild_bank_entry.itemid)); insert_values.push_back(std::to_string(guild_bank_entry.qty)); - insert_values.push_back("'" + EscapeString(guild_bank_entry.donator) + "'"); + insert_values.push_back("'" + Strings::Escape(guild_bank_entry.donator) + "'"); insert_values.push_back(std::to_string(guild_bank_entry.permissions)); - insert_values.push_back("'" + EscapeString(guild_bank_entry.whofor) + "'"); + insert_values.push_back("'" + Strings::Escape(guild_bank_entry.whofor) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -266,7 +246,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/guild_members_repository.h b/common/repositories/guild_members_repository.h deleted file mode 100644 index 3afa2f198..000000000 --- a/common/repositories/guild_members_repository.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef EQEMU_GUILD_MEMBERS_REPOSITORY_H -#define EQEMU_GUILD_MEMBERS_REPOSITORY_H - -#include "../database.h" -#include "../string_util.h" -#include "base/base_guild_members_repository.h" - -class GuildMembersRepository: public BaseGuildMembersRepository { -public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * GuildMembersRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * GuildMembersRepository::GetWhereNeverExpires() - * GuildMembersRepository::GetWhereXAndY() - * GuildMembersRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - - // Custom extended repository methods here - -}; - -#endif //EQEMU_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/guild_ranks_repository.h b/common/repositories/guild_ranks_repository.h index 949227b49..1a5a00455 100644 --- a/common/repositories/guild_ranks_repository.h +++ b/common/repositories/guild_ranks_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GUILD_RANKS_REPOSITORY_H #define EQEMU_GUILD_RANKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_guild_ranks_repository.h" class GuildRanksRepository: public BaseGuildRanksRepository { diff --git a/common/repositories/guild_relations_repository.h b/common/repositories/guild_relations_repository.h index 59b5cca5e..a86c80c64 100644 --- a/common/repositories/guild_relations_repository.h +++ b/common/repositories/guild_relations_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GUILD_RELATIONS_REPOSITORY_H #define EQEMU_GUILD_RELATIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_guild_relations_repository.h" class GuildRelationsRepository: public BaseGuildRelationsRepository { diff --git a/common/repositories/guilds_repository.h b/common/repositories/guilds_repository.h index c563f5cad..b55510156 100644 --- a/common/repositories/guilds_repository.h +++ b/common/repositories/guilds_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_GUILDS_REPOSITORY_H #define EQEMU_GUILDS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_guilds_repository.h" class GuildsRepository: public BaseGuildsRepository { diff --git a/common/repositories/hackers_repository.h b/common/repositories/hackers_repository.h index 89c5de5b1..516ab0e6f 100644 --- a/common/repositories/hackers_repository.h +++ b/common/repositories/hackers_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_HACKERS_REPOSITORY_H #define EQEMU_HACKERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_hackers_repository.h" class HackersRepository: public BaseHackersRepository { diff --git a/common/repositories/horses_repository.h b/common/repositories/horses_repository.h index 66211d3ca..18c1abbfc 100644 --- a/common/repositories/horses_repository.h +++ b/common/repositories/horses_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_HORSES_REPOSITORY_H #define EQEMU_HORSES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_horses_repository.h" class HorsesRepository: public BaseHorsesRepository { diff --git a/common/repositories/instance_list_player_repository.h b/common/repositories/instance_list_player_repository.h index 3a526a73e..8a8e31c0f 100644 --- a/common/repositories/instance_list_player_repository.h +++ b/common/repositories/instance_list_player_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_INSTANCE_LIST_PLAYER_REPOSITORY_H #define EQEMU_INSTANCE_LIST_PLAYER_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_instance_list_player_repository.h" class InstanceListPlayerRepository: public BaseInstanceListPlayerRepository { @@ -77,7 +57,7 @@ public: insert_values.push_back(std::to_string(instance_list_player_entry.id)); insert_values.push_back(std::to_string(instance_list_player_entry.charid)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -87,12 +67,33 @@ public: "INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = VALUES(id)", TableName(), ColumnsRaw(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); return (results.Success() ? results.RowsAffected() : 0); } + + static bool ReplaceOne(Database& db, InstanceListPlayer e) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.charid)); + + auto results = db.QueryDatabase( + fmt::format( + "REPLACE INTO {} VALUES ({})", + TableName(), + Strings::Implode(",", v) + ) + ); + if (results.Success()) { + return true; + } + + return false; + } }; #endif //EQEMU_INSTANCE_LIST_PLAYER_REPOSITORY_H diff --git a/common/repositories/instance_list_repository.h b/common/repositories/instance_list_repository.h index 6af82e302..e643383e2 100644 --- a/common/repositories/instance_list_repository.h +++ b/common/repositories/instance_list_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_INSTANCE_LIST_REPOSITORY_H #define EQEMU_INSTANCE_LIST_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_instance_list_repository.h" class InstanceListRepository: public BaseInstanceListRepository { diff --git a/common/repositories/inventory_repository.h b/common/repositories/inventory_repository.h index 176cd2989..8b4b859ee 100644 --- a/common/repositories/inventory_repository.h +++ b/common/repositories/inventory_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_INVENTORY_REPOSITORY_H #define EQEMU_INVENTORY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_inventory_repository.h" class InventoryRepository: public BaseInventoryRepository { diff --git a/common/repositories/inventory_snapshots_repository.h b/common/repositories/inventory_snapshots_repository.h index 2ad48abe4..742810a25 100644 --- a/common/repositories/inventory_snapshots_repository.h +++ b/common/repositories/inventory_snapshots_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H #define EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_inventory_snapshots_repository.h" class InventorySnapshotsRepository: public BaseInventorySnapshotsRepository { diff --git a/common/repositories/inventory_versions_repository.h b/common/repositories/inventory_versions_repository.h index 4469756de..7b279a6fe 100644 --- a/common/repositories/inventory_versions_repository.h +++ b/common/repositories/inventory_versions_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_INVENTORY_VERSIONS_REPOSITORY_H #define EQEMU_INVENTORY_VERSIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" class InventoryVersionsRepository { public: @@ -48,7 +28,7 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string InsertColumnsRaw() @@ -63,7 +43,7 @@ public: insert_columns.push_back(column); } - return std::string(implode(", ", insert_columns)); + return std::string(Strings::Implode(", ", insert_columns)); } static std::string TableName() @@ -172,7 +152,7 @@ public: fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), inventory_versions_entry. ) @@ -195,7 +175,7 @@ public: fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -222,7 +202,7 @@ public: insert_values.push_back(std::to_string(inventory_versions_entry.step)); insert_values.push_back(std::to_string(inventory_versions_entry.bot_step)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -231,7 +211,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/ip_exemptions_repository.h b/common/repositories/ip_exemptions_repository.h index e21ea22a0..64b5f7603 100644 --- a/common/repositories/ip_exemptions_repository.h +++ b/common/repositories/ip_exemptions_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_IP_EXEMPTIONS_REPOSITORY_H #define EQEMU_IP_EXEMPTIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_ip_exemptions_repository.h" class IpExemptionsRepository: public BaseIpExemptionsRepository { diff --git a/common/repositories/item_tick_repository.h b/common/repositories/item_tick_repository.h index 0cd798479..352595ac5 100644 --- a/common/repositories/item_tick_repository.h +++ b/common/repositories/item_tick_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ITEM_TICK_REPOSITORY_H #define EQEMU_ITEM_TICK_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_item_tick_repository.h" class ItemTickRepository: public BaseItemTickRepository { diff --git a/common/repositories/items_repository.h b/common/repositories/items_repository.h index 20be4f024..aac7d3697 100644 --- a/common/repositories/items_repository.h +++ b/common/repositories/items_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ITEMS_REPOSITORY_H #define EQEMU_ITEMS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_items_repository.h" class ItemsRepository: public BaseItemsRepository { diff --git a/common/repositories/ldon_trap_entries_repository.h b/common/repositories/ldon_trap_entries_repository.h index 38847056b..e2d6a882a 100644 --- a/common/repositories/ldon_trap_entries_repository.h +++ b/common/repositories/ldon_trap_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LDON_TRAP_ENTRIES_REPOSITORY_H #define EQEMU_LDON_TRAP_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_ldon_trap_entries_repository.h" class LdonTrapEntriesRepository: public BaseLdonTrapEntriesRepository { diff --git a/common/repositories/ldon_trap_templates_repository.h b/common/repositories/ldon_trap_templates_repository.h index 1f0aaffc1..7d94f80b4 100644 --- a/common/repositories/ldon_trap_templates_repository.h +++ b/common/repositories/ldon_trap_templates_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LDON_TRAP_TEMPLATES_REPOSITORY_H #define EQEMU_LDON_TRAP_TEMPLATES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_ldon_trap_templates_repository.h" class LdonTrapTemplatesRepository: public BaseLdonTrapTemplatesRepository { diff --git a/common/repositories/level_exp_mods_repository.h b/common/repositories/level_exp_mods_repository.h index cd52eb4fb..6bc893aed 100644 --- a/common/repositories/level_exp_mods_repository.h +++ b/common/repositories/level_exp_mods_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LEVEL_EXP_MODS_REPOSITORY_H #define EQEMU_LEVEL_EXP_MODS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_level_exp_mods_repository.h" class LevelExpModsRepository: public BaseLevelExpModsRepository { diff --git a/common/repositories/lfguild_repository.h b/common/repositories/lfguild_repository.h index 202e0c0dd..9f415c944 100644 --- a/common/repositories/lfguild_repository.h +++ b/common/repositories/lfguild_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LFGUILD_REPOSITORY_H #define EQEMU_LFGUILD_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_lfguild_repository.h" class LfguildRepository: public BaseLfguildRepository { diff --git a/common/repositories/login_accounts_repository.h b/common/repositories/login_accounts_repository.h index 0bc1a1340..2ad6797ae 100644 --- a/common/repositories/login_accounts_repository.h +++ b/common/repositories/login_accounts_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOGIN_ACCOUNTS_REPOSITORY_H #define EQEMU_LOGIN_ACCOUNTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_login_accounts_repository.h" class LoginAccountsRepository: public BaseLoginAccountsRepository { diff --git a/common/repositories/login_api_tokens_repository.h b/common/repositories/login_api_tokens_repository.h index a0b941c9e..46bfd3316 100644 --- a/common/repositories/login_api_tokens_repository.h +++ b/common/repositories/login_api_tokens_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOGIN_API_TOKENS_REPOSITORY_H #define EQEMU_LOGIN_API_TOKENS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_login_api_tokens_repository.h" class LoginApiTokensRepository: public BaseLoginApiTokensRepository { diff --git a/common/repositories/login_server_admins_repository.h b/common/repositories/login_server_admins_repository.h index cb75cf60e..8afda242c 100644 --- a/common/repositories/login_server_admins_repository.h +++ b/common/repositories/login_server_admins_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOGIN_SERVER_ADMINS_REPOSITORY_H #define EQEMU_LOGIN_SERVER_ADMINS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_login_server_admins_repository.h" class LoginServerAdminsRepository: public BaseLoginServerAdminsRepository { diff --git a/common/repositories/login_server_list_types_repository.h b/common/repositories/login_server_list_types_repository.h index 84554c769..37aef18eb 100644 --- a/common/repositories/login_server_list_types_repository.h +++ b/common/repositories/login_server_list_types_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H #define EQEMU_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_login_server_list_types_repository.h" class LoginServerListTypesRepository: public BaseLoginServerListTypesRepository { diff --git a/common/repositories/login_world_servers_repository.h b/common/repositories/login_world_servers_repository.h index c0af6aaa1..8cda28e32 100644 --- a/common/repositories/login_world_servers_repository.h +++ b/common/repositories/login_world_servers_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOGIN_WORLD_SERVERS_REPOSITORY_H #define EQEMU_LOGIN_WORLD_SERVERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_login_world_servers_repository.h" class LoginWorldServersRepository: public BaseLoginWorldServersRepository { diff --git a/common/repositories/logsys_categories_repository.h b/common/repositories/logsys_categories_repository.h index ab494f1e8..7d2f0898a 100644 --- a/common/repositories/logsys_categories_repository.h +++ b/common/repositories/logsys_categories_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOGSYS_CATEGORIES_REPOSITORY_H #define EQEMU_LOGSYS_CATEGORIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_logsys_categories_repository.h" class LogsysCategoriesRepository: public BaseLogsysCategoriesRepository { diff --git a/common/repositories/lootdrop_entries_repository.h b/common/repositories/lootdrop_entries_repository.h index 39d4abf3a..398ab46a4 100644 --- a/common/repositories/lootdrop_entries_repository.h +++ b/common/repositories/lootdrop_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOOTDROP_ENTRIES_REPOSITORY_H #define EQEMU_LOOTDROP_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_lootdrop_entries_repository.h" class LootdropEntriesRepository: public BaseLootdropEntriesRepository { diff --git a/common/repositories/lootdrop_repository.h b/common/repositories/lootdrop_repository.h index 732e23a0b..abd2ec844 100644 --- a/common/repositories/lootdrop_repository.h +++ b/common/repositories/lootdrop_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOOTDROP_REPOSITORY_H #define EQEMU_LOOTDROP_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_lootdrop_repository.h" class LootdropRepository: public BaseLootdropRepository { diff --git a/common/repositories/loottable_entries_repository.h b/common/repositories/loottable_entries_repository.h index 52720c10a..9e2c9d989 100644 --- a/common/repositories/loottable_entries_repository.h +++ b/common/repositories/loottable_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOOTTABLE_ENTRIES_REPOSITORY_H #define EQEMU_LOOTTABLE_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_loottable_entries_repository.h" class LoottableEntriesRepository: public BaseLoottableEntriesRepository { diff --git a/common/repositories/loottable_repository.h b/common/repositories/loottable_repository.h index c16d6cea7..ef9845c87 100644 --- a/common/repositories/loottable_repository.h +++ b/common/repositories/loottable_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_LOOTTABLE_REPOSITORY_H #define EQEMU_LOOTTABLE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_loottable_repository.h" class LoottableRepository: public BaseLoottableRepository { diff --git a/common/repositories/mail_repository.h b/common/repositories/mail_repository.h index 04aec17f2..c1e2934ae 100644 --- a/common/repositories/mail_repository.h +++ b/common/repositories/mail_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_MAIL_REPOSITORY_H #define EQEMU_MAIL_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_mail_repository.h" class MailRepository: public BaseMailRepository { diff --git a/common/repositories/merc_armorinfo_repository.h b/common/repositories/merc_armorinfo_repository.h new file mode 100644 index 000000000..6861ea0d0 --- /dev/null +++ b/common/repositories/merc_armorinfo_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_ARMORINFO_REPOSITORY_H +#define EQEMU_MERC_ARMORINFO_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_armorinfo_repository.h" + +class MercArmorinfoRepository: public BaseMercArmorinfoRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercArmorinfoRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercArmorinfoRepository::GetWhereNeverExpires() + * MercArmorinfoRepository::GetWhereXAndY() + * MercArmorinfoRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_ARMORINFO_REPOSITORY_H diff --git a/common/repositories/merc_buffs_repository.h b/common/repositories/merc_buffs_repository.h new file mode 100644 index 000000000..c8c56c206 --- /dev/null +++ b/common/repositories/merc_buffs_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_BUFFS_REPOSITORY_H +#define EQEMU_MERC_BUFFS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_buffs_repository.h" + +class MercBuffsRepository: public BaseMercBuffsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercBuffsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercBuffsRepository::GetWhereNeverExpires() + * MercBuffsRepository::GetWhereXAndY() + * MercBuffsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_BUFFS_REPOSITORY_H diff --git a/common/repositories/merc_inventory_repository.h b/common/repositories/merc_inventory_repository.h new file mode 100644 index 000000000..43a241564 --- /dev/null +++ b/common/repositories/merc_inventory_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_INVENTORY_REPOSITORY_H +#define EQEMU_MERC_INVENTORY_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_inventory_repository.h" + +class MercInventoryRepository: public BaseMercInventoryRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercInventoryRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercInventoryRepository::GetWhereNeverExpires() + * MercInventoryRepository::GetWhereXAndY() + * MercInventoryRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_INVENTORY_REPOSITORY_H diff --git a/common/repositories/merc_merchant_entries_repository.h b/common/repositories/merc_merchant_entries_repository.h new file mode 100644 index 000000000..2ad0a833b --- /dev/null +++ b/common/repositories/merc_merchant_entries_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_MERCHANT_ENTRIES_REPOSITORY_H +#define EQEMU_MERC_MERCHANT_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_merchant_entries_repository.h" + +class MercMerchantEntriesRepository: public BaseMercMerchantEntriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercMerchantEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercMerchantEntriesRepository::GetWhereNeverExpires() + * MercMerchantEntriesRepository::GetWhereXAndY() + * MercMerchantEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_MERCHANT_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_merchant_template_entries_repository.h b/common/repositories/merc_merchant_template_entries_repository.h new file mode 100644 index 000000000..8d60acfab --- /dev/null +++ b/common/repositories/merc_merchant_template_entries_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H +#define EQEMU_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_merchant_template_entries_repository.h" + +class MercMerchantTemplateEntriesRepository: public BaseMercMerchantTemplateEntriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercMerchantTemplateEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercMerchantTemplateEntriesRepository::GetWhereNeverExpires() + * MercMerchantTemplateEntriesRepository::GetWhereXAndY() + * MercMerchantTemplateEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_merchant_templates_repository.h b/common/repositories/merc_merchant_templates_repository.h new file mode 100644 index 000000000..b2798a201 --- /dev/null +++ b/common/repositories/merc_merchant_templates_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_MERCHANT_TEMPLATES_REPOSITORY_H +#define EQEMU_MERC_MERCHANT_TEMPLATES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_merchant_templates_repository.h" + +class MercMerchantTemplatesRepository: public BaseMercMerchantTemplatesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercMerchantTemplatesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercMerchantTemplatesRepository::GetWhereNeverExpires() + * MercMerchantTemplatesRepository::GetWhereXAndY() + * MercMerchantTemplatesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_MERCHANT_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/merc_name_types_repository.h b/common/repositories/merc_name_types_repository.h new file mode 100644 index 000000000..994241bd5 --- /dev/null +++ b/common/repositories/merc_name_types_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_NAME_TYPES_REPOSITORY_H +#define EQEMU_MERC_NAME_TYPES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_name_types_repository.h" + +class MercNameTypesRepository: public BaseMercNameTypesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercNameTypesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercNameTypesRepository::GetWhereNeverExpires() + * MercNameTypesRepository::GetWhereXAndY() + * MercNameTypesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_NAME_TYPES_REPOSITORY_H diff --git a/common/repositories/merc_npc_types_repository.h b/common/repositories/merc_npc_types_repository.h new file mode 100644 index 000000000..2604bda30 --- /dev/null +++ b/common/repositories/merc_npc_types_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_NPC_TYPES_REPOSITORY_H +#define EQEMU_MERC_NPC_TYPES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_npc_types_repository.h" + +class MercNpcTypesRepository: public BaseMercNpcTypesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercNpcTypesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercNpcTypesRepository::GetWhereNeverExpires() + * MercNpcTypesRepository::GetWhereXAndY() + * MercNpcTypesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_NPC_TYPES_REPOSITORY_H diff --git a/common/repositories/merc_spell_list_entries_repository.h b/common/repositories/merc_spell_list_entries_repository.h new file mode 100644 index 000000000..4a841a221 --- /dev/null +++ b/common/repositories/merc_spell_list_entries_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H +#define EQEMU_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_spell_list_entries_repository.h" + +class MercSpellListEntriesRepository: public BaseMercSpellListEntriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercSpellListEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercSpellListEntriesRepository::GetWhereNeverExpires() + * MercSpellListEntriesRepository::GetWhereXAndY() + * MercSpellListEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_spell_lists_repository.h b/common/repositories/merc_spell_lists_repository.h new file mode 100644 index 000000000..525149b49 --- /dev/null +++ b/common/repositories/merc_spell_lists_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_SPELL_LISTS_REPOSITORY_H +#define EQEMU_MERC_SPELL_LISTS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_spell_lists_repository.h" + +class MercSpellListsRepository: public BaseMercSpellListsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercSpellListsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercSpellListsRepository::GetWhereNeverExpires() + * MercSpellListsRepository::GetWhereXAndY() + * MercSpellListsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_SPELL_LISTS_REPOSITORY_H diff --git a/common/repositories/merc_stance_entries_repository.h b/common/repositories/merc_stance_entries_repository.h new file mode 100644 index 000000000..81ec095d1 --- /dev/null +++ b/common/repositories/merc_stance_entries_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_STANCE_ENTRIES_REPOSITORY_H +#define EQEMU_MERC_STANCE_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_stance_entries_repository.h" + +class MercStanceEntriesRepository: public BaseMercStanceEntriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercStanceEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercStanceEntriesRepository::GetWhereNeverExpires() + * MercStanceEntriesRepository::GetWhereXAndY() + * MercStanceEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_STANCE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_stats_repository.h b/common/repositories/merc_stats_repository.h new file mode 100644 index 000000000..383131a9f --- /dev/null +++ b/common/repositories/merc_stats_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_STATS_REPOSITORY_H +#define EQEMU_MERC_STATS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_stats_repository.h" + +class MercStatsRepository: public BaseMercStatsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercStatsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercStatsRepository::GetWhereNeverExpires() + * MercStatsRepository::GetWhereXAndY() + * MercStatsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_STATS_REPOSITORY_H diff --git a/common/repositories/merc_subtypes_repository.h b/common/repositories/merc_subtypes_repository.h new file mode 100644 index 000000000..8bad2d198 --- /dev/null +++ b/common/repositories/merc_subtypes_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_SUBTYPES_REPOSITORY_H +#define EQEMU_MERC_SUBTYPES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_subtypes_repository.h" + +class MercSubtypesRepository: public BaseMercSubtypesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercSubtypesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercSubtypesRepository::GetWhereNeverExpires() + * MercSubtypesRepository::GetWhereXAndY() + * MercSubtypesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_SUBTYPES_REPOSITORY_H diff --git a/common/repositories/merc_templates_repository.h b/common/repositories/merc_templates_repository.h new file mode 100644 index 000000000..714dcccef --- /dev/null +++ b/common/repositories/merc_templates_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_TEMPLATES_REPOSITORY_H +#define EQEMU_MERC_TEMPLATES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_templates_repository.h" + +class MercTemplatesRepository: public BaseMercTemplatesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercTemplatesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercTemplatesRepository::GetWhereNeverExpires() + * MercTemplatesRepository::GetWhereXAndY() + * MercTemplatesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/merc_types_repository.h b/common/repositories/merc_types_repository.h new file mode 100644 index 000000000..4d91145d5 --- /dev/null +++ b/common/repositories/merc_types_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_TYPES_REPOSITORY_H +#define EQEMU_MERC_TYPES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_types_repository.h" + +class MercTypesRepository: public BaseMercTypesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercTypesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercTypesRepository::GetWhereNeverExpires() + * MercTypesRepository::GetWhereXAndY() + * MercTypesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_TYPES_REPOSITORY_H diff --git a/common/repositories/merc_weaponinfo_repository.h b/common/repositories/merc_weaponinfo_repository.h new file mode 100644 index 000000000..0c73fd71a --- /dev/null +++ b/common/repositories/merc_weaponinfo_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERC_WEAPONINFO_REPOSITORY_H +#define EQEMU_MERC_WEAPONINFO_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_merc_weaponinfo_repository.h" + +class MercWeaponinfoRepository: public BaseMercWeaponinfoRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercWeaponinfoRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercWeaponinfoRepository::GetWhereNeverExpires() + * MercWeaponinfoRepository::GetWhereXAndY() + * MercWeaponinfoRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERC_WEAPONINFO_REPOSITORY_H diff --git a/common/repositories/merchantlist_repository.h b/common/repositories/merchantlist_repository.h index ab0229315..37f4c82ef 100644 --- a/common/repositories/merchantlist_repository.h +++ b/common/repositories/merchantlist_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_MERCHANTLIST_REPOSITORY_H #define EQEMU_MERCHANTLIST_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_merchantlist_repository.h" class MerchantlistRepository: public BaseMerchantlistRepository { diff --git a/common/repositories/merchantlist_temp_repository.h b/common/repositories/merchantlist_temp_repository.h index ceaae788f..0cbb7669e 100644 --- a/common/repositories/merchantlist_temp_repository.h +++ b/common/repositories/merchantlist_temp_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_MERCHANTLIST_TEMP_REPOSITORY_H #define EQEMU_MERCHANTLIST_TEMP_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_merchantlist_temp_repository.h" class MerchantlistTempRepository: public BaseMerchantlistTempRepository { diff --git a/common/repositories/mercs_repository.h b/common/repositories/mercs_repository.h new file mode 100644 index 000000000..f339ae82c --- /dev/null +++ b/common/repositories/mercs_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_MERCS_REPOSITORY_H +#define EQEMU_MERCS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_mercs_repository.h" + +class MercsRepository: public BaseMercsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * MercsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * MercsRepository::GetWhereNeverExpires() + * MercsRepository::GetWhereXAndY() + * MercsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_MERCS_REPOSITORY_H diff --git a/common/repositories/name_filter_repository.h b/common/repositories/name_filter_repository.h index 3cf63f55b..43dc3ecf0 100644 --- a/common/repositories/name_filter_repository.h +++ b/common/repositories/name_filter_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NAME_FILTER_REPOSITORY_H #define EQEMU_NAME_FILTER_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_name_filter_repository.h" class NameFilterRepository: public BaseNameFilterRepository { diff --git a/common/repositories/npc_emotes_repository.h b/common/repositories/npc_emotes_repository.h index ef855b1f0..438ad9be4 100644 --- a/common/repositories/npc_emotes_repository.h +++ b/common/repositories/npc_emotes_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_EMOTES_REPOSITORY_H #define EQEMU_NPC_EMOTES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_emotes_repository.h" class NpcEmotesRepository: public BaseNpcEmotesRepository { diff --git a/common/repositories/npc_faction_entries_repository.h b/common/repositories/npc_faction_entries_repository.h index 48182fd24..eb9d92b44 100644 --- a/common/repositories/npc_faction_entries_repository.h +++ b/common/repositories/npc_faction_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_FACTION_ENTRIES_REPOSITORY_H #define EQEMU_NPC_FACTION_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_faction_entries_repository.h" class NpcFactionEntriesRepository: public BaseNpcFactionEntriesRepository { diff --git a/common/repositories/npc_faction_repository.h b/common/repositories/npc_faction_repository.h index 73bf0a94a..0e4cbbbc4 100644 --- a/common/repositories/npc_faction_repository.h +++ b/common/repositories/npc_faction_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_FACTION_REPOSITORY_H #define EQEMU_NPC_FACTION_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_faction_repository.h" class NpcFactionRepository: public BaseNpcFactionRepository { diff --git a/common/repositories/npc_scale_global_base_repository.h b/common/repositories/npc_scale_global_base_repository.h index b0748e18a..1ef4ffb1a 100644 --- a/common/repositories/npc_scale_global_base_repository.h +++ b/common/repositories/npc_scale_global_base_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H #define EQEMU_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_scale_global_base_repository.h" class NpcScaleGlobalBaseRepository: public BaseNpcScaleGlobalBaseRepository { diff --git a/common/repositories/npc_spells_effects_entries_repository.h b/common/repositories/npc_spells_effects_entries_repository.h index 101edc188..87570ceef 100644 --- a/common/repositories/npc_spells_effects_entries_repository.h +++ b/common/repositories/npc_spells_effects_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H #define EQEMU_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_spells_effects_entries_repository.h" class NpcSpellsEffectsEntriesRepository: public BaseNpcSpellsEffectsEntriesRepository { diff --git a/common/repositories/npc_spells_effects_repository.h b/common/repositories/npc_spells_effects_repository.h index eeeb500b9..46a56819a 100644 --- a/common/repositories/npc_spells_effects_repository.h +++ b/common/repositories/npc_spells_effects_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_SPELLS_EFFECTS_REPOSITORY_H #define EQEMU_NPC_SPELLS_EFFECTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_spells_effects_repository.h" class NpcSpellsEffectsRepository: public BaseNpcSpellsEffectsRepository { diff --git a/common/repositories/npc_spells_entries_repository.h b/common/repositories/npc_spells_entries_repository.h index 15a971843..4b21beff4 100644 --- a/common/repositories/npc_spells_entries_repository.h +++ b/common/repositories/npc_spells_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_SPELLS_ENTRIES_REPOSITORY_H #define EQEMU_NPC_SPELLS_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_spells_entries_repository.h" class NpcSpellsEntriesRepository: public BaseNpcSpellsEntriesRepository { diff --git a/common/repositories/npc_spells_repository.h b/common/repositories/npc_spells_repository.h index 3ecd8d4f9..e9b017085 100644 --- a/common/repositories/npc_spells_repository.h +++ b/common/repositories/npc_spells_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_SPELLS_REPOSITORY_H #define EQEMU_NPC_SPELLS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_spells_repository.h" class NpcSpellsRepository: public BaseNpcSpellsRepository { diff --git a/common/repositories/npc_types_repository.h b/common/repositories/npc_types_repository.h index d89a306a0..a8f8a53a3 100644 --- a/common/repositories/npc_types_repository.h +++ b/common/repositories/npc_types_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_TYPES_REPOSITORY_H #define EQEMU_NPC_TYPES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_types_repository.h" class NpcTypesRepository: public BaseNpcTypesRepository { diff --git a/common/repositories/npc_types_tint_repository.h b/common/repositories/npc_types_tint_repository.h index 21bf02322..aa501acf8 100644 --- a/common/repositories/npc_types_tint_repository.h +++ b/common/repositories/npc_types_tint_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_NPC_TYPES_TINT_REPOSITORY_H #define EQEMU_NPC_TYPES_TINT_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_npc_types_tint_repository.h" class NpcTypesTintRepository: public BaseNpcTypesTintRepository { diff --git a/common/repositories/object_contents_repository.h b/common/repositories/object_contents_repository.h index c7a308241..6ed16bd33 100644 --- a/common/repositories/object_contents_repository.h +++ b/common/repositories/object_contents_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_OBJECT_CONTENTS_REPOSITORY_H #define EQEMU_OBJECT_CONTENTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_object_contents_repository.h" class ObjectContentsRepository: public BaseObjectContentsRepository { diff --git a/common/repositories/object_repository.h b/common/repositories/object_repository.h index 30df82443..151572b35 100644 --- a/common/repositories/object_repository.h +++ b/common/repositories/object_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_OBJECT_REPOSITORY_H #define EQEMU_OBJECT_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_object_repository.h" class ObjectRepository: public BaseObjectRepository { diff --git a/common/repositories/perl_event_export_settings_repository.h b/common/repositories/perl_event_export_settings_repository.h index 1c441bb76..a7e195f54 100644 --- a/common/repositories/perl_event_export_settings_repository.h +++ b/common/repositories/perl_event_export_settings_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H #define EQEMU_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_perl_event_export_settings_repository.h" class PerlEventExportSettingsRepository: public BasePerlEventExportSettingsRepository { diff --git a/common/repositories/petitions_repository.h b/common/repositories/petitions_repository.h index 505f97986..0625845a8 100644 --- a/common/repositories/petitions_repository.h +++ b/common/repositories/petitions_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_PETITIONS_REPOSITORY_H #define EQEMU_PETITIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_petitions_repository.h" class PetitionsRepository: public BasePetitionsRepository { diff --git a/common/repositories/pets_beastlord_data_repository.h b/common/repositories/pets_beastlord_data_repository.h index 8d4bb55da..598c154d2 100644 --- a/common/repositories/pets_beastlord_data_repository.h +++ b/common/repositories/pets_beastlord_data_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_PETS_BEASTLORD_DATA_REPOSITORY_H #define EQEMU_PETS_BEASTLORD_DATA_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_pets_beastlord_data_repository.h" class PetsBeastlordDataRepository: public BasePetsBeastlordDataRepository { diff --git a/common/repositories/pets_equipmentset_entries_repository.h b/common/repositories/pets_equipmentset_entries_repository.h index 866b65e31..b66f739c1 100644 --- a/common/repositories/pets_equipmentset_entries_repository.h +++ b/common/repositories/pets_equipmentset_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H #define EQEMU_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_pets_equipmentset_entries_repository.h" class PetsEquipmentsetEntriesRepository: public BasePetsEquipmentsetEntriesRepository { diff --git a/common/repositories/pets_equipmentset_repository.h b/common/repositories/pets_equipmentset_repository.h index 1042972ab..e676ebe5b 100644 --- a/common/repositories/pets_equipmentset_repository.h +++ b/common/repositories/pets_equipmentset_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_PETS_EQUIPMENTSET_REPOSITORY_H #define EQEMU_PETS_EQUIPMENTSET_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_pets_equipmentset_repository.h" class PetsEquipmentsetRepository: public BasePetsEquipmentsetRepository { diff --git a/common/repositories/pets_repository.h b/common/repositories/pets_repository.h index 8aa99fde5..df8e66bc8 100644 --- a/common/repositories/pets_repository.h +++ b/common/repositories/pets_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_PETS_REPOSITORY_H #define EQEMU_PETS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_pets_repository.h" class PetsRepository: public BasePetsRepository { diff --git a/common/repositories/player_titlesets_repository.h b/common/repositories/player_titlesets_repository.h index 330b9ba48..f2f679347 100644 --- a/common/repositories/player_titlesets_repository.h +++ b/common/repositories/player_titlesets_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_PLAYER_TITLESETS_REPOSITORY_H #define EQEMU_PLAYER_TITLESETS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_player_titlesets_repository.h" class PlayerTitlesetsRepository: public BasePlayerTitlesetsRepository { diff --git a/common/repositories/proximities_repository.h b/common/repositories/proximities_repository.h deleted file mode 100644 index 3044c2348..000000000 --- a/common/repositories/proximities_repository.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef EQEMU_PROXIMITIES_REPOSITORY_H -#define EQEMU_PROXIMITIES_REPOSITORY_H - -#include "../database.h" -#include "../string_util.h" -#include "base/base_proximities_repository.h" - -class ProximitiesRepository: public BaseProximitiesRepository { -public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * ProximitiesRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * ProximitiesRepository::GetWhereNeverExpires() - * ProximitiesRepository::GetWhereXAndY() - * ProximitiesRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - - // Custom extended repository methods here - -}; - -#endif //EQEMU_PROXIMITIES_REPOSITORY_H diff --git a/common/repositories/quest_globals_repository.h b/common/repositories/quest_globals_repository.h index 6be19d286..efdc6d5f0 100644 --- a/common/repositories/quest_globals_repository.h +++ b/common/repositories/quest_globals_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_QUEST_GLOBALS_REPOSITORY_H #define EQEMU_QUEST_GLOBALS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_quest_globals_repository.h" class QuestGlobalsRepository: public BaseQuestGlobalsRepository { diff --git a/common/repositories/raid_details_repository.h b/common/repositories/raid_details_repository.h index a9763096c..524903cf2 100644 --- a/common/repositories/raid_details_repository.h +++ b/common/repositories/raid_details_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_RAID_DETAILS_REPOSITORY_H #define EQEMU_RAID_DETAILS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_raid_details_repository.h" class RaidDetailsRepository: public BaseRaidDetailsRepository { diff --git a/common/repositories/raid_leaders_repository.h b/common/repositories/raid_leaders_repository.h index 592f0ca01..0b6c344ff 100644 --- a/common/repositories/raid_leaders_repository.h +++ b/common/repositories/raid_leaders_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_RAID_LEADERS_REPOSITORY_H #define EQEMU_RAID_LEADERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" class RaidLeadersRepository { public: @@ -60,7 +40,7 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string InsertColumnsRaw() @@ -75,7 +55,7 @@ public: insert_columns.push_back(column); } - return std::string(implode(", ", insert_columns)); + return std::string(Strings::Implode(", ", insert_columns)); } static std::string TableName() @@ -190,19 +170,19 @@ public: update_values.push_back(columns[0] + " = " + std::to_string(raid_leaders_entry.gid)); update_values.push_back(columns[1] + " = " + std::to_string(raid_leaders_entry.rid)); - update_values.push_back(columns[2] + " = '" + EscapeString(raid_leaders_entry.marknpc) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(raid_leaders_entry.maintank) + "'"); - update_values.push_back(columns[4] + " = '" + EscapeString(raid_leaders_entry.assist) + "'"); - update_values.push_back(columns[5] + " = '" + EscapeString(raid_leaders_entry.puller) + "'"); - update_values.push_back(columns[6] + " = '" + EscapeString(raid_leaders_entry.leadershipaa) + "'"); - update_values.push_back(columns[7] + " = '" + EscapeString(raid_leaders_entry.mentoree) + "'"); + update_values.push_back(columns[2] + " = '" + Strings::Escape(raid_leaders_entry.marknpc) + "'"); + update_values.push_back(columns[3] + " = '" + Strings::Escape(raid_leaders_entry.maintank) + "'"); + update_values.push_back(columns[4] + " = '" + Strings::Escape(raid_leaders_entry.assist) + "'"); + update_values.push_back(columns[5] + " = '" + Strings::Escape(raid_leaders_entry.puller) + "'"); + update_values.push_back(columns[6] + " = '" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'"); + update_values.push_back(columns[7] + " = '" + Strings::Escape(raid_leaders_entry.mentoree) + "'"); update_values.push_back(columns[8] + " = " + std::to_string(raid_leaders_entry.mentor_percent)); auto results = database.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), raid_leaders_entry. ) @@ -219,19 +199,19 @@ public: insert_values.push_back(std::to_string(raid_leaders_entry.gid)); insert_values.push_back(std::to_string(raid_leaders_entry.rid)); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.marknpc) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.maintank) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.assist) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.puller) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.leadershipaa) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.mentoree) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.marknpc) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.maintank) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.assist) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.puller) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.mentoree) + "'"); insert_values.push_back(std::to_string(raid_leaders_entry.mentor_percent)); auto results = database.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -256,15 +236,15 @@ public: insert_values.push_back(std::to_string(raid_leaders_entry.gid)); insert_values.push_back(std::to_string(raid_leaders_entry.rid)); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.marknpc) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.maintank) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.assist) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.puller) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.leadershipaa) + "'"); - insert_values.push_back("'" + EscapeString(raid_leaders_entry.mentoree) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.marknpc) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.maintank) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.assist) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.puller) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'"); + insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.mentoree) + "'"); insert_values.push_back(std::to_string(raid_leaders_entry.mentor_percent)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -273,7 +253,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/raid_members_repository.h b/common/repositories/raid_members_repository.h index 1d904dfa6..e8f5ddb82 100644 --- a/common/repositories/raid_members_repository.h +++ b/common/repositories/raid_members_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_RAID_MEMBERS_REPOSITORY_H #define EQEMU_RAID_MEMBERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_raid_members_repository.h" class RaidMembersRepository: public BaseRaidMembersRepository { diff --git a/common/repositories/reports_repository.h b/common/repositories/reports_repository.h index 4b94ce7c8..96639f9d1 100644 --- a/common/repositories/reports_repository.h +++ b/common/repositories/reports_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_REPORTS_REPOSITORY_H #define EQEMU_REPORTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_reports_repository.h" class ReportsRepository: public BaseReportsRepository { diff --git a/common/repositories/respawn_times_repository.h b/common/repositories/respawn_times_repository.h index 09561f056..a4d7179b6 100644 --- a/common/repositories/respawn_times_repository.h +++ b/common/repositories/respawn_times_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_RESPAWN_TIMES_REPOSITORY_H #define EQEMU_RESPAWN_TIMES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_respawn_times_repository.h" class RespawnTimesRepository: public BaseRespawnTimesRepository { diff --git a/common/repositories/rule_sets_repository.h b/common/repositories/rule_sets_repository.h index 20fae60d6..d4633c422 100644 --- a/common/repositories/rule_sets_repository.h +++ b/common/repositories/rule_sets_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_RULE_SETS_REPOSITORY_H #define EQEMU_RULE_SETS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_rule_sets_repository.h" class RuleSetsRepository: public BaseRuleSetsRepository { @@ -64,7 +44,53 @@ public: */ // Custom extended repository methods here + static int GetRuleSetID(Database& db, std::string rule_set_name) + { + const auto query = fmt::format( + "SELECT ruleset_id FROM {} WHERE `name` = '{}'", + TableName(), + Strings::Escape(rule_set_name) + ); + auto results = db.QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + return -1; + } + auto row = results.begin(); + return std::stoi(row[0]); + } + + static int CreateNewRuleSet(Database& db, std::string rule_set_name) + { + const auto query = fmt::format( + "INSERT INTO {} (`name`) VALUES ('{}')", + TableName(), + rule_set_name + ); + auto results = db.QueryDatabase(query); + if (!results.Success() || !results.RowsAffected()) { + return -1; + } + + return static_cast(results.LastInsertedID()); + } + + static std::string GetRuleSetName(Database& db, int rule_set_id) + { + const auto query = fmt::format( + "SELECT `name` FROM {} WHERE ruleset_id = {}", + TableName(), + rule_set_id + ); + auto results = db.QueryDatabase(query); + if (!results.Success() || !results.RowsAffected()) { + return std::string(); + } + + auto row = results.begin(); + + return std::string(row[0]); + } }; #endif //EQEMU_RULE_SETS_REPOSITORY_H diff --git a/common/repositories/rule_values_repository.h b/common/repositories/rule_values_repository.h index 703fd07a1..072175d5f 100644 --- a/common/repositories/rule_values_repository.h +++ b/common/repositories/rule_values_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_RULE_VALUES_REPOSITORY_H #define EQEMU_RULE_VALUES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_rule_values_repository.h" class RuleValuesRepository: public BaseRuleValuesRepository { @@ -64,6 +44,87 @@ public: */ // Custom extended repository methods here + static std::vector GetRuleNames(Database &db, int rule_set_id) + { + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "SELECT rule_name FROM {} WHERE ruleset_id = {}", + TableName(), + rule_set_id + ) + ); + if (!results.Success() || !results.RowCount()) { + return v; + } + + for (auto row : results) { + v.push_back(row[0]); + } + + return v; + } + + static std::vector GetGroupedRules(Database &db) + { + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "SELECT rule_name FROM {} GROUP BY rule_name", + TableName() + ) + ); + if (!results.Success() || !results.RowCount()) { + return v; + } + + for (auto row : results) { + v.push_back(row[0]); + } + + return v; + } + + static bool DeleteOrphanedRules(Database& db, std::vector& v) + { + const auto query = fmt::format( + "DELETE FROM {} WHERE rule_name IN ({})", + TableName(), + Strings::ImplodePair(",", std::pair('\'', '\''), v) + ); + + return db.QueryDatabase(query).Success(); + } + + static bool InjectRules(Database& db, std::vector>& v) + { + const auto query = fmt::format( + "REPLACE INTO {} (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}", + TableName(), + Strings::ImplodePair( + ",", + std::pair('(', ')'), + join_tuple(",", std::pair('\'', '\''), v) + ) + ); + + return db.QueryDatabase(query).Success(); + } + + static bool UpdateRuleNote(Database& db, int rule_set_id, std::string rule_name, std::string notes) + { + const auto query = fmt::format( + "UPDATE {} SET notes = '{}' WHERE ruleset_id = {} AND rule_name = '{}'", + TableName(), + Strings::Escape(notes), + rule_set_id, + rule_name + ); + + return db.QueryDatabase(query).Success(); + } }; diff --git a/common/repositories/saylink_repository.h b/common/repositories/saylink_repository.h index a2abaceae..4efc13ff1 100644 --- a/common/repositories/saylink_repository.h +++ b/common/repositories/saylink_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SAYLINK_REPOSITORY_H #define EQEMU_SAYLINK_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_saylink_repository.h" class SaylinkRepository: public BaseSaylinkRepository { diff --git a/common/repositories/server_scheduled_events_repository.h b/common/repositories/server_scheduled_events_repository.h index edcc21dbc..e42fa372d 100644 --- a/common/repositories/server_scheduled_events_repository.h +++ b/common/repositories/server_scheduled_events_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SERVER_SCHEDULED_EVENTS_REPOSITORY_H #define EQEMU_SERVER_SCHEDULED_EVENTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_server_scheduled_events_repository.h" class ServerScheduledEventsRepository: public BaseServerScheduledEventsRepository { diff --git a/common/repositories/shared_task_activity_state_repository.h b/common/repositories/shared_task_activity_state_repository.h index 1e48c7e76..25aaa4391 100644 --- a/common/repositories/shared_task_activity_state_repository.h +++ b/common/repositories/shared_task_activity_state_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H #define EQEMU_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_shared_task_activity_state_repository.h" class SharedTaskActivityStateRepository: public BaseSharedTaskActivityStateRepository { diff --git a/common/repositories/shared_task_dynamic_zones_repository.h b/common/repositories/shared_task_dynamic_zones_repository.h index 61ee9c9f5..e3148cd9e 100644 --- a/common/repositories/shared_task_dynamic_zones_repository.h +++ b/common/repositories/shared_task_dynamic_zones_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H #define EQEMU_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_shared_task_dynamic_zones_repository.h" class SharedTaskDynamicZonesRepository: public BaseSharedTaskDynamicZonesRepository { diff --git a/common/repositories/shared_task_members_repository.h b/common/repositories/shared_task_members_repository.h index 51b8606ad..d55289c17 100644 --- a/common/repositories/shared_task_members_repository.h +++ b/common/repositories/shared_task_members_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SHARED_TASK_MEMBERS_REPOSITORY_H #define EQEMU_SHARED_TASK_MEMBERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_shared_task_members_repository.h" class SharedTaskMembersRepository: public BaseSharedTaskMembersRepository { diff --git a/common/repositories/shared_tasks_repository.h b/common/repositories/shared_tasks_repository.h index 3ec764beb..827597b84 100644 --- a/common/repositories/shared_tasks_repository.h +++ b/common/repositories/shared_tasks_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SHARED_TASKS_REPOSITORY_H #define EQEMU_SHARED_TASKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_shared_tasks_repository.h" class SharedTasksRepository: public BaseSharedTasksRepository { diff --git a/common/repositories/sharedbank_repository.h b/common/repositories/sharedbank_repository.h index 440412ff4..15243d83e 100644 --- a/common/repositories/sharedbank_repository.h +++ b/common/repositories/sharedbank_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SHAREDBANK_REPOSITORY_H #define EQEMU_SHAREDBANK_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" class SharedbankRepository { public: @@ -64,7 +44,7 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string InsertColumnsRaw() @@ -79,7 +59,7 @@ public: insert_columns.push_back(column); } - return std::string(implode(", ", insert_columns)); + return std::string(Strings::Implode(", ", insert_columns)); } static std::string TableName() @@ -206,13 +186,13 @@ public: update_values.push_back(columns[7] + " = " + std::to_string(sharedbank_entry.augslot4)); update_values.push_back(columns[8] + " = " + std::to_string(sharedbank_entry.augslot5)); update_values.push_back(columns[9] + " = " + std::to_string(sharedbank_entry.augslot6)); - update_values.push_back(columns[10] + " = '" + EscapeString(sharedbank_entry.custom_data) + "'"); + update_values.push_back(columns[10] + " = '" + Strings::Escape(sharedbank_entry.custom_data) + "'"); auto results = database.QueryDatabase( fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), sharedbank_entry. ) @@ -237,13 +217,13 @@ public: insert_values.push_back(std::to_string(sharedbank_entry.augslot4)); insert_values.push_back(std::to_string(sharedbank_entry.augslot5)); insert_values.push_back(std::to_string(sharedbank_entry.augslot6)); - insert_values.push_back("'" + EscapeString(sharedbank_entry.custom_data) + "'"); + insert_values.push_back("'" + Strings::Escape(sharedbank_entry.custom_data) + "'"); auto results = database.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -276,9 +256,9 @@ public: insert_values.push_back(std::to_string(sharedbank_entry.augslot4)); insert_values.push_back(std::to_string(sharedbank_entry.augslot5)); insert_values.push_back(std::to_string(sharedbank_entry.augslot6)); - insert_values.push_back("'" + EscapeString(sharedbank_entry.custom_data) + "'"); + insert_values.push_back("'" + Strings::Escape(sharedbank_entry.custom_data) + "'"); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -287,7 +267,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/skill_caps_repository.h b/common/repositories/skill_caps_repository.h index 9ecbe24f2..6388bacc2 100644 --- a/common/repositories/skill_caps_repository.h +++ b/common/repositories/skill_caps_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SKILL_CAPS_REPOSITORY_H #define EQEMU_SKILL_CAPS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_skill_caps_repository.h" class SkillCapsRepository: public BaseSkillCapsRepository { diff --git a/common/repositories/spawn2_repository.h b/common/repositories/spawn2_repository.h index fd633c738..5b2dabcaa 100644 --- a/common/repositories/spawn2_repository.h +++ b/common/repositories/spawn2_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPAWN2_REPOSITORY_H #define EQEMU_SPAWN2_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spawn2_repository.h" class Spawn2Repository: public BaseSpawn2Repository { diff --git a/common/repositories/spawn_condition_values_repository.h b/common/repositories/spawn_condition_values_repository.h index 96a5a7ee7..14a136037 100644 --- a/common/repositories/spawn_condition_values_repository.h +++ b/common/repositories/spawn_condition_values_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPAWN_CONDITION_VALUES_REPOSITORY_H #define EQEMU_SPAWN_CONDITION_VALUES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spawn_condition_values_repository.h" class SpawnConditionValuesRepository: public BaseSpawnConditionValuesRepository { diff --git a/common/repositories/spawn_conditions_repository.h b/common/repositories/spawn_conditions_repository.h index 3e0197eb0..0ff130faa 100644 --- a/common/repositories/spawn_conditions_repository.h +++ b/common/repositories/spawn_conditions_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPAWN_CONDITIONS_REPOSITORY_H #define EQEMU_SPAWN_CONDITIONS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spawn_conditions_repository.h" class SpawnConditionsRepository: public BaseSpawnConditionsRepository { diff --git a/common/repositories/spawn_events_repository.h b/common/repositories/spawn_events_repository.h index 2df6b981e..4e008e79d 100644 --- a/common/repositories/spawn_events_repository.h +++ b/common/repositories/spawn_events_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPAWN_EVENTS_REPOSITORY_H #define EQEMU_SPAWN_EVENTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spawn_events_repository.h" class SpawnEventsRepository: public BaseSpawnEventsRepository { diff --git a/common/repositories/spawnentry_repository.h b/common/repositories/spawnentry_repository.h index 67416e61c..0a61a5287 100644 --- a/common/repositories/spawnentry_repository.h +++ b/common/repositories/spawnentry_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPAWNENTRY_REPOSITORY_H #define EQEMU_SPAWNENTRY_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spawnentry_repository.h" class SpawnentryRepository: public BaseSpawnentryRepository { diff --git a/common/repositories/spawngroup_repository.h b/common/repositories/spawngroup_repository.h index b9390b958..6e0a7b59b 100644 --- a/common/repositories/spawngroup_repository.h +++ b/common/repositories/spawngroup_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPAWNGROUP_REPOSITORY_H #define EQEMU_SPAWNGROUP_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spawngroup_repository.h" class SpawngroupRepository: public BaseSpawngroupRepository { diff --git a/common/repositories/spell_buckets_repository.h b/common/repositories/spell_buckets_repository.h index 547ac3a3b..ddba4be0c 100644 --- a/common/repositories/spell_buckets_repository.h +++ b/common/repositories/spell_buckets_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPELL_BUCKETS_REPOSITORY_H #define EQEMU_SPELL_BUCKETS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spell_buckets_repository.h" class SpellBucketsRepository: public BaseSpellBucketsRepository { diff --git a/common/repositories/spell_globals_repository.h b/common/repositories/spell_globals_repository.h index eb6f19587..91cb74caf 100644 --- a/common/repositories/spell_globals_repository.h +++ b/common/repositories/spell_globals_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPELL_GLOBALS_REPOSITORY_H #define EQEMU_SPELL_GLOBALS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spell_globals_repository.h" class SpellGlobalsRepository: public BaseSpellGlobalsRepository { diff --git a/common/repositories/spells_new_repository.h b/common/repositories/spells_new_repository.h index 3da162558..cafbad33f 100644 --- a/common/repositories/spells_new_repository.h +++ b/common/repositories/spells_new_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_SPELLS_NEW_REPOSITORY_H #define EQEMU_SPELLS_NEW_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_spells_new_repository.h" class SpellsNewRepository: public BaseSpellsNewRepository { diff --git a/common/repositories/start_zones_repository.h b/common/repositories/start_zones_repository.h index fedafb7d9..99f29da21 100644 --- a/common/repositories/start_zones_repository.h +++ b/common/repositories/start_zones_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_START_ZONES_REPOSITORY_H #define EQEMU_START_ZONES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_start_zones_repository.h" class StartZonesRepository: public BaseStartZonesRepository { diff --git a/common/repositories/starting_items_repository.h b/common/repositories/starting_items_repository.h index 2a8d25f45..8389008ac 100644 --- a/common/repositories/starting_items_repository.h +++ b/common/repositories/starting_items_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_STARTING_ITEMS_REPOSITORY_H #define EQEMU_STARTING_ITEMS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_starting_items_repository.h" class StartingItemsRepository: public BaseStartingItemsRepository { diff --git a/common/repositories/task_activities_repository.h b/common/repositories/task_activities_repository.h index b66bb8eee..3a57ccdc4 100644 --- a/common/repositories/task_activities_repository.h +++ b/common/repositories/task_activities_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TASK_ACTIVITIES_REPOSITORY_H #define EQEMU_TASK_ACTIVITIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_task_activities_repository.h" class TaskActivitiesRepository: public BaseTaskActivitiesRepository { diff --git a/common/repositories/tasks_repository.h b/common/repositories/tasks_repository.h index 1e91ca9f6..59c2f14fa 100644 --- a/common/repositories/tasks_repository.h +++ b/common/repositories/tasks_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TASKS_REPOSITORY_H #define EQEMU_TASKS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_tasks_repository.h" class TasksRepository: public BaseTasksRepository { diff --git a/common/repositories/tasksets_repository.h b/common/repositories/tasksets_repository.h index a98364993..44dd1fc47 100644 --- a/common/repositories/tasksets_repository.h +++ b/common/repositories/tasksets_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TASKSETS_REPOSITORY_H #define EQEMU_TASKSETS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_tasksets_repository.h" class TasksetsRepository: public BaseTasksetsRepository { diff --git a/common/repositories/template/base_repository.template b/common/repositories/template/base_repository.template index d4ab7b6fc..5c0693383 100644 --- a/common/repositories/template/base_repository.template +++ b/common/repositories/template/base_repository.template @@ -13,8 +13,9 @@ #define EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H #include "../../database.h" -#include "../../string_util.h" +#include "../../strings.h" #include +{{ADDITIONAL_INCLUDES}} class Base{{TABLE_NAME_CLASS}}Repository { public: @@ -43,12 +44,12 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string SelectColumnsRaw() { - return std::string(implode(", ", SelectColumns())); + return std::string(Strings::Implode(", ", SelectColumns())); } static std::string TableName() @@ -76,14 +77,14 @@ public: static {{TABLE_NAME_STRUCT}} NewEntity() { - {{TABLE_NAME_STRUCT}} entry{}; + {{TABLE_NAME_STRUCT}} e{}; {{DEFAULT_ENTRIES}} - return entry; + return e; } - static {{TABLE_NAME_STRUCT}} Get{{TABLE_NAME_STRUCT}}Entry( + static {{TABLE_NAME_STRUCT}} Get{{TABLE_NAME_STRUCT}}( const std::vector<{{TABLE_NAME_STRUCT}}> &{{TABLE_NAME_VAR}}s, int {{TABLE_NAME_VAR}}_id ) @@ -104,18 +105,19 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), {{TABLE_NAME_VAR}}_id ) ); auto row = results.begin(); if (results.RowCount() == 1) { - {{TABLE_NAME_STRUCT}} entry{}; + {{TABLE_NAME_STRUCT}} e{}; {{FIND_ONE_ENTRIES}} - return entry; + return e; } return NewEntity(); @@ -140,10 +142,10 @@ public: static int UpdateOne( Database& db, - {{TABLE_NAME_STRUCT}} {{TABLE_NAME_VAR}}_entry + const {{TABLE_NAME_STRUCT}} &e ) { - std::vector update_values; + std::vector v; auto columns = Columns(); @@ -153,9 +155,9 @@ public: fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", v), PrimaryKey(), - {{TABLE_NAME_VAR}}_entry.{{PRIMARY_KEY_STRING}} + e.{{PRIMARY_KEY_STRING}} ) ); @@ -164,10 +166,10 @@ public: static {{TABLE_NAME_STRUCT}} InsertOne( Database& db, - {{TABLE_NAME_STRUCT}} {{TABLE_NAME_VAR}}_entry + {{TABLE_NAME_STRUCT}} e ) { - std::vector insert_values; + std::vector v; {{INSERT_ONE_ENTRIES}} @@ -175,42 +177,42 @@ public: fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", v) ) ); if (results.Success()) { - {{TABLE_NAME_VAR}}_entry.{{PRIMARY_KEY_STRING}} = results.LastInsertedID(); - return {{TABLE_NAME_VAR}}_entry; + e.{{PRIMARY_KEY_STRING}} = results.LastInsertedID(); + return e; } - {{TABLE_NAME_VAR}}_entry = NewEntity(); + e = NewEntity(); - return {{TABLE_NAME_VAR}}_entry; + return e; } static int InsertMany( Database& db, - std::vector<{{TABLE_NAME_STRUCT}}> {{TABLE_NAME_VAR}}_entries + const std::vector<{{TABLE_NAME_STRUCT}}> &entries ) { std::vector insert_chunks; - for (auto &{{TABLE_NAME_VAR}}_entry: {{TABLE_NAME_VAR}}_entries) { - std::vector insert_values; + for (auto &e: entries) { + std::vector v; {{INSERT_MANY_ENTRIES}} - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } - std::vector insert_values; + std::vector v; auto results = db.QueryDatabase( fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); @@ -231,17 +233,17 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - {{TABLE_NAME_STRUCT}} entry{}; + {{TABLE_NAME_STRUCT}} e{}; {{ALL_ENTRIES}} - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static std::vector<{{TABLE_NAME_STRUCT}}> GetWhere(Database& db, std::string where_filter) + static std::vector<{{TABLE_NAME_STRUCT}}> GetWhere(Database& db, const std::string &where_filter) { std::vector<{{TABLE_NAME_STRUCT}}> all_entries; @@ -256,17 +258,17 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - {{TABLE_NAME_STRUCT}} entry{}; + {{TABLE_NAME_STRUCT}} e{}; {{ALL_ENTRIES}} - all_entries.push_back(entry); + all_entries.push_back(e); } return all_entries; } - static int DeleteWhere(Database& db, std::string where_filter) + static int DeleteWhere(Database& db, const std::string &where_filter) { auto results = db.QueryDatabase( fmt::format( @@ -291,6 +293,32 @@ public: return (results.Success() ? results.RowsAffected() : 0); } + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + }; #endif //EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H diff --git a/common/repositories/template/repository.template b/common/repositories/template/repository.template index 00d5b6db3..d5de51e4e 100644 --- a/common/repositories/template/repository.template +++ b/common/repositories/template/repository.template @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_{{TABLE_NAME_UPPER}}_REPOSITORY_H #define EQEMU_{{TABLE_NAME_UPPER}}_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_{{TABLE_NAME_VAR}}_repository.h" class {{TABLE_NAME_CLASS}}Repository: public Base{{TABLE_NAME_CLASS}}Repository { diff --git a/common/repositories/timers_repository.h b/common/repositories/timers_repository.h index dcd867210..eb497f12b 100644 --- a/common/repositories/timers_repository.h +++ b/common/repositories/timers_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TIMERS_REPOSITORY_H #define EQEMU_TIMERS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_timers_repository.h" class TimersRepository: public BaseTimersRepository { diff --git a/common/repositories/titles_repository.h b/common/repositories/titles_repository.h index 32b9fd5e3..3ff4544ae 100644 --- a/common/repositories/titles_repository.h +++ b/common/repositories/titles_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TITLES_REPOSITORY_H #define EQEMU_TITLES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_titles_repository.h" class TitlesRepository: public BaseTitlesRepository { diff --git a/common/repositories/tool_game_objects_repository.h b/common/repositories/tool_game_objects_repository.h index d4d6009b5..0afbf2334 100644 --- a/common/repositories/tool_game_objects_repository.h +++ b/common/repositories/tool_game_objects_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TOOL_GAME_OBJECTS_REPOSITORY_H #define EQEMU_TOOL_GAME_OBJECTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_tool_game_objects_repository.h" class ToolGameObjectsRepository: public BaseToolGameObjectsRepository { diff --git a/common/repositories/trader_audit_repository.h b/common/repositories/trader_audit_repository.h index e7be6f677..491a4c1a6 100644 --- a/common/repositories/trader_audit_repository.h +++ b/common/repositories/trader_audit_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TRADER_AUDIT_REPOSITORY_H #define EQEMU_TRADER_AUDIT_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" class TraderAuditRepository { public: @@ -56,7 +36,7 @@ public: static std::string ColumnsRaw() { - return std::string(implode(", ", Columns())); + return std::string(Strings::Implode(", ", Columns())); } static std::string InsertColumnsRaw() @@ -71,7 +51,7 @@ public: insert_columns.push_back(column); } - return std::string(implode(", ", insert_columns)); + return std::string(Strings::Implode(", ", insert_columns)); } static std::string TableName() @@ -180,10 +160,10 @@ public: auto columns = Columns(); - update_values.push_back(columns[0] + " = '" + EscapeString(trader_audit_entry.time) + "'"); - update_values.push_back(columns[1] + " = '" + EscapeString(trader_audit_entry.seller) + "'"); - update_values.push_back(columns[2] + " = '" + EscapeString(trader_audit_entry.buyer) + "'"); - update_values.push_back(columns[3] + " = '" + EscapeString(trader_audit_entry.itemname) + "'"); + update_values.push_back(columns[0] + " = '" + Strings::Escape(trader_audit_entry.time) + "'"); + update_values.push_back(columns[1] + " = '" + Strings::Escape(trader_audit_entry.seller) + "'"); + update_values.push_back(columns[2] + " = '" + Strings::Escape(trader_audit_entry.buyer) + "'"); + update_values.push_back(columns[3] + " = '" + Strings::Escape(trader_audit_entry.itemname) + "'"); update_values.push_back(columns[4] + " = " + std::to_string(trader_audit_entry.quantity)); update_values.push_back(columns[5] + " = " + std::to_string(trader_audit_entry.totalcost)); update_values.push_back(columns[6] + " = " + std::to_string(trader_audit_entry.trantype)); @@ -192,7 +172,7 @@ public: fmt::format( "UPDATE {} SET {} WHERE {} = {}", TableName(), - implode(", ", update_values), + Strings::Implode(", ", update_values), PrimaryKey(), trader_audit_entry. ) @@ -207,10 +187,10 @@ public: { std::vector insert_values; - insert_values.push_back("'" + EscapeString(trader_audit_entry.time) + "'"); - insert_values.push_back("'" + EscapeString(trader_audit_entry.seller) + "'"); - insert_values.push_back("'" + EscapeString(trader_audit_entry.buyer) + "'"); - insert_values.push_back("'" + EscapeString(trader_audit_entry.itemname) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.time) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.seller) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.buyer) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.itemname) + "'"); insert_values.push_back(std::to_string(trader_audit_entry.quantity)); insert_values.push_back(std::to_string(trader_audit_entry.totalcost)); insert_values.push_back(std::to_string(trader_audit_entry.trantype)); @@ -219,7 +199,7 @@ public: fmt::format( "{} VALUES ({})", BaseInsert(), - implode(",", insert_values) + Strings::Implode(",", insert_values) ) ); @@ -242,15 +222,15 @@ public: for (auto &trader_audit_entry: trader_audit_entries) { std::vector insert_values; - insert_values.push_back("'" + EscapeString(trader_audit_entry.time) + "'"); - insert_values.push_back("'" + EscapeString(trader_audit_entry.seller) + "'"); - insert_values.push_back("'" + EscapeString(trader_audit_entry.buyer) + "'"); - insert_values.push_back("'" + EscapeString(trader_audit_entry.itemname) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.time) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.seller) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.buyer) + "'"); + insert_values.push_back("'" + Strings::Escape(trader_audit_entry.itemname) + "'"); insert_values.push_back(std::to_string(trader_audit_entry.quantity)); insert_values.push_back(std::to_string(trader_audit_entry.totalcost)); insert_values.push_back(std::to_string(trader_audit_entry.trantype)); - insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); } std::vector insert_values; @@ -259,7 +239,7 @@ public: fmt::format( "{} VALUES {}", BaseInsert(), - implode(",", insert_chunks) + Strings::Implode(",", insert_chunks) ) ); diff --git a/common/repositories/trader_repository.h b/common/repositories/trader_repository.h index 50cf496f5..31f8fae87 100644 --- a/common/repositories/trader_repository.h +++ b/common/repositories/trader_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TRADER_REPOSITORY_H #define EQEMU_TRADER_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_trader_repository.h" class TraderRepository: public BaseTraderRepository { diff --git a/common/repositories/tradeskill_recipe_entries_repository.h b/common/repositories/tradeskill_recipe_entries_repository.h index 5a2f3b1ea..cb575ed9c 100644 --- a/common/repositories/tradeskill_recipe_entries_repository.h +++ b/common/repositories/tradeskill_recipe_entries_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H #define EQEMU_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_tradeskill_recipe_entries_repository.h" class TradeskillRecipeEntriesRepository: public BaseTradeskillRecipeEntriesRepository { diff --git a/common/repositories/tradeskill_recipe_repository.h b/common/repositories/tradeskill_recipe_repository.h index 2f94d586f..287fecd99 100644 --- a/common/repositories/tradeskill_recipe_repository.h +++ b/common/repositories/tradeskill_recipe_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TRADESKILL_RECIPE_REPOSITORY_H #define EQEMU_TRADESKILL_RECIPE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_tradeskill_recipe_repository.h" class TradeskillRecipeRepository: public BaseTradeskillRecipeRepository { diff --git a/common/repositories/traps_repository.h b/common/repositories/traps_repository.h index 76d1e217b..a32465fc5 100644 --- a/common/repositories/traps_repository.h +++ b/common/repositories/traps_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TRAPS_REPOSITORY_H #define EQEMU_TRAPS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_traps_repository.h" class TrapsRepository: public BaseTrapsRepository { diff --git a/common/repositories/tribute_levels_repository.h b/common/repositories/tribute_levels_repository.h index 04391798d..26fb01a24 100644 --- a/common/repositories/tribute_levels_repository.h +++ b/common/repositories/tribute_levels_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TRIBUTE_LEVELS_REPOSITORY_H #define EQEMU_TRIBUTE_LEVELS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_tribute_levels_repository.h" class TributeLevelsRepository: public BaseTributeLevelsRepository { diff --git a/common/repositories/tributes_repository.h b/common/repositories/tributes_repository.h index 860588524..ea0145057 100644 --- a/common/repositories/tributes_repository.h +++ b/common/repositories/tributes_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_TRIBUTES_REPOSITORY_H #define EQEMU_TRIBUTES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_tributes_repository.h" class TributesRepository: public BaseTributesRepository { diff --git a/common/repositories/variables_repository.h b/common/repositories/variables_repository.h index 6e07e1bb2..216e234b3 100644 --- a/common/repositories/variables_repository.h +++ b/common/repositories/variables_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_VARIABLES_REPOSITORY_H #define EQEMU_VARIABLES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_variables_repository.h" class VariablesRepository: public BaseVariablesRepository { diff --git a/common/repositories/veteran_reward_templates_repository.h b/common/repositories/veteran_reward_templates_repository.h index 3e9ad2745..24dfb94f3 100644 --- a/common/repositories/veteran_reward_templates_repository.h +++ b/common/repositories/veteran_reward_templates_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_VETERAN_REWARD_TEMPLATES_REPOSITORY_H #define EQEMU_VETERAN_REWARD_TEMPLATES_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_veteran_reward_templates_repository.h" class VeteranRewardTemplatesRepository: public BaseVeteranRewardTemplatesRepository { diff --git a/common/repositories/zone_points_repository.h b/common/repositories/zone_points_repository.h index a4f885fc6..bcf37abe9 100644 --- a/common/repositories/zone_points_repository.h +++ b/common/repositories/zone_points_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ZONE_POINTS_REPOSITORY_H #define EQEMU_ZONE_POINTS_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_zone_points_repository.h" class ZonePointsRepository: public BaseZonePointsRepository { diff --git a/common/repositories/zone_repository.h b/common/repositories/zone_repository.h index 41115ef44..09b91a788 100644 --- a/common/repositories/zone_repository.h +++ b/common/repositories/zone_repository.h @@ -1,28 +1,8 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #ifndef EQEMU_ZONE_REPOSITORY_H #define EQEMU_ZONE_REPOSITORY_H #include "../database.h" -#include "../string_util.h" +#include "../strings.h" #include "base/base_zone_repository.h" class ZoneRepository: public BaseZoneRepository { diff --git a/common/rulesys.cpp b/common/rulesys.cpp index d5b7332d5..f07956572 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -17,468 +17,465 @@ */ #include "rulesys.h" +#include "eqemu_logsys.h" #include "database.h" -#include "string_util.h" +#include "strings.h" #include #include #include -/* - Commands: - #rules: - current -> lists current set name - switch (set name) -> change set in the DB, but dont reload - load (set name) -> load set into this zone without changing the world - wload (set name) -> tell world and all zones to load this rule set - store [set name] -> store the current rules in this zone to the set (or active if not specified) - reset -> reset all rule values to their defaults. - list [catname] - set (cat) (rule) (value) - values [catname] -> show the values of all rules in the specified category/ -*/ +#include "../common/repositories/rule_sets_repository.h" +#include "../common/repositories/rule_values_repository.h" -const char *RuleManager::s_categoryNames[_CatCount+1] = { - #define RULE_CATEGORY(catname) \ - #catname , +const char *RuleManager::s_categoryNames[_CatCount + 1] = { + #define RULE_CATEGORY(category_name) \ + #category_name , #include "ruletypes.h" "InvalidCategory" }; -const RuleManager::RuleInfo RuleManager::s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount+1] = { +const RuleManager::RuleInfo RuleManager::s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + 1] = { /* this is done in three steps so we can reliably get to them by index*/ - #define RULE_INT(cat, rule, default_value, notes) \ - { #cat ":" #rule, Category__##cat, IntRule, Int__##rule, notes }, + #define RULE_INT(category_name, rule_name, default_value, notes) \ + { #category_name ":" #rule_name, Category__##category_name, IntRule, Int__##rule_name, notes }, #include "ruletypes.h" - #define RULE_REAL(cat, rule, default_value, notes) \ - { #cat ":" #rule, Category__##cat, RealRule, Real__##rule, notes }, + #define RULE_REAL(category_name, rule_name, default_value, notes) \ + { #category_name ":" #rule_name, Category__##category_name, RealRule, Real__##rule_name, notes }, #include "ruletypes.h" - #define RULE_BOOL(cat, rule, default_value, notes) \ - { #cat ":" #rule, Category__##cat, BoolRule, Bool__##rule, notes }, + #define RULE_BOOL(category_name, rule_name, default_value, notes) \ + { #category_name ":" #rule_name, Category__##category_name, BoolRule, Bool__##rule_name, notes }, #include "ruletypes.h" { "Invalid Rule", _CatCount, IntRule } }; RuleManager::RuleManager() -: m_activeRuleset(0), - m_activeName("default") + : m_activeRuleset(0), + m_activeName("default") { ResetRules(false); } -RuleManager::CategoryType RuleManager::FindCategory(const char *catname) { - int i; - for (i = 0; i < _CatCount; i++) { - if (strcasecmp(catname, s_categoryNames[i]) == 0) - return((CategoryType)i); - } - return(InvalidCategory); -} - -bool RuleManager::ListRules(const char *catname, std::vector &into) { - CategoryType cat = InvalidCategory; - if (catname != nullptr) { - cat = FindCategory(catname); - if (cat == InvalidCategory) { - Log(Logs::Detail, Logs::Rules, "Unable to find category '%s'", catname); - return(false); +RuleManager::CategoryType RuleManager::FindCategory(const std::string &category_name) +{ + for (int i = 0; i < _CatCount; i++) { + if (Strings::Contains(category_name, s_categoryNames[i])) { + return static_cast(i); } } - int i; - int rule_count = CountRules(); - for (i = 0; i < rule_count; i++) { - const RuleInfo &rule = s_RuleInfo[i]; - if (catname == nullptr || cat == rule.category) { - into.push_back(rule.name); + + return InvalidCategory; +} + +bool RuleManager::ListRules(const std::string &category_name, std::vector &l) +{ + CategoryType category_type = InvalidCategory; + if (!category_name.empty()) { + category_type = FindCategory(category_name); + if (category_type == InvalidCategory) { + LogRulesDetail("Unable to find category '{}'.", category_name); + return false; } } - return(true); -} -bool RuleManager::ListCategories(std::vector &into) { - int i; - for (i = 0; i < _CatCount; i++) { - into.push_back(s_categoryNames[i]); + for (int i = 0; i < CountRules(); i++) { + const auto& r = s_RuleInfo[i]; + if (category_name.empty() || category_type == r.category) { + l.push_back(r.name); + } } - return(true); -} - -bool RuleManager::GetRule(const char *rule_name, std::string &return_value) { - RuleType type; - uint16 index; - if (!_FindRule(rule_name, type, index)) - return false; - - char tmp[255] = ""; - switch(type) { - case IntRule: - sprintf(tmp, "%i", m_RuleIntValues[index]); - break; - case RealRule: - sprintf(tmp, "%f", m_RuleRealValues[index]); - break; - case BoolRule: - std::string tmp_val = m_RuleBoolValues[index] ? "true" : "false"; - sprintf(tmp, "%s", tmp_val.c_str()); - break; - } - - return_value = tmp; return true; } -bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save, bool reload) { - if(rule_name == nullptr || rule_value == nullptr) - return(false); +bool RuleManager::ListCategories(std::vector &l) +{ + for (int i = 0; i < _CatCount; i++) { + l.push_back(s_categoryNames[i]); + } + + return true; +} + +bool RuleManager::GetRule(const std::string &rule_name, std::string &rule_value) +{ + RuleType type; + uint16 index; + if (!_FindRule(rule_name, type, index)) { + return false; + } + + switch (type) { + case IntRule: + rule_value = fmt::format("{}", m_RuleIntValues[index]); + break; + case RealRule: + rule_value = fmt::format("{}", m_RuleRealValues[index]); + break; + case BoolRule: + rule_value = m_RuleBoolValues[index] ? "true" : "false"; + break; + } + + return true; +} + +bool RuleManager::SetRule(const std::string &rule_name, const std::string &rule_value, Database *db, bool db_save, bool reload) +{ + if (rule_name.empty() || rule_value.empty()) { + return false; + } RuleType type; uint16 index; - if(!_FindRule(rule_name, type, index)) - return(false); - - if (reload) { - if (strcasecmp(rule_name, "World:ExpansionSettings") == 0) - return(false); - if (strcasecmp(rule_name, "World:UseClientBasedExpansionSettings") == 0) - return(false); + if (!_FindRule(rule_name, type, index)) { + return (false); } - switch(type) { + if (reload) { + bool is_client = Strings::EqualFold(rule_name, "World:UseClientBasedExpansionSettings"); + bool is_world = Strings::EqualFold(rule_name, "World:ExpansionSettings"); + if (is_client || is_world) { + return false; + } + } + + switch (type) { case IntRule: - m_RuleIntValues[index] = atoi(rule_value); + m_RuleIntValues[index] = atoi(rule_value.c_str()); LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleIntValues[index]); break; case RealRule: - m_RuleRealValues[index] = atof(rule_value); - LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleRealValues[index]); + m_RuleRealValues[index] = atof(rule_value.c_str()); + LogRules("Set rule [{}] to value [{:.2f}]", rule_name, m_RuleRealValues[index]); break; case BoolRule: - uint32 val = 0; - if (!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1")) - val = 1; - - m_RuleBoolValues[index] = val; + m_RuleBoolValues[index] = static_cast(Strings::ToBool(rule_value)); LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false"); break; } - if(db_save) - _SaveRule(database, type, index); + if (db_save) { + _SaveRule(db, type, index); + } - return(true); + return true; } void RuleManager::ResetRules(bool reload) { - std::string expansion1; - std::string expansion2; + std::string client_rule; + std::string world_rule; // these rules must not change during server runtime if (reload) { - GetRule("World:ExpansionSettings", expansion1); - GetRule("World:UseClientBasedExpansionSettings", expansion2); + GetRule("World:UseClientBasedExpansionSettings", client_rule); + GetRule("World:ExpansionSettings", world_rule); } - Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values"); - #define RULE_INT(cat, rule, default_value, notes) \ - m_RuleIntValues[ Int__##rule ] = default_value; - #define RULE_REAL(cat, rule, default_value, notes) \ - m_RuleRealValues[ Real__##rule ] = default_value; - #define RULE_BOOL(cat, rule, default_value, notes) \ - m_RuleBoolValues[ Bool__##rule ] = default_value; + LogRulesDetail("Resetting running rules to default values."); + + #define RULE_INT(category_name, rule_name, default_value, notes) \ + m_RuleIntValues[ Int__##rule_name ] = default_value; + #define RULE_REAL(category_name, rule_name, default_value, notes) \ + m_RuleRealValues[ Real__##rule_name ] = default_value; + #define RULE_BOOL(category_name, rule_name, default_value, notes) \ + m_RuleBoolValues[ Bool__##rule_name ] = default_value; #include "ruletypes.h" // restore these rules to their pre-reset values if (reload) { - SetRule("World:ExpansionSettings", expansion1.c_str(), nullptr, false, false); - SetRule("World:UseClientBasedExpansionSettings", expansion2.c_str(), nullptr, false, false); + SetRule("World:UseClientBasedExpansionSettings", client_rule); + SetRule("World:ExpansionSettings", world_rule); } } -bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) { - if (rule_name == nullptr) - return(false); +bool RuleManager::_FindRule(const std::string &rule_name, RuleType &type_into, uint16 &index_into) { + if (rule_name.empty()) { + return false; + } - int i; - int rule_count = CountRules(); - for (i = 0; i < rule_count; i++) { - const RuleInfo &rule = s_RuleInfo[i]; - if (strcmp(rule_name, rule.name) == 0) { - type_into = rule.type; - index_into = rule.rule_index; - return(true); + for (int i = 0; i < CountRules(); i++) { + const auto& r = s_RuleInfo[i]; + if (rule_name == r.name) { + type_into = r.type; + index_into = r.rule_index; + return true; } } - Log(Logs::Detail, Logs::Rules, "Unable to find rule '%s'", rule_name); - return(false); + + LogRulesDetail("Unable to find rule '{}'.", rule_name); + return false; } //assumes index is valid! -const char *RuleManager::_GetRuleName(RuleType type, uint16 index) { +std::string RuleManager::_GetRuleName(RuleType type, uint16 index) { switch (type) { - case IntRule: - return(s_RuleInfo[index].name); - case RealRule: - return(s_RuleInfo[index+_IntRuleCount].name); - case BoolRule: - return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name); - default: - break; + case IntRule: + return s_RuleInfo[index].name; + case RealRule: + return s_RuleInfo[index + IntRuleCount].name; + case BoolRule: + return s_RuleInfo[index + IntRuleCount + RealRuleCount].name; + default: + break; } - //should never happen - return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].name); // no need to create a string when one already exists... + + return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount].name; } //assumes index is valid! const std::string &RuleManager::_GetRuleNotes(RuleType type, uint16 index) { switch (type) { - case IntRule: - return(s_RuleInfo[index].notes); - case RealRule: - return(s_RuleInfo[index+_IntRuleCount].notes); - case BoolRule: - return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].notes); - default: - break; + case IntRule: + return s_RuleInfo[index].notes; + case RealRule: + return s_RuleInfo[index + IntRuleCount].notes; + case BoolRule: + return s_RuleInfo[index + IntRuleCount + RealRuleCount].notes; + default: + break; } - //should never happen - return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].notes); + + return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount].notes; } -bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) { - - int ruleset_id = GetRulesetID(database, ruleset_name); - if (ruleset_id < 0) { - Log(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name); - return (false); +bool RuleManager::LoadRules(Database *db, const std::string &rule_set_name, bool reload) { + const auto rule_set_id = RuleSetsRepository::GetRuleSetID(*db, rule_set_name); + if (rule_set_id < 0) { + LogRulesDetail("Failed to find Rule Set {} for load operation. Canceling.", rule_set_name); + return false; } - m_activeRuleset = ruleset_id; - m_activeName = ruleset_name; + m_activeRuleset = rule_set_id; + m_activeName = rule_set_name; /* Load default ruleset values first if we're loading something other than default */ - if (strcasecmp(ruleset_name, "default") != 0) { - std::string default_ruleset_name = "default"; - int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str()); + const std::string default_ruleset_name = "default"; + bool is_default = rule_set_name == default_ruleset_name; - if (default_ruleset_id < 0) { - Log(Logs::Detail, - Logs::Rules, - "Failed to find default ruleset '%s' for load operation. Canceling.", - default_ruleset_name.c_str() + if (!is_default) { + const auto default_rule_set_id = RuleSetsRepository::GetRuleSetID(*db, default_ruleset_name); + + if (default_rule_set_id < 0) { + LogRulesDetail( + "Failed to load default Rule Set {} for load operation.", + default_ruleset_name ); - return (false); - } - - Log(Logs::Detail, Logs::Rules, "Processing rule set '%s' (%d) load...", default_ruleset_name.c_str(), default_ruleset_id); - - std::string query = StringFormat( - "SELECT `rule_name`, `rule_value` FROM `rule_values` WHERE `ruleset_id` = %d", - default_ruleset_id - ); - - auto results = database->QueryDatabase(query); - if (!results.Success()) { return false; } - for (auto row = results.begin(); row != results.end(); ++row) { - if (!SetRule(row[0], row[1], nullptr, false, reload)) { - Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for '%s'", row[0]); + LogRulesDetail("Loading Rule Set {} ({}).", default_ruleset_name, default_rule_set_id); + + const auto& l = RuleValuesRepository::GetWhere( + *db, + fmt::format( + "ruleset_id = {}", + default_rule_set_id + ) + ); + if (l.empty()) { + return false; + } + + for (const auto& e : l) { + if (!SetRule(e.rule_name, e.rule_value, nullptr, false, reload)) { + LogRulesDetail("Unable to interpret rule record for '{}'.", e.rule_name); } } } - Log(Logs::Detail, Logs::Rules, "Processing rule set '%s' (%d) load...", ruleset_name, ruleset_id); + LogRulesDetail("Loading Rule Set {} ({}).", rule_set_name, rule_set_id); - std::string query = StringFormat("SELECT `rule_name`, `rule_value` FROM `rule_values` WHERE `ruleset_id` = %d", ruleset_id); - - auto results = database->QueryDatabase(query); - if (!results.Success()) { + const auto& l = RuleValuesRepository::GetWhere( + *db, + fmt::format( + "ruleset_id = {}", + rule_set_id + ) + ); + if (l.empty()) { return false; } - for (auto row = results.begin(); row != results.end(); ++row) { - if (!SetRule(row[0], row[1], nullptr, false, reload)) { - Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for '%s'", row[0]); + for (const auto& e : l) { + if (!SetRule(e.rule_name, e.rule_value, nullptr, false, reload)) { + LogRulesDetail("Unable to interpret Rule record for Rule '{}'.", e.rule_name); } } + LogInfo( + "Loaded [{}] rules(s) in rule_set [{}] id [{}]", + Strings::Commify(std::to_string(l.size())), + rule_set_name, + rule_set_id + ); + return true; } -void RuleManager::SaveRules(Database *database, const char *ruleset_name) { - - if (ruleset_name != nullptr) { - //saving to a specific name - if (m_activeName != ruleset_name) { - //a new name... - - m_activeRuleset = _FindOrCreateRuleset(database, ruleset_name); +void RuleManager::SaveRules(Database *db, const std::string &rule_set_name) { + if (!rule_set_name.empty()) { + if (m_activeName != rule_set_name) { + m_activeRuleset = _FindOrCreateRuleset(db, rule_set_name); if (m_activeRuleset == -1) { - Log(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset_name); + LogRulesDetail("Unable to find or create Rule Set {}.", rule_set_name); return; } - m_activeName = ruleset_name; + + m_activeName = rule_set_name; } - Log(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset_name, m_activeRuleset); - } - else { - Log(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset); + + LogRulesDetail("Saving running rules into Rule Set {} ({}).", rule_set_name, m_activeRuleset); + } else { + LogRulesDetail("Saving running rules into running Rule Set {} ({}).", m_activeName, m_activeRuleset); } int i; - for (i = 0; i < _IntRuleCount; i++) { - _SaveRule(database, IntRule, i); + for (i = 0; i < IntRuleCount; i++) { + _SaveRule(db, IntRule, i); } - for (i = 0; i < _RealRuleCount; i++) { - _SaveRule(database, RealRule, i); + + for (i = 0; i < RealRuleCount; i++) { + _SaveRule(db, RealRule, i); } - for (i = 0; i < _BoolRuleCount; i++) { - _SaveRule(database, BoolRule, i); + + for (i = 0; i < BoolRuleCount; i++) { + _SaveRule(db, BoolRule, i); } } -void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) { - char value_string[100]; +void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) { + const auto rule_name = _GetRuleName(type, index); - if (type == IntRule && strcasecmp(_GetRuleName(type, index), "World:ExpansionSettings") == 0) - return; - if (type == BoolRule && strcasecmp(_GetRuleName(type, index), "World:UseClientBasedExpansionSettings") == 0) + if ( + (type == BoolRule && Strings::EqualFold(rule_name, "World:UseClientBasedExpansionSettings")) || + (type == IntRule && Strings::EqualFold(rule_name, "World:ExpansionSettings")) + ) { return; + } + + std::string rule_value; switch (type) { case IntRule: - sprintf(value_string, "%d", m_RuleIntValues[index]); + rule_value = fmt::format("{}", m_RuleIntValues[index]); break; case RealRule: - sprintf(value_string, "%.13f", m_RuleRealValues[index]); + rule_value = fmt::format("{:.13f}", m_RuleRealValues[index]); break; case BoolRule: - sprintf(value_string, "%s", m_RuleBoolValues[index] ? "true" : "false"); + rule_value = m_RuleBoolValues[index] ? "true" : "false"; break; } - std::string query = StringFormat( - "REPLACE INTO `rule_values`" - "(`ruleset_id`, `rule_name`, `rule_value`, `notes`)" - " VALUES('%d', '%s', '%s', '%s')", + const auto rule_notes = _GetRuleNotes(type, index); + + const auto& l = RuleValuesRepository::GetWhere( + *db, + fmt::format( + "ruleset_id = {} AND rule_name = '{}' LIMIT 1", m_activeRuleset, - _GetRuleName(type, index), - value_string, - EscapeString(_GetRuleNotes(type, index)).c_str() + rule_name + ) ); - database->QueryDatabase(query); + if (!l.empty()) { + auto e = l[0]; + e.rule_value = rule_value; + e.notes = rule_notes; + + RuleValuesRepository::UpdateOne(*db, e); + return; + } + + auto e = RuleValuesRepository::NewEntity(); + + e.ruleset_id = m_activeRuleset; + e.rule_name = _GetRuleName(type, index); + e.rule_value = rule_value; + e.notes = rule_notes; + + RuleValuesRepository::InsertOne(*db, e); } -bool RuleManager::UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update) +bool RuleManager::UpdateInjectedRules(Database *db, const std::string &rule_set_name, bool quiet_update) { - std::vector database_data; - std::map> rule_data; + std::map> rule_data; std::vector> injected_rule_entries; - if (ruleset_name == nullptr) { + if (rule_set_name.empty()) { return false; } - int ruleset_id = GetRulesetID(db, ruleset_name); - if (ruleset_id < 0) { + const auto rule_set_id = RuleSetsRepository::GetRuleSetID(*db, rule_set_name); + if (rule_set_id < 0) { return false; } - // load database rule names - std::string query(StringFormat("SELECT `rule_name` FROM `rule_values` WHERE `ruleset_id` = '%i'", ruleset_id)); - - auto results = db->QueryDatabase(query); - if (!results.Success()) { + const auto& v = RuleValuesRepository::GetRuleNames(*db, rule_set_id); + if (v.empty()) { return false; } - // build database data entries - for (auto row : results) { - database_data.push_back(std::string(row[0])); - } - // build rule data entries - for (const auto &ri_iter : s_RuleInfo) { - if (strcasecmp(ri_iter.name, "Invalid Rule") == 0) { + for (const auto& r : s_RuleInfo) { + if (Strings::EqualFold(r.name, "Invalid Rule")) { continue; } - char buffer[100]; - - switch (ri_iter.type) { - case IntRule: - sprintf(buffer, "%d", m_RuleIntValues[ri_iter.rule_index]); - rule_data[ri_iter.name].first = buffer; - rule_data[ri_iter.name].second = &ri_iter.notes; - break; - case RealRule: - sprintf(buffer, "%.13f", m_RuleRealValues[ri_iter.rule_index]); - rule_data[ri_iter.name].first = buffer; - rule_data[ri_iter.name].second = &ri_iter.notes; - break; - case BoolRule: - sprintf(buffer, "%s", (m_RuleBoolValues[ri_iter.rule_index] ? "true" : "false")); - rule_data[ri_iter.name].first = buffer; - rule_data[ri_iter.name].second = &ri_iter.notes; - break; - default: - break; + switch (r.type) { + case IntRule: + rule_data[r.name].first = fmt::format("{}", m_RuleIntValues[r.rule_index]); + rule_data[r.name].second = &r.notes; + break; + case RealRule: + rule_data[r.name].first = fmt::format("{:.13f}", m_RuleRealValues[r.rule_index]); + rule_data[r.name].second = &r.notes; + break; + case BoolRule: + rule_data[r.name].first = fmt::format("{}", m_RuleBoolValues[r.rule_index] ? "true" : "false"); + rule_data[r.name].second = &r.notes; + break; + default: + break; } } // build injected entries - for (const auto &rd_iter : rule_data) { - - const auto &dd_iter = std::find(database_data.begin(), database_data.end(), rd_iter.first); - if (dd_iter == database_data.end()) { - + for (const auto &d : rule_data) { + if (std::find(v.begin(), v.end(), d.first) == v.end()) { injected_rule_entries.push_back( std::tuple( - ruleset_id, // `ruleset_id` - rd_iter.first, // `rule_name` - rd_iter.second.first, // `rule_value` - EscapeString(*rd_iter.second.second) // `notes` + rule_set_id, + d.first, + d.second.first, + Strings::Escape(*d.second.second) ) ); if (!quiet_update) { LogInfo( "Adding new rule [{}] ruleset [{}] ({}) value [{}]", - rd_iter.first.c_str(), - ruleset_name, - ruleset_id, - rd_iter.second.first.c_str() + d.first, + rule_set_name, + rule_set_id, + d.second.first ); } } } if (injected_rule_entries.size()) { - - std::string query( - fmt::format( - "REPLACE INTO `rule_values`(`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}", - implode( - ",", - std::pair('(', ')'), - join_tuple(",", std::pair('\'', '\''), injected_rule_entries) - ) - ) - ); - - if (!db->QueryDatabase(query).Success()) { + if (!RuleValuesRepository::InjectRules(*db, injected_rule_entries)) { return false; } LogInfo( "[{}] New rule(s) added to ruleset [{}] [{}]", injected_rule_entries.size(), - ruleset_name, - ruleset_id + rule_set_name, + rule_set_id ); } @@ -490,50 +487,36 @@ bool RuleManager::UpdateOrphanedRules(Database *db, bool quiet_update) std::vector rule_data; std::vector orphaned_rule_entries; - // load database rule names - std::string query("SELECT `rule_name` FROM `rule_values` GROUP BY `rule_name`"); - - auto results = db->QueryDatabase(query); - if (!results.Success()) { + const auto& l = RuleValuesRepository::GetGroupedRules(*db); + if (l.empty()) { return false; } // build rule data entries - for (const auto &ri_iter : s_RuleInfo) { - if (strcasecmp(ri_iter.name, "Invalid Rule") == 0) { + for (const auto &r : s_RuleInfo) { + if (Strings::EqualFold(r.name, "Invalid Rule")) { continue; } - rule_data.push_back(ri_iter.name); + rule_data.push_back(r.name); } - // build orphaned entries - for (auto row : results) { - - const auto &rd_iter = std::find(rule_data.begin(), rule_data.end(), row[0]); - if (rd_iter == rule_data.end()) { - - orphaned_rule_entries.push_back(std::string(row[0])); + for (const auto& e : l) { + const auto &d = std::find(rule_data.begin(), rule_data.end(), e); + if (d == rule_data.end()) { + orphaned_rule_entries.push_back(e); if (!quiet_update) { LogInfo( "Rule [{}] no longer exists... Deleting orphaned entry from `rule_values` table...", - row[0] + e ); } } } if (orphaned_rule_entries.size()) { - - std::string query ( - fmt::format( - "DELETE FROM `rule_values` WHERE `rule_name` IN ({})", - implode(",", std::pair('\'', '\''), orphaned_rule_entries) - ) - ); - - if (!db->QueryDatabase(query).Success()) { + if (!RuleValuesRepository::DeleteOrphanedRules(*db, orphaned_rule_entries)) { return false; } @@ -545,139 +528,83 @@ bool RuleManager::UpdateOrphanedRules(Database *db, bool quiet_update) bool RuleManager::RestoreRuleNotes(Database *db) { - std::string query("SELECT `ruleset_id`, `rule_name`, `notes` FROM `rule_values`"); - - auto results = db->QueryDatabase(query); - if (!results.Success()) { + const auto& l = RuleValuesRepository::All(*db); + if (l.empty()) { return false; } int update_count = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - - auto rule = [](const char *rule_name) { + for (const auto& e : l) { + auto rule = [](std::string rule_name) { for (auto rule_iter : s_RuleInfo) { - if (strcasecmp(rule_iter.name, rule_name) == 0) { + if (Strings::EqualFold(rule_iter.name, rule_name)) { return rule_iter; } } - return s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount]; - }(row[1]); + return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount]; + }(e.rule_name); - if (strcasecmp(rule.name, row[1]) != 0) { + if (Strings::Contains(rule.name, e.rule_name)) { continue; } - if (row[2] != nullptr && rule.notes.compare(row[2]) == 0) { + if (!e.notes.empty() && !rule.notes.compare(e.notes)) { continue; } - std::string query( - fmt::format( - "UPDATE `rule_values` SET `notes` = '{}' WHERE `ruleset_id` = '{}' AND `rule_name` = '{}'", - EscapeString(rule.notes), - row[0], - row[1] - ) - ); - - if (!db->QueryDatabase(query).Success()) { + if (!RuleValuesRepository::UpdateRuleNote(*db, e.ruleset_id, e.rule_name, rule.notes)) { continue; } ++update_count; } - if (update_count > 0) { - LogInfo("[{}] Rule Note [{}] Restored", update_count, (update_count == 1 ? "" : "s")); + if (update_count) { + LogInfo("[{}] Rule Note{} Restored", update_count, update_count != 1 ? "s" : ""); } return true; } -int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) { +int RuleManager::_FindOrCreateRuleset(Database *db, const std::string &rule_set_name) +{ + const auto rule_set_id = RuleSetsRepository::GetRuleSetID(*db, rule_set_name); + if (rule_set_id >= 0) { + return rule_set_id; + } - uint32 len = static_cast(strlen(ruleset_name)); - auto rst = new char[2 * len + 1]; - database->DoEscapeString(rst, ruleset_name, len); - - std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst); - safe_delete_array(rst); - auto results = database->QueryDatabase(query); - if (!results.Success()) - return -1; - - if (results.RowCount() == 0) - return -1; - - auto row = results.begin(); - - return atoi(row[0]); + return RuleSetsRepository::CreateNewRuleSet(*db, rule_set_name); } -int RuleManager::_FindOrCreateRuleset(Database *database, const char *in_ruleset_name) { +bool RuleManager::ListRulesets(Database *db, std::map &m) +{ + m[0] = "default"; - int ruleset_id = GetRulesetID(database, in_ruleset_name); - if (ruleset_id >= 0) - return ruleset_id; //found and existing one... - - uint32 len = strlen(in_ruleset_name); - auto ruleset_name = new char[2 * len + 1]; - database->DoEscapeString(ruleset_name, in_ruleset_name, len); - - std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", ruleset_name); - safe_delete_array(ruleset_name); - auto results = database->QueryDatabase(query); - if (!results.Success()) - return -1; - - return results.LastInsertedID(); -} - -std::string RuleManager::GetRulesetName(Database *database, int ruleset_id) { - std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", ruleset_id); - auto results = database->QueryDatabase(query); - if (!results.Success()) - return ""; - - if (results.RowCount() == 0) - return ""; - - auto row = results.begin(); - - return row[0]; -} - -bool RuleManager::ListRulesets(Database *database, std::map &into) { - - //start out with the default set which is always present. - into[0] = "default"; - - std::string query = "SELECT ruleset_id, name FROM rule_sets"; - auto results = database->QueryDatabase(query); - if (results.Success()) + const auto& l = RuleSetsRepository::All(*db); + if (l.empty()) { return false; + } - for (auto row = results.begin(); row != results.end(); ++row) - into[atoi(row[0])] = row[1]; + for (const auto& e : l) { + m[e.ruleset_id] = e.name; + } return true; } -int32 RuleManager::GetIntRule(RuleManager::IntType t) const +int RuleManager::GetIntRule(RuleManager::IntType t) const { - return (m_RuleIntValues[t]); + return m_RuleIntValues[t]; } float RuleManager::GetRealRule(RuleManager::RealType t) const { - return (m_RuleRealValues[t]); + return m_RuleRealValues[t]; } bool RuleManager::GetBoolRule(RuleManager::BoolType t) const { - return (m_RuleBoolValues[t] == 1); + return m_RuleBoolValues[t] == 1; } - diff --git a/common/rulesys.h b/common/rulesys.h index e9d3365fe..403f611e4 100644 --- a/common/rulesys.h +++ b/common/rulesys.h @@ -29,12 +29,12 @@ //note, these macros assume there is always a RuleManager *rules in scope, //which makes it a global for now, but with instancing we will do exactly //what we do with the zone global and just make it a member of core classes -#define RuleI(cat, rule) \ - RuleManager::Instance()->GetIntRule( RuleManager::Int__##rule ) -#define RuleR(cat, rule) \ - RuleManager::Instance()->GetRealRule( RuleManager::Real__##rule ) -#define RuleB(cat, rule) \ - RuleManager::Instance()->GetBoolRule( RuleManager::Bool__##rule ) +#define RuleI(category_name, rule_name) \ + RuleManager::Instance()->GetIntRule( RuleManager::Int__##rule_name ) +#define RuleR(category_name, rule_name) \ + RuleManager::Instance()->GetRealRule( RuleManager::Real__##rule_name ) +#define RuleB(category_name, rule_name) \ + RuleManager::Instance()->GetBoolRule( RuleManager::Bool__##rule_name ) #include @@ -49,91 +49,107 @@ class RuleManager { public: //generate our rule enums: typedef enum { - #define RULE_INT(cat, rule, default_value, notes) \ - Int__##rule, - #include "ruletypes.h" +#define RULE_INT(category_name, rule_name, default_value, notes) \ + Int__##rule_name, + +#include "ruletypes.h" + _IntRuleCount } IntType; + static const int IntRuleCount = static_cast(_IntRuleCount); + typedef enum { - #define RULE_REAL(cat, rule, default_value, notes) \ - Real__##rule, - #include "ruletypes.h" +#define RULE_REAL(category_name, rule_name, default_value, notes) \ + Real__##rule_name, + +#include "ruletypes.h" + _RealRuleCount } RealType; + static const int RealRuleCount = static_cast(_RealRuleCount); + typedef enum { - #define RULE_BOOL(cat, rule, default_value, notes) \ - Bool__##rule, - #include "ruletypes.h" +#define RULE_BOOL(category_name, rule_name, default_value, notes) \ + Bool__##rule_name, + +#include "ruletypes.h" + _BoolRuleCount } BoolType; + static const int BoolRuleCount = static_cast(_BoolRuleCount); + typedef enum { - #define RULE_CATEGORY(catname) \ - Category__##catname, - #include "ruletypes.h" +#define RULE_CATEGORY(category_name) \ + Category__##category_name, + +#include "ruletypes.h" + _CatCount } CategoryType; - static RuleManager* Instance() { + static RuleManager *Instance() + { static RuleManager rules; return &rules; } - static const IntType InvalidInt = _IntRuleCount; - static const RealType InvalidReal = _RealRuleCount; - static const BoolType InvalidBool = _BoolRuleCount; + static const IntType InvalidInt = _IntRuleCount; + static const RealType InvalidReal = _RealRuleCount; + static const BoolType InvalidBool = _BoolRuleCount; static const CategoryType InvalidCategory = _CatCount; - static const uint32 _RulesCount = _IntRuleCount+_RealRuleCount+_BoolRuleCount; + static const uint32 RulesCount = IntRuleCount + RealRuleCount + BoolRuleCount; //fetch routines, you should generally use the Rule* macros instead of this - int32 GetIntRule (IntType t) const; + int GetIntRule(IntType t) const; float GetRealRule(RealType t) const; bool GetBoolRule(BoolType t) const; //management routines - static const char *GetRuleName(IntType t) { return(s_RuleInfo[t].name); } - static const char *GetRuleName(RealType t) { return(s_RuleInfo[t+_IntRuleCount].name); } - static const char *GetRuleName(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].name); } - static const std::string &GetRuleNotes(IntType t) { return(s_RuleInfo[t].notes); } - static const std::string &GetRuleNotes(RealType t) { return(s_RuleInfo[t+_IntRuleCount].notes); } - static const std::string &GetRuleNotes(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].notes); } - static uint32 CountRules() { return(_RulesCount); } - static CategoryType FindCategory(const char *catname); - bool ListRules(const char *catname, std::vector &into); - bool ListCategories(std::vector &into); - bool GetRule(const char *rule_name, std::string &ret_val); - bool SetRule(const char *rule_name, const char *rule_value, Database *db = nullptr, bool db_save = false, bool reload = false); + static std::string GetRuleName(IntType t) { return s_RuleInfo[static_cast(t)].name; } + static std::string GetRuleName(RealType t) { return s_RuleInfo[static_cast(t) + IntRuleCount].name; } + static std::string GetRuleName(BoolType t) { return s_RuleInfo[static_cast(t) + IntRuleCount + RealRuleCount].name; } + static const std::string &GetRuleNotes(IntType t) { return s_RuleInfo[static_cast(t)].notes; } + static const std::string &GetRuleNotes(RealType t) { return s_RuleInfo[static_cast(t) + IntRuleCount].notes; } + static const std::string &GetRuleNotes(BoolType t) { return s_RuleInfo[static_cast(t) + IntRuleCount + RealRuleCount].notes; } + static uint32 CountRules() { return RulesCount; } + static CategoryType FindCategory(const std::string &category_name); + bool ListRules(const std::string &category_name, std::vector &l); + bool ListCategories(std::vector &l); + bool GetRule(const std::string &rule_name, std::string &rule_value); + bool SetRule( + const std::string &rule_name, + const std::string &rule_value, + Database *db = nullptr, + bool db_save = false, + bool reload = false + ); - int GetActiveRulesetID() const { return(m_activeRuleset); } - const char *GetActiveRuleset() const { return(m_activeName.c_str()); } - static int GetRulesetID(Database *db, const char *rulesetname); - static std::string GetRulesetName(Database *db, int id); - static bool ListRulesets(Database *db, std::map &into); + int GetActiveRulesetID() const { return m_activeRuleset; } + std::string GetActiveRuleset() const { return m_activeName; } + static bool ListRulesets(Database *db, std::map &l); void ResetRules(bool reload = false); - bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false); - void SaveRules(Database *db, const char *ruleset = nullptr); - bool UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update = false); + bool LoadRules(Database *db, const std::string &rule_set_name, bool reload = false); + void SaveRules(Database *db, const std::string &rule_set_name); + bool UpdateInjectedRules(Database *db, const std::string &rule_set_name, bool quiet_update = false); bool UpdateOrphanedRules(Database *db, bool quiet_update = false); bool RestoreRuleNotes(Database *db); private: RuleManager(); - RuleManager(const RuleManager&); - const RuleManager& operator=(const RuleManager&); + RuleManager(const RuleManager &); + const RuleManager &operator=(const RuleManager &); - int m_activeRuleset; + int m_activeRuleset; std::string m_activeName; -#ifdef WIN64 - uint32 m_RuleIntValues [_IntRuleCount ]; -#else - int m_RuleIntValues [_IntRuleCount ]; -#endif - float m_RuleRealValues[_RealRuleCount]; - uint32 m_RuleBoolValues[_BoolRuleCount]; + + int m_RuleIntValues[IntRuleCount]; + float m_RuleRealValues[RealRuleCount]; + uint32 m_RuleBoolValues[BoolRuleCount]; typedef enum { IntRule, @@ -141,23 +157,21 @@ private: BoolRule } RuleType; - static bool _FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into); - static const char *_GetRuleName(RuleType type, uint16 index); + static bool _FindRule(const std::string &rule_name, RuleType &type_into, uint16 &index_into); + static std::string _GetRuleName(RuleType type, uint16 index); static const std::string &_GetRuleNotes(RuleType type, uint16 index); - static int _FindOrCreateRuleset(Database *db, const char *ruleset); + static int _FindOrCreateRuleset(Database *db, const std::string &rule_set_name); void _SaveRule(Database *db, RuleType type, uint16 index); - - static const char *s_categoryNames[]; + + static const char* s_categoryNames[]; typedef struct { - const char *name; - CategoryType category; - RuleType type; - uint16 rule_index; //index into its 'type' array + std::string name; + CategoryType category; + RuleType type; + uint16 rule_index; const std::string notes; } RuleInfo; static const RuleInfo s_RuleInfo[]; - }; #endif /*RULESYS_H_*/ - diff --git a/common/ruletypes.h b/common/ruletypes.h index d06f9280c..d30c1be98 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -44,6 +44,7 @@ RULE_INT(Character, DeathExpLossLevel, 10, "Any level equal to or greater than t RULE_INT(Character, DeathExpLossMaxLevel, 255, "Every higher level will no longer lose experience at death") RULE_INT(Character, DeathItemLossLevel, 10, "From this level on, items are left in the corpse when LeaveCorpses is activated") RULE_INT(Character, DeathExpLossMultiplier, 3, "Adjust how much experience is lost. Default 3.5% (0=0.5%, 1=1.5%, 2=2.5%, 3=3.5%, 4=4.5%, 5=5.5%, 6=6.5%, 7=7.5%, 8=8.5%, 9=9.5%, 10=11%)") +RULE_BOOL(Character, DeathKeepLevel, false, "Players can not drop below 0% experience from death.") RULE_BOOL(Character, UseDeathExpLossMult, false, "Setting to control whether DeathExpLossMultiplier or the code default is used: (Level x Level / 18.0) x 12000") RULE_BOOL(Character, UseOldRaceRezEffects, false, "Older clients had ID 757 for races with high starting STR, but it doesn't seem used anymore") RULE_INT(Character, CorpseDecayTimeMS, 10800000, "Time after which the corpse decays (milliseconds)") @@ -129,17 +130,17 @@ RULE_INT(Character, BaseRunSpeedCap, 158, "Base Run Speed Cap, on live it's 158% RULE_INT(Character, OrnamentationAugmentType, 20, "Ornamentation Augment Type") RULE_REAL(Character, EnvironmentDamageMulipliter, 1, "Multiplier for environmental damage like fall damage.") RULE_BOOL(Character, UnmemSpellsOnDeath, true, "Setting whether at death all memorized Spells are forgotten") -RULE_INT(Character, TradeskillUpAlchemy, 2, "Alchemy skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpBaking, 2, "Baking skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpBlacksmithing, 2, "Blacksmithing skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpBrewing, 3, "Brewing skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpFletching, 2, "Fletching skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpJewelcrafting, 2, "Jewelcrafting skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpMakePoison, 2, "Make Poison skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpPottery, 4, "Pottery skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpResearch, 1, "Research skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpTinkering, 2, "Tinkering skillup rate adjustment. Lower is faster") -RULE_INT(Character, TradeskillUpTailoring, 2, "Tailoring skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpAlchemy, 2.0, "Alchemy skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpBaking, 2.0, "Baking skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpBlacksmithing, 2.0, "Blacksmithing skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpBrewing, 3.0, "Brewing skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpFletching, 2.0, "Fletching skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpJewelcrafting, 2.0, "Jewelcrafting skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpMakePoison, 2.0, "Make Poison skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpPottery, 4.0, "Pottery skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpResearch, 1.0, "Research skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpTinkering, 2.0, "Tinkering skillup rate adjustment. Lower is faster") +RULE_REAL(Character, TradeskillUpTailoring, 2.0, "Tailoring skillup rate adjustment. Lower is faster") RULE_BOOL(Character, MarqueeHPUpdates, false, "Will show health percentage in center of screen if health lesser than 100%") RULE_INT(Character, IksarCommonTongue, 95, "Starting value for Common Tongue for Iksars") RULE_INT(Character, OgreCommonTongue, 95, "Starting value for Common Tongue for Ogres") @@ -150,8 +151,6 @@ RULE_INT(Character, InvSnapshotMinRetryM, 30, "Time to re-attempt an inventory s RULE_INT(Character, InvSnapshotHistoryD, 30, "Time to keep snapshot entries (days)") RULE_BOOL(Character, RestrictSpellScribing, false, "Setting whether to restrict spell scribing to allowable races/classes of spell scroll") RULE_BOOL(Character, UseStackablePickPocketing, true, "Allows stackable pickpocketed items to stack instead of only being allowed in empty inventory slots") -RULE_BOOL(Character, EnableAvoidanceCap, false, "Setting whether the avoidance cap should be activated") -RULE_INT(Character, AvoidanceCap, 750, "750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance") RULE_BOOL(Character, AllowMQTarget, false, "Disables putting players in the 'hackers' list for targeting beyond the clip plane or attempting to target something untargetable") RULE_BOOL(Character, UseOldBindWound, false, "Uses the original bind wound behavior") RULE_BOOL(Character, GrantHoTTOnCreate, false, "Grant Health of Target's Target leadership AA on character creation") @@ -160,6 +159,7 @@ RULE_BOOL(Character, OPClientUpdateVisualDebug, false, "Shows a pulse and forwar RULE_BOOL(Character, AllowCrossClassTrainers, false, "If the value is true, a player can also train with other class Guildmasters.") RULE_BOOL(Character, PetsUseReagents, true, "Conjuring pets consumes reagents") RULE_BOOL(Character, DismountWater, true, "Dismount horses when entering water") +RULE_BOOL(Character, NoSkillsOnHorse, false, "Enabling this will prevent Bind Wound and Foraging while on a mount") RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing") RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted") RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated") @@ -193,6 +193,13 @@ RULE_INT(Character, EnchanterTrackingDistanceMultiplier, 0, "If you want enchant RULE_INT(Character, BeastlordTrackingDistanceMultiplier, 0, "If you want beastlords to be able to track, increase this above 0. 0 disables tracking packets.") RULE_INT(Character, BerserkerTrackingDistanceMultiplier, 0, "If you want berserkers to be able to track, increase this above 0. 0 disables tracking packets.") RULE_BOOL(Character, OnInviteReceiveAlreadyinGroupMessage, true, "If you want clients to receive a message when trying to invite a player into a group that is currently in another group.") +RULE_BOOL(Character, PetZoneWithOwner, true, "Should Pets Zone with Owner") +RULE_BOOL(Character, FullManaOnDeath, true, "On death set mana to full") +RULE_BOOL(Character, FullEndurOnDeath, true, "On death set endurance to full") +RULE_INT(Character, ExperiencePercentCapPerKill, -1, "Caps the percentage of experience that can be gained per kill. -1 disables the cap; 0 blocks all (non-aa) xp.") +RULE_BOOL(Character, EnableGroupEXPModifier, true, "Enable or disable the group experience modifier based on number of players in group, default is true") +RULE_REAL(Character, GroupMemberEXPModifier, 0.2, "Sets the group experience modifier per members between 2 and 5, default is 0.2") +RULE_REAL(Character, FullGroupEXPModifier, 2.16, "Sets the group experience modifier for a full group, default is 2.16") RULE_CATEGORY_END() RULE_CATEGORY(Mercs) @@ -283,7 +290,7 @@ RULE_CATEGORY(Zone) RULE_INT(Zone, ClientLinkdeadMS, 90000, "The time a client remains link dead on the server after a sudden disconnection (milliseconds)") RULE_INT(Zone, GraveyardTimeMS, 1200000, "Time until a player corpse is moved to a zone's graveyard, if one is specified for the zone (milliseconds)") RULE_BOOL(Zone, EnableShadowrest, 1, "Enables or disables the Shadowrest zone feature for player corpses. Default is turned on") -RULE_INT(Zone, AutoShutdownDelay, 5000, "How long a dynamic zone stays loaded while empty (milliseconds)") +RULE_INT(Zone, AutoShutdownDelay, 60000, "How long a dynamic zone stays loaded while empty (milliseconds)") RULE_INT(Zone, PEQZoneReuseTime, 900, "Seconds between two uses of the #peqzone command (Set to 0 to disable)") RULE_INT(Zone, PEQZoneDebuff1, 4454, "First debuff casted by #peqzone Default is Cursed Keeper's Blight") RULE_INT(Zone, PEQZoneDebuff2, 2209, "Second debuff casted by #peqzone Default is Tendrils of Apathy") @@ -302,6 +309,7 @@ RULE_INT(Zone, GlobalLootMultiplier, 1, "Sets Global Loot drop multiplier for da RULE_BOOL(Zone, KillProcessOnDynamicShutdown, true, "When process has booted a zone and has hit its zone shut down timer, it will hard kill the process to free memory back to the OS") RULE_INT(Zone, SecondsBeforeIdle, 60, "Seconds before IDLE_WHEN_EMPTY define kicks in") RULE_INT(Zone, SpawnEventMin, 3, "When strict is set in spawn_events, specifies the max EQ minutes into the trigger hour a spawn_event will fire. Going below 3 may cause the spawn_event to not fire.") +RULE_INT(Zone, ForageChance, 25, "Chance of foraging from zone table vs global table") RULE_CATEGORY_END() RULE_CATEGORY(Map) @@ -350,7 +358,6 @@ RULE_INT(Spells, MaxTotalSlotsPET, 30, "Maximum total of pet slots. The default RULE_BOOL (Spells, EnableBlockedBuffs, true, "Allow blocked spells") RULE_INT(Spells, ReflectType, 4, "Reflect type. 0=disabled, 1=single target player spells only, 2=all player spells, 3=all single target spells, 4=all spells") RULE_BOOL(Spells, ReflectMessagesClose, true, "True (Live functionality) is for Reflect messages to show to players within close proximity. False shows just player reflecting") -RULE_INT(Spells, VirusSpreadDistance, 30, "The distance a viral spell will jump to its next victim") RULE_BOOL(Spells, LiveLikeFocusEffects, true, "Determines whether specific healing, dmg and mana reduction focuses are randomized") RULE_INT(Spells, BaseImmunityLevel, 55, "The level that targets start to be immune to stun, fear and mez spells with a maximum level of 0") RULE_BOOL(Spells, NPCIgnoreBaseImmunity, true, "Whether or not NPC get to ignore the BaseImmunityLevel for their spells") @@ -402,6 +409,7 @@ RULE_BOOL(Spells, ItemExtraSpellAmtCalcAsPercent, false, "Apply the Item stats S RULE_BOOL(Spells, AllowItemTGB, false, "Target group buff (/tgb) doesn't work with items on live, custom servers want it though") RULE_BOOL(Spells, NPCInnateProcOverride, true, "NPC innate procs override the target type to single target") RULE_BOOL(Spells, OldRainTargets, false, "Use old incorrectly implemented maximum targets for rains") +RULE_REAL(Spells, CallOfTheHeroAggroClearDist, 250.0, "Distance at which CoTH will wipe aggro. To disable and always enable aggro wipe on any distance of CoTH, set to 0.") RULE_BOOL(Spells, NPCSpellPush, false, "Enable spell push on NPCs") RULE_BOOL(Spells, July242002PetResists, true, "Enable Pets using PCs resist change from July 24 2002") RULE_INT(Spells, AOEMaxTargets, 0, "Max number of targets a Targeted AOE spell can cast on. Set to 0 for no limit.") @@ -417,6 +425,11 @@ RULE_BOOL(Spells, CompoundLifetapHeals, true, "True: Lifetap heals calculate dam RULE_BOOL(Spells, UseFadingMemoriesMaxLevel, false, "Enables to limit field in spell data to set the max level that over which an NPC will ignore fading memories effect and not lose aggro.") RULE_BOOL(Spells, FixBeaconHeading, false, "Beacon spells use casters heading to fix live bug. False: Live like heading always 0.") RULE_BOOL(Spells, UseSpellImpliedTargeting, false, "Replicates EQ2-style targeting behavior for spells. Spells will 'pass through' inappropriate targets to target's target if it is appropriate.") +RULE_BOOL(Spells, BuffsFadeOnDeath, true, "Disable to keep buffs from fading on death") +RULE_BOOL(Spells, IllusionsAlwaysPersist, false, "Allows Illusions to persist beyond death and zoning always.") +RULE_BOOL(Spells, UseItemCastMessage, false, "Enable to use the \"item begins to glow\" messages when casting from an item.") +RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type") +RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true") RULE_CATEGORY_END() RULE_CATEGORY(Combat) @@ -441,17 +454,6 @@ RULE_REAL(Combat, AvgProcsPerMinute, 2.0, "Average proc rate per minute") RULE_REAL(Combat, ProcPerMinDexContrib, 0.075, "Increases the probability of a proc increased by DEX by the value indicated") RULE_REAL(Combat, BaseProcChance, 0.035, "Base chance for procs") RULE_REAL(Combat, ProcDexDivideBy, 11000, "Divisor for the probability of a proc increased by dexterity") -RULE_REAL(Combat, BaseHitChance, 69.0, "Base chance to hit") -RULE_REAL(Combat, NPCBonusHitChance, 26.0, "Bonus chance to hit for NPC") -RULE_REAL(Combat, HitFalloffMinor, 5.0, "Hit will fall off up to value over the initial level range (percent)") -RULE_REAL(Combat, HitFalloffModerate, 7.0, "Hit will fall off up to value over the three levels after the initial level range (percent)") -RULE_REAL(Combat, HitFalloffMajor, 50.0, "Hit will fall off sharply if we're outside the minor and moderate range") -RULE_REAL(Combat, HitBonusPerLevel, 1.2, "You gain this percentage of hit for every level you are above your target") -RULE_REAL(Combat, WeaponSkillFalloff, 0.33, "For every weapon skill point that's not maxed you lose this percentage of hit") -RULE_REAL(Combat, ArcheryHitPenalty, 0.25, "Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it") -RULE_REAL(Combat, AgiHitFactor, 0.01, "Factor with which agility is taken into account in the hit probability. Higher is better") -RULE_REAL(Combat, MinChancetoHit, 5.0, "Minimum percentage chance to hit with regular melee/ranged") -RULE_REAL(Combat, MaxChancetoHit, 95.0, "Maximum percentage chance to hit with regular melee/ranged") RULE_INT(Combat, MinRangedAttackDist, 25, "Minimum Distance to use Ranged Attacks") RULE_BOOL(Combat, ArcheryBonusRequiresStationary, true, "does the 2x archery bonus chance require a stationary npc") RULE_REAL(Combat, ArcheryNPCMultiplier, 1.0, "Value is multiplied by the regular dmg to get the archery dmg") @@ -460,40 +462,13 @@ RULE_INT(Combat, MaxRampageTargets, 3, "Maximum number of people hit with rampag RULE_INT(Combat, DefaultRampageTargets, 1, "Default number of people to hit with rampage") RULE_BOOL(Combat, RampageHitsTarget, false, "Rampage will hit the target if it still has targets left") RULE_INT(Combat, MaxFlurryHits, 2, "Maximum number of extra hits from flurry") -RULE_REAL(Combat, NPCACFactor, 2.25, "If UseIntervalAC is enabled, the armor class for NPC is divided by this value") -RULE_INT(Combat, ClothACSoftcap, 75, "If OldACSoftcapRules is true: armorclass softcap for cloth armor") -RULE_INT(Combat, LeatherACSoftcap, 100, "If OldACSoftcapRules is true: armorclass softcap for leather armor") -RULE_INT(Combat, MonkACSoftcap, 120, "If OldACSoftcapRules is true: armorclass softcap for monks") -RULE_INT(Combat, ChainACSoftcap, 200, "If OldACSoftcapRules is true: armorclass softcap for chain armor") -RULE_INT(Combat, PlateACSoftcap, 300, "If OldACSoftcapRules is true: armorclass softcap for plate armor") -RULE_REAL(Combat, AAMitigationACFactor, 3.0, "If OldACSoftcapRules: AA mitgation armorclass factor") -RULE_REAL(Combat, WarriorACSoftcapReturn, 0.45, "If OldACSoftcapRules: warrior armorclass softcap increase-factor") -RULE_REAL(Combat, KnightACSoftcapReturn, 0.33, "If OldACSoftcapRules: SHD/PAL/MNK armorclass softcap increase-factor") -RULE_REAL(Combat, LowPlateChainACSoftcapReturn, 0.23, "If OldACSoftcapRules: CLR/BRD/BSK/ROG/SHA/MNK armorclass softcap increase-factor") -RULE_REAL(Combat, LowChainLeatherACSoftcapReturn, 0.17, "If OldACSoftcapRules: RNG/BST armorclass softcap increase-factor") -RULE_REAL(Combat, CasterACSoftcapReturn, 0.06, "If OldACSoftcapRules: WIZ/MAG/NEC/ENC/DRU armorclass softcap increase-factor") -RULE_REAL(Combat, MiscACSoftcapReturn, 0.3, "If OldACSoftcapRules true/false: unspecified classes armorclass softcap increase-factor") -RULE_BOOL(Combat, OldACSoftcapRules, false, "Setting if the old softcap values should be used") -RULE_BOOL(Combat, UseOldDamageIntervalRules, false, "Use old damage formulas for everything") -RULE_REAL(Combat, WarACSoftcapReturn, 0.3448, "WAR armorclass softcap increase-factor") -RULE_REAL(Combat, ClrRngMnkBrdACSoftcapReturn, 0.3030, "CLR/RNG/MNK/BRD armorclass softcap increase-factor") -RULE_REAL(Combat, PalShdACSoftcapReturn, 0.3226, "SHD/PAL armorclass softcap increase-factor") -RULE_REAL(Combat, DruNecWizEncMagACSoftcapReturn, 0.2000, "DRU/NEC/WIZ/ENC/MAG softcap increase-factor") -RULE_REAL(Combat, RogShmBstBerACSoftcapReturn, 0.2500, "ROG/SHM/BST/BER softcap increase-factor") -RULE_REAL(Combat, SoftcapFactor, 1.88, "When UseIntervalAC is enabled, the softcap for mitigation capability is multiplied by this value") -RULE_REAL(Combat, ACthac0Factor, 0.55, "If a mob is attacked and the attack roll is greater than his defense roll, the attack rating is multiplied by this value") -RULE_REAL(Combat, ACthac20Factor, 0.55, "If a mob is attacked and his defense roll is greater than the attack roll, the attack rating is multiplied by this value") -RULE_INT(Combat, HitCapPre20, 40, "Hit cap before level 20. Live has it capped at 40") -RULE_INT(Combat, HitCapPre10, 20, "Hit cap before level 10. Live has it capped at 20") RULE_INT(Combat, MinHastedDelay, 400, "Minimum hasted combat delay") RULE_REAL(Combat, AvgDefProcsPerMinute, 2.0, "Average defense procs per minute") RULE_REAL(Combat, DefProcPerMinAgiContrib, 0.075, "How much agility contributes to defensive proc rate") -RULE_INT(Combat, SpecialAttackACBonus, 15, "Percent amount of damage per AC gained for certain special attacks (damage = AC*SpecialAttackACBonus/100)") RULE_INT(Combat, NPCFlurryChance, 20, "Chance for NPC to flurry") RULE_BOOL(Combat, TauntOverLevel, 1, "Allows you to taunt NPC's over warriors level") RULE_REAL(Combat, TauntSkillFalloff, 0.33, "For every taunt skill point that's not maxed you lose this percentage chance to taunt") RULE_BOOL(Combat, EXPFromDmgShield, false, "Determine if damage from a damage shield counts for experience gain") -RULE_INT(Combat, MonkACBonusWeight, 15, "Usually, a monk under this weight threshold gets an AC bonus") RULE_INT(Combat, QuiverHasteCap, 1000, "Quiver haste cap 1000 on live for a while, currently 700 on live") RULE_INT(Combat, BerserkerFrenzyStart, 35, "Percentage Health Points below which Warrior and Berserker start frenzy") RULE_INT(Combat, BerserkerFrenzyEnd, 45, "Percentage Health Points above which Warrior and Berserker end frenzy") @@ -518,6 +493,15 @@ RULE_BOOL(Combat, Classic2HBAnimation, false, "2HB will use the 2 hand piercing RULE_BOOL(Combat, ArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption") RULE_BOOL(Combat, ThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption") RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SE_RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.") +RULE_INT(Combat, FrontalStunImmunityClasses, 0, "Bitmask for Classes than have frontal stun immunity, No Races (0) by default.") +RULE_BOOL(Combat, NPCsUseFrontalStunImmunityClasses, false, "Enable or disable NPCs using frontal stun immunity Classes from Combat:FrontalStunImmunityClasses, false by default.") +RULE_INT(Combat, FrontalStunImmunityRaces, 512, "Bitmask for Races than have frontal stun immunity, Ogre (512) only by default.") +RULE_BOOL(Combat, NPCsUseFrontalStunImmunityRaces, true, "Enable or disable NPCs using frontal stun immunity Races from Combat:FrontalStunImmunityRaces, true by default.") +RULE_BOOL(Combat, AssassinateOnlyHumanoids, true, "Enable or disable Assassinate only being allowed on Humanoids, true by default.") +RULE_BOOL(Combat, HeadshotOnlyHumanoids, true, "Enable or disable Headshot only being allowed on Humanoids, true by default.") +RULE_BOOL(Combat, EnableWarriorShielding, true, "Enable or disable Warrior Shielding Ability (/shield), true by default.") +RULE_BOOL(Combat, BackstabIgnoresElemental, false, "Enable or disable Elemental weapon damage affecting backstab damage, false by default.") +RULE_BOOL(Combat, BackstabIgnoresBane, false, "Enable or disable Bane weapon damage affecting backstab damage, false by default.") RULE_CATEGORY_END() RULE_CATEGORY(NPC) @@ -550,6 +534,7 @@ RULE_BOOL(NPC, UseMeditateBasedManaRegen, false, "Based NPC ooc regen on Meditat RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the NPC will heal on gate if enabled") RULE_BOOL(NPC, AnimalsOpenDoors, true, "Determines or not whether animals open doors or not when they approach them") RULE_INT(NPC, MaxRaceID, 732, "Maximum Race ID, RoF2 by default supports up to 732") +RULE_BOOL(NPC, DisableLastNames, false, "Enable to disable NPC Last Names") RULE_CATEGORY_END() RULE_CATEGORY(Aggro) @@ -581,6 +566,9 @@ RULE_BOOL(TaskSystem, RecordCompletedOptionalActivities, false, "Record complete RULE_BOOL(TaskSystem, KeepOneRecordPerCompletedTask, true, "Keep only one record per completed task") RULE_BOOL(TaskSystem, EnableTaskProximity, true, "Enable task proximity system") RULE_INT(TaskSystem, RequestCooldownTimerSeconds, 15, "Seconds between allowing characters to request tasks (live-like default: 15 seconds)") +RULE_INT(TaskSystem, SharedTasksWorldProcessRate, 6000, "Timer interval (milliseconds) that shared tasks are processed in world") +RULE_INT(TaskSystem, SharedTasksTerminateTimerMS, 120000, "Delay (milliseconds) until a shared task is terminated if requirements are no longer met after member removal (default: 2 minutes)") +RULE_BOOL(TaskSystem, UpdateOneElementPerTask, true, "If true (live-like) task updates only increment the first matching activity. If false all matching elements will be incremented.") RULE_CATEGORY_END() RULE_CATEGORY(Range) @@ -597,11 +585,11 @@ RULE_INT(Range, CriticalDamage, 80, "The packet range in which critical hit mess RULE_INT(Range, MobCloseScanDistance, 600, "Close scan distance") RULE_CATEGORY_END() - -#ifdef BOTS RULE_CATEGORY(Bots) +RULE_BOOL(Bots, Enabled, false, "Enable of disable bot functionality, default is false") RULE_INT(Bots, BotExpansionSettings, 16383, "Sets the expansion settings for bot use. Defaults to all expansions enabled up to TSS") RULE_BOOL(Bots, AllowCamelCaseNames, false, "Allows the use of 'MyBot' type names") +RULE_BOOL(Bots, AllowBotEquipAnyRaceGear, false, "Allows Bots to wear Equipment even if their race is not valid") RULE_INT(Bots, CommandSpellRank, 1, "Filters bot command spells by rank. 1, 2 and 3 are valid filters - any other number allows all ranks") RULE_INT(Bots, CreationLimit, 150, "Number of bots that each account can create") RULE_BOOL(Bots, FinishBuffing, false, "Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat") @@ -627,7 +615,6 @@ RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell") RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell") RULE_CATEGORY_END() -#endif RULE_CATEGORY(Chat) RULE_BOOL(Chat, ServerWideOOC, true, "Enable server wide ooc-chat") @@ -636,6 +623,7 @@ RULE_BOOL(Chat, EnableVoiceMacros, true, "Enable voice macros") RULE_BOOL(Chat, EnableMailKeyIPVerification, true, "Setting whether the authenticity of the client should be verified via its IP address when accessing the InGame mailbox") RULE_BOOL(Chat, EnableAntiSpam, true, "Enable anti-spam system for chat") RULE_BOOL(Chat, SuppressCommandErrors, false, "Do not suppress command errors by default") +RULE_INT(Chat, MaxPermanentPlayerChannels, 0, "Maximum number of permanent chat channels a player can make. Default 0.") RULE_INT(Chat, MinStatusToBypassAntiSpam, 100, "Minimum status to bypass the anti-spam system") RULE_INT(Chat, MinimumMessagesPerInterval, 4, "Minimum number of chat messages allowed per interval. The karma value is added to this value") RULE_INT(Chat, MaximumMessagesPerInterval, 12, "Maximum value of chat messages allowed per interval") @@ -698,6 +686,7 @@ RULE_INT(Adventure, ItemIDToEnablePorts, 41000, "ItemID to enable adventure port RULE_INT(Adventure, LDoNTrapDistanceUse, 625, "LDoN trap distance use") RULE_REAL(Adventure, LDoNBaseTrapDifficulty, 15.0, "LDoN base trap difficulty") RULE_REAL(Adventure, LDoNCriticalFailTrapThreshold, 10.0, "LDoN critical fail trap threshold") +RULE_INT(Adventure, LDoNLootCountModifier, 10, "LDoN Loot Count Modifier, lower is better (default is 10)") RULE_CATEGORY_END() RULE_CATEGORY(AA) @@ -709,6 +698,7 @@ RULE_REAL(AA, ModernAAScalingStartPercent, 1000, "1000% or 10x AA experience at RULE_INT(AA, ModernAAScalingAAMinimum, 0, "The minimum number of earned AA before AA experience scaling begins") RULE_INT(AA, ModernAAScalingAALimit, 4000, "The number of earned AA when AA experience scaling ends") RULE_BOOL(AA, SoundForAAEarned, false, "Play sound when AA point earned") +RULE_INT(AA, UnusedAAPointCap, -1, "Cap for Unused AA Points. Default: -1. NOTE: DO NOT LOWER THIS WITHOUT KNOWING WHAT YOU ARE DOING. MAY RESULT IN PLAYERS LOSING AAs.") RULE_CATEGORY_END() RULE_CATEGORY(Console) @@ -763,8 +753,6 @@ RULE_CATEGORY_END() RULE_CATEGORY(Bugs) RULE_BOOL(Bugs, ReportingSystemActive, true, "Activates bug reporting") -RULE_BOOL(Bugs, UseOldReportingMethod, true, "Forces the use of the old bug reporting system") -RULE_BOOL(Bugs, DumpTargetEntity, false, "Dumps the target entity, if one is provided") RULE_CATEGORY_END() RULE_CATEGORY(Faction) @@ -833,12 +821,25 @@ RULE_CATEGORY_END() RULE_CATEGORY(Command) RULE_BOOL(Command, DyeCommandRequiresDyes, false, "Enable this to require a Prismatic Dye (32557) each time someone uses #dye.") +RULE_BOOL(Command, HideMeCommandDisablesTells, true, "Disable this to allow tells to be received when using #hideme.") RULE_CATEGORY_END() RULE_CATEGORY(Doors) RULE_BOOL(Doors, RequireKeyOnCursor, false, "Enable this to require pre-keyring keys to be on player cursor to open doors.") RULE_CATEGORY_END() +RULE_CATEGORY(Items) +RULE_BOOL(Items, DisableAttuneable, false, "Enable this to disable Attuneable Items") +RULE_BOOL(Items, DisableBardFocusEffects, false, "Enable this to disable Bard Focus Effects on Items") +RULE_BOOL(Items, DisableLore, false, "Enable this to disable Lore Items") +RULE_BOOL(Items, DisableNoDrop, false, "Enable this to disable No Drop Items") +RULE_BOOL(Items, DisableNoPet, false, "Enable this to disable No Pet Items") +RULE_BOOL(Items, DisableNoRent, false, "Enable this to disable No Rent Items") +RULE_BOOL(Items, DisableNoTransfer, false, "Enable this to disable No Transfer Items") +RULE_BOOL(Items, DisablePotionBelt, false, "Enable this to disable Potion Belt Items") +RULE_BOOL(Items, DisableSpellFocusEffects, false, "Enable this to disable Spell Focus Effects on Items") +RULE_CATEGORY_END() + #undef RULE_CATEGORY #undef RULE_INT #undef RULE_REAL diff --git a/common/say_link.cpp b/common/say_link.cpp index a10dc4b2d..fc9f61696 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -20,7 +20,7 @@ #include "say_link.h" #include "emu_constants.h" -#include "string_util.h" +#include "strings.h" #include "item_instance.h" #include "item_data.h" #include "../zone/zonedb.h" @@ -322,145 +322,54 @@ std::string EQ::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bo std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message) { - std::string new_message = message; - int link_index = 0; - int saylink_index = 0; - std::vector links = {}; - std::vector saylinks = {}; - int saylink_length = 50; - std::string saylink_separator = "\u0012"; - std::string saylink_partial = "00000"; + LogSaylinkDetail("message [{}]", message); - LogSaylinkDetail("new_message pre pass 1 [{}]", new_message); + std::string new_message; + new_message.reserve(strlen(message)); - // first pass - strip existing saylinks by putting placeholder anchors on them - for (auto &saylink: split_string(new_message, saylink_separator)) { - if (!saylink.empty() && saylink.length() > saylink_length && - saylink.find(saylink_partial) != std::string::npos) { - saylinks.emplace_back(saylink); + bool in_bracket_state = false; + bool in_link_state = false; - LogSaylinkDetail("Found saylink [{}]", saylink); + const char* ch = message; + const char* startpos = message; + for (; *ch != '\0'; ++ch) + { + // saylinks not added if spaces touch brackets + bool abort_space = in_bracket_state && *ch == ' ' && (*(ch-1) == '[' || *(ch+1) == ']'); - // replace with anchor - find_replace( - new_message, - fmt::format("{}", saylink), - fmt::format("", saylink_index) - ); - - saylink_index++; + if (in_bracket_state && (*ch == '[' || *ch == '\x12' || abort_space)) + { + // abort due to nested bracket (which starts another) or existing saylink + new_message.append(startpos, ch - startpos); + in_bracket_state = false; } - } - - LogSaylinkDetail("new_message post pass 1 [{}]", new_message); - - LogSaylinkDetail("saylink separator count [{}]", std::count(new_message.begin(), new_message.end(), '\u0012')); - - // loop through brackets until none exist - if (new_message.find('[') != std::string::npos) { - for (auto &b: split_string(new_message, "[")) { - if (!b.empty() && b.find(']') != std::string::npos) { - std::vector right_split = split_string(b, "]"); - if (!right_split.empty()) { - std::string bracket_message = trim(right_split[0]); - - // we shouldn't see a saylink fragment here, ignore this bracket - if (bracket_message.find(saylink_partial) != std::string::npos) { - continue; - } - - // skip where multiple saylinks are within brackets - if (bracket_message.find(saylink_separator) != std::string::npos && - std::count(bracket_message.begin(), bracket_message.end(), '\u0012') > 1) { - continue; - } - - // if non empty bracket contents - if (!bracket_message.empty()) { - LogSaylinkDetail("Found bracket_message [{}]", bracket_message); - - // already a saylink - // todo: improve this later - if (!bracket_message.empty() && - (bracket_message.length() > saylink_length || - bracket_message.find(saylink_separator) != std::string::npos)) { - links.emplace_back(bracket_message); - } - else { - links.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - bracket_message, - false, - bracket_message - ) - ); - } - - // replace with anchor - find_replace( - new_message, - fmt::format("[{}]", bracket_message), - fmt::format("", link_index) - ); - - link_index++; - } - } + else if (in_bracket_state && *ch == ']') + { + if (ch != startpos) + { + std::string str(startpos, ch - startpos); + new_message += EQ::SayLinkEngine::GenerateQuestSaylink(str, false, str); } + in_bracket_state = false; + } + + if (!in_bracket_state) + { + new_message.push_back(*ch); + } + + if (*ch == '[' && !in_link_state) + { + startpos = ch + 1; + in_bracket_state = true; + } + else if (*ch == '\x12') + { + in_link_state = !in_link_state; } } - LogSaylinkDetail("new_message post pass 2 (post brackets) [{}]", new_message); - - // strip any current delimiters of saylinks - find_replace(new_message, saylink_separator, ""); - - // pop links onto anchors - link_index = 0; - for (auto &link: links) { - - // strip any current delimiters of saylinks - find_replace(link, saylink_separator, ""); - - find_replace( - new_message, - fmt::format("", link_index), - fmt::format("[\u0012{}\u0012]", link) - ); - link_index++; - } - - LogSaylinkDetail("new_message post pass 3 (post prelink anchor pop) [{}]", new_message); - - // pop links onto anchors - saylink_index = 0; - for (auto &link: saylinks) { - // strip any current delimiters of saylinks - find_replace(link, saylink_separator, ""); - - // check to see if we did a double anchor pass (existing saylink that was also inside brackets) - // this means we found a saylink and we're checking to see if we're already encoded before double encoding - if (new_message.find(fmt::format("\u0012\u0012", saylink_index)) != std::string::npos) { - LogSaylinkDetail("Found encoded saylink at index [{}]", saylink_index); - - find_replace( - new_message, - fmt::format("\u0012\u0012", saylink_index), - fmt::format("\u0012{}\u0012", link) - ); - saylink_index++; - continue; - } - - find_replace( - new_message, - fmt::format("", saylink_index), - fmt::format("\u0012{}\u0012", link) - ); - saylink_index++; - } - - LogSaylinkDetail("new_message post pass 4 (post saylink anchor pop) [{}]", new_message); + LogSaylinkDetail("new_message [{}]", new_message); return new_message; } @@ -485,7 +394,7 @@ SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string sayli auto saylinks = SaylinkRepository::GetWhere( database, - fmt::format("phrase = '{}'", EscapeString(saylink_text)) + fmt::format("phrase = '{}'", Strings::Escape(saylink_text)) ); // return if found from the database @@ -508,3 +417,12 @@ SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string sayli return {}; } + +std::string Saylink::Create(const std::string &saylink_text, bool silent, const std::string &link_name) +{ + return EQ::SayLinkEngine::GenerateQuestSaylink(saylink_text, silent, (link_name.empty() ? saylink_text : link_name)); +} + +std::string Saylink::Silent(const std::string &saylink_text, const std::string &link_name) { + return EQ::SayLinkEngine::GenerateQuestSaylink(saylink_text, true, (link_name.empty() ? saylink_text : link_name)); +} diff --git a/common/say_link.h b/common/say_link.h index aec8d8879..d31a10142 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -127,4 +127,10 @@ namespace EQ } /*EQEmu*/ +class Saylink { +public: + static std::string Create(const std::string &saylink_text, bool silent, const std::string &link_name = ""); + static std::string Silent(const std::string &saylink_text, const std::string &link_name = ""); +}; + #endif /*COMMON_SAY_LINK_H*/ diff --git a/common/server_event_scheduler.cpp b/common/server_event_scheduler.cpp index 1034eebfe..2fa592b22 100644 --- a/common/server_event_scheduler.cpp +++ b/common/server_event_scheduler.cpp @@ -1,5 +1,5 @@ #include "../common/database.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "server_event_scheduler.h" #include "../common/cron/croncpp.h" #include @@ -109,7 +109,7 @@ bool ServerEventScheduler::ValidateEventReadyToActivate( if (now_time_unix >= start_time_unix && (doesnt_end || now_time_unix < end_time_unix)) { LogSchedulerDetail( - "[ValidateEventReadyToActivate] now_time [{}] start_time [{}] doesnt_end [{}] end_time [{}]", + "now_time [{}] start_time [{}] doesnt_end [{}] end_time [{}]", now_time_unix, start_time_unix, doesnt_end ? "true" : "false", @@ -131,7 +131,7 @@ ServerEventScheduler *ServerEventScheduler::SetDatabase(Database *db) bool ServerEventScheduler::ValidateDatabaseConnection() { if (!m_database) { - LogError("[ServerEventScheduler::LoadScheduledEvents] No database connection"); + LogError("No database connection"); return false; } @@ -174,7 +174,7 @@ bool ServerEventScheduler::CheckIfEventsChanged() dbe.created_at != e.created_at || dbe.deleted_at != e.deleted_at ) { - LogSchedulerDetail("[CheckIfEventsChanged] Field change detected"); + LogSchedulerDetail("Field change detected"); m_events = events; return true; } diff --git a/common/servertalk.h b/common/servertalk.h index bcc4d739f..904477e21 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -169,6 +169,8 @@ #define ServerOP_DzExpireWarning 0x045b #define ServerOP_DzCreated 0x045c #define ServerOP_DzDeleted 0x045d +#define ServerOP_DzSetSwitchID 0x045e +#define ServerOP_DzMovePC 0x045f #define ServerOP_LSInfo 0x1000 #define ServerOP_LSStatus 0x1001 @@ -219,28 +221,32 @@ #define ServerOP_UCSServerStatusReply 0x4005 #define ServerOP_UCSServerStatusRequest 0x4006 #define ServerOP_UpdateSchedulerEvents 0x4007 +#define ServerOP_DiscordWebhookMessage 0x4008 #define ServerOP_ReloadAAData 0x4100 #define ServerOP_ReloadAlternateCurrencies 0x4101 #define ServerOP_ReloadBlockedSpells 0x4102 -#define ServerOP_ReloadContentFlags 0x4103 -#define ServerOP_ReloadDoors 0x4104 -#define ServerOP_ReloadGroundSpawns 0x4105 -#define ServerOP_ReloadLevelEXPMods 0x4106 -#define ServerOP_ReloadLogs 0x4107 -#define ServerOP_ReloadMerchants 0x4108 -#define ServerOP_ReloadNPCEmotes 0x4109 -#define ServerOP_ReloadObjects 0x4110 -#define ServerOP_ReloadPerlExportSettings 0x4111 -#define ServerOP_ReloadRules 0x4112 -#define ServerOP_ReloadStaticZoneData 0x4113 -#define ServerOP_ReloadTasks 0x4114 -#define ServerOP_ReloadTitles 0x4115 -#define ServerOP_ReloadTraps 0x4116 -#define ServerOP_ReloadVariables 0x4117 -#define ServerOP_ReloadVeteranRewards 0x4118 -#define ServerOP_ReloadWorld 0x4119 -#define ServerOP_ReloadZonePoints 0x4120 +#define ServerOP_ReloadCommands 0x4103 +#define ServerOP_ReloadContentFlags 0x4104 +#define ServerOP_ReloadDoors 0x4105 +#define ServerOP_ReloadGroundSpawns 0x4106 +#define ServerOP_ReloadLevelEXPMods 0x4107 +#define ServerOP_ReloadLogs 0x4108 +#define ServerOP_ReloadMerchants 0x4109 +#define ServerOP_ReloadNPCEmotes 0x4110 +#define ServerOP_ReloadObjects 0x4111 +#define ServerOP_ReloadPerlExportSettings 0x4112 +#define ServerOP_ReloadRules 0x4113 +#define ServerOP_ReloadStaticZoneData 0x4114 +#define ServerOP_ReloadTasks 0x4115 +#define ServerOP_ReloadTitles 0x4116 +#define ServerOP_ReloadTraps 0x4117 +#define ServerOP_ReloadVariables 0x4118 +#define ServerOP_ReloadVeteranRewards 0x4119 +#define ServerOP_ReloadWorld 0x4120 +#define ServerOP_ReloadZonePoints 0x4121 +#define ServerOP_ReloadDzTemplates 0x4122 +#define ServerOP_ReloadZoneData 0x4123 #define ServerOP_CZDialogueWindow 0x4500 #define ServerOP_CZLDoNUpdate 0x4501 @@ -599,7 +605,7 @@ struct ServerKickPlayer_Struct { char adminname[64]; int16 adminrank; char name[64]; - uint32 AccountID; + uint32 account_id; }; struct ServerLSInfo_Struct { @@ -740,8 +746,8 @@ struct ServerMultiLineMsg_Struct { }; struct ServerLock_Struct { - char myname[64]; // User that did it - uint8 mode; // 0 = Unlocked ; 1 = Locked + char character_name[64]; + bool is_locked; }; struct ServerMotd_Struct { @@ -1283,7 +1289,7 @@ struct ServerLeaderboardRequest_Struct struct ServerCameraShake_Struct { uint32 duration; // milliseconds - uint32 intensity; // number from 1-10 + float intensity; }; struct ServerMailMessageHeader_Struct { @@ -1449,6 +1455,11 @@ struct QSMerchantLogTransaction_Struct { QSTransactionItems_Struct items[0]; }; +struct DiscordWebhookMessage_Struct { + uint32 webhook_id; + char message[2000]; +}; + struct QSGeneralQuery_Struct { char QueryString[0]; }; @@ -1517,7 +1528,7 @@ struct CZSetEntityVariable_Struct { struct CZSignal_Struct { uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name, 6 - NPC int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name - uint32 signal; + int signal_id; char client_name[64]; // Only used by Character Name Type, else empty }; @@ -1590,7 +1601,7 @@ struct WWSetEntityVariable_Struct { struct WWSignal_Struct { uint8 update_type; // 0 - Character, 1 - NPC - uint32 signal; + int signal_id; uint8 min_status; uint8 max_status; }; @@ -1665,6 +1676,13 @@ struct ServerDzMemberStatuses_Struct { ServerDzMemberStatusEntry_Struct entries[0]; }; +struct ServerDzMovePC_Struct { + uint32 dz_id; + uint16 sender_zone_id; + uint16 sender_instance_id; + uint32 character_id; +}; + struct ServerExpeditionLockout_Struct { uint32 expedition_id; uint64 expire_time; @@ -1746,6 +1764,11 @@ struct ServerDzLocation_Struct { float heading; }; +struct ServerDzSwitchID_Struct { + uint32 dz_id; + int dz_switch_id; +}; + struct ServerDzMember_Struct { uint32 dz_id; uint16 dz_zone_id; @@ -1788,6 +1811,10 @@ struct ServerFlagUpdate_Struct { int16 admin; }; +struct ServerOOCMute_Struct { + bool is_muted; +}; + #pragma pack() #endif diff --git a/common/shared_tasks.cpp b/common/shared_tasks.cpp index 18ffbfe78..049cc2f6a 100644 --- a/common/shared_tasks.cpp +++ b/common/shared_tasks.cpp @@ -7,7 +7,7 @@ std::vector SharedTask::GetActivityState() const return m_shared_task_activity_state; } -std::vector SharedTask::GetMembers() const +const std::vector& SharedTask::GetMembers() const { return m_members; } @@ -52,21 +52,22 @@ void SharedTask::SetDbSharedTask(const SharedTasksRepository::SharedTasks &m_db_ SharedTask::m_db_shared_task = m_db_shared_task; } -SharedTaskRequestCharacters SharedTask::GetRequestCharacters(Database &db, uint32_t requested_character_id) +SharedTaskRequest SharedTask::GetRequestCharacters(Database &db, uint32_t requested_character_id) { - SharedTaskRequestCharacters request{}; + // todo: group/raid refactors to check online members without querying + SharedTaskRequest request{}; request.group_type = SharedTaskRequestGroupType::Group; - request.characters = CharacterDataRepository::GetWhere( + auto characters = CharacterDataRepository::GetWhere( db, fmt::format( "id IN (select charid from group_id where groupid = (select groupid from group_id where charid = {}))", requested_character_id ) ); - if (request.characters.empty()) { + if (characters.empty()) { request.group_type = SharedTaskRequestGroupType::Raid; - request.characters = CharacterDataRepository::GetWhere( + characters = CharacterDataRepository::GetWhere( db, fmt::format( "id IN (select charid from raid_members where raidid = (select raidid from raid_members where charid = {}))", requested_character_id @@ -74,10 +75,10 @@ SharedTaskRequestCharacters SharedTask::GetRequestCharacters(Database &db, uint3 ); } - if (request.characters.empty()) // solo request + if (characters.empty()) // solo request { request.group_type = SharedTaskRequestGroupType::Solo; - request.characters = CharacterDataRepository::GetWhere( + characters = CharacterDataRepository::GetWhere( db, fmt::format( "id = {} LIMIT 1", requested_character_id @@ -85,12 +86,24 @@ SharedTaskRequestCharacters SharedTask::GetRequestCharacters(Database &db, uint3 ); } + request.leader_id = requested_character_id; request.lowest_level = std::numeric_limits::max(); request.highest_level = 0; - for (const auto &character: request.characters) { + request.members.reserve(characters.size()); + for (const auto& character: characters) + { request.lowest_level = std::min(request.lowest_level, character.level); request.highest_level = std::max(request.highest_level, character.level); request.character_ids.emplace_back(character.id); // convenience + + SharedTaskMember member = {}; + member.character_id = character.id; + member.character_name = character.name; + if (character.id == requested_character_id) + { + member.is_leader = true; + } + request.members.emplace_back(member); } return request; @@ -137,3 +150,8 @@ SharedTaskMember SharedTask::GetLeader() const } return {}; } + +bool SharedTask::IsExpired() const +{ + return m_db_shared_task.expire_time > 0 && m_db_shared_task.expire_time < std::time(nullptr); +} diff --git a/common/shared_tasks.h b/common/shared_tasks.h index 2a2363ffd..c11a0a74a 100644 --- a/common/shared_tasks.h +++ b/common/shared_tasks.h @@ -2,6 +2,8 @@ #define EQEMU_SHARED_TASKS_H #include "database.h" +#include "timer.h" +#include "tasks.h" #include "types.h" #include "repositories/character_data_repository.h" #include "repositories/tasks_repository.h" @@ -16,7 +18,7 @@ #define ServerOP_SharedTaskAddPlayer 0x0301 // bidirectional. /taskaddplayer request zone -> world. success world -> zone #define ServerOP_SharedTaskMakeLeader 0x0302 // zone -> world -> zone #define ServerOP_SharedTaskRemovePlayer 0x0303 // zone -> world -> zone -#define ServerOP_SharedTaskAttemptRemove 0x0304 // zone -> world. Player trying to delete task +#define ServerOP_SharedTaskQuit 0x0304 // zone -> world. Player trying to delete task #define ServerOP_SharedTaskUpdate 0x0305 // zone -> world. Client sending task update to world. Relayed world -> zone on confirmation #define ServerOP_SharedTaskMemberlist 0x0306 // world -> zone. Send shared task memberlist #define ServerOP_SharedTaskRequestMemberlist 0x0307 // zone -> world. Send shared task memberlist (zone in initial for now, could change) @@ -28,6 +30,10 @@ #define ServerOP_SharedTaskPlayerList 0x0313 // zone -> world /taskplayerlist command #define ServerOP_SharedTaskMemberChange 0x0314 // world -> zone. Send shared task single member added/removed (client also handles message) #define ServerOP_SharedTaskKickPlayers 0x0315 // zone -> world /kickplayers task +#define ServerOP_SharedTaskLock 0x0316 // zone -> world +#define ServerOP_SharedTaskEnd 0x0317 // zone -> world +#define ServerOP_SharedTaskEndByDz 0x0318 // zone -> world +#define ServerOP_SharedTaskFailed 0x0319 // world -> zone. Sends red text task failed banner to client enum class SharedTaskRequestGroupType { Solo = 0, @@ -54,11 +60,11 @@ struct ServerSharedTaskInvitePlayer_Struct { char inviter_name[64]; }; -// ServerOP_SharedTaskAttemptRemove +// ServerOP_SharedTaskQuit // gets re-used when sent back to clients -struct ServerSharedTaskAttemptRemove_Struct { +struct ServerSharedTaskQuit_Struct { uint32 requested_character_id; - uint32 requested_task_id; + uint32 task_id; bool remove_from_db; }; @@ -76,12 +82,13 @@ struct SharedTaskMember { }; // used in shared task requests to validate group/raid members -struct SharedTaskRequestCharacters { - int lowest_level; - int highest_level; +struct SharedTaskRequest { + uint32_t lowest_level; + uint32_t highest_level; + uint32_t leader_id; SharedTaskRequestGroupType group_type; std::vector character_ids; - std::vector characters; + std::vector members; }; // ServerOP_SharedTaskMemberlist @@ -105,6 +112,10 @@ struct SharedTaskActivityStateEntry { uint32 max_done_count; // goalcount uint32 updated_time; uint32 completed_time; + int req_activity_id; + int step; + bool optional; + ActivityState activity_state; // world only uses Hidden and Completed states }; struct ServerSharedTaskActivityUpdate_Struct { @@ -162,17 +173,36 @@ struct ServerSharedTaskKickPlayers_Struct { uint32 task_id; }; +struct ServerSharedTaskLock_Struct { + uint32 source_character_id; + uint32 task_id; + bool lock; +}; + +struct ServerSharedTaskCharacterTask_Struct { + uint32 character_id; + uint32 task_id; +}; + +struct ServerSharedTaskEnd_Struct { + uint32 character_id; + uint32 task_id; + uint32 dz_id; + bool send_fail; // if true members receive red text failure banner +}; + class SharedTask { public: // used in both zone and world validation - static SharedTaskRequestCharacters GetRequestCharacters(Database& db, uint32_t requested_character_id); + static SharedTaskRequest GetRequestCharacters(Database& db, uint32_t requested_character_id); void AddCharacterToMemberHistory(uint32_t character_id); SharedTaskMember FindMemberFromCharacterID(uint32_t character_id) const; SharedTaskMember FindMemberFromCharacterName(const std::string& character_name) const; SharedTaskMember GetLeader() const; std::vector GetActivityState() const; - std::vector GetMembers() const; + const std::vector& GetMembers() const; + bool IsExpired() const; // getters const std::vector &GetTaskActivityData() const; @@ -193,6 +223,8 @@ public: std::vector member_id_history; // past and present members for replay timers std::vector dynamic_zone_ids; + Timer terminate_timer; + protected: SharedTasksRepository::SharedTasks m_db_shared_task; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 2cc1d8c15..0f949f861 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -26,7 +26,6 @@ #include "classes.h" #include "eq_packet_structs.h" -#include "eqemu_exception.h" #include "faction.h" #include "features.h" #include "ipc_mutex.h" @@ -36,9 +35,14 @@ #include "mysql.h" #include "rulesys.h" #include "shareddb.h" -#include "string_util.h" +#include "strings.h" #include "eqemu_config.h" +#include "data_verification.h" #include "repositories/criteria/content_filter_criteria.h" +#include "repositories/account_repository.h" +#include "repositories/faction_association_repository.h" +#include "path_manager.h" +#include "repositories/loottable_repository.h" namespace ItemField { @@ -61,52 +65,67 @@ SharedDatabase::SharedDatabase(const char* host, const char* user, const char* p { } -SharedDatabase::~SharedDatabase() { -} +SharedDatabase::~SharedDatabase() = default; bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) { - std::string query = StringFormat("UPDATE account SET hideme = %i WHERE id = %i", hideme, account_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; + auto a = AccountRepository::FindOne(*this, account_id); + if (a.id > 0) { + a.hideme = hideme ? 1 : 0; + AccountRepository::UpdateOne(*this, a); } - return true; + return a.id > 0; } uint8 SharedDatabase::GetGMSpeed(uint32 account_id) { - std::string query = StringFormat("SELECT gmspeed FROM account WHERE id = '%i'", account_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; + auto a = AccountRepository::FindOne(*this, account_id); + if (a.id > 0) { + return a.gmspeed; } - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); + return 0; } bool SharedDatabase::SetGMSpeed(uint32 account_id, uint8 gmspeed) { - std::string query = StringFormat("UPDATE account SET gmspeed = %i WHERE id = %i", gmspeed, account_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; + auto a = AccountRepository::FindOne(*this, account_id); + if (a.id > 0) { + a.gmspeed = gmspeed ? 1 : 0; + AccountRepository::UpdateOne(*this, a); } - return true; + return a.id > 0; +} + +bool SharedDatabase::SetGMInvul(uint32 account_id, bool gminvul) +{ + auto a = AccountRepository::FindOne(*this, account_id); + if (a.id > 0) { + a.invulnerable = gminvul ? 1 : 0; + AccountRepository::UpdateOne(*this, a); + } + + return a.id > 0; +} + +bool SharedDatabase::SetGMFlymode(uint32 account_id, uint8 flymode) +{ + auto a = AccountRepository::FindOne(*this, account_id); + if (a.id > 0) { + a.flymode = flymode; + AccountRepository::UpdateOne(*this, a); + } + + return a.id > 0; } uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { uint32 EntitledTime = 0; - std::string query = StringFormat("SELECT `time_played` FROM `character_data` WHERE `account_id` = %u", AccountID); + const std::string query = StringFormat("SELECT `time_played` FROM `character_data` WHERE `account_id` = %u", AccountID); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { EntitledTime += atoi(row[0]); } return EntitledTime; @@ -121,9 +140,9 @@ void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) else sprintf(MailKeyString, "%08X", MailKey); - std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'", - MailKeyString, CharID); - auto results = QueryDatabase(query); + const std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'", + MailKeyString, CharID); + const auto results = QueryDatabase(query); if (!results.Success()) LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, MailKeyString, results.ErrorMessage().c_str()); @@ -131,7 +150,7 @@ void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) std::string SharedDatabase::GetMailKey(int CharID, bool key_only) { - std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID); + const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID); auto results = QueryDatabase(query); if (!results.Success()) { @@ -146,7 +165,7 @@ std::string SharedDatabase::GetMailKey(int CharID, bool key_only) return std::string(); } - auto row = results.begin(); + auto& row = results.begin(); if (row != results.end()) { std::string mail_key = row[0]; @@ -168,22 +187,22 @@ std::string SharedDatabase::GetMailKey(int CharID, bool key_only) bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end) { // Delete cursor items - std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i " - "AND ((slotid >= 8000 AND slotid <= 8999) " - "OR slotid = %i OR (slotid >= %i AND slotid <= %i) )", - char_id, EQ::invslot::slotCursor, - EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END); - auto results = QueryDatabase(query); + const std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i " + "AND ((slotid >= 8000 AND slotid <= 8999) " + "OR slotid = %i OR (slotid >= %i AND slotid <= %i) )", + char_id, EQ::invslot::slotCursor, + EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END); + const auto results = QueryDatabase(query); if (!results.Success()) { std::cout << "Clearing cursor failed: " << results.ErrorMessage() << std::endl; return false; } int i = 8000; - for(auto it = start; it != end; ++it, i++) { + for(auto& it = start; it != end; ++it, i++) { if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high - EQ::ItemInstance *inst = *it; - int16 use_slot = (i == 8000) ? EQ::invslot::slotCursor : i; + const EQ::ItemInstance *inst = *it; + const int16 use_slot = (i == 8000) ? EQ::invslot::slotCursor : i; if (!SaveInventory(char_id, inst, use_slot)) { return false; } @@ -195,9 +214,9 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::co bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const EQ::ItemInstance* inst) { // Delete cursor items - std::string query = StringFormat("SELECT itemid, charges FROM sharedbank " - "WHERE acctid = %d AND slotid = %d", - account_id, slot_id); + const std::string query = StringFormat("SELECT itemid, charges FROM sharedbank " + "WHERE acctid = %d AND slotid = %d", + account_id, slot_id); auto results = QueryDatabase(query); if (!results.Success()) { //returning true is less harmful in the face of a query error @@ -207,12 +226,12 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const EQ: if (results.RowCount() == 0) return false; - auto row = results.begin(); + auto& row = results.begin(); - uint32 id = atoi(row[0]); - uint16 charges = atoi(row[1]); + const uint32 id = atoi(row[0]); + const uint16 charges = atoi(row[1]); - uint16 expect_charges = 0; + uint16 expect_charges; if(inst->GetCharges() >= 0) expect_charges = inst->GetCharges(); @@ -263,30 +282,30 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance* uint32 augslot[EQ::invaug::SOCKET_COUNT] = { 0, 0, 0, 0, 0, 0 }; if (inst->IsClassCommon()) { for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - EQ::ItemInstance *auginst = inst->GetItem(i); + const EQ::ItemInstance *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } } - uint16 charges = 0; + uint16 charges; if(inst->GetCharges() >= 0) charges = inst->GetCharges(); else charges = 0x7FFF; // Update/Insert item - std::string query = StringFormat("REPLACE INTO inventory " - "(charid, slotid, itemid, charges, instnodrop, custom_data, color, " - "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) " - "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, " - "%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)", - (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, - (unsigned long)charges, (unsigned long)(inst->IsAttuned()? 1: 0), - inst->GetCustomDataString().c_str(), (unsigned long)inst->GetColor(), - (unsigned long)augslot[0], (unsigned long)augslot[1], (unsigned long)augslot[2], - (unsigned long)augslot[3], (unsigned long)augslot[4], (unsigned long)augslot[5], (unsigned long)inst->GetOrnamentationIcon(), - (unsigned long)inst->GetOrnamentationIDFile(), (unsigned long)inst->GetOrnamentHeroModel()); - auto results = QueryDatabase(query); + const std::string query = StringFormat("REPLACE INTO inventory " + "(charid, slotid, itemid, charges, instnodrop, custom_data, color, " + "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) " + "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, " + "%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)", + static_cast(char_id), static_cast(slot_id), static_cast(inst->GetItem()->ID), + static_cast(charges), static_cast(inst->IsAttuned() ? 1 : 0), + inst->GetCustomDataString().c_str(), static_cast(inst->GetColor()), + static_cast(augslot[0]), static_cast(augslot[1]), static_cast(augslot[2]), + static_cast(augslot[3]), static_cast(augslot[4]), static_cast(augslot[5]), static_cast(inst->GetOrnamentationIcon()), + static_cast(inst->GetOrnamentationIDFile()), static_cast(inst->GetOrnamentHeroModel())); + const auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id)) @@ -310,29 +329,29 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQ::ItemInstance uint32 augslot[EQ::invaug::SOCKET_COUNT] = { 0, 0, 0, 0, 0, 0 }; if (inst->IsClassCommon()) { for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - EQ::ItemInstance *auginst = inst->GetItem(i); + const EQ::ItemInstance *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } } // Update/Insert item - uint32 account_id = GetAccountIDByChar(char_id); - uint16 charges = 0; + const uint32 account_id = GetAccountIDByChar(char_id); + uint16 charges; if(inst->GetCharges() >= 0) charges = inst->GetCharges(); else charges = 0x7FFF; - std::string query = StringFormat("REPLACE INTO sharedbank " - "(acctid, slotid, itemid, charges, custom_data, " - "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6) " - "VALUES( %lu, %lu, %lu, %lu, '%s', " - "%lu, %lu, %lu, %lu, %lu, %lu)", - (unsigned long)account_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, - (unsigned long)charges, inst->GetCustomDataString().c_str(), (unsigned long)augslot[0], - (unsigned long)augslot[1], (unsigned long)augslot[2], (unsigned long)augslot[3], (unsigned long)augslot[4], - (unsigned long)augslot[5]); - auto results = QueryDatabase(query); + const std::string query = StringFormat("REPLACE INTO sharedbank " + "(acctid, slotid, itemid, charges, custom_data, " + "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6) " + "VALUES( %lu, %lu, %lu, %lu, '%s', " + "%lu, %lu, %lu, %lu, %lu, %lu)", + static_cast(account_id), static_cast(slot_id), static_cast(inst->GetItem()->ID), + static_cast(charges), inst->GetCustomDataString().c_str(), static_cast(augslot[0]), + static_cast(augslot[1]), static_cast(augslot[2]), static_cast(augslot[3]), static_cast(augslot[4]), + static_cast(augslot[5])); + const auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id)) { @@ -364,7 +383,7 @@ bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) { if (!EQ::InventoryProfile::SupportsContainers(slot_id)) return true; - int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); + const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i", char_id, base_slot_id, (base_slot_id+10)); results = QueryDatabase(query); @@ -379,7 +398,7 @@ bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) { bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { // Delete item - uint32 account_id = GetAccountIDByChar(char_id); + const uint32 account_id = GetAccountIDByChar(char_id); std::string query = StringFormat("DELETE FROM sharedbank WHERE acctid=%i AND slotid=%i", account_id, slot_id); auto results = QueryDatabase(query); if (!results.Success()) { @@ -390,7 +409,7 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { if (!EQ::InventoryProfile::SupportsContainers(slot_id)) return true; - int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); + const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i " "AND slotid >= %i AND slotid < %i", account_id, base_slot_id, (base_slot_id+10)); @@ -406,7 +425,7 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) { - std::string query = StringFormat("SELECT sharedplat FROM account WHERE id = '%i'", account_id); + const std::string query = StringFormat("SELECT sharedplat FROM account WHERE id = '%i'", account_id); auto results = QueryDatabase(query); if (!results.Success()) { return false; @@ -415,14 +434,14 @@ int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) if (results.RowCount() != 1) return 0; - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { - std::string query = StringFormat("UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id); - auto results = QueryDatabase(query); + const std::string query = StringFormat("UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id); + const auto results = QueryDatabase(query); if (!results.Success()) { return false; } @@ -434,7 +453,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQ::InventoryPro const EQ::ItemData *myitem; - std::string query = StringFormat( + const std::string query = StringFormat( "SELECT itemid, item_charges, slot FROM starting_items " "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " "(deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND " @@ -453,16 +472,16 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQ::InventoryPro } - for (auto row = results.begin(); row != results.end(); ++row) { - int32 itemid = atoi(row[0]); - int32 charges = atoi(row[1]); + for (auto& row = results.begin(); row != results.end(); ++row) { + const int32 itemid = atoi(row[0]); + const int32 charges = atoi(row[1]); int32 slot = atoi(row[2]); myitem = GetItem(itemid); if(!myitem) continue; - EQ::ItemInstance* myinst = CreateBaseItem(myitem, charges); + const EQ::ItemInstance* myinst = CreateBaseItem(myitem, charges); if(slot < 0) slot = inv->FindFreeSlot(0, 0); @@ -498,18 +517,18 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is return false; } - for (auto row = results.begin(); row != results.end(); ++row) { - int16 slot_id = (int16)atoi(row[0]); - uint32 item_id = (uint32)atoi(row[1]); - int16 charges = (int16)atoi(row[2]); + for (auto& row = results.begin(); row != results.end(); ++row) { + int16 slot_id = static_cast(atoi(row[0])); + uint32 item_id = static_cast(atoi(row[1])); + const int16 charges = static_cast(atoi(row[2])); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = (uint32)atoi(row[3]); - aug[1] = (uint32)atoi(row[4]); - aug[2] = (uint32)atoi(row[5]); - aug[3] = (uint32)atoi(row[6]); - aug[4] = (uint32)atoi(row[7]); - aug[5] = (uint32)atoi(row[8]); + aug[0] = static_cast(atoi(row[3])); + aug[1] = static_cast(atoi(row[4])); + aug[2] = static_cast(atoi(row[5])); + aug[3] = static_cast(atoi(row[6])); + aug[4] = static_cast(atoi(row[7])); + aug[5] = static_cast(atoi(row[8])); const EQ::ItemData *item = GetItem(item_id); @@ -519,8 +538,6 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is continue; } - int16 put_slot_id = INVALID_INDEX; - EQ::ItemInstance *inst = CreateBaseItem(item, charges); if (inst && item->IsClassCommon()) { for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { @@ -546,7 +563,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is continue; } - char v = data_str[i]; + const char v = data_str[i]; if (use_id) idAsString.push_back(v); else @@ -555,7 +572,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is } // theoretically inst can be nullptr ... this would be very bad ... - put_slot_id = inv->PutItem(slot_id, *inst); + const int16 put_slot_id = inv->PutItem(slot_id, *inst); safe_delete(inst); // Save ptr to item in inventory @@ -579,7 +596,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) return false; // Retrieve character inventory - std::string query = + const std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, " "augslot6, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model FROM " "inventory WHERE charid = %i ORDER BY slotid", @@ -592,24 +609,24 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) return false; } - auto timestamps = GetItemRecastTimestamps(char_id); + const auto timestamps = GetItemRecastTimestamps(char_id); auto cv_conflict = false; - auto pmask = inv->GetLookup()->PossessionsBitmask; - auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank; + const auto pmask = inv->GetLookup()->PossessionsBitmask; + const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { int16 slot_id = atoi(row[0]); if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { // Titanium thru UF check - if ((((uint64)1 << slot_id) & pmask) == 0) { + if (((static_cast(1) << slot_id) & pmask) == 0) { cv_conflict = true; continue; } } else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) { // Titanium thru UF check - auto parent_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); - if ((((uint64)1 << parent_slot) & pmask) == 0) { + const auto parent_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); + if (((static_cast(1) << parent_slot) & pmask) == 0) { cv_conflict = true; continue; } @@ -621,7 +638,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) } } else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { // Titanium check - auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); + const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); if (parent_index < EQ::invslot::SLOT_BEGIN || parent_index >= bank_size) { cv_conflict = true; continue; @@ -629,23 +646,23 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) } uint32 item_id = atoi(row[1]); - uint16 charges = atoi(row[2]); - uint32 color = atoul(row[3]); + const uint16 charges = atoi(row[2]); + const uint32 color = atoul(row[3]); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = (uint32)atoul(row[4]); - aug[1] = (uint32)atoul(row[5]); - aug[2] = (uint32)atoul(row[6]); - aug[3] = (uint32)atoul(row[7]); - aug[4] = (uint32)atoul(row[8]); - aug[5] = (uint32)atoul(row[9]); + aug[0] = std::stoul(row[4]); + aug[1] = std::stoul(row[5]); + aug[2] = std::stoul(row[6]); + aug[3] = std::stoul(row[7]); + aug[4] = std::stoul(row[8]); + aug[5] = std::stoul(row[9]); - bool instnodrop = (row[10] && (uint16)atoi(row[10])) ? true : false; + const bool instnodrop = (row[10] && static_cast(atoi(row[10]))) ? true : false; - uint32 ornament_icon = (uint32)atoul(row[12]); - uint32 ornament_idfile = (uint32)atoul(row[13]); - uint32 ornament_hero_model = (uint32)atoul(row[14]); + const uint32 ornament_icon = std::stoul(row[12]); + const uint32 ornament_idfile = std::stoul(row[13]); + uint32 ornament_hero_model = std::stoul(row[14]); const EQ::ItemData *item = GetItem(item_id); @@ -655,8 +672,6 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) continue; } - int16 put_slot_id = INVALID_INDEX; - EQ::ItemInstance *inst = CreateBaseItem(item, charges); if (inst == nullptr) @@ -680,7 +695,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) continue; } - char v = data_str[i]; + const char v = data_str[i]; if (use_id) idAsString.push_back(v); else @@ -719,6 +734,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) } } + int16 put_slot_id; if (slot_id >= 8000 && slot_id <= 8999) { put_slot_id = inv->PushCursor(*inst); } else if (slot_id >= 3111 && slot_id <= 3179) { @@ -758,7 +774,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv) // deprecated { // Retrieve character inventory - std::string query = + const std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, " "augslot2, augslot3, augslot4, augslot5, augslot6, instnodrop, custom_data, ornamenticon, " "ornamentidfile, ornament_hero_model " @@ -773,27 +789,26 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryPr return false; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { int16 slot_id = atoi(row[0]); uint32 item_id = atoi(row[1]); - int8 charges = atoi(row[2]); - uint32 color = atoul(row[3]); + const int8 charges = atoi(row[2]); + const uint32 color = atoul(row[3]); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = (uint32)atoi(row[4]); - aug[1] = (uint32)atoi(row[5]); - aug[2] = (uint32)atoi(row[6]); - aug[3] = (uint32)atoi(row[7]); - aug[4] = (uint32)atoi(row[8]); - aug[5] = (uint32)atoi(row[9]); + aug[0] = static_cast(atoi(row[4])); + aug[1] = static_cast(atoi(row[5])); + aug[2] = static_cast(atoi(row[6])); + aug[3] = static_cast(atoi(row[7])); + aug[4] = static_cast(atoi(row[8])); + aug[5] = static_cast(atoi(row[9])); - bool instnodrop = (row[10] && (uint16)atoi(row[10])) ? true : false; - uint32 ornament_icon = (uint32)atoul(row[12]); - uint32 ornament_idfile = (uint32)atoul(row[13]); - uint32 ornament_hero_model = (uint32)atoul(row[14]); + const bool instnodrop = (row[10] && static_cast(atoi(row[10]))) ? true : false; + const uint32 ornament_icon = std::stoul(row[12]); + const uint32 ornament_idfile = std::stoul(row[13]); + uint32 ornament_hero_model = std::stoul(row[14]); const EQ::ItemData *item = GetItem(item_id); - int16 put_slot_id = INVALID_INDEX; if (!item) continue; @@ -822,7 +837,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryPr continue; } - char v = data_str[i]; + const char v = data_str[i]; if (use_id) idAsString.push_back(v); else @@ -846,6 +861,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryPr } } + int16 put_slot_id; if (slot_id >= 8000 && slot_id <= 8999) put_slot_id = inv->PushCursor(*inst); else @@ -866,32 +882,32 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryPr std::map SharedDatabase::GetItemRecastTimestamps(uint32 char_id) { std::map timers; - std::string query = StringFormat("SELECT recast_type,timestamp FROM character_item_recast WHERE id=%u", char_id); + const std::string query = StringFormat("SELECT recast_type,timestamp FROM character_item_recast WHERE id=%u", char_id); auto results = QueryDatabase(query); if (!results.Success() || results.RowCount() == 0) return timers; - for (auto row = results.begin(); row != results.end(); ++row) + for (auto& row = results.begin(); row != results.end(); ++row) timers[atoul(row[0])] = atoul(row[1]); return timers; // RVO or move assigned } uint32 SharedDatabase::GetItemRecastTimestamp(uint32 char_id, uint32 recast_type) { - std::string query = StringFormat("SELECT timestamp FROM character_item_recast WHERE id=%u AND recast_type=%u", - char_id, recast_type); + const std::string query = StringFormat("SELECT timestamp FROM character_item_recast WHERE id=%u AND recast_type=%u", + char_id, recast_type); auto results = QueryDatabase(query); if (!results.Success() || results.RowCount() == 0) return 0; - auto row = results.begin(); + auto& row = results.begin(); return static_cast(atoul(row[0])); } void SharedDatabase::ClearOldRecastTimestamps(uint32 char_id) { // This actually isn't strictly live-like. Live your recast timestamps are forever - std::string query = + const std::string query = StringFormat("DELETE FROM character_item_recast WHERE id = %u and timestamp < UNIX_TIMESTAMP()", char_id); QueryDatabase(query); } @@ -910,7 +926,7 @@ void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) if (results.RowCount() == 0) return; - auto row = results.begin(); + auto& row = results.begin(); if (row[0]) max_id = atoi(row[0]); @@ -923,14 +939,15 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { items_mmf.reset(nullptr); try { - auto Config = EQEmuConfig::get(); + const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("items"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("items"); - LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("items")); items_mmf = std::make_unique(file_name); - items_hash = std::make_unique>(reinterpret_cast(items_mmf->Get()), items_mmf->Size()); + items_hash = std::make_unique>(static_cast(items_mmf->Get()), items_mmf->Size()); mutex.Unlock(); + + LogInfo("Loaded [{}] items via shared memory", Strings::Commify(m_shared_items_count)); } catch(std::exception& ex) { LogError("Error Loading Items: {}", ex.what()); return false; @@ -941,31 +958,43 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { - EQ::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); + EQ::FixedMemoryHashSet hash(static_cast(data), size, items, max_item_id); - std::string ndbuffer; - bool disableNoRent = false; - if (GetVariable("disablenorent", ndbuffer)) { - if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoRent = true; + std::string variable_buffer; + + bool disable_attuneable = RuleB(Items, DisableAttuneable); + bool disable_bard_focus_effects = RuleB(Items, DisableBardFocusEffects); + bool disable_lore = RuleB(Items, DisableLore); + bool disable_no_drop = RuleB(Items, DisableNoDrop); + bool disable_no_pet = RuleB(Items, DisableNoPet); + bool disable_no_rent = RuleB(Items, DisableNoRent); + bool disable_no_transfer = RuleB(Items, DisableNoTransfer); + bool disable_potion_belt = RuleB(Items, DisablePotionBelt); + bool disable_spell_focus_effects = RuleB(Items, DisableSpellFocusEffects); + + // Old Variable Code + if (GetVariable("disablelore", variable_buffer)) { + if (variable_buffer == "1") { + disable_lore = true; } } - bool disableNoDrop = false; - if (GetVariable("disablenodrop", ndbuffer)) { - if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoDrop = true; + + if (GetVariable("disablenodrop", variable_buffer)) { + if (variable_buffer == "1") { + disable_no_drop = true; } } - bool disableLoreGroup = false; - if (GetVariable("disablelore", ndbuffer)) { - if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableLoreGroup = true; + + if (GetVariable("disablenorent", variable_buffer)) { + if (variable_buffer == "1") { + disable_no_rent = true; } } - bool disableNoTransfer = false; - if (GetVariable("disablenotransfer", ndbuffer)) { - if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoTransfer = true; + + + if (GetVariable("disablenotransfer", variable_buffer)) { + if (variable_buffer == "1") { + disable_no_transfer = true; } } @@ -981,215 +1010,272 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ return; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { memset(&item, 0, sizeof(EQ::ItemData)); - item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); - strcpy(item.Name, row[ItemField::name]); - strcpy(item.Lore, row[ItemField::lore]); - strcpy(item.IDFile, row[ItemField::idfile]); + // Unique Identifier + item.ID = std::stoul(row[ItemField::id]); - item.ID = (uint32)atoul(row[ItemField::id]); - item.Weight = (int32)atoi(row[ItemField::weight]); - item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]); - item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]); - item.Size = (uint8)atoi(row[ItemField::size]); - item.Slots = (uint32)atoul(row[ItemField::slots]); - item.Price = (uint32)atoul(row[ItemField::price]); - item.Icon = (uint32)atoul(row[ItemField::icon]); - item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0); - item.Tradeskills = (atoi(row[ItemField::tradeskills]) == 0) ? false : true; - item.CR = (int8)atoi(row[ItemField::cr]); - item.DR = (int8)atoi(row[ItemField::dr]); - item.PR = (int8)atoi(row[ItemField::pr]); - item.MR = (int8)atoi(row[ItemField::mr]); - item.FR = (int8)atoi(row[ItemField::fr]); - item.AStr = (int8)atoi(row[ItemField::astr]); - item.ASta = (int8)atoi(row[ItemField::asta]); - item.AAgi = (int8)atoi(row[ItemField::aagi]); - item.ADex = (int8)atoi(row[ItemField::adex]); - item.ACha = (int8)atoi(row[ItemField::acha]); - item.AInt = (int8)atoi(row[ItemField::aint]); - item.AWis = (int8)atoi(row[ItemField::awis]); - item.HP = (int32)atoul(row[ItemField::hp]); - item.Mana = (int32)atoul(row[ItemField::mana]); - item.AC = (int32)atoul(row[ItemField::ac]); - item.Deity = (uint32)atoul(row[ItemField::deity]); - item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]); - item.SkillModMax = (int32)atoul(row[ItemField::skillmodmax]); - item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]); - item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]); - item.BaneDmgAmt = (int32)atoul(row[ItemField::banedmgamt]); - item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]); - item.Magic = (atoi(row[ItemField::magic]) == 0) ? false : true; - item.CastTime_ = (int32)atoul(row[ItemField::casttime_]); - item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]); - item.BardType = (uint32)atoul(row[ItemField::bardtype]); - item.BardValue = (int32)atoul(row[ItemField::bardvalue]); - item.Light = (int8)atoi(row[ItemField::light]); - item.Delay = (uint8)atoi(row[ItemField::delay]); - item.RecLevel = (uint8)atoi(row[ItemField::reclevel]); - item.RecSkill = (uint8)atoi(row[ItemField::recskill]); - item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]); - item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]); - item.Range = (uint8)atoi(row[ItemField::range]); - item.Damage = (uint32)atoi(row[ItemField::damage]); - item.Color = (uint32)atoul(row[ItemField::color]); - item.Classes = (uint32)atoul(row[ItemField::classes]); - item.Races = (uint32)atoul(row[ItemField::races]); + // Name and Lore + strn0cpy(item.Name, row[ItemField::name], sizeof(item.Name)); + strn0cpy(item.Lore, row[ItemField::lore], sizeof(item.Lore)); - item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); - item.ItemType = (uint8)atoi(row[ItemField::itemtype]); - item.SubType = atoi(row[ItemField::subtype]); - item.Material = (uint8)atoi(row[ItemField::material]); - item.HerosForgeModel = (uint32)atoi(row[ItemField::herosforgemodel]); - item.SellRate = (float)atof(row[ItemField::sellrate]); - item.CastTime = (uint32)atoul(row[ItemField::casttime]); - item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]); - item.ProcRate = (int32)atoi(row[ItemField::procrate]); - item.CombatEffects = (int8)atoi(row[ItemField::combateffects]); - item.Shielding = (int8)atoi(row[ItemField::shielding]); - item.StunResist = (int8)atoi(row[ItemField::stunresist]); - item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]); - item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]); - item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]); - item.SpellShield = (int8)atoi(row[ItemField::spellshield]); - item.Avoidance = (int8)atoi(row[ItemField::avoidance]); - item.Accuracy = (int8)atoi(row[ItemField::accuracy]); - item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]); - item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]); - item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]); - item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]); - item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]); - item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]); - item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]); - item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]); - item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]); + // Flags + item.ArtifactFlag = std::stoi(row[ItemField::artifactflag]) ? true : false; + item.Attuneable = disable_attuneable ? false : std::stoi(row[ItemField::attuneable]) ? true : false; + item.BenefitFlag = std::stoi(row[ItemField::benefitflag]) ? true : false; + item.FVNoDrop = std::stoi(row[ItemField::fvnodrop]) ? true : false; + item.Magic = std::stoi(row[ItemField::magic]) ? true : false; + item.NoDrop = disable_no_drop ? static_cast(255) : static_cast(std::stoul(row[ItemField::nodrop])); + item.NoPet = disable_no_pet ? false : std::stoi(row[ItemField::nopet]) ? true : false; + item.NoRent = disable_no_rent ? static_cast(255) : static_cast(std::stoul(row[ItemField::norent])); + item.NoTransfer = disable_no_transfer ? false : std::stoi(row[ItemField::notransfer]) ? true : false; + item.PendingLoreFlag = std::stoi(row[ItemField::pendingloreflag]) ? true : false; + item.QuestItemFlag = std::stoi(row[ItemField::questitemflag]) ? true : false; + item.Stackable = std::stoi(row[ItemField::stackable]) ? true : false; + item.Tradeskills = std::stoi(row[ItemField::tradeskills]) ? true : false; + item.SummonedFlag = std::stoi(row[ItemField::summonedflag]) ? true : false; - strcpy(item.CharmFile, row[ItemField::charmfile]); + // Lore + item.LoreGroup = disable_lore ? 0 : std::stoi(row[ItemField::loregroup]); + item.LoreFlag = disable_lore ? false : item.LoreGroup != 0; - item.AugType = (uint32)atoul(row[ItemField::augtype]); - item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]); - item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]); - item.AugSlotUnk2[0] = 0; - item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]); - item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]); - item.AugSlotUnk2[1] = 0; - item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]); - item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]); - item.AugSlotUnk2[2] = 0; - item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]); - item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]); - item.AugSlotUnk2[3] = 0; - item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]); - item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]); - item.AugSlotUnk2[4] = 0; - item.AugSlotType[5] = (uint8)atoi(row[ItemField::augslot6type]); - item.AugSlotVisible[5] = (uint8)atoi(row[ItemField::augslot6visible]); - item.AugSlotUnk2[5] = 0; + // Type + item.AugType = std::stoul(row[ItemField::augtype]); + item.ItemType = static_cast(std::stoul(row[ItemField::itemtype])); + item.SubType = std::stoi(row[ItemField::subtype]); - item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]); - item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]); - item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]); - item.BagType = (uint8)atoi(row[ItemField::bagtype]); - item.BagSlots = (uint8)std::min(atoi(row[ItemField::bagslots]), 10); // FIXME: remove when big bags supported - item.BagSize = (uint8)atoi(row[ItemField::bagsize]); - item.BagWR = (uint8)atoi(row[ItemField::bagwr]); - item.Book = (uint8)atoi(row[ItemField::book]); - item.BookType = (uint32)atoul(row[ItemField::booktype]); + // Miscellaneous + item.ExpendableArrow = static_cast(std::stoul(row[ItemField::expendablearrow])); + item.Light = static_cast(std::stoi(row[ItemField::light])); + item.MaxCharges = static_cast(std::stoi(row[ItemField::maxcharges])); + item.Size = static_cast(std::stoul(row[ItemField::size])); + item.StackSize = static_cast(std::stoi(row[ItemField::stacksize])); + item.Weight = std::stoi(row[ItemField::weight]); - strcpy(item.Filename, row[ItemField::filename]); + // Potion Belt + item.PotionBelt = disable_potion_belt ? false : std::stoi(row[ItemField::potionbelt]) ? true : false; + item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast(std::stoul(row[ItemField::potionbeltslots])); - item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]); - item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]); - item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]); - item.LoreFlag = item.LoreGroup != 0; - item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag]) == 0) ? false : true; - item.ArtifactFlag = (atoi(row[ItemField::artifactflag]) == 0) ? false : true; - item.SummonedFlag = (atoi(row[ItemField::summonedflag]) == 0) ? false : true; - item.Favor = (uint32)atoul(row[ItemField::favor]); - item.FVNoDrop = (atoi(row[ItemField::fvnodrop]) == 0) ? false : true; - item.Endur = (uint32)atoul(row[ItemField::endur]); - item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]); - item.Attack = (uint32)atoul(row[ItemField::attack]); - item.Regen = (uint32)atoul(row[ItemField::regen]); - item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]); - item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]); - item.Haste = (uint32)atoul(row[ItemField::haste]); - item.DamageShield = (uint32)atoul(row[ItemField::damageshield]); - item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]); - item.RecastType = (int)atoi(row[ItemField::recasttype]); - item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]); - item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]); - item.Attuneable = (atoi(row[ItemField::attuneable]) == 0) ? false : true; - item.NoPet = (atoi(row[ItemField::nopet]) == 0) ? false : true; - item.PointType = (uint32)atoul(row[ItemField::pointtype]); - item.PotionBelt = (atoi(row[ItemField::potionbelt]) == 0) ? false : true; - item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots]) == 0) ? false : true; - item.StackSize = (uint16)atoi(row[ItemField::stacksize]); - item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer]) == 0) ? false : true; - item.Stackable = (atoi(row[ItemField::stackable]) == 0) ? false : true; - item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]); - item.Click.Type = (uint8)atoul(row[ItemField::clicktype]); - item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]); - item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]); + // Merchant + item.Favor = std::stoul(row[ItemField::favor]); + item.GuildFavor = std::stoul(row[ItemField::guildfavor]); + item.Price = std::stoul(row[ItemField::price]); + item.SellRate = std::stof(row[ItemField::sellrate]); - strcpy(item.CharmFile, row[ItemField::charmfile]); + // Display + item.Color = std::stoul(row[ItemField::color]); + item.EliteMaterial = std::stoul(row[ItemField::elitematerial]); + item.HerosForgeModel = std::stoul(row[ItemField::herosforgemodel]); + item.Icon = std::stoul(row[ItemField::icon]); + strn0cpy(item.IDFile, row[ItemField::idfile], sizeof(item.IDFile)); + item.Material = static_cast(std::stoul(row[ItemField::material])); - item.Proc.Effect = (int32)atoul(row[ItemField::proceffect]); - item.Proc.Type = (uint8)atoul(row[ItemField::proctype]); - item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]); - item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]); - item.Worn.Effect = (int32)atoul(row[ItemField::worneffect]); - item.Worn.Type = (uint8)atoul(row[ItemField::worntype]); - item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]); - item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]); - item.Focus.Effect = (int32)atoul(row[ItemField::focuseffect]); - item.Focus.Type = (uint8)atoul(row[ItemField::focustype]); - item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]); - item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]); - item.Scroll.Effect = (int32)atoul(row[ItemField::scrolleffect]); - item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]); - item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]); - item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]); - item.Bard.Effect = (int32)atoul(row[ItemField::bardeffect]); - item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]); - item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]); - item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]); - item.QuestItemFlag = (atoi(row[ItemField::questitemflag]) == 0) ? false : true; - item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]); - item.Purity = (uint32)atoul(row[ItemField::purity]); - item.EvolvingItem = (uint8)atoul(row[ItemField::evoitem]); - item.EvolvingID = (uint8)atoul(row[ItemField::evoid]); - item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]); - item.EvolvingMax = (uint8)atoul(row[ItemField::evomax]); - item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]); - item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]); - item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]); - item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]); - item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]); - item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]); - item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]); - item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]); - item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]); - item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]); - item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]); - item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]); - item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]); - item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]); - item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]); - item.HealAmt = (int32)atoi(row[ItemField::healamt]); - item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]); - item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]); - item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]); - item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]); - item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]); + // Resists + item.CR = static_cast(EQ::Clamp(std::stoi(row[ItemField::cr]), -128, 127)); + item.DR = static_cast(EQ::Clamp(std::stoi(row[ItemField::dr]), -128, 127)); + item.FR = static_cast(EQ::Clamp(std::stoi(row[ItemField::fr]), -128, 127)); + item.MR = static_cast(EQ::Clamp(std::stoi(row[ItemField::mr]), -128, 127)); + item.PR = static_cast(EQ::Clamp(std::stoi(row[ItemField::pr]), -128, 127)); + item.SVCorruption = static_cast(EQ::Clamp(std::stoi(row[ItemField::svcorruption]), -128, 127)); - strcpy(item.ClickName, row[ItemField::clickname]); - strcpy(item.ProcName, row[ItemField::procname]); - strcpy(item.WornName, row[ItemField::wornname]); - strcpy(item.FocusName, row[ItemField::focusname]); - strcpy(item.ScrollName, row[ItemField::scrollname]); + // Heroic Resists + item.HeroicCR = std::stoi(row[ItemField::heroic_cr]); + item.HeroicDR = std::stoi(row[ItemField::heroic_dr]); + item.HeroicFR = std::stoi(row[ItemField::heroic_fr]); + item.HeroicMR = std::stoi(row[ItemField::heroic_mr]); + item.HeroicPR = std::stoi(row[ItemField::heroic_pr]); + item.HeroicSVCorrup = std::stoi(row[ItemField::heroic_svcorrup]); + + // Stats + item.AAgi = static_cast(EQ::Clamp(std::stoi(row[ItemField::aagi]), -128, 127)); + item.ACha = static_cast(EQ::Clamp(std::stoi(row[ItemField::acha]), -128, 127)); + item.ADex = static_cast(EQ::Clamp(std::stoi(row[ItemField::adex]), -128, 127)); + item.AInt = static_cast(EQ::Clamp(std::stoi(row[ItemField::aint]), -128, 127)); + item.ASta = static_cast(EQ::Clamp(std::stoi(row[ItemField::asta]), -128, 127)); + item.AStr = static_cast(EQ::Clamp(std::stoi(row[ItemField::astr]), -128, 127)); + item.AWis = static_cast(EQ::Clamp(std::stoi(row[ItemField::awis]), -128, 127)); + + // Heroic Stats + item.HeroicAgi = std::stoi(row[ItemField::heroic_agi]); + item.HeroicCha = std::stoi(row[ItemField::heroic_cha]); + item.HeroicDex = std::stoi(row[ItemField::heroic_dex]); + item.HeroicInt = std::stoi(row[ItemField::heroic_int]); + item.HeroicSta = std::stoi(row[ItemField::heroic_sta]); + item.HeroicStr = std::stoi(row[ItemField::heroic_str]); + item.HeroicWis = std::stoi(row[ItemField::heroic_wis]); + + // Health, Mana, and Endurance + item.HP = std::stoi(row[ItemField::hp]); + item.Regen = std::stoi(row[ItemField::regen]); + item.Mana = std::stoi(row[ItemField::mana]); + item.ManaRegen = std::stoi(row[ItemField::manaregen]); + item.Endur = std::stoi(row[ItemField::endur]); + item.EnduranceRegen = std::stoi(row[ItemField::enduranceregen]); + + // Bane Damage + item.BaneDmgAmt = std::stoi(row[ItemField::banedmgamt]); + item.BaneDmgBody = std::stoul(row[ItemField::banedmgbody]); + item.BaneDmgRace = std::stoul(row[ItemField::banedmgrace]); + item.BaneDmgRaceAmt = std::stoul(row[ItemField::banedmgraceamt]); + + // Elemental Damage + item.ElemDmgType = static_cast(std::stoul(row[ItemField::elemdmgtype])); + item.ElemDmgAmt = static_cast(std::stoul(row[ItemField::elemdmgamt])); + + // Combat + item.BackstabDmg = std::stoul(row[ItemField::backstabdmg]); + item.Damage = std::stoul(row[ItemField::damage]); + item.Delay = static_cast(std::stoul(row[ItemField::delay])); + item.Range = static_cast(std::stoul(row[ItemField::range])); + + // Combat Stats + item.AC = std::stoi(row[ItemField::ac]); + item.Accuracy = static_cast(EQ::Clamp(std::stoi(row[ItemField::accuracy]), -128, 127)); + item.Attack = std::stoi(row[ItemField::attack]); + item.Avoidance = static_cast(EQ::Clamp(std::stoi(row[ItemField::avoidance]), -128, 127)); + item.Clairvoyance = std::stoul(row[ItemField::clairvoyance]); + item.CombatEffects = Strings::IsNumber(row[ItemField::combateffects]) ? static_cast(EQ::Clamp(std::stoi(row[ItemField::combateffects]), -128, 127)) : 0; + item.DamageShield = std::stoi(row[ItemField::damageshield]); + item.DotShielding = std::stoi(row[ItemField::dotshielding]); + item.DSMitigation = std::stoul(row[ItemField::dsmitigation]); + item.Haste = std::stoi(row[ItemField::haste]); + item.HealAmt = std::stoi(row[ItemField::healamt]); + item.Purity = std::stoul(row[ItemField::purity]); + item.Shielding = static_cast(EQ::Clamp(std::stoi(row[ItemField::shielding]), -128, 127)); + item.SpellDmg = std::stoi(row[ItemField::spelldmg]); + item.SpellShield = static_cast(EQ::Clamp(std::stoi(row[ItemField::spellshield]), -128, 127)); + item.StrikeThrough = static_cast(EQ::Clamp(std::stoi(row[ItemField::strikethrough]), -128, 127)); + item.StunResist = static_cast(EQ::Clamp(std::stoi(row[ItemField::stunresist]), -128, 127)); + + // Restrictions + item.AugRestrict = std::stoul(row[ItemField::augrestrict]); + item.Classes = std::stoul(row[ItemField::classes]); + item.Deity = std::stoul(row[ItemField::deity]); + item.ItemClass = static_cast(std::stoul(row[ItemField::itemclass])); + item.Races = std::stoul(row[ItemField::races]); + item.RecLevel = static_cast(std::stoul(row[ItemField::reclevel])); + item.RecSkill = static_cast(std::stoul(row[ItemField::recskill])); + item.ReqLevel = static_cast(std::stoul(row[ItemField::reqlevel])); + item.Slots = std::stoul(row[ItemField::slots]); + + // Skill Modifier + item.SkillModValue = std::stoi(row[ItemField::skillmodvalue]); + item.SkillModMax = std::stoi(row[ItemField::skillmodmax]); + item.SkillModType = std::stoul(row[ItemField::skillmodtype]); + + // Extra Damage Skill + item.ExtraDmgSkill = std::stoul(row[ItemField::extradmgskill]); + item.ExtraDmgAmt = std::stoul(row[ItemField::extradmgamt]); + + // Bard + item.BardType = std::stoul(row[ItemField::bardtype]); + item.BardValue = std::stoi(row[ItemField::bardvalue]); + + // Faction + item.FactionAmt1 = std::stoi(row[ItemField::factionamt1]); + item.FactionMod1 = std::stoi(row[ItemField::factionmod1]); + item.FactionAmt2 = std::stoi(row[ItemField::factionamt2]); + item.FactionMod2 = std::stoi(row[ItemField::factionmod2]); + item.FactionAmt3 = std::stoi(row[ItemField::factionamt3]); + item.FactionMod3 = std::stoi(row[ItemField::factionmod3]); + item.FactionAmt4 = std::stoi(row[ItemField::factionamt4]); + item.FactionMod4 = std::stoi(row[ItemField::factionmod4]); + + // Augment + item.AugDistiller = std::stoul(row[ItemField::augdistiller]); + item.AugSlotType[0] = static_cast(std::stoul(row[ItemField::augslot1type])); + item.AugSlotVisible[0] = static_cast(std::stoul(row[ItemField::augslot1visible])); + item.AugSlotType[1] = static_cast(std::stoul(row[ItemField::augslot2type])); + item.AugSlotVisible[1] = static_cast(std::stoul(row[ItemField::augslot2visible])); + item.AugSlotType[2] = static_cast(std::stoul(row[ItemField::augslot3type])); + item.AugSlotVisible[2] = static_cast(std::stoul(row[ItemField::augslot3visible])); + item.AugSlotType[3] = static_cast(std::stoul(row[ItemField::augslot4type])); + item.AugSlotVisible[3] = static_cast(std::stoul(row[ItemField::augslot4visible])); + item.AugSlotType[4] = static_cast(std::stoul(row[ItemField::augslot5type])); + item.AugSlotVisible[4] = static_cast(std::stoul(row[ItemField::augslot5visible])); + item.AugSlotType[5] = static_cast(std::stoul(row[ItemField::augslot6type])); + item.AugSlotVisible[5] = static_cast(std::stoul(row[ItemField::augslot6visible])); + + // Augment Unknowns + for (uint8 i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { + item.AugSlotUnk2[i] = 0; + } + + // LDoN + item.LDoNTheme = std::stoul(row[ItemField::ldontheme]); + item.LDoNPrice = std::stoul(row[ItemField::ldonprice]); + item.LDoNSellBackRate = std::stoul(row[ItemField::ldonsellbackrate]); + item.LDoNSold = std::stoul(row[ItemField::ldonsold]); + item.PointType = std::stoul(row[ItemField::pointtype]); + + // Bag + item.BagSize = static_cast(std::stoul(row[ItemField::bagsize])); + item.BagSlots = static_cast(EQ::Clamp(std::stoi(row[ItemField::bagslots]), 0, 10)); // Will need to be changed from std::min to just use database value when bag slots are increased + item.BagType = static_cast(std::stoul(row[ItemField::bagtype])); + item.BagWR = static_cast(EQ::Clamp(std::stoi(row[ItemField::bagwr]), 0, 100)); + + // Bard Effect + item.Bard.Effect = disable_bard_focus_effects ? 0 : std::stoi(row[ItemField::bardeffect]); + item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::bardtype])); + item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::bardlevel])); + item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::bardlevel2])); + + // Book + item.Book = static_cast(std::stoul(row[ItemField::book])); + item.BookType = std::stoul(row[ItemField::booktype]); + + // Click Effect + item.CastTime = std::stoul(row[ItemField::casttime]); + item.CastTime_ = std::stoi(row[ItemField::casttime_]); + item.Click.Effect = std::stoi(row[ItemField::clickeffect]); + item.Click.Type = static_cast(std::stoul(row[ItemField::clicktype])); + item.Click.Level = static_cast(std::stoul(row[ItemField::clicklevel])); + item.Click.Level2 = static_cast(std::stoul(row[ItemField::clicklevel2])); + strn0cpy(item.ClickName, row[ItemField::clickname], sizeof(item.ClickName)); + item.RecastDelay = std::stoul(row[ItemField::recastdelay]); + item.RecastType = std::stoi(row[ItemField::recasttype]); + + // Focus Effect + item.Focus.Effect = disable_spell_focus_effects ? 0 : std::stoi(row[ItemField::focuseffect]); + item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::focustype])); + item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::focuslevel])); + item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::focuslevel2])); + strn0cpy(item.FocusName, disable_spell_focus_effects ? "" : row[ItemField::focusname], sizeof(item.FocusName)); + + // Proc Effect + item.Proc.Effect = std::stoi(row[ItemField::proceffect]); + item.Proc.Type = static_cast(std::stoul(row[ItemField::proctype])); + item.Proc.Level = static_cast(std::stoul(row[ItemField::proclevel])); + item.Proc.Level2 = static_cast(std::stoul(row[ItemField::proclevel2])); + strn0cpy(item.ProcName, row[ItemField::procname], sizeof(item.ProcName)); + item.ProcRate = std::stoi(row[ItemField::procrate]); + + // Scroll Effect + item.Scroll.Effect = std::stoi(row[ItemField::scrolleffect]); + item.Scroll.Type = static_cast(std::stoul(row[ItemField::scrolltype])); + item.Scroll.Level = static_cast(std::stoul(row[ItemField::scrolllevel])); + item.Scroll.Level2 = static_cast(std::stoul(row[ItemField::scrolllevel2])); + strn0cpy(item.ScrollName, row[ItemField::scrollname], sizeof(item.ScrollName)); + + // Worn Effect + item.Worn.Effect = std::stoi(row[ItemField::worneffect]); + item.Worn.Type = static_cast(std::stoul(row[ItemField::worntype])); + item.Worn.Level = static_cast(std::stoul(row[ItemField::wornlevel])); + item.Worn.Level2 = static_cast(std::stoul(row[ItemField::wornlevel2])); + strn0cpy(item.WornName, row[ItemField::wornname], sizeof(item.WornName)); + + // Evolving Item + item.EvolvingID = std::stoul(row[ItemField::evoid]); + item.EvolvingItem = static_cast(std::stoul(row[ItemField::evoitem])); + item.EvolvingLevel = static_cast(std::stoul(row[ItemField::evolvinglevel])); + item.EvolvingMax = static_cast(std::stoul(row[ItemField::evomax])); + + // Scripting + item.CharmFileID = Strings::IsNumber(row[ItemField::charmfileid]) ? std::stoul(row[ItemField::charmfileid]) : 0; + strn0cpy(item.CharmFile, row[ItemField::charmfile], sizeof(item.CharmFile)); + strn0cpy(item.Filename, row[ItemField::filename], sizeof(item.Filename)); + item.ScriptFileID = std::stoul(row[ItemField::scriptfileid]); try { hash.insert(item.ID, item); @@ -1200,7 +1286,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } -const EQ::ItemData *SharedDatabase::GetItem(uint32 id) +const EQ::ItemData *SharedDatabase::GetItem(uint32 id) const { if (id == 0) { return nullptr; @@ -1217,7 +1303,8 @@ const EQ::ItemData *SharedDatabase::GetItem(uint32 id) return nullptr; } -const EQ::ItemData* SharedDatabase::IterateItems(uint32* id) { +const EQ::ItemData* SharedDatabase::IterateItems(uint32* id) const +{ if(!items_hash || !id) { return nullptr; } @@ -1243,7 +1330,7 @@ std::string SharedDatabase::GetBook(const char *txtfile, int16 *language) std::string txtout; strcpy(txtfile2, txtfile); - std::string query = StringFormat("SELECT txtfile, language FROM books WHERE name = '%s'", txtfile2); + const std::string query = StringFormat("SELECT txtfile, language FROM books WHERE name = '%s'", txtfile2); auto results = QueryDatabase(query); if (!results.Success()) { txtout.assign(" ",1); @@ -1256,7 +1343,7 @@ std::string SharedDatabase::GetBook(const char *txtfile, int16 *language) return txtout; } - auto row = results.begin(); + auto& row = results.begin(); txtout.assign(row[0],strlen(row[0])); *language = static_cast(atoi(row[1])); @@ -1276,13 +1363,14 @@ void SharedDatabase::GetFactionListInfo(uint32 &list_count, uint32 &max_lists) { if (results.RowCount() == 0) return; - auto row = results.begin(); + auto& row = results.begin(); list_count = static_cast(atoul(row[0])); max_lists = static_cast(atoul(row[1] ? row[1] : "0")); } -const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) { +const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) const +{ if(!faction_hash) { return nullptr; } @@ -1295,7 +1383,7 @@ const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) { } void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists) { - EQ::FixedMemoryHashSet hash(reinterpret_cast(data), size, list_count, max_lists); + EQ::FixedMemoryHashSet hash(static_cast(data), size, list_count, max_lists); NPCFactionList faction; const std::string query = "SELECT npc_faction.id, npc_faction.primaryfaction, npc_faction.ignore_primary_assist, " @@ -1310,8 +1398,8 @@ void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_co uint32 current_id = 0; uint32 current_entry = 0; - for(auto row = results.begin(); row != results.end(); ++row) { - uint32 id = static_cast(atoul(row[0])); + for(auto& row = results.begin(); row != results.end(); ++row) { + const uint32 id = static_cast(atoul(row[0])); if(id != current_id) { if(current_id != 0) { hash.insert(current_id, faction); @@ -1348,14 +1436,16 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { faction_hash.reset(nullptr); try { - auto Config = EQEmuConfig::get(); + const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("faction"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("faction"); - LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("faction")); + LogInfo("Loading [{}]", file_name); faction_mmf = std::make_unique(file_name); - faction_hash = std::make_unique>(reinterpret_cast(faction_mmf->Get()), faction_mmf->Size()); + faction_hash = std::make_unique>(static_cast(faction_mmf->Get()), faction_mmf->Size()); mutex.Unlock(); + + LogInfo("Loaded faction lists via shared memory"); } catch(std::exception& ex) { LogError("Error Loading npc factions: {}", ex.what()); return false; @@ -1364,17 +1454,101 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { return true; } -// Create appropriate EQ::ItemInstance class -EQ::ItemInstance* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) +void SharedDatabase::GetFactionAssociationInfo(uint32 &list_count, uint32 &max_lists) { - const EQ::ItemData* item = nullptr; + list_count = static_cast(FactionAssociationRepository::Count(*this)); + max_lists = static_cast(FactionAssociationRepository::GetMaxId(*this)); +} + +const FactionAssociations *SharedDatabase::GetFactionAssociationHit(int id) +{ + if (!faction_associations_hash) { + return nullptr; + } + + if (faction_associations_hash->exists(id)) { + return &(faction_associations_hash->at(id)); + } + + return nullptr; +} + +void SharedDatabase::LoadFactionAssociation(void *data, uint32 size, uint32 list_count, uint32 max_lists) +{ + EQ::FixedMemoryHashSet hash(reinterpret_cast(data), size, list_count, max_lists); + FactionAssociations faction{}; + + auto results = FactionAssociationRepository::All(*this); + for (auto &row : results) { + faction.hits[0].id = row.id_1; + faction.hits[0].multiplier = row.mod_1; + faction.hits[1].id = row.id_2; + faction.hits[1].multiplier = row.mod_2; + faction.hits[2].id = row.id_3; + faction.hits[2].multiplier = row.mod_3; + faction.hits[3].id = row.id_4; + faction.hits[3].multiplier = row.mod_4; + faction.hits[4].id = row.id_5; + faction.hits[4].multiplier = row.mod_5; + faction.hits[5].id = row.id_6; + faction.hits[5].multiplier = row.mod_6; + faction.hits[6].id = row.id_7; + faction.hits[6].multiplier = row.mod_7; + faction.hits[7].id = row.id_8; + faction.hits[7].multiplier = row.mod_8; + faction.hits[8].id = row.id_9; + faction.hits[8].multiplier = row.mod_9; + faction.hits[9].id = row.id_10; + faction.hits[9].multiplier = row.mod_10; + + hash.insert(row.id, faction); + } +} + +bool SharedDatabase::LoadFactionAssociation(const std::string &prefix) +{ + faction_associations_mmf.reset(nullptr); + faction_associations_hash.reset(nullptr); + + try { + auto Config = EQEmuConfig::get(); + EQ::IPCMutex mutex("factionassociations"); + mutex.Lock(); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("factionassociations")); + faction_associations_mmf = std::unique_ptr(new EQ::MemoryMappedFile(file_name)); + faction_associations_hash = std::unique_ptr>( + new EQ::FixedMemoryHashSet(reinterpret_cast(faction_associations_mmf->Get()), + faction_associations_mmf->Size())); + mutex.Unlock(); + + LogInfo("Loaded faction associations via shared memory"); + } catch (std::exception &ex) { + LogError("Error Loading faction associations: {}", ex.what()); + return false; + } + + return true; +} + +// Create appropriate EQ::ItemInstance class +EQ::ItemInstance* SharedDatabase::CreateItem( + uint32 item_id, + int16 charges, + uint32 aug1, + uint32 aug2, + uint32 aug3, + uint32 aug4, + uint32 aug5, + uint32 aug6, + bool attuned +) { EQ::ItemInstance* inst = nullptr; - item = GetItem(item_id); + const EQ::ItemData* item = GetItem(item_id); if (item) { inst = CreateBaseItem(item, charges); - if (inst == nullptr) { + if (!inst) { LogError("Error: valid item data returned a null reference for EQ::ItemInstance creation in SharedDatabase::CreateItem()"); LogError("Item Data = ID: {}, Name: {}, Charges: {}", item->ID, item->Name, charges); return nullptr; @@ -1394,13 +1568,22 @@ EQ::ItemInstance* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint // Create appropriate EQ::ItemInstance class -EQ::ItemInstance* SharedDatabase::CreateItem(const EQ::ItemData* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) -{ +EQ::ItemInstance* SharedDatabase::CreateItem( + const EQ::ItemData* item, + int16 charges, + uint32 aug1, + uint32 aug2, + uint32 aug3, + uint32 aug4, + uint32 aug5, + uint32 aug6, + bool attuned +) { EQ::ItemInstance* inst = nullptr; if (item) { inst = CreateBaseItem(item, charges); - if (inst == nullptr) { + if (!inst) { LogError("Error: valid item data returned a null reference for EQ::ItemInstance creation in SharedDatabase::CreateItem()"); LogError("Item Data = ID: {}, Name: {}, Charges: {}", item->ID, item->Name, charges); return nullptr; @@ -1446,21 +1629,21 @@ EQ::ItemInstance* SharedDatabase::CreateBaseItem(const EQ::ItemData* item, int16 int32 SharedDatabase::DeleteStalePlayerCorpses() { if(RuleB(Zone, EnableShadowrest)) { - std::string query = StringFormat( + const std::string query = StringFormat( "UPDATE `character_corpses` SET `is_buried` = 1 WHERE `is_buried` = 0 AND " "(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) > %d AND NOT time_of_death = 0", (RuleI(Character, CorpseDecayTimeMS) / 1000)); - auto results = QueryDatabase(query); + const auto results = QueryDatabase(query); if (!results.Success()) return -1; return results.RowsAffected(); } - std::string query = StringFormat( + const std::string query = StringFormat( "DELETE FROM `character_corpses` WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) > %d " "AND NOT time_of_death = 0", (RuleI(Character, CorpseDecayTimeMS) / 1000)); - auto results = QueryDatabase(query); + const auto results = QueryDatabase(query); if (!results.Success()) return -1; @@ -1471,17 +1654,17 @@ bool SharedDatabase::GetCommandSettings(std::map aliases = SplitString(row[2], '|'); + std::vector aliases = Strings::Split(row[2], '|'); for (auto iter = aliases.begin(); iter != aliases.end(); ++iter) { if (iter->empty()) continue; @@ -1495,10 +1678,9 @@ bool SharedDatabase::GetCommandSettings(std::map> &injected) { if (injected.size()) { - - std::string query = fmt::format( + const std::string query = fmt::format( "REPLACE INTO `command_settings`(`command`, `access`) VALUES {}", - implode( + Strings::ImplodePair( ",", std::pair('(', ')'), join_pair(",", std::pair('\'', '\''), injected) @@ -1521,10 +1703,9 @@ bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector &orphaned) { if (orphaned.size()) { - - std::string query = fmt::format( + const std::string query = fmt::format( "DELETE FROM `command_settings` WHERE `command` IN ({})", - implode(",", std::pair('\'', '\''), orphaned) + Strings::ImplodePair(",", std::pair('\'', '\''), orphaned) ); if (!QueryDatabase(query).Success()) { @@ -1544,18 +1725,16 @@ bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vectorSharedMemDir + prefix + std::string("skill_caps"); - LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("skill_caps")); + LogInfo("Loading [{}]", file_name); skill_caps_mmf = std::make_unique(file_name); + + LogInfo("Loaded skill caps via shared memory"); + mutex.Unlock(); } catch(std::exception &ex) { LogError("Error loading skill caps: {}", ex.what()); @@ -1566,10 +1745,10 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { } void SharedDatabase::LoadSkillCaps(void *data) { - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - uint16 *skill_caps_table = reinterpret_cast(data); + const uint32 class_count = PLAYER_CLASS_COUNT; + const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1; + const uint32 level_count = HARD_LEVEL_CAP + 1; + uint16 *skill_caps_table = static_cast(data); const std::string query = "SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level"; auto results = QueryDatabase(query); @@ -1578,21 +1757,22 @@ void SharedDatabase::LoadSkillCaps(void *data) { return; } - for(auto row = results.begin(); row != results.end(); ++row) { - uint8 skillID = atoi(row[0]); - uint8 class_ = atoi(row[1]) - 1; - uint8 level = atoi(row[2]); - uint16 cap = atoi(row[3]); + for(auto& row = results.begin(); row != results.end(); ++row) { + const uint8 skillID = atoi(row[0]); + const uint8 class_ = atoi(row[1]) - 1; + const uint8 level = atoi(row[2]); + const uint16 cap = atoi(row[3]); if(skillID >= skill_count || class_ >= class_count || level >= level_count) continue; - uint32 index = (((class_ * skill_count) + skillID) * level_count) + level; + const uint32 index = (((class_ * skill_count) + skillID) * level_count) + level; skill_caps_table[index] = cap; } } -uint16 SharedDatabase::GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) { +uint16 SharedDatabase::GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const +{ if(!skill_caps_mmf) { return 0; } @@ -1605,9 +1785,9 @@ uint16 SharedDatabase::GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, ui SkillMaxLevel = RuleI(Character, MaxLevel); } - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; + const uint32 class_count = PLAYER_CLASS_COUNT; + const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1; + const uint32 level_count = HARD_LEVEL_CAP + 1; if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { return 0; } @@ -1616,12 +1796,13 @@ uint16 SharedDatabase::GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, ui Level = static_cast(SkillMaxLevel); } - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count) + Level; - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); + const uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count) + Level; + const uint16 *skill_caps_table = static_cast(skill_caps_mmf->Get()); return skill_caps_table[index]; } -uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) { +uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const +{ if(!skill_caps_mmf) { return 0; } @@ -1634,17 +1815,17 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, u SkillMaxLevel = RuleI(Character, MaxLevel); } - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; + const uint32 class_count = PLAYER_CLASS_COUNT; + const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1; + const uint32 level_count = HARD_LEVEL_CAP + 1; if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { return 0; } uint8 ret = 0; if(Level > static_cast(SkillMaxLevel)) { - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); + const uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); + const uint16 *skill_caps_table = static_cast(skill_caps_mmf->Get()); for(uint8 x = 0; x < Level; x++){ if(skill_caps_table[index + x]){ ret = x; @@ -1654,8 +1835,8 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, u } else { - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); + const uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); + const uint16 *skill_caps_table = static_cast(skill_caps_mmf->Get()); for(int x = 0; x < SkillMaxLevel; x++){ if(skill_caps_table[index + x]){ ret = x; @@ -1671,16 +1852,15 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, u } void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) { - - std::string query = StringFormat("SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 " - "AND `spellid` <= %i", iMaxSpellID); + const std::string query = StringFormat("SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 " + "AND `spellid` <= %i", iMaxSpellID); auto results = QueryDatabase(query); if (!results.Success()) { return; } - for(auto row = results.begin(); row != results.end(); ++row) { - int spellID = atoi(row[0]); + for(auto& row = results.begin(); row != results.end(); ++row) { + const int spellID = atoi(row[0]); if((spellID > 0) && (spellID <= iMaxSpellID)) sp[spellID].damage_shield_type = atoi(row[1]); } @@ -1692,13 +1872,13 @@ const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { } int SharedDatabase::GetMaxSpellID() { - std::string query = "SELECT MAX(id) FROM spells_new"; + const std::string query = "SELECT MAX(id) FROM spells_new"; auto results = QueryDatabase(query); if (!results.Success()) { return -1; } - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } @@ -1707,27 +1887,30 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const spells_mmf.reset(nullptr); try { - auto Config = EQEmuConfig::get(); + const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("spells"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("spells"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("spells")); spells_mmf = std::make_unique(file_name); - LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); - *records = *reinterpret_cast(spells_mmf->Get()); - *sp = reinterpret_cast((char*)spells_mmf->Get() + 4); + LogInfo("Loading [{}]", file_name); + *records = *static_cast(spells_mmf->Get()); + *sp = reinterpret_cast(static_cast(spells_mmf->Get()) + 4); mutex.Unlock(); + + LogInfo("Loaded [{}] spells via shared memory", Strings::Commify(m_shared_spells_count)); } catch(std::exception& ex) { LogError("Error Loading Spells: {}", ex.what()); return false; } + return true; } void SharedDatabase::LoadSpells(void *data, int max_spells) { - *(uint32*)data = max_spells; - SPDat_Spell_Struct *sp = reinterpret_cast((char*)data + sizeof(uint32)); + *static_cast(data) = max_spells; + SPDat_Spell_Struct *sp = reinterpret_cast(static_cast(data) + sizeof(uint32)); const std::string query = "SELECT * FROM spells_new ORDER BY id ASC"; auto results = QueryDatabase(query); @@ -1740,15 +1923,14 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { return; } - int tempid = 0; - int counter = 0; + int counter = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - tempid = atoi(row[0]); + for (auto& row = results.begin(); row != results.end(); ++row) { + const int tempid = atoi(row[0]); if(tempid >= max_spells) { - LogSpells("Non fatal error: spell.id >= max_spells, ignoring"); - continue; - } + LogSpells("Non fatal error: spell.id >= max_spells, ignoring"); + continue; + } ++counter; sp[tempid].id = tempid; @@ -1802,15 +1984,15 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { for(y=0; y< EFFECT_COUNT;y++) sp[tempid].effect_id[y]=atoi(row[86+y]); - sp[tempid].target_type = (SpellTargetType) atoi(row[98]); + sp[tempid].target_type = static_cast(atoi(row[98])); sp[tempid].base_difficulty=atoi(row[99]); - int tmp_skill = atoi(row[100]);; + int tmp_skill = atoi(row[100]); if (tmp_skill < 0 || tmp_skill > EQ::skills::HIGHEST_SKILL) sp[tempid].skill = EQ::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated else - sp[tempid].skill = (EQ::skills::SkillType) tmp_skill; + sp[tempid].skill = static_cast(tmp_skill); sp[tempid].zone_type=atoi(row[101]); sp[tempid].environment_type=atoi(row[102]); @@ -1890,10 +2072,10 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].spell_class = atoi(row[221]); sp[tempid].spell_subclass = atoi(row[222]); sp[tempid].persist_death = atoi(row[224]) != 0; - sp[tempid].min_distance = atof(row[227]); - sp[tempid].min_distance_mod = atof(row[228]); - sp[tempid].max_distance = atof(row[229]); - sp[tempid].max_distance_mod = atof(row[230]); + sp[tempid].min_distance = static_cast(atof(row[227])); + sp[tempid].min_distance_mod = static_cast(atof(row[228])); + sp[tempid].max_distance = static_cast(atof(row[229])); + sp[tempid].max_distance_mod = static_cast(atof(row[230])); sp[tempid].min_range = static_cast(atoi(row[231])); sp[tempid].no_remove = atoi(row[232]) != 0; sp[tempid].damage_shield_type = 0; @@ -1912,7 +2094,7 @@ int SharedDatabase::GetMaxBaseDataLevel() { if (results.RowCount() == 0) return -1; - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } @@ -1921,13 +2103,15 @@ bool SharedDatabase::LoadBaseData(const std::string &prefix) { base_data_mmf.reset(nullptr); try { - auto Config = EQEmuConfig::get(); + const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("base_data"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("base_data"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("base_data")); base_data_mmf = std::make_unique(file_name); mutex.Unlock(); + + LogInfo("Loaded base data via shared memory"); } catch(std::exception& ex) { LogError("Error Loading Base Data: {}", ex.what()); return false; @@ -1937,7 +2121,7 @@ bool SharedDatabase::LoadBaseData(const std::string &prefix) { } void SharedDatabase::LoadBaseData(void *data, int max_level) { - char *base_ptr = reinterpret_cast(data); + char *base_ptr = static_cast(data); const std::string query = "SELECT * FROM base_data ORDER BY level, class ASC"; auto results = QueryDatabase(query); @@ -1945,12 +2129,9 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) { return; } - int lvl = 0; - int cl = 0; - - for (auto row = results.begin(); row != results.end(); ++row) { - lvl = atoi(row[0]); - cl = atoi(row[1]); + for (auto& row = results.begin(); row != results.end(); ++row) { + const int lvl = atoi(row[0]); + const int cl = atoi(row[1]); if(lvl <= 0) { LogError("Non fatal error: base_data.level <= 0, ignoring."); @@ -1984,7 +2165,8 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) { } } -const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) { +const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) const +{ if(!base_data_mmf) { return nullptr; } @@ -2001,15 +2183,15 @@ const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) { return nullptr; } - char *base_ptr = reinterpret_cast(base_data_mmf->Get()); + char *base_ptr = static_cast(base_data_mmf->Get()); - uint32 offset = ((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct); + const uint32 offset = ((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct); if(offset >= base_data_mmf->Size()) { return nullptr; } - BaseDataStruct *bd = reinterpret_cast(base_ptr + offset); + const BaseDataStruct *bd = reinterpret_cast(base_ptr + offset); return bd; } @@ -2030,7 +2212,7 @@ void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot if (results.RowCount() == 0) return; - auto row = results.begin(); + auto& row = results.begin(); loot_table_count = static_cast(atoul(row[0])); max_loot_table = static_cast(atoul(row[1] ? row[1] : "0")); @@ -2055,7 +2237,7 @@ void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_d if (results.RowCount() == 0) return; - auto row =results.begin(); + auto& row =results.begin(); loot_drop_count = static_cast(atoul(row[0])); max_loot_drop = static_cast(atoul(row[1] ? row[1] : "0")); @@ -2063,7 +2245,7 @@ void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_d } void SharedDatabase::LoadLootTables(void *data, uint32 size) { - EQ::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); + EQ::FixedMemoryVariableHashSet hash(static_cast(data), size); uint8 loot_table[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)]; LootTable_Struct *lt = reinterpret_cast(loot_table); @@ -2102,8 +2284,8 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) { uint32 current_id = 0; uint32 current_entry = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - uint32 id = static_cast(atoul(row[0])); + for (auto& row = results.begin(); row != results.end(); ++row) { + const uint32 id = static_cast(atoul(row[0])); if (id != current_id) { if (current_id != 0) { hash.insert( @@ -2156,7 +2338,7 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) { void SharedDatabase::LoadLootDrops(void *data, uint32 size) { - EQ::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); + EQ::FixedMemoryVariableHashSet hash(static_cast(data), size); uint8 loot_drop[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)]; LootDrop_Struct *p_loot_drop_struct = reinterpret_cast(loot_drop); @@ -2196,8 +2378,8 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { uint32 current_id = 0; uint32 current_entry = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - auto id = static_cast(atoul(row[0])); + for (auto& row = results.begin(); row != results.end(); ++row) { + const auto id = static_cast(atoul(row[0])); if (id != current_id) { if (current_id != 0) { hash.insert( @@ -2245,18 +2427,22 @@ bool SharedDatabase::LoadLoot(const std::string &prefix) { loot_drop_mmf.reset(nullptr); try { - auto Config = EQEmuConfig::get(); + const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("loot"); mutex.Lock(); - std::string file_name_lt = Config->SharedMemDir + prefix + std::string("loot_table"); + std::string file_name_lt = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("loot_table")); + loot_table_mmf = std::make_unique(file_name_lt); loot_table_hash = std::make_unique>( - reinterpret_cast(loot_table_mmf->Get()), + static_cast(loot_table_mmf->Get()), loot_table_mmf->Size()); - std::string file_name_ld = Config->SharedMemDir + prefix + std::string("loot_drop"); + + LogInfo("Loaded loot tables via shared memory"); + + std::string file_name_ld = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("loot_drop")); loot_drop_mmf = std::make_unique(file_name_ld); loot_drop_hash = std::make_unique>( - reinterpret_cast(loot_drop_mmf->Get()), + static_cast(loot_drop_mmf->Get()), loot_drop_mmf->Size()); mutex.Unlock(); } catch(std::exception &ex) { @@ -2267,7 +2453,8 @@ bool SharedDatabase::LoadLoot(const std::string &prefix) { return true; } -const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) { +const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) const +{ if(!loot_table_hash) return nullptr; @@ -2281,7 +2468,8 @@ const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) { return nullptr; } -const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { +const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) const +{ if(!loot_drop_hash) return nullptr; @@ -2296,16 +2484,57 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { } void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) { - std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id); + const std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id); auto results = QueryDatabase(query); - auto row = results.begin(); memset(message, '\0', sizeof(InspectMessage_Struct)); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { memcpy(message, row[0], sizeof(InspectMessage_Struct)); } } void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) { - std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, EscapeString(message->text).c_str()); + const std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, Strings::Escape(message->text).c_str()); auto results = QueryDatabase(query); } + +uint32 SharedDatabase::GetSpellsCount() +{ + auto results = QueryDatabase("SELECT count(*) FROM spells_new"); + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto& row = results.begin(); + + if (row[0]) { + return atoul(row[0]); + } + + return 0; +} + +uint32 SharedDatabase::GetItemsCount() +{ + auto results = QueryDatabase("SELECT count(*) FROM items"); + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto& row = results.begin(); + + if (row[0]) { + return atoul(row[0]); + } + + return 0; +} + +void SharedDatabase::SetSharedItemsCount(uint32 shared_items_count) +{ + SharedDatabase::m_shared_items_count = shared_items_count; +} + +void SharedDatabase::SetSharedSpellsCount(uint32 shared_spells_count) +{ + SharedDatabase::m_shared_spells_count = shared_spells_count; +} diff --git a/common/shareddb.h b/common/shareddb.h index 13548c0d3..fc5f89932 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -21,8 +21,6 @@ #ifndef SHAREDDB_H_ #define SHAREDDB_H_ -#define MAX_ITEM_ID 200000 - #include "database.h" #include "skills.h" #include "spdat.h" @@ -41,6 +39,7 @@ struct InspectMessage_Struct; struct PlayerProfile_Struct; struct SPDat_Spell_Struct; struct NPCFactionList; +struct FactionAssociations; struct LootTable_Struct; struct LootDrop_Struct; @@ -79,6 +78,8 @@ public: bool UpdateInjectedCommandSettings(const std::vector> &injected); bool UpdateOrphanedCommandSettings(const std::vector &orphaned); uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID); + bool SetGMInvul(uint32 account_id, bool gminvul); + bool SetGMFlymode(uint32 account_id, uint8 flymode); void SetMailKey(int CharID, int IPAddress, int MailKey); std::string GetMailKey(int CharID, bool key_only = false); bool SaveCursor( @@ -125,7 +126,7 @@ public: uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, - uint8 attuned = 0 + bool attuned = 0 ); EQ::ItemInstance *CreateItem( const EQ::ItemData *item, @@ -136,25 +137,35 @@ public: uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, - uint8 attuned = 0 + bool attuned = 0 ); EQ::ItemInstance *CreateBaseItem(const EQ::ItemData *item, int16 charges = 0); void GetItemsCount(int32 &item_count, uint32 &max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); bool LoadItems(const std::string &prefix); - const EQ::ItemData *IterateItems(uint32 *id); - const EQ::ItemData *GetItem(uint32 id); + const EQ::ItemData *IterateItems(uint32 *id) const; + const EQ::ItemData *GetItem(uint32 id) const; const EvolveInfo *GetEvolveInfo(uint32 loregroup); + uint32 GetSharedItemsCount() { return m_shared_items_count; } + uint32 GetItemsCount(); /** * faction */ void GetFactionListInfo(uint32 &list_count, uint32 &max_lists); - const NPCFactionList *GetNPCFactionEntry(uint32 id); + const NPCFactionList *GetNPCFactionEntry(uint32 id) const; void LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists); bool LoadNPCFactionLists(const std::string &prefix); + /** + * faction associations + */ + void GetFactionAssociationInfo(uint32 &list_count, uint32 &max_lists); + const FactionAssociations *GetFactionAssociationHit(int id); + void LoadFactionAssociation(void *data, uint32 size, uint32 list_count, uint32 max_lists); + bool LoadFactionAssociation(const std::string &prefix); + /** * loot */ @@ -163,16 +174,16 @@ public: void LoadLootTables(void *data, uint32 size); void LoadLootDrops(void *data, uint32 size); bool LoadLoot(const std::string &prefix); - const LootTable_Struct *GetLootTable(uint32 loottable_id); - const LootDrop_Struct *GetLootDrop(uint32 lootdrop_id); + const LootTable_Struct *GetLootTable(uint32 loottable_id) const; + const LootDrop_Struct *GetLootDrop(uint32 lootdrop_id) const; /** * skills */ void LoadSkillCaps(void *data); bool LoadSkillCaps(const std::string &prefix); - uint16 GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level); - uint8 GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level); + uint16 GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const; + uint8 GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const; /** * spells @@ -181,6 +192,8 @@ public: bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp); void LoadSpells(void *data, int max_spells); void LoadDamageShieldTypes(SPDat_Spell_Struct *sp, int32 iMaxSpellID); + uint32 GetSharedSpellsCount() { return m_shared_spells_count; } + uint32 GetSpellsCount(); /** * basedata @@ -188,9 +201,10 @@ public: int GetMaxBaseDataLevel(); bool LoadBaseData(const std::string &prefix); void LoadBaseData(void *data, int max_level); - const BaseDataStruct *GetBaseData(int lvl, int cl); + const BaseDataStruct *GetBaseData(int lvl, int cl) const; - std::string CreateItemLink(uint32 item_id) { + std::string CreateItemLink(uint32 item_id) const + { EQ::SayLinkEngine linker; linker.SetLinkType(EQ::saylink::SayLinkItemData); const EQ::ItemData *item = GetItem(item_id); @@ -205,12 +219,21 @@ protected: std::unique_ptr> items_hash; std::unique_ptr faction_mmf; std::unique_ptr> faction_hash; + std::unique_ptr faction_associations_mmf; + std::unique_ptr> faction_associations_hash; std::unique_ptr loot_table_mmf; std::unique_ptr> loot_table_hash; std::unique_ptr loot_drop_mmf; std::unique_ptr> loot_drop_hash; std::unique_ptr base_data_mmf; std::unique_ptr spells_mmf; + +public: + void SetSharedItemsCount(uint32 shared_items_count); + void SetSharedSpellsCount(uint32 shared_spells_count); +protected: + uint32 m_shared_items_count = 0; + uint32 m_shared_spells_count = 0; }; #endif /*SHAREDDB_H_*/ diff --git a/common/spdat.cpp b/common/spdat.cpp index 2c22bcd33..43cc191e2 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -76,6 +76,7 @@ #include "classes.h" #include "spdat.h" +#include "../common/rulesys.h" #ifndef WIN32 #include @@ -101,14 +102,18 @@ bool IsSacrificeSpell(uint16 spell_id) bool IsLifetapSpell(uint16 spell_id) { - // Ancient Lifebane: 2115 - if (IsValidSpell(spell_id) && - (spells[spell_id].target_type == ST_Tap || - spells[spell_id].target_type == ST_TargetAETap || - spell_id == 2115)) - return true; + if ( + IsValidSpell(spell_id) && + ( + spells[spell_id].target_type == ST_Tap || + spells[spell_id].target_type == ST_TargetAETap || + spell_id == SPELL_ANCIENT_LIFEBANE + ) + ) { + return true; + } - return false; + return false; } bool IsMezSpell(uint16 spell_id) @@ -139,7 +144,7 @@ bool IsEvacSpell(uint16 spellid) bool IsDamageSpell(uint16 spellid) { - if (spells[spellid].target_type == ST_Tap) + if (IsLifetapSpell(spellid)) return false; for (int o = 0; o < EFFECT_COUNT; o++) { @@ -370,13 +375,16 @@ bool IsAEDurationSpell(uint16 spell_id) There are plenty of spells with aoe_duration set at single digit numbers, but these do not act as duration effects. */ - if (IsValidSpell(spell_id) && + if ( + IsValidSpell(spell_id) && spells[spell_id].aoe_duration >= 2500 && - ( spells[spell_id].target_type == ST_AETarget || + ( + spells[spell_id].target_type == ST_AETarget || spells[spell_id].target_type == ST_UndeadAE || spells[spell_id].target_type == ST_AECaster || - spells[spell_id].target_type == ST_Ring) - ) { + spells[spell_id].target_type == ST_Ring + ) + ) { return true; } @@ -505,6 +513,27 @@ bool IsEffectInSpell(uint16 spellid, int effect) return false; } + +uint16 GetTriggerSpellID(uint16 spell_id, uint32 effect) { + + for (int index = 0; index < EFFECT_COUNT; index++) { + if ( + spells[spell_id].effect_id[index] == SE_TriggerOnCast || + spells[spell_id].effect_id[index] == SE_SpellTrigger || + spells[spell_id].effect_id[index] == SE_ApplyEffect || + spells[spell_id].effect_id[index] == SE_Trigger_Spell_Non_Item + ) { + int apply_effect_spell_id = spells[spell_id].limit_value[index]; + if (IsEffectInSpell(apply_effect_spell_id, effect)) { + if (IsValidSpell(apply_effect_spell_id)) { + return apply_effect_spell_id; + } + } + } + } + return 0; +} + // arguments are spell id and the index of the effect to check. // this is used in loops that process effects inside a spell to skip // the blanks @@ -740,8 +769,9 @@ bool IsCombatSkill(uint16 spell_id) bool IsResurrectionEffects(uint16 spell_id) { // spell id 756 is Resurrection Effects spell - if(IsValidSpell(spell_id) && (spell_id == 756 || spell_id == 757)) + if (IsValidSpell(spell_id) && (spell_id == RuleI(Character, ResurrectionSicknessSpellID) || spell_id == RuleI(Character, OldResurrectionSicknessSpellID))) { return true; + } return false; } @@ -929,18 +959,32 @@ int32 GetSpellTargetType(uint16 spell_id) bool IsHealOverTimeSpell(uint16 spell_id) { - if (IsEffectInSpell(spell_id, SE_HealOverTime) && !IsGroupSpell(spell_id)) + if ( + ( + IsEffectInSpell(spell_id, SE_HealOverTime) || + GetTriggerSpellID(spell_id, SE_HealOverTime) + ) && + !IsGroupSpell(spell_id) + ) { return true; + } return false; } bool IsCompleteHealSpell(uint16 spell_id) { - if (spell_id == 13 || IsEffectInSpell(spell_id, SE_CompleteHeal) || - (IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id))) + if ( + ( + spell_id == SPELL_COMPLETE_HEAL || + IsEffectInSpell(spell_id, SE_CompleteHeal) || + IsPercentalHealSpell(spell_id) || + GetTriggerSpellID(spell_id, SE_CompleteHeal) + ) && + !IsGroupSpell(spell_id) + ) { return true; - + } return false; } @@ -948,11 +992,25 @@ bool IsFastHealSpell(uint16 spell_id) { const int MaxFastHealCastingTime = 2000; - if (spells[spell_id].cast_time <= MaxFastHealCastingTime && - spells[spell_id].effect_id[0] == 0 && spells[spell_id].base_value[0] > 0 && - !IsGroupSpell(spell_id)) - return true; - + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (spells[spell_id].cast_time <= MaxFastHealCastingTime && spells[spell_id].good_effect && !IsGroupSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 + ) { + return true; + } + } + } + } return false; } @@ -960,30 +1018,77 @@ bool IsVeryFastHealSpell(uint16 spell_id) { const int MaxFastHealCastingTime = 1000; - if (spells[spell_id].cast_time <= MaxFastHealCastingTime && - spells[spell_id].effect_id[0] == 0 && spells[spell_id].base_value[0] > 0 && - !IsGroupSpell(spell_id)) - return true; + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (spells[spell_id].cast_time <= MaxFastHealCastingTime && spells[spell_id].good_effect && !IsGroupSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 + ) { + return true; + } + } + } + } return false; } bool IsRegularSingleTargetHealSpell(uint16 spell_id) { - if(spells[spell_id].effect_id[0] == 0 && spells[spell_id].base_value[0] > 0 && - spells[spell_id].target_type == ST_Target && spells[spell_id].buff_duration == 0 && - !IsCompleteHealSpell(spell_id) && - !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) - return true; + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (spells[spell_id].target_type == ST_Target && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 && + spells[spell_id].buff_duration == 0 + ) { + return true; + } + } + } + } return false; } bool IsRegularGroupHealSpell(uint16 spell_id) { - if (IsGroupSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id)) - return true; - + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (IsGroupSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 && + spells[spell_id].buff_duration == 0 + ) { + return true; + } + } + } + } return false; } @@ -1478,6 +1583,7 @@ bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect) case SE_WaterBreathing: case SE_ModelSize: case SE_ChangeHeight: + case SE_MakeDrunk: return false; default: return true; @@ -1490,15 +1596,17 @@ bool IsPulsingBardSong(int32 spell_id) if (!IsValidSpell(spell_id)) { return false; } - - if (spells[spell_id].buff_duration == 0xFFFF || - spells[spell_id].recast_time> 0 || - spells[spell_id].mana > 0 || - IsEffectInSpell(spell_id, SE_TemporaryPets) || - IsEffectInSpell(spell_id, SE_Familiar)) { + + if ( + spells[spell_id].buff_duration == 0xFFFF || + spells[spell_id].recast_time > 0 || + spells[spell_id].mana > 0 || + IsEffectInSpell(spell_id, SE_TemporaryPets) || + IsEffectInSpell(spell_id, SE_Familiar) + ) { return false; } - + return true; } diff --git a/common/spdat.h b/common/spdat.h index 3a0d1636a..0a9ce18b9 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -26,6 +26,7 @@ #define SPELLBOOK_UNKNOWN 0xFFFFFFFF //player profile spells are 32 bit //some spell IDs which will prolly change, but are needed +#define SPELL_COMPLETE_HEAL 13 #define SPELL_LIFEBURN 2755 #define SPELL_LEECH_TOUCH 2766 #define SPELL_LAY_ON_HANDS 87 @@ -169,6 +170,7 @@ #define SPELL_ILLUSION_FEMALE 1731 #define SPELL_ILLUSION_MALE 1732 #define SPELL_UNSUMMON_SELF 892 +#define SPELL_ANCIENT_LIFEBANE 2115 //spellgroup ids #define SPELLGROUP_FRENZIED_BURNOUT 2754 @@ -513,6 +515,7 @@ enum SpellRestriction IS_SUMMONED_OR_UNDEAD = 49326, // IS_CLASS_CASTER_PRIEST = 49529, // IS_END_OR_MANA_ABOVE_20_PCT = 49543, // You must have at least 20% of your maximum mana and endurance to use this ability. //pure melee class check end, other check mana + IS_END_OR_MANA_BELOW_10_PCT = 49545, // //pure melee class check end, other check mana, hybrid check both IS_END_OR_MANA_BELOW_30_PCT = 49573, // Your target already has 30% or more of their maximum mana or endurance. //pure melee class check the, other check more IS_CLASS_BARD2 = 49574, // IS_NOT_CLASS_BARD = 49575, // @@ -892,7 +895,7 @@ typedef enum { #define SE_SpellDamageShield 157 // implemented, @DS, causes non-melee damage on caster of a spell, base: Amt DS (negative), limit: none, max: unknown (same as base but +) #define SE_Reflect 158 // implemented, @SpellMisc, reflect casted detrimental spell back at caster, base: chance pct, limit: resist modifier (positive value reduces resists), max: pct of base dmg mod (50=50pct of base) #define SE_AllStats 159 // implemented -//#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance) +#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance) #define SE_MitigateSpellDamage 161 // implemented, @Runes, mitigate incoming spell damage by percentage until rune fades, base: percent mitigation, limit: max dmg absorbed per hit, max: rune amt, Note: If placed on item or AA, will provide stackable percent mitigation. #define SE_MitigateMeleeDamage 162 // implemented - rune with max value #define SE_NegateAttacks 163 // implemented @@ -925,7 +928,7 @@ typedef enum { #define SE_EndurancePool 190 // implemented #define SE_Amnesia 191 // implemented - Silence vs Melee Effect #define SE_Hate 192 // implemented - Instant and hate over time. -#define SE_SkillAttack 193 // implemented, +#define SE_SkillAttack 193 // implemented, #define SE_FadingMemories 194 // implemented, @Aggro, Remove from hate lists and make invisible. Can set max level of NPCs that can be affected. base: success chance, limit: max level (ROF2), max: max level (modern client), Note: Support for max level requires Rule (Spells, UseFadingMemoriesMaxLevel) to be true. If used from limit field, then it set as the level, ie. max level of 75 would use limit value of 75. If set from max field, max level 75 would use max value of 1075, if you want to set it so it checks a level range above the spell target then for it to only work on mobs 5 levels or below you set max value to 5. #define SE_StunResist 195 // implemented #define SE_StrikeThrough 196 // implemented @@ -1297,7 +1300,7 @@ struct SPDat_Spell_Struct /* 016 */ uint32 buff_duration_formula; // -- DURATIONBASE /* 017 */ uint32 buff_duration; // -- DURATIONCAP /* 018 */ uint32 aoe_duration; // sentinel, rain of something -- IMPACTDURATION -/* 019 */ uint16 mana; // Mana Used -- MANACOST +/* 019 */ int32 mana; // Mana Used -- MANACOST /* 020 */ int base_value[EFFECT_COUNT]; //various purposes -- BASEAFFECT1 .. BASEAFFECT12 /* 032 */ int limit_value[EFFECT_COUNT]; //various purposes -- BASE_EFFECT2_1 ... BASE_EFFECT2_12 /* 044 */ int32 max_value[EFFECT_COUNT]; // -- AFFECT1CAP ... AFFECT12CAP @@ -1309,7 +1312,7 @@ struct SPDat_Spell_Struct // If it is a number between 1-4 it means components[number] is a focus and not to expend it // If it is a valid itemid it means this item is a focus as well // -- NOEXPENDREAGENT1 ... NOEXPENDREAGENT4 -/* 070 */ uint16 formula[EFFECT_COUNT]; // Spell's value formula -- LEVELAFFECT1MOD ... LEVELAFFECT12MOD +/* 070 */ uint32 formula[EFFECT_COUNT]; // Spell's value formula -- LEVELAFFECT1MOD ... LEVELAFFECT12MOD /* 082 */ //int LightType; // probaly another effecttype flag -- LIGHTTYPE /* 083 */ int8 good_effect; //0=detrimental, 1=Beneficial, 2=Beneficial, Group Only -- BENEFICIAL /* 084 */ int activated; // probably another effecttype flag -- ACTIVATED @@ -1478,6 +1481,7 @@ bool IsGroupSpell(uint16 spell_id); bool IsTGBCompatibleSpell(uint16 spell_id); bool IsBardSong(uint16 spell_id); bool IsEffectInSpell(uint16 spellid, int effect); +uint16 GetTriggerSpellID(uint16 spell_id, uint32 effect); bool IsBlankSpellEffect(uint16 spellid, int effect_index); bool IsValidSpell(uint32 spellid); bool IsSummonSpell(uint16 spellid); diff --git a/common/stacktrace/backward.hpp b/common/stacktrace/backward.hpp new file mode 100644 index 000000000..c2a81628e --- /dev/null +++ b/common/stacktrace/backward.hpp @@ -0,0 +1,4476 @@ +/* + * backward.hpp + * Copyright 2013 Google Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89 +#define H_6B9572DA_A64B_49E6_B234_051480991C89 + +#ifndef __cplusplus +#error "It's not going to compile without a C++ compiler..." +#endif + +#if defined(BACKWARD_CXX11) +#elif defined(BACKWARD_CXX98) +#else +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) +#define BACKWARD_CXX11 +#define BACKWARD_ATLEAST_CXX11 +#define BACKWARD_ATLEAST_CXX98 +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define BACKWARD_ATLEAST_CXX17 +#endif +#else +#define BACKWARD_CXX98 +#define BACKWARD_ATLEAST_CXX98 +#endif +#endif + +// You can define one of the following (or leave it to the auto-detection): +// +// #define BACKWARD_SYSTEM_LINUX +// - specialization for linux +// +// #define BACKWARD_SYSTEM_DARWIN +// - specialization for Mac OS X 10.5 and later. +// +// #define BACKWARD_SYSTEM_WINDOWS +// - specialization for Windows (Clang 9 and MSVC2017) +// +// #define BACKWARD_SYSTEM_UNKNOWN +// - placebo implementation, does nothing. +// +#if defined(BACKWARD_SYSTEM_LINUX) +#elif defined(BACKWARD_SYSTEM_DARWIN) +#elif defined(BACKWARD_SYSTEM_UNKNOWN) +#elif defined(BACKWARD_SYSTEM_WINDOWS) +#else +#if defined(__linux) || defined(__linux__) +#define BACKWARD_SYSTEM_LINUX +#elif defined(__APPLE__) +#define BACKWARD_SYSTEM_DARWIN +#elif defined(_WIN32) +#define BACKWARD_SYSTEM_WINDOWS +#else +#define BACKWARD_SYSTEM_UNKNOWN +#endif +#endif + +#define NOINLINE __attribute__((noinline)) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BACKWARD_SYSTEM_LINUX) + +// On linux, backtrace can back-trace or "walk" the stack using the following +// libraries: +// +// #define BACKWARD_HAS_UNWIND 1 +// - unwind comes from libgcc, but I saw an equivalent inside clang itself. +// - with unwind, the stacktrace is as accurate as it can possibly be, since +// this is used by the C++ runtime in gcc/clang for stack unwinding on +// exception. +// - normally libgcc is already linked to your program by default. +// +// #define BACKWARD_HAS_LIBUNWIND 1 +// - libunwind provides, in some cases, a more accurate stacktrace as it knows +// to decode signal handler frames and lets us edit the context registers when +// unwinding, allowing stack traces over bad function references. +// +// #define BACKWARD_HAS_BACKTRACE == 1 +// - backtrace seems to be a little bit more portable than libunwind, but on +// linux, it uses unwind anyway, but abstract away a tiny information that is +// sadly really important in order to get perfectly accurate stack traces. +// - backtrace is part of the (e)glib library. +// +// The default is: +// #define BACKWARD_HAS_UNWIND == 1 +// +// Note that only one of the define should be set to 1 at a time. +// +#if BACKWARD_HAS_UNWIND == 1 +#elif BACKWARD_HAS_LIBUNWIND == 1 +#elif BACKWARD_HAS_BACKTRACE == 1 +#else +#undef BACKWARD_HAS_UNWIND +#define BACKWARD_HAS_UNWIND 1 +#undef BACKWARD_HAS_LIBUNWIND +#define BACKWARD_HAS_LIBUNWIND 0 +#undef BACKWARD_HAS_BACKTRACE +#define BACKWARD_HAS_BACKTRACE 0 +#endif + +// On linux, backward can extract detailed information about a stack trace +// using one of the following libraries: +// +// #define BACKWARD_HAS_DW 1 +// - libdw gives you the most juicy details out of your stack traces: +// - object filename +// - function name +// - source filename +// - line and column numbers +// - source code snippet (assuming the file is accessible) +// - variable names (if not optimized out) +// - variable values (not supported by backward-cpp) +// - You need to link with the lib "dw": +// - apt-get install libdw-dev +// - g++/clang++ -ldw ... +// +// #define BACKWARD_HAS_BFD 1 +// - With libbfd, you get a fair amount of details: +// - object filename +// - function name +// - source filename +// - line numbers +// - source code snippet (assuming the file is accessible) +// - You need to link with the lib "bfd": +// - apt-get install binutils-dev +// - g++/clang++ -lbfd ... +// +// #define BACKWARD_HAS_DWARF 1 +// - libdwarf gives you the most juicy details out of your stack traces: +// - object filename +// - function name +// - source filename +// - line and column numbers +// - source code snippet (assuming the file is accessible) +// - variable names (if not optimized out) +// - variable values (not supported by backward-cpp) +// - You need to link with the lib "dwarf": +// - apt-get install libdwarf-dev +// - g++/clang++ -ldwarf ... +// +// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1 +// - backtrace provides minimal details for a stack trace: +// - object filename +// - function name +// - backtrace is part of the (e)glib library. +// +// The default is: +// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1 +// +// Note that only one of the define should be set to 1 at a time. +// +#if BACKWARD_HAS_DW == 1 +#elif BACKWARD_HAS_BFD == 1 +#elif BACKWARD_HAS_DWARF == 1 +#elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 +#else +#undef BACKWARD_HAS_DW +#define BACKWARD_HAS_DW 0 +#undef BACKWARD_HAS_BFD +#define BACKWARD_HAS_BFD 0 +#undef BACKWARD_HAS_DWARF +#define BACKWARD_HAS_DWARF 0 +#undef BACKWARD_HAS_BACKTRACE_SYMBOL +#define BACKWARD_HAS_BACKTRACE_SYMBOL 1 +#endif + +#include +#include +#ifdef __ANDROID__ +// Old Android API levels define _Unwind_Ptr in both link.h and +// unwind.h Rename the one in link.h as we are not going to be using +// it +#define _Unwind_Ptr _Unwind_Ptr_Custom +#include +#undef _Unwind_Ptr +#else +#include +#endif +#if defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \ + defined(__POWERPC__) +// Linux kernel header required for the struct pt_regs definition +// to access the NIP (Next Instruction Pointer) register value +#include +#endif +#include +#include +#include +#include + +#if BACKWARD_HAS_BFD == 1 +// NOTE: defining PACKAGE{,_VERSION} is required before including +// bfd.h on some platforms, see also: +// https://sourceware.org/bugzilla/show_bug.cgi?id=14243 +#ifndef PACKAGE +#define PACKAGE +#endif +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION +#endif +#include +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#include +#undef _GNU_SOURCE +#else +#include +#endif +#endif + +#if BACKWARD_HAS_DW == 1 +#include +#include +#include +#endif + +#if BACKWARD_HAS_DWARF == 1 +#include +#include +#include +#include +#include +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#include +#undef _GNU_SOURCE +#else +#include +#endif +#endif + +#if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) +// then we shall rely on backtrace +#include +#endif + +#endif // defined(BACKWARD_SYSTEM_LINUX) + +#if defined(BACKWARD_SYSTEM_DARWIN) +// On Darwin, backtrace can back-trace or "walk" the stack using the following +// libraries: +// +// #define BACKWARD_HAS_UNWIND 1 +// - unwind comes from libgcc, but I saw an equivalent inside clang itself. +// - with unwind, the stacktrace is as accurate as it can possibly be, since +// this is used by the C++ runtime in gcc/clang for stack unwinding on +// exception. +// - normally libgcc is already linked to your program by default. +// +// #define BACKWARD_HAS_LIBUNWIND 1 +// - libunwind comes from clang, which implements an API compatible version. +// - libunwind provides, in some cases, a more accurate stacktrace as it knows +// to decode signal handler frames and lets us edit the context registers when +// unwinding, allowing stack traces over bad function references. +// +// #define BACKWARD_HAS_BACKTRACE == 1 +// - backtrace is available by default, though it does not produce as much +// information as another library might. +// +// The default is: +// #define BACKWARD_HAS_UNWIND == 1 +// +// Note that only one of the define should be set to 1 at a time. +// +#if BACKWARD_HAS_UNWIND == 1 +#elif BACKWARD_HAS_BACKTRACE == 1 +#elif BACKWARD_HAS_LIBUNWIND == 1 +#else +#undef BACKWARD_HAS_UNWIND +#define BACKWARD_HAS_UNWIND 1 +#undef BACKWARD_HAS_BACKTRACE +#define BACKWARD_HAS_BACKTRACE 0 +#undef BACKWARD_HAS_LIBUNWIND +#define BACKWARD_HAS_LIBUNWIND 0 +#endif + +// On Darwin, backward can extract detailed information about a stack trace +// using one of the following libraries: +// +// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1 +// - backtrace provides minimal details for a stack trace: +// - object filename +// - function name +// +// The default is: +// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1 +// +#if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 +#else +#undef BACKWARD_HAS_BACKTRACE_SYMBOL +#define BACKWARD_HAS_BACKTRACE_SYMBOL 1 +#endif + +#include +#include +#include +#include +#include +#include + +#if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) +#include +#endif +#endif // defined(BACKWARD_SYSTEM_DARWIN) + +#if defined(BACKWARD_SYSTEM_WINDOWS) + +#include +#include +#include + +#include + +#ifdef _WIN64 +typedef SSIZE_T ssize_t; +#else +typedef int ssize_t; +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include + +#include +#include + +#ifndef __clang__ +#undef NOINLINE +#define NOINLINE __declspec(noinline) +#endif + +#ifdef _MSC_VER +#pragma comment(lib, "psapi.lib") +#pragma comment(lib, "dbghelp.lib") +#endif + +// Comment / packing is from stackoverflow: +// https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app/28276227#28276227 +// Some versions of imagehlp.dll lack the proper packing directives themselves +// so we need to do it. +#pragma pack(push, before_imagehlp, 8) +#include +#pragma pack(pop, before_imagehlp) + +// TODO maybe these should be undefined somewhere else? +#undef BACKWARD_HAS_UNWIND +#undef BACKWARD_HAS_BACKTRACE +#if BACKWARD_HAS_PDB_SYMBOL == 1 +#else +#undef BACKWARD_HAS_PDB_SYMBOL +#define BACKWARD_HAS_PDB_SYMBOL 1 +#endif + +#endif + +#if BACKWARD_HAS_UNWIND == 1 + +#include +// while gcc's unwind.h defines something like that: +// extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); +// extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *); +// +// clang's unwind.h defines something like this: +// uintptr_t _Unwind_GetIP(struct _Unwind_Context* __context); +// +// Even if the _Unwind_GetIPInfo can be linked to, it is not declared, worse we +// cannot just redeclare it because clang's unwind.h doesn't define _Unwind_Ptr +// anyway. +// +// Luckily we can play on the fact that the guard macros have a different name: +#ifdef __CLANG_UNWIND_H +// In fact, this function still comes from libgcc (on my different linux boxes, +// clang links against libgcc). +#include +extern "C" uintptr_t _Unwind_GetIPInfo(_Unwind_Context *, int *); +#endif + +#endif // BACKWARD_HAS_UNWIND == 1 + +#if BACKWARD_HAS_LIBUNWIND == 1 +#define UNW_LOCAL_ONLY +#include +#endif // BACKWARD_HAS_LIBUNWIND == 1 + +#ifdef BACKWARD_ATLEAST_CXX11 +#include +#include // for std::swap +namespace backward { + namespace details { + template struct hashtable { + typedef std::unordered_map type; + }; + using std::move; + } // namespace details +} // namespace backward +#else // NOT BACKWARD_ATLEAST_CXX11 +#define nullptr NULL +#define override +#include +namespace backward { +namespace details { +template struct hashtable { + typedef std::map type; +}; +template const T &move(const T &v) { return v; } +template T &move(T &v) { return v; } +} // namespace details +} // namespace backward +#endif // BACKWARD_ATLEAST_CXX11 + +namespace backward { + namespace details { +#if defined(BACKWARD_SYSTEM_WINDOWS) + const char kBackwardPathDelimiter[] = ";"; +#else + const char kBackwardPathDelimiter[] = ":"; +#endif + } // namespace details +} // namespace backward + +namespace backward { + + namespace system_tag { + struct linux_tag; // seems that I cannot call that "linux" because the name +// is already defined... so I am adding _tag everywhere. + struct darwin_tag; + struct windows_tag; + struct unknown_tag; + +#if defined(BACKWARD_SYSTEM_LINUX) + typedef linux_tag current_tag; +#elif defined(BACKWARD_SYSTEM_DARWIN) + typedef darwin_tag current_tag; +#elif defined(BACKWARD_SYSTEM_WINDOWS) +typedef windows_tag current_tag; +#elif defined(BACKWARD_SYSTEM_UNKNOWN) +typedef unknown_tag current_tag; +#else +#error "May I please get my system defines?" +#endif + } // namespace system_tag + + namespace trace_resolver_tag { +#if defined(BACKWARD_SYSTEM_LINUX) + struct libdw; + struct libbfd; + struct libdwarf; + struct backtrace_symbol; + +#if BACKWARD_HAS_DW == 1 + typedef libdw current; +#elif BACKWARD_HAS_BFD == 1 + typedef libbfd current; +#elif BACKWARD_HAS_DWARF == 1 + typedef libdwarf current; +#elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 + typedef backtrace_symbol current; +#else +#error "You shall not pass, until you know what you want." +#endif +#elif defined(BACKWARD_SYSTEM_DARWIN) + struct backtrace_symbol; + +#if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 +typedef backtrace_symbol current; +#else +#error "You shall not pass, until you know what you want." +#endif +#elif defined(BACKWARD_SYSTEM_WINDOWS) +struct pdb_symbol; +#if BACKWARD_HAS_PDB_SYMBOL == 1 +typedef pdb_symbol current; +#else +#error "You shall not pass, until you know what you want." +#endif +#endif + } // namespace trace_resolver_tag + + namespace details { + + template struct rm_ptr { typedef T type; }; + + template struct rm_ptr { typedef T type; }; + + template struct rm_ptr { typedef const T type; }; + + template struct deleter { + template void operator()(U &ptr) const { (*F)(ptr); } + }; + + template struct default_delete { + void operator()(T &ptr) const { delete ptr; } + }; + + template > + class handle { + struct dummy; + T _val; + bool _empty; + +#ifdef BACKWARD_ATLEAST_CXX11 + handle(const handle &) = delete; + handle &operator=(const handle &) = delete; +#endif + + public: + ~handle() { + if (!_empty) { + Deleter()(_val); + } + } + + explicit handle() : _val(), _empty(true) {} + explicit handle(T val) : _val(val), _empty(false) { + if (!_val) + _empty = true; + } + +#ifdef BACKWARD_ATLEAST_CXX11 + handle(handle &&from) : _empty(true) { swap(from); } + handle &operator=(handle &&from) { + swap(from); + return *this; + } +#else + explicit handle(const handle &from) : _empty(true) { + // some sort of poor man's move semantic. + swap(const_cast(from)); + } + handle &operator=(const handle &from) { + // some sort of poor man's move semantic. + swap(const_cast(from)); + return *this; + } +#endif + + void reset(T new_val) { + handle tmp(new_val); + swap(tmp); + } + + void update(T new_val) { + _val = new_val; + _empty = !static_cast(new_val); + } + + operator const dummy *() const { + if (_empty) { + return nullptr; + } + return reinterpret_cast(_val); + } + T get() { return _val; } + T release() { + _empty = true; + return _val; + } + void swap(handle &b) { + using std::swap; + swap(b._val, _val); // can throw, we are safe here. + swap(b._empty, _empty); // should not throw: if you cannot swap two + // bools without throwing... It's a lost cause anyway! + } + + T &operator->() { return _val; } + const T &operator->() const { return _val; } + + typedef typename rm_ptr::type &ref_t; + typedef const typename rm_ptr::type &const_ref_t; + ref_t operator*() { return *_val; } + const_ref_t operator*() const { return *_val; } + ref_t operator[](size_t idx) { return _val[idx]; } + + // Watch out, we've got a badass over here + T *operator&() { + _empty = false; + return &_val; + } + }; + +// Default demangler implementation (do nothing). + template struct demangler_impl { + static std::string demangle(const char *funcname) { return funcname; } + }; + +#if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN) + + template <> struct demangler_impl { + demangler_impl() : _demangle_buffer_length(0) {} + + std::string demangle(const char *funcname) { + using namespace details; + char *result = abi::__cxa_demangle(funcname, _demangle_buffer.get(), + &_demangle_buffer_length, nullptr); + if (result) { + _demangle_buffer.update(result); + return result; + } + return funcname; + } + + private: + details::handle _demangle_buffer; + size_t _demangle_buffer_length; + }; + +#endif // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN + + struct demangler : public demangler_impl {}; + +// Split a string on the platform's PATH delimiter. Example: if delimiter +// is ":" then: +// "" --> [] +// ":" --> ["",""] +// "::" --> ["","",""] +// "/a/b/c" --> ["/a/b/c"] +// "/a/b/c:/d/e/f" --> ["/a/b/c","/d/e/f"] +// etc. + inline std::vector split_source_prefixes(const std::string &s) { + std::vector out; + size_t last = 0; + size_t next = 0; + size_t delimiter_size = sizeof(kBackwardPathDelimiter) - 1; + while ((next = s.find(kBackwardPathDelimiter, last)) != std::string::npos) { + out.push_back(s.substr(last, next - last)); + last = next + delimiter_size; + } + if (last <= s.length()) { + out.push_back(s.substr(last)); + } + return out; + } + + } // namespace details + +/*************** A TRACE ***************/ + + struct Trace { + void *addr; + size_t idx; + + Trace() : addr(nullptr), idx(0) {} + + explicit Trace(void *_addr, size_t _idx) : addr(_addr), idx(_idx) {} + }; + + struct ResolvedTrace : public Trace { + + struct SourceLoc { + std::string function; + std::string filename; + unsigned line; + unsigned col; + + SourceLoc() : line(0), col(0) {} + + bool operator==(const SourceLoc &b) const { + return function == b.function && filename == b.filename && + line == b.line && col == b.col; + } + + bool operator!=(const SourceLoc &b) const { return !(*this == b); } + }; + + // In which binary object this trace is located. + std::string object_filename; + + // The function in the object that contain the trace. This is not the same + // as source.function which can be an function inlined in object_function. + std::string object_function; + + // The source location of this trace. It is possible for filename to be + // empty and for line/col to be invalid (value 0) if this information + // couldn't be deduced, for example if there is no debug information in the + // binary object. + SourceLoc source; + + // An optionals list of "inliners". All the successive sources location + // from where the source location of the trace (the attribute right above) + // is inlined. It is especially useful when you compiled with optimization. + typedef std::vector source_locs_t; + source_locs_t inliners; + + ResolvedTrace() : Trace() {} + ResolvedTrace(const Trace &mini_trace) : Trace(mini_trace) {} + }; + +/*************** STACK TRACE ***************/ + +// default implemention. + template class StackTraceImpl { + public: + size_t size() const { return 0; } + Trace operator[](size_t) const { return Trace(); } + size_t load_here(size_t = 0) { return 0; } + size_t load_from(void *, size_t = 0, void * = nullptr, void * = nullptr) { + return 0; + } + size_t thread_id() const { return 0; } + void skip_n_firsts(size_t) {} + }; + + class StackTraceImplBase { + public: + StackTraceImplBase() + : _thread_id(0), _skip(0), _context(nullptr), _error_addr(nullptr) {} + + size_t thread_id() const { return _thread_id; } + + void skip_n_firsts(size_t n) { _skip = n; } + + protected: + void load_thread_info() { +#ifdef BACKWARD_SYSTEM_LINUX +#ifndef __ANDROID__ + _thread_id = static_cast(syscall(SYS_gettid)); +#else + _thread_id = static_cast(gettid()); +#endif + if (_thread_id == static_cast(getpid())) { + // If the thread is the main one, let's hide that. + // I like to keep little secret sometimes. + _thread_id = 0; + } +#elif defined(BACKWARD_SYSTEM_DARWIN) + _thread_id = reinterpret_cast(pthread_self()); + if (pthread_main_np() == 1) { + // If the thread is the main one, let's hide that. + _thread_id = 0; + } +#endif + } + + void set_context(void *context) { _context = context; } + void *context() const { return _context; } + + void set_error_addr(void *error_addr) { _error_addr = error_addr; } + void *error_addr() const { return _error_addr; } + + size_t skip_n_firsts() const { return _skip; } + + private: + size_t _thread_id; + size_t _skip; + void *_context; + void *_error_addr; + }; + + class StackTraceImplHolder : public StackTraceImplBase { + public: + size_t size() const { + return (_stacktrace.size() >= skip_n_firsts()) + ? _stacktrace.size() - skip_n_firsts() + : 0; + } + Trace operator[](size_t idx) const { + if (idx >= size()) { + return Trace(); + } + return Trace(_stacktrace[idx + skip_n_firsts()], idx); + } + void *const *begin() const { + if (size()) { + return &_stacktrace[skip_n_firsts()]; + } + return nullptr; + } + + protected: + std::vector _stacktrace; + }; + +#if BACKWARD_HAS_UNWIND == 1 + + namespace details { + + template class Unwinder { + public: + size_t operator()(F &f, size_t depth) { + _f = &f; + _index = -1; + _depth = depth; + _Unwind_Backtrace(&this->backtrace_trampoline, this); + return static_cast(_index); + } + + private: + F *_f; + ssize_t _index; + size_t _depth; + + static _Unwind_Reason_Code backtrace_trampoline(_Unwind_Context *ctx, + void *self) { + return (static_cast(self))->backtrace(ctx); + } + + _Unwind_Reason_Code backtrace(_Unwind_Context *ctx) { + if (_index >= 0 && static_cast(_index) >= _depth) + return _URC_END_OF_STACK; + + int ip_before_instruction = 0; + uintptr_t ip = _Unwind_GetIPInfo(ctx, &ip_before_instruction); + + if (!ip_before_instruction) { + // calculating 0-1 for unsigned, looks like a possible bug to sanitizers, + // so let's do it explicitly: + if (ip == 0) { + ip = std::numeric_limits::max(); // set it to 0xffff... (as + // from casting 0-1) + } else { + ip -= 1; // else just normally decrement it (no overflow/underflow will + // happen) + } + } + + if (_index >= 0) { // ignore first frame. + (*_f)(static_cast(_index), reinterpret_cast(ip)); + } + _index += 1; + return _URC_NO_REASON; + } + }; + + template size_t unwind(F f, size_t depth) { + Unwinder unwinder; + return unwinder(f, depth); + } + + } // namespace details + + template <> + class StackTraceImpl : public StackTraceImplHolder { + public: + NOINLINE + size_t load_here(size_t depth = 32, void *context = nullptr, + void *error_addr = nullptr) { + load_thread_info(); + set_context(context); + set_error_addr(error_addr); + if (depth == 0) { + return 0; + } + _stacktrace.resize(depth); + size_t trace_cnt = details::unwind(callback(*this), depth); + _stacktrace.resize(trace_cnt); + skip_n_firsts(0); + return size(); + } + size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, + void *error_addr = nullptr) { + load_here(depth + 8, context, error_addr); + + for (size_t i = 0; i < _stacktrace.size(); ++i) { + if (_stacktrace[i] == addr) { + skip_n_firsts(i); + break; + } + } + + _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); + return size(); + } + + private: + struct callback { + StackTraceImpl &self; + callback(StackTraceImpl &_self) : self(_self) {} + + void operator()(size_t idx, void *addr) { self._stacktrace[idx] = addr; } + }; + }; + +#elif BACKWARD_HAS_LIBUNWIND == 1 + + template <> +class StackTraceImpl : public StackTraceImplHolder { +public: + __attribute__((noinline)) size_t load_here(size_t depth = 32, + void *_context = nullptr, + void *_error_addr = nullptr) { + set_context(_context); + set_error_addr(_error_addr); + load_thread_info(); + if (depth == 0) { + return 0; + } + _stacktrace.resize(depth + 1); + + int result = 0; + + unw_context_t ctx; + size_t index = 0; + + // Add the tail call. If the Instruction Pointer is the crash address it + // means we got a bad function pointer dereference, so we "unwind" the + // bad pointer manually by using the return address pointed to by the + // Stack Pointer as the Instruction Pointer and letting libunwind do + // the rest + + if (context()) { + ucontext_t *uctx = reinterpret_cast(context()); +#ifdef REG_RIP // x86_64 + if (uctx->uc_mcontext.gregs[REG_RIP] == + reinterpret_cast(error_addr())) { + uctx->uc_mcontext.gregs[REG_RIP] = + *reinterpret_cast(uctx->uc_mcontext.gregs[REG_RSP]); + } + _stacktrace[index] = + reinterpret_cast(uctx->uc_mcontext.gregs[REG_RIP]); + ++index; + ctx = *reinterpret_cast(uctx); +#elif defined(REG_EIP) // x86_32 + if (uctx->uc_mcontext.gregs[REG_EIP] == + reinterpret_cast(error_addr())) { + uctx->uc_mcontext.gregs[REG_EIP] = + *reinterpret_cast(uctx->uc_mcontext.gregs[REG_ESP]); + } + _stacktrace[index] = + reinterpret_cast(uctx->uc_mcontext.gregs[REG_EIP]); + ++index; + ctx = *reinterpret_cast(uctx); +#elif defined(__arm__) + // libunwind uses its own context type for ARM unwinding. + // Copy the registers from the signal handler's context so we can + // unwind + unw_getcontext(&ctx); + ctx.regs[UNW_ARM_R0] = uctx->uc_mcontext.arm_r0; + ctx.regs[UNW_ARM_R1] = uctx->uc_mcontext.arm_r1; + ctx.regs[UNW_ARM_R2] = uctx->uc_mcontext.arm_r2; + ctx.regs[UNW_ARM_R3] = uctx->uc_mcontext.arm_r3; + ctx.regs[UNW_ARM_R4] = uctx->uc_mcontext.arm_r4; + ctx.regs[UNW_ARM_R5] = uctx->uc_mcontext.arm_r5; + ctx.regs[UNW_ARM_R6] = uctx->uc_mcontext.arm_r6; + ctx.regs[UNW_ARM_R7] = uctx->uc_mcontext.arm_r7; + ctx.regs[UNW_ARM_R8] = uctx->uc_mcontext.arm_r8; + ctx.regs[UNW_ARM_R9] = uctx->uc_mcontext.arm_r9; + ctx.regs[UNW_ARM_R10] = uctx->uc_mcontext.arm_r10; + ctx.regs[UNW_ARM_R11] = uctx->uc_mcontext.arm_fp; + ctx.regs[UNW_ARM_R12] = uctx->uc_mcontext.arm_ip; + ctx.regs[UNW_ARM_R13] = uctx->uc_mcontext.arm_sp; + ctx.regs[UNW_ARM_R14] = uctx->uc_mcontext.arm_lr; + ctx.regs[UNW_ARM_R15] = uctx->uc_mcontext.arm_pc; + + // If we have crashed in the PC use the LR instead, as this was + // a bad function dereference + if (reinterpret_cast(error_addr()) == + uctx->uc_mcontext.arm_pc) { + ctx.regs[UNW_ARM_R15] = + uctx->uc_mcontext.arm_lr - sizeof(unsigned long); + } + _stacktrace[index] = reinterpret_cast(ctx.regs[UNW_ARM_R15]); + ++index; +#elif defined(__APPLE__) && defined(__x86_64__) + unw_getcontext(&ctx); + // OS X's implementation of libunwind uses its own context object + // so we need to convert the passed context to libunwind's format + // (information about the data layout taken from unw_getcontext.s + // in Apple's libunwind source + ctx.data[0] = uctx->uc_mcontext->__ss.__rax; + ctx.data[1] = uctx->uc_mcontext->__ss.__rbx; + ctx.data[2] = uctx->uc_mcontext->__ss.__rcx; + ctx.data[3] = uctx->uc_mcontext->__ss.__rdx; + ctx.data[4] = uctx->uc_mcontext->__ss.__rdi; + ctx.data[5] = uctx->uc_mcontext->__ss.__rsi; + ctx.data[6] = uctx->uc_mcontext->__ss.__rbp; + ctx.data[7] = uctx->uc_mcontext->__ss.__rsp; + ctx.data[8] = uctx->uc_mcontext->__ss.__r8; + ctx.data[9] = uctx->uc_mcontext->__ss.__r9; + ctx.data[10] = uctx->uc_mcontext->__ss.__r10; + ctx.data[11] = uctx->uc_mcontext->__ss.__r11; + ctx.data[12] = uctx->uc_mcontext->__ss.__r12; + ctx.data[13] = uctx->uc_mcontext->__ss.__r13; + ctx.data[14] = uctx->uc_mcontext->__ss.__r14; + ctx.data[15] = uctx->uc_mcontext->__ss.__r15; + ctx.data[16] = uctx->uc_mcontext->__ss.__rip; + + // If the IP is the same as the crash address we have a bad function + // dereference The caller's address is pointed to by %rsp, so we + // dereference that value and set it to be the next frame's IP. + if (uctx->uc_mcontext->__ss.__rip == + reinterpret_cast<__uint64_t>(error_addr())) { + ctx.data[16] = + *reinterpret_cast<__uint64_t *>(uctx->uc_mcontext->__ss.__rsp); + } + _stacktrace[index] = reinterpret_cast(ctx.data[16]); + ++index; +#elif defined(__APPLE__) + unw_getcontext(&ctx) + // TODO: Convert the ucontext_t to libunwind's unw_context_t like + // we do in 64 bits + if (ctx.uc_mcontext->__ss.__eip == + reinterpret_cast(error_addr())) { + ctx.uc_mcontext->__ss.__eip = ctx.uc_mcontext->__ss.__esp; + } + _stacktrace[index] = + reinterpret_cast(ctx.uc_mcontext->__ss.__eip); + ++index; +#endif + } + + unw_cursor_t cursor; + if (context()) { +#if defined(UNW_INIT_SIGNAL_FRAME) + result = unw_init_local2(&cursor, &ctx, UNW_INIT_SIGNAL_FRAME); +#else + result = unw_init_local(&cursor, &ctx); +#endif + } else { + unw_getcontext(&ctx); + ; + result = unw_init_local(&cursor, &ctx); + } + + if (result != 0) + return 1; + + unw_word_t ip = 0; + + while (index <= depth && unw_step(&cursor) > 0) { + result = unw_get_reg(&cursor, UNW_REG_IP, &ip); + if (result == 0) { + _stacktrace[index] = reinterpret_cast(--ip); + ++index; + } + } + --index; + + _stacktrace.resize(index + 1); + skip_n_firsts(0); + return size(); + } + + size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, + void *error_addr = nullptr) { + load_here(depth + 8, context, error_addr); + + for (size_t i = 0; i < _stacktrace.size(); ++i) { + if (_stacktrace[i] == addr) { + skip_n_firsts(i); + _stacktrace[i] = (void *)((uintptr_t)_stacktrace[i]); + break; + } + } + + _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); + return size(); + } +}; + +#elif defined(BACKWARD_HAS_BACKTRACE) + +template <> +class StackTraceImpl : public StackTraceImplHolder { +public: + NOINLINE + size_t load_here(size_t depth = 32, void *context = nullptr, + void *error_addr = nullptr) { + set_context(context); + set_error_addr(error_addr); + load_thread_info(); + if (depth == 0) { + return 0; + } + _stacktrace.resize(depth + 1); + size_t trace_cnt = backtrace(&_stacktrace[0], _stacktrace.size()); + _stacktrace.resize(trace_cnt); + skip_n_firsts(1); + return size(); + } + + size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, + void *error_addr = nullptr) { + load_here(depth + 8, context, error_addr); + + for (size_t i = 0; i < _stacktrace.size(); ++i) { + if (_stacktrace[i] == addr) { + skip_n_firsts(i); + _stacktrace[i] = (void *)((uintptr_t)_stacktrace[i] + 1); + break; + } + } + + _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); + return size(); + } +}; + +#elif defined(BACKWARD_SYSTEM_WINDOWS) + +template <> +class StackTraceImpl : public StackTraceImplHolder { +public: + // We have to load the machine type from the image info + // So we first initialize the resolver, and it tells us this info + void set_machine_type(DWORD machine_type) { machine_type_ = machine_type; } + void set_context(CONTEXT *ctx) { ctx_ = ctx; } + void set_thread_handle(HANDLE handle) { thd_ = handle; } + + NOINLINE + size_t load_here(size_t depth = 32, void *context = nullptr, + void *error_addr = nullptr) { + set_context(static_cast(context)); + set_error_addr(error_addr); + CONTEXT localCtx; // used when no context is provided + + if (depth == 0) { + return 0; + } + + if (!ctx_) { + ctx_ = &localCtx; + RtlCaptureContext(ctx_); + } + + if (!thd_) { + thd_ = GetCurrentThread(); + } + + HANDLE process = GetCurrentProcess(); + + STACKFRAME64 s; + memset(&s, 0, sizeof(STACKFRAME64)); + + // TODO: 32 bit context capture + s.AddrStack.Mode = AddrModeFlat; + s.AddrFrame.Mode = AddrModeFlat; + s.AddrPC.Mode = AddrModeFlat; +#ifdef _M_X64 + s.AddrPC.Offset = ctx_->Rip; + s.AddrStack.Offset = ctx_->Rsp; + s.AddrFrame.Offset = ctx_->Rbp; +#else + s.AddrPC.Offset = ctx_->Eip; + s.AddrStack.Offset = ctx_->Esp; + s.AddrFrame.Offset = ctx_->Ebp; +#endif + + if (!machine_type_) { +#ifdef _M_X64 + machine_type_ = IMAGE_FILE_MACHINE_AMD64; +#else + machine_type_ = IMAGE_FILE_MACHINE_I386; +#endif + } + + for (;;) { + // NOTE: this only works if PDBs are already loaded! + SetLastError(0); + if (!StackWalk64(machine_type_, process, thd_, &s, ctx_, NULL, + SymFunctionTableAccess64, SymGetModuleBase64, NULL)) + break; + + if (s.AddrReturn.Offset == 0) + break; + + _stacktrace.push_back(reinterpret_cast(s.AddrPC.Offset)); + + if (size() >= depth) + break; + } + + return size(); + } + + size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, + void *error_addr = nullptr) { + load_here(depth + 8, context, error_addr); + + for (size_t i = 0; i < _stacktrace.size(); ++i) { + if (_stacktrace[i] == addr) { + skip_n_firsts(i); + break; + } + } + + _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); + return size(); + } + +private: + DWORD machine_type_ = 0; + HANDLE thd_ = 0; + CONTEXT *ctx_ = nullptr; +}; + +#endif + + class StackTrace : public StackTraceImpl {}; + +/*************** TRACE RESOLVER ***************/ + + class TraceResolverImplBase { + public: + virtual ~TraceResolverImplBase() {} + + virtual void load_addresses(void *const*addresses, int address_count) { + (void)addresses; + (void)address_count; + } + + template void load_stacktrace(ST &st) { + load_addresses(st.begin(), static_cast(st.size())); + } + + virtual ResolvedTrace resolve(ResolvedTrace t) { return t; } + + protected: + std::string demangle(const char *funcname) { + return _demangler.demangle(funcname); + } + + private: + details::demangler _demangler; + }; + + template class TraceResolverImpl; + +#ifdef BACKWARD_SYSTEM_UNKNOWN + + template <> class TraceResolverImpl + : public TraceResolverImplBase {}; + +#endif + +#ifdef BACKWARD_SYSTEM_LINUX + + class TraceResolverLinuxBase : public TraceResolverImplBase { + public: + TraceResolverLinuxBase() + : argv0_(get_argv0()), exec_path_(read_symlink("/proc/self/exe")) {} + std::string resolve_exec_path(Dl_info &symbol_info) const { + // mutates symbol_info.dli_fname to be filename to open and returns filename + // to display + if (symbol_info.dli_fname == argv0_) { + // dladdr returns argv[0] in dli_fname for symbols contained in + // the main executable, which is not a valid path if the + // executable was found by a search of the PATH environment + // variable; In that case, we actually open /proc/self/exe, which + // is always the actual executable (even if it was deleted/replaced!) + // but display the path that /proc/self/exe links to. + // However, this right away reduces probability of successful symbol + // resolution, because libbfd may try to find *.debug files in the + // same dir, in case symbols are stripped. As a result, it may try + // to find a file /proc/self/.debug, which obviously does + // not exist. /proc/self/exe is a last resort. First load attempt + // should go for the original executable file path. + symbol_info.dli_fname = "/proc/self/exe"; + return exec_path_; + } else { + return symbol_info.dli_fname; + } + } + + private: + std::string argv0_; + std::string exec_path_; + + static std::string get_argv0() { + std::string argv0; + std::ifstream ifs("/proc/self/cmdline"); + std::getline(ifs, argv0, '\0'); + return argv0; + } + + static std::string read_symlink(std::string const &symlink_path) { + std::string path; + path.resize(100); + + while (true) { + ssize_t len = + ::readlink(symlink_path.c_str(), &*path.begin(), path.size()); + if (len < 0) { + return ""; + } + if (static_cast(len) == path.size()) { + path.resize(path.size() * 2); + } else { + path.resize(static_cast(len)); + break; + } + } + + return path; + } + }; + + template class TraceResolverLinuxImpl; + +#if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 + + template <> + class TraceResolverLinuxImpl + : public TraceResolverLinuxBase { + public: + void load_addresses(void *const*addresses, int address_count) override { + if (address_count == 0) { + return; + } + _symbols.reset(backtrace_symbols(addresses, address_count)); + } + + ResolvedTrace resolve(ResolvedTrace trace) override { + char *filename = _symbols[trace.idx]; + char *funcname = filename; + while (*funcname && *funcname != '(') { + funcname += 1; + } + trace.object_filename.assign(filename, + funcname); // ok even if funcname is the ending + // \0 (then we assign entire string) + + if (*funcname) { // if it's not end of string (e.g. from last frame ip==0) + funcname += 1; + char *funcname_end = funcname; + while (*funcname_end && *funcname_end != ')' && *funcname_end != '+') { + funcname_end += 1; + } + *funcname_end = '\0'; + trace.object_function = this->demangle(funcname); + trace.source.function = trace.object_function; // we cannot do better. + } + return trace; + } + + private: + details::handle _symbols; + }; + +#endif // BACKWARD_HAS_BACKTRACE_SYMBOL == 1 + +#if BACKWARD_HAS_BFD == 1 + + template <> +class TraceResolverLinuxImpl + : public TraceResolverLinuxBase { +public: + TraceResolverLinuxImpl() : _bfd_loaded(false) {} + + ResolvedTrace resolve(ResolvedTrace trace) override { + Dl_info symbol_info; + + // trace.addr is a virtual address in memory pointing to some code. + // Let's try to find from which loaded object it comes from. + // The loaded object can be yourself btw. + if (!dladdr(trace.addr, &symbol_info)) { + return trace; // dat broken trace... + } + + // Now we get in symbol_info: + // .dli_fname: + // pathname of the shared object that contains the address. + // .dli_fbase: + // where the object is loaded in memory. + // .dli_sname: + // the name of the nearest symbol to trace.addr, we expect a + // function name. + // .dli_saddr: + // the exact address corresponding to .dli_sname. + + if (symbol_info.dli_sname) { + trace.object_function = demangle(symbol_info.dli_sname); + } + + if (!symbol_info.dli_fname) { + return trace; + } + + trace.object_filename = resolve_exec_path(symbol_info); + bfd_fileobject *fobj; + // Before rushing to resolution need to ensure the executable + // file still can be used. For that compare inode numbers of + // what is stored by the executable's file path, and in the + // dli_fname, which not necessarily equals to the executable. + // It can be a shared library, or /proc/self/exe, and in the + // latter case has drawbacks. See the exec path resolution for + // details. In short - the dli object should be used only as + // the last resort. + // If inode numbers are equal, it is known dli_fname and the + // executable file are the same. This is guaranteed by Linux, + // because if the executable file is changed/deleted, it will + // be done in a new inode. The old file will be preserved in + // /proc/self/exe, and may even have inode 0. The latter can + // happen if the inode was actually reused, and the file was + // kept only in the main memory. + // + struct stat obj_stat; + struct stat dli_stat; + if (stat(trace.object_filename.c_str(), &obj_stat) == 0 && + stat(symbol_info.dli_fname, &dli_stat) == 0 && + obj_stat.st_ino == dli_stat.st_ino) { + // The executable file, and the shared object containing the + // address are the same file. Safe to use the original path. + // this is preferable. Libbfd will search for stripped debug + // symbols in the same directory. + fobj = load_object_with_bfd(trace.object_filename); + } else{ + // The original object file was *deleted*! The only hope is + // that the debug symbols are either inside the shared + // object file, or are in the same directory, and this is + // not /proc/self/exe. + fobj = nullptr; + } + if (fobj == nullptr || !fobj->handle) { + fobj = load_object_with_bfd(symbol_info.dli_fname); + if (!fobj->handle) { + return trace; + } + } + + find_sym_result *details_selected; // to be filled. + + // trace.addr is the next instruction to be executed after returning + // from the nested stack frame. In C++ this usually relate to the next + // statement right after the function call that leaded to a new stack + // frame. This is not usually what you want to see when printing out a + // stacktrace... + find_sym_result details_call_site = + find_symbol_details(fobj, trace.addr, symbol_info.dli_fbase); + details_selected = &details_call_site; + +#if BACKWARD_HAS_UNWIND == 0 + // ...this is why we also try to resolve the symbol that is right + // before the return address. If we are lucky enough, we will get the + // line of the function that was called. But if the code is optimized, + // we might get something absolutely not related since the compiler + // can reschedule the return address with inline functions and + // tail-call optimization (among other things that I don't even know + // or cannot even dream about with my tiny limited brain). + find_sym_result details_adjusted_call_site = find_symbol_details( + fobj, (void *)(uintptr_t(trace.addr) - 1), symbol_info.dli_fbase); + + // In debug mode, we should always get the right thing(TM). + if (details_call_site.found && details_adjusted_call_site.found) { + // Ok, we assume that details_adjusted_call_site is a better estimation. + details_selected = &details_adjusted_call_site; + trace.addr = (void *)(uintptr_t(trace.addr) - 1); + } + + if (details_selected == &details_call_site && details_call_site.found) { + // we have to re-resolve the symbol in order to reset some + // internal state in BFD... so we can call backtrace_inliners + // thereafter... + details_call_site = + find_symbol_details(fobj, trace.addr, symbol_info.dli_fbase); + } +#endif // BACKWARD_HAS_UNWIND + + if (details_selected->found) { + if (details_selected->filename) { + trace.source.filename = details_selected->filename; + } + trace.source.line = details_selected->line; + + if (details_selected->funcname) { + // this time we get the name of the function where the code is + // located, instead of the function were the address is + // located. In short, if the code was inlined, we get the + // function corresponding to the code. Else we already got in + // trace.function. + trace.source.function = demangle(details_selected->funcname); + + if (!symbol_info.dli_sname) { + // for the case dladdr failed to find the symbol name of + // the function, we might as well try to put something + // here. + trace.object_function = trace.source.function; + } + } + + // Maybe the source of the trace got inlined inside the function + // (trace.source.function). Let's see if we can get all the inlined + // calls along the way up to the initial call site. + trace.inliners = backtrace_inliners(fobj, *details_selected); + +#if 0 + if (trace.inliners.size() == 0) { + // Maybe the trace was not inlined... or maybe it was and we + // are lacking the debug information. Let's try to make the + // world better and see if we can get the line number of the + // function (trace.source.function) now. + // + // We will get the location of where the function start (to be + // exact: the first instruction that really start the + // function), not where the name of the function is defined. + // This can be quite far away from the name of the function + // btw. + // + // If the source of the function is the same as the source of + // the trace, we cannot say if the trace was really inlined or + // not. However, if the filename of the source is different + // between the function and the trace... we can declare it as + // an inliner. This is not 100% accurate, but better than + // nothing. + + if (symbol_info.dli_saddr) { + find_sym_result details = find_symbol_details(fobj, + symbol_info.dli_saddr, + symbol_info.dli_fbase); + + if (details.found) { + ResolvedTrace::SourceLoc diy_inliner; + diy_inliner.line = details.line; + if (details.filename) { + diy_inliner.filename = details.filename; + } + if (details.funcname) { + diy_inliner.function = demangle(details.funcname); + } else { + diy_inliner.function = trace.source.function; + } + if (diy_inliner != trace.source) { + trace.inliners.push_back(diy_inliner); + } + } + } + } +#endif + } + + return trace; + } + +private: + bool _bfd_loaded; + + typedef details::handle > + bfd_handle_t; + + typedef details::handle bfd_symtab_t; + + struct bfd_fileobject { + bfd_handle_t handle; + bfd_vma base_addr; + bfd_symtab_t symtab; + bfd_symtab_t dynamic_symtab; + }; + + typedef details::hashtable::type fobj_bfd_map_t; + fobj_bfd_map_t _fobj_bfd_map; + + bfd_fileobject *load_object_with_bfd(const std::string &filename_object) { + using namespace details; + + if (!_bfd_loaded) { + using namespace details; + bfd_init(); + _bfd_loaded = true; + } + + fobj_bfd_map_t::iterator it = _fobj_bfd_map.find(filename_object); + if (it != _fobj_bfd_map.end()) { + return &it->second; + } + + // this new object is empty for now. + bfd_fileobject *r = &_fobj_bfd_map[filename_object]; + + // we do the work temporary in this one; + bfd_handle_t bfd_handle; + + int fd = open(filename_object.c_str(), O_RDONLY); + bfd_handle.reset(bfd_fdopenr(filename_object.c_str(), "default", fd)); + if (!bfd_handle) { + close(fd); + return r; + } + + if (!bfd_check_format(bfd_handle.get(), bfd_object)) { + return r; // not an object? You lose. + } + + if ((bfd_get_file_flags(bfd_handle.get()) & HAS_SYMS) == 0) { + return r; // that's what happen when you forget to compile in debug. + } + + ssize_t symtab_storage_size = bfd_get_symtab_upper_bound(bfd_handle.get()); + + ssize_t dyn_symtab_storage_size = + bfd_get_dynamic_symtab_upper_bound(bfd_handle.get()); + + if (symtab_storage_size <= 0 && dyn_symtab_storage_size <= 0) { + return r; // weird, is the file is corrupted? + } + + bfd_symtab_t symtab, dynamic_symtab; + ssize_t symcount = 0, dyn_symcount = 0; + + if (symtab_storage_size > 0) { + symtab.reset(static_cast( + malloc(static_cast(symtab_storage_size)))); + symcount = bfd_canonicalize_symtab(bfd_handle.get(), symtab.get()); + } + + if (dyn_symtab_storage_size > 0) { + dynamic_symtab.reset(static_cast( + malloc(static_cast(dyn_symtab_storage_size)))); + dyn_symcount = bfd_canonicalize_dynamic_symtab(bfd_handle.get(), + dynamic_symtab.get()); + } + + if (symcount <= 0 && dyn_symcount <= 0) { + return r; // damned, that's a stripped file that you got there! + } + + r->handle = move(bfd_handle); + r->symtab = move(symtab); + r->dynamic_symtab = move(dynamic_symtab); + return r; + } + + struct find_sym_result { + bool found; + const char *filename; + const char *funcname; + unsigned int line; + }; + + struct find_sym_context { + TraceResolverLinuxImpl *self; + bfd_fileobject *fobj; + void *addr; + void *base_addr; + find_sym_result result; + }; + + find_sym_result find_symbol_details(bfd_fileobject *fobj, void *addr, + void *base_addr) { + find_sym_context context; + context.self = this; + context.fobj = fobj; + context.addr = addr; + context.base_addr = base_addr; + context.result.found = false; + bfd_map_over_sections(fobj->handle.get(), &find_in_section_trampoline, + static_cast(&context)); + return context.result; + } + + static void find_in_section_trampoline(bfd *, asection *section, void *data) { + find_sym_context *context = static_cast(data); + context->self->find_in_section( + reinterpret_cast(context->addr), + reinterpret_cast(context->base_addr), context->fobj, section, + context->result); + } + + void find_in_section(bfd_vma addr, bfd_vma base_addr, bfd_fileobject *fobj, + asection *section, find_sym_result &result) { + if (result.found) + return; + +#ifdef bfd_get_section_flags + if ((bfd_get_section_flags(fobj->handle.get(), section) & SEC_ALLOC) == 0) +#else + if ((bfd_section_flags(section) & SEC_ALLOC) == 0) +#endif + return; // a debug section is never loaded automatically. + +#ifdef bfd_get_section_vma + bfd_vma sec_addr = bfd_get_section_vma(fobj->handle.get(), section); +#else + bfd_vma sec_addr = bfd_section_vma(section); +#endif +#ifdef bfd_get_section_size + bfd_size_type size = bfd_get_section_size(section); +#else + bfd_size_type size = bfd_section_size(section); +#endif + + // are we in the boundaries of the section? + if (addr < sec_addr || addr >= sec_addr + size) { + addr -= base_addr; // oops, a relocated object, lets try again... + if (addr < sec_addr || addr >= sec_addr + size) { + return; + } + } + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + if (!result.found && fobj->symtab) { + result.found = bfd_find_nearest_line( + fobj->handle.get(), section, fobj->symtab.get(), addr - sec_addr, + &result.filename, &result.funcname, &result.line); + } + + if (!result.found && fobj->dynamic_symtab) { + result.found = bfd_find_nearest_line( + fobj->handle.get(), section, fobj->dynamic_symtab.get(), + addr - sec_addr, &result.filename, &result.funcname, &result.line); + } +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + } + + ResolvedTrace::source_locs_t + backtrace_inliners(bfd_fileobject *fobj, find_sym_result previous_result) { + // This function can be called ONLY after a SUCCESSFUL call to + // find_symbol_details. The state is global to the bfd_handle. + ResolvedTrace::source_locs_t results; + while (previous_result.found) { + find_sym_result result; + result.found = bfd_find_inliner_info(fobj->handle.get(), &result.filename, + &result.funcname, &result.line); + + if (result + .found) /* and not ( + cstrings_eq(previous_result.filename, + result.filename) and + cstrings_eq(previous_result.funcname, result.funcname) + and result.line == previous_result.line + )) */ + { + ResolvedTrace::SourceLoc src_loc; + src_loc.line = result.line; + if (result.filename) { + src_loc.filename = result.filename; + } + if (result.funcname) { + src_loc.function = demangle(result.funcname); + } + results.push_back(src_loc); + } + previous_result = result; + } + return results; + } + + bool cstrings_eq(const char *a, const char *b) { + if (!a || !b) { + return false; + } + return strcmp(a, b) == 0; + } +}; +#endif // BACKWARD_HAS_BFD == 1 + +#if BACKWARD_HAS_DW == 1 + + template <> +class TraceResolverLinuxImpl + : public TraceResolverLinuxBase { +public: + TraceResolverLinuxImpl() : _dwfl_handle_initialized(false) {} + + ResolvedTrace resolve(ResolvedTrace trace) override { + using namespace details; + + Dwarf_Addr trace_addr = reinterpret_cast(trace.addr); + + if (!_dwfl_handle_initialized) { + // initialize dwfl... + _dwfl_cb.reset(new Dwfl_Callbacks); + _dwfl_cb->find_elf = &dwfl_linux_proc_find_elf; + _dwfl_cb->find_debuginfo = &dwfl_standard_find_debuginfo; + _dwfl_cb->debuginfo_path = 0; + + _dwfl_handle.reset(dwfl_begin(_dwfl_cb.get())); + _dwfl_handle_initialized = true; + + if (!_dwfl_handle) { + return trace; + } + + // ...from the current process. + dwfl_report_begin(_dwfl_handle.get()); + int r = dwfl_linux_proc_report(_dwfl_handle.get(), getpid()); + dwfl_report_end(_dwfl_handle.get(), NULL, NULL); + if (r < 0) { + return trace; + } + } + + if (!_dwfl_handle) { + return trace; + } + + // find the module (binary object) that contains the trace's address. + // This is not using any debug information, but the addresses ranges of + // all the currently loaded binary object. + Dwfl_Module *mod = dwfl_addrmodule(_dwfl_handle.get(), trace_addr); + if (mod) { + // now that we found it, lets get the name of it, this will be the + // full path to the running binary or one of the loaded library. + const char *module_name = dwfl_module_info(mod, 0, 0, 0, 0, 0, 0, 0); + if (module_name) { + trace.object_filename = module_name; + } + // We also look after the name of the symbol, equal or before this + // address. This is found by walking the symtab. We should get the + // symbol corresponding to the function (mangled) containing the + // address. If the code corresponding to the address was inlined, + // this is the name of the out-most inliner function. + const char *sym_name = dwfl_module_addrname(mod, trace_addr); + if (sym_name) { + trace.object_function = demangle(sym_name); + } + } + + // now let's get serious, and find out the source location (file and + // line number) of the address. + + // This function will look in .debug_aranges for the address and map it + // to the location of the compilation unit DIE in .debug_info and + // return it. + Dwarf_Addr mod_bias = 0; + Dwarf_Die *cudie = dwfl_module_addrdie(mod, trace_addr, &mod_bias); + +#if 1 + if (!cudie) { + // Sadly clang does not generate the section .debug_aranges, thus + // dwfl_module_addrdie will fail early. Clang doesn't either set + // the lowpc/highpc/range info for every compilation unit. + // + // So in order to save the world: + // for every compilation unit, we will iterate over every single + // DIEs. Normally functions should have a lowpc/highpc/range, which + // we will use to infer the compilation unit. + + // note that this is probably badly inefficient. + while ((cudie = dwfl_module_nextcu(mod, cudie, &mod_bias))) { + Dwarf_Die die_mem; + Dwarf_Die *fundie = + find_fundie_by_pc(cudie, trace_addr - mod_bias, &die_mem); + if (fundie) { + break; + } + } + } +#endif + +//#define BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE +#ifdef BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE + if (!cudie) { + // If it's still not enough, lets dive deeper in the shit, and try + // to save the world again: for every compilation unit, we will + // load the corresponding .debug_line section, and see if we can + // find our address in it. + + Dwarf_Addr cfi_bias; + Dwarf_CFI *cfi_cache = dwfl_module_eh_cfi(mod, &cfi_bias); + + Dwarf_Addr bias; + while ((cudie = dwfl_module_nextcu(mod, cudie, &bias))) { + if (dwarf_getsrc_die(cudie, trace_addr - bias)) { + + // ...but if we get a match, it might be a false positive + // because our (address - bias) might as well be valid in a + // different compilation unit. So we throw our last card on + // the table and lookup for the address into the .eh_frame + // section. + + handle frame; + dwarf_cfi_addrframe(cfi_cache, trace_addr - cfi_bias, &frame); + if (frame) { + break; + } + } + } + } +#endif + + if (!cudie) { + return trace; // this time we lost the game :/ + } + + // Now that we have a compilation unit DIE, this function will be able + // to load the corresponding section in .debug_line (if not already + // loaded) and hopefully find the source location mapped to our + // address. + Dwarf_Line *srcloc = dwarf_getsrc_die(cudie, trace_addr - mod_bias); + + if (srcloc) { + const char *srcfile = dwarf_linesrc(srcloc, 0, 0); + if (srcfile) { + trace.source.filename = srcfile; + } + int line = 0, col = 0; + dwarf_lineno(srcloc, &line); + dwarf_linecol(srcloc, &col); + trace.source.line = static_cast(line); + trace.source.col = static_cast(col); + } + + deep_first_search_by_pc(cudie, trace_addr - mod_bias, + inliners_search_cb(trace)); + if (trace.source.function.size() == 0) { + // fallback. + trace.source.function = trace.object_function; + } + + return trace; + } + +private: + typedef details::handle > + dwfl_handle_t; + details::handle > + _dwfl_cb; + dwfl_handle_t _dwfl_handle; + bool _dwfl_handle_initialized; + + // defined here because in C++98, template function cannot take locally + // defined types... grrr. + struct inliners_search_cb { + void operator()(Dwarf_Die *die) { + switch (dwarf_tag(die)) { + const char *name; + case DW_TAG_subprogram: + if ((name = dwarf_diename(die))) { + trace.source.function = name; + } + break; + + case DW_TAG_inlined_subroutine: + ResolvedTrace::SourceLoc sloc; + Dwarf_Attribute attr_mem; + + if ((name = dwarf_diename(die))) { + sloc.function = name; + } + if ((name = die_call_file(die))) { + sloc.filename = name; + } + + Dwarf_Word line = 0, col = 0; + dwarf_formudata(dwarf_attr(die, DW_AT_call_line, &attr_mem), &line); + dwarf_formudata(dwarf_attr(die, DW_AT_call_column, &attr_mem), &col); + sloc.line = static_cast(line); + sloc.col = static_cast(col); + + trace.inliners.push_back(sloc); + break; + }; + } + ResolvedTrace &trace; + inliners_search_cb(ResolvedTrace &t) : trace(t) {} + }; + + static bool die_has_pc(Dwarf_Die *die, Dwarf_Addr pc) { + Dwarf_Addr low, high; + + // continuous range + if (dwarf_hasattr(die, DW_AT_low_pc) && dwarf_hasattr(die, DW_AT_high_pc)) { + if (dwarf_lowpc(die, &low) != 0) { + return false; + } + if (dwarf_highpc(die, &high) != 0) { + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = dwarf_attr(die, DW_AT_high_pc, &attr_mem); + Dwarf_Word value; + if (dwarf_formudata(attr, &value) != 0) { + return false; + } + high = low + value; + } + return pc >= low && pc < high; + } + + // non-continuous range. + Dwarf_Addr base; + ptrdiff_t offset = 0; + while ((offset = dwarf_ranges(die, offset, &base, &low, &high)) > 0) { + if (pc >= low && pc < high) { + return true; + } + } + return false; + } + + static Dwarf_Die *find_fundie_by_pc(Dwarf_Die *parent_die, Dwarf_Addr pc, + Dwarf_Die *result) { + if (dwarf_child(parent_die, result) != 0) { + return 0; + } + + Dwarf_Die *die = result; + do { + switch (dwarf_tag(die)) { + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: + if (die_has_pc(die, pc)) { + return result; + } + }; + bool declaration = false; + Dwarf_Attribute attr_mem; + dwarf_formflag(dwarf_attr(die, DW_AT_declaration, &attr_mem), + &declaration); + if (!declaration) { + // let's be curious and look deeper in the tree, + // function are not necessarily at the first level, but + // might be nested inside a namespace, structure etc. + Dwarf_Die die_mem; + Dwarf_Die *indie = find_fundie_by_pc(die, pc, &die_mem); + if (indie) { + *result = die_mem; + return result; + } + } + } while (dwarf_siblingof(die, result) == 0); + return 0; + } + + template + static bool deep_first_search_by_pc(Dwarf_Die *parent_die, Dwarf_Addr pc, + CB cb) { + Dwarf_Die die_mem; + if (dwarf_child(parent_die, &die_mem) != 0) { + return false; + } + + bool branch_has_pc = false; + Dwarf_Die *die = &die_mem; + do { + bool declaration = false; + Dwarf_Attribute attr_mem; + dwarf_formflag(dwarf_attr(die, DW_AT_declaration, &attr_mem), + &declaration); + if (!declaration) { + // let's be curious and look deeper in the tree, function are + // not necessarily at the first level, but might be nested + // inside a namespace, structure, a function, an inlined + // function etc. + branch_has_pc = deep_first_search_by_pc(die, pc, cb); + } + if (!branch_has_pc) { + branch_has_pc = die_has_pc(die, pc); + } + if (branch_has_pc) { + cb(die); + } + } while (dwarf_siblingof(die, &die_mem) == 0); + return branch_has_pc; + } + + static const char *die_call_file(Dwarf_Die *die) { + Dwarf_Attribute attr_mem; + Dwarf_Word file_idx = 0; + + dwarf_formudata(dwarf_attr(die, DW_AT_call_file, &attr_mem), &file_idx); + + if (file_idx == 0) { + return 0; + } + + Dwarf_Die die_mem; + Dwarf_Die *cudie = dwarf_diecu(die, &die_mem, 0, 0); + if (!cudie) { + return 0; + } + + Dwarf_Files *files = 0; + size_t nfiles; + dwarf_getsrcfiles(cudie, &files, &nfiles); + if (!files) { + return 0; + } + + return dwarf_filesrc(files, file_idx, 0, 0); + } +}; +#endif // BACKWARD_HAS_DW == 1 + +#if BACKWARD_HAS_DWARF == 1 + + template <> +class TraceResolverLinuxImpl + : public TraceResolverLinuxBase { +public: + TraceResolverLinuxImpl() : _dwarf_loaded(false) {} + + ResolvedTrace resolve(ResolvedTrace trace) override { + // trace.addr is a virtual address in memory pointing to some code. + // Let's try to find from which loaded object it comes from. + // The loaded object can be yourself btw. + + Dl_info symbol_info; + int dladdr_result = 0; +#if defined(__GLIBC__) + link_map *link_map; + // We request the link map so we can get information about offsets + dladdr_result = + dladdr1(trace.addr, &symbol_info, reinterpret_cast(&link_map), + RTLD_DL_LINKMAP); +#else + // Android doesn't have dladdr1. Don't use the linker map. + dladdr_result = dladdr(trace.addr, &symbol_info); +#endif + if (!dladdr_result) { + return trace; // dat broken trace... + } + + // Now we get in symbol_info: + // .dli_fname: + // pathname of the shared object that contains the address. + // .dli_fbase: + // where the object is loaded in memory. + // .dli_sname: + // the name of the nearest symbol to trace.addr, we expect a + // function name. + // .dli_saddr: + // the exact address corresponding to .dli_sname. + // + // And in link_map: + // .l_addr: + // difference between the address in the ELF file and the address + // in memory + // l_name: + // absolute pathname where the object was found + + if (symbol_info.dli_sname) { + trace.object_function = demangle(symbol_info.dli_sname); + } + + if (!symbol_info.dli_fname) { + return trace; + } + + trace.object_filename = resolve_exec_path(symbol_info); + dwarf_fileobject &fobj = load_object_with_dwarf(symbol_info.dli_fname); + if (!fobj.dwarf_handle) { + return trace; // sad, we couldn't load the object :( + } + +#if defined(__GLIBC__) + // Convert the address to a module relative one by looking at + // the module's loading address in the link map + Dwarf_Addr address = reinterpret_cast(trace.addr) - + reinterpret_cast(link_map->l_addr); +#else + Dwarf_Addr address = reinterpret_cast(trace.addr); +#endif + + if (trace.object_function.empty()) { + symbol_cache_t::iterator it = fobj.symbol_cache.lower_bound(address); + + if (it != fobj.symbol_cache.end()) { + if (it->first != address) { + if (it != fobj.symbol_cache.begin()) { + --it; + } + } + trace.object_function = demangle(it->second.c_str()); + } + } + + // Get the Compilation Unit DIE for the address + Dwarf_Die die = find_die(fobj, address); + + if (!die) { + return trace; // this time we lost the game :/ + } + + // libdwarf doesn't give us direct access to its objects, it always + // allocates a copy for the caller. We keep that copy alive in a cache + // and we deallocate it later when it's no longer required. + die_cache_entry &die_object = get_die_cache(fobj, die); + if (die_object.isEmpty()) + return trace; // We have no line section for this DIE + + die_linemap_t::iterator it = die_object.line_section.lower_bound(address); + + if (it != die_object.line_section.end()) { + if (it->first != address) { + if (it == die_object.line_section.begin()) { + // If we are on the first item of the line section + // but the address does not match it means that + // the address is below the range of the DIE. Give up. + return trace; + } else { + --it; + } + } + } else { + return trace; // We didn't find the address. + } + + // Get the Dwarf_Line that the address points to and call libdwarf + // to get source file, line and column info. + Dwarf_Line line = die_object.line_buffer[it->second]; + Dwarf_Error error = DW_DLE_NE; + + char *filename; + if (dwarf_linesrc(line, &filename, &error) == DW_DLV_OK) { + trace.source.filename = std::string(filename); + dwarf_dealloc(fobj.dwarf_handle.get(), filename, DW_DLA_STRING); + } + + Dwarf_Unsigned number = 0; + if (dwarf_lineno(line, &number, &error) == DW_DLV_OK) { + trace.source.line = number; + } else { + trace.source.line = 0; + } + + if (dwarf_lineoff_b(line, &number, &error) == DW_DLV_OK) { + trace.source.col = number; + } else { + trace.source.col = 0; + } + + std::vector namespace_stack; + deep_first_search_by_pc(fobj, die, address, namespace_stack, + inliners_search_cb(trace, fobj, die)); + + dwarf_dealloc(fobj.dwarf_handle.get(), die, DW_DLA_DIE); + + return trace; + } + +public: + static int close_dwarf(Dwarf_Debug dwarf) { + return dwarf_finish(dwarf, NULL); + } + +private: + bool _dwarf_loaded; + + typedef details::handle > + dwarf_file_t; + + typedef details::handle > + dwarf_elf_t; + + typedef details::handle > + dwarf_handle_t; + + typedef std::map die_linemap_t; + + typedef std::map die_specmap_t; + + struct die_cache_entry { + die_specmap_t spec_section; + die_linemap_t line_section; + Dwarf_Line *line_buffer; + Dwarf_Signed line_count; + Dwarf_Line_Context line_context; + + inline bool isEmpty() { + return line_buffer == NULL || line_count == 0 || line_context == NULL || + line_section.empty(); + } + + die_cache_entry() : line_buffer(0), line_count(0), line_context(0) {} + + ~die_cache_entry() { + if (line_context) { + dwarf_srclines_dealloc_b(line_context); + } + } + }; + + typedef std::map die_cache_t; + + typedef std::map symbol_cache_t; + + struct dwarf_fileobject { + dwarf_file_t file_handle; + dwarf_elf_t elf_handle; + dwarf_handle_t dwarf_handle; + symbol_cache_t symbol_cache; + + // Die cache + die_cache_t die_cache; + die_cache_entry *current_cu; + }; + + typedef details::hashtable::type + fobj_dwarf_map_t; + fobj_dwarf_map_t _fobj_dwarf_map; + + static bool cstrings_eq(const char *a, const char *b) { + if (!a || !b) { + return false; + } + return strcmp(a, b) == 0; + } + + dwarf_fileobject &load_object_with_dwarf(const std::string &filename_object) { + + if (!_dwarf_loaded) { + // Set the ELF library operating version + // If that fails there's nothing we can do + _dwarf_loaded = elf_version(EV_CURRENT) != EV_NONE; + } + + fobj_dwarf_map_t::iterator it = _fobj_dwarf_map.find(filename_object); + if (it != _fobj_dwarf_map.end()) { + return it->second; + } + + // this new object is empty for now + dwarf_fileobject &r = _fobj_dwarf_map[filename_object]; + + dwarf_file_t file_handle; + file_handle.reset(open(filename_object.c_str(), O_RDONLY)); + if (file_handle.get() < 0) { + return r; + } + + // Try to get an ELF handle. We need to read the ELF sections + // because we want to see if there is a .gnu_debuglink section + // that points to a split debug file + dwarf_elf_t elf_handle; + elf_handle.reset(elf_begin(file_handle.get(), ELF_C_READ, NULL)); + if (!elf_handle) { + return r; + } + + const char *e_ident = elf_getident(elf_handle.get(), 0); + if (!e_ident) { + return r; + } + + // Get the number of sections + // We use the new APIs as elf_getshnum is deprecated + size_t shdrnum = 0; + if (elf_getshdrnum(elf_handle.get(), &shdrnum) == -1) { + return r; + } + + // Get the index to the string section + size_t shdrstrndx = 0; + if (elf_getshdrstrndx(elf_handle.get(), &shdrstrndx) == -1) { + return r; + } + + std::string debuglink; + // Iterate through the ELF sections to try to get a gnu_debuglink + // note and also to cache the symbol table. + // We go the preprocessor way to avoid having to create templated + // classes or using gelf (which might throw a compiler error if 64 bit + // is not supported +#define ELF_GET_DATA(ARCH) \ + Elf_Scn *elf_section = 0; \ + Elf_Data *elf_data = 0; \ + Elf##ARCH##_Shdr *section_header = 0; \ + Elf_Scn *symbol_section = 0; \ + size_t symbol_count = 0; \ + size_t symbol_strings = 0; \ + Elf##ARCH##_Sym *symbol = 0; \ + const char *section_name = 0; \ + \ + while ((elf_section = elf_nextscn(elf_handle.get(), elf_section)) != NULL) { \ + section_header = elf##ARCH##_getshdr(elf_section); \ + if (section_header == NULL) { \ + return r; \ + } \ + \ + if ((section_name = elf_strptr(elf_handle.get(), shdrstrndx, \ + section_header->sh_name)) == NULL) { \ + return r; \ + } \ + \ + if (cstrings_eq(section_name, ".gnu_debuglink")) { \ + elf_data = elf_getdata(elf_section, NULL); \ + if (elf_data && elf_data->d_size > 0) { \ + debuglink = \ + std::string(reinterpret_cast(elf_data->d_buf)); \ + } \ + } \ + \ + switch (section_header->sh_type) { \ + case SHT_SYMTAB: \ + symbol_section = elf_section; \ + symbol_count = section_header->sh_size / section_header->sh_entsize; \ + symbol_strings = section_header->sh_link; \ + break; \ + \ + /* We use .dynsyms as a last resort, we prefer .symtab */ \ + case SHT_DYNSYM: \ + if (!symbol_section) { \ + symbol_section = elf_section; \ + symbol_count = section_header->sh_size / section_header->sh_entsize; \ + symbol_strings = section_header->sh_link; \ + } \ + break; \ + } \ + } \ + \ + if (symbol_section && symbol_count && symbol_strings) { \ + elf_data = elf_getdata(symbol_section, NULL); \ + symbol = reinterpret_cast(elf_data->d_buf); \ + for (size_t i = 0; i < symbol_count; ++i) { \ + int type = ELF##ARCH##_ST_TYPE(symbol->st_info); \ + if (type == STT_FUNC && symbol->st_value > 0) { \ + r.symbol_cache[symbol->st_value] = std::string( \ + elf_strptr(elf_handle.get(), symbol_strings, symbol->st_name)); \ + } \ + ++symbol; \ + } \ + } + + if (e_ident[EI_CLASS] == ELFCLASS32) { + ELF_GET_DATA(32) + } else if (e_ident[EI_CLASS] == ELFCLASS64) { + // libelf might have been built without 64 bit support +#if __LIBELF64 + ELF_GET_DATA(64) +#endif + } + + if (!debuglink.empty()) { + // We have a debuglink section! Open an elf instance on that + // file instead. If we can't open the file, then return + // the elf handle we had already opened. + dwarf_file_t debuglink_file; + debuglink_file.reset(open(debuglink.c_str(), O_RDONLY)); + if (debuglink_file.get() > 0) { + dwarf_elf_t debuglink_elf; + debuglink_elf.reset(elf_begin(debuglink_file.get(), ELF_C_READ, NULL)); + + // If we have a valid elf handle, return the new elf handle + // and file handle and discard the original ones + if (debuglink_elf) { + elf_handle = move(debuglink_elf); + file_handle = move(debuglink_file); + } + } + } + + // Ok, we have a valid ELF handle, let's try to get debug symbols + Dwarf_Debug dwarf_debug; + Dwarf_Error error = DW_DLE_NE; + dwarf_handle_t dwarf_handle; + + int dwarf_result = dwarf_elf_init(elf_handle.get(), DW_DLC_READ, NULL, NULL, + &dwarf_debug, &error); + + // We don't do any special handling for DW_DLV_NO_ENTRY specially. + // If we get an error, or the file doesn't have debug information + // we just return. + if (dwarf_result != DW_DLV_OK) { + return r; + } + + dwarf_handle.reset(dwarf_debug); + + r.file_handle = move(file_handle); + r.elf_handle = move(elf_handle); + r.dwarf_handle = move(dwarf_handle); + + return r; + } + + die_cache_entry &get_die_cache(dwarf_fileobject &fobj, Dwarf_Die die) { + Dwarf_Error error = DW_DLE_NE; + + // Get the die offset, we use it as the cache key + Dwarf_Off die_offset; + if (dwarf_dieoffset(die, &die_offset, &error) != DW_DLV_OK) { + die_offset = 0; + } + + die_cache_t::iterator it = fobj.die_cache.find(die_offset); + + if (it != fobj.die_cache.end()) { + fobj.current_cu = &it->second; + return it->second; + } + + die_cache_entry &de = fobj.die_cache[die_offset]; + fobj.current_cu = &de; + + Dwarf_Addr line_addr; + Dwarf_Small table_count; + + // The addresses in the line section are not fully sorted (they might + // be sorted by block of code belonging to the same file), which makes + // it necessary to do so before searching is possible. + // + // As libdwarf allocates a copy of everything, let's get the contents + // of the line section and keep it around. We also create a map of + // program counter to line table indices so we can search by address + // and get the line buffer index. + // + // To make things more difficult, the same address can span more than + // one line, so we need to keep the index pointing to the first line + // by using insert instead of the map's [ operator. + + // Get the line context for the DIE + if (dwarf_srclines_b(die, 0, &table_count, &de.line_context, &error) == + DW_DLV_OK) { + // Get the source lines for this line context, to be deallocated + // later + if (dwarf_srclines_from_linecontext(de.line_context, &de.line_buffer, + &de.line_count, + &error) == DW_DLV_OK) { + + // Add all the addresses to our map + for (int i = 0; i < de.line_count; i++) { + if (dwarf_lineaddr(de.line_buffer[i], &line_addr, &error) != + DW_DLV_OK) { + line_addr = 0; + } + de.line_section.insert(std::pair(line_addr, i)); + } + } + } + + // For each CU, cache the function DIEs that contain the + // DW_AT_specification attribute. When building with -g3 the function + // DIEs are separated in declaration and specification, with the + // declaration containing only the name and parameters and the + // specification the low/high pc and other compiler attributes. + // + // We cache those specifications so we don't skip over the declarations, + // because they have no pc, and we can do namespace resolution for + // DWARF function names. + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + Dwarf_Die current_die = 0; + if (dwarf_child(die, ¤t_die, &error) == DW_DLV_OK) { + for (;;) { + Dwarf_Die sibling_die = 0; + + Dwarf_Half tag_value; + dwarf_tag(current_die, &tag_value, &error); + + if (tag_value == DW_TAG_subprogram || + tag_value == DW_TAG_inlined_subroutine) { + + Dwarf_Bool has_attr = 0; + if (dwarf_hasattr(current_die, DW_AT_specification, &has_attr, + &error) == DW_DLV_OK) { + if (has_attr) { + Dwarf_Attribute attr_mem; + if (dwarf_attr(current_die, DW_AT_specification, &attr_mem, + &error) == DW_DLV_OK) { + Dwarf_Off spec_offset = 0; + if (dwarf_formref(attr_mem, &spec_offset, &error) == + DW_DLV_OK) { + Dwarf_Off spec_die_offset; + if (dwarf_dieoffset(current_die, &spec_die_offset, &error) == + DW_DLV_OK) { + de.spec_section[spec_offset] = spec_die_offset; + } + } + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + } + } + + int result = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); + if (result == DW_DLV_ERROR) { + break; + } else if (result == DW_DLV_NO_ENTRY) { + break; + } + + if (current_die != die) { + dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); + current_die = 0; + } + + current_die = sibling_die; + } + } + return de; + } + + static Dwarf_Die get_referenced_die(Dwarf_Debug dwarf, Dwarf_Die die, + Dwarf_Half attr, bool global) { + Dwarf_Error error = DW_DLE_NE; + Dwarf_Attribute attr_mem; + + Dwarf_Die found_die = NULL; + if (dwarf_attr(die, attr, &attr_mem, &error) == DW_DLV_OK) { + Dwarf_Off offset; + int result = 0; + if (global) { + result = dwarf_global_formref(attr_mem, &offset, &error); + } else { + result = dwarf_formref(attr_mem, &offset, &error); + } + + if (result == DW_DLV_OK) { + if (dwarf_offdie(dwarf, offset, &found_die, &error) != DW_DLV_OK) { + found_die = NULL; + } + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + return found_die; + } + + static std::string get_referenced_die_name(Dwarf_Debug dwarf, Dwarf_Die die, + Dwarf_Half attr, bool global) { + Dwarf_Error error = DW_DLE_NE; + std::string value; + + Dwarf_Die found_die = get_referenced_die(dwarf, die, attr, global); + + if (found_die) { + char *name; + if (dwarf_diename(found_die, &name, &error) == DW_DLV_OK) { + if (name) { + value = std::string(name); + } + dwarf_dealloc(dwarf, name, DW_DLA_STRING); + } + dwarf_dealloc(dwarf, found_die, DW_DLA_DIE); + } + + return value; + } + + // Returns a spec DIE linked to the passed one. The caller should + // deallocate the DIE + static Dwarf_Die get_spec_die(dwarf_fileobject &fobj, Dwarf_Die die) { + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + Dwarf_Error error = DW_DLE_NE; + Dwarf_Off die_offset; + if (fobj.current_cu && + dwarf_die_CU_offset(die, &die_offset, &error) == DW_DLV_OK) { + die_specmap_t::iterator it = + fobj.current_cu->spec_section.find(die_offset); + + // If we have a DIE that completes the current one, check if + // that one has the pc we are looking for + if (it != fobj.current_cu->spec_section.end()) { + Dwarf_Die spec_die = 0; + if (dwarf_offdie(dwarf, it->second, &spec_die, &error) == DW_DLV_OK) { + return spec_die; + } + } + } + + // Maybe we have an abstract origin DIE with the function information? + return get_referenced_die(fobj.dwarf_handle.get(), die, + DW_AT_abstract_origin, true); + } + + static bool die_has_pc(dwarf_fileobject &fobj, Dwarf_Die die, Dwarf_Addr pc) { + Dwarf_Addr low_pc = 0, high_pc = 0; + Dwarf_Half high_pc_form = 0; + Dwarf_Form_Class return_class; + Dwarf_Error error = DW_DLE_NE; + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + bool has_lowpc = false; + bool has_highpc = false; + bool has_ranges = false; + + if (dwarf_lowpc(die, &low_pc, &error) == DW_DLV_OK) { + // If we have a low_pc check if there is a high pc. + // If we don't have a high pc this might mean we have a base + // address for the ranges list or just an address. + has_lowpc = true; + + if (dwarf_highpc_b(die, &high_pc, &high_pc_form, &return_class, &error) == + DW_DLV_OK) { + // We do have a high pc. In DWARF 4+ this is an offset from the + // low pc, but in earlier versions it's an absolute address. + + has_highpc = true; + // In DWARF 2/3 this would be a DW_FORM_CLASS_ADDRESS + if (return_class == DW_FORM_CLASS_CONSTANT) { + high_pc = low_pc + high_pc; + } + + // We have low and high pc, check if our address + // is in that range + return pc >= low_pc && pc < high_pc; + } + } else { + // Reset the low_pc, in case dwarf_lowpc failing set it to some + // undefined value. + low_pc = 0; + } + + // Check if DW_AT_ranges is present and search for the PC in the + // returned ranges list. We always add the low_pc, as it not set it will + // be 0, in case we had a DW_AT_low_pc and DW_AT_ranges pair + bool result = false; + + Dwarf_Attribute attr; + if (dwarf_attr(die, DW_AT_ranges, &attr, &error) == DW_DLV_OK) { + + Dwarf_Off offset; + if (dwarf_global_formref(attr, &offset, &error) == DW_DLV_OK) { + Dwarf_Ranges *ranges; + Dwarf_Signed ranges_count = 0; + Dwarf_Unsigned byte_count = 0; + + if (dwarf_get_ranges_a(dwarf, offset, die, &ranges, &ranges_count, + &byte_count, &error) == DW_DLV_OK) { + has_ranges = ranges_count != 0; + for (int i = 0; i < ranges_count; i++) { + if (ranges[i].dwr_addr1 != 0 && + pc >= ranges[i].dwr_addr1 + low_pc && + pc < ranges[i].dwr_addr2 + low_pc) { + result = true; + break; + } + } + dwarf_ranges_dealloc(dwarf, ranges, ranges_count); + } + } + } + + // Last attempt. We might have a single address set as low_pc. + if (!result && low_pc != 0 && pc == low_pc) { + result = true; + } + + // If we don't have lowpc, highpc and ranges maybe this DIE is a + // declaration that relies on a DW_AT_specification DIE that happens + // later. Use the specification cache we filled when we loaded this CU. + if (!result && (!has_lowpc && !has_highpc && !has_ranges)) { + Dwarf_Die spec_die = get_spec_die(fobj, die); + if (spec_die) { + result = die_has_pc(fobj, spec_die, pc); + dwarf_dealloc(dwarf, spec_die, DW_DLA_DIE); + } + } + + return result; + } + + static void get_type(Dwarf_Debug dwarf, Dwarf_Die die, std::string &type) { + Dwarf_Error error = DW_DLE_NE; + + Dwarf_Die child = 0; + if (dwarf_child(die, &child, &error) == DW_DLV_OK) { + get_type(dwarf, child, type); + } + + if (child) { + type.insert(0, "::"); + dwarf_dealloc(dwarf, child, DW_DLA_DIE); + } + + char *name; + if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { + type.insert(0, std::string(name)); + dwarf_dealloc(dwarf, name, DW_DLA_STRING); + } else { + type.insert(0, ""); + } + } + + static std::string get_type_by_signature(Dwarf_Debug dwarf, Dwarf_Die die) { + Dwarf_Error error = DW_DLE_NE; + + Dwarf_Sig8 signature; + Dwarf_Bool has_attr = 0; + if (dwarf_hasattr(die, DW_AT_signature, &has_attr, &error) == DW_DLV_OK) { + if (has_attr) { + Dwarf_Attribute attr_mem; + if (dwarf_attr(die, DW_AT_signature, &attr_mem, &error) == DW_DLV_OK) { + if (dwarf_formsig8(attr_mem, &signature, &error) != DW_DLV_OK) { + return std::string(""); + } + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + } + + Dwarf_Unsigned next_cu_header; + Dwarf_Sig8 tu_signature; + std::string result; + bool found = false; + + while (dwarf_next_cu_header_d(dwarf, 0, 0, 0, 0, 0, 0, 0, &tu_signature, 0, + &next_cu_header, 0, &error) == DW_DLV_OK) { + + if (strncmp(signature.signature, tu_signature.signature, 8) == 0) { + Dwarf_Die type_cu_die = 0; + if (dwarf_siblingof_b(dwarf, 0, 0, &type_cu_die, &error) == DW_DLV_OK) { + Dwarf_Die child_die = 0; + if (dwarf_child(type_cu_die, &child_die, &error) == DW_DLV_OK) { + get_type(dwarf, child_die, result); + found = !result.empty(); + dwarf_dealloc(dwarf, child_die, DW_DLA_DIE); + } + dwarf_dealloc(dwarf, type_cu_die, DW_DLA_DIE); + } + } + } + + if (found) { + while (dwarf_next_cu_header_d(dwarf, 0, 0, 0, 0, 0, 0, 0, 0, 0, + &next_cu_header, 0, &error) == DW_DLV_OK) { + // Reset the cu header state. Unfortunately, libdwarf's + // next_cu_header API keeps its own iterator per Dwarf_Debug + // that can't be reset. We need to keep fetching elements until + // the end. + } + } else { + // If we couldn't resolve the type just print out the signature + std::ostringstream string_stream; + string_stream << "<0x" << std::hex << std::setfill('0'); + for (int i = 0; i < 8; ++i) { + string_stream << std::setw(2) << std::hex + << (int)(unsigned char)(signature.signature[i]); + } + string_stream << ">"; + result = string_stream.str(); + } + return result; + } + + struct type_context_t { + bool is_const; + bool is_typedef; + bool has_type; + bool has_name; + std::string text; + + type_context_t() + : is_const(false), is_typedef(false), has_type(false), has_name(false) { + } + }; + + // Types are resolved from right to left: we get the variable name first + // and then all specifiers (like const or pointer) in a chain of DW_AT_type + // DIEs. Call this function recursively until we get a complete type + // string. + static void set_parameter_string(dwarf_fileobject &fobj, Dwarf_Die die, + type_context_t &context) { + char *name; + Dwarf_Error error = DW_DLE_NE; + + // typedefs contain also the base type, so we skip it and only + // print the typedef name + if (!context.is_typedef) { + if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { + if (!context.text.empty()) { + context.text.insert(0, " "); + } + context.text.insert(0, std::string(name)); + dwarf_dealloc(fobj.dwarf_handle.get(), name, DW_DLA_STRING); + } + } else { + context.is_typedef = false; + context.has_type = true; + if (context.is_const) { + context.text.insert(0, "const "); + context.is_const = false; + } + } + + bool next_type_is_const = false; + bool is_keyword = true; + + Dwarf_Half tag = 0; + Dwarf_Bool has_attr = 0; + if (dwarf_tag(die, &tag, &error) == DW_DLV_OK) { + switch (tag) { + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + case DW_TAG_enumeration_type: + context.has_type = true; + if (dwarf_hasattr(die, DW_AT_signature, &has_attr, &error) == + DW_DLV_OK) { + // If we have a signature it means the type is defined + // in .debug_types, so we need to load the DIE pointed + // at by the signature and resolve it + if (has_attr) { + std::string type = + get_type_by_signature(fobj.dwarf_handle.get(), die); + if (context.is_const) + type.insert(0, "const "); + + if (!context.text.empty()) + context.text.insert(0, " "); + context.text.insert(0, type); + } + + // Treat enums like typedefs, and skip printing its + // base type + context.is_typedef = (tag == DW_TAG_enumeration_type); + } + break; + case DW_TAG_const_type: + next_type_is_const = true; + break; + case DW_TAG_pointer_type: + context.text.insert(0, "*"); + break; + case DW_TAG_reference_type: + context.text.insert(0, "&"); + break; + case DW_TAG_restrict_type: + context.text.insert(0, "restrict "); + break; + case DW_TAG_rvalue_reference_type: + context.text.insert(0, "&&"); + break; + case DW_TAG_volatile_type: + context.text.insert(0, "volatile "); + break; + case DW_TAG_typedef: + // Propagate the const-ness to the next type + // as typedefs are linked to its base type + next_type_is_const = context.is_const; + context.is_typedef = true; + context.has_type = true; + break; + case DW_TAG_base_type: + context.has_type = true; + break; + case DW_TAG_formal_parameter: + context.has_name = true; + break; + default: + is_keyword = false; + break; + } + } + + if (!is_keyword && context.is_const) { + context.text.insert(0, "const "); + } + + context.is_const = next_type_is_const; + + Dwarf_Die ref = + get_referenced_die(fobj.dwarf_handle.get(), die, DW_AT_type, true); + if (ref) { + set_parameter_string(fobj, ref, context); + dwarf_dealloc(fobj.dwarf_handle.get(), ref, DW_DLA_DIE); + } + + if (!context.has_type && context.has_name) { + context.text.insert(0, "void "); + context.has_type = true; + } + } + + // Resolve the function return type and parameters + static void set_function_parameters(std::string &function_name, + std::vector &ns, + dwarf_fileobject &fobj, Dwarf_Die die) { + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + Dwarf_Error error = DW_DLE_NE; + Dwarf_Die current_die = 0; + std::string parameters; + bool has_spec = true; + // Check if we have a spec DIE. If we do we use it as it contains + // more information, like parameter names. + Dwarf_Die spec_die = get_spec_die(fobj, die); + if (!spec_die) { + has_spec = false; + spec_die = die; + } + + std::vector::const_iterator it = ns.begin(); + std::string ns_name; + for (it = ns.begin(); it < ns.end(); ++it) { + ns_name.append(*it).append("::"); + } + + if (!ns_name.empty()) { + function_name.insert(0, ns_name); + } + + // See if we have a function return type. It can be either on the + // current die or in its spec one (usually true for inlined functions) + std::string return_type = + get_referenced_die_name(dwarf, die, DW_AT_type, true); + if (return_type.empty()) { + return_type = get_referenced_die_name(dwarf, spec_die, DW_AT_type, true); + } + if (!return_type.empty()) { + return_type.append(" "); + function_name.insert(0, return_type); + } + + if (dwarf_child(spec_die, ¤t_die, &error) == DW_DLV_OK) { + for (;;) { + Dwarf_Die sibling_die = 0; + + Dwarf_Half tag_value; + dwarf_tag(current_die, &tag_value, &error); + + if (tag_value == DW_TAG_formal_parameter) { + // Ignore artificial (ie, compiler generated) parameters + bool is_artificial = false; + Dwarf_Attribute attr_mem; + if (dwarf_attr(current_die, DW_AT_artificial, &attr_mem, &error) == + DW_DLV_OK) { + Dwarf_Bool flag = 0; + if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) { + is_artificial = flag != 0; + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + + if (!is_artificial) { + type_context_t context; + set_parameter_string(fobj, current_die, context); + + if (parameters.empty()) { + parameters.append("("); + } else { + parameters.append(", "); + } + parameters.append(context.text); + } + } + + int result = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); + if (result == DW_DLV_ERROR) { + break; + } else if (result == DW_DLV_NO_ENTRY) { + break; + } + + if (current_die != die) { + dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); + current_die = 0; + } + + current_die = sibling_die; + } + } + if (parameters.empty()) + parameters = "("; + parameters.append(")"); + + // If we got a spec DIE we need to deallocate it + if (has_spec) + dwarf_dealloc(dwarf, spec_die, DW_DLA_DIE); + + function_name.append(parameters); + } + + // defined here because in C++98, template function cannot take locally + // defined types... grrr. + struct inliners_search_cb { + void operator()(Dwarf_Die die, std::vector &ns) { + Dwarf_Error error = DW_DLE_NE; + Dwarf_Half tag_value; + Dwarf_Attribute attr_mem; + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + + dwarf_tag(die, &tag_value, &error); + + switch (tag_value) { + char *name; + case DW_TAG_subprogram: + if (!trace.source.function.empty()) + break; + if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { + trace.source.function = std::string(name); + dwarf_dealloc(dwarf, name, DW_DLA_STRING); + } else { + // We don't have a function name in this DIE. + // Check if there is a referenced non-defining + // declaration. + trace.source.function = + get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true); + if (trace.source.function.empty()) { + trace.source.function = + get_referenced_die_name(dwarf, die, DW_AT_specification, true); + } + } + + // Append the function parameters, if available + set_function_parameters(trace.source.function, ns, fobj, die); + + // If the object function name is empty, it's possible that + // there is no dynamic symbol table (maybe the executable + // was stripped or not built with -rdynamic). See if we have + // a DWARF linkage name to use instead. We try both + // linkage_name and MIPS_linkage_name because the MIPS tag + // was the unofficial one until it was adopted in DWARF4. + // Old gcc versions generate MIPS_linkage_name + if (trace.object_function.empty()) { + details::demangler demangler; + + if (dwarf_attr(die, DW_AT_linkage_name, &attr_mem, &error) != + DW_DLV_OK) { + if (dwarf_attr(die, DW_AT_MIPS_linkage_name, &attr_mem, &error) != + DW_DLV_OK) { + break; + } + } + + char *linkage; + if (dwarf_formstring(attr_mem, &linkage, &error) == DW_DLV_OK) { + trace.object_function = demangler.demangle(linkage); + dwarf_dealloc(dwarf, linkage, DW_DLA_STRING); + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + break; + + case DW_TAG_inlined_subroutine: + ResolvedTrace::SourceLoc sloc; + + if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { + sloc.function = std::string(name); + dwarf_dealloc(dwarf, name, DW_DLA_STRING); + } else { + // We don't have a name for this inlined DIE, it could + // be that there is an abstract origin instead. + // Get the DW_AT_abstract_origin value, which is a + // reference to the source DIE and try to get its name + sloc.function = + get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true); + } + + set_function_parameters(sloc.function, ns, fobj, die); + + std::string file = die_call_file(dwarf, die, cu_die); + if (!file.empty()) + sloc.filename = file; + + Dwarf_Unsigned number = 0; + if (dwarf_attr(die, DW_AT_call_line, &attr_mem, &error) == DW_DLV_OK) { + if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) { + sloc.line = number; + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + + if (dwarf_attr(die, DW_AT_call_column, &attr_mem, &error) == + DW_DLV_OK) { + if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) { + sloc.col = number; + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + + trace.inliners.push_back(sloc); + break; + }; + } + ResolvedTrace &trace; + dwarf_fileobject &fobj; + Dwarf_Die cu_die; + inliners_search_cb(ResolvedTrace &t, dwarf_fileobject &f, Dwarf_Die c) + : trace(t), fobj(f), cu_die(c) {} + }; + + static Dwarf_Die find_fundie_by_pc(dwarf_fileobject &fobj, + Dwarf_Die parent_die, Dwarf_Addr pc, + Dwarf_Die result) { + Dwarf_Die current_die = 0; + Dwarf_Error error = DW_DLE_NE; + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + + if (dwarf_child(parent_die, ¤t_die, &error) != DW_DLV_OK) { + return NULL; + } + + for (;;) { + Dwarf_Die sibling_die = 0; + Dwarf_Half tag_value; + dwarf_tag(current_die, &tag_value, &error); + + switch (tag_value) { + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: + if (die_has_pc(fobj, current_die, pc)) { + return current_die; + } + }; + bool declaration = false; + Dwarf_Attribute attr_mem; + if (dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == + DW_DLV_OK) { + Dwarf_Bool flag = 0; + if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) { + declaration = flag != 0; + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + + if (!declaration) { + // let's be curious and look deeper in the tree, functions are + // not necessarily at the first level, but might be nested + // inside a namespace, structure, a function, an inlined + // function etc. + Dwarf_Die die_mem = 0; + Dwarf_Die indie = find_fundie_by_pc(fobj, current_die, pc, die_mem); + if (indie) { + result = die_mem; + return result; + } + } + + int res = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); + if (res == DW_DLV_ERROR) { + return NULL; + } else if (res == DW_DLV_NO_ENTRY) { + break; + } + + if (current_die != parent_die) { + dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); + current_die = 0; + } + + current_die = sibling_die; + } + return NULL; + } + + template + static bool deep_first_search_by_pc(dwarf_fileobject &fobj, + Dwarf_Die parent_die, Dwarf_Addr pc, + std::vector &ns, CB cb) { + Dwarf_Die current_die = 0; + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + Dwarf_Error error = DW_DLE_NE; + + if (dwarf_child(parent_die, ¤t_die, &error) != DW_DLV_OK) { + return false; + } + + bool branch_has_pc = false; + bool has_namespace = false; + for (;;) { + Dwarf_Die sibling_die = 0; + + Dwarf_Half tag; + if (dwarf_tag(current_die, &tag, &error) == DW_DLV_OK) { + if (tag == DW_TAG_namespace || tag == DW_TAG_class_type) { + char *ns_name = NULL; + if (dwarf_diename(current_die, &ns_name, &error) == DW_DLV_OK) { + if (ns_name) { + ns.push_back(std::string(ns_name)); + } else { + ns.push_back(""); + } + dwarf_dealloc(dwarf, ns_name, DW_DLA_STRING); + } else { + ns.push_back(""); + } + has_namespace = true; + } + } + + bool declaration = false; + Dwarf_Attribute attr_mem; + if (tag != DW_TAG_class_type && + dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == + DW_DLV_OK) { + Dwarf_Bool flag = 0; + if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) { + declaration = flag != 0; + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + } + + if (!declaration) { + // let's be curious and look deeper in the tree, function are + // not necessarily at the first level, but might be nested + // inside a namespace, structure, a function, an inlined + // function etc. + branch_has_pc = deep_first_search_by_pc(fobj, current_die, pc, ns, cb); + } + + if (!branch_has_pc) { + branch_has_pc = die_has_pc(fobj, current_die, pc); + } + + if (branch_has_pc) { + cb(current_die, ns); + } + + int result = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); + if (result == DW_DLV_ERROR) { + return false; + } else if (result == DW_DLV_NO_ENTRY) { + break; + } + + if (current_die != parent_die) { + dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); + current_die = 0; + } + + if (has_namespace) { + has_namespace = false; + ns.pop_back(); + } + current_die = sibling_die; + } + + if (has_namespace) { + ns.pop_back(); + } + return branch_has_pc; + } + + static std::string die_call_file(Dwarf_Debug dwarf, Dwarf_Die die, + Dwarf_Die cu_die) { + Dwarf_Attribute attr_mem; + Dwarf_Error error = DW_DLE_NE; + Dwarf_Unsigned file_index; + + std::string file; + + if (dwarf_attr(die, DW_AT_call_file, &attr_mem, &error) == DW_DLV_OK) { + if (dwarf_formudata(attr_mem, &file_index, &error) != DW_DLV_OK) { + file_index = 0; + } + dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); + + if (file_index == 0) { + return file; + } + + char **srcfiles = 0; + Dwarf_Signed file_count = 0; + if (dwarf_srcfiles(cu_die, &srcfiles, &file_count, &error) == DW_DLV_OK) { + if (file_count > 0 && file_index <= static_cast(file_count)) { + file = std::string(srcfiles[file_index - 1]); + } + + // Deallocate all strings! + for (int i = 0; i < file_count; ++i) { + dwarf_dealloc(dwarf, srcfiles[i], DW_DLA_STRING); + } + dwarf_dealloc(dwarf, srcfiles, DW_DLA_LIST); + } + } + return file; + } + + Dwarf_Die find_die(dwarf_fileobject &fobj, Dwarf_Addr addr) { + // Let's get to work! First see if we have a debug_aranges section so + // we can speed up the search + + Dwarf_Debug dwarf = fobj.dwarf_handle.get(); + Dwarf_Error error = DW_DLE_NE; + Dwarf_Arange *aranges; + Dwarf_Signed arange_count; + + Dwarf_Die returnDie; + bool found = false; + if (dwarf_get_aranges(dwarf, &aranges, &arange_count, &error) != + DW_DLV_OK) { + aranges = NULL; + } + + if (aranges) { + // We have aranges. Get the one where our address is. + Dwarf_Arange arange; + if (dwarf_get_arange(aranges, arange_count, addr, &arange, &error) == + DW_DLV_OK) { + + // We found our address. Get the compilation-unit DIE offset + // represented by the given address range. + Dwarf_Off cu_die_offset; + if (dwarf_get_cu_die_offset(arange, &cu_die_offset, &error) == + DW_DLV_OK) { + // Get the DIE at the offset returned by the aranges search. + // We set is_info to 1 to specify that the offset is from + // the .debug_info section (and not .debug_types) + int dwarf_result = + dwarf_offdie_b(dwarf, cu_die_offset, 1, &returnDie, &error); + + found = dwarf_result == DW_DLV_OK; + } + dwarf_dealloc(dwarf, arange, DW_DLA_ARANGE); + } + } + + if (found) + return returnDie; // The caller is responsible for freeing the die + + // The search for aranges failed. Try to find our address by scanning + // all compilation units. + Dwarf_Unsigned next_cu_header; + Dwarf_Half tag = 0; + returnDie = 0; + + while (!found && + dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, + &next_cu_header, 0, &error) == DW_DLV_OK) { + + if (returnDie) + dwarf_dealloc(dwarf, returnDie, DW_DLA_DIE); + + if (dwarf_siblingof(dwarf, 0, &returnDie, &error) == DW_DLV_OK) { + if ((dwarf_tag(returnDie, &tag, &error) == DW_DLV_OK) && + tag == DW_TAG_compile_unit) { + if (die_has_pc(fobj, returnDie, addr)) { + found = true; + } + } + } + } + + if (found) { + while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, + &next_cu_header, 0, &error) == DW_DLV_OK) { + // Reset the cu header state. Libdwarf's next_cu_header API + // keeps its own iterator per Dwarf_Debug that can't be reset. + // We need to keep fetching elements until the end. + } + } + + if (found) + return returnDie; + + // We couldn't find any compilation units with ranges or a high/low pc. + // Try again by looking at all DIEs in all compilation units. + Dwarf_Die cudie; + while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, + &next_cu_header, 0, &error) == DW_DLV_OK) { + if (dwarf_siblingof(dwarf, 0, &cudie, &error) == DW_DLV_OK) { + Dwarf_Die die_mem = 0; + Dwarf_Die resultDie = find_fundie_by_pc(fobj, cudie, addr, die_mem); + + if (resultDie) { + found = true; + break; + } + } + } + + if (found) { + while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, + &next_cu_header, 0, &error) == DW_DLV_OK) { + // Reset the cu header state. Libdwarf's next_cu_header API + // keeps its own iterator per Dwarf_Debug that can't be reset. + // We need to keep fetching elements until the end. + } + } + + if (found) + return cudie; + + // We failed. + return NULL; + } +}; +#endif // BACKWARD_HAS_DWARF == 1 + + template <> + class TraceResolverImpl + : public TraceResolverLinuxImpl {}; + +#endif // BACKWARD_SYSTEM_LINUX + +#ifdef BACKWARD_SYSTEM_DARWIN + + template class TraceResolverDarwinImpl; + +template <> +class TraceResolverDarwinImpl + : public TraceResolverImplBase { +public: + void load_addresses(void *const*addresses, int address_count) override { + if (address_count == 0) { + return; + } + _symbols.reset(backtrace_symbols(addresses, address_count)); + } + + ResolvedTrace resolve(ResolvedTrace trace) override { + // parse: + // + + char *filename = _symbols[trace.idx]; + + // skip " " + while (*filename && *filename != ' ') + filename++; + while (*filename == ' ') + filename++; + + // find start of from end ( may contain a space) + char *p = filename + strlen(filename) - 1; + // skip to start of " + " + while (p > filename && *p != ' ') + p--; + while (p > filename && *p == ' ') + p--; + while (p > filename && *p != ' ') + p--; + while (p > filename && *p == ' ') + p--; + char *funcname_end = p + 1; + + // skip to start of "" + while (p > filename && *p != ' ') + p--; + char *funcname = p + 1; + + // skip to start of " " + while (p > filename && *p == ' ') + p--; + while (p > filename && *p != ' ') + p--; + while (p > filename && *p == ' ') + p--; + + // skip "", handling the case where it contains a + char *filename_end = p + 1; + if (p == filename) { + // something went wrong, give up + filename_end = filename + strlen(filename); + funcname = filename_end; + } + trace.object_filename.assign( + filename, filename_end); // ok even if filename_end is the ending \0 + // (then we assign entire string) + + if (*funcname) { // if it's not end of string + *funcname_end = '\0'; + + trace.object_function = this->demangle(funcname); + trace.object_function += " "; + trace.object_function += (funcname_end + 1); + trace.source.function = trace.object_function; // we cannot do better. + } + return trace; + } + +private: + details::handle _symbols; +}; + +template <> +class TraceResolverImpl + : public TraceResolverDarwinImpl {}; + +#endif // BACKWARD_SYSTEM_DARWIN + +#ifdef BACKWARD_SYSTEM_WINDOWS + + // Load all symbol info +// Based on: +// https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app/28276227#28276227 + +struct module_data { + std::string image_name; + std::string module_name; + void *base_address; + DWORD load_size; +}; + +class get_mod_info { + HANDLE process; + static const int buffer_length = 4096; + +public: + get_mod_info(HANDLE h) : process(h) {} + + module_data operator()(HMODULE module) { + module_data ret; + char temp[buffer_length]; + MODULEINFO mi; + + GetModuleInformation(process, module, &mi, sizeof(mi)); + ret.base_address = mi.lpBaseOfDll; + ret.load_size = mi.SizeOfImage; + + GetModuleFileNameExA(process, module, temp, sizeof(temp)); + ret.image_name = temp; + GetModuleBaseNameA(process, module, temp, sizeof(temp)); + ret.module_name = temp; + std::vector img(ret.image_name.begin(), ret.image_name.end()); + std::vector mod(ret.module_name.begin(), ret.module_name.end()); + SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, + ret.load_size); + return ret; + } +}; + +template <> class TraceResolverImpl + : public TraceResolverImplBase { +public: + TraceResolverImpl() { + + HANDLE process = GetCurrentProcess(); + + std::vector modules; + DWORD cbNeeded; + std::vector module_handles(1); + SymInitialize(process, NULL, false); + DWORD symOptions = SymGetOptions(); + symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME; + SymSetOptions(symOptions); + EnumProcessModules(process, &module_handles[0], + module_handles.size() * sizeof(HMODULE), &cbNeeded); + module_handles.resize(cbNeeded / sizeof(HMODULE)); + EnumProcessModules(process, &module_handles[0], + module_handles.size() * sizeof(HMODULE), &cbNeeded); + std::transform(module_handles.begin(), module_handles.end(), + std::back_inserter(modules), get_mod_info(process)); + void *base = modules[0].base_address; + IMAGE_NT_HEADERS *h = ImageNtHeader(base); + image_type = h->FileHeader.Machine; + } + + static const int max_sym_len = 255; + struct symbol_t { + SYMBOL_INFO sym; + char buffer[max_sym_len]; + } sym; + + DWORD64 displacement; + + ResolvedTrace resolve(ResolvedTrace t) override { + HANDLE process = GetCurrentProcess(); + + char name[256]; + + memset(&sym, 0, sizeof(sym)); + sym.sym.SizeOfStruct = sizeof(SYMBOL_INFO); + sym.sym.MaxNameLen = max_sym_len; + + if (!SymFromAddr(process, (ULONG64)t.addr, &displacement, &sym.sym)) { + // TODO: error handling everywhere + char* lpMsgBuf; + DWORD dw = GetLastError(); + + if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char*)&lpMsgBuf, 0, NULL)) { + std::fprintf(stderr, "%s\n", lpMsgBuf); + LocalFree(lpMsgBuf); + } + + // abort(); + } + UnDecorateSymbolName(sym.sym.Name, (PSTR)name, 256, UNDNAME_COMPLETE); + + DWORD offset = 0; + IMAGEHLP_LINE line; + if (SymGetLineFromAddr(process, (ULONG64)t.addr, &offset, &line)) { + t.object_filename = line.FileName; + t.source.filename = line.FileName; + t.source.line = line.LineNumber; + t.source.col = offset; + } + + t.source.function = name; + t.object_filename = ""; + t.object_function = name; + + return t; + } + + DWORD machine_type() const { return image_type; } + +private: + DWORD image_type; +}; + +#endif + + class TraceResolver : public TraceResolverImpl {}; + +/*************** CODE SNIPPET ***************/ + + class SourceFile { + public: + typedef std::vector > lines_t; + + SourceFile() {} + SourceFile(const std::string &path) { + // 1. If BACKWARD_CXX_SOURCE_PREFIXES is set then assume it contains + // a colon-separated list of path prefixes. Try prepending each + // to the given path until a valid file is found. + const std::vector &prefixes = get_paths_from_env_variable(); + for (size_t i = 0; i < prefixes.size(); ++i) { + // Double slashes (//) should not be a problem. + std::string new_path = prefixes[i] + '/' + path; + _file.reset(new std::ifstream(new_path.c_str())); + if (is_open()) + break; + } + // 2. If no valid file found then fallback to opening the path as-is. + if (!_file || !is_open()) { + _file.reset(new std::ifstream(path.c_str())); + } + } + bool is_open() const { return _file->is_open(); } + + lines_t &get_lines(unsigned line_start, unsigned line_count, lines_t &lines) { + using namespace std; + // This function make uses of the dumbest algo ever: + // 1) seek(0) + // 2) read lines one by one and discard until line_start + // 3) read line one by one until line_start + line_count + // + // If you are getting snippets many time from the same file, it is + // somewhat a waste of CPU, feel free to benchmark and propose a + // better solution ;) + + _file->clear(); + _file->seekg(0); + string line; + unsigned line_idx; + + for (line_idx = 1; line_idx < line_start; ++line_idx) { + std::getline(*_file, line); + if (!*_file) { + return lines; + } + } + + // think of it like a lambda in C++98 ;) + // but look, I will reuse it two times! + // What a good boy am I. + struct isspace { + bool operator()(char c) { return std::isspace(c); } + }; + + bool started = false; + for (; line_idx < line_start + line_count; ++line_idx) { + getline(*_file, line); + if (!*_file) { + return lines; + } + if (!started) { + if (std::find_if(line.begin(), line.end(), not_isspace()) == line.end()) + continue; + started = true; + } + lines.push_back(make_pair(line_idx, line)); + } + + lines.erase( + std::find_if(lines.rbegin(), lines.rend(), not_isempty()).base(), + lines.end()); + return lines; + } + + lines_t get_lines(unsigned line_start, unsigned line_count) { + lines_t lines; + return get_lines(line_start, line_count, lines); + } + + // there is no find_if_not in C++98, lets do something crappy to + // workaround. + struct not_isspace { + bool operator()(char c) { return !std::isspace(c); } + }; + // and define this one here because C++98 is not happy with local defined + // struct passed to template functions, fuuuu. + struct not_isempty { + bool operator()(const lines_t::value_type &p) { + return !(std::find_if(p.second.begin(), p.second.end(), not_isspace()) == + p.second.end()); + } + }; + + void swap(SourceFile &b) { _file.swap(b._file); } + +#ifdef BACKWARD_ATLEAST_CXX11 + SourceFile(SourceFile &&from) : _file(nullptr) { swap(from); } + SourceFile &operator=(SourceFile &&from) { + swap(from); + return *this; + } +#else + explicit SourceFile(const SourceFile &from) { + // some sort of poor man's move semantic. + swap(const_cast(from)); + } + SourceFile &operator=(const SourceFile &from) { + // some sort of poor man's move semantic. + swap(const_cast(from)); + return *this; + } +#endif + + private: + details::handle > + _file; + + std::vector get_paths_from_env_variable_impl() { + std::vector paths; + const char *prefixes_str = std::getenv("BACKWARD_CXX_SOURCE_PREFIXES"); + if (prefixes_str && prefixes_str[0]) { + paths = details::split_source_prefixes(prefixes_str); + } + return paths; + } + + const std::vector &get_paths_from_env_variable() { + static std::vector paths = get_paths_from_env_variable_impl(); + return paths; + } + +#ifdef BACKWARD_ATLEAST_CXX11 + SourceFile(const SourceFile &) = delete; + SourceFile &operator=(const SourceFile &) = delete; +#endif + }; + + class SnippetFactory { + public: + typedef SourceFile::lines_t lines_t; + + lines_t get_snippet(const std::string &filename, unsigned line_start, + unsigned context_size) { + + SourceFile &src_file = get_src_file(filename); + unsigned start = line_start - context_size / 2; + return src_file.get_lines(start, context_size); + } + + lines_t get_combined_snippet(const std::string &filename_a, unsigned line_a, + const std::string &filename_b, unsigned line_b, + unsigned context_size) { + SourceFile &src_file_a = get_src_file(filename_a); + SourceFile &src_file_b = get_src_file(filename_b); + + lines_t lines = + src_file_a.get_lines(line_a - context_size / 4, context_size / 2); + src_file_b.get_lines(line_b - context_size / 4, context_size / 2, lines); + return lines; + } + + lines_t get_coalesced_snippet(const std::string &filename, unsigned line_a, + unsigned line_b, unsigned context_size) { + SourceFile &src_file = get_src_file(filename); + + using std::max; + using std::min; + unsigned a = min(line_a, line_b); + unsigned b = max(line_a, line_b); + + if ((b - a) < (context_size / 3)) { + return src_file.get_lines((a + b - context_size + 1) / 2, context_size); + } + + lines_t lines = src_file.get_lines(a - context_size / 4, context_size / 2); + src_file.get_lines(b - context_size / 4, context_size / 2, lines); + return lines; + } + + private: + typedef details::hashtable::type src_files_t; + src_files_t _src_files; + + SourceFile &get_src_file(const std::string &filename) { + src_files_t::iterator it = _src_files.find(filename); + if (it != _src_files.end()) { + return it->second; + } + SourceFile &new_src_file = _src_files[filename]; + new_src_file = SourceFile(filename); + return new_src_file; + } + }; + +/*************** PRINTER ***************/ + + namespace ColorMode { + enum type { automatic, never, always }; + } + + class cfile_streambuf : public std::streambuf { + public: + cfile_streambuf(FILE *_sink) : sink(_sink) {} + int_type underflow() override { return traits_type::eof(); } + int_type overflow(int_type ch) override { + if (traits_type::not_eof(ch) && fputc(ch, sink) != EOF) { + return ch; + } + return traits_type::eof(); + } + + std::streamsize xsputn(const char_type *s, std::streamsize count) override { + return static_cast( + fwrite(s, sizeof *s, static_cast(count), sink)); + } + +#ifdef BACKWARD_ATLEAST_CXX11 + public: + cfile_streambuf(const cfile_streambuf &) = delete; + cfile_streambuf &operator=(const cfile_streambuf &) = delete; +#else + private: + cfile_streambuf(const cfile_streambuf &); + cfile_streambuf &operator=(const cfile_streambuf &); +#endif + + private: + FILE *sink; + std::vector buffer; + }; + +#ifdef BACKWARD_SYSTEM_LINUX + + namespace Color { + enum type { yellow = 33, purple = 35, reset = 39 }; + } // namespace Color + + class Colorize { + public: + Colorize(std::ostream &os) : _os(os), _reset(false), _enabled(false) {} + + void activate(ColorMode::type mode) { _enabled = mode == ColorMode::always; } + + void activate(ColorMode::type mode, FILE *fp) { activate(mode, fileno(fp)); } + + void set_color(Color::type ccode) { + if (!_enabled) + return; + + // I assume that the terminal can handle basic colors. Seriously I + // don't want to deal with all the termcap shit. + _os << "\033[" << static_cast(ccode) << "m"; + _reset = (ccode != Color::reset); + } + + ~Colorize() { + if (_reset) { + set_color(Color::reset); + } + } + + private: + void activate(ColorMode::type mode, int fd) { + activate(mode == ColorMode::automatic && isatty(fd) ? ColorMode::always + : mode); + } + + std::ostream &_os; + bool _reset; + bool _enabled; + }; + +#else // ndef BACKWARD_SYSTEM_LINUX + + namespace Color { +enum type { yellow = 0, purple = 0, reset = 0 }; +} // namespace Color + +class Colorize { +public: + Colorize(std::ostream &) {} + void activate(ColorMode::type) {} + void activate(ColorMode::type, FILE *) {} + void set_color(Color::type) {} +}; + +#endif // BACKWARD_SYSTEM_LINUX + + class Printer { + public: + bool snippet; + ColorMode::type color_mode; + bool address; + bool object; + int inliner_context_size; + int trace_context_size; + + Printer() + : snippet(true), color_mode(ColorMode::automatic), address(false), + object(false), inliner_context_size(5), trace_context_size(7) {} + + template FILE *print(ST &st, FILE *fp = stderr) { + cfile_streambuf obuf(fp); + std::ostream os(&obuf); + Colorize colorize(os); + colorize.activate(color_mode, fp); + print_stacktrace(st, os, colorize); + return fp; + } + + template std::ostream &print(ST &st, std::ostream &os) { + Colorize colorize(os); + colorize.activate(color_mode); + print_stacktrace(st, os, colorize); + return os; + } + + template + FILE *print(IT begin, IT end, FILE *fp = stderr, size_t thread_id = 0) { + cfile_streambuf obuf(fp); + std::ostream os(&obuf); + Colorize colorize(os); + colorize.activate(color_mode, fp); + print_stacktrace(begin, end, os, thread_id, colorize); + return fp; + } + + template + std::ostream &print(IT begin, IT end, std::ostream &os, + size_t thread_id = 0) { + Colorize colorize(os); + colorize.activate(color_mode); + print_stacktrace(begin, end, os, thread_id, colorize); + return os; + } + + TraceResolver const &resolver() const { return _resolver; } + + private: + TraceResolver _resolver; + SnippetFactory _snippets; + + template + void print_stacktrace(ST &st, std::ostream &os, Colorize &colorize) { + print_header(os, st.thread_id()); + _resolver.load_stacktrace(st); + for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) { + print_trace(os, _resolver.resolve(st[trace_idx - 1]), colorize); + } + } + + template + void print_stacktrace(IT begin, IT end, std::ostream &os, size_t thread_id, + Colorize &colorize) { + print_header(os, thread_id); + for (; begin != end; ++begin) { + print_trace(os, *begin, colorize); + } + } + + void print_header(std::ostream &os, size_t thread_id) { + os << "Stack trace (most recent call last)"; + if (thread_id) { + os << " in thread " << thread_id; + } + os << ":\n"; + } + + void print_trace(std::ostream &os, const ResolvedTrace &trace, + Colorize &colorize) { + os << "#" << std::left << std::setw(2) << trace.idx << std::right; + bool already_indented = true; + + if (!trace.source.filename.size() || object) { + os << " Object \"" << trace.object_filename << "\", at " << trace.addr + << ", in " << trace.object_function << "\n"; + already_indented = false; + } + + for (size_t inliner_idx = trace.inliners.size(); inliner_idx > 0; + --inliner_idx) { + if (!already_indented) { + os << " "; + } + const ResolvedTrace::SourceLoc &inliner_loc = + trace.inliners[inliner_idx - 1]; + print_source_loc(os, " | ", inliner_loc); + if (snippet) { + print_snippet(os, " | ", inliner_loc, colorize, Color::purple, + inliner_context_size); + } + already_indented = false; + } + + if (trace.source.filename.size()) { + if (!already_indented) { + os << " "; + } + print_source_loc(os, " ", trace.source, trace.addr); + if (snippet) { + print_snippet(os, " ", trace.source, colorize, Color::yellow, + trace_context_size); + } + } + } + + void print_snippet(std::ostream &os, const char *indent, + const ResolvedTrace::SourceLoc &source_loc, + Colorize &colorize, Color::type color_code, + int context_size) { + using namespace std; + typedef SnippetFactory::lines_t lines_t; + + lines_t lines = _snippets.get_snippet(source_loc.filename, source_loc.line, + static_cast(context_size)); + + for (lines_t::const_iterator it = lines.begin(); it != lines.end(); ++it) { + if (it->first == source_loc.line) { + colorize.set_color(color_code); + os << indent << ">"; + } else { + os << indent << " "; + } + os << std::setw(4) << it->first << ": " << it->second << "\n"; + if (it->first == source_loc.line) { + colorize.set_color(Color::reset); + } + } + } + + void print_source_loc(std::ostream &os, const char *indent, + const ResolvedTrace::SourceLoc &source_loc, + void *addr = nullptr) { + os << indent << "Source \"" << source_loc.filename << "\", line " + << source_loc.line << ", in " << source_loc.function; + + if (address && addr != nullptr) { + os << " [" << addr << "]"; + } + os << "\n"; + } + }; + +/*************** SIGNALS HANDLING ***************/ + +#if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN) + + class SignalHandling { + public: + static std::vector make_default_signals() { + const int posix_signals[] = { + // Signals for which the default action is "Core". + SIGABRT, // Abort signal from abort(3) + SIGBUS, // Bus error (bad memory access) + SIGFPE, // Floating point exception + SIGILL, // Illegal Instruction + SIGIOT, // IOT trap. A synonym for SIGABRT + SIGQUIT, // Quit from keyboard + SIGSEGV, // Invalid memory reference + SIGSYS, // Bad argument to routine (SVr4) + SIGTRAP, // Trace/breakpoint trap + SIGXCPU, // CPU time limit exceeded (4.2BSD) + SIGXFSZ, // File size limit exceeded (4.2BSD) +#if defined(BACKWARD_SYSTEM_DARWIN) + SIGEMT, // emulation instruction executed +#endif + }; + return std::vector(posix_signals, + posix_signals + + sizeof posix_signals / sizeof posix_signals[0]); + } + + SignalHandling(const std::vector &posix_signals = make_default_signals()) + : _loaded(false) { + bool success = true; + + const size_t stack_size = 1024 * 1024 * 8; + _stack_content.reset(static_cast(malloc(stack_size))); + if (_stack_content) { + stack_t ss; + ss.ss_sp = _stack_content.get(); + ss.ss_size = stack_size; + ss.ss_flags = 0; + if (sigaltstack(&ss, nullptr) < 0) { + success = false; + } + } else { + success = false; + } + + for (size_t i = 0; i < posix_signals.size(); ++i) { + struct sigaction action; + memset(&action, 0, sizeof action); + action.sa_flags = + static_cast(SA_SIGINFO | SA_ONSTACK | SA_NODEFER | SA_RESETHAND); + sigfillset(&action.sa_mask); + sigdelset(&action.sa_mask, posix_signals[i]); +#if defined(__clang__) + #pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" +#endif + action.sa_sigaction = &sig_handler; +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + + int r = sigaction(posix_signals[i], &action, nullptr); + if (r < 0) + success = false; + } + + _loaded = success; + } + + bool loaded() const { return _loaded; } + + static void handleSignal(int, siginfo_t *info, void *_ctx) { + ucontext_t *uctx = static_cast(_ctx); + + StackTrace st; + void *error_addr = nullptr; +#ifdef REG_RIP // x86_64 + error_addr = reinterpret_cast(uctx->uc_mcontext.gregs[REG_RIP]); +#elif defined(REG_EIP) // x86_32 + error_addr = reinterpret_cast(uctx->uc_mcontext.gregs[REG_EIP]); +#elif defined(__arm__) + error_addr = reinterpret_cast(uctx->uc_mcontext.arm_pc); +#elif defined(__aarch64__) + #if defined(__APPLE__) + error_addr = reinterpret_cast(uctx->uc_mcontext->__ss.__pc); + #else + error_addr = reinterpret_cast(uctx->uc_mcontext.pc); + #endif +#elif defined(__mips__) + error_addr = reinterpret_cast( + reinterpret_cast(&uctx->uc_mcontext)->sc_pc); +#elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \ + defined(__POWERPC__) + error_addr = reinterpret_cast(uctx->uc_mcontext.regs->nip); +#elif defined(__riscv) + error_addr = reinterpret_cast(uctx->uc_mcontext.__gregs[REG_PC]); +#elif defined(__s390x__) + error_addr = reinterpret_cast(uctx->uc_mcontext.psw.addr); +#elif defined(__APPLE__) && defined(__x86_64__) + error_addr = reinterpret_cast(uctx->uc_mcontext->__ss.__rip); +#elif defined(__APPLE__) + error_addr = reinterpret_cast(uctx->uc_mcontext->__ss.__eip); +#else +#warning ":/ sorry, ain't know no nothing none not of your architecture!" +#endif + if (error_addr) { + st.load_from(error_addr, 32, reinterpret_cast(uctx), + info->si_addr); + } else { + st.load_here(32, reinterpret_cast(uctx), info->si_addr); + } + + Printer printer; + printer.address = true; + printer.print(st, stderr); + +#if (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || \ + (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) + psiginfo(info, nullptr); +#else + (void)info; +#endif + } + + private: + details::handle _stack_content; + bool _loaded; + +#ifdef __GNUC__ + __attribute__((noreturn)) +#endif + static void + sig_handler(int signo, siginfo_t *info, void *_ctx) { + handleSignal(signo, info, _ctx); + + // try to forward the signal. + raise(info->si_signo); + + // terminate the process immediately. + puts("watf? exit"); + _exit(EXIT_FAILURE); + } + }; + +#endif // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN + +#ifdef BACKWARD_SYSTEM_WINDOWS + + class SignalHandling { +public: + SignalHandling(const std::vector & = std::vector()) + : reporter_thread_([]() { + /* We handle crashes in a utility thread: + backward structures and some Windows functions called here + need stack space, which we do not have when we encounter a + stack overflow. + To support reporting stack traces during a stack overflow, + we create a utility thread at startup, which waits until a + crash happens or the program exits normally. */ + + { + std::unique_lock lk(mtx()); + cv().wait(lk, [] { return crashed() != crash_status::running; }); + } + if (crashed() == crash_status::crashed) { + handle_stacktrace(skip_recs()); + } + { + std::unique_lock lk(mtx()); + crashed() = crash_status::ending; + } + cv().notify_one(); + }) { + SetUnhandledExceptionFilter(crash_handler); + + signal(SIGABRT, signal_handler); + _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + + std::set_terminate(&terminator); +#ifndef BACKWARD_ATLEAST_CXX17 + std::set_unexpected(&terminator); +#endif + _set_purecall_handler(&terminator); + _set_invalid_parameter_handler(&invalid_parameter_handler); + } + bool loaded() const { return true; } + + ~SignalHandling() { + { + std::unique_lock lk(mtx()); + crashed() = crash_status::normal_exit; + } + + cv().notify_one(); + + reporter_thread_.join(); + } + +private: + static CONTEXT *ctx() { + static CONTEXT data; + return &data; + } + + enum class crash_status { running, crashed, normal_exit, ending }; + + static crash_status &crashed() { + static crash_status data; + return data; + } + + static std::mutex &mtx() { + static std::mutex data; + return data; + } + + static std::condition_variable &cv() { + static std::condition_variable data; + return data; + } + + static HANDLE &thread_handle() { + static HANDLE handle; + return handle; + } + + std::thread reporter_thread_; + + // TODO: how not to hardcode these? + static const constexpr int signal_skip_recs = +#ifdef __clang__ + // With clang, RtlCaptureContext also captures the stack frame of the + // current function Below that, there are 3 internal Windows functions + 4 +#else + // With MSVC cl, RtlCaptureContext misses the stack frame of the current + // function The first entries during StackWalk are the 3 internal Windows + // functions + 3 +#endif + ; + + static int &skip_recs() { + static int data; + return data; + } + + static inline void terminator() { + crash_handler(signal_skip_recs); + abort(); + } + + static inline void signal_handler(int) { + crash_handler(signal_skip_recs); + abort(); + } + + static inline void __cdecl invalid_parameter_handler(const wchar_t *, + const wchar_t *, + const wchar_t *, + unsigned int, + uintptr_t) { + crash_handler(signal_skip_recs); + abort(); + } + + NOINLINE static LONG WINAPI crash_handler(EXCEPTION_POINTERS *info) { + // The exception info supplies a trace from exactly where the issue was, + // no need to skip records + crash_handler(0, info->ContextRecord); + return EXCEPTION_CONTINUE_SEARCH; + } + + NOINLINE static void crash_handler(int skip, CONTEXT *ct = nullptr) { + + if (ct == nullptr) { + RtlCaptureContext(ctx()); + } else { + memcpy(ctx(), ct, sizeof(CONTEXT)); + } + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &thread_handle(), 0, FALSE, + DUPLICATE_SAME_ACCESS); + + skip_recs() = skip; + + { + std::unique_lock lk(mtx()); + crashed() = crash_status::crashed; + } + + cv().notify_one(); + + { + std::unique_lock lk(mtx()); + cv().wait(lk, [] { return crashed() != crash_status::crashed; }); + } + } + + static void handle_stacktrace(int skip_frames = 0) { + // printer creates the TraceResolver, which can supply us a machine type + // for stack walking. Without this, StackTrace can only guess using some + // macros. + // StackTrace also requires that the PDBs are already loaded, which is done + // in the constructor of TraceResolver + Printer printer; + + StackTrace st; + st.set_machine_type(printer.resolver().machine_type()); + st.set_thread_handle(thread_handle()); + st.load_here(32 + skip_frames, ctx()); + st.skip_n_firsts(skip_frames); + + printer.address = true; + printer.print(st, std::cerr); + } +}; + +#endif // BACKWARD_SYSTEM_WINDOWS + +#ifdef BACKWARD_SYSTEM_UNKNOWN + + class SignalHandling { +public: + SignalHandling(const std::vector & = std::vector()) {} + bool init() { return false; } + bool loaded() { return false; } +}; + +#endif // BACKWARD_SYSTEM_UNKNOWN + +} // namespace backward + +#endif /* H_GUARD */ diff --git a/common/string_util.cpp b/common/string_util.cpp deleted file mode 100644 index aa469a76d..000000000 --- a/common/string_util.cpp +++ /dev/null @@ -1,1288 +0,0 @@ -/* - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "string_util.h" -#include -#include -#include - -#ifdef _WINDOWS -#include - -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp - -#else - -#include -#include -#include - -#endif - -#ifndef va_copy -#define va_copy(d,s) ((d) = (s)) -#endif - -// original source: -// https://github.com/facebook/folly/blob/master/folly/String.cpp -// -const std::string vStringFormat(const char *format, va_list args) -{ - std::string output; - va_list tmpargs; - - va_copy(tmpargs, args); - int characters_used = vsnprintf(nullptr, 0, format, tmpargs); - va_end(tmpargs); - - // Looks like we have a valid format string. - if (characters_used > 0) { - output.resize(characters_used + 1); - - va_copy(tmpargs, args); - characters_used = vsnprintf(&output[0], output.capacity(), format, tmpargs); - va_end(tmpargs); - - output.resize(characters_used); - - // We shouldn't have a format error by this point, but I can't imagine what error we - // could have by this point. Still, return empty string; - if (characters_used < 0) { - output.clear(); - } - } - return output; -} - -const std::string str_tolower(std::string s) -{ - std::transform( - s.begin(), s.end(), s.begin(), - [](unsigned char c) { return ::tolower(c); } - ); - return s; -} - -const std::string str_toupper(std::string s) -{ - std::transform( - s.begin(), s.end(), s.begin(), - [](unsigned char c) { return ::toupper(c); } - ); - return s; -} - -const std::string ucfirst(std::string s) -{ - std::string output = s; - if (!s.empty()) { - output[0] = static_cast(::toupper(s[0])); - } - - return output; -} - -const std::string StringFormat(const char *format, ...) -{ - va_list args; - va_start(args, format); - std::string output = vStringFormat(format, args); - va_end(args); - return output; -} - -std::vector SplitString(const std::string &str, const char delim) -{ - std::vector ret; - std::string::size_type start = 0; - auto end = str.find(delim); - while (end != std::string::npos) { - ret.emplace_back(str, start, end - start); - start = end + 1; - end = str.find(delim, start); - } - // this will catch the last word since the string is unlikely to end with a delimiter - if (str.length() > start) { - ret.emplace_back(str, start, str.length() - start); - } - return ret; -} - -// this one takes delimiter length into consideration -std::vector split_string(std::string s, std::string delimiter) -{ - size_t pos_start = 0, pos_end, delim_len = delimiter.length(); - std::string token; - std::vector res; - - while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) { - token = s.substr(pos_start, pos_end - pos_start); - pos_start = pos_end + delim_len; - res.push_back(token); - } - - res.push_back(s.substr(pos_start)); - return res; -} - -std::string get_between(const std::string &s, std::string start_delim, std::string stop_delim) -{ - if (s.find(start_delim) == std::string::npos && s.find(stop_delim) == std::string::npos) { - return ""; - } - - auto first_split = split_string(s, start_delim); - if (!first_split.empty()) { - std::string remaining_block = first_split[1]; - auto second_split = split_string(remaining_block, stop_delim); - if (!second_split.empty()) { - std::string between = second_split[0]; - return between; - } - } - - return ""; -} - -std::string::size_type -search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator) -{ - // this shouldn't go out of bounds, even without obvious bounds checks - auto pos = haystack.find(needle); - while (pos != std::string::npos) { - auto c = haystack[pos + needle.length()]; - if ((c == '\0' || c == deliminator) && (pos == 0 || haystack[pos - 1] == deliminator)) { - return pos; - } - pos = haystack.find(needle, pos + needle.length()); - } - return std::string::npos; -} - -std::string implode(std::string glue, std::vector src) -{ - if (src.empty()) { - return {}; - } - - std::ostringstream output; - std::vector::iterator src_iter; - - for (src_iter = src.begin(); src_iter != src.end(); src_iter++) { - output << *src_iter << glue; - } - - std::string final_output = output.str(); - final_output.resize(output.str().size() - glue.size()); - - return final_output; -} - -std::vector wrap(std::vector &src, std::string character) -{ - std::vector new_vector; - new_vector.reserve(src.size()); - - for (auto &e: src) { - if (e == "null") { - new_vector.emplace_back(e); - continue; - } - - new_vector.emplace_back(character + e + character); - } - - return new_vector; -} - -std::string EscapeString(const std::string &s) -{ - std::string ret; - - size_t sz = s.length(); - for (size_t i = 0; i < sz; ++i) { - char c = s[i]; - switch (c) { - case '\x00': - ret += "\\x00"; - break; - case '\n': - ret += "\\n"; - break; - case '\r': - ret += "\\r"; - break; - case '\\': - ret += "\\\\"; - break; - case '\'': - ret += "\\'"; - break; - case '\"': - ret += "\\\""; - break; - case '\x1a': - ret += "\\x1a"; - break; - default: - ret.push_back(c); - break; - } - } - - return ret; -} - -std::string EscapeString(const char *src, size_t sz) -{ - std::string ret; - - for (size_t i = 0; i < sz; ++i) { - char c = src[i]; - switch (c) { - case '\x00': - ret += "\\x00"; - break; - case '\n': - ret += "\\n"; - break; - case '\r': - ret += "\\r"; - break; - case '\\': - ret += "\\\\"; - break; - case '\'': - ret += "\\'"; - break; - case '\"': - ret += "\\\""; - break; - case '\x1a': - ret += "\\x1a"; - break; - default: - ret.push_back(c); - break; - } - } - - return ret; -} - -bool StringIsNumber(const std::string &s) -{ - try { - auto r = stod(s); - return true; - } - catch (std::exception &) { - return false; - } -} - -void ToLowerString(std::string &s) -{ - std::transform(s.begin(), s.end(), s.begin(), ::tolower); -} - -void ToUpperString(std::string &s) -{ - std::transform(s.begin(), s.end(), s.begin(), ::toupper); -} - -std::string JoinString(const std::vector &ar, const std::string &delim) -{ - std::string ret; - for (size_t i = 0; i < ar.size(); ++i) { - if (i != 0) { - ret += delim; - } - - ret += ar[i]; - } - - return ret; -} - -void find_replace(std::string &string_subject, const std::string &search_string, const std::string &replace_string) -{ - if (string_subject.find(search_string) == std::string::npos) { - return; - } - - size_t start_pos = 0; - while ((start_pos = string_subject.find(search_string, start_pos)) != std::string::npos) { - string_subject.replace(start_pos, search_string.length(), replace_string); - start_pos += replace_string.length(); - } -} - -std::string replace_string(std::string subject, const std::string &search, const std::string &replace) -{ - size_t pos = 0; - while ((pos = subject.find(search, pos)) != std::string::npos) { - subject.replace(pos, search.length(), replace); - pos += replace.length(); - } - return subject; -} - -void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver) -{ - auto split = SplitString(s, ':'); - if (split.size() == 2) { - loginserver = split[0]; - account = split[1]; - } - else if (split.size() == 1) { - account = split[0]; - } -} - -//Const char based - -// normal strncpy doesnt put a null term on copied strings, this one does -// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp -char *strn0cpy(char *dest, const char *source, uint32 size) -{ - if (!dest) { - return 0; - } - if (size == 0 || source == 0) { - dest[0] = 0; - return dest; - } - strncpy(dest, source, size); - dest[size - 1] = 0; - return dest; -} - -// String N w/null Copy Truncated? -// return value =true if entire string(source) fit, false if it was truncated -bool strn0cpyt(char *dest, const char *source, uint32 size) -{ - if (!dest) { - return 0; - } - if (size == 0 || source == 0) { - dest[0] = 0; - return false; - } - strncpy(dest, source, size); - dest[size - 1] = 0; - return (bool) (source[strlen(dest)] == 0); -} - -const char *MakeLowerString(const char *source) -{ - static char str[128]; - if (!source) { - return nullptr; - } - MakeLowerString(source, str); - return str; -} - -void MakeLowerString(const char *source, char *target) -{ - if (!source || !target) { - *target = 0; - return; - } - while (*source) { - *target = tolower(*source); - target++; - source++; - } - *target = 0; -} - -uint32 hextoi(const char *num) -{ - if (num == nullptr) { - return 0; - } - - int len = strlen(num); - if (len < 3) { - return 0; - } - - if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X')) { - return 0; - } - - uint32 ret = 0; - int mul = 1; - for (int i = len - 1; i >= 2; i--) { - if (num[i] >= 'A' && num[i] <= 'F') { - ret += ((num[i] - 'A') + 10) * mul; - } - else if (num[i] >= 'a' && num[i] <= 'f') { - ret += ((num[i] - 'a') + 10) * mul; - } - else if (num[i] >= '0' && num[i] <= '9') { - ret += (num[i] - '0') * mul; - } - else { - return 0; - } - mul *= 16; - } - return ret; -} - -uint64 hextoi64(const char *num) -{ - if (num == nullptr) { - return 0; - } - - int len = strlen(num); - if (len < 3) { - return 0; - } - - if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X')) { - return 0; - } - - uint64 ret = 0; - int mul = 1; - for (int i = len - 1; i >= 2; i--) { - if (num[i] >= 'A' && num[i] <= 'F') { - ret += ((num[i] - 'A') + 10) * mul; - } - else if (num[i] >= 'a' && num[i] <= 'f') { - ret += ((num[i] - 'a') + 10) * mul; - } - else if (num[i] >= '0' && num[i] <= '9') { - ret += (num[i] - '0') * mul; - } - else { - return 0; - } - mul *= 16; - } - return ret; -} - -bool atobool(const char *iBool) -{ - - if (iBool == nullptr) { - return false; - } - if (!strcasecmp(iBool, "true")) { - return true; - } - if (!strcasecmp(iBool, "false")) { - return false; - } - if (!strcasecmp(iBool, "yes")) { - return true; - } - if (!strcasecmp(iBool, "no")) { - return false; - } - if (!strcasecmp(iBool, "on")) { - return true; - } - if (!strcasecmp(iBool, "off")) { - return false; - } - if (!strcasecmp(iBool, "enable")) { - return true; - } - if (!strcasecmp(iBool, "disable")) { - return false; - } - if (!strcasecmp(iBool, "enabled")) { - return true; - } - if (!strcasecmp(iBool, "disabled")) { - return false; - } - if (!strcasecmp(iBool, "y")) { - return true; - } - if (!strcasecmp(iBool, "n")) { - return false; - } - if (atoi(iBool)) { - return true; - } - return false; -} - -// removes the crap and turns the underscores into spaces. -char *CleanMobName(const char *in, char *out) -{ - unsigned i, j; - - for (i = j = 0; i < strlen(in); i++) { - // convert _ to space.. any other conversions like this? I *think* this - // is the only non alpha char that's not stripped but converted. - if (in[i] == '_') { - out[j++] = ' '; - } - else { - if (isalpha(in[i]) || (in[i] == '`')) { // numbers, #, or any other crap just gets skipped - out[j++] = in[i]; - } - } - } - out[j] = 0; // terimnate the string before returning it - return out; -} - - -void RemoveApostrophes(std::string &s) -{ - for (unsigned int i = 0; i < s.length(); ++i) - if (s[i] == '\'') { - s[i] = '_'; - } -} - -char *RemoveApostrophes(const char *s) -{ - auto NewString = new char[strlen(s) + 1]; - - strcpy(NewString, s); - - for (unsigned int i = 0; i < strlen(NewString); ++i) - if (NewString[i] == '\'') { - NewString[i] = '_'; - } - - return NewString; -} - -const char *ConvertArray(int64 input, char *returnchar) -{ - sprintf(returnchar, "%lld", input); - return returnchar; -} - -const char *ConvertArrayF(float input, char *returnchar) -{ - sprintf(returnchar, "%0.2f", input); - return returnchar; -} - -bool isAlphaNumeric(const char *text) -{ - for (unsigned int charIndex = 0; charIndex < strlen(text); charIndex++) { - if ((text[charIndex] < 'a' || text[charIndex] > 'z') && - (text[charIndex] < 'A' || text[charIndex] > 'Z') && - (text[charIndex] < '0' || text[charIndex] > '9')) { - return false; - } - } - - return true; -} - -// Function to convert single digit or two digit number into words -std::string convert2digit(int n, std::string suffix) -{ - // if n is zero - if (n == 0) { - return ""; - } - - // split n if it is more than 19 - if (n > 19) { - return NUM_TO_ENGLISH_Y[n / 10] + NUM_TO_ENGLISH_X[n % 10] + suffix; - } - else { - return NUM_TO_ENGLISH_X[n] + suffix; - } -} - -// Function to convert a given number (max 9-digits) into words -std::string numberToWords(unsigned long long int n) -{ - // string to store word representation of given number - std::string res; - - // this handles digits at ones & tens place - res = convert2digit((n % 100), ""); - - if (n > 100 && n % 100) { - res = "and " + res; - } - - // this handles digit at hundreds place - res = convert2digit(((n / 100) % 10), "Hundred ") + res; - - // this handles digits at thousands & tens thousands place - res = convert2digit(((n / 1000) % 100), "Thousand ") + res; - - // this handles digits at hundred thousands & one millions place - res = convert2digit(((n / 100000) % 100), "Lakh, ") + res; - - // this handles digits at ten millions & hundred millions place - res = convert2digit((n / 10000000) % 100, "Crore, ") + res; - - // this handles digits at ten millions & hundred millions place - res = convert2digit((n / 1000000000) % 100, "Billion, ") + res; - - return res; -} - -// first letter capitalized and rest made lower case -std::string FormatName(const std::string &char_name) -{ - std::string formatted(char_name); - if (!formatted.empty()) { - std::transform(formatted.begin(), formatted.end(), formatted.begin(), ::tolower); - formatted[0] = ::toupper(formatted[0]); - } - return formatted; -} - -bool IsAllowedWorldServerCharacterList(char c) -{ - const char *valid_characters = ":[](){}.!@#$%^&*-=+<>/\\|'\""; - if (strchr(valid_characters, c)) { - return true; - } - - return false; -} - -void SanitizeWorldServerName(char *name) -{ - std::string server_long_name = name; - - strcpy(name, SanitizeWorldServerName(server_long_name).c_str()); -} - -std::string SanitizeWorldServerName(std::string server_long_name) -{ - server_long_name.erase( - std::remove_if( - server_long_name.begin(), - server_long_name.end(), - [](char c) { - return !(std::isalpha(c) || std::isalnum(c) || std::isspace(c) || IsAllowedWorldServerCharacterList(c)); - } - ), server_long_name.end() - ); - - server_long_name = trim(server_long_name); - - // bad word filter - for (auto &piece: split_string(server_long_name, " ")) { - for (auto &word: GetBadWords()) { - // for shorter words that can actually be part of legitimate words - // make sure that it isn't part of another word by matching on a space - if (str_tolower(piece) == word) { - find_replace( - server_long_name, - piece, - repeat("*", (int) word.length()) - ); - continue; - } - - auto pos = str_tolower(piece).find(word); - if (str_tolower(piece).find(word) != std::string::npos && piece.length() > 4 && word.length() > 4) { - auto found_word = piece.substr(pos, word.length()); - std::string replaced_piece = piece.substr(pos, word.length()); - - find_replace( - server_long_name, - replaced_piece, - repeat("*", (int) word.length()) - ); - } - } - } - - return server_long_name; -} - -std::string repeat(std::string s, int n) -{ - std::string s1 = s; - for (int i = 1; i < n; i++) { - s += s1; - } - - return s; -} - -std::vector GetBadWords() -{ - return std::vector{ - "2g1c", - "acrotomophilia", - "anal", - "anilingus", - "anus", - "apeshit", - "arsehole", - "ass", - "asshole", - "assmunch", - "autoerotic", - "babeland", - "bangbros", - "bangbus", - "bareback", - "barenaked", - "bastard", - "bastardo", - "bastinado", - "bbw", - "bdsm", - "beaner", - "beaners", - "beaver", - "beastiality", - "bestiality", - "bimbos", - "birdlock", - "bitch", - "bitches", - "blowjob", - "blumpkin", - "bollocks", - "bondage", - "boner", - "boob", - "boobs", - "bukkake", - "bulldyke", - "bullshit", - "bung", - "bunghole", - "busty", - "butt", - "buttcheeks", - "butthole", - "camel toe", - "camgirl", - "camslut", - "camwhore", - "carpetmuncher", - "cialis", - "circlejerk", - "clit", - "clitoris", - "clusterfuck", - "cock", - "cocks", - "coprolagnia", - "coprophilia", - "cornhole", - "coon", - "coons", - "creampie", - "cum", - "cumming", - "cumshot", - "cumshots", - "cunnilingus", - "cunt", - "darkie", - "daterape", - "deepthroat", - "dendrophilia", - "dick", - "dildo", - "dingleberry", - "dingleberries", - "doggiestyle", - "doggystyle", - "dolcett", - "domination", - "dominatrix", - "dommes", - "hump", - "dvda", - "ecchi", - "ejaculation", - "erotic", - "erotism", - "escort", - "eunuch", - "fag", - "faggot", - "fecal", - "felch", - "fellatio", - "feltch", - "femdom", - "figging", - "fingerbang", - "fingering", - "fisting", - "footjob", - "frotting", - "fuck", - "fuckin", - "fucking", - "fucktards", - "fudgepacker", - "futanari", - "gangbang", - "gangbang", - "gaysex", - "genitals", - "goatcx", - "goatse", - "gokkun", - "goodpoop", - "goregasm", - "grope", - "g-spot", - "guro", - "handjob", - "hentai", - "homoerotic", - "honkey", - "hooker", - "horny", - "humping", - "incest", - "intercourse", - "jailbait", - "jigaboo", - "jiggaboo", - "jiggerboo", - "jizz", - "juggs", - "kike", - "kinbaku", - "kinkster", - "kinky", - "knobbing", - "livesex", - "lolita", - "lovemaking", - "masturbate", - "masturbating", - "masturbation", - "milf", - "mong", - "motherfucker", - "muffdiving", - "nambla", - "nawashi", - "negro", - "neonazi", - "nigga", - "nigger", - "nimphomania", - "nipple", - "nipples", - "nsfw", - "nude", - "nudity", - "nutten", - "nympho", - "nymphomania", - "octopussy", - "omorashi", - "orgasm", - "orgy", - "paedophile", - "paki", - "panties", - "panty", - "pedobear", - "pedophile", - "pegging", - "penis", - "pikey", - "pissing", - "pisspig", - "playboy", - "ponyplay", - "poof", - "poon", - "poontang", - "punany", - "poopchute", - "porn", - "porno", - "pornography", - "pthc", - "pubes", - "pussy", - "queaf", - "queef", - "quim", - "raghead", - "rape", - "raping", - "rapist", - "rectum", - "rimjob", - "rimming", - "sadism", - "santorum", - "scat", - "schlong", - "scissoring", - "semen", - "sex", - "sexcam", - "sexo", - "sexy", - "sexual", - "sexually", - "sexuality", - "shemale", - "shibari", - "shit", - "shitblimp", - "shitty", - "shota", - "shrimping", - "skeet", - "slanteye", - "slut", - "s&m", - "smut", - "snatch", - "snowballing", - "sodomize", - "sodomy", - "spastic", - "spic", - "splooge", - "spooge", - "spunk", - "strapon", - "strappado", - "suck", - "sucks", - "swastika", - "swinger", - "threesome", - "throating", - "thumbzilla", - "tight white", - "tit", - "tits", - "titties", - "titty", - "topless", - "tosser", - "towelhead", - "tranny", - "tribadism", - "tubgirl", - "tushy", - "twat", - "twink", - "twinkie", - "undressing", - "upskirt", - "urophilia", - "vagina", - "viagra", - "vibrator", - "vorarephilia", - "voyeur", - "voyeurweb", - "voyuer", - "vulva", - "wank", - "wetback", - "whore", - "worldsex", - "xx", - "xxx", - "yaoi", - "yiffy", - "zoophilia" - }; -} - -bool contains(std::vector container, std::string element) -{ - return std::find(container.begin(), container.end(), element) != container.end(); -} - -std::string ConvertSecondsToTime(int duration, bool is_milliseconds) -{ - if (duration <= 0) { - return "Unknown"; - } - - if (is_milliseconds && duration < 1000) { - return fmt::format( - "{} Millisecond{}", - duration, - duration != 1 ? "s" : "" - ); - } - - int timer_length = ( - is_milliseconds ? - static_cast(std::ceil(static_cast(duration) / 1000.0f)) : - duration - ); - - int days = int(timer_length / 86400); - timer_length %= 86400; - int hours = int(timer_length / 3600); - timer_length %= 3600; - int minutes = int(timer_length / 60); - timer_length %= 60; - int seconds = timer_length; - std::string time_string = "Unknown"; - std::string day_string = (days == 1 ? "Day" : "Days"); - std::string hour_string = (hours == 1 ? "Hour" : "Hours"); - std::string minute_string = (minutes == 1 ? "Minute" : "Minutes"); - std::string second_string = (seconds == 1 ? "Second" : "Seconds"); - if (days && hours && minutes && seconds) { // DHMS - time_string = fmt::format( - "{} {}, {} {}, {} {}, and {} {}", - days, - day_string, - hours, - hour_string, - minutes, - minute_string, - seconds, - second_string - ); - } else if (days && hours && minutes && !seconds) { // DHM - time_string = fmt::format( - "{} {}, {} {}, and {} {}", - days, - day_string, - hours, - hour_string, - minutes, - minute_string - ); - } else if (days && hours && !minutes && seconds) { // DHS - time_string = fmt::format( - "{} {}, {} {}, and {} {}", - days, - day_string, - hours, - hour_string, - seconds, - second_string - ); - } else if (days && hours && !minutes && !seconds) { // DH - time_string = fmt::format( - "{} {} and {} {}", - days, - day_string, - hours, - hour_string - ); - } else if (days && !hours && minutes && seconds) { // DMS - time_string = fmt::format( - "{} {}, {} {}, and {} {}", - days, - day_string, - minutes, - minute_string, - seconds, - second_string - ); - } else if (days && !hours && minutes && !seconds) { // DM - time_string = fmt::format( - "{} {} and {} {}", - days, - day_string, - minutes, - minute_string - ); - } else if (days && !hours && !minutes && seconds) { // DS - time_string = fmt::format( - "{} {} and {} {}", - days, - day_string, - seconds, - second_string - ); - } else if (days && !hours && !minutes && !seconds) { // D - time_string = fmt::format( - "{} {}", - days, - day_string - ); - } else if (!days && hours && minutes && seconds) { // HMS - time_string = fmt::format( - "{} {}, {} {}, and {} {}", - hours, - hour_string, - minutes, - minute_string, - seconds, - second_string - ); - } else if (!days && hours && minutes && !seconds) { // HM - time_string = fmt::format( - "{} {} and {} {}", - hours, - hour_string, - minutes, - minute_string - ); - } else if (!days && hours && !minutes && seconds) { // HS - time_string = fmt::format( - "{} {} and {} {}", - hours, - hour_string, - seconds, - second_string - ); - } else if (!days && hours && !minutes && !seconds) { // H - time_string = fmt::format( - "{} {}", - hours, - hour_string - ); - } else if (!days && !hours && minutes && seconds) { // MS - time_string = fmt::format( - "{} {} and {} {}", - minutes, - minute_string, - seconds, - second_string - ); - } else if (!days && !hours && minutes && !seconds) { // M - time_string = fmt::format( - "{} {}", - minutes, - minute_string - ); - } else if (!days && !hours && !minutes && seconds) { // S - time_string = fmt::format( - "{} {}", - seconds, - second_string - ); - } - return time_string; -} - -std::string ConvertMoneyToString(uint32 platinum, uint32 gold, uint32 silver, uint32 copper) -{ - std::string money_string = "Unknown"; - if (copper && silver && gold && platinum) { // CSGP - money_string = fmt::format( - "{} Platinum, {} Gold, {} Silver, and {} Copper", - platinum, - gold, - silver, - copper - ); - } else if (copper && silver && gold && !platinum) { // CSG - money_string = fmt::format( - "{} Gold, {} Silver, and {} Copper", - gold, - silver, - copper - ); - } else if (copper && silver && !gold && !platinum) { // CS - money_string = fmt::format( - "{} Silver and {} Copper", - silver, - copper - ); - } else if (!copper && silver && gold && platinum) { // SGP - money_string = fmt::format( - "{} Platinum, {} Gold, and {} Silver", - platinum, - gold, - silver - ); - } else if (!copper && silver && gold && !platinum) { // SG - money_string = fmt::format( - "{} Gold and {} Silver", - gold, - silver - ); - } else if (copper && !silver && gold && platinum) { // CGP - money_string = fmt::format( - "{} Platinum, {} Gold, and {} Copper", - platinum, - gold, - copper - ); - } else if (copper && !silver && gold && !platinum) { // CG - money_string = fmt::format( - "{} Gold and {} Copper", - gold, - copper - ); - } else if (!copper && !silver && gold && platinum) { // GP - money_string = fmt::format( - "{} Platinum and {} Gold", - platinum, - gold - ); - } else if (!copper && !silver && !gold && platinum) { // P - money_string = fmt::format( - "{} Platinum", - platinum - ); - } else if (!copper && !silver && gold && !platinum) { // G - money_string = fmt::format( - "{} Gold", - gold - ); - } else if (!copper && silver && !gold && !platinum) { // S - money_string = fmt::format( - "{} Silver", - silver - ); - } else if (copper && !silver && !gold && !platinum) { // C - money_string = fmt::format( - "{} Copper", - copper - ); - } - return money_string; -} - -std::string commify(const std::string &number) { - std::string temp_string; - - auto string_length = static_cast(number.length()); - - int i = 0; - for (i = string_length - 3; i >= 0; i -= 3) { - if (i > 0) { - temp_string = "," + number.substr(static_cast(i), 3) + temp_string; - } else { - temp_string = number.substr(static_cast(i), 3) + temp_string; - } - } - - if (i < 0) { - temp_string = number.substr(0, static_cast(3 + i)) + temp_string; - } - - return temp_string; -} diff --git a/common/string_util.h b/common/string_util.h deleted file mode 100644 index c0451f655..000000000 --- a/common/string_util.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _STRINGUTIL_H_ -#define _STRINGUTIL_H_ - -#include -#include -#include -#include -#include - -#ifndef _WIN32 -// this doesn't appear to affect linux-based systems..need feedback for _WIN64 -#include -#endif - -#ifdef _WINDOWS -#include -#include -#include -#endif - -#include "types.h" - -//std::string based -const std::string str_tolower(std::string s); -const std::string str_toupper(std::string s); -const std::string ucfirst(std::string s); -const std::string StringFormat(const char* format, ...); -const std::string vStringFormat(const char* format, va_list args); -std::vector wrap(std::vector &src, std::string character); -std::string implode(std::string glue, std::vector src); -std::string convert2digit(int n, std::string suffix); -std::string numberToWords(unsigned long long int n); -std::string ConvertMoneyToString(uint32 platinum, uint32 gold = 0, uint32 silver = 0, uint32 copper = 0); -std::string ConvertSecondsToTime(int duration, bool is_milliseconds = false); -inline std::string ConvertMillisecondsToTime(int duration) { - return ConvertSecondsToTime(duration, true); -} - -// For converstion of numerics into English -// Used for grid nodes, as NPC names remove numerals. -// But general purpose - -const std::string NUM_TO_ENGLISH_X[] = { "", "One ", "Two ", "Three ", "Four ", - "Five ", "Six ", "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ", - "Twelve ", "Thirteen ", "Fourteen ", "Fifteen ", - "Sixteen ", "Seventeen ", "Eighteen ", "Nineteen " }; - -const std::string NUM_TO_ENGLISH_Y[] = { "", "", "Twenty ", "Thirty ", "Forty ", - "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety " }; - -/** - * @param str - * @param chars - * @return - */ -inline std::string <rim(std::string &str, const std::string &chars = "\t\n\v\f\r ") -{ - str.erase(0, str.find_first_not_of(chars)); - return str; -} - -/** - * @param str - * @param chars - * @return - */ -inline std::string &rtrim(std::string &str, const std::string &chars = "\t\n\v\f\r ") -{ - str.erase(str.find_last_not_of(chars) + 1); - return str; -} - -/** - * @param str - * @param chars - * @return - */ -inline std::string &trim(std::string &str, const std::string &chars = "\t\n\v\f\r ") -{ - return ltrim(rtrim(str, chars), chars); -} - -template -std::string implode(const std::string &glue, const std::pair &encapsulation, const std::vector &src) -{ - if (src.empty()) { - return {}; - } - - std::ostringstream oss; - - for (const T &src_iter : src) { - oss << encapsulation.first << src_iter << encapsulation.second << glue; - } - - std::string output(oss.str()); - output.resize(output.size() - glue.size()); - - return output; -} - -// _WIN32 builds require that #include be included in whatever code file the invocation is made from (no header files) -template -std::vector join_pair(const std::string &glue, const std::pair &encapsulation, const std::vector> &src) -{ - if (src.empty()) { - return {}; - } - - std::vector output; - - for (const std::pair &src_iter : src) { - output.push_back( - - fmt::format( - "{}{}{}{}{}{}{}", - encapsulation.first, - src_iter.first, - encapsulation.second, - glue, - encapsulation.first, - src_iter.second, - encapsulation.second - ) - ); - } - - return output; -} - -// _WIN32 builds require that #include be included in whatever code file the invocation is made from (no header files) -template -std::vector join_tuple(const std::string &glue, const std::pair &encapsulation, const std::vector> &src) -{ - if (src.empty()) { - return {}; - } - - std::vector output; - - for (const std::tuple &src_iter : src) { - - output.push_back( - - fmt::format( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - encapsulation.first, - std::get<0>(src_iter), - encapsulation.second, - glue, - encapsulation.first, - std::get<1>(src_iter), - encapsulation.second, - glue, - encapsulation.first, - std::get<2>(src_iter), - encapsulation.second, - glue, - encapsulation.first, - std::get<3>(src_iter), - encapsulation.second - ) - ); - } - - return output; -} - -std::vector SplitString(const std::string &s, const char delim = ','); -std::vector split_string(std::string s, std::string delimiter); -std::string get_between(const std::string &s, std::string start_delim, std::string stop_delim); -std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator = ','); -std::string EscapeString(const char *src, size_t sz); -std::string EscapeString(const std::string &s); -bool StringIsNumber(const std::string &s); -void ToLowerString(std::string &s); -void ToUpperString(std::string &s); -std::string JoinString(const std::vector& ar, const std::string &delim); -void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string); -std::string replace_string(std::string subject, const std::string &search, const std::string &replace); -void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver); -std::string commify(const std::string &number); - -//const char based - -bool atobool(const char* iBool); -bool isAlphaNumeric(const char *text); -bool strn0cpyt(char* dest, const char* source, uint32 size); -char *CleanMobName(const char *in, char *out); -char *RemoveApostrophes(const char *s); -char* strn0cpy(char* dest, const char* source, uint32 size); -const char *ConvertArray(int64 input, char *returnchar); -const char *ConvertArrayF(float input, char *returnchar); -const char *MakeLowerString(const char *source); -uint32 hextoi(const char* num); -uint64 hextoi64(const char* num); -void MakeLowerString(const char *source, char *target); -void RemoveApostrophes(std::string &s); -std::string convert2digit(int n, std::string suffix); -std::string numberToWords(unsigned long long int n); -std::string FormatName(const std::string& char_name); -bool IsAllowedWorldServerCharacterList(char c); -void SanitizeWorldServerName(char *name); -std::string SanitizeWorldServerName(std::string server_long_name); -std::string repeat(std::string s, int n); -std::vector GetBadWords(); -bool contains(std::vector container, std::string element); - -template -auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result) -{ - for (; first != last; ++first) { - if(*first == '_') { - *result = ' '; - } else if (isalpha(*first) || *first == '`') { - *result = *first; - } - } - return result; -} - -#endif diff --git a/common/strings.cpp b/common/strings.cpp new file mode 100644 index 000000000..2b31a3881 --- /dev/null +++ b/common/strings.cpp @@ -0,0 +1,765 @@ +// for folly stuff +/* + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// for our stuff +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "strings.h" +#include +#include +#include + +#include +#include +#include + +//Const char based +#include "strings_legacy.cpp" // legacy c functions +#include "strings_misc.cpp" // anything non "Strings" scoped + +std::vector Strings::Split(const std::string &str, const char delim) +{ + std::vector ret; + std::string::size_type start = 0; + auto end = str.find(delim); + while (end != std::string::npos) { + ret.emplace_back(str, start, end - start); + start = end + 1; + end = str.find(delim, start); + } + // this will catch the last word since the string is unlikely to end with a delimiter + if (str.length() > start) { + ret.emplace_back(str, start, str.length() - start); + } + return ret; +} + +// this one takes delimiter length into consideration +std::vector Strings::Split(const std::string& s, const std::string& delimiter) +{ + size_t pos_start = 0, pos_end, delim_len = delimiter.length(); + std::string token; + std::vector res; + + while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) { + token = s.substr(pos_start, pos_end - pos_start); + pos_start = pos_end + delim_len; + res.push_back(token); + } + + res.push_back(s.substr(pos_start)); + return res; +} + +std::string Strings::Strings::GetBetween(const std::string &s, std::string start_delim, std::string stop_delim) +{ + if (s.find(start_delim) == std::string::npos && s.find(stop_delim) == std::string::npos) { + return ""; + } + + auto first_split = Strings::Split(s, start_delim); + if (!first_split.empty()) { + std::string remaining_block = first_split[1]; + auto second_split = Strings::Split(remaining_block, stop_delim); + if (!second_split.empty()) { + std::string between = second_split[0]; + return between; + } + } + + return ""; +} + +std::string::size_type +Strings::SearchDelim(const std::string &haystack, const std::string &needle, const char deliminator) +{ + // this shouldn't go out of bounds, even without obvious bounds checks + auto pos = haystack.find(needle); + while (pos != std::string::npos) { + auto c = haystack[pos + needle.length()]; + if ((c == '\0' || c == deliminator) && (pos == 0 || haystack[pos - 1] == deliminator)) { + return pos; + } + pos = haystack.find(needle, pos + needle.length()); + } + return std::string::npos; +} + + +std::string Strings::Implode(std::string glue, std::vector src) +{ + if (src.empty()) { + return {}; + } + + std::ostringstream output; + std::vector::iterator src_iter; + + for (src_iter = src.begin(); src_iter != src.end(); src_iter++) { + output << *src_iter << glue; + } + + std::string final_output = output.str(); + final_output.resize(output.str().size() - glue.size()); + + return final_output; +} + +std::vector wrap(std::vector &src, std::string character) +{ + std::vector new_vector; + new_vector.reserve(src.size()); + + for (auto &e: src) { + if (e == "null") { + new_vector.emplace_back(e); + continue; + } + + new_vector.emplace_back(character + e + character); + } + + return new_vector; +} + +std::string Strings::Escape(const std::string &s) +{ + std::string ret; + + size_t sz = s.length(); + for (size_t i = 0; i < sz; ++i) { + char c = s[i]; + switch (c) { + case '\x00': + ret += "\\x00"; + break; + case '\n': + ret += "\\n"; + break; + case '\r': + ret += "\\r"; + break; + case '\\': + ret += "\\\\"; + break; + case '\'': + ret += "\\'"; + break; + case '\"': + ret += "\\\""; + break; + case '\x1a': + ret += "\\x1a"; + break; + default: + ret.push_back(c); + break; + } + } + + return ret; +} + +bool Strings::IsNumber(const std::string &s) +{ + try { + auto r = stoi(s); + return true; + } + catch (std::exception &) { + return false; + } +} + +bool Strings::IsFloat(const std::string &s) +{ + try { + auto r = stof(s); + return true; + } + catch (std::exception &) { + return false; + } +} + +std::string Strings::Join(const std::vector &ar, const std::string &delim) +{ + std::string ret; + for (size_t i = 0; i < ar.size(); ++i) { + if (i != 0) { + ret += delim; + } + + ret += ar[i]; + } + + return ret; +} + +void +Strings::FindReplace(std::string &string_subject, const std::string &search_string, const std::string &replace_string) +{ + if (string_subject.find(search_string) == std::string::npos) { + return; + } + + size_t start_pos = 0; + while ((start_pos = string_subject.find(search_string, start_pos)) != std::string::npos) { + string_subject.replace(start_pos, search_string.length(), replace_string); + start_pos += replace_string.length(); + } +} + +std::string Strings::Replace(std::string subject, const std::string &search, const std::string &replace) +{ + size_t pos = 0; + while ((pos = subject.find(search, pos)) != std::string::npos) { + subject.replace(pos, search.length(), replace); + pos += replace.length(); + } + return subject; +} + +std::string Strings::Repeat(std::string s, int n) +{ + std::string s1 = s; + for (int i = 1; i < n; i++) { + s += s1; + } + + return s; +} + +bool Strings::Contains(std::vector container, std::string element) +{ + return std::find(container.begin(), container.end(), element) != container.end(); +} + +std::string Strings::Commify(const std::string &number) +{ + std::string temp_string; + + auto string_length = static_cast(number.length()); + + int i = 0; + for (i = string_length - 3; i >= 0; i -= 3) { + if (i > 0) { + temp_string = "," + number.substr(static_cast(i), 3) + temp_string; + } + else { + temp_string = number.substr(static_cast(i), 3) + temp_string; + } + } + + if (i < 0) { + temp_string = number.substr(0, static_cast(3 + i)) + temp_string; + } + + return temp_string; +} + +const std::string Strings::ToLower(std::string s) +{ + std::transform( + s.begin(), s.end(), s.begin(), + [](unsigned char c) { return ::tolower(c); } + ); + return s; +} +const std::string Strings::ToUpper(std::string s) +{ + std::transform( + s.begin(), s.end(), s.begin(), + [](unsigned char c) { return ::toupper(c); } + ); + return s; +} +const std::string Strings::UcFirst(std::string s) +{ + std::string output = s; + if (!s.empty()) { + output[0] = static_cast(::toupper(s[0])); + } + + return output; +} + + +std::vector Strings::Wrap(std::vector &src, std::string character) +{ + std::vector new_vector; + new_vector.reserve(src.size()); + + for (auto &e: src) { + if (e == "null") { + new_vector.emplace_back(e); + continue; + } + + new_vector.emplace_back(character + e + character); + } + + return new_vector; +} + +std::string Strings::NumberToWords(unsigned long long int n) +{ + // string to store word representation of given number + std::string res; + + // this handles digits at ones & tens place + res = Strings::ConvertToDigit((n % 100), ""); + + if (n > 100 && n % 100) { + res = "and " + res; + } + + // this handles digit at hundreds place + res = Strings::ConvertToDigit(((n / 100) % 10), "Hundred ") + res; + + // this handles digits at thousands & tens thousands place + res = Strings::ConvertToDigit(((n / 1000) % 100), "Thousand ") + res; + + // this handles digits at hundred thousands & one millions place + res = Strings::ConvertToDigit(((n / 100000) % 100), "Lakh, ") + res; + + // this handles digits at ten millions & hundred millions place + res = Strings::ConvertToDigit((n / 10000000) % 100, "Crore, ") + res; + + // this handles digits at ten millions & hundred millions place + res = Strings::ConvertToDigit((n / 1000000000) % 100, "Billion, ") + res; + + return res; +} +std::string Strings::Money(uint32 platinum, uint32 gold, uint32 silver, uint32 copper) +{ + std::string money_string = "Unknown"; + if (copper && silver && gold && platinum) { // CSGP + money_string = fmt::format( + "{} Platinum, {} Gold, {} Silver, and {} Copper", + Strings::Commify(std::to_string(platinum)), + Strings::Commify(std::to_string(gold)), + Strings::Commify(std::to_string(silver)), + Strings::Commify(std::to_string(copper)) + ); + } + else if (copper && silver && !gold && platinum) { // CSP + money_string = fmt::format( + "{} Platinum, {} Silver, and {} Copper", + Strings::Commify(std::to_string(platinum)), + Strings::Commify(std::to_string(silver)), + Strings::Commify(std::to_string(copper)) + ); + } + else if (copper && silver && gold && !platinum) { // CSG + money_string = fmt::format( + "{} Gold, {} Silver, and {} Copper", + Strings::Commify(std::to_string(gold)), + Strings::Commify(std::to_string(silver)), + Strings::Commify(std::to_string(copper)) + ); + } + else if (copper && !silver && !gold && platinum) { // CP + money_string = fmt::format( + "{} Platinum and {} Copper", + Strings::Commify(std::to_string(platinum)), + Strings::Commify(std::to_string(copper)) + ); + } + else if (copper && silver && !gold && !platinum) { // CS + money_string = fmt::format( + "{} Silver and {} Copper", + Strings::Commify(std::to_string(silver)), + Strings::Commify(std::to_string(copper)) + ); + } + else if (!copper && silver && gold && platinum) { // SGP + money_string = fmt::format( + "{} Platinum, {} Gold, and {} Silver", + Strings::Commify(std::to_string(platinum)), + Strings::Commify(std::to_string(gold)), + Strings::Commify(std::to_string(silver)) + ); + } + else if (!copper && silver && !gold && platinum) { // SP + money_string = fmt::format( + "{} Platinum and {} Silver", + Strings::Commify(std::to_string(platinum)), + Strings::Commify(std::to_string(silver)) + ); + } + else if (!copper && silver && gold && !platinum) { // SG + money_string = fmt::format( + "{} Gold and {} Silver", + Strings::Commify(std::to_string(gold)), + Strings::Commify(std::to_string(silver)) + ); + } + else if (copper && !silver && gold && platinum) { // CGP + money_string = fmt::format( + "{} Platinum, {} Gold, and {} Copper", + Strings::Commify(std::to_string(platinum)), + Strings::Commify(std::to_string(gold)), + Strings::Commify(std::to_string(copper)) + ); + } + else if (copper && !silver && gold && !platinum) { // CG + money_string = fmt::format( + "{} Gold and {} Copper", + Strings::Commify(std::to_string(gold)), + Strings::Commify(std::to_string(copper)) + ); + } + else if (!copper && !silver && gold && platinum) { // GP + money_string = fmt::format( + "{} Platinum and {} Gold", + Strings::Commify(std::to_string(platinum)), + Strings::Commify(std::to_string(gold)) + ); + } + else if (!copper && !silver && !gold && platinum) { // P + money_string = fmt::format( + "{} Platinum", + Strings::Commify(std::to_string(platinum)) + ); + } + else if (!copper && !silver && gold && !platinum) { // G + money_string = fmt::format( + "{} Gold", + Strings::Commify(std::to_string(gold)) + ); + } + else if (!copper && silver && !gold && !platinum) { // S + money_string = fmt::format( + "{} Silver", + Strings::Commify(std::to_string(silver)) + ); + } + else if (copper && !silver && !gold && !platinum) { // C + money_string = fmt::format( + "{} Copper", + Strings::Commify(std::to_string(copper)) + ); + } + return money_string; +} +std::string Strings::SecondsToTime(int duration, bool is_milliseconds) +{ + if (duration <= 0) { + return "Unknown"; + } + + if (is_milliseconds && duration < 1000) { + return fmt::format( + "{} Millisecond{}", + duration, + duration != 1 ? "s" : "" + ); + } + + int timer_length = ( + is_milliseconds ? + static_cast(std::ceil(static_cast(duration) / 1000.0f)) : + duration + ); + + int days = int(timer_length / 86400); + timer_length %= 86400; + int hours = int(timer_length / 3600); + timer_length %= 3600; + int minutes = int(timer_length / 60); + timer_length %= 60; + int seconds = timer_length; + std::string time_string = "Unknown"; + std::string day_string = (days == 1 ? "Day" : "Days"); + std::string hour_string = (hours == 1 ? "Hour" : "Hours"); + std::string minute_string = (minutes == 1 ? "Minute" : "Minutes"); + std::string second_string = (seconds == 1 ? "Second" : "Seconds"); + if (days && hours && minutes && seconds) { // DHMS + time_string = fmt::format( + "{} {}, {} {}, {} {}, and {} {}", + days, + day_string, + hours, + hour_string, + minutes, + minute_string, + seconds, + second_string + ); + } + else if (days && hours && minutes && !seconds) { // DHM + time_string = fmt::format( + "{} {}, {} {}, and {} {}", + days, + day_string, + hours, + hour_string, + minutes, + minute_string + ); + } + else if (days && hours && !minutes && seconds) { // DHS + time_string = fmt::format( + "{} {}, {} {}, and {} {}", + days, + day_string, + hours, + hour_string, + seconds, + second_string + ); + } + else if (days && hours && !minutes && !seconds) { // DH + time_string = fmt::format( + "{} {} and {} {}", + days, + day_string, + hours, + hour_string + ); + } + else if (days && !hours && minutes && seconds) { // DMS + time_string = fmt::format( + "{} {}, {} {}, and {} {}", + days, + day_string, + minutes, + minute_string, + seconds, + second_string + ); + } + else if (days && !hours && minutes && !seconds) { // DM + time_string = fmt::format( + "{} {} and {} {}", + days, + day_string, + minutes, + minute_string + ); + } + else if (days && !hours && !minutes && seconds) { // DS + time_string = fmt::format( + "{} {} and {} {}", + days, + day_string, + seconds, + second_string + ); + } + else if (days && !hours && !minutes && !seconds) { // D + time_string = fmt::format( + "{} {}", + days, + day_string + ); + } + else if (!days && hours && minutes && seconds) { // HMS + time_string = fmt::format( + "{} {}, {} {}, and {} {}", + hours, + hour_string, + minutes, + minute_string, + seconds, + second_string + ); + } + else if (!days && hours && minutes && !seconds) { // HM + time_string = fmt::format( + "{} {} and {} {}", + hours, + hour_string, + minutes, + minute_string + ); + } + else if (!days && hours && !minutes && seconds) { // HS + time_string = fmt::format( + "{} {} and {} {}", + hours, + hour_string, + seconds, + second_string + ); + } + else if (!days && hours && !minutes && !seconds) { // H + time_string = fmt::format( + "{} {}", + hours, + hour_string + ); + } + else if (!days && !hours && minutes && seconds) { // MS + time_string = fmt::format( + "{} {} and {} {}", + minutes, + minute_string, + seconds, + second_string + ); + } + else if (!days && !hours && minutes && !seconds) { // M + time_string = fmt::format( + "{} {}", + minutes, + minute_string + ); + } + else if (!days && !hours && !minutes && seconds) { // S + time_string = fmt::format( + "{} {}", + seconds, + second_string + ); + } + return time_string; +} + +std::string &Strings::LTrim(std::string &str, const std::string &chars) +{ + str.erase(0, str.find_first_not_of(chars)); + return str; +} + +std::string Strings::MillisecondsToTime(int duration) +{ + return SecondsToTime(duration, true); +} + +std::string &Strings::RTrim(std::string &str, const std::string &chars) +{ + str.erase(str.find_last_not_of(chars) + 1); + return str; +} + +std::string &Strings::Trim(std::string &str, const std::string &chars) +{ + return LTrim(RTrim(str, chars), chars); +} + +// Function to convert single digit or two digit number into words +std::string Strings::ConvertToDigit(int n, std::string suffix) +{ + // if n is zero + if (n == 0) { + return ""; + } + + // split n if it is more than 19 + if (n > 19) { + return NUM_TO_ENGLISH_Y[n / 10] + NUM_TO_ENGLISH_X[n % 10] + suffix; + } + else { + return NUM_TO_ENGLISH_X[n] + suffix; + } +} +bool Strings::Contains(const std::string& subject, const std::string& search) +{ + return subject.find(search) != std::string::npos; +} + +uint32 Strings::TimeToSeconds(std::string time_string) +{ + if (time_string.empty()) { + return 0; + } + + time_string = Strings::ToLower(time_string); + + if (time_string == "f") { + return 0; + } + + std::string time_unit = time_string; + + time_unit.erase( + remove_if( + time_unit.begin(), + time_unit.end(), + [](char c) { + return !isdigit(c); + } + ), + time_unit.end() + ); + + auto unit = std::stoul(time_unit); + uint32 duration = 0; + + if (Strings::Contains(time_string, "s")) { + duration = unit; + } else if (Strings::Contains(time_string, "m")) { + duration = unit * 60; + } else if (Strings::Contains(time_string, "h")) { + duration = unit * 3600; + } else if (Strings::Contains(time_string, "d")) { + duration = unit * 86400; + } else if (Strings::Contains(time_string, "y")) { + duration = unit * 31556926; + } + + return duration; +} + +bool Strings::ToBool(std::string bool_string) +{ + if ( + Strings::Contains(bool_string, "true") || + Strings::Contains(bool_string, "y") || + Strings::Contains(bool_string, "yes") || + Strings::Contains(bool_string, "on") || + Strings::Contains(bool_string, "enable") || + Strings::Contains(bool_string, "enabled") || + (Strings::IsNumber(bool_string) && std::stoi(bool_string)) + ) { + return true; + } + + return false; +} + +// returns a random string of specified length +std::string Strings::Random(size_t length) +{ + auto randchar = []() -> char { + const char charset[] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const size_t max_index = (sizeof(charset) - 1); + return charset[static_cast(std::rand()) % max_index]; + }; + std::string str(length, 0); + std::generate_n(str.begin(), length, randchar); + return str; +} diff --git a/common/strings.h b/common/strings.h new file mode 100644 index 000000000..a70a7432f --- /dev/null +++ b/common/strings.h @@ -0,0 +1,313 @@ +// for folly stuff +/* + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// for our stuff +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef _STRINGUTIL_H_ +#define _STRINGUTIL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef _WIN32 +// this doesn't appear to affect linux-based systems..need feedback for _WIN64 + +#endif + +#ifdef _WINDOWS +#include +#include +#include +#endif + +#include "types.h" + +namespace detail { + // template magic to check if std::from_chars floating point functions exist + template + struct has_from_chars_float : std::false_type { }; + + // basically it "uses" this template if they do exist because reasons + template + struct has_from_chars_float < T, + std::void_t(), std::declval(), + std::declval()))>> : std::true_type { }; +}; // namespace detail + +namespace EQ { +// lame -- older GCC's didn't define this, clang's libc++ however does, even though they lack FP support +#if defined(__GNUC__) && (__GNUC__ < 11) && !defined(__clang__) + enum class chars_format { + scientific = 1, fixed = 2, hex = 4, general = fixed | scientific + }; +#else + using chars_format = std::chars_format; +#endif +}; // namespace EQ + +class Strings { +public: + static bool Contains(std::vector container, std::string element); + static bool Contains(const std::string& subject, const std::string& search); + static bool IsNumber(const std::string &s); + static bool IsFloat(const std::string &s); + static const std::string ToLower(std::string s); + static const std::string ToUpper(std::string s); + static const std::string UcFirst(std::string s); + static std::string <rim(std::string &str, const std::string &chars = "\t\n\v\f\r "); + static std::string &RTrim(std::string &str, const std::string &chars = "\t\n\v\f\r "); + static std::string &Trim(std::string &str, const std::string &chars = "\t\n\v\f\r "); + static std::string Commify(const std::string &number); + static std::string Commify(uint16 number) { return Strings::Commify(std::to_string(number)); }; + static std::string Commify(uint32 number) { return Strings::Commify(std::to_string(number)); }; + static std::string Commify(uint64 number) { return Strings::Commify(std::to_string(number)); }; + static std::string Commify(int16 number) { return Strings::Commify(std::to_string(number)); }; + static std::string Commify(int32 number) { return Strings::Commify(std::to_string(number)); }; + static std::string Commify(int64 number) { return Strings::Commify(std::to_string(number)); }; + static std::string ConvertToDigit(int n, std::string suffix); + static std::string Escape(const std::string &s); + static std::string GetBetween(const std::string &s, std::string start_delim, std::string stop_delim); + static std::string Implode(std::string glue, std::vector src); + static std::string Join(const std::vector &ar, const std::string &delim); + static std::string MillisecondsToTime(int duration); + static std::string Money(uint32 platinum, uint32 gold = 0, uint32 silver = 0, uint32 copper = 0); + static std::string NumberToWords(unsigned long long int n); + static std::string Repeat(std::string s, int n); + static std::string Replace(std::string subject, const std::string &search, const std::string &replace); + static std::string SecondsToTime(int duration, bool is_milliseconds = false); + static std::string::size_type SearchDelim(const std::string &haystack, const std::string &needle, const char deliminator = ','); + static std::vector Split(const std::string &s, const char delim = ','); + static std::vector Split(const std::string& s, const std::string& delimiter); + static std::vector Wrap(std::vector &src, std::string character); + static void FindReplace(std::string &string_subject, const std::string &search_string, const std::string &replace_string); + static uint32 TimeToSeconds(std::string time_string); + static bool ToBool(std::string bool_string); + static inline bool EqualFold(const std::string &string_one, const std::string &string_two) { return strcasecmp(string_one.c_str(), string_two.c_str()) == 0; } + static std::string Random(size_t length); + + template + static std::string + ImplodePair(const std::string &glue, const std::pair &encapsulation, const std::vector &src) + { + if (src.empty()) { + return {}; + } + std::ostringstream oss; + for (const T &src_iter: src) { + oss << encapsulation.first << src_iter << encapsulation.second << glue; + } + std::string output(oss.str()); + output.resize(output.size() - glue.size()); + return output; + } + + // basic string_view overloads that just use std stuff since they work! + template + std::enable_if_t && detail::has_from_chars_float::value, std::from_chars_result> + static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general) + { + return std::from_chars(str.data(), str.data() + str.size(), value, fmt); + } + + template + std::enable_if_t, std::from_chars_result> + static from_chars(std::string_view str, T& value, int base = 10) + { + return std::from_chars(str.data(), str.data() + str.size(), value, base); + } + + // fallback versions of floating point in case they're not implemented + // TODO: add error handling ... + // This does have to allocate since from_chars doesn't need a null terminated string and neither does string_view + template + std::enable_if_t && !detail::has_from_chars_float::value && std::is_same_v, std::from_chars_result> + static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general) + { + std::from_chars_result res{}; + std::string tmp_str(str.data(), str.size()); + value = strtof(tmp_str.data(), nullptr); + return res; + } + + template + std::enable_if_t && !detail::has_from_chars_float::value && std::is_same_v, std::from_chars_result> + static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general) + { + std::from_chars_result res{}; + std::string tmp_str(str.data(), str.size()); + value = strtod(tmp_str.data(), nullptr); + return res; + } + +}; + +const std::string StringFormat(const char *format, ...); +const std::string vStringFormat(const char *format, va_list args); + +// For converstion of numerics into English +// Used for grid nodes, as NPC names remove numerals. +// But general purpose + +const std::string NUM_TO_ENGLISH_X[] = { + "", "One ", "Two ", "Three ", "Four ", + "Five ", "Six ", "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ", + "Twelve ", "Thirteen ", "Fourteen ", "Fifteen ", + "Sixteen ", "Seventeen ", "Eighteen ", "Nineteen " +}; + +const std::string NUM_TO_ENGLISH_Y[] = { + "", "", "Twenty ", "Thirty ", "Forty ", + "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety " +}; + +// _WIN32 builds require that #include be included in whatever code file the invocation is made from (no header files) +template +std::vector join_pair( + const std::string &glue, + const std::pair &encapsulation, + const std::vector> &src +) +{ + if (src.empty()) { + return {}; + } + + std::vector output; + + for (const std::pair &src_iter: src) { + output.push_back( + + fmt::format( + "{}{}{}{}{}{}{}", + encapsulation.first, + src_iter.first, + encapsulation.second, + glue, + encapsulation.first, + src_iter.second, + encapsulation.second + ) + ); + } + + return output; +} + +// _WIN32 builds require that #include be included in whatever code file the invocation is made from (no header files) +template +std::vector join_tuple( + const std::string &glue, + const std::pair &encapsulation, + const std::vector> &src +) +{ + if (src.empty()) { + return {}; + } + + std::vector output; + + for (const std::tuple &src_iter: src) { + + output.push_back( + + fmt::format( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + encapsulation.first, + std::get<0>(src_iter), + encapsulation.second, + glue, + encapsulation.first, + std::get<1>(src_iter), + encapsulation.second, + glue, + encapsulation.first, + std::get<2>(src_iter), + encapsulation.second, + glue, + encapsulation.first, + std::get<3>(src_iter), + encapsulation.second + ) + ); + } + + return output; +} + +// misc functions +std::string SanitizeWorldServerName(std::string server_long_name); +std::vector GetBadWords(); +void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver); + +// old c string functions + +bool atobool(const char *iBool); +bool isAlphaNumeric(const char *text); +bool strn0cpyt(char *dest, const char *source, uint32 size); +char *CleanMobName(const char *in, char *out); +char *RemoveApostrophes(const char *s); +char *strn0cpy(char *dest, const char *source, uint32 size); +const char *ConvertArray(int64 input, char *returnchar); +const char *ConvertArrayF(float input, char *returnchar); +const char *MakeLowerString(const char *source); +uint32 hextoi(const char *num); +uint64 hextoi64(const char *num); +void MakeLowerString(const char *source, char *target); +void RemoveApostrophes(std::string &s); +std::string FormatName(const std::string &char_name); +bool IsAllowedWorldServerCharacterList(char c); +void SanitizeWorldServerName(char *name); + +template +auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result) +{ + for (; first != last; ++first) { + if (*first == '_') { + *result = ' '; + } + else if (isalpha(*first) || *first == '`') { + *result = *first; + } + } + return result; +} + +#endif diff --git a/common/strings_legacy.cpp b/common/strings_legacy.cpp new file mode 100644 index 000000000..480a4ebe5 --- /dev/null +++ b/common/strings_legacy.cpp @@ -0,0 +1,336 @@ +#include +#include "strings.h" +#include +#include +#include +#include + +#ifdef _WINDOWS +#include + +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp + +#else + +#include +#include +#include + +#endif + +#ifndef va_copy +#define va_copy(d,s) ((d) = (s)) +#endif + +// normal strncpy doesnt put a null term on copied strings, this one does +// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp +char *strn0cpy(char *dest, const char *source, uint32 size) +{ + if (!dest) { + return 0; + } + if (size == 0 || source == 0) { + dest[0] = 0; + return dest; + } + strncpy(dest, source, size); + dest[size - 1] = 0; + return dest; +} + +// String N w/null Copy Truncated? +// return value =true if entire string(source) fit, false if it was truncated +bool strn0cpyt(char *dest, const char *source, uint32 size) +{ + if (!dest) { + return 0; + } + if (size == 0 || source == 0) { + dest[0] = 0; + return false; + } + strncpy(dest, source, size); + dest[size - 1] = 0; + return (bool) (source[strlen(dest)] == 0); +} + +const char *MakeLowerString(const char *source) +{ + static char str[128]; + if (!source) { + return nullptr; + } + MakeLowerString(source, str); + return str; +} + +void MakeLowerString(const char *source, char *target) +{ + if (!source || !target) { + *target = 0; + return; + } + while (*source) { + *target = tolower(*source); + target++; + source++; + } + *target = 0; +} + +uint32 hextoi(const char *num) +{ + if (num == nullptr) { + return 0; + } + + int len = strlen(num); + if (len < 3) { + return 0; + } + + if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X')) { + return 0; + } + + uint32 ret = 0; + int mul = 1; + for (int i = len - 1; i >= 2; i--) { + if (num[i] >= 'A' && num[i] <= 'F') { + ret += ((num[i] - 'A') + 10) * mul; + } + else if (num[i] >= 'a' && num[i] <= 'f') { + ret += ((num[i] - 'a') + 10) * mul; + } + else if (num[i] >= '0' && num[i] <= '9') { + ret += (num[i] - '0') * mul; + } + else { + return 0; + } + mul *= 16; + } + return ret; +} + +uint64 hextoi64(const char *num) +{ + if (num == nullptr) { + return 0; + } + + int len = strlen(num); + if (len < 3) { + return 0; + } + + if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X')) { + return 0; + } + + uint64 ret = 0; + int mul = 1; + for (int i = len - 1; i >= 2; i--) { + if (num[i] >= 'A' && num[i] <= 'F') { + ret += ((num[i] - 'A') + 10) * mul; + } + else if (num[i] >= 'a' && num[i] <= 'f') { + ret += ((num[i] - 'a') + 10) * mul; + } + else if (num[i] >= '0' && num[i] <= '9') { + ret += (num[i] - '0') * mul; + } + else { + return 0; + } + mul *= 16; + } + return ret; +} + +bool atobool(const char *iBool) +{ + + if (iBool == nullptr) { + return false; + } + if (!strcasecmp(iBool, "true")) { + return true; + } + if (!strcasecmp(iBool, "false")) { + return false; + } + if (!strcasecmp(iBool, "yes")) { + return true; + } + if (!strcasecmp(iBool, "no")) { + return false; + } + if (!strcasecmp(iBool, "on")) { + return true; + } + if (!strcasecmp(iBool, "off")) { + return false; + } + if (!strcasecmp(iBool, "enable")) { + return true; + } + if (!strcasecmp(iBool, "disable")) { + return false; + } + if (!strcasecmp(iBool, "enabled")) { + return true; + } + if (!strcasecmp(iBool, "disabled")) { + return false; + } + if (!strcasecmp(iBool, "y")) { + return true; + } + if (!strcasecmp(iBool, "n")) { + return false; + } + if (atoi(iBool)) { + return true; + } + return false; +} + +// removes the crap and turns the underscores into spaces. +char *CleanMobName(const char *in, char *out) +{ + unsigned i, j; + + for (i = j = 0; i < strlen(in); i++) { + // convert _ to space.. any other conversions like this? I *think* this + // is the only non alpha char that's not stripped but converted. + if (in[i] == '_') { + out[j++] = ' '; + } + else { + if (isalpha(in[i]) || (in[i] == '`')) { // numbers, #, or any other crap just gets skipped + out[j++] = in[i]; + } + } + } + out[j] = 0; // terimnate the string before returning it + return out; +} + + +void RemoveApostrophes(std::string &s) +{ + for (unsigned int i = 0; i < s.length(); ++i) + if (s[i] == '\'') { + s[i] = '_'; + } +} + +char *RemoveApostrophes(const char *s) +{ + auto NewString = new char[strlen(s) + 1]; + + strcpy(NewString, s); + + for (unsigned int i = 0; i < strlen(NewString); ++i) + if (NewString[i] == '\'') { + NewString[i] = '_'; + } + + return NewString; +} + +const char *ConvertArray(int64 input, char *returnchar) +{ + sprintf(returnchar, "%" PRId64, input); + return returnchar; +} + +const char *ConvertArrayF(float input, char *returnchar) +{ + sprintf(returnchar, "%0.2f", input); + return returnchar; +} + +bool isAlphaNumeric(const char *text) +{ + for (unsigned int charIndex = 0; charIndex < strlen(text); charIndex++) { + if ((text[charIndex] < 'a' || text[charIndex] > 'z') && + (text[charIndex] < 'A' || text[charIndex] > 'Z') && + (text[charIndex] < '0' || text[charIndex] > '9')) { + return false; + } + } + + return true; +} + +// first letter capitalized and rest made lower case +std::string FormatName(const std::string &char_name) +{ + std::string formatted(char_name); + if (!formatted.empty()) { + std::transform(formatted.begin(), formatted.end(), formatted.begin(), ::tolower); + formatted[0] = ::toupper(formatted[0]); + } + return formatted; +} + +bool IsAllowedWorldServerCharacterList(char c) +{ + const char *valid_characters = ":[](){}.!@#$%^&*-=+<>/\\|'\""; + if (strchr(valid_characters, c)) { + return true; + } + + return false; +} + +void SanitizeWorldServerName(char *name) +{ + std::string server_long_name = name; + + strcpy(name, SanitizeWorldServerName(server_long_name).c_str()); +} + +// original source: +// https://github.com/facebook/folly/blob/master/folly/String.cpp +// +const std::string vStringFormat(const char *format, va_list args) +{ + std::string output; + va_list tmpargs; + + va_copy(tmpargs, args); + int characters_used = vsnprintf(nullptr, 0, format, tmpargs); + va_end(tmpargs); + + // Looks like we have a valid format string. + if (characters_used > 0) { + output.resize(characters_used + 1); + + va_copy(tmpargs, args); + characters_used = vsnprintf(&output[0], output.capacity(), format, tmpargs); + va_end(tmpargs); + + output.resize(characters_used); + + // We shouldn't have a format error by this point, but I can't imagine what error we + // could have by this point. Still, return empty string; + if (characters_used < 0) { + output.clear(); + } + } + return output; +} + +const std::string StringFormat(const char *format, ...) +{ + va_list args; + va_start(args, format); + std::string output = vStringFormat(format, args); + va_end(args); + return output; +} diff --git a/common/strings_misc.cpp b/common/strings_misc.cpp new file mode 100644 index 000000000..08355e15e --- /dev/null +++ b/common/strings_misc.cpp @@ -0,0 +1,371 @@ +#include +#include "strings.h" +#include +#include +#include + +#ifdef _WINDOWS +#include + +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp + +#else + +#include +#include +#include + +#endif + +#ifndef va_copy +#define va_copy(d,s) ((d) = (s)) +#endif + +std::string SanitizeWorldServerName(std::string server_long_name) +{ + server_long_name.erase( + std::remove_if( + server_long_name.begin(), + server_long_name.end(), + [](char c) { + return !(std::isalpha(c) || std::isalnum(c) || std::isspace(c) || IsAllowedWorldServerCharacterList(c)); + } + ), server_long_name.end() + ); + + server_long_name = Strings::Trim(server_long_name); + + // bad word filter + for (auto &piece: Strings::Split(server_long_name, " ")) { + for (auto &word: GetBadWords()) { + // for shorter words that can actually be part of legitimate words + // make sure that it isn't part of another word by matching on a space + if (Strings::ToLower(piece) == word) { + Strings::FindReplace( + server_long_name, + piece, + Strings::Repeat("*", (int) word.length()) + ); + continue; + } + + auto pos = Strings::ToLower(piece).find(word); + if (Strings::ToLower(piece).find(word) != std::string::npos && piece.length() > 4 && word.length() > 4) { + auto found_word = piece.substr(pos, word.length()); + std::string replaced_piece = piece.substr(pos, word.length()); + + Strings::FindReplace( + server_long_name, + replaced_piece, + Strings::Repeat("*", (int) word.length()) + ); + } + } + } + + return server_long_name; +} + +std::vector GetBadWords() +{ + return std::vector{ + "2g1c", + "acrotomophilia", + "anal", + "anilingus", + "anus", + "apeshit", + "arsehole", + "ass", + "asshole", + "assmunch", + "autoerotic", + "babeland", + "bangbros", + "bangbus", + "bareback", + "barenaked", + "bastard", + "bastardo", + "bastinado", + "bbw", + "bdsm", + "beaner", + "beaners", + "beaver", + "beastiality", + "bestiality", + "bimbos", + "birdlock", + "bitch", + "bitches", + "blowjob", + "blumpkin", + "bollocks", + "bondage", + "boner", + "boob", + "boobs", + "bukkake", + "bulldyke", + "bullshit", + "bung", + "bunghole", + "busty", + "butt", + "buttcheeks", + "butthole", + "camel toe", + "camgirl", + "camslut", + "camwhore", + "carpetmuncher", + "cialis", + "circlejerk", + "clit", + "clitoris", + "clusterfuck", + "cock", + "cocks", + "coprolagnia", + "coprophilia", + "cornhole", + "coon", + "coons", + "creampie", + "cum", + "cumming", + "cumshot", + "cumshots", + "cunnilingus", + "cunt", + "darkie", + "daterape", + "deepthroat", + "dendrophilia", + "dick", + "dildo", + "dingleberry", + "dingleberries", + "doggiestyle", + "doggystyle", + "dolcett", + "domination", + "dominatrix", + "dommes", + "hump", + "dvda", + "ecchi", + "ejaculation", + "erotic", + "erotism", + "escort", + "eunuch", + "fag", + "faggot", + "fecal", + "felch", + "fellatio", + "feltch", + "femdom", + "figging", + "fingerbang", + "fingering", + "fisting", + "footjob", + "frotting", + "fuck", + "fuckin", + "fucking", + "fucktards", + "fudgepacker", + "futanari", + "gangbang", + "gangbang", + "gaysex", + "genitals", + "goatcx", + "goatse", + "gokkun", + "goodpoop", + "goregasm", + "grope", + "g-spot", + "guro", + "handjob", + "hentai", + "homoerotic", + "honkey", + "hooker", + "horny", + "humping", + "incest", + "intercourse", + "jailbait", + "jigaboo", + "jiggaboo", + "jiggerboo", + "jizz", + "juggs", + "kike", + "kinbaku", + "kinkster", + "kinky", + "knobbing", + "livesex", + "lolita", + "lovemaking", + "masturbate", + "masturbating", + "masturbation", + "milf", + "mong", + "motherfucker", + "muffdiving", + "nambla", + "nawashi", + "negro", + "neonazi", + "nigga", + "nigger", + "nimphomania", + "nipple", + "nipples", + "nsfw", + "nude", + "nudity", + "nutten", + "nympho", + "nymphomania", + "octopussy", + "omorashi", + "orgasm", + "orgy", + "paedophile", + "paki", + "panties", + "panty", + "pedobear", + "pedophile", + "pegging", + "penis", + "pikey", + "pissing", + "pisspig", + "playboy", + "ponyplay", + "poof", + "poon", + "poontang", + "punany", + "poopchute", + "porn", + "porno", + "pornography", + "pthc", + "pubes", + "pussy", + "queaf", + "queef", + "quim", + "raghead", + "rape", + "raping", + "rapist", + "rectum", + "rimjob", + "rimming", + "sadism", + "santorum", + "scat", + "schlong", + "scissoring", + "semen", + "sex", + "sexcam", + "sexo", + "sexy", + "sexual", + "sexually", + "sexuality", + "shemale", + "shibari", + "shit", + "shitblimp", + "shitty", + "shota", + "shrimping", + "skeet", + "slanteye", + "slut", + "s&m", + "smut", + "snatch", + "snowballing", + "sodomize", + "sodomy", + "spastic", + "spic", + "splooge", + "spooge", + "spunk", + "strapon", + "strappado", + "suck", + "sucks", + "swastika", + "swinger", + "threesome", + "throating", + "thumbzilla", + "tight white", + "tit", + "tits", + "titties", + "titty", + "topless", + "tosser", + "towelhead", + "tranny", + "tribadism", + "tubgirl", + "tushy", + "twat", + "twink", + "twinkie", + "undressing", + "upskirt", + "urophilia", + "vagina", + "viagra", + "vibrator", + "vorarephilia", + "voyeur", + "voyeurweb", + "voyuer", + "vulva", + "wank", + "wetback", + "whore", + "worldsex", + "xx", + "xxx", + "yaoi", + "yiffy", + "zoophilia" + }; +} + +void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver) +{ + auto split = Strings::Split(s, ':'); + if (split.size() == 2) { + loginserver = split[0]; + account = split[1]; + } + else if (split.size() == 1) { + account = split[0]; + } +} diff --git a/common/tasks.h b/common/tasks.h index 680297a7a..612aca1f0 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -1,9 +1,11 @@ #ifndef EQEMU_TASKS_H #define EQEMU_TASKS_H +#include "../common/strings.h" #include "serialize_buffer.h" +#include +#include -#define MAXTASKS 10000 #define MAXTASKSETS 1000 #define MAXACTIVEQUESTS 19 // The Client has a hard cap of 19 active quests, 29 in SoD+ #define MAXCHOOSERENTRIES 40 // The Max Chooser (Task Selector entries) is capped at 40 in the Titanium Client. @@ -15,13 +17,10 @@ // Command Codes for worldserver ServerOP_ReloadTasks #define RELOADTASKS 0 -#define RELOADTASKGOALLISTS 1 -#define RELOADTASKPROXIMITIES 2 -#define RELOADTASKSETS 3 +#define RELOADTASKSETS 2 typedef enum { METHODSINGLEID = 0, - METHODLIST = 1, METHODQUEST = 2 } TaskMethodType; @@ -51,7 +50,8 @@ enum class TaskTimerType }; struct ActivityInformation { - int step_number; + int req_activity_id; + int step; TaskActivityType activity_type; std::string target_name; // name mob, location -- default empty, max length 64 std::string item_list; // likely defaults to empty @@ -60,21 +60,31 @@ struct ActivityInformation { std::string description_override; // overrides auto generated description -- default empty, max length 128 int skill_id; // older clients, first id from above int spell_id; // older clients, first id from above - int goal_id; - std::string goal_match_list; TaskMethodType goal_method; int goal_count; - int deliver_to_npc; + std::string npc_match_list; // delimited by '|' for partial name matches but also supports ids + std::string item_id_list; // delimited by '|' to support multiple item ids + int dz_switch_id; + float min_x; + float min_y; + float min_z; + float max_x; + float max_y; + float max_z; std::vector zone_ids; std::string zones; // IDs ; separated, ZoneID is the first in this list for older clients -- default empty string, max length 64 + int zone_version; bool optional; + bool has_area; // non-database field - inline bool CheckZone(int zone_id) + inline bool CheckZone(int zone_id, int version) const { if (zone_ids.empty()) { return true; } - return std::find(zone_ids.begin(), zone_ids.end(), zone_id) != zone_ids.end(); + bool found_zone = std::find(zone_ids.begin(), zone_ids.end(), zone_id) != zone_ids.end(); + + return found_zone && (zone_version == version || zone_version == -1); } void SerializeSelector(SerializeBuffer& out, EQ::versions::ClientVersion client_version) const @@ -146,7 +156,7 @@ struct ActivityInformation { out.WriteInt32(zone_ids.empty() ? 0 : zone_ids.front()); } - out.WriteInt32(0); // unknown id + out.WriteInt32(dz_switch_id); out.WriteString(description_override); out.WriteInt32(done_count); out.WriteInt8(1); // unknown @@ -158,11 +168,6 @@ struct ActivityInformation { } }; -typedef enum { - ActivitiesSequential = 0, - ActivitiesStepped = 1 -} SequenceType; - enum class TaskType { Task = 0, // can have at max 1 Shared = 1, // can have at max 1 @@ -183,31 +188,32 @@ enum class DurationCode { struct TaskInformation { TaskType type; - int duration{}; + uint32_t duration{}; DurationCode duration_code; // description for time investment for when duration == 0 std::string title{}; // max length 64 std::string description{}; // max length 4000, 2048 on Tit std::string reward{}; std::string item_link{}; // max length 128 older clients, item link gets own string std::string completion_emote{}; // emote after completing task, yellow. Maybe should make more generic ... but yellow for now! - int reward_id{}; - int cash_reward{}; // Expressed in copper + std::string reward_id_list{}; + uint32_t cash_reward{}; // Expressed in copper int experience_reward{}; - int faction_reward{}; // just a npc_faction_id + int faction_reward{}; // npc_faction_id if amount == 0, otherwise primary faction ID + int faction_amount{}; // faction hit value TaskMethodType reward_method; - int reward_radiant_crystals; - int reward_ebon_crystals; + int reward_points; + int32_t reward_point_type; int activity_count{}; - SequenceType sequence_mode; - int last_step{}; - short min_level{}; - short max_level{}; - int level_spread; - int min_players; - int max_players; + uint8_t min_level{}; + uint8_t max_level{}; + uint32_t level_spread; + uint32_t min_players; + uint32_t max_players; bool repeatable{}; - int replay_timer_seconds; - int request_timer_seconds; + uint32_t replay_timer_group; + uint32_t replay_timer_seconds; + uint32_t request_timer_group; + uint32_t request_timer_seconds; ActivityInformation activity_information[MAXACTIVITIESPERTASK]; void SerializeSelector(SerializeBuffer& out, EQ::versions::ClientVersion client_version) const @@ -251,9 +257,9 @@ struct ClientActivityInformation { struct ClientTaskInformation { int slot; // intrusive, but makes things easier :P int task_id; - int current_step; int accepted_time; bool updated; + bool was_rewarded; // character has received reward for this task ClientActivityInformation activity[MAXACTIVITIESPERTASK]; }; @@ -322,17 +328,115 @@ namespace Tasks { return "Task"; } } + + struct ActiveElements + { + bool is_task_complete; + std::vector active; + }; + + // Processes task activity states and returns those currently active + // It is templated to support the different structs used by zone and world + template + ActiveElements GetActiveElements(const Td& activity_data, const Ts& activity_states, size_t activity_count) + { + ActiveElements result; + result.is_task_complete = true; + result.active.reserve(activity_count); + + std::array completed_ids; + completed_ids.fill(false); + std::fill_n(completed_ids.begin(), activity_count, true); + + bool sequence_mode = true; + int current_step = std::numeric_limits::max(); // lowest step not completed + + // fill non-completed elements and find the current task step + for (int i = 0; i < activity_count; ++i) + { + const auto& el = activity_data[i]; + + if (activity_states[i].activity_state != ActivityCompleted) + { + completed_ids[i] = false; + current_step = std::min(current_step, el.step); + if (!el.optional) + { + result.is_task_complete = false; + } + } + + // if all steps are 0 treat each as a separate step (previously called "sequential" mode) + if (el.step != 0) + { + sequence_mode = false; + } + } + + // fill active elements based on current step and req activity ids + bool added_sequence = false; + for (int i = 0; i < activity_count; ++i) + { + const auto& el = activity_data[i]; + + if (activity_states[i].activity_state != ActivityCompleted) + { + bool has_req_id = el.req_activity_id >= 0 && el.req_activity_id < activity_count; + + // if a valid requirement is set then it's active if its req is completed + // in non-sequence mode all on current step and optionals in previous steps are active + // in sequence mode the first non-complete is active (and any optionals up to it) + if ((has_req_id && completed_ids[el.req_activity_id]) || + (!has_req_id && !sequence_mode && el.step <= current_step) || + (!has_req_id && sequence_mode && !added_sequence)) + { + result.active.push_back(i); + if (!has_req_id && sequence_mode) + { + added_sequence = !el.optional; + } + } + } + } + + return result; + } + + static bool IsInMatchList(const std::string& match_list, const std::string& entry) + { + for (auto &s: Strings::Split(match_list, '|')) { + if (s == entry) { + return true; + } + } + + return false; + } + + static bool IsInMatchListPartial(const std::string &match_list, const std::string &entry) + { + std::string entry_match = Strings::ToLower(entry); + for (auto &s: Strings::Split(match_list, '|')) { + if (entry_match.find(Strings::ToLower(s)) != std::string::npos) { + return true; + } + } + + return false; + } + + } -namespace SharedTaskMessage { - constexpr uint16 TASK_ASSIGN_WAIT_REPLAY_TIMER = 8017; // This task can not be assigned to you because you must wait %1d:%2h:%3m before you can do another task of this type. +namespace TaskStr { + constexpr uint16 ASSIGN_REPLAY_TIMER = 8017; // This task can not be assigned to you because you must wait %1d:%2h:%3m before you can do another task of this type. constexpr uint16 COULD_NOT_USE_COMMAND = 8272; // You could not use this command because you are not currently assigned to a shared task. - constexpr uint16 AVG_LVL_LOW = 8553; // You can not be assigned this shared task because your party's average level is too low. - constexpr uint16 AVG_LVL_HIGH = 8889; // You can not be assigned this shared task because your party's average level is too high. + constexpr uint16 LVL_TOO_LOW = 8553; // You can not be assigned this shared task because your party's average level is too low. + constexpr uint16 LVL_TOO_HIGH = 8889; // You can not be assigned this shared task because your party's average level is too high. constexpr uint16 LVL_SPREAD_HIGH = 8890; // You can not be assigned this shared task because your party's level spread is too high. - constexpr uint16 PARTY_EXCEED_MAX_PLAYER = 8891; // You can not be assigned this shared task because your party exceeds the maximum allowed number of players. + constexpr uint16 MAX_PLAYERS = 8891; // You can not be assigned this shared task because your party exceeds the maximum allowed number of players. constexpr uint16 LEADER_NOT_MEET_REQUIREMENTS = 8892; // You can not be assigned this shared task because the leader does not meet the shared task requirements. - constexpr uint16 SHARED_TASK_NOT_MEET_MIN_NUM_PLAYER = 8895; // You can not be assigned this shared task because your party does not contain the minimum required number of players. + constexpr uint16 MIN_PLAYERS = 8895; // You can not be assigned this shared task because your party does not contain the minimum required number of players. constexpr uint16 WILL_REMOVE_ZONE_TWO_MIN_RAID_NOT_MIN_NUM_PLAYER = 8908; // %1 will be removed from their zone in two minutes because your raid does not meet the minimum requirement of qualified players. constexpr uint16 WILL_REMOVE_ZONE_TWO_MIN_GROUP_NOT_MIN_NUM_PLAYER = 8909; // %1 will be removed from their zone in two minutes because your group does not meet the minimum requirement of qualified players. constexpr uint16 WILL_REMOVE_AREA_TWO_MIN_RAID_NOT_MIN_NUM_PLAYER = 8910; // %1 will be removed from their area in two minutes because your raid does not meet the minimum requirement of qualified players. @@ -343,12 +447,12 @@ namespace SharedTaskMessage { constexpr uint16 HAS_REMOVED_AREA_TWO_MIN_GROUP_NOT_MIN_NUM_PLAYER = 8915; // %1 has been removed from their area because your group does not meet the minimum requirement of qualified players. constexpr uint16 SEND_INVITE_TO = 8916; // Sending a shared task invitation to %1. constexpr uint16 COULD_NOT_BE_INVITED = 8917; // %1 could not be invited to join you. - constexpr uint16 YOU_ARE_NOT_LEADER_COMMAND_ISSUE = 8919; // You are not the shared task leader. Only %1 can issue this command. + constexpr uint16 NOT_LEADER = 8919; // You are not the shared task leader. Only %1 can issue this command. constexpr uint16 SWAP_SENDING_INVITATION_TO = 8920; // Sending an invitation to: %1. They must accept in order to swap party members. constexpr uint16 SWAP_ACCEPTED_OFFER = 8921; // %1 has accepted your offer to join your shared task. Swapping %1 for %2. constexpr uint16 IS_NOT_MEMBER = 8922; // %1 is not a member of this shared task. constexpr uint16 NOT_ALLOW_PLAYER_REMOVE = 8923; // The shared task is not allowing players to be removed from it at this time. - constexpr uint16 PLAYER_HAS_BEEN_REMOVED = 8924; // %1 has been removed from your shared task, '%2'. + constexpr uint16 PLAYER_REMOVED = 8924; // %1 has been removed from your shared task, '%2'. constexpr uint16 TRANSFER_LEADERSHIP_NOT_ONLINE = 8925; // %1 is not currently online. You can only transfer leadership to an online member of the shared task. constexpr uint16 MADE_LEADER = 8926; // %1 has been made the leader for this shared task. constexpr uint16 YOU_MADE_LEADER = 8927; // You have been made the leader of this shared task. @@ -356,43 +460,43 @@ namespace SharedTaskMessage { constexpr uint16 MEMBERS_PRINT = 8929; // Shared Task Members: %1 constexpr uint16 PLAYER_ACCEPTED_OFFER_JOIN = 8930; // %1 has accepted your offer to join your shared task. constexpr uint16 PLAYER_HAS_BEEN_ADDED = 8931; // %1 has been added to your shared task, '%2'. - constexpr uint16 ACCEPTED_OFFER_TO_JOIN_BUT_COULD_NOT = 8932; // %1 accepted your offer to join your shared task but could not. + constexpr uint16 COULD_NOT_JOIN = 8932; // %1 accepted your offer to join your shared task but could not. constexpr uint16 PLAYER_DECLINED_OFFER = 8933; // %1 has declined your offer to join your shared task. constexpr uint16 PLAYER_HAS_ASKED_YOU_TO_JOIN = 8934; // %1 has asked you to join the shared task '%2'. Would you like to join? - constexpr uint16 NO_REQUEST_BECAUSE_HAVE_ONE = 8935; // You may not request a shared task because you already have one. - constexpr uint16 NO_REQUEST_BECAUSE_RAID_HAS_ONE = 8936; // You may not request a shared task because someone in your raid, %1, already has one. - constexpr uint16 NO_REQUEST_BECAUSE_GROUP_HAS_ONE = 8937; // You may not request a shared task because someone in your group, %1, already has one. - constexpr uint16 YOU_DO_NOT_MEET_REQ_AVAILABLE = 8938; // You do not meet the requirements for any available shared tasks. + constexpr uint16 REQUEST_HAVE = 8935; // You may not request a shared task because you already have one. + constexpr uint16 REQUEST_RAID_HAS = 8936; // You may not request a shared task because someone in your raid, %1, already has one. + constexpr uint16 REQUEST_GROUP_HAS = 8937; // You may not request a shared task because someone in your group, %1, already has one. + constexpr uint16 NOT_MEET_REQ = 8938; // You do not meet the requirements for any available shared tasks. constexpr uint16 YOUR_RAID_DOES_NOT_MEET_REQ = 8939; // Your raid does not meet the requirements for any available shared tasks. constexpr uint16 YOUR_GROUP_DOES_NOT_MEET_REQ = 8940; // Your group does not meet the requirements for any available shared tasks. constexpr uint16 YOUR_GROUP__RAID_DOES_NOT_MEET_REQ = 8941; // You can not be assigned this shared task because the raid or group does not meet the shared task requirements. - constexpr uint16 YOU_NO_LONGER_MEMBER = 8942; // You are no longer a member of the shared task. + constexpr uint16 NO_LONGER_MEMBER = 8942; // You are no longer a member of the shared task. constexpr uint16 YOU_MAY_NOT_REQUEST_EXPANSION = 8943; // You may not request this shared task because you do not have the required expansion. constexpr uint16 PLAYER_MAY_NOT_REQUEST_EXPANSION = 8944; // You may not request this shared task because %1 does not have the required expansion. - constexpr uint16 TWO_MIN_REQ_TASK_TERMINATED = 8945; // If your party does not meet the requirements in two minutes, the shared task will be terminated. - constexpr uint16 YOU_MUST_WAIT_REPLAY_TIMER = 8946; // You may not request this shared task because you must wait %1d:%2h:%3m before you can do another task of this type. - constexpr uint16 PLAYER_MUST_WAIT_REPLAY_TIMER = 8947; // You may not request this shared task because %1 must wait %2d:%3h:%4m before they can do another task of this type. + constexpr uint16 REQS_TWO_MIN = 8945; // If your party does not meet the requirements in two minutes, the shared task will be terminated. + constexpr uint16 YOU_REPLAY_TIMER = 8946; // You may not request this shared task because you must wait %1d:%2h:%3m before you can do another task of this type. + constexpr uint16 PLAYER_REPLAY_TIMER = 8947; // You may not request this shared task because %1 must wait %2d:%3h:%4m before they can do another task of this type. constexpr uint16 PLAYER_NOW_LEADER = 8948; // %1 is now the leader of your shared task, '%2'. constexpr uint16 HAS_ENDED = 8951; // Your shared task, '%1', has ended. constexpr uint16 YOU_ALREADY_LEADER = 8952; // You are already the leader of the shared task. constexpr uint16 TASK_NO_LONGER_ACTIVE = 8953; // Your shared task, '%1', is no longer active. constexpr uint16 YOU_HAVE_BEEN_ADDED_TO_TASK = 8954; // You have been added to the shared task '%1'. constexpr uint16 YOU_ARE_NOW_LEADER = 8955; // You are now the leader of your shared task, '%1'. - constexpr uint16 YOU_HAVE_BEEN_REMOVED = 8956; // You have been removed from the shared task '%1'. - constexpr uint16 YOU_ARE_NO_LONGER_A_MEMBER = 8960; // You are no longer a member of the shared task, '%1'. - constexpr uint16 YOUR_TASK_NOW_LOCKED = 8961; // Your shared task is now locked. You may no longer add or remove players. - constexpr uint16 TASK_NOT_ALLOWING_PLAYERS_AT_TIME = 8962; // The shared task is not allowing players to be added at this time. - constexpr uint16 PLAYER_NOT_ONLINE_TO_ADD = 8963; // %1 is not currently online. A player needs to be online to be added to a shared task. - constexpr uint16 CANT_ADD_PLAYER_ALREADY_MEMBER = 8964; // You can not add %1 because they are already a member of this shared task. - constexpr uint16 CANT_ADD_PLAYER_ALREADY_ASSIGNED = 8965; // You can not add %1 because they are already assigned to another shared task. - constexpr uint16 PLAYER_ALREADY_OUTSTANDING_INVITATION_THIS = 8966; // %1 already has an outstanding invitation to join this shared task. - constexpr uint16 PLAYER_ALREADY_OUTSTANDING_ANOTHER = 8967; // %1 already has an outstanding invitation to join another shared task. Players may only have one invitation outstanding. - constexpr uint16 CANT_ADD_PLAYER_MAX_PLAYERS = 8968; // You can not add another player since you currently have the maximum number of players allowed (%1) in this shared task. - constexpr uint16 CANT_ADD_PLAYER_MAX_LEVEL_SPREAD = 8969; // You can not add this player because you would exceed the maximum level spread (%1) for this shared task. - constexpr uint16 CANT_ADD_PLAYER_MAX_AVERAGE_LEVEL = 8970; // You can not add this player because you would exceed the maximum average level for this shared task. - constexpr uint16 CANT_ADD_PLAYER_FALL_MIN_AVG_LEVEL = 8971; // You can not add this player because you would fall below the minimum average level for this shared task. + constexpr uint16 YOU_REMOVED = 8956; // You have been removed from the shared task '%1'. + constexpr uint16 NO_LONGER_MEMBER_TITLE = 8960; // You are no longer a member of the shared task, '%1'. + constexpr uint16 TASK_LOCKED = 8961; // Your shared task is now locked. You may no longer add or remove players. + constexpr uint16 NOT_ALLOWING_PLAYERS = 8962; // The shared task is not allowing players to be added at this time. + constexpr uint16 PLAYER_NOT_ONLINE = 8963; // %1 is not currently online. A player needs to be online to be added to a shared task. + constexpr uint16 PLAYER_ALREADY_MEMBER = 8964; // You can not add %1 because they are already a member of this shared task. + constexpr uint16 PLAYER_ALREADY_ASSIGNED = 8965; // You can not add %1 because they are already assigned to another shared task. + constexpr uint16 PLAYER_INVITED = 8966; // %1 already has an outstanding invitation to join this shared task. + constexpr uint16 PLAYER_INVITED_OTHER = 8967; // %1 already has an outstanding invitation to join another shared task. Players may only have one invitation outstanding. + constexpr uint16 CANT_ADD_MAX_PLAYERS = 8968; // You can not add another player since you currently have the maximum number of players allowed (%1) in this shared task. + constexpr uint16 CANT_ADD_LVL_SPREAD = 8969; // You can not add this player because you would exceed the maximum level spread (%1) for this shared task. + constexpr uint16 CANT_ADD_MAX_LEVEL = 8970; // You can not add this player because you would exceed the maximum average level for this shared task. + constexpr uint16 CANT_ADD_MIN_LEVEL = 8971; // You can not add this player because you would fall below the minimum average level for this shared task. constexpr uint16 PLAYER_DOES_NOT_OWN_EXPANSION = 8972; // %1 does not own the expansion needed for this shared task. - constexpr uint16 CANT_ADD_PLAYER_PARTY_FILTER_REQ_FOR_TASK = 8973; // You can not add this player because your party would no longer meet the filter requirements for this shared task. + constexpr uint16 CANT_ADD_FILTER_REQS = 8973; // You can not add this player because your party would no longer meet the filter requirements for this shared task. constexpr uint16 CANT_ADD_PLAYER_ONE_OF_GROUP_RAID_HAS_TASK = 8977; // You can not add %1 because they or one of their group or raid members is in another shared task. constexpr uint16 CANT_JOIN_GROUP_ACTIVE_TASK = 8978; // You can not join that group because you have an active shared task. constexpr uint16 CANT_ADD_PLAYER_REPLAY_TIMER = 8979; // You may not add %1 because they must wait %2d:%3h:%4m before they can do another task of this type. @@ -403,40 +507,48 @@ namespace SharedTaskMessage { constexpr uint16 PLAYER_CANT_ADD_RAID_BECAUSE_DIFF_TASK = 8984; // %1 can not be added to the raid because they are in a different shared task. constexpr uint16 YOU_CANT_ADD_RAID_BECAUSE_DIFF_TASK = 8985; // You can not be added to the raid because you are in a different shared task. constexpr uint16 REPLAY_TIMER_REMAINING = 8987; // '%1' replay timer: %2d:%3h:%4m remaining. - constexpr uint16 YOU_NO_CURRENT_REPLAY_TIMERS = 8989; // You do not currently have any task replay timers. + constexpr uint16 NO_REPLAY_TIMERS = 8989; // You do not currently have any task replay timers. constexpr uint16 SURE_QUIT_TASK = 8995; // Are you sure you want to quit the task '%1'? constexpr uint16 SURE_REMOVE_SELF_FROM_TASK = 8996; // Are you sure you want to remove yourself from the shared task '%1' - constexpr uint16 TASK_ASSIGN_WAIT_REQUEST_TIMER = 14506; // This task can not be assigned to you because you must wait %1d:%2h:%3m before you can request another task of this type. + constexpr uint16 ASSIGN_REQUEST_TIMER = 14506; // This task can not be assigned to you because you must wait %1d:%2h:%3m before you can request another task of this type. constexpr uint16 REQUEST_TIMER_REMAINING = 14507; // '%1' request timer: %2d:%3h:%4m remaining. - constexpr uint16 YOU_MUST_WAIT_REQUEST_TIMER = 14508; // You may not request this shared task because you must wait %1d:%2h:%3m before you can request another task of this type. + constexpr uint16 YOU_REQUEST_TIMER = 14508; // You may not request this shared task because you must wait %1d:%2h:%3m before you can request another task of this type. constexpr uint16 RECEIVED_REQUEST_TIMER = 14509; // You have received a request timer for '%1': %2d:%3h:%4m remaining. constexpr uint16 RECEIVED_REPLAY_TIMER = 14510; // You have received a replay timer for '%1': %2d:%3h:%4m remaining. - constexpr uint16 PLAYER_MUST_WAIT_REQUEST_TIMER = 14511; // You may not request this shared task because %1 must wait %2d:%3h:%4m before they can request another task of this type. + constexpr uint16 PLAYER_REQUEST_TIMER = 14511; // You may not request this shared task because %1 must wait %2d:%3h:%4m before they can request another task of this type. constexpr uint16 CANT_ADD_PLAYER_REQUEST_TIMER = 14512; // You may not add %1 because they must wait %2d:%3h:%4m before they can request another task of this type. // for eqstrs not in current emu clients (some are also used by non-shared tasks) - constexpr auto GetEQStr(uint16 eqstr_id) + constexpr auto Get(uint16 eqstr_id) { switch (eqstr_id) { - case SharedTaskMessage::COULD_NOT_USE_COMMAND: + case TaskStr::LVL_TOO_LOW: + return "You can not be assigned this shared task because your party's minimum level is too low."; + case TaskStr::LVL_TOO_HIGH: + return "You can not be assigned this shared task because your party's maximum level is too high."; + case TaskStr::COULD_NOT_USE_COMMAND: return "You could not use this command because you are not currently assigned to a shared task."; - case SharedTaskMessage::TASK_ASSIGN_WAIT_REQUEST_TIMER: + case TaskStr::CANT_ADD_MAX_LEVEL: + return "You can not add this player because their level exceeds the maximum level limit for this shared task."; + case TaskStr::CANT_ADD_MIN_LEVEL: + return "You can not add this player because their level is below the minimum required level for this shared task."; + case TaskStr::ASSIGN_REQUEST_TIMER: return "This task can not be assigned to you because you must wait {}d:{}h:{}m before you can request another task of this type."; - case SharedTaskMessage::REQUEST_TIMER_REMAINING: + case TaskStr::REQUEST_TIMER_REMAINING: return "'{}' request timer: {}d:{}h:{}m remaining."; - case SharedTaskMessage::YOU_MUST_WAIT_REQUEST_TIMER: + case TaskStr::YOU_REQUEST_TIMER: return "You may not request this shared task because you must wait {}d:{}h:{}m before you can request another task of this type."; - case SharedTaskMessage::RECEIVED_REQUEST_TIMER: + case TaskStr::RECEIVED_REQUEST_TIMER: return "You have received a request timer for '{}': {}d:{}h:{}m remaining."; - case SharedTaskMessage::RECEIVED_REPLAY_TIMER: + case TaskStr::RECEIVED_REPLAY_TIMER: return "You have received a replay timer for '{}': {}d:{}h:{}m remaining."; - case SharedTaskMessage::PLAYER_MUST_WAIT_REQUEST_TIMER: + case TaskStr::PLAYER_REQUEST_TIMER: return "You may not request this shared task because {} must wait {}d:{}h:{}m before they can request another task of this type."; - case SharedTaskMessage::CANT_ADD_PLAYER_REQUEST_TIMER: + case TaskStr::CANT_ADD_PLAYER_REQUEST_TIMER: return "You may not add {} because they must wait {}d:{}h:{}m before they can request another task of this type."; default: - LogTasks("[GetEQStr] Unhandled eqstr id [{}]", eqstr_id); + LogTasks("[TaskStr::Get] Unhandled eqstr id [{}]", eqstr_id); break; } return "Unknown EQStr"; diff --git a/common/termcolor/rang.hpp b/common/termcolor/rang.hpp new file mode 100644 index 000000000..68f830b6f --- /dev/null +++ b/common/termcolor/rang.hpp @@ -0,0 +1,502 @@ +#ifndef RANG_DOT_HPP +#define RANG_DOT_HPP + +#if defined(__unix__) || defined(__unix) || defined(__linux__) +#define OS_LINUX +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) +#define OS_WIN +#elif defined(__APPLE__) || defined(__MACH__) +#define OS_MAC +#else +#error Unknown Platform +#endif + +#if defined(OS_LINUX) || defined(OS_MAC) +#include + +#elif defined(OS_WIN) + +#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600) +#error \ + "Please include rang.hpp before any windows system headers or set _WIN32_WINNT at least to _WIN32_WINNT_VISTA" +#elif !defined(_WIN32_WINNT) +#define _WIN32_WINNT _WIN32_WINNT_VISTA +#endif + +#include +#include +#include + +// Only defined in windows 10 onwards, redefining in lower windows since it +// doesn't gets used in lower versions +// https://docs.microsoft.com/en-us/windows/console/getconsolemode +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif + +#endif + +#include +#include +#include +#include +#include + +namespace rang { + +/* For better compability with most of terminals do not use any style settings + * except of reset, bold and reversed. + * Note that on Windows terminals bold style is same as fgB color. + */ + enum class style { + reset = 0, + bold = 1, + dim = 2, + italic = 3, + underline = 4, + blink = 5, + rblink = 6, + reversed = 7, + conceal = 8, + crossed = 9 + }; + + enum class fg { + black = 30, + red = 31, + green = 32, + yellow = 33, + blue = 34, + magenta = 35, + cyan = 36, + gray = 37, + reset = 39 + }; + + enum class bg { + black = 40, + red = 41, + green = 42, + yellow = 43, + blue = 44, + magenta = 45, + cyan = 46, + gray = 47, + reset = 49 + }; + + enum class fgB { + black = 90, + red = 91, + green = 92, + yellow = 93, + blue = 94, + magenta = 95, + cyan = 96, + gray = 97 + }; + + enum class bgB { + black = 100, + red = 101, + green = 102, + yellow = 103, + blue = 104, + magenta = 105, + cyan = 106, + gray = 107 + }; + + enum class control { // Behaviour of rang function calls + Off = 0, // toggle off rang style/color calls + Auto = 1, // (Default) autodect terminal and colorize if needed + Force = 2 // force ansi color output to non terminal streams + }; +// Use rang::setControlMode to set rang control mode + + enum class winTerm { // Windows Terminal Mode + Auto = 0, // (Default) automatically detects wheter Ansi or Native API + Ansi = 1, // Force use Ansi API + Native = 2 // Force use Native API + }; +// Use rang::setWinTermMode to explicitly set terminal API for Windows +// Calling rang::setWinTermMode have no effect on other OS + + namespace rang_implementation { + + inline std::atomic &controlMode() noexcept + { + static std::atomic value(control::Auto); + return value; + } + + inline std::atomic &winTermMode() noexcept +{ + static std::atomic termMode(winTerm::Auto); + return termMode; +} + +inline bool supportsColor() noexcept +{ +#if defined(OS_LINUX) || defined(OS_MAC) + +static const bool result = [] { + const char *Terms[] + = { "ansi", "color", "console", "cygwin", "gnome", + "konsole", "kterm", "linux", "msys", "putty", + "rxvt", "screen", "vt100", "xterm" }; + + const char *env_p = std::getenv("TERM"); + if (env_p == nullptr) { + return false; + } + return std::any_of(std::begin(Terms), std::end(Terms), + [&](const char *term) { + return std::strstr(env_p, term) != nullptr; + }); + }(); + +#elif defined(OS_WIN) +// All windows versions support colors through native console methods + static constexpr bool result = true; +#endif +return result; +} + +#ifdef OS_WIN + + +inline bool isMsysPty(int fd) noexcept + { + // Dynamic load for binary compability with old Windows + const auto ptrGetFileInformationByHandleEx + = reinterpret_cast( + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), + "GetFileInformationByHandleEx")); + if (!ptrGetFileInformationByHandleEx) { + return false; + } + + HANDLE h = reinterpret_cast(_get_osfhandle(fd)); + if (h == INVALID_HANDLE_VALUE) { + return false; + } + + // Check that it's a pipe: + if (GetFileType(h) != FILE_TYPE_PIPE) { + return false; + } + + // POD type is binary compatible with FILE_NAME_INFO from WinBase.h + // It have the same alignment and used to avoid UB in caller code + struct MY_FILE_NAME_INFO { + DWORD FileNameLength; + WCHAR FileName[MAX_PATH]; + }; + + auto pNameInfo = std::unique_ptr( + new (std::nothrow) MY_FILE_NAME_INFO()); + if (!pNameInfo) { + return false; + } + + // Check pipe name is template of + // {"cygwin-","msys-"}XXXXXXXXXXXXXXX-ptyX-XX + if (!ptrGetFileInformationByHandleEx(h, FileNameInfo, pNameInfo.get(), + sizeof(MY_FILE_NAME_INFO))) { + return false; + } + std::wstring name(pNameInfo->FileName, pNameInfo->FileNameLength / sizeof(WCHAR)); + if ((name.find(L"msys-") == std::wstring::npos + && name.find(L"cygwin-") == std::wstring::npos) + || name.find(L"-pty") == std::wstring::npos) { + return false; + } + + return true; + } + +#endif + +inline bool isTerminal(const std::streambuf *osbuf) noexcept +{ +using std::cerr; +using std::clog; +using std::cout; +#if defined(OS_LINUX) || defined(OS_MAC) +if (osbuf == cout.rdbuf()) { + static const bool cout_term = isatty(fileno(stdout)) != 0; + return cout_term; + } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) { + static const bool cerr_term = isatty(fileno(stderr)) != 0; + return cerr_term; + } +#elif defined(OS_WIN) +if (osbuf == cout.rdbuf()) { + static const bool cout_term + = (_isatty(_fileno(stdout)) || isMsysPty(_fileno(stdout))); + return cout_term; + } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) { + static const bool cerr_term + = (_isatty(_fileno(stderr)) || isMsysPty(_fileno(stderr))); + return cerr_term; + } +#endif +return false; +} + +template +using enableStd = typename std::enable_if< + std::is_same::value || std::is_same::value + || std::is_same::value || std::is_same::value + || std::is_same::value, + std::ostream &>::type; + + +#ifdef OS_WIN + +struct SGR { // Select Graphic Rendition parameters for Windows console + BYTE fgColor; // foreground color (0-15) lower 3 rgb bits + intense bit + BYTE bgColor; // background color (0-15) lower 3 rgb bits + intense bit + BYTE bold; // emulated as FOREGROUND_INTENSITY bit + BYTE underline; // emulated as BACKGROUND_INTENSITY bit + BOOLEAN inverse; // swap foreground/bold & background/underline + BOOLEAN conceal; // set foreground/bold to background/underline + }; + + enum class AttrColor : BYTE { // Color attributes for console screen buffer + black = 0, + red = 4, + green = 2, + yellow = 6, + blue = 1, + magenta = 5, + cyan = 3, + gray = 7 + }; + + inline HANDLE getConsoleHandle(const std::streambuf *osbuf) noexcept + { + if (osbuf == std::cout.rdbuf()) { + static const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + return hStdout; + } else if (osbuf == std::cerr.rdbuf() || osbuf == std::clog.rdbuf()) { + static const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE); + return hStderr; + } + return INVALID_HANDLE_VALUE; + } + + inline bool setWinTermAnsiColors(const std::streambuf *osbuf) noexcept + { + HANDLE h = getConsoleHandle(osbuf); + if (h == INVALID_HANDLE_VALUE) { + return false; + } + DWORD dwMode = 0; + if (!GetConsoleMode(h, &dwMode)) { + return false; + } + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(h, dwMode)) { + return false; + } + return true; + } + + inline bool supportsAnsi(const std::streambuf *osbuf) noexcept + { + using std::cerr; + using std::clog; + using std::cout; + if (osbuf == cout.rdbuf()) { + static const bool cout_ansi + = (isMsysPty(_fileno(stdout)) || setWinTermAnsiColors(osbuf)); + return cout_ansi; + } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) { + static const bool cerr_ansi + = (isMsysPty(_fileno(stderr)) || setWinTermAnsiColors(osbuf)); + return cerr_ansi; + } + return false; + } + + inline const SGR &defaultState() noexcept + { + static const SGR defaultSgr = []() -> SGR { + CONSOLE_SCREEN_BUFFER_INFO info; + WORD attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), + &info) + || GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), + &info)) { + attrib = info.wAttributes; + } + SGR sgr = { 0, 0, 0, 0, FALSE, FALSE }; + sgr.fgColor = attrib & 0x0F; + sgr.bgColor = (attrib & 0xF0) >> 4; + return sgr; + }(); + return defaultSgr; + } + + inline BYTE ansi2attr(BYTE rgb) noexcept + { + static const AttrColor rev[8] + = { AttrColor::black, AttrColor::red, AttrColor::green, + AttrColor::yellow, AttrColor::blue, AttrColor::magenta, + AttrColor::cyan, AttrColor::gray }; + return static_cast(rev[rgb]); + } + + inline void setWinSGR(rang::bg col, SGR &state) noexcept + { + if (col != rang::bg::reset) { + state.bgColor = ansi2attr(static_cast(col) - 40); + } else { + state.bgColor = defaultState().bgColor; + } + } + + inline void setWinSGR(rang::fg col, SGR &state) noexcept + { + if (col != rang::fg::reset) { + state.fgColor = ansi2attr(static_cast(col) - 30); + } else { + state.fgColor = defaultState().fgColor; + } + } + + inline void setWinSGR(rang::bgB col, SGR &state) noexcept + { + state.bgColor = (BACKGROUND_INTENSITY >> 4) + | ansi2attr(static_cast(col) - 100); + } + + inline void setWinSGR(rang::fgB col, SGR &state) noexcept + { + state.fgColor + = FOREGROUND_INTENSITY | ansi2attr(static_cast(col) - 90); + } + + inline void setWinSGR(rang::style style, SGR &state) noexcept + { + switch (style) { + case rang::style::reset: state = defaultState(); break; + case rang::style::bold: state.bold = FOREGROUND_INTENSITY; break; + case rang::style::underline: + case rang::style::blink: + state.underline = BACKGROUND_INTENSITY; + break; + case rang::style::reversed: state.inverse = TRUE; break; + case rang::style::conceal: state.conceal = TRUE; break; + default: break; + } + } + + inline SGR ¤t_state() noexcept + { + static SGR state = defaultState(); + return state; + } + + inline WORD SGR2Attr(const SGR &state) noexcept + { + WORD attrib = 0; + if (state.conceal) { + if (state.inverse) { + attrib = (state.fgColor << 4) | state.fgColor; + if (state.bold) + attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; + } else { + attrib = (state.bgColor << 4) | state.bgColor; + if (state.underline) + attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; + } + } else if (state.inverse) { + attrib = (state.fgColor << 4) | state.bgColor; + if (state.bold) attrib |= BACKGROUND_INTENSITY; + if (state.underline) attrib |= FOREGROUND_INTENSITY; + } else { + attrib = state.fgColor | (state.bgColor << 4) | state.bold + | state.underline; + } + return attrib; + } + + template + inline void setWinColorAnsi(std::ostream &os, T const value) + { + os << "\033[" << static_cast(value) << "m"; + } + + template + inline void setWinColorNative(std::ostream &os, T const value) + { + const HANDLE h = getConsoleHandle(os.rdbuf()); + if (h != INVALID_HANDLE_VALUE) { + setWinSGR(value, current_state()); + // Out all buffered text to console with previous settings: + os.flush(); + SetConsoleTextAttribute(h, SGR2Attr(current_state())); + } + } + + template + inline enableStd setColor(std::ostream &os, T const value) + { + if (winTermMode() == winTerm::Auto) { + if (supportsAnsi(os.rdbuf())) { + setWinColorAnsi(os, value); + } else { + setWinColorNative(os, value); + } + } else if (winTermMode() == winTerm::Ansi) { + setWinColorAnsi(os, value); + } else { + setWinColorNative(os, value); + } + return os; + } +#else +template +inline enableStd setColor(std::ostream &os, T const value) +{ + return os << "\033[" << static_cast(value) << "m"; +} +#endif +} // namespace rang_implementation + +template +inline rang_implementation::enableStd operator<<(std::ostream &os, + const T value) +{ + const control option = rang_implementation::controlMode(); + switch (option) { + case control::Auto: + return rang_implementation::supportsColor() + && rang_implementation::isTerminal(os.rdbuf()) + ? rang_implementation::setColor(os, value) + : os; + case control::Force: return rang_implementation::setColor(os, value); + default: return os; + } +} + +inline void setWinTermMode(const rang::winTerm value) noexcept +{ +rang_implementation::winTermMode() = value; +} + +inline void setControlMode(const control value) noexcept +{ +rang_implementation::controlMode() = value; +} + +} // namespace rang + +#undef OS_LINUX +#undef OS_WIN +#undef OS_MAC + +#endif /* ifndef RANG_DOT_HPP */ diff --git a/common/version.h b/common/version.h index b9f3d43b3..b667db189 100644 --- a/common/version.h +++ b/common/version.h @@ -34,13 +34,8 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9183 - -#ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9028 -#else - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 -#endif +#define CURRENT_BINARY_DATABASE_VERSION 9217 +#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9036 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ diff --git a/zone/zone_store.cpp b/common/zone_store.cpp similarity index 58% rename from zone/zone_store.cpp rename to common/zone_store.cpp index 52eeace3c..cbc232617 100644 --- a/zone/zone_store.cpp +++ b/common/zone_store.cpp @@ -19,15 +19,18 @@ */ #include "zone_store.h" -#include "../common/repositories/content_flags_repository.h" #include "../common/content/world_content_service.h" +#include "stacktrace/backward.hpp" ZoneStore::ZoneStore() = default; ZoneStore::~ZoneStore() = default; -void ZoneStore::LoadZones() +// cache record of zones for fast successive retrieval +void ZoneStore::LoadZones(Database &db) { - zones = ZoneRepository::All(content_db); + m_zones = ZoneRepository::All(db); + + LogInfo("Loaded [{}] zones", m_zones.size()); } /** @@ -40,7 +43,7 @@ uint32 ZoneStore::GetZoneID(const char *in_zone_name) return 0; } - std::string zone_name = str_tolower(in_zone_name); + std::string zone_name = Strings::ToLower(in_zone_name); return GetZoneID(zone_name); } @@ -51,12 +54,14 @@ uint32 ZoneStore::GetZoneID(const char *in_zone_name) */ uint32 ZoneStore::GetZoneID(std::string zone_name) { - for (auto &z: zones) { + for (auto &z: m_zones) { if (z.short_name == zone_name) { return z.zoneidnumber; } } + LogInfo("Failed to get zone_name [{}]", zone_name); + return 0; } @@ -67,7 +72,7 @@ uint32 ZoneStore::GetZoneID(std::string zone_name) */ const char *ZoneStore::GetZoneName(uint32 zone_id, bool error_unknown) { - for (auto &z: zones) { + for (auto &z: m_zones) { if (z.zoneidnumber == zone_id) { return z.short_name.c_str(); } @@ -87,7 +92,7 @@ const char *ZoneStore::GetZoneName(uint32 zone_id, bool error_unknown) */ const char *ZoneStore::GetZoneLongName(uint32 zone_id, bool error_unknown) { - for (auto &z: zones) { + for (auto &z: m_zones) { if (z.zoneidnumber == zone_id) { return z.long_name.c_str(); } @@ -106,13 +111,15 @@ const char *ZoneStore::GetZoneLongName(uint32 zone_id, bool error_unknown) */ std::string ZoneStore::GetZoneName(uint32 zone_id) { - for (auto &z: zones) { + for (auto &z: m_zones) { if (z.zoneidnumber == zone_id) { return z.short_name; } } - return std::string(); + LogInfo("Failed to get zone long name by zone_id [{}]", zone_id); + + return {}; } /** @@ -121,13 +128,15 @@ std::string ZoneStore::GetZoneName(uint32 zone_id) */ std::string ZoneStore::GetZoneLongName(uint32 zone_id) { - for (auto &z: zones) { + for (auto &z: m_zones) { if (z.zoneidnumber == zone_id) { return z.long_name; } } - return std::string(); + LogInfo("Failed to get zone long name by zone_id [{}]", zone_id); + + return {}; } /** @@ -135,28 +144,69 @@ std::string ZoneStore::GetZoneLongName(uint32 zone_id) * @param version * @return */ -ZoneRepository::Zone ZoneStore::GetZone(uint32 zone_id, int version) +ZoneRepository::Zone *ZoneStore::GetZone(uint32 zone_id, int version) { - for (auto &z: zones) { + for (auto &z: m_zones) { if (z.zoneidnumber == zone_id && z.version == version) { - return z; + return &z; } } - return ZoneRepository::Zone(); + LogInfo("Failed to get zone by zone_id [{}] version [{}]", zone_id, version); + + return nullptr; } /** * @param in_zone_name * @return */ -ZoneRepository::Zone ZoneStore::GetZone(const char *in_zone_name) +ZoneRepository::Zone *ZoneStore::GetZone(const char *in_zone_name) { - for (auto &z: zones) { + for (auto &z: m_zones) { if (z.short_name == in_zone_name) { - return z; + return &z; } } - return ZoneRepository::Zone(); + LogInfo("Failed to get zone by zone_name [{}]", in_zone_name); + + return nullptr; +} + +ZoneRepository::Zone *ZoneStore::GetZone(std::string in_zone_name) +{ + for (auto &z: m_zones) { + if (z.short_name == in_zone_name) { + return &z; + } + } + + return nullptr; +} + +const std::vector &ZoneStore::GetZones() const +{ + return m_zones; +} + +// gets zone data by using explicit version and falling back to version 0 if not found +ZoneRepository::Zone *ZoneStore::GetZoneWithFallback(uint32 zone_id, int version) +{ + for (auto &z: m_zones) { + if (z.zoneidnumber == zone_id && z.version == version) { + return &z; + } + } + + // second pass, default to version 0 if specific doesn't exist + for (auto &z: m_zones) { + if (z.zoneidnumber == zone_id && z.version == 0) { + return &z; + } + } + + LogInfo("Failed to get zone by zone_id [{}] version [{}]", zone_id, version); + + return nullptr; } diff --git a/zone/zone_store.h b/common/zone_store.h similarity index 68% rename from zone/zone_store.h rename to common/zone_store.h index 7238b0ade..e769d30d6 100644 --- a/zone/zone_store.h +++ b/common/zone_store.h @@ -21,7 +21,6 @@ #ifndef EQEMU_ZONE_STORE_H #define EQEMU_ZONE_STORE_H -#include "zonedb.h" #include "../common/repositories/zone_repository.h" #include "../common/repositories/base/base_content_flags_repository.h" @@ -30,18 +29,22 @@ public: ZoneStore(); virtual ~ZoneStore(); - std::vector zones; + const std::vector &GetZones() const; - void LoadZones(); + void LoadZones(Database &db); - ZoneRepository::Zone GetZone(uint32 zone_id, int version = 0); - ZoneRepository::Zone GetZone(const char *in_zone_name); + ZoneRepository::Zone *GetZone(uint32 zone_id, int version = 0); + ZoneRepository::Zone *GetZone(const char *in_zone_name); + ZoneRepository::Zone *GetZone(std::string in_zone_name); uint32 GetZoneID(const char *in_zone_name); uint32 GetZoneID(std::string zone_name); std::string GetZoneName(uint32 zone_id); std::string GetZoneLongName(uint32 zone_id); const char *GetZoneName(uint32 zone_id, bool error_unknown = false); const char *GetZoneLongName(uint32 zone_id, bool error_unknown = false); + ZoneRepository::Zone *GetZoneWithFallback(uint32 zone_id, int version = 0); +private: + std::vector m_zones; }; extern ZoneStore zone_store; @@ -65,7 +68,22 @@ inline const char *ZoneLongName(uint32 zone_id, bool error_unknown = false) error_unknown ); } -inline ZoneRepository::Zone GetZone(uint32 zone_id, int version = 0) { return zone_store.GetZone(zone_id, version); }; -inline ZoneRepository::Zone GetZone(const char *in_zone_name) { return zone_store.GetZone(in_zone_name); }; +inline ZoneRepository::Zone *GetZone(uint32 zone_id, int version = 0) { return zone_store.GetZone(zone_id, version); }; +inline ZoneRepository::Zone *GetZone(const char *in_zone_name) { return zone_store.GetZone(in_zone_name); }; +inline ZoneRepository::Zone *GetZone(const char *in_zone_name, int version = 0) +{ + return zone_store.GetZone( + ZoneID( + in_zone_name + ), version + ); +}; +inline ZoneRepository::Zone *GetZoneVersionWithFallback(uint32 zone_id, int version = 0) +{ + return zone_store.GetZoneWithFallback( + zone_id, + version + ); +}; #endif //EQEMU_ZONE_STORE_H diff --git a/eqlaunch/CMakeLists.txt b/eqlaunch/CMakeLists.txt index c5e7bbd03..4fde2c222 100644 --- a/eqlaunch/CMakeLists.txt +++ b/eqlaunch/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(eqlaunch_sources eqlaunch.cpp diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index 4cb7f7b9c..ea41b1803 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -21,6 +21,7 @@ #include "../common/proc_launcher.h" #include "../common/eqemu_config.h" #include "../common/servertalk.h" +#include "../common/path_manager.h" #include "../common/platform.h" #include "../common/crash.h" #include "../common/unix.h" @@ -33,6 +34,7 @@ #include EQEmuLogSys LogSys; +PathManager path; bool RunLoops = false; @@ -43,6 +45,8 @@ int main(int argc, char *argv[]) { LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + std::string launcher_name; if(argc == 2) { launcher_name = argv[1]; @@ -101,11 +105,17 @@ int main(int argc, char *argv[]) { Log(Logs::Detail, Logs::Launcher, "Starting main loop..."); ProcLauncher *launch = ProcLauncher::get(); + RunLoops = true; - while(RunLoops) { + auto loop_fn = [&](EQ::Timer* t) { //Advance the timer to our current point in time Timer::SetCurrentTime(); + if (!RunLoops) { + EQ::EventLoop::Get().Shutdown(); + return; + } + /* * Let the process manager look for dead children */ @@ -116,29 +126,31 @@ int main(int argc, char *argv[]) { */ zone = zones.begin(); zend = zones.end(); - for(; zone != zend; ++zone) { - if(!zone->second->Process()) + for (; zone != zend; ++zone) { + if (!zone->second->Process()) to_remove.insert(zone->first); } /* * Kill off any zones which have stopped */ - while(!to_remove.empty()) { + while (!to_remove.empty()) { std::string rem = *to_remove.begin(); to_remove.erase(rem); zone = zones.find(rem); - if(zone == zones.end()) { + if (zone == zones.end()) { //wtf... continue; } delete zone->second; zones.erase(rem); } + }; - EQ::EventLoop::Get().Process(); - Sleep(5); - } + EQ::Timer process_timer(loop_fn); + process_timer.Start(32, true); + + EQ::EventLoop::Get().Run(); //try to be semi-nice about this... without waiting too long zone = zones.begin(); diff --git a/eqlaunch/worldserver.cpp b/eqlaunch/worldserver.cpp index c50b58e09..98e34da81 100644 --- a/eqlaunch/worldserver.cpp +++ b/eqlaunch/worldserver.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/eqemu_logsys.h" #include "../common/servertalk.h" #include "../common/eqemu_config.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "worldserver.h" #include "zone_launch.h" diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index f454d164a..d5b325aec 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,3 +1,7 @@ IF(EQEMU_BUILD_LUA) ADD_SUBDIRECTORY(luabind) ENDIF(EQEMU_BUILD_LUA) + +IF(EQEMU_BUILD_PERL) + ADD_SUBDIRECTORY(perlbind) +ENDIF(EQEMU_BUILD_PERL) diff --git a/libs/luabind/CMakeLists.txt b/libs/luabind/CMakeLists.txt index d29bb4bb1..74d95ee70 100644 --- a/libs/luabind/CMakeLists.txt +++ b/libs/luabind/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(lb_sources src/class.cpp diff --git a/libs/luabind/luabind/detail/policy.hpp b/libs/luabind/luabind/detail/policy.hpp index 79577c9a4..e154507e4 100644 --- a/libs/luabind/luabind/detail/policy.hpp +++ b/libs/luabind/luabind/detail/policy.hpp @@ -142,11 +142,11 @@ namespace luabind { namespace detail { static const T& t; - BOOST_STATIC_CONSTANT(bool, value = + BOOST_STATIC_CONSTANT(bool, value = sizeof(is_policy_cons_test(t)) == sizeof(yes_t)); typedef boost::mpl::bool_ type; - }; + }; template struct is_string_literal @@ -160,7 +160,7 @@ namespace luabind { namespace detail { static no_t helper(indirection_layer); }; - + namespace mpl = boost::mpl; @@ -217,7 +217,7 @@ namespace luabind { namespace detail template void apply(lua_State* L, T* ptr) { - if (ptr == 0) + if (ptr == 0) { lua_pushnil(L); return; @@ -251,7 +251,7 @@ namespace luabind { namespace detail } template - void converter_postcall(lua_State*, by_pointer, int) + void converter_postcall(lua_State*, by_pointer, int) {} }; @@ -328,7 +328,7 @@ namespace luabind { namespace detail template void apply(lua_State* L, const T* ptr) { - if (ptr == 0) + if (ptr == 0) { lua_pushnil(L); return; @@ -472,7 +472,7 @@ namespace luabind { namespace detail { return 1; } - + void apply(lua_State* L, int val) { lua_pushnumber(L, val); @@ -483,7 +483,7 @@ namespace luabind { namespace detail { return static_cast(static_cast(lua_tonumber(L, index))); } - + template static int match(lua_State* L, by_value, int index) { @@ -532,7 +532,7 @@ namespace luabind { namespace detail template static int match(lua_State* L, by_const_reference, int index) { - return value_wrapper_traits::check(L, index) + return value_wrapper_traits::check(L, index) ? (std::numeric_limits::max)() / LUABIND_MAX_ARITY : -1; } @@ -694,9 +694,11 @@ LUABIND_NUMBER_CONVERTER(unsigned char, integer) LUABIND_NUMBER_CONVERTER(signed short, integer) LUABIND_NUMBER_CONVERTER(unsigned short, integer) LUABIND_NUMBER_CONVERTER(signed int, integer) +LUABIND_NUMBER_CONVERTER(signed long long, integer) LUABIND_NUMBER_CONVERTER(unsigned int, number) LUABIND_NUMBER_CONVERTER(unsigned long, number) +LUABIND_NUMBER_CONVERTER(unsigned long long, number) LUABIND_NUMBER_CONVERTER(signed long, integer) LUABIND_NUMBER_CONVERTER(float, number) diff --git a/libs/luabind/src/class_info.cpp b/libs/luabind/src/class_info.cpp index 531f6e0cc..30d1032a5 100644 --- a/libs/luabind/src/class_info.cpp +++ b/libs/luabind/src/class_info.cpp @@ -33,7 +33,7 @@ namespace luabind LUABIND_API class_info get_class_info(argument const& o) { lua_State* L = o.interpreter(); - + o.push(L); detail::object_rep* obj = detail::get_instance(L, -1); @@ -106,15 +106,15 @@ namespace luabind LUABIND_API void bind_class_info(lua_State* L) { module(L) - [ + [( class_("class_info_data") .def_readonly("name", &class_info::name) .def_readonly("methods", &class_info::methods) .def_readonly("attributes", &class_info::attributes), - + def("class_info", &get_class_info), def("class_names", &get_class_names) - ]; + )]; } } diff --git a/libs/perlbind/.gitignore b/libs/perlbind/.gitignore new file mode 100644 index 000000000..af66ff704 --- /dev/null +++ b/libs/perlbind/.gitignore @@ -0,0 +1,21 @@ +* +!.gitignore +!.editorconfig +!CMakeLists.txt +!LICENSE +!README.md + +!.github/ +!.github/** + +!doc/ +!doc/** + +!include/ +!include/** + +!src/ +!src/* + +!test/ +!test/* diff --git a/libs/perlbind/CMakeLists.txt b/libs/perlbind/CMakeLists.txt new file mode 100644 index 000000000..c03dd8e3a --- /dev/null +++ b/libs/perlbind/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.7) + +project(perlbind LANGUAGES CXX) + +set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".so" ".a") + +find_package(PerlLibs) + +set(PERLBIND_HEADERS + include/perlbind/array.h + include/perlbind/forward.h + include/perlbind/function.h + include/perlbind/hash.h + include/perlbind/interpreter.h + include/perlbind/iterator.h + include/perlbind/package.h + include/perlbind/perlbind.h + include/perlbind/scalar.h + include/perlbind/stack.h + include/perlbind/stack_push.h + include/perlbind/stack_read.h + include/perlbind/subcaller.h + include/perlbind/traits.h + include/perlbind/typemap.h + include/perlbind/types.h + include/perlbind/util.h + include/perlbind/version.h +) + +set(PERLBIND_SOURCES + src/function.cpp + src/hash.cpp + src/interpreter.cpp + src/package.cpp +) + +if(MSVC) + set(PERLBIND_SOURCES ${PERLBIND_SOURCES} src/perlbind.natvis) +endif() + +add_library(perlbind ${PERLBIND_SOURCES} ${PERLBIND_HEADERS}) + +target_include_directories(perlbind PUBLIC + ${PERL_INCLUDE_PATH} + $ + $) + +option(PERLBIND_BUILD_TESTS "Build tests" OFF) +option(PERLBIND_ENABLE_ASAN "Build with address sanitizer" OFF) + +if(PERLBIND_ENABLE_ASAN) + target_compile_options(perlbind PRIVATE -fsanitize=address -fno-omit-frame-pointer) + target_link_options(perlbind PRIVATE -fsanitize=address -fno-omit-frame-pointer) +endif() + +if(PERLBIND_BUILD_TESTS) + enable_testing() + add_subdirectory(test) + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT tests) + + target_include_directories(tests PRIVATE + ${PERL_INCLUDE_PATH} + ${CMAKE_CURRENT_SOURCE_DIR}/include) +endif() diff --git a/libs/perlbind/LICENSE b/libs/perlbind/LICENSE new file mode 100644 index 000000000..37bca4200 --- /dev/null +++ b/libs/perlbind/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2022 hg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libs/perlbind/include/perlbind/array.h b/libs/perlbind/include/perlbind/array.h new file mode 100644 index 000000000..be9b7781a --- /dev/null +++ b/libs/perlbind/include/perlbind/array.h @@ -0,0 +1,119 @@ +#pragma once + +#include "types.h" +#include "iterator.h" +#include + +namespace perlbind { + +struct array : public type_base +{ + using iterator = detail::array_iterator; + + ~array() noexcept + { + SvREFCNT_dec(m_av); + } + + array() noexcept + : type_base(), m_av(newAV()) {} + array(PerlInterpreter* interp) noexcept + : type_base(interp), m_av(newAV()) {} + array(const array& other) noexcept + : type_base(other.my_perl), m_av(copy_array(other.m_av)) {} + array(array&& other) noexcept + : type_base(other.my_perl), m_av(other.m_av) + { + other.m_av = newAV(); + } + array(AV*& value) noexcept + : type_base(), m_av(copy_array(value)) {} + array(AV*&& value) noexcept + : type_base(), m_av(value) {} // take ownership + array(scalar ref) + : type_base(ref.my_perl) + { + if (!ref.is_array_ref()) + throw std::runtime_error("cannot construct array from non-array reference"); + + reset(reinterpret_cast(SvREFCNT_inc(*ref))); + } + array(scalar_proxy proxy) + : array(scalar(SvREFCNT_inc(proxy.sv()))) {} + + array& operator=(const array& other) noexcept + { + if (this != &other) + m_av = copy_array(other.m_av); + + return *this; + } + + array& operator=(array&& other) noexcept + { + if (this != &other) + std::swap(m_av, other.m_av); + + return *this; + } + + array& operator=(AV*& value) noexcept + { + if (m_av != value) + m_av = copy_array(value); + + return *this; + } + + array& operator=(AV*&& value) noexcept + { + reset(value); + return *this; + } + + operator AV*() const { return m_av; } + operator SV*() const { return reinterpret_cast(m_av); } + + AV* release() noexcept + { + AV* tmp = m_av; + m_av = newAV(); + return tmp; + } + + void reset(AV* value) noexcept + { + SvREFCNT_dec(m_av); + m_av = value; + } + + void clear() noexcept { av_clear(m_av); } // decreases refcnt of all SV elements + scalar pop_back() noexcept { return av_pop(m_av); } + scalar pop_front() noexcept { return av_shift(m_av); } + void push_back(const scalar& value) { av_push(m_av, newSVsv(value)); } + void push_back(scalar&& value) { av_push(m_av, value.release()); } + void reserve(size_t count) { av_extend(m_av, count > 0 ? count - 1 : 0); } + size_t size() const { return av_len(m_av) + 1; } + SV* sv() const { return reinterpret_cast(m_av); } + + // returns a proxy that takes ownership of one reference to the SV element + // extends the array and creates an undef SV if index out of range + scalar_proxy operator[](size_t index) + { + SV** sv = av_fetch(m_av, index, 1); + return scalar_proxy(my_perl, SvREFCNT_inc(*sv)); + } + + iterator begin() const noexcept { return { my_perl, m_av, 0 }; } + iterator end() const noexcept { return { my_perl, m_av, size() }; } + +private: + AV* copy_array(AV* other) + { + return av_make(av_len(other)+1, AvARRAY(other)); + } + + AV* m_av = nullptr; +}; + +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/forward.h b/libs/perlbind/include/perlbind/forward.h new file mode 100644 index 000000000..9757eb19c --- /dev/null +++ b/libs/perlbind/include/perlbind/forward.h @@ -0,0 +1,22 @@ +#pragma once + +namespace perlbind { + +namespace detail { + +class xsub_stack; +struct function_base; +struct array_iterator; +struct hash_iterator; + +} // namespace detail + +class interpreter; +class package; +struct scalar; +struct scalar_proxy; +struct reference; +struct array; +struct hash; + +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/function.h b/libs/perlbind/include/perlbind/function.h new file mode 100644 index 000000000..2d4455a9b --- /dev/null +++ b/libs/perlbind/include/perlbind/function.h @@ -0,0 +1,144 @@ +#pragma once + +namespace perlbind { namespace detail { + +// traits for function and class method exports +template +struct base_traits +{ + using return_t = Ret; + using sig_t = util::type_name; + using stack_tuple = std::conditional_t::value, + std::tuple, + std::tuple>; + static constexpr int arity = sizeof...(Args); + static constexpr int stack_arity = sizeof...(Args) + (std::is_void::value ? 0 : 1); + static constexpr int vararg_count = count_of::value + + count_of::value; + static constexpr bool is_vararg = vararg_count > 0; + static constexpr bool is_vararg_last = is_last::value || + is_last::value; + + static_assert(!is_vararg || (vararg_count == 1 && is_vararg_last), + "A function may only accept a single array or hash and it must be " + "be the last parameter. Prefer using reference parameters instead."); +}; + +template ::value> +struct function_traits : public function_traits {}; + +template +struct function_traits : base_traits +{ + using type = Ret(*)(Args...); +}; + +template +struct function_traits : base_traits +{ + using type = Ret(Class::*)(Args...); +}; + +template +struct function_traits : base_traits +{ + using type = Ret(Class::*)(Args...) const; +}; + +template +struct function_traits : base_traits +{ + using type = Ret(*)(Args...); +}; + +// represents a bound native function +struct function_base +{ + virtual ~function_base() = default; + virtual std::string get_signature() const = 0; + virtual bool is_compatible(xsub_stack&) const = 0; + virtual void call(xsub_stack&) const = 0; + + static const MGVTBL mgvtbl; +}; + +template +struct function : public function_base, function_traits +{ + using target_t = typename function::type; + using return_t = typename function::return_t; + + function() = delete; + function(PerlInterpreter* interp, T func) + : my_perl(interp), m_func(func) {} + + std::string get_signature() const override + { + return util::type_name::str(); + }; + + bool is_compatible(xsub_stack& stack) const override + { + return function::is_vararg || stack.check_types(typename function::stack_tuple{}); + } + + void call(xsub_stack& stack) const override + { + if (!function::is_vararg && stack.size() != function::stack_arity) + { + using sig = typename function::sig_t; + int count = std::is_member_function_pointer::value ? stack.size() - 1 : stack.size(); + SV* err = newSVpvf("'%s(%s)' called with %d argument(s), expected %d\n argument(s): (%s)\n", + stack.name().c_str(), sig::str().c_str(), count, function::arity, stack.types().c_str()); + err = sv_2mortal(err); + throw std::runtime_error(SvPV_nolen(err)); + } + + call_impl(stack, std::is_void()); + } + +private: + void call_impl(xsub_stack& stack, std::false_type) const + { + return_t result = apply(m_func, stack.convert_stack(typename function::stack_tuple{})); + stack.push_return(std::move(result)); + } + + void call_impl(xsub_stack& stack, std::true_type) const + { + apply(m_func, stack.convert_stack(typename function::stack_tuple{})); + } + + // c++14 call function template with tuple arg unpacking (c++17 can use std::apply()) + template + auto call_func(F func, Tuple&& t, std::index_sequence) const + { + return func(std::get(std::forward(t))...); + } + + template + auto call_member(F method, Tuple&& t, std::index_sequence) const + { + return (std::get<0>(t)->*method)(std::get(std::forward(t))...); + } + + template ::value, bool> = true> + auto apply(F func, Tuple&& t) const + { + using make_sequence = std::make_index_sequence::value>; + return call_func(func, std::forward(t), make_sequence{}); + } + + template ::value, bool> = true> + auto apply(F func, Tuple&& t) const + { + using make_sequence = std::make_index_sequence::value - 1>; + return call_member(func, std::forward(t), make_sequence{}); + } + + PerlInterpreter* my_perl = nullptr; + T m_func; +}; + +} // namespace detail +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/hash.h b/libs/perlbind/include/perlbind/hash.h new file mode 100644 index 000000000..28bf72d53 --- /dev/null +++ b/libs/perlbind/include/perlbind/hash.h @@ -0,0 +1,124 @@ +#pragma once + +#include "types.h" +#include + +namespace perlbind { + +struct hash : public type_base +{ + using iterator = detail::hash_iterator; + + ~hash() noexcept + { + SvREFCNT_dec(m_hv); + } + + hash() noexcept + : type_base(), m_hv(newHV()) {} + hash(PerlInterpreter* interp) noexcept + : type_base(interp), m_hv(newHV()) {} + hash(const hash& other) noexcept + : type_base(other.my_perl), m_hv(copy_hash(other.m_hv)) {} + hash(hash&& other) noexcept + : type_base(other.my_perl), m_hv(other.m_hv) + { + other.m_hv = newHV(); + } + hash(HV*& value) noexcept + : type_base(), m_hv(copy_hash(value)) {} + hash(HV*&& value) noexcept + : type_base(), m_hv(value) {} // take ownership + hash(scalar ref); + hash(scalar_proxy proxy); + + hash& operator=(const hash& other) noexcept + { + if (this != &other) + m_hv = copy_hash(other.m_hv); + + return *this; + } + + hash& operator=(hash&& other) noexcept + { + if (this != &other) + std::swap(m_hv, other.m_hv); + + return *this; + } + + hash& operator=(HV*& value) noexcept + { + if (m_hv != value) + m_hv = copy_hash(value); + + return *this; + } + + hash& operator=(HV*&& value) noexcept + { + reset(value); + return *this; + } + + operator HV*() const { return m_hv; } + operator SV*() const { return reinterpret_cast(m_hv); } + + HV* release() noexcept + { + HV* tmp = m_hv; + m_hv = newHV(); + return tmp; + } + + void reset(HV* value) noexcept + { + SvREFCNT_dec(m_hv); + m_hv = value; + } + + scalar at(const char* key); + scalar at(const std::string& key); + void clear() noexcept { hv_clear(m_hv); } + bool exists(const char* key) const + { + return hv_exists(m_hv, key, static_cast(strlen(key))); + } + bool exists(const std::string& key) const + { + return hv_exists(m_hv, key.c_str(), static_cast(key.size())); + } + void insert(const char* key, scalar value); + void insert(const std::string& key, scalar value); + void remove(const char* key) + { + hv_delete(m_hv, key, static_cast(strlen(key)), 0); + } + void remove(const std::string& key) + { + hv_delete(m_hv, key.c_str(), static_cast(key.size()), 0); + } + size_t size() const { return HvTOTALKEYS(m_hv); } + SV* sv() const { return reinterpret_cast(m_hv); } + + // returns a proxy that takes ownership of one reference to the SV value + // creates an undef SV entry for the key if it doesn't exist + scalar_proxy operator[](const std::string& key); + + iterator begin() const noexcept; + iterator end() const noexcept; + iterator find(const char* key); + iterator find(const std::string& key); + +private: + scalar at(const char* key, size_t size); + iterator find(const char* key, size_t size); + void insert(const char* key, size_t size, scalar value); + + HV* copy_hash(HV* other) noexcept; + + HV* m_hv = nullptr; +}; + +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/interpreter.h b/libs/perlbind/include/perlbind/interpreter.h new file mode 100644 index 000000000..5d4f03caf --- /dev/null +++ b/libs/perlbind/include/perlbind/interpreter.h @@ -0,0 +1,63 @@ +#pragma once + +namespace perlbind { + +class interpreter +{ +public: + interpreter(); + interpreter(PerlInterpreter* interp) : my_perl(interp) {} + interpreter(int argc, const char** argv); + interpreter(const interpreter& other) = delete; + interpreter(interpreter&& other) = delete; + interpreter& operator=(const interpreter& other) = delete; + interpreter& operator=(interpreter&& other) = delete; + ~interpreter(); + + PerlInterpreter* get() const { return my_perl; } + + void load_script(std::string packagename, std::string filename); + void eval(const char* str); + + template + T call_sub(const char* subname, Args&&... args) const + { + detail::sub_caller caller(my_perl); + return caller.call_sub(subname, std::forward(args)...); + } + + // returns interface to add bindings to package name + package new_package(const char* name) + { + return package(my_perl, name); + } + + // registers type for blessing objects, returns interface + template + class_ new_class(const char* name) + { + static_assert(!std::is_pointer::value && !std::is_reference::value, + "new_class 'T' should not be a pointer or reference"); + + auto typemap = detail::typemap::get(my_perl); + auto type_id = detail::usertype::id(); + typemap[type_id] = name; + + return class_(my_perl, name); + } + + // helper to bind functions in default main:: package + template + void add(const char* name, T&& func) + { + new_package("main").add(name, std::forward(func)); + } + +private: + void init(int argc, const char** argv); + + bool m_is_owner = false; + PerlInterpreter* my_perl = nullptr; +}; + +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/iterator.h b/libs/perlbind/include/perlbind/iterator.h new file mode 100644 index 000000000..c53174129 --- /dev/null +++ b/libs/perlbind/include/perlbind/iterator.h @@ -0,0 +1,100 @@ +#pragma once + +namespace perlbind { namespace detail { + +struct array_iterator +{ + array_iterator() = default; + array_iterator(PerlInterpreter* interp, AV* av, size_t index) + : my_perl(interp), m_av(av), m_index(index), m_scalar(interp) + { + fetch(); + } + + bool operator!=(const array_iterator& other) const + { + return m_index != other.m_index; + } + + array_iterator& operator++() + { + ++m_index; + fetch(); + return *this; + } + + scalar* operator->() + { + return &m_scalar; + } + + scalar& operator*() + { + return m_scalar; + } + +private: + void fetch() + { + SV** sv = av_fetch(m_av, m_index, 0); + if (sv) + m_scalar = SvREFCNT_inc(*sv); + } + + PerlInterpreter* my_perl; + AV* m_av; + size_t m_index; + scalar m_scalar; +}; + +struct hash_iterator +{ + hash_iterator() = default; + hash_iterator(PerlInterpreter* interp, HV* hv, HE* he) + : my_perl(interp), m_hv(hv), m_he(he) + { + fetch(); + } + + bool operator==(const hash_iterator& other) const + { + return m_he == other.m_he; + } + + bool operator!=(const hash_iterator& other) const + { + return !(*this == other); + } + + hash_iterator& operator++() + { + m_he = hv_iternext(m_hv); + fetch(); + return *this; + } + + std::pair* operator->() + { + return &m_pair; + } + + std::pair& operator*() + { + return m_pair; + } + +private: + void fetch() + { + if (m_he) + m_pair = { HePV(m_he, PL_na), scalar(my_perl, SvREFCNT_inc(HeVAL(m_he))) }; + } + + PerlInterpreter* my_perl; + HV* m_hv; + HE* m_he; + std::pair m_pair; +}; + +} // namespace detail +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/package.h b/libs/perlbind/include/perlbind/package.h new file mode 100644 index 000000000..3e8238662 --- /dev/null +++ b/libs/perlbind/include/perlbind/package.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +namespace perlbind { + +class package +{ +public: + virtual ~package() = default; + package() = delete; + package(PerlInterpreter* interp, const char* name) + : my_perl(interp), m_name(name), m_stash(gv_stashpv(name, GV_ADD)) + {} + + // bind a function pointer to a function name in the package + // overloads with same name must be explicit (default parameters not supported) + // overloads have a runtime lookup cost and chooses the first compatible overload + template + void add(const char* name, T func) + { + // ownership of function object is given to perl + auto function = new detail::function(my_perl, func); + add_impl(name, static_cast(function)); + } + + // specify a base class name for object inheritance (must be registered) + // calling object methods missing from the package will search parent classes + // base classes are searched in registered order and include any grandparents + void add_base_class(const char* name) + { + std::string package_isa = m_name + "::ISA"; + AV* av = get_av(package_isa.c_str(), GV_ADD); + array isa_array = reinterpret_cast(SvREFCNT_inc(av)); + isa_array.push_back(name); + } + + // add a constant value to this package namespace + template + void add_const(const char* name, T&& value) + { + newCONSTSUB(m_stash, name, scalar(value).release()); + } + +private: + void add_impl(const char* name, detail::function_base* function); + + std::string m_name; + PerlInterpreter* my_perl = nullptr; + HV* m_stash = nullptr; +}; + +template +struct class_ : public package +{ + using package::package; +}; + +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/perlbind.h b/libs/perlbind/include/perlbind/perlbind.h new file mode 100644 index 000000000..7e1a7830e --- /dev/null +++ b/libs/perlbind/include/perlbind/perlbind.h @@ -0,0 +1,55 @@ +#pragma once + +// Defining PERLBIND_STRICT_NUMERIC_TYPES will enable strict type checks +// for integers and floats.This is required for overloads that depend on +// int and float type differences. +// #define PERLBIND_STRICT_NUMERIC_TYPES + +// Defining PERLBIND_NO_STRICT_SCALAR_TYPES will disable strict type checks +// for all int, float, and string function arguments. These types will only +// be checked for scalar validity and converted to the function's expected +// paramter type. This will break overloads that depend on distinct types. +// This option overrides PERLBIND_STRICT_NUMERIC_TYPES. +//#define PERLBIND_NO_STRICT_SCALAR_TYPES + +// defining PERL_NO_GET_CONTEXT gets context from local variable "my_perl" +// instead of calling Perl_get_context() in macros +#define PERL_NO_GET_CONTEXT + +#define WIN32IO_IS_STDIO +#if _MSC_VER +#define __inline__ __inline +// perl 5.30+ defines HAS_BUILTIN_EXPECT for msvc which breaks builds +#define __builtin_expect(expr,val) (expr) +// avoid INT64_C and UINT64_C redefinition warnings +#if PERL_VERSION < 28 +#include +#endif +#endif + +#include +#include +#include + +// short name perl macros that cause issues +#undef Move +#undef Copy +#undef Zero +#undef list +#undef seed +#undef do_open +#undef do_close + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/libs/perlbind/include/perlbind/scalar.h b/libs/perlbind/include/perlbind/scalar.h new file mode 100644 index 000000000..ea2d97ade --- /dev/null +++ b/libs/perlbind/include/perlbind/scalar.h @@ -0,0 +1,254 @@ +#pragma once + +#include "types.h" +#include +#include + +namespace perlbind { + +struct scalar : type_base +{ + virtual ~scalar() noexcept + { + SvREFCNT_dec(m_sv); + } + + scalar() noexcept + : type_base(), m_sv(newSV(0)) {} // nothing allocated + scalar(PerlInterpreter* interp) noexcept + : type_base(interp), m_sv(newSV(0)) {} + scalar(PerlInterpreter* interp, SV*&& sv) noexcept + : type_base(interp), m_sv(sv) {} + scalar(const scalar& other) noexcept + : type_base(other.my_perl), m_sv(newSVsv(other.m_sv)) {} + scalar(scalar&& other) noexcept + : type_base(other.my_perl), m_sv(other.m_sv) + { + other.m_sv = newSV(0); + } + scalar(SV*& value) noexcept + : type_base(), m_sv(newSVsv(value)) {} + scalar(SV*&& value) noexcept + : type_base(), m_sv(value) {} + scalar(const char* value) noexcept + : type_base(), m_sv(newSVpv(value, 0)) {} + scalar(const std::string& value) noexcept + : type_base(), m_sv(newSVpvn(value.c_str(), value.size())) {} + + template ::value, bool> = true> + scalar(T value) noexcept : type_base(), m_sv(newSViv(static_cast(value))) {} + + template ::value, bool> = true> + scalar(T value) noexcept : type_base(), m_sv(newSVuv(value)) {} + + template ::value, bool> = true> + scalar(T value) noexcept : type_base(), m_sv(newSVnv(value)) {} + + template ::value, bool> = true> + scalar(T value) noexcept : type_base(), m_sv(newSV(0)) + { + *this = std::move(value); + } + + scalar& operator=(const scalar& other) noexcept + { + if (this != &other) + sv_setsv(m_sv, other.m_sv); + + return *this; + } + + scalar& operator=(scalar&& other) noexcept + { + if (this != &other) + std::swap(m_sv, other.m_sv); + + return *this; + } + + scalar& operator=(SV*& value) noexcept + { + sv_setsv(m_sv, value); + return *this; + } + + scalar& operator=(SV*&& value) noexcept + { + reset(value); + return *this; + } + + scalar& operator=(const char* value) noexcept + { + sv_setpv(m_sv, value); + return *this; + } + + scalar& operator=(const std::string& value) noexcept + { + sv_setpvn(m_sv, value.c_str(), value.size()); + return *this; + } + + template ::value, bool> = true> + scalar& operator=(T value) noexcept + { + sv_setiv(m_sv, static_cast(value)); + return *this; + } + + template ::value, bool> = true> + scalar& operator=(T value) noexcept + { + sv_setuv(m_sv, value); + return *this; + } + + template ::value, bool> = true> + scalar& operator=(T value) noexcept + { + sv_setnv(m_sv, value); + return *this; + } + + template ::value, bool> = true> + scalar& operator=(T value) noexcept + { + // bless if it's in the typemap + const char* type_name = detail::typemap::template get_name(my_perl); + sv_setref_pv(m_sv, type_name, static_cast(value)); + return *this; + } + + operator SV*() const { return m_sv; } + operator void*() const { return m_sv; } + operator const char*() const { return SvPV_nolen(m_sv); } + operator std::string() const { return SvPV_nolen(m_sv); } + template ::value, bool> = true> + operator T() const { return static_cast(SvIV(m_sv)); } + template ::value, bool> = true> + operator T() const { return static_cast(SvUV(m_sv)); } + template ::value, bool> = true> + operator T() const { return static_cast(SvNV(m_sv)); } + template ::value, bool> = true> + operator T() const + { + const char* type_name = detail::typemap::template get_name(my_perl); + if (type_name && sv_isobject(m_sv) && sv_derived_from(m_sv, type_name)) + { + IV tmp = SvIV(SvRV(m_sv)); + return INT2PTR(T, tmp); + } + return nullptr; + } + + template + T as() const { return static_cast(*this); } + + // release ownership of SV + SV* release() noexcept + { + SV* tmp = m_sv; + m_sv = newSV(0); + return tmp; + } + // take ownership of an SV + void reset(SV* value) noexcept + { + SvREFCNT_dec(m_sv); + m_sv = value; + } + + SV* sv() const { return m_sv; } + SV* deref() const { return SvRV(m_sv); } + size_t size() const { return SvPOK(m_sv) ? sv_len(m_sv) : 0; } + svtype type() const { return SvTYPE(m_sv); } + const char* c_str() const { return SvPV_nolen(m_sv); } + + SV* operator*() { return SvRV(m_sv); } + + bool is_null() const { return type() == SVt_NULL; } //SvOK(m_sv) + bool is_integer() const { return SvIOK(m_sv); } + bool is_float() const { return SvNOK(m_sv); } + bool is_string() const { return SvPOK(m_sv); } + bool is_reference() const { return SvROK(m_sv); } + bool is_scalar_ref() const { return SvROK(m_sv) && SvTYPE(SvRV(m_sv)) < SVt_PVAV; } + bool is_array_ref() const { return SvROK(m_sv) && SvTYPE(SvRV(m_sv)) == SVt_PVAV; } + bool is_hash_ref() const { return SvROK(m_sv) && SvTYPE(SvRV(m_sv)) == SVt_PVHV; } + +protected: + SV* m_sv = nullptr; +}; + +// references are scalars that take ownership of one new reference to a value +// use reset() to take ownership of an existing RV +struct reference : public scalar +{ + reference() = default; + + template ::value, bool> = true> + reference(T& value) noexcept : scalar(value.my_perl, nullptr) { m_sv = newRV_inc(value); } + + // increments referent for rvalues of scalar objects (not raw SVs) since they dec on destruct + template ::value, bool> = true> + reference(T&& value) noexcept : scalar(value.my_perl, nullptr) { m_sv = newRV_inc(value); } + + template ::value, bool> = true> + reference(T& value) noexcept { reset(newRV_inc(reinterpret_cast(value))); } + + template ::value, bool> = true> + reference(T&& value) noexcept { reset(newRV_noinc(reinterpret_cast(value))); } + + SV* operator*() { return SvRV(m_sv); } +}; + +// scalar proxy reference is used for array and hash index operator[] overloads +struct scalar_proxy +{ + scalar_proxy() = delete; + scalar_proxy(PerlInterpreter* interp, scalar&& value) noexcept + : my_perl(interp), m_value(std::move(value)) {} + + SV* sv() const { return m_value; } + const char* c_str() const { return static_cast(m_value); } + + template + T as() const { return m_value.as(); } + + operator std::string() const { return m_value; } + + // copying value to supported conversion types (e.g. int val = arr[i]) + template ::value, bool> = true> + operator T() const + { + return static_cast(m_value); + } + + // taking a reference to the source SV (e.g. scalar val = arr[i]) + template ::value, bool> = true> + operator T() const + { + return SvREFCNT_inc(m_value); + } + + // assigning scalar to proxy, the source SV is modified (arr[i] = "new value") + scalar_proxy& operator=(scalar value) + { + m_value = value; + return *this; + } + + scalar_proxy& operator=(const scalar_proxy& other) + { + m_value = other.m_value; + return *this; + } + + // todo: nested proxy[] + +private: + PerlInterpreter* my_perl = nullptr; + scalar m_value; +}; + +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/stack.h b/libs/perlbind/include/perlbind/stack.h new file mode 100644 index 000000000..64bdb2e04 --- /dev/null +++ b/libs/perlbind/include/perlbind/stack.h @@ -0,0 +1,137 @@ +#pragma once + +#include "stack_push.h" +#include "stack_read.h" +#include +#include +#include + +namespace perlbind { namespace detail { + +// handles xsub call stack from perl, inherits stack::pusher to push return values +class xsub_stack : public stack::pusher +{ +public: + xsub_stack() = delete; + xsub_stack(PerlInterpreter* my_perl, CV* cv) + : stack::pusher(my_perl) + { + GV* gv = CvGV(cv); + m_sub_name = GvNAME(gv); + m_pkg_name = HvNAME(GvSTASH(gv)); + + dXSARGS; + this->sp = sp; + this->ax = ax; + this->mark = mark; + this->items = items; + } + ~xsub_stack() { XSRETURN(m_pushed); } + + int size() const { return items; } + std::string name() const { return std::string(pkg_name()) + "::" + sub_name(); } + const char* pkg_name() const { return m_pkg_name; } + const char* sub_name() const { return m_sub_name; } + + template + void push_return(T&& value) + { + XSprePUSH; + push(std::forward(value)); + } + + // returns true if all perl stack arguments are compatible with expected native arg types + template + bool check_types(Tuple&& types) + { + static constexpr int count = std::tuple_size::value; + if (items != count) + return false; + else if (count == 0) + return true; + + using make_sequence = std::make_index_sequence; + return check_stack(std::forward(types), make_sequence()); + } + + // returns tuple of converted perl stack arguments, throws on an incompatible type + template + auto convert_stack(Tuple&& types) + { + using make_sequence = std::make_index_sequence::value>; + return get_stack(std::forward(types), make_sequence()); + } + + std::string types() + { + std::string args; + for (int i = 0; i < items; ++i) + { + args += get_type_name(ST(i)); + if (i < (items - 1)) + args += ", "; + } + return args.empty() ? "void" : args; + } + +protected: + int ax = 0; + int items = 0; + SV** mark = nullptr; + const char* m_pkg_name = nullptr; + const char* m_sub_name = nullptr; + + std::string get_type_name(SV* item) + { + switch (SvTYPE(item)) + { + case SVt_NULL: return ""; + case SVt_NV: return "double"; + case SVt_PV: return "string"; + case SVt_PVAV: return "array"; + case SVt_PVHV: return "hash"; + case SVt_IV: + if (sv_isobject(item)) + return std::string(sv_reftype(SvRV(item), true)) + "*"; + else if (SvROK(item)) + return "ref"; + else + return "int"; + default: + return sv_reftype(item, true); + } + } + +private: + template + bool check_index(T t, size_t index) + { + return stack::read_as::check(my_perl, static_cast(index), ax, items); + } + + // return true if perl stack matches all expected argument types in tuple + template + bool check_stack(Tuple&& t, std::index_sequence) + { + // lists compatibility of each expected arg type (no short-circuit) + std::initializer_list res = { + check_index(std::get(std::forward(t)), I)... }; + + return std::all_of(res.begin(), res.end(), [](bool same) { return same; }); + } + + template + T get_stack_index(T t, size_t index) + { + return stack::read_as::get(my_perl, static_cast(index), ax, items); + } + + template + auto get_stack(Tuple&& t, std::index_sequence) + { + return Tuple{ get_stack_index(std::get(std::forward(t)), I)... }; + } +}; + +} // namespace detail +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/stack_push.h b/libs/perlbind/include/perlbind/stack_push.h new file mode 100644 index 000000000..61a514cce --- /dev/null +++ b/libs/perlbind/include/perlbind/stack_push.h @@ -0,0 +1,118 @@ +#pragma once + +#include + +namespace perlbind { namespace stack { + +// base class for pushing value types to perl stack +// methods use macros that push new mortalized SVs but do not extend the stack +// the stack is only extended when pushing an array, hash, or using push_args(). +// this is because for xsubs the "stack is always large enough to take one return value" +struct pusher +{ + virtual ~pusher() = default; + + pusher() = delete; + pusher(PerlInterpreter* interp) : my_perl(interp), sp(PL_stack_sp) {} + + SV* pop() { return POPs; } + + void push(bool value) { PUSHs(boolSV(value)); ++m_pushed; } + void push(const char* value) + { + if (!value) + PUSHs(&PL_sv_undef); + else + mPUSHp(value, strlen(value)); + + ++m_pushed; + } + void push(const std::string& value) { mPUSHp(value.c_str(), value.size()); ++m_pushed; } + void push(scalar value) { mPUSHs(value.release()); ++m_pushed; }; + void push(reference value) { mPUSHs(value.release()); ++m_pushed; }; + + void push(array value) + { + int count = static_cast(value.size()); + EXTEND(sp, count); + for (int i = 0; i < count; ++i) + { + // mortalizes one reference to array element to avoid copying + PUSHs(sv_2mortal(SvREFCNT_inc(value[i].sv()))); + } + m_pushed += count; + } + + void push(hash value) + { + // hashes are pushed to the perl stack as alternating keys and values + // this is less efficient than pushing a reference to the hash + auto count = hv_iterinit(value) * 2; + EXTEND(sp, count); + while (HE* entry = hv_iternext(value)) + { + auto val = HeVAL(entry); + PUSHs(hv_iterkeysv(entry)); // mortalizes new key sv (keys are not stored as sv) + PUSHs(sv_2mortal(SvREFCNT_inc(val))); + } + m_pushed += count; + } + + template ::value, bool> = true> + void push(T value) { mPUSHi(static_cast(value)); ++m_pushed; } + + template ::value, bool> = true> + void push(T value) { mPUSHu(value); ++m_pushed; } + + template ::value, bool> = true> + void push(T value) { mPUSHn(value); ++m_pushed; } + + template ::value, bool> = true> + void push(T value) + { + const char* type_name = detail::typemap::get_name(my_perl); + if (!type_name) + { + throw std::runtime_error("cannot push unregistered pointer of type '" + util::type_name::str() + "'"); + } + + SV* sv = sv_newmortal(); + sv_setref_pv(sv, type_name, static_cast(value)); + PUSHs(sv); + ++m_pushed; + }; + + void push(void* value) + { + SV* sv = sv_newmortal(); + sv_setref_pv(sv, nullptr, value); // unblessed + PUSHs(sv); + ++m_pushed; + } + + template + void push_args(Args&&... args) + { + EXTEND(sp, sizeof...(Args)); + push_args_impl(std::forward(args)...); + }; + +protected: + PerlInterpreter* my_perl = nullptr; + SV** sp = nullptr; + int m_pushed = 0; + +private: + template + void push_args_impl(Args&&... args) {} + + template + void push_args_impl(T&& value, Args&&... args) + { + push(std::forward(value)); + push_args_impl(std::forward(args)...); + } +}; + +} // namespace stack +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/stack_read.h b/libs/perlbind/include/perlbind/stack_read.h new file mode 100644 index 000000000..fe5794124 --- /dev/null +++ b/libs/perlbind/include/perlbind/stack_read.h @@ -0,0 +1,266 @@ +#pragma once + +#include + +namespace perlbind { namespace stack { + +// perl stack reader to convert types, throws if perl stack value isn't type compatible +template +struct read_as; + +template +struct read_as::value || std::is_enum::value>> +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { +#ifdef PERLBIND_NO_STRICT_SCALAR_TYPES + return SvTYPE(ST(i)) < SVt_PVAV; +#elif !defined PERLBIND_STRICT_NUMERIC_TYPES + return SvNIOK(ST(i)); +#else + return SvIOK(ST(i)); +#endif + } + + static T get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be an integer"); + } + return static_cast(SvIV(ST(i))); // unsigned and bools casted + } +}; + +template +struct read_as::value>> +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { +#ifdef PERLBIND_NO_STRICT_SCALAR_TYPES + return SvTYPE(ST(i)) < SVt_PVAV; +#elif !defined PERLBIND_STRICT_NUMERIC_TYPES + return SvNIOK(ST(i)); +#else + return SvNOK(ST(i)); +#endif + } + + static T get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be a floating point"); + } + return static_cast(SvNV(ST(i))); + } +}; + +template <> +struct read_as +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { +#ifdef PERLBIND_NO_STRICT_SCALAR_TYPES + return SvTYPE(ST(i)) < SVt_PVAV; +#else + return SvPOK(ST(i)); +#endif + } + + static const char* get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be a string"); + } + return static_cast(SvPV_nolen(ST(i))); + } +}; + +template <> +struct read_as : read_as +{ +}; + +template <> +struct read_as +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + return sv_isobject(ST(i)); + } + + static void* get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be a reference to an object"); + } + + IV tmp = SvIV(SvRV(ST(i))); + return INT2PTR(void*, tmp); + } +}; + +template +struct read_as::value>> +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + const char* type_name = detail::typemap::get_name(my_perl); + return type_name && sv_isobject(ST(i)) && sv_derived_from(ST(i), type_name); + } + + static T get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + // would prefer to check for unregistered types at compile time (not possible?) + const char* type_name = detail::typemap::get_name(my_perl); + if (!type_name) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be a reference to an unregistered type (method unusable)"); + } + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be a reference to an object of type '" + type_name + "'"); + } + + IV tmp = SvIV(SvRV(ST(i))); + return INT2PTR(T, tmp); + } +}; + +template +struct read_as> +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + return true; + } + + static nullable get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (sv_isobject(ST(i))) + { + const char* type_name = detail::typemap::get_name(my_perl); + if (type_name && sv_derived_from(ST(i), type_name)) + { + IV tmp = SvIV(SvRV(ST(i))); + return INT2PTR(T, tmp); + } + } + return nullptr; + } +}; + +template <> +struct read_as +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + return i < items; + } + + static SV* get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be valid scalar value"); + } + return ST(i); + } +}; + +// scalar, array, and hash readers return reference to stack items (not copies) +template <> +struct read_as +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + return (SvROK(ST(i)) && SvTYPE(SvRV(ST(i))) < SVt_PVAV) || SvTYPE(ST(i)) < SVt_PVAV; + } + + static scalar get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be a scalar or reference to a scalar"); + } + return SvROK(ST(i)) ? SvREFCNT_inc(SvRV(ST(i))) : SvREFCNT_inc(ST(i)); + } +}; + +template <> +struct read_as +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + return SvROK(ST(i)); + } + + static reference get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be a reference"); + } + // take ownership of a reference to the RV itself (avoid reference to a reference) + reference result; + result.reset(SvREFCNT_inc(ST(i))); + return result; + } +}; + +template <> +struct read_as +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + return items > i; + } + + static array get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be start of a perl array"); + } + + array result; + result.reserve(items - i); + for (int index = i; index < items; ++index) + { + result.push_back(SvREFCNT_inc(ST(index))); + } + return result; + } +}; + +template <> +struct read_as +{ + static bool check(PerlInterpreter* my_perl, int i, int ax, int items) + { + int remaining = items - i; + return remaining > 0 && remaining % 2 == 0 && SvTYPE(ST(i)) == SVt_PV; + } + + static hash get(PerlInterpreter* my_perl, int i, int ax, int items) + { + if (!check(my_perl, i, ax, items)) + { + throw std::runtime_error("expected argument " + std::to_string(i+1) + " to be start of a perl hash"); + } + + hash result; + for (int index = i; index < items; index += 2) + { + const char* key = SvPV_nolen(ST(index)); + result[key] = SvREFCNT_inc(ST(index + 1)); + } + return result; + } +}; + +} // namespace stack +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/subcaller.h b/libs/perlbind/include/perlbind/subcaller.h new file mode 100644 index 000000000..fb8c9d5c4 --- /dev/null +++ b/libs/perlbind/include/perlbind/subcaller.h @@ -0,0 +1,78 @@ +#pragma once + +#include + +namespace perlbind { namespace detail { + +// handles calls to perl, inherits stack::pusher to push args to perl sub +class sub_caller : public stack::pusher +{ +public: + sub_caller() = delete; + sub_caller(PerlInterpreter* my_perl) : stack::pusher(my_perl) + { + ENTER; // enter scope boundary for any mortals we create + SAVETMPS; + } + ~sub_caller() + { + PUTBACK; // set global sp back to local for any popped return values + FREETMPS; + LEAVE; // leave scope, decref mortals and values returned by perl + } + + template ::value, bool> = true> + auto call_sub(const char* subname, Args&&... args) + { + call_sub_impl(subname, G_EVAL|G_VOID, std::forward(args)...); + } + + template ::value, bool> = true> + auto call_sub(const char* subname, Args&&... args) + { + T result = 0; + + try + { + int count = call_sub_impl(subname, G_EVAL|G_SCALAR, std::forward(args)...); + + if (count == 1) + { + SV* sv_result = pop(); + result = static_cast(SvIV(sv_result)); + } + } + catch (...) + { + pop(); // top of stack holds undef on error when called with these flags + throw; + } + + return result; + } + +private: + template + int call_sub_impl(const char* subname, int flags, Args&&... args) + { + PUSHMARK(SP); // notify perl of local sp (required even if not pushing args) + push_args(std::forward(args)...); + PUTBACK; // set global sp back to local so call will know pushed arg count + + int result_count = call_pv(subname, flags); + + SPAGAIN; // refresh local sp since call may reallocate stack for scalar returns + + // ERRSV doesn't work in perl 5.28+ here for unknown reasons + SV* err = get_sv("@", 0); + if (SvTRUE(err)) + { + throw std::runtime_error("Perl error: " + std::string(SvPV_nolen(err))); + } + + return result_count; + } +}; + +} //namespace detail +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/traits.h b/libs/perlbind/include/perlbind/traits.h new file mode 100644 index 000000000..e4f9da21e --- /dev/null +++ b/libs/perlbind/include/perlbind/traits.h @@ -0,0 +1,33 @@ +#pragma once + +namespace perlbind { namespace detail { + +template +struct is_any : std::false_type {}; +template +struct is_any : std::is_same {}; +template +struct is_any : std::integral_constant::value || is_any::value> {}; + +template +struct is_signed_integral : std::integral_constant::value && std::is_signed::value> {}; + +template +struct is_signed_integral_or_enum : std::integral_constant::value || std::is_enum::value> {}; + +template +struct count_of : std::integral_constant {}; +template +struct count_of : std::integral_constant::value ? 1 : 0> {}; +template +struct count_of : std::integral_constant::value + count_of::value> {}; + +template +struct is_last : std::false_type {}; +template +struct is_last : std::is_same {}; +template +struct is_last : std::integral_constant::value> {}; + +} // namespace detail +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/typemap.h b/libs/perlbind/include/perlbind/typemap.h new file mode 100644 index 000000000..c5a3e50d5 --- /dev/null +++ b/libs/perlbind/include/perlbind/typemap.h @@ -0,0 +1,45 @@ +#pragma once + +namespace perlbind { namespace detail { + +struct usertype_counter +{ + static std::size_t next_id() + { + static std::size_t counter = 0; + return counter++; + } +}; + +template +struct usertype +{ + static std::string id() + { + static std::size_t id = usertype_counter::next_id(); + return std::to_string(id); + } +}; + +namespace typemap +{ + // type names are stored in a hash on interpreter when registered with + // unique id keys generated by usertype counter + inline hash get(PerlInterpreter* my_perl) + { + HV* hv = get_hv("__perlbind::typemap", GV_ADD); + return reinterpret_cast(SvREFCNT_inc(hv)); + } + + template + const char* get_name(PerlInterpreter* my_perl) + { + auto typemap = detail::typemap::get(my_perl); + auto type_id = detail::template usertype::id(); + + return typemap.exists(type_id) ? typemap[type_id].c_str() : nullptr; + } +} // namespace typemap + +} // namespace detail +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/types.h b/libs/perlbind/include/perlbind/types.h new file mode 100644 index 000000000..ed3916ab0 --- /dev/null +++ b/libs/perlbind/include/perlbind/types.h @@ -0,0 +1,25 @@ +#pragma once + +namespace perlbind { + +struct type_base +{ + type_base() : my_perl(PERL_GET_THX) {} + type_base(PerlInterpreter* interp) : my_perl(interp) {} + PerlInterpreter* my_perl = nullptr; +}; + +// helper type to allow null object reference arguments in bindings +template +struct nullable +{ + static_assert(std::is_pointer::value, "nullable 'T' must be pointer"); + + nullable() = default; + nullable(T ptr) : m_ptr(ptr) {} + T get() { return m_ptr; } +private: + T m_ptr = nullptr; +}; + +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/util.h b/libs/perlbind/include/perlbind/util.h new file mode 100644 index 000000000..8b1e306de --- /dev/null +++ b/libs/perlbind/include/perlbind/util.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#ifndef _MSC_VER +#include +#endif + +namespace perlbind { namespace util { + +inline std::string demangle(const char* name) +{ +#ifndef _MSC_VER + int status = 0; + char* res = abi::__cxa_demangle(name, nullptr, nullptr, &status); + if (res) + { + std::string demangled = res; + free(res); + return demangled; + } + return ""; +#else + return name; +#endif +} + +template +struct type_name; + +template <> +struct type_name<> +{ + static std::string str() { return "void"; } +}; + +template +struct type_name +{ + static std::string str() { return demangle(typeid(T).name()); } +}; + +template +struct type_name +{ + static std::string str() { return type_name::str() + "," + type_name::str(); } +}; + +} // namespace util +} // namespace perlbind diff --git a/libs/perlbind/include/perlbind/version.h b/libs/perlbind/include/perlbind/version.h new file mode 100644 index 000000000..bc6f6e3d8 --- /dev/null +++ b/libs/perlbind/include/perlbind/version.h @@ -0,0 +1,10 @@ +#pragma once + +constexpr int perlbind_version_major = 1; +constexpr int perlbind_version_minor = 0; +constexpr int perlbind_version_patch = 0; + +constexpr int perlbind_version() +{ + return perlbind_version_major * 10000 + perlbind_version_minor * 100 + perlbind_version_patch; +} diff --git a/libs/perlbind/src/function.cpp b/libs/perlbind/src/function.cpp new file mode 100644 index 000000000..3143b39b0 --- /dev/null +++ b/libs/perlbind/src/function.cpp @@ -0,0 +1,15 @@ +#include + +namespace perlbind { namespace detail { + +extern "C" int gc(pTHX_ SV* sv, MAGIC* mg) +{ + auto pfunc = INT2PTR(perlbind::detail::function_base*, SvIV(sv)); + delete pfunc; + return 1; +} + +const MGVTBL function_base::mgvtbl = { 0, 0, 0, 0, gc, 0, 0, 0 }; + +} // namespace detail +} // namespace perlbind diff --git a/libs/perlbind/src/hash.cpp b/libs/perlbind/src/hash.cpp new file mode 100644 index 000000000..96cdaa2d7 --- /dev/null +++ b/libs/perlbind/src/hash.cpp @@ -0,0 +1,107 @@ +#include +#include +#include + +namespace perlbind { + +hash::hash(scalar ref) + : type_base(ref.my_perl) +{ + if (!ref.is_hash_ref()) + throw std::runtime_error("cannot construct hash from non-hash reference"); + + reset(reinterpret_cast(SvREFCNT_inc(*ref))); +} + +hash::hash(scalar_proxy proxy) + : hash(scalar(SvREFCNT_inc(proxy.sv()))) +{} + +scalar hash::at(const char* key) +{ + return at(key, strlen(key)); +} + +scalar hash::at(const std::string& key) +{ + return at(key.c_str(), key.size()); +} + +scalar hash::at(const char* key, size_t size) +{ + SV** sv = hv_fetch(m_hv, key, static_cast(size), 1); + return SvREFCNT_inc(*sv); +} + +void hash::insert(const char* key, scalar value) +{ + insert(key, strlen(key), value); +} + +void hash::insert(const std::string& key, scalar value) +{ + insert(key.c_str(), key.size(), value); +} + +scalar_proxy hash::operator[](const std::string& key) +{ + return scalar_proxy(my_perl, at(key.c_str(), key.size())); +} + +hash::iterator hash::begin() const noexcept +{ + hv_iterinit(m_hv); + return { my_perl, m_hv, hv_iternext(m_hv) }; +} + +hash::iterator hash::end() const noexcept +{ + return { my_perl, m_hv, nullptr }; +} + +hash::iterator hash::find(const char* key) +{ + return find(key, static_cast(strlen(key))); +} + +hash::iterator hash::find(const std::string& key) +{ + return find(key.c_str(), static_cast(key.size())); +} + +hash::iterator hash::find(const char* key, size_t size) +{ + // key sv made mortal with SVs_TEMP flag + SV* keysv = newSVpvn_flags(key, static_cast(size), SVs_TEMP); + HE* he = hv_fetch_ent(m_hv, keysv, 0, 0); + return { my_perl, m_hv, he }; +} + +void hash::insert(const char* key, size_t size, scalar value) +{ + if (!hv_store(m_hv, key, static_cast(size), SvREFCNT_inc(value), 0)) + { + SvREFCNT_dec(value); + } +} + +HV* hash::copy_hash(HV* other) noexcept +{ + HV* hv = newHV(); + + hv_iterinit(other); + while (HE* entry = hv_iternext(other)) + { + size_t key_size; + auto key = HePV(entry, key_size); + auto value = newSVsv(HeVAL(entry)); + if (!hv_store(hv, key, static_cast(key_size), value, HeHASH(entry))) + { + SvREFCNT_dec(value); + } + } + + return hv; +} + +} // namespace perlbind diff --git a/libs/perlbind/src/interpreter.cpp b/libs/perlbind/src/interpreter.cpp new file mode 100644 index 000000000..2a10df4f0 --- /dev/null +++ b/libs/perlbind/src/interpreter.cpp @@ -0,0 +1,98 @@ +#include + +#include +#include +#include + +EXTERN_C +{ + void boot_DynaLoader(pTHX_ CV* cv); + static void xs_init(pTHX) + { + newXS(const_cast("DynaLoader::boot_DynaLoader"), boot_DynaLoader, const_cast(__FILE__)); + } +} + +namespace perlbind { + +interpreter::interpreter() + : m_is_owner(true) +{ + const char* argv[] = { "", "-ew", "0", nullptr }; + constexpr int argc = (sizeof(argv) / sizeof(*argv)) - 1; + init(argc, argv); +} + +interpreter::interpreter(int argc, const char** argv) + : m_is_owner(true) +{ + init(argc, argv); +} + +void interpreter::init(int argc, const char** argv) +{ + char** argvs = const_cast(argv); + char** env = { nullptr }; + + // PERL_SYS_INIT3 and PERL_SYS_TERM should only be called once per program + PERL_SYS_INIT3(&argc, &argvs, &env); + + my_perl = perl_alloc(); + PERL_SET_CONTEXT(my_perl); + PL_perl_destruct_level = 1; + perl_construct(my_perl); + perl_parse(my_perl, xs_init, argc, argvs, nullptr); + + perl_run(my_perl); +} + +interpreter::~interpreter() +{ + if (m_is_owner) + { + PL_perl_destruct_level = 1; + perl_destruct(my_perl); + perl_free(my_perl); + + PERL_SYS_TERM(); + } +} + +void interpreter::load_script(std::string packagename, std::string filename) +{ + struct stat st{}; + if (stat(filename.c_str(), &st) != 0) + { + throw std::runtime_error("Unable to read perl file '" + filename + "'"); + } + + std::ifstream ifs(filename); + std::stringstream buffer; + buffer << "package " << packagename << "; " << ifs.rdbuf(); + + try + { + eval(buffer.str().c_str()); + } + catch (std::exception& e) + { + throw std::runtime_error("Error loading script '" + filename + "':\n " + e.what()); + } +} + +void interpreter::eval(const char* str) +{ + SV* sv = eval_pv(str, 0); + if (sv == &PL_sv_undef) + { + SV* err = get_sv("@", 0); + if (err && err->sv_u.svu_pv[0]) + { + throw std::runtime_error(err->sv_u.svu_pv); + } + + throw std::runtime_error("unknown error in eval()"); + } +} + +} // namespace perlbind diff --git a/libs/perlbind/src/package.cpp b/libs/perlbind/src/package.cpp new file mode 100644 index 000000000..3531265df --- /dev/null +++ b/libs/perlbind/src/package.cpp @@ -0,0 +1,88 @@ +#include + +namespace perlbind { + +namespace detail { + extern "C" void xsub(PerlInterpreter* my_perl, CV* cv); +} // namespace detail + +void package::add_impl(const char* name, detail::function_base* function) +{ + std::string export_name = m_name + "::" + name; + + // the sv is assigned a magic metamethod table to delete the function + // object when perl frees the sv + SV* sv = newSViv(PTR2IV(function)); + sv_magicext(sv, nullptr, PERL_MAGIC_ext, &detail::function_base::mgvtbl, nullptr, 0); + + CV* cv = get_cv(export_name.c_str(), 0); + if (!cv) + { + cv = newXS(export_name.c_str(), &detail::xsub, __FILE__); + CvXSUBANY(cv).any_ptr = function; + } + else // function exists, remove target to search overloads when called + { + CvXSUBANY(cv).any_ptr = nullptr; + } + + // create an array with same name to store overloads in the CV's GV + AV* av = GvAV(CvGV(cv)); + if (!av) + { + av = get_av(export_name.c_str(), GV_ADD); + } + + array overloads = reinterpret_cast(SvREFCNT_inc(av)); + overloads.push_back(sv); // giving only ref to GV array +} + +extern "C" void detail::xsub(PerlInterpreter* my_perl, CV* cv) +{ + // croak does not unwind so inner calls throw exceptions to prevent leaks + try + { + detail::xsub_stack stack(my_perl, cv); + + auto target = static_cast(CvXSUBANY(cv).any_ptr); + if (target) + { + return target->call(stack); + } + + // find first compatible overload + AV* av = GvAV(CvGV(cv)); + + array functions = reinterpret_cast(SvREFCNT_inc(av)); + for (const auto& function : functions) + { + auto func = INT2PTR(detail::function_base*, SvIV(function.sv())); + if (func->is_compatible(stack)) + { + return func->call(stack); + } + } + + SV* err = newSVpvf("no overload of '%s' matched the %d argument(s):\n (%s)\ncandidates:\n ", + stack.name().c_str(), stack.size(), stack.types().c_str()); + + for (const auto& function : functions) + { + auto func = INT2PTR(detail::function_base*, SvIV(function.sv())); + Perl_sv_catpvf(aTHX_ err, "%s\n ", func->get_signature().c_str()); + } + + err = sv_2mortal(err); + throw std::runtime_error(SvPV_nolen(err)); + } + catch (std::exception& e) + { + Perl_croak(aTHX_ "%s", e.what()); + } + catch (...) + { + Perl_croak(aTHX_ "unhandled exception"); + } +} + +} // namespace perlbind diff --git a/libs/perlbind/src/perlbind.natvis b/libs/perlbind/src/perlbind.natvis new file mode 100644 index 000000000..11e30d724 --- /dev/null +++ b/libs/perlbind/src/perlbind.natvis @@ -0,0 +1,112 @@ + + + + + {{ m_sv={(void*)m_sv} refcnt={m_sv->sv_refcnt,d} type={(svtype)(m_sv->sv_flags & 0xff),d} }} + + m_sv + + + + {{ size={(m_av->sv_any)->xav_fill + 1,d} refcnt={m_av->sv_refcnt,d} } + + m_av + + + + {{ size={(m_hv->sv_any)->xhv_keys,d} refcnt={m_hv->sv_refcnt,d} }} + + m_hv + + + + + + {{ refcnt={sv_refcnt,d} type={(svtype)(sv_flags & 0xff),d} }} + + sv_refcnt,d + (svtype)(sv_flags & 0xff),d + sv_u.svu_rv + + (av*)this + + (hv*)this + + (gv*)this + + ((XPVMG*)(sv_any)) + + sv_u.svu_pv,na + sv_u.svu_iv,i + sv_u.svu_uv + sv_u.svu_nv,f + sv_u.svu_rv + + + + + {{ size={(sv_any)->xav_fill + 1,d} refcnt={sv_refcnt,d} type={(svtype)(sv_flags & 0xff),d} } + + sv_refcnt,d + (sv_any)->xav_fill + 1 + (sv_any)->xav_max + + (sv_any)->xav_fill + 1 + (sv_u).svu_array + + + + + + {{ size={(sv_any)->xhv_keys,d} refcnt={sv_refcnt,d} type={(svtype)(sv_flags & 0xff),d} }} + + sv_refcnt,d + (sv_any)->xhv_keys + (sv_any)->xhv_max + + + + + + + + + + index++ + bucket_inc = __findnonnull(bucket_array + index, max_index - index) + + index += bucket_inc + entry = bucket_array[index] + + (entry->he_valu).hent_val + entry = entry->hent_next + + + + + + + {{ refcnt={sv_refcnt,d} type={(svtype)(sv_flags & 0xff),d} }} + + sv_refcnt,d + (svtype)(sv_flags & 0xff),d + (sv_u.svu_gp)->gp_sv + (sv_u.svu_gp)->gp_cv + (sv_u.svu_gp)->gp_av + (sv_u.svu_gp)->gp_hv + (sv_u.svu_gp) + + + diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index eec55af2a..e55c32c1d 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(eqlogin_sources account_management.cpp diff --git a/loginserver/account_management.cpp b/loginserver/account_management.cpp index 2c3506db0..6be011951 100644 --- a/loginserver/account_management.cpp +++ b/loginserver/account_management.cpp @@ -3,7 +3,7 @@ #include "../common/event/task_scheduler.h" #include "../common/event/event_loop.h" #include "../common/net/dns.h" -#include "../common/string_util.h" +#include "../common/strings.h" extern LoginServer server; EQ::Event::TaskScheduler task_runner; @@ -150,7 +150,7 @@ uint32 AccountManagement::CheckLoginserverUserCredentials( if (!login_server_admin.loaded) { LogError( - "CheckLoginUserCredentials account [{0}] source_loginserver [{1}] not found!", + "account [{0}] source_loginserver [{1}] not found!", in_account_username, source_loginserver ); @@ -167,7 +167,7 @@ uint32 AccountManagement::CheckLoginserverUserCredentials( if (!validated_credentials) { LogError( - "CheckLoginUserCredentials account [{0}] source_loginserver [{1}] invalid credentials!", + "account [{0}] source_loginserver [{1}] invalid credentials!", in_account_username, source_loginserver ); @@ -176,7 +176,7 @@ uint32 AccountManagement::CheckLoginserverUserCredentials( } LogInfo( - "CheckLoginUserCredentials account [{0}] source_loginserver [{1}] credentials validated success!", + "account [{0}] source_loginserver [{1}] credentials validated success!", in_account_username, source_loginserver ); @@ -206,7 +206,7 @@ bool AccountManagement::UpdateLoginserverUserCredentials( if (!login_server_account.loaded) { LogError( - "ChangeLoginserverUserCredentials account [{0}] source_loginserver [{1}] not found!", + "account [{0}] source_loginserver [{1}] not found!", in_account_username, source_loginserver ); @@ -225,7 +225,7 @@ bool AccountManagement::UpdateLoginserverUserCredentials( ); LogInfo( - "ChangeLoginserverUserCredentials account [{0}] source_loginserver [{1}] credentials updated!", + "account [{0}] source_loginserver [{1}] credentials updated!", in_account_username, source_loginserver ); @@ -378,7 +378,7 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials( } ); - auto s = SplitString(server.options.GetEQEmuLoginServerAddress(), ':'); + auto s = Strings::Split(server.options.GetEQEmuLoginServerAddress(), ':'); if (s.size() == 2) { auto address = s[0]; auto port = std::stoi(s[1]); @@ -401,7 +401,7 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials( while (running) { std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); if (std::chrono::duration_cast(end - begin).count() > REQUEST_TIMEOUT_MS) { - LogInfo("[CheckExternalLoginserverUserCredentials] Deadline exceeded [{}]", REQUEST_TIMEOUT_MS); + LogInfo("Deadline exceeded [{}]", REQUEST_TIMEOUT_MS); running = false; } diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 01a5abf50..c862538cb 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -2,7 +2,7 @@ #include "login_server.h" #include "../common/misc_functions.h" #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "encryption.h" #include "account_management.h" @@ -26,13 +26,13 @@ bool Client::Process() { EQApplicationPacket *app = m_connection->PopPacket(); while (app) { - if (server.options.IsTraceOn()) { - LogDebug("Application packet received from client (size {0})", app->Size()); - } - - if (server.options.IsDumpInPacketsOn()) { - DumpPacket(app); - } + LogPacketClientServer( + "[{}] [{:#06x}] Size [{}] {}", + OpcodeManager::EmuToName(app->GetOpcode()), + m_connection->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + app->Size(), + (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") + ); if (m_client_status == cs_failed_to_login) { delete app; @@ -42,9 +42,7 @@ bool Client::Process() switch (app->GetOpcode()) { case OP_SessionReady: { - if (server.options.IsTraceOn()) { - LogInfo("Session ready received from client"); - } + LogInfo("Session ready received from client account {}", GetClientDescription()); Handle_SessionReady((const char *) app->pBuffer, app->Size()); break; } @@ -54,9 +52,7 @@ bool Client::Process() break; } - if (server.options.IsTraceOn()) { - LogInfo("Login received from client"); - } + LogInfo("Login received from client {}", GetClientDescription()); Handle_Login((const char *) app->pBuffer, app->Size()); break; @@ -67,9 +63,7 @@ bool Client::Process() break; } - if (server.options.IsTraceOn()) { - LogDebug("Server list request received from client"); - } + LogInfo("Server list request received from client {}", GetClientDescription()); SendServerListPacket(*(uint32_t *) app->pBuffer); break; @@ -83,13 +77,6 @@ bool Client::Process() Handle_Play((const char *) app->pBuffer); break; } - default: { - if (LogSys.log_settings[Logs::PacketClientServerUnhandled].is_category_enabled == 1) { - char dump[64]; - app->build_header_dump(dump); - LogError("Recieved unhandled application packet from the client: [{}]", dump); - } - } } delete app; @@ -128,10 +115,6 @@ void Client::Handle_SessionReady(const char *data, unsigned int size) buf->base_reply.success = true; buf->base_reply.error_str_id = 0x65; // 101 "No Error" - if (server.options.IsDumpOutPacketsOn()) { - DumpPacket(outapp); - } - m_connection->QueuePacket(outapp); delete outapp; } @@ -217,7 +200,7 @@ void Client::Handle_Login(const char *data, unsigned int size) else { if (server.options.IsPasswordLoginAllowed()) { cred = (&outbuffer[1 + user.length()]); - auto components = SplitString(user, ':'); + auto components = Strings::Split(user, ':'); if (components.size() == 2) { db_loginserver = components[0]; user = components[1]; @@ -240,7 +223,7 @@ void Client::Handle_Login(const char *data, unsigned int size) if (server.db->GetLoginDataFromAccountInfo(user, db_loginserver, db_account_password_hash, db_account_id)) { result = VerifyLoginHash(user, db_loginserver, cred, db_account_password_hash); - LogDebug("[VerifyLoginHash] Success [{0}]", (result ? "true" : "false")); + LogDebug("Success [{0}]", (result ? "true" : "false")); } else { m_client_status = cs_creating_account; @@ -290,14 +273,12 @@ void Client::Handle_Play(const char *data) auto server_id_in = (unsigned int) play->server_number; auto sequence_in = (unsigned int) play->base_header.sequence; - if (server.options.IsTraceOn()) { - LogInfo( - "Play received from client [{0}] server number {1} sequence {2}", - GetAccountName(), - server_id_in, - sequence_in - ); - } + LogInfo( + "[Handle_Play] Play received from client [{}] server number [{}] sequence [{}]", + GetAccountName(), + server_id_in, + sequence_in + ); m_play_server_id = (unsigned int) play->server_number; m_play_sequence_id = sequence_in; @@ -310,21 +291,14 @@ void Client::Handle_Play(const char *data) */ void Client::SendServerListPacket(uint32 seq) { - auto outapp = server.server_manager->CreateServerListPacket(this, seq); + auto app = server.server_manager->CreateServerListPacket(this, seq); - if (server.options.IsDumpOutPacketsOn()) { - DumpPacket(outapp.get()); - } - - m_connection->QueuePacket(outapp.get()); + m_connection->QueuePacket(app.get()); } void Client::SendPlayResponse(EQApplicationPacket *outapp) { - if (server.options.IsTraceOn()) { - LogDebug("Sending play response for {0}", GetAccountName()); - // server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size); - } + LogInfo("Sending play response for {}", GetClientDescription()); m_connection->QueuePacket(outapp); } @@ -358,7 +332,7 @@ void Client::AttemptLoginAccountCreation( const std::string &loginserver ) { - LogInfo("[AttemptLoginAccountCreation] user [{}] loginserver [{}]", user, loginserver); + LogInfo("user [{}] loginserver [{}]", user, loginserver); #ifdef LSPX if (loginserver == "eqemu") { @@ -377,7 +351,7 @@ void Client::AttemptLoginAccountCreation( ); if (account_id > 0) { - LogInfo("[AttemptLoginAccountCreation] Found and creating eqemu account [{}]", account_id); + LogInfo("Found and creating eqemu account [{}]", account_id); CreateEQEmuAccount(user, pass, account_id); return; } @@ -422,10 +396,6 @@ void Client::DoFailedLogin() outapp.WriteData(&base_header, sizeof(base_header)); outapp.WriteData(&encrypted_buffer, sizeof(encrypted_buffer)); - if (server.options.IsDumpOutPacketsOn()) { - DumpPacket(&outapp); - } - m_connection->QueuePacket(&outapp); m_client_status = cs_failed_to_login; } @@ -563,6 +533,8 @@ void Client::DoSuccessfulLogin( login_reply.web_offer_cooldown_minutes = 0; memcpy(login_reply.key, m_key.c_str(), m_key.size()); + SendExpansionPacketData(login_reply); + char encrypted_buffer[80] = {0}; auto rc = eqcrypt_block((const char*)&login_reply, sizeof(login_reply), encrypted_buffer, 1); if (rc == nullptr) { @@ -574,15 +546,73 @@ void Client::DoSuccessfulLogin( outapp->WriteData(&base_header, sizeof(base_header)); outapp->WriteData(&encrypted_buffer, sizeof(encrypted_buffer)); - if (server.options.IsDumpOutPacketsOn()) { - DumpPacket(outapp.get()); - } - m_connection->QueuePacket(outapp.get()); m_client_status = cs_logged_in; } +void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs) +{ + SerializeBuffer buf; + //from eqlsstr_us.txt id of each expansion, excluding 'Everquest' + int ExpansionLookup[20] = { 3007, 3008, 3009, 3010, 3012, + 3014, 3031, 3033, 3036, 3040, + 3045, 3046, 3047, 3514, 3516, + 3518, 3520, 3522, 3524 }; + + + if (server.options.IsDisplayExpansions()) { + + int32_t expansion = server.options.GetMaxExpansions(); + int32_t owned_expansion = (expansion << 1) | 1; + + if (m_client_version == cv_sod) { + + // header info of packet. Requires OP_LoginExpansionPacketData=0x0031 to be in login_opcodes_sod.conf + buf.WriteInt32(0x00); + buf.WriteInt32(0x01); + buf.WriteInt16(0x00); + buf.WriteInt32(19); //number of expansions to include in packet + + //generate expansion data + for (int i = 0; i < 19; i++) + { + buf.WriteInt32(i); //sequenctial number + buf.WriteInt32((expansion & (1 << i)) == (1 << i) ? 0x01 : 0x00); //1 own 0 not own + buf.WriteInt8(0x00); + buf.WriteInt32(ExpansionLookup[i]); //from eqlsstr_us.txt + buf.WriteInt32(0x179E); //from eqlsstr_us.txt for buttons/order + buf.WriteInt32(0xFFFFFFFF); //end identification + buf.WriteInt8(0x0); //force order window to appear 1 appear 0 not appear + buf.WriteInt8(0x0); + buf.WriteInt32(0x0000); + buf.WriteInt32(0x0000); + buf.WriteInt32(0xFFFFFFFF); + } + + auto out = std::make_unique(OP_LoginExpansionPacketData, buf); + m_connection->QueuePacket(out.get()); + + } + else if (m_client_version == cv_titanium) + { + if (expansion >= EQ::expansions::bitPoR) + { + // Titanium shipped with 10 expansions. Set owned expansions to be max 10. + plrs.offer_min_days = ((EQ::expansions::bitDoD << 2) | 1) - 2; + } + else + { + plrs.offer_min_days = owned_expansion; + } + // Titanium shipped with 10 expansions. Set owned expansions to be max 10. + plrs.web_offer_min_views = ((EQ::expansions::bitDoD << 2) | 1) - 2; + } + + } + +} + /** * @param username * @param password @@ -775,3 +805,17 @@ bool Client::ProcessHealthCheck(std::string username) return false; } + +std::string Client::GetClientDescription() +{ + in_addr in{}; + in.s_addr = GetConnection()->GetRemoteIP(); + std::string client_ip = inet_ntoa(in); + + return fmt::format( + "account_name [{}] account_id ({}) ip_address [{}]", + GetAccountName(), + GetAccountID(), + client_ip + ); +} diff --git a/loginserver/client.h b/loginserver/client.h index 95aa0cfa7..d96bc5302 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -52,6 +52,18 @@ public: */ void Handle_Login(const char *data, unsigned int size); + /** + * Sends the expansion data packet + * + * Titanium uses the encrypted data block to contact the expansion (You own xxx:) and the max expansions (of yyy) + * Rof uses a seperate data packet specifically for the expansion data + * Live, as of July 2021 uses a similar but slightly different seperate data packet + * + * @param PlayerLoginReply_Struct + * + */ + void SendExpansionPacketData(PlayerLoginReply_Struct& plrs); + /** * Sends a packet to the requested server to see if the client is allowed or not * @@ -99,6 +111,12 @@ public: */ std::string GetAccountName() const { return m_account_name; } + /** + * Returns a description for the client for logging + * @return std::string + */ + std::string GetClientDescription(); + /** * Gets the key generated at login for this client * diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index 6b3fc0bce..7bb352929 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -6,6 +6,7 @@ extern bool run_server; #include "../common/eqemu_logsys.h" #include "../common/misc.h" +#include "../common/path_manager.h" ClientManager::ClientManager() { @@ -15,13 +16,18 @@ ClientManager::ClientManager() titanium_stream = new EQ::Net::EQStreamManager(titanium_opts); titanium_ops = new RegularOpcodeManager; - if (!titanium_ops->LoadOpcodes( + + std::string opcodes_path = fmt::format( + "{}/{}", + path.GetServerPath(), server.config.GetVariableString( "client_configuration", "titanium_opcodes", "login_opcodes.conf" - ).c_str())) { + ) + ); + if (!titanium_ops->LoadOpcodes(opcodes_path.c_str())) { LogError( "ClientManager fatal error: couldn't load opcodes for Titanium file [{0}]", server.config.GetVariableString("client_configuration", "titanium_opcodes", "login_opcodes.conf") @@ -49,14 +55,18 @@ ClientManager::ClientManager() EQStreamManagerInterfaceOptions sod_opts(sod_port, false, false); sod_stream = new EQ::Net::EQStreamManager(sod_opts); sod_ops = new RegularOpcodeManager; - if ( - !sod_ops->LoadOpcodes( - server.config.GetVariableString( - "client_configuration", - "sod_opcodes", - "login_opcodes.conf" - ).c_str() - )) { + + opcodes_path = fmt::format( + "{}/{}", + path.GetServerPath(), + server.config.GetVariableString( + "client_configuration", + "sod_opcodes", + "login_opcodes.conf" + ) + ); + + if (!sod_ops->LoadOpcodes(opcodes_path.c_str())) { LogError( "ClientManager fatal error: couldn't load opcodes for SoD file {0}", server.config.GetVariableString("client_configuration", "sod_opcodes", "login_opcodes.conf").c_str() diff --git a/loginserver/database.cpp b/loginserver/database.cpp index 18612dac6..b07b0a1c2 100644 --- a/loginserver/database.cpp +++ b/loginserver/database.cpp @@ -3,7 +3,7 @@ #include "database.h" #include "login_server.h" #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/util/uuid.h" extern LoginServer server; @@ -41,7 +41,7 @@ Database::Database( exit(1); } else { - LogStatus("Using database [{0}] at [{1}:{2}]", name, host, port); + LogInfo("Using database [{0}] at [{1}:{2}]", name, host, port); } } @@ -71,8 +71,8 @@ bool Database::GetLoginDataFromAccountInfo( { auto query = fmt::format( "SELECT id, account_password FROM login_accounts WHERE account_name = '{0}' AND source_loginserver = '{1}' LIMIT 1", - EscapeString(name), - EscapeString(loginserver) + Strings::Escape(name), + Strings::Escape(loginserver) ); auto results = QueryDatabase(query); @@ -125,8 +125,8 @@ bool Database::GetLoginTokenDataFromToken( "SELECT tbllogintokens.Id, tbllogintokens.IpAddress, tbllogintokenclaims.Name, tbllogintokenclaims.Value FROM tbllogintokens " "JOIN tbllogintokenclaims ON tbllogintokens.Id = tbllogintokenclaims.TokenId WHERE tbllogintokens.Expires > NOW() " "AND tbllogintokens.Id='{0}' AND tbllogintokens.IpAddress='{1}'", - EscapeString(token), - EscapeString(ip) + Strings::Escape(token), + Strings::Escape(ip) ); auto results = QueryDatabase(query); @@ -168,7 +168,7 @@ unsigned int Database::GetFreeID(const std::string &loginserver) { auto query = fmt::format( "SELECT IFNULL(MAX(id), 0) + 1 FROM login_accounts WHERE source_loginserver = '{0}'", - EscapeString(loginserver) + Strings::Escape(loginserver) ); auto results = QueryDatabase(query); @@ -225,10 +225,10 @@ uint32 Database::CreateLoginAccount( "INSERT INTO login_accounts (id, source_loginserver, account_name, account_password, account_email, last_login_date, last_ip_address, created_at) " "VALUES ({0}, '{1}', '{2}', '{3}', '{4}', NOW(), '127.0.0.1', NOW())", free_id, - EscapeString(loginserver), - EscapeString(name), - EscapeString(password), - EscapeString(email) + Strings::Escape(loginserver), + Strings::Escape(name), + Strings::Escape(password), + Strings::Escape(email) ); auto results = QueryDatabase(query); @@ -258,9 +258,9 @@ bool Database::CreateLoginDataWithID( "INSERT INTO login_accounts (id, source_loginserver, account_name, account_password, account_email, last_login_date, last_ip_address, created_at) " "VALUES ({0}, '{1}', '{2}', '{3}', 'local_creation', NOW(), '127.0.0.1', NOW())", id, - EscapeString(loginserver), - EscapeString(in_account_name), - EscapeString(in_account_password) + Strings::Escape(loginserver), + Strings::Escape(in_account_name), + Strings::Escape(in_account_password) ); auto results = QueryDatabase(query); @@ -288,8 +288,8 @@ bool Database::DoesLoginServerAccountExist( auto query = fmt::format( "SELECT account_name FROM login_accounts WHERE account_name = '{0}' AND source_loginserver = '{1}'", - EscapeString(name), - EscapeString(loginserver) + Strings::Escape(name), + Strings::Escape(loginserver) ); auto results = QueryDatabase(query); @@ -321,8 +321,8 @@ void Database::UpdateLoginserverAccountPasswordHash( auto query = fmt::format( "UPDATE login_accounts SET account_password = '{0}' WHERE account_name = '{1}' AND source_loginserver = '{2}'", hash, - EscapeString(name), - EscapeString(loginserver) + Strings::Escape(name), + Strings::Escape(loginserver) ); QueryDatabase(query); @@ -353,8 +353,8 @@ Database::DbWorldRegistration Database::GetWorldRegistration( " JOIN login_server_list_types AS SLT ON WSR.login_server_list_type_id = SLT.id\n" "WHERE\n" " WSR.short_name = '{}' AND WSR.long_name = '{}' AND WSR.login_server_admin_id = {} LIMIT 1", - EscapeString(short_name), - EscapeString(long_name), + Strings::Escape(short_name), + Strings::Escape(long_name), login_world_server_admin_id ); @@ -426,9 +426,9 @@ void Database::UpdateLSAccountInfo( "REPLACE login_accounts SET id = {0}, account_name = '{1}', account_password = sha('{2}'), " "account_email = '{3}', last_ip_address = '0.0.0.0', last_login_date = now()", id, - EscapeString(name), - EscapeString(password), - EscapeString(email) + Strings::Escape(name), + Strings::Escape(password), + Strings::Escape(email) ); QueryDatabase(query); @@ -444,7 +444,7 @@ void Database::UpdateWorldRegistration(unsigned int id, std::string long_name, s auto query = fmt::format( "UPDATE login_world_servers SET last_login_date = NOW(), last_ip_address = '{0}', long_name = '{1}' WHERE id = {2}", ip_address, - EscapeString(long_name), + Strings::Escape(long_name), id ); @@ -463,7 +463,7 @@ bool Database::UpdateLoginWorldAdminAccountPassword( auto results = QueryDatabase( fmt::format( "UPDATE login_server_admins SET account_password = '{}' WHERE id = {}", - EscapeString(admin_account_password_hash), + Strings::Escape(admin_account_password_hash), id ) ); @@ -484,8 +484,8 @@ bool Database::UpdateLoginWorldAdminAccountPasswordByUsername( auto results = QueryDatabase( fmt::format( "UPDATE login_server_admins SET account_password = '{}' WHERE account_name = '{}'", - EscapeString(admin_account_password_hash), - EscapeString(admin_account_username) + Strings::Escape(admin_account_password_hash), + Strings::Escape(admin_account_username) ) ); @@ -518,8 +518,8 @@ bool Database::CreateWorldRegistration( "INSERT INTO login_world_servers SET id = {0}, long_name = '{1}', short_name = '{2}', last_ip_address = '{3}', \n" "login_server_list_type_id = 3, login_server_admin_id = {4}, is_server_trusted = 0, tag_description = ''", id, - EscapeString(server_long_name), - EscapeString(server_short_name), + Strings::Escape(server_long_name), + Strings::Escape(server_short_name), server_remote_ip, server_admin_id ); @@ -598,11 +598,11 @@ uint32 Database::CreateLoginserverWorldAdminAccount( "INSERT INTO login_server_admins (account_name, account_password, first_name, last_name, email, registration_date, " "registration_ip_address) " "VALUES ('{0}', '{1}', '{2}', '{3}', '{4}', NOW(), '{5}')", - EscapeString(account_name), - EscapeString(account_password), - EscapeString(first_name), - EscapeString(last_name), - EscapeString(email), + Strings::Escape(account_name), + Strings::Escape(account_password), + Strings::Escape(first_name), + Strings::Escape(last_name), + Strings::Escape(email), ip_address ); @@ -621,7 +621,7 @@ bool Database::DoesLoginserverWorldAdminAccountExist( { auto query = fmt::format( "SELECT account_name FROM login_server_admins WHERE account_name = '{0}' LIMIT 1", - EscapeString(account_name) + Strings::Escape(account_name) ); auto results = QueryDatabase(query); @@ -638,7 +638,7 @@ Database::DbLoginServerAdmin Database::GetLoginServerAdmin(const std::string &ac auto query = fmt::format( "SELECT id, account_name, account_password, first_name, last_name, email, registration_date, registration_ip_address" " FROM login_server_admins WHERE account_name = '{0}' LIMIT 1", - EscapeString(account_name) + Strings::Escape(account_name) ); auto results = QueryDatabase(query); @@ -673,8 +673,8 @@ Database::DbLoginServerAccount Database::GetLoginServerAccountByAccountName( "SELECT id, account_name, account_password, account_email, source_loginserver, last_ip_address, last_login_date, " "created_at, updated_at" " FROM login_accounts WHERE account_name = '{0}' and source_loginserver = '{1}' LIMIT 1", - EscapeString(account_name), - EscapeString(source_loginserver) + Strings::Escape(account_name), + Strings::Escape(source_loginserver) ); auto results = QueryDatabase(query); diff --git a/loginserver/login_server.h b/loginserver/login_server.h index 015a35fcc..b80cf6ee5 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -11,7 +11,7 @@ #include "loginserver_webserver.h" /** - * Login server struct, contains every variable for the server that needs to exist outside the scope of main() + * Login server struct, Contains every variable for the server that needs to exist outside the scope of main() */ struct LoginServer { diff --git a/loginserver/login_util/login.json b/loginserver/login_util/login.json index c25242f7c..c61b60ce5 100644 --- a/loginserver/login_util/login.json +++ b/loginserver/login_util/login.json @@ -35,6 +35,8 @@ "titanium_port": 5998, "titanium_opcodes": "login_opcodes.conf", "sod_port": 5999, - "sod_opcodes": "login_opcodes_sod.conf" + "sod_opcodes": "login_opcodes_sod.conf", + "display_expansions" : true, + "max_expansions_mask" : 524287 } } diff --git a/loginserver/login_util/login_opcodes_sod.conf b/loginserver/login_util/login_opcodes_sod.conf index fc0d8bb94..cdc856d2c 100644 --- a/loginserver/login_util/login_opcodes_sod.conf +++ b/loginserver/login_util/login_opcodes_sod.conf @@ -8,5 +8,6 @@ OP_ChatMessage=0x0017 OP_LoginAccepted=0x0018 OP_ServerListResponse=0x0019 OP_Poll=0x0029 +OP_LoginExpansionPacketData=0x0031 OP_EnterChat=0x000f OP_PollResponse=0x0011 diff --git a/loginserver/loginserver_webserver.cpp b/loginserver/loginserver_webserver.cpp index bea7dc8ae..eb0acb551 100644 --- a/loginserver/loginserver_webserver.cpp +++ b/loginserver/loginserver_webserver.cpp @@ -2,7 +2,7 @@ #include "server_manager.h" #include "login_server.h" #include "../common/json/json.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "account_management.h" extern LoginServer server; @@ -444,7 +444,7 @@ namespace LoginserverWebserver { auto header_value = header.second; if (header_key == "Authorization") { authorization_key = header.second; - find_replace(authorization_key, "Bearer ", ""); + Strings::FindReplace(authorization_key, "Bearer ", ""); if (LoginserverWebserver::TokenManager::TokenExists(authorization_key)) { user_token = server.token_manager->GetToken(authorization_key); } diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 46f2313b3..43daa4551 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -10,7 +10,8 @@ #include "login_server.h" #include "loginserver_webserver.h" #include "loginserver_command_handler.h" -#include "../common/string_util.h" +#include "../common/strings.h" +#include "../common/path_manager.h" #include #include #include @@ -20,6 +21,7 @@ LoginServer server; EQEmuLogSys LogSys; bool run_server = true; +PathManager path; void ResolveAddresses(); void CatchSignal(int sig_num) @@ -42,18 +44,11 @@ void LoadDatabaseConnection() void LoadServerConfig() { - server.config = EQ::JsonConfigFile::Load("login.json"); + server.config = EQ::JsonConfigFile::Load( + fmt::format("{}/login.json", path.GetServerPath()) + ); LogInfo("Config System Init"); - - /** - * Logging - */ - server.options.Trace(server.config.GetVariableBool("logging", "trace", false)); - server.options.WorldTrace(server.config.GetVariableBool("logging", "world_trace", false)); - server.options.DumpInPackets(server.config.GetVariableBool("logging", "dump_packets_in", false)); - server.options.DumpOutPackets(server.config.GetVariableBool("logging", "dump_packets_out", false)); - /** * Worldservers */ @@ -63,7 +58,7 @@ void LoadServerConfig() "reject_duplicate_servers", false ) - ); + ); server.options.SetShowPlayerCount(server.config.GetVariableBool("worldservers", "show_player_count", false)); server.options.AllowUnregistered( server.config.GetVariableBool( @@ -87,6 +82,22 @@ void LoadServerConfig() ) ); + /** + * Expansion Display Settings + */ + server.options.DisplayExpansions( + server.config.GetVariableBool( + "client_configuration", + "display_expansions", + false + )); //disable by default + server.options.MaxExpansions( + server.config.GetVariableInt( + "client_configuration", + "max_expansions_mask", + 67108863 + )); //enable display of all expansions + /** * Account */ @@ -137,6 +148,8 @@ void LoadServerConfig() void start_web_server() { + Sleep(1); + int web_api_port = server.config.GetVariableInt("web_api", "port", 6000); LogInfo("Webserver API now listening on port [{0}]", web_api_port); @@ -165,6 +178,8 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); } + path.LoadPaths(); + /** * Command handler */ @@ -175,7 +190,7 @@ int main(int argc, char **argv) LoadDatabaseConnection(); LogSys.LoadLogSettingsDefaults(); - LogSys.log_settings[Logs::Debug].log_to_console = static_cast(Logs::General); + LogSys.log_settings[Logs::Debug].log_to_console = static_cast(Logs::General); LogSys.log_settings[Logs::Debug].is_category_enabled = 1; LoginserverCommandHandler::CommandHandler(argc, argv); @@ -190,6 +205,7 @@ int main(int argc, char **argv) if (argc == 1) { LogSys.SetDatabase(server.db) + ->SetLogPath("logs") ->LoadLogDatabaseSettings() ->StartFileLogs(); } @@ -239,9 +255,6 @@ int main(int argc, char **argv) #endif LogInfo("Server Started"); - if (LogSys.log_settings[Logs::Loginserver].log_to_console == 1) { - LogInfo("Loginserver logging set to level [1] for more debugging, enable detail [3]"); - } /** * Web API @@ -252,11 +265,10 @@ int main(int argc, char **argv) web_api_thread.detach(); } - LogInfo("[Config] [Logging] IsTraceOn [{0}]", server.options.IsTraceOn()); - LogInfo("[Config] [Logging] IsWorldTraceOn [{0}]", server.options.IsWorldTraceOn()); - LogInfo("[Config] [Logging] IsDumpInPacketsOn [{0}]", server.options.IsDumpInPacketsOn()); - LogInfo("[Config] [Logging] IsDumpOutPacketsOn [{0}]", server.options.IsDumpOutPacketsOn()); LogInfo("[Config] [Account] CanAutoCreateAccounts [{0}]", server.options.CanAutoCreateAccounts()); + LogInfo("[Config] [ClientConfiguration] DisplayExpansions [{0}]", server.options.IsDisplayExpansions()); + LogInfo("[Config] [ClientConfiguration] MaxExpansions [{0}]", server.options.GetMaxExpansions()); + #ifdef LSPX LogInfo("[Config] [Account] CanAutoLinkAccounts [{0}]", server.options.CanAutoLinkAccounts()); #endif @@ -276,13 +288,21 @@ int main(int argc, char **argv) LogInfo("[Config] [Security] IsPasswordLoginAllowed [{0}]", server.options.IsPasswordLoginAllowed()); LogInfo("[Config] [Security] IsUpdatingInsecurePasswords [{0}]", server.options.IsUpdatingInsecurePasswords()); - while (run_server) { + auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); - server.client_manager->Process(); - EQ::EventLoop::Get().Process(); - Sleep(5); - } + if (!run_server) { + EQ::EventLoop::Get().Shutdown(); + return; + } + + server.client_manager->Process(); + }; + + EQ::Timer process_timer(loop_fn); + process_timer.Start(32, true); + + EQ::EventLoop::Get().Run(); LogInfo("Server Shutdown"); diff --git a/loginserver/options.h b/loginserver/options.h index cf1de76d3..0171a6e7d 100644 --- a/loginserver/options.h +++ b/loginserver/options.h @@ -13,9 +13,8 @@ public: */ Options() : allow_unregistered(true), - trace(false), - dump_in_packets(false), - dump_out_packets(false), + display_expansions(false), + max_expansions_mask(0), encryption_mode(5), reject_duplicate_servers(false), allow_password_login(true), @@ -27,51 +26,19 @@ public: */ inline void AllowUnregistered(bool b) { allow_unregistered = b; } + /** + * Returns the value of expansion display settings. + */ + inline void DisplayExpansions(bool b) { display_expansions = b; } + inline void MaxExpansions(int i) { max_expansions_mask = i; } + inline bool IsDisplayExpansions() const { return display_expansions; } + inline int GetMaxExpansions() const { return max_expansions_mask; } + /** * Returns the value of allow_unregistered. */ inline bool IsUnregisteredAllowed() const { return allow_unregistered; } - /** - * Sets trace. - */ - inline void Trace(bool b) { trace = b; } - - /** - * Returns the value of trace. - */ - inline bool IsTraceOn() const { return trace; } - - /** - * Sets trace. - */ - inline void WorldTrace(bool b) { world_trace = b; } - - /** - * Returns the value of trace. - */ - inline bool IsWorldTraceOn() const { return world_trace; } - - /** - * Sets dump_in_packets. - */ - inline void DumpInPackets(bool b) { dump_in_packets = b; } - - /** - * Returns the value of dump_in_packets. - */ - inline bool IsDumpInPacketsOn() const { return dump_in_packets; } - - /** - * Sets dump_out_packets. - */ - inline void DumpOutPackets(bool b) { dump_out_packets = b; } - - /** - * Returns the value of dump_out_packets. - */ - inline bool IsDumpOutPacketsOn() const { return dump_out_packets; } - /** * Sets encryption_mode. */ @@ -138,10 +105,7 @@ public: private: bool allow_unregistered; - bool trace; - bool world_trace; - bool dump_in_packets; - bool dump_out_packets; + bool display_expansions; bool reject_duplicate_servers; bool world_dev_test_servers_list_bottom; bool world_special_character_start_list_bottom; @@ -152,6 +116,7 @@ private: bool auto_link_accounts; bool update_insecure_passwords; int encryption_mode; + int max_expansions_mask; std::string eqemu_loginserver_address; std::string default_loginserver_name; }; diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index 05758dc07..77b70fd8a 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -180,21 +180,23 @@ void ServerManager::SendUserToWorldRequest( EQ::Net::DynamicPacket outapp; outapp.Resize(sizeof(UsertoWorldRequest_Struct)); - auto *user_to_world_request = (UsertoWorldRequest_Struct *) outapp.Data(); - user_to_world_request->worldid = server_id; - user_to_world_request->lsaccountid = client_account_id; - strncpy(user_to_world_request->login, &client_loginserver[0], 64); + auto *r = (UsertoWorldRequest_Struct *) outapp.Data(); + r->worldid = server_id; + r->lsaccountid = client_account_id; + strncpy(r->login, &client_loginserver[0], 64); (*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp); found = true; - if (server.options.IsDumpInPacketsOn()) { - LogInfo("{0}", outapp.ToString()); - } + LogNetcode( + "[UsertoWorldRequest] [Size: {}]\n{}", + outapp.Length(), + outapp.ToString() + ); } ++iter; } - if (!found && server.options.IsTraceOn()) { + if (!found) { LogError("Client requested a user to world but supplied an invalid id of {0}", server_id); } } diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 24004347d..1f7fc404e 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -2,7 +2,7 @@ #include "login_server.h" #include "login_types.h" #include "../common/ip_util.h" -#include "../common/string_util.h" +#include "../common/strings.h" extern LoginServer server; @@ -63,7 +63,7 @@ WorldServer::~WorldServer() = default; void WorldServer::Reset() { - m_server_id; + m_server_id = 0; m_zones_booted = 0; m_players_online = 0; m_server_status = 0; @@ -79,17 +79,12 @@ void WorldServer::Reset() */ void WorldServer::ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet) { - if (server.options.IsWorldTraceOn()) { - LogDebug( - "Application packet received from server: [{0}], (size {1})", - opcode, - packet.Length() - ); - } - - if (server.options.IsDumpInPacketsOn()) { - DumpPacket(opcode, packet); - } + LogNetcode( + "Application packet received from server [{:#04x}] [Size: {}]\n{}", + opcode, + packet.Length(), + packet.ToString() + ); if (packet.Length() < sizeof(ServerNewLSInfo_Struct)) { LogError( @@ -129,18 +124,13 @@ void WorldServer::ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packe */ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet) { - Log( - Logs::Detail, - Logs::Netcode, - "Application packet received from server: 0x%.4X, (size %u)", + LogNetcode( + "Application packet received from server [{:#04x}] [Size: {}]\n{}", opcode, - packet.Length() + packet.Length(), + packet.ToString() ); - if (server.options.IsDumpInPacketsOn()) { - DumpPacket(opcode, packet); - } - if (packet.Length() < sizeof(ServerLSStatus_Struct)) { LogError( "Received application packet from server that had opcode ServerOP_LSStatus, but was too small. Discarded to avoid buffer overrun" @@ -151,15 +141,13 @@ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet auto *ls_status = (ServerLSStatus_Struct *) packet.Data(); - if (server.options.IsWorldTraceOn()) { - LogDebug( - "World Server Status Update Received | Server [{0}] Status [{1}] Players [{2}] Zones [{3}]", - GetServerLongName(), - ls_status->status, - ls_status->num_players, - ls_status->num_zones - ); - } + LogDebug( + "World Server Status Update Received | Server [{0}] Status [{1}] Players [{2}] Zones [{3}]", + GetServerLongName(), + ls_status->status, + ls_status->num_players, + ls_status->num_zones + ); Handle_LSStatus(ls_status); } @@ -170,17 +158,12 @@ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet */ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet) { - if (server.options.IsWorldTraceOn()) { - LogDebug( - "Application packet received from server: [{0}], (size {1})", - opcode, - packet.Length() - ); - } - - if (server.options.IsDumpInPacketsOn()) { - DumpPacket(opcode, packet); - } + LogNetcode( + "Application packet received from server [{:#04x}] [Size: {}]\n{}", + opcode, + packet.Length(), + packet.ToString() + ); if (packet.Length() < sizeof(UsertoWorldResponseLegacy_Struct)) { LogError( @@ -191,19 +174,11 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne return; } - //I don't use world trace for this and here is why: - //Because this is a part of the client login procedure it makes tracking client errors - //While keeping world server spam with multiple servers connected almost impossible. - if (server.options.IsTraceOn()) { - LogDebug("User-To-World Response received"); - } - auto *r = (UsertoWorldResponseLegacy_Struct *) packet.Data(); LogDebug("Trying to find client with user id of [{0}]", r->lsaccountid); Client *client = server.client_manager->GetClient(r->lsaccountid, "eqemu"); if (client) { - LogDebug( "Found client with user id of [{0}] and account name of [{1}]", r->lsaccountid, @@ -254,21 +229,13 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne break; } - if (server.options.IsWorldTraceOn()) { - LogDebug( - "Sending play response: allowed [{0}] sequence [{1}] server number [{2}] message [{3}]", - per->base_reply.success, - per->base_header.sequence, - per->server_number, - per->base_reply.error_str_id - ); - - LogDebug("[Size: [{0}]] {1}", outapp->size, DumpPacketToString(outapp)); - } - - if (server.options.IsDumpOutPacketsOn()) { - DumpPacket(outapp); - } + LogDebug( + "Sending play response: allowed [{0}] sequence [{1}] server number [{2}] message [{3}]", + per->base_reply.success, + per->base_header.sequence, + per->server_number, + per->base_reply.error_str_id + ); client->SendPlayResponse(outapp); delete outapp; @@ -287,17 +254,12 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne */ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Packet &packet) { - if (server.options.IsWorldTraceOn()) { - LogDebug( - "Application packet received from server: 0x%.4X, (size %u)", - opcode, - packet.Length() - ); - } - - if (server.options.IsDumpInPacketsOn()) { - DumpPacket(opcode, packet); - } + LogNetcode( + "Application packet received from server [{:#04x}] [Size: {}]\n{}", + opcode, + packet.Length(), + packet.ToString() + ); if (packet.Length() < sizeof(UsertoWorldResponse_Struct)) { LogError( @@ -308,25 +270,18 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac return; } - //I don't use world trace for this and here is why: - //Because this is a part of the client login procedure it makes tracking client errors - //While keeping world server spam with multiple servers connected almost impossible. - if (server.options.IsTraceOn()) { - LogDebug("User-To-World Response received"); - } - auto user_to_world_response = (UsertoWorldResponse_Struct *) packet.Data(); LogDebug("Trying to find client with user id of [{0}]", user_to_world_response->lsaccountid); - Client *client = server.client_manager->GetClient( + Client *c = server.client_manager->GetClient( user_to_world_response->lsaccountid, user_to_world_response->login ); - if (client) { + if (c) { LogDebug("Found client with user id of [{0}] and account name of {1}", user_to_world_response->lsaccountid, - client->GetAccountName().c_str() + c->GetAccountName().c_str() ); auto *outapp = new EQApplicationPacket( @@ -334,69 +289,62 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac sizeof(PlayEverquestResponse_Struct) ); - auto *per = (PlayEverquestResponse_Struct *) outapp->pBuffer; - per->base_header.sequence = client->GetPlaySequence(); - per->server_number = client->GetPlayServerID(); + auto *r = (PlayEverquestResponse_Struct *) outapp->pBuffer; + r->base_header.sequence = c->GetPlaySequence(); + r->server_number = c->GetPlayServerID(); LogDebug( "Found sequence and play of [{0}] [{1}]", - client->GetPlaySequence(), - client->GetPlayServerID() + c->GetPlaySequence(), + c->GetPlayServerID() ); LogDebug("[Size: [{0}]] {1}", outapp->size, DumpPacketToString(outapp)); if (user_to_world_response->response > 0) { - per->base_reply.success = true; + r->base_reply.success = true; SendClientAuth( - client->GetConnection()->GetRemoteAddr(), - client->GetAccountName(), - client->GetKey(), - client->GetAccountID(), - client->GetLoginServerName() + c->GetConnection()->GetRemoteAddr(), + c->GetAccountName(), + c->GetKey(), + c->GetAccountID(), + c->GetLoginServerName() ); } switch (user_to_world_response->response) { case UserToWorldStatusSuccess: - per->base_reply.error_str_id = LS::ErrStr::ERROR_NONE; + r->base_reply.error_str_id = LS::ErrStr::ERROR_NONE; break; case UserToWorldStatusWorldUnavail: - per->base_reply.error_str_id = LS::ErrStr::ERROR_SERVER_UNAVAILABLE; + r->base_reply.error_str_id = LS::ErrStr::ERROR_SERVER_UNAVAILABLE; break; case UserToWorldStatusSuspended: - per->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_SUSPENDED; + r->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_SUSPENDED; break; case UserToWorldStatusBanned: - per->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_BANNED; + r->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_BANNED; break; case UserToWorldStatusWorldAtCapacity: - per->base_reply.error_str_id = LS::ErrStr::ERROR_WORLD_MAX_CAPACITY; + r->base_reply.error_str_id = LS::ErrStr::ERROR_WORLD_MAX_CAPACITY; break; case UserToWorldStatusAlreadyOnline: - per->base_reply.error_str_id = LS::ErrStr::ERROR_ACTIVE_CHARACTER; + r->base_reply.error_str_id = LS::ErrStr::ERROR_ACTIVE_CHARACTER; break; default: - per->base_reply.error_str_id = LS::ErrStr::ERROR_UNKNOWN; + r->base_reply.error_str_id = LS::ErrStr::ERROR_UNKNOWN; break; } - if (server.options.IsTraceOn()) { - LogDebug( - "Sending play response with following data, allowed [{0}], sequence {1}, server number {2}, message {3}", - per->base_reply.success, - per->base_header.sequence, - per->server_number, - per->base_reply.error_str_id - ); - LogDebug("[Size: [{0}]] {1}", outapp->size, DumpPacketToString(outapp)); - } + LogDebug( + "Sending play response with following data, allowed [{0}], sequence {1}, server number {2}, message {3}", + r->base_reply.success, + r->base_header.sequence, + r->server_number, + r->base_reply.error_str_id + ); - if (server.options.IsDumpOutPacketsOn()) { - DumpPacket(outapp); - } - - client->SendPlayResponse(outapp); + c->SendPlayResponse(outapp); delete outapp; } else { @@ -413,17 +361,12 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac */ void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &packet) { - if (server.options.IsWorldTraceOn()) { - LogDebug( - "Application packet received from server: [{0}], (size {1})", - opcode, - packet.Length() - ); - } - - if (server.options.IsDumpInPacketsOn()) { - DumpPacket(opcode, packet); - } + LogNetcode( + "Application packet received from server [{:#04x}] [Size: {}]\n{}", + opcode, + packet.Length(), + packet.ToString() + ); if (packet.Length() < sizeof(ServerLSAccountUpdate_Struct)) { LogError( @@ -434,9 +377,7 @@ void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet return; } - if (server.options.IsWorldTraceOn()) { - LogDebug("ServerOP_LSAccountUpdate packet received from [{0}]", m_short_name); - } + LogDebug("ServerOP_LSAccountUpdate packet received from [{0}]", m_short_name); auto *loginserver_update = (ServerLSAccountUpdate_Struct *) packet.Data(); if (IsServerTrusted()) { @@ -448,7 +389,7 @@ void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet name.assign(loginserver_update->useraccount); password.assign(loginserver_update->userpassword); - if (loginserver_update->user_email) { + if (loginserver_update->user_email[0] != '\0') { email.assign(loginserver_update->user_email); } @@ -517,7 +458,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct *new_world_server_info if (login_server_admin.loaded) { LogDebug( - "WorldServer::Handle_NewLSInfo | Attempting to authenticate world admin... [{0}] ({1}) against worldserver [{2}]", + "Attempting to authenticate world admin... [{0}] ({1}) against worldserver [{2}]", GetAccountName(), login_server_admin.id, GetServerShortName() @@ -530,7 +471,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct *new_world_server_info login_server_admin.account_password )) { LogDebug( - "WorldServer::Handle_NewLSInfo | Authenticating world admin... [{0}] ({1}) success! World ({2})", + "Authenticating world admin... [{0}] ({1}) success! World ({2})", GetAccountName(), login_server_admin.id, GetServerShortName() @@ -607,34 +548,34 @@ void WorldServer::SendClientAuth( ) { EQ::Net::DynamicPacket outapp; - ClientAuth_Struct client_auth{}; + ClientAuth_Struct a{}; - client_auth.loginserver_account_id = account_id; + a.loginserver_account_id = account_id; - strncpy(client_auth.account_name, account.c_str(), 30); - strncpy(client_auth.key, key.c_str(), 30); + strncpy(a.account_name, account.c_str(), 30); + strncpy(a.key, key.c_str(), 30); - client_auth.lsadmin = 0; - client_auth.is_world_admin = 0; - client_auth.ip = inet_addr(ip.c_str()); - strncpy(client_auth.loginserver_name, &loginserver_name[0], 64); + a.lsadmin = 0; + a.is_world_admin = 0; + a.ip = inet_addr(ip.c_str()); + strncpy(a.loginserver_name, &loginserver_name[0], 64); const std::string &client_address(ip); std::string world_address(m_connection->Handle()->RemoteIP()); if (client_address == world_address) { - client_auth.is_client_from_local_network = 1; + a.is_client_from_local_network = 1; } else if (IpUtil::IsIpInPrivateRfc1918(client_address)) { LogInfo("Client is authenticating from a local address [{0}]", client_address); - client_auth.is_client_from_local_network = 1; + a.is_client_from_local_network = 1; } else { - client_auth.is_client_from_local_network = 0; + a.is_client_from_local_network = 0; } struct in_addr ip_addr{}; - ip_addr.s_addr = client_auth.ip; + ip_addr.s_addr = a.ip; LogInfo( "Client authentication response: world_address [{0}] client_address [{1}]", @@ -645,22 +586,25 @@ void WorldServer::SendClientAuth( LogInfo( "Sending Client Authentication Response ls_account_id [{0}] ls_name [{1}] name [{2}] key [{3}] ls_admin [{4}] " "world_admin [{5}] ip [{6}] local [{7}]", - client_auth.loginserver_account_id, - client_auth.loginserver_name, - client_auth.account_name, - client_auth.key, - client_auth.lsadmin, - client_auth.is_world_admin, + a.loginserver_account_id, + a.loginserver_name, + a.account_name, + a.key, + a.lsadmin, + a.is_world_admin, inet_ntoa(ip_addr), - client_auth.is_client_from_local_network + a.is_client_from_local_network ); - outapp.PutSerialize(0, client_auth); + outapp.PutSerialize(0, a); m_connection->Send(ServerOP_LSClientAuth, outapp); - if (server.options.IsDumpInPacketsOn()) { - DumpPacket(ServerOP_LSClientAuth, outapp); - } + LogNetcode( + "Sending [{:#04x}] [Size: {}]\n{}", + ServerOP_LSClientAuth, + outapp.Length(), + outapp.ToString() + ); } constexpr static int MAX_ACCOUNT_NAME_LENGTH = 30; @@ -1360,12 +1304,12 @@ void WorldServer::OnKeepAlive(EQ::Timer *t) void WorldServer::FormatWorldServerName(char *name, int8 server_list_type) { std::string server_long_name = name; - server_long_name = trim(server_long_name); + server_long_name = Strings::Trim(server_long_name); bool name_set_to_bottom = false; if (server_list_type == LS::ServerType::Standard) { if (server.options.IsWorldDevTestServersListBottom()) { - std::string s = str_tolower(server_long_name); + std::string s = Strings::ToLower(server_long_name); if (s.find("dev") != std::string::npos) { server_long_name = fmt::format("|D| {}", server_long_name); name_set_to_bottom = true; diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index 15c900e53..bd6e37ecd 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -1,18 +1,18 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(qserv_sources - database.cpp - lfguild.cpp - queryserv.cpp - queryservconfig.cpp - worldserver.cpp + database.cpp + lfguild.cpp + queryserv.cpp + queryservconfig.cpp + worldserver.cpp ) SET(qserv_headers - database.h - lfguild.h - queryservconfig.h - worldserver.h + database.h + lfguild.h + queryservconfig.h + worldserver.h ) ADD_EXECUTABLE(queryserv ${qserv_sources} ${qserv_headers}) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 950a21f5c..5b655a21e 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -47,59 +47,11 @@ #include "database.h" #include "../common/eq_packet_structs.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/servertalk.h" -Database::Database() -{ - DBInitVars(); -} -/* -Establish a connection to a mysql database with the supplied parameters -*/ - -Database::Database(const char *host, const char *user, const char *passwd, const char *database, uint32 port) -{ - DBInitVars(); - Connect(host, user, passwd, database, port); -} - -bool Database::Connect(const char *host, const char *user, const char *passwd, const char *database, uint32 port) -{ - uint32 errnum = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { - LogError("Failed to connect to database: Error: {}", errbuf); - HandleMysqlError(errnum); - - return false; - } - else { - LogInfo("Using database [{}] at [{}]:[{}]", database, host, port); - return true; - } -} - -void Database::DBInitVars() -{ - -} - - -void Database::HandleMysqlError(uint32 errnum) -{ -} - -/* - -Close the connection to the database -*/ -Database::~Database() -{ -} - -void Database::AddSpeech( +void QSDatabase::AddSpeech( const char *from, const char *to, const char *message, @@ -134,7 +86,7 @@ void Database::AddSpeech( } -void Database::LogPlayerDropItem(QSPlayerDropItem_Struct *QS) +void QSDatabase::LogPlayerDropItem(QSPlayerDropItem_Struct *QS) { std::string query = StringFormat( @@ -173,7 +125,7 @@ void Database::LogPlayerDropItem(QSPlayerDropItem_Struct *QS) } } -void Database::LogPlayerTrade(QSPlayerLogTrade_Struct *QS, uint32 detailCount) +void QSDatabase::LogPlayerTrade(QSPlayerLogTrade_Struct *QS, uint32 detailCount) { std::string query = StringFormat( @@ -220,7 +172,7 @@ void Database::LogPlayerTrade(QSPlayerLogTrade_Struct *QS, uint32 detailCount) } -void Database::LogPlayerHandin(QSPlayerLogHandin_Struct *QS, uint32 detailCount) +void QSDatabase::LogPlayerHandin(QSPlayerLogHandin_Struct *QS, uint32 detailCount) { std::string query = StringFormat( @@ -269,7 +221,7 @@ void Database::LogPlayerHandin(QSPlayerLogHandin_Struct *QS, uint32 detailCount) } -void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct *QS, uint32 members) +void QSDatabase::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct *QS, uint32 members) { std::string query = StringFormat( @@ -306,7 +258,7 @@ void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct *QS, uint32 members) } -void Database::LogPlayerDelete(QSPlayerLogDelete_Struct *QS, uint32 items) +void QSDatabase::LogPlayerDelete(QSPlayerLogDelete_Struct *QS, uint32 items) { std::string query = StringFormat( @@ -345,7 +297,7 @@ void Database::LogPlayerDelete(QSPlayerLogDelete_Struct *QS, uint32 items) } -void Database::LogPlayerMove(QSPlayerLogMove_Struct *QS, uint32 items) +void QSDatabase::LogPlayerMove(QSPlayerLogMove_Struct *QS, uint32 items) { /* These are item moves */ @@ -385,7 +337,7 @@ void Database::LogPlayerMove(QSPlayerLogMove_Struct *QS, uint32 items) } } -void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct *QS, uint32 items) +void QSDatabase::LogMerchantTransaction(QSMerchantLogTransaction_Struct *QS, uint32 items) { /* Merchant transactions are from the perspective of the merchant, not the player */ std::string query = StringFormat( @@ -433,7 +385,7 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct *QS, uint3 } // this function does not delete the ServerPacket, so it must be handled at call site -void Database::GeneralQueryReceive(ServerPacket *pack) +void QSDatabase::GeneralQueryReceive(ServerPacket *pack) { /* These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again diff --git a/queryserv/database.h b/queryserv/database.h index 9aa6383a3..0741f9aa0 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -26,7 +26,7 @@ #include "../common/eqemu_logsys.h" #include "../common/global_define.h" #include "../common/types.h" -#include "../common/dbcore.h" +#include "../common/database.h" #include "../common/linked_list.h" #include "../common/servertalk.h" #include @@ -36,13 +36,8 @@ //atoi is not uint32 or uint32 safe!!!! #define atoul(str) strtoul(str, nullptr, 10) -class Database : public DBcore { +class QSDatabase : public Database { public: - Database(); - Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); - bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port); - ~Database(); - void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type); void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount); void LogPlayerDropItem(QSPlayerDropItem_Struct* QS); diff --git a/queryserv/lfguild.cpp b/queryserv/lfguild.cpp index df2a50c24..d97cc3855 100644 --- a/queryserv/lfguild.cpp +++ b/queryserv/lfguild.cpp @@ -3,12 +3,12 @@ #include "database.h" #include "worldserver.h" #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/packet_dump.h" #include "../common/rulesys.h" extern WorldServer *worldserver; -extern Database database; +extern QSDatabase database; PlayerLookingForGuild::PlayerLookingForGuild(char *Name, char *Comments, uint32 Level, uint32 Class, uint32 AACount, uint32 Timezone, uint32 TimePosted) { diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index 005d54c6a..aabfb5f1d 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -24,41 +24,51 @@ #include "../common/servertalk.h" #include "../common/platform.h" #include "../common/crash.h" +#include "../common/strings.h" #include "../common/event/event_loop.h" #include "../common/timer.h" #include "database.h" #include "queryservconfig.h" #include "lfguild.h" #include "worldserver.h" +#include "../common/path_manager.h" +#include "../common/zone_store.h" #include #include +#include volatile bool RunLoops = true; -Database database; -LFGuildManager lfguildmanager; -std::string WorldShortName; +QSDatabase database; +LFGuildManager lfguildmanager; +std::string WorldShortName; const queryservconfig *Config; -WorldServer *worldserver = 0; -EQEmuLogSys LogSys; +WorldServer *worldserver = 0; +EQEmuLogSys LogSys; +PathManager path; +ZoneStore zone_store; -void CatchSignal(int sig_num) { +void CatchSignal(int sig_num) +{ RunLoops = false; } -int main() { +int main() +{ RegisterExecutablePlatform(ExePlatformQueryServ); LogSys.LoadLogSettingsDefaults(); set_exception_handler(); Timer LFGuildExpireTimer(60000); + path.LoadPaths(); + LogInfo("Starting EQEmu QueryServ"); if (!queryservconfig::LoadConfig()) { LogInfo("Loading server configuration failed"); return 1; } - Config = queryservconfig::get(); + Config = queryservconfig::get(); WorldShortName = Config->ShortName; LogInfo("Connecting to MySQL"); @@ -69,20 +79,22 @@ int main() { Config->QSDatabaseUsername.c_str(), Config->QSDatabasePassword.c_str(), Config->QSDatabaseDB.c_str(), - Config->QSDatabasePort)) { + Config->QSDatabasePort + )) { LogInfo("Cannot continue without a database connection"); return 1; } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); - if (signal(SIGINT, CatchSignal) == SIG_ERR) { + if (signal(SIGINT, CatchSignal) == SIG_ERR) { LogInfo("Could not set signal handler"); return 1; } - if (signal(SIGTERM, CatchSignal) == SIG_ERR) { + if (signal(SIGTERM, CatchSignal) == SIG_ERR) { LogInfo("Could not set signal handler"); return 1; } @@ -94,18 +106,29 @@ int main() { /* Load Looking For Guild Manager */ lfguildmanager.LoadDatabase(); - while(RunLoops) { + auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); - if(LFGuildExpireTimer.Check()) - lfguildmanager.ExpireEntries(); - EQ::EventLoop::Get().Process(); - Sleep(5); - } + if (!RunLoops) { + EQ::EventLoop::Get().Shutdown(); + return; + } + + if (LFGuildExpireTimer.Check()) { + lfguildmanager.ExpireEntries(); + } + }; + + EQ::Timer process_timer(loop_fn); + process_timer.Start(32, true); + + EQ::EventLoop::Get().Run(); + LogSys.CloseFileLogs(); } -void UpdateWindowTitle(char* iNewTitle) { +void UpdateWindowTitle(char *iNewTitle) +{ #ifdef _WINDOWS char tmp[500]; if (iNewTitle) { diff --git a/queryserv/queryservconfig.h b/queryserv/queryservconfig.h index 9878493f7..5c9d63bd6 100644 --- a/queryserv/queryservconfig.h +++ b/queryserv/queryservconfig.h @@ -40,13 +40,13 @@ public: } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_chat_config != nullptr) delete _chat_config; _chat_config=new queryservconfig; _config=_chat_config; - return _config->parseFile(); + return _config->parseFile(path); } }; diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index 1c65b92fd..70dc91577 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -37,10 +37,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include -extern WorldServer worldserver; +extern WorldServer worldserver; extern const queryservconfig *Config; -extern Database database; -extern LFGuildManager lfguildmanager; +extern QSDatabase database; +extern LFGuildManager lfguildmanager; WorldServer::WorldServer() { @@ -52,7 +52,13 @@ WorldServer::~WorldServer() void WorldServer::Connect() { - m_connection = std::make_unique(Config->WorldIP, Config->WorldTCPPort, false, "QueryServ", Config->SharedKey); + m_connection = std::make_unique( + Config->WorldIP, + Config->WorldTCPPort, + false, + "QueryServ", + Config->SharedKey + ); m_connection->OnMessage(std::bind(&WorldServer::HandleMessage, this, std::placeholders::_1, std::placeholders::_2)); } @@ -80,109 +86,109 @@ bool WorldServer::Connected() const void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { switch (opcode) { - case 0: { - break; - } - case ServerOP_KeepAlive: { - break; - } - case ServerOP_Speech: { - Server_Speech_Struct *SSS = (Server_Speech_Struct*)p.Data(); - std::string tmp1 = SSS->from; - std::string tmp2 = SSS->to; - database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type); - break; - } - case ServerOP_QSPlayerLogTrades: { - QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct*)p.Data(); - database.LogPlayerTrade(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerDropItem: { - QSPlayerDropItem_Struct *QS = (QSPlayerDropItem_Struct *) p.Data(); - database.LogPlayerDropItem(QS); - break; - } - case ServerOP_QSPlayerLogHandins: { - QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)p.Data(); - database.LogPlayerHandin(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerLogNPCKills: { - QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct*)p.Data(); - uint32 Members = (uint32)(p.Length() - sizeof(QSPlayerLogNPCKill_Struct)); - if (Members > 0) Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct); - database.LogPlayerNPCKill(QS, Members); - break; - } - case ServerOP_QSPlayerLogDeletes: { - QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct*)p.Data(); - uint32 Items = QS->char_count; - database.LogPlayerDelete(QS, Items); - break; - } - case ServerOP_QSPlayerLogMoves: { - QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct*)p.Data(); - uint32 Items = QS->char_count; - database.LogPlayerMove(QS, Items); - break; - } - case ServerOP_QSPlayerLogMerchantTransactions: { - QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct*)p.Data(); - uint32 Items = QS->char_count + QS->merchant_count; - database.LogMerchantTransaction(QS, Items); - break; - } - case ServerOP_QueryServGeneric: { - /* - The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets - each time we add functionality to queryserv. + case 0: { + break; + } + case ServerOP_KeepAlive: { + break; + } + case ServerOP_Speech: { + Server_Speech_Struct *SSS = (Server_Speech_Struct *) p.Data(); + std::string tmp1 = SSS->from; + std::string tmp2 = SSS->to; + database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type); + break; + } + case ServerOP_QSPlayerLogTrades: { + QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct *) p.Data(); + database.LogPlayerTrade(QS, QS->_detail_count); + break; + } + case ServerOP_QSPlayerDropItem: { + QSPlayerDropItem_Struct *QS = (QSPlayerDropItem_Struct *) p.Data(); + database.LogPlayerDropItem(QS); + break; + } + case ServerOP_QSPlayerLogHandins: { + QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct *) p.Data(); + database.LogPlayerHandin(QS, QS->_detail_count); + break; + } + case ServerOP_QSPlayerLogNPCKills: { + QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct *) p.Data(); + uint32 Members = (uint32) (p.Length() - sizeof(QSPlayerLogNPCKill_Struct)); + if (Members > 0) { Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct); } + database.LogPlayerNPCKill(QS, Members); + break; + } + case ServerOP_QSPlayerLogDeletes: { + QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct *) p.Data(); + uint32 Items = QS->char_count; + database.LogPlayerDelete(QS, Items); + break; + } + case ServerOP_QSPlayerLogMoves: { + QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct *) p.Data(); + uint32 Items = QS->char_count; + database.LogPlayerMove(QS, Items); + break; + } + case ServerOP_QSPlayerLogMerchantTransactions: { + QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct *) p.Data(); + uint32 Items = QS->char_count + QS->merchant_count; + database.LogMerchantTransaction(QS, Items); + break; + } + case ServerOP_QueryServGeneric: { + /* + The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets + each time we add functionality to queryserv. - A ServerOP_QueryServGeneric packet has the following format: + A ServerOP_QueryServGeneric packet has the following format: - uint32 SourceZoneID - uint32 SourceInstanceID - char OriginatingCharacterName[0] - - Null terminated name of the character this packet came from. This could be just - - an empty string if it has no meaning in the context of a particular packet. - uint32 Type + uint32 SourceZoneID + uint32 SourceInstanceID + char OriginatingCharacterName[0] + - Null terminated name of the character this packet came from. This could be just + - an empty string if it has no meaning in the context of a particular packet. + uint32 Type - The 'Type' field is a 'sub-opcode'. A value of 0 is used for the LFGuild packets. The next feature to be added - to queryserv would use 1, etc. + The 'Type' field is a 'sub-opcode'. A value of 0 is used for the LFGuild packets. The next feature to be added + to queryserv would use 1, etc. - Obviously, any fields in the packet following the 'Type' will be unique to the particular type of packet. The - 'Generic' in the name of this ServerOP code relates to the four header fields. - */ + Obviously, any fields in the packet following the 'Type' will be unique to the particular type of packet. The + 'Generic' in the name of this ServerOP code relates to the four header fields. + */ - auto from = p.GetCString(8); - uint32 Type = p.GetUInt32(8 + from.length() + 1); + auto from = p.GetCString(8); + uint32 Type = p.GetUInt32(8 + from.length() + 1); - switch (Type) { - case QSG_LFGuild: { + switch (Type) { + case QSG_LFGuild: { + ServerPacket pack; + pack.pBuffer = (uchar *) p.Data(); + pack.opcode = opcode; + pack.size = (uint32) p.Length(); + lfguildmanager.HandlePacket(&pack); + pack.pBuffer = nullptr; + break; + } + default: + LogInfo("Received unhandled ServerOP_QueryServGeneric", Type); + break; + } + break; + } + case ServerOP_QSSendQuery: { + /* Process all packets here */ ServerPacket pack; - pack.pBuffer = (uchar*)p.Data(); - pack.opcode = opcode; - pack.size = (uint32)p.Length(); - lfguildmanager.HandlePacket(&pack); + pack.pBuffer = (uchar *) p.Data(); + pack.opcode = opcode; + pack.size = (uint32) p.Length(); + + database.GeneralQueryReceive(&pack); pack.pBuffer = nullptr; break; } - default: - LogInfo("Received unhandled ServerOP_QueryServGeneric", Type); - break; - } - break; - } - case ServerOP_QSSendQuery: { - /* Process all packets here */ - ServerPacket pack; - pack.pBuffer = (uchar*)p.Data(); - pack.opcode = opcode; - pack.size = (uint32)p.Length(); - - database.GeneralQueryReceive(&pack); - pack.pBuffer = nullptr; - break; - } } } diff --git a/queryserv/worldserver.h b/queryserv/worldserver.h index 7a3d21e6f..5774f5ca8 100644 --- a/queryserv/worldserver.h +++ b/queryserv/worldserver.h @@ -18,24 +18,25 @@ #ifndef WORLDSERVER_H #define WORLDSERVER_H +#include #include "../common/eq_packet_structs.h" #include "../common/net/servertalk_client_connection.h" -class WorldServer -{ - public: - WorldServer(); - ~WorldServer(); +class WorldServer { +public: + WorldServer(); + ~WorldServer(); - void Connect(); - bool SendPacket(ServerPacket* pack); - std::string GetIP() const; - uint16 GetPort() const; - bool Connected() const; + void Connect(); + bool SendPacket(ServerPacket *pack); + std::string GetIP() const; + uint16 GetPort() const; + bool Connected() const; + + void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); +private: + std::unique_ptr m_connection; - void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); - private: - std::unique_ptr m_connection; }; #endif diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index 6902a8b83..86fa47d6b 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -1,7 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(shared_memory_sources base_data.cpp + faction_association.cpp items.cpp loot.cpp main.cpp @@ -12,6 +13,7 @@ SET(shared_memory_sources SET(shared_memory_headers base_data.h + faction_association.h items.h loot.h npc_faction.h diff --git a/shared_memory/faction_association.cpp b/shared_memory/faction_association.cpp new file mode 100644 index 000000000..c0ee0a9e9 --- /dev/null +++ b/shared_memory/faction_association.cpp @@ -0,0 +1,45 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "faction_association.h" +#include "../common/global_define.h" +#include "../common/shareddb.h" +#include "../common/ipc_mutex.h" +#include "../common/memory_mapped_file.h" +#include "../common/eqemu_exception.h" +#include "../common/faction.h" + +void LoadFactionAssociation(SharedDatabase *database, const std::string &prefix) { + EQ::IPCMutex mutex("factionassociations"); + mutex.Lock(); + + uint32 lists = 0; + uint32 max_list = 0; + database->GetFactionAssociationInfo(lists, max_list); + + uint32 size = static_cast(EQ::FixedMemoryHashSet::estimated_size(lists, max_list)); + + auto Config = EQEmuConfig::get(); + std::string file_name = Config->SharedMemDir + prefix + std::string("factionassociations"); + EQ::MemoryMappedFile mmf(file_name, size); + mmf.ZeroFile(); + + void *ptr = mmf.Get(); + database->LoadFactionAssociation(ptr, size, lists, max_list); + mutex.Unlock(); +} diff --git a/shared_memory/faction_association.h b/shared_memory/faction_association.h new file mode 100644 index 000000000..54d850a08 --- /dev/null +++ b/shared_memory/faction_association.h @@ -0,0 +1,28 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_SHARED_MEMORY_FACTION_ASSOCIATION_H +#define __EQEMU_SHARED_MEMORY_FACTION_ASSOCIATION_H + +#include +#include "../common/eqemu_config.h" + +class SharedDatabase; +void LoadFactionAssociation(SharedDatabase *database, const std::string &prefix); + +#endif diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index d6e57d6f8..98a9c46b4 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -26,7 +26,8 @@ #include "../common/crash.h" #include "../common/rulesys.h" #include "../common/eqemu_exception.h" -#include "../common/string_util.h" +#include "../common/strings.h" +#include "faction_association.h" #include "items.h" #include "npc_faction.h" #include "loot.h" @@ -34,9 +35,13 @@ #include "spells.h" #include "base_data.h" #include "../common/content/world_content_service.h" +#include "../common/zone_store.h" +#include "../common/path_manager.h" EQEmuLogSys LogSys; WorldContentService content_service; +ZoneStore zone_store; +PathManager path; #ifdef _WINDOWS #include @@ -80,6 +85,8 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + LogInfo("Shared Memory Loader Program"); if (!EQEmuConfig::LoadConfig()) { LogError("Unable to load configuration file"); @@ -121,6 +128,7 @@ int main(int argc, char **argv) } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); @@ -156,13 +164,9 @@ int main(int argc, char **argv) if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { LogInfo("No rule set configured, using default rules"); } - else { - LogInfo("Loaded default rule set 'default'"); - } } EQ::InitializeDynamicLookups(); - LogInfo("Initialized dynamic dictionary entries"); } @@ -179,13 +183,14 @@ int main(int argc, char **argv) std::string hotfix_name = ""; - bool load_all = true; - bool load_items = false; - bool load_factions = false; - bool load_loot = false; - bool load_skill_caps = false; - bool load_spells = false; - bool load_bd = false; + bool load_all = true; + bool load_items = false; + bool load_factions = false; + bool load_faction_assoc = false; + bool load_loot = false; + bool load_skill_caps = false; + bool load_spells = false; + bool load_bd = false; if (argc > 1) { for (int i = 1; i < argc; ++i) { @@ -227,9 +232,13 @@ int main(int argc, char **argv) load_spells = true; load_all = false; } + else if (strcasecmp("faction_assoc", argv[i]) == 0) { + load_faction_assoc = true; + load_all = false; + } break; case '-': { - auto split = SplitString(argv[i], '='); + auto split = Strings::Split(argv[i], '='); if (split.size() >= 2) { auto command = split[0]; auto argument = split[1]; @@ -259,7 +268,6 @@ int main(int argc, char **argv) } if (load_all || load_factions) { - LogInfo("Loading factions"); try { LoadFactions(&content_db, hotfix_name); } catch (std::exception &ex) { @@ -298,6 +306,16 @@ int main(int argc, char **argv) } } + if (load_all || load_faction_assoc) { + LogInfo("Loading faction associations"); + try { + LoadFactionAssociation(&content_db, hotfix_name); + } catch(std::exception &ex) { + LogError("{}", ex.what()); + return 1; + } + } + if (load_all || load_bd) { LogInfo("Loading base data"); try { diff --git a/submodules/cereal b/submodules/cereal index 51cbda5f3..ebef1e929 160000 --- a/submodules/cereal +++ b/submodules/cereal @@ -1 +1 @@ -Subproject commit 51cbda5f30e56c801c07fe3d3aba5d7fb9e6cca4 +Subproject commit ebef1e929807629befafbb2918ea1a08c7194554 diff --git a/submodules/fmt b/submodules/fmt index 9e554999c..a33701196 160000 --- a/submodules/fmt +++ b/submodules/fmt @@ -1 +1 @@ -Subproject commit 9e554999ce02cf86fcdfe74fe740c4fe3f5a56d5 +Subproject commit a33701196adfad74917046096bf5a2aa0ab0bb50 diff --git a/submodules/libuv b/submodules/libuv index 8669d8d3e..0c1fa696a 160000 --- a/submodules/libuv +++ b/submodules/libuv @@ -1 +1 @@ -Subproject commit 8669d8d3e93cddb62611b267ef62a3ddb5ba3ca0 +Subproject commit 0c1fa696aa502eb749c2c4735005f41ba00a27b8 diff --git a/submodules/websocketpp b/submodules/websocketpp index c6d7e295b..b9aeec6ea 160000 --- a/submodules/websocketpp +++ b/submodules/websocketpp @@ -1 +1 @@ -Subproject commit c6d7e295bf5a0ab9b5f896720cc1a0e0fdc397a7 +Subproject commit b9aeec6eaf3d5610503439b4fae3581d9aff08e8 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 41c7aa547..6ed82f5b8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,11 +16,12 @@ SET(tests_headers memory_mapped_file_test.h string_util_test.h skills_util_test.h + task_state_test.h ) ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers}) -TARGET_LINK_LIBRARIES(tests common cppunit fmt) +TARGET_LINK_LIBRARIES(tests common cppunit fmt ${SERVER_LIBS}) INSTALL(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/atobool_test.h b/tests/atobool_test.h index 5cc9ad872..21ef277d1 100644 --- a/tests/atobool_test.h +++ b/tests/atobool_test.h @@ -20,7 +20,7 @@ #define __EQEMU_TESTS_ATOBOOL_H #include "cppunit/cpptest.h" -#include "../common/string_util.h" +#include "../common/strings.h" class atoboolTest : public Test::Suite { typedef void(atoboolTest::*TestFunction)(void); diff --git a/tests/hextoi_32_64_test.h b/tests/hextoi_32_64_test.h index 1ad6c9d24..cd7bb83bd 100644 --- a/tests/hextoi_32_64_test.h +++ b/tests/hextoi_32_64_test.h @@ -20,7 +20,7 @@ #define __EQEMU_TESTS_HEXTOI_32_64_H #include "cppunit/cpptest.h" -#include "../common/string_util.h" +#include "../common/strings.h" class hextoi_32_64_Test : public Test::Suite { typedef void(hextoi_32_64_Test::*TestFunction)(void); @@ -100,12 +100,12 @@ public: // A bit excessive to do an exhaustive test like this // but it usefully tests multi digit hex. void DoubleDigitUpper32Test() { - + std::string prepend = "0x"; std::string hexToTest; std::string hexElements = "0123456789ABCDEF"; - uint32 value = 0; + uint32 value = 0; for (std::string::iterator firstDigitIter = hexElements.begin(); firstDigitIter != hexElements.end(); ++firstDigitIter) { for (std::string::iterator secondDigitIter = hexElements.begin(); secondDigitIter != hexElements.end(); ++secondDigitIter) { std::string hexToTest = prepend + *firstDigitIter + *secondDigitIter; @@ -122,7 +122,7 @@ public: std::string hexToTest; std::string hexElements = "0123456789abcdef"; - uint32 value = 0; + uint32 value = 0; for (std::string::iterator firstDigitIter = hexElements.begin(); firstDigitIter != hexElements.end(); ++firstDigitIter) { for (std::string::iterator secondDigitIter = hexElements.begin(); secondDigitIter != hexElements.end(); ++secondDigitIter) { std::string hexToTest = prepend + *firstDigitIter + *secondDigitIter; @@ -151,7 +151,7 @@ public: std::string hexToTest; std::string hexElements = "0123456789ABCDEF"; - uint64 value = 0; + uint64 value = 0; for (std::string::iterator firstDigitIter = hexElements.begin(); firstDigitIter != hexElements.end(); ++firstDigitIter) { std::string hexToTest = prepend + *firstDigitIter; TEST_ASSERT(hextoi64(hexToTest.c_str()) == value); @@ -165,7 +165,7 @@ public: std::string hexToTest; std::string hexElements = "0123456789abcdef"; - uint64 value = 0; + uint64 value = 0; for (std::string::iterator firstDigitIter = hexElements.begin(); firstDigitIter != hexElements.end(); ++firstDigitIter) { std::string hexToTest = prepend + *firstDigitIter; TEST_ASSERT(hextoi64(hexToTest.c_str()) == value); @@ -176,12 +176,12 @@ public: // A bit excessive to do an exhaustive test like this // but it usefully tests multi digit hex. void DoubleDigitUpper64Test() { - + std::string prepend = "0x"; std::string hexToTest; std::string hexElements = "0123456789ABCDEF"; - uint64 value = 0; + uint64 value = 0; for (std::string::iterator firstDigitIter = hexElements.begin(); firstDigitIter != hexElements.end(); ++firstDigitIter) { for (std::string::iterator secondDigitIter = hexElements.begin(); secondDigitIter != hexElements.end(); ++secondDigitIter) { std::string hexToTest = prepend + *firstDigitIter + *secondDigitIter; @@ -198,7 +198,7 @@ public: std::string hexToTest; std::string hexElements = "0123456789abcdef"; - uint64 value = 0; + uint64 value = 0; for (std::string::iterator firstDigitIter = hexElements.begin(); firstDigitIter != hexElements.end(); ++firstDigitIter) { for (std::string::iterator secondDigitIter = hexElements.begin(); secondDigitIter != hexElements.end(); ++secondDigitIter) { std::string hexToTest = prepend + *firstDigitIter + *secondDigitIter; diff --git a/tests/main.cpp b/tests/main.cpp index 9d72da520..2f32c2840 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -20,6 +20,8 @@ #include #include #include +#include "../common/platform.h" +#include "../common/path_manager.h" #include "memory_mapped_file_test.h" #include "ipc_mutex_test.h" #include "fixed_memory_test.h" @@ -29,17 +31,24 @@ #include "string_util_test.h" #include "data_verification_test.h" #include "skills_util_test.h" -#include "../common/eqemu_config.h" +#include "task_state_test.h" const EQEmuConfig *Config; +EQEmuLogSys LogSys; +PathManager path; + +int main() +{ + RegisterExecutablePlatform(ExePlatformClientImport); + LogSys.LoadLogSettingsDefaults(); + path.LoadPaths(); -int main() { auto ConfigLoadResult = EQEmuConfig::LoadConfig(); - Config = EQEmuConfig::get(); + Config = EQEmuConfig::get(); try { - std::ofstream outfile("test_output.txt"); + std::ofstream outfile("test_output.txt"); std::unique_ptr output(new Test::TextOutput(Test::TextOutput::Verbose, outfile)); - Test::Suite tests; + Test::Suite tests; tests.add(new MemoryMappedFileTest()); tests.add(new IPCMutexTest()); tests.add(new FixedMemoryHashTest()); @@ -49,8 +58,9 @@ int main() { tests.add(new StringUtilTest()); tests.add(new DataVerificationTest()); tests.add(new SkillsUtilsTest()); + tests.add(new TaskStateTest()); tests.run(*output, true); - } catch(...) { + } catch (...) { return -1; } return 0; diff --git a/tests/string_util_test.h b/tests/string_util_test.h index 1fdd325f9..5d8a3a956 100644 --- a/tests/string_util_test.h +++ b/tests/string_util_test.h @@ -20,7 +20,7 @@ #define __EQEMU_TESTS_STRING_UTIL_H #include "cppunit/cpptest.h" -#include "../common/string_util.h" +#include "../common/strings.h" class StringUtilTest : public Test::Suite { typedef void(StringUtilTest::*TestFunction)(void); @@ -28,9 +28,9 @@ public: StringUtilTest() { TEST_ADD(StringUtilTest::StringFormatTest); TEST_ADD(StringUtilTest::EscapeStringTest); - TEST_ADD(StringUtilTest::EscapeStringMemoryTest); TEST_ADD(StringUtilTest::SearchDeliminatedStringTest); TEST_ADD(StringUtilTest::SplitStringTest); + TEST_ADD(StringUtilTest::FromCharsTest); } ~StringUtilTest() { @@ -42,7 +42,7 @@ public: char c = 'a'; int i = 2014; float f = 3.1416; - + auto s = StringFormat(fmt, c, i, f); TEST_ASSERT_EQUALS(s.length(), 17); TEST_ASSERT(s.compare("Test: a 2014 3.14") == 0); @@ -62,62 +62,60 @@ public: t[8] = '\"'; t[9] = '\x1a'; - auto s = EscapeString(t); - TEST_ASSERT(s.compare("abc\\x00\\n\\r\\\\\\'\\\"\\x1a") == 0); - } - - void EscapeStringMemoryTest() { - char t[10] = { 0 }; - t[0] = 'a'; - t[1] = 'b'; - t[2] = 'c'; - t[3] = '\x00'; - t[4] = '\n'; - t[5] = '\r'; - t[6] = '\\'; - t[7] = '\''; - t[8] = '\"'; - t[9] = '\x1a'; - - auto s = EscapeString(t, 10); + auto s = Strings::Escape(t); TEST_ASSERT(s.compare("abc\\x00\\n\\r\\\\\\'\\\"\\x1a") == 0); } void SearchDeliminatedStringTest() { std::string h = "befallen,charasis,dalnir,frontiermtns,gukbottom,iceclad,lakeofillomen,northkarana,qey2hh1,soldunga,southro,wakening,podisease,velketor,akheva,riwwi,bothunder,poair"; - TEST_ASSERT(search_deliminated_string(h, "befallen") == 0); - TEST_ASSERT(search_deliminated_string(h, "charasis") == 9); - TEST_ASSERT(search_deliminated_string(h, "dalnir") == 18); - TEST_ASSERT(search_deliminated_string(h, "frontiermtns") == 25); - TEST_ASSERT(search_deliminated_string(h, "gukbottom") == 38); - TEST_ASSERT(search_deliminated_string(h, "iceclad") == 48); - TEST_ASSERT(search_deliminated_string(h, "lakeofillomen") == 56); - TEST_ASSERT(search_deliminated_string(h, "northkarana") == 70); - TEST_ASSERT(search_deliminated_string(h, "qey2hh1") == 82); - TEST_ASSERT(search_deliminated_string(h, "soldunga") == 90); - TEST_ASSERT(search_deliminated_string(h, "southro") == 99); - TEST_ASSERT(search_deliminated_string(h, "wakening") == 107); - TEST_ASSERT(search_deliminated_string(h, "podisease") == 116); - TEST_ASSERT(search_deliminated_string(h, "velketor") == 126); - TEST_ASSERT(search_deliminated_string(h, "akheva") == 135); - TEST_ASSERT(search_deliminated_string(h, "riwwi") == 142); - TEST_ASSERT(search_deliminated_string(h, "bothunder") == 148); - TEST_ASSERT(search_deliminated_string(h, "poair") == 158); - TEST_ASSERT(search_deliminated_string(h, "pod") == std::string::npos); - TEST_ASSERT(search_deliminated_string(h, "air") == std::string::npos); - TEST_ASSERT(search_deliminated_string(h, "bef") == std::string::npos); - TEST_ASSERT(search_deliminated_string(h, "wwi") == std::string::npos); + TEST_ASSERT(Strings::SearchDelim(h, "befallen") == 0); + TEST_ASSERT(Strings::SearchDelim(h, "charasis") == 9); + TEST_ASSERT(Strings::SearchDelim(h, "dalnir") == 18); + TEST_ASSERT(Strings::SearchDelim(h, "frontiermtns") == 25); + TEST_ASSERT(Strings::SearchDelim(h, "gukbottom") == 38); + TEST_ASSERT(Strings::SearchDelim(h, "iceclad") == 48); + TEST_ASSERT(Strings::SearchDelim(h, "lakeofillomen") == 56); + TEST_ASSERT(Strings::SearchDelim(h, "northkarana") == 70); + TEST_ASSERT(Strings::SearchDelim(h, "qey2hh1") == 82); + TEST_ASSERT(Strings::SearchDelim(h, "soldunga") == 90); + TEST_ASSERT(Strings::SearchDelim(h, "southro") == 99); + TEST_ASSERT(Strings::SearchDelim(h, "wakening") == 107); + TEST_ASSERT(Strings::SearchDelim(h, "podisease") == 116); + TEST_ASSERT(Strings::SearchDelim(h, "velketor") == 126); + TEST_ASSERT(Strings::SearchDelim(h, "akheva") == 135); + TEST_ASSERT(Strings::SearchDelim(h, "riwwi") == 142); + TEST_ASSERT(Strings::SearchDelim(h, "bothunder") == 148); + TEST_ASSERT(Strings::SearchDelim(h, "poair") == 158); + TEST_ASSERT(Strings::SearchDelim(h, "pod") == std::string::npos); + TEST_ASSERT(Strings::SearchDelim(h, "air") == std::string::npos); + TEST_ASSERT(Strings::SearchDelim(h, "bef") == std::string::npos); + TEST_ASSERT(Strings::SearchDelim(h, "wwi") == std::string::npos); } void SplitStringTest() { std::string s = "123,456,789,"; - auto v = SplitString(s, ','); + auto v = Strings::Split(s, ','); TEST_ASSERT(v.size() == 3); TEST_ASSERT(v[0] == "123"); TEST_ASSERT(v[1] == "456"); TEST_ASSERT(v[2] == "789"); } + + void FromCharsTest() { + char int_chars[] = "123"; + int int_value = 0; + + char float_chars[] = "3.14"; + float float_value = 0.0f; + + Strings::from_chars(int_chars, int_value); + TEST_ASSERT(int_value == 123); + + Strings::from_chars(float_chars, float_value); + TEST_ASSERT(float_value == 3.14f); + + } }; #endif diff --git a/tests/task_state_test.h b/tests/task_state_test.h new file mode 100644 index 000000000..d1a0551b6 --- /dev/null +++ b/tests/task_state_test.h @@ -0,0 +1,1183 @@ +#pragma once + +#include "cppunit/cpptest.h" +#include "../common/eqemu_logsys.h" +#include "../common/tasks.h" +#include "../common/shared_tasks.h" + +class TaskStateTest: public Test::Suite +{ +public: + TaskStateTest() + { + TEST_ADD(TaskStateTest::TestSequenceMode); + TEST_ADD(TaskStateTest::TestSteps); + TEST_ADD(TaskStateTest::TestStepGaps); + TEST_ADD(TaskStateTest::TestUnorderedSteps); + TEST_ADD(TaskStateTest::TestOptionalSteps); + TEST_ADD(TaskStateTest::TestOptionalLastSteps); + TEST_ADD(TaskStateTest::TestOptionalSequence); + TEST_ADD(TaskStateTest::TestWorldTemplateSupport); + TEST_ADD(TaskStateTest::TestReqActivityID); + TEST_ADD(TaskStateTest::TestReqActivityIDOverrideStep); + TEST_ADD(TaskStateTest::TestReqActivityIDSteps); + TEST_ADD(TaskStateTest::TestReqActivityIDUnorderedSteps); + TEST_ADD(TaskStateTest::TestReqActivityIDMixSteps); + TEST_ADD(TaskStateTest::TestReqActivityIDSequenceMode); + TEST_ADD(TaskStateTest::TestReqActivityIDOptional); + TEST_ADD(TaskStateTest::TestReqActivityIDOptionalLastSteps); + } + +private: + void TestSequenceMode(); + void TestSteps(); + void TestStepGaps(); + void TestUnorderedSteps(); + void TestOptionalSteps(); + void TestOptionalLastSteps(); + void TestOptionalSequence(); + void TestWorldTemplateSupport(); + void TestReqActivityID(); + void TestReqActivityIDOverrideStep(); + void TestReqActivityIDSteps(); + void TestReqActivityIDUnorderedSteps(); + void TestReqActivityIDMixSteps(); + void TestReqActivityIDSequenceMode(); + void TestReqActivityIDOptional(); + void TestReqActivityIDOptionalLastSteps(); + + TaskInformation GetMockZoneData(int count) + { + TaskInformation task; + task.activity_count = count; + for (int i = 0; i < task.activity_count; ++i) + { + task.activity_information[i].req_activity_id = -1; + task.activity_information[i].step = 0; + task.activity_information[i].optional = false; + } + return task; + } + + ClientTaskInformation GetMockZoneState(int count) + { + ClientTaskInformation state; + for (int i = 0; i < count; ++i) + { + state.activity[i].activity_id = i; + state.activity[i].activity_state = ActivityState::ActivityHidden; + } + return state; + } + + std::vector GetMockWorldData(int count) + { + std::vector data; + data.resize(count); + for (int i = 0; i < count; ++i) + { + data[i].activityid = i; + data[i].req_activity_id = -1; + data[i].step = 0; + data[i].optional = false; + } + return data; + } + + std::vector GetMockWorldState(int count) + { + std::vector states; + states.resize(count); + for (int i = 0; i < count; ++i) + { + states[i].activity_id = i; + states[i].req_activity_id = -1; + states[i].step = 0; + states[i].optional = false; + states[i].activity_state = ActivityState::ActivityHidden; + } + return states; + } +}; + +void TaskStateTest::TestSequenceMode() +{ + int activity_count = 3; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + + { + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | hidden (active) + // 1 | 0 | hidden + // 2 | 0 | hidden + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 0 | hidden (active) + // 2 | 0 | hidden + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id |step | state + // 0 | 0 | completed + // 1 | 0 | completed + // 2 | 0 | hidden (active) + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 0 | completed + // 2 | 0 | completed + + // task completed, none should be active + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityHidden; + data.activity_information[2].optional = true; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 0 | completed + // 2 | 0 | hidden | optional (active) + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } +} + +void TaskStateTest::TestSteps() +{ + int activity_count = 4; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[1].step = 1; + data.activity_information[2].step = 1; + data.activity_information[3].step = 2; + + { + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | hidden (active) + // 1 | 1 | hidden + // 2 | 1 | hidden + // 3 | 2 | hidden + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 1 | hidden (active) + // 2 | 1 | hidden (active) + // 3 | 2 | hidden + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 1 | completed + // 2 | 1 | hidden (active) + // 3 | 2 | hidden + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 1 | completed + // 2 | 1 | completed + // 3 | 2 | hidden (active) + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 1 | completed + // 2 | 1 | completed + // 3 | 2 | completed + + // should be complete with none active + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityHidden; + data.activity_information[3].optional = true; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // activity_id | step | state + // 0 | 0 | completed + // 1 | 1 | completed + // 2 | 1 | completed + // 3 | 2 | hidden | optional (active) + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } +} + +void TaskStateTest::TestStepGaps() +{ + int activity_count = 5; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[0].step = 1; + data.activity_information[1].step = 5; + data.activity_information[2].step = 5; + data.activity_information[3].step = 100; + data.activity_information[4].step = 100; + + { + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 0 should be active starting at step 1 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // indexes 1 and 2 should be active at step 5 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // only index 2 should be active with step 5 since index 1 is completed + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // indexes 3 and 4 should be active for step 100 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + state.activity[4].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } +} + +void TaskStateTest::TestUnorderedSteps() +{ + int activity_count = 5; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[0].step = 100; + data.activity_information[1].step = 100; + data.activity_information[2].step = 3; + data.activity_information[3].step = 20; + data.activity_information[4].step = 1; + + { + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 4 should be active as the lowest step + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } + + { + state.activity[4].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 2 should be the next lowest step (3) after step 1 completed + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state.activity[4].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 3 should be active as step 20 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } + + { + state.activity[4].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // indexes 0 and 1 should both be active as step 100 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } +} + +void TaskStateTest::TestOptionalSteps() +{ + int activity_count = 4; + auto data = GetMockWorldData(activity_count); + auto state = GetMockWorldState(activity_count); + data[0].step = 0; + data[1].step = 1; + data[1].optional = true; + data[2].step = 2; + data[2].optional = true; + data[3].step = 2; + + { + auto res = Tasks::GetActiveElements(data, state, activity_count); + + // activity_id | step | state + // 0 | 0 | hidden (active) + // 1 | 1 | hidden | optional + // 2 | 2 | hidden | optional + // 3 | 2 | hidden + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 1 | hidden | optional (active) + // 2 | 2 | hidden | optional + // 3 | 2 | hidden + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + // since optional is on its own step it's effectively non-optional to open next step + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 1 | complete | optional + // 2 | 2 | hidden | optional (active) + // 3 | 2 | hidden (active) + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + state[3].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 1 | complete | optional + // 2 | 2 | hidden | optional (active) + // 3 | 2 | complete + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + state[2].activity_state = ActivityState::ActivityCompleted; + state[3].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } +} + +void TaskStateTest::TestOptionalLastSteps() +{ + int activity_count = 3; + auto data = GetMockWorldData(activity_count); + auto state = GetMockWorldState(activity_count); + data[0].step = 0; + data[1].optional = true; + data[1].step = 2; + data[2].optional = true; + data[2].step = 3; + + { + // activity_id | step | state + // 0 | 0 | hidden (active) + // 1 | 1 | hidden | optional + // 2 | 2 | hidden | optional + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 1 | hidden | optional (active) + // 2 | 2 | hidden | optional + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 1 | complete | optional + // 2 | 2 | hidden | optional (active) + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } +} + +void TaskStateTest::TestOptionalSequence() +{ + int activity_count = 3; + auto data = GetMockWorldData(activity_count); + auto state = GetMockWorldState(activity_count); + data[0].step = 0; + data[1].step = 0; + data[1].optional = true; + data[2].step = 0; + + { + // activity_id | step | state + // 0 | 0 | hidden (active) + // 1 | 0 | hidden | optional + // 2 | 0 | hidden + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 0 | hidden | optional (active) + // 2 | 0 | hidden (active) + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 0 | complete + // 2 | 0 | hidden (active) + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityHidden; + state[2].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | 0 | complete + // 1 | 0 | hidden | optional (active) + // 2 | 0 | complete + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + state[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } +} + +void TaskStateTest::TestWorldTemplateSupport() +{ + int activity_count = 3; + auto data = GetMockWorldData(activity_count); + auto state = GetMockWorldState(activity_count); + data[0].step = 1; + data[1].step = 5; + data[2].step = 10; + state[0].step = 1; + state[1].step = 5; + state[2].step = 10; + state[0].activity_state = ActivityState::ActivityCompleted; + + { + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + // using the state struct as both data and state source + auto res = Tasks::GetActiveElements(state, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } +} + +void TaskStateTest::TestReqActivityID() +{ + int activity_count = 5; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[1].req_activity_id = 0; + data.activity_information[2].req_activity_id = 0; + data.activity_information[3].req_activity_id = 1; + data.activity_information[4].req_activity_id = 2; + + { + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + state.activity[4].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } +} + +void TaskStateTest::TestReqActivityIDOverrideStep() +{ + int activity_count = 4; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[0].step = 0; + data.activity_information[1].step = 1; + data.activity_information[2].req_activity_id = 1; + data.activity_information[2].step = 1; + data.activity_information[3].req_activity_id = 1; + data.activity_information[3].step = 1; + + state.activity[0].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // indexes 2 and 3 should require index 1 to be completed instead of activating with step 1 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); +} + +void TaskStateTest::TestReqActivityIDSteps() +{ + int activity_count = 5; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[0].step = 0; + data.activity_information[1].step = 1; + data.activity_information[2].req_activity_id = 0; + data.activity_information[2].step = 2; + data.activity_information[3].req_activity_id = 0; + data.activity_information[3].step = 2; + data.activity_information[4].step = 3; + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 1 should become active as next step, indexes 2 and 3 because of reqs + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 3); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | -1 | 1 | complete + // 2 | 0 | 2 | hidden (active) + // 3 | 0 | 2 | hidden (active) + // 4 | -1 | 3 | hidden + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 4 (step 3) should not become active until step 2 is completed + // even though index 2 and 3 are active because of reqs + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // should still be on step 2 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + state.activity[4].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } +} + + +void TaskStateTest::TestReqActivityIDUnorderedSteps() +{ + int activity_count = 5; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[0].step = 0; + data.activity_information[1].step = 1; + data.activity_information[2].req_activity_id = 0; + data.activity_information[2].step = 0; + data.activity_information[3].req_activity_id = 0; + data.activity_information[3].step = 0; + data.activity_information[4].step = 3; + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | -1 | 1 | hidden + // 2 | 0 | 0 | hidden (active) + // 3 | 0 | 0 | hidden (active) + // 4 | -1 | 3 | hidden + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | -1 | 1 | hidden (active) + // 2 | 0 | 0 | complete + // 3 | 0 | 0 | complete + // 4 | -1 | 3 | hidden + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | -1 | 1 | complete + // 2 | 0 | 0 | complete + // 3 | 0 | 0 | complete + // 4 | -1 | 3 | hidden (active) + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // should still be on step 3 + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } +} + +void TaskStateTest::TestReqActivityIDMixSteps() +{ + int activity_count = 6; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[0].step = 0; + data.activity_information[1].step = 1; + data.activity_information[2].step = 2; + data.activity_information[3].req_activity_id = 0; + data.activity_information[3].step = 2; + data.activity_information[4].req_activity_id = 0; + data.activity_information[4].step = 2; + data.activity_information[5].step = 3; + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | -1 | 1 | complete + // 2 | -1 | 2 | hidden (active) + // 3 | 0 | 2 | hidden (active) + // 4 | 0 | 2 | hidden (active) + // 5 | -1 | 3 | hidden + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 3); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | -1 | 1 | complete + // 2 | -1 | 2 | complete + // 3 | 0 | 2 | hidden (active) + // 4 | 0 | 2 | hidden (active) + // 5 | -1 | 3 | hidden + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 5 (step 3) should not be active yet after completing only index with non-req id + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 2); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + state.activity[2].activity_state = ActivityState::ActivityCompleted; + state.activity[3].activity_state = ActivityState::ActivityCompleted; + state.activity[4].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | -1 | 1 | complete + // 2 | -1 | 2 | complete + // 3 | 0 | 2 | complete + // 4 | 0 | 2 | complete + // 5 | -1 | 3 | hidden (active) + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 5) != res.active.end()); + } +} + +void TaskStateTest::TestReqActivityIDSequenceMode() +{ + int activity_count = 6; + TaskInformation data = GetMockZoneData(activity_count); + ClientTaskInformation state = GetMockZoneState(activity_count); + data.activity_information[4].req_activity_id = 1; + data.activity_information[5].req_activity_id = 0; + + { + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state.activity[0].activity_state = ActivityState::ActivityCompleted; + state.activity[1].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data.activity_information, state.activity, activity_count); + + // index 2 because of sequence mode, index 4 and 5 due to req indexes being complete + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 3); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 4) != res.active.end()); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 5) != res.active.end()); + } +} + +void TaskStateTest::TestReqActivityIDOptional() +{ + int activity_count = 3; + auto data = GetMockWorldData(activity_count); + auto state = GetMockWorldState(activity_count); + data[0].step = 0; + data[1].req_activity_id = 0; + data[1].step = 1; + data[1].optional = true; + data[2].req_activity_id = 1; + data[2].step = 2; + + { + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | hidden (active) + // 1 | 0 | 1 | hidden | optional + // 2 | 1 | 2 | hidden + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | 0 | 1 | hidden | optional (active) + // 2 | 1 | 2 | hidden + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + // index 1 is effectively non-optional since non-optional index 2 requires it + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | 0 | 1 | complete | optional + // 2 | 1 | 2 | hidden (active) + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + state[2].activity_state = ActivityState::ActivityCompleted; + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.empty()); + } +} + +void TaskStateTest::TestReqActivityIDOptionalLastSteps() +{ + int activity_count = 3; + auto data = GetMockWorldData(activity_count); + auto state = GetMockWorldState(activity_count); + data[0].step = 0; + data[1].req_activity_id = 0; + data[1].step = 1; + data[1].optional = true; + data[2].req_activity_id = 1; + data[2].step = 2; + data[2].optional = true; + + { + // activity_id | req_activity_id | step | state + // 0 | -1 | 0 | hidden (active) + // 1 | 0 | 1 | hidden | optional + // 2 | 1 | 2 | hidden | optional + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == false); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 0) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | 0 | 1 | hidden | optional (active) + // 2 | 1 | 2 | hidden | optional + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end()); + } + + { + state[0].activity_state = ActivityState::ActivityCompleted; + state[1].activity_state = ActivityState::ActivityCompleted; + + // activity_id | step | state + // 0 | -1 | 0 | complete + // 1 | 0 | 1 | complete | optional + // 2 | 1 | 2 | hidden | optional (active) + + auto res = Tasks::GetActiveElements(data, state, activity_count); + + TEST_ASSERT(res.is_task_complete == true); + TEST_ASSERT(res.active.size() == 1); + TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end()); + } +} diff --git a/ucs/CMakeLists.txt b/ucs/CMakeLists.txt index a1c0b32b4..660d168d8 100644 --- a/ucs/CMakeLists.txt +++ b/ucs/CMakeLists.txt @@ -1,5 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) - +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(ucs_sources chatchannel.cpp clientlist.cpp diff --git a/ucs/chatchannel.cpp b/ucs/chatchannel.cpp index da3390f55..20e0e0603 100644 --- a/ucs/chatchannel.cpp +++ b/ucs/chatchannel.cpp @@ -18,14 +18,14 @@ */ #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "chatchannel.h" #include "clientlist.h" #include "database.h" #include #include -extern Database database; +extern UCSDatabase database; extern uint32 ChatMessagesSent; void ServerToClient45SayLink(std::string& clientSayLink, const std::string& serverSayLink); @@ -33,33 +33,33 @@ void ServerToClient50SayLink(std::string& clientSayLink, const std::string& serv void ServerToClient55SayLink(std::string& clientSayLink, const std::string& serverSayLink); ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string inPassword, bool inPermanent, int inMinimumStatus) : - DeleteTimer(0) { + m_delete_timer(0) { - Name = inName; + m_name = inName; - Owner = inOwner; + m_owner = inOwner; - Password = inPassword; + m_password = inPassword; - Permanent = inPermanent; + m_permanent = inPermanent; - MinimumStatus = inMinimumStatus; + m_minimum_status = inMinimumStatus; - Moderated = false; + m_moderated = false; LogDebug( - "New ChatChannel created: Name: [[{}]], Owner: [[{}]], Password: [[{}]], MinStatus: [{}]", - Name.c_str(), - Owner.c_str(), - Password.c_str(), - MinimumStatus + "New ChatChannel created: Name: [{}], Owner: [{}], Password: [{}], MinStatus: [{}]", + m_name.c_str(), + m_owner.c_str(), + m_password.c_str(), + m_minimum_status ); } ChatChannel::~ChatChannel() { - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); @@ -67,18 +67,79 @@ ChatChannel::~ChatChannel() { iterator.RemoveCurrent(false); } -ChatChannel* ChatChannelList::CreateChannel(std::string Name, std::string Owner, std::string Password, bool Permanent, int MinimumStatus) { +ChatChannel *ChatChannelList::CreateChannel( + const std::string& name, + const std::string& owner, + const std::string& password, + bool permanent, + int minimum_status, + bool save_to_db +) +{ + uint8 max_perm_player_channels = RuleI(Chat, MaxPermanentPlayerChannels); - ChatChannel *NewChannel = new ChatChannel(CapitaliseName(Name), Owner, Password, Permanent, MinimumStatus); + if (!database.CheckChannelNameFilter(name)) { + if (!(owner == SYSTEM_OWNER)) { + return nullptr; + } + else { + LogDebug("Ignoring Name Filter as channel is owned by System..."); + } + } - ChatChannels.Insert(NewChannel); + if (IsOnChannelBlockList(name)) { + if (!(owner == SYSTEM_OWNER)) { + LogInfo("Channel name [{}] is a reserved/blocked channel name. Channel creation canceled.", name); + return nullptr; + } + else { + LogInfo("Ignoring reserved/blocked channel name [{}] as channel is owned by System...", name); + } + } + else { + LogDebug("Channel name [{}] passed the reserved/blocked channel name check...", name); + } - return NewChannel; + + auto *new_channel = new ChatChannel(CapitaliseName(name), owner, password, permanent, minimum_status); + + ChatChannels.Insert(new_channel); + + if (owner == SYSTEM_OWNER) { + save_to_db = false; + } + + // If permanent player channels are enabled (and not a system channel) + // save channel to database if not exceeding limit. + bool can_save_channel = (max_perm_player_channels > 0) && !(owner == SYSTEM_OWNER) && save_to_db; + if (can_save_channel) { + + // Ensure there is room to save another chat channel to the database. + bool player_under_channel_limit = database.CurrentPlayerChannelCount(owner) + 1 <= max_perm_player_channels; + if (player_under_channel_limit) { + database.SaveChatChannel( + CapitaliseName(name), + owner, + password, + minimum_status + ); + } + else { + LogDebug( + "Maximum number of channels [{}] reached for player [{}], channel [{}] save to database aborted.", + max_perm_player_channels, + owner, + CapitaliseName(name) + ); + } + } + + return new_channel; } ChatChannel* ChatChannelList::FindChannel(std::string Name) { - std::string NormalisedName = CapitaliseName(Name); + std::string normalized_name = CapitaliseName(Name); LinkedListIterator iterator(ChatChannels); @@ -86,9 +147,9 @@ ChatChannel* ChatChannelList::FindChannel(std::string Name) { while(iterator.MoreElements()) { - ChatChannel *CurrentChannel = iterator.GetData(); + auto *current_channel = iterator.GetData(); - if(CurrentChannel && (CurrentChannel->Name == NormalisedName)) + if(current_channel && (current_channel->m_name == normalized_name)) return iterator.GetData(); iterator.Advance(); @@ -159,7 +220,7 @@ void ChatChannelList::SendAllChannels(Client *c) { void ChatChannelList::RemoveChannel(ChatChannel *Channel) { - LogDebug("RemoveChannel ([{}])", Channel->GetName().c_str()); + LogDebug("Remove channel [{}]", Channel->GetName().c_str()); LinkedListIterator iterator(ChatChannels); @@ -194,7 +255,7 @@ int ChatChannel::MemberCount(int Status) { int Count = 0; - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); @@ -211,30 +272,43 @@ int ChatChannel::MemberCount(int Status) { return Count; } -void ChatChannel::SetPassword(std::string inPassword) { +void ChatChannel::SetPassword(const std::string& in_password) { - Password = inPassword; + m_password = in_password; - if(Permanent) + if(m_permanent) { - RemoveApostrophes(Password); - database.SetChannelPassword(Name, Password); + RemoveApostrophes(m_password); + database.SetChannelPassword(m_name, m_password); } } -void ChatChannel::SetOwner(std::string inOwner) { +void ChatChannel::SetOwner(std::string& in_owner) { - Owner = inOwner; + m_owner = in_owner; - if(Permanent) - database.SetChannelOwner(Name, Owner); + if(m_permanent) + database.SetChannelOwner(m_name, m_owner); +} + +// Returns the owner's name in type std::string() +std::string& ChatChannel::GetOwnerName() { + return m_owner; +} + +void ChatChannel::SetTemporary() { + m_permanent = false; +} + +void ChatChannel::SetPermanent() { + m_permanent = true; } void ChatChannel::AddClient(Client *c) { if(!c) return; - DeleteTimer.Disable(); + m_delete_timer.Disable(); if(IsClientInChannel(c)) { @@ -247,9 +321,9 @@ void ChatChannel::AddClient(Client *c) { int AccountStatus = c->GetAccountStatus(); - LogDebug("Adding [{}] to channel [{}]", c->GetName().c_str(), Name.c_str()); + LogDebug("Adding [{}] to channel [{}]", c->GetName().c_str(), m_name.c_str()); - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); @@ -264,7 +338,7 @@ void ChatChannel::AddClient(Client *c) { iterator.Advance(); } - ClientsInChannel.Insert(c); + m_clients_in_channel.Insert(c); } @@ -272,46 +346,46 @@ bool ChatChannel::RemoveClient(Client *c) { if(!c) return false; - LogDebug("RemoveClient [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str()); + LogDebug("Remove client [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str()); - bool HideMe = c->GetHideMe(); + bool hide_me = c->GetHideMe(); - int AccountStatus = c->GetAccountStatus(); + int account_status = c->GetAccountStatus(); - int PlayersInChannel = 0; + int players_in_channel = 0; - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); while(iterator.MoreElements()) { - Client *CurrentClient = iterator.GetData(); + auto *current_client = iterator.GetData(); - if(CurrentClient == c) { + if(current_client == c) { iterator.RemoveCurrent(false); } - else if(CurrentClient) { + else if(current_client) { - PlayersInChannel++; + players_in_channel++; - if(CurrentClient->IsAnnounceOn()) - if(!HideMe || (CurrentClient->GetAccountStatus() > AccountStatus)) - CurrentClient->AnnounceLeave(this, c); + if(current_client->IsAnnounceOn()) + if(!hide_me || (current_client->GetAccountStatus() > account_status)) + current_client->AnnounceLeave(this, c); iterator.Advance(); } } - if((PlayersInChannel == 0) && !Permanent) { + if((players_in_channel == 0) && !m_permanent) { - if((Password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0)) + if((m_password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0)) return false; - LogDebug("Starting delete timer for empty password protected channel [{}]", Name.c_str()); + LogDebug("Starting delete timer for empty password protected channel [{}]", m_name.c_str()); - DeleteTimer.Start(RuleI(Channels, DeleteTimer) * 60000); + m_delete_timer.Start(RuleI(Channels, DeleteTimer) * 60000); } return true; @@ -322,9 +396,9 @@ void ChatChannel::SendOPList(Client *c) if (!c) return; - c->GeneralChannelMessage("Channel " + Name + " op-list: (Owner=" + Owner + ")"); + c->GeneralChannelMessage("Channel " + m_name + " op-list: (Owner=" + m_owner + ")"); - for (auto &&m : Moderators) + for (auto &&m : m_moderators) c->GeneralChannelMessage(m); } @@ -350,7 +424,7 @@ void ChatChannel::SendChannelMembers(Client *c) { int MembersInLine = 0; - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); @@ -389,7 +463,7 @@ void ChatChannel::SendChannelMembers(Client *c) { } -void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) { +void ChatChannel::SendMessageToChannel(const std::string& Message, Client* Sender) { if(!Sender) return; @@ -397,40 +471,40 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) { ChatMessagesSent++; - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); while(iterator.MoreElements()) { - Client *ChannelClient = iterator.GetData(); + auto *channel_client = iterator.GetData(); - if(ChannelClient) + if(channel_client) { LogDebug("Sending message to [{}] from [{}]", - ChannelClient->GetName().c_str(), Sender->GetName().c_str()); + channel_client->GetName().c_str(), Sender->GetName().c_str()); - if (cv_messages[static_cast(ChannelClient->GetClientVersion())].length() == 0) { - switch (ChannelClient->GetClientVersion()) { + if (cv_messages[static_cast(channel_client->GetClientVersion())].length() == 0) { + switch (channel_client->GetClientVersion()) { case EQ::versions::ClientVersion::Titanium: - ServerToClient45SayLink(cv_messages[static_cast(ChannelClient->GetClientVersion())], Message); + ServerToClient45SayLink(cv_messages[static_cast(channel_client->GetClientVersion())], Message); break; case EQ::versions::ClientVersion::SoF: case EQ::versions::ClientVersion::SoD: case EQ::versions::ClientVersion::UF: - ServerToClient50SayLink(cv_messages[static_cast(ChannelClient->GetClientVersion())], Message); + ServerToClient50SayLink(cv_messages[static_cast(channel_client->GetClientVersion())], Message); break; case EQ::versions::ClientVersion::RoF: - ServerToClient55SayLink(cv_messages[static_cast(ChannelClient->GetClientVersion())], Message); + ServerToClient55SayLink(cv_messages[static_cast(channel_client->GetClientVersion())], Message); break; case EQ::versions::ClientVersion::RoF2: default: - cv_messages[static_cast(ChannelClient->GetClientVersion())] = Message; + cv_messages[static_cast(channel_client->GetClientVersion())] = Message; break; } } - ChannelClient->SendChannelMessage(Name, cv_messages[static_cast(ChannelClient->GetClientVersion())], Sender); + channel_client->SendChannelMessage(m_name, cv_messages[static_cast(channel_client->GetClientVersion())], Sender); } iterator.Advance(); @@ -439,9 +513,9 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) { void ChatChannel::SetModerated(bool inModerated) { - Moderated = inModerated; + m_moderated = inModerated; - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); @@ -451,10 +525,10 @@ void ChatChannel::SetModerated(bool inModerated) { if(ChannelClient) { - if(Moderated) - ChannelClient->GeneralChannelMessage("Channel " + Name + " is now moderated."); + if(m_moderated) + ChannelClient->GeneralChannelMessage("Channel " + m_name + " is now moderated."); else - ChannelClient->GeneralChannelMessage("Channel " + Name + " is no longer moderated."); + ChannelClient->GeneralChannelMessage("Channel " + m_name + " is no longer moderated."); } iterator.Advance(); @@ -465,7 +539,7 @@ bool ChatChannel::IsClientInChannel(Client *c) { if(!c) return false; - LinkedListIterator iterator(ClientsInChannel); + LinkedListIterator iterator(m_clients_in_channel); iterator.Reset(); @@ -480,54 +554,80 @@ bool ChatChannel::IsClientInChannel(Client *c) { return false; } -ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client *c) { +ChatChannel *ChatChannelList::AddClientToChannel(std::string channel_name, Client *c, bool command_directed) { if(!c) return nullptr; - if((ChannelName.length() > 0) && (isdigit(ChannelName[0]))) { - + if ((channel_name.length() > 0) && (isdigit(channel_name[0]))) { // Ensure channel name does not start with a number c->GeneralChannelMessage("The channel name can not begin with a number."); - + return nullptr; + } + else if (channel_name.empty()) { // Ensure channel name is not empty return nullptr; } - std::string NormalisedName, Password; + std::string normalized_name, password; - std::string::size_type Colon = ChannelName.find_first_of(":"); + std::string::size_type Colon = channel_name.find_first_of(":"); if(Colon == std::string::npos) - NormalisedName = CapitaliseName(ChannelName); + normalized_name = CapitaliseName(channel_name); else { - NormalisedName = CapitaliseName(ChannelName.substr(0, Colon)); + normalized_name = CapitaliseName(channel_name.substr(0, Colon)); - Password = ChannelName.substr(Colon + 1); + password = channel_name.substr(Colon + 1); } - if((NormalisedName.length() > 64) || (Password.length() > 64)) { + if((normalized_name.length() > 64) || (password.length() > 64)) { c->GeneralChannelMessage("The channel name or password cannot exceed 64 characters."); return nullptr; } - LogDebug("AddClient to channel [[{}]] with password [[{}]]", NormalisedName.c_str(), Password.c_str()); + ChatChannel *RequiredChannel = FindChannel(normalized_name); - ChatChannel *RequiredChannel = FindChannel(NormalisedName); + if (RequiredChannel) { + if (IsOnChannelBlockList(channel_name)) { // Ensure channel name is not blocked + if (!(RequiredChannel->GetOwnerName() == SYSTEM_OWNER)) { + c->GeneralChannelMessage("That channel name is blocked by the server operator."); + return nullptr; + } + else { + LogDebug("Reserved/blocked channel name check for [{}] ignored due to channel being owned by System...", normalized_name); + } + } + } - if(!RequiredChannel) - RequiredChannel = CreateChannel(NormalisedName, c->GetName(), Password, false, 0); + const std::string& channel_owner = c->GetName(); - if(RequiredChannel->GetMinStatus() > c->GetAccountStatus()) { + bool permanent = false; + if (command_directed && RuleI(Chat, MaxPermanentPlayerChannels) > 0) { + permanent = true; + } - std::string Message = "You do not have the required account status to join channel " + NormalisedName; + if (!RequiredChannel) { + RequiredChannel = CreateChannel(normalized_name, channel_owner, password, permanent, 0, command_directed); + if (RequiredChannel == nullptr) { + LogDebug("Failed to create new channel with name: {}. Possible blocked or reserved channel name.", normalized_name); + c->GeneralChannelMessage("Failed to create new channel with provided name. Possible blocked or reserved channel name."); + return nullptr; + } + LogDebug("Created and added Client to channel [{}] with password [{}]. Owner: {}. Command Directed: {}", normalized_name.c_str(), password.c_str(), channel_owner, command_directed); + } + + LogDebug("Checking status requirement of channel: {}. Channel status required: {}, player status: {}.", normalized_name, std::to_string(RequiredChannel->GetMinStatus()), std::to_string(c->GetAccountStatus())); + if (RequiredChannel->GetMinStatus() > c->GetAccountStatus()) { + std::string Message = "You do not have the required account status to join channel " + normalized_name; c->GeneralChannelMessage(Message); - + LogInfo("Client [{}] connection to channel [{}] refused due to insufficient status.", c->GetName(), normalized_name); return nullptr; } - if(RequiredChannel->IsClientInChannel(c)) + if (RequiredChannel->IsClientInChannel(c)) { return nullptr; + } if(RequiredChannel->IsInvitee(c->GetName())) { @@ -538,7 +638,7 @@ ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client return RequiredChannel; } - if(RequiredChannel->CheckPassword(Password) || RequiredChannel->IsOwner(c->GetName()) || RequiredChannel->IsModerator(c->GetName()) || + if(RequiredChannel->CheckPassword(password) || RequiredChannel->IsOwner(c->GetName()) || RequiredChannel->IsModerator(c->GetName()) || c->IsChannelAdmin()) { RequiredChannel->AddClient(c); @@ -546,32 +646,42 @@ ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client return RequiredChannel; } - c->GeneralChannelMessage("Incorrect password for channel " + (NormalisedName)); + c->GeneralChannelMessage("Incorrect password for channel " + (normalized_name)); return nullptr; } -ChatChannel *ChatChannelList::RemoveClientFromChannel(std::string inChannelName, Client *c) { - +ChatChannel *ChatChannelList::RemoveClientFromChannel(const std::string& in_channel_name, Client *c, bool command_directed) { if(!c) return nullptr; - std::string ChannelName = inChannelName; + std::string channel_name = in_channel_name; - if((inChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = c->ChannelSlotName(atoi(inChannelName.c_str())); + if (in_channel_name.length() > 0 && isdigit(channel_name[0])) { + channel_name = c->ChannelSlotName(atoi(in_channel_name.c_str())); + } - ChatChannel *RequiredChannel = FindChannel(ChannelName); + auto *required_channel = FindChannel(channel_name); - if(!RequiredChannel) + if (!required_channel) { return nullptr; + } + + LogDebug("Client [{}] removed from channel [{}]. Channel is owned by {}. Command directed: {}", c->GetName(), channel_name, required_channel->GetOwnerName(), command_directed); + if (c->GetName() == required_channel->GetOwnerName() && command_directed) { // Check if the client that is leaving is the the channel owner + LogDebug("Owner left the channel [{}], removing channel from database...", channel_name); + database.DeleteChatChannel(channel_name); // Remove the channel from the database. + LogDebug("Flagging [{}] channel as temporary...", channel_name); + required_channel->SetTemporary(); + } // RemoveClient will return false if there is no-one left in the channel, and the channel is not permanent and has // no password. - // - if(!RequiredChannel->RemoveClient(c)) - RemoveChannel(RequiredChannel); + if (!required_channel->RemoveClient(c)) { + LogDebug("Noone left in the temporary channel [{}] and no password is set; removing temporary channel.", channel_name); + RemoveChannel(required_channel); + } - return RequiredChannel; + return required_channel; } void ChatChannelList::Process() { @@ -600,76 +710,76 @@ void ChatChannelList::Process() { void ChatChannel::AddInvitee(const std::string &Invitee) { if (!IsInvitee(Invitee)) { - Invitees.push_back(Invitee); + m_invitees.push_back(Invitee); - LogDebug("Added [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str()); + LogDebug("Added [{}] as invitee to channel [{}]", Invitee.c_str(), m_name.c_str()); } } void ChatChannel::RemoveInvitee(std::string Invitee) { - auto it = std::find(std::begin(Invitees), std::end(Invitees), Invitee); + auto it = std::find(std::begin(m_invitees), std::end(m_invitees), Invitee); - if(it != std::end(Invitees)) { - Invitees.erase(it); - LogDebug("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str()); + if(it != std::end(m_invitees)) { + m_invitees.erase(it); + LogDebug("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), m_name.c_str()); } } bool ChatChannel::IsInvitee(std::string Invitee) { - return std::find(std::begin(Invitees), std::end(Invitees), Invitee) != std::end(Invitees); + return std::find(std::begin(m_invitees), std::end(m_invitees), Invitee) != std::end(m_invitees); } void ChatChannel::AddModerator(const std::string &Moderator) { if (!IsModerator(Moderator)) { - Moderators.push_back(Moderator); + m_moderators.push_back(Moderator); - LogInfo("Added [{}] as moderator to channel [{}]", Moderator.c_str(), Name.c_str()); + LogInfo("Added [{}] as moderator to channel [{}]", Moderator.c_str(), m_name.c_str()); } } void ChatChannel::RemoveModerator(const std::string &Moderator) { - auto it = std::find(std::begin(Moderators), std::end(Moderators), Moderator); + auto it = std::find(std::begin(m_moderators), std::end(m_moderators), Moderator); - if (it != std::end(Moderators)) { - Moderators.erase(it); - LogInfo("Removed [{}] as moderator to channel [{}]", Moderator.c_str(), Name.c_str()); + if (it != std::end(m_moderators)) { + m_moderators.erase(it); + LogInfo("Removed [{}] as moderator to channel [{}]", Moderator.c_str(), m_name.c_str()); } } bool ChatChannel::IsModerator(std::string Moderator) { - return std::find(std::begin(Moderators), std::end(Moderators), Moderator) != std::end(Moderators); + return std::find(std::begin(m_moderators), std::end(m_moderators), Moderator) != std::end(m_moderators); } void ChatChannel::AddVoice(const std::string &inVoiced) { if (!HasVoice(inVoiced)) { - Voiced.push_back(inVoiced); + m_voiced.push_back(inVoiced); - LogInfo("Added [{}] as voiced to channel [{}]", inVoiced.c_str(), Name.c_str()); + LogInfo("Added [{}] as voiced to channel [{}]", inVoiced.c_str(), m_name.c_str()); } } void ChatChannel::RemoveVoice(const std::string &inVoiced) { - auto it = std::find(std::begin(Voiced), std::end(Voiced), inVoiced); + auto it = std::find(std::begin(m_voiced), std::end(m_voiced), inVoiced); - if (it != std::end(Voiced)) { - Voiced.erase(it); + if (it != std::end(m_voiced)) { + m_voiced.erase(it); - LogInfo("Removed [{}] as voiced to channel [{}]", inVoiced.c_str(), Name.c_str()); + LogInfo("Removed [{}] as voiced to channel [{}]", inVoiced.c_str(), m_name.c_str()); } } bool ChatChannel::HasVoice(std::string inVoiced) { - return std::find(std::begin(Voiced), std::end(Voiced), inVoiced) != std::end(Voiced); + return std::find(std::begin(m_voiced), std::end(m_voiced), inVoiced) != std::end(m_voiced); } std::string CapitaliseName(std::string inString) { @@ -687,13 +797,61 @@ std::string CapitaliseName(std::string inString) { return NormalisedName; } +bool ChatChannelList::IsOnChannelBlockList(const std::string& channel_name) { + if (channel_name.empty()) { + return false; + } + + // Check if channel_name is already in the BlockedChannelNames vector + return Strings::Contains(GetBlockedChannelNames(), channel_name); +} + +bool ChatChannelList::IsOnFilteredNameList(const std::string& name) { + if (name.empty()) { + return false; + } + + // Check if name is already in the filtered name vector + return Strings::Contains(GetFilteredNames(), name); +} + + +void ChatChannelList::AddToChannelBlockList(const std::string& channel_name) { + if (channel_name.empty()) { + return; + } + + // Check if channelName is already in the BlockedChannelNames vector + bool is_found = Strings::Contains(ChatChannelList::GetBlockedChannelNames(), channel_name); + + // Add channelName to the BlockedChannelNames vector if it is not already present + if (!is_found) { + auto blocked_channel_names = GetBlockedChannelNames(); // Get current blocked list + blocked_channel_names.push_back(channel_name); // Add new name to local blocked list + SetChannelBlockList(blocked_channel_names); // Set blocked list to match local blocked list + } +} + +void ChatChannelList::AddToFilteredNames(const std::string& name) { + if (name.empty()) { + return; + } + + // Add name to the filtered names vector if it is not already present + if (!Strings::Contains(ChatChannelList::GetFilteredNames(), name)) { + auto filtered_names = GetFilteredNames(); // Get current filter name list + filtered_names.push_back(name); // Add new name to local filtered names list + SetFilteredNameList(filtered_names); // Set filtered names list to match local filtered names list + } +} + void ServerToClient45SayLink(std::string& clientSayLink, const std::string& serverSayLink) { if (serverSayLink.find('\x12') == std::string::npos) { clientSayLink = serverSayLink; return; } - auto segments = SplitString(serverSayLink, '\x12'); + auto segments = Strings::Split(serverSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -732,7 +890,7 @@ void ServerToClient50SayLink(std::string& clientSayLink, const std::string& serv return; } - auto segments = SplitString(serverSayLink, '\x12'); + auto segments = Strings::Split(serverSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -771,7 +929,7 @@ void ServerToClient55SayLink(std::string& clientSayLink, const std::string& serv return; } - auto segments = SplitString(serverSayLink, '\x12'); + auto segments = Strings::Split(serverSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/ucs/chatchannel.h b/ucs/chatchannel.h index 718ab8e4c..a5a7836fc 100644 --- a/ucs/chatchannel.h +++ b/ucs/chatchannel.h @@ -9,6 +9,8 @@ class Client; +#define SYSTEM_OWNER std::string("*System*") + class ChatChannel { public: @@ -21,15 +23,19 @@ public: bool IsClientInChannel(Client *c); int MemberCount(int Status); - const std::string &GetName() { return Name; } - void SendMessageToChannel(std::string Message, Client* Sender); - bool CheckPassword(std::string inPassword) { return Password.empty() || Password == inPassword; } - void SetPassword(std::string inPassword); - bool IsOwner(std::string Name) { return (Owner == Name); } - void SetOwner(std::string inOwner); + const std::string &GetName() { return m_name; } + void SendMessageToChannel(const std::string& Message, Client* Sender); + bool CheckPassword(const std::string& in_password) { return m_password.empty() || m_password == in_password; } + void SetPassword(const std::string& in_password); + bool IsOwner(const std::string& name) { return (m_owner == name); } + const std::string& GetPassword() { return m_password; } + void SetOwner(std::string& inOwner); + std::string& GetOwnerName(); + void SetTemporary(); + void SetPermanent(); void SendChannelMembers(Client *c); - int GetMinStatus() { return MinimumStatus; } - bool ReadyToDelete() { return DeleteTimer.Check(); } + int GetMinStatus() { return m_minimum_status; } + bool ReadyToDelete() { return m_delete_timer.Check(); } void SendOPList(Client *c); void AddInvitee(const std::string &Invitee); void RemoveInvitee(std::string Invitee); @@ -40,48 +46,58 @@ public: void AddVoice(const std::string &Voiced); void RemoveVoice(const std::string &Voiced); bool HasVoice(std::string Voiced); - inline bool IsModerated() { return Moderated; } + inline bool IsModerated() { return m_moderated; } void SetModerated(bool inModerated); friend class ChatChannelList; private: - std::string Name; - std::string Owner; - std::string Password; + std::string m_name; + std::string m_owner; + std::string m_password; - bool Permanent; - bool Moderated; + bool m_permanent; + bool m_moderated; - int MinimumStatus; + int m_minimum_status; - Timer DeleteTimer; + Timer m_delete_timer; - LinkedList ClientsInChannel; + LinkedList m_clients_in_channel; - std::vector Moderators; - std::vector Invitees; - std::vector Voiced; + std::vector m_moderators; + std::vector m_invitees; + std::vector m_voiced; }; class ChatChannelList { public: - ChatChannel* CreateChannel(std::string Name, std::string Owner, std::string Passwordi, bool Permanent, int MinimumStatus = 0); - ChatChannel* FindChannel(std::string Name); - ChatChannel* AddClientToChannel(std::string Channel, Client *c); - ChatChannel* RemoveClientFromChannel(std::string Channel, Client *c); - void RemoveClientFromAllChannels(Client *c); + ChatChannel* CreateChannel(const std::string& name, const std::string& owner, const std::string& password, bool permanent, int minimum_status, bool save_to_database = false); + ChatChannel* FindChannel(std::string name); + ChatChannel* AddClientToChannel(std::string channel_name, Client* c, bool command_directed = false); + ChatChannel* RemoveClientFromChannel(const std::string& in_channel_name, Client* c, bool command_directed = false); void RemoveChannel(ChatChannel *Channel); void RemoveAllChannels(); void SendAllChannels(Client *c); void Process(); - + static inline std::vector GetBlockedChannelNames() { return m_blocked_channel_names; } + static inline std::vector GetFilteredNames() { return m_filtered_names; } + static inline void ClearChannelBlockList() { m_blocked_channel_names.clear(); }; + static inline void ClearFilteredNameList() { m_filtered_names.clear(); }; + static void AddToChannelBlockList(const std::string& channel_name); + static void AddToFilteredNames(const std::string& name); + static bool IsOnChannelBlockList(const std::string& channel_name); + static bool IsOnFilteredNameList(const std::string& channel_name); + static inline void SetChannelBlockList(std::vector new_list) { m_blocked_channel_names = new_list; } + static inline void SetFilteredNameList(std::vector new_list) { m_filtered_names = new_list; } private: LinkedList ChatChannels; + static inline std::vector m_blocked_channel_names; + static inline std::vector m_filtered_names; }; diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index 18f18a276..dd4220bd7 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "../common/global_define.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/eqemu_logsys.h" #include "../common/misc_functions.h" @@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "clientlist.h" #include "database.h" #include "chatchannel.h" +#include "../common/path_manager.h" #include #include @@ -33,7 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include -extern Database database; +extern UCSDatabase database; extern std::string WorldShortName; extern std::string GetMailPrefix(); extern ChatChannelList *ChannelList; @@ -47,8 +48,10 @@ int LookupCommand(const char *ChatCommand) { for (int i = 0; i < CommandEndOfList; i++) { - if (!strcasecmp(Commands[i].CommandString, ChatCommand)) + if (!strcasecmp(Commands[i].CommandString, ChatCommand)) { return Commands[i].CommandCode; + } + } return -1; @@ -478,12 +481,15 @@ Clientlist::Clientlist(int ChatPort) { const ucsconfig *Config = ucsconfig::get(); - LogInfo("Loading [{}]", Config->MailOpCodesFile.c_str()); - if (!ChatOpMgr->LoadOpcodes(Config->MailOpCodesFile.c_str())) + + std::string opcodes_file = fmt::format("{}/{}", path.GetServerPath(), Config->MailOpCodesFile); + + LogInfo("Loading [{}]", opcodes_file); + if (!ChatOpMgr->LoadOpcodes(opcodes_file.c_str())) exit(1); chatsf->OnNewConnection([this](std::shared_ptr stream) { - LogF(Logs::General, Logs::Loginserver, "New Client UDP connection from {0}:{1}", stream->GetRemoteIP(), stream->GetRemotePort()); + LogInfo("New Client UDP connection from [{0}] [{1}]", stream->GetRemoteIP(), stream->GetRemotePort()); stream->SetOpcodeManager(&ChatOpMgr); auto c = new Client(stream); @@ -590,6 +596,28 @@ void Clientlist::CheckForStaleConnections(Client *c) { } } +std::string RemoveDuplicateChannels(const std::string& in_channels) { + // Split the string by ", " and store the names in a vector + std::vector channel_names = Strings::Split(in_channels, ", "); + + // Remove duplicates by inserting the names of the channels into an unordered set + // and then copying the unique elements back into the original vector + std::unordered_set unique_channels; + channel_names.erase( + std::remove_if( + channel_names.begin(), channel_names.end(), + [&unique_channels](const std::string &channel) { + return !unique_channels.insert(channel).second; + } + ), channel_names.end() + ); + + // Concatenate the names of the unique channels into a single string + std::string unique_channels_string = Strings::Implode(", ", channel_names); + + return unique_channels_string; +} + void Clientlist::Process() { auto it = ClientChatConnections.begin(); @@ -615,6 +643,14 @@ void Clientlist::Process() while (KeyValid && !(*it)->GetForceDisconnect() && (app = (*it)->ClientStream->PopPacket())) { EmuOpcode opcode = app->GetOpcode(); + LogPacketClientServer( + "[{}] [{:#06x}] Size [{}] {}", + OpcodeManager::EmuToName(app->GetOpcode()), + (*it)->ClientStream->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + app->Size(), + (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") + ); + switch (opcode) { case OP_MailLogin: { char *PacketBuffer = (char *)app->pBuffer + 1; @@ -670,10 +706,18 @@ void Clientlist::Process() CheckForStaleConnections((*it)); break; } - case OP_Mail: { - std::string CommandString = (const char *)app->pBuffer + 1; - ProcessOPMailCommand((*it), CommandString); + std::string command_string = (const char *)app->pBuffer + 1; + bool command_directed = false; + if (command_string.empty()) { + break; + } + + if (Strings::Contains(Strings::ToLower(command_string), "leave")) { + command_directed = true; + } + + ProcessOPMailCommand((*it), command_string, command_directed); break; } @@ -704,106 +748,112 @@ void Clientlist::Process() } } -void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString) +void Clientlist::ProcessOPMailCommand(Client *c, std::string command_string, bool command_directed) { - if (CommandString.length() == 0) + if (command_string.length() == 0) return; - if (isdigit(CommandString[0])) + if (isdigit(command_string[0])) { - c->SendChannelMessageByNumber(CommandString); + c->SendChannelMessageByNumber(command_string); return; } - if (CommandString[0] == '#') { + if (command_string[0] == '#') { - c->SendChannelMessage(CommandString); + c->SendChannelMessage(command_string); return; } - std::string Command, Parameters; + std::string command, parameters; - std::string::size_type Space = CommandString.find_first_of(" "); + std::string::size_type Space = command_string.find_first_of(" "); if (Space != std::string::npos) { - Command = CommandString.substr(0, Space); + command = command_string.substr(0, Space); - std::string::size_type ParametersStart = CommandString.find_first_not_of(" ", Space); + std::string::size_type parameters_start = command_string.find_first_not_of(" ", Space); - if (ParametersStart != std::string::npos) - Parameters = CommandString.substr(ParametersStart); + if (parameters_start != std::string::npos) + parameters = command_string.substr(parameters_start); + } + else { + command = command_string; } - else - Command = CommandString; - int CommandCode = LookupCommand(Command.c_str()); - - switch (CommandCode) { + auto command_code = LookupCommand(command.c_str()); + switch (command_code) { case CommandJoin: - c->JoinChannels(Parameters); + if (!command_directed) { + //Append saved channels to params + parameters = parameters + ", " + database.CurrentPlayerChannels(c->GetName()); + parameters = RemoveDuplicateChannels(parameters); + } + c->JoinChannels(parameters, command_directed); break; case CommandLeaveAll: - c->LeaveAllChannels(); + c->LeaveAllChannels(true, true); break; case CommandLeave: - c->LeaveChannels(Parameters); + c->LeaveChannels(parameters, command_directed); break; case CommandListAll: + ChannelList->SendAllChannels(c); break; case CommandList: - c->ProcessChannelList(Parameters); + c->ProcessChannelList(parameters); break; case CommandSet: c->LeaveAllChannels(false); - c->JoinChannels(Parameters); + c->JoinChannels(parameters, command_directed); break; case CommandAnnounce: - c->ToggleAnnounce(Parameters); + c->ToggleAnnounce(parameters); break; case CommandSetOwner: - c->SetChannelOwner(Parameters); + c->SetChannelOwner(parameters); break; case CommandOPList: - c->OPList(Parameters); + c->OPList(parameters); break; case CommandInvite: - c->ChannelInvite(Parameters); + c->ChannelInvite(parameters); break; case CommandGrant: - c->ChannelGrantModerator(Parameters); + c->ChannelGrantModerator(parameters); break; case CommandModerate: - c->ChannelModerate(Parameters); + c->ChannelModerate(parameters); break; case CommandVoice: - c->ChannelGrantVoice(Parameters); + c->ChannelGrantVoice(parameters); break; case CommandKick: - c->ChannelKick(Parameters); + c->ChannelKick(parameters); break; case CommandPassword: - c->SetChannelPassword(Parameters); + c->SetChannelPassword(parameters); break; case CommandToggleInvites: @@ -822,43 +872,44 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString) break; case CommandGetBody: - database.SendBody(c, atoi(Parameters.c_str())); + database.SendBody(c, atoi(parameters.c_str())); break; case CommandMailTo: - ProcessMailTo(c, Parameters); + ProcessMailTo(c, parameters); break; case CommandSetMessageStatus: - LogInfo("Set Message Status, Params: [{}]", Parameters.c_str()); - ProcessSetMessageStatus(Parameters); + LogInfo("Set Message Status, Params: [{}]", parameters.c_str()); + ProcessSetMessageStatus(parameters); break; case CommandSelectMailBox: { - std::string::size_type NumStart = Parameters.find_first_of("0123456789"); - c->ChangeMailBox(atoi(Parameters.substr(NumStart).c_str())); + std::string::size_type NumStart = parameters.find_first_of("0123456789"); + c->ChangeMailBox(atoi(parameters.substr(NumStart).c_str())); break; } case CommandSetMailForwarding: break; case CommandBuddy: - RemoveApostrophes(Parameters); - ProcessCommandBuddy(c, Parameters); + RemoveApostrophes(parameters); + ProcessCommandBuddy(c, parameters); break; case CommandIgnorePlayer: - RemoveApostrophes(Parameters); - ProcessCommandIgnore(c, Parameters); + RemoveApostrophes(parameters); + ProcessCommandIgnore(c, parameters); break; default: c->SendHelp(); - LogInfo("Unhandled OP_Mail command: [{}]", CommandString.c_str()); + LogInfo("Unhandled OP_Mail command: [{}]", command_string.c_str()); } } + void Clientlist::CloseAllConnections() { @@ -887,7 +938,8 @@ void Client::AddCharacter(int CharID, const char *CharacterName, int Level) { } void Client::SendKeepAlive() { - QueuePacket(new EQApplicationPacket(OP_SessionReady, 0)); + EQApplicationPacket outapp(OP_SessionReady, 0); + QueuePacket(&outapp); } void Client::SendMailBoxes() { @@ -979,51 +1031,51 @@ int Client::ChannelCount() { } -void Client::JoinChannels(std::string ChannelNameList) { +void Client::JoinChannels(std::string& channel_name_list, bool command_directed) { - for (auto &elem : ChannelNameList) { + for (auto &elem : channel_name_list) { if (elem == '%') { elem = '/'; } } - LogInfo("Client: [{}] joining channels [{}]", GetName().c_str(), ChannelNameList.c_str()); + LogInfo("Client: [{}] joining channels [{}]", GetName().c_str(), channel_name_list.c_str()); - int NumberOfChannels = ChannelCount(); + auto number_of_channels = ChannelCount(); - std::string::size_type CurrentPos = ChannelNameList.find_first_not_of(" "); + auto current_pos = channel_name_list.find_first_not_of(" "); - while (CurrentPos != std::string::npos) { + while (current_pos != std::string::npos) { - if (NumberOfChannels == MAX_JOINED_CHANNELS) { + if (number_of_channels == MAX_JOINED_CHANNELS) { GeneralChannelMessage("You have joined the maximum number of channels. /leave one before trying to join another."); break; } - std::string::size_type Comma = ChannelNameList.find_first_of(", ", CurrentPos); + auto comma = channel_name_list.find_first_of(", ", current_pos); - if (Comma == std::string::npos) { + if (comma == std::string::npos) { + auto* joined_channel = ChannelList->AddClientToChannel(channel_name_list.substr(current_pos), this, command_directed); - ChatChannel* JoinedChannel = ChannelList->AddClientToChannel(ChannelNameList.substr(CurrentPos), this); - - if (JoinedChannel) - AddToChannelList(JoinedChannel); + if (joined_channel) { + AddToChannelList(joined_channel); + } break; } - ChatChannel* JoinedChannel = ChannelList->AddClientToChannel(ChannelNameList.substr(CurrentPos, Comma - CurrentPos), this); + auto* joined_channel = ChannelList->AddClientToChannel(channel_name_list.substr(current_pos, comma - current_pos), this, command_directed); - if (JoinedChannel) { + if (joined_channel) { - AddToChannelList(JoinedChannel); + AddToChannelList(joined_channel); - NumberOfChannels++; + number_of_channels++; } - CurrentPos = ChannelNameList.find_first_not_of(", ", Comma); + current_pos = channel_name_list.find_first_not_of(", ", comma); } std::string JoinedChannelsList, ChannelMessage; @@ -1084,37 +1136,36 @@ void Client::JoinChannels(std::string ChannelNameList) { safe_delete(outapp); } -void Client::LeaveChannels(std::string ChannelNameList) { +void Client::LeaveChannels(std::string& channel_name_list, bool command_directed) { + LogInfo("Client: [{}] leaving channels [{}]", GetName().c_str(), channel_name_list.c_str()); - LogInfo("Client: [{}] leaving channels [{}]", GetName().c_str(), ChannelNameList.c_str()); + auto current_pos = 0; - std::string::size_type CurrentPos = 0; + while (current_pos != std::string::npos) { - while (CurrentPos != std::string::npos) { - - std::string::size_type Comma = ChannelNameList.find_first_of(", ", CurrentPos); + std::string::size_type Comma = channel_name_list.find_first_of(", ", current_pos); if (Comma == std::string::npos) { - ChatChannel* JoinedChannel = ChannelList->RemoveClientFromChannel(ChannelNameList.substr(CurrentPos), this); + auto* joined_channel = ChannelList->RemoveClientFromChannel(channel_name_list.substr(current_pos), this, command_directed); - if (JoinedChannel) - RemoveFromChannelList(JoinedChannel); + if (joined_channel) + RemoveFromChannelList(joined_channel); break; } - ChatChannel* JoinedChannel = ChannelList->RemoveClientFromChannel(ChannelNameList.substr(CurrentPos, Comma - CurrentPos), this); + auto* joined_channel = ChannelList->RemoveClientFromChannel(channel_name_list.substr(current_pos, Comma - current_pos), this, command_directed); - if (JoinedChannel) - RemoveFromChannelList(JoinedChannel); + if (joined_channel) + RemoveFromChannelList(joined_channel); - CurrentPos = ChannelNameList.find_first_not_of(", ", Comma); + current_pos = channel_name_list.find_first_not_of(", ", Comma); } - std::string JoinedChannelsList, ChannelMessage; + std::string joined_channels_list, channel_message; - ChannelMessage = "Channels: "; + channel_message = "Channels: "; char tmp[200]; @@ -1126,26 +1177,26 @@ void Client::LeaveChannels(std::string ChannelNameList) { if (ChannelCount) { - JoinedChannelsList = JoinedChannelsList + ","; + joined_channels_list = joined_channels_list + ","; - ChannelMessage = ChannelMessage + ","; + channel_message = channel_message + ","; } - JoinedChannelsList = JoinedChannelsList + JoinedChannels[i]->GetName(); + joined_channels_list = joined_channels_list + JoinedChannels[i]->GetName(); sprintf(tmp, "%i=%s(%i)", i + 1, JoinedChannels[i]->GetName().c_str(), JoinedChannels[i]->MemberCount(Status)); - ChannelMessage += tmp; + channel_message += tmp; ChannelCount++; } } - auto outapp = new EQApplicationPacket(OP_Mail, JoinedChannelsList.length() + 1); + auto outapp = new EQApplicationPacket(OP_Mail, joined_channels_list.length() + 1); char *PacketBuffer = (char *)outapp->pBuffer; - sprintf(PacketBuffer, "%s", JoinedChannelsList.c_str()); + sprintf(PacketBuffer, "%s", joined_channels_list.c_str()); QueuePacket(outapp); @@ -1153,15 +1204,15 @@ void Client::LeaveChannels(std::string ChannelNameList) { safe_delete(outapp); if (ChannelCount == 0) - ChannelMessage = "You are not on any channels."; + channel_message = "You are not on any channels."; - outapp = new EQApplicationPacket(OP_ChannelMessage, ChannelMessage.length() + 3); + outapp = new EQApplicationPacket(OP_ChannelMessage, channel_message.length() + 3); PacketBuffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x00); VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x00); - VARSTRUCT_ENCODE_STRING(PacketBuffer, ChannelMessage.c_str()); + VARSTRUCT_ENCODE_STRING(PacketBuffer, channel_message.c_str()); QueuePacket(outapp); @@ -1169,19 +1220,19 @@ void Client::LeaveChannels(std::string ChannelNameList) { safe_delete(outapp); } -void Client::LeaveAllChannels(bool SendUpdatedChannelList) { +void Client::LeaveAllChannels(bool send_updated_channel_list, bool command_directed) { for (auto &elem : JoinedChannels) { if (elem) { - ChannelList->RemoveClientFromChannel(elem->GetName(), this); + ChannelList->RemoveClientFromChannel(elem->GetName(), this, command_directed); elem = nullptr; } } - if (SendUpdatedChannelList) + if (send_updated_channel_list) SendChannelList(); } @@ -1630,6 +1681,7 @@ void Client::SetChannelPassword(std::string ChannelPassword) { } RequiredChannel->SetPassword(Password); + database.SaveChatChannel(RequiredChannel->GetName(), RequiredChannel->GetOwnerName(), Password, RequiredChannel->GetMinStatus()); // Update DB with new password GeneralChannelMessage(Message); @@ -1690,6 +1742,7 @@ void Client::SetChannelOwner(std::string CommandString) { } RequiredChannel->SetOwner(NewOwner); + database.SaveChatChannel(RequiredChannel->GetName(), NewOwner, RequiredChannel->GetPassword(), RequiredChannel->GetMinStatus()); // Update DB with new owner if (RequiredChannel->IsModerator(NewOwner)) RequiredChannel->RemoveModerator(NewOwner); @@ -2108,7 +2161,7 @@ void Client::ChannelKick(std::string CommandString) { GeneralChannelMessage("Kicked " + Kickee + " from channel " + ChannelName); - RequiredClient->LeaveChannels(ChannelName); + RequiredClient->LeaveChannels(ChannelName, false); } void Client::ToggleInvites() { diff --git a/ucs/clientlist.h b/ucs/clientlist.h index 13d31784c..ac511176c 100644 --- a/ucs/clientlist.h +++ b/ucs/clientlist.h @@ -92,9 +92,9 @@ public: void SendMailBoxes(); inline void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) { ClientStream->QueuePacket(p, ack_req); } std::string GetName() { if(Characters.size()) return Characters[0].Name; else return ""; } - void JoinChannels(std::string ChannelList); - void LeaveChannels(std::string ChannelList); - void LeaveAllChannels(bool SendUpdatedChannelList = true); + void JoinChannels(std::string& channel_name_list, bool command_directed = false); + void LeaveChannels(std::string& channel_name_list, bool command_directed = false); + void LeaveAllChannels(bool send_updated_channel_list = true, bool command_directed = false); void AddToChannelList(ChatChannel *JoinedChannel); void RemoveFromChannelList(ChatChannel *JoinedChannel); void SendChannelMessage(std::string Message); @@ -112,6 +112,7 @@ public: void ProcessChannelList(std::string CommandString); void AccountUpdate(); int ChannelCount(); + std::string RemoveDuplicateChannels(std::string& in_channels); inline void SetAccountID(int inAccountID) { AccountID = inAccountID; } inline int GetAccountID() { return AccountID; } inline void SetAccountStatus(int inStatus) { Status = inStatus; } @@ -187,7 +188,7 @@ public: void CheckForStaleConnectionsAll(); void CheckForStaleConnections(Client *c); Client *IsCharacterOnline(std::string CharacterName); - void ProcessOPMailCommand(Client *c, std::string CommandString); + void ProcessOPMailCommand(Client* c, std::string command_string, bool command_directed = false); private: EQ::Net::EQStreamManager *chatsf; diff --git a/ucs/database.cpp b/ucs/database.cpp index d3e01b54d..4c4e6dfbe 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -47,64 +47,18 @@ #include "database.h" #include "../common/eq_packet_structs.h" #include "../common/misc_functions.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "chatchannel.h" +#include "../common/repositories/chatchannel_reserved_names_repository.h" +#include "../common/repositories/chatchannels_repository.h" +#include "../common/repositories/name_filter_repository.h" extern Clientlist *g_Clientlist; extern std::string GetMailPrefix(); extern ChatChannelList *ChannelList; extern uint32 MailMessagesSent; -Database::Database() -{ - DBInitVars(); -} - -/* -Establish a connection to a mysql database with the supplied parameters -*/ - -Database::Database(const char *host, const char *user, const char *passwd, const char *database, uint32 port) -{ - DBInitVars(); - Connect(host, user, passwd, database, port); -} - -bool Database::Connect(const char *host, const char *user, const char *passwd, const char *database, uint32 port) -{ - uint32 errnum = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { - LogError("Failed to connect to database: Error: {}", errbuf); - HandleMysqlError(errnum); - - return false; - } - else { - LogInfo("Using database [{}] at [{}]:[{}]", database, host, port); - return true; - } -} - -void Database::DBInitVars() -{ - -} - - -void Database::HandleMysqlError(uint32 errnum) -{ -} - -/* - -Close the connection to the database -*/ -Database::~Database() -{ -} - -void Database::GetAccountStatus(Client *client) +void UCSDatabase::GetAccountStatus(Client *client) { std::string query = StringFormat( @@ -144,7 +98,7 @@ void Database::GetAccountStatus(Client *client) ); } -int Database::FindAccount(const char *characterName, Client *client) +int UCSDatabase::FindAccount(const char *characterName, Client *client) { LogInfo("FindAccount for character [{}]", characterName); @@ -188,7 +142,7 @@ int Database::FindAccount(const char *characterName, Client *client) return accountID; } -bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::string MailKey) +bool UCSDatabase::VerifyMailKey(std::string characterName, int IPAddress, std::string MailKey) { std::string query = StringFormat( @@ -221,7 +175,7 @@ bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::stri return !strcmp(row[0], combinedKey); } -int Database::FindCharacter(const char *characterName) +int UCSDatabase::FindCharacter(const char *characterName) { char *safeCharName = RemoveApostrophes(characterName); std::string query = StringFormat( @@ -248,7 +202,7 @@ int Database::FindCharacter(const char *characterName) return characterID; } -bool Database::GetVariable(const char *varname, char *varvalue, uint16 varvalue_len) +bool UCSDatabase::GetVariable(const char *varname, char *varvalue, uint16 varvalue_len) { std::string query = StringFormat("SELECT `value` FROM `variables` WHERE `varname` = '%s'", varname); @@ -268,52 +222,176 @@ bool Database::GetVariable(const char *varname, char *varvalue, uint16 varvalue_ return true; } -bool Database::LoadChatChannels() -{ +bool UCSDatabase::LoadChatChannels() +{ + LoadFilteredNamesFromDB(); + LoadReservedNamesFromDB(); LogInfo("Loading chat channels from the database"); const std::string query = "SELECT `name`, `owner`, `password`, `minstatus` FROM `chatchannels`"; - auto results = QueryDatabase(query); + auto results = QueryDatabase(query); if (!results.Success()) { return false; } for (auto row = results.begin(); row != results.end(); ++row) { - std::string channelName = row[0]; - std::string channelOwner = row[1]; - std::string channelPassword = row[2]; + std::string channel_name = row[0]; + std::string channel_owner = row[1]; + std::string channel_password = row[2]; + auto channel_min_status = row[3]; - ChannelList->CreateChannel(channelName, channelOwner, channelPassword, true, atoi(row[3])); + if (!ChannelList->FindChannel(channel_name)) { + ChannelList->CreateChannel(channel_name, channel_owner, channel_password, true, atoi(channel_min_status), false); + } } - return true; } -void Database::SetChannelPassword(std::string channelName, std::string password) +void UCSDatabase::LoadReservedNamesFromDB() { - LogInfo("Database::SetChannelPassword([{}], [{}])", channelName.c_str(), password.c_str()); + ChatChannelList::ClearChannelBlockList(); - std::string query = StringFormat( - "UPDATE `chatchannels` SET `password` = '%s' WHERE `name` = '%s'", - password.c_str(), channelName.c_str()); + auto channels = ChatchannelReservedNamesRepository::All(*this); + if (channels.empty()) { + LogDebug("No reserved names exist in the database..."); + } + + for (auto &e: channels) { + ChatChannelList::AddToChannelBlockList(e.name); + LogInfo("Adding channel [{}] to blocked list from database...", e.name); + } + + LogInfo("Loaded [{}] reserved channel name(s)", channels.size()); +} + +void UCSDatabase::LoadFilteredNamesFromDB() +{ + ChatChannelList::ClearFilteredNameList(); + + auto names = NameFilterRepository::All(*this); + if (names.empty()) { + LogDebug("No filtered names exist in the database..."); + } + + for (const auto& e : names) { + ChatChannelList::AddToFilteredNames(e.name); + } + + LogInfo("Loaded [{}] filtered channel name(s)", names.size()); +} + +bool UCSDatabase::IsChatChannelInDB(const std::string& channel_name) +{ + auto r = ChatchannelsRepository::Count( + *this, + fmt::format( + "name = {}", Strings::Escape(channel_name) + ) + ); + + return r > 0; +} + +void UCSDatabase::SaveChatChannel( + const std::string& channel_name, + const std::string& channel_owner, + const std::string& channel_password, + const uint16& min_status +) +{ + auto e = ChatchannelsRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}' LIMIT 1", Strings::Escape(channel_name) + ) + ); + + // If channel name is blocked, do not save it to the database + if (ChatChannelList::IsOnChannelBlockList(channel_name)) { + LogInfo("Channel [{}] already found on the block list, ignoring", channel_name); + return; + } + + // update if exists, create new if it doesn't + auto c = !e.empty() ? e[0] : ChatchannelsRepository::NewEntity(); + c.name = channel_name; + c.owner = channel_owner; + c.password = channel_password; + c.minstatus = min_status; + + if (e.empty()) { + ChatchannelsRepository::InsertOne(*this, c); + return; + } + + ChatchannelsRepository::UpdateOne(*this, c); +} + +void UCSDatabase::DeleteChatChannel(const std::string& channel_name) +{ + ChatchannelsRepository::DeleteWhere(*this, fmt::format("`name` = '{}'", Strings::Escape(channel_name))); + LogInfo("Deleting channel [{}] from the database.", channel_name); +} + +std::string UCSDatabase::CurrentPlayerChannels(const std::string& player_name) { + int current_player_channel_count = CurrentPlayerChannelCount(player_name); + if (current_player_channel_count == 0) { + return ""; + } + const auto rquery = fmt::format("SELECT GROUP_CONCAT(`name` SEPARATOR ', ') FROM chatchannels WHERE `owner` = '{}'; ", Strings::Escape(player_name)); + auto results = QueryDatabase(rquery); + auto row = results.begin(); + std::string channels = row[0]; + LogDebug("Player [{}] has the following permanent channels saved to the database: [{}].", player_name, channels); + return channels; +} + +int UCSDatabase::CurrentPlayerChannelCount(const std::string& player_name) +{ + return (int) ChatchannelsRepository::Count(*this, fmt::format("`owner` = '{}'", Strings::Escape(player_name))); +} + +void UCSDatabase::SetChannelPassword(const std::string& channel_name, const std::string& password) +{ + LogInfo("UCSDatabase::SetChannelPassword([{}], [{}])", channel_name.c_str(), password.c_str()); + + std::string query = fmt::format( + "UPDATE `chatchannels` SET `password` = '{}' WHERE `name` = '{}'", + Strings::Escape(password), Strings::Escape(channel_name)); QueryDatabase(query); } -void Database::SetChannelOwner(std::string channelName, std::string owner) +void UCSDatabase::SetChannelOwner(const std::string& channel_name, const std::string& owner) { - LogInfo("Database::SetChannelOwner([{}], [{}])", channelName.c_str(), owner.c_str()); + LogInfo("Setting channel [{}] owner to [{}]", channel_name, owner); - std::string query = StringFormat( - "UPDATE `chatchannels` SET `owner` = '%s' WHERE `name` = '%s'", - owner.c_str(), - channelName.c_str() + std::string query = fmt::format( + "UPDATE `chatchannels` SET `owner` = '{}' WHERE `name` = '{}'", + Strings::Escape(owner), + Strings::Escape(channel_name) ); QueryDatabase(query); } -void Database::SendHeaders(Client *client) +bool UCSDatabase::CheckChannelNameFilter(const std::string& channel_name) +{ + LogDebug("Checking if [{}] is on the name filter", channel_name); + + for (const auto &e: ChatChannelList::GetFilteredNames()) { + if (Strings::Contains(Strings::ToLower(channel_name), Strings::ToLower(e))) { + LogInfo("Failed to pass name filter check for [{}] against word [{}]", channel_name, e); + return false; + } + } + + LogDebug("Name Filter Check Passed!"); + + return true; +} + +void UCSDatabase::SendHeaders(Client *client) { int unknownField2 = 25015275; @@ -405,7 +483,7 @@ void Database::SendHeaders(Client *client) } -void Database::SendBody(Client *client, int messageNumber) +void UCSDatabase::SendBody(Client *client, const int& messageNumber) { int characterID = FindCharacter(client->MailBoxName().c_str()); @@ -460,12 +538,12 @@ void Database::SendBody(Client *client, int messageNumber) safe_delete(outapp); } -bool Database::SendMail( - std::string recipient, - std::string from, - std::string subject, - std::string body, - std::string recipientsString +bool UCSDatabase::SendMail( + const std::string& recipient, + const std::string& from, + const std::string& subject, + const std::string& body, + const std::string& recipientsString ) { @@ -533,7 +611,7 @@ bool Database::SendMail( return true; } -void Database::SetMessageStatus(int messageNumber, int status) +void UCSDatabase::SetMessageStatus(const int& messageNumber, const int& status) { LogInfo("SetMessageStatus [{}] [{}]", messageNumber, status); @@ -548,7 +626,7 @@ void Database::SetMessageStatus(int messageNumber, int status) QueryDatabase(query); } -void Database::ExpireMail() +void UCSDatabase::ExpireMail() { LogInfo("Expiring mail"); @@ -606,7 +684,7 @@ void Database::ExpireMail() } } -void Database::AddFriendOrIgnore(int charID, int type, std::string name) +void UCSDatabase::AddFriendOrIgnore(const int& charID, const int& type, const std::string& name) { std::string query = StringFormat( "INSERT INTO `friends` (`charid`, `type`, `name`) " @@ -628,7 +706,7 @@ void Database::AddFriendOrIgnore(int charID, int type, std::string name) } } -void Database::RemoveFriendOrIgnore(int charID, int type, std::string name) +void UCSDatabase::RemoveFriendOrIgnore(const int& charID, const int& type, const std::string& name) { std::string query = StringFormat( "DELETE FROM `friends` WHERE `charid` = %i AND `type` = %i AND `name` = '%s'", @@ -649,7 +727,7 @@ void Database::RemoveFriendOrIgnore(int charID, int type, std::string name) } } -void Database::GetFriendsAndIgnore(int charID, std::vector &friends, std::vector &ignorees) +void UCSDatabase::GetFriendsAndIgnore(const int& charID, std::vector &friends, std::vector &ignorees) { std::string query = StringFormat("select `type`, `name` FROM `friends` WHERE `charid`=%i", charID); diff --git a/ucs/database.h b/ucs/database.h index fc9b96d19..26eead391 100644 --- a/ucs/database.h +++ b/ucs/database.h @@ -7,7 +7,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; + are required to give you total support for your newly bought product without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -25,9 +25,11 @@ #include "../common/global_define.h" #include "../common/types.h" -#include "../common/dbcore.h" +#include "../common/database.h" #include "../common/linked_list.h" +#include "../common/database.h" #include "clientlist.h" +#include "chatchannel.h" #include #include #include @@ -35,30 +37,32 @@ //atoi is not uint32 or uint32 safe!!!! #define atoul(str) strtoul(str, nullptr, 10) -class Database : public DBcore { +class UCSDatabase : public Database { public: - Database(); - Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); - bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port); - ~Database(); - int FindAccount(const char *CharacterName, Client *c); int FindCharacter(const char *CharacterName); bool VerifyMailKey(std::string CharacterName, int IPAddress, std::string MailKey); bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len); bool LoadChatChannels(); + void LoadReservedNamesFromDB(); + void LoadFilteredNamesFromDB(); + bool IsChatChannelInDB(const std::string& channel_name); + bool CheckChannelNameFilter(const std::string& channel_name); + void SaveChatChannel(const std::string& channel_name, const std::string& channel_owner, const std::string& channel_password, const uint16& min_status); + void DeleteChatChannel(const std::string& channel_name); + int CurrentPlayerChannelCount(const std::string& player_name); + std::string CurrentPlayerChannels(const std::string& player_name); void GetAccountStatus(Client *c); - void SetChannelPassword(std::string ChannelName, std::string Password); - void SetChannelOwner(std::string ChannelName, std::string Owner); + void SetChannelPassword(const std::string& channel_name, const std::string& password); + void SetChannelOwner(const std::string& channel_name, const std::string& owner); void SendHeaders(Client *c); - void SendBody(Client *c, int MessageNumber); - bool SendMail(std::string Recipient, std::string From, std::string Subject, std::string Body, std::string RecipientsString); - void SetMessageStatus(int MessageNumber, int Status); + void SendBody(Client *c, const int& message_number); + bool SendMail(const std::string& recipient, const std::string& from, const std::string& subject, const std::string& body, const std::string& recipients_string); + void SetMessageStatus(const int& message_number, const int& Status); void ExpireMail(); - void AddFriendOrIgnore(int CharID, int Type, std::string Name); - void RemoveFriendOrIgnore(int CharID, int Type, std::string Name); - void GetFriendsAndIgnore(int CharID, std::vector &Friends, std::vector &Ignorees); - + void AddFriendOrIgnore(const int& char_id, const int& type, const std::string& name); + void RemoveFriendOrIgnore(const int& char_id, const int& type, const std::string& name); + void GetFriendsAndIgnore(const int& char_id, std::vector &Friends, std::vector &Ignorees); protected: void HandleMysqlError(uint32 errnum); diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index 1e365f41e..78dabcc08 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -37,12 +37,18 @@ #include "../common/net/tcp_server.h" #include "../common/net/servertalk_client_connection.h" +#include "../common/discord_manager.h" +#include "../common/path_manager.h" +#include "../common/zone_store.h" ChatChannelList *ChannelList; Clientlist *g_Clientlist; EQEmuLogSys LogSys; -Database database; +UCSDatabase database; WorldServer *worldserver = nullptr; +DiscordManager discord_manager; +PathManager path; +ZoneStore zone_store; const ucsconfig *Config; @@ -87,12 +93,20 @@ void CatchSignal(int sig_num) { } } +void DiscordQueueListener() { + while (caught_loop == 0) { + discord_manager.ProcessMessageQueue(); + Sleep(100); + } +} int main() { RegisterExecutablePlatform(ExePlatformUCS); LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + // Check every minute for unused channels we can delete // Timer ChannelListProcessTimer(60000); @@ -124,6 +138,7 @@ int main() { } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); @@ -138,13 +153,10 @@ int main() { } else { if(!RuleManager::Instance()->LoadRules(&database, "default", false)) { LogInfo("No rule set configured, using default rules"); - } else { - LogInfo("Loaded default rule set 'default'", tmp); } } EQ::InitializeDynamicLookups(); - LogInfo("Initialized dynamic dictionary entries"); database.ExpireMail(); @@ -165,6 +177,8 @@ int main() { std::signal(SIGKILL, CatchSignal); std::signal(SIGSEGV, CatchSignal); + std::thread(DiscordQueueListener).detach(); + worldserver = new WorldServer; // uncomment to simulate timed crash for catching SIGSEV diff --git a/ucs/ucsconfig.h b/ucs/ucsconfig.h index 5424dfeb5..887ff821b 100644 --- a/ucs/ucsconfig.h +++ b/ucs/ucsconfig.h @@ -40,13 +40,13 @@ public: } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_chat_config != nullptr) delete _chat_config; _chat_config=new ucsconfig; _config=_chat_config; - return _config->parseFile(); + return _config->parseFile(path); } }; diff --git a/ucs/worldserver.cpp b/ucs/worldserver.cpp index 64bdfc2a7..f7522040c 100644 --- a/ucs/worldserver.cpp +++ b/ucs/worldserver.cpp @@ -21,11 +21,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/misc_functions.h" #include "../common/packet_functions.h" #include "../common/md5.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "worldserver.h" #include "clientlist.h" #include "ucsconfig.h" #include "database.h" +#include "../common/discord_manager.h" #include #include @@ -35,10 +36,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include -extern WorldServer worldserver; -extern Clientlist *g_Clientlist; +extern WorldServer worldserver; +extern Clientlist *g_Clientlist; extern const ucsconfig *Config; -extern Database database; +extern UCSDatabase database; +extern DiscordManager discord_manager; void ProcessMailTo(Client *c, std::string from, std::string subject, std::string message); @@ -72,6 +74,20 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p) { break; } + case ServerOP_ReloadLogs: { + LogSys.LoadLogDatabaseSettings(); + break; + } + case ServerOP_DiscordWebhookMessage: { + auto *q = (DiscordWebhookMessage_Struct *) p.Data(); + + discord_manager.QueueWebhookMessage( + q->webhook_id, + q->message + ); + + break; + } case ServerOP_UCSMessage: { char *Buffer = (char *)pack->pBuffer; @@ -122,7 +138,7 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p) } else if (Message[0] == '[') { - g_Clientlist->ProcessOPMailCommand(c, Message.substr(1, std::string::npos)); + g_Clientlist->ProcessOPMailCommand(c, Message.substr(1, std::string::npos), true); // Flag as command_directed } break; @@ -147,7 +163,7 @@ void Client45ToServerSayLink(std::string& serverSayLink, const std::string& clie return; } - auto segments = SplitString(clientSayLink, '\x12'); + auto segments = Strings::Split(clientSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -184,7 +200,7 @@ void Client50ToServerSayLink(std::string& serverSayLink, const std::string& clie return; } - auto segments = SplitString(clientSayLink, '\x12'); + auto segments = Strings::Split(clientSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { @@ -219,7 +235,7 @@ void Client55ToServerSayLink(std::string& serverSayLink, const std::string& clie return; } - auto segments = SplitString(clientSayLink, '\x12'); + auto segments = Strings::Split(clientSayLink, '\x12'); for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index 6a031ec86..885822868 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -8,40 +8,6 @@ * ]] -MonkACBonusWeight = RuleI.Get(Rule.MonkACBonusWeight); -NPCACFactor = RuleR.Get(Rule.NPCACFactor); -OldACSoftcapRules = RuleB.Get(Rule.OldACSoftcapRules); -ClothACSoftcap = RuleI.Get(Rule.ClothACSoftcap); -LeatherACSoftcap = RuleI.Get(Rule.LeatherACSoftcap); -MonkACSoftcap = RuleI.Get(Rule.MonkACSoftcap); -ChainACSoftcap = RuleI.Get(Rule.ChainACSoftcap); -PlateACSoftcap = RuleI.Get(Rule.PlateACSoftcap); -AAMitigationACFactor = RuleR.Get(Rule.AAMitigationACFactor); -WarriorACSoftcapReturn = RuleR.Get(Rule.WarriorACSoftcapReturn); -KnightACSoftcapReturn = RuleR.Get(Rule.KnightACSoftcapReturn); -LowPlateChainACSoftcapReturn = RuleR.Get(Rule.LowPlateChainACSoftcapReturn); -LowChainLeatherACSoftcapReturn = RuleR.Get(Rule.LowChainLeatherACSoftcapReturn); -CasterACSoftcapReturn = RuleR.Get(Rule.CasterACSoftcapReturn); -MiscACSoftcapReturn = RuleR.Get(Rule.MiscACSoftcapReturn); -WarACSoftcapReturn = RuleR.Get(Rule.WarACSoftcapReturn); -ClrRngMnkBrdACSoftcapReturn = RuleR.Get(Rule.ClrRngMnkBrdACSoftcapReturn); -PalShdACSoftcapReturn = RuleR.Get(Rule.PalShdACSoftcapReturn); -DruNecWizEncMagACSoftcapReturn = RuleR.Get(Rule.DruNecWizEncMagACSoftcapReturn); -RogShmBstBerACSoftcapReturn = RuleR.Get(Rule.RogShmBstBerACSoftcapReturn); -SoftcapFactor = RuleR.Get(Rule.SoftcapFactor); -ACthac0Factor = RuleR.Get(Rule.ACthac0Factor); -ACthac20Factor = RuleR.Get(Rule.ACthac20Factor); -BaseHitChance = RuleR.Get(Rule.BaseHitChance); -NPCBonusHitChance = RuleR.Get(Rule.NPCBonusHitChance); -HitFalloffMinor = RuleR.Get(Rule.HitFalloffMinor); -HitFalloffModerate = RuleR.Get(Rule.HitFalloffModerate); -HitFalloffMajor = RuleR.Get(Rule.HitFalloffMajor); -HitBonusPerLevel = RuleR.Get(Rule.HitBonusPerLevel); -AgiHitFactor = RuleR.Get(Rule.AgiHitFactor); -WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff); -ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty); -UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules); -CriticalMessageRange = RuleI.Get(Rule.CriticalDamage); --[[ * @@ -51,6 +17,41 @@ CriticalMessageRange = RuleI.Get(Rule.CriticalDamage); * ]] +MonkACBonusWeight = 15; +NPCACFactor = 2.25; +OldACSoftcapRules = false; +ClothACSoftcap = 75; +LeatherACSoftcap = 100; +MonkACSoftcap = 120; +ChainACSoftcap = 200; +PlateACSoftcap = 300; +AAMitigationACFactor = 3.0; +WarriorACSoftcapReturn = 0.45; +KnightACSoftcapReturn = 0.33; +LowPlateChainACSoftcapReturn = 0.23; +LowChainLeatherACSoftcapReturn = 0.17; +CasterACSoftcapReturn = 0.06; +MiscACSoftcapReturn = 0.3; +WarACSoftcapReturn = 0.3448; +ClrRngMnkBrdACSoftcapReturn = 0.3030; +PalShdACSoftcapReturn = 0.3226; +DruNecWizEncMagACSoftcapReturn = 0.2; +RogShmBstBerACSoftcapReturn = 0.25; +SoftcapFactor = 1.88; +ACthac0Factor = 0.55; +ACthac20Factor = 0.55; +BaseHitChance = 69.0; +NPCBonusHitChance = 26.0; +HitFalloffMinor = 5.0; +HitFalloffModerate = 7.0; +HitFalloffMajor = 50.0; +HitBonusPerLevel = 1.2; +AgiHitFactor = 0.01; +WeaponSkillFalloff = 0.33; +ArcheryHitPenalty = 0.25; +UseOldDamageIntervalRules = false; +CriticalMessageRange = RuleI.Get(Rule.CriticalDamage); + MeleeBaseCritChance = 0.0; ClientBaseCritChance = 0.0; BerserkBaseCritChance = 6.0; @@ -851,7 +852,12 @@ function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ra ); -- Changed from positive to negative per original - damage = damage - (damage * (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100); + local spell_based_mitigation = defender:GetSpellBonuses():MeleeMitigationEffect() * -1; + local item_based_mitigation = defender:GetItemBonuses():MeleeMitigationEffect() * -1; + local aa_based_mitigation = defender:GetAABonuses():MeleeMitigationEffect() * -1; + + -- Changed from positive to negative per original + damage = damage - (damage * (spell_based_mitigation + item_based_mitigation + aa_based_mitigation) / 100); eq.log_combat( string.format("[%s] [Mob::GetMeleeMitDmg] Damage [%02f] SpellMit [%i] ItemMit [%i] AAMit [%i] Post All Mit Bonuses", diff --git a/utils/mods/spell_formula.lua b/utils/mods/spell_formula.lua new file mode 100644 index 000000000..fd2e4d738 --- /dev/null +++ b/utils/mods/spell_formula.lua @@ -0,0 +1,92 @@ +function CalcSpellEffectValue_formula(e) + --THE FUNCTIONALITY OF THIS IS FOR ADDING CUSTOM SPELL FORMULAS WITHOUT INTERFERING WITH EXISTING FORMULAS + if (e.formula >= 100000) then + e.IgnoreDefault = true; + else + e.IgnoreDefault = false; + return e; + end + + local result = 0 + local updownsign = 1 + local ubase = e.base_value + local formula = e.formula + local base_value = e.base_value + local max_value = e.max_value + local caster_level = e.caster_level + local spell_id = e.spell_id + local ticsremaining = e.ticsremaining + + if (ubase < 0) then + ubase = 0 - ubase; + end + + if (max_value < base_value and max_value ~= 0) then + --values are calculated down + updownsign = -1; + else + --values are calculated up + updownsign = 1; + end + + --ADD FORMULAS HERE NO NEED TO TOUCH OTHER CODE UNLESS YOU KNOW WHAT YOU ARE DOING!!! + --FORMULA NUMBERS 100,000+++ are considered "custom" and other spells will use normal logic from source!!! + local switch = { + [100000] = function () + result = updownsign * (ubase + (e.self:GetSTR()/2)); --Half strength added to damage! + end, + [100001] = function () + result = (updownsign * (ubase + (caster_level * 2))) * math.random(1,caster_level); -- multiplies final damage randomly from 1 up to caster level! + end, + } + + eq.log_spells( + string.format("[Mob::CalcSpellEffectValue_formula] spell [%i] formula [%i] base [%i] max [%i] lvl [%i] Up/Down [%i]", + e.spell_id, + e.formula, + e.base_value, + e.max_value, + e.caster_level, + updownsign + ) + ); + + local f = switch[e.formula] + if (f) then + f() + else + result = ubase; --DEFAULT YOU MAY CHANGE THIS TO WHATEVER YOU WISH BUT WILL ONLY CHANGE CUSTOM FORMULAS above 100,000 THAT AREN'T IN THE TABLE ABOVE! + end + + local oresult = result; + + --now check result against the allowed maximum + if (max_value ~= 0) then + if (updownsign == 1) then + if (result > max_value) then + result = max_value; + end + else + if (result < max_value) then + result = max_value; + end + end + end + + --if base is less than zero, then the result need to be negative too + if (base_value < 0 and result > 0) then + result = result * -1; + end + + eq.log_spells( + string.format("[Mob::CalcSpellEffectValue_formula] Result: [%i] (orig [%i]) cap [%i]", + result, + oresult, + max_value + ) + ); + + e.ReturnValue = result; + return e; +end + \ No newline at end of file diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 8065ca53c..f961afadf 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -311,6 +311,7 @@ OP_SendFindableNPCs=0x34c3 OP_FindPersonRequest=0x2f3b OP_FindPersonReply=0x44f7 OP_Sound=0x3cec +OP_CashReward=0x17a5 OP_PetBuffWindow=0x7197 OP_LevelAppearance=0x7c4d OP_Translocate=0x6f01 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 8f7d63b39..08e02b93c 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -312,6 +312,7 @@ OP_SendFindableNPCs=0x4613 OP_FindPersonRequest=0x5cea OP_FindPersonReply=0x7e58 OP_Sound=0x1a30 +OP_CashReward=0x5f7a OP_PetBuffWindow=0x5882 OP_LevelAppearance=0x3bc9 OP_Translocate=0x6580 diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 5cb5d2a30..e0c4752d0 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -307,6 +307,7 @@ OP_SendFindableNPCs=0x5360 OP_FindPersonRequest=0x3168 # C OP_FindPersonReply=0x1ac8 # C OP_Sound=0x303e # C +OP_CashReward=0x3703 OP_PetBuffWindow=0x2dd3 # C OP_LevelAppearance=0x6dc3 # C OP_Translocate=0x2042 # C diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 874c91cc3..a7640ec08 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -299,6 +299,7 @@ OP_Stun=0x55BF #Derision 2009 OP_FindPersonRequest=0x07F0 #Derision 2009 OP_FindPersonReply=0x7770 #Derision 2009 OP_Sound=0x2B02 #Derision 2009 +OP_CashReward=0x5e80 OP_PetBuffWindow=0x124A #Derision 2009 OP_LevelAppearance=0x3EC8 #Derision 2009 OP_Translocate=0x1F0F #Derision 2009 diff --git a/utils/patches/patch_Titanium.conf b/utils/patches/patch_Titanium.conf index 28074dcf9..e1f017c8a 100644 --- a/utils/patches/patch_Titanium.conf +++ b/utils/patches/patch_Titanium.conf @@ -437,6 +437,7 @@ OP_FindPersonReply=0x5711 # ShowEQ 10/27/05 OP_ForceFindPerson=0x0000 OP_LoginComplete=0x0000 OP_Sound=0x541e +OP_CashReward=0x4c8c #maybe #OP_Zone_MissingName01=0x0000 #remove on recompile OP_MobRename=0x0498 # ShowEQ 10/27/05 OP_BankerChange=0x6a5b diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 8c95cbe67..9e78cf140 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -316,6 +316,7 @@ OP_SendFindableNPCs=0x6193 # C OP_FindPersonRequest=0x1e04 # C OP_FindPersonReply=0x7cae # C OP_Sound=0x737a # C +OP_CashReward=0x039d OP_PetBuffWindow=0x7b87 # C OP_LevelAppearance=0x1bd4 # C OP_Translocate=0x3d9c # C diff --git a/utils/scripts/database_dumper.pl b/utils/scripts/database_dumper.pl deleted file mode 100644 index 51b16eabc..000000000 --- a/utils/scripts/database_dumper.pl +++ /dev/null @@ -1,252 +0,0 @@ -#!/usr/bin/perl - -############################################################ -#::: Script: db_dumper.pl -#::: Purpose: Utility to easily manage database backups and compress. -#::: Export Individual DB Tables... -#::: Export specific databases... -#::: Built for both Windows and Linux -#::: Windows uses WinRar or 7-Zip for compression -#::: Linux uses tar for compression -#::: Author: Akkadius -############################################################ - -$localdrive = "C:"; #::: Where Windows and all Install Programs are... -$linesep = "---------------------------------------"; - -use POSIX qw(strftime); -my $date = strftime "%m_%d_%Y", localtime; -print "\nTodays Date: " . $date . "\n"; - -use Config; -print "Operating System is: $Config{osname}\n"; -if($Config{osname}=~/linux/i){ $OS = "Linux"; } -if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } - -if(!$ARGV[0]){ - print "\nERROR! Need arguments\n"; - print "#::: Help :::#\n"; - print "######################################################\n"; - print "Arguments\n"; - print " loc=\"C:\\File Location\" - File path location to backup...\n"; - print " database=\"dbname\" - Manually specify databasename, default is database in eqemu_config.xml\n"; - print " tables=\"table1,table2,table3\" - Manually specify tables, default is to dump all tables from database\n"; - print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; - print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; - print " backup_name=\"name\" - Sets database backup prefix name\n"; - print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n"; - print "######################################################\n"; - exit; -} - -sub read_eqemu_config_json { - use JSON; - my $json = new JSON(); - - my $content; - open(my $fh, '<', "eqemu_config.json") or die "Unable to open config: eqemu_config.json - This must be in your EQEmu Server Folder\n"; { - local $/; - $content = <$fh>; - } - close($fh); - - $config = $json->decode($content); - - $db = $config->{"server"}{"database"}{"db"}; - $host = $config->{"server"}{"database"}{"host"}; - $user = $config->{"server"}{"database"}{"username"}; - $pass = $config->{"server"}{"database"}{"password"}; - $long_name = $config->{"server"}{"world"}{"longname"}; - -} - -read_eqemu_config_json(); - -$Debug = 0; -print "[db_dumper.pl] Arguments\n" if $Debug; -$n = 0; -while($ARGV[$n]){ - print $n . ': ' . $ARGV[$n] . "\n" if $Debug; - if($ARGV[$n]=~/nolock/i){ - $no_lock = 1; - } - if($ARGV[$n]=~/compress/i){ - print "[db_dumper.pl] Compression SET\n"; - $Compress = 1; - } - if($ARGV[$n]=~/database=/i){ - @DB_NAME = split('=', $ARGV[$n]); - print "[db_dumper.pl] Database is " . $DB_NAME[1] . "\n"; - $db = $DB_NAME[1]; - } - if($ARGV[$n]=~/backup_name=/i){ - @data = split('=', $ARGV[$n]); - print "[db_dumper.pl] Backup Name is " . $data[1] . "\n"; - $backup_name = $data[1]; - } - if($ARGV[$n]=~/loc=/i){ - @backup_location = split('=', $ARGV[$n]); - print "[db_dumper.pl] Backup Directory: " . $backup_location[1] . "\n"; - } - if($ARGV[$n]=~/tables=/i){ - @Tables = split('=', $ARGV[$n]); @TList = split(',', $Tables[1]); - foreach my $tables (@TList){ - $t_tables .= $tables . " "; - $t_tables_l .= $tables . "_"; - $t_tables_p .= $tables . "\n"; - } - print "[db_dumper.pl] Backing up tables: \n############################\n" . $t_tables_p . "############################\n"; - } - $n++; -} - -#::: Check for Backup Directory existence, if doesn't exist then create... -if (-d $backup_location[1]) { - print "[db_dumper.pl] Directory currently exists... Adding files to it...\n"; -} -elsif($backup_location[1] ne ""){ - print "[db_dumper.pl] Directory does NOT exist! Creating...\n"; - mkdir($backup_location[1]) or die 'Failed to create folder, maybe created the folder manually at "' . $backup_location[1]. '" ?'; -} -else{ - print "[db_dumper.pl] No save location specified... Saving to folder script is running in...\n"; -} -if($backup_location[1] ne ""){ - if($OS eq "Windows"){ $file_app = "\\"; } - if($OS eq "Linux"){ $file_app = "/"; } -} -else { - $file_app = ""; -} - -if($t_tables ne ""){ - $tables_f_l = substr($t_tables_l, 0, 20) . '-'; - if($backup_name){ - $target_file = $backup_name . '_' . $date . ''; - } - else { - $target_file = '' . $tables_f_l . '_' . $date . ''; - } - - print "[db_dumper.pl] Performing table based backup...\n"; - #::: Backup Database... - print "[db_dumper.pl] Backing up Database " . $db . "... \n"; - if($no_lock == 1){ - $added_parameters .= " --skip-lock-tables "; - } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; - printcmd($cmd); - system($cmd); -} -else{ #::: Entire DB Backup - - if($backup_name){ - $target_file = $backup_name . '_' . $db . '_' . $date . ''; - } - else { - $target_file = '' . $db . '_' . $date . ''; - } - - #::: Backup Database... - print "[db_dumper.pl] Backing up Database " . $db . "... \n"; - if($no_lock == 1){ - $added_parameters .= " --skip-lock-tables "; - } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; - printcmd($cmd); - system($cmd); -} - -#::: Get File Size -$fileloc = '' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql'; -$filesize = -s $fileloc; -if($filesize < 1000){ print "[db_dumper.pl] " . 'Error occurred... exiting...' . "\n"; exit; } -print "[db_dumper.pl] Backup DONE... DB Backup File Size '" . $filesize . "' (" . get_filesize_str($fileloc) . ")\n"; - -#::: WinRar Get, check compression flag -if($Compress == 1){ - if($OS eq "Windows"){ - if(-d $localdrive . "\\Program Files\\7-Zip"){ - print "[db_dumper.pl] ::: You have 7-Zip installed as 64 Bit...\n"; - $S_ZIP = $localdrive . "\\Program Files\\7-Zip"; - } - elsif(-d $localdrive . "\\Program Files (x86)\\7-Zip"){ - print "[db_dumper.pl] ::: You have 7-Zip installed as 32 Bit...\n"; - $S_ZIP = $localdrive . "\\Program Files (x86)\\7-Zip"; - } - elsif(-d $localdrive . "\\Program Files (x86)\\WinRAR"){ - print "[db_dumper.pl] ::: You have WinRAR installed as 32 Bit...\n"; - $WinRar = $localdrive . "\\Program Files (x86)\\WinRAR"; - } - elsif(-d $localdrive . "\\Program Files\\WinRAR"){ - print "[db_dumper.pl] ::: You have WinRAR installed as 64 Bit...\n"; - $WinRar = $localdrive . "\\Program Files\\WinRAR"; - } - else{ - print "[db_dumper.pl] No WinRAR installed... Will not compress...\n"; - } - if($S_ZIP ne ""){ - print "[db_dumper.pl] Compressing Database with 7-ZIP... \n"; - $cmd = '"' . $S_ZIP . '\\7z" a -t7z -m0=lzma -mx=9 "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.7z" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; - $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - $final_file = $target_file . ".7z"; - } - elsif($WinRar ne ""){ - print "[db_dumper.pl] Compressing Database with WinRAR... \n"; - $cmd = '"' . $WinRar . '\\rar" a "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.rar" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; - $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - $final_file = $target_file . ".rar"; - } - } - if($OS eq "Linux"){ - print "[db_dumper.pl] Compressing Database with Tarball... \n"; - $cmd = 'tar -zcvf "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.tar.gz" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; - $cmd = 'rm "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - $final_file = $target_file . ".tar.gz"; - } -} -else { - $final_file = $target_file . ".sql"; -} - -#::: Get Final File Location for display -if($backup_location[1] ne ""){ $final_loc = $backup_location[1] . '' . $file_app . ""; } -else{ - if($OS eq "Windows"){ - $final_loc = `echo %cd%`; - } - elsif($OS eq "Linux"){ - $final_loc = `pwd`; - } -} - -print "[db_dumper.pl] Final file located: " . $final_loc . "" . $final_file . "\n"; - -sub printcmd{ - print "[db_dumper.pl] Command [" . $_[0] . "]\n"; -} - -sub get_filesize_str{ - my $file = shift(); - my $size = (stat($file))[7] || die "stat($file): $!\n"; - if ($size > 1099511627776) { return sprintf("%.2f TiB", $size / 1099511627776); } - elsif ($size > 1073741824) { return sprintf("%.2f GiB", $size / 1073741824); } - elsif ($size > 1048576) { return sprintf("%.2f MiB", $size / 1048576); } - elsif ($size > 1024) { return sprintf("%.2f KiB", $size / 1024); } - else { return "$size byte" . ($size == 1 ? "" : "s"); } -} diff --git a/utils/scripts/db_dumper.pl b/utils/scripts/db_dumper.pl deleted file mode 100644 index af734124d..000000000 --- a/utils/scripts/db_dumper.pl +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/perl - -############################################################ -#::: Script: db_dumper.pl -#::: Purpose: Utility to easily manage database backups and compress. -#::: Export Individual DB Tables... -#::: Export specific databases... -#::: Built for both Windows and Linux -#::: Windows uses WinRar or 7-Zip for compression -#::: Linux uses tar for compression -#::: Author: Akkadius -############################################################ - -$localdrive = "C:"; #::: Where Windows and all Install Programs are... -$linesep = "---------------------------------------"; - -use POSIX qw(strftime); -my $date = strftime "%m_%d_%Y", localtime; -print "\nTodays Date: " . $date . "\n"; - -use Config; -print "Operating System is: $Config{osname}\n"; -if($Config{osname}=~/linux/i){ $OS = "Linux"; } -if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } - -if(!$ARGV[0]){ - print "\nERROR! Need arguments\n"; - print "#::: Help :::#\n"; - print "######################################################\n"; - print "Arguments\n"; - print " loc=\"C:\\File Location\" - File path location to backup...\n"; - print " database=\"dbname\" - Manually specify databasename, default is database in eqemu_config.xml\n"; - print " tables=\"table1,table2,table3\" - Manually specify tables, default is to dump all tables from database\n"; - print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; - print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; - print " backup_name=\"name\" - Sets database backup prefix name\n"; - print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n"; - print "######################################################\n"; - exit; -} - -#::: CONFIG VARIABLES - Parsed from eqemu_config.xml - -my $confile = "eqemu_config.xml"; #default -open(F, "<$confile") or die "Unable to open config: $confile - This must be in your EQEmu Server Folder with your XML config\n"; -my $indb = 0; - -while() { - s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } -} - -$Debug = 0; -print "[db_dumper.pl] Arguments\n" if $Debug; -$n = 0; -while($ARGV[$n]){ - print $n . ': ' . $ARGV[$n] . "\n" if $Debug; - if($ARGV[$n]=~/nolock/i){ - $no_lock = 1; - } - if($ARGV[$n]=~/compress/i){ - print "[db_dumper.pl] Compression SET\n"; - $Compress = 1; - } - if($ARGV[$n]=~/database=/i){ - @DB_NAME = split('=', $ARGV[$n]); - print "[db_dumper.pl] Database is " . $DB_NAME[1] . "\n"; - $db = $DB_NAME[1]; - } - if($ARGV[$n]=~/backup_name=/i){ - @data = split('=', $ARGV[$n]); - print "[db_dumper.pl] Backup Name is " . $data[1] . "\n"; - $backup_name = $data[1]; - } - if($ARGV[$n]=~/loc=/i){ - @backup_location = split('=', $ARGV[$n]); - print "[db_dumper.pl] Backup Directory: " . $backup_location[1] . "\n"; - } - if($ARGV[$n]=~/tables=/i){ - @Tables = split('=', $ARGV[$n]); @TList = split(',', $Tables[1]); - foreach my $tables (@TList){ - $t_tables .= $tables . " "; - $t_tables_l .= $tables . "_"; - $t_tables_p .= $tables . "\n"; - } - print "[db_dumper.pl] Backing up tables: \n############################\n" . $t_tables_p . "############################\n"; - } - $n++; -} - -#::: Check for Backup Directory existence, if doesn't exist then create... -if (-d $backup_location[1]) { - print "[db_dumper.pl] Directory currently exists... Adding files to it...\n"; -} -elsif($backup_location[1] ne ""){ - print "[db_dumper.pl] Directory does NOT exist! Creating...\n"; - mkdir($backup_location[1]) or die 'Failed to create folder, maybe created the folder manually at "' . $backup_location[1]. '" ?'; -} -else{ - print "[db_dumper.pl] No save location specified... Saving to folder script is running in...\n"; -} -if($backup_location[1] ne ""){ - if($OS eq "Windows"){ $file_app = "\\"; } - if($OS eq "Linux"){ $file_app = "/"; } -} -else { - $file_app = ""; -} - -if($t_tables ne ""){ - $tables_f_l = substr($t_tables_l, 0, 20) . '-'; - if($backup_name){ - $target_file = $backup_name . '_' . $date . ''; - } - else { - $target_file = '' . $tables_f_l . '_' . $date . ''; - } - - print "[db_dumper.pl] Performing table based backup...\n"; - #::: Backup Database... - print "[db_dumper.pl] Backing up Database " . $db . "... \n"; - if($no_lock == 1){ - $added_parameters .= " --skip-lock-tables "; - } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; - printcmd($cmd); - system($cmd); -} -else{ #::: Entire DB Backup - - if($backup_name){ - $target_file = $backup_name . '_' . $db . '_' . $date . ''; - } - else { - $target_file = '' . $db . '_' . $date . ''; - } - - #::: Backup Database... - print "[db_dumper.pl] Backing up Database " . $db . "... \n"; - if($no_lock == 1){ - $added_parameters .= " --skip-lock-tables "; - } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; - printcmd($cmd); - system($cmd); -} - -#::: Get File Size -$fileloc = '' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql'; -$filesize = -s $fileloc; -if($filesize < 1000){ print "[db_dumper.pl] " . 'Error occurred... exiting...' . "\n"; exit; } -print "[db_dumper.pl] Backup DONE... DB Backup File Size '" . $filesize . "' (" . get_filesize_str($fileloc) . ")\n"; - -#::: WinRar Get, check compression flag -if($Compress == 1){ - if($OS eq "Windows"){ - if(-d $localdrive . "\\Program Files\\7-Zip"){ - print "[db_dumper.pl] ::: You have 7-Zip installed as 64 Bit...\n"; - $S_ZIP = $localdrive . "\\Program Files\\7-Zip"; - } - elsif(-d $localdrive . "\\Program Files (x86)\\7-Zip"){ - print "[db_dumper.pl] ::: You have 7-Zip installed as 32 Bit...\n"; - $S_ZIP = $localdrive . "\\Program Files (x86)\\7-Zip"; - } - elsif(-d $localdrive . "\\Program Files (x86)\\WinRAR"){ - print "[db_dumper.pl] ::: You have WinRAR installed as 32 Bit...\n"; - $WinRar = $localdrive . "\\Program Files (x86)\\WinRAR"; - } - elsif(-d $localdrive . "\\Program Files\\WinRAR"){ - print "[db_dumper.pl] ::: You have WinRAR installed as 64 Bit...\n"; - $WinRar = $localdrive . "\\Program Files\\WinRAR"; - } - else{ - print "[db_dumper.pl] No WinRAR installed... Will not compress...\n"; - } - if($S_ZIP ne ""){ - print "[db_dumper.pl] Compressing Database with 7-ZIP... \n"; - $cmd = '"' . $S_ZIP . '\\7z" a -t7z -m0=lzma -mx=9 "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.7z" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; - $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - $final_file = $target_file . ".7z"; - } - elsif($WinRar ne ""){ - print "[db_dumper.pl] Compressing Database with WinRAR... \n"; - $cmd = '"' . $WinRar . '\\rar" a "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.rar" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; - $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - $final_file = $target_file . ".rar"; - } - } - if($OS eq "Linux"){ - print "[db_dumper.pl] Compressing Database with Tarball... \n"; - $cmd = 'tar -zcvf "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.tar.gz" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; - $cmd = 'rm "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; - printcmd($cmd); - system($cmd); - $final_file = $target_file . ".tar.gz"; - } -} -else { - $final_file = $target_file . ".sql"; -} - -#::: Get Final File Location for display -if($backup_location[1] ne ""){ $final_loc = $backup_location[1] . '' . $file_app . ""; } -else{ - if($OS eq "Windows"){ - $final_loc = `echo %cd%`; - } - elsif($OS eq "Linux"){ - $final_loc = `pwd`; - } -} - -print "[db_dumper.pl] Final file located: " . $final_loc . "" . $final_file . "\n"; - -sub printcmd{ - print "[db_dumper.pl] Command [" . $_[0] . "]\n"; -} - -sub get_filesize_str{ - my $file = shift(); - my $size = (stat($file))[7] || die "stat($file): $!\n"; - if ($size > 1099511627776) { return sprintf("%.2f TiB", $size / 1099511627776); } - elsif ($size > 1073741824) { return sprintf("%.2f GiB", $size / 1073741824); } - elsif ($size > 1048576) { return sprintf("%.2f MiB", $size / 1048576); } - elsif ($size > 1024) { return sprintf("%.2f KiB", $size / 1024); } - else { return "$size byte" . ($size == 1 ? "" : "s"); } -} diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 22e2f1de8..efdff15fa 100755 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -50,6 +50,11 @@ if ($Config{osname} =~ /Win|MS/i) { $OS = "Windows"; } +if (-e "../eqemu_config.json") { + print "[Info] Config is up one level, let's set current directory up one level...\n"; + chdir("../"); +} + ############################################# # internet check ############################################# @@ -83,6 +88,8 @@ if (-d "bin") { $bin_dir = "bin/"; } +my $world_path = get_world_path(); + ############################################# # run routines ############################################# @@ -255,7 +262,7 @@ sub show_install_summary_info sub new_server { $build_options = $_[0]; - $file_count = 0; + $file_count = 0; opendir(DIR, ".") or die $!; while (my $file = readdir(DIR)) { next if ($file =~ m/^\./); @@ -299,9 +306,9 @@ sub new_server open(MYSQL_CHECK, "mysqlcheck.txt"); while () { chomp; - $o = $_; - if ($o =~ /Error/i) {$mysql_pass = 0;} - if ($o =~ /SHOW PROCESSLIST/i) {$mysql_pass = 1;} + $o = $_; + if ($o =~ /Error/i) { $mysql_pass = 0; } + if ($o =~ /SHOW PROCESSLIST/i) { $mysql_pass = 1; } } close(MYSQL_CHECK); unlink("mysqlcheck.txt"); @@ -423,11 +430,6 @@ sub build_linux_source $cmake_options = ""; $source_folder_post_fix = ""; - if ($build_options =~ /bots/i) { - $cmake_options .= " -DEQEMU_ENABLE_BOTS=ON"; - $source_folder_post_fix = "_bots"; - } - $current_directory = `pwd`; @directories = split('/', $current_directory); foreach my $val (@directories) { @@ -437,8 +439,8 @@ sub build_linux_source } my $eqemu_server_directory = "/home/eqemu"; # source between bots and not is the same, just different build results, so use the same source folder, different build folders - my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source'; - my $build_dir = $eqemu_server_directory . '/' . $last_directory . '_build' . $source_folder_post_fix; + my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source'; + my $build_dir = $eqemu_server_directory . '/' . $last_directory . '_build' . $source_folder_post_fix; $current_directory = trim($current_directory); @@ -522,34 +524,24 @@ sub do_installer_routines fetch_utility_scripts(); #::: Database Routines - $root_user = $user; + $root_user = $user; $root_password = $pass; print "[Database] Creating Database '" . $db_name . "'\n"; - if (defined($ENV{'MYSQL_ROOT_PASSWORD'})) - { + if (defined($ENV{'MYSQL_ROOT_PASSWORD'})) { # In the case that the user doesn't have privileges to create databases, support passing in the root password during setup print "[Database] Using 'root' for database management.\n"; - $root_user = "root"; + $root_user = "root"; $root_password = $ENV{'MYSQL_ROOT_PASSWORD'}; } print `"$path" --host $host --user $root_user --password="$root_password" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; print `"$path" --host $host --user $root_user --password="$root_password" -N -B -e "CREATE DATABASE $db_name"`; - if (defined($ENV{'MYSQL_ROOT_PASSWORD'})) - { + if (defined($ENV{'MYSQL_ROOT_PASSWORD'})) { # If we used root, make sure $user has permissions on db print "[Database] Assigning ALL PRIVILEGES to $user on $db_name.\n"; print `"$path" --host $host --user $root_user --password="$root_password" -N -B -e "GRANT ALL PRIVILEGES ON $db_name.* TO '$user.%'"`; print `"$path" --host $host --user $root_user --password="$root_password" -N -B -e "FLUSH PRIVILEGES"`; } - my $world_path = "world"; - if (-e "bin/world") { - $world_path = "bin/world"; - } - elsif (-e "bin/world.exe") { - $world_path = "bin/world.exe"; - } - #::: Get Binary DB version if ($OS eq "Windows") { @db_version = split(': ', `"$world_path" db_version`); @@ -568,11 +560,7 @@ sub do_installer_routines fetch_peq_db_full(); print "[Database] Fetching and Applying Latest Database Updates...\n"; main_db_management(); - - # if bots - if ($build_options =~ /bots/i) { - bots_db_management(); - } + bots_db_management(); remove_duplicate_rule_values(); @@ -594,15 +582,6 @@ sub check_for_input sub check_for_world_bootup_database_update { - - my $world_path = "world"; - if (-e "bin/world") { - $world_path = "bin/world"; - } - elsif (-e "bin/world.exe") { - $world_path = "bin/world.exe"; - } - $binary_database_version = 0; $local_database_version = 0; @@ -647,7 +626,7 @@ sub check_for_world_bootup_database_update print "[Update] Database version is ahead of current binaries...\n"; } - if (!$db) {print "[eqemu_server.pl] No database connection found... Running without\n";} + if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; } show_menu_prompt(); } } @@ -682,7 +661,7 @@ sub check_for_world_bootup_database_update print "[Update] Bots database version is ahead of current binaries...\n"; } - if (!$db) {print "[eqemu_server.pl] No database connection found... Running without\n";} + if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; } show_menu_prompt(); } } @@ -726,7 +705,8 @@ sub get_perl_version no warnings; } -sub get_windows_wget { +sub get_windows_wget +{ if (!-e "bin/wget.exe" && $OS eq "Windows") { if (!-d "bin") { mkdir("bin"); @@ -764,7 +744,7 @@ sub do_self_update_check_routine my @files; my $start_dir = "updates_staged/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -802,9 +782,9 @@ sub do_self_update_check_routine sub get_installation_variables { # Read installation variables from the ENV if set, but override them with install_variables.txt - if ($ENV{"MYSQL_HOST"}) { $installation_variables{"mysql_host"} = $ENV{"MYSQL_HOST"}; } - if ($ENV{"MYSQL_DATABASE"}) { $installation_variables{"mysql_eqemu_db_name"} = $ENV{"MYSQL_DATABASE"}; } - if ($ENV{"MYSQL_USER"}) { $installation_variables{"mysql_eqemu_user"} = $ENV{"MYSQL_USER"} } + if ($ENV{"MYSQL_HOST"}) { $installation_variables{"mysql_host"} = $ENV{"MYSQL_HOST"}; } + if ($ENV{"MYSQL_DATABASE"}) { $installation_variables{"mysql_eqemu_db_name"} = $ENV{"MYSQL_DATABASE"}; } + if ($ENV{"MYSQL_USER"}) { $installation_variables{"mysql_eqemu_user"} = $ENV{"MYSQL_USER"} } if ($ENV{"MYSQL_PASSWORD"}) { $installation_variables{"mysql_eqemu_password"} = $ENV{"MYSQL_PASSWORD"} } #::: Fetch installation variables before building the config @@ -840,9 +820,9 @@ sub do_install_config_json my $content; open(my $fh, '<', "eqemu_config_template.json") or die "cannot open file $filename"; { - local $/; - $content = <$fh>; - } + local $/; + $content = <$fh>; +} close($fh); $config = $json->decode($content); @@ -865,11 +845,11 @@ sub do_install_config_json $host = "127.0.0.1"; } - $config->{"server"}{"database"}{"host"} = $host; + $config->{"server"}{"database"}{"host"} = $host; $config->{"server"}{"database"}{"username"} = $installation_variables{"mysql_eqemu_user"}; $config->{"server"}{"database"}{"password"} = $installation_variables{"mysql_eqemu_password"}; $config->{"server"}{"database"}{"db"} = $db_name; - $config->{"server"}{"qsdatabase"}{"host"} = $host; + $config->{"server"}{"qsdatabase"}{"host"} = $host; $config->{"server"}{"qsdatabase"}{"username"} = $installation_variables{"mysql_eqemu_user"}; $config->{"server"}{"qsdatabase"}{"password"} = $installation_variables{"mysql_eqemu_password"}; $config->{"server"}{"qsdatabase"}{"db"} = $db_name; @@ -895,9 +875,9 @@ sub do_install_config_login_json my $content; open(my $fh, '<', "login_template.json") or die "cannot open file $filename"; { - local $/; - $content = <$fh>; - } + local $/; + $content = <$fh>; +} close($fh); $config = $json->decode($content); @@ -943,7 +923,7 @@ sub fetch_utility_scripts foreach my $file (@files) { my $full_file = "bin/" . $file; - if ($file=~/test|launch/i) { + if ($file =~ /test|launch/i) { next; } @@ -983,9 +963,6 @@ sub fetch_utility_scripts sub setup_bots { - if ($OS eq "Windows") { - fetch_latest_windows_appveyor_bots(); - } if ($OS eq "Linux") { build_linux_source("bots"); } @@ -1046,8 +1023,6 @@ sub show_menu_prompt print ">>> Windows\n"; print " [windows_server_download] Updates server via latest 'stable' code\n"; print " [windows_server_latest] Updates server via latest commit 'unstable'\n"; - print " [windows_server_download_bots] Updates server (bots) via latest 'stable'\n"; - print " [windows_server_latest_bots] Updates server (bots) via latest commit 'unstable'\n"; print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; print " [setup_loginserver] Sets up loginserver for Windows\n"; } @@ -1100,17 +1075,13 @@ sub show_menu_prompt $dc = 1; } elsif ($input eq "windows_server_download") { - fetch_latest_windows_binaries(); + fetch_latest_windows_appveyor(); $dc = 1; } elsif ($input eq "windows_server_latest") { fetch_latest_windows_appveyor(); $dc = 1; } - elsif ($input eq "windows_server_latest_bots") { - fetch_latest_windows_appveyor_bots(); - $dc = 1; - } elsif ($input eq "fetch_dlls") { fetch_server_dlls(); $dc = 1; @@ -1135,10 +1106,6 @@ sub show_menu_prompt new_server(); $dc = 1; } - elsif ($input eq "new_server_with_bots") { - new_server("bots"); - $dc = 1; - } elsif ($input eq "setup_bots") { setup_bots(); $dc = 1; @@ -1248,97 +1215,55 @@ sub get_mysql_path } } -sub check_for_database_dump_script +sub get_world_path { - #::: Check for internet connection before updating - if (!$has_internet_connection) { - print "[Update] Cannot check update without internet connection...\n"; - return; + if (-e "world") { + return "world"; + } + elsif (-e "world.exe") { + return "world.exe"; + } + elsif (-e "bin/world") { + return "bin/world"; + } + elsif (-e "bin/world.exe") { + return "bin/world.exe"; + } +} + +sub get_world_command +{ + my $command = ""; + my $world_path = get_world_path(); + if ($OS eq "Windows") { + $command = "\"$world_path\""; + } + if ($OS eq "Linux") { + $command = "./$world_path"; } - #::: Check for script changes :: database_dumper.pl - get_remote_file($eqemu_repository_request_url . "utils/scripts/database_dumper.pl", - "updates_staged/database_dumper.pl", - 0, - 1, - 1); - - if (-e "updates_staged/database_dumper.pl") { - - my $remote_script_size = -s "updates_staged/database_dumper.pl"; - my $local_script_size = -s "database_dumper.pl"; - - if ($remote_script_size != $local_script_size) { - print "[Update] Script has been updated, updating...\n"; - - my @files; - my $start_dir = "updates_staged/"; - find( - sub {push @files, $File::Find::name unless -d;}, - $start_dir - ); - for my $file (@files) { - if ($file =~ /database_dumper/i) { - $destination_file = $file; - $destination_file =~ s/updates_staged\///g; - print "[Install] Installing [" . $destination_file . "]\n"; - unlink($destination_file); - copy_file($file, $destination_file); - if ($OS eq "Linux") { - system("chmod 755 database_dumper.pl"); - } - } - } - print "[Install] Done\n"; - } - else { - print "[Update] No script update necessary...\n"; - } - - unlink("updates_staged/database_dumper.pl"); - } - - return; - + return $command; } sub database_dump { - check_for_database_dump_script(); print "[Database] Performing database backup....\n"; - print `perl database_dumper.pl database="$db" loc="backups"`; + my $command = get_world_command(); + print `$command database:dump --all`; } sub database_dump_player_tables { - check_for_database_dump_script(); print "[Database] Performing database backup of player tables....\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/character_table_list.txt", - "backups/character_table_list.txt"); - - $tables = ""; - open(FILE, "backups/character_table_list.txt"); - $i = 0; - while () { - chomp; - $o = $_; - $tables .= $o . ","; - } - $tables = substr($tables, 0, -1); - - print `perl database_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; - - print "[Database] Press any key to continue...\n"; - - <>; #Read from STDIN - + my $command = get_world_command(); + print `$command database:dump --player-tables`; } sub database_dump_compress { - check_for_database_dump_script(); print "[Database] Performing database backup....\n"; - print `perl database_dumper.pl database="$db" loc="backups" compress`; + my $command = get_world_command(); + print `$command database:dump --all --compress`; } sub script_exit @@ -1364,8 +1289,8 @@ sub check_db_version_table sub get_mysql_result { my $run_query = $_[0]; - if (!$db) {return;} - if ($OS eq "Windows") {return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`;} + if (!$db) { return; } + if ($OS eq "Windows") { return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; } if ($OS eq "Linux") { $run_query =~ s/`//g; return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; @@ -1505,9 +1430,9 @@ sub read_eqemu_config_json my $content; open(my $fh, '<', "eqemu_config.json") or die "cannot open file $filename"; { - local $/; - $content = <$fh>; - } + local $/; + $content = <$fh>; +} close($fh); $config = $json->decode($content); @@ -1631,18 +1556,18 @@ sub copy_file sub fetch_latest_windows_appveyor { print "[Update] Fetching Latest Windows Binaries (unstable) from Appveyor... \n"; - get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server-pglwk/artifacts/build_x64.zip", - "updates_staged/build_x64.zip", + get_remote_file("https://github.com/eqemu/server/releases/latest/download/eqemu-server-windows-x64.zip", + "updates_staged/eqemu-server-windows-x64.zip", 1 ); print "[Update] Fetched Latest Windows Binaries (unstable) from Appveyor... \n"; print "[Update] Extracting... --- \n"; - unzip('updates_staged/build_x64.zip', 'updates_staged/binaries/'); + unzip('updates_staged/eqemu-server-windows-x64.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1656,60 +1581,6 @@ sub fetch_latest_windows_appveyor rmtree('updates_staged'); } -sub fetch_latest_windows_binaries -{ - print "[Update] Fetching Latest Windows Binaries... \n"; - get_remote_file($install_repository_request_url . "master_windows_build.zip", - "updates_staged/master_windows_build.zip", - 1 - ); - print "[Update] Fetched Latest Windows Binaries... \n"; - print "[Update] Extracting... --- \n"; - unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); - my @files; - my $start_dir = "updates_staged/binaries"; - find( - sub {push @files, $File::Find::name unless -d;}, - $start_dir - ); - for my $file (@files) { - my $destination_file = $file; - $destination_file =~ s/updates_staged\/binaries\///g; - print "[Update] Installing [" . $bin_dir . $destination_file . "]\n"; - copy_file($file, $bin_dir . $destination_file); - } - print "[Update] Done\n"; - - rmtree('updates_staged'); -} - -sub fetch_latest_windows_appveyor_bots -{ - print "[Update] Fetching Latest Windows Binaries with Bots (unstable) from Appveyor... \n"; - get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server-87crp/artifacts/build_x64.zip", - "updates_staged/eqemu-x64-bots.zip", - 1); - - print "[Update] Fetched Latest Windows Binaries (unstable) from Appveyor... \n"; - print "[Update] Extracting... --- \n"; - unzip('updates_staged/eqemu-x64-bots.zip', 'updates_staged/binaries/'); - my @files; - my $start_dir = "updates_staged/binaries"; - find( - sub {push @files, $File::Find::name unless -d;}, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~ s/updates_staged\/binaries\///g; - print "[Update] Installing [" . $bin_dir . $destination_file . "]\n"; - copy_file($file, $bin_dir . $destination_file); - } - print "[Update] Done\n"; - - rmtree('updates_staged'); -} - sub do_windows_login_server_setup { print "[Install] Pulling down Loginserver database tables...\n"; @@ -1895,7 +1766,7 @@ sub fetch_peq_db_full unzip('updates_staged/peq-latest.zip', 'updates_staged/peq_db/'); my $start_dir = "updates_staged/peq_db/peq-dump"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1916,7 +1787,7 @@ sub map_files_fetch_bulk my @files; my $start_dir = "maps/EQEmuMaps-master/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1931,45 +1802,6 @@ sub map_files_fetch_bulk unlink('maps/maps.zip'); } -sub map_files_fetch -{ - print "[Install] Fetching Latest Maps --- \n"; - - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", - "updates_staged/eqemu_maps_manifest.txt"); - - #::: Get Data from manifest - open(FILE, "updates_staged/eqemu_maps_manifest.txt"); - $i = 0; - while () { - chomp; - $o = $_; - @manifest_map_data = split(',', $o); - if ($manifest_map_data[0] ne "") { - $maps_manifest[$i] = [ $manifest_map_data[0], $manifest_map_data[1] ]; - $i++; - } - } - - #::: Download - $fc = 0; - for ($m = 0; $m <= $i; $m++) { - my $file_existing = $maps_manifest[$m][0]; - my $file_existing_size = (stat $file_existing)[7]; - if ($file_existing_size != $maps_manifest[$m][1]) { - print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], - $maps_manifest[$m][0], - 1); - $fc++; - } - } - - if ($fc == 0) { - print "[Install] No Map Updates found... \n\n"; - } -} - sub quest_files_fetch { if (!-e "updates_staged/projecteqquests-master/") { @@ -1989,7 +1821,7 @@ sub quest_files_fetch my @files; my $start_dir = "updates_staged/projecteqquests-master/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -2054,7 +1886,7 @@ sub lua_modules_fetch my @files; my $start_dir = "updates_staged/projecteqquests-master/lua_modules/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -2116,7 +1948,7 @@ sub plugins_fetch my @files; my $start_dir = "updates_staged/projecteqquests-master/plugins/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -2603,7 +2435,7 @@ sub fetch_missing_db_update sub print_match_debug { - if (!$debug) {return;} + if (!$debug) { return; } print " Match Type: '" . $match_type . "'\n"; print " Match Text: '" . $match_text . "'\n"; print " Query Check: '" . $query_check . "'\n"; @@ -2612,7 +2444,7 @@ sub print_match_debug sub print_break { - if (!$debug) {return;} + if (!$debug) { return; } print "\n==============================================\n"; } @@ -2652,13 +2484,13 @@ sub quest_heading_convert my @files; my $start_dir = "quests/."; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { #::: Skip non script files - if ($file !~ /lua|pl/i) {next;} + if ($file !~ /lua|pl/i) { next; } if ($file =~ /lua|pl/i) { $print_buffer = ""; @@ -2672,7 +2504,7 @@ sub quest_heading_convert $line = $_; #::: Loop through matches - foreach my $key (sort (keys %matches)) { + foreach my $key (sort(keys %matches)) { $argument_position = $matches{$key}[1]; $match = $matches{$key}[0]; @@ -2783,7 +2615,7 @@ sub quest_faction_convert my @files; my $start_dir = "quests/."; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -2804,7 +2636,7 @@ sub quest_faction_convert $line = $_; #::: Loop through matches - foreach my $key (sort (keys %matches)) { + foreach my $key (sort(keys %matches)) { $argument_position = $matches{$key}[1]; $match = $matches{$key}[0]; @@ -2870,7 +2702,7 @@ sub fix_quest_factions my @files; my $start_dir = "quests/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { diff --git a/utils/scripts/generators/log-alias-generator.pl b/utils/scripts/generators/log-alias-generator.pl new file mode 100755 index 000000000..be79fa32e --- /dev/null +++ b/utils/scripts/generators/log-alias-generator.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl + +use strict; +use warnings FATAL => 'all'; + +my $filename = './common/eqemu_logsys.h'; +open(my $fh, '<:encoding(UTF-8)', $filename) + or die "Could not open file '$filename' $!"; + +my $contents = ""; +while (my $row = <$fh>) { + chomp $row; + $contents .= $row . "\n"; +} + +my @enum = split('enum LogCategory \{', $contents); + +if (scalar(@enum) > 0) { + # print $enum[1]; + my @second_split = split('};', $enum[1]); + if (scalar(@second_split) > 0) { + my $categories = $second_split[0]; + $categories =~ s/^\s+//; + $categories =~ s/\s+$//; + $categories =~ s/ //g; + $categories =~ s/ //g; + $categories =~ s/\n//g; + $categories =~ s/None=0,//g; + $categories =~ s/,MaxCategoryID//g; + $categories =~ s/\/\*//g; + $categories =~ s/\*\///g; + $categories =~ s/Don'tRemovethis//g; + + my @cats = split(',', $categories); + + foreach my $cat (@cats) { + print "#define Log" . $cat . "(message, ...) do {\\ + if (LogSys.IsLogEnabled(Logs::General, Logs::" . $cat . "))\\ + OutF(LogSys, Logs::General, Logs::" . $cat . ", __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\\ +} while (0) + +#define Log" . $cat . "Detail(message, ...) do {\\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::" . $cat . "))\\ + OutF(LogSys, Logs::Detail, Logs::" . $cat . ", __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\\ +} while (0) + +"; + # print "$cat\n"; + } + } +} + +close $fh; diff --git a/utils/scripts/generators/lua-doc-parser.pl b/utils/scripts/generators/lua-doc-parser.pl deleted file mode 100644 index a5608944a..000000000 --- a/utils/scripts/generators/lua-doc-parser.pl +++ /dev/null @@ -1,241 +0,0 @@ -#!/usr/bin/perl - -# Author: Akkadius -# @file: lua-doc-parser.pl -# @description: Script meant to parse the source code to build the LUA API list - -use File::Find; -use Data::Dumper; - -sub usage() { - print "Usage:\n"; - print " --client - Prints methods for just client class methods\n"; - print " --mob - Prints methods for just mob class methods\n"; - print " --npc - Prints methods for just npc class methods\n"; - print " --entity - Prints methods for just entity class methods\n"; - print " --entity_list - Prints methods for just entity_list class methods\n"; - print " --door - Prints methods for just door class methods\n"; - print " --object - Prints methods for just object class methods\n"; - print " --group - Prints methods for just group class methods\n"; - print " --raid - Prints methods for just raid class methods\n"; - print " --item - Prints methods for just item class methods\n"; - print " --iteminst - Prints methods for just iteminst class methods\n"; - print " --inventory - Prints methods for just inventory class methods\n"; - print " --corpse - Prints methods for just corpse class methods\n"; - print " --hate_entry - Prints methods for just hate_entry class methods\n"; - print " --quest - Prints methods for just quest class methods\n"; - print " --spell - Prints methods for just spell class methods\n"; - print " --spawn - Prints methods for just spawn class methods\n"; - print " --packet - Prints methods for just packet class methods\n"; - print " --stat_bonuses - Prints methods for just stat_bonuses class methods\n"; - print " --all - Prints methods for all classes\n"; - exit(1); -} - -if($#ARGV < 0) { - usage(); -} - -#::: Open File -my $filename = 'lua-api.md'; -open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; - -my $export = $ARGV[0]; -$export=~s/--//g; - -my $export_file_search = $export; - -if ($export eq "quest") { - $export_file_search = "lua_general"; -} - -my @files; -my $start_dir = "zone/"; -find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir -); -for my $file (@files) { - - #::: Skip non lua.cpp files - if($file!~/lua_/i || $file!~/cpp/i){ - next; - } - - #::: If we are specifying a specific class type, skip everything else - if ($export ne "all" && $export ne "") { - if ($file!~/$export_file_search\.cpp/i) { - next; - } - } - - @methods = (); - $split_key = ""; - $object_prefix = ""; - - #::: Client Export - if ($export=~/all|client/i && $file=~/_client/i) { - $split_key = "Client::"; - $object_prefix = "client:"; - } - - #::: Mob Export - if ($export=~/all|mob/i && $file=~/_mob/i) { - $split_key = "Mob::"; - $object_prefix = "mob:"; - } - - #::: NPC Export - if ($export=~/all|npc/i && $file=~/_npc/i) { - $split_key = "NPC::"; - $object_prefix = "npc:"; - } - - #::: Object Export - if ($export=~/all|object/i && $file=~/_object/i) { - $split_key = "Object::"; - $object_prefix = "object:"; - } - - #::: Door Export - if ($export=~/all|door/i && $file=~/_door/i) { - $split_key = "Door::"; - $object_prefix = "door:"; - } - - #::: Entity Export - if ($export=~/all|entity/i && $file=~/_entity/i) { - $split_key = "Entity::"; - $object_prefix = "entity:"; - } - - #::: Entity List Export - if ($export=~/all|entity_list/i && $file=~/_entity_list/i) { - $split_key = "EntityList::"; - $object_prefix = "entity_list:"; - } - - #::: Group - if ($export=~/all|group/i && $file=~/_group/i) { - $split_key = "Group::"; - $object_prefix = "group:"; - } - - #::: Raid - if ($export=~/all|raid/i && $file=~/_raid/i) { - $split_key = "Raid::"; - $object_prefix = "raid:"; - } - - #::: Corpse - if ($export=~/all|corpse/i && $file=~/_corpse/i) { - $split_key = "Corpse::"; - $object_prefix = "corpse:"; - } - - #::: Hateentry - if ($export=~/all|hate_entry/i && $file=~/_hate_entry/i) { - $split_key = "HateEntry::"; - $object_prefix = "hate_entry:"; - } - - #::: Spell - if ($export=~/all|spell/i && $file=~/_spell/i) { - $split_key = "Spell::"; - $object_prefix = "spell:"; - } - - #::: Spawn - if ($export=~/all|spawn/i && $file=~/_spawn/i) { - $split_key = "Spawn::"; - $object_prefix = "spawn:"; - } - - #::: StatBonuses - if ($export=~/all|stat_bonuses/i && $file=~/stat_bonuses/i) { - $split_key = "StatBonuses::"; - $object_prefix = "statbonuses:"; - } - - #::: Item - if ($export=~/all|item/i && $file=~/_item/i) { - $split_key = "Item::"; - $object_prefix = "item:"; - } - - #::: ItemInst - if ($export=~/all|iteminst/i && $file=~/_iteminst/i) { - $split_key = "ItemInst::"; - $object_prefix = "iteminst:"; - } - - #::: Inventory - if ($export=~/all|inventory/i && $file=~/_inventory/i) { - $split_key = "Inventory::"; - $object_prefix = "inventory:"; - } - - #::: Packet - if ($export=~/all|packet/i && $file=~/_packet/i) { - $split_key = "Packet::"; - $object_prefix = "packet:"; - } - - #::: Quest - if ($export=~/all|quest/i && $file=~/lua_general/i) { - $split_key = " lua_"; - $object_prefix = "eq."; - } - - #::: Open File - print "\nOpening '" . $file . "'\n"; - - if ($split_key eq "") { - next; - } - - open (FILE, $file); - while () { - chomp; - $line = $_; - - @data = split(" ", $line); - - if ((lc(substr($data[1], 0, 4)) eq "lua_") && $line!~/luabind/i && $line!~/return |#ifdef|struct /i) { - #::: Get return type - $return_type = trim($data[0]); - - @method_split = split($split_key, $line); - @method_end = split("{", $method_split[1]); - - $method = $object_prefix . trim($method_end[0]) . "; -- " . $return_type . "\n"; - - push @methods, $method; - } - } - - #::: Header - $header = $split_key; - $header =~s/:://g; - - print $fh "# " . $header . "\n"; - print $fh "```lua\n"; - - @methods = sort @methods; - foreach $method (@methods) { - print $fh $method; - print $method; - } - - print $fh "```\n\n"; -} - -close $fh; - -#::: Trim Whitespaces -sub trim { - my $string = $_[0]; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; -} \ No newline at end of file diff --git a/utils/scripts/generators/perl-doc-parser.pl b/utils/scripts/generators/perl-doc-parser.pl deleted file mode 100755 index 30cf6e116..000000000 --- a/utils/scripts/generators/perl-doc-parser.pl +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/perl - -# Author: Akkadius -# @file: perl-doc-parser.pl -# @description: Script meant to parse the source code to build the Perl API list - -use File::Find; -use Data::Dumper; - -sub usage() { - print "Usage:\n"; - print " --client - Prints methods for just client class methods\n"; - print " --mob - Prints methods for just mob class methods\n"; - print " --npc - Prints methods for just npc class methods\n"; - print " --entity - Prints methods for just entity class methods\n"; - print " --door - Prints methods for just door class methods\n"; - print " --object - Prints methods for just object class methods\n"; - print " --group - Prints methods for just group class methods\n"; - print " --raid - Prints methods for just raid class methods\n"; - print " --questitem - Prints methods for just questitem class methods\n"; - print " --corpse - Prints methods for just corpse class methods\n"; - print " --hateentry - Prints methods for just hateentry class methods\n"; - print " --quest - Prints methods for just quest class methods\n"; - print " --all - Prints methods for all classes\n"; - exit(1); -} - -if($#ARGV < 0) { - usage(); -} - -my $export = $ARGV[0]; -$export=~s/--//g; - -my $export_file_search = $export; - -if ($export eq "quest") { - $export_file_search = "embparser_api"; -} - -my @files; -my $start_dir = "zone/"; -find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir -); -for my $file (@files) { - - #::: Skip non Perl files - if($file!~/perl_|embparser_api/i){ - next; - } - - #::: If we are specifying a specific class type, skip everything else - if ($export ne "all" && $export ne "") { - if ($file!~/$export_file_search/i) { - next; - } - } - - @methods = (); - $split_key = ""; - $object_prefix = ""; - - #::: Open File - print "\nOpening '" . $file . "'\n"; - open (FILE, $file); - while () { - chomp; - $line = $_; - - if ($line=~/Perl_croak/i && $line=~/Usa/i && $line=~/::/i && $line!~/::new/i) { - - #::: Client export - if ($export=~/all|client/i && $line=~/Client::/i) { - $split_key = "Client::"; - $object_prefix = "\$client->"; - } - - #::: Mob export - if ($export=~/all|mob/i && $line=~/Mob::/i) { - $split_key = "Mob::"; - $object_prefix = "\$mob->"; - } - - #::: NPC export - if ($export=~/all|npc/i && $line=~/NPC::/i) { - $split_key = "NPC::"; - $object_prefix = "\$npc->"; - } - - #::: Corpse export - if ($export=~/all|corpse/i && $line=~/Corpse::/i) { - $split_key = "Corpse::"; - $object_prefix = "\$corpse->"; - } - - #::: Entity export - if ($export=~/all|entity/i && $line=~/EntityList::/i) { - $split_key = "EntityList::"; - $object_prefix = "\$entity_list->"; - } - - #::: Doors export - if ($export=~/all|door/i && $line=~/Doors::/i) { - $split_key = "Doors::"; - $object_prefix = "\$door->"; - } - - #::: Object export - if ($export=~/all|object/i && $line=~/Object::/i) { - $split_key = "Object::"; - $object_prefix = "\$object->"; - } - - #::: Group export - if ($export=~/all|group/i && $line=~/Group::/i) { - $split_key = "Group::"; - $object_prefix = "\$group->"; - } - - #::: Raid export - if ($export=~/all|raid/i && $line=~/Raid::/i) { - $split_key = "Raid::"; - $object_prefix = "\$raid->"; - } - - #::: Hateentry export - if ($export=~/all|hateentry/i && $line=~/HateEntry::/i) { - $split_key = "HateEntry::"; - $object_prefix = "\$hate_entry->"; - } - - #::: Questitem export - if ($export=~/all|questitem/i && $line=~/QuestItem::/i) { - $split_key = "QuestItem::"; - $object_prefix = "\$quest_item->"; - } - - #::: Quest:: exports - if ($export=~/all|quest/i && $line=~/quest::/i) { - $split_key = "quest::"; - $object_prefix = "\quest::"; - } - - #::: Split on croak usage - @data = split($split_key, $line); - $usage = trim($data[1]); - - #::: Split out param borders and get method name - @params_begin = split('\(', $usage); - $method_name = trim($params_begin[0]); - - #::: Get params string built - @params_end = split('\)', $params_begin[1]); - $params_string = trim($params_end[0]); - $params_string =~s/THIS\,//g; - $params_string =~s/THIS//g; - $params_string = trim($params_string); - - $method = $object_prefix . $method_name . "(" . lc($params_string) . ")\n"; - - push @methods, $method; - } - } - - @methods = sort @methods; - foreach $method (@methods) { - print $method; - } -} - -#::: Trim Whitespaces -sub trim { - my $string = $_[0]; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; -} \ No newline at end of file diff --git a/utils/scripts/generators/repository-generator.pl b/utils/scripts/generators/repository-generator.pl index 975f4a227..438323d66 100644 --- a/utils/scripts/generators/repository-generator.pl +++ b/utils/scripts/generators/repository-generator.pl @@ -111,6 +111,10 @@ if ($requested_table_to_generate ne "all") { @tables = ($requested_table_to_generate); } +my @cereal_enabled_tables = ( + "player_event_logs" +); + my $generated_base_repository_files = ""; my $generated_repository_files = ""; @@ -119,6 +123,7 @@ foreach my $table_to_generate (@tables) { my $table_found_in_schema = 0; my @categories = ( + "bot_tables", "content_tables", "version_tables", "state_tables", @@ -130,10 +135,8 @@ foreach my $table_to_generate (@tables) { # These tables don't have a typical schema my @table_ignore_list = ( "character_enabledtasks", - "grid", # Manually created - "grid_entries", # Manually created + # "grid", # Manually created # "tradeskill_recipe", # Manually created - # "character_recipe_list", # Manually created "guild_bank", "inventory_versions", "raid_leaders", @@ -157,6 +160,11 @@ foreach my $table_to_generate (@tables) { $table_found_in_schema = 0; } + my $cereal_enabled = 0; + if ($table_to_generate ~~ @cereal_enabled_tables) { + $cereal_enabled = 1; + } + if ($table_found_in_schema == 0 && ($requested_table_to_generate eq "" || $requested_table_to_generate eq "all")) { print "Table [$table_to_generate] not found in schema, skipping\n"; next; @@ -190,12 +198,13 @@ foreach my $table_to_generate (@tables) { my $column_name = $row[0]; my $column_name_formatted = format_column_name_for_cpp_var($column_name); my $data_type = $row[2]; + my $column_type = $row[3]; if ($longest_column_length < length($column_name_formatted)) { $longest_column_length = length($column_name_formatted); } - my $struct_data_type = translate_mysql_data_type_to_c($data_type); + my $struct_data_type = translate_mysql_data_type_to_c($data_type, $column_type); if ($longest_data_type_length < length($struct_data_type)) { $longest_data_type_length = length($struct_data_type); @@ -210,6 +219,7 @@ foreach my $table_to_generate (@tables) { my $column_names_quoted = ""; my $select_column_names_quoted = ""; my $table_struct_columns = ""; + my $cereal_columns = ""; my $update_one_entries = ""; my $all_entries = ""; my $index = 0; @@ -254,13 +264,17 @@ foreach my $table_to_generate (@tables) { $default_value = 0; } - my $struct_data_type = translate_mysql_data_type_to_c($data_type); + my $struct_data_type = translate_mysql_data_type_to_c($data_type, $column_type); # struct $table_struct_columns .= sprintf("\t\t\%-${longest_data_type_length}s %s;\n", $struct_data_type, $column_name_formatted); + if ($cereal_enabled == 1) { + $cereal_columns .= sprintf("\t\t\t\tCEREAL_NVP(%s),\n", $column_name_formatted); + } + # new entity - $default_entries .= sprintf("\t\tentry.%-${longest_column_length}s = %s;\n", $column_name_formatted, $default_value); + $default_entries .= sprintf("\t\te.%-${longest_column_length}s = %s;\n", $column_name_formatted, $default_value); # column names (string) $column_names_quoted .= sprintf("\t\t\t\"%s\",\n", format_column_name_for_mysql($column_name)); @@ -273,53 +287,68 @@ foreach my $table_to_generate (@tables) { # update one if ($extra ne "auto_increment") { - my $query_value = sprintf('\'" + EscapeString(%s_entry.%s) + "\'");', $table_name, $column_name_formatted); + my $query_value = sprintf('\'" + Strings::Escape(e.%s) + "\'");', $column_name_formatted); if ($data_type =~ /int|float|double|decimal/) { - $query_value = sprintf('" + std::to_string(%s_entry.%s));', $table_name, $column_name_formatted); + $query_value = sprintf('" + std::to_string(e.%s));', $column_name_formatted); } elsif ($data_type =~ /datetime/) { - $query_value = sprintf('FROM_UNIXTIME(" + (%s_entry.%s > 0 ? std::to_string(%s_entry.%s) : "null") + ")");', $table_name, $column_name_formatted, $table_name, $column_name_formatted); + $query_value = sprintf('FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")");', $column_name_formatted, $column_name_formatted); } $update_one_entries .= sprintf( - "\t\t" . 'update_values.push_back(columns[%s] + " = %s' . "\n", + "\t\t" . 'v.push_back(columns[%s] + " = %s' . "\n", $index, $query_value ); } # insert - my $value = sprintf("\"'\" + EscapeString(%s_entry.%s) + \"'\"", $table_name, $column_name_formatted); + my $value = sprintf("\"'\" + Strings::Escape(e.%s) + \"'\"", $column_name_formatted); if ($data_type =~ /int|float|double|decimal/) { - $value = sprintf('std::to_string(%s_entry.%s)', $table_name, $column_name_formatted); + $value = sprintf('std::to_string(e.%s)', $column_name_formatted); } elsif ($data_type =~ /datetime/) { - $value = sprintf('"FROM_UNIXTIME(" + (%s_entry.%s > 0 ? std::to_string(%s_entry.%s) : "null") + ")"', $table_name, $column_name_formatted, $table_name, $column_name_formatted); + $value = sprintf('"FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")"', $column_name_formatted, $column_name_formatted); } - $insert_one_entries .= sprintf("\t\tinsert_values.push_back(%s);\n", $value); - $insert_many_entries .= sprintf("\t\t\tinsert_values.push_back(%s);\n", $value); + $insert_one_entries .= sprintf("\t\tv.push_back(%s);\n", $value); + $insert_many_entries .= sprintf("\t\t\tv.push_back(%s);\n", $value); # find one / all (select) - if ($data_type =~ /bigint/) { - $all_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = strtoll(row[%s], nullptr, 10);\n", $column_name_formatted, $index); - $find_one_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = strtoll(row[%s], nullptr, 10);\n", $column_name_formatted, $index); + + if ($column_type =~ /unsigned/) { + if ($data_type =~ /bigint/) { + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoull(row[%s], nullptr, 10);\n", $column_name_formatted, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoull(row[%s], nullptr, 10);\n", $column_name_formatted, $index); + } + elsif ($data_type =~ /int/) { + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = static_cast<%s>(strtoul(row[%s], nullptr, 10));\n", $column_name_formatted, $struct_data_type, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = static_cast<%s>(strtoul(row[%s], nullptr, 10));\n", $column_name_formatted, $struct_data_type, $index); + } + } + elsif ($data_type =~ /bigint/) { + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s], nullptr, 10);\n", $column_name_formatted, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s], nullptr, 10);\n", $column_name_formatted, $index); } elsif ($data_type =~ /datetime/) { - $all_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index); - $find_one_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index); + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index); } elsif ($data_type =~ /int/) { - $all_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = atoi(row[%s]);\n", $column_name_formatted, $index); - $find_one_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = atoi(row[%s]);\n", $column_name_formatted, $index); + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = static_cast<%s>(atoi(row[%s]));\n", $column_name_formatted, $struct_data_type, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = static_cast<%s>(atoi(row[%s]));\n", $column_name_formatted, $struct_data_type, $index); } - elsif ($data_type =~ /float|double|decimal/) { - $all_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = static_cast(atof(row[%s]));\n", $column_name_formatted, $index); - $find_one_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = static_cast(atof(row[%s]));\n", $column_name_formatted, $index); + elsif ($data_type =~ /float|decimal/) { + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtof(row[%s], nullptr);\n", $column_name_formatted, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtof(row[%s], nullptr);\n", $column_name_formatted, $index); + } + elsif ($data_type =~ /double/) { + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtod(row[%s], nullptr);\n", $column_name_formatted, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtod(row[%s], nullptr);\n", $column_name_formatted, $index); } else { - $all_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = row[%s] ? row[%s] : \"\";\n", $column_name_formatted, $index, $index); - $find_one_entries .= sprintf("\t\t\tentry.%-${longest_column_length}s = row[%s] ? row[%s] : \"\";\n", $column_name_formatted, $index, $index); + $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? row[%s] : \"\";\n", $column_name_formatted, $index, $index); + $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? row[%s] : \"\";\n", $column_name_formatted, $index, $index); } # print $column_name . "\n"; @@ -385,6 +414,22 @@ foreach my $table_to_generate (@tables) { $database_connection = "content_db"; } + my $additional_includes = ""; + if ($cereal_enabled) { + chomp($cereal_columns); + # remove the last comma "," from string + $cereal_columns = substr($cereal_columns, 0, -1); + + $table_struct_columns .= " + // cereal + template + void serialize(Archive &ar) + { + ar(\n" . $cereal_columns . "\n\t\t\t);\n\t\t}"; + + $additional_includes .= "#include "; + } + chomp($column_names_quoted); chomp($select_column_names_quoted); chomp($table_struct_columns); @@ -420,6 +465,7 @@ foreach my $table_to_generate (@tables) { $new_base_repository =~ s/\{\{INSERT_MANY_ENTRIES}}/$insert_many_entries/g; $new_base_repository =~ s/\{\{ALL_ENTRIES}}/$all_entries/g; $new_base_repository =~ s/\{\{GENERATED_DATE}}/$generated_date/g; + $new_base_repository =~ s/\{\{ADDITIONAL_INCLUDES}}/$additional_includes/g; # Extended repository my $new_repository = $repository_template; @@ -493,23 +539,41 @@ sub trim { sub translate_mysql_data_type_to_c { my $mysql_data_type = $_[0]; + my $mysql_column_type = $_[1]; my $struct_data_type = "std::string"; - if ($mysql_data_type =~ /tinyint/) { - $struct_data_type = 'int'; - } - elsif ($mysql_data_type =~ /smallint/) { - $struct_data_type = 'int'; + if ($mysql_column_type =~ /unsigned/) { + if ($mysql_data_type =~ /bigint/) { + $struct_data_type = 'uint64_t'; + } + elsif ($mysql_data_type =~ /tinyint/) { + $struct_data_type = 'uint8_t'; + } + elsif ($mysql_data_type =~ /smallint/) { + $struct_data_type = 'uint16_t'; + } + elsif ($mysql_data_type =~ /int/) { + $struct_data_type = 'uint32_t'; + } } elsif ($mysql_data_type =~ /bigint/) { - $struct_data_type = 'int64'; + $struct_data_type = 'int64_t'; + } + elsif ($mysql_data_type =~ /tinyint/) { + $struct_data_type = 'int8_t'; + } + elsif ($mysql_data_type =~ /smallint/) { + $struct_data_type = 'int16_t'; } elsif ($mysql_data_type =~ /int/) { - $struct_data_type = 'int'; + $struct_data_type = 'int32_t'; } - elsif ($mysql_data_type =~ /float|double|decimal/) { + elsif ($mysql_data_type =~ /float|decimal/) { $struct_data_type = 'float'; } + elsif ($mysql_data_type =~ /double/) { + $struct_data_type = 'double'; + } elsif ($mysql_data_type =~ /datetime/) { $struct_data_type = 'time_t'; } diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 5cef4ab8b..49397e564 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -64,11 +64,10 @@ if [ ! -f ./install_variables.txt ]; then echo "" echo "" groupadd eqemu - useradd -g eqemu -d $eqemu_server_directory eqemu + useradd -g eqemu -m -d $eqemu_server_directory eqemu passwd eqemu - #::: Make server directory and go to it - mkdir $eqemu_server_directory + #::: Go to server directory cd $eqemu_server_directory #::: Setup MySQL root user PW diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 8b17eba27..1302574d3 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -437,6 +437,40 @@ 9181|2022_05_03_task_activity_goal_match_list.sql|SHOW COLUMNS FROM `task_activities` LIKE 'goal_match_list'|empty| 9182|2022_05_02_npc_types_int64.sql|SHOW COLUMNS FROM `npc_types` LIKE 'hp'|missing|bigint 9183|2022_05_07_merchant_data_buckets.sql|SHOW COLUMNS FROM `merchantlist` LIKE 'bucket_comparison'|empty +9184|2022_05_21_schema_consistency.sql|SELECT * FROM db_version WHERE version >= 9184|empty| +9185|2022_05_07_discord_webhooks.sql|SHOW TABLES LIKE 'discord_webhooks'|empty| +9186|2022_07_09_zone_expansion_deprecate.sql|SHOW COLUMNS FROM `zone` LIKE 'expansion'|not_empty| +9187|2022_07_09_task_zone_version_matching.sql|SHOW COLUMNS FROM `task_activities` LIKE 'zone_version'|empty| +9188|2022_07_14_zone_expansion_revert.sql|SHOW COLUMNS FROM `zone` LIKE 'expansion'|empty| +9189|2022_07_10_character_task_rewarded.sql|SHOW COLUMNS FROM `character_tasks` LIKE 'was_rewarded'|empty| +9190|2022_07_13_task_reward_points.sql|SHOW COLUMNS FROM `tasks` LIKE 'reward_points'|empty| +9191|2022_07_28_gm_state_changes.sql|SHOW COLUMNS FROM `account` LIKE 'invulnerable'|empty| +9192|2022_07_13_task_lock_activity.sql|SHOW COLUMNS FROM `tasks` LIKE 'lock_activity_id'|empty| +9193|2022_07_16_task_timer_groups.sql|SHOW COLUMNS FROM `tasks` LIKE 'replay_timer_group'|empty| +9194|2022_07_23_dz_switch_id.sql|SHOW COLUMNS FROM `doors` LIKE 'dz_switch_id'|empty| +9195|2022_07_23_dz_templates.sql|SHOW TABLES like 'dynamic_zone_templates'|empty| +9196|2022_07_30_merchantlist_temp.sql|SHOW COLUMNS FROM `merchantlist_temp` LIKE 'zone_id'|empty| +9197|2022_08_01_drop_expansion_account.sql|SHOW COLUMNS FROM `account` LIKE 'expansion'|not_empty| +9198|2022_08_14_exp_modifier_instance_versions.sql|SHOW COLUMNS FROM `character_exp_modifiers` LIKE 'instance_version'|empty| +9199|2022_08_08_task_req_activity_id.sql|SHOW COLUMNS FROM `task_activities` LIKE 'req_activity_id'|empty| +9200|2022_08_19_zone_expansion_consistency.sql|SELECT * FROM db_version WHERE version >= 9200|empty| +9201|2022_08_22_npc_types_heroic_strikethrough.sql|SHOW COLUMNS FROM `npc_types` LIKE 'heroic_strikethrough'|empty| +9202|2022_08_24_task_activities_step.sql|SHOW COLUMNS FROM `task_activities` LIKE 'step'|contains|unsigned +9203|2022_08_07_replace_task_goals.sql|SHOW COLUMNS FROM `task_activities` LIKE 'item_id'|empty| +9204|2022_09_02_faction_association.sql|SHOW TABLES LIKE 'faction_association'|empty| +9205|2022_09_03_fix_starting_point_heading.sql|SELECT * FROM db_version WHERE version >= 9205|empty| +9206|2022_09_03_fix_door_destination_headings.sql|SELECT * FROM db_version WHERE version >= 9206|empty| +9207|2022_09_03_fix_zone_point_heading_data.sql|SELECT * FROM db_version WHERE version >= 9207|empty| +9208|2022_09_25_task_concat_matchlists.sql|SHOW COLUMNS FROM `task_activities` LIKE 'npc_id'|not_empty| +9209|2022_09_28_discord_webhooks.sql|SHOW COLUMNS FROM `logsys_categories` LIKE 'log_to_discord'|empty| +9210|2022_10_11_fix_misty_pok_stone.sql|select * from doors where id = 2040 and `name` = 'POKRVPORT500' and client_version_mask = 4294967232|empty| +9211|2022_10_14_fix_neriak_pok_stone.sql|select * from doors where id = 2057 and `name` = 'POKNRKPORT500' and client_version_mask = 4294967232|empty| +9212|2022_10_14_fix_misty_pok_stone.sql|select * from doors where id = 2040 and `name` = 'POKRVPORT500' and dest_zone = 'misty'|empty| +9213|2022_12_24_npc_keeps_sold_items.sql|SHOW COLUMNS FROM `npc_types` LIKE 'keeps_sold_items'|empty| +9214|2022_12_24_character_exp_toggle.sql|SHOW COLUMNS FROM `character_data` LIKE 'exp_enabled'|empty| +9215|2023_01_08_zone_max_level.sql|SHOW COLUMNS FROM `zone` LIKE 'max_level'|empty| +9216|2023_01_15_merc_data.sql|SHOW TABLES LIKE 'mercs'|empty| +9217|2023_01_15_chatchannel_reserved_names.sql|SHOW TABLES LIKE 'chatchannel_reserved_names'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 221020683..c67c33969 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -27,6 +27,14 @@ 9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty| 9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty| 9028|2021_06_04_bot_create_combinations.sql|SHOW TABLES LIKE 'bot_create_combinations'|empty| +9029|2022_06_21_bot_groups_auto_spawn.sql|SHOW COLUMNS from `bot_groups` LIKE 'auto_spawm'|empty| +9030|2022_10_27_bot_data_buckets.sql|SHOW COLUMNS FROM `bot_spells_entries` LIKE 'bucket_name'|empty| +9031|2022_11_13_bot_spells_entries.sql|SELECT * FROM db_version WHERE bots_version >= 9031|empty| +9032|2022_11_07_bot_expansion_bitmask.sql|SHOW COLUMNS FROM `bot_data` LIKE 'expansion_bitmask'|empty| +9033|2022_11_19_bot_spell_settings.sql|SHOW TABLES LIKE 'bot_spell_settings'|empty| +9034|2022_12_02_bot_spell_settings.sql|SHOW COLUMNS FROM `bot_data` LIKE 'enforce_spell_settings'|empty| +9035|2022_12_04_bot_archery.sql|SHOW COLUMNS FROM `bot_data` LIKE 'archery_setting'|empty| +9036|2023_01_19_drop_bot_views.sql|SHOW TABLES LIKE 'vw_groups'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2022_06_21_bot_groups_auto_spawn.sql b/utils/sql/git/bots/required/2022_06_21_bot_groups_auto_spawn.sql new file mode 100644 index 000000000..4b320e368 --- /dev/null +++ b/utils/sql/git/bots/required/2022_06_21_bot_groups_auto_spawn.sql @@ -0,0 +1 @@ +ALTER TABLE `bot_groups` ADD COLUMN `auto_spawn` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `group_name`; \ No newline at end of file diff --git a/utils/sql/git/bots/required/2022_10_27_bot_data_buckets.sql b/utils/sql/git/bots/required/2022_10_27_bot_data_buckets.sql new file mode 100644 index 000000000..a46efa902 --- /dev/null +++ b/utils/sql/git/bots/required/2022_10_27_bot_data_buckets.sql @@ -0,0 +1,4 @@ +ALTER TABLE `bot_spells_entries` +ADD COLUMN `bucket_name` varchar(100) NOT NULL DEFAULT '' AFTER `max_hp`, +ADD COLUMN `bucket_value` varchar(100) NOT NULL DEFAULT '' AFTER `bucket_name`, +ADD COLUMN `bucket_comparison` tinyint UNSIGNED NULL DEFAULT 0 AFTER `bucket_value`; \ No newline at end of file diff --git a/utils/sql/git/bots/required/2022_11_07_bot_expansion_bitmask.sql b/utils/sql/git/bots/required/2022_11_07_bot_expansion_bitmask.sql new file mode 100644 index 000000000..c46686bb4 --- /dev/null +++ b/utils/sql/git/bots/required/2022_11_07_bot_expansion_bitmask.sql @@ -0,0 +1,2 @@ +ALTER TABLE `bot_data` +ADD COLUMN `expansion_bitmask` int(11) NOT NULL DEFAULT -1 AFTER `stop_melee_level`; diff --git a/utils/sql/git/bots/required/2022_11_13_bot_spells_entries.sql b/utils/sql/git/bots/required/2022_11_13_bot_spells_entries.sql new file mode 100644 index 000000000..6d60e216f --- /dev/null +++ b/utils/sql/git/bots/required/2022_11_13_bot_spells_entries.sql @@ -0,0 +1,10 @@ +UPDATE bot_spells_entries SET bucket_comparison = 0 WHERE bucket_comparison IS NULL; +UPDATE bot_spells_entries SET min_hp = 0 WHERE min_hp IS NULL; +UPDATE bot_spells_entries SET max_hp = 0 WHERE max_hp IS NULL; +UPDATE bot_spells_entries SET resist_adjust = 0 WHERE resist_adjust IS NULL; + +ALTER TABLE `bot_spells_entries` +MODIFY COLUMN `resist_adjust` int(11) NOT NULL DEFAULT 0 AFTER `priority`, +MODIFY COLUMN `min_hp` smallint(5) NOT NULL DEFAULT 0 AFTER `resist_adjust`, +MODIFY COLUMN `max_hp` smallint(5) NOT NULL DEFAULT 0 AFTER `min_hp`, +MODIFY COLUMN `bucket_comparison` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `bucket_value`; diff --git a/utils/sql/git/bots/required/2022_11_19_bot_spell_settings.sql b/utils/sql/git/bots/required/2022_11_19_bot_spell_settings.sql new file mode 100644 index 000000000..0224034aa --- /dev/null +++ b/utils/sql/git/bots/required/2022_11_19_bot_spell_settings.sql @@ -0,0 +1,12 @@ +CREATE TABLE `bot_spell_settings` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `bot_id` int(11) NOT NULL DEFAULT 0, + `spell_id` smallint(5) NOT NULL DEFAULT 0, + `priority` smallint(5) NOT NULL DEFAULT 0, + `min_level` smallint(5) unsigned NOT NULL DEFAULT 0, + `max_level` smallint(5) unsigned NOT NULL DEFAULT 255, + `min_hp` smallint(5) NOT NULL DEFAULT 0, + `max_hp` smallint(5) NOT NULL DEFAULT 0, + `is_enabled` tinyint(1) unsigned NOT NULL DEFAULT 1, + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/utils/sql/git/bots/required/2022_12_02_bot_spell_settings.sql b/utils/sql/git/bots/required/2022_12_02_bot_spell_settings.sql new file mode 100644 index 000000000..28e825da6 --- /dev/null +++ b/utils/sql/git/bots/required/2022_12_02_bot_spell_settings.sql @@ -0,0 +1,5 @@ +ALTER TABLE `bot_data` +ADD COLUMN `enforce_spell_settings` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `expansion_bitmask`; + +ALTER TABLE `bot_spell_settings` DROP `min_level`; +ALTER TABLE `bot_spell_settings` DROP `max_level`; diff --git a/utils/sql/git/bots/required/2022_12_04_bot_archery.sql b/utils/sql/git/bots/required/2022_12_04_bot_archery.sql new file mode 100644 index 000000000..ae05f4132 --- /dev/null +++ b/utils/sql/git/bots/required/2022_12_04_bot_archery.sql @@ -0,0 +1,2 @@ +ALTER TABLE `bot_data` +ADD COLUMN `archery_setting` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `enforce_spell_settings`; \ No newline at end of file diff --git a/utils/sql/git/bots/required/2023_01_19_drop_bot_views.sql b/utils/sql/git/bots/required/2023_01_19_drop_bot_views.sql new file mode 100644 index 000000000..7ca7cbf3b --- /dev/null +++ b/utils/sql/git/bots/required/2023_01_19_drop_bot_views.sql @@ -0,0 +1,6 @@ +DROP VIEW vw_bot_groups; +DROP VIEW vw_bot_character_mobs; +DROP VIEW vw_groups; +DROP VIEW vw_guild_members; + +DROP TABLE bot_guild_members; diff --git a/utils/sql/git/optional/2022_09_02_faction_association.sql b/utils/sql/git/optional/2022_09_02_faction_association.sql new file mode 100644 index 000000000..ab5b9f9ad --- /dev/null +++ b/utils/sql/git/optional/2022_09_02_faction_association.sql @@ -0,0 +1,371 @@ +INSERT INTO `faction_association` VALUES (218,217,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (219,262,1,304,-0.5,273,-1,291,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (220,281,0.25,296,-0.15,330,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (221,262,-0.15,296,0.1,341,-0.25,230,0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (222,308,-0.1,235,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (223,291,-0.15,230,0.15,262,-0.15,273,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (225,355,-0.05,263,-0.1,312,-0.05,475,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (226,279,1,335,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (227,274,1,293,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (228,274,-1,261,1,232,1,337,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (229,281,1,291,0.75,336,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (230,262,-0.15,273,0.15,223,0.1,221,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (231,266,0.1,265,-0.15,267,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (232,228,0.15,261,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (233,226,0.1,265,-0.15,267,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (234,312,-0.05,246,-0.15,270,0,326,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (235,222,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (236,334,0.1,370,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (237,308,0.25,251,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (238,245,-0.1,255,-0.1,240,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (239,303,0.15,278,-0.15,275,-0.15,245,-0.15,1522,-2,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (240,288,0.15,255,0.15,238,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (241,223,0.05,292,-0.05,336,0.05,329,0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (242,266,0.15,265,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (244,262,-0.05,320,-0.25,263,-0.1,329,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (245,238,-0.15,239,-0.05,255,0.15,333,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (246,279,0.25,226,0.25,310,0.25,234,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (247,318,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (248,326,0.75,312,0.75,441,-0.05,313,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (249,323,-0.15,319,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (254,267,0.15,266,0.1,265,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (255,288,0.25,333,0.25,238,-0.25,1604,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (256,313,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (257,441,-0.1,248,-0.1,259,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (258,1732,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (259,451,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (261,228,0.5,312,-0.15,308,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (262,219,0.15,230,-0.15,223,-0.25,291,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (263,286,0.15,355,0.1,292,0.15,334,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (264,268,0.25,444,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (265,242,-1,254,-1,231,-1,233,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (266,267,1,265,-1,304,-0.5,277,-0.5,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (267,266,0.15,265,-0.15,289,0.75,277,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (269,302,0.15,272,0.15,324,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (270,326,-0.15,311,-0.05,1522,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (271,281,-0.15,296,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (272,302,0.25,343,0.15,324,-0.25,262,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (274,312,1,304,-0.5,228,-1,285,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (275,279,0.25,246,0.15,239,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (276,246,0.1,326,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (278,303,-1,270,0.75,239,-0.75,279,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (280,221,-1,341,0.75,262,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (281,271,-0.15,330,-0.15,362,0.2,311,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (282,323,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (284,281,0.15,262,0.15,304,-0.05,285,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (285,279,-0.25,426,1,284,-0.25,304,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (286,263,1,292,1,300,1,225,-0.5,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (287,255,-0.75,333,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (289,266,0.75,267,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (290,312,0.2,322,-0.2,293,0.1,274,0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (291,223,-0.2,219,0.15,229,0.1,262,0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (292,241,0.05,263,0.15,286,0.15,336,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (293,274,0.75,312,0.75,227,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (296,271,0.25,239,0.25,238,0.25,221,0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (297,274,0.75,227,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (298,226,0.25,265,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (300,286,0.1,263,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (302,272,0.25,306,-0.15,262,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (304,284,-0.25,285,-0.15,318,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (306,262,-0.05,309,-0.05,272,-0.05,291,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (307,441,-0.05,451,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (308,261,-0.15,222,-0.25,235,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (309,262,0.15,361,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (310,279,0.15,246,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (311,262,0.2,230,-0.15,330,-0.15,281,0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (312,274,0.15,293,0.15,290,0.25,232,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (313,248,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (315,441,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (317,251,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (319,249,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (320,327,0.2,328,0.25,311,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (321,262,-0.15,306,0.15,345,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (322,223,-0.05,379,-0.05,241,0.05,244,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (323,255,0.1,333,0.1,288,0.1,322,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (324,262,-0.25,272,-0.75,343,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (326,270,-0.15,325,0.1,276,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (327,328,0.15,223,-0.15,336,-0.15,244,-0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (328,320,0.75,327,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (329,336,0.75,304,-0.25,332,1,331,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (330,336,0.15,281,-0.1,362,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (331,332,1,329,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (332,329,0.15,331,0.15,230,0.05,330,0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (333,245,0.15,255,0.15,238,-0.1,287,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (334,236,0.15,270,0.1,370,0.25,326,-0.01,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (336,229,1,329,0.1,230,0.05,330,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (337,228,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (338,228,0.75,337,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (340,278,0.15,362,-0.35,226,341,0,1522,-4,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (341,280,0.3,262,0.5,221,-0.25,219,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (342,221,-0.25,262,0.15,296,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (343,302,0.2,272,0.2,366,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (345,262,0.25,341,0.15,280,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (346,330,0.25,281,0.25,362,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (355,286,0.1,292,0.15,324,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (361,281,0.15,309,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (362,330,-0.1,281,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (363,239,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (364,332,-0.15,269,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (365,263,-0.1,475,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (366,345,-0.1,262,-0.1,332,-0.05,223,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (370,236,0.15,270,0.15,1522,-1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (373,332,-0.1,345,-0.4,366,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (375,281,-0.1,263,-0.1,361,-0.1,346,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (378,263,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (379,312,-0.05,322,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (398,312,-0.05,326,-0.05,255,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (402,403,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (403,402,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (405,406,1,429,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (406,405,0.25,448,-0.1,419,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (407,460,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (412,312,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (415,416,-0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (416,415,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (417,418,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (418,417,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (419,448,0.25,406,-0.5,430,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (426,285,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (429,448,1,436,-0.5,405,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (430,436,0.25,448,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (431,432,-0.1,439,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (432,431,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (433,430,0.1,304,0.1,315,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (435,429,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (436,430,1,429,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (438,226,2,310,2,246,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (439,431,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (440,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (441,440,0.25,445,0.25,442,0.25,444,0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (442,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (443,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (444,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (445,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (446,441,-0.2,443,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (448,419,0.25,429,0.25,430,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (451,307,1,259,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (454,285,-0.05,318,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (455,304,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (456,459,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (459,456,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (462,464,0.1,463,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (463,464,-0.1,462,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (464,430,-0.1,462,0.1,304,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (467,430,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (469,226,2,310,2,246,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (471,267,-0.1,265,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (473,298,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (474,365,0.1,225,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (475,365,-0.1,225,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1007,1013,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1010,1013,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1013,1007,-0.1,1010,-0.1,1016,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1016,1013,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1020,1021,1,1022,-1,1023,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1021,1020,1,1022,-1,1023,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1022,1023,1,1020,-1,1021,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1023,1022,1,1020,-1,1021,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1024,1025,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1025,1024,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1026,1027,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1027,1026,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1028,1029,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1029,1028,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1030,1031,1,1032,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1031,1030,1,1032,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1032,1030,1,1031,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1033,1035,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1034,1035,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1035,1033,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1048,1051,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1050,1051,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1051,1050,-1,1048,-1,1049,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1052,1058,1,1053,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1053,1052,-1,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1054,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1055,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1056,1055,-1,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1058,1054,-1,1055,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1063,330,1,229,1,281,1,362,1,271,1,311,1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1068,1078,-1,1080,-1,1072,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1069,1068,-1,1073,-1,1077,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1070,1071,-1,1077,-1,1078,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1071,1070,-1,1077,-1,1078,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1072,1068,-1,1074,-1,1075,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1073,1069,-1,1074,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1074,1072,-1,1073,-1,1075,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1075,1072,-1,1074,-1,1079,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1076,1078,-1,1079,-1,1080,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1077,1069,-1,1070,-1,1071,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1078,1070,-1,1071,-1,1076,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1079,1075,-1,1076,-1,1080,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1080,1068,-1,1076,-1,1079,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1085,1086,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1086,1085,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1088,1085,-1,1089,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1089,1085,-1,1088,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1093,1110,-1,1094,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1094,1093,1,1095,-1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1095,1094,-1,1129,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1100,1103,-1,1104,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1101,1103,-1,1105,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1107,1108,1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1108,1107,1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1109,1107,-1,1108,-1,1110,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1110,1109,1,1111,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1111,1109,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1112,1107,-2,1108,-2,1109,-10,1110,-10,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1113,1107,-1,1108,-1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1114,1109,-1,1110,-5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1115,1107,-1,1108,-1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1116,1109,1,1110,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1120,1121,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1121,1120,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1123,1124,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1124,1123,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1125,1126,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1126,1125,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1140,1142,-1,1144,-1.5,1141,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1141,1142,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1142,1141,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1143,1145,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1145,1143,2.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1146,1147,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1147,1146,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1148,1149,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1149,1148,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1166,1244,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1175,1135,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1176,1134,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1181,1183,-0.1,1184,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1186,1623,1,430,-1,436,-1,1188,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1192,1183,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1193,1184,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1194,1189,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1195,1191,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1197,1185,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1198,1185,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1200,1199,0.1,1221,0.1,1222,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1201,1199,-0.1,1200,-0.1,1222,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1202,1203,-0.1,1222,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1204,1223,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1205,1223,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1209,1210,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1210,1209,-1,1226,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1211,1212,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1212,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1213,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1216,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1220,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1221,1224,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1232,1233,-1,1234,1,1235,1,1238,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1233,1232,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1234,1235,1,1232,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1235,1234,1,1232,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1237,1232,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1238,1232,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1243,1242,-1,1241,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1244,1166,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1483,1484,1,1485,1,1487,1,1502,-0.1,1503,-0.1,1504,-0.1,1561,-0.1,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1484,1485,-0.1,1486,-0.1,1483,0.05,1541,1,1503,-0.5,1504,-0.1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1485,1484,-0.1,1486,-0.1,1483,0.05,1542,-0.1,1504,-0.25,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1486,1485,-0.1,1487,-0.1,1483,0.05,1561,-0.5,1505,-0.1,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1487,1486,-0.1,1485,-0.1,1483,0.05,1502,-0.25,1505,-0.25,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1488,1484,-0.1,1486,-0.1,1485,-0.1,1487,-0.1,1542,0.1,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1499,1484,0.1,1486,0.1,1485,0.1,1487,0.1,1502,-0.5,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1500,1501,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1501,1500,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1502,1503,0.1,1504,0.1,1499,-0.5,1483,-0.1,1487,-0.1,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1503,1502,0.1,1504,0.1,1505,-0.1,1506,-0.1,1483,-0.1,1484,-0.5,1485,-0.1,1541,-0.1,0,0,0,0); +INSERT INTO `faction_association` VALUES (1504,1502,0.1,1503,0.1,1483,-0.1,1484,-0.1,1485,-0.25,1541,-0.25,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1505,1503,-0.1,1506,-0.1,1486,-0.1,1487,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1506,1503,-0.1,1505,-0.1,1507,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1507,1506,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1508,1510,0.1,1511,0.1,1512,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1509,1510,1,1542,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1510,1509,1,1508,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1511,1508,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1512,1508,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1519,1513,-0.1,1500,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1520,1521,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1521,1520,-0.1,1501,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1524,1502,0.1,1504,0.1,1505,-0.1,1506,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1526,430,0.25,304,0.25,448,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1527,1483,-0.1,1484,-0.1,1485,-0.1,1486,-0.1,1487,-0.1,1499,-0.1,1488,0.1,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1528,1483,-0.1,1484,-0.1,1485,-0.1,1486,-0.1,1487,-0.1,1499,-0.1,1488,0.1,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1535,1536,1,1562,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1536,1535,1,1562,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1538,1505,-0.1,1502,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1541,1484,1,1485,-0.1,1483,0.05,1486,-0.1,1503,-0.25,1504,-0.1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1542,1559,0.1,1510,-0.5,1511,-0.5,1512,-0.5,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1543,1544,0.1,1545,0.1,1546,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1544,1543,0.1,1546,0.1,1545,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1545,1543,0.1,1546,0.1,1544,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1546,1543,0.1,1545,0.1,1544,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1548,1549,0.1,1550,0.1,1551,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1549,1548,0.1,1550,0.1,1551,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1550,1548,0.1,1549,0.1,1551,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1551,1550,-0.1,1548,-0.1,1549,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1555,1556,0.1,1483,-1,1484,-1,1487,-1,1486,-1,1541,-1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1556,1555,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1557,1556,0.1,1555,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1559,1509,-0.1,1542,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1562,1535,0.5,1536,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1563,1563,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1570,1506,0.5,1507,0.1,1521,-0.1,1501,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1571,1520,-0.1,1501,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1580,1579,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1597,272,0.5,302,0.5,262,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1599,1597,-1,272,-0.5,302,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1601,1597,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1602,1597,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1604,255,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1607,1608,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1609,1618,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1610,1614,1,1609,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1611,1615,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1612,1616,1,1609,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1613,1617,1,1609,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1620,1597,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1621,1619,-0.2,1609,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1622,316,-0.1,326,-0.1,310,-0.1,246,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1623,430,-0.1,419,0.2,448,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1626,1625,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1627,1628,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1628,1627,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1665,251,-0.25,1593,-0.5,315,1,441,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1718,1709,1,1716,1,1717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1719,1709,1,1716,1,1717,1,1718,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1720,1709,1,1716,1,1717,1,1718,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1725,441,1,440,1,445,1,444,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1728,451,-1,1729,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1729,451,-0.66,1728,0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1732,258,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1763,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1764,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1765,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1766,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1767,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1768,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1770,1771,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1771,1770,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1778,1779,0.5,1780,-0.5,1781,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1779,1778,0.5,1780,-0.5,1781,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1784,1785,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1786,1787,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1787,1786,1,1788,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1788,1786,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1789,1791,-0.6,1795,0.33,1793,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1790,1789,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1791,1789,-0.6,1793,0.33,1795,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1792,1791,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1793,1795,-0.6,1791,0.33,1789,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1794,1793,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1795,1793,-0.6,1789,0.33,1791,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1796,1795,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1798,1799,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1799,1775,-1,1788,-1,1799,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1801,1802,-1,1803,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1802,1801,-1,1803,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1803,1801,-1,1802,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1804,1817,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); diff --git a/utils/sql/git/optional/2022_11_22_bugs_table_migration.sql b/utils/sql/git/optional/2022_11_22_bugs_table_migration.sql new file mode 100644 index 000000000..bf9752871 --- /dev/null +++ b/utils/sql/git/optional/2022_11_22_bugs_table_migration.sql @@ -0,0 +1 @@ +INSERT INTO bug_reports (zone, character_name, ui_path, pos_x, pos_y, pos_z, category_name, optional_info_mask, target_name, bug_report, report_datetime, bug_status) SELECT zone, `name`, ui, x, y, z, `type`, flag, target, bug, `date`, status FROM bugs; diff --git a/utils/sql/git/optional/2023_01_15_merc_liaisons.sql b/utils/sql/git/optional/2023_01_15_merc_liaisons.sql new file mode 100644 index 000000000..7d1505de9 --- /dev/null +++ b/utils/sql/git/optional/2023_01_15_merc_liaisons.sql @@ -0,0 +1,3 @@ +UPDATE `npc_types` +SET `class` = 71 +WHERE `lastname` LIKE '%Mercenary Liaison'; diff --git a/utils/sql/git/required/2022_04_30_hp_regen_per_second.sql b/utils/sql/git/required/2022_04_30_hp_regen_per_second.sql index cc2d85a47..6f61ae838 100644 --- a/utils/sql/git/required/2022_04_30_hp_regen_per_second.sql +++ b/utils/sql/git/required/2022_04_30_hp_regen_per_second.sql @@ -1 +1 @@ -ALTER TABLE npc_types ADD COLUMN hp_regen_per_second bigint(11) DEFAULT 0 AFTER hp_regen_rate; \ No newline at end of file +ALTER TABLE npc_types ADD COLUMN hp_regen_per_second bigint DEFAULT 0 AFTER hp_regen_rate; diff --git a/utils/sql/git/required/2022_05_02_npc_types_int64.sql b/utils/sql/git/required/2022_05_02_npc_types_int64.sql index 5a018b919..fb52824ee 100644 --- a/utils/sql/git/required/2022_05_02_npc_types_int64.sql +++ b/utils/sql/git/required/2022_05_02_npc_types_int64.sql @@ -1,4 +1,4 @@ -ALTER TABLE npc_types MODIFY COLUMN hp BIGINT; -ALTER TABLE npc_types MODIFY COLUMN mana BIGINT; -ALTER TABLE npc_types MODIFY COLUMN hp_regen_rate BIGINT; -ALTER TABLE npc_types MODIFY COLUMN mana_regen_rate BIGINT; +ALTER TABLE npc_types MODIFY COLUMN hp BIGINT NOT NULL DEFAULT 0; +ALTER TABLE npc_types MODIFY COLUMN mana BIGINT NOT NULL DEFAULT 0; +ALTER TABLE npc_types MODIFY COLUMN hp_regen_rate BIGINT NOT NULL DEFAULT 0; +ALTER TABLE npc_types MODIFY COLUMN mana_regen_rate BIGINT NOT NULL DEFAULT 0; diff --git a/utils/sql/git/required/2022_05_07_discord_webhooks.sql b/utils/sql/git/required/2022_05_07_discord_webhooks.sql new file mode 100644 index 000000000..9f368c13e --- /dev/null +++ b/utils/sql/git/required/2022_05_07_discord_webhooks.sql @@ -0,0 +1,15 @@ +CREATE TABLE discord_webhooks +( + id INT auto_increment primary key NULL, + webhook_name varchar(100) NULL, + webhook_url varchar(255) NULL, + created_at DATETIME NULL, + deleted_at DATETIME NULL +) ENGINE=InnoDB +DEFAULT CHARSET=utf8mb4 +COLLATE=utf8mb4_general_ci; + +ALTER TABLE logsys_categories + ADD log_to_discord smallint(11) default 0 AFTER log_to_gmsay; +ALTER TABLE logsys_categories + ADD discord_webhook_id int(11) default 0 AFTER log_to_discord; diff --git a/utils/sql/git/required/2022_05_21_schema_consistency.sql b/utils/sql/git/required/2022_05_21_schema_consistency.sql new file mode 100644 index 000000000..5f8004f15 --- /dev/null +++ b/utils/sql/git/required/2022_05_21_schema_consistency.sql @@ -0,0 +1,5 @@ +ALTER TABLE npc_types MODIFY COLUMN hp BIGINT NOT NULL DEFAULT 0; +ALTER TABLE npc_types MODIFY COLUMN mana BIGINT NOT NULL DEFAULT 0; +ALTER TABLE npc_types MODIFY COLUMN hp_regen_rate BIGINT NOT NULL DEFAULT 0; +ALTER TABLE npc_types MODIFY COLUMN mana_regen_rate BIGINT NOT NULL DEFAULT 0; +ALTER TABLE npc_types MODIFY COLUMN hp_regen_per_second BIGINT NOT NULL DEFAULT 0; diff --git a/utils/sql/git/required/2022_07_09_task_zone_version_matching.sql b/utils/sql/git/required/2022_07_09_task_zone_version_matching.sql new file mode 100644 index 000000000..8421ab418 --- /dev/null +++ b/utils/sql/git/required/2022_07_09_task_zone_version_matching.sql @@ -0,0 +1 @@ +ALTER TABLE `task_activities` ADD COLUMN `zone_version` int(11) default -1 AFTER zones; diff --git a/utils/sql/git/required/2022_07_09_zone_expansion_deprecate.sql b/utils/sql/git/required/2022_07_09_zone_expansion_deprecate.sql new file mode 100644 index 000000000..e69de29bb diff --git a/utils/sql/git/required/2022_07_10_character_task_rewarded.sql b/utils/sql/git/required/2022_07_10_character_task_rewarded.sql new file mode 100644 index 000000000..3e70ef199 --- /dev/null +++ b/utils/sql/git/required/2022_07_10_character_task_rewarded.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_tasks` + ADD COLUMN `was_rewarded` TINYINT NOT NULL DEFAULT '0' AFTER `acceptedtime`; diff --git a/utils/sql/git/required/2022_07_13_task_lock_activity.sql b/utils/sql/git/required/2022_07_13_task_lock_activity.sql new file mode 100644 index 000000000..2c4f15321 --- /dev/null +++ b/utils/sql/git/required/2022_07_13_task_lock_activity.sql @@ -0,0 +1,2 @@ +ALTER TABLE `tasks` + ADD COLUMN `lock_activity_id` INT NOT NULL DEFAULT '-1' AFTER `request_timer_seconds`; diff --git a/utils/sql/git/required/2022_07_13_task_reward_points.sql b/utils/sql/git/required/2022_07_13_task_reward_points.sql new file mode 100644 index 000000000..a27b8c20e --- /dev/null +++ b/utils/sql/git/required/2022_07_13_task_reward_points.sql @@ -0,0 +1,13 @@ +ALTER TABLE `tasks` + ADD COLUMN `reward_points` INT NOT NULL DEFAULT '0' AFTER `rewardmethod`, + ADD COLUMN `reward_point_type` INT NOT NULL DEFAULT '0' AFTER `reward_points`; + +-- convert don crystal points to new fields +UPDATE tasks SET reward_point_type = 4 WHERE reward_radiant_crystals > 0; +UPDATE tasks SET reward_point_type = 5 WHERE reward_ebon_crystals > 0; +UPDATE tasks SET reward_points = reward_radiant_crystals WHERE reward_radiant_crystals > 0; +UPDATE tasks SET reward_points = reward_ebon_crystals WHERE reward_ebon_crystals > 0; + +ALTER TABLE `tasks` + DROP COLUMN `reward_radiant_crystals`, + DROP COLUMN `reward_ebon_crystals`; diff --git a/utils/sql/git/required/2022_07_14_zone_expansion_revert.sql b/utils/sql/git/required/2022_07_14_zone_expansion_revert.sql new file mode 100644 index 000000000..8c94d9f91 --- /dev/null +++ b/utils/sql/git/required/2022_07_14_zone_expansion_revert.sql @@ -0,0 +1,593 @@ +ALTER table zone ADD `expansion` tinyint(3) NOT NULL DEFAULT 0; + +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 160; -- halas +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 146; -- guildlobby +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 145; -- guildhall +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 144; -- guardian +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 143; -- growthplane +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 142; -- grobb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 141; -- grimling +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 140; -- griegsend +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 139; -- greatdivide +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 138; -- gfaydark +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 137; -- fungusgrove +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 147; -- guka +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 148; -- gukb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 149; -- gukbottom +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 159; -- gyrospirez +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 158; -- gyrospireb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 6 WHERE `id` = 157; -- gunthak +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 156; -- guktop +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 155; -- gukh +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 154; -- gukg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 153; -- gukf +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 152; -- guke +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 151; -- gukd +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 150; -- gukc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 136; -- frozenshadow +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 135; -- frostcrypt +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 134; -- frontiermtns +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 120; -- firiona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 119; -- fieldofbone +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 118; -- fhalls +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 117; -- ferubi +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 116; -- felwitheb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 115; -- felwithea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 114; -- feerrott +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 113; -- fearplane +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 112; -- everfrost +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 111; -- erudsxing2 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 121; -- freeportacademy +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 122; -- freeportarena +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 123; -- freeportcityhall +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 133; -- freportw +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 132; -- freportn +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 131; -- freporte +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 130; -- freeportwest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 129; -- freeporttheater +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 128; -- freeporttemple +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 127; -- freeportsewers +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 126; -- freeportmilitia +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 125; -- freeporthall +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 124; -- freeporteast +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 110; -- erudsxing +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 211; -- mechanotus +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 197; -- kodtaz +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 196; -- kithicor +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 195; -- kithforest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 194; -- kerraridge +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 193; -- kedge +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 192; -- kattacastrum +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 191; -- katta +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 190; -- karnor +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 189; -- kaladimb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 188; -- kaladima +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 198; -- korascian +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 199; -- kurn +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 200; -- lakeofillomen +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 210; -- mansion +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 209; -- maidensgrave +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 208; -- maiden +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 207; -- lopingplains +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 206; -- load2 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 205; -- load +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 204; -- lfaydark +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 203; -- letalis +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 202; -- lavastorm +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 201; -- lakerathe +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 187; -- kaesora +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 186; -- kael +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 185; -- jardelshook +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 171; -- hohonorb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 170; -- hohonora +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 169; -- hillsofshade +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 168; -- highpasskeep +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 167; -- highpasshold +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 166; -- highpass +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 165; -- highkeep +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 6 WHERE `id` = 164; -- hatesfury +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 163; -- hateplaneb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 162; -- hateplane +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 172; -- hole +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 173; -- hollowshade +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 174; -- iceclad +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 184; -- jaggedpine +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 183; -- innothuleb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 182; -- innothule +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 181; -- inktuta +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 180; -- illsalinc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 179; -- illsalinb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 178; -- illsalina +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 177; -- illsalin +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 176; -- ikkinz +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 175; -- icefall +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 161; -- harbingers +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 51; -- commons +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 37; -- chambersa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 36; -- cazicthule +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 35; -- causeway +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 34; -- cauldron +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 33; -- cabwest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 32; -- cabeast +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 31; -- butcher +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 30; -- burningwood +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 29; -- buriedsea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 28; -- broodlands +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 38; -- chambersb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 39; -- chambersc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 40; -- chambersd +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 50; -- commonlands +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 49; -- codecay +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 48; -- cobaltscar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 47; -- clz +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 46; -- citymist +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 6 WHERE `id` = 45; -- chardokb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 44; -- chardok +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 43; -- charasis +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 42; -- chambersf +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 41; -- chamberse +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 27; -- bothunder +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 26; -- bloodmoon +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 25; -- bloodfields +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 11; -- arttest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 10; -- arena2 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 9; -- arena +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 8; -- arcstone +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 7; -- apprentice +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 6; -- anguish +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 5; -- akheva +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 4; -- akanon +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 3; -- airplane +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 2; -- acrylia +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 12; -- ashengate +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 13; -- atiiki +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 14; -- aviak +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 24; -- blacksail +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 23; -- blackburrow +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 22; -- bertoxtemple +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 21; -- beholder +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 20; -- befallenb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 19; -- befallen +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 18; -- bazaar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 17; -- barter +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 16; -- barren +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 15; -- barindu +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 1; -- abysmal +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 109; -- erudnint +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 95; -- dreadlands +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 94; -- draniksscar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 93; -- draniksewersc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 92; -- draniksewersb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 91; -- draniksewersa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 83; -- dranikhollowsc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 82; -- dranikhollowsb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 81; -- dranikhollowsa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 80; -- dranikcatacombsc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 79; -- dranikcatacombsb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 96; -- dreadspire +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 97; -- droga +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 6 WHERE `id` = 98; -- dulak +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 108; -- erudnext +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 107; -- emeraldjungle +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 106; -- elddara +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 105; -- elddar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 104; -- ecommons +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 103; -- echo +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 102; -- eastwastes +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 101; -- eastkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 100; -- eastkorlach +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 99; -- eastkarana +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 78; -- dranikcatacombsa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 77; -- dranik +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 76; -- dragonscaleb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 62; -- dawnshroud +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 61; -- dalnir +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 60; -- cshome +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 59; -- crystallos +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 58; -- crystal +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 57; -- cryptofshade +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 56; -- crushbone +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 55; -- crescent +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 54; -- corathusb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 53; -- corathusa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 63; -- deadbone +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 64; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 65; -- delveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 75; -- dragonscale +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 74; -- drachnidhivec +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 73; -- drachnidhiveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 72; -- drachnidhivea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 71; -- drachnidhive +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 70; -- discordtower +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 69; -- discord +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 68; -- direwind +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 67; -- devastation +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 66; -- devastationa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 52; -- corathus +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5975; -- westkorlachb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5957; -- delveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5956; -- delveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5954; -- delveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5953; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5952; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5951; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5949; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5946; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5958; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5959; -- delveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5961; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 5974; -- rujj +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 5970; -- taka +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 5967; -- mirc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 5966; -- gukc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5965; -- delveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5964; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5963; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5962; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5945; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5944; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5943; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5929; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5928; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5927; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5926; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5925; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5924; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5923; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5921; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5930; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5933; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5934; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5942; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5941; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5940; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5939; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5938; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5937; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5936; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5935; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5920; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5976; -- westkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 6019; -- gukg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6007; -- drachnidhive +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6006; -- drachnidhive +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6005; -- drachnidhivea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6004; -- drachnidhivea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6003; -- drachnidhivea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6002; -- drachnidhiveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6001; -- illsalinb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6000; -- illsalinb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6008; -- drachnidhive +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6009; -- drachnidhive +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6010; -- drachnidhive +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 6018; -- take +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6017; -- eastkorlach +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6016; -- illsalinc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6015; -- illsalinc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6014; -- illsalinc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6013; -- illsalinc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6012; -- westkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 6011; -- corathusb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5999; -- illsalinb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5998; -- illsalinb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5997; -- westkorlach +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5985; -- westkorlachc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5984; -- westkorlachc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5983; -- westkorlachc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5982; -- westkorlachc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5981; -- illsalina +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5980; -- dreadspire +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5979; -- corathusb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5978; -- corathusb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5986; -- westkorlachc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5987; -- westkorlachc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5988; -- drachnidhivec +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5996; -- westkorlach +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5995; -- westkorlach +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5994; -- corathusa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5993; -- corathusa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5992; -- eastkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5991; -- eastkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5990; -- eastkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5989; -- shadowspine +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 5977; -- westkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5873; -- cityofbronze +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5565; -- thulehouse1 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5564; -- thuledream +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5563; -- somnium +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5562; -- miragulmare +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5561; -- housegarden +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5560; -- feerrott2 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5559; -- fallen +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5558; -- alkabormare +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5566; -- thulehouse2 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5567; -- well +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5568; -- neighborhood +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5872; -- windsong +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5871; -- pillarsalra +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5870; -- resplendent +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5869; -- beastdomain +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5868; -- rubak +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5867; -- sarithcity +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5866; -- arelis +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5865; -- argath +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5557; -- morellcastle +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 18 WHERE `id` = 5556; -- thulelibrary +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 448; -- convorteum +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 435; -- westkorlachc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 434; -- westkorlachb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 433; -- westkorlacha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 432; -- westkorlach +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 431; -- warslikswood +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 430; -- warrens +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 429; -- wallofslaughter +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 428; -- wakening +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 436; -- westwastes +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 437; -- yxtta +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 438; -- zhisza +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 447; -- stonesnake +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 446; -- brellsarena +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 445; -- underquarry +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 444; -- foundation +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 443; -- arthicrex +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 442; -- pellucid +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 441; -- coolingchamber +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 440; -- brellsrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 427; -- vxed +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5919; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5907; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5906; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5905; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5904; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5903; -- delveb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5902; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5900; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5899; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5908; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5909; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5910; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5918; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5917; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5916; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5915; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5914; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5913; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5912; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5911; -- delvea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5898; -- thundercrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5896; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 5895; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 5883; -- lichencreep +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 5882; -- fungalforest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 5881; -- brellstemple +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 5880; -- bazaar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 5879; -- dragoncrypt +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 5878; -- weddingchapeldark +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 5877; -- weddingchapel +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5876; -- westsepulcher +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5875; -- eastsepulcher +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 17 WHERE `id` = 5884; -- shiningcity +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5886; -- breedinggrounds +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5894; -- xorbb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5893; -- shardslanding +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5892; -- kaelshard +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5891; -- grelleth +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5890; -- eviltree +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5889; -- eastwastesshard +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5888; -- crystalshard +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 20 WHERE `id` = 5887; -- chapterhouse +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 19 WHERE `id` = 5874; -- sepulcher +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 371; -- stonehive +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 357; -- soltemple +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 356; -- solrotower +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 6 WHERE `id` = 355; -- soldungc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 354; -- soldungb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 353; -- soldunga +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 352; -- snpool +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 351; -- snplant +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 350; -- snlair +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 349; -- sncrematory +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 348; -- sleeper +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 347; -- skyshrine +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 358; -- solteris +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 359; -- southkarana +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 370; -- stonebrunt +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 369; -- stillmoonb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 368; -- stillmoona +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 367; -- steppes +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 366; -- steamfontmts +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 365; -- steamfont +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 364; -- steamfactory +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 363; -- ssratemple +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 362; -- sseru +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 361; -- sro +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 360; -- southro +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 346; -- skylance +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 345; -- skyfire +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 344; -- sirens +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 330; -- scarlet +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 329; -- runnyeye +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 328; -- rujj +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 327; -- ruji +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 326; -- rujh +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 325; -- rujg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 324; -- rujf +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 323; -- ruje +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 322; -- rujd +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 321; -- rujc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 320; -- rujb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 331; -- sebilis +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 332; -- shadeweaver +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 343; -- silyssar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 15 WHERE `id` = 342; -- shipworkshop +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 341; -- shipuvu +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 340; -- shippvu +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 339; -- shipmvu +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 338; -- shipmvp +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 337; -- shipmvm +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 336; -- sharvahl +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 335; -- shadowspine +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 334; -- shadowrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 333; -- shadowhaven +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 319; -- ruja +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 426; -- vexthal +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 412; -- trakanon +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 411; -- toxxulia +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 410; -- tox +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 409; -- toskirakk +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 6 WHERE `id` = 408; -- torgiran +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 407; -- tipt +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 406; -- timorous +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 405; -- thurgadinb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 404; -- thurgadina +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 402; -- thevoidg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 401; -- thevoidf +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 413; -- tutorial +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 414; -- tutoriala +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 425; -- vergalid +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 424; -- velketor +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 423; -- veksar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 422; -- veeshan +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 421; -- valdeholm +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 420; -- uqua +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 419; -- unrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 418; -- umbral +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 417; -- txevu +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 416; -- twilight +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 415; -- tutorialb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 400; -- thevoide +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 399; -- thevoidd +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 398; -- thevoidc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 384; -- taki +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 383; -- takh +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 382; -- takg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 381; -- takf +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 380; -- take +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 379; -- takd +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 378; -- takc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 377; -- takb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 375; -- tacvi +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 374; -- swampofnohope +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 373; -- sunderock +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 385; -- takishruins +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 386; -- takishruinsa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 397; -- thevoidb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 396; -- thevoida +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 10 WHERE `id` = 395; -- thenest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 394; -- thegrey +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 393; -- thedeep +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 392; -- theatera +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 391; -- theater +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 390; -- thalassius +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 389; -- tenebrous +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 388; -- templeveeshan +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 387; -- takj +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 372; -- suncrest +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 318; -- roost +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 264; -- oldblackburrow +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 250; -- neriakc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 249; -- neriakb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 248; -- neriaka +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 11 WHERE `id` = 247; -- nektulosa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = 10, `expansion` = 1 WHERE `id` = 246; -- nektulos +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 245; -- nektropos +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 244; -- nedaria +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 243; -- necropolis +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 242; -- natimbi +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 241; -- najena +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 6 WHERE `id` = 240; -- nadox +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 99 WHERE `id` = 251; -- neriakd +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 252; -- netherbian +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 263; -- oggok +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 262; -- oceanoftears +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 261; -- oceangreenvillage +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 260; -- oceangreenhills +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 259; -- oasis +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 258; -- nurga +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 257; -- nro +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 256; -- northro +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 255; -- northkarana +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 254; -- nightmareb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 253; -- nexus +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 239; -- mseru +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 238; -- moors +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 237; -- monkeyrock +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 3 WHERE `id` = 223; -- mischiefplane +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 222; -- mirj +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 221; -- miri +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 220; -- mirh +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 219; -- mirg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 218; -- mirf +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 217; -- mire +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 216; -- mird +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 215; -- mirc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 214; -- mirb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 213; -- mira +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 224; -- mistmoore +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 225; -- misty +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 236; -- mmcj +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 235; -- mmci +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 234; -- mmch +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 233; -- mmcg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 232; -- mmcf +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 231; -- mmce +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 230; -- mmcd +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 229; -- mmcc +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 228; -- mmcb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 7 WHERE `id` = 227; -- mmca +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 226; -- mistythicket +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 13 WHERE `id` = 212; -- mesa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 317; -- riwwi +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 303; -- qeynos2 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 302; -- qeynos +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 301; -- qey2hh1 +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 300; -- qcat +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 299; -- provinggrounds +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 298; -- precipiceofwar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 297; -- powater +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 296; -- powar +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 295; -- povalor +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 294; -- potranquility +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 293; -- potorment +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 304; -- qeytoqrg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 305; -- qinimi +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 316; -- rivervale +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 9 WHERE `id` = 315; -- riftseekers +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 314; -- relic +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 14 WHERE `id` = 313; -- redfeather +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 312; -- rathemtn +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 311; -- rathechamber +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 310; -- ragea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 12 WHERE `id` = 309; -- rage +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 308; -- qvicb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 8 WHERE `id` = 307; -- qvic +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 306; -- qrg +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 292; -- potimeb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 291; -- potimea +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 290; -- potactics +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 276; -- paineel +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 2 WHERE `id` = 275; -- overthere +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 274; -- oot +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 273; -- oldkurn +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 272; -- oldkithicor +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 271; -- oldkaesorab +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 270; -- oldkaesoraa +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 269; -- oldhighpass +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 268; -- oldfieldofbone +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 267; -- olddranik +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 266; -- oldcommons +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 4 WHERE `id` = 277; -- paludal +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 278; -- paw +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 289; -- postorms +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 288; -- ponightmare +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 287; -- poknowledge +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 286; -- pojustice +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 285; -- poinnovation +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 284; -- pofire +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 283; -- poearthb +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 282; -- poeartha +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 281; -- podisease +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 5 WHERE `id` = 280; -- poair +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 279; -- permafrost +UPDATE `zone` SET `min_expansion` = -1, `max_expansion` = -1, `expansion` = 16 WHERE `id` = 265; -- oldbloodfield +UPDATE `zone` SET `min_expansion` = 10, `max_expansion` = -1, `expansion` = 1 WHERE `id` = 439; -- nektulos diff --git a/utils/sql/git/required/2022_07_16_task_timer_groups.sql b/utils/sql/git/required/2022_07_16_task_timer_groups.sql new file mode 100644 index 000000000..1dcb96516 --- /dev/null +++ b/utils/sql/git/required/2022_07_16_task_timer_groups.sql @@ -0,0 +1,6 @@ +ALTER TABLE `tasks` + ADD COLUMN `replay_timer_group` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `completion_emote`, + ADD COLUMN `request_timer_group` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `replay_timer_seconds`; + +ALTER TABLE `character_task_timers` + ADD COLUMN `timer_group` INT NOT NULL DEFAULT '0' AFTER `timer_type`; diff --git a/utils/sql/git/required/2022_07_23_dz_switch_id.sql b/utils/sql/git/required/2022_07_23_dz_switch_id.sql new file mode 100644 index 000000000..55ecdce71 --- /dev/null +++ b/utils/sql/git/required/2022_07_23_dz_switch_id.sql @@ -0,0 +1,5 @@ +ALTER TABLE `doors` + ADD COLUMN `dz_switch_id` INT NOT NULL DEFAULT '0' AFTER `is_ldon_door`; + +ALTER TABLE `dynamic_zones` + ADD COLUMN `dz_switch_id` INT NOT NULL DEFAULT '0' AFTER `max_players`; diff --git a/utils/sql/git/required/2022_07_23_dz_templates.sql b/utils/sql/git/required/2022_07_23_dz_templates.sql new file mode 100644 index 000000000..82759ad6e --- /dev/null +++ b/utils/sql/git/required/2022_07_23_dz_templates.sql @@ -0,0 +1,28 @@ +CREATE TABLE `dynamic_zone_templates` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `zone_id` int(11) NOT NULL DEFAULT 0, + `zone_version` int(11) NOT NULL DEFAULT 0, + `name` varchar(128) NOT NULL DEFAULT '', + `min_players` int(11) NOT NULL DEFAULT 0, + `max_players` int(11) NOT NULL DEFAULT 0, + `duration_seconds` int(11) NOT NULL DEFAULT 0, + `dz_switch_id` int(11) NOT NULL DEFAULT 0, + `compass_zone_id` int(11) NOT NULL DEFAULT 0, + `compass_x` float NOT NULL DEFAULT 0, + `compass_y` float NOT NULL DEFAULT 0, + `compass_z` float NOT NULL DEFAULT 0, + `return_zone_id` int(11) NOT NULL DEFAULT 0, + `return_x` float NOT NULL DEFAULT 0, + `return_y` float NOT NULL DEFAULT 0, + `return_z` float NOT NULL DEFAULT 0, + `return_h` float NOT NULL DEFAULT 0, + `override_zone_in` tinyint(4) NOT NULL DEFAULT 0, + `zone_in_x` float NOT NULL DEFAULT 0, + `zone_in_y` float NOT NULL DEFAULT 0, + `zone_in_z` float NOT NULL DEFAULT 0, + `zone_in_h` float NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +ALTER TABLE `tasks` + ADD COLUMN `dz_template_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `request_timer_seconds`; diff --git a/utils/sql/git/required/2022_07_28_gm_state_changes.sql b/utils/sql/git/required/2022_07_28_gm_state_changes.sql new file mode 100644 index 000000000..ef61477d6 --- /dev/null +++ b/utils/sql/git/required/2022_07_28_gm_state_changes.sql @@ -0,0 +1,4 @@ +ALTER TABLE `account` + ADD COLUMN `invulnerable` TINYINT(4) NULL DEFAULT '0' AFTER `gmspeed`, + ADD COLUMN `flymode` TINYINT(4) NULL DEFAULT '0' AFTER `invulnerable`, + ADD COLUMN `ignore_tells` TINYINT(4) NULL DEFAULT '0' AFTER `flymode`; diff --git a/utils/sql/git/required/2022_07_30_merchantlist_temp.sql b/utils/sql/git/required/2022_07_30_merchantlist_temp.sql new file mode 100644 index 000000000..b02c9ac63 --- /dev/null +++ b/utils/sql/git/required/2022_07_30_merchantlist_temp.sql @@ -0,0 +1,3 @@ +ALTER TABLE `merchantlist_temp` ADD COLUMN `zone_id` INT(11) NOT NULL DEFAULT '0' AFTER `slot`; +ALTER TABLE `merchantlist_temp` ADD COLUMN `instance_id` INT(11) NOT NULL DEFAULT '0' AFTER `zone_id`; +ALTER TABLE `merchantlist_temp` DROP PRIMARY KEY, ADD PRIMARY KEY (`npcid`, `slot`, `zone_id`, `instance_id`); diff --git a/utils/sql/git/required/2022_08_01_drop_expansion_account.sql b/utils/sql/git/required/2022_08_01_drop_expansion_account.sql new file mode 100644 index 000000000..8a4f7eecb --- /dev/null +++ b/utils/sql/git/required/2022_08_01_drop_expansion_account.sql @@ -0,0 +1 @@ +ALTER TABLE `account` DROP `expansion`; diff --git a/utils/sql/git/required/2022_08_07_replace_task_goals.sql b/utils/sql/git/required/2022_08_07_replace_task_goals.sql new file mode 100644 index 000000000..023fa6ffa --- /dev/null +++ b/utils/sql/git/required/2022_08_07_replace_task_goals.sql @@ -0,0 +1,95 @@ +-- backup original since this is a complex migration +CREATE TABLE `task_activities_backup_9203` LIKE `task_activities`; +INSERT INTO `task_activities_backup_9203` SELECT * FROM `task_activities`; + +ALTER TABLE `task_activities` + CHANGE COLUMN `description_override` `description_override` VARCHAR(128) NOT NULL DEFAULT '' COLLATE 'latin1_swedish_ci' AFTER `goalcount`, + ADD COLUMN `npc_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `description_override`, + ADD COLUMN `npc_goal_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `npc_id`, + ADD COLUMN `npc_match_list` TEXT NULL DEFAULT NULL AFTER `npc_goal_id`, + ADD COLUMN `item_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `npc_match_list`, + ADD COLUMN `item_goal_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `item_id`, + ADD COLUMN `item_id_list` TEXT NULL DEFAULT NULL AFTER `item_goal_id`, + CHANGE COLUMN `item_list` `item_list` VARCHAR(128) NOT NULL DEFAULT '' COLLATE 'latin1_swedish_ci' AFTER `item_id_list`, + ADD COLUMN `dz_switch_id` INT(11) NOT NULL DEFAULT '0' AFTER `delivertonpc`, + ADD COLUMN `min_x` FLOAT NOT NULL DEFAULT 0 AFTER `dz_switch_id`, + ADD COLUMN `min_y` FLOAT NOT NULL DEFAULT 0 AFTER `min_x`, + ADD COLUMN `min_z` FLOAT NOT NULL DEFAULT 0 AFTER `min_y`, + ADD COLUMN `max_x` FLOAT NOT NULL DEFAULT 0 AFTER `min_z`, + ADD COLUMN `max_y` FLOAT NOT NULL DEFAULT 0 AFTER `max_x`, + ADD COLUMN `max_z` FLOAT NOT NULL DEFAULT 0 AFTER `max_y`, + CHANGE COLUMN `skill_list` `skill_list` VARCHAR(64) NOT NULL DEFAULT '-1' COLLATE 'latin1_swedish_ci' AFTER `max_z`, + CHANGE COLUMN `spell_list` `spell_list` VARCHAR(64) NOT NULL DEFAULT '0' COLLATE 'latin1_swedish_ci' AFTER `skill_list`; + +-- move Explore (5) goalid proximities to the new location fields +-- does not migrate where zone was different and ignores lists (unsupported) +UPDATE `task_activities` +INNER JOIN `proximities` + ON `task_activities`.`goalid` = `proximities`.`exploreid` + AND CAST(`task_activities`.`zones` AS INT) = `proximities`.`zoneid` +SET + `task_activities`.`goalid` = 0, + `task_activities`.`min_x` = `proximities`.`minx`, + `task_activities`.`min_y` = `proximities`.`miny`, + `task_activities`.`min_z` = `proximities`.`minz`, + `task_activities`.`max_x` = `proximities`.`maxx`, + `task_activities`.`max_y` = `proximities`.`maxy`, + `task_activities`.`max_z` = `proximities`.`maxz` +WHERE + `task_activities`.`goalmethod` = 0 + AND `task_activities`.`activitytype` = 5; + +-- dz_switch_id for Touch (11) +UPDATE `task_activities` +SET `task_activities`.`dz_switch_id` = `task_activities`.`goalid` +WHERE `task_activities`.`goalmethod` = 0 + AND `task_activities`.`activitytype` = 11; + +-- single item ids for Deliver (1), Loot (3), TradeSkill (6), Fish (7), Forage (8) +UPDATE `task_activities` +SET `task_activities`.`item_id` = `task_activities`.`goalid` +WHERE `task_activities`.`goalmethod` = 0 + AND `task_activities`.`activitytype` IN (1, 3, 6, 7, 8); + +-- item goallist id +UPDATE `task_activities` +SET `task_activities`.`item_goal_id` = `task_activities`.`goalid` +WHERE `task_activities`.`goalmethod` = 1 + AND `task_activities`.`activitytype` IN (1, 3, 6, 7, 8); + +-- item id match list +UPDATE `task_activities` +SET `task_activities`.`item_id_list` = `task_activities`.`goal_match_list` +WHERE `task_activities`.`goalmethod` = 1 + AND `task_activities`.`activitytype` IN (1, 3, 6, 7, 8); + +-- single npc ids for Kill (2), SpeakWith (4) +UPDATE `task_activities` +SET `task_activities`.`npc_id` = `task_activities`.`goalid` +WHERE `task_activities`.`goalmethod` = 0 + AND `task_activities`.`activitytype` IN (2, 4); + +-- npc goallist id +UPDATE `task_activities` +SET `task_activities`.`npc_goal_id` = `task_activities`.`goalid` +WHERE `task_activities`.`goalmethod` = 1 + AND `task_activities`.`activitytype` IN (2, 4); + +-- npc match list +UPDATE `task_activities` +SET `task_activities`.`npc_match_list` = `task_activities`.`goal_match_list` +WHERE `task_activities`.`goalmethod` = 1 + AND `task_activities`.`activitytype` IN (2, 4); + +-- delivertonpc npc_ids for Deliver (1), GiveCash (100) +UPDATE `task_activities` +SET `task_activities`.`npc_id` = `task_activities`.`delivertonpc` +WHERE `task_activities`.`activitytype` IN (1, 100); + +ALTER TABLE `task_activities` + DROP COLUMN `goalid`, + DROP COLUMN `goal_match_list`, + DROP COLUMN `delivertonpc`; + +-- leave proximities table backup in case of regressions +ALTER TABLE `proximities` RENAME `proximities_backup_9203`; diff --git a/utils/sql/git/required/2022_08_08_task_req_activity_id.sql b/utils/sql/git/required/2022_08_08_task_req_activity_id.sql new file mode 100644 index 000000000..3f8e127ec --- /dev/null +++ b/utils/sql/git/required/2022_08_08_task_req_activity_id.sql @@ -0,0 +1,2 @@ +ALTER TABLE `task_activities` + ADD COLUMN `req_activity_id` INT SIGNED NOT NULL DEFAULT '-1' AFTER `activityid`; diff --git a/utils/sql/git/required/2022_08_14_exp_modifier_instance_versions.sql b/utils/sql/git/required/2022_08_14_exp_modifier_instance_versions.sql new file mode 100644 index 000000000..441dfe8d9 --- /dev/null +++ b/utils/sql/git/required/2022_08_14_exp_modifier_instance_versions.sql @@ -0,0 +1,4 @@ +ALTER TABLE character_exp_modifiers +ADD COLUMN instance_version int NOT NULL DEFAULT -1 AFTER zone_id, +DROP PRIMARY KEY, +ADD PRIMARY KEY (character_id, zone_id, instance_version) USING BTREE; \ No newline at end of file diff --git a/utils/sql/git/required/2022_08_19_zone_expansion_consistency.sql b/utils/sql/git/required/2022_08_19_zone_expansion_consistency.sql new file mode 100644 index 000000000..cad2a1385 --- /dev/null +++ b/utils/sql/git/required/2022_08_19_zone_expansion_consistency.sql @@ -0,0 +1,609 @@ +ALTER TABLE `zone` + ADD COLUMN `bypass_expansion_check` tinyint(3) NOT NULL DEFAULT 0 AFTER `expansion`; + +UPDATE `zone` SET `bypass_expansion_check` = 1 WHERE `short_name` +IN ( + 'befallenb', + 'commonlands', + 'freeportacademy', + 'freeportarena', + 'freeportcityhall', + 'freeporteast', + 'freeporthall', + 'freeportmilitia', + 'freeportsewers', + 'freeportwest', + 'guildhall', + 'guildlobby', + 'highpasshold', + 'highpasskeep', + 'innothuleb', + 'kithforest', + 'mistythicket', + 'moors', + 'nektulosa', + 'northro', + 'oceanoftears', + 'southro', + 'steamfontmts', + 'toxxulia' +); + +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 244; -- nedaria +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 132; -- freportn +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 131; -- freporte +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 257; -- nro +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 60; -- cshome +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 259; -- oasis +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 439; -- nektulosnektulos +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 334; -- shadowrest +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 263; -- oggok +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 56; -- crushbone +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 133; -- freportw +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 255; -- northkarana +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 149; -- gukbottom +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 248; -- neriaka +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 249; -- neriakb +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 250; -- neriakc +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 142; -- grobb +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 51; -- commons +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 138; -- gfaydark +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 274; -- oot +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 276; -- paineel +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 99; -- eastkarana +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 116; -- felwitheb +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 115; -- felwithea +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 114; -- feerrott +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 113; -- fearplane +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 112; -- everfrost +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 109; -- erudnint +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 108; -- erudnext +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 279; -- permafrost +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 300; -- qcat +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 301; -- qey2hh1 +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 329; -- runnyeye +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 316; -- rivervale +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 278; -- paw +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 312; -- rathemtn +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 306; -- qrg +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 304; -- qeytoqrg +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 303; -- qeynos2 +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 302; -- qeynos +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 104; -- ecommons +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 241; -- najena +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 353; -- soldunga +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 193; -- kedge +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 194; -- kerraridge +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 196; -- kithicor +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 172; -- hole +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 19; -- befallen +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 21; -- beholder +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 419; -- unrest +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 23; -- blackburrow +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 415; -- tutorialb +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 414; -- tutoriala +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 3; -- airplane +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 4; -- akanon +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 184; -- jaggedpine +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 188; -- kaladima +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 410; -- tox +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 182; -- innothule +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 9; -- arena +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 189; -- kaladimb +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 201; -- lakerathe +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 202; -- lavastorm +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 162; -- hateplane +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 160; -- halas +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 156; -- guktop +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 34; -- cauldron +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 224; -- mistmoore +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 36; -- cazicthule +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 361; -- sro +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 225; -- misty +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 31; -- butcher +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 163; -- hateplaneb +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 204; -- lfaydark +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 354; -- soldungb +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 166; -- highpass +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 359; -- southkarana +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 365; -- steamfont +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 165; -- highkeep +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 107; -- emeraldjungle +UPDATE `zone` SET `expansion` = 0 WHERE `id` = 110; -- erudsxing +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 370; -- stonebrunt +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 187; -- kaesora +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 190; -- karnor +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 134; -- frontiermtns +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 199; -- kurn +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 200; -- lakeofillomen +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 275; -- overthere +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 258; -- nurga +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 120; -- firiona +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 44; -- chardok +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 33; -- cabwest +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 374; -- swampofnohope +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 422; -- veeshan +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 423; -- veksar +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 30; -- burningwood +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 345; -- skyfire +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 431; -- warslikswood +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 119; -- fieldofbone +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 331; -- sebilis +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 32; -- cabeast +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 61; -- dalnir +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 430; -- warrens +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 97; -- droga +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 412; -- trakanon +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 46; -- citymist +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 43; -- charasis +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 95; -- dreadlands +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 357; -- soltemple +UPDATE `zone` SET `expansion` = 1 WHERE `id` = 406; -- timorous +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 436; -- westwastes +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 58; -- crystal +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 405; -- thurgadinb +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 243; -- necropolis +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 344; -- sirens +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 348; -- sleeper +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 48; -- cobaltscar +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 136; -- frozenshadow +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 404; -- thurgadina +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 428; -- wakening +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 139; -- greatdivide +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 223; -- mischiefplane +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 143; -- growthplane +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 388; -- templeveeshan +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 174; -- iceclad +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 347; -- skyshrine +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 102; -- eastwastes +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 186; -- kael +UPDATE `zone` SET `expansion` = 2 WHERE `id` = 424; -- velketor +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 5; -- akheva +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 2; -- acrylia +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 393; -- thedeep +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 394; -- thegrey +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 191; -- katta +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 239; -- mseru +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 416; -- twilight +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 208; -- maiden +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 389; -- tenebrous +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 173; -- hollowshade +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 18; -- bazaar +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 203; -- letalis +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 426; -- vexthal +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 363; -- ssratemple +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 362; -- sseru +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 252; -- netherbian +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 103; -- echo +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 330; -- scarlet +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 277; -- paludal +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 332; -- shadeweaver +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 333; -- shadowhaven +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 62; -- dawnshroud +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 336; -- sharvahl +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 137; -- fungusgrove +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 140; -- griegsend +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 141; -- grimling +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 418; -- umbral +UPDATE `zone` SET `expansion` = 3 WHERE `id` = 253; -- nexus +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 288; -- ponightmare +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 289; -- postorms +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 282; -- poeartha +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 283; -- poearthb +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 284; -- pofire +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 287; -- poknowledge +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 285; -- poinnovation +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 286; -- pojustice +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 291; -- potimea +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 290; -- potactics +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 356; -- solrotower +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 297; -- powater +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 296; -- powar +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 280; -- poair +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 281; -- podisease +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 295; -- povalor +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 294; -- potranquility +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 293; -- potorment +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 292; -- potimeb +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 254; -- nightmareb +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 27; -- bothunder +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 170; -- hohonora +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 171; -- hohonorb +UPDATE `zone` SET `expansion` = 4 WHERE `id` = 49; -- codecay +UPDATE `zone` SET `expansion` = 5 WHERE `id` = 408; -- torgiran +UPDATE `zone` SET `expansion` = 5 WHERE `id` = 45; -- chardokb +UPDATE `zone` SET `expansion` = 5 WHERE `id` = 240; -- nadox +UPDATE `zone` SET `expansion` = 5 WHERE `id` = 164; -- hatesfury +UPDATE `zone` SET `expansion` = 5 WHERE `id` = 157; -- gunthak +UPDATE `zone` SET `expansion` = 5 WHERE `id` = 355; -- soldungc +UPDATE `zone` SET `expansion` = 5 WHERE `id` = 98; -- dulak +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 234; -- mmch +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 153; -- gukf +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 230; -- mmcd +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 231; -- mmce +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 328; -- rujj +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 217; -- mire +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 236; -- mmcj +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 232; -- mmcf +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 233; -- mmcg +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 235; -- mmci +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 229; -- mmcc +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 228; -- mmcb +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 327; -- ruji +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 5967; -- mirc +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 5970; -- taka +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 5974; -- rujj +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 320; -- rujb +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 319; -- ruja +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 321; -- rujc +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 322; -- rujd +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 323; -- ruje +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 147; -- guka +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 148; -- gukb +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 324; -- rujf +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 150; -- gukc +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 325; -- rujg +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 151; -- gukd +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 326; -- rujh +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 227; -- mmca +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 155; -- gukh +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 154; -- gukg +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 377; -- takb +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 378; -- takc +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 379; -- takd +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 380; -- take +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 381; -- takf +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 382; -- takg +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 383; -- takh +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 384; -- taki +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 387; -- takj +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 152; -- guke +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 5966; -- gukc +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 219; -- mirg +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 221; -- miri +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 220; -- mirh +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 218; -- mirf +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 216; -- mird +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 215; -- mirc +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 214; -- mirb +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 213; -- mira +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 222; -- mirj +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 6019; -- gukg +UPDATE `zone` SET `expansion` = 6 WHERE `id` = 6018; -- take +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 407; -- tipt +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 15; -- barindu +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 349; -- sncrematory +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 375; -- tacvi +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 351; -- snplant +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 352; -- snpool +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 117; -- ferubi +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 118; -- fhalls +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 305; -- qinimi +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 1; -- abysmal +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 350; -- snlair +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 308; -- qvicb +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 317; -- riwwi +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 417; -- txevu +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 420; -- uqua +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 437; -- yxtta +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 427; -- vxed +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 307; -- qvic +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 176; -- ikkinz +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 197; -- kodtaz +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 181; -- inktuta +UPDATE `zone` SET `expansion` = 7 WHERE `id` = 242; -- natimbi +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 41; -- chamberse +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 81; -- dranikhollowsa +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 83; -- dranikhollowsc +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 91; -- draniksewersa +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 92; -- draniksewersb +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 93; -- draniksewersc +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 299; -- provinggrounds +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 79; -- dranikcatacombsb +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 40; -- chambersd +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 429; -- wallofslaughter +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 78; -- dranikcatacombsa +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 77; -- dranik +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 39; -- chambersc +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 161; -- harbingers +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 35; -- causeway +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 37; -- chambersa +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 94; -- draniksscar +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 25; -- bloodfields +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 42; -- chambersf +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 6; -- anguish +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 80; -- dranikcatacombsc +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 38; -- chambersb +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 315; -- riftseekers +UPDATE `zone` SET `expansion` = 8 WHERE `id` = 82; -- dranikhollowsb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5926; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5949; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5935; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 65; -- delveb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5925; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 64; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5919; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5923; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5946; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5945; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5921; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5920; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 28; -- broodlands +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5937; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5938; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 395; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5939; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5940; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 17; -- barter +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5933; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5930; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5941; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5942; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5943; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5944; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5928; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 369; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5934; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 368; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5927; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5936; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5913; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5953; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5915; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5952; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5899; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5896; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5962; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5895; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5961; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5959; -- delveb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5954; -- delveb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5963; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5964; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5914; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5912; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5957; -- delveb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5956; -- delveb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5900; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5908; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5965; -- delveb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5911; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5910; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5929; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5924; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5918; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5903; -- delveb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5909; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 145; -- guildhall +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5916; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5904; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5905; -- thenest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5906; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 146; -- guildlobby +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5917; -- stillmoona +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5907; -- stillmoonb +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5951; -- thundercrest +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5902; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5958; -- delvea +UPDATE `zone` SET `expansion` = 9 WHERE `id` = 5898; -- thundercrest +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6007; -- drachnidhive +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6004; -- drachnidhivea +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6001; -- illsalinb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6003; -- drachnidhivea +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6002; -- drachnidhiveb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5986; -- westkorlachc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6005; -- drachnidhivea +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6006; -- drachnidhive +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6000; -- illsalinb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5999; -- illsalinb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5998; -- illsalinb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5990; -- eastkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5989; -- shadowspine +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 432; -- westkorlach +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 433; -- westkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 434; -- westkorlachb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 435; -- westkorlachc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5988; -- drachnidhivec +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5987; -- westkorlachc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5985; -- westkorlachc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5984; -- westkorlachc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5983; -- westkorlachc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5991; -- eastkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5992; -- eastkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5994; -- corathusa +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5997; -- westkorlach +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5975; -- westkorlachb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5996; -- westkorlach +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5993; -- corathusa +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5976; -- westkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5977; -- westkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5995; -- westkorlach +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5978; -- corathusb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5979; -- corathusb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5980; -- dreadspire +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5981; -- illsalina +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 5982; -- westkorlachc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 247; -- nektulosa +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 335; -- shadowspine +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 101; -- eastkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 100; -- eastkorlach +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 96; -- dreadspire +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 72; -- drachnidhivea +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 71; -- drachnidhive +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 54; -- corathusb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 53; -- corathusa +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 52; -- corathus +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 74; -- drachnidhivec +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 73; -- drachnidhiveb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6008; -- drachnidhive +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 177; -- illsalin +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 178; -- illsalina +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 180; -- illsalinc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 179; -- illsalinb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6017; -- eastkorlach +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6016; -- illsalinc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6015; -- illsalinc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6014; -- illsalinc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6013; -- illsalinc +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6012; -- westkorlacha +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6011; -- corathusb +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6010; -- drachnidhive +UPDATE `zone` SET `expansion` = 10 WHERE `id` = 6009; -- drachnidhive +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 386; -- takishruinsa +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 130; -- freeportwest +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 67; -- devastation +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 310; -- ragea +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 309; -- rage +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 256; -- northro +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 105; -- elddar +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 106; -- elddara +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 129; -- freeporttheater +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 314; -- relic +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 128; -- freeporttemple +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 127; -- freeportsewers +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 126; -- freeportmilitia +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 124; -- freeporteast +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 123; -- freeportcityhall +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 122; -- freeportarena +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 121; -- freeportacademy +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 125; -- freeporthall +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 391; -- theater +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 392; -- theatera +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 346; -- skylance +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 385; -- takishruins +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 66; -- devastationa +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 8; -- arcstone +UPDATE `zone` SET `expansion` = 11 WHERE `id` = 360; -- southro +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 20; -- befallenb +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 183; -- innothuleb +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 411; -- toxxulia +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 425; -- vergalid +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 262; -- oceanoftears +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 175; -- icefall +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 371; -- stonehive +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 421; -- valdeholm +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 168; -- highpasskeep +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 373; -- sunderock +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 135; -- frostcrypt +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 167; -- highpasshold +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 50; -- commonlands +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 238; -- moors +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 55; -- crescent +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 318; -- roost +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 212; -- mesa +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 367; -- steppes +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 226; -- mistythicket +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 195; -- kithforest +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 68; -- direwind +UPDATE `zone` SET `expansion` = 12 WHERE `id` = 12; -- ashengate +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 209; -- maidensgrave +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 192; -- kattacastrum +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 24; -- blacksail +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 16; -- barren +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 237; -- monkeyrock +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 13; -- atiiki +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 185; -- jardelshook +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 343; -- silyssar +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 63; -- deadbone +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 340; -- shippvu +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 29; -- buriedsea +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 341; -- shipuvu +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 372; -- suncrest +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 390; -- thalassius +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 339; -- shipmvu +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 338; -- shipmvp +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 337; -- shipmvm +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 313; -- redfeather +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 438; -- zhisza +UPDATE `zone` SET `expansion` = 13 WHERE `id` = 358; -- solteris +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 59; -- crystallos +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 211; -- mechanotus +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 57; -- cryptofshade +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 342; -- shipworkshop +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 207; -- lopingplains +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 144; -- guardian +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 26; -- bloodmoon +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 158; -- gyrospireb +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 159; -- gyrospirez +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 169; -- hillsofshade +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 366; -- steamfontmts +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 210; -- mansion +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 364; -- steamfactory +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 76; -- dragonscaleb +UPDATE `zone` SET `expansion` = 14 WHERE `id` = 75; -- dragonscale +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 402; -- thevoidg +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 198; -- korascian +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 69; -- discord +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 70; -- discordtower +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 22; -- bertoxtemple +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 260; -- oceangreenhills +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 261; -- oceangreenvillage +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 399; -- thevoidd +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 398; -- thevoidc +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 272; -- oldkithicor +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 273; -- oldkurn +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 311; -- rathechamber +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 409; -- toskirakk +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 396; -- thevoida +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 298; -- precipiceofwar +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 397; -- thevoidb +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 400; -- thevoide +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 271; -- oldkaesorab +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 264; -- oldblackburrow +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 401; -- thevoidf +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 265; -- oldbloodfield +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 266; -- oldcommons +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 267; -- olddranik +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 268; -- oldfieldofbone +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 269; -- oldhighpass +UPDATE `zone` SET `expansion` = 15 WHERE `id` = 270; -- oldkaesoraa +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 446; -- brellsarena +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 448; -- convorteum +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 447; -- stonesnake +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 445; -- underquarry +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 444; -- foundation +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 443; -- arthicrex +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 442; -- pellucid +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 441; -- coolingchamber +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 440; -- brellsrest +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 5878; -- weddingchapeldark +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 5879; -- dragoncrypt +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 5881; -- brellstemple +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 5882; -- fungalforest +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 5883; -- lichencreep +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 5884; -- shiningcity +UPDATE `zone` SET `expansion` = 16 WHERE `id` = 5877; -- weddingchapel +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5563; -- somnium +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5565; -- thulehouse1 +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5566; -- thulehouse2 +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5567; -- well +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5568; -- neighborhood +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5557; -- morellcastle +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5562; -- miragulmare +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5561; -- housegarden +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5560; -- feerrott2 +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5559; -- fallen +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5558; -- alkabormare +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5556; -- thulelibrary +UPDATE `zone` SET `expansion` = 17 WHERE `id` = 5564; -- thuledream +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5868; -- rubak +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5865; -- argath +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5875; -- eastsepulcher +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5874; -- sepulcher +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5873; -- cityofbronze +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5872; -- windsong +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5871; -- pillarsalra +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5870; -- resplendent +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5869; -- beastdomain +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5867; -- sarithcity +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5876; -- westsepulcher +UPDATE `zone` SET `expansion` = 18 WHERE `id` = 5866; -- arelis +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5894; -- xorbb +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5893; -- shardslanding +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5892; -- kaelshard +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5891; -- grelleth +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5890; -- eviltree +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5886; -- breedinggrounds +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5887; -- chapterhouse +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5888; -- crystalshard +UPDATE `zone` SET `expansion` = 19 WHERE `id` = 5889; -- eastwastesshard diff --git a/utils/sql/git/required/2022_08_22_npc_types_heroic_strikethrough.sql b/utils/sql/git/required/2022_08_22_npc_types_heroic_strikethrough.sql new file mode 100644 index 000000000..cf5abb1fe --- /dev/null +++ b/utils/sql/git/required/2022_08_22_npc_types_heroic_strikethrough.sql @@ -0,0 +1,2 @@ +ALTER TABLE `npc_types` +ADD COLUMN `heroic_strikethrough` INT NOT NULL DEFAULT 0 AFTER `exp_mod`; \ No newline at end of file diff --git a/utils/sql/git/required/2022_08_24_task_activities_step.sql b/utils/sql/git/required/2022_08_24_task_activities_step.sql new file mode 100644 index 000000000..b0d5019ef --- /dev/null +++ b/utils/sql/git/required/2022_08_24_task_activities_step.sql @@ -0,0 +1 @@ +ALTER TABLE `task_activities` MODIFY `step` INT(11) NOT NULL DEFAULT '0'; diff --git a/utils/sql/git/required/2022_09_02_faction_association.sql b/utils/sql/git/required/2022_09_02_faction_association.sql new file mode 100644 index 000000000..333562c74 --- /dev/null +++ b/utils/sql/git/required/2022_09_02_faction_association.sql @@ -0,0 +1,27 @@ +CREATE TABLE `faction_association` ( + `id` INT(10) NOT NULL, + `id_1` INT(10) NOT NULL DEFAULT 0, + `mod_1` FLOAT NOT NULL DEFAULT 0, + `id_2` INT(10) NOT NULL DEFAULT 0, + `mod_2` FLOAT NOT NULL DEFAULT 0, + `id_3` INT(10) NOT NULL DEFAULT 0, + `mod_3` FLOAT NOT NULL DEFAULT 0, + `id_4` INT(10) NOT NULL DEFAULT 0, + `mod_4` FLOAT NOT NULL DEFAULT 0, + `id_5` INT(10) NOT NULL DEFAULT 0, + `mod_5` FLOAT NOT NULL DEFAULT 0, + `id_6` INT(10) NOT NULL DEFAULT 0, + `mod_6` FLOAT NOT NULL DEFAULT 0, + `id_7` INT(10) NOT NULL DEFAULT 0, + `mod_7` FLOAT NOT NULL DEFAULT 0, + `id_8` INT(10) NOT NULL DEFAULT 0, + `mod_8` FLOAT NOT NULL DEFAULT 0, + `id_9` INT(10) NOT NULL DEFAULT 0, + `mod_9` FLOAT NOT NULL DEFAULT 0, + `id_10` INT(10) NOT NULL DEFAULT 0, + `mod_10` FLOAT NOT NULL DEFAULT 0, + PRIMARY KEY(`id`) +); + +ALTER TABLE `npc_types` ADD `faction_amount` INT(10) NOT NULL DEFAULT '0'; +ALTER TABLE `tasks` ADD `faction_amount` INT(10) NOT NULL DEFAULT '0'; diff --git a/utils/sql/git/required/2022_09_03_fix_door_destination_headings.sql b/utils/sql/git/required/2022_09_03_fix_door_destination_headings.sql new file mode 100644 index 000000000..32ed658f8 --- /dev/null +++ b/utils/sql/git/required/2022_09_03_fix_door_destination_headings.sql @@ -0,0 +1,1237 @@ +UPDATE doors set dest_heading = 256 WHERE zone = 'Tox' AND version = 0 AND dest_zone = 'poknowledge' AND id = '9'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '143'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '144'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '145'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '146'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '147'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '148'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '149'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '150'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '151'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '152'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '153'; +UPDATE doors set dest_heading = 168 WHERE zone = 'blackburrow' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '154'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1398'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1399'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1400'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1401'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1402'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1403'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1404'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1405'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1406'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1407'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1408'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1409'; +UPDATE doors set dest_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND dest_zone = 'NONE' AND id = '1410'; +UPDATE doors set dest_heading = 38 WHERE zone = 'qcat' AND version = 0 AND dest_zone = 'tox' AND id = '1917'; +UPDATE doors set dest_heading = 253 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'mistythicket' AND id = '2040'; +UPDATE doors set dest_heading = 326.58 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Gfaydark' AND id = '2041'; +UPDATE doors set dest_heading = 5.90002 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Butcher' AND id = '2042'; +UPDATE doors set dest_heading = 477.46 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Everfrost' AND id = '2043'; +UPDATE doors set dest_heading = 34 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Gfaydark' AND id = '2044'; +UPDATE doors set dest_heading = 256 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Nexus' AND id = '2046'; +UPDATE doors set dest_heading = 476 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Shadeweaver' AND id = '2048'; +UPDATE doors set dest_heading = 6 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Qeynos2' AND id = '2049'; +UPDATE doors set dest_heading = 238 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'PoTranquility' AND id = '2050'; +UPDATE doors set dest_heading = 510 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'overthere' AND id = '2054'; +UPDATE doors set dest_heading = 256 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Nektulos' AND id = '2057'; +UPDATE doors set dest_heading = 496 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Feerrott' AND id = '2058'; +UPDATE doors set dest_heading = 256 WHERE zone = 'qrg' AND version = 0 AND dest_zone = 'jaggedpine' AND id = '2095'; +UPDATE doors set dest_heading = 504 WHERE zone = 'Tox' AND version = 0 AND dest_zone = 'poknowledge' AND id = '2353'; +UPDATE doors set dest_heading = 256 WHERE zone = 'Everfrost' AND version = 0 AND dest_zone = 'poknowledge' AND id = '3415'; +UPDATE doors set dest_heading = 256 WHERE zone = 'Misty' AND version = 0 AND dest_zone = 'poknowledge' AND id = '4139'; +UPDATE doors set dest_heading = 262 WHERE zone = 'Nexus' AND version = 0 AND dest_zone = 'poknowledge' AND id = '4446'; +UPDATE doors set dest_heading = 500 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5321'; +UPDATE doors set dest_heading = 500 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5322'; +UPDATE doors set dest_heading = 500 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5323'; +UPDATE doors set dest_heading = 500 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5324'; +UPDATE doors set dest_heading = 500 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5325'; +UPDATE doors set dest_heading = 500 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5326'; +UPDATE doors set dest_heading = 500 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5327'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5328'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5329'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5331'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5332'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5333'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5334'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5335'; +UPDATE doors set dest_heading = 462 WHERE zone = 'airplane' AND version = 0 AND dest_zone = 'airplane' AND id = '5336'; +UPDATE doors set dest_heading = 510 WHERE zone = 'feerrott' AND version = 0 AND dest_zone = 'poknowledge' AND id = '5337'; +UPDATE doors set dest_heading = 4 WHERE zone = 'freportw' AND version = 0 AND dest_zone = 'poknowledge' AND id = '5783'; +UPDATE doors set dest_heading = 254 WHERE zone = 'qeynos2' AND version = 0 AND dest_zone = 'poknowledge' AND id = '5996'; +UPDATE doors set dest_heading = 504 WHERE zone = 'neriakc' AND version = 0 AND dest_zone = 'lfaydark' AND id = '6229'; +UPDATE doors set dest_heading = 2 WHERE zone = 'fieldofbone' AND version = 0 AND dest_zone = 'poknowledge' AND id = '6623'; +UPDATE doors set dest_heading = 254 WHERE zone = 'firiona' AND version = 0 AND dest_zone = 'poknowledge' AND id = '6624'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7009'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7010'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7011'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7012'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7013'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7014'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7015'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7016'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7017'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7018'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7019'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7020'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7021'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7022'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7023'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7024'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7025'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7026'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7027'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7028'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7029'; +UPDATE doors set dest_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND dest_zone = 'blackburrow' AND id = '7030'; +UPDATE doors set dest_heading = 508 WHERE zone = 'overthere' AND version = 0 AND dest_zone = 'poknowledge' AND id = '7123'; +UPDATE doors set dest_heading = 462 WHERE zone = 'overthere' AND version = 0 AND dest_zone = 'charasis' AND id = '7145'; +UPDATE doors set dest_heading = 256 WHERE zone = 'stonebrunt' AND version = 0 AND dest_zone = 'gunthak' AND id = '7590'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'cabwest' AND id = '7717'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'freporte' AND id = '7718'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'halas' AND id = '7719'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'felwithea' AND id = '7720'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'gfaydark' AND id = '7721'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'neriakb' AND id = '7722'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'erudnext' AND id = '7723'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'oggok' AND id = '7724'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'grobb' AND id = '7725'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'rivervale' AND id = '7726'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'akanon' AND id = '7727'; +UPDATE doors set dest_heading = 462 WHERE zone = 'timorous' AND version = 0 AND dest_zone = 'kaladima' AND id = '7728'; +UPDATE doors set dest_heading = 256 WHERE zone = 'trakanon' AND version = 0 AND dest_zone = 'sebilis' AND id = '7739'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7780'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7781'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7782'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7783'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7784'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7785'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7786'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7787'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7788'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7789'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7790'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7791'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7792'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7793'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7794'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7795'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7796'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7797'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7798'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7799'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7800'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7801'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7802'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7803'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7804'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'airplane' AND id = '7805'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'skyfire' AND id = '7806'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'skyfire' AND id = '7807'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'skyfire' AND id = '7808'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'skyfire' AND id = '7809'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'skyfire' AND id = '7810'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'skyfire' AND id = '7811'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'skyfire' AND id = '7812'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7813'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7814'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7815'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7816'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7817'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7818'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7819'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7820'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7821'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7822'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7823'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7824'; +UPDATE doors set dest_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'swampofnohope' AND id = '7825'; +UPDATE doors set dest_heading = 256 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'freporte' AND id = '7826'; +UPDATE doors set dest_heading = 256 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'freporte' AND id = '7827'; +UPDATE doors set dest_heading = 256 WHERE zone = 'veeshan' AND version = 0 AND dest_zone = 'freporte' AND id = '7828'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'sleeper' AND id = '7941'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7954'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7955'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7956'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7957'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7958'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7959'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7960'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7961'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7962'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7963'; +UPDATE doors set dest_heading = 256 WHERE zone = 'eastwastes' AND version = 0 AND dest_zone = 'crystal' AND id = '7964'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '7974'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '7975'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '7976'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '7977'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '8001'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '8003'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '8005'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'frozenshadow' AND id = '8012'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'frozenshadow' AND id = '8013'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'frozenshadow' AND id = '8014'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'frozenshadow' AND id = '8015'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'frozenshadow' AND id = '8016'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '8017'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '8018'; +UPDATE doors set dest_heading = 184 WHERE zone = 'frozenshadow' AND version = 0 AND dest_zone = 'iceclad' AND id = '8020'; +UPDATE doors set dest_heading = 84 WHERE zone = 'greatdivide' AND version = 0 AND dest_zone = 'poknowledge' AND id = '8046'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8185'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8187'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8188'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8189'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8190'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8191'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8192'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8193'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8194'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8196'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8198'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8199'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8200'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8201'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8202'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8203'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8204'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8205'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8206'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8207'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8208'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8209'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8210'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8211'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8212'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8213'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8214'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8215'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8216'; +UPDATE doors set dest_heading = 270 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8217'; +UPDATE doors set dest_heading = 270 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8218'; +UPDATE doors set dest_heading = 270 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8219'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8220'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8221'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8222'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8223'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8224'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8225'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8226'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8227'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8228'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8230'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8231'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8232'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8233'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8234'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8235'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8236'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8237'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8238'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8240'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8241'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8242'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8243'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8244'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8245'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8246'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8247'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8248'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8249'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8250'; +UPDATE doors set dest_heading = 132 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8251'; +UPDATE doors set dest_heading = 132 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8252'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8253'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8254'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8255'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8256'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8257'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8258'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8259'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8260'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8261'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8262'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8263'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8264'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8265'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8266'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8267'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8268'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8269'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8270'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8271'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8272'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8273'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8274'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8275'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8276'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8277'; +UPDATE doors set dest_heading = 254 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8279'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8280'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8281'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8282'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8283'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8284'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8285'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8286'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8287'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8288'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8289'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8290'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8291'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8292'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8293'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8294'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8295'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8296'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8297'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8298'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8300'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8302'; +UPDATE doors set dest_heading = 510 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8303'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8305'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8307'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8310'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8311'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8312'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8313'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8315'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8316'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8317'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8318'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8320'; +UPDATE doors set dest_heading = 508 WHERE zone = 'mischiefplane' AND version = 0 AND dest_zone = 'mischiefplane' AND id = '8322'; +UPDATE doors set dest_heading = 260 WHERE zone = 'necropolis' AND version = 0 AND dest_zone = 'westwastes' AND id = '8326'; +UPDATE doors set dest_heading = 260 WHERE zone = 'necropolis' AND version = 0 AND dest_zone = 'westwastes' AND id = '8327'; +UPDATE doors set dest_heading = 260 WHERE zone = 'necropolis' AND version = 0 AND dest_zone = 'westwastes' AND id = '8328'; +UPDATE doors set dest_heading = 260 WHERE zone = 'necropolis' AND version = 0 AND dest_zone = 'westwastes' AND id = '8329'; +UPDATE doors set dest_heading = 260 WHERE zone = 'necropolis' AND version = 0 AND dest_zone = 'westwastes' AND id = '8330'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND dest_zone = 'skyshrine' AND id = '8397'; +UPDATE doors set dest_heading = 10 WHERE zone = 'skyshrine' AND version = 0 AND dest_zone = 'cobaltscar' AND id = '8398'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND dest_zone = 'skyshrine' AND id = '8470'; +UPDATE doors set dest_heading = 258 WHERE zone = 'skyshrine' AND version = 0 AND dest_zone = 'skyshrine' AND id = '8471'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND dest_zone = 'skyshrine' AND id = '8472'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND dest_zone = 'skyshrine' AND id = '8473'; +UPDATE doors set dest_heading = 408 WHERE zone = 'sleeper' AND version = 0 AND dest_zone = 'eastwastes' AND id = '8507'; +UPDATE doors set dest_heading = 422 WHERE zone = 'westwastes' AND version = 0 AND dest_zone = 'templeveeshan' AND id = '8702'; +UPDATE doors set dest_heading = 338 WHERE zone = 'westwastes' AND version = 0 AND dest_zone = 'necropolis' AND id = '8703'; +UPDATE doors set dest_heading = 256 WHERE zone = 'echo' AND version = 0 AND dest_zone = 'fungusgrove' AND id = '8719'; +UPDATE doors set dest_heading = 256 WHERE zone = 'echo' AND version = 0 AND dest_zone = 'fungusgrove' AND id = '8720'; +UPDATE doors set dest_heading = 256 WHERE zone = 'echo' AND version = 0 AND dest_zone = 'fungusgrove' AND id = '8721'; +UPDATE doors set dest_heading = 256 WHERE zone = 'echo' AND version = 0 AND dest_zone = 'fungusgrove' AND id = '8722'; +UPDATE doors set dest_heading = 256 WHERE zone = 'echo' AND version = 0 AND dest_zone = 'fungusgrove' AND id = '8723'; +UPDATE doors set dest_heading = 256 WHERE zone = 'echo' AND version = 0 AND dest_zone = 'fungusgrove' AND id = '8724'; +UPDATE doors set dest_heading = 488 WHERE zone = 'katta' AND version = 0 AND dest_zone = 'katta' AND id = '8734'; +UPDATE doors set dest_heading = 488 WHERE zone = 'katta' AND version = 0 AND dest_zone = 'katta' AND id = '8735'; +UPDATE doors set dest_heading = 508 WHERE zone = 'katta' AND version = 0 AND dest_zone = 'katta' AND id = '8794'; +UPDATE doors set dest_heading = 14 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8796'; +UPDATE doors set dest_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8797'; +UPDATE doors set dest_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8798'; +UPDATE doors set dest_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8799'; +UPDATE doors set dest_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8881'; +UPDATE doors set dest_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8886'; +UPDATE doors set dest_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8889'; +UPDATE doors set dest_heading = 256 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8890'; +UPDATE doors set dest_heading = 386.2 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8892'; +UPDATE doors set dest_heading = 14 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8893'; +UPDATE doors set dest_heading = 504 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8894'; +UPDATE doors set dest_heading = 504 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'vexthal' AND id = '8895'; +UPDATE doors set dest_heading = 506 WHERE zone = 'vexthal' AND version = 0 AND dest_zone = 'umbral' AND id = '8896'; +UPDATE doors set dest_heading = 256 WHERE zone = 'twilight' AND version = 0 AND dest_zone = 'fungusgrove' AND id = '8916'; +UPDATE doors set dest_heading = 128.8 WHERE zone = 'umbral' AND version = 0 AND dest_zone = 'vexthal' AND id = '8917'; +UPDATE doors set dest_heading = 256 WHERE zone = 'ssratemple' AND version = 0 AND dest_zone = 'ssratemple' AND id = '8920'; +UPDATE doors set dest_heading = 252 WHERE zone = 'ssratemple' AND version = 0 AND dest_zone = 'ssratemple' AND id = '8926'; +UPDATE doors set dest_heading = 498 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9113'; +UPDATE doors set dest_heading = 496 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9114'; +UPDATE doors set dest_heading = 240 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9115'; +UPDATE doors set dest_heading = 504 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9116'; +UPDATE doors set dest_heading = 494 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9117'; +UPDATE doors set dest_heading = 248 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9118'; +UPDATE doors set dest_heading = 238 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9119'; +UPDATE doors set dest_heading = 6 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9120'; +UPDATE doors set dest_heading = 256 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9121'; +UPDATE doors set dest_heading = 504 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9122'; +UPDATE doors set dest_heading = 264 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9123'; +UPDATE doors set dest_heading = 6 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9124'; +UPDATE doors set dest_heading = 254 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9125'; +UPDATE doors set dest_heading = 508 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9126'; +UPDATE doors set dest_heading = 494 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9127'; +UPDATE doors set dest_heading = 244 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9128'; +UPDATE doors set dest_heading = 494 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9129'; +UPDATE doors set dest_heading = 240 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9130'; +UPDATE doors set dest_heading = 492 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9132'; +UPDATE doors set dest_heading = 242 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9133'; +UPDATE doors set dest_heading = 506 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9134'; +UPDATE doors set dest_heading = 248 WHERE zone = 'sseru' AND version = 0 AND dest_zone = 'sseru' AND id = '9135'; +UPDATE doors set dest_heading = 462 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'shadowhaven' AND id = '9261'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9282'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9283'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9284'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9285'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9286'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9287'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9288'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9289'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9290'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9291'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9292'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9293'; +UPDATE doors set dest_heading = 254 WHERE zone = 'shadowhaven' AND version = 0 AND dest_zone = 'bazaar' AND id = '9294'; +UPDATE doors set dest_heading = 384 WHERE zone = 'shadeweaver' AND version = 0 AND dest_zone = 'poknowledge' AND id = '9363'; +UPDATE doors set dest_heading = 2 WHERE zone = 'nexus' AND version = 0 AND dest_zone = 'poknowledge' AND id = '9372'; +UPDATE doors set dest_heading = 244 WHERE zone = 'griegsend' AND version = 0 AND dest_zone = 'griegsend' AND id = '9462'; +UPDATE doors set dest_heading = 382 WHERE zone = 'bazaar' AND version = 0 AND dest_zone = 'bazaar' AND id = '9622'; +UPDATE doors set dest_heading = 640 WHERE zone = 'bazaar' AND version = 0 AND dest_zone = 'bazaar' AND id = '9624'; +UPDATE doors set dest_heading = 136 WHERE zone = 'bazaar' AND version = 0 AND dest_zone = 'poknowledge' AND id = '9678'; +UPDATE doors set dest_heading = 370 WHERE zone = 'codecay' AND version = 0 AND dest_zone = 'potranquility' AND id = '10807'; +UPDATE doors set dest_heading = 370 WHERE zone = 'codecay' AND version = 0 AND dest_zone = 'potranquility' AND id = '10809'; +UPDATE doors set dest_heading = 220 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10810'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10812'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10815'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10816'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10817'; +UPDATE doors set dest_heading = 492 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10818'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10819'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10821'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10822'; +UPDATE doors set dest_heading = 398 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'potranquility' AND id = '10863'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10871'; +UPDATE doors set dest_heading = 504 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10881'; +UPDATE doors set dest_heading = 240 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10914'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10917'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10918'; +UPDATE doors set dest_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND dest_zone = 'pojustice' AND id = '10923'; +UPDATE doors set dest_heading = 254 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'poknowledge' AND id = '10927'; +UPDATE doors set dest_heading = 254 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'pojustice' AND id = '10941'; +UPDATE doors set dest_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'hohonora' AND id = '10943'; +UPDATE doors set dest_heading = 188 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'potimea' AND id = '10947'; +UPDATE doors set dest_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'codecay' AND id = '10949'; +UPDATE doors set dest_heading = 374 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'poinnovation' AND id = '10952'; +UPDATE doors set dest_heading = 502 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'pofire' AND id = '10977'; +UPDATE doors set dest_heading = 113.8 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'powater' AND id = '10979'; +UPDATE doors set dest_heading = 10 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'ponightmare' AND id = '10980'; +UPDATE doors set dest_heading = 250 WHERE zone = 'ponightmare' AND version = 0 AND dest_zone = 'nightmareb' AND id = '10981'; +UPDATE doors set dest_heading = 242 WHERE zone = 'ponightmare' AND version = 0 AND dest_zone = 'potranquility' AND id = '10986'; +UPDATE doors set dest_heading = 244 WHERE zone = 'ponightmare' AND version = 0 AND dest_zone = 'potranquility' AND id = '11015'; +UPDATE doors set dest_heading = 248 WHERE zone = 'poinnovation' AND version = 0 AND dest_zone = 'potranquility' AND id = '11040'; +UPDATE doors set dest_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'povalor' AND id = '11187'; +UPDATE doors set dest_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND dest_zone = 'bothunder' AND id = '11198'; +UPDATE doors set dest_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND dest_zone = 'bothunder' AND id = '11202'; +UPDATE doors set dest_heading = 184 WHERE zone = 'bothunder' AND version = 0 AND dest_zone = 'potranquility' AND id = '11204'; +UPDATE doors set dest_heading = 312 WHERE zone = 'postorms' AND version = 0 AND dest_zone = 'potranquility' AND id = '11218'; +UPDATE doors set dest_heading = 256 WHERE zone = 'hohonora' AND version = 0 AND dest_zone = 'hohonorb' AND id = '11223'; +UPDATE doors set dest_heading = 256 WHERE zone = 'hohonora' AND version = 0 AND dest_zone = 'hohonorb' AND id = '11224'; +UPDATE doors set dest_heading = 294 WHERE zone = 'hohonora' AND version = 0 AND dest_zone = 'potranquility' AND id = '11225'; +UPDATE doors set dest_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'povalor' AND id = '11263'; +UPDATE doors set dest_heading = 264 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'nexus' AND id = '11264'; +UPDATE doors set dest_heading = 472 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'shadeweaver' AND id = '11265'; +UPDATE doors set dest_heading = 498 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'potranquility' AND id = '11266'; +UPDATE doors set dest_heading = 262 WHERE zone = 'potranquility' AND version = 0 AND dest_zone = 'potranquility' AND id = '11267'; +UPDATE doors set dest_heading = 256 WHERE zone = 'pofire' AND version = 0 AND dest_zone = 'potranquility' AND id = '11321'; +UPDATE doors set dest_heading = 256 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'potimeb' AND id = '11359'; +UPDATE doors set dest_heading = 462 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'potimea' AND id = '11361'; +UPDATE doors set dest_heading = 462 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'potimea' AND id = '11362'; +UPDATE doors set dest_heading = 462 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'potimea' AND id = '11364'; +UPDATE doors set dest_heading = 256 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'potimeb' AND id = '11377'; +UPDATE doors set dest_heading = 10 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'ponightmare' AND id = '11379'; +UPDATE doors set dest_heading = 2 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'fearplane' AND id = '11382'; +UPDATE doors set dest_heading = 392 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'potimeb' AND id = '11405'; +UPDATE doors set dest_heading = 462 WHERE zone = 'potimeb' AND version = 0 AND dest_zone = 'potimea' AND id = '11406'; +UPDATE doors set dest_heading = 60 WHERE zone = 'kodtaz' AND version = 0 AND dest_zone = 'natimbi' AND id = '11552'; +UPDATE doors set dest_heading = 462 WHERE zone = 'kodtaz' AND version = 0 AND dest_zone = 'yxtta' AND id = '11571'; +UPDATE doors set dest_heading = 462 WHERE zone = 'kodtaz' AND version = 0 AND dest_zone = 'yxtta' AND id = '11572'; +UPDATE doors set dest_heading = 462 WHERE zone = 'kodtaz' AND version = 0 AND dest_zone = 'yxtta' AND id = '11573'; +UPDATE doors set dest_heading = 128 WHERE zone = 'qvic' AND version = 0 AND dest_zone = 'txevu' AND id = '11659'; +UPDATE doors set dest_heading = 128 WHERE zone = 'tacvi' AND version = 0 AND dest_zone = 'txevu' AND id = '11715'; +UPDATE doors set dest_heading = 348 WHERE zone = 'tipt' AND version = 0 AND dest_zone = 'barindu' AND id = '11719'; +UPDATE doors set dest_heading = 384 WHERE zone = 'txevu' AND version = 0 AND dest_zone = 'qvic' AND id = '11746'; +UPDATE doors set dest_heading = 348 WHERE zone = 'vxed' AND version = 0 AND dest_zone = 'barindu' AND id = '11753'; +UPDATE doors set dest_heading = 256 WHERE zone = 'provinggrounds' AND version = 0 AND dest_zone = 'wallofslaughter' AND id = '11828'; +UPDATE doors set dest_heading = 256 WHERE zone = 'riftseekers' AND version = 0 AND dest_zone = 'provinggrounds' AND id = '11942'; +UPDATE doors set dest_heading = 332 WHERE zone = 'wallofslaughter' AND version = 0 AND dest_zone = 'provinggrounds' AND id = '11943'; +UPDATE doors set dest_heading = 94 WHERE zone = 'delvea' AND version = 0 AND dest_zone = 'delveb' AND id = '11957'; +UPDATE doors set dest_heading = 386 WHERE zone = 'delvea' AND version = 0 AND dest_zone = 'delveb' AND id = '11958'; +UPDATE doors set dest_heading = 260 WHERE zone = 'guildhall' AND version = 0 AND dest_zone = 'guildlobby' AND id = '11962'; +UPDATE doors set dest_heading = 450 WHERE zone = 'guildlobby' AND version = 0 AND dest_zone = 'poknowledge' AND id = '11964'; +UPDATE doors set dest_heading = 256 WHERE zone = 'gunthak' AND version = 0 AND dest_zone = 'poknowledge' AND id = '12119'; +UPDATE doors set dest_heading = 256 WHERE zone = 'poknowledge' AND version = 0 AND dest_zone = 'arena' AND id = '12122'; +UPDATE doors set dest_heading = 2 WHERE zone = 'nektulos' AND version = 0 AND dest_zone = 'poknowledge' AND id = '12283'; +UPDATE doors set dest_heading = 34 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Rathemtn' AND id = '12285'; +UPDATE doors set dest_heading = 256 WHERE zone = 'povalor' AND version = 0 AND dest_zone = 'hohonora' AND id = '12290'; +UPDATE doors set dest_heading = 306 WHERE zone = 'povalor' AND version = 0 AND dest_zone = 'potranquility' AND id = '12296'; +UPDATE doors set dest_heading = 298 WHERE zone = 'potactics' AND version = 0 AND dest_zone = 'potranquility' AND id = '12314'; +UPDATE doors set dest_heading = 298 WHERE zone = 'potactics' AND version = 0 AND dest_zone = 'potranquility' AND id = '12315'; +UPDATE doors set dest_heading = 298 WHERE zone = 'potactics' AND version = 0 AND dest_zone = 'potranquility' AND id = '12316'; +UPDATE doors set dest_heading = 298 WHERE zone = 'potactics' AND version = 0 AND dest_zone = 'potranquility' AND id = '12317'; +UPDATE doors set dest_heading = 496 WHERE zone = 'potorment' AND version = 0 AND dest_zone = 'potranquility' AND id = '12519'; +UPDATE doors set dest_heading = 496 WHERE zone = 'potorment' AND version = 0 AND dest_zone = 'potranquility' AND id = '12520'; +UPDATE doors set dest_heading = 256 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12532'; +UPDATE doors set dest_heading = 504 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12533'; +UPDATE doors set dest_heading = 246 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12534'; +UPDATE doors set dest_heading = 224 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12535'; +UPDATE doors set dest_heading = 250 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12537'; +UPDATE doors set dest_heading = 10 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12538'; +UPDATE doors set dest_heading = 506 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12539'; +UPDATE doors set dest_heading = 252 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12540'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12541'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12542'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12543'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12544'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12545'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12546'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12547'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12548'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12549'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12550'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12551'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12552'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12553'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12554'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12555'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12556'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12557'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12558'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12559'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12560'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'solrotower' AND id = '12561'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'NONE' AND id = '12562'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'NONE' AND id = '12563'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'NONE' AND id = '12564'; +UPDATE doors set dest_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND dest_zone = 'NONE' AND id = '12565'; +UPDATE doors set dest_heading = 498 WHERE zone = 'poair' AND version = 0 AND dest_zone = 'potranquility' AND id = '12567'; +UPDATE doors set dest_heading = 256 WHERE zone = 'poair' AND version = 0 AND dest_zone = 'poair' AND id = '12568'; +UPDATE doors set dest_heading = 256 WHERE zone = 'poair' AND version = 0 AND dest_zone = 'poair' AND id = '12569'; +UPDATE doors set dest_heading = 366 WHERE zone = 'powater' AND version = 0 AND dest_zone = 'potranquility' AND id = '12572'; +UPDATE doors set dest_heading = 264 WHERE zone = 'poeartha' AND version = 0 AND dest_zone = 'poearthb' AND id = '12573'; +UPDATE doors set dest_heading = 264 WHERE zone = 'poeartha' AND version = 0 AND dest_zone = 'poearthb' AND id = '12575'; +UPDATE doors set dest_heading = 264 WHERE zone = 'poeartha' AND version = 0 AND dest_zone = 'poearthb' AND id = '12576'; +UPDATE doors set dest_heading = 264 WHERE zone = 'poeartha' AND version = 0 AND dest_zone = 'potranquility' AND id = '12577'; +UPDATE doors set dest_heading = 256 WHERE zone = 'hohonorb' AND version = 0 AND dest_zone = 'hohonora' AND id = '12578'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rathemtn' AND version = 0 AND dest_zone = 'poknowledge' AND id = '12797'; +UPDATE doors set dest_heading = 256 WHERE zone = 'shadowrest' AND version = 0 AND dest_zone = 'poknowledge' AND id = '12798'; +UPDATE doors set dest_heading = 510 WHERE zone = 'butcher' AND version = 0 AND dest_zone = 'poknowledge' AND id = '12913'; +UPDATE doors set dest_heading = 510 WHERE zone = 'everfrost' AND version = 0 AND dest_zone = 'NONE' AND id = '12951'; +UPDATE doors set dest_heading = 510 WHERE zone = 'everfrost' AND version = 0 AND dest_zone = 'NONE' AND id = '12954'; +UPDATE doors set dest_heading = 510 WHERE zone = 'everfrost' AND version = 0 AND dest_zone = 'NONE' AND id = '12955'; +UPDATE doors set dest_heading = 510 WHERE zone = 'everfrost' AND version = 0 AND dest_zone = 'NONE' AND id = '12956'; +UPDATE doors set dest_heading = 256 WHERE zone = 'innothule' AND version = 0 AND dest_zone = 'NONE' AND id = '13011'; +UPDATE doors set dest_heading = 2 WHERE zone = 'nektulos' AND version = 0 AND dest_zone = 'corathus' AND id = '13016'; +UPDATE doors set dest_heading = 396 WHERE zone = 'corathus' AND version = 1 AND dest_zone = 'nektulos' AND id = '13017'; +UPDATE doors set dest_heading = 260 WHERE zone = 'guildhall' AND version = 1 AND dest_zone = 'guildlobby' AND id = '14152'; +UPDATE doors set dest_heading = 149 WHERE zone = 'poknowledge' AND version = 0 AND dest_zone = 'crescent' AND id = '14153'; +UPDATE doors set dest_heading = 126 WHERE zone = 'crescent' AND version = 0 AND dest_zone = 'poknowledge' AND id = '14156'; +UPDATE doors set dest_heading = 28 WHERE zone = 'snplant' AND version = 0 AND dest_zone = 'barindu' AND id = '15971'; +UPDATE doors set dest_heading = 28 WHERE zone = 'snplant' AND version = 0 AND dest_zone = 'barindu' AND id = '15972'; +UPDATE doors set dest_heading = 28 WHERE zone = 'snplant' AND version = 1 AND dest_zone = 'barindu' AND id = '15973'; +UPDATE doors set dest_heading = 28 WHERE zone = 'snplant' AND version = 1 AND dest_zone = 'barindu' AND id = '15974'; +UPDATE doors set dest_heading = 2 WHERE zone = 'nektulos' AND version = 1 AND dest_zone = 'poknowledge' AND id = '15975'; +UPDATE doors set dest_heading = 256 WHERE zone = 'mistythicket' AND version = 0 AND dest_zone = 'poknowledge' AND id = '15987'; +UPDATE doors set dest_heading = 28 WHERE zone = 'sncrematory' AND version = 0 AND dest_zone = 'barindu' AND id = '15990'; +UPDATE doors set dest_heading = 28 WHERE zone = 'sncrematory' AND version = 0 AND dest_zone = 'barindu' AND id = '15991'; +UPDATE doors set dest_heading = 28 WHERE zone = 'snlair' AND version = 0 AND dest_zone = 'barindu' AND id = '16069'; +UPDATE doors set dest_heading = 28 WHERE zone = 'snpool' AND version = 0 AND dest_zone = 'barindu' AND id = '16070'; +UPDATE doors set dest_heading = 134 WHERE zone = 'ikkinz' AND version = 0 AND dest_zone = 'kodtaz' AND id = '16113'; +UPDATE doors set dest_heading = 510 WHERE zone = 'uqua' AND version = 0 AND dest_zone = 'yxtta' AND id = '16143'; +UPDATE doors set dest_heading = 258 WHERE zone = 'ikkinz' AND version = 1 AND dest_zone = 'kodtaz' AND id = '16144'; +UPDATE doors set dest_heading = 14 WHERE zone = 'ikkinz' AND version = 2 AND dest_zone = 'kodtaz' AND id = '16160'; +UPDATE doors set dest_heading = 260 WHERE zone = 'inktuta' AND version = 0 AND dest_zone = 'qvic' AND id = '16201'; +UPDATE doors set dest_heading = 714 WHERE zone = 'drachnidhive' AND version = 0 AND dest_zone = 'westkorlach' AND id = '16233'; +UPDATE doors set dest_heading = 268 WHERE zone = 'westkorlach' AND version = 0 AND dest_zone = 'drachnidhive' AND id = '16287'; +UPDATE doors set dest_heading = 1999998 WHERE zone = 'freeportwest' AND version = 0 AND dest_zone = 'freeportwest' AND id = '16852'; +UPDATE doors set dest_heading = 1999998 WHERE zone = 'freeportwest' AND version = 0 AND dest_zone = 'freeportwest' AND id = '16853'; +UPDATE doors set dest_heading = 4 WHERE zone = 'freeportwest' AND version = 0 AND dest_zone = 'poknowledge' AND id = '16889'; +UPDATE doors set dest_heading = 1999998 WHERE zone = 'moors' AND version = 0 AND dest_zone = 'moors' AND id = '16998'; +UPDATE doors set dest_heading = 1999998 WHERE zone = 'moors' AND version = 0 AND dest_zone = 'moors' AND id = '16999'; +UPDATE doors set dest_heading = 12.6 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'Nektulos' AND id = '17151'; +UPDATE doors set dest_heading = 498.6 WHERE zone = 'corathus' AND version = 0 AND dest_zone = 'nektulos' AND id = '17152'; +UPDATE doors set dest_heading = 962 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17210'; +UPDATE doors set dest_heading = 684 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17211'; +UPDATE doors set dest_heading = 238 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17212'; +UPDATE doors set dest_heading = 694 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17213'; +UPDATE doors set dest_heading = 766 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17214'; +UPDATE doors set dest_heading = 320 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17215'; +UPDATE doors set dest_heading = 300 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17216'; +UPDATE doors set dest_heading = 644 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17217'; +UPDATE doors set dest_heading = 892 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17218'; +UPDATE doors set dest_heading = 270 WHERE zone = 'roost' AND version = 0 AND dest_zone = 'roost' AND id = '17219'; +UPDATE doors set dest_heading = 514 WHERE zone = 'toxxulia' AND version = 0 AND dest_zone = 'poknowledge' AND id = '17328'; +UPDATE doors set dest_heading = 512 WHERE zone = 'toxxulia' AND version = 0 AND dest_zone = 'poknowledge' AND id = '17329'; +UPDATE doors set dest_heading = 768 WHERE zone = 'innothuleb' AND version = 0 AND dest_zone = 'poknowledge' AND id = '17404'; +UPDATE doors set dest_heading = 768 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17417'; +UPDATE doors set dest_heading = 1002 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17440'; +UPDATE doors set dest_heading = 1020 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17441'; +UPDATE doors set dest_heading = 512 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17444'; +UPDATE doors set dest_heading = 512 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17445'; +UPDATE doors set dest_heading = 768 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17448'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17449'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17450'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17451'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17452'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17453'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17454'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17455'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17456'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17457'; +UPDATE doors set dest_heading = 768 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17458'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17461'; +UPDATE doors set dest_heading = 96 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17462'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17463'; +UPDATE doors set dest_heading = 186 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17464'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17465'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17466'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17467'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17468'; +UPDATE doors set dest_heading = 318 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17470'; +UPDATE doors set dest_heading = 450 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17471'; +UPDATE doors set dest_heading = 768 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17472'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17473'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17474'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17475'; +UPDATE doors set dest_heading = 726 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17476'; +UPDATE doors set dest_heading = 580 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17477'; +UPDATE doors set dest_heading = 768 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17478'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17479'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17480'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17481'; +UPDATE doors set dest_heading = 954 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17482'; +UPDATE doors set dest_heading = 804 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17483'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17484'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17485'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17486'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17487'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17490'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17491'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17492'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17493'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17496'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17497'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17498'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17499'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17502'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17503'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17504'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17505'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17508'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17509'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17510'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17511'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17514'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17515'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17516'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17517'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17520'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17521'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17522'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17523'; +UPDATE doors set dest_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17526'; +UPDATE doors set dest_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17527'; +UPDATE doors set dest_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17528'; +UPDATE doors set dest_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '17529'; +UPDATE doors set dest_heading = 512 WHERE zone = 'kattacastrum' AND version = 0 AND dest_zone = 'buriedsea' AND id = '17532'; +UPDATE doors set dest_heading = 512 WHERE zone = 'steamfontmts' AND version = 0 AND dest_zone = 'poknowledge' AND id = '17586'; +UPDATE doors set dest_heading = 452 WHERE zone = 'zhisza' AND version = 0 AND dest_zone = 'silyssar' AND id = '18621'; +UPDATE doors set dest_heading = 614 WHERE zone = 'zhisza' AND version = 0 AND dest_zone = 'kattacastrum' AND id = '18623'; +UPDATE doors set dest_heading = 190 WHERE zone = 'discord' AND version = 0 AND dest_zone = 'thevoida' AND id = '18698'; +UPDATE doors set dest_heading = 584 WHERE zone = 'oceangreenhills' AND version = 0 AND dest_zone = 'thevoida' AND id = '18706'; +UPDATE doors set dest_heading = 868 WHERE zone = 'oldbloodfield' AND version = 0 AND dest_zone = 'thevoida' AND id = '18737'; +UPDATE doors set dest_heading = 112 WHERE zone = 'oldkithicor' AND version = 0 AND dest_zone = 'thevoida' AND id = '18761'; +UPDATE doors set dest_heading = 260 WHERE zone = 'oldfieldofbone' AND version = 0 AND dest_zone = 'thevoida' AND id = '18818'; +UPDATE doors set dest_heading = 816 WHERE zone = 'toskirakk' AND version = 0 AND dest_zone = 'thevoida' AND id = '18879'; +UPDATE doors set dest_heading = 256 WHERE zone = 'ruja' AND version = 0 AND dest_zone = 'sro' AND id = '24445'; +UPDATE doors set dest_heading = 256 WHERE zone = 'ruja' AND version = -1 AND dest_zone = 'sro' AND id = '24446'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujb' AND version = 0 AND dest_zone = 'sro' AND id = '24478'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujb' AND version = -1 AND dest_zone = 'sro' AND id = '24479'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujc' AND version = 0 AND dest_zone = 'sro' AND id = '24654'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujc' AND version = -1 AND dest_zone = 'sro' AND id = '24655'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujd' AND version = 0 AND dest_zone = 'sro' AND id = '25127'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujd' AND version = -1 AND dest_zone = 'sro' AND id = '25128'; +UPDATE doors set dest_heading = 256 WHERE zone = 'ruje' AND version = 0 AND dest_zone = 'sro' AND id = '25262'; +UPDATE doors set dest_heading = 256 WHERE zone = 'ruje' AND version = -1 AND dest_zone = 'sro' AND id = '25263'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujf' AND version = 0 AND dest_zone = 'sro' AND id = '25343'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujf' AND version = -1 AND dest_zone = 'sro' AND id = '25344'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujg' AND version = 0 AND dest_zone = 'sro' AND id = '25688'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujg' AND version = -1 AND dest_zone = 'sro' AND id = '25689'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujh' AND version = 0 AND dest_zone = 'sro' AND id = '26051'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujh' AND version = -1 AND dest_zone = 'sro' AND id = '26052'; +UPDATE doors set dest_heading = 256 WHERE zone = 'ruji' AND version = 0 AND dest_zone = 'sro' AND id = '26182'; +UPDATE doors set dest_heading = 256 WHERE zone = 'ruji' AND version = -1 AND dest_zone = 'sro' AND id = '26183'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujj' AND version = 0 AND dest_zone = 'sro' AND id = '26193'; +UPDATE doors set dest_heading = 256 WHERE zone = 'rujj' AND version = -1 AND dest_zone = 'sro' AND id = '26194'; +UPDATE doors set dest_heading = 520 WHERE zone = 'arena' AND version = 0 AND dest_zone = 'poknowledge' AND id = '33835'; +UPDATE doors set dest_heading = 262 WHERE zone = 'silyssar' AND version = 0 AND dest_zone = 'zhisza' AND id = '33848'; +UPDATE doors set dest_heading = 60 WHERE zone = 'potimea' AND version = 0 AND dest_zone = 'thevoida' AND id = '33871'; +UPDATE doors set dest_heading = 758 WHERE zone = 'nightmareb' AND version = 0 AND dest_zone = 'ponightmare' AND id = '33872'; +UPDATE doors set dest_heading = 386 WHERE zone = 'ikkinz' AND version = 3 AND dest_zone = 'kodtaz' AND id = '33887'; +UPDATE doors set dest_heading = 252 WHERE zone = 'ikkinz' AND version = 4 AND dest_zone = 'kodtaz' AND id = '33903'; +UPDATE doors set dest_heading = 382 WHERE zone = 'ikkinz' AND version = 5 AND dest_zone = 'kodtaz' AND id = '33919'; +UPDATE doors set dest_heading = 386 WHERE zone = 'ikkinz' AND version = 6 AND dest_zone = 'kodtaz' AND id = '33935'; +UPDATE doors set dest_heading = 127 WHERE zone = 'weddingchapel' AND version = 0 AND dest_zone = 'poknowledge' AND id = '33952'; +UPDATE doors set dest_heading = 127 WHERE zone = 'weddingchapeldark' AND version = 0 AND dest_zone = 'poknowledge' AND id = '33953'; +UPDATE doors set dest_heading = 495 WHERE zone = 'well' AND version = 0 AND dest_zone = 'housegarden' AND id = '33954'; +UPDATE doors set dest_heading = 495 WHERE zone = 'well' AND version = 0 AND dest_zone = 'housegarden' AND id = '33955'; +UPDATE doors set dest_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34031'; +UPDATE doors set dest_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34032'; +UPDATE doors set dest_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34033'; +UPDATE doors set dest_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34034'; +UPDATE doors set dest_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34035'; +UPDATE doors set dest_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34036'; +UPDATE doors set dest_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34039'; +UPDATE doors set dest_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34040'; +UPDATE doors set dest_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34041'; +UPDATE doors set dest_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34042'; +UPDATE doors set dest_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34043'; +UPDATE doors set dest_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34044'; +UPDATE doors set dest_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34047'; +UPDATE doors set dest_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34048'; +UPDATE doors set dest_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34049'; +UPDATE doors set dest_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34050'; +UPDATE doors set dest_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34051'; +UPDATE doors set dest_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34052'; +UPDATE doors set dest_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34055'; +UPDATE doors set dest_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34056'; +UPDATE doors set dest_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34057'; +UPDATE doors set dest_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34058'; +UPDATE doors set dest_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34059'; +UPDATE doors set dest_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34060'; +UPDATE doors set dest_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34063'; +UPDATE doors set dest_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34064'; +UPDATE doors set dest_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34065'; +UPDATE doors set dest_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34066'; +UPDATE doors set dest_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34067'; +UPDATE doors set dest_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34068'; +UPDATE doors set dest_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34071'; +UPDATE doors set dest_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34072'; +UPDATE doors set dest_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34073'; +UPDATE doors set dest_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34074'; +UPDATE doors set dest_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34075'; +UPDATE doors set dest_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34076'; +UPDATE doors set dest_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34079'; +UPDATE doors set dest_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34080'; +UPDATE doors set dest_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34081'; +UPDATE doors set dest_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34082'; +UPDATE doors set dest_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34083'; +UPDATE doors set dest_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'neighborhood' AND id = '34084'; +UPDATE doors set dest_heading = 254 WHERE zone = 'neighborhood' AND version = 0 AND dest_zone = 'guildlobby' AND id = '34089'; +UPDATE doors set dest_heading = 510 WHERE zone = 'fallen' AND version = 0 AND dest_zone = 'fallen' AND id = '34163'; +UPDATE doors set dest_heading = 127 WHERE zone = 'fallen' AND version = 0 AND dest_zone = 'fallen' AND id = '34164'; +UPDATE doors set dest_heading = 255 WHERE zone = 'fallen' AND version = 0 AND dest_zone = 'thulehouse1' AND id = '34170'; +UPDATE doors set dest_heading = 255 WHERE zone = 'feerrott2' AND version = 0 AND dest_zone = 'poknowledge' AND id = '34179'; +UPDATE doors set dest_heading = 255 WHERE zone = 'housegarden' AND version = 0 AND dest_zone = 'thulehouse1' AND id = '34188'; +UPDATE doors set dest_heading = 383 WHERE zone = 'miragulmare' AND version = 0 AND dest_zone = 'thulehouse2' AND id = '34191'; +UPDATE doors set dest_heading = 104 WHERE zone = 'morellcastle' AND version = 0 AND dest_zone = 'morellcastle' AND id = '34199'; +UPDATE doors set dest_heading = 511 WHERE zone = 'thulehouse1' AND version = 0 AND dest_zone = 'thulelibrary' AND id = '34444'; +UPDATE doors set dest_heading = 462 WHERE zone = 'thulehouse1' AND version = 0 AND dest_zone = 'feerrott2' AND id = '34466'; +UPDATE doors set dest_heading = 382 WHERE zone = 'thulehouse1' AND version = 0 AND dest_zone = 'housegarden' AND id = '34468'; +UPDATE doors set dest_heading = 440 WHERE zone = 'thulehouse2' AND version = 0 AND dest_zone = 'alkabormare' AND id = '34487'; +UPDATE doors set dest_heading = 82 WHERE zone = 'thulehouse2' AND version = 0 AND dest_zone = 'thuledream' AND id = '34508'; +UPDATE doors set dest_heading = 128 WHERE zone = 'thulehouse2' AND version = 0 AND dest_zone = 'miragulmare' AND id = '34520'; +UPDATE doors set dest_heading = 383 WHERE zone = 'thulelibrary' AND version = 0 AND dest_zone = 'thulehouse1' AND id = '34558'; +UPDATE doors set dest_heading = 500 WHERE zone = 'guke' AND version = 50 AND dest_zone = 'INNOTHULE' AND id = '34739'; +UPDATE doors set dest_heading = 192 WHERE zone = 'discordtower' AND version = 0 AND dest_zone = 'discord' AND id = '34902'; +UPDATE doors set dest_heading = 170 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35557'; +UPDATE doors set dest_heading = 182 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35560'; +UPDATE doors set dest_heading = 273 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35562'; +UPDATE doors set dest_heading = 42 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35564'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35566'; +UPDATE doors set dest_heading = 410 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35567'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35568'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35569'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35570'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35571'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35572'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35573'; +UPDATE doors set dest_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35575'; +UPDATE doors set dest_heading = 245 WHERE zone = 'pillarsalra' AND version = 0 AND dest_zone = 'pillarsalra' AND id = '35576'; +UPDATE doors set dest_heading = 10 WHERE zone = 'skyshrine' AND version = 1 AND dest_zone = 'cobaltscar' AND id = '35794'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND dest_zone = 'skyshrine' AND id = '35795'; +UPDATE doors set dest_heading = 258 WHERE zone = 'skyshrine' AND version = 1 AND dest_zone = 'skyshrine' AND id = '35796'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND dest_zone = 'skyshrine' AND id = '35797'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND dest_zone = 'skyshrine' AND id = '35798'; +UPDATE doors set dest_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND dest_zone = 'skyshrine' AND id = '35801'; +UPDATE doors set dest_heading = 485 WHERE zone = 'breedinggrounds' AND version = 0 AND dest_zone = '752' AND id = '35877'; +UPDATE doors set dest_heading = 508 WHERE zone = 'breedinggrounds' AND version = 0 AND dest_zone = 'necropolis' AND id = '35893'; +UPDATE doors set dest_heading = 312 WHERE zone = 'chapterhouse' AND version = 0 AND dest_zone = '752' AND id = '35997'; +UPDATE doors set dest_heading = 384 WHERE zone = 'eastwastesshard' AND version = 0 AND dest_zone = '756' AND id = '36040'; +UPDATE doors set dest_heading = 426 WHERE zone = 'eastwastesshard' AND version = 0 AND dest_zone = '752' AND id = '36061'; +UPDATE doors set dest_heading = 15 WHERE zone = 'eastwastesshard' AND version = 0 AND dest_zone = 'eastwastes' AND id = '36062'; +UPDATE doors set dest_heading = 145 WHERE zone = 'eviltree' AND version = 0 AND dest_zone = '752' AND id = '36114'; +UPDATE doors set dest_heading = 427 WHERE zone = 'eviltree' AND version = 0 AND dest_zone = 'beastdomain' AND id = '36160'; +UPDATE doors set dest_heading = 75 WHERE zone = 'grelleth' AND version = 0 AND dest_zone = '752' AND id = '36203'; +UPDATE doors set dest_heading = 314 WHERE zone = 'grelleth' AND version = 0 AND dest_zone = 'resplendent' AND id = '36204'; +UPDATE doors set dest_heading = 314 WHERE zone = 'grelleth' AND version = 0 AND dest_zone = 'resplendent' AND id = '36205'; +UPDATE doors set dest_heading = 128 WHERE zone = 'shardslanding' AND version = 0 AND dest_zone = '760' AND id = '36427'; +UPDATE doors set dest_heading = 507 WHERE zone = 'shardslanding' AND version = 0 AND dest_zone = '753' AND id = '36428'; +UPDATE doors set dest_heading = 29 WHERE zone = 'shardslanding' AND version = 0 AND dest_zone = '755' AND id = '36429'; +UPDATE doors set dest_heading = 66 WHERE zone = 'shardslanding' AND version = 0 AND dest_zone = '758' AND id = '36432'; +UPDATE doors set dest_heading = 366 WHERE zone = 'xorbb' AND version = 0 AND dest_zone = '752' AND id = '36461'; +UPDATE doors set dest_heading = 321 WHERE zone = 'xorbb' AND version = 0 AND dest_zone = 'beholder' AND id = '36535'; +UPDATE doors set dest_heading = 328 WHERE zone = 'guildlobby' AND version = 1 AND dest_zone = 'poknowledge' AND id = '36631'; +UPDATE doors set dest_heading = 260 WHERE zone = 'guildhall' AND version = 0 AND dest_zone = 'guildlobby' AND id = '36666'; +UPDATE doors set dest_heading = 260 WHERE zone = 'guildhall' AND version = 1 AND dest_zone = 'guildlobby' AND id = '36667'; +UPDATE doors set dest_heading = 4 WHERE zone = 'PoKnowledge' AND version = 0 AND dest_zone = 'misty' AND id = '36669'; +UPDATE doors set dest_heading = 216 WHERE zone = 'gukg' AND version = 50 AND dest_zone = 'innothule' AND id = '36796'; +UPDATE doors set dest_heading = 384 WHERE zone = 'chambersa' AND version = 0 AND dest_zone = 'provinggrounds' AND id = '36801'; +UPDATE doors set dest_heading = 330 WHERE zone = 'chambersd' AND version = 0 AND dest_zone = 'provinggrounds' AND id = '36804'; +UPDATE doors set dest_heading = 178 WHERE zone = 'chambersf' AND version = 0 AND dest_zone = 'provinggrounds' AND id = '36806'; +UPDATE doors set dest_heading = 384 WHERE zone = 'chambersa' AND version = 1 AND dest_zone = 'provinggrounds' AND id = '36807'; +UPDATE doors set dest_heading = 330 WHERE zone = 'chambersd' AND version = 1 AND dest_zone = 'provinggrounds' AND id = '36810'; +UPDATE doors set dest_heading = 178 WHERE zone = 'chambersf' AND version = 1 AND dest_zone = 'provinggrounds' AND id = '36812'; +UPDATE doors set dest_heading = 384 WHERE zone = 'chambersa' AND version = 2 AND dest_zone = 'provinggrounds' AND id = '36813'; +UPDATE doors set dest_heading = 330 WHERE zone = 'chambersd' AND version = 2 AND dest_zone = 'provinggrounds' AND id = '36816'; +UPDATE doors set dest_heading = 178 WHERE zone = 'chambersf' AND version = 2 AND dest_zone = 'provinggrounds' AND id = '36818'; + +UPDATE doors SET dest_x = -852, dest_y = 1122, dest_z = -50, dest_heading = 275 WHERE id = 1917; +UPDATE doors SET dest_x = -734, dest_y = -188, dest_z = -3, dest_heading = 430 WHERE id = 2041; +UPDATE doors SET dest_x = -523, dest_y = 1726, dest_z = -1, dest_heading = 45 WHERE id = 2042; +UPDATE doors SET dest_x = -31, dest_y = 2835, dest_z = -62, dest_heading = 453 WHERE id = 2043; +UPDATE doors SET dest_x = -1824, dest_y = -2223, dest_z = -1, dest_heading = 244 WHERE id = 2044; +UPDATE doors SET dest_x = 442, dest_y = 48, dest_z = -29, dest_heading = 388 WHERE id = 2046; +UPDATE doors SET dest_x = -2433, dest_y = -2970, dest_z = -215, dest_heading = 236 WHERE id = 2048; +UPDATE doors SET dest_x = 487, dest_y = 219, dest_z = 2, dest_heading = 267 WHERE id = 2049; +UPDATE doors SET dest_x = -1463, dest_y = 774, dest_z = -878, dest_heading = 131 WHERE id = 2050; +UPDATE doors SET dest_x = 4673, dest_y = -455, dest_z = 9, dest_heading = 128 WHERE id = 2051; +UPDATE doors SET dest_x = 1888, dest_y = 3133, dest_z = -51, dest_heading = 128 WHERE id = 2054; +UPDATE doors SET dest_x = 1845, dest_y = -2980, dest_z = 11, dest_heading = 259 WHERE id = 2055; +UPDATE doors SET dest_x = -843, dest_y = -814, dest_z = 9, dest_heading = 457 WHERE id = 2057; +UPDATE doors SET dest_x = 0, dest_y = -110, dest_z = 5, dest_heading = 999 WHERE id = 2057; +UPDATE doors SET dest_x = -163, dest_y = 908, dest_z = -9, dest_heading = 248 WHERE id = 2058; +UPDATE doors SET dest_x = 131, dest_y = 846, dest_z = -157, dest_heading = 511 WHERE id = 3415; +UPDATE doors SET dest_x = -76, dest_y = 381, dest_z = -157, dest_heading = 1 WHERE id = 4446; +UPDATE doors SET dest_x = 97, dest_y = 812, dest_z = -157, dest_heading = 380 WHERE id = 4968; +UPDATE doors SET dest_x = 882, dest_y = 838, dest_z = -157, dest_heading = 2 WHERE id = 4969; +UPDATE doors SET dest_x = 574, dest_y = 1463, dest_z = -765, dest_heading = 250 WHERE id = 5321; +UPDATE doors SET dest_x = -434, dest_y = -103, dest_z = -359, dest_heading = 999 WHERE id = 5328; +UPDATE doors SET dest_x = -781, dest_y = 1185, dest_z = 130, dest_heading = 999 WHERE id = 5329; +UPDATE doors SET dest_x = 1089, dest_y = -884, dest_z = 412, dest_heading = 999 WHERE id = 5331; +UPDATE doors SET dest_x = 306, dest_y = -750, dest_z = 772, dest_heading = 999 WHERE id = 5332; +UPDATE doors SET dest_x = -471, dest_y = -984, dest_z = 1013, dest_heading = 999 WHERE id = 5333; +UPDATE doors SET dest_x = -1294, dest_y = -262, dest_z = 1221, dest_heading = 999 WHERE id = 5334; +UPDATE doors SET dest_x = 1108, dest_y = 516, dest_z = -8, dest_heading = 999 WHERE id = 5335; +UPDATE doors SET dest_x = -434, dest_y = -103, dest_z = -359, dest_heading = 999 WHERE id = 5336; +UPDATE doors SET dest_x = 444, dest_y = -844, dest_z = -157, dest_heading = 255 WHERE id = 5337; +UPDATE doors SET dest_x = -190, dest_y = 290, dest_z = 7, dest_heading = 256 WHERE id = 5677; +UPDATE doors SET dest_x = 73, dest_y = -177, dest_z = -298, dest_heading = 145 WHERE id = 5678; +UPDATE doors SET dest_x = 73, dest_y = -177, dest_z = -298, dest_heading = 145 WHERE id = 5679; +UPDATE doors SET dest_x = 73, dest_y = -177, dest_z = -298, dest_heading = 145 WHERE id = 5680; +UPDATE doors SET dest_x = -234, dest_y = -406, dest_z = -157, dest_heading = 258 WHERE id = 5783; +UPDATE doors SET dest_x = -289, dest_y = 147, dest_z = -157, dest_heading = 383 WHERE id = 5996; +UPDATE doors SET dest_x = 36, dest_y = -655, dest_z = -157, dest_heading = 1 WHERE id = 6623; +UPDATE doors SET dest_x = -279, dest_y = -363, dest_z = -157, dest_heading = 383 WHERE id = 6624; +UPDATE doors SET dest_x = 155, dest_y = 155, dest_z = -155, dest_heading = 255 WHERE id = 7009; +UPDATE doors SET dest_x = -511, dest_y = 66, dest_z = 42, dest_heading = 256 WHERE id = 7031; +UPDATE doors SET dest_x = 884, dest_y = -840, dest_z = -157, dest_heading = 254 WHERE id = 7123; +UPDATE doors SET dest_x = 0, dest_y = 0, dest_z = -2, dest_heading = 999 WHERE id = 7145; +UPDATE doors SET dest_x = -940, dest_y = 1460, dest_z = 16, dest_heading = 128 WHERE id = 7590; +UPDATE doors SET dest_x = 767, dest_y = -783, dest_z = 8, dest_heading = 999 WHERE id = 7717; +UPDATE doors SET dest_x = -818, dest_y = -616, dest_z = 2, dest_heading = 999 WHERE id = 7718; +UPDATE doors SET dest_x = 94, dest_y = -25, dest_z = 3, dest_heading = 999 WHERE id = 7720; +UPDATE doors SET dest_x = 10, dest_y = -20, dest_z = 0, dest_heading = 999 WHERE id = 7721; +UPDATE doors SET dest_x = -500, dest_y = 3, dest_z = -10, dest_heading = 999 WHERE id = 7722; +UPDATE doors SET dest_x = 0, dest_y = 0, dest_z = 20, dest_heading = 999 WHERE id = 7723; +UPDATE doors SET dest_x = -99, dest_y = -345, dest_z = 4, dest_heading = 999 WHERE id = 7724; +UPDATE doors SET dest_x = 0, dest_y = -100, dest_z = 3, dest_heading = 999 WHERE id = 7725; +UPDATE doors SET dest_x = 0, dest_y = 0, dest_z = 4, dest_heading = 999 WHERE id = 7726; +UPDATE doors SET dest_x = -35, dest_y = 47, dest_z = 4, dest_heading = 999 WHERE id = 7727; +UPDATE doors SET dest_x = -2, dest_y = -18, dest_z = 3, dest_heading = 999 WHERE id = 7728; +UPDATE doors SET dest_x = -1, dest_y = 248, dest_z = 41, dest_heading = 257 WHERE id = 7739; +UPDATE doors SET dest_x = 785, dest_y = -3095, dest_z = -158, dest_heading = 999 WHERE id = 7780; +UPDATE doors SET dest_x = 785, dest_y = -3095, dest_z = -158, dest_heading = 999 WHERE id = 7806; +UPDATE doors SET dest_x = 785, dest_y = -3095, dest_z = -158, dest_heading = 999 WHERE id = 7813; +UPDATE doors SET dest_x = -1442, dest_y = -1012, dest_z = 35, dest_heading = 999 WHERE id = 7826; +UPDATE doors SET dest_x = -37, dest_y = -13, dest_z = 3, dest_heading = 128 WHERE id = 7941; +UPDATE doors SET dest_x = 303, dest_y = 487, dest_z = -74, dest_heading = 384 WHERE id = 7954; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 7974; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8001; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8003; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8005; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8012; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8013; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8014; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8015; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8016; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8017; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8018; +UPDATE doors SET dest_x = 2739, dest_y = 1786, dest_z = 113, dest_heading = 348 WHERE id = 8020; +UPDATE doors SET dest_x = -235, dest_y = 393, dest_z = -157, dest_heading = 810 WHERE id = 8046; +UPDATE doors SET dest_x = 77, dest_y = 335, dest_z = 170, dest_heading = 255 WHERE id = 8187; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8196; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8197; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 128 WHERE id = 8198; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8199; +UPDATE doors SET dest_x = -127, dest_y = 760, dest_z = 175, dest_heading = 0 WHERE id = 8199; +UPDATE doors SET dest_x = 114, dest_y = 230, dest_z = 175, dest_heading = 135 WHERE id = 8217; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8220; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 128 WHERE id = 8222; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8223; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8235; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8240; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8242; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8245; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8246; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8247; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8248; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8249; +UPDATE doors SET dest_x = 77, dest_y = 335, dest_z = 170, dest_heading = 255 WHERE id = 8250; +UPDATE doors SET dest_x = 421, dest_y = 1428, dest_z = -5, dest_heading = 322 WHERE id = 8251; +UPDATE doors SET dest_x = 114, dest_y = 712, dest_z = 147, dest_heading = 383 WHERE id = 8253; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 128 WHERE id = 8274; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8274; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 255 WHERE id = 8274; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 128 WHERE id = 8275; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8275; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 255 WHERE id = 8275; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 128 WHERE id = 8276; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8276; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 255 WHERE id = 8276; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 128 WHERE id = 8277; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 383 WHERE id = 8279; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 255 WHERE id = 8280; +UPDATE doors SET dest_x = -390, dest_y = 95, dest_z = 120, dest_heading = 510 WHERE id = 8281; +UPDATE doors SET dest_x = -127, dest_y = 687, dest_z = 175, dest_heading = 128 WHERE id = 8282; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8300; +UPDATE doors SET dest_x = -180, dest_y = 80, dest_z = 115, dest_heading = 255 WHERE id = 8300; +UPDATE doors SET dest_x = -415, dest_y = 1520, dest_z = 270, dest_heading = 255 WHERE id = 8302; +UPDATE doors SET dest_x = -6, dest_y = 83, dest_z = 115, dest_heading = 255 WHERE id = 8303; +UPDATE doors SET dest_x = -180, dest_y = 80, dest_z = 115, dest_heading = 255 WHERE id = 8303; +UPDATE doors SET dest_x = -390, dest_y = 95, dest_z = 120, dest_heading = 510 WHERE id = 8305; +UPDATE doors SET dest_x = -390, dest_y = 95, dest_z = 120, dest_heading = 510 WHERE id = 8307; +UPDATE doors SET dest_x = 508, dest_y = -2867, dest_z = -196, dest_heading = 386 WHERE id = 8326; +UPDATE doors SET dest_x = -326, dest_y = 425, dest_z = 44, dest_heading = 999 WHERE id = 8397; +UPDATE doors SET dest_x = 894, dest_y = -942, dest_z = 315, dest_heading = 5 WHERE id = 8398; +UPDATE doors SET dest_x = -326, dest_y = 425, dest_z = 44, dest_heading = 999 WHERE id = 8470; +UPDATE doors SET dest_x = 660, dest_y = -60, dest_z = 4, dest_heading = 385 WHERE id = 8471; +UPDATE doors SET dest_x = -326, dest_y = 425, dest_z = 44, dest_heading = 999 WHERE id = 8472; +UPDATE doors SET dest_x = 1198, dest_y = 1231, dest_z = 4, dest_heading = 999 WHERE id = 8473; +UPDATE doors SET dest_x = 133, dest_y = -7279, dest_z = 161, dest_heading = 204 WHERE id = 8507; +UPDATE doors SET dest_x = 3019, dest_y = -2493, dest_z = -21, dest_heading = 256 WHERE id = 8648; +UPDATE doors SET dest_x = -499, dest_y = -2025, dest_z = -44, dest_heading = 211 WHERE id = 8702; +UPDATE doors SET dest_x = 1976, dest_y = -86, dest_z = 4, dest_heading = 425 WHERE id = 8703; +UPDATE doors SET dest_x = 1798, dest_y = 380, dest_z = -54, dest_heading = 256 WHERE id = 8718; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8719; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8720; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8720; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8721; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8721; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8722; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8722; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8723; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8724; +UPDATE doors SET dest_x = -1145, dest_y = -2328, dest_z = -308, dest_heading = 128 WHERE id = 8724; +UPDATE doors SET dest_x = 1798, dest_y = 380, dest_z = -54, dest_heading = 256 WHERE id = 8725; +UPDATE doors SET dest_x = -1085, dest_y = -163, dest_z = -266, dest_heading = 244 WHERE id = 8734; +UPDATE doors SET dest_x = -1085, dest_y = -163, dest_z = -266, dest_heading = 244 WHERE id = 8735; +UPDATE doors SET dest_x = -96, dest_y = -907, dest_z = 143, dest_heading = 256 WHERE id = 8736; +UPDATE doors SET dest_x = -96, dest_y = -907, dest_z = 210, dest_heading = 256 WHERE id = 8736; +UPDATE doors SET dest_x = -96, dest_y = -907, dest_z = 143, dest_heading = 256 WHERE id = 8737; +UPDATE doors SET dest_x = -96, dest_y = -907, dest_z = 210, dest_heading = 256 WHERE id = 8737; +UPDATE doors SET dest_x = -100, dest_y = -760, dest_z = 4, dest_heading = 510 WHERE id = 8794; +UPDATE doors SET dest_x = -96, dest_y = -907, dest_z = 73, dest_heading = 256 WHERE id = 8795; +UPDATE doors SET dest_x = -316, dest_y = 734, dest_z = -33, dest_heading = 263 WHERE id = 8796; +UPDATE doors SET dest_x = 907, dest_y = 0, dest_z = 129, dest_heading = 382 WHERE id = 8797; +UPDATE doors SET dest_x = 907, dest_y = 0, dest_z = 129, dest_heading = 382 WHERE id = 8797; +UPDATE doors SET dest_x = 907, dest_y = 0, dest_z = 129, dest_heading = 382 WHERE id = 8798; +UPDATE doors SET dest_x = 907, dest_y = 0, dest_z = 129, dest_heading = 382 WHERE id = 8798; +UPDATE doors SET dest_x = -1265, dest_y = 363, dest_z = -35, dest_heading = 126 WHERE id = 8799; +UPDATE doors SET dest_x = 1529, dest_y = 473, dest_z = 120, dest_heading = 382 WHERE id = 8881; +UPDATE doors SET dest_x = 1534, dest_y = -470, dest_z = 120, dest_heading = 382 WHERE id = 8881; +UPDATE doors SET dest_x = 1529, dest_y = 473, dest_z = 120, dest_heading = 382 WHERE id = 8886; +UPDATE doors SET dest_x = 1534, dest_y = -470, dest_z = 120, dest_heading = 382 WHERE id = 8886; +UPDATE doors SET dest_x = 1100, dest_y = 0, dest_z = 237, dest_heading = 126 WHERE id = 8889; +UPDATE doors SET dest_x = 1455, dest_y = 3, dest_z = 118, dest_heading = 128 WHERE id = 8890; +UPDATE doors SET dest_x = -1287, dest_y = 358, dest_z = -39, dest_heading = 125 WHERE id = 8892; +UPDATE doors SET dest_x = -316, dest_y = 734, dest_z = -33, dest_heading = 263 WHERE id = 8893; +UPDATE doors SET dest_x = -316, dest_y = -742, dest_z = -33, dest_heading = 508 WHERE id = 8894; +UPDATE doors SET dest_x = -316, dest_y = -742, dest_z = -33, dest_heading = 508 WHERE id = 8895; +UPDATE doors SET dest_x = -741, dest_y = -1451, dest_z = 12, dest_heading = 253 WHERE id = 8896; +UPDATE doors SET dest_x = 2333, dest_y = 1955, dest_z = 19, dest_heading = 384 WHERE id = 8916; +UPDATE doors SET dest_x = -1664, dest_y = 216, dest_z = -35, dest_heading = 2 WHERE id = 8917; +UPDATE doors SET dest_x = 620, dest_y = -324, dest_z = 405, dest_heading = 126 WHERE id = 8926; +UPDATE doors SET dest_x = -447, dest_y = 1016, dest_z = 225, dest_heading = 249 WHERE id = 9113; +UPDATE doors SET dest_x = -12, dest_y = 1017, dest_z = 225, dest_heading = 248 WHERE id = 9114; +UPDATE doors SET dest_x = 64, dest_y = 82, dest_z = 157, dest_heading = 376 WHERE id = 9115; +UPDATE doors SET dest_x = 280, dest_y = -730, dest_z = 157, dest_heading = 3 WHERE id = 9115; +UPDATE doors SET dest_x = 281, dest_y = -137, dest_z = 157, dest_heading = 252 WHERE id = 9116; +UPDATE doors SET dest_x = 65, dest_y = -947, dest_z = 157, dest_heading = 388 WHERE id = 9116; +UPDATE doors SET dest_x = 179, dest_y = -132, dest_z = 122, dest_heading = 247 WHERE id = 9117; +UPDATE doors SET dest_x = 65, dest_y = -22, dest_z = 122, dest_heading = 380 WHERE id = 9118; +UPDATE doors SET dest_x = 179, dest_y = -730, dest_z = 122, dest_heading = 510 WHERE id = 9118; +UPDATE doors SET dest_x = -526, dest_y = 82, dest_z = 157, dest_heading = 119 WHERE id = 9119; +UPDATE doors SET dest_x = -528, dest_y = -944, dest_z = 157, dest_heading = 122 WHERE id = 9119; +UPDATE doors SET dest_x = -743, dest_y = -132, dest_z = 157, dest_heading = 259 WHERE id = 9120; +UPDATE doors SET dest_x = -746, dest_y = -724, dest_z = 157, dest_heading = 503 WHERE id = 9120; +UPDATE doors SET dest_x = -533, dest_y = -17, dest_z = 122, dest_heading = 128 WHERE id = 9121; +UPDATE doors SET dest_x = -531, dest_y = -843, dest_z = 122, dest_heading = 120 WHERE id = 9121; +UPDATE doors SET dest_x = -642, dest_y = -134, dest_z = 122, dest_heading = 252 WHERE id = 9122; +UPDATE doors SET dest_x = -643, dest_y = -730, dest_z = 122, dest_heading = 503 WHERE id = 9122; +UPDATE doors SET dest_x = 281, dest_y = -137, dest_z = 157, dest_heading = 252 WHERE id = 9123; +UPDATE doors SET dest_x = 65, dest_y = -947, dest_z = 157, dest_heading = 388 WHERE id = 9123; +UPDATE doors SET dest_x = 64, dest_y = 82, dest_z = 157, dest_heading = 376 WHERE id = 9124; +UPDATE doors SET dest_x = 280, dest_y = -730, dest_z = 157, dest_heading = 3 WHERE id = 9124; +UPDATE doors SET dest_x = 66, dest_y = -844, dest_z = 122, dest_heading = 383 WHERE id = 9125; +UPDATE doors SET dest_x = 65, dest_y = -22, dest_z = 122, dest_heading = 380 WHERE id = 9126; +UPDATE doors SET dest_x = 179, dest_y = -730, dest_z = 122, dest_heading = 510 WHERE id = 9126; +UPDATE doors SET dest_x = -743, dest_y = -132, dest_z = 157, dest_heading = 259 WHERE id = 9127; +UPDATE doors SET dest_x = -746, dest_y = -724, dest_z = 157, dest_heading = 503 WHERE id = 9127; +UPDATE doors SET dest_x = -526, dest_y = 82, dest_z = 157, dest_heading = 119 WHERE id = 9128; +UPDATE doors SET dest_x = -528, dest_y = -944, dest_z = 157, dest_heading = 122 WHERE id = 9128; +UPDATE doors SET dest_x = -642, dest_y = -134, dest_z = 122, dest_heading = 252 WHERE id = 9129; +UPDATE doors SET dest_x = -643, dest_y = -730, dest_z = 122, dest_heading = 503 WHERE id = 9129; +UPDATE doors SET dest_x = -533, dest_y = -17, dest_z = 122, dest_heading = 128 WHERE id = 9130; +UPDATE doors SET dest_x = -531, dest_y = -843, dest_z = 122, dest_heading = 120 WHERE id = 9130; +UPDATE doors SET dest_x = -331, dest_y = 987, dest_z = 59, dest_heading = 251 WHERE id = 9131; +UPDATE doors SET dest_x = -133, dest_y = 995, dest_z = 59, dest_heading = 246 WHERE id = 9132; +UPDATE doors SET dest_x = -372, dest_y = -282, dest_z = 130, dest_heading = 124 WHERE id = 9133; +UPDATE doors SET dest_x = 367, dest_y = 1148, dest_z = 59, dest_heading = 121 WHERE id = 9133; +UPDATE doors SET dest_x = -92, dest_y = -579, dest_z = 193, dest_heading = 509 WHERE id = 9134; +UPDATE doors SET dest_x = -372, dest_y = -282, dest_z = 130, dest_heading = 124 WHERE id = 9135; +UPDATE doors SET dest_x = 367, dest_y = 1148, dest_z = 59, dest_heading = 121 WHERE id = 9135; +UPDATE doors SET dest_x = 1300, dest_y = 190, dest_z = -55, dest_heading = 999 WHERE id = 9261; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9282; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9282; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9283; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9283; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9284; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9284; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9285; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9285; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9286; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9286; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9286; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9287; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9287; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9287; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9288; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9288; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9288; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9289; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9290; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9291; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9291; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9292; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9292; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9293; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9293; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9294; +UPDATE doors SET dest_x = -335, dest_y = -145, dest_z = 3, dest_heading = 127 WHERE id = 9294; +UPDATE doors SET dest_x = -293, dest_y = 364, dest_z = -157, dest_heading = 383 WHERE id = 9363; +UPDATE doors SET dest_x = -76, dest_y = 381, dest_z = -157, dest_heading = 1 WHERE id = 9372; +UPDATE doors SET dest_x = 2390, dest_y = 191, dest_z = -54, dest_heading = 378 WHERE id = 9462; +UPDATE doors SET dest_x = 1340, dest_y = 243, dest_z = -108, dest_heading = 68 WHERE id = 9678; +UPDATE doors SET dest_x = -1140, dest_y = 1925, dest_z = -877, dest_heading = 185 WHERE id = 10807; +UPDATE doors SET dest_x = -1140, dest_y = 1925, dest_z = -877, dest_heading = 185 WHERE id = 10809; +UPDATE doors SET dest_x = 715, dest_y = -471, dest_z = -26, dest_heading = 110 WHERE id = 10810; +UPDATE doors SET dest_x = 613, dest_y = -434, dest_z = -26, dest_heading = 254 WHERE id = 10812; +UPDATE doors SET dest_x = 615, dest_y = -535, dest_z = -26, dest_heading = 254 WHERE id = 10812; +UPDATE doors SET dest_x = 445, dest_y = -500, dest_z = -26, dest_heading = 502 WHERE id = 10813; +UPDATE doors SET dest_x = 275, dest_y = -436, dest_z = -26, dest_heading = 254 WHERE id = 10815; +UPDATE doors SET dest_x = 275, dest_y = -539, dest_z = -26, dest_heading = 254 WHERE id = 10815; +UPDATE doors SET dest_x = 613, dest_y = -434, dest_z = -26, dest_heading = 254 WHERE id = 10816; +UPDATE doors SET dest_x = 615, dest_y = -535, dest_z = -26, dest_heading = 254 WHERE id = 10816; +UPDATE doors SET dest_x = 530, dest_y = -438, dest_z = -26, dest_heading = 254 WHERE id = 10817; +UPDATE doors SET dest_x = 445, dest_y = -500, dest_z = -26, dest_heading = 502 WHERE id = 10818; +UPDATE doors SET dest_x = 444, dest_y = -400, dest_z = -26, dest_heading = 0 WHERE id = 10818; +UPDATE doors SET dest_x = 445, dest_y = -436, dest_z = -26, dest_heading = 254 WHERE id = 10819; +UPDATE doors SET dest_x = 445, dest_y = -539, dest_z = -26, dest_heading = 254 WHERE id = 10819; +UPDATE doors SET dest_x = 360, dest_y = -436, dest_z = -26, dest_heading = 254 WHERE id = 10821; +UPDATE doors SET dest_x = 275, dest_y = -436, dest_z = -26, dest_heading = 254 WHERE id = 10822; +UPDATE doors SET dest_x = 275, dest_y = -539, dest_z = -26, dest_heading = 254 WHERE id = 10822; +UPDATE doors SET dest_x = -587, dest_y = -30, dest_z = -519, dest_heading = 455 WHERE id = 10863; +UPDATE doors SET dest_x = 445, dest_y = -539, dest_z = -26, dest_heading = 254 WHERE id = 10871; +UPDATE doors SET dest_x = 470, dest_y = 862, dest_z = 9, dest_heading = 252 WHERE id = 10881; +UPDATE doors SET dest_x = 680, dest_y = -471, dest_z = -23, dest_heading = 376 WHERE id = 10914; +UPDATE doors SET dest_x = 445, dest_y = -539, dest_z = -26, dest_heading = 254 WHERE id = 10917; +UPDATE doors SET dest_x = 445, dest_y = -539, dest_z = -26, dest_heading = 254 WHERE id = 10918; +UPDATE doors SET dest_x = 445, dest_y = -436, dest_z = -26, dest_heading = 254 WHERE id = 10923; +UPDATE doors SET dest_x = 445, dest_y = -539, dest_z = -26, dest_heading = 254 WHERE id = 10923; +UPDATE doors SET dest_x = -285, dest_y = -148, dest_z = -159, dest_heading = 383 WHERE id = 10927; +UPDATE doors SET dest_x = -2755, dest_y = 0, dest_z = 0, dest_heading = 128 WHERE id = 10943; +UPDATE doors SET dest_x = 223, dest_y = 140, dest_z = 9, dest_heading = 350 WHERE id = 10947; +UPDATE doors SET dest_x = -170, dest_y = -65, dest_z = -93, dest_heading = 128 WHERE id = 10949; +UPDATE doors SET dest_x = 263, dest_y = 516, dest_z = -53, dest_heading = 187 WHERE id = 10952; +UPDATE doors SET dest_x = -1387, dest_y = 1210, dest_z = -180, dest_heading = 251 WHERE id = 10977; +UPDATE doors SET dest_x = 1668, dest_y = 282, dest_z = 212, dest_heading = 5 WHERE id = 10980; +UPDATE doors SET dest_x = 1597, dest_y = 23, dest_z = -324, dest_heading = 125 WHERE id = 10981; +UPDATE doors SET dest_x = -1225, dest_y = -189, dest_z = -902, dest_heading = 377 WHERE id = 10986; +UPDATE doors SET dest_x = -1246, dest_y = -182, dest_z = -902, dest_heading = 378 WHERE id = 11015; +UPDATE doors SET dest_x = 245, dest_y = -1549, dest_z = -919, dest_heading = 380 WHERE id = 11040; +UPDATE doors SET dest_x = 0, dest_y = 0, dest_z = -1550, dest_heading = 256 WHERE id = 11196; +UPDATE doors SET dest_x = 0, dest_y = 0, dest_z = -1550, dest_heading = 128 WHERE id = 11198; +UPDATE doors SET dest_x = 0, dest_y = 0, dest_z = -1550, dest_heading = 128 WHERE id = 11202; +UPDATE doors SET dest_x = 1740, dest_y = -720, dest_z = -931, dest_heading = 348 WHERE id = 11204; +UPDATE doors SET dest_x = 178, dest_y = 207, dest_z = -1620, dest_heading = 256 WHERE id = 11214; +UPDATE doors SET dest_x = 1097, dest_y = -682, dest_z = -929, dest_heading = 412 WHERE id = 11218; +UPDATE doors SET dest_x = 960, dest_y = -1, dest_z = 397, dest_heading = 128 WHERE id = 11223; +UPDATE doors SET dest_x = 960, dest_y = -1, dest_z = 397, dest_heading = 128 WHERE id = 11224; +UPDATE doors SET dest_x = -8, dest_y = -192, dest_z = -628, dest_heading = 403 WHERE id = 11225; +UPDATE doors SET dest_x = -2100, dest_y = 255, dest_z = -928, dest_heading = 384 WHERE id = 11321; +UPDATE doors SET dest_x = -959, dest_y = 1537, dest_z = -348, dest_heading = 999 WHERE id = 11571; +UPDATE doors SET dest_x = -959, dest_y = 1537, dest_z = -348, dest_heading = 999 WHERE id = 11572; +UPDATE doors SET dest_x = -959, dest_y = 1537, dest_z = -348, dest_heading = 999 WHERE id = 11573; +UPDATE doors SET dest_x = 210, dest_y = -158, dest_z = -372, dest_heading = 383 WHERE id = 11746; +UPDATE doors SET dest_x = -1696, dest_y = 1980, dest_z = 109, dest_heading = 128 WHERE id = 11828; +UPDATE doors SET dest_x = -840, dest_y = -2404, dest_z = -306, dest_heading = 128 WHERE id = 11942; +UPDATE doors SET dest_x = -131, dest_y = -5690, dest_z = -306, dest_heading = 166 WHERE id = 11943; +UPDATE doors SET dest_x = -1017, dest_y = 535, dest_z = -13, dest_heading = 47 WHERE id = 11957; +UPDATE doors SET dest_x = -89, dest_y = -385, dest_z = 18, dest_heading = 449 WHERE id = 11958; +UPDATE doors SET dest_x = 128, dest_y = 1567, dest_z = 124, dest_heading = 256 WHERE id = 11999; +UPDATE doors SET dest_x = 1203, dest_y = -747, dest_z = -157, dest_heading = 128 WHERE id = 12119; +UPDATE doors SET dest_x = -2755, dest_y = 0, dest_z = 0, dest_heading = 128 WHERE id = 12290; +UPDATE doors SET dest_x = -50, dest_y = -181, dest_z = -616, dest_heading = 153 WHERE id = 12296; +UPDATE doors SET dest_x = -4, dest_y = -191, dest_z = -628, dest_heading = 149 WHERE id = 12314; +UPDATE doors SET dest_x = -4, dest_y = -191, dest_z = -628, dest_heading = 149 WHERE id = 12315; +UPDATE doors SET dest_x = -1647, dest_y = 686, dest_z = -911, dest_heading = 504 WHERE id = 12519; +UPDATE doors SET dest_x = 184, dest_y = 673, dest_z = -381, dest_heading = 384 WHERE id = 12532; +UPDATE doors SET dest_x = -1295, dest_y = -606, dest_z = -381, dest_heading = 508 WHERE id = 12533; +UPDATE doors SET dest_x = -397, dest_y = 300, dest_z = 2, dest_heading = 379 WHERE id = 12534; +UPDATE doors SET dest_x = 1582, dest_y = 258, dest_z = 577, dest_heading = 112 WHERE id = 12535; +UPDATE doors SET dest_x = -1243, dest_y = 1079, dest_z = -958, dest_heading = 125 WHERE id = 12537; +UPDATE doors SET dest_x = 1104, dest_y = 1440, dest_z = -550, dest_heading = 5 WHERE id = 12538; +UPDATE doors SET dest_x = -1608, dest_y = -2537, dest_z = -1342, dest_heading = 509 WHERE id = 12539; +UPDATE doors SET dest_x = 413, dest_y = 299, dest_z = 2, dest_heading = 126 WHERE id = 12540; +UPDATE doors SET dest_x = 1296, dest_y = -601, dest_z = -381, dest_heading = 507 WHERE id = 12541; +UPDATE doors SET dest_x = -689, dest_y = 788, dest_z = -613, dest_heading = 505 WHERE id = 12567; +UPDATE doors SET dest_x = -617, dest_y = -5, dest_z = 1450, dest_heading = 128 WHERE id = 12568; +UPDATE doors SET dest_x = 1030, dest_y = -1200, dest_z = -778, dest_heading = 439 WHERE id = 12572; +UPDATE doors SET dest_x = -764, dest_y = 333, dest_z = -59, dest_heading = 132 WHERE id = 12573; +UPDATE doors SET dest_x = -764, dest_y = 333, dest_z = -59, dest_heading = 132 WHERE id = 12575; +UPDATE doors SET dest_x = -764, dest_y = 333, dest_z = -59, dest_heading = 132 WHERE id = 12576; +UPDATE doors SET dest_x = 2167, dest_y = -1337, dest_z = -715, dest_heading = 388 WHERE id = 12577; +UPDATE doors SET dest_x = 104, dest_y = 2, dest_z = 4, dest_heading = 384 WHERE id = 12578; +UPDATE doors SET dest_x = 1182, dest_y = 771, dest_z = -156, dest_heading = 128 WHERE id = 12797; +UPDATE doors SET dest_x = 460, dest_y = -13, dest_z = -90, dest_heading = 128 WHERE id = 12798; +UPDATE doors SET dest_x = 474, dest_y = 829, dest_z = -157, dest_heading = 511 WHERE id = 12913; +UPDATE doors SET dest_x = 132, dest_y = -841, dest_z = -157, dest_heading = 257 WHERE id = 15975; +UPDATE doors SET dest_x = 1227, dest_y = 830, dest_z = -157, dest_heading = 511 WHERE id = 15987; +UPDATE doors SET dest_x = -432, dest_y = -65, dest_z = 61, dest_heading = 357 WHERE id = 16233; +UPDATE doors SET dest_x = -11, dest_y = -262, dest_z = -123, dest_heading = 134 WHERE id = 16287; +UPDATE doors SET dest_x = -1067, dest_y = -196, dest_z = -187, dest_heading = 999999 WHERE id = 16852; +UPDATE doors SET dest_x = -771, dest_y = -196, dest_z = -187, dest_heading = 999999 WHERE id = 16853; +UPDATE doors SET dest_x = 2958, dest_y = 1758, dest_z = 428, dest_heading = 999999 WHERE id = 16998; +UPDATE doors SET dest_x = 2958, dest_y = 1758, dest_z = 428, dest_heading = 999999 WHERE id = 16999; +UPDATE doors SET dest_x = -843, dest_y = -814, dest_z = 9, dest_heading = 457 WHERE id = 17151; +UPDATE doors SET dest_x = 0, dest_y = -110, dest_z = 5, dest_heading = 999 WHERE id = 17151; +UPDATE doors SET dest_x = -488, dest_y = 2668, dest_z = -192, dest_heading = 481 WHERE id = 17210; +UPDATE doors SET dest_x = -1002, dest_y = 2291, dest_z = -306, dest_heading = 342 WHERE id = 17211; +UPDATE doors SET dest_x = 403, dest_y = 3190, dest_z = -108, dest_heading = 119 WHERE id = 17212; +UPDATE doors SET dest_x = -138, dest_y = 3268, dest_z = -191, dest_heading = 347 WHERE id = 17213; +UPDATE doors SET dest_x = 36, dest_y = 3775, dest_z = 6, dest_heading = 383 WHERE id = 17214; +UPDATE doors SET dest_x = 572, dest_y = 3715, dest_z = -78, dest_heading = 160 WHERE id = 17215; +UPDATE doors SET dest_x = 771, dest_y = 5423, dest_z = -27, dest_heading = 150 WHERE id = 17216; +UPDATE doors SET dest_x = 193, dest_y = 5114, dest_z = -131, dest_heading = 322 WHERE id = 17217; +UPDATE doors SET dest_x = -69, dest_y = 6198, dest_z = 223, dest_heading = 446 WHERE id = 17218; +UPDATE doors SET dest_x = 419, dest_y = 6149, dest_z = 24, dest_heading = 135 WHERE id = 17219; +UPDATE doors SET dest_x = 1227, dest_y = -840, dest_z = -157, dest_heading = 257 WHERE id = 17328; +UPDATE doors SET dest_x = 36, dest_y = 662, dest_z = -158, dest_heading = 256 WHERE id = 17329; +UPDATE doors SET dest_x = 95, dest_y = -812, dest_z = -157, dest_heading = 384 WHERE id = 17404; +UPDATE doors SET dest_x = 1314, dest_y = 931, dest_z = -69, dest_heading = 384 WHERE id = 17417; +UPDATE doors SET dest_x = 648, dest_y = -1143, dest_z = 6, dest_heading = 501 WHERE id = 17440; +UPDATE doors SET dest_x = 652, dest_y = -1124, dest_z = -104, dest_heading = 510 WHERE id = 17440; +UPDATE doors SET dest_x = 648, dest_y = -1143, dest_z = 6, dest_heading = 501 WHERE id = 17441; +UPDATE doors SET dest_x = 652, dest_y = -1124, dest_z = -104, dest_heading = 510 WHERE id = 17441; +UPDATE doors SET dest_x = 0, dest_y = 19, dest_z = 559, dest_heading = 256 WHERE id = 17444; +UPDATE doors SET dest_x = 65, dest_y = 11, dest_z = 99, dest_heading = 256 WHERE id = 17445; +UPDATE doors SET dest_x = -107, dest_y = 72, dest_z = 12, dest_heading = 384 WHERE id = 17448; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17449; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17450; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17451; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17452; +UPDATE doors SET dest_x = 107, dest_y = 72, dest_z = 12, dest_heading = 128 WHERE id = 17453; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17454; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17455; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17456; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17457; +UPDATE doors SET dest_x = 1314, dest_y = 931, dest_z = -69, dest_heading = 384 WHERE id = 17458; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17461; +UPDATE doors SET dest_x = -2581, dest_y = -4210, dest_z = -500, dest_heading = 48 WHERE id = 17462; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17463; +UPDATE doors SET dest_x = -4563, dest_y = -1890, dest_z = -501, dest_heading = 93 WHERE id = 17464; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17465; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17466; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17467; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17468; +UPDATE doors SET dest_x = -4562, dest_y = 1890, dest_z = -501, dest_heading = 159 WHERE id = 17470; +UPDATE doors SET dest_x = -1890, dest_y = 4563, dest_z = -501, dest_heading = 225 WHERE id = 17471; +UPDATE doors SET dest_x = 1314, dest_y = 931, dest_z = -69, dest_heading = 384 WHERE id = 17472; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17473; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17474; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17475; +UPDATE doors SET dest_x = 4802, dest_y = 1153, dest_z = -501, dest_heading = 363 WHERE id = 17476; +UPDATE doors SET dest_x = 1890, dest_y = 4564, dest_z = -501, dest_heading = 290 WHERE id = 17477; +UPDATE doors SET dest_x = 1314, dest_y = 931, dest_z = -69, dest_heading = 384 WHERE id = 17478; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17479; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17480; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17481; +UPDATE doors SET dest_x = 1890, dest_y = -4562, dest_z = -502, dest_heading = 477 WHERE id = 17482; +UPDATE doors SET dest_x = 4801, dest_y = -1152, dest_z = -501, dest_heading = 402 WHERE id = 17483; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17484; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17485; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17486; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17487; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17490; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17491; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17492; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17493; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17496; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17497; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17498; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17499; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17502; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17503; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17504; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17505; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17508; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17509; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17510; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17511; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17514; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17515; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17516; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17517; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17520; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17521; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17522; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17523; +UPDATE doors SET dest_x = -2429, dest_y = -1095, dest_z = -181, dest_heading = 128 WHERE id = 17526; +UPDATE doors SET dest_x = -1873, dest_y = 2195, dest_z = -313, dest_heading = 202 WHERE id = 17527; +UPDATE doors SET dest_x = 2031, dest_y = 2031, dest_z = -314, dest_heading = 317 WHERE id = 17528; +UPDATE doors SET dest_x = 2023, dest_y = -2053, dest_z = -351, dest_heading = 65 WHERE id = 17529; +UPDATE doors SET dest_x = 3666, dest_y = -400, dest_z = 356, dest_heading = 256 WHERE id = 17532; +UPDATE doors SET dest_x = 3666, dest_y = -400, dest_z = 356, dest_heading = 256 WHERE id = 17532; +UPDATE doors SET dest_x = -76, dest_y = -401, dest_z = -158, dest_heading = 256 WHERE id = 17586; +UPDATE doors SET dest_x = -267, dest_y = 1637, dest_z = -108, dest_heading = 226 WHERE id = 18621; +UPDATE doors SET dest_x = 2557, dest_y = 4172, dest_z = -520, dest_heading = 307 WHERE id = 18623; +UPDATE doors SET dest_x = 150, dest_y = -194, dest_z = -59, dest_heading = 95 WHERE id = 18698; +UPDATE doors SET dest_x = 86, dest_y = 333, dest_z = 41, dest_heading = 292 WHERE id = 18706; +UPDATE doors SET dest_x = 306, dest_y = 83, dest_z = -21, dest_heading = 434 WHERE id = 18737; +UPDATE doors SET dest_x = -85, dest_y = -27, dest_z = 11, dest_heading = 56 WHERE id = 18761; +UPDATE doors SET dest_x = -279, dest_y = 182, dest_z = -6, dest_heading = 130 WHERE id = 18818; +UPDATE doors SET dest_x = 270, dest_y = -148, dest_z = -59, dest_heading = 408 WHERE id = 18879; +UPDATE doors SET dest_x = 140, dest_y = -430, dest_z = -152, dest_heading = 260 WHERE id = 33835; +UPDATE doors SET dest_x = -27, dest_y = -300, dest_z = 25, dest_heading = 131 WHERE id = 33848; +UPDATE doors SET dest_x = -1904, dest_y = 198, dest_z = 126, dest_heading = 379 WHERE id = 33872; +UPDATE doors SET dest_x = -1512, dest_y = 1552, dest_z = -300, dest_heading = 128 WHERE id = 33951; +UPDATE doors SET dest_x = -757, dest_y = 442, dest_z = 730, dest_heading = 999999 WHERE id = 35566; +UPDATE doors SET dest_x = -758, dest_y = 443, dest_z = 803, dest_heading = 999999 WHERE id = 35568; +UPDATE doors SET dest_x = -757, dest_y = 442, dest_z = 672, dest_heading = 999999 WHERE id = 35569; +UPDATE doors SET dest_x = -757, dest_y = 442, dest_z = 851, dest_heading = 999999 WHERE id = 35570; +UPDATE doors SET dest_x = -757, dest_y = 442, dest_z = 730, dest_heading = 999999 WHERE id = 35571; +UPDATE doors SET dest_x = -704, dest_y = 403, dest_z = 908, dest_heading = 999999 WHERE id = 35572; +UPDATE doors SET dest_x = -758, dest_y = 443, dest_z = 803, dest_heading = 999999 WHERE id = 35573; +UPDATE doors SET dest_x = -757, dest_y = 442, dest_z = 851, dest_heading = 999999 WHERE id = 35575; +UPDATE doors SET dest_x = 894, dest_y = -942, dest_z = 315, dest_heading = 5 WHERE id = 35794; +UPDATE doors SET dest_x = -326, dest_y = 425, dest_z = 44, dest_heading = 999 WHERE id = 35795; +UPDATE doors SET dest_x = 660, dest_y = -60, dest_z = 4, dest_heading = 385 WHERE id = 35796; +UPDATE doors SET dest_x = -326, dest_y = 425, dest_z = 44, dest_heading = 999 WHERE id = 35797; +UPDATE doors SET dest_x = -326, dest_y = 425, dest_z = 44, dest_heading = 999 WHERE id = 35798; +UPDATE doors SET dest_x = 1198, dest_y = 1231, dest_z = 4, dest_heading = 999 WHERE id = 35801; +UPDATE doors SET dest_x = 13, dest_y = -41, dest_z = 70, dest_heading = 486 WHERE id = 36348; +UPDATE doors SET dest_x = -213, dest_y = -553, dest_z = -33, dest_heading = 157 WHERE id = 36433; +UPDATE doors SET dest_x = -972, dest_y = -380, dest_z = 3, dest_heading = 160 WHERE id = 36435; +UPDATE doors SET dest_x = -209, dest_y = -324, dest_z = 8, dest_heading = 253 WHERE id = 36669; + +-- bazaar portal discs + +UPDATE doors SET `doorid` = 58, `zone` = 'bazaar', `version` = 0, `name` = 'PORTAL_DISC', `pos_y` = 49.6421, `pos_x` = 302.859, `pos_z` = 29.3518, `heading` = 215, `opentype` = 57, `guild` = 0, `lockpick` = 0, `keyitem` = 0, `nokeyring` = 0, `triggerdoor` = 0, `triggertype` = 0, `disable_timer` = 0, `doorisopen` = 0, `door_param` = 570, `dest_zone` = 'bazaar', `dest_instance` = 0, `dest_x` = 921, `dest_y` = 1213, `dest_z` = 2, `dest_heading` = 128, `invert_state` = 0, `incline` = 0, `size` = 200, `buffer` = 0, `client_version_mask` = 4294967295, `is_ldon_door` = 0, `dz_switch_id` = 0, `min_expansion` = -1, `max_expansion` = -1, `content_flags` = NULL, `content_flags_disabled` = NULL WHERE `id` = 9620; +UPDATE doors SET `doorid` = 59, `zone` = 'bazaar', `version` = 0, `name` = 'PORTAL_DISC', `pos_y` = 303.295, `pos_x` = -52.0403, `pos_z` = 29.2439, `heading` = 230, `opentype` = 57, `guild` = 0, `lockpick` = 0, `keyitem` = 0, `nokeyring` = 0, `triggerdoor` = 0, `triggertype` = 0, `disable_timer` = 0, `doorisopen` = 0, `door_param` = 580, `dest_zone` = 'bazaar', `dest_instance` = 0, `dest_x` = -891, `dest_y` = 1212, `dest_z` = 2, `dest_heading` = 128, `invert_state` = 0, `incline` = 0, `size` = 200, `buffer` = 0, `client_version_mask` = 4294967295, `is_ldon_door` = 0, `dz_switch_id` = 0, `min_expansion` = -1, `max_expansion` = -1, `content_flags` = NULL, `content_flags_disabled` = NULL WHERE `id` = 9621; +UPDATE doors SET `doorid` = 60, `zone` = 'bazaar', `version` = 0, `name` = 'PORTAL_DISC', `pos_y` = 1162.82, `pos_x` = 923.967, `pos_z` = -3.18447, `heading` = 183, `opentype` = 57, `guild` = 0, `lockpick` = 0, `keyitem` = 0, `nokeyring` = 0, `triggerdoor` = 0, `triggertype` = 0, `disable_timer` = 0, `doorisopen` = 0, `door_param` = 590, `dest_zone` = 'bazaar', `dest_instance` = 0, `dest_x` = 327, `dest_y` = 27, `dest_z` = 34, `dest_heading` = 442, `invert_state` = 0, `incline` = 0, `size` = 200, `buffer` = 0, `client_version_mask` = 4294967295, `is_ldon_door` = 0, `dz_switch_id` = 0, `min_expansion` = -1, `max_expansion` = -1, `content_flags` = NULL, `content_flags_disabled` = NULL WHERE `id` = 9622; +UPDATE doors SET `doorid` = 62, `zone` = 'bazaar', `version` = 0, `name` = 'PORTAL_DISC', `pos_y` = 1162.14, `pos_x` = -887.543, `pos_z` = -3.21821, `heading` = 231, `opentype` = 57, `guild` = 0, `lockpick` = 0, `keyitem` = 0, `nokeyring` = 0, `triggerdoor` = 0, `triggertype` = 0, `disable_timer` = 0, `doorisopen` = 0, `door_param` = 610, `dest_zone` = 'bazaar', `dest_instance` = 0, `dest_x` = -89, `dest_y` = 265, `dest_z` = 34, `dest_heading` = 315, `invert_state` = 0, `incline` = 0, `size` = 200, `buffer` = 0, `client_version_mask` = 4294967295, `is_ldon_door` = 0, `dz_switch_id` = 0, `min_expansion` = -1, `max_expansion` = -1, `content_flags` = NULL, `content_flags_disabled` = NULL WHERE `id` = 9624; diff --git a/utils/sql/git/required/2022_09_03_fix_starting_point_heading.sql b/utils/sql/git/required/2022_09_03_fix_starting_point_heading.sql new file mode 100644 index 000000000..a73eae36d --- /dev/null +++ b/utils/sql/git/required/2022_09_03_fix_starting_point_heading.sql @@ -0,0 +1,411 @@ +UPDATE start_zones SET heading = 192 WHERE x = 504 AND y = 1147 AND z = -38.22 AND zone_id = 75 AND player_choice = 0 AND player_class = 2 AND player_deity = 203 AND player_race = 3 AND start_zone = 75; +UPDATE start_zones SET heading = 0 WHERE x = -385 AND y = -1071 AND z = 67.72 AND zone_id = 24 AND player_choice = 0 AND player_class = 2 AND player_deity = 209 AND player_race = 3 AND start_zone = 24; +UPDATE start_zones SET heading = 288 WHERE x = -80 AND y = -639 AND z = 67.72 AND zone_id = 24 AND player_choice = 0 AND player_class = 2 AND player_deity = 210 AND player_race = 3 AND start_zone = 24; +UPDATE start_zones SET heading = 384 WHERE x = -374 AND y = -1040 AND z = 51.72 AND zone_id = 24 AND player_choice = 0 AND player_class = 3 AND player_deity = 209 AND player_race = 3 AND start_zone = 24; +UPDATE start_zones SET heading = 96 WHERE x = -64 AND y = -656 AND z = 67.72 AND zone_id = 24 AND player_choice = 0 AND player_class = 3 AND player_deity = 210 AND player_race = 3 AND start_zone = 24; +UPDATE start_zones SET heading = 256 WHERE x = 456 AND y = 880 AND z = -120.18 AND zone_id = 75 AND player_choice = 0 AND player_class = 5 AND player_deity = 203 AND player_race = 3 AND start_zone = 75; +UPDATE start_zones SET heading = 0 WHERE x = 840 AND y = 781 AND z = -22.25 AND zone_id = 75 AND player_choice = 0 AND player_class = 11 AND player_deity = 203 AND player_race = 3 AND start_zone = 75; +UPDATE start_zones SET heading = 384 WHERE x = 740 AND y = 887 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 12 AND player_deity = 209 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 384 WHERE x = 740 AND y = 887 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 12 AND player_deity = 210 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 384 WHERE x = 740 AND y = 887 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 12 AND player_deity = 213 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 384 WHERE x = 740 AND y = 887 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 12 AND player_deity = 396 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 0 WHERE x = 920 AND y = 716 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 13 AND player_deity = 209 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 0 WHERE x = 920 AND y = 716 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 13 AND player_deity = 210 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 0 WHERE x = 920 AND y = 716 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 13 AND player_deity = 396 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 128 WHERE x = 753 AND y = 536 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 14 AND player_deity = 209 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 128 WHERE x = 753 AND y = 536 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 14 AND player_deity = 210 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 128 WHERE x = 753 AND y = 536 AND z = 83.72 AND zone_id = 23 AND player_choice = 0 AND player_class = 14 AND player_deity = 396 AND player_race = 3 AND start_zone = 23; +UPDATE start_zones SET heading = 340 WHERE x = -371 AND y = 329 AND z = -38.22 AND zone_id = 45 AND player_choice = 1 AND player_class = 1 AND player_deity = 201 AND player_race = 1 AND start_zone = 45; +UPDATE start_zones SET heading = 0 WHERE x = -510 AND y = 57 AND z = 31.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 207 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -510 AND y = 57 AND z = 31.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 211 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -510 AND y = 57 AND z = 31.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 212 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -510 AND y = 57 AND z = 31.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 396 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 128 WHERE x = -625 AND y = 354 AND z = -35.25 AND zone_id = 45 AND player_choice = 1 AND player_class = 2 AND player_deity = 201 AND player_race = 1 AND start_zone = 45; +UPDATE start_zones SET heading = 0 WHERE x = -440 AND y = -173 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 2 AND player_deity = 207 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -677 AND y = -75 AND z = -10.25 AND zone_id = 2 AND player_choice = 1 AND player_class = 2 AND player_deity = 212 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = -509 AND y = -149 AND z = 6.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 3 AND player_deity = 207 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -677 AND y = -187 AND z = -10.25 AND zone_id = 2 AND player_choice = 1 AND player_class = 3 AND player_deity = 212 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 256 WHERE x = 84 AND y = 127 AND z = 2.75 AND zone_id = 3 AND player_choice = 1 AND player_class = 4 AND player_deity = 207 AND player_race = 1 AND start_zone = 3; +UPDATE start_zones SET heading = 256 WHERE x = 84 AND y = 127 AND z = 2.75 AND zone_id = 3 AND player_choice = 1 AND player_class = 4 AND player_deity = 215 AND player_race = 1 AND start_zone = 3; +UPDATE start_zones SET heading = 128 WHERE x = -319 AND y = 416 AND z = -38.22 AND zone_id = 45 AND player_choice = 1 AND player_class = 5 AND player_deity = 201 AND player_race = 1 AND start_zone = 45; +UPDATE start_zones SET heading = 384 WHERE x = -430 AND y = -209 AND z = 6.75 AND zone_id = 3 AND player_choice = 1 AND player_class = 6 AND player_deity = 207 AND player_race = 1 AND start_zone = 3; +UPDATE start_zones SET heading = 384 WHERE x = -430 AND y = -209 AND z = 6.75 AND zone_id = 3 AND player_choice = 1 AND player_class = 6 AND player_deity = 215 AND player_race = 1 AND start_zone = 3; +UPDATE start_zones SET heading = 128 WHERE x = 288 AND y = 344 AND z = 3.75 AND zone_id = 2 AND player_choice = 1 AND player_class = 7 AND player_deity = 396 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 202 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 205 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 207 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 209 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 210 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 211 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 212 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 213 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 214 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 215 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 216 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -141 AND y = 515 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 396 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 384 WHERE x = 167 AND y = 30 AND z = -29.25 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 201 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 167 AND y = 30 AND z = -29.25 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 205 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 167 AND y = 30 AND z = -29.25 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 207 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 167 AND y = 30 AND z = -29.25 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 212 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 167 AND y = 30 AND z = -29.25 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 396 AND player_race = 1 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = -427 AND y = 302 AND z = -38.22 AND zone_id = 45 AND player_choice = 1 AND player_class = 11 AND player_deity = 201 AND player_race = 1 AND start_zone = 45; +UPDATE start_zones SET heading = 0 WHERE x = -353 AND y = 309 AND z = -38.22 AND zone_id = 45 AND player_choice = 1 AND player_class = 12 AND player_deity = 201 AND player_race = 1 AND start_zone = 0; +UPDATE start_zones SET heading = 384 WHERE x = -653 AND y = 314 AND z = -3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 12 AND player_deity = 207 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 384 WHERE x = -653 AND y = 314 AND z = -3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 12 AND player_deity = 212 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 384 WHERE x = -653 AND y = 314 AND z = -3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 12 AND player_deity = 213 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 384 WHERE x = -653 AND y = 314 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 12 AND player_deity = 396 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 64 WHERE x = -363 AND y = 382 AND z = -38.22 AND zone_id = 45 AND player_choice = 1 AND player_class = 13 AND player_deity = 201 AND player_race = 1 AND start_zone = 45; +UPDATE start_zones SET heading = 320 WHERE x = -654 AND y = 319 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 13 AND player_deity = 207 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 320 WHERE x = -654 AND y = 319 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 13 AND player_deity = 212 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 320 WHERE x = -654 AND y = 319 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 13 AND player_deity = 396 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 352 WHERE x = -370 AND y = 397 AND z = -38.22 AND zone_id = 45 AND player_choice = 1 AND player_class = 14 AND player_deity = 201 AND player_race = 1 AND start_zone = 45; +UPDATE start_zones SET heading = 464 WHERE x = -654 AND y = 305 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 14 AND player_deity = 207 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 464 WHERE x = -654 AND y = 305 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 14 AND player_deity = 212 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 464 WHERE x = -654 AND y = 305 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 14 AND player_deity = 396 AND player_race = 1 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -372 AND y = 294 AND z = -38.65 AND zone_id = 45 AND player_choice = 1 AND player_class = 1 AND player_deity = 201 AND player_race = 7 AND start_zone = 45; +UPDATE start_zones SET heading = 0 WHERE x = -513 AND y = 48 AND z = 31.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 207 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -513 AND y = 48 AND z = 31.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 209 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -513 AND y = 48 AND z = 31.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 211 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -513 AND y = 48 AND z = 31.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 212 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -513 AND y = 48 AND z = 31.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 214 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -513 AND y = 48 AND z = 31.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 1 AND player_deity = 396 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -148 AND y = -491 AND z = -3.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 3 AND player_deity = 207 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 0 WHERE x = -148 AND y = -491 AND z = -3.44 AND zone_id = 1 AND player_choice = 1 AND player_class = 3 AND player_deity = 212 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = 84 AND y = 133 AND z = 2.44 AND zone_id = 3 AND player_choice = 1 AND player_class = 4 AND player_deity = 207 AND player_race = 7 AND start_zone = 3; +UPDATE start_zones SET heading = 256 WHERE x = 84 AND y = 133 AND z = 2.44 AND zone_id = 3 AND player_choice = 1 AND player_class = 4 AND player_deity = 215 AND player_race = 7 AND start_zone = 3; +UPDATE start_zones SET heading = 384 WHERE x = -413 AND y = -210 AND z = 5.74 AND zone_id = 3 AND player_choice = 1 AND player_class = 6 AND player_deity = 207 AND player_race = 7 AND start_zone = 3; +UPDATE start_zones SET heading = 384 WHERE x = -413 AND y = -210 AND z = 5.74 AND zone_id = 3 AND player_choice = 1 AND player_class = 6 AND player_deity = 215 AND player_race = 7 AND start_zone = 3; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 202 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 205 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 207 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 209 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 210 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 211 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 212 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 213 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 214 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 215 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 216 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 256 WHERE x = -140 AND y = 528 AND z = 3.75 AND zone_id = 1 AND player_choice = 1 AND player_class = 8 AND player_deity = 396 AND player_race = 7 AND start_zone = 1; +UPDATE start_zones SET heading = 384 WHERE x = 168 AND y = 31 AND z = -29.56 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 201 AND player_race = 7 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 168 AND y = 31 AND z = -29.56 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 205 AND player_race = 7 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 168 AND y = 31 AND z = -29.56 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 207 AND player_race = 7 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 168 AND y = 31 AND z = -29.56 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 212 AND player_race = 7 AND start_zone = 2; +UPDATE start_zones SET heading = 384 WHERE x = 168 AND y = 31 AND z = -29.56 AND zone_id = 2 AND player_choice = 1 AND player_class = 9 AND player_deity = 396 AND player_race = 7 AND start_zone = 2; +UPDATE start_zones SET heading = 336 WHERE x = 300 AND y = -1455 AND z = -48.42 AND zone_id = 382 AND player_choice = 2 AND player_class = 5 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 336 WHERE x = -1539 AND y = -235 AND z = -135.76 AND zone_id = 383 AND player_choice = 2 AND player_class = 7 AND player_deity = 210 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 256 WHERE x = 578 AND y = -1358 AND z = -48.93 AND zone_id = 382 AND player_choice = 2 AND player_class = 11 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 384 WHERE x = -456 AND y = 560 AND z = -26.62 AND zone_id = 29 AND player_choice = 2 AND player_class = 1 AND player_deity = 211 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 384 WHERE x = -456 AND y = 560 AND z = -26.62 AND zone_id = 29 AND player_choice = 2 AND player_class = 1 AND player_deity = 214 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 384 WHERE x = -456 AND y = 560 AND z = -26.62 AND zone_id = 29 AND player_choice = 2 AND player_class = 1 AND player_deity = 396 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 128 WHERE x = 141 AND y = 271 AND z = 9.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 9 AND player_deity = 205 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 128 WHERE x = 141 AND y = 271 AND z = 9.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 9 AND player_deity = 214 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 128 WHERE x = 141 AND y = 271 AND z = 9.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 9 AND player_deity = 396 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 128 WHERE x = 449 AND y = 332 AND z = -19.62 AND zone_id = 29 AND player_choice = 2 AND player_class = 10 AND player_deity = 214 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 384 WHERE x = 210 AND y = 586 AND z = 4.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 15 AND player_deity = 208 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 384 WHERE x = 210 AND y = 586 AND z = 4.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 15 AND player_deity = 214 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 96 WHERE x = 325 AND y = 565 AND z = 4.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 16 AND player_deity = 211 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 96 WHERE x = 325 AND y = 565 AND z = 4.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 16 AND player_deity = 214 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 96 WHERE x = 325 AND y = 565 AND z = 4.38 AND zone_id = 29 AND player_choice = 2 AND player_class = 16 AND player_deity = 396 AND player_race = 2 AND start_zone = 29; +UPDATE start_zones SET heading = 288 WHERE x = -152 AND y = 100 AND z = 46.16 AND zone_id = 19 AND player_choice = 3 AND player_class = 1 AND player_deity = 202 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 288 WHERE x = -152 AND y = 100 AND z = 46.16 AND zone_id = 19 AND player_choice = 3 AND player_class = 1 AND player_deity = 211 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 288 WHERE x = -152 AND y = 100 AND z = 46.16 AND zone_id = 19 AND player_choice = 3 AND player_class = 1 AND player_deity = 396 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 384 WHERE x = -369 AND y = -228 AND z = -17.81 AND zone_id = 19 AND player_choice = 3 AND player_class = 2 AND player_deity = 205 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 256 WHERE x = -312 AND y = -247 AND z = -9.81 AND zone_id = 19 AND player_choice = 3 AND player_class = 3 AND player_deity = 207 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 0 WHERE x = -439 AND y = -47 AND z = -11.81 AND zone_id = 19 AND player_choice = 3 AND player_class = 4 AND player_deity = 207 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 0 WHERE x = -424 AND y = -52 AND z = -11.81 AND zone_id = 19 AND player_choice = 3 AND player_class = 6 AND player_deity = 207 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 448 WHERE x = -181 AND y = -58 AND z = 40.19 AND zone_id = 19 AND player_choice = 3 AND player_class = 9 AND player_deity = 202 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 448 WHERE x = -181 AND y = -58 AND z = 40.19 AND zone_id = 19 AND player_choice = 3 AND player_class = 9 AND player_deity = 205 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 448 WHERE x = -181 AND y = -58 AND z = 40.19 AND zone_id = 19 AND player_choice = 3 AND player_class = 9 AND player_deity = 396 AND player_race = 11 AND start_zone = 19; +UPDATE start_zones SET heading = 0 WHERE x = -42 AND y = -309 AND z = -10.25 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 204 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -42 AND y = -309 AND z = -10.25 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 206 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -42 AND y = -309 AND z = -10.25 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 208 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -42 AND y = -309 AND z = -10.25 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 211 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -42 AND y = -309 AND z = -10.25 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 396 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = 335 AND y = 147 AND z = 73.72 AND zone_id = 8 AND player_choice = 4 AND player_class = 2 AND player_deity = 204 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = -199 AND y = -30 AND z = -94.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 2 AND player_deity = 206 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = 201 AND y = -126 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 2 AND player_deity = 208 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 326 AND y = 129 AND z = -24.25 AND zone_id = 8 AND player_choice = 4 AND player_class = 3 AND player_deity = 204 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = -183 AND y = 241 AND z = 3.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 3 AND player_deity = 208 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = -303 AND y = -220 AND z = -108.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 5 AND player_deity = 206 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -807 AND y = -239 AND z = -10.25 AND zone_id = 9 AND player_choice = 4 AND player_class = 7 AND player_deity = 210 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 202 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 204 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 205 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 208 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 209 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 210 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 211 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 213 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 214 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 215 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 216 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 560 AND y = -145 AND z = 17.75 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 396 AND player_race = 1 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = -864 AND y = -321 AND z = -108.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 9 AND player_deity = 204 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -864 AND y = -321 AND z = -108.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 9 AND player_deity = 205 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -864 AND y = -321 AND z = -108.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 9 AND player_deity = 206 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -864 AND y = -321 AND z = -108.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 9 AND player_deity = 396 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -184 AND y = -68 AND z = -94.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 11 AND player_deity = 206 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -710 AND y = 138 AND z = 17.75 AND zone_id = 9 AND player_choice = 4 AND player_class = 12 AND player_deity = 204 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -250 AND y = -38 AND z = -94.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 12 AND player_deity = 206 AND player_race = 1 AND start_zone = 0; +UPDATE start_zones SET heading = 0 WHERE x = -710 AND y = 138 AND z = 17.75 AND zone_id = 9 AND player_choice = 4 AND player_class = 12 AND player_deity = 208 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -710 AND y = 138 AND z = -17.75 AND zone_id = 9 AND player_choice = 4 AND player_class = 12 AND player_deity = 213 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -710 AND y = 138 AND z = 17.75 AND zone_id = 9 AND player_choice = 4 AND player_class = 12 AND player_deity = 396 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -747 AND y = 146 AND z = 31.75 AND zone_id = 9 AND player_choice = 4 AND player_class = 13 AND player_deity = 204 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -254 AND y = -42 AND z = -94.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 13 AND player_deity = 206 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -747 AND y = 146 AND z = 31.75 AND zone_id = 9 AND player_choice = 4 AND player_class = 13 AND player_deity = 208 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -747 AND y = 146 AND z = 31.75 AND zone_id = 9 AND player_choice = 4 AND player_class = 13 AND player_deity = 396 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = 72 AND y = -812 AND z = -52.22 AND zone_id = 9 AND player_choice = 4 AND player_class = 14 AND player_deity = 204 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -252 AND y = -37 AND z = -94.22 AND zone_id = 10 AND player_choice = 4 AND player_class = 14 AND player_deity = 206 AND player_race = 1 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = 72 AND y = -812 AND z = -52.22 AND zone_id = 9 AND player_choice = 4 AND player_class = 14 AND player_deity = 208 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = 72 AND y = -812 AND z = -52.22 AND zone_id = 9 AND player_choice = 4 AND player_class = 14 AND player_deity = 396 AND player_race = 1 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -291 AND y = -44 AND z = -10.56 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 204 AND player_race = 7 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -291 AND y = -44 AND z = -10.56 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 206 AND player_race = 7 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -291 AND y = -44 AND z = -10.56 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 208 AND player_race = 7 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -291 AND y = -44 AND z = -10.56 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 209 AND player_race = 7 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -291 AND y = -44 AND z = -10.56 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 211 AND player_race = 7 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -291 AND y = -44 AND z = -10.56 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 214 AND player_race = 7 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = -291 AND y = -44 AND z = -10.56 AND zone_id = 9 AND player_choice = 4 AND player_class = 1 AND player_deity = 396 AND player_race = 7 AND start_zone = 9; +UPDATE start_zones SET heading = 0 WHERE x = 328 AND y = 118 AND z = -24.56 AND zone_id = 8 AND player_choice = 4 AND player_class = 3 AND player_deity = 204 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 328 AND y = 118 AND z = -24.56 AND zone_id = 8 AND player_choice = 4 AND player_class = 3 AND player_deity = 208 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 202 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 204 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 205 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 208 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 209 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 210 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 211 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 213 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 214 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 215 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 216 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = 561 AND y = -126 AND z = 17.31 AND zone_id = 8 AND player_choice = 4 AND player_class = 8 AND player_deity = 396 AND player_race = 7 AND start_zone = 8; +UPDATE start_zones SET heading = 0 WHERE x = -864 AND y = -309 AND z = -108.53 AND zone_id = 10 AND player_choice = 4 AND player_class = 9 AND player_deity = 204 AND player_race = 7 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -864 AND y = -309 AND z = -108.53 AND zone_id = 10 AND player_choice = 4 AND player_class = 9 AND player_deity = 205 AND player_race = 7 AND start_zone = 10; +UPDATE start_zones SET heading = 0 WHERE x = -864 AND y = -309 AND z = -108.53 AND zone_id = 10 AND player_choice = 4 AND player_class = 9 AND player_deity = 396 AND player_race = 7 AND start_zone = 10; +UPDATE start_zones SET heading = 160 WHERE x = -1633 AND y = 1393 AND z = -195.23 AND zone_id = 383 AND player_choice = 5 AND player_class = 3 AND player_deity = 204 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 0 WHERE x = -500 AND y = 1123 AND z = -126.73 AND zone_id = 383 AND player_choice = 5 AND player_class = 3 AND player_deity = 208 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 96 WHERE x = -896 AND y = -511 AND z = -187.26 AND zone_id = 383 AND player_choice = 5 AND player_class = 12 AND player_deity = 204 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 192 WHERE x = 600 AND y = -1566 AND z = -49.22 AND zone_id = 382 AND player_choice = 5 AND player_class = 12 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 96 WHERE x = -896 AND y = -511 AND z = -187.26 AND zone_id = 383 AND player_choice = 5 AND player_class = 12 AND player_deity = 208 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 96 WHERE x = -896 AND y = -511 AND z = -187.26 AND zone_id = 383 AND player_choice = 5 AND player_class = 12 AND player_deity = 213 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 96 WHERE x = -896 AND y = -511 AND z = -187.26 AND zone_id = 383 AND player_choice = 5 AND player_class = 12 AND player_deity = 396 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 0 WHERE x = -1133 AND y = -76 AND z = -52.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 1 AND player_deity = 206 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 0 WHERE x = -1133 AND y = -76 AND z = -52.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 1 AND player_deity = 211 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 0 WHERE x = -1133 AND y = -76 AND z = -52.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 1 AND player_deity = 396 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 400 WHERE x = -774 AND y = 405 AND z = -52.84 AND zone_id = 42 AND player_choice = 5 AND player_class = 2 AND player_deity = 206 AND player_race = 6 AND start_zone = 42; +UPDATE start_zones SET heading = 0 WHERE x = -1238 AND y = 1255 AND z = -80.84 AND zone_id = 42 AND player_choice = 5 AND player_class = 5 AND player_deity = 206 AND player_race = 6 AND start_zone = 42; +UPDATE start_zones SET heading = 370 WHERE x = -1305 AND y = 634 AND z = -80.84 AND zone_id = 42 AND player_choice = 5 AND player_class = 9 AND player_deity = 205 AND player_race = 6 AND start_zone = 42; +UPDATE start_zones SET heading = 370 WHERE x = -1305 AND y = 634 AND z = -80.84 AND zone_id = 42 AND player_choice = 5 AND player_class = 9 AND player_deity = 206 AND player_race = 6 AND start_zone = 42; +UPDATE start_zones SET heading = 370 WHERE x = -1305 AND y = 634 AND z = -80.84 AND zone_id = 42 AND player_choice = 5 AND player_class = 9 AND player_deity = 396 AND player_race = 6 AND start_zone = 42; +UPDATE start_zones SET heading = 0 WHERE x = -1253 AND y = 1255 AND z = -80.84 AND zone_id = 42 AND player_choice = 5 AND player_class = 11 AND player_deity = 206 AND player_race = 6 AND start_zone = 42; +UPDATE start_zones SET heading = 384 WHERE x = -947 AND y = 141 AND z = -38.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 12 AND player_deity = 206 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 384 WHERE x = -947 AND y = 141 AND z = -38.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 12 AND player_deity = 213 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 384 WHERE x = -947 AND y = 141 AND z = -38.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 12 AND player_deity = 396 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 128 WHERE x = -980 AND y = 148 AND z = -38.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 13 AND player_deity = 206 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 128 WHERE x = -980 AND y = 148 AND z = -38.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 13 AND player_deity = 396 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 448 WHERE x = -951 AND y = 144 AND z = -38.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 14 AND player_deity = 206 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 448 WHERE x = -951 AND y = 144 AND z = -38.84 AND zone_id = 41 AND player_choice = 5 AND player_class = 14 AND player_deity = 396 AND player_race = 6 AND start_zone = 41; +UPDATE start_zones SET heading = 160 WHERE x = -1633 AND y = 1393 AND z = -195.23 AND zone_id = 383 AND player_choice = 5 AND player_class = 3 AND player_deity = 204 AND player_race = 7 AND start_zone = 383; +UPDATE start_zones SET heading = 0 WHERE x = -500 AND y = 1123 AND z = -126.73 AND zone_id = 383 AND player_choice = 5 AND player_class = 3 AND player_deity = 208 AND player_race = 7 AND start_zone = 383; +UPDATE start_zones SET heading = 364 WHERE x = -150 AND y = 310 AND z = 25 AND zone_id = 52 AND player_choice = 5 AND player_class = 1 AND player_deity = 203 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 364 WHERE x = -150 AND y = 310 AND z = 25 AND zone_id = 52 AND player_choice = 5 AND player_class = 1 AND player_deity = 206 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 364 WHERE x = -150 AND y = 310 AND z = 25 AND zone_id = 52 AND player_choice = 5 AND player_class = 1 AND player_deity = 211 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 364 WHERE x = -150 AND y = 310 AND z = 25 AND zone_id = 52 AND player_choice = 5 AND player_class = 1 AND player_deity = 396 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 372 WHERE x = -935 AND y = 515 AND z = 15 AND zone_id = 52 AND player_choice = 5 AND player_class = 5 AND player_deity = 203 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 372 WHERE x = -935 AND y = 515 AND z = 15 AND zone_id = 52 AND player_choice = 5 AND player_class = 5 AND player_deity = 206 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 256 WHERE x = -487 AND y = 39 AND z = 55 AND zone_id = 52 AND player_choice = 5 AND player_class = 10 AND player_deity = 203 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 256 WHERE x = -487 AND y = 39 AND z = 55 AND zone_id = 52 AND player_choice = 5 AND player_class = 10 AND player_deity = 206 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 294 WHERE x = -407 AND y = 12 AND z = 75 AND zone_id = 52 AND player_choice = 5 AND player_class = 15 AND player_deity = 203 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 294 WHERE x = -407 AND y = 12 AND z = 75 AND zone_id = 52 AND player_choice = 5 AND player_class = 15 AND player_deity = 206 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 480 WHERE x = -1704 AND y = 1493 AND z = 16.77 AND zone_id = 383 AND player_choice = 6 AND player_class = 2 AND player_deity = 204 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 288 WHERE x = 574 AND y = -1520 AND z = -49.5 AND zone_id = 382 AND player_choice = 6 AND player_class = 2 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 384 WHERE x = -796 AND y = 806 AND z = -166.73 AND zone_id = 383 AND player_choice = 6 AND player_class = 2 AND player_deity = 208 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 0 WHERE x = 319 AND y = -433 AND z = 3.13 AND zone_id = 52 AND player_choice = 6 AND player_class = 1 AND player_deity = 208 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 0 WHERE x = 340 AND y = -472 AND z = 3.13 AND zone_id = 52 AND player_choice = 6 AND player_class = 2 AND player_deity = 208 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 0 WHERE x = 391 AND y = -444 AND z = 3.13 AND zone_id = 52 AND player_choice = 6 AND player_class = 3 AND player_deity = 208 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 0 WHERE x = 383 AND y = -424 AND z = 3.13 AND zone_id = 52 AND player_choice = 6 AND player_class = 10 AND player_deity = 208 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 0 WHERE x = 385 AND y = -483 AND z = 3.13 AND zone_id = 52 AND player_choice = 6 AND player_class = 12 AND player_deity = 208 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 140 WHERE x = 117 AND y = 244 AND z = -5.3 AND zone_id = 52 AND player_choice = 6 AND player_class = 16 AND player_deity = 203 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 140 WHERE x = 117 AND y = 244 AND z = -5.3 AND zone_id = 52 AND player_choice = 6 AND player_class = 16 AND player_deity = 206 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 140 WHERE x = 117 AND y = 244 AND z = -5.3 AND zone_id = 52 AND player_choice = 6 AND player_class = 16 AND player_deity = 211 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 140 WHERE x = 117 AND y = 244 AND z = -5.3 AND zone_id = 52 AND player_choice = 6 AND player_class = 16 AND player_deity = 396 AND player_race = 9 AND start_zone = 52; +UPDATE start_zones SET heading = 64 WHERE x = 612 AND y = -1297 AND z = -49.22 AND zone_id = 382 AND player_choice = 7 AND player_class = 9 AND player_deity = 204 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 64 WHERE x = 612 AND y = -1297 AND z = -49.22 AND zone_id = 382 AND player_choice = 7 AND player_class = 9 AND player_deity = 205 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 64 WHERE x = 612 AND y = -1297 AND z = -49.22 AND zone_id = 382 AND player_choice = 7 AND player_class = 9 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 64 WHERE x = 612 AND y = -1297 AND z = -49.22 AND zone_id = 382 AND player_choice = 7 AND player_class = 9 AND player_deity = 396 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 256 WHERE x = -924 AND y = -550 AND z = -187.26 AND zone_id = 383 AND player_choice = 7 AND player_class = 13 AND player_deity = 204 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 288 WHERE x = 561 AND y = -1562 AND z = -49.74 AND zone_id = 382 AND player_choice = 7 AND player_class = 13 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 256 WHERE x = -924 AND y = -550 AND z = -187.26 AND zone_id = 383 AND player_choice = 7 AND player_class = 13 AND player_deity = 208 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 256 WHERE x = -924 AND y = -550 AND z = -187.26 AND zone_id = 383 AND player_choice = 7 AND player_class = 13 AND player_deity = 396 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 224 WHERE x = -880 AND y = -248 AND z = -77.26 AND zone_id = 383 AND player_choice = 7 AND player_class = 14 AND player_deity = 204 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 112 WHERE x = 586 AND y = -1507 AND z = -49.74 AND zone_id = 382 AND player_choice = 7 AND player_class = 14 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 224 WHERE x = -880 AND y = -248 AND z = -77.26 AND zone_id = 383 AND player_choice = 7 AND player_class = 14 AND player_deity = 208 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 224 WHERE x = -880 AND y = -248 AND z = -77.26 AND zone_id = 383 AND player_choice = 7 AND player_class = 14 AND player_deity = 396 AND player_race = 1 AND start_zone = 383; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 7 AND player_class = 1 AND player_deity = 204 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 320 WHERE x = 591 AND y = -1447 AND z = -49.21 AND zone_id = 382 AND player_choice = 7 AND player_class = 1 AND player_deity = 206 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 7 AND player_class = 1 AND player_deity = 208 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 7 AND player_class = 1 AND player_deity = 209 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 7 AND player_class = 1 AND player_deity = 211 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 7 AND player_class = 1 AND player_deity = 214 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 7 AND player_class = 1 AND player_deity = 396 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 64 WHERE x = 612 AND y = -1297 AND z = -49.22 AND zone_id = 382 AND player_choice = 7 AND player_class = 9 AND player_deity = 204 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 64 WHERE x = 612 AND y = -1297 AND z = -49.22 AND zone_id = 382 AND player_choice = 7 AND player_class = 9 AND player_deity = 205 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 64 WHERE x = 612 AND y = -1297 AND z = -49.22 AND zone_id = 382 AND player_choice = 7 AND player_class = 9 AND player_deity = 396 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 0 WHERE x = 71 AND y = -2 AND z = -25 AND zone_id = 49 AND player_choice = 7 AND player_class = 1 AND player_deity = 203 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 0 WHERE x = 71 AND y = -2 AND z = -25 AND zone_id = 49 AND player_choice = 7 AND player_class = 1 AND player_deity = 211 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 0 WHERE x = 71 AND y = -2 AND z = -25 AND zone_id = 49 AND player_choice = 7 AND player_class = 1 AND player_deity = 396 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 384 WHERE x = -7 AND y = 334 AND z = 6.5 AND zone_id = 49 AND player_choice = 7 AND player_class = 5 AND player_deity = 203 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 384 WHERE x = -7 AND y = 334 AND z = 6.5 AND zone_id = 49 AND player_choice = 7 AND player_class = 5 AND player_deity = 211 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 286 WHERE x = 991 AND y = 648 AND z = 81.7 AND zone_id = 49 AND player_choice = 7 AND player_class = 10 AND player_deity = 211 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 154 WHERE x = 1074 AND y = 289 AND z = 81.7 AND zone_id = 49 AND player_choice = 7 AND player_class = 15 AND player_deity = 211 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 248 WHERE x = -255 AND y = 303 AND z = 5.5 AND zone_id = 49 AND player_choice = 7 AND player_class = 16 AND player_deity = 203 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 248 WHERE x = -255 AND y = 303 AND z = 5.5 AND zone_id = 49 AND player_choice = 7 AND player_class = 16 AND player_deity = 211 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 248 WHERE x = -255 AND y = 303 AND z = 5.5 AND zone_id = 49 AND player_choice = 7 AND player_class = 16 AND player_deity = 396 AND player_race = 10 AND start_zone = 49; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 8 AND player_class = 1 AND player_deity = 204 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 320 WHERE x = 591 AND y = -1447 AND z = -49.21 AND zone_id = 382 AND player_choice = 8 AND player_class = 1 AND player_deity = 206 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 8 AND player_class = 1 AND player_deity = 208 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 8 AND player_class = 1 AND player_deity = 211 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -681 AND y = 663 AND z = -21.52 AND zone_id = 382 AND player_choice = 8 AND player_class = 1 AND player_deity = 396 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 0 WHERE x = 304 AND y = 41 AND z = 14.5 AND zone_id = 60 AND player_choice = 8 AND player_class = 1 AND player_deity = 202 AND player_race = 8 AND start_zone = 60; +UPDATE start_zones SET heading = 0 WHERE x = 304 AND y = 41 AND z = 14.5 AND zone_id = 60 AND player_choice = 8 AND player_class = 1 AND player_deity = 396 AND player_race = 8 AND start_zone = 60; +UPDATE start_zones SET heading = 0 WHERE x = 132 AND y = 771 AND z = 2.5 AND zone_id = 67 AND player_choice = 8 AND player_class = 2 AND player_deity = 202 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 256 WHERE x = 132 AND y = 1351 AND z = 46.47 AND zone_id = 67 AND player_choice = 8 AND player_class = 3 AND player_deity = 202 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 480 WHERE x = 218 AND y = 546 AND z = -33.5 AND zone_id = 67 AND player_choice = 8 AND player_class = 9 AND player_deity = 202 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 480 WHERE x = 218 AND y = 546 AND z = -33.5 AND zone_id = 67 AND player_choice = 8 AND player_class = 9 AND player_deity = 205 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 480 WHERE x = 218 AND y = 546 AND z = -33.5 AND zone_id = 67 AND player_choice = 8 AND player_class = 9 AND player_deity = 396 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 184 WHERE x = 298 AND y = 494 AND z = -33.5 AND zone_id = 67 AND player_choice = 8 AND player_class = 16 AND player_deity = 202 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 184 WHERE x = 298 AND y = 494 AND z = -33.5 AND zone_id = 67 AND player_choice = 8 AND player_class = 16 AND player_deity = 205 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 184 WHERE x = 298 AND y = 494 AND z = -33.5 AND zone_id = 67 AND player_choice = 8 AND player_class = 16 AND player_deity = 396 AND player_race = 8 AND start_zone = 67; +UPDATE start_zones SET heading = 410 WHERE x = 283 AND y = 340 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 207 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 410 WHERE x = 283 AND y = 340 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 211 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 410 WHERE x = 283 AND y = 340 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 215 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 410 WHERE x = 283 AND y = 340 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 396 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 523 AND y = -447 AND z = 117.53 AND zone_id = 54 AND player_choice = 9 AND player_class = 4 AND player_deity = 215 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = 226 AND y = -629 AND z = 77.06 AND zone_id = 54 AND player_choice = 9 AND player_class = 6 AND player_deity = 215 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 202 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 204 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 205 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 207 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 208 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 209 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 210 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 211 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 212 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 213 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 214 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 215 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 216 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 270 WHERE x = 252 AND y = -234 AND z = 77.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 396 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = -216 AND y = -504 AND z = 161.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 9 AND player_deity = 205 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = -216 AND y = -504 AND z = 161.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 9 AND player_deity = 207 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = -216 AND y = -504 AND z = 161.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 9 AND player_deity = 215 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = -216 AND y = -504 AND z = 161.09 AND zone_id = 54 AND player_choice = 9 AND player_class = 9 AND player_deity = 396 AND player_race = 4 AND start_zone = 54; +UPDATE start_zones SET heading = 250 WHERE x = 282 AND y = 340 AND z = 77.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 209 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 250 WHERE x = 282 AND y = 340 AND z = 77.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 211 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 250 WHERE x = 282 AND y = 340 AND z = 77.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 214 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 250 WHERE x = 282 AND y = 340 AND z = 77.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 215 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 250 WHERE x = 282 AND y = 340 AND z = 77.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 1 AND player_deity = 396 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 184 WHERE x = 493 AND y = -431 AND z = 117.5 AND zone_id = 54 AND player_choice = 9 AND player_class = 4 AND player_deity = 215 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = 226 AND y = -629 AND z = 77.06 AND zone_id = 54 AND player_choice = 9 AND player_class = 6 AND player_deity = 215 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 202 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 205 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 209 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 210 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 211 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 213 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 214 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 215 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 216 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 256 WHERE x = 243 AND y = -238 AND z = 77.28 AND zone_id = 54 AND player_choice = 9 AND player_class = 8 AND player_deity = 396 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = -210 AND y = -501 AND z = 161.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 9 AND player_deity = 205 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = -210 AND y = -501 AND z = 161.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 9 AND player_deity = 215 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 320 WHERE x = -210 AND y = -501 AND z = 161.41 AND zone_id = 54 AND player_choice = 9 AND player_class = 9 AND player_deity = 396 AND player_race = 7 AND start_zone = 54; +UPDATE start_zones SET heading = 128 WHERE x = -445 AND y = 11 AND z = 0 AND zone_id = 61 AND player_choice = 10 AND player_class = 2 AND player_deity = 215 AND player_race = 5 AND start_zone = 61; +UPDATE start_zones SET heading = 416 WHERE x = -317 AND y = 8 AND z = 8.75 AND zone_id = 61 AND player_choice = 10 AND player_class = 3 AND player_deity = 215 AND player_race = 5 AND start_zone = 61; +UPDATE start_zones SET heading = 128 WHERE x = -422 AND y = 506 AND z = 0 AND zone_id = 62 AND player_choice = 10 AND player_class = 12 AND player_deity = 204 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 128 WHERE x = -422 AND y = 506 AND z = 0 AND zone_id = 62 AND player_choice = 10 AND player_class = 12 AND player_deity = 207 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 128 WHERE x = -422 AND y = 506 AND z = 0 AND zone_id = 62 AND player_choice = 10 AND player_class = 12 AND player_deity = 208 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 128 WHERE x = -422 AND y = 506 AND z = 0 AND zone_id = 62 AND player_choice = 10 AND player_class = 12 AND player_deity = 213 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 128 WHERE x = -422 AND y = 506 AND z = 0 AND zone_id = 62 AND player_choice = 10 AND player_class = 12 AND player_deity = 215 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 128 WHERE x = -422 AND y = 506 AND z = 0 AND zone_id = 62 AND player_choice = 10 AND player_class = 12 AND player_deity = 396 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 32 WHERE x = -603 AND y = 784 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 13 AND player_deity = 204 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 32 WHERE x = -603 AND y = 784 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 13 AND player_deity = 207 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 32 WHERE x = -603 AND y = 784 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 13 AND player_deity = 208 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 32 WHERE x = -603 AND y = 784 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 13 AND player_deity = 215 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 32 WHERE x = -603 AND y = 784 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 13 AND player_deity = 396 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 352 WHERE x = -830 AND y = 559 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 14 AND player_deity = 204 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 352 WHERE x = -830 AND y = 559 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 14 AND player_deity = 207 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 352 WHERE x = -830 AND y = 559 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 14 AND player_deity = 208 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 352 WHERE x = -830 AND y = 559 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 14 AND player_deity = 215 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 352 WHERE x = -830 AND y = 559 AND z = 4 AND zone_id = 62 AND player_choice = 10 AND player_class = 14 AND player_deity = 396 AND player_race = 5 AND start_zone = 62; +UPDATE start_zones SET heading = 384 WHERE x = -295 AND y = 3 AND z = 3.31 AND zone_id = 61 AND player_choice = 10 AND player_class = 3 AND player_deity = 215 AND player_race = 7 AND start_zone = 61; +UPDATE start_zones SET heading = 160 WHERE x = -511 AND y = 2113 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 1 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 192 WHERE x = -442 AND y = 854 AND z = -30.12 AND zone_id = 55 AND player_choice = 11 AND player_class = 1 AND player_deity = 202 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 192 WHERE x = -442 AND y = 854 AND z = -30.12 AND zone_id = 55 AND player_choice = 11 AND player_class = 1 AND player_deity = 211 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 192 WHERE x = -442 AND y = 854 AND z = -30.12 AND zone_id = 55 AND player_choice = 11 AND player_class = 1 AND player_deity = 396 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 90 WHERE x = -401 AND y = 2091 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 2 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 384 WHERE x = -549 AND y = 1191 AND z = -40.09 AND zone_id = 55 AND player_choice = 11 AND player_class = 2 AND player_deity = 202 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 384 WHERE x = -549 AND y = 1191 AND z = -40.09 AND zone_id = 55 AND player_choice = 11 AND player_class = 2 AND player_deity = 205 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 128 WHERE x = -553 AND y = 1231 AND z = -40.09 AND zone_id = 55 AND player_choice = 11 AND player_class = 3 AND player_deity = 202 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 64 WHERE x = -443 AND y = 2132 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 5 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 352 WHERE x = -497 AND y = 2073 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 9 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 480 WHERE x = -596 AND y = 1231 AND z = -54.09 AND zone_id = 55 AND player_choice = 11 AND player_class = 9 AND player_deity = 202 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 480 WHERE x = -596 AND y = 1231 AND z = -54.09 AND zone_id = 55 AND player_choice = 11 AND player_class = 9 AND player_deity = 205 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 480 WHERE x = -596 AND y = 1231 AND z = -54.09 AND zone_id = 55 AND player_choice = 11 AND player_class = 9 AND player_deity = 396 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 0 WHERE x = -406 AND y = 2086 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 11 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 320 WHERE x = -585 AND y = 2040 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 12 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 256 WHERE x = -992 AND y = 1065 AND z = 29.88 AND zone_id = 55 AND player_choice = 11 AND player_class = 12 AND player_deity = 202 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 256 WHERE x = -992 AND y = 1065 AND z = 29.88 AND zone_id = 55 AND player_choice = 11 AND player_class = 12 AND player_deity = 213 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 256 WHERE x = -992 AND y = 1065 AND z = 29.88 AND zone_id = 55 AND player_choice = 11 AND player_class = 12 AND player_deity = 396 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 256 WHERE x = -588 AND y = 2037 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 13 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 480 WHERE x = -1023 AND y = 1093 AND z = 29.88 AND zone_id = 55 AND player_choice = 11 AND player_class = 13 AND player_deity = 202 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 480 WHERE x = -1023 AND y = 1093 AND z = 29.88 AND zone_id = 55 AND player_choice = 11 AND player_class = 13 AND player_deity = 396 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 192 WHERE x = -588 AND y = 2036 AND z = -182.06 AND zone_id = 55 AND player_choice = 11 AND player_class = 14 AND player_deity = 201 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 96 WHERE x = -993 AND y = 1092 AND z = 29.88 AND zone_id = 55 AND player_choice = 11 AND player_class = 14 AND player_deity = 202 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 96 WHERE x = -993 AND y = 1092 AND z = 29.88 AND zone_id = 55 AND player_choice = 11 AND player_class = 14 AND player_deity = 396 AND player_race = 12 AND start_zone = 55; +UPDATE start_zones SET heading = 64 WHERE x = 16 AND y = -477 AND z = 59.72 AND zone_id = 106 AND player_choice = 12 AND player_class = 1 AND player_deity = 203 AND player_race = 128 AND start_zone = 106; +UPDATE start_zones SET heading = 256 WHERE x = -189 AND y = 1027 AND z = 73.72 AND zone_id = 106 AND player_choice = 12 AND player_class = 5 AND player_deity = 203 AND player_race = 128 AND start_zone = 106; +UPDATE start_zones SET heading = 128 WHERE x = -50 AND y = 421 AND z = 6.75 AND zone_id = 106 AND player_choice = 12 AND player_class = 7 AND player_deity = 203 AND player_race = 128 AND start_zone = 106; +UPDATE start_zones SET heading = 0 WHERE x = -189 AND y = 1017 AND z = 18.75 AND zone_id = 106 AND player_choice = 12 AND player_class = 10 AND player_deity = 203 AND player_race = 128 AND start_zone = 106; +UPDATE start_zones SET heading = 128 WHERE x = 761 AND y = 316 AND z = 76.72 AND zone_id = 82 AND player_choice = 12 AND player_class = 11 AND player_deity = 203 AND player_race = 128 AND start_zone = 82; +UPDATE start_zones SET heading = 0 WHERE x = -204 AND y = 1040 AND z = 45.72 AND zone_id = 106 AND player_choice = 12 AND player_class = 15 AND player_deity = 203 AND player_race = 128 AND start_zone = 106; +UPDATE start_zones SET heading = 128 WHERE x = -535 AND y = -143 AND z = -259 AND zone_id = 155 AND player_choice = 13 AND player_class = 1 AND player_deity = 396 AND player_race = 130 AND start_zone = 155; +UPDATE start_zones SET heading = 0 WHERE x = 529 AND y = -3 AND z = -103.6 AND zone_id = 155 AND player_choice = 13 AND player_class = 8 AND player_deity = 396 AND player_race = 130 AND start_zone = 155; +UPDATE start_zones SET heading = 128 WHERE x = -300 AND y = 190 AND z = -247.5 AND zone_id = 155 AND player_choice = 13 AND player_class = 9 AND player_deity = 396 AND player_race = 130 AND start_zone = 155; +UPDATE start_zones SET heading = 256 WHERE x = 100 AND y = 55 AND z = -259.5 AND zone_id = 155 AND player_choice = 13 AND player_class = 10 AND player_deity = 396 AND player_race = 130 AND start_zone = 155; +UPDATE start_zones SET heading = 160 WHERE x = 76 AND y = 318 AND z = -259.6 AND zone_id = 155 AND player_choice = 13 AND player_class = 15 AND player_deity = 396 AND player_race = 130 AND start_zone = 155; +UPDATE start_zones SET heading = 256 WHERE x = 50 AND y = 70 AND z = -258.1 AND zone_id = 155 AND player_choice = 13 AND player_class = 16 AND player_deity = 396 AND player_race = 130 AND start_zone = 155; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 202 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 204 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 205 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 208 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 209 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 210 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 211 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 213 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 214 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 215 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 216 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 396 AND player_race = 1 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 202 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 204 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 205 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 208 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 209 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 210 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 211 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 213 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 214 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 215 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 216 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 192 WHERE x = -920 AND y = -1080 AND z = 12.43 AND zone_id = 382 AND player_choice = 14 AND player_class = 8 AND player_deity = 396 AND player_race = 7 AND start_zone = 382; +UPDATE start_zones SET heading = 288 WHERE x = 368 AND y = -1622 AND z = 0.41 AND zone_id = 50 AND player_choice = 14 AND player_class = 1 AND player_deity = 208 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 128 WHERE x = 2037 AND y = -1889 AND z = 1.4 AND zone_id = 50 AND player_choice = 14 AND player_class = 2 AND player_deity = 206 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 300 WHERE x = 346 AND y = -1697 AND z = 0.81 AND zone_id = 50 AND player_choice = 14 AND player_class = 2 AND player_deity = 208 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 64 WHERE x = 340 AND y = -1690 AND z = 0.69 AND zone_id = 50 AND player_choice = 14 AND player_class = 3 AND player_deity = 208 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 64 WHERE x = 2132 AND y = -1764 AND z = 1.52 AND zone_id = 50 AND player_choice = 14 AND player_class = 5 AND player_deity = 206 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 448 WHERE x = 2114 AND y = -1764 AND z = 1.16 AND zone_id = 50 AND player_choice = 14 AND player_class = 9 AND player_deity = 206 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 160 WHERE x = 420 AND y = -1679 AND z = 1.76 AND zone_id = 50 AND player_choice = 14 AND player_class = 10 AND player_deity = 208 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 256 WHERE x = 1959 AND y = -2035 AND z = 0.54 AND zone_id = 50 AND player_choice = 14 AND player_class = 11 AND player_deity = 206 AND player_race = 330 AND start_zone = 50; +UPDATE start_zones SET heading = 416 WHERE x = 298 AND y = -1634 AND z = 0.41 AND zone_id = 50 AND player_choice = 14 AND player_class = 12 AND player_deity = 208 AND player_race = 330 AND start_zone = 50; diff --git a/utils/sql/git/required/2022_09_03_fix_zone_point_heading_data.sql b/utils/sql/git/required/2022_09_03_fix_zone_point_heading_data.sql new file mode 100644 index 000000000..205a93a20 --- /dev/null +++ b/utils/sql/git/required/2022_09_03_fix_zone_point_heading_data.sql @@ -0,0 +1,3056 @@ +UPDATE zone_points SET target_heading = 0 WHERE zone = 'qeynos' AND version = 0 AND number = 1 AND id = 1 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'qeynos' AND version = 0 AND number = 2 AND id = 3 AND target_heading = 0; +UPDATE zone_points SET target_heading = 5.2 WHERE zone = 'qeynos2' AND version = 0 AND number = 9 AND id = 7 AND target_heading = 2.6; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'feerrott' AND version = 0 AND number = 5 AND id = 10 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'feerrott' AND version = 0 AND number = 77 AND id = 11 AND target_heading = 231; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'acrylia' AND version = 0 AND number = 1 AND id = 13 AND target_heading = 195; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'commons' AND version = 0 AND number = 0 AND id = 14 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qey2hh1' AND version = 0 AND number = 2 AND id = 17 AND target_heading = 231; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'northkarana' AND version = 0 AND number = 1 AND id = 18 AND target_heading = 64; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'northkarana' AND version = 0 AND number = 2 AND id = 19 AND target_heading = 192; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'eastkarana' AND version = 0 AND number = 1 AND id = 20 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'northkarana' AND version = 0 AND number = 3 AND id = 21 AND target_heading = 128; +UPDATE zone_points SET target_heading = 64 WHERE zone = 'eastkarana' AND version = 0 AND number = 2 AND id = 23 AND target_heading = 32; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'beholder' AND version = 0 AND number = 1 AND id = 24 AND target_heading = 130; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'eastkarana' AND version = 0 AND number = 3 AND id = 25 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'southkarana' AND version = 0 AND number = 2 AND id = 27 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'beholder' AND version = 0 AND number = 2 AND id = 31 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'highkeep' AND version = 0 AND number = 1 AND id = 38 AND target_heading = 128; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'commons' AND version = 0 AND number = 1 AND id = 40 AND target_heading = 132; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'kithicor' AND version = 0 AND number = 3 AND id = 41 AND target_heading = 231; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'commons' AND version = 0 AND number = 2 AND id = 45 AND target_heading = 194; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'commons' AND version = 0 AND number = 3 AND id = 47 AND target_heading = 191; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'ecommons' AND version = 0 AND number = 2 AND id = 49 AND target_heading = 65; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'ecommons' AND version = 0 AND number = 3 AND id = 51 AND target_heading = 191; +UPDATE zone_points SET target_heading = 100 WHERE zone = 'ecommons' AND version = 0 AND number = 4 AND id = 53 AND target_heading = 50; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'gukbottom' AND version = 0 AND number = 7 AND id = 71 AND target_heading = 65; +UPDATE zone_points SET target_heading = 453.8 WHERE zone = 'feerrott' AND version = 0 AND number = 1 AND id = 94 AND target_heading = 226.9; +UPDATE zone_points SET target_heading = 118.2 WHERE zone = 'feerrott' AND version = 0 AND number = 2 AND id = 97 AND target_heading = 59.1; +UPDATE zone_points SET target_heading = 5 WHERE zone = 'feerrott' AND version = 0 AND number = 4 AND id = 99 AND target_heading = 2.5; +UPDATE zone_points SET target_heading = 123.2 WHERE zone = 'feerrott' AND version = 0 AND number = 3 AND id = 101 AND target_heading = 61.6; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'southkarana' AND version = 0 AND number = 4 AND id = 108 AND target_heading = 0; +UPDATE zone_points SET target_heading = 208 WHERE zone = 'erudsxing' AND version = 0 AND number = 1 AND id = 121 AND target_heading = 104; +UPDATE zone_points SET target_heading = 66 WHERE zone = 'akanon' AND version = 0 AND number = 1000 AND id = 148 AND target_heading = 33; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'warslikswoods' AND version = 0 AND number = 3 AND id = 156 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'erudnint' AND version = 0 AND number = 1 AND id = 181 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'erudnint' AND version = 0 AND number = 2 AND id = 182 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'butcher' AND version = 0 AND number = 4 AND id = 186 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'oasis' AND version = 0 AND number = 3 AND id = 187 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'highkeep' AND version = 0 AND number = 2 AND id = 197 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qeynos' AND version = 0 AND number = 5 AND id = 214 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westwastes' AND version = 0 AND number = 2 AND id = 310 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'necropolis' AND version = 0 AND number = 1 AND id = 311 AND target_heading = 0; +UPDATE zone_points SET target_heading = 168 WHERE zone = 'westwastes' AND version = 0 AND number = 3 AND id = 312 AND target_heading = 84; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'felwithea' AND version = 0 AND number = 2 AND id = 336 AND target_heading = 0; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'felwithea' AND version = 0 AND number = 3 AND id = 337 AND target_heading = 65; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'gfaydark' AND version = 0 AND number = 1 AND id = 338 AND target_heading = 187; +UPDATE zone_points SET target_heading = 198.8 WHERE zone = 'gfaydark' AND version = 0 AND number = 2 AND id = 339 AND target_heading = 99.4; +UPDATE zone_points SET target_heading = 56 WHERE zone = 'gfaydark' AND version = 0 AND number = 3 AND id = 340 AND target_heading = 28; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'gfaydark' AND version = 0 AND number = 4 AND id = 341 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'gfaydark' AND version = 0 AND number = 177 AND id = 342 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'gfaydark' AND version = 0 AND number = 178 AND id = 343 AND target_heading = 231; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'crushbone' AND version = 0 AND number = 1 AND id = 345 AND target_heading = 130; +UPDATE zone_points SET target_heading = 300 WHERE zone = 'gunthak' AND version = 0 AND number = 1 AND id = 346 AND target_heading = 150; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'gunthak' AND version = 0 AND number = 2 AND id = 347 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'gunthak' AND version = 0 AND number = 3 AND id = 348 AND target_heading = 0; +UPDATE zone_points SET target_heading = 10 WHERE zone = 'gunthak' AND version = 0 AND number = 4 AND id = 349 AND target_heading = 5; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'felwitheb' AND version = 0 AND number = 1 AND id = 370 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'felwitheb' AND version = 0 AND number = 2 AND id = 371 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'felwitheb' AND version = 0 AND number = 3 AND id = 372 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'felwitheb' AND version = 0 AND number = 4 AND id = 373 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'felwitheb' AND version = 0 AND number = 5 AND id = 374 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'felwitheb' AND version = 0 AND number = 6 AND id = 375 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'felwitheb' AND version = 0 AND number = 7 AND id = 376 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'freporte' AND version = 0 AND number = 9 AND id = 377 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'freporte' AND version = 0 AND number = 10 AND id = 378 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'freporte' AND version = 0 AND number = 11 AND id = 379 AND target_heading = 128; +UPDATE zone_points SET target_heading = 196 WHERE zone = 'freporte' AND version = 0 AND number = 53 AND id = 380 AND target_heading = 98; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'freportw' AND version = 0 AND number = 5 AND id = 381 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'freportw' AND version = 0 AND number = 6 AND id = 382 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'freportw' AND version = 0 AND number = 7 AND id = 383 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'freportw' AND version = 0 AND number = 8 AND id = 384 AND target_heading = 0; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'freportw' AND version = 0 AND number = 9 AND id = 385 AND target_heading = 65; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'freportw' AND version = 0 AND number = 10 AND id = 386 AND target_heading = 130; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'freportw' AND version = 0 AND number = 12 AND id = 387 AND target_heading = 63; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'freportw' AND version = 0 AND number = 51 AND id = 388 AND target_heading = 65; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'freportw' AND version = 0 AND number = 52 AND id = 389 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'freportw' AND version = 0 AND number = 53 AND id = 390 AND target_heading = 231; +UPDATE zone_points SET target_heading = 4 WHERE zone = 'freportw' AND version = 0 AND number = 177 AND id = 391 AND target_heading = 2; +UPDATE zone_points SET target_heading = 253.8 WHERE zone = 'freportn' AND version = 0 AND number = 7 AND id = 392 AND target_heading = 126.9; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'freportn' AND version = 0 AND number = 8 AND id = 393 AND target_heading = 125; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'freportn' AND version = 0 AND number = 51 AND id = 394 AND target_heading = 160; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'freportn' AND version = 0 AND number = 52 AND id = 395 AND target_heading = 0; +UPDATE zone_points SET target_heading = 255 WHERE zone = 'grobb' AND version = 0 AND number = 1 AND id = 396 AND target_heading = 127.5; +UPDATE zone_points SET target_heading = 196 WHERE zone = 'halas' AND version = 0 AND number = 1 AND id = 397 AND target_heading = 98; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'kaladima' AND version = 0 AND number = 1 AND id = 398 AND target_heading = 130; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'kaladima' AND version = 0 AND number = 2 AND id = 399 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'kaladima' AND version = 0 AND number = 3 AND id = 400 AND target_heading = 231; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'kaladimb' AND version = 0 AND number = 1 AND id = 401 AND target_heading = 160; +UPDATE zone_points SET target_heading = 200 WHERE zone = 'kaladimb' AND version = 0 AND number = 2 AND id = 402 AND target_heading = 100; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'katta' AND version = 0 AND number = 1 AND id = 403 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'katta' AND version = 0 AND number = 2 AND id = 404 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'katta' AND version = 0 AND number = 3 AND id = 405 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'katta' AND version = 0 AND number = 7 AND id = 407 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'katta' AND version = 0 AND number = 8 AND id = 408 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'katta' AND version = 0 AND number = 9 AND id = 409 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'katta' AND version = 0 AND number = 10 AND id = 410 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'katta' AND version = 0 AND number = 11 AND id = 411 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'katta' AND version = 0 AND number = 12 AND id = 412 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'neriaka' AND version = 0 AND number = 1 AND id = 413 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'neriaka' AND version = 0 AND number = 2 AND id = 414 AND target_heading = 231; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'neriaka' AND version = 0 AND number = 3 AND id = 415 AND target_heading = 64; +UPDATE zone_points SET target_heading = 380 WHERE zone = 'neriakb' AND version = 0 AND number = 1 AND id = 416 AND target_heading = 190; +UPDATE zone_points SET target_heading = 134 WHERE zone = 'neriakb' AND version = 0 AND number = 2 AND id = 417 AND target_heading = 67; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'neriakb' AND version = 0 AND number = 3 AND id = 418 AND target_heading = 231; +UPDATE zone_points SET target_heading = 261.6 WHERE zone = 'neriakc' AND version = 0 AND number = 1 AND id = 419 AND target_heading = 130.8; +UPDATE zone_points SET target_heading = 504 WHERE zone = 'neriakc' AND version = 0 AND number = 2 AND id = 420 AND target_heading = 252; +UPDATE zone_points SET target_heading = 502 WHERE zone = 'nexus' AND version = 0 AND number = 0 AND id = 425 AND target_heading = 251; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'nexus' AND version = 0 AND number = 2 AND id = 426 AND target_heading = 64; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'nexus' AND version = 0 AND number = 3 AND id = 427 AND target_heading = 231; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'nexus' AND version = 0 AND number = 4 AND id = 428 AND target_heading = 192; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'nexus' AND version = 0 AND number = 6 AND id = 429 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'nexus' AND version = 0 AND number = 7 AND id = 430 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nexus' AND version = 0 AND number = 8 AND id = 431 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nexus' AND version = 0 AND number = 9 AND id = 432 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nexus' AND version = 0 AND number = 10 AND id = 433 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nexus' AND version = 0 AND number = 11 AND id = 434 AND target_heading = 0; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'nexus' AND version = 0 AND number = 12 AND id = 435 AND target_heading = 249; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nexus' AND version = 0 AND number = 13 AND id = 436 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'nexus' AND version = 0 AND number = 14 AND id = 437 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nexus' AND version = 0 AND number = 25 AND id = 438 AND target_heading = 0; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'nexus' AND version = 0 AND number = 77 AND id = 439 AND target_heading = 1; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'oggok' AND version = 0 AND number = 1 AND id = 440 AND target_heading = 126; +UPDATE zone_points SET target_heading = 6 WHERE zone = 'poknowledge' AND version = 0 AND number = 1 AND id = 452 AND target_heading = 3; +UPDATE zone_points SET target_heading = 348 WHERE zone = 'poknowledge' AND version = 0 AND number = 2 AND id = 453 AND target_heading = 174; +UPDATE zone_points SET target_heading = 90 WHERE zone = 'poknowledge' AND version = 0 AND number = 3 AND id = 454 AND target_heading = 45; +UPDATE zone_points SET target_heading = 394 WHERE zone = 'poknowledge' AND version = 0 AND number = 4 AND id = 455 AND target_heading = 197; +UPDATE zone_points SET target_heading = 488 WHERE zone = 'poknowledge' AND version = 0 AND number = 5 AND id = 456 AND target_heading = 244; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'poknowledge' AND version = 0 AND number = 6 AND id = 457 AND target_heading = 119; +UPDATE zone_points SET target_heading = 270 WHERE zone = 'poknowledge' AND version = 0 AND number = 7 AND id = 458 AND target_heading = 135; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'poknowledge' AND version = 0 AND number = 8 AND id = 459 AND target_heading = 0; +UPDATE zone_points SET target_heading = 472 WHERE zone = 'poknowledge' AND version = 0 AND number = 9 AND id = 460 AND target_heading = 236; +UPDATE zone_points SET target_heading = 22 WHERE zone = 'poknowledge' AND version = 0 AND number = 10 AND id = 461 AND target_heading = 11; +UPDATE zone_points SET target_heading = 262 WHERE zone = 'poknowledge' AND version = 0 AND number = 11 AND id = 462 AND target_heading = 131; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'poknowledge' AND version = 0 AND number = 12 AND id = 463 AND target_heading = 128; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'poknowledge' AND version = 0 AND number = 13 AND id = 464 AND target_heading = 255; +UPDATE zone_points SET target_heading = 496 WHERE zone = 'poknowledge' AND version = 0 AND number = 14 AND id = 465 AND target_heading = 248; +UPDATE zone_points SET target_heading = 6 WHERE zone = 'poknowledge' AND version = 0 AND number = 15 AND id = 466 AND target_heading = 3; +UPDATE zone_points SET target_heading = 432 WHERE zone = 'poknowledge' AND version = 0 AND number = 16 AND id = 467 AND target_heading = 216; +UPDATE zone_points SET target_heading = 40 WHERE zone = 'poknowledge' AND version = 0 AND number = 17 AND id = 468 AND target_heading = 20; +UPDATE zone_points SET target_heading = 496 WHERE zone = 'poknowledge' AND version = 0 AND number = 18 AND id = 469 AND target_heading = 248; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'poknowledge' AND version = 0 AND number = 19 AND id = 470 AND target_heading = 128; +UPDATE zone_points SET target_heading = 232 WHERE zone = 'poknowledge' AND version = 0 AND number = 20 AND id = 471 AND target_heading = 116; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'qeynos' AND version = 0 AND number = 3 AND id = 472 AND target_heading = 129; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'qeynos' AND version = 0 AND number = 4 AND id = 473 AND target_heading = 250; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qeynos' AND version = 0 AND number = 22 AND id = 474 AND target_heading = 231; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'qeynos' AND version = 0 AND number = 33 AND id = 475 AND target_heading = 195; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qeynos2' AND version = 0 AND number = 1 AND id = 476 AND target_heading = 231; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'qeynos2' AND version = 0 AND number = 2 AND id = 477 AND target_heading = 250; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'qeynos2' AND version = 0 AND number = 4 AND id = 478 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qeynos2' AND version = 0 AND number = 5 AND id = 479 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qeynos2' AND version = 0 AND number = 6 AND id = 480 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'qeynos2' AND version = 0 AND number = 14 AND id = 481 AND target_heading = 0; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'qeynos2' AND version = 0 AND number = 77 AND id = 482 AND target_heading = 127; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'qeynos2' AND version = 0 AND number = 99 AND id = 483 AND target_heading = 127; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'qcat' AND version = 0 AND number = 1 AND id = 484 AND target_heading = 65; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'qcat' AND version = 0 AND number = 2 AND id = 485 AND target_heading = 65; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qcat' AND version = 0 AND number = 3 AND id = 486 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qcat' AND version = 0 AND number = 4 AND id = 487 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qcat' AND version = 0 AND number = 5 AND id = 488 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qcat' AND version = 0 AND number = 6 AND id = 489 AND target_heading = 231; +UPDATE zone_points SET target_heading = 38 WHERE zone = 'qcat' AND version = 0 AND number = 7 AND id = 490 AND target_heading = 19; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'qcat' AND version = 0 AND number = 99 AND id = 491 AND target_heading = 231; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'rivervale' AND version = 0 AND number = 98 AND id = 492 AND target_heading = 132; +UPDATE zone_points SET target_heading = 12.2 WHERE zone = 'rivervale' AND version = 0 AND number = 99 AND id = 493 AND target_heading = 6.1; +UPDATE zone_points SET target_heading = 64 WHERE zone = 'sseru' AND version = 0 AND number = 1 AND id = 494 AND target_heading = 32; +UPDATE zone_points SET target_heading = 490 WHERE zone = 'sseru' AND version = 0 AND number = 2 AND id = 495 AND target_heading = 245; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'sseru' AND version = 0 AND number = 3 AND id = 496 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'sseru' AND version = 0 AND number = 6 AND id = 497 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'sseru' AND version = 0 AND number = 8 AND id = 498 AND target_heading = 0; +UPDATE zone_points SET target_heading = 496 WHERE zone = 'sseru' AND version = 0 AND number = 188 AND id = 499 AND target_heading = 248; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'sseru' AND version = 0 AND number = 189 AND id = 500 AND target_heading = 249; +UPDATE zone_points SET target_heading = 504 WHERE zone = 'sseru' AND version = 0 AND number = 191 AND id = 501 AND target_heading = 252; +UPDATE zone_points SET target_heading = 240 WHERE zone = 'sseru' AND version = 0 AND number = 192 AND id = 502 AND target_heading = 120; +UPDATE zone_points SET target_heading = 248 WHERE zone = 'sseru' AND version = 0 AND number = 193 AND id = 503 AND target_heading = 124; +UPDATE zone_points SET target_heading = 494 WHERE zone = 'sseru' AND version = 0 AND number = 194 AND id = 504 AND target_heading = 247; +UPDATE zone_points SET target_heading = 6 WHERE zone = 'sseru' AND version = 0 AND number = 195 AND id = 505 AND target_heading = 3; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'sseru' AND version = 0 AND number = 196 AND id = 506 AND target_heading = 119; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'sseru' AND version = 0 AND number = 197 AND id = 507 AND target_heading = 128; +UPDATE zone_points SET target_heading = 504 WHERE zone = 'sseru' AND version = 0 AND number = 198 AND id = 508 AND target_heading = 252; +UPDATE zone_points SET target_heading = 6 WHERE zone = 'sseru' AND version = 0 AND number = 201 AND id = 509 AND target_heading = 3; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'sseru' AND version = 0 AND number = 202 AND id = 510 AND target_heading = 132; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'sseru' AND version = 0 AND number = 203 AND id = 511 AND target_heading = 127; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'sseru' AND version = 0 AND number = 204 AND id = 512 AND target_heading = 254; +UPDATE zone_points SET target_heading = 244 WHERE zone = 'sseru' AND version = 0 AND number = 205 AND id = 513 AND target_heading = 122; +UPDATE zone_points SET target_heading = 494 WHERE zone = 'sseru' AND version = 0 AND number = 206 AND id = 514 AND target_heading = 247; +UPDATE zone_points SET target_heading = 494 WHERE zone = 'sseru' AND version = 0 AND number = 207 AND id = 515 AND target_heading = 247; +UPDATE zone_points SET target_heading = 240 WHERE zone = 'sseru' AND version = 0 AND number = 208 AND id = 516 AND target_heading = 120; +UPDATE zone_points SET target_heading = 248 WHERE zone = 'sseru' AND version = 0 AND number = 209 AND id = 517 AND target_heading = 124; +UPDATE zone_points SET target_heading = 506 WHERE zone = 'sseru' AND version = 0 AND number = 210 AND id = 518 AND target_heading = 253; +UPDATE zone_points SET target_heading = 242 WHERE zone = 'sseru' AND version = 0 AND number = 211 AND id = 519 AND target_heading = 121; +UPDATE zone_points SET target_heading = 492 WHERE zone = 'sseru' AND version = 0 AND number = 212 AND id = 520 AND target_heading = 246; +UPDATE zone_points SET target_heading = 502 WHERE zone = 'sseru' AND version = 0 AND number = 213 AND id = 521 AND target_heading = 251; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'shadowhaven' AND version = 0 AND number = 1 AND id = 522 AND target_heading = 231; +UPDATE zone_points SET target_heading = 71.2 WHERE zone = 'shadowhaven' AND version = 0 AND number = 2 AND id = 523 AND target_heading = 35.6; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'shadowhaven' AND version = 0 AND number = 3 AND id = 524 AND target_heading = 65; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'shadowhaven' AND version = 0 AND number = 4 AND id = 525 AND target_heading = 192; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'shadowhaven' AND version = 0 AND number = 6 AND id = 526 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'shadowhaven' AND version = 0 AND number = 7 AND id = 527 AND target_heading = 231; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'shadowhaven' AND version = 0 AND number = 8 AND id = 528 AND target_heading = 256; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'shadowhaven' AND version = 0 AND number = 9 AND id = 529 AND target_heading = 128; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'shadowhaven' AND version = 0 AND number = 10 AND id = 530 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'shadowhaven' AND version = 0 AND number = 11 AND id = 531 AND target_heading = 128; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'sharvahl' AND version = 0 AND number = 1 AND id = 533 AND target_heading = 65; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'sharvahl' AND version = 0 AND number = 2 AND id = 534 AND target_heading = 194; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'qrg' AND version = 0 AND number = 5 AND id = 537 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'qrg' AND version = 0 AND number = 7 AND id = 538 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'thurgadina' AND version = 0 AND number = 1 AND id = 539 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thurgadina' AND version = 0 AND number = 2 AND id = 540 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thurgadina' AND version = 0 AND number = 3 AND id = 541 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'thurgadinb' AND version = 0 AND number = 1 AND id = 542 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thurgadinb' AND version = 0 AND number = 2 AND id = 543 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'thurgadinb' AND version = 0 AND number = 3 AND id = 544 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'butcher' AND version = 0 AND number = 1 AND id = 549 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'butcher' AND version = 0 AND number = 2 AND id = 550 AND target_heading = 0; +UPDATE zone_points SET target_heading = 176 WHERE zone = 'butcher' AND version = 0 AND number = 3 AND id = 551 AND target_heading = 88; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'butcher' AND version = 0 AND number = 77 AND id = 552 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'cobaltscar' AND version = 0 AND number = 1 AND id = 555 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'cobaltscar' AND version = 0 AND number = 10 AND id = 556 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'cauldron' AND version = 0 AND number = 1 AND id = 557 AND target_heading = 231; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'cauldron' AND version = 0 AND number = 2 AND id = 558 AND target_heading = 191; +UPDATE zone_points SET target_heading = 310 WHERE zone = 'cauldron' AND version = 0 AND number = 3 AND id = 559 AND target_heading = 155; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'dawnshroud' AND version = 0 AND number = 1 AND id = 560 AND target_heading = 128; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'dawnshroud' AND version = 0 AND number = 2 AND id = 561 AND target_heading = 192; +UPDATE zone_points SET target_heading = 380.8 WHERE zone = 'dawnshroud' AND version = 0 AND number = 3 AND id = 562 AND target_heading = 190.4; +UPDATE zone_points SET target_heading = 253.6 WHERE zone = 'dawnshroud' AND version = 0 AND number = 4 AND id = 563 AND target_heading = 126.8; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'dawnshroud' AND version = 0 AND number = 5 AND id = 564 AND target_heading = 128; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'dawnshroud' AND version = 0 AND number = 6 AND id = 565 AND target_heading = 64; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'dulak' AND version = 0 AND number = 1 AND id = 573 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'dulak' AND version = 0 AND number = 2 AND id = 574 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'ecommons' AND version = 0 AND number = 1 AND id = 575 AND target_heading = 231; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'eastwastes' AND version = 0 AND number = 1 AND id = 581 AND target_heading = 192; +UPDATE zone_points SET target_heading = 131.8 WHERE zone = 'eastwastes' AND version = 0 AND number = 2 AND id = 582 AND target_heading = 65.9; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'eastwastes' AND version = 0 AND number = 3 AND id = 583 AND target_heading = 65; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'eastwastes' AND version = 0 AND number = 5 AND id = 584 AND target_heading = 195; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'eastwastes' AND version = 0 AND number = 13 AND id = 585 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'everfrost' AND version = 0 AND number = 1 AND id = 590 AND target_heading = 231; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'everfrost' AND version = 0 AND number = 2 AND id = 591 AND target_heading = 125; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'everfrost' AND version = 0 AND number = 3 AND id = 592 AND target_heading = 195; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'everfrost' AND version = 0 AND number = 77 AND id = 594 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'greatdivide' AND version = 0 AND number = 0 AND id = 615 AND target_heading = 0; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'greatdivide' AND version = 0 AND number = 1 AND id = 616 AND target_heading = 191; +UPDATE zone_points SET target_heading = 8 WHERE zone = 'greatdivide' AND version = 0 AND number = 2 AND id = 617 AND target_heading = 4; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'greatdivide' AND version = 0 AND number = 3 AND id = 618 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'greatdivide' AND version = 0 AND number = 4 AND id = 619 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'greatdivide' AND version = 0 AND number = 77 AND id = 620 AND target_heading = 231; +UPDATE zone_points SET target_heading = 168 WHERE zone = 'thegrey' AND version = 0 AND number = 1 AND id = 621 AND target_heading = 84; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'thegrey' AND version = 0 AND number = 2 AND id = 622 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'thegrey' AND version = 0 AND number = 3 AND id = 623 AND target_heading = 128; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'grimling' AND version = 0 AND number = 1 AND id = 624 AND target_heading = 130; +UPDATE zone_points SET target_heading = 192 WHERE zone = 'grimling' AND version = 0 AND number = 2 AND id = 625 AND target_heading = 96; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'grimling' AND version = 0 AND number = 3 AND id = 626 AND target_heading = 231; +UPDATE zone_points SET target_heading = 143.2 WHERE zone = 'hollowshade' AND version = 0 AND number = 1 AND id = 633 AND target_heading = 71.6; +UPDATE zone_points SET target_heading = 64 WHERE zone = 'hollowshade' AND version = 0 AND number = 2 AND id = 634 AND target_heading = 32; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'hollowshade' AND version = 0 AND number = 3 AND id = 635 AND target_heading = 130; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'iceclad' AND version = 0 AND number = 1 AND id = 637 AND target_heading = 64; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'iceclad' AND version = 0 AND number = 7 AND id = 638 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'iceclad' AND version = 0 AND number = 9 AND id = 639 AND target_heading = 0; +UPDATE zone_points SET target_heading = 384.4 WHERE zone = 'innothule' AND version = 0 AND number = 1 AND id = 640 AND target_heading = 192.2; +UPDATE zone_points SET target_heading = 16 WHERE zone = 'innothule' AND version = 0 AND number = 2 AND id = 641 AND target_heading = 8; +UPDATE zone_points SET target_heading = 511.8 WHERE zone = 'innothule' AND version = 0 AND number = 3 AND id = 642 AND target_heading = 255.9; +UPDATE zone_points SET target_heading = 511 WHERE zone = 'innothule' AND version = 0 AND number = 4 AND id = 643 AND target_heading = 255.5; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'innothule' AND version = 0 AND number = 77 AND id = 644 AND target_heading = 231; +UPDATE zone_points SET target_heading = 396 WHERE zone = 'kerraridge' AND version = 0 AND number = 1 AND id = 647 AND target_heading = 198; +UPDATE zone_points SET target_heading = 28 WHERE zone = 'kithicor' AND version = 0 AND number = 1 AND id = 648 AND target_heading = 14; +UPDATE zone_points SET target_heading = 502 WHERE zone = 'kithicor' AND version = 0 AND number = 2 AND id = 649 AND target_heading = 251; +UPDATE zone_points SET target_heading = 176 WHERE zone = 'lavastorm' AND version = 0 AND number = 0 AND id = 658 AND target_heading = 88; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'lfaydark' AND version = 0 AND number = 1 AND id = 663 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'lfaydark' AND version = 0 AND number = 2 AND id = 664 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'lfaydark' AND version = 0 AND number = 3 AND id = 665 AND target_heading = 231; +UPDATE zone_points SET target_heading = 452 WHERE zone = 'lfaydark' AND version = 0 AND number = 9 AND id = 666 AND target_heading = 226; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'maiden' AND version = 0 AND number = 1 AND id = 667 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'maiden' AND version = 0 AND number = 2 AND id = 668 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'maiden' AND version = 0 AND number = 3 AND id = 669 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'maiden' AND version = 0 AND number = 4 AND id = 670 AND target_heading = 128; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'mseru' AND version = 0 AND number = 1 AND id = 671 AND target_heading = 191; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'mseru' AND version = 0 AND number = 2 AND id = 672 AND target_heading = 192; +UPDATE zone_points SET target_heading = 100 WHERE zone = 'mseru' AND version = 0 AND number = 3 AND id = 673 AND target_heading = 50; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'mseru' AND version = 0 AND number = 4 AND id = 674 AND target_heading = 192; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'misty' AND version = 0 AND number = 1 AND id = 675 AND target_heading = 106; +UPDATE zone_points SET target_heading = 380 WHERE zone = 'misty' AND version = 0 AND number = 2 AND id = 676 AND target_heading = 190; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'misty' AND version = 0 AND number = 77 AND id = 677 AND target_heading = 255; +UPDATE zone_points SET target_heading = 466 WHERE zone = 'letalis' AND version = 0 AND number = 1 AND id = 678 AND target_heading = 233; +UPDATE zone_points SET target_heading = 166 WHERE zone = 'letalis' AND version = 0 AND number = 2 AND id = 679 AND target_heading = 83; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'nadox' AND version = 0 AND number = 1 AND id = 681 AND target_heading = 192; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'nadox' AND version = 0 AND number = 2 AND id = 682 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nadox' AND version = 0 AND number = 3 AND id = 683 AND target_heading = 0; +UPDATE zone_points SET target_heading = 330 WHERE zone = 'nadox' AND version = 0 AND number = 4 AND id = 684 AND target_heading = 165; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'nro' AND version = 0 AND number = 1 AND id = 686 AND target_heading = 254; +UPDATE zone_points SET target_heading = 268 WHERE zone = 'nro' AND version = 0 AND number = 2 AND id = 687 AND target_heading = 134; +UPDATE zone_points SET target_heading = 102 WHERE zone = 'nro' AND version = 0 AND number = 3 AND id = 688 AND target_heading = 51; +UPDATE zone_points SET target_heading = 132 WHERE zone = 'nro' AND version = 0 AND number = 4 AND id = 689 AND target_heading = 66; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'northkarana' AND version = 0 AND number = 4 AND id = 691 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'oasis' AND version = 0 AND number = 1 AND id = 692 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'oasis' AND version = 0 AND number = 2 AND id = 693 AND target_heading = 128; +UPDATE zone_points SET target_heading = 262 WHERE zone = 'qeytoqrg' AND version = 0 AND number = 1 AND id = 700 AND target_heading = 131; +UPDATE zone_points SET target_heading = 328 WHERE zone = 'qeytoqrg' AND version = 0 AND number = 2 AND id = 701 AND target_heading = 164; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'qeytoqrg' AND version = 0 AND number = 3 AND id = 703 AND target_heading = 65; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'qeytoqrg' AND version = 0 AND number = 4 AND id = 704 AND target_heading = 0; +UPDATE zone_points SET target_heading = 72 WHERE zone = 'rathemtn' AND version = 0 AND number = 1 AND id = 725 AND target_heading = 36; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'rathemtn' AND version = 0 AND number = 2 AND id = 726 AND target_heading = 130; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'scarlet' AND version = 0 AND number = 1 AND id = 727 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'scarlet' AND version = 0 AND number = 2 AND id = 728 AND target_heading = 0; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'scarlet' AND version = 0 AND number = 3 AND id = 729 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'shadeweaver' AND version = 0 AND number = 1 AND id = 730 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'shadeweaver' AND version = 0 AND number = 3 AND id = 731 AND target_heading = 64; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'shadeweaver' AND version = 0 AND number = 77 AND id = 733 AND target_heading = 127; +UPDATE zone_points SET target_heading = 22.4 WHERE zone = 'sro' AND version = 0 AND number = 1 AND id = 738 AND target_heading = 11.2; +UPDATE zone_points SET target_heading = 234.2 WHERE zone = 'sro' AND version = 0 AND number = 2 AND id = 739 AND target_heading = 117.1; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'southkarana' AND version = 0 AND number = 1 AND id = 740 AND target_heading = 129; +UPDATE zone_points SET target_heading = 144 WHERE zone = 'steamfont' AND version = 0 AND number = 1 AND id = 741 AND target_heading = 72; +UPDATE zone_points SET target_heading = 64 WHERE zone = 'steamfont' AND version = 0 AND number = 2 AND id = 742 AND target_heading = 32; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'steamfont' AND version = 0 AND number = 77 AND id = 743 AND target_heading = 255; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'soltemple' AND version = 0 AND number = 1 AND id = 752 AND target_heading = 130; +UPDATE zone_points SET target_heading = 300 WHERE zone = 'tenebrous' AND version = 0 AND number = 1 AND id = 753 AND target_heading = 150; +UPDATE zone_points SET target_heading = 135.2 WHERE zone = 'tenebrous' AND version = 0 AND number = 2 AND id = 754 AND target_heading = 67.6; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'torgiran' AND version = 0 AND number = 1 AND id = 767 AND target_heading = 0; +UPDATE zone_points SET target_heading = 274 WHERE zone = 'torgiran' AND version = 0 AND number = 2 AND id = 768 AND target_heading = 137; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'tox' AND version = 0 AND number = 0 AND id = 769 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'tox' AND version = 0 AND number = 1 AND id = 770 AND target_heading = 0; +UPDATE zone_points SET target_heading = 189.6 WHERE zone = 'tox' AND version = 0 AND number = 2 AND id = 771 AND target_heading = 94.8; +UPDATE zone_points SET target_heading = 76 WHERE zone = 'tox' AND version = 0 AND number = 3 AND id = 772 AND target_heading = 38; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'tox' AND version = 0 AND number = 77 AND id = 774 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'tox' AND version = 0 AND number = 177 AND id = 775 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'twilight' AND version = 0 AND number = 1 AND id = 779 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'twilight' AND version = 0 AND number = 2 AND id = 780 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'twilight' AND version = 0 AND number = 6 AND id = 782 AND target_heading = 0; +UPDATE zone_points SET target_heading = 248 WHERE zone = 'umbral' AND version = 0 AND number = 1 AND id = 783 AND target_heading = 124; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'umbral' AND version = 0 AND number = 2 AND id = 784 AND target_heading = 65; +UPDATE zone_points SET target_heading = 128.8 WHERE zone = 'umbral' AND version = 0 AND number = 45 AND id = 785 AND target_heading = 64.4; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'wakening' AND version = 0 AND number = 1 AND id = 786 AND target_heading = 0; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'wakening' AND version = 0 AND number = 2 AND id = 787 AND target_heading = 195; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'wakening' AND version = 0 AND number = 7 AND id = 788 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westwastes' AND version = 0 AND number = 1 AND id = 796 AND target_heading = 128; +UPDATE zone_points SET target_heading = 48 WHERE zone = 'westwastes' AND version = 0 AND number = 20 AND id = 797 AND target_heading = 24; +UPDATE zone_points SET target_heading = 168 WHERE zone = 'westwastes' AND version = 0 AND number = 56 AND id = 798 AND target_heading = 84; +UPDATE zone_points SET target_heading = 62 WHERE zone = 'qey2hh1' AND version = 0 AND number = 1 AND id = 799 AND target_heading = 31; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'befallen' AND version = 0 AND number = 1 AND id = 801 AND target_heading = 231; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'blackburrow' AND version = 0 AND number = 1 AND id = 802 AND target_heading = 130; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'blackburrow' AND version = 0 AND number = 2 AND id = 803 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'blackburrow' AND version = 0 AND number = 7 AND id = 804 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'lakerathe' AND version = 0 AND number = 1 AND id = 806 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'lakerathe' AND version = 0 AND number = 2 AND id = 807 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'lakerathe' AND version = 0 AND number = 3 AND id = 808 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'crystal' AND version = 0 AND number = 1 AND id = 811 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'crystal' AND version = 0 AND number = 2 AND id = 812 AND target_heading = 231; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'thedeep' AND version = 0 AND number = 1 AND id = 816 AND target_heading = 64; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thedeep' AND version = 0 AND number = 2 AND id = 817 AND target_heading = 0; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'echo' AND version = 0 AND number = 1 AND id = 821 AND target_heading = 130; +UPDATE zone_points SET target_heading = 131 WHERE zone = 'echo' AND version = 0 AND number = 2 AND id = 822 AND target_heading = 65.5; +UPDATE zone_points SET target_heading = 121.6 WHERE zone = 'echo' AND version = 0 AND number = 3 AND id = 823 AND target_heading = 60.8; +UPDATE zone_points SET target_heading = 6.2 WHERE zone = 'echo' AND version = 0 AND number = 4 AND id = 824 AND target_heading = 3.1; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 2 AND id = 826 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 3 AND id = 827 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 4 AND id = 828 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 5 AND id = 829 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 6 AND id = 830 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 7 AND id = 831 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 8 AND id = 832 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 9 AND id = 833 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 10 AND id = 834 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 11 AND id = 835 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 12 AND id = 836 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 13 AND id = 837 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 14 AND id = 838 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 15 AND id = 839 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 16 AND id = 840 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 17 AND id = 841 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 18 AND id = 842 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 19 AND id = 843 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frozenshadow' AND version = 0 AND number = 20 AND id = 844 AND target_heading = 231; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'fungusgrove' AND version = 0 AND number = 1 AND id = 845 AND target_heading = 192; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'fungusgrove' AND version = 0 AND number = 3 AND id = 846 AND target_heading = 0; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'griegsend' AND version = 0 AND number = 1 AND id = 847 AND target_heading = 64; +UPDATE zone_points SET target_heading = 511.6 WHERE zone = 'griegsend' AND version = 0 AND number = 2 AND id = 848 AND target_heading = 255.8; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'griegsend' AND version = 0 AND number = 3 AND id = 849 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'griegsend' AND version = 0 AND number = 4 AND id = 850 AND target_heading = 0; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'guktop' AND version = 0 AND number = 1 AND id = 851 AND target_heading = 195; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'guktop' AND version = 0 AND number = 2 AND id = 852 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'guktop' AND version = 0 AND number = 4 AND id = 853 AND target_heading = 0; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'guktop' AND version = 0 AND number = 5 AND id = 854 AND target_heading = 129; +UPDATE zone_points SET target_heading = 130.2 WHERE zone = 'guktop' AND version = 0 AND number = 6 AND id = 855 AND target_heading = 65.1; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'gukbottom' AND version = 0 AND number = 1 AND id = 857 AND target_heading = 65; +UPDATE zone_points SET target_heading = 196 WHERE zone = 'gukbottom' AND version = 0 AND number = 2 AND id = 858 AND target_heading = 98; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'gukbottom' AND version = 0 AND number = 4 AND id = 860 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'gukbottom' AND version = 0 AND number = 5 AND id = 861 AND target_heading = 128; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'gukbottom' AND version = 0 AND number = 3 AND id = 862 AND target_heading = 65; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'hatesfury' AND version = 0 AND number = 1 AND id = 863 AND target_heading = 0; +UPDATE zone_points SET target_heading = 248 WHERE zone = 'hatesfury' AND version = 0 AND number = 2 AND id = 864 AND target_heading = 124; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'hatesfury' AND version = 0 AND number = 3 AND id = 865 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'hatesfury' AND version = 0 AND number = 4 AND id = 866 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'hatesfury' AND version = 0 AND number = 5 AND id = 867 AND target_heading = 0; +UPDATE zone_points SET target_heading = 248 WHERE zone = 'hatesfury' AND version = 0 AND number = 6 AND id = 868 AND target_heading = 124; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'hatesfury' AND version = 0 AND number = 7 AND id = 869 AND target_heading = 128; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'kael' AND version = 0 AND number = 1 AND id = 879 AND target_heading = 65; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'kael' AND version = 0 AND number = 2 AND id = 880 AND target_heading = 231; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'mistmoore' AND version = 0 AND number = 1 AND id = 888 AND target_heading = 130; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'najena' AND version = 0 AND number = 1 AND id = 889 AND target_heading = 130; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'necropolis' AND version = 0 AND number = 66 AND id = 890 AND target_heading = 130; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'netherbian' AND version = 0 AND number = 1 AND id = 891 AND target_heading = 192; +UPDATE zone_points SET target_heading = 324 WHERE zone = 'netherbian' AND version = 0 AND number = 2 AND id = 892 AND target_heading = 162; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'netherbian' AND version = 0 AND number = 3 AND id = 893 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'netherbian' AND version = 0 AND number = 4 AND id = 894 AND target_heading = 64; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'netherbian' AND version = 0 AND number = 5 AND id = 895 AND target_heading = 192; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'netherbian' AND version = 0 AND number = 6 AND id = 896 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'paludal' AND version = 0 AND number = 1 AND id = 902 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'paludal' AND version = 0 AND number = 2 AND id = 903 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'paludal' AND version = 0 AND number = 3 AND id = 904 AND target_heading = 128; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'permafrost' AND version = 0 AND number = 1 AND id = 905 AND target_heading = 65; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'sirens' AND version = 0 AND number = 1 AND id = 908 AND target_heading = 130; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'sirens' AND version = 0 AND number = 2 AND id = 909 AND target_heading = 64; +UPDATE zone_points SET target_heading = 94 WHERE zone = 'soldunga' AND version = 0 AND number = 1 AND id = 910 AND target_heading = 47; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 2 AND id = 911 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 3 AND id = 912 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 4 AND id = 913 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 5 AND id = 914 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 6 AND id = 915 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 7 AND id = 916 AND target_heading = 231; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'soldunga' AND version = 0 AND number = 8 AND id = 917 AND target_heading = 195; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'soldunga' AND version = 0 AND number = 9 AND id = 918 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 10 AND id = 919 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldunga' AND version = 0 AND number = 11 AND id = 920 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'soldunga' AND version = 0 AND number = 12 AND id = 921 AND target_heading = 128; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 0 AND number = 1 AND id = 922 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 2 AND id = 923 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 3 AND id = 924 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 4 AND id = 925 AND target_heading = 250; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 5 AND id = 926 AND target_heading = 250; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 6 AND id = 927 AND target_heading = 250; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 0 AND number = 7 AND id = 928 AND target_heading = 125; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 0 AND number = 8 AND id = 929 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0.2 WHERE zone = 'skyshrine' AND version = 0 AND number = 9 AND id = 930 AND target_heading = 0.1; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 10 AND id = 931 AND target_heading = 250; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 11 AND id = 932 AND target_heading = 250; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 0 AND number = 12 AND id = 933 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 13 AND id = 934 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 14 AND id = 935 AND target_heading = 250; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 15 AND id = 936 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 16 AND id = 937 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 17 AND id = 938 AND target_heading = 250; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'skyshrine' AND version = 0 AND number = 18 AND id = 939 AND target_heading = 129; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 19 AND id = 940 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 0 AND number = 20 AND id = 941 AND target_heading = 250; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 21 AND id = 942 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 22 AND id = 943 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND number = 23 AND id = 944 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 24 AND id = 945 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND number = 30 AND id = 946 AND target_heading = 231; +UPDATE zone_points SET target_heading = 10 WHERE zone = 'skyshrine' AND version = 0 AND number = 40 AND id = 947 AND target_heading = 5; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND number = 41 AND id = 948 AND target_heading = 231; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'skyshrine' AND version = 0 AND number = 42 AND id = 949 AND target_heading = 129; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND number = 43 AND id = 950 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND number = 44 AND id = 951 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 0 AND number = 45 AND id = 952 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 0 AND number = 46 AND id = 953 AND target_heading = 231; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'skyshrine' AND version = 0 AND number = 50 AND id = 954 AND target_heading = 254; +UPDATE zone_points SET target_heading = 396 WHERE zone = 'soldungc' AND version = 0 AND number = 1 AND id = 968 AND target_heading = 198; +UPDATE zone_points SET target_heading = 338 WHERE zone = 'soldungc' AND version = 0 AND number = 2 AND id = 969 AND target_heading = 169; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'unrest' AND version = 0 AND number = 1 AND id = 971 AND target_heading = 231; +UPDATE zone_points SET target_heading = 386 WHERE zone = 'velketor' AND version = 0 AND number = 1 AND id = 972 AND target_heading = 193; +UPDATE zone_points SET target_heading = 259 WHERE zone = 'qeynos2' AND version = 0 AND number = 7 AND id = 977 AND target_heading = 129.5; +UPDATE zone_points SET target_heading = 259 WHERE zone = 'qeynos2' AND version = 0 AND number = 8 AND id = 978 AND target_heading = 129.5; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'nedaria' AND version = 0 AND number = 1 AND id = 979 AND target_heading = 128; +UPDATE zone_points SET target_heading = 290 WHERE zone = 'chardokb' AND version = 0 AND number = 1 AND id = 980 AND target_heading = 145; +UPDATE zone_points SET target_heading = 290 WHERE zone = 'chardokb' AND version = 0 AND number = 2 AND id = 981 AND target_heading = 145; +UPDATE zone_points SET target_heading = 290 WHERE zone = 'chardokb' AND version = 0 AND number = 3 AND id = 982 AND target_heading = 145; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 2 AND id = 983 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 3 AND id = 984 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 4 AND id = 985 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 5 AND id = 986 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 6 AND id = 987 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 7 AND id = 988 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 8 AND id = 989 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 9 AND id = 990 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 10 AND id = 991 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 11 AND id = 992 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 12 AND id = 993 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 13 AND id = 994 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 14 AND id = 995 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 15 AND id = 996 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 16 AND id = 997 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 17 AND id = 998 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 18 AND id = 999 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 19 AND id = 1000 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 20 AND id = 1001 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 21 AND id = 1002 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 22 AND id = 1003 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 23 AND id = 1004 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 24 AND id = 1005 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 25 AND id = 1006 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 26 AND id = 1007 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 27 AND id = 1008 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 28 AND id = 1009 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 29 AND id = 1010 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 30 AND id = 1011 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 31 AND id = 1012 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 32 AND id = 1013 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 33 AND id = 1014 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 34 AND id = 1015 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 35 AND id = 1016 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 36 AND id = 1017 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 37 AND id = 1018 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 38 AND id = 1019 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 39 AND id = 1020 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bothunder' AND version = 0 AND number = 40 AND id = 1021 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bothunder' AND version = 0 AND number = 41 AND id = 1022 AND target_heading = 128; +UPDATE zone_points SET target_heading = 184 WHERE zone = 'bothunder' AND version = 0 AND number = 42 AND id = 1023 AND target_heading = 92; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'povalor' AND version = 0 AND number = 1 AND id = 1024 AND target_heading = 0; +UPDATE zone_points SET target_heading = 306 WHERE zone = 'povalor' AND version = 0 AND number = 5 AND id = 1025 AND target_heading = 153; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'povalor' AND version = 0 AND number = 77 AND id = 1026 AND target_heading = 128; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'codecay' AND version = 0 AND number = 1 AND id = 1027 AND target_heading = 185; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'codecay' AND version = 0 AND number = 2 AND id = 1028 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'hohonora' AND version = 0 AND number = 1 AND id = 1029 AND target_heading = 128; +UPDATE zone_points SET target_heading = 294 WHERE zone = 'hohonora' AND version = 0 AND number = 2 AND id = 1030 AND target_heading = 147; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'hohonorb' AND version = 0 AND number = 1 AND id = 1031 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'poair' AND version = 0 AND number = 1 AND id = 1032 AND target_heading = 128; +UPDATE zone_points SET target_heading = 96 WHERE zone = 'poair' AND version = 0 AND number = 2 AND id = 1033 AND target_heading = 48; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'poair' AND version = 0 AND number = 10 AND id = 1034 AND target_heading = 249; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'podisease' AND version = 0 AND number = 1 AND id = 1035 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'podisease' AND version = 0 AND number = 2 AND id = 1036 AND target_heading = 0; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'poearthb' AND version = 0 AND number = 1 AND id = 1037 AND target_heading = 130; +UPDATE zone_points SET target_heading = 96 WHERE zone = 'poearthb' AND version = 0 AND number = 2 AND id = 1038 AND target_heading = 48; +UPDATE zone_points SET target_heading = 266 WHERE zone = 'poeartha' AND version = 0 AND number = 1 AND id = 1039 AND target_heading = 133; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'poeartha' AND version = 0 AND number = 2 AND id = 1040 AND target_heading = 132; +UPDATE zone_points SET target_heading = 96 WHERE zone = 'poeartha' AND version = 0 AND number = 3 AND id = 1041 AND target_heading = 48; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'poeartha' AND version = 0 AND number = 10 AND id = 1042 AND target_heading = 132; +UPDATE zone_points SET target_heading = 248 WHERE zone = 'poinnovation' AND version = 0 AND number = 1 AND id = 1043 AND target_heading = 124; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'poinnovation' AND version = 0 AND number = 5 AND id = 1044 AND target_heading = 129; +UPDATE zone_points SET target_heading = 8 WHERE zone = 'poinnovation' AND version = 0 AND number = 6 AND id = 1045 AND target_heading = 4; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'poinnovation' AND version = 0 AND number = 7 AND id = 1046 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'poinnovation' AND version = 0 AND number = 50 AND id = 1047 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'poinnovation' AND version = 0 AND number = 60 AND id = 1048 AND target_heading = 0; +UPDATE zone_points SET target_heading = 188 WHERE zone = 'poinnovation' AND version = 0 AND number = 70 AND id = 1049 AND target_heading = 94; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'poinnovation' AND version = 0 AND number = 71 AND id = 1050 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 1 AND id = 1051 AND target_heading = 0; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 2 AND id = 1052 AND target_heading = 254; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 3 AND id = 1053 AND target_heading = 0; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 4 AND id = 1054 AND target_heading = 254; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 5 AND id = 1055 AND target_heading = 0; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 6 AND id = 1056 AND target_heading = 254; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 7 AND id = 1057 AND target_heading = 0; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 8 AND id = 1058 AND target_heading = 254; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 9 AND id = 1059 AND target_heading = 0; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 10 AND id = 1060 AND target_heading = 254; +UPDATE zone_points SET target_heading = 220 WHERE zone = 'pojustice' AND version = 0 AND number = 11 AND id = 1061 AND target_heading = 110; +UPDATE zone_points SET target_heading = 240 WHERE zone = 'pojustice' AND version = 0 AND number = 12 AND id = 1062 AND target_heading = 120; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 13 AND id = 1063 AND target_heading = 254; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 14 AND id = 1064 AND target_heading = 0; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 15 AND id = 1065 AND target_heading = 254; +UPDATE zone_points SET target_heading = 492 WHERE zone = 'pojustice' AND version = 0 AND number = 16 AND id = 1066 AND target_heading = 246; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'pojustice' AND version = 0 AND number = 17 AND id = 1067 AND target_heading = 254; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 18 AND id = 1068 AND target_heading = 0; +UPDATE zone_points SET target_heading = 504 WHERE zone = 'pojustice' AND version = 0 AND number = 19 AND id = 1069 AND target_heading = 252; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'pojustice' AND version = 0 AND number = 20 AND id = 1070 AND target_heading = 255; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 21 AND id = 1071 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 22 AND id = 1072 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 23 AND id = 1073 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'pojustice' AND version = 0 AND number = 24 AND id = 1074 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'pojustice' AND version = 0 AND number = 25 AND id = 1075 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 26 AND id = 1076 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'pojustice' AND version = 0 AND number = 27 AND id = 1077 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'pojustice' AND version = 0 AND number = 28 AND id = 1078 AND target_heading = 0; +UPDATE zone_points SET target_heading = 398 WHERE zone = 'pojustice' AND version = 0 AND number = 29 AND id = 1079 AND target_heading = 199; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'postorms' AND version = 0 AND number = 1 AND id = 1080 AND target_heading = 0; +UPDATE zone_points SET target_heading = 396 WHERE zone = 'postorms' AND version = 0 AND number = 2 AND id = 1081 AND target_heading = 198; +UPDATE zone_points SET target_heading = 184 WHERE zone = 'postorms' AND version = 0 AND number = 3 AND id = 1082 AND target_heading = 92; +UPDATE zone_points SET target_heading = 312 WHERE zone = 'postorms' AND version = 0 AND number = 4 AND id = 1083 AND target_heading = 156; +UPDATE zone_points SET target_heading = 124 WHERE zone = 'potorment' AND version = 0 AND number = 2 AND id = 1084 AND target_heading = 62; +UPDATE zone_points SET target_heading = 496 WHERE zone = 'potorment' AND version = 0 AND number = 13 AND id = 1085 AND target_heading = 248; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND number = 1 AND id = 1086 AND target_heading = 128; +UPDATE zone_points SET target_heading = 90 WHERE zone = 'potranquility' AND version = 0 AND number = 3 AND id = 1087 AND target_heading = 45; +UPDATE zone_points SET target_heading = 488 WHERE zone = 'potranquility' AND version = 0 AND number = 5 AND id = 1088 AND target_heading = 244; +UPDATE zone_points SET target_heading = 40 WHERE zone = 'potranquility' AND version = 0 AND number = 17 AND id = 1089 AND target_heading = 20; +UPDATE zone_points SET target_heading = 496 WHERE zone = 'potranquility' AND version = 0 AND number = 18 AND id = 1090 AND target_heading = 248; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND number = 19 AND id = 1091 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 21 AND id = 1092 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 22 AND id = 1093 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND number = 23 AND id = 1094 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 24 AND id = 1095 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 25 AND id = 1096 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 26 AND id = 1097 AND target_heading = 0; +UPDATE zone_points SET target_heading = 210 WHERE zone = 'potranquility' AND version = 0 AND number = 27 AND id = 1098 AND target_heading = 105; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 28 AND id = 1099 AND target_heading = 0; +UPDATE zone_points SET target_heading = 502 WHERE zone = 'potranquility' AND version = 0 AND number = 29 AND id = 1100 AND target_heading = 251; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 30 AND id = 1101 AND target_heading = 0; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'potranquility' AND version = 0 AND number = 37 AND id = 1102 AND target_heading = 187; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'potranquility' AND version = 0 AND number = 47 AND id = 1103 AND target_heading = 127; +UPDATE zone_points SET target_heading = 10 WHERE zone = 'potranquility' AND version = 0 AND number = 57 AND id = 1104 AND target_heading = 5; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND number = 77 AND id = 1105 AND target_heading = 128; +UPDATE zone_points SET target_heading = 366 WHERE zone = 'powater' AND version = 0 AND number = 1 AND id = 1106 AND target_heading = 183; +UPDATE zone_points SET target_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND number = 1 AND id = 1107 AND target_heading = 251; +UPDATE zone_points SET target_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND number = 15 AND id = 1108 AND target_heading = 251; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'solrotower' AND version = 0 AND number = 16 AND id = 1109 AND target_heading = 126; +UPDATE zone_points SET target_heading = 506 WHERE zone = 'solrotower' AND version = 0 AND number = 17 AND id = 1110 AND target_heading = 253; +UPDATE zone_points SET target_heading = 10 WHERE zone = 'solrotower' AND version = 0 AND number = 18 AND id = 1111 AND target_heading = 5; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'solrotower' AND version = 0 AND number = 19 AND id = 1112 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'solrotower' AND version = 0 AND number = 20 AND id = 1113 AND target_heading = 0; +UPDATE zone_points SET target_heading = 246 WHERE zone = 'solrotower' AND version = 0 AND number = 21 AND id = 1114 AND target_heading = 123; +UPDATE zone_points SET target_heading = 504 WHERE zone = 'solrotower' AND version = 0 AND number = 22 AND id = 1115 AND target_heading = 252; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'solrotower' AND version = 0 AND number = 23 AND id = 1116 AND target_heading = 128; +UPDATE zone_points SET target_heading = 224 WHERE zone = 'solrotower' AND version = 0 AND number = 24 AND id = 1117 AND target_heading = 112; +UPDATE zone_points SET target_heading = 224 WHERE zone = 'solrotower' AND version = 0 AND number = 25 AND id = 1118 AND target_heading = 112; +UPDATE zone_points SET target_heading = 502 WHERE zone = 'solrotower' AND version = 0 AND number = 26 AND id = 1119 AND target_heading = 251; +UPDATE zone_points SET target_heading = -2 WHERE zone = 'potactics' AND version = 0 AND number = 1 AND id = 1120 AND target_heading = -1; +UPDATE zone_points SET target_heading = 4 WHERE zone = 'potactics' AND version = 0 AND number = 2 AND id = 1121 AND target_heading = 2; +UPDATE zone_points SET target_heading = 298 WHERE zone = 'potactics' AND version = 0 AND number = 3 AND id = 1122 AND target_heading = 149; +UPDATE zone_points SET target_heading = 446 WHERE zone = 'potactics' AND version = 0 AND number = 5 AND id = 1123 AND target_heading = 223; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potactics' AND version = 0 AND number = 6 AND id = 1124 AND target_heading = 0; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'potactics' AND version = 0 AND number = 7 AND id = 1125 AND target_heading = 192; +UPDATE zone_points SET target_heading = 20 WHERE zone = 'potactics' AND version = 0 AND number = 8 AND id = 1126 AND target_heading = 10; +UPDATE zone_points SET target_heading = 360 WHERE zone = 'potactics' AND version = 0 AND number = 9 AND id = 1127 AND target_heading = 180; +UPDATE zone_points SET target_heading = 244 WHERE zone = 'potactics' AND version = 0 AND number = 10 AND id = 1128 AND target_heading = 122; +UPDATE zone_points SET target_heading = 410 WHERE zone = 'potactics' AND version = 0 AND number = 11 AND id = 1129 AND target_heading = 205; +UPDATE zone_points SET target_heading = 106 WHERE zone = 'potactics' AND version = 0 AND number = 12 AND id = 1130 AND target_heading = 53; +UPDATE zone_points SET target_heading = 266 WHERE zone = 'potactics' AND version = 0 AND number = 13 AND id = 1131 AND target_heading = 133; +UPDATE zone_points SET target_heading = 242 WHERE zone = 'ponightmare' AND version = 0 AND number = 1 AND id = 1132 AND target_heading = 121; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'ponightmare' AND version = 0 AND number = 10 AND id = 1133 AND target_heading = 126; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'ponightmare' AND version = 0 AND number = 11 AND id = 1134 AND target_heading = 126; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'ponightmare' AND version = 0 AND number = 12 AND id = 1135 AND target_heading = 126; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'ponightmare' AND version = 0 AND number = 13 AND id = 1136 AND target_heading = 125; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'ponightmare' AND version = 0 AND number = 14 AND id = 1137 AND target_heading = 126; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'ponightmare' AND version = 0 AND number = 15 AND id = 1138 AND target_heading = 126; +UPDATE zone_points SET target_heading = 220 WHERE zone = 'ponightmare' AND version = 0 AND number = 16 AND id = 1139 AND target_heading = 110; +UPDATE zone_points SET target_heading = 244 WHERE zone = 'ponightmare' AND version = 0 AND number = 17 AND id = 1140 AND target_heading = 122; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'ponightmare' AND version = 0 AND number = 77 AND id = 1141 AND target_heading = 125; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'kedge' AND version = 0 AND number = 1 AND id = 1142 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'highpass' AND version = 0 AND number = 1 AND id = 1145 AND target_heading = 0; +UPDATE zone_points SET target_heading = 216 WHERE zone = 'highpass' AND version = 0 AND number = 2 AND id = 1146 AND target_heading = 108; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'soldungb' AND version = 0 AND number = 1 AND id = 1147 AND target_heading = 64; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldungb' AND version = 0 AND number = 2 AND id = 1148 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldungb' AND version = 0 AND number = 3 AND id = 1149 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldungb' AND version = 0 AND number = 4 AND id = 1150 AND target_heading = 231; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'soldungb' AND version = 0 AND number = 5 AND id = 1151 AND target_heading = 65; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldungb' AND version = 0 AND number = 6 AND id = 1152 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldungb' AND version = 0 AND number = 7 AND id = 1153 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldungb' AND version = 0 AND number = 8 AND id = 1154 AND target_heading = 231; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'soldungb' AND version = 0 AND number = 9 AND id = 1155 AND target_heading = 130; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'soldungb' AND version = 0 AND number = 10 AND id = 1156 AND target_heading = 231; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'soldungb' AND version = 0 AND number = 11 AND id = 1157 AND target_heading = 64; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'runnyeye' AND version = 0 AND number = 1 AND id = 1158 AND target_heading = 999; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'runnyeye' AND version = 0 AND number = 2 AND id = 1159 AND target_heading = 231; +UPDATE zone_points SET target_heading = 463.2 WHERE zone = 'erudnext' AND version = 0 AND number = 1 AND id = 1160 AND target_heading = 231.6; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'erudnext' AND version = 0 AND number = 2 AND id = 1161 AND target_heading = 128; +UPDATE zone_points SET target_heading = 242 WHERE zone = 'erudnext' AND version = 0 AND number = 3 AND id = 1162 AND target_heading = 121; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 1 AND id = 1163 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 3 AND id = 1164 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 4 AND id = 1165 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 5 AND id = 1166 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 6 AND id = 1167 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 7 AND id = 1168 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 8 AND id = 1169 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 9 AND id = 1170 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 10 AND id = 1171 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 11 AND id = 1172 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'airplane' AND version = 0 AND number = 12 AND id = 1173 AND target_heading = 231; +UPDATE zone_points SET target_heading = 509.8 WHERE zone = 'cazicthule' AND version = 0 AND number = 1 AND id = 1174 AND target_heading = 254.9; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'burningwood' AND version = 0 AND number = 1 AND id = 1175 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'burningwood' AND version = 0 AND number = 2 AND id = 1176 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'burningwood' AND version = 0 AND number = 3 AND id = 1177 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'burningwood' AND version = 0 AND number = 4 AND id = 1178 AND target_heading = 128; +UPDATE zone_points SET target_heading = 312 WHERE zone = 'cabeast' AND version = 0 AND number = 1 AND id = 1179 AND target_heading = 156; +UPDATE zone_points SET target_heading = 38 WHERE zone = 'cabeast' AND version = 0 AND number = 2 AND id = 1180 AND target_heading = 19; +UPDATE zone_points SET target_heading = 190 WHERE zone = 'cabeast' AND version = 0 AND number = 3 AND id = 1181 AND target_heading = 95; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'cabeast' AND version = 0 AND number = 4 AND id = 1182 AND target_heading = 194; +UPDATE zone_points SET target_heading = 8 WHERE zone = 'cabeast' AND version = 0 AND number = 9 AND id = 1183 AND target_heading = 4; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'cabeast' AND version = 0 AND number = 10 AND id = 1184 AND target_heading = 1; +UPDATE zone_points SET target_heading = 126.8 WHERE zone = 'cabeast' AND version = 0 AND number = 80 AND id = 1185 AND target_heading = 63.4; +UPDATE zone_points SET target_heading = 126.8 WHERE zone = 'cabeast' AND version = 0 AND number = 81 AND id = 1186 AND target_heading = 63.4; +UPDATE zone_points SET target_heading = 56 WHERE zone = 'cabwest' AND version = 0 AND number = 5 AND id = 1187 AND target_heading = 28; +UPDATE zone_points SET target_heading = 310 WHERE zone = 'cabwest' AND version = 0 AND number = 6 AND id = 1188 AND target_heading = 155; +UPDATE zone_points SET target_heading = 174 WHERE zone = 'cabwest' AND version = 0 AND number = 7 AND id = 1189 AND target_heading = 87; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'cabwest' AND version = 0 AND number = 8 AND id = 1190 AND target_heading = 220; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'cabwest' AND version = 0 AND number = 81 AND id = 1191 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'charasis' AND version = 0 AND number = 1 AND id = 1192 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'charasis' AND version = 0 AND number = 2 AND id = 1193 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'charasis' AND version = 0 AND number = 3 AND id = 1194 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'charasis' AND version = 0 AND number = 4 AND id = 1195 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'charasis' AND version = 0 AND number = 5 AND id = 1196 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'chardok' AND version = 0 AND number = 1 AND id = 1197 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'chardok' AND version = 0 AND number = 2 AND id = 1198 AND target_heading = 0; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'citymist' AND version = 0 AND number = 1 AND id = 1199 AND target_heading = 192; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'citymist' AND version = 0 AND number = 2 AND id = 1200 AND target_heading = 192; +UPDATE zone_points SET target_heading = 120 WHERE zone = 'dalnir' AND version = 0 AND number = 1 AND id = 1201 AND target_heading = 60; +UPDATE zone_points SET target_heading = 120 WHERE zone = 'dalnir' AND version = 0 AND number = 2 AND id = 1202 AND target_heading = 60; +UPDATE zone_points SET target_heading = 120 WHERE zone = 'dalnir' AND version = 0 AND number = 99 AND id = 1203 AND target_heading = 60; +UPDATE zone_points SET target_heading = 200 WHERE zone = 'dreadlands' AND version = 0 AND number = 1 AND id = 1205 AND target_heading = 100; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'dreadlands' AND version = 0 AND number = 2 AND id = 1206 AND target_heading = 0; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'dreadlands' AND version = 0 AND number = 3 AND id = 1207 AND target_heading = 160; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'dreadlands' AND version = 0 AND number = 4 AND id = 1208 AND target_heading = 194; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'dreadlands' AND version = 0 AND number = 5 AND id = 1209 AND target_heading = 194; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'dreadlands' AND version = 0 AND number = 6 AND id = 1210 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'droga' AND version = 0 AND number = 1 AND id = 1211 AND target_heading = 231; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'droga' AND version = 0 AND number = 5 AND id = 1212 AND target_heading = 132; +UPDATE zone_points SET target_heading = 255 WHERE zone = 'droga' AND version = 0 AND number = 6 AND id = 1213 AND target_heading = 127.5; +UPDATE zone_points SET target_heading = 32 WHERE zone = 'emeraldjungle' AND version = 0 AND number = 1 AND id = 1214 AND target_heading = 16; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'emeraldjungle' AND version = 0 AND number = 2 AND id = 1215 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'emeraldjungle' AND version = 0 AND number = 3 AND id = 1216 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'emeraldjungle' AND version = 0 AND number = 4 AND id = 1217 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'fearplane' AND version = 0 AND number = 1 AND id = 1218 AND target_heading = 231; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'fieldofbone' AND version = 0 AND number = 1 AND id = 1219 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'fieldofbone' AND version = 0 AND number = 2 AND id = 1220 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'fieldofbone' AND version = 0 AND number = 3 AND id = 1221 AND target_heading = 128; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'fieldofbone' AND version = 0 AND number = 4 AND id = 1222 AND target_heading = 64; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'fieldofbone' AND version = 0 AND number = 5 AND id = 1223 AND target_heading = 256; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'fieldofbone' AND version = 0 AND number = 6 AND id = 1224 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'fieldofbone' AND version = 0 AND number = 7 AND id = 1225 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'fieldofbone' AND version = 0 AND number = 8 AND id = 1226 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'fieldofbone' AND version = 0 AND number = 77 AND id = 1227 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'firiona' AND version = 0 AND number = 1 AND id = 1228 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'firiona' AND version = 0 AND number = 2 AND id = 1229 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'firiona' AND version = 0 AND number = 3 AND id = 1230 AND target_heading = 0; +UPDATE zone_points SET target_heading = 93.6 WHERE zone = 'firiona' AND version = 0 AND number = 4 AND id = 1231 AND target_heading = 46.8; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'firiona' AND version = 0 AND number = 77 AND id = 1232 AND target_heading = 127; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'frontiermtns' AND version = 0 AND number = 1 AND id = 1233 AND target_heading = 191; +UPDATE zone_points SET target_heading = 64 WHERE zone = 'frontiermtns' AND version = 0 AND number = 2 AND id = 1234 AND target_heading = 32; +UPDATE zone_points SET target_heading = 284 WHERE zone = 'frontiermtns' AND version = 0 AND number = 3 AND id = 1235 AND target_heading = 142; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'frontiermtns' AND version = 0 AND number = 4 AND id = 1236 AND target_heading = 231; +UPDATE zone_points SET target_heading = 300 WHERE zone = 'frontiermtns' AND version = 0 AND number = 5 AND id = 1237 AND target_heading = 150; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'frontiermtns' AND version = 0 AND number = 7 AND id = 1238 AND target_heading = 0; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'hole' AND version = 0 AND number = 1 AND id = 1239 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'hole' AND version = 0 AND number = 3 AND id = 1240 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'hole' AND version = 0 AND number = 4 AND id = 1241 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'hole' AND version = 0 AND number = 5 AND id = 1242 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'jaggedpine' AND version = 0 AND number = 1 AND id = 1243 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'jaggedpine' AND version = 0 AND number = 2 AND id = 1244 AND target_heading = 128; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'jaggedpine' AND version = 0 AND number = 3 AND id = 1245 AND target_heading = 255; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'kaesora' AND version = 0 AND number = 1 AND id = 1246 AND target_heading = 192; +UPDATE zone_points SET target_heading = 124 WHERE zone = 'karnor' AND version = 0 AND number = 1 AND id = 1247 AND target_heading = 62; +UPDATE zone_points SET target_heading = 124 WHERE zone = 'karnor' AND version = 0 AND number = 2 AND id = 1248 AND target_heading = 62; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'kurn' AND version = 0 AND number = 1 AND id = 1249 AND target_heading = 192; +UPDATE zone_points SET target_heading = 158 WHERE zone = 'kurn' AND version = 0 AND number = 2 AND id = 1250 AND target_heading = 79; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'lakeofillomen' AND version = 0 AND number = 1 AND id = 1252 AND target_heading = 64; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'lakeofillomen' AND version = 0 AND number = 2 AND id = 1253 AND target_heading = 256; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'lakeofillomen' AND version = 0 AND number = 3 AND id = 1254 AND target_heading = 64; +UPDATE zone_points SET target_heading = 372 WHERE zone = 'lakeofillomen' AND version = 0 AND number = 4 AND id = 1255 AND target_heading = 186; +UPDATE zone_points SET target_heading = 194 WHERE zone = 'lakeofillomen' AND version = 0 AND number = 5 AND id = 1256 AND target_heading = 97; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'lakeofillomen' AND version = 0 AND number = 6 AND id = 1257 AND target_heading = 191; +UPDATE zone_points SET target_heading = 8 WHERE zone = 'lakeofillomen' AND version = 0 AND number = 7 AND id = 1258 AND target_heading = 4; +UPDATE zone_points SET target_heading = 263.2 WHERE zone = 'nurga' AND version = 0 AND number = 2 AND id = 1259 AND target_heading = 131.6; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'nurga' AND version = 0 AND number = 5 AND id = 1260 AND target_heading = 231; +UPDATE zone_points SET target_heading = 504.8 WHERE zone = 'nurga' AND version = 0 AND number = 6 AND id = 1261 AND target_heading = 252.4; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'overthere' AND version = 0 AND number = 1 AND id = 1262 AND target_heading = 192; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'overthere' AND version = 0 AND number = 2 AND id = 1263 AND target_heading = 128; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'overthere' AND version = 0 AND number = 3 AND id = 1264 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'overthere' AND version = 0 AND number = 4 AND id = 1265 AND target_heading = 64; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'overthere' AND version = 0 AND number = 5 AND id = 1266 AND target_heading = 231; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'overthere' AND version = 0 AND number = 77 AND id = 1267 AND target_heading = 254; +UPDATE zone_points SET target_heading = 80 WHERE zone = 'paineel' AND version = 0 AND number = 1 AND id = 1268 AND target_heading = 40; +UPDATE zone_points SET target_heading = 454 WHERE zone = 'paineel' AND version = 0 AND number = 2 AND id = 1269 AND target_heading = 227; +UPDATE zone_points SET target_heading = 386 WHERE zone = 'paineel' AND version = 0 AND number = 3 AND id = 1270 AND target_heading = 193; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'paineel' AND version = 0 AND number = 4 AND id = 1271 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'paineel' AND version = 0 AND number = 5 AND id = 1272 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'paineel' AND version = 0 AND number = 10 AND id = 1273 AND target_heading = 128; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'paineel' AND version = 0 AND number = 11 AND id = 1274 AND target_heading = 195; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'paineel' AND version = 0 AND number = 12 AND id = 1275 AND target_heading = 128; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'paineel' AND version = 0 AND number = 13 AND id = 1276 AND target_heading = 256; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'paineel' AND version = 0 AND number = 14 AND id = 1277 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'sebilis' AND version = 0 AND number = 1 AND id = 1279 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'sebilis' AND version = 0 AND number = 2 AND id = 1280 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'skyfire' AND version = 0 AND number = 1 AND id = 1281 AND target_heading = 128; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'skyfire' AND version = 0 AND number = 2 AND id = 1282 AND target_heading = 192; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'skyfire' AND version = 0 AND number = 3 AND id = 1283 AND target_heading = 192; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyfire' AND version = 0 AND number = 5 AND id = 1284 AND target_heading = 231; +UPDATE zone_points SET target_heading = 378 WHERE zone = 'stonebrunt' AND version = 0 AND number = 1 AND id = 1285 AND target_heading = 189; +UPDATE zone_points SET target_heading = 124 WHERE zone = 'stonebrunt' AND version = 0 AND number = 5 AND id = 1286 AND target_heading = 62; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'swampofnohope' AND version = 0 AND number = 2 AND id = 1287 AND target_heading = 130; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'swampofnohope' AND version = 0 AND number = 3 AND id = 1288 AND target_heading = 130; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'swampofnohope' AND version = 0 AND number = 4 AND id = 1289 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'swampofnohope' AND version = 0 AND number = 5 AND id = 1290 AND target_heading = 0; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'swampofnohope' AND version = 0 AND number = 6 AND id = 1291 AND target_heading = 65; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'swampofnohope' AND version = 0 AND number = 7 AND id = 1292 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 1 AND id = 1293 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 2 AND id = 1294 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 3 AND id = 1295 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 4 AND id = 1296 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 5 AND id = 1297 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 6 AND id = 1298 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 7 AND id = 1299 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 8 AND id = 1300 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 9 AND id = 1301 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 10 AND id = 1302 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 11 AND id = 1303 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'timorous' AND version = 0 AND number = 12 AND id = 1304 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'trakanon' AND version = 0 AND number = 1 AND id = 1305 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'trakanon' AND version = 0 AND number = 2 AND id = 1306 AND target_heading = 0; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'trakanon' AND version = 0 AND number = 3 AND id = 1307 AND target_heading = 1; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND number = 1 AND id = 1308 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'veeshan' AND version = 0 AND number = 2 AND id = 1309 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND number = 3 AND id = 1310 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'veeshan' AND version = 0 AND number = 4 AND id = 1311 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'veksar' AND version = 0 AND number = 1 AND id = 1312 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'veksar' AND version = 0 AND number = 2 AND id = 1313 AND target_heading = 128; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'warrens' AND version = 0 AND number = 2 AND id = 1314 AND target_heading = 65; +UPDATE zone_points SET target_heading = 106 WHERE zone = 'warrens' AND version = 0 AND number = 3 AND id = 1315 AND target_heading = 53; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'warslikswood' AND version = 0 AND number = 1 AND id = 1316 AND target_heading = 256; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'warslikswood' AND version = 0 AND number = 2 AND id = 1317 AND target_heading = 64; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'warslikswood' AND version = 0 AND number = 3 AND id = 1318 AND target_heading = 130; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'warslikswood' AND version = 0 AND number = 4 AND id = 1319 AND target_heading = 195; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'warslikswood' AND version = 0 AND number = 5 AND id = 1320 AND target_heading = 231; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'warslikswood' AND version = 0 AND number = 6 AND id = 1321 AND target_heading = 160; +UPDATE zone_points SET target_heading = 390 WHERE zone = 'ssratemple' AND version = 0 AND number = 1 AND id = 1322 AND target_heading = 195; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'ssratemple' AND version = 0 AND number = 2 AND id = 1323 AND target_heading = 192; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'ssratemple' AND version = 0 AND number = 7 AND id = 1324 AND target_heading = 126; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'ssratemple' AND version = 0 AND number = 78 AND id = 1325 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'twilight' AND version = 0 AND number = 4 AND id = 1326 AND target_heading = 128; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'erudnext' AND version = 0 AND number = 4 AND id = 1327 AND target_heading = 192; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'highpass' AND version = 0 AND number = 3 AND id = 1328 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'highpass' AND version = 0 AND number = 4 AND id = 1329 AND target_heading = 0; +UPDATE zone_points SET target_heading = 9 WHERE zone = 'akheva' AND version = 0 AND number = 1 AND id = 1330 AND target_heading = 4.5; +UPDATE zone_points SET target_heading = 7.6 WHERE zone = 'akheva' AND version = 0 AND number = 2 AND id = 1331 AND target_heading = 3.8; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'gunthak' AND version = 0 AND number = 5 AND id = 1333 AND target_heading = 128; +UPDATE zone_points SET target_heading = 96 WHERE zone = 'potranquility' AND version = 0 AND number = 2 AND id = 1334 AND target_heading = 48; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'potranquility' AND version = 0 AND number = 10 AND id = 1335 AND target_heading = 249; +UPDATE zone_points SET target_heading = 394 WHERE zone = 'potranquility' AND version = 0 AND number = 4 AND id = 1336 AND target_heading = 197; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'potranquility' AND version = 0 AND number = 6 AND id = 1337 AND target_heading = 119; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'potranquility' AND version = 0 AND number = 7 AND id = 1338 AND target_heading = 132; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potranquility' AND version = 0 AND number = 8 AND id = 1339 AND target_heading = 0; +UPDATE zone_points SET target_heading = 472 WHERE zone = 'potranquility' AND version = 0 AND number = 9 AND id = 1340 AND target_heading = 236; +UPDATE zone_points SET target_heading = 262 WHERE zone = 'potranquility' AND version = 0 AND number = 11 AND id = 1341 AND target_heading = 131; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potranquility' AND version = 0 AND number = 12 AND id = 1342 AND target_heading = 128; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'potranquility' AND version = 0 AND number = 13 AND id = 1343 AND target_heading = 255; +UPDATE zone_points SET target_heading = 496 WHERE zone = 'potranquility' AND version = 0 AND number = 14 AND id = 1344 AND target_heading = 248; +UPDATE zone_points SET target_heading = 6 WHERE zone = 'potranquility' AND version = 0 AND number = 15 AND id = 1345 AND target_heading = 3; +UPDATE zone_points SET target_heading = 432 WHERE zone = 'potranquility' AND version = 0 AND number = 16 AND id = 1346 AND target_heading = 216; +UPDATE zone_points SET target_heading = 232 WHERE zone = 'potranquility' AND version = 0 AND number = 20 AND id = 1347 AND target_heading = 116; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'pofire' AND version = 0 AND number = 1 AND id = 1348 AND target_heading = 128; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'potimea' AND version = 0 AND number = 3 AND id = 1349 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potimea' AND version = 0 AND number = 5 AND id = 1350 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potimea' AND version = 0 AND number = 6 AND id = 1351 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potimea' AND version = 0 AND number = 7 AND id = 1352 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potimea' AND version = 0 AND number = 8 AND id = 1353 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potimea' AND version = 0 AND number = 9 AND id = 1354 AND target_heading = 128; +UPDATE zone_points SET target_heading = 96 WHERE zone = 'potimea' AND version = 0 AND number = 10 AND id = 1355 AND target_heading = 48; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'potimeb' AND version = 0 AND number = 3 AND id = 1356 AND target_heading = 231; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potimeb' AND version = 0 AND number = 5 AND id = 1357 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'potimeb' AND version = 0 AND number = 6 AND id = 1358 AND target_heading = 128; +UPDATE zone_points SET target_heading = 184 WHERE zone = 'potimeb' AND version = 0 AND number = 7 AND id = 1359 AND target_heading = 92; +UPDATE zone_points SET target_heading = 96 WHERE zone = 'potimeb' AND version = 0 AND number = 10 AND id = 1360 AND target_heading = 48; +UPDATE zone_points SET target_heading = 10 WHERE zone = 'potimeb' AND version = 0 AND number = 20 AND id = 1361 AND target_heading = 5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potimeb' AND version = 0 AND number = 21 AND id = 1362 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potimeb' AND version = 0 AND number = 22 AND id = 1363 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potimeb' AND version = 0 AND number = 23 AND id = 1364 AND target_heading = 0; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'potimeb' AND version = 0 AND number = 24 AND id = 1365 AND target_heading = 1; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'potimeb' AND version = 0 AND number = 25 AND id = 1366 AND target_heading = 0; +UPDATE zone_points SET target_heading = 90 WHERE zone = 'abysmal' AND version = 0 AND number = 1 AND id = 1367 AND target_heading = 45; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'barindu' AND version = 0 AND number = 1 AND id = 1368 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'barindu' AND version = 0 AND number = 2 AND id = 1369 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'barindu' AND version = 0 AND number = 3 AND id = 1370 AND target_heading = 64; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'barindu' AND version = 0 AND number = 4 AND id = 1371 AND target_heading = 160; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'barindu' AND version = 0 AND number = 5 AND id = 1372 AND target_heading = 160; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'ferubi' AND version = 0 AND number = 1 AND id = 1373 AND target_heading = 250; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'ferubi' AND version = 0 AND number = 2 AND id = 1374 AND target_heading = 192; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'ferubi' AND version = 0 AND number = 3 AND id = 1375 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'kodtaz' AND version = 0 AND number = 1 AND id = 1376 AND target_heading = 128; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'kodtaz' AND version = 0 AND number = 2 AND id = 1377 AND target_heading = 64; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'kodtaz' AND version = 0 AND number = 3 AND id = 1378 AND target_heading = 64; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'qinimi' AND version = 0 AND number = 1 AND id = 1379 AND target_heading = 192; +UPDATE zone_points SET target_heading = 380 WHERE zone = 'qinimi' AND version = 0 AND number = 2 AND id = 1380 AND target_heading = 190; +UPDATE zone_points SET target_heading = 422 WHERE zone = 'qinimi' AND version = 0 AND number = 3 AND id = 1381 AND target_heading = 211; +UPDATE zone_points SET target_heading = 422 WHERE zone = 'qinimi' AND version = 0 AND number = 4 AND id = 1382 AND target_heading = 211; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'qinimi' AND version = 0 AND number = 5 AND id = 1383 AND target_heading = 192; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'qinimi' AND version = 0 AND number = 6 AND id = 1384 AND target_heading = 192; +UPDATE zone_points SET target_heading = 6 WHERE zone = 'qinimi' AND version = 0 AND number = 7 AND id = 1385 AND target_heading = 3; +UPDATE zone_points SET target_heading = 249.34 WHERE zone = 'qinimi' AND version = 0 AND number = 8 AND id = 1386 AND target_heading = 124.67; +UPDATE zone_points SET target_heading = 236.62 WHERE zone = 'qinimi' AND version = 0 AND number = 9 AND id = 1387 AND target_heading = 118.31; +UPDATE zone_points SET target_heading = 248.64 WHERE zone = 'qinimi' AND version = 0 AND number = 10 AND id = 1388 AND target_heading = 124.32; +UPDATE zone_points SET target_heading = 90 WHERE zone = 'qinimi' AND version = 0 AND number = 11 AND id = 1389 AND target_heading = 45; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'qvic' AND version = 0 AND number = 1 AND id = 1390 AND target_heading = 192; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'qvic' AND version = 0 AND number = 2 AND id = 1391 AND target_heading = 192; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'qvic' AND version = 0 AND number = 3 AND id = 1392 AND target_heading = 128; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'riwwi' AND version = 0 AND number = 1 AND id = 1393 AND target_heading = 132; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'riwwi' AND version = 0 AND number = 2 AND id = 1394 AND target_heading = 167; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'riwwi' AND version = 0 AND number = 3 AND id = 1395 AND target_heading = 167; +UPDATE zone_points SET target_heading = 422 WHERE zone = 'riwwi' AND version = 0 AND number = 4 AND id = 1396 AND target_heading = 211; +UPDATE zone_points SET target_heading = 422 WHERE zone = 'riwwi' AND version = 0 AND number = 5 AND id = 1397 AND target_heading = 211; +UPDATE zone_points SET target_heading = 480 WHERE zone = 'tipt' AND version = 0 AND number = 1 AND id = 1398 AND target_heading = 240; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'txevu' AND version = 0 AND number = 1 AND id = 1399 AND target_heading = 192; +UPDATE zone_points SET target_heading = 480 WHERE zone = 'vxed' AND version = 0 AND number = 1 AND id = 1400 AND target_heading = 240; +UPDATE zone_points SET target_heading = 208 WHERE zone = 'anguish' AND version = 0 AND number = 10 AND id = 1401 AND target_heading = 104; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'bloodfields' AND version = 0 AND number = 10 AND id = 1402 AND target_heading = 270; +UPDATE zone_points SET target_heading = 168 WHERE zone = 'bloodfields' AND version = 0 AND number = 20 AND id = 1403 AND target_heading = 84; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'bloodfields' AND version = 0 AND number = 30 AND id = 1404 AND target_heading = 256; +UPDATE zone_points SET target_heading = 254.8 WHERE zone = 'causeway' AND version = 0 AND number = 10 AND id = 1405 AND target_heading = 127.4; +UPDATE zone_points SET target_heading = 60 WHERE zone = 'causeway' AND version = 0 AND number = 20 AND id = 1406 AND target_heading = 30; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'provinggrounds' AND version = 0 AND number = 10 AND id = 1407 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'provinggrounds' AND version = 0 AND number = 11 AND id = 1408 AND target_heading = 0; +UPDATE zone_points SET target_heading = 794 WHERE zone = 'dranik' AND version = 0 AND number = 10 AND id = 1409 AND target_heading = 397; +UPDATE zone_points SET target_heading = 394 WHERE zone = 'dranik' AND version = 0 AND number = 20 AND id = 1410 AND target_heading = 197; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'draniksscar' AND version = 0 AND number = 10 AND id = 1411 AND target_heading = 128; +UPDATE zone_points SET target_heading = 414 WHERE zone = 'draniksscar' AND version = 0 AND number = 20 AND id = 1412 AND target_heading = 207; +UPDATE zone_points SET target_heading = 482 WHERE zone = 'draniksscar' AND version = 0 AND number = 30 AND id = 1413 AND target_heading = 241; +UPDATE zone_points SET target_heading = 68 WHERE zone = 'harbingers' AND version = 0 AND number = 30 AND id = 1414 AND target_heading = 34; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'riftseekers' AND version = 0 AND number = 10 AND id = 1415 AND target_heading = 128; +UPDATE zone_points SET target_heading = 270 WHERE zone = 'wallofslaughter' AND version = 0 AND number = 20 AND id = 1416 AND target_heading = 135; +UPDATE zone_points SET target_heading = 332 WHERE zone = 'wallofslaughter' AND version = 0 AND number = 50 AND id = 1417 AND target_heading = 166; +UPDATE zone_points SET target_heading = 492 WHERE zone = 'broodlands' AND version = 0 AND number = 30 AND id = 1418 AND target_heading = 246; +UPDATE zone_points SET target_heading = 194 WHERE zone = 'broodlands' AND version = 0 AND number = 40 AND id = 1419 AND target_heading = 97; +UPDATE zone_points SET target_heading = 448 WHERE zone = 'broodlands' AND version = 0 AND number = 50 AND id = 1420 AND target_heading = 224; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'broodlands' AND version = 0 AND number = 60 AND id = 1421 AND target_heading = 0; +UPDATE zone_points SET target_heading = 106 WHERE zone = 'broodlands' AND version = 0 AND number = 501 AND id = 1422 AND target_heading = 53; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'broodlands' AND version = 0 AND number = 571 AND id = 1423 AND target_heading = 0; +UPDATE zone_points SET target_heading = 496 WHERE zone = 'delvea' AND version = 0 AND number = 10 AND id = 1424 AND target_heading = 248; +UPDATE zone_points SET target_heading = 104 WHERE zone = 'delvea' AND version = 0 AND number = 20 AND id = 1425 AND target_heading = 52; +UPDATE zone_points SET target_heading = 94 WHERE zone = 'delvea' AND version = 0 AND number = 40 AND id = 1426 AND target_heading = 47; +UPDATE zone_points SET target_heading = 386 WHERE zone = 'delvea' AND version = 0 AND number = 50 AND id = 1427 AND target_heading = 193; +UPDATE zone_points SET target_heading = 174 WHERE zone = 'delveb' AND version = 0 AND number = 40 AND id = 1428 AND target_heading = 87; +UPDATE zone_points SET target_heading = 380 WHERE zone = 'delveb' AND version = 0 AND number = 50 AND id = 1429 AND target_heading = 190; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'guildlobby' AND version = 0 AND number = 20 AND id = 1430 AND target_heading = 225; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'stillmoona' AND version = 0 AND number = 10 AND id = 1431 AND target_heading = 1; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'stillmoona' AND version = 0 AND number = 50 AND id = 1432 AND target_heading = 0; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'stillmoonb' AND version = 0 AND number = 10 AND id = 1433 AND target_heading = 1; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'stillmoonb' AND version = 0 AND number = 20 AND id = 1434 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'stillmoonb' AND version = 0 AND number = 30 AND id = 1435 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bazaar' AND version = 0 AND number = 20 AND id = 1436 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bazaar' AND version = 0 AND number = 30 AND id = 1437 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'bazaar' AND version = 0 AND number = 40 AND id = 1438 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bazaar' AND version = 0 AND number = 570 AND id = 1439 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bazaar' AND version = 0 AND number = 580 AND id = 1440 AND target_heading = 0; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'bazaar' AND version = 0 AND number = 590 AND id = 1441 AND target_heading = 191; +UPDATE zone_points SET target_heading = 132 WHERE zone = 'bazaar' AND version = 0 AND number = 610 AND id = 1442 AND target_heading = 66; +UPDATE zone_points SET target_heading = 136 WHERE zone = 'bazaar' AND version = 0 AND number = 1150 AND id = 1443 AND target_heading = 68; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'nektulos' AND version = 0 AND number = 1 AND id = 1444 AND target_heading = 130; +UPDATE zone_points SET target_heading = 220 WHERE zone = 'nektulos' AND version = 0 AND number = 2 AND id = 1445 AND target_heading = 110; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nektulos' AND version = 0 AND number = 3 AND id = 1446 AND target_heading = 0; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'nektulos' AND version = 0 AND number = 77 AND id = 1447 AND target_heading = 1; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'poknowledge' AND version = 0 AND number = 30 AND id = 1448 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bazaar' AND version = 0 AND number = 1 AND id = 1450 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bazaar' AND version = 0 AND number = 2 AND id = 1451 AND target_heading = 0; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'bazaar' AND version = 0 AND number = 3 AND id = 1452 AND target_heading = 191; +UPDATE zone_points SET target_heading = 132 WHERE zone = 'bazaar' AND version = 0 AND number = 4 AND id = 1453 AND target_heading = 66; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'templeveeshan' AND version = 0 AND number = 1 AND id = 1454 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'templeveeshan' AND version = 0 AND number = 2 AND id = 1455 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'templeveeshan' AND version = 0 AND number = 3 AND id = 1456 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'templeveeshan' AND version = 0 AND number = 12 AND id = 1457 AND target_heading = 0; +UPDATE zone_points SET target_heading = 339 WHERE zone = 'corathus' AND version = 0 AND number = 1 AND id = 1458 AND target_heading = 169.5; +UPDATE zone_points SET target_heading = 120 WHERE zone = 'natimbi' AND version = 0 AND number = 1 AND id = 1460 AND target_heading = 60; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'snplant' AND version = 0 AND number = 1 AND id = 1461 AND target_heading = 249; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'mistythicket' AND version = 0 AND number = 10 AND id = 1462 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'mistythicket' AND version = 0 AND number = 30 AND id = 1463 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1022 WHERE zone = 'mistythicket' AND version = 0 AND number = 50 AND id = 1464 AND target_heading = 511; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'sncrematory' AND version = 0 AND number = 1 AND id = 1465 AND target_heading = 249; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'snlair' AND version = 0 AND number = 1 AND id = 1471 AND target_heading = 249; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'snpool' AND version = 0 AND number = 1 AND id = 1472 AND target_heading = 249; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'yxtta' AND version = 0 AND number = 1 AND id = 1473 AND target_heading = 64; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'yxtta' AND version = 0 AND number = 2 AND id = 1474 AND target_heading = 192; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'yxtta' AND version = 0 AND number = 3 AND id = 1475 AND target_heading = 64; +UPDATE zone_points SET target_heading = 1012 WHERE zone = 'nektulos' AND version = 1 AND number = 10 AND id = 1476 AND target_heading = 506; +UPDATE zone_points SET target_heading = 290 WHERE zone = 'nektulos' AND version = 1 AND number = 20 AND id = 1477 AND target_heading = 145; +UPDATE zone_points SET target_heading = 174 WHERE zone = 'nektulos' AND version = 1 AND number = 30 AND id = 1478 AND target_heading = 87; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'nektulos' AND version = 1 AND number = 50 AND id = 1479 AND target_heading = 128; +UPDATE zone_points SET target_heading = 514 WHERE zone = 'nektulos' AND version = 1 AND number = 77 AND id = 1480 AND target_heading = 257; +UPDATE zone_points SET target_heading = 112 WHERE zone = 'drachnidhive' AND version = 0 AND number = 10 AND id = 1481 AND target_heading = 56; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'drachnidhive' AND version = 0 AND number = 30 AND id = 1482 AND target_heading = 999; +UPDATE zone_points SET target_heading = 714 WHERE zone = 'drachnidhive' AND version = 0 AND number = 40 AND id = 1483 AND target_heading = 357; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'dreadspire' AND version = 0 AND number = 30 AND id = 1484 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'dreadspire' AND version = 0 AND number = 40 AND id = 1485 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'dreadspire' AND version = 0 AND number = 50 AND id = 1486 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'dreadspire' AND version = 0 AND number = 60 AND id = 1487 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'dreadspire' AND version = 0 AND number = 70 AND id = 1488 AND target_heading = 999; +UPDATE zone_points SET target_heading = 20 WHERE zone = 'dreadspire' AND version = 0 AND number = 80 AND id = 1489 AND target_heading = 10; +UPDATE zone_points SET target_heading = 492 WHERE zone = 'westkorlach' AND version = 0 AND number = 10 AND id = 1490 AND target_heading = 246; +UPDATE zone_points SET target_heading = 790 WHERE zone = 'westkorlach' AND version = 0 AND number = 20 AND id = 1491 AND target_heading = 395; +UPDATE zone_points SET target_heading = 268 WHERE zone = 'westkorlach' AND version = 0 AND number = 40 AND id = 1492 AND target_heading = 134; +UPDATE zone_points SET target_heading = 652 WHERE zone = 'eastkorlach' AND version = 0 AND number = 10 AND id = 1493 AND target_heading = 326; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'eastkorlach' AND version = 0 AND number = 20 AND id = 1494 AND target_heading = 254; +UPDATE zone_points SET target_heading = 552 WHERE zone = 'eastkorlach' AND version = 0 AND number = 30 AND id = 1495 AND target_heading = 276; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'eastkorlach' AND version = 0 AND number = 40 AND id = 1496 AND target_heading = 130; +UPDATE zone_points SET target_heading = 728 WHERE zone = 'eastkorlach' AND version = 0 AND number = 50 AND id = 1497 AND target_heading = 364; +UPDATE zone_points SET target_heading = 42 WHERE zone = 'illsalin' AND version = 0 AND number = 0 AND id = 1498 AND target_heading = 21; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'corathus' AND version = 0 AND number = 10 AND id = 1499 AND target_heading = 132; +UPDATE zone_points SET target_heading = 270 WHERE zone = 'corathus' AND version = 0 AND number = 20 AND id = 1500 AND target_heading = 135; +UPDATE zone_points SET target_heading = 884 WHERE zone = 'corathus' AND version = 0 AND number = 30 AND id = 1501 AND target_heading = 442; +UPDATE zone_points SET target_heading = 378 WHERE zone = 'arcstone' AND version = 0 AND number = 5 AND id = 1502 AND target_heading = 189; +UPDATE zone_points SET target_heading = 378 WHERE zone = 'arcstone' AND version = 0 AND number = 15 AND id = 1503 AND target_heading = 189; +UPDATE zone_points SET target_heading = 378 WHERE zone = 'arcstone' AND version = 0 AND number = 30 AND id = 1504 AND target_heading = 189; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'devastation' AND version = 0 AND number = 0 AND id = 1505 AND target_heading = 255; +UPDATE zone_points SET target_heading = 292 WHERE zone = 'elddar' AND version = 0 AND number = 9 AND id = 1506 AND target_heading = 146; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'freeporteast' AND version = 0 AND number = 10 AND id = 1507 AND target_heading = 999; +UPDATE zone_points SET target_heading = 40 WHERE zone = 'freeporteast' AND version = 0 AND number = 20 AND id = 1508 AND target_heading = 20; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'freeporteast' AND version = 0 AND number = 30 AND id = 1509 AND target_heading = 64; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'freeporteast' AND version = 0 AND number = 40 AND id = 1510 AND target_heading = 128; +UPDATE zone_points SET target_heading = 124 WHERE zone = 'freeporteast' AND version = 0 AND number = 50 AND id = 1511 AND target_heading = 62; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'freeporteast' AND version = 0 AND number = 60 AND id = 1512 AND target_heading = 999; +UPDATE zone_points SET target_heading = 490 WHERE zone = 'freeportsewers' AND version = 0 AND number = 10 AND id = 1513 AND target_heading = 245; +UPDATE zone_points SET target_heading = 748 WHERE zone = 'freeportsewers' AND version = 0 AND number = 20 AND id = 1514 AND target_heading = 374; +UPDATE zone_points SET target_heading = 516 WHERE zone = 'freeportsewers' AND version = 0 AND number = 30 AND id = 1515 AND target_heading = 258; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'freeportsewers' AND version = 0 AND number = 50 AND id = 1516 AND target_heading = 999; +UPDATE zone_points SET target_heading = 804 WHERE zone = 'freeportsewers' AND version = 0 AND number = 60 AND id = 1517 AND target_heading = 402; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'northro' AND version = 0 AND number = 20 AND id = 1518 AND target_heading = 0; +UPDATE zone_points SET target_heading = 28 WHERE zone = 'northro' AND version = 0 AND number = 40 AND id = 1519 AND target_heading = 14; +UPDATE zone_points SET target_heading = 190 WHERE zone = 'northro' AND version = 0 AND number = 50 AND id = 1520 AND target_heading = 95; +UPDATE zone_points SET target_heading = 322 WHERE zone = 'northro' AND version = 0 AND number = 60 AND id = 1521 AND target_heading = 161; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'northro' AND version = 0 AND number = 70 AND id = 1522 AND target_heading = 126; +UPDATE zone_points SET target_heading = 226 WHERE zone = 'northro' AND version = 0 AND number = 90 AND id = 1523 AND target_heading = 113; +UPDATE zone_points SET target_heading = 270 WHERE zone = 'northro' AND version = 0 AND number = 100 AND id = 1524 AND target_heading = 135; +UPDATE zone_points SET target_heading = 244 WHERE zone = 'rage' AND version = 0 AND number = 0 AND id = 1525 AND target_heading = 122; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'relic' AND version = 0 AND number = 10 AND id = 1526 AND target_heading = 35; +UPDATE zone_points SET target_heading = 104 WHERE zone = 'relic' AND version = 0 AND number = 20 AND id = 1527 AND target_heading = 52; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'relic' AND version = 0 AND number = 30 AND id = 1528 AND target_heading = 160; +UPDATE zone_points SET target_heading = 378 WHERE zone = 'relic' AND version = 0 AND number = 50 AND id = 1529 AND target_heading = 189; +UPDATE zone_points SET target_heading = 454 WHERE zone = 'relic' AND version = 0 AND number = 75 AND id = 1530 AND target_heading = 227; +UPDATE zone_points SET target_heading = 210 WHERE zone = 'southro' AND version = 0 AND number = 10 AND id = 1531 AND target_heading = 105; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'southro' AND version = 0 AND number = 20 AND id = 1532 AND target_heading = 250; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'southro' AND version = 0 AND number = 30 AND id = 1533 AND target_heading = 999; +UPDATE zone_points SET target_heading = 416 WHERE zone = 'southro' AND version = 0 AND number = 50 AND id = 1534 AND target_heading = 208; +UPDATE zone_points SET target_heading = 420 WHERE zone = 'southro' AND version = 0 AND number = 60 AND id = 1535 AND target_heading = 210; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'southro' AND version = 0 AND number = 80 AND id = 1536 AND target_heading = 250; +UPDATE zone_points SET target_heading = 328 WHERE zone = 'southro' AND version = 0 AND number = 100 AND id = 1537 AND target_heading = 164; +UPDATE zone_points SET target_heading = 44 WHERE zone = 'takishruins' AND version = 0 AND number = 9 AND id = 1538 AND target_heading = 22; +UPDATE zone_points SET target_heading = 774 WHERE zone = 'takishruins' AND version = 0 AND number = 9 AND id = 1539 AND target_heading = 387; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'freeportwest' AND version = 0 AND number = 0 AND id = 1540 AND target_heading = 130; +UPDATE zone_points SET target_heading = 322 WHERE zone = 'freeportwest' AND version = 0 AND number = 10 AND id = 1541 AND target_heading = 161; +UPDATE zone_points SET target_heading = 308 WHERE zone = 'freeportwest' AND version = 0 AND number = 30 AND id = 1542 AND target_heading = 154; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'freeportwest' AND version = 0 AND number = 40 AND id = 1543 AND target_heading = 194; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'freeportwest' AND version = 0 AND number = 50 AND id = 1544 AND target_heading = 64; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'freeportwest' AND version = 0 AND number = 60 AND id = 1545 AND target_heading = 255; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'freeportwest' AND version = 0 AND number = 80 AND id = 1546 AND target_heading = 254; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'freeportwest' AND version = 0 AND number = 90 AND id = 1547 AND target_heading = 384; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'freeportwest' AND version = 0 AND number = 104 AND id = 1548 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'freeportwest' AND version = 0 AND number = 105 AND id = 1549 AND target_heading = 0; +UPDATE zone_points SET target_heading = 1999998 WHERE zone = 'freeportwest' AND version = 0 AND number = 106 AND id = 1550 AND target_heading = 999999; +UPDATE zone_points SET target_heading = 1999998 WHERE zone = 'freeportwest' AND version = 0 AND number = 107 AND id = 1551 AND target_heading = 999999; +UPDATE zone_points SET target_heading = 344 WHERE zone = 'skylance' AND version = 0 AND number = 10 AND id = 1552 AND target_heading = 172; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'skylance' AND version = 0 AND number = 20 AND id = 1553 AND target_heading = 106; +UPDATE zone_points SET target_heading = 6 WHERE zone = 'skylance' AND version = 0 AND number = 30 AND id = 1554 AND target_heading = 3; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skylance' AND version = 0 AND number = 40 AND id = 1555 AND target_heading = 0; +UPDATE zone_points SET target_heading = 1020 WHERE zone = 'skylance' AND version = 0 AND number = 50 AND id = 1556 AND target_heading = 510; +UPDATE zone_points SET target_heading = 624 WHERE zone = 'skylance' AND version = 0 AND number = 60 AND id = 1557 AND target_heading = 312; +UPDATE zone_points SET target_heading = 528 WHERE zone = 'skylance' AND version = 0 AND number = 70 AND id = 1558 AND target_heading = 264; +UPDATE zone_points SET target_heading = 1012 WHERE zone = 'skylance' AND version = 0 AND number = 80 AND id = 1559 AND target_heading = 506; +UPDATE zone_points SET target_heading = 770 WHERE zone = 'skylance' AND version = 0 AND number = 90 AND id = 1560 AND target_heading = 385; +UPDATE zone_points SET target_heading = 494 WHERE zone = 'moors' AND version = 0 AND number = 10 AND id = 1567 AND target_heading = 247; +UPDATE zone_points SET target_heading = 376 WHERE zone = 'moors' AND version = 0 AND number = 20 AND id = 1568 AND target_heading = 188; +UPDATE zone_points SET target_heading = 410 WHERE zone = 'moors' AND version = 0 AND number = 30 AND id = 1569 AND target_heading = 205; +UPDATE zone_points SET target_heading = 1002 WHERE zone = 'moors' AND version = 0 AND number = 40 AND id = 1570 AND target_heading = 501; +UPDATE zone_points SET target_heading = 988 WHERE zone = 'moors' AND version = 0 AND number = 40 AND id = 1571 AND target_heading = 494; +UPDATE zone_points SET target_heading = 1999998 WHERE zone = 'moors' AND version = 0 AND number = 48 AND id = 1572 AND target_heading = 999999; +UPDATE zone_points SET target_heading = 1010 WHERE zone = 'crescent' AND version = 0 AND number = 10 AND id = 1573 AND target_heading = 505; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'commonlands' AND version = 0 AND number = 10 AND id = 1574 AND target_heading = 130; +UPDATE zone_points SET target_heading = 470 WHERE zone = 'commonlands' AND version = 0 AND number = 20 AND id = 1575 AND target_heading = 235; +UPDATE zone_points SET target_heading = 328 WHERE zone = 'commonlands' AND version = 0 AND number = 30 AND id = 1576 AND target_heading = 164; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'commonlands' AND version = 0 AND number = 40 AND id = 1577 AND target_heading = 194; +UPDATE zone_points SET target_heading = 388 WHERE zone = 'commonlands' AND version = 0 AND number = 50 AND id = 1578 AND target_heading = 194; +UPDATE zone_points SET target_heading = 244 WHERE zone = 'frostcrypt' AND version = 0 AND number = 0 AND id = 1579 AND target_heading = 122; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'highpasshold' AND version = 0 AND number = 100 AND id = 1580 AND target_heading = 119; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'highpasshold' AND version = 0 AND number = 200 AND id = 1581 AND target_heading = 999; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'highpasshold' AND version = 0 AND number = 300 AND id = 1582 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'highpasshold' AND version = 0 AND number = 400 AND id = 1583 AND target_heading = 0; +UPDATE zone_points SET target_heading = 236 WHERE zone = 'highpasshold' AND version = 0 AND number = 500 AND id = 1584 AND target_heading = 118; +UPDATE zone_points SET target_heading = 493.6 WHERE zone = 'ecommons' AND version = 0 AND number = 4 AND id = 1585 AND target_heading = 246.8; +UPDATE zone_points SET target_heading = 143 WHERE zone = 'neriaka' AND version = 0 AND number = 3 AND id = 1586 AND target_heading = 71.5; +UPDATE zone_points SET target_heading = 437.6 WHERE zone = 'poknowledge' AND version = 0 AND number = 17 AND id = 1587 AND target_heading = 218.8; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'lavastorm' AND version = 0 AND number = 0 AND id = 1588 AND target_heading = 128; +UPDATE zone_points SET target_heading = 442.6 WHERE zone = 'corathus' AND version = 0 AND number = 1 AND id = 1589 AND target_heading = 221.3; +UPDATE zone_points SET target_heading = 246 WHERE zone = 'stonehive' AND version = 0 AND number = 0 AND id = 1590 AND target_heading = 123; +UPDATE zone_points SET target_heading = 772 WHERE zone = 'icefall' AND version = 0 AND number = 10 AND id = 1591 AND target_heading = 386; +UPDATE zone_points SET target_heading = 884 WHERE zone = 'icefall' AND version = 0 AND number = 20 AND id = 1592 AND target_heading = 442; +UPDATE zone_points SET target_heading = 782 WHERE zone = 'roost' AND version = 0 AND number = 10 AND id = 1593 AND target_heading = 391; +UPDATE zone_points SET target_heading = 962 WHERE zone = 'roost' AND version = 0 AND number = 101 AND id = 1594 AND target_heading = 481; +UPDATE zone_points SET target_heading = 684 WHERE zone = 'roost' AND version = 0 AND number = 102 AND id = 1595 AND target_heading = 342; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'roost' AND version = 0 AND number = 103 AND id = 1596 AND target_heading = 119; +UPDATE zone_points SET target_heading = 694 WHERE zone = 'roost' AND version = 0 AND number = 104 AND id = 1597 AND target_heading = 347; +UPDATE zone_points SET target_heading = 766 WHERE zone = 'roost' AND version = 0 AND number = 105 AND id = 1598 AND target_heading = 383; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'roost' AND version = 0 AND number = 106 AND id = 1599 AND target_heading = 160; +UPDATE zone_points SET target_heading = 300 WHERE zone = 'roost' AND version = 0 AND number = 107 AND id = 1600 AND target_heading = 150; +UPDATE zone_points SET target_heading = 644 WHERE zone = 'roost' AND version = 0 AND number = 108 AND id = 1601 AND target_heading = 322; +UPDATE zone_points SET target_heading = 892 WHERE zone = 'roost' AND version = 0 AND number = 109 AND id = 1602 AND target_heading = 446; +UPDATE zone_points SET target_heading = 270 WHERE zone = 'roost' AND version = 0 AND number = 110 AND id = 1603 AND target_heading = 135; +UPDATE zone_points SET target_heading = 698 WHERE zone = 'steppes' AND version = 0 AND number = 10 AND id = 1604 AND target_heading = 349; +UPDATE zone_points SET target_heading = 1016 WHERE zone = 'steppes' AND version = 0 AND number = 20 AND id = 1605 AND target_heading = 508; +UPDATE zone_points SET target_heading = 600 WHERE zone = 'valdeholm' AND version = 0 AND number = 10 AND id = 1606 AND target_heading = 300; +UPDATE zone_points SET target_heading = 1024 WHERE zone = 'valdeholm' AND version = 0 AND number = 20 AND id = 1607 AND target_heading = 512; +UPDATE zone_points SET target_heading = 516 WHERE zone = 'mesa' AND version = 0 AND number = 10 AND id = 1608 AND target_heading = 258; +UPDATE zone_points SET target_heading = 916 WHERE zone = 'mesa' AND version = 0 AND number = 20 AND id = 1609 AND target_heading = 458; +UPDATE zone_points SET target_heading = 42 WHERE zone = 'mesa' AND version = 0 AND number = 30 AND id = 1610 AND target_heading = 21; +UPDATE zone_points SET target_heading = 226 WHERE zone = 'mesa' AND version = 0 AND number = 40 AND id = 1611 AND target_heading = 113; +UPDATE zone_points SET target_heading = 730 WHERE zone = 'toxxulia' AND version = 0 AND number = 10 AND id = 1612 AND target_heading = 365; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'toxxulia' AND version = 0 AND number = 20 AND id = 1613 AND target_heading = 256; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'toxxulia' AND version = 0 AND number = 30 AND id = 1614 AND target_heading = 0; +UPDATE zone_points SET target_heading = 514 WHERE zone = 'toxxulia' AND version = 0 AND number = 40 AND id = 1615 AND target_heading = 257; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'toxxulia' AND version = 0 AND number = 50 AND id = 1616 AND target_heading = 192; +UPDATE zone_points SET target_heading = 328 WHERE zone = 'ashengate' AND version = 0 AND number = 10 AND id = 1617 AND target_heading = 164; +UPDATE zone_points SET target_heading = 598 WHERE zone = 'ashengate' AND version = 0 AND number = 30 AND id = 1618 AND target_heading = 299; +UPDATE zone_points SET target_heading = 170 WHERE zone = 'ashengate' AND version = 0 AND number = 40 AND id = 1619 AND target_heading = 85; +UPDATE zone_points SET target_heading = 170 WHERE zone = 'ashengate' AND version = 0 AND number = 50 AND id = 1620 AND target_heading = 85; +UPDATE zone_points SET target_heading = 994 WHERE zone = 'direwind' AND version = 0 AND number = 10 AND id = 1621 AND target_heading = 497; +UPDATE zone_points SET target_heading = 716 WHERE zone = 'direwind' AND version = 0 AND number = 20 AND id = 1622 AND target_heading = 358; +UPDATE zone_points SET target_heading = 310 WHERE zone = 'sunderock' AND version = 0 AND number = 10 AND id = 1623 AND target_heading = 155; +UPDATE zone_points SET target_heading = 94 WHERE zone = 'sunderock' AND version = 0 AND number = 20 AND id = 1624 AND target_heading = 47; +UPDATE zone_points SET target_heading = 564 WHERE zone = 'vergalid' AND version = 0 AND number = 0 AND id = 1625 AND target_heading = 282; +UPDATE zone_points SET target_heading = 392 WHERE zone = 'innothuleb' AND version = 0 AND number = 10 AND id = 1626 AND target_heading = 196; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'innothuleb' AND version = 0 AND number = 20 AND id = 1627 AND target_heading = 35; +UPDATE zone_points SET target_heading = 488 WHERE zone = 'innothuleb' AND version = 0 AND number = 30 AND id = 1628 AND target_heading = 244; +UPDATE zone_points SET target_heading = 436 WHERE zone = 'innothuleb' AND version = 0 AND number = 40 AND id = 1629 AND target_heading = 218; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'innothuleb' AND version = 0 AND number = 77 AND id = 1630 AND target_heading = 384; +UPDATE zone_points SET target_heading = 1002 WHERE zone = 'kattacastrum' AND version = 0 AND number = 10 AND id = 1631 AND target_heading = 501; +UPDATE zone_points SET target_heading = 1020 WHERE zone = 'kattacastrum' AND version = 0 AND number = 20 AND id = 1632 AND target_heading = 510; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'kattacastrum' AND version = 0 AND number = 30 AND id = 1633 AND target_heading = 0; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'kattacastrum' AND version = 0 AND number = 40 AND id = 1634 AND target_heading = 256; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'kattacastrum' AND version = 0 AND number = 50 AND id = 1635 AND target_heading = 256; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND number = 60 AND id = 1636 AND target_heading = 128; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'kattacastrum' AND version = 0 AND number = 61 AND id = 1637 AND target_heading = 384; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'kattacastrum' AND version = 0 AND number = 62 AND id = 1638 AND target_heading = 0; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'kattacastrum' AND version = 0 AND number = 63 AND id = 1639 AND target_heading = 384; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'kattacastrum' AND version = 0 AND number = 64 AND id = 1640 AND target_heading = 128; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'kattacastrum' AND version = 0 AND number = 65 AND id = 1641 AND target_heading = 65; +UPDATE zone_points SET target_heading = 634 WHERE zone = 'kattacastrum' AND version = 0 AND number = 66 AND id = 1642 AND target_heading = 317; +UPDATE zone_points SET target_heading = 404 WHERE zone = 'kattacastrum' AND version = 0 AND number = 67 AND id = 1643 AND target_heading = 202; +UPDATE zone_points SET target_heading = 96 WHERE zone = 'kattacastrum' AND version = 0 AND number = 68 AND id = 1644 AND target_heading = 48; +UPDATE zone_points SET target_heading = 186 WHERE zone = 'kattacastrum' AND version = 0 AND number = 69 AND id = 1645 AND target_heading = 93; +UPDATE zone_points SET target_heading = 318 WHERE zone = 'kattacastrum' AND version = 0 AND number = 70 AND id = 1646 AND target_heading = 159; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'kattacastrum' AND version = 0 AND number = 71 AND id = 1647 AND target_heading = 225; +UPDATE zone_points SET target_heading = 580 WHERE zone = 'kattacastrum' AND version = 0 AND number = 72 AND id = 1648 AND target_heading = 290; +UPDATE zone_points SET target_heading = 726 WHERE zone = 'kattacastrum' AND version = 0 AND number = 73 AND id = 1649 AND target_heading = 363; +UPDATE zone_points SET target_heading = 804 WHERE zone = 'kattacastrum' AND version = 0 AND number = 74 AND id = 1650 AND target_heading = 402; +UPDATE zone_points SET target_heading = 954 WHERE zone = 'kattacastrum' AND version = 0 AND number = 75 AND id = 1651 AND target_heading = 477; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'kattacastrum' AND version = 0 AND number = 80 AND id = 1652 AND target_heading = 256; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'barren' AND version = 0 AND number = 10 AND id = 1653 AND target_heading = 119; +UPDATE zone_points SET target_heading = 520 WHERE zone = 'buriedsea' AND version = 0 AND number = 10 AND id = 1654 AND target_heading = 260; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'steamfontmts' AND version = 0 AND number = 10 AND id = 1655 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'steamfontmts' AND version = 0 AND number = 20 AND id = 1656 AND target_heading = 999; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'steamfontmts' AND version = 0 AND number = 30 AND id = 1657 AND target_heading = 128; +UPDATE zone_points SET target_heading = 210 WHERE zone = 'steamfontmts' AND version = 0 AND number = 40 AND id = 1658 AND target_heading = 105; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'steamfontmts' AND version = 0 AND number = 50 AND id = 1659 AND target_heading = 256; +UPDATE zone_points SET target_heading = 866 WHERE zone = 'bloodmoon' AND version = 0 AND number = 0 AND id = 1660 AND target_heading = 433; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bloodmoon' AND version = 0 AND number = 9 AND id = 1661 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'bloodmoon' AND version = 0 AND number = 20 AND id = 1662 AND target_heading = 0; +UPDATE zone_points SET target_heading = 38 WHERE zone = 'bloodmoon' AND version = 0 AND number = 30 AND id = 1663 AND target_heading = 19; +UPDATE zone_points SET target_heading = 1016 WHERE zone = 'dragonscale' AND version = 0 AND number = 100 AND id = 1664 AND target_heading = 508; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'dragonscale' AND version = 0 AND number = 200 AND id = 1665 AND target_heading = 0; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'dragonscale' AND version = 0 AND number = 300 AND id = 1666 AND target_heading = 76; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'gyrospireb' AND version = 0 AND number = 10 AND id = 1667 AND target_heading = 999; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'gyrospireb' AND version = 0 AND number = 20 AND id = 1668 AND target_heading = 76; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'gyrospirez' AND version = 0 AND number = 10 AND id = 1669 AND target_heading = 999; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'gyrospirez' AND version = 0 AND number = 20 AND id = 1670 AND target_heading = 76; +UPDATE zone_points SET target_heading = 216 WHERE zone = 'hillsofshade' AND version = 0 AND number = 10 AND id = 1671 AND target_heading = 108; +UPDATE zone_points SET target_heading = 988 WHERE zone = 'lopingplains' AND version = 0 AND number = 10 AND id = 1672 AND target_heading = 494; +UPDATE zone_points SET target_heading = 310 WHERE zone = 'lopingplains' AND version = 0 AND number = 20 AND id = 1673 AND target_heading = 155; +UPDATE zone_points SET target_heading = 770 WHERE zone = 'mansion' AND version = 0 AND number = 10 AND id = 1674 AND target_heading = 385; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'mansion' AND version = 0 AND number = 14 AND id = 1675 AND target_heading = 256; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'mechanotus' AND version = 0 AND number = 0 AND id = 1676 AND target_heading = 0; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'mechanotus' AND version = 0 AND number = 0 AND id = 1677 AND target_heading = 130; +UPDATE zone_points SET target_heading = 1000 WHERE zone = 'mechanotus' AND version = 0 AND number = 10 AND id = 1678 AND target_heading = 500; +UPDATE zone_points SET target_heading = 930 WHERE zone = 'mechanotus' AND version = 0 AND number = 20 AND id = 1679 AND target_heading = 465; +UPDATE zone_points SET target_heading = 200 WHERE zone = 'mechanotus' AND version = 0 AND number = 30 AND id = 1680 AND target_heading = 100; +UPDATE zone_points SET target_heading = 750 WHERE zone = 'mechanotus' AND version = 0 AND number = 70 AND id = 1681 AND target_heading = 375; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'mechanotus' AND version = 0 AND number = 80 AND id = 1682 AND target_heading = 0; +UPDATE zone_points SET target_heading = 1000 WHERE zone = 'mechanotus' AND version = 0 AND number = 90 AND id = 1683 AND target_heading = 500; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'mechanotus' AND version = 0 AND number = 100 AND id = 1684 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'mechanotus' AND version = 0 AND number = 110 AND id = 1685 AND target_heading = 0; +UPDATE zone_points SET target_heading = 520 WHERE zone = 'shipworkshop' AND version = 0 AND number = 10 AND id = 1686 AND target_heading = 260; +UPDATE zone_points SET target_heading = 560 WHERE zone = 'shipworkshop' AND version = 0 AND number = 20 AND id = 1687 AND target_heading = 280; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'steamfactory' AND version = 0 AND number = 10 AND id = 1688 AND target_heading = 384; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'steamfactory' AND version = 0 AND number = 20 AND id = 1689 AND target_heading = 256; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'steamfactory' AND version = 0 AND number = 30 AND id = 1690 AND target_heading = 125; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'steamfactory' AND version = 0 AND number = 40 AND id = 1691 AND target_heading = 129; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'steamfactory' AND version = 0 AND number = 40 AND id = 1692 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'steamfactory' AND version = 0 AND number = 50 AND id = 1693 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'steamfactory' AND version = 0 AND number = 60 AND id = 1694 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'steamfactory' AND version = 0 AND number = 70 AND id = 1695 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'steamfactory' AND version = 0 AND number = 80 AND id = 1696 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'steamfactory' AND version = 0 AND number = 90 AND id = 1697 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'steamfactory' AND version = 0 AND number = 100 AND id = 1698 AND target_heading = 0; +UPDATE zone_points SET target_heading = 614 WHERE zone = 'zhisza' AND version = 0 AND number = 10 AND id = 1699 AND target_heading = 307; +UPDATE zone_points SET target_heading = 452 WHERE zone = 'zhisza' AND version = 0 AND number = 90 AND id = 1700 AND target_heading = 226; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'eastkarana' AND version = 0 AND number = 3 AND id = 1701 AND target_heading = 128; +UPDATE zone_points SET target_heading = 282 WHERE zone = 'highkeep' AND version = 0 AND number = 1 AND id = 1702 AND target_heading = 141; +UPDATE zone_points SET target_heading = 32 WHERE zone = 'highkeep' AND version = 0 AND number = 2 AND id = 1703 AND target_heading = 16; +UPDATE zone_points SET target_heading = 490 WHERE zone = 'kithicor' AND version = 0 AND number = 1 AND id = 1704 AND target_heading = 245; +UPDATE zone_points SET target_heading = 12 WHERE zone = 'bertoxtemple' AND version = 0 AND number = 10 AND id = 1705 AND target_heading = 6; +UPDATE zone_points SET target_heading = 974 WHERE zone = 'oldkaesorab' AND version = 0 AND number = 10 AND id = 1706 AND target_heading = 487; +UPDATE zone_points SET target_heading = 132 WHERE zone = 'oldkaesoraa' AND version = 0 AND number = 10 AND id = 1707 AND target_heading = 66; +UPDATE zone_points SET target_heading = 190 WHERE zone = 'discord' AND version = 0 AND number = 26 AND id = 1708 AND target_heading = 95; +UPDATE zone_points SET target_heading = 320 WHERE zone = 'korascian' AND version = 0 AND number = 10 AND id = 1709 AND target_heading = 160; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'korascian' AND version = 0 AND number = 20 AND id = 1710 AND target_heading = 384; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oceangreenhills' AND version = 0 AND number = 10 AND id = 1711 AND target_heading = 999; +UPDATE zone_points SET target_heading = 750 WHERE zone = 'oceangreenhills' AND version = 0 AND number = 20 AND id = 1712 AND target_heading = 375; +UPDATE zone_points SET target_heading = 584 WHERE zone = 'oceangreenhills' AND version = 0 AND number = 21 AND id = 1713 AND target_heading = 292; +UPDATE zone_points SET target_heading = 180 WHERE zone = 'oceangreenhills' AND version = 0 AND number = 30 AND id = 1714 AND target_heading = 90; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oceangreenvillage' AND version = 0 AND number = 10 AND id = 1715 AND target_heading = 999; +UPDATE zone_points SET target_heading = 770 WHERE zone = 'oceangreenvillage' AND version = 0 AND number = 20 AND id = 1716 AND target_heading = 385; +UPDATE zone_points SET target_heading = 512 WHERE zone = 'oldbloodfield' AND version = 0 AND number = 10 AND id = 1717 AND target_heading = 256; +UPDATE zone_points SET target_heading = 444 WHERE zone = 'oldbloodfield' AND version = 0 AND number = 20 AND id = 1718 AND target_heading = 222; +UPDATE zone_points SET target_heading = 868 WHERE zone = 'oldbloodfield' AND version = 0 AND number = 25 AND id = 1719 AND target_heading = 434; +UPDATE zone_points SET target_heading = 522 WHERE zone = 'olddranik' AND version = 0 AND number = 10 AND id = 1720 AND target_heading = 261; +UPDATE zone_points SET target_heading = 218 WHERE zone = 'oldcommons' AND version = 0 AND number = 10 AND id = 1721 AND target_heading = 109; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oldcommons' AND version = 0 AND number = 20 AND id = 1722 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oldcommons' AND version = 0 AND number = 30 AND id = 1723 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oldcommons' AND version = 0 AND number = 40 AND id = 1724 AND target_heading = 999; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'oldcommons' AND version = 0 AND number = 50 AND id = 1725 AND target_heading = 384; +UPDATE zone_points SET target_heading = 580 WHERE zone = 'oldkithicor' AND version = 0 AND number = 10 AND id = 1726 AND target_heading = 290; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oldkithicor' AND version = 0 AND number = 20 AND id = 1727 AND target_heading = 999; +UPDATE zone_points SET target_heading = 112 WHERE zone = 'oldkithicor' AND version = 0 AND number = 22 AND id = 1728 AND target_heading = 56; +UPDATE zone_points SET target_heading = 546 WHERE zone = 'oldkithicor' AND version = 0 AND number = 30 AND id = 1729 AND target_heading = 273; +UPDATE zone_points SET target_heading = 524 WHERE zone = 'oldkurn' AND version = 0 AND number = 0 AND id = 1730 AND target_heading = 262; +UPDATE zone_points SET target_heading = 524 WHERE zone = 'oldkurn' AND version = 0 AND number = 10 AND id = 1731 AND target_heading = 262; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oldblackburrow' AND version = 0 AND number = 10 AND id = 1732 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'oldblackburrow' AND version = 0 AND number = 20 AND id = 1733 AND target_heading = 999; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'oldfieldofbone' AND version = 0 AND number = 10 AND id = 1734 AND target_heading = 250; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'oldfieldofbone' AND version = 0 AND number = 23 AND id = 1735 AND target_heading = 130; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'oldfieldofbone' AND version = 0 AND number = 200 AND id = 1736 AND target_heading = 127; +UPDATE zone_points SET target_heading = 766 WHERE zone = 'oldfieldofbone' AND version = 0 AND number = 210 AND id = 1737 AND target_heading = 383; +UPDATE zone_points SET target_heading = 480 WHERE zone = 'oldfieldofbone' AND version = 0 AND number = 500 AND id = 1738 AND target_heading = 240; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'rathechamber' AND version = 0 AND number = 10 AND id = 1739 AND target_heading = 128; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'thevoide' AND version = 0 AND number = 10 AND id = 1740 AND target_heading = 167; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'thevoide' AND version = 0 AND number = 20 AND id = 1741 AND target_heading = 76; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'thevoide' AND version = 0 AND number = 30 AND id = 1742 AND target_heading = 225; +UPDATE zone_points SET target_heading = 896 WHERE zone = 'thevoide' AND version = 0 AND number = 40 AND id = 1743 AND target_heading = 448; +UPDATE zone_points SET target_heading = 50 WHERE zone = 'thevoide' AND version = 0 AND number = 50 AND id = 1744 AND target_heading = 25; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'thevoide' AND version = 0 AND number = 60 AND id = 1745 AND target_heading = 106; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'thevoide' AND version = 0 AND number = 70 AND id = 1746 AND target_heading = 185; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'thevoide' AND version = 0 AND number = 80 AND id = 1747 AND target_heading = 270; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'thevoide' AND version = 0 AND number = 90 AND id = 1748 AND target_heading = 125; +UPDATE zone_points SET target_heading = 700 WHERE zone = 'thevoide' AND version = 0 AND number = 100 AND id = 1749 AND target_heading = 350; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thevoide' AND version = 0 AND number = 110 AND id = 1750 AND target_heading = 0; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'thevoide' AND version = 0 AND number = 120 AND id = 1751 AND target_heading = 288; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'thevoide' AND version = 0 AND number = 130 AND id = 1752 AND target_heading = 35; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thevoide' AND version = 0 AND number = 140 AND id = 1753 AND target_heading = 220; +UPDATE zone_points SET target_heading = 350 WHERE zone = 'thevoide' AND version = 0 AND number = 150 AND id = 1754 AND target_heading = 175; +UPDATE zone_points SET target_heading = 882 WHERE zone = 'thevoide' AND version = 0 AND number = 160 AND id = 1755 AND target_heading = 441; +UPDATE zone_points SET target_heading = 1014 WHERE zone = 'toskirakk' AND version = 0 AND number = 20 AND id = 1756 AND target_heading = 507; +UPDATE zone_points SET target_heading = 816 WHERE zone = 'toskirakk' AND version = 0 AND number = 24 AND id = 1757 AND target_heading = 408; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'thevoida' AND version = 0 AND number = 10 AND id = 1758 AND target_heading = 167; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'thevoida' AND version = 0 AND number = 20 AND id = 1759 AND target_heading = 76; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'thevoida' AND version = 0 AND number = 30 AND id = 1760 AND target_heading = 225; +UPDATE zone_points SET target_heading = 896 WHERE zone = 'thevoida' AND version = 0 AND number = 40 AND id = 1761 AND target_heading = 448; +UPDATE zone_points SET target_heading = 50 WHERE zone = 'thevoida' AND version = 0 AND number = 50 AND id = 1762 AND target_heading = 25; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'thevoida' AND version = 0 AND number = 60 AND id = 1763 AND target_heading = 106; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'thevoida' AND version = 0 AND number = 70 AND id = 1764 AND target_heading = 185; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'thevoida' AND version = 0 AND number = 80 AND id = 1765 AND target_heading = 270; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'thevoida' AND version = 0 AND number = 90 AND id = 1766 AND target_heading = 125; +UPDATE zone_points SET target_heading = 700 WHERE zone = 'thevoida' AND version = 0 AND number = 100 AND id = 1767 AND target_heading = 350; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thevoida' AND version = 0 AND number = 110 AND id = 1768 AND target_heading = 0; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'thevoida' AND version = 0 AND number = 120 AND id = 1769 AND target_heading = 288; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'thevoida' AND version = 0 AND number = 130 AND id = 1770 AND target_heading = 35; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thevoida' AND version = 0 AND number = 140 AND id = 1771 AND target_heading = 220; +UPDATE zone_points SET target_heading = 350 WHERE zone = 'thevoida' AND version = 0 AND number = 150 AND id = 1772 AND target_heading = 175; +UPDATE zone_points SET target_heading = 882 WHERE zone = 'thevoida' AND version = 0 AND number = 160 AND id = 1773 AND target_heading = 441; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'crystallos' AND version = 0 AND number = 10 AND id = 1774 AND target_heading = 0; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'thevoidb' AND version = 0 AND number = 10 AND id = 1775 AND target_heading = 167; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'thevoidb' AND version = 0 AND number = 20 AND id = 1776 AND target_heading = 76; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'thevoidb' AND version = 0 AND number = 30 AND id = 1777 AND target_heading = 225; +UPDATE zone_points SET target_heading = 896 WHERE zone = 'thevoidb' AND version = 0 AND number = 40 AND id = 1778 AND target_heading = 448; +UPDATE zone_points SET target_heading = 50 WHERE zone = 'thevoidb' AND version = 0 AND number = 50 AND id = 1779 AND target_heading = 25; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'thevoidb' AND version = 0 AND number = 60 AND id = 1780 AND target_heading = 106; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'thevoidb' AND version = 0 AND number = 70 AND id = 1781 AND target_heading = 185; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'thevoidb' AND version = 0 AND number = 80 AND id = 1782 AND target_heading = 270; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'thevoidb' AND version = 0 AND number = 90 AND id = 1783 AND target_heading = 125; +UPDATE zone_points SET target_heading = 700 WHERE zone = 'thevoidb' AND version = 0 AND number = 100 AND id = 1784 AND target_heading = 350; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thevoidb' AND version = 0 AND number = 110 AND id = 1785 AND target_heading = 0; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'thevoidb' AND version = 0 AND number = 120 AND id = 1786 AND target_heading = 288; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'thevoidb' AND version = 0 AND number = 130 AND id = 1787 AND target_heading = 35; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thevoidb' AND version = 0 AND number = 140 AND id = 1788 AND target_heading = 220; +UPDATE zone_points SET target_heading = 350 WHERE zone = 'thevoidb' AND version = 0 AND number = 150 AND id = 1789 AND target_heading = 175; +UPDATE zone_points SET target_heading = 882 WHERE zone = 'thevoidb' AND version = 0 AND number = 160 AND id = 1790 AND target_heading = 441; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'thevoidc' AND version = 0 AND number = 10 AND id = 1791 AND target_heading = 167; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'thevoidc' AND version = 0 AND number = 20 AND id = 1792 AND target_heading = 76; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'thevoidc' AND version = 0 AND number = 30 AND id = 1793 AND target_heading = 225; +UPDATE zone_points SET target_heading = 896 WHERE zone = 'thevoidc' AND version = 0 AND number = 40 AND id = 1794 AND target_heading = 448; +UPDATE zone_points SET target_heading = 50 WHERE zone = 'thevoidc' AND version = 0 AND number = 50 AND id = 1795 AND target_heading = 25; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'thevoidc' AND version = 0 AND number = 60 AND id = 1796 AND target_heading = 106; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'thevoidc' AND version = 0 AND number = 70 AND id = 1797 AND target_heading = 185; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'thevoidc' AND version = 0 AND number = 80 AND id = 1798 AND target_heading = 270; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'thevoidc' AND version = 0 AND number = 90 AND id = 1799 AND target_heading = 125; +UPDATE zone_points SET target_heading = 700 WHERE zone = 'thevoidc' AND version = 0 AND number = 100 AND id = 1800 AND target_heading = 350; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thevoidc' AND version = 0 AND number = 110 AND id = 1801 AND target_heading = 0; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'thevoidc' AND version = 0 AND number = 120 AND id = 1802 AND target_heading = 288; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'thevoidc' AND version = 0 AND number = 130 AND id = 1803 AND target_heading = 35; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thevoidc' AND version = 0 AND number = 140 AND id = 1804 AND target_heading = 220; +UPDATE zone_points SET target_heading = 350 WHERE zone = 'thevoidc' AND version = 0 AND number = 150 AND id = 1805 AND target_heading = 175; +UPDATE zone_points SET target_heading = 882 WHERE zone = 'thevoidc' AND version = 0 AND number = 160 AND id = 1806 AND target_heading = 441; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'thevoidd' AND version = 0 AND number = 10 AND id = 1807 AND target_heading = 167; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'thevoidd' AND version = 0 AND number = 20 AND id = 1808 AND target_heading = 76; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'thevoidd' AND version = 0 AND number = 30 AND id = 1809 AND target_heading = 225; +UPDATE zone_points SET target_heading = 896 WHERE zone = 'thevoidd' AND version = 0 AND number = 40 AND id = 1810 AND target_heading = 448; +UPDATE zone_points SET target_heading = 50 WHERE zone = 'thevoidd' AND version = 0 AND number = 50 AND id = 1811 AND target_heading = 25; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'thevoidd' AND version = 0 AND number = 60 AND id = 1812 AND target_heading = 106; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'thevoidd' AND version = 0 AND number = 70 AND id = 1813 AND target_heading = 185; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'thevoidd' AND version = 0 AND number = 80 AND id = 1814 AND target_heading = 270; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'thevoidd' AND version = 0 AND number = 90 AND id = 1815 AND target_heading = 125; +UPDATE zone_points SET target_heading = 700 WHERE zone = 'thevoidd' AND version = 0 AND number = 100 AND id = 1816 AND target_heading = 350; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thevoidd' AND version = 0 AND number = 110 AND id = 1817 AND target_heading = 0; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'thevoidd' AND version = 0 AND number = 120 AND id = 1818 AND target_heading = 288; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'thevoidd' AND version = 0 AND number = 130 AND id = 1819 AND target_heading = 35; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thevoidd' AND version = 0 AND number = 140 AND id = 1820 AND target_heading = 220; +UPDATE zone_points SET target_heading = 350 WHERE zone = 'thevoidd' AND version = 0 AND number = 150 AND id = 1821 AND target_heading = 175; +UPDATE zone_points SET target_heading = 882 WHERE zone = 'thevoidd' AND version = 0 AND number = 160 AND id = 1822 AND target_heading = 441; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'thevoidf' AND version = 0 AND number = 10 AND id = 1823 AND target_heading = 167; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'thevoidf' AND version = 0 AND number = 20 AND id = 1824 AND target_heading = 76; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'thevoidf' AND version = 0 AND number = 30 AND id = 1825 AND target_heading = 225; +UPDATE zone_points SET target_heading = 896 WHERE zone = 'thevoidf' AND version = 0 AND number = 40 AND id = 1826 AND target_heading = 448; +UPDATE zone_points SET target_heading = 50 WHERE zone = 'thevoidf' AND version = 0 AND number = 50 AND id = 1827 AND target_heading = 25; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'thevoidf' AND version = 0 AND number = 60 AND id = 1828 AND target_heading = 106; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'thevoidf' AND version = 0 AND number = 70 AND id = 1829 AND target_heading = 185; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'thevoidf' AND version = 0 AND number = 80 AND id = 1830 AND target_heading = 270; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'thevoidf' AND version = 0 AND number = 90 AND id = 1831 AND target_heading = 125; +UPDATE zone_points SET target_heading = 700 WHERE zone = 'thevoidf' AND version = 0 AND number = 100 AND id = 1832 AND target_heading = 350; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thevoidf' AND version = 0 AND number = 110 AND id = 1833 AND target_heading = 0; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'thevoidf' AND version = 0 AND number = 120 AND id = 1834 AND target_heading = 288; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'thevoidf' AND version = 0 AND number = 130 AND id = 1835 AND target_heading = 35; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thevoidf' AND version = 0 AND number = 140 AND id = 1836 AND target_heading = 220; +UPDATE zone_points SET target_heading = 350 WHERE zone = 'thevoidf' AND version = 0 AND number = 150 AND id = 1837 AND target_heading = 175; +UPDATE zone_points SET target_heading = 882 WHERE zone = 'thevoidf' AND version = 0 AND number = 160 AND id = 1838 AND target_heading = 441; +UPDATE zone_points SET target_heading = 334 WHERE zone = 'thevoidg' AND version = 0 AND number = 10 AND id = 1839 AND target_heading = 167; +UPDATE zone_points SET target_heading = 152 WHERE zone = 'thevoidg' AND version = 0 AND number = 20 AND id = 1840 AND target_heading = 76; +UPDATE zone_points SET target_heading = 450 WHERE zone = 'thevoidg' AND version = 0 AND number = 30 AND id = 1841 AND target_heading = 225; +UPDATE zone_points SET target_heading = 896 WHERE zone = 'thevoidg' AND version = 0 AND number = 40 AND id = 1842 AND target_heading = 448; +UPDATE zone_points SET target_heading = 50 WHERE zone = 'thevoidg' AND version = 0 AND number = 50 AND id = 1843 AND target_heading = 25; +UPDATE zone_points SET target_heading = 212 WHERE zone = 'thevoidg' AND version = 0 AND number = 60 AND id = 1844 AND target_heading = 106; +UPDATE zone_points SET target_heading = 370 WHERE zone = 'thevoidg' AND version = 0 AND number = 70 AND id = 1845 AND target_heading = 185; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'thevoidg' AND version = 0 AND number = 80 AND id = 1846 AND target_heading = 270; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'thevoidg' AND version = 0 AND number = 90 AND id = 1847 AND target_heading = 125; +UPDATE zone_points SET target_heading = 700 WHERE zone = 'thevoidg' AND version = 0 AND number = 100 AND id = 1848 AND target_heading = 350; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thevoidg' AND version = 0 AND number = 110 AND id = 1849 AND target_heading = 0; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'thevoidg' AND version = 0 AND number = 120 AND id = 1850 AND target_heading = 288; +UPDATE zone_points SET target_heading = 70 WHERE zone = 'thevoidg' AND version = 0 AND number = 130 AND id = 1851 AND target_heading = 35; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thevoidg' AND version = 0 AND number = 140 AND id = 1852 AND target_heading = 220; +UPDATE zone_points SET target_heading = 350 WHERE zone = 'thevoidg' AND version = 0 AND number = 150 AND id = 1853 AND target_heading = 175; +UPDATE zone_points SET target_heading = 882 WHERE zone = 'thevoidg' AND version = 0 AND number = 160 AND id = 1854 AND target_heading = 441; +UPDATE zone_points SET target_heading = 478 WHERE zone = 'brellsrest' AND version = 0 AND number = 10 AND id = 1855 AND target_heading = 239; +UPDATE zone_points SET target_heading = 304 WHERE zone = 'brellsrest' AND version = 0 AND number = 20 AND id = 1856 AND target_heading = 152; +UPDATE zone_points SET target_heading = 754 WHERE zone = 'brellsrest' AND version = 0 AND number = 30 AND id = 1857 AND target_heading = 377; +UPDATE zone_points SET target_heading = 90 WHERE zone = 'brellsrest' AND version = 0 AND number = 40 AND id = 1858 AND target_heading = 45; +UPDATE zone_points SET target_heading = 480 WHERE zone = 'brellsrest' AND version = 0 AND number = 50 AND id = 1859 AND target_heading = 240; +UPDATE zone_points SET target_heading = 940 WHERE zone = 'coolingchamber' AND version = 0 AND number = 10 AND id = 1860 AND target_heading = 470; +UPDATE zone_points SET target_heading = 576 WHERE zone = 'coolingchamber' AND version = 0 AND number = 30 AND id = 1861 AND target_heading = 288; +UPDATE zone_points SET target_heading = 62 WHERE zone = 'pellucid' AND version = 0 AND number = 10 AND id = 1862 AND target_heading = 31; +UPDATE zone_points SET target_heading = 664 WHERE zone = 'pellucid' AND version = 0 AND number = 370 AND id = 1863 AND target_heading = 332; +UPDATE zone_points SET target_heading = 486 WHERE zone = 'pellucid' AND version = 0 AND number = 520 AND id = 1864 AND target_heading = 243; +UPDATE zone_points SET target_heading = 760 WHERE zone = 'arthicrex' AND version = 0 AND number = 10 AND id = 1865 AND target_heading = 380; +UPDATE zone_points SET target_heading = 34 WHERE zone = 'foundation' AND version = 0 AND number = 10 AND id = 1866 AND target_heading = 17; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'foundation' AND version = 0 AND number = 20 AND id = 1867 AND target_heading = 0; +UPDATE zone_points SET target_heading = 60 WHERE zone = 'underquarry' AND version = 0 AND number = 0 AND id = 1868 AND target_heading = 30; +UPDATE zone_points SET target_heading = 246 WHERE zone = 'underquarry' AND version = 0 AND number = 10 AND id = 1869 AND target_heading = 123; +UPDATE zone_points SET target_heading = 36 WHERE zone = 'underquarry' AND version = 0 AND number = 20 AND id = 1870 AND target_heading = 18; +UPDATE zone_points SET target_heading = 540 WHERE zone = 'underquarry' AND version = 0 AND number = 30 AND id = 1871 AND target_heading = 270; +UPDATE zone_points SET target_heading = 1020 WHERE zone = 'arena' AND version = 0 AND number = 10 AND id = 1872 AND target_heading = 510; +UPDATE zone_points SET target_heading = 520 WHERE zone = 'arena' AND version = 0 AND number = 2 AND id = 1874 AND target_heading = 260; +UPDATE zone_points SET target_heading = 956 WHERE zone = 'lavastorm' AND version = 0 AND number = 10 AND id = 1876 AND target_heading = 478; +UPDATE zone_points SET target_heading = 130 WHERE zone = 'lavastorm' AND version = 0 AND number = 20 AND id = 1877 AND target_heading = 65; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'lavastorm' AND version = 0 AND number = 30 AND id = 1878 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'lavastorm' AND version = 0 AND number = 40 AND id = 1879 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'lavastorm' AND version = 0 AND number = 50 AND id = 1880 AND target_heading = 999; +UPDATE zone_points SET target_heading = 330 WHERE zone = 'lavastorm' AND version = 0 AND number = 60 AND id = 1881 AND target_heading = 165; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'lavastorm' AND version = 0 AND number = 88 AND id = 1882 AND target_heading = 999; +UPDATE zone_points SET target_heading = 262 WHERE zone = 'silyssar' AND version = 0 AND number = 90 AND id = 1884 AND target_heading = 131; +UPDATE zone_points SET target_heading = 408 WHERE zone = 'sleeper' AND version = 0 AND number = 10 AND id = 1886 AND target_heading = 204; +UPDATE zone_points SET target_heading = 758 WHERE zone = 'nightmareb' AND version = 0 AND number = 77 AND id = 1887 AND target_heading = 379; +UPDATE zone_points SET target_heading = 514 WHERE zone = 'morellcastle' AND version = 0 AND number = 0 AND id = 1912 AND target_heading = 257; +UPDATE zone_points SET target_heading = 24 WHERE zone = 'morellcastle' AND version = 0 AND number = 10 AND id = 1913 AND target_heading = 12; +UPDATE zone_points SET target_heading = 208 WHERE zone = 'morellcastle' AND version = 0 AND number = 11 AND id = 1914 AND target_heading = 104; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'morellcastle' AND version = 0 AND number = 30 AND id = 1915 AND target_heading = 127; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'morellcastle' AND version = 0 AND number = 40 AND id = 1916 AND target_heading = 127; +UPDATE zone_points SET target_heading = 514 WHERE zone = 'morellcastle' AND version = 0 AND number = 0 AND id = 1917 AND target_heading = 257; +UPDATE zone_points SET target_heading = 24 WHERE zone = 'morellcastle' AND version = 0 AND number = 10 AND id = 1918 AND target_heading = 12; +UPDATE zone_points SET target_heading = 208 WHERE zone = 'morellcastle' AND version = 0 AND number = 11 AND id = 1919 AND target_heading = 104; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'morellcastle' AND version = 0 AND number = 30 AND id = 1920 AND target_heading = 127; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'morellcastle' AND version = 0 AND number = 40 AND id = 1921 AND target_heading = 127; +UPDATE zone_points SET target_heading = 766 WHERE zone = 'alkabormare' AND version = 0 AND number = 11 AND id = 1922 AND target_heading = 383; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'fallen' AND version = 0 AND number = 23 AND id = 1923 AND target_heading = 127; +UPDATE zone_points SET target_heading = 1020 WHERE zone = 'fallen' AND version = 0 AND number = 32 AND id = 1924 AND target_heading = 510; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'fallen' AND version = 0 AND number = 33 AND id = 1925 AND target_heading = 255; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'housegarden' AND version = 0 AND number = 1 AND id = 1926 AND target_heading = 255; +UPDATE zone_points SET target_heading = 1999998 WHERE zone = 'housegarden' AND version = 0 AND number = 10 AND id = 1927 AND target_heading = 999999; +UPDATE zone_points SET target_heading = 514 WHERE zone = 'morellcastle' AND version = 0 AND number = 0 AND id = 1928 AND target_heading = 257; +UPDATE zone_points SET target_heading = 24 WHERE zone = 'morellcastle' AND version = 0 AND number = 10 AND id = 1929 AND target_heading = 12; +UPDATE zone_points SET target_heading = 208 WHERE zone = 'morellcastle' AND version = 0 AND number = 11 AND id = 1930 AND target_heading = 104; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'morellcastle' AND version = 0 AND number = 30 AND id = 1931 AND target_heading = 127; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'morellcastle' AND version = 0 AND number = 40 AND id = 1932 AND target_heading = 127; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thuledream' AND version = 0 AND number = 10 AND id = 1933 AND target_heading = 0; +UPDATE zone_points SET target_heading = 108 WHERE zone = 'thulehouse2' AND version = 0 AND number = 10 AND id = 1934 AND target_heading = 54; +UPDATE zone_points SET target_heading = 108 WHERE zone = 'thulehouse2' AND version = 0 AND number = 20 AND id = 1935 AND target_heading = 54; +UPDATE zone_points SET target_heading = 108 WHERE zone = 'thulehouse2' AND version = 0 AND number = 30 AND id = 1936 AND target_heading = 54; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'thulehouse2' AND version = 0 AND number = 51 AND id = 1937 AND target_heading = 128; +UPDATE zone_points SET target_heading = 880 WHERE zone = 'thulehouse2' AND version = 0 AND number = 61 AND id = 1938 AND target_heading = 440; +UPDATE zone_points SET target_heading = 164 WHERE zone = 'thulehouse2' AND version = 0 AND number = 72 AND id = 1939 AND target_heading = 82; +UPDATE zone_points SET target_heading = 996 WHERE zone = 'thulehouse2' AND version = 0 AND number = 82 AND id = 1940 AND target_heading = 498; +UPDATE zone_points SET target_heading = 990 WHERE zone = 'well' AND version = 0 AND number = 9 AND id = 1941 AND target_heading = 495; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'neighborhood' AND version = 0 AND number = 1 AND id = 1942 AND target_heading = 254; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'neighborhood' AND version = 0 AND number = 10 AND id = 1943 AND target_heading = 254; +UPDATE zone_points SET target_heading = 748 WHERE zone = 'neighborhood' AND version = 0 AND number = 12 AND id = 1944 AND target_heading = 374; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'neighborhood' AND version = 0 AND number = 13 AND id = 1945 AND target_heading = 119; +UPDATE zone_points SET target_heading = 134 WHERE zone = 'neighborhood' AND version = 0 AND number = 14 AND id = 1946 AND target_heading = 67; +UPDATE zone_points SET target_heading = 712 WHERE zone = 'neighborhood' AND version = 0 AND number = 15 AND id = 1947 AND target_heading = 356; +UPDATE zone_points SET target_heading = 784 WHERE zone = 'neighborhood' AND version = 0 AND number = 16 AND id = 1948 AND target_heading = 392; +UPDATE zone_points SET target_heading = 138 WHERE zone = 'neighborhood' AND version = 0 AND number = 17 AND id = 1949 AND target_heading = 69; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'neighborhood' AND version = 0 AND number = 21 AND id = 1950 AND target_heading = 27; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'neighborhood' AND version = 0 AND number = 23 AND id = 1951 AND target_heading = 119; +UPDATE zone_points SET target_heading = 134 WHERE zone = 'neighborhood' AND version = 0 AND number = 24 AND id = 1952 AND target_heading = 67; +UPDATE zone_points SET target_heading = 712 WHERE zone = 'neighborhood' AND version = 0 AND number = 25 AND id = 1953 AND target_heading = 356; +UPDATE zone_points SET target_heading = 784 WHERE zone = 'neighborhood' AND version = 0 AND number = 26 AND id = 1954 AND target_heading = 392; +UPDATE zone_points SET target_heading = 138 WHERE zone = 'neighborhood' AND version = 0 AND number = 27 AND id = 1955 AND target_heading = 69; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'neighborhood' AND version = 0 AND number = 31 AND id = 1956 AND target_heading = 27; +UPDATE zone_points SET target_heading = 748 WHERE zone = 'neighborhood' AND version = 0 AND number = 32 AND id = 1957 AND target_heading = 374; +UPDATE zone_points SET target_heading = 134 WHERE zone = 'neighborhood' AND version = 0 AND number = 34 AND id = 1958 AND target_heading = 67; +UPDATE zone_points SET target_heading = 712 WHERE zone = 'neighborhood' AND version = 0 AND number = 35 AND id = 1959 AND target_heading = 356; +UPDATE zone_points SET target_heading = 784 WHERE zone = 'neighborhood' AND version = 0 AND number = 36 AND id = 1960 AND target_heading = 392; +UPDATE zone_points SET target_heading = 138 WHERE zone = 'neighborhood' AND version = 0 AND number = 37 AND id = 1961 AND target_heading = 69; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'neighborhood' AND version = 0 AND number = 41 AND id = 1962 AND target_heading = 27; +UPDATE zone_points SET target_heading = 748 WHERE zone = 'neighborhood' AND version = 0 AND number = 42 AND id = 1963 AND target_heading = 374; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'neighborhood' AND version = 0 AND number = 43 AND id = 1964 AND target_heading = 119; +UPDATE zone_points SET target_heading = 712 WHERE zone = 'neighborhood' AND version = 0 AND number = 45 AND id = 1965 AND target_heading = 356; +UPDATE zone_points SET target_heading = 784 WHERE zone = 'neighborhood' AND version = 0 AND number = 46 AND id = 1966 AND target_heading = 392; +UPDATE zone_points SET target_heading = 138 WHERE zone = 'neighborhood' AND version = 0 AND number = 47 AND id = 1967 AND target_heading = 69; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'neighborhood' AND version = 0 AND number = 51 AND id = 1968 AND target_heading = 27; +UPDATE zone_points SET target_heading = 748 WHERE zone = 'neighborhood' AND version = 0 AND number = 52 AND id = 1969 AND target_heading = 374; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'neighborhood' AND version = 0 AND number = 53 AND id = 1970 AND target_heading = 119; +UPDATE zone_points SET target_heading = 134 WHERE zone = 'neighborhood' AND version = 0 AND number = 54 AND id = 1971 AND target_heading = 67; +UPDATE zone_points SET target_heading = 784 WHERE zone = 'neighborhood' AND version = 0 AND number = 56 AND id = 1972 AND target_heading = 392; +UPDATE zone_points SET target_heading = 138 WHERE zone = 'neighborhood' AND version = 0 AND number = 57 AND id = 1973 AND target_heading = 69; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'neighborhood' AND version = 0 AND number = 61 AND id = 1974 AND target_heading = 27; +UPDATE zone_points SET target_heading = 748 WHERE zone = 'neighborhood' AND version = 0 AND number = 62 AND id = 1975 AND target_heading = 374; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'neighborhood' AND version = 0 AND number = 63 AND id = 1976 AND target_heading = 119; +UPDATE zone_points SET target_heading = 134 WHERE zone = 'neighborhood' AND version = 0 AND number = 64 AND id = 1977 AND target_heading = 67; +UPDATE zone_points SET target_heading = 712 WHERE zone = 'neighborhood' AND version = 0 AND number = 65 AND id = 1978 AND target_heading = 356; +UPDATE zone_points SET target_heading = 138 WHERE zone = 'neighborhood' AND version = 0 AND number = 67 AND id = 1979 AND target_heading = 69; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'neighborhood' AND version = 0 AND number = 71 AND id = 1980 AND target_heading = 27; +UPDATE zone_points SET target_heading = 748 WHERE zone = 'neighborhood' AND version = 0 AND number = 72 AND id = 1981 AND target_heading = 374; +UPDATE zone_points SET target_heading = 238 WHERE zone = 'neighborhood' AND version = 0 AND number = 73 AND id = 1982 AND target_heading = 119; +UPDATE zone_points SET target_heading = 134 WHERE zone = 'neighborhood' AND version = 0 AND number = 74 AND id = 1983 AND target_heading = 67; +UPDATE zone_points SET target_heading = 712 WHERE zone = 'neighborhood' AND version = 0 AND number = 75 AND id = 1984 AND target_heading = 356; +UPDATE zone_points SET target_heading = 784 WHERE zone = 'neighborhood' AND version = 0 AND number = 76 AND id = 1985 AND target_heading = 392; +UPDATE zone_points SET target_heading = 15.2 WHERE zone = 'feerrott2' AND version = 0 AND number = 0 AND id = 1986 AND target_heading = 7.6; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'feerrott2' AND version = 0 AND number = 15 AND id = 1987 AND target_heading = 0; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'feerrott2' AND version = 0 AND number = 25 AND id = 1988 AND target_heading = 255; +UPDATE zone_points SET target_heading = 910 WHERE zone = 'feerrott2' AND version = 0 AND number = 30 AND id = 1989 AND target_heading = 455; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'feerrott2' AND version = 0 AND number = 40 AND id = 1990 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'feerrott2' AND version = 0 AND number = 100 AND id = 1991 AND target_heading = 999; +UPDATE zone_points SET target_heading = 766 WHERE zone = 'miragulmare' AND version = 0 AND number = 31 AND id = 1992 AND target_heading = 383; +UPDATE zone_points SET target_heading = 16 WHERE zone = 'somnium' AND version = 0 AND number = 0 AND id = 1993 AND target_heading = 8; +UPDATE zone_points SET target_heading = 652 WHERE zone = 'somnium' AND version = 0 AND number = 10 AND id = 1994 AND target_heading = 326; +UPDATE zone_points SET target_heading = 264 WHERE zone = 'somnium' AND version = 0 AND number = 20 AND id = 1995 AND target_heading = 132; +UPDATE zone_points SET target_heading = 768 WHERE zone = 'somnium' AND version = 0 AND number = 30 AND id = 1996 AND target_heading = 384; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'somnium' AND version = 0 AND number = 100 AND id = 1997 AND target_heading = 129; +UPDATE zone_points SET target_heading = 584 WHERE zone = 'thulehouse1' AND version = 0 AND number = 10 AND id = 1998 AND target_heading = 292; +UPDATE zone_points SET target_heading = 402 WHERE zone = 'thulehouse1' AND version = 0 AND number = 19 AND id = 1999 AND target_heading = 201; +UPDATE zone_points SET target_heading = 432 WHERE zone = 'thulehouse1' AND version = 0 AND number = 20 AND id = 2000 AND target_heading = 216; +UPDATE zone_points SET target_heading = 764 WHERE zone = 'thulehouse1' AND version = 0 AND number = 21 AND id = 2001 AND target_heading = 382; +UPDATE zone_points SET target_heading = 120 WHERE zone = 'thulehouse1' AND version = 0 AND number = 40 AND id = 2002 AND target_heading = 60; +UPDATE zone_points SET target_heading = 924 WHERE zone = 'thulehouse1' AND version = 0 AND number = 41 AND id = 2003 AND target_heading = 462; +UPDATE zone_points SET target_heading = 1022 WHERE zone = 'thulehouse1' AND version = 0 AND number = 51 AND id = 2004 AND target_heading = 511; +UPDATE zone_points SET target_heading = 766 WHERE zone = 'thulelibrary' AND version = 0 AND number = 11 AND id = 2005 AND target_heading = 383; +UPDATE zone_points SET target_heading = 127 WHERE zone = 'weddingchapel' AND version = 0 AND number = 1 AND id = 2006 AND target_heading = 63.5; +UPDATE zone_points SET target_heading = 127 WHERE zone = 'weddingchapeldark' AND version = 0 AND number = 1 AND id = 2007 AND target_heading = 63.5; +UPDATE zone_points SET target_heading = 495 WHERE zone = 'well' AND version = 0 AND number = 9 AND id = 2008 AND target_heading = 247.5; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'alkabormare' AND version = 0 AND number = 11 AND id = 2009 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'neighborhood' AND version = 0 AND number = 1 AND id = 2010 AND target_heading = 127; +UPDATE zone_points SET target_heading = 254 WHERE zone = 'neighborhood' AND version = 0 AND number = 10 AND id = 2011 AND target_heading = 127; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND number = 12 AND id = 2012 AND target_heading = 187; +UPDATE zone_points SET target_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND number = 13 AND id = 2013 AND target_heading = 59.5; +UPDATE zone_points SET target_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND number = 14 AND id = 2014 AND target_heading = 33.5; +UPDATE zone_points SET target_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND number = 15 AND id = 2015 AND target_heading = 178; +UPDATE zone_points SET target_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND number = 16 AND id = 2016 AND target_heading = 196; +UPDATE zone_points SET target_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND number = 17 AND id = 2017 AND target_heading = 34.5; +UPDATE zone_points SET target_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND number = 21 AND id = 2018 AND target_heading = 13.5; +UPDATE zone_points SET target_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND number = 23 AND id = 2019 AND target_heading = 59.5; +UPDATE zone_points SET target_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND number = 24 AND id = 2020 AND target_heading = 33.5; +UPDATE zone_points SET target_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND number = 25 AND id = 2021 AND target_heading = 178; +UPDATE zone_points SET target_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND number = 26 AND id = 2022 AND target_heading = 196; +UPDATE zone_points SET target_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND number = 27 AND id = 2023 AND target_heading = 34.5; +UPDATE zone_points SET target_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND number = 31 AND id = 2024 AND target_heading = 13.5; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND number = 32 AND id = 2025 AND target_heading = 187; +UPDATE zone_points SET target_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND number = 34 AND id = 2026 AND target_heading = 33.5; +UPDATE zone_points SET target_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND number = 35 AND id = 2027 AND target_heading = 178; +UPDATE zone_points SET target_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND number = 36 AND id = 2028 AND target_heading = 196; +UPDATE zone_points SET target_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND number = 37 AND id = 2029 AND target_heading = 34.5; +UPDATE zone_points SET target_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND number = 41 AND id = 2030 AND target_heading = 13.5; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND number = 42 AND id = 2031 AND target_heading = 187; +UPDATE zone_points SET target_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND number = 43 AND id = 2032 AND target_heading = 59.5; +UPDATE zone_points SET target_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND number = 45 AND id = 2033 AND target_heading = 178; +UPDATE zone_points SET target_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND number = 46 AND id = 2034 AND target_heading = 196; +UPDATE zone_points SET target_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND number = 47 AND id = 2035 AND target_heading = 34.5; +UPDATE zone_points SET target_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND number = 51 AND id = 2036 AND target_heading = 13.5; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND number = 52 AND id = 2037 AND target_heading = 187; +UPDATE zone_points SET target_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND number = 53 AND id = 2038 AND target_heading = 59.5; +UPDATE zone_points SET target_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND number = 54 AND id = 2039 AND target_heading = 33.5; +UPDATE zone_points SET target_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND number = 56 AND id = 2040 AND target_heading = 196; +UPDATE zone_points SET target_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND number = 57 AND id = 2041 AND target_heading = 34.5; +UPDATE zone_points SET target_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND number = 61 AND id = 2042 AND target_heading = 13.5; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND number = 62 AND id = 2043 AND target_heading = 187; +UPDATE zone_points SET target_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND number = 63 AND id = 2044 AND target_heading = 59.5; +UPDATE zone_points SET target_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND number = 64 AND id = 2045 AND target_heading = 33.5; +UPDATE zone_points SET target_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND number = 65 AND id = 2046 AND target_heading = 178; +UPDATE zone_points SET target_heading = 69 WHERE zone = 'neighborhood' AND version = 0 AND number = 67 AND id = 2047 AND target_heading = 34.5; +UPDATE zone_points SET target_heading = 27 WHERE zone = 'neighborhood' AND version = 0 AND number = 71 AND id = 2048 AND target_heading = 13.5; +UPDATE zone_points SET target_heading = 374 WHERE zone = 'neighborhood' AND version = 0 AND number = 72 AND id = 2049 AND target_heading = 187; +UPDATE zone_points SET target_heading = 119 WHERE zone = 'neighborhood' AND version = 0 AND number = 73 AND id = 2050 AND target_heading = 59.5; +UPDATE zone_points SET target_heading = 67 WHERE zone = 'neighborhood' AND version = 0 AND number = 74 AND id = 2051 AND target_heading = 33.5; +UPDATE zone_points SET target_heading = 356 WHERE zone = 'neighborhood' AND version = 0 AND number = 75 AND id = 2052 AND target_heading = 178; +UPDATE zone_points SET target_heading = 392 WHERE zone = 'neighborhood' AND version = 0 AND number = 76 AND id = 2053 AND target_heading = 196; +UPDATE zone_points SET target_heading = 127 WHERE zone = 'fallen' AND version = 0 AND number = 23 AND id = 2054 AND target_heading = 63.5; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'fallen' AND version = 0 AND number = 32 AND id = 2055 AND target_heading = 255; +UPDATE zone_points SET target_heading = 255 WHERE zone = 'fallen' AND version = 0 AND number = 33 AND id = 2056 AND target_heading = 127.5; +UPDATE zone_points SET target_heading = 7.6 WHERE zone = 'feerrott2' AND version = 0 AND number = 0 AND id = 2057 AND target_heading = 3.8; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'feerrott2' AND version = 0 AND number = 15 AND id = 2058 AND target_heading = 0; +UPDATE zone_points SET target_heading = 255 WHERE zone = 'feerrott2' AND version = 0 AND number = 25 AND id = 2059 AND target_heading = 127.5; +UPDATE zone_points SET target_heading = 455 WHERE zone = 'feerrott2' AND version = 0 AND number = 30 AND id = 2060 AND target_heading = 227.5; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'feerrott2' AND version = 0 AND number = 40 AND id = 2061 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'feerrott2' AND version = 0 AND number = 100 AND id = 2062 AND target_heading = 999; +UPDATE zone_points SET target_heading = 255 WHERE zone = 'housegarden' AND version = 0 AND number = 1 AND id = 2063 AND target_heading = 127.5; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'housegarden' AND version = 0 AND number = 10 AND id = 2064 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'miragulmare' AND version = 0 AND number = 31 AND id = 2065 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 257 WHERE zone = 'morellcastle' AND version = 0 AND number = 0 AND id = 2066 AND target_heading = 128.5; +UPDATE zone_points SET target_heading = 12 WHERE zone = 'morellcastle' AND version = 0 AND number = 10 AND id = 2067 AND target_heading = 6; +UPDATE zone_points SET target_heading = 104 WHERE zone = 'morellcastle' AND version = 0 AND number = 11 AND id = 2068 AND target_heading = 52; +UPDATE zone_points SET target_heading = 127 WHERE zone = 'morellcastle' AND version = 0 AND number = 30 AND id = 2069 AND target_heading = 63.5; +UPDATE zone_points SET target_heading = 127 WHERE zone = 'morellcastle' AND version = 0 AND number = 40 AND id = 2070 AND target_heading = 63.5; +UPDATE zone_points SET target_heading = 8 WHERE zone = 'somnium' AND version = 0 AND number = 0 AND id = 2071 AND target_heading = 4; +UPDATE zone_points SET target_heading = 326 WHERE zone = 'somnium' AND version = 0 AND number = 10 AND id = 2072 AND target_heading = 163; +UPDATE zone_points SET target_heading = 132 WHERE zone = 'somnium' AND version = 0 AND number = 20 AND id = 2073 AND target_heading = 66; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'somnium' AND version = 0 AND number = 30 AND id = 2074 AND target_heading = 192; +UPDATE zone_points SET target_heading = 129 WHERE zone = 'somnium' AND version = 0 AND number = 100 AND id = 2075 AND target_heading = 64.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'thuledream' AND version = 0 AND number = 10 AND id = 2076 AND target_heading = 0; +UPDATE zone_points SET target_heading = 292 WHERE zone = 'thulehouse1' AND version = 0 AND number = 10 AND id = 2077 AND target_heading = 146; +UPDATE zone_points SET target_heading = 201 WHERE zone = 'thulehouse1' AND version = 0 AND number = 19 AND id = 2078 AND target_heading = 100.5; +UPDATE zone_points SET target_heading = 216 WHERE zone = 'thulehouse1' AND version = 0 AND number = 20 AND id = 2079 AND target_heading = 108; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'thulehouse1' AND version = 0 AND number = 21 AND id = 2080 AND target_heading = 191; +UPDATE zone_points SET target_heading = 60 WHERE zone = 'thulehouse1' AND version = 0 AND number = 40 AND id = 2081 AND target_heading = 30; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'thulehouse1' AND version = 0 AND number = 41 AND id = 2082 AND target_heading = 231; +UPDATE zone_points SET target_heading = 511 WHERE zone = 'thulehouse1' AND version = 0 AND number = 51 AND id = 2083 AND target_heading = 255.5; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'thulehouse2' AND version = 0 AND number = 10 AND id = 2084 AND target_heading = 27; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'thulehouse2' AND version = 0 AND number = 20 AND id = 2085 AND target_heading = 27; +UPDATE zone_points SET target_heading = 54 WHERE zone = 'thulehouse2' AND version = 0 AND number = 30 AND id = 2086 AND target_heading = 27; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'thulehouse2' AND version = 0 AND number = 51 AND id = 2087 AND target_heading = 64; +UPDATE zone_points SET target_heading = 440 WHERE zone = 'thulehouse2' AND version = 0 AND number = 61 AND id = 2088 AND target_heading = 220; +UPDATE zone_points SET target_heading = 82 WHERE zone = 'thulehouse2' AND version = 0 AND number = 72 AND id = 2089 AND target_heading = 41; +UPDATE zone_points SET target_heading = 498 WHERE zone = 'thulehouse2' AND version = 0 AND number = 82 AND id = 2090 AND target_heading = 249; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'thulelibrary' AND version = 0 AND number = 11 AND id = 2091 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 23 WHERE zone = 'solteris' AND version = 0 AND number = 80 AND id = 2092 AND target_heading = 11.5; +UPDATE zone_points SET target_heading = 192 WHERE zone = 'discordtower' AND version = 0 AND number = 1 AND id = 2093 AND target_heading = 96; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'natimbi' AND version = 0 AND number = 10 AND id = 2094 AND target_heading = 64; +UPDATE zone_points SET target_heading = 163 WHERE zone = 'argath' AND version = 0 AND number = 10 AND id = 2095 AND target_heading = 81.5; +UPDATE zone_points SET target_heading = 65 WHERE zone = 'argath' AND version = 0 AND number = 20 AND id = 2096 AND target_heading = 32.5; +UPDATE zone_points SET target_heading = 115 WHERE zone = 'arelis' AND version = 0 AND number = 10 AND id = 2097 AND target_heading = 57.5; +UPDATE zone_points SET target_heading = 35 WHERE zone = 'arelis' AND version = 0 AND number = 20 AND id = 2098 AND target_heading = 17.5; +UPDATE zone_points SET target_heading = 47 WHERE zone = 'arelis' AND version = 0 AND number = 40 AND id = 2099 AND target_heading = 23.5; +UPDATE zone_points SET target_heading = 190 WHERE zone = 'beastdomain' AND version = 0 AND number = 10 AND id = 2100 AND target_heading = 95; +UPDATE zone_points SET target_heading = 100 WHERE zone = 'resplendent' AND version = 0 AND number = 10 AND id = 2101 AND target_heading = 50; +UPDATE zone_points SET target_heading = 510 WHERE zone = 'resplendent' AND version = 0 AND number = 20 AND id = 2102 AND target_heading = 255; +UPDATE zone_points SET target_heading = 137 WHERE zone = 'resplendent' AND version = 0 AND number = 30 AND id = 2103 AND target_heading = 68.5; +UPDATE zone_points SET target_heading = 180 WHERE zone = 'resplendent' AND version = 0 AND number = 40 AND id = 2104 AND target_heading = 90; +UPDATE zone_points SET target_heading = 47 WHERE zone = 'sarithcity' AND version = 0 AND number = 10 AND id = 2105 AND target_heading = 23.5; +UPDATE zone_points SET target_heading = 5 WHERE zone = 'sarithcity' AND version = 0 AND number = 20 AND id = 2106 AND target_heading = 2.5; +UPDATE zone_points SET target_heading = 65 WHERE zone = 'sarithcity' AND version = 0 AND number = 30 AND id = 2107 AND target_heading = 32.5; +UPDATE zone_points SET target_heading = 330 WHERE zone = 'sarithcity' AND version = 0 AND number = 40 AND id = 2108 AND target_heading = 165; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'cityofbronze' AND version = 0 AND number = 10 AND id = 2109 AND target_heading = 0; +UPDATE zone_points SET target_heading = 397 WHERE zone = 'cityofbronze' AND version = 0 AND number = 20 AND id = 2110 AND target_heading = 198.5; +UPDATE zone_points SET target_heading = 230 WHERE zone = 'cityofbronze' AND version = 0 AND number = 30 AND id = 2111 AND target_heading = 115; +UPDATE zone_points SET target_heading = 127.1 WHERE zone = 'sepulcher' AND version = 0 AND number = 10 AND id = 2112 AND target_heading = 63.55; +UPDATE zone_points SET target_heading = 382.09 WHERE zone = 'sepulcher' AND version = 0 AND number = 20 AND id = 2113 AND target_heading = 191.045; +UPDATE zone_points SET target_heading = 300.12 WHERE zone = 'sepulcher' AND version = 0 AND number = 30 AND id = 2114 AND target_heading = 150.06; +UPDATE zone_points SET target_heading = 511.25 WHERE zone = 'sepulcher' AND version = 0 AND number = 40 AND id = 2115 AND target_heading = 255.625; +UPDATE zone_points SET target_heading = 317.54 WHERE zone = 'sepulcher' AND version = 0 AND number = 50 AND id = 2116 AND target_heading = 158.77; +UPDATE zone_points SET target_heading = 124.43 WHERE zone = 'sepulcher' AND version = 0 AND number = 60 AND id = 2117 AND target_heading = 62.215; +UPDATE zone_points SET target_heading = 129.45 WHERE zone = 'sepulcher' AND version = 0 AND number = 70 AND id = 2118 AND target_heading = 64.725; +UPDATE zone_points SET target_heading = 511.72 WHERE zone = 'sepulcher' AND version = 0 AND number = 80 AND id = 2119 AND target_heading = 255.86; +UPDATE zone_points SET target_heading = 193.78 WHERE zone = 'sepulcher' AND version = 0 AND number = 90 AND id = 2120 AND target_heading = 96.89; +UPDATE zone_points SET target_heading = 170 WHERE zone = 'pillarsalra' AND version = 0 AND number = 1 AND id = 2121 AND target_heading = 85; +UPDATE zone_points SET target_heading = 245 WHERE zone = 'pillarsalra' AND version = 0 AND number = 2 AND id = 2122 AND target_heading = 122.5; +UPDATE zone_points SET target_heading = 182 WHERE zone = 'pillarsalra' AND version = 0 AND number = 3 AND id = 2123 AND target_heading = 91; +UPDATE zone_points SET target_heading = 273 WHERE zone = 'pillarsalra' AND version = 0 AND number = 4 AND id = 2124 AND target_heading = 136.5; +UPDATE zone_points SET target_heading = 42 WHERE zone = 'pillarsalra' AND version = 0 AND number = 5 AND id = 2125 AND target_heading = 21; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 6 AND id = 2126 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 410 WHERE zone = 'pillarsalra' AND version = 0 AND number = 7 AND id = 2127 AND target_heading = 205; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 8 AND id = 2128 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 9 AND id = 2129 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 122 WHERE zone = 'pillarsalra' AND version = 0 AND number = 10 AND id = 2130 AND target_heading = 61; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 11 AND id = 2131 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 12 AND id = 2132 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 13 AND id = 2133 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 14 AND id = 2134 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'pillarsalra' AND version = 0 AND number = 15 AND id = 2135 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 277 WHERE zone = 'pillarsalra' AND version = 0 AND number = 20 AND id = 2136 AND target_heading = 138.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'windsong' AND version = 0 AND number = 11 AND id = 2137 AND target_heading = 0; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'windsong' AND version = 0 AND number = 100 AND id = 2138 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 255.54 WHERE zone = 'eastsepulcher' AND version = 0 AND number = 10 AND id = 2139 AND target_heading = 127.77; +UPDATE zone_points SET target_heading = 128.92 WHERE zone = 'eastsepulcher' AND version = 0 AND number = 20 AND id = 2140 AND target_heading = 64.46; +UPDATE zone_points SET target_heading = 64.22 WHERE zone = 'eastsepulcher' AND version = 0 AND number = 30 AND id = 2141 AND target_heading = 32.11; +UPDATE zone_points SET target_heading = 126.99 WHERE zone = 'eastsepulcher' AND version = 0 AND number = 40 AND id = 2142 AND target_heading = 63.495; +UPDATE zone_points SET target_heading = 168.79 WHERE zone = 'eastsepulcher' AND version = 0 AND number = 50 AND id = 2143 AND target_heading = 84.395; +UPDATE zone_points SET target_heading = 490.31 WHERE zone = 'eastsepulcher' AND version = 0 AND number = 60 AND id = 2144 AND target_heading = 245.155; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 0 AND id = 2145 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 10 AND id = 2146 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 20 AND id = 2147 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 30 AND id = 2148 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 40 AND id = 2149 AND target_heading = 0; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 50 AND id = 2150 AND target_heading = 63; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 60 AND id = 2151 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 70 AND id = 2152 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 80 AND id = 2153 AND target_heading = 128; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 90 AND id = 2154 AND target_heading = 63; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 100 AND id = 2155 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 110 AND id = 2156 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 120 AND id = 2157 AND target_heading = 0; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 130 AND id = 2158 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 140 AND id = 2159 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 150 AND id = 2160 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 160 AND id = 2161 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 170 AND id = 2162 AND target_heading = 0; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 180 AND id = 2163 AND target_heading = 63; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 190 AND id = 2164 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 200 AND id = 2165 AND target_heading = 0; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 210 AND id = 2166 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 220 AND id = 2167 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 230 AND id = 2168 AND target_heading = 0; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 240 AND id = 2169 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 250 AND id = 2170 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 260 AND id = 2171 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 270 AND id = 2172 AND target_heading = 128; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 280 AND id = 2173 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 290 AND id = 2174 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 300 AND id = 2175 AND target_heading = 63; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 310 AND id = 2176 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 320 AND id = 2177 AND target_heading = 0; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 330 AND id = 2178 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 340 AND id = 2179 AND target_heading = 63; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 350 AND id = 2180 AND target_heading = 0; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 360 AND id = 2181 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 370 AND id = 2182 AND target_heading = 128; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 380 AND id = 2183 AND target_heading = 63; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 390 AND id = 2184 AND target_heading = 128; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 400 AND id = 2185 AND target_heading = 63; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 410 AND id = 2186 AND target_heading = 0; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 420 AND id = 2187 AND target_heading = 63; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 430 AND id = 2188 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 440 AND id = 2189 AND target_heading = 0; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 450 AND id = 2190 AND target_heading = 63; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 460 AND id = 2191 AND target_heading = 63; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 470 AND id = 2192 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 480 AND id = 2193 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 490 AND id = 2194 AND target_heading = 128; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 500 AND id = 2195 AND target_heading = 128; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 510 AND id = 2196 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 520 AND id = 2197 AND target_heading = 0; +UPDATE zone_points SET target_heading = 383 WHERE zone = 'westsepulcher' AND version = 0 AND number = 530 AND id = 2198 AND target_heading = 191.5; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 540 AND id = 2199 AND target_heading = 63; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 550 AND id = 2200 AND target_heading = 63; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 560 AND id = 2201 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 570 AND id = 2202 AND target_heading = 128; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 580 AND id = 2203 AND target_heading = 0; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 590 AND id = 2204 AND target_heading = 63; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 600 AND id = 2205 AND target_heading = 0; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'westsepulcher' AND version = 0 AND number = 610 AND id = 2206 AND target_heading = 128; +UPDATE zone_points SET target_heading = 126 WHERE zone = 'westsepulcher' AND version = 0 AND number = 620 AND id = 2207 AND target_heading = 63; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'westsepulcher' AND version = 0 AND number = 630 AND id = 2208 AND target_heading = 0; +UPDATE zone_points SET target_heading = 385.03 WHERE zone = 'westsepulcher' AND version = 0 AND number = 640 AND id = 2209 AND target_heading = 192.515; +UPDATE zone_points SET target_heading = 381.19 WHERE zone = 'westsepulcher' AND version = 0 AND number = 650 AND id = 2210 AND target_heading = 190.595; +UPDATE zone_points SET target_heading = 252.44 WHERE zone = 'westsepulcher' AND version = 0 AND number = 660 AND id = 2211 AND target_heading = 126.22; +UPDATE zone_points SET target_heading = 370.49 WHERE zone = 'westsepulcher' AND version = 0 AND number = 670 AND id = 2212 AND target_heading = 185.245; +UPDATE zone_points SET target_heading = 448.26 WHERE zone = 'westsepulcher' AND version = 0 AND number = 690 AND id = 2213 AND target_heading = 224.13; +UPDATE zone_points SET target_heading = 317.24 WHERE zone = 'westsepulcher' AND version = 0 AND number = 710 AND id = 2214 AND target_heading = 158.62; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'bazaar' AND version = 1 AND number = 1 AND id = 2215 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'bazaar' AND version = 1 AND number = 2 AND id = 2216 AND target_heading = 999; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'bazaar' AND version = 1 AND number = 3 AND id = 2217 AND target_heading = 999; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'nexus' AND version = 0 AND number = 4 AND id = 2218 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shadowhaven' AND version = 0 AND number = 8 AND id = 2219 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shadowhaven' AND version = 0 AND number = 9 AND id = 2220 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'paineel' AND version = 0 AND number = 15 AND id = 2243 AND target_heading = 0; +UPDATE zone_points SET target_heading = 65 WHERE zone = 'brellstemple' AND version = 0 AND number = 10 AND id = 2244 AND target_heading = 32.5; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 40 AND id = 2245 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 50 AND id = 2246 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 60 AND id = 2247 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 70 AND id = 2248 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 80 AND id = 2249 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 90 AND id = 2250 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 100 AND id = 2251 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 110 AND id = 2252 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 120 AND id = 2253 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 130 AND id = 2254 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 140 AND id = 2255 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 150 AND id = 2256 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 160 AND id = 2257 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 170 AND id = 2258 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 180 AND id = 2259 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 1000000 WHERE zone = 'lichencreep' AND version = 0 AND number = 190 AND id = 2260 AND target_heading = 500000; +UPDATE zone_points SET target_heading = 385 WHERE zone = 'shiningcity' AND version = 0 AND number = 10 AND id = 2261 AND target_heading = 192.5; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 1 AND number = 1 AND id = 2262 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 2 AND id = 2263 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 3 AND id = 2264 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 4 AND id = 2265 AND target_heading = 250; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 5 AND id = 2266 AND target_heading = 250; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 6 AND id = 2267 AND target_heading = 250; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 1 AND number = 7 AND id = 2268 AND target_heading = 125; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 1 AND number = 8 AND id = 2269 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0.2 WHERE zone = 'skyshrine' AND version = 1 AND number = 9 AND id = 2270 AND target_heading = 0.1; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 10 AND id = 2271 AND target_heading = 250; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 11 AND id = 2272 AND target_heading = 250; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'skyshrine' AND version = 1 AND number = 12 AND id = 2273 AND target_heading = 125; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 13 AND id = 2274 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 14 AND id = 2275 AND target_heading = 250; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 15 AND id = 2276 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 16 AND id = 2277 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 17 AND id = 2278 AND target_heading = 250; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'skyshrine' AND version = 1 AND number = 18 AND id = 2279 AND target_heading = 129; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 19 AND id = 2280 AND target_heading = 0; +UPDATE zone_points SET target_heading = 500 WHERE zone = 'skyshrine' AND version = 1 AND number = 20 AND id = 2281 AND target_heading = 250; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 21 AND id = 2282 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 22 AND id = 2283 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND number = 23 AND id = 2284 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 24 AND id = 2285 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND number = 30 AND id = 2286 AND target_heading = 231; +UPDATE zone_points SET target_heading = 10 WHERE zone = 'skyshrine' AND version = 1 AND number = 40 AND id = 2287 AND target_heading = 5; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND number = 41 AND id = 2288 AND target_heading = 231; +UPDATE zone_points SET target_heading = 258 WHERE zone = 'skyshrine' AND version = 1 AND number = 42 AND id = 2289 AND target_heading = 129; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND number = 43 AND id = 2290 AND target_heading = 231; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND number = 44 AND id = 2291 AND target_heading = 231; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'skyshrine' AND version = 1 AND number = 45 AND id = 2292 AND target_heading = 0; +UPDATE zone_points SET target_heading = 462 WHERE zone = 'skyshrine' AND version = 1 AND number = 46 AND id = 2293 AND target_heading = 231; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'skyshrine' AND version = 1 AND number = 50 AND id = 2294 AND target_heading = 254; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'kurn' AND version = 0 AND number = 3 AND id = 2295 AND target_heading = 0; +UPDATE zone_points SET target_heading = 485 WHERE zone = 'breedinggrounds' AND version = 0 AND number = 101 AND id = 2296 AND target_heading = 242.5; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'breedinggrounds' AND version = 0 AND number = 102 AND id = 2297 AND target_heading = 254; +UPDATE zone_points SET target_heading = 312 WHERE zone = 'chapterhouse' AND version = 0 AND number = 101 AND id = 2298 AND target_heading = 156; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'chapterhouse' AND version = 0 AND number = 1183 AND id = 2299 AND target_heading = 0; +UPDATE zone_points SET target_heading = 505 WHERE zone = 'crystalshard' AND version = 0 AND number = 1 AND id = 2300 AND target_heading = 252.5; +UPDATE zone_points SET target_heading = 372 WHERE zone = 'crystalshard' AND version = 0 AND number = 2 AND id = 2301 AND target_heading = 186; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 1 AND id = 2302 AND target_heading = 999; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 2 AND id = 2303 AND target_heading = 64; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 3 AND id = 2304 AND target_heading = 999; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 5 AND id = 2305 AND target_heading = 192; +UPDATE zone_points SET target_heading = 384 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 5 AND id = 2306 AND target_heading = 192; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 13 AND id = 2307 AND target_heading = 64; +UPDATE zone_points SET target_heading = 426 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 101 AND id = 2308 AND target_heading = 213; +UPDATE zone_points SET target_heading = 15 WHERE zone = 'eastwastesshard' AND version = 0 AND number = 1181 AND id = 2309 AND target_heading = 7.5; +UPDATE zone_points SET target_heading = 255 WHERE zone = 'eviltree' AND version = 0 AND number = 20 AND id = 2310 AND target_heading = 127.5; +UPDATE zone_points SET target_heading = 220 WHERE zone = 'eviltree' AND version = 0 AND number = 30 AND id = 2311 AND target_heading = 110; +UPDATE zone_points SET target_heading = 268 WHERE zone = 'eviltree' AND version = 0 AND number = 40 AND id = 2312 AND target_heading = 134; +UPDATE zone_points SET target_heading = 145 WHERE zone = 'eviltree' AND version = 0 AND number = 101 AND id = 2313 AND target_heading = 72.5; +UPDATE zone_points SET target_heading = 427 WHERE zone = 'eviltree' AND version = 0 AND number = 1182 AND id = 2314 AND target_heading = 213.5; +UPDATE zone_points SET target_heading = 314 WHERE zone = 'grelleth' AND version = 0 AND number = 51 AND id = 2315 AND target_heading = 157; +UPDATE zone_points SET target_heading = 75 WHERE zone = 'grelleth' AND version = 0 AND number = 52 AND id = 2316 AND target_heading = 37.5; +UPDATE zone_points SET target_heading = 86 WHERE zone = 'grelleth' AND version = 0 AND number = 101 AND id = 2317 AND target_heading = 43; +UPDATE zone_points SET target_heading = 382 WHERE zone = 'kaelshard' AND version = 0 AND number = 2 AND id = 2318 AND target_heading = 191; +UPDATE zone_points SET target_heading = 210 WHERE zone = 'shardslanding' AND version = 0 AND number = 10 AND id = 2319 AND target_heading = 105; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'shardslanding' AND version = 0 AND number = 101 AND id = 2320 AND target_heading = 64; +UPDATE zone_points SET target_heading = 507 WHERE zone = 'shardslanding' AND version = 0 AND number = 102 AND id = 2321 AND target_heading = 253.5; +UPDATE zone_points SET target_heading = 29 WHERE zone = 'shardslanding' AND version = 0 AND number = 103 AND id = 2322 AND target_heading = 14.5; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shardslanding' AND version = 0 AND number = 104 AND id = 2323 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shardslanding' AND version = 0 AND number = 105 AND id = 2324 AND target_heading = 0; +UPDATE zone_points SET target_heading = 66 WHERE zone = 'shardslanding' AND version = 0 AND number = 106 AND id = 2325 AND target_heading = 33; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shardslanding' AND version = 0 AND number = 107 AND id = 2326 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shardslanding' AND version = 0 AND number = 108 AND id = 2327 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shardslanding' AND version = 0 AND number = 109 AND id = 2328 AND target_heading = 0; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'shardslanding' AND version = 0 AND number = 110 AND id = 2329 AND target_heading = 0; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'shardslanding' AND version = 0 AND number = 111 AND id = 2330 AND target_heading = 125; +UPDATE zone_points SET target_heading = 34 WHERE zone = 'shardslanding' AND version = 0 AND number = 112 AND id = 2331 AND target_heading = 17; +UPDATE zone_points SET target_heading = 200 WHERE zone = 'shardslanding' AND version = 0 AND number = 113 AND id = 2332 AND target_heading = 100; +UPDATE zone_points SET target_heading = 200 WHERE zone = 'shardslanding' AND version = 0 AND number = 114 AND id = 2333 AND target_heading = 100; +UPDATE zone_points SET target_heading = 366 WHERE zone = 'xorbb' AND version = 0 AND number = 101 AND id = 2334 AND target_heading = 183; +UPDATE zone_points SET target_heading = 321 WHERE zone = 'xorbb' AND version = 0 AND number = 2935 AND id = 2335 AND target_heading = 160.5; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'runnyeye' AND version = 0 AND number = 2 AND id = 2336 AND target_heading = 999; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'rivervale' AND version = 0 AND number = 99 AND id = 2337 AND target_heading = 0; +UPDATE zone_points SET target_heading = 203 WHERE zone = 'nektulos' AND version = 1 AND number = 30 AND id = 2339 AND target_heading = 101.5; +UPDATE zone_points SET target_heading = 273 WHERE zone = 'kithicor' AND version = 0 AND number = 3 AND id = 2340 AND target_heading = 136.5; +UPDATE zone_points SET target_heading = 225 WHERE zone = 'grobb' AND version = 0 AND number = 1 AND id = 2341 AND target_heading = 112.5; +UPDATE zone_points SET target_heading = 508 WHERE zone = 'guktop' AND version = 0 AND number = 6 AND id = 2342 AND target_heading = 254; +UPDATE zone_points SET target_heading = 455 WHERE zone = 'feerrott' AND version = 0 AND number = 1 AND id = 2343 AND target_heading = 227.5; +UPDATE zone_points SET target_heading = 509 WHERE zone = 'paineel' AND version = 0 AND number = 1 AND id = 2344 AND target_heading = 254.5; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'erudnext' AND version = 0 AND number = 3 AND id = 2345 AND target_heading = 999; +UPDATE zone_points SET target_heading = 128 WHERE zone = 'akanon' AND version = 0 AND number = 1000 AND id = 2346 AND target_heading = 64; +UPDATE zone_points SET target_heading = 415 WHERE zone = 'lfaydark' AND version = 0 AND number = 1 AND id = 2347 AND target_heading = 207.5; +UPDATE zone_points SET target_heading = 495 WHERE zone = 'befallen' AND version = 0 AND number = 1 AND id = 2348 AND target_heading = 247.5; +UPDATE zone_points SET target_heading = 1998 WHERE zone = 'paw' AND version = 0 AND number = 1 AND id = 2349 AND target_heading = 999; +UPDATE zone_points SET target_heading = 0 WHERE zone = 'ecommons' AND version = 0 AND number = 2 AND id = 2350 AND target_heading = 0; +UPDATE zone_points SET target_heading = 260 WHERE zone = 'vexthal' AND version = 0 AND number = 6 AND id = 2351 AND target_heading = 130; +UPDATE zone_points SET target_heading = 2 WHERE zone = 'vexthal' AND version = 0 AND number = 35 AND id = 2352 AND target_heading = 1; +UPDATE zone_points SET target_heading = 516 WHERE zone = 'vexthal' AND version = 0 AND number = 36 AND id = 2353 AND target_heading = 258; +UPDATE zone_points SET target_heading = 526 WHERE zone = 'vexthal' AND version = 0 AND number = 37 AND id = 2354 AND target_heading = 263; +UPDATE zone_points SET target_heading = 1016 WHERE zone = 'vexthal' AND version = 0 AND number = 38 AND id = 2355 AND target_heading = 508; +UPDATE zone_points SET target_heading = 256 WHERE zone = 'vexthal' AND version = 0 AND number = 39 AND id = 2356 AND target_heading = 128; +UPDATE zone_points SET target_heading = 250 WHERE zone = 'vexthal' AND version = 0 AND number = 40 AND id = 2357 AND target_heading = 125; +UPDATE zone_points SET target_heading = 764 WHERE zone = 'vexthal' AND version = 0 AND number = 41 AND id = 2358 AND target_heading = 382; +UPDATE zone_points SET target_heading = 764 WHERE zone = 'vexthal' AND version = 0 AND number = 42 AND id = 2359 AND target_heading = 382; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND number = 43 AND id = 2360 AND target_heading = 126; +UPDATE zone_points SET target_heading = 252 WHERE zone = 'vexthal' AND version = 0 AND number = 44 AND id = 2361 AND target_heading = 126; +UPDATE zone_points SET target_heading = 526 WHERE zone = 'vexthal' AND version = 0 AND number = 45 AND id = 2362 AND target_heading = 263; +UPDATE zone_points SET target_heading = 1016 WHERE zone = 'vexthal' AND version = 0 AND number = 46 AND id = 2363 AND target_heading = 508; +UPDATE zone_points SET target_heading = 764 WHERE zone = 'vexthal' AND version = 0 AND number = 48 AND id = 2364 AND target_heading = 382; +UPDATE zone_points SET target_heading = 764 WHERE zone = 'vexthal' AND version = 0 AND number = 49 AND id = 2365 AND target_heading = 382; +UPDATE zone_points SET target_heading = 506 WHERE zone = 'vexthal' AND version = 0 AND number = 47 AND id = 2366 AND target_heading = 253; + +UPDATE zone_points SET target_heading = 250 WHERE id = 473; -- qeynos (4) +UPDATE zone_points SET target_heading = 250 WHERE id = 477; -- qeynos2 (2) +UPDATE zone_points SET target_heading = 384 WHERE id = 478; -- qeynos2 (4) +UPDATE zone_points SET target_heading = 383 WHERE id = 482; -- qeynos2 (77) +UPDATE zone_points SET target_heading = 128 WHERE id = 538; -- qrg (7) +UPDATE zone_points SET target_heading = 258 WHERE id = 391; -- freportw (177) +UPDATE zone_points SET target_heading = 128 WHERE id = 14; -- commons (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 615; -- greatdivide (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 769; -- tox (0) +UPDATE zone_points SET target_heading = 340 WHERE id = 804; -- blackburrow (7) +UPDATE zone_points SET target_heading = 128 WHERE id = 14; -- commons (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 615; -- greatdivide (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 769; -- tox (0) +UPDATE zone_points SET target_heading = 506 WHERE id = 1476; -- nektulos (10) +UPDATE zone_points SET target_heading = 145 WHERE id = 1477; -- nektulos (20) +UPDATE zone_points SET target_heading = 256 WHERE id = 1479; -- nektulos (50) +UPDATE zone_points SET target_heading = 257 WHERE id = 1447; -- nektulos (77) +UPDATE zone_points SET target_heading = 257 WHERE id = 1480; -- nektulos (77) +UPDATE zone_points SET target_heading = 478 WHERE id = 1876; -- lavastorm (10) +UPDATE zone_points SET target_heading = 165 WHERE id = 1881; -- lavastorm (60) +UPDATE zone_points SET target_heading = 511 WHERE id = 594; -- everfrost (77) +UPDATE zone_points SET target_heading = 256 WHERE id = 1155; -- soldungb (9) +UPDATE zone_points SET target_heading = 322 WHERE id = 689; -- nro (4) +UPDATE zone_points SET target_heading = 384 WHERE id = 1240; -- hole (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 1241; -- hole (4) +UPDATE zone_points SET target_heading = 384 WHERE id = 1242; -- hole (5) +UPDATE zone_points SET target_heading = 252 WHERE id = 420; -- neriakc (2) +UPDATE zone_points SET target_heading = 275 WHERE id = 490; -- qcat (7) +UPDATE zone_points SET target_heading = 2 WHERE id = 342; -- gfaydark (177) +UPDATE zone_points SET target_heading = 380 WHERE id = 343; -- gfaydark (178) +UPDATE zone_points SET target_heading = 226 WHERE id = 666; -- lfaydark (9) +UPDATE zone_points SET target_heading = 0 WHERE id = 399; -- kaladima (2) +UPDATE zone_points SET target_heading = 0 WHERE id = 400; -- kaladima (3) +UPDATE zone_points SET target_heading = 176 WHERE id = 371; -- felwitheb (2) +UPDATE zone_points SET target_heading = 43 WHERE id = 372; -- felwitheb (3) +UPDATE zone_points SET target_heading = 469 WHERE id = 373; -- felwitheb (4) +UPDATE zone_points SET target_heading = 494 WHERE id = 374; -- felwitheb (5) +UPDATE zone_points SET target_heading = 494 WHERE id = 375; -- felwitheb (6) +UPDATE zone_points SET target_heading = 494 WHERE id = 376; -- felwitheb (7) +UPDATE zone_points SET target_heading = 360 WHERE id = 851; -- guktop (1) +UPDATE zone_points SET target_heading = 419 WHERE id = 852; -- guktop (2) +UPDATE zone_points SET target_heading = 165 WHERE id = 858; -- gukbottom (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 402; -- kaladimb (2) +UPDATE zone_points SET target_heading = 511 WHERE id = 552; -- butcher (77) +UPDATE zone_points SET target_heading = 483 WHERE id = 1269; -- paineel (2) +UPDATE zone_points SET target_heading = 388 WHERE id = 1270; -- paineel (3) +UPDATE zone_points SET target_heading = 128 WHERE id = 1273; -- paineel (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 1274; -- paineel (11) +UPDATE zone_points SET target_heading = 0 WHERE id = 1276; -- paineel (13) +UPDATE zone_points SET target_heading = 510 WHERE id = 1872; -- arena (10) +UPDATE zone_points SET target_heading = 1 WHERE id = 1227; -- fieldofbone (77) +UPDATE zone_points SET target_heading = 260 WHERE id = 1319; -- warslikswood (4) +UPDATE zone_points SET target_heading = 383 WHERE id = 1232; -- firiona (77) +UPDATE zone_points SET target_heading = 176 WHERE id = 1252; -- lakeofillomen (1) +UPDATE zone_points SET target_heading = 4 WHERE id = 1258; -- lakeofillomen (7) +UPDATE zone_points SET target_heading = 128 WHERE id = 14; -- commons (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 615; -- greatdivide (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 769; -- tox (0) +UPDATE zone_points SET target_heading = 384 WHERE id = 1178; -- burningwood (4) +UPDATE zone_points SET target_heading = 380 WHERE id = 1246; -- kaesora (1) +UPDATE zone_points SET target_heading = 256 WHERE id = 1279; -- sebilis (1) +UPDATE zone_points SET target_heading = 256 WHERE id = 1280; -- sebilis (2) +UPDATE zone_points SET target_heading = 384 WHERE id = 1199; -- citymist (1) +UPDATE zone_points SET target_heading = 384 WHERE id = 1200; -- citymist (2) +UPDATE zone_points SET target_heading = 384 WHERE id = 1233; -- frontiermtns (1) +UPDATE zone_points SET target_heading = 384 WHERE id = 1262; -- overthere (1) +UPDATE zone_points SET target_heading = 254 WHERE id = 1267; -- overthere (77) +UPDATE zone_points SET target_heading = 128 WHERE id = 1215; -- emeraldjungle (2) +UPDATE zone_points SET target_heading = 128 WHERE id = 1216; -- emeraldjungle (3) +UPDATE zone_points SET target_heading = 257 WHERE id = 1307; -- trakanon (3) +UPDATE zone_points SET target_heading = 504 WHERE id = 2295; -- kurn (3) +UPDATE zone_points SET target_heading = 511 WHERE id = 1285; -- stonebrunt (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 1286; -- stonebrunt (5) +UPDATE zone_points SET target_heading = 251 WHERE id = 1314; -- warrens (2) +UPDATE zone_points SET target_heading = 107 WHERE id = 1315; -- warrens (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 1198; -- chardok (2) +UPDATE zone_points SET target_heading = 60 WHERE id = 1201; -- dalnir (1) +UPDATE zone_points SET target_heading = 60 WHERE id = 1202; -- dalnir (2) +UPDATE zone_points SET target_heading = 60 WHERE id = 1203; -- dalnir (99) +UPDATE zone_points SET target_heading = 306 WHERE id = 1179; -- cabeast (1) +UPDATE zone_points SET target_heading = 47 WHERE id = 1180; -- cabeast (2) +UPDATE zone_points SET target_heading = 193 WHERE id = 1181; -- cabeast (3) +UPDATE zone_points SET target_heading = 446 WHERE id = 1182; -- cabeast (4) +UPDATE zone_points SET target_heading = 260 WHERE id = 1183; -- cabeast (9) +UPDATE zone_points SET target_heading = 257 WHERE id = 1184; -- cabeast (10) +UPDATE zone_points SET target_heading = 128 WHERE id = 1312; -- veksar (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 1313; -- veksar (2) +UPDATE zone_points SET target_heading = 145 WHERE id = 639; -- iceclad (9) +UPDATE zone_points SET target_heading = 0 WHERE id = 826; -- frozenshadow (2) +UPDATE zone_points SET target_heading = 0 WHERE id = 827; -- frozenshadow (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 828; -- frozenshadow (4) +UPDATE zone_points SET target_heading = 0 WHERE id = 829; -- frozenshadow (5) +UPDATE zone_points SET target_heading = 0 WHERE id = 830; -- frozenshadow (6) +UPDATE zone_points SET target_heading = 256 WHERE id = 831; -- frozenshadow (7) +UPDATE zone_points SET target_heading = 0 WHERE id = 832; -- frozenshadow (8) +UPDATE zone_points SET target_heading = 0 WHERE id = 833; -- frozenshadow (9) +UPDATE zone_points SET target_heading = 0 WHERE id = 834; -- frozenshadow (10) +UPDATE zone_points SET target_heading = 0 WHERE id = 835; -- frozenshadow (11) +UPDATE zone_points SET target_heading = 256 WHERE id = 836; -- frozenshadow (12) +UPDATE zone_points SET target_heading = 0 WHERE id = 837; -- frozenshadow (13) +UPDATE zone_points SET target_heading = 0 WHERE id = 838; -- frozenshadow (14) +UPDATE zone_points SET target_heading = 384 WHERE id = 839; -- frozenshadow (15) +UPDATE zone_points SET target_heading = 0 WHERE id = 840; -- frozenshadow (16) +UPDATE zone_points SET target_heading = 0 WHERE id = 841; -- frozenshadow (17) +UPDATE zone_points SET target_heading = 0 WHERE id = 842; -- frozenshadow (18) +UPDATE zone_points SET target_heading = 0 WHERE id = 843; -- frozenshadow (19) +UPDATE zone_points SET target_heading = 348 WHERE id = 844; -- frozenshadow (20) +UPDATE zone_points SET target_heading = 395 WHERE id = 972; -- velketor (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 879; -- kael (1) +UPDATE zone_points SET target_heading = 381 WHERE id = 880; -- kael (2) +UPDATE zone_points SET target_heading = 125 WHERE id = 922; -- skyshrine (1) +UPDATE zone_points SET target_heading = 125 WHERE id = 2262; -- skyshrine (1) +UPDATE zone_points SET target_heading = 250 WHERE id = 925; -- skyshrine (4) +UPDATE zone_points SET target_heading = 250 WHERE id = 2265; -- skyshrine (4) +UPDATE zone_points SET target_heading = 250 WHERE id = 926; -- skyshrine (5) +UPDATE zone_points SET target_heading = 250 WHERE id = 2266; -- skyshrine (5) +UPDATE zone_points SET target_heading = 250 WHERE id = 927; -- skyshrine (6) +UPDATE zone_points SET target_heading = 250 WHERE id = 2267; -- skyshrine (6) +UPDATE zone_points SET target_heading = 125 WHERE id = 928; -- skyshrine (7) +UPDATE zone_points SET target_heading = 125 WHERE id = 2268; -- skyshrine (7) +UPDATE zone_points SET target_heading = 125 WHERE id = 929; -- skyshrine (8) +UPDATE zone_points SET target_heading = 125 WHERE id = 2269; -- skyshrine (8) +UPDATE zone_points SET target_heading = 250 WHERE id = 931; -- skyshrine (10) +UPDATE zone_points SET target_heading = 250 WHERE id = 2271; -- skyshrine (10) +UPDATE zone_points SET target_heading = 250 WHERE id = 932; -- skyshrine (11) +UPDATE zone_points SET target_heading = 250 WHERE id = 2272; -- skyshrine (11) +UPDATE zone_points SET target_heading = 125 WHERE id = 933; -- skyshrine (12) +UPDATE zone_points SET target_heading = 125 WHERE id = 2273; -- skyshrine (12) +UPDATE zone_points SET target_heading = 250 WHERE id = 935; -- skyshrine (14) +UPDATE zone_points SET target_heading = 250 WHERE id = 2275; -- skyshrine (14) +UPDATE zone_points SET target_heading = 250 WHERE id = 938; -- skyshrine (17) +UPDATE zone_points SET target_heading = 250 WHERE id = 2278; -- skyshrine (17) +UPDATE zone_points SET target_heading = 385 WHERE id = 939; -- skyshrine (18) +UPDATE zone_points SET target_heading = 385 WHERE id = 2279; -- skyshrine (18) +UPDATE zone_points SET target_heading = 250 WHERE id = 941; -- skyshrine (20) +UPDATE zone_points SET target_heading = 250 WHERE id = 2281; -- skyshrine (20) +UPDATE zone_points SET target_heading = 372 WHERE id = 946; -- skyshrine (30) +UPDATE zone_points SET target_heading = 372 WHERE id = 2286; -- skyshrine (30) +UPDATE zone_points SET target_heading = 5 WHERE id = 947; -- skyshrine (40) +UPDATE zone_points SET target_heading = 5 WHERE id = 2287; -- skyshrine (40) +UPDATE zone_points SET target_heading = 385 WHERE id = 949; -- skyshrine (42) +UPDATE zone_points SET target_heading = 385 WHERE id = 2289; -- skyshrine (42) +UPDATE zone_points SET target_heading = 254 WHERE id = 954; -- skyshrine (50) +UPDATE zone_points SET target_heading = 254 WHERE id = 2294; -- skyshrine (50) +UPDATE zone_points SET target_heading = 384 WHERE id = 584; -- eastwastes (5) +UPDATE zone_points SET target_heading = 510 WHERE id = 555; -- cobaltscar (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 14; -- commons (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 615; -- greatdivide (0) +UPDATE zone_points SET target_heading = 128 WHERE id = 769; -- tox (0) +UPDATE zone_points SET target_heading = 0 WHERE id = 617; -- greatdivide (2) +UPDATE zone_points SET target_heading = 254 WHERE id = 618; -- greatdivide (3) +UPDATE zone_points SET target_heading = 810 WHERE id = 620; -- greatdivide (77) +UPDATE zone_points SET target_heading = 20 WHERE id = 786; -- wakening (1) +UPDATE zone_points SET target_heading = 384 WHERE id = 787; -- wakening (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 788; -- wakening (7) +UPDATE zone_points SET target_heading = 505 WHERE id = 811; -- crystal (1) +UPDATE zone_points SET target_heading = 372 WHERE id = 812; -- crystal (2) +UPDATE zone_points SET target_heading = 386 WHERE id = 890; -- necropolis (66) +UPDATE zone_points SET target_heading = 256 WHERE id = 1454; -- templeveeshan (1) +UPDATE zone_points SET target_heading = 256 WHERE id = 1455; -- templeveeshan (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 1456; -- templeveeshan (3) +UPDATE zone_points SET target_heading = 265 WHERE id = 908; -- sirens (1) +UPDATE zone_points SET target_heading = 132 WHERE id = 909; -- sirens (2) +UPDATE zone_points SET target_heading = 204 WHERE id = 1886; -- sleeper (10) +UPDATE zone_points SET target_heading = 0 WHERE id = 523; -- shadowhaven (2) +UPDATE zone_points SET target_heading = 0 WHERE id = 524; -- shadowhaven (3) +UPDATE zone_points SET target_heading = 384 WHERE id = 531; -- shadowhaven (11) +UPDATE zone_points SET target_heading = 256 WHERE id = 1436; -- bazaar (20) +UPDATE zone_points SET target_heading = 256 WHERE id = 1438; -- bazaar (40) +UPDATE zone_points SET target_heading = 128 WHERE id = 1439; -- bazaar (570) +UPDATE zone_points SET target_heading = 128 WHERE id = 1440; -- bazaar (580) +UPDATE zone_points SET target_heading = 68 WHERE id = 1443; -- bazaar (1150) +UPDATE zone_points SET target_heading = 251 WHERE id = 425; -- nexus (0) +UPDATE zone_points SET target_heading = 125 WHERE id = 426; -- nexus (2) +UPDATE zone_points SET target_heading = 128 WHERE id = 429; -- nexus (6) +UPDATE zone_points SET target_heading = 384 WHERE id = 430; -- nexus (7) +UPDATE zone_points SET target_heading = 256 WHERE id = 433; -- nexus (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 434; -- nexus (11) +UPDATE zone_points SET target_heading = 249 WHERE id = 435; -- nexus (12) +UPDATE zone_points SET target_heading = 128 WHERE id = 437; -- nexus (14) +UPDATE zone_points SET target_heading = 1 WHERE id = 439; -- nexus (77) +UPDATE zone_points SET target_heading = 256 WHERE id = 821; -- echo (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 822; -- echo (2) +UPDATE zone_points SET target_heading = 128 WHERE id = 823; -- echo (3) +UPDATE zone_points SET target_heading = 0 WHERE id = 824; -- echo (4) +UPDATE zone_points SET target_heading = 125 WHERE id = 533; -- sharvahl (1) +UPDATE zone_points SET target_heading = 380 WHERE id = 534; -- sharvahl (2) +UPDATE zone_points SET target_heading = 265 WHERE id = 902; -- paludal (1) +UPDATE zone_points SET target_heading = 385 WHERE id = 904; -- paludal (3) +UPDATE zone_points SET target_heading = 253 WHERE id = 2366; -- vexthal (47) +UPDATE zone_points SET target_heading = 128 WHERE id = 494; -- sseru (1) +UPDATE zone_points SET target_heading = 384 WHERE id = 496; -- sseru (3) +UPDATE zone_points SET target_heading = 248 WHERE id = 499; -- sseru (188) +UPDATE zone_points SET target_heading = 249 WHERE id = 500; -- sseru (189) +UPDATE zone_points SET target_heading = 252 WHERE id = 501; -- sseru (191) +UPDATE zone_points SET target_heading = 376 WHERE id = 502; -- sseru (192) +UPDATE zone_points SET target_heading = 380 WHERE id = 503; -- sseru (193) +UPDATE zone_points SET target_heading = 247 WHERE id = 504; -- sseru (194) +UPDATE zone_points SET target_heading = 259 WHERE id = 505; -- sseru (195) +UPDATE zone_points SET target_heading = 119 WHERE id = 506; -- sseru (196) +UPDATE zone_points SET target_heading = 128 WHERE id = 507; -- sseru (197) +UPDATE zone_points SET target_heading = 252 WHERE id = 508; -- sseru (198) +UPDATE zone_points SET target_heading = 3 WHERE id = 509; -- sseru (201) +UPDATE zone_points SET target_heading = 388 WHERE id = 510; -- sseru (202) +UPDATE zone_points SET target_heading = 383 WHERE id = 511; -- sseru (203) +UPDATE zone_points SET target_heading = 510 WHERE id = 512; -- sseru (204) +UPDATE zone_points SET target_heading = 122 WHERE id = 513; -- sseru (205) +UPDATE zone_points SET target_heading = 503 WHERE id = 514; -- sseru (206) +UPDATE zone_points SET target_heading = 503 WHERE id = 515; -- sseru (207) +UPDATE zone_points SET target_heading = 120 WHERE id = 516; -- sseru (208) +UPDATE zone_points SET target_heading = 124 WHERE id = 517; -- sseru (209) +UPDATE zone_points SET target_heading = 509 WHERE id = 518; -- sseru (210) +UPDATE zone_points SET target_heading = 121 WHERE id = 519; -- sseru (211) +UPDATE zone_points SET target_heading = 246 WHERE id = 520; -- sseru (212) +UPDATE zone_points SET target_heading = 251 WHERE id = 521; -- sseru (213) +UPDATE zone_points SET target_heading = 380 WHERE id = 403; -- katta (1) +UPDATE zone_points SET target_heading = 130 WHERE id = 404; -- katta (2) +UPDATE zone_points SET target_heading = 129 WHERE id = 405; -- katta (3) +UPDATE zone_points SET target_heading = 510 WHERE id = 410; -- katta (10) +UPDATE zone_points SET target_heading = 244 WHERE id = 411; -- katta (11) +UPDATE zone_points SET target_heading = 244 WHERE id = 412; -- katta (12) +UPDATE zone_points SET target_heading = 383 WHERE id = 891; -- netherbian (1) +UPDATE zone_points SET target_heading = 162 WHERE id = 892; -- netherbian (2) +UPDATE zone_points SET target_heading = 126 WHERE id = 893; -- netherbian (3) +UPDATE zone_points SET target_heading = 127 WHERE id = 894; -- netherbian (4) +UPDATE zone_points SET target_heading = 380 WHERE id = 895; -- netherbian (5) +UPDATE zone_points SET target_heading = 114 WHERE id = 896; -- netherbian (6) +UPDATE zone_points SET target_heading = 126 WHERE id = 1324; -- ssratemple (7) +UPDATE zone_points SET target_heading = 128 WHERE id = 1325; -- ssratemple (78) +UPDATE zone_points SET target_heading = 129 WHERE id = 847; -- griegsend (1) +UPDATE zone_points SET target_heading = 382 WHERE id = 849; -- griegsend (3) +UPDATE zone_points SET target_heading = 378 WHERE id = 850; -- griegsend (4) +UPDATE zone_points SET target_heading = 256 WHERE id = 730; -- shadeweaver (1) +UPDATE zone_points SET target_heading = 131 WHERE id = 731; -- shadeweaver (3) +UPDATE zone_points SET target_heading = 0 WHERE id = 634; -- hollowshade (2) +UPDATE zone_points SET target_heading = 264 WHERE id = 635; -- hollowshade (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 624; -- grimling (1) +UPDATE zone_points SET target_heading = 256 WHERE id = 625; -- grimling (2) +UPDATE zone_points SET target_heading = 470 WHERE id = 626; -- grimling (3) +UPDATE zone_points SET target_heading = 379 WHERE id = 671; -- mseru (1) +UPDATE zone_points SET target_heading = 377 WHERE id = 672; -- mseru (2) +UPDATE zone_points SET target_heading = 382 WHERE id = 674; -- mseru (4) +UPDATE zone_points SET target_heading = 489 WHERE id = 678; -- letalis (1) +UPDATE zone_points SET target_heading = 237 WHERE id = 679; -- letalis (2) +UPDATE zone_points SET target_heading = 384 WHERE id = 1326; -- twilight (4) +UPDATE zone_points SET target_heading = 340 WHERE id = 621; -- thegrey (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 622; -- thegrey (2) +UPDATE zone_points SET target_heading = 384 WHERE id = 623; -- thegrey (3) +UPDATE zone_points SET target_heading = 261 WHERE id = 753; -- tenebrous (1) +UPDATE zone_points SET target_heading = 252 WHERE id = 754; -- tenebrous (2) +UPDATE zone_points SET target_heading = 385 WHERE id = 670; -- maiden (4) +UPDATE zone_points SET target_heading = 257 WHERE id = 560; -- dawnshroud (1) +UPDATE zone_points SET target_heading = 2 WHERE id = 561; -- dawnshroud (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 563; -- dawnshroud (4) +UPDATE zone_points SET target_heading = 1 WHERE id = 727; -- scarlet (1) +UPDATE zone_points SET target_heading = 145 WHERE id = 729; -- scarlet (3) +UPDATE zone_points SET target_heading = 380 WHERE id = 783; -- umbral (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 784; -- umbral (2) +UPDATE zone_points SET target_heading = 128 WHERE id = 1244; -- jaggedpine (2) +UPDATE zone_points SET target_heading = 255 WHERE id = 1245; -- jaggedpine (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 979; -- nedaria (1) +UPDATE zone_points SET target_heading = 45 WHERE id = 454; -- poknowledge (3) +UPDATE zone_points SET target_heading = 244 WHERE id = 456; -- poknowledge (5) +UPDATE zone_points SET target_heading = 236 WHERE id = 460; -- poknowledge (9) +UPDATE zone_points SET target_heading = 131 WHERE id = 462; -- poknowledge (11) +UPDATE zone_points SET target_heading = 128 WHERE id = 463; -- poknowledge (12) +UPDATE zone_points SET target_heading = 248 WHERE id = 469; -- poknowledge (18) +UPDATE zone_points SET target_heading = 128 WHERE id = 470; -- poknowledge (19) +UPDATE zone_points SET target_heading = 0 WHERE id = 1089; -- potranquility (17) +UPDATE zone_points SET target_heading = 128 WHERE id = 1035; -- podisease (1) +UPDATE zone_points SET target_heading = 256 WHERE id = 1036; -- podisease (2) +UPDATE zone_points SET target_heading = 62 WHERE id = 1084; -- potorment (2) +UPDATE zone_points SET target_heading = 504 WHERE id = 1085; -- potorment (13) +UPDATE zone_points SET target_heading = 153 WHERE id = 1025; -- povalor (5) +UPDATE zone_points SET target_heading = 128 WHERE id = 1026; -- povalor (77) +UPDATE zone_points SET target_heading = 256 WHERE id = 983; -- bothunder (2) +UPDATE zone_points SET target_heading = 128 WHERE id = 984; -- bothunder (3) +UPDATE zone_points SET target_heading = 128 WHERE id = 985; -- bothunder (4) +UPDATE zone_points SET target_heading = 128 WHERE id = 986; -- bothunder (5) +UPDATE zone_points SET target_heading = 128 WHERE id = 987; -- bothunder (6) +UPDATE zone_points SET target_heading = 128 WHERE id = 988; -- bothunder (7) +UPDATE zone_points SET target_heading = 128 WHERE id = 990; -- bothunder (9) +UPDATE zone_points SET target_heading = 256 WHERE id = 991; -- bothunder (10) +UPDATE zone_points SET target_heading = 384 WHERE id = 994; -- bothunder (13) +UPDATE zone_points SET target_heading = 128 WHERE id = 995; -- bothunder (14) +UPDATE zone_points SET target_heading = 128 WHERE id = 996; -- bothunder (15) +UPDATE zone_points SET target_heading = 128 WHERE id = 997; -- bothunder (16) +UPDATE zone_points SET target_heading = 384 WHERE id = 999; -- bothunder (18) +UPDATE zone_points SET target_heading = 128 WHERE id = 1001; -- bothunder (20) +UPDATE zone_points SET target_heading = 256 WHERE id = 1002; -- bothunder (21) +UPDATE zone_points SET target_heading = 128 WHERE id = 1003; -- bothunder (22) +UPDATE zone_points SET target_heading = 256 WHERE id = 1004; -- bothunder (23) +UPDATE zone_points SET target_heading = 128 WHERE id = 1005; -- bothunder (24) +UPDATE zone_points SET target_heading = 128 WHERE id = 1006; -- bothunder (25) +UPDATE zone_points SET target_heading = 128 WHERE id = 1007; -- bothunder (26) +UPDATE zone_points SET target_heading = 128 WHERE id = 1008; -- bothunder (27) +UPDATE zone_points SET target_heading = 128 WHERE id = 1009; -- bothunder (28) +UPDATE zone_points SET target_heading = 128 WHERE id = 1010; -- bothunder (29) +UPDATE zone_points SET target_heading = 384 WHERE id = 1012; -- bothunder (31) +UPDATE zone_points SET target_heading = 128 WHERE id = 1013; -- bothunder (32) +UPDATE zone_points SET target_heading = 128 WHERE id = 1014; -- bothunder (33) +UPDATE zone_points SET target_heading = 128 WHERE id = 1015; -- bothunder (34) +UPDATE zone_points SET target_heading = 128 WHERE id = 1016; -- bothunder (35) +UPDATE zone_points SET target_heading = 256 WHERE id = 1017; -- bothunder (36) +UPDATE zone_points SET target_heading = 128 WHERE id = 1018; -- bothunder (37) +UPDATE zone_points SET target_heading = 384 WHERE id = 1019; -- bothunder (38) +UPDATE zone_points SET target_heading = 384 WHERE id = 1020; -- bothunder (39) +UPDATE zone_points SET target_heading = 256 WHERE id = 1021; -- bothunder (40) +UPDATE zone_points SET target_heading = 384 WHERE id = 1022; -- bothunder (41) +UPDATE zone_points SET target_heading = 348 WHERE id = 1023; -- bothunder (42) +UPDATE zone_points SET target_heading = 251 WHERE id = 1107; -- solrotower (1) +UPDATE zone_points SET target_heading = 507 WHERE id = 1108; -- solrotower (15) +UPDATE zone_points SET target_heading = 126 WHERE id = 1109; -- solrotower (16) +UPDATE zone_points SET target_heading = 509 WHERE id = 1110; -- solrotower (17) +UPDATE zone_points SET target_heading = 5 WHERE id = 1111; -- solrotower (18) +UPDATE zone_points SET target_heading = 125 WHERE id = 1112; -- solrotower (19) +UPDATE zone_points SET target_heading = 379 WHERE id = 1114; -- solrotower (21) +UPDATE zone_points SET target_heading = 508 WHERE id = 1115; -- solrotower (22) +UPDATE zone_points SET target_heading = 384 WHERE id = 1116; -- solrotower (23) +UPDATE zone_points SET target_heading = 112 WHERE id = 1117; -- solrotower (24) +UPDATE zone_points SET target_heading = 112 WHERE id = 1118; -- solrotower (25) +UPDATE zone_points SET target_heading = 251 WHERE id = 1119; -- solrotower (26) +UPDATE zone_points SET target_heading = -1 WHERE id = 1120; -- potactics (1) +UPDATE zone_points SET target_heading = 258 WHERE id = 1121; -- potactics (2) +UPDATE zone_points SET target_heading = 149 WHERE id = 1122; -- potactics (3) +UPDATE zone_points SET target_heading = 479 WHERE id = 1123; -- potactics (5) +UPDATE zone_points SET target_heading = 448 WHERE id = 1125; -- potactics (7) +UPDATE zone_points SET target_heading = 10 WHERE id = 1126; -- potactics (8) +UPDATE zone_points SET target_heading = 436 WHERE id = 1127; -- potactics (9) +UPDATE zone_points SET target_heading = 378 WHERE id = 1128; -- potactics (10) +UPDATE zone_points SET target_heading = 461 WHERE id = 1129; -- potactics (11) +UPDATE zone_points SET target_heading = 53 WHERE id = 1130; -- potactics (12) +UPDATE zone_points SET target_heading = 133 WHERE id = 1131; -- potactics (13) +UPDATE zone_points SET target_heading = 128 WHERE id = 1032; -- poair (1) +UPDATE zone_points SET target_heading = 48 WHERE id = 1033; -- poair (2) +UPDATE zone_points SET target_heading = 48 WHERE id = 1038; -- poearthb (2) +UPDATE zone_points SET target_heading = 505 WHERE id = 1034; -- poair (10) +UPDATE zone_points SET target_heading = 439 WHERE id = 1106; -- powater (1) +UPDATE zone_points SET target_heading = 133 WHERE id = 1039; -- poeartha (1) +UPDATE zone_points SET target_heading = 132 WHERE id = 1040; -- poeartha (2) +UPDATE zone_points SET target_heading = 48 WHERE id = 1041; -- poeartha (3) +UPDATE zone_points SET target_heading = 388 WHERE id = 1042; -- poeartha (10) +UPDATE zone_points SET target_heading = 48 WHERE id = 1360; -- potimeb (10) +UPDATE zone_points SET target_heading = 384 WHERE id = 1031; -- hohonorb (1) +UPDATE zone_points SET target_heading = 379 WHERE id = 1887; -- nightmareb (77) +UPDATE zone_points SET target_heading = 130 WHERE id = 1037; -- poearthb (1) +UPDATE zone_points SET target_heading = 48 WHERE id = 1033; -- poair (2) +UPDATE zone_points SET target_heading = 48 WHERE id = 1038; -- poearthb (2) +UPDATE zone_points SET target_heading = 352 WHERE id = 346; -- gunthak (1) +UPDATE zone_points SET target_heading = 506 WHERE id = 348; -- gunthak (3) +UPDATE zone_points SET target_heading = 384 WHERE id = 349; -- gunthak (4) +UPDATE zone_points SET target_heading = 384 WHERE id = 573; -- dulak (1) +UPDATE zone_points SET target_heading = 256 WHERE id = 768; -- torgiran (2) +UPDATE zone_points SET target_heading = 128 WHERE id = 682; -- nadox (2) +UPDATE zone_points SET target_heading = 380 WHERE id = 864; -- hatesfury (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 867; -- hatesfury (5) +UPDATE zone_points SET target_heading = 380 WHERE id = 868; -- hatesfury (6) +UPDATE zone_points SET target_heading = 128 WHERE id = 869; -- hatesfury (7) +UPDATE zone_points SET target_heading = 145 WHERE id = 980; -- chardokb (1) +UPDATE zone_points SET target_heading = 145 WHERE id = 981; -- chardokb (2) +UPDATE zone_points SET target_heading = 145 WHERE id = 982; -- chardokb (3) +UPDATE zone_points SET target_heading = 175 WHERE id = 968; -- soldungc (1) +UPDATE zone_points SET target_heading = 425 WHERE id = 969; -- soldungc (2) +UPDATE zone_points SET target_heading = 384 WHERE id = 1379; -- qinimi (1) +UPDATE zone_points SET target_heading = 356 WHERE id = 1380; -- qinimi (2) +UPDATE zone_points SET target_heading = 421 WHERE id = 1381; -- qinimi (3) +UPDATE zone_points SET target_heading = 421 WHERE id = 1382; -- qinimi (4) +UPDATE zone_points SET target_heading = 382 WHERE id = 1383; -- qinimi (5) +UPDATE zone_points SET target_heading = 382 WHERE id = 1384; -- qinimi (6) +UPDATE zone_points SET target_heading = 259 WHERE id = 1385; -- qinimi (7) +UPDATE zone_points SET target_heading = 45 WHERE id = 1389; -- qinimi (11) +UPDATE zone_points SET target_heading = 256 WHERE id = 1393; -- riwwi (1) +UPDATE zone_points SET target_heading = 423 WHERE id = 1396; -- riwwi (4) +UPDATE zone_points SET target_heading = 423 WHERE id = 1397; -- riwwi (5) +UPDATE zone_points SET target_heading = 128 WHERE id = 1369; -- barindu (2) +UPDATE zone_points SET target_heading = 128 WHERE id = 1370; -- barindu (3) +UPDATE zone_points SET target_heading = 351 WHERE id = 1371; -- barindu (4) +UPDATE zone_points SET target_heading = 351 WHERE id = 1372; -- barindu (5) +UPDATE zone_points SET target_heading = 506 WHERE id = 1373; -- ferubi (1) +UPDATE zone_points SET target_heading = 388 WHERE id = 1374; -- ferubi (2) +UPDATE zone_points SET target_heading = 249 WHERE id = 1461; -- snplant (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1465; -- sncrematory (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1471; -- snlair (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1472; -- snpool (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1461; -- snplant (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1465; -- sncrematory (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1471; -- snlair (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1472; -- snpool (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1461; -- snplant (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1465; -- sncrematory (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1471; -- snlair (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1472; -- snpool (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1461; -- snplant (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1465; -- sncrematory (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1471; -- snlair (1) +UPDATE zone_points SET target_heading = 249 WHERE id = 1472; -- snpool (1) +UPDATE zone_points SET target_heading = 240 WHERE id = 1398; -- tipt (1) +UPDATE zone_points SET target_heading = 240 WHERE id = 1400; -- vxed (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 1392; -- qvic (3) +UPDATE zone_points SET target_heading = 383 WHERE id = 1399; -- txevu (1) +UPDATE zone_points SET target_heading = 135 WHERE id = 1416; -- wallofslaughter (20) +UPDATE zone_points SET target_heading = 166 WHERE id = 1417; -- wallofslaughter (50) +UPDATE zone_points SET target_heading = 84 WHERE id = 1403; -- bloodfields (20) +UPDATE zone_points SET target_heading = 256 WHERE id = 1404; -- bloodfields (30) +UPDATE zone_points SET target_heading = 128 WHERE id = 1411; -- draniksscar (10) +UPDATE zone_points SET target_heading = 409 WHERE id = 1412; -- draniksscar (20) +UPDATE zone_points SET target_heading = 30 WHERE id = 1406; -- causeway (20) +UPDATE zone_points SET target_heading = 240 WHERE id = 1400; -- vxed (1) +UPDATE zone_points SET target_heading = 128 WHERE id = 1407; -- provinggrounds (10) +UPDATE zone_points SET target_heading = 360 WHERE id = 1401; -- anguish (10) +UPDATE zone_points SET target_heading = 128 WHERE id = 1415; -- riftseekers (10) +UPDATE zone_points SET target_heading = 397 WHERE id = 1409; -- dranik (10) +UPDATE zone_points SET target_heading = 197 WHERE id = 1410; -- dranik (20) +UPDATE zone_points SET target_heading = 246 WHERE id = 1418; -- broodlands (30) +UPDATE zone_points SET target_heading = 353 WHERE id = 1419; -- broodlands (40) +UPDATE zone_points SET target_heading = 224 WHERE id = 1420; -- broodlands (50) +UPDATE zone_points SET target_heading = 53 WHERE id = 1422; -- broodlands (501) +UPDATE zone_points SET target_heading = 1 WHERE id = 1431; -- stillmoona (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 1432; -- stillmoona (50) +UPDATE zone_points SET target_heading = 257 WHERE id = 1433; -- stillmoonb (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 1434; -- stillmoonb (20) +UPDATE zone_points SET target_heading = 248 WHERE id = 1424; -- delvea (10) +UPDATE zone_points SET target_heading = 308 WHERE id = 1425; -- delvea (20) +UPDATE zone_points SET target_heading = 47 WHERE id = 1426; -- delvea (40) +UPDATE zone_points SET target_heading = 449 WHERE id = 1427; -- delvea (50) +UPDATE zone_points SET target_heading = 343 WHERE id = 1428; -- delveb (40) +UPDATE zone_points SET target_heading = 190 WHERE id = 1429; -- delveb (50) +UPDATE zone_points SET target_heading = 328 WHERE id = 1430; -- guildlobby (20) +UPDATE zone_points SET target_heading = 21 WHERE id = 1498; -- illsalin (0) +UPDATE zone_points SET target_heading = 10 WHERE id = 1489; -- dreadspire (80) +UPDATE zone_points SET target_heading = 56 WHERE id = 1481; -- drachnidhive (10) +UPDATE zone_points SET target_heading = 395 WHERE id = 1491; -- westkorlach (20) +UPDATE zone_points SET target_heading = 326 WHERE id = 1493; -- eastkorlach (10) +UPDATE zone_points SET target_heading = 254 WHERE id = 1494; -- eastkorlach (20) +UPDATE zone_points SET target_heading = 276 WHERE id = 1495; -- eastkorlach (30) +UPDATE zone_points SET target_heading = 364 WHERE id = 1497; -- eastkorlach (50) +UPDATE zone_points SET target_heading = 132 WHERE id = 1499; -- corathus (10) +UPDATE zone_points SET target_heading = 135 WHERE id = 1500; -- corathus (20) +UPDATE zone_points SET target_heading = 442 WHERE id = 1501; -- corathus (30) +UPDATE zone_points SET target_heading = 189 WHERE id = 1502; -- arcstone (5) +UPDATE zone_points SET target_heading = 189 WHERE id = 1503; -- arcstone (15) +UPDATE zone_points SET target_heading = 189 WHERE id = 1504; -- arcstone (30) +UPDATE zone_points SET target_heading = 35 WHERE id = 1526; -- relic (10) +UPDATE zone_points SET target_heading = 52 WHERE id = 1527; -- relic (20) +UPDATE zone_points SET target_heading = 160 WHERE id = 1528; -- relic (30) +UPDATE zone_points SET target_heading = 189 WHERE id = 1529; -- relic (50) +UPDATE zone_points SET target_heading = 227 WHERE id = 1530; -- relic (75) +UPDATE zone_points SET target_heading = 255 WHERE id = 1505; -- devastation (0) +UPDATE zone_points SET target_heading = 122 WHERE id = 1525; -- rage (0) +UPDATE zone_points SET target_heading = 387 WHERE id = 1539; -- takishruins (9) +UPDATE zone_points SET target_heading = 22 WHERE id = 1538; -- takishruins (9) +UPDATE zone_points SET target_heading = 146 WHERE id = 1506; -- elddar (9) +UPDATE zone_points SET target_heading = 128 WHERE id = 1511; -- freeporteast (50) +UPDATE zone_points SET target_heading = 319 WHERE id = 1541; -- freeportwest (10) +UPDATE zone_points SET target_heading = 140 WHERE id = 1544; -- freeportwest (50) +UPDATE zone_points SET target_heading = 255 WHERE id = 1545; -- freeportwest (60) +UPDATE zone_points SET target_heading = 254 WHERE id = 1546; -- freeportwest (80) +UPDATE zone_points SET target_heading = 384 WHERE id = 1547; -- freeportwest (90) +UPDATE zone_points SET target_heading = 245 WHERE id = 1513; -- freeportsewers (10) +UPDATE zone_points SET target_heading = 374 WHERE id = 1514; -- freeportsewers (20) +UPDATE zone_points SET target_heading = 258 WHERE id = 1515; -- freeportsewers (30) +UPDATE zone_points SET target_heading = 402 WHERE id = 1517; -- freeportsewers (60) +UPDATE zone_points SET target_heading = 56 WHERE id = 1519; -- northro (40) +UPDATE zone_points SET target_heading = 135 WHERE id = 1524; -- northro (100) +UPDATE zone_points SET target_heading = 216 WHERE id = 1531; -- southro (10) +UPDATE zone_points SET target_heading = 164 WHERE id = 1537; -- southro (100) +UPDATE zone_points SET target_heading = 505 WHERE id = 1573; -- crescent (10) +UPDATE zone_points SET target_heading = 247 WHERE id = 1567; -- moors (10) +UPDATE zone_points SET target_heading = 188 WHERE id = 1568; -- moors (20) +UPDATE zone_points SET target_heading = 414 WHERE id = 1569; -- moors (30) +UPDATE zone_points SET target_heading = 494 WHERE id = 1571; -- moors (40) +UPDATE zone_points SET target_heading = 501 WHERE id = 1570; -- moors (40) +UPDATE zone_points SET target_heading = 123 WHERE id = 1590; -- stonehive (0) +UPDATE zone_points SET target_heading = 258 WHERE id = 1608; -- mesa (10) +UPDATE zone_points SET target_heading = 458 WHERE id = 1609; -- mesa (20) +UPDATE zone_points SET target_heading = 21 WHERE id = 1610; -- mesa (30) +UPDATE zone_points SET target_heading = 113 WHERE id = 1611; -- mesa (40) +UPDATE zone_points SET target_heading = 391 WHERE id = 1593; -- roost (10) +UPDATE zone_points SET target_heading = 481 WHERE id = 1594; -- roost (101) +UPDATE zone_points SET target_heading = 342 WHERE id = 1595; -- roost (102) +UPDATE zone_points SET target_heading = 119 WHERE id = 1596; -- roost (103) +UPDATE zone_points SET target_heading = 347 WHERE id = 1597; -- roost (104) +UPDATE zone_points SET target_heading = 383 WHERE id = 1598; -- roost (105) +UPDATE zone_points SET target_heading = 160 WHERE id = 1599; -- roost (106) +UPDATE zone_points SET target_heading = 150 WHERE id = 1600; -- roost (107) +UPDATE zone_points SET target_heading = 322 WHERE id = 1601; -- roost (108) +UPDATE zone_points SET target_heading = 446 WHERE id = 1602; -- roost (109) +UPDATE zone_points SET target_heading = 135 WHERE id = 1603; -- roost (110) +UPDATE zone_points SET target_heading = 349 WHERE id = 1604; -- steppes (10) +UPDATE zone_points SET target_heading = 508 WHERE id = 1605; -- steppes (20) +UPDATE zone_points SET target_heading = 386 WHERE id = 1591; -- icefall (10) +UPDATE zone_points SET target_heading = 442 WHERE id = 1592; -- icefall (20) +UPDATE zone_points SET target_heading = 300 WHERE id = 1606; -- valdeholm (10) +UPDATE zone_points SET target_heading = 512 WHERE id = 1607; -- valdeholm (20) +UPDATE zone_points SET target_heading = 122 WHERE id = 1579; -- frostcrypt (0) +UPDATE zone_points SET target_heading = 155 WHERE id = 1623; -- sunderock (10) +UPDATE zone_points SET target_heading = 47 WHERE id = 1624; -- sunderock (20) +UPDATE zone_points SET target_heading = 282 WHERE id = 1625; -- vergalid (0) +UPDATE zone_points SET target_heading = 497 WHERE id = 1621; -- direwind (10) +UPDATE zone_points SET target_heading = 358 WHERE id = 1622; -- direwind (20) +UPDATE zone_points SET target_heading = 164 WHERE id = 1617; -- ashengate (10) +UPDATE zone_points SET target_heading = 299 WHERE id = 1618; -- ashengate (30) +UPDATE zone_points SET target_heading = 85 WHERE id = 1619; -- ashengate (40) +UPDATE zone_points SET target_heading = 85 WHERE id = 1620; -- ashengate (50) +UPDATE zone_points SET target_heading = 119 WHERE id = 1580; -- highpasshold (100) +UPDATE zone_points SET target_heading = 118 WHERE id = 1584; -- highpasshold (500) +UPDATE zone_points SET target_heading = 310 WHERE id = 1574; -- commonlands (10) +UPDATE zone_points SET target_heading = 384 WHERE id = 1578; -- commonlands (50) +UPDATE zone_points SET target_heading = 384 WHERE id = 1725; -- oldcommons (50) +UPDATE zone_points SET target_heading = 398 WHERE id = 1626; -- innothuleb (10) +UPDATE zone_points SET target_heading = 500 WHERE id = 1628; -- innothuleb (30) +UPDATE zone_points SET target_heading = 384 WHERE id = 1629; -- innothuleb (40) +UPDATE zone_points SET target_heading = 384 WHERE id = 644; -- innothule (77) +UPDATE zone_points SET target_heading = 384 WHERE id = 1630; -- innothuleb (77) +UPDATE zone_points SET target_heading = 365 WHERE id = 1612; -- toxxulia (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 1613; -- toxxulia (20) +UPDATE zone_points SET target_heading = 257 WHERE id = 1615; -- toxxulia (40) +UPDATE zone_points SET target_heading = 192 WHERE id = 1616; -- toxxulia (50) +UPDATE zone_points SET target_heading = 511 WHERE id = 1464; -- mistythicket (50) +UPDATE zone_points SET target_heading = 501 WHERE id = 1631; -- kattacastrum (10) +UPDATE zone_points SET target_heading = 510 WHERE id = 1632; -- kattacastrum (20) +UPDATE zone_points SET target_heading = 256 WHERE id = 1634; -- kattacastrum (40) +UPDATE zone_points SET target_heading = 256 WHERE id = 1635; -- kattacastrum (50) +UPDATE zone_points SET target_heading = 128 WHERE id = 1636; -- kattacastrum (60) +UPDATE zone_points SET target_heading = 384 WHERE id = 1637; -- kattacastrum (61) +UPDATE zone_points SET target_heading = 384 WHERE id = 1639; -- kattacastrum (63) +UPDATE zone_points SET target_heading = 128 WHERE id = 1640; -- kattacastrum (64) +UPDATE zone_points SET target_heading = 65 WHERE id = 1641; -- kattacastrum (65) +UPDATE zone_points SET target_heading = 317 WHERE id = 1642; -- kattacastrum (66) +UPDATE zone_points SET target_heading = 202 WHERE id = 1643; -- kattacastrum (67) +UPDATE zone_points SET target_heading = 48 WHERE id = 1644; -- kattacastrum (68) +UPDATE zone_points SET target_heading = 93 WHERE id = 1645; -- kattacastrum (69) +UPDATE zone_points SET target_heading = 159 WHERE id = 1646; -- kattacastrum (70) +UPDATE zone_points SET target_heading = 225 WHERE id = 1647; -- kattacastrum (71) +UPDATE zone_points SET target_heading = 290 WHERE id = 1648; -- kattacastrum (72) +UPDATE zone_points SET target_heading = 363 WHERE id = 1649; -- kattacastrum (73) +UPDATE zone_points SET target_heading = 402 WHERE id = 1650; -- kattacastrum (74) +UPDATE zone_points SET target_heading = 477 WHERE id = 1651; -- kattacastrum (75) +UPDATE zone_points SET target_heading = 256 WHERE id = 1652; -- kattacastrum (80) +UPDATE zone_points SET target_heading = 256 WHERE id = 1652; -- kattacastrum (80) +UPDATE zone_points SET target_heading = 307 WHERE id = 1699; -- zhisza (10) +UPDATE zone_points SET target_heading = 226 WHERE id = 1700; -- zhisza (90) +UPDATE zone_points SET target_heading = 131 WHERE id = 1884; -- silyssar (90) +UPDATE zone_points SET target_heading = 119 WHERE id = 1653; -- barren (10) +UPDATE zone_points SET target_heading = 130 WHERE id = 1677; -- mechanotus (0) +UPDATE zone_points SET target_heading = 500 WHERE id = 1678; -- mechanotus (10) +UPDATE zone_points SET target_heading = 465 WHERE id = 1679; -- mechanotus (20) +UPDATE zone_points SET target_heading = 100 WHERE id = 1680; -- mechanotus (30) +UPDATE zone_points SET target_heading = 375 WHERE id = 1681; -- mechanotus (70) +UPDATE zone_points SET target_heading = 500 WHERE id = 1683; -- mechanotus (90) +UPDATE zone_points SET target_heading = 385 WHERE id = 1674; -- mansion (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 1675; -- mansion (14) +UPDATE zone_points SET target_heading = 384 WHERE id = 1688; -- steamfactory (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 1689; -- steamfactory (20) +UPDATE zone_points SET target_heading = 125 WHERE id = 1690; -- steamfactory (30) +UPDATE zone_points SET target_heading = 129 WHERE id = 1691; -- steamfactory (40) +UPDATE zone_points SET target_heading = 260 WHERE id = 1686; -- shipworkshop (10) +UPDATE zone_points SET target_heading = 280 WHERE id = 1687; -- shipworkshop (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1668; -- gyrospireb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1670; -- gyrospirez (20) +UPDATE zone_points SET target_heading = 508 WHERE id = 1664; -- dragonscale (100) +UPDATE zone_points SET target_heading = 76 WHERE id = 1666; -- dragonscale (300) +UPDATE zone_points SET target_heading = 494 WHERE id = 1672; -- lopingplains (10) +UPDATE zone_points SET target_heading = 319 WHERE id = 1673; -- lopingplains (20) +UPDATE zone_points SET target_heading = 108 WHERE id = 1671; -- hillsofshade (10) +UPDATE zone_points SET target_heading = 433 WHERE id = 1660; -- bloodmoon (0) +UPDATE zone_points SET target_heading = 19 WHERE id = 1663; -- bloodmoon (30) +UPDATE zone_points SET target_heading = 258 WHERE id = 1657; -- steamfontmts (30) +UPDATE zone_points SET target_heading = 105 WHERE id = 1658; -- steamfontmts (40) +UPDATE zone_points SET target_heading = 256 WHERE id = 1659; -- steamfontmts (50) +UPDATE zone_points SET target_heading = 250 WHERE id = 1734; -- oldfieldofbone (10) +UPDATE zone_points SET target_heading = 130 WHERE id = 1735; -- oldfieldofbone (23) +UPDATE zone_points SET target_heading = 127 WHERE id = 1736; -- oldfieldofbone (200) +UPDATE zone_points SET target_heading = 383 WHERE id = 1737; -- oldfieldofbone (210) +UPDATE zone_points SET target_heading = 240 WHERE id = 1738; -- oldfieldofbone (500) +UPDATE zone_points SET target_heading = 66 WHERE id = 1707; -- oldkaesoraa (10) +UPDATE zone_points SET target_heading = 487 WHERE id = 1706; -- oldkaesorab (10) +UPDATE zone_points SET target_heading = 262 WHERE id = 1730; -- oldkurn (0) +UPDATE zone_points SET target_heading = 262 WHERE id = 1731; -- oldkurn (10) +UPDATE zone_points SET target_heading = 290 WHERE id = 1726; -- oldkithicor (10) +UPDATE zone_points SET target_heading = 56 WHERE id = 1728; -- oldkithicor (22) +UPDATE zone_points SET target_heading = 273 WHERE id = 1729; -- oldkithicor (30) +UPDATE zone_points SET target_heading = 109 WHERE id = 1721; -- oldcommons (10) +UPDATE zone_points SET target_heading = 384 WHERE id = 1578; -- commonlands (50) +UPDATE zone_points SET target_heading = 384 WHERE id = 1725; -- oldcommons (50) +UPDATE zone_points SET target_heading = 167 WHERE id = 1758; -- thevoida (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1741; -- thevoide (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1759; -- thevoida (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1776; -- thevoidb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1792; -- thevoidc (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1808; -- thevoidd (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1824; -- thevoidf (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1840; -- thevoidg (20) +UPDATE zone_points SET target_heading = 225 WHERE id = 1742; -- thevoide (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1760; -- thevoida (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1777; -- thevoidb (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1793; -- thevoidc (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1809; -- thevoidd (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1825; -- thevoidf (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1841; -- thevoidg (30) +UPDATE zone_points SET target_heading = 448 WHERE id = 1761; -- thevoida (40) +UPDATE zone_points SET target_heading = 25 WHERE id = 1762; -- thevoida (50) +UPDATE zone_points SET target_heading = 106 WHERE id = 1763; -- thevoida (60) +UPDATE zone_points SET target_heading = 185 WHERE id = 1764; -- thevoida (70) +UPDATE zone_points SET target_heading = 270 WHERE id = 1747; -- thevoide (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1765; -- thevoida (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1782; -- thevoidb (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1798; -- thevoidc (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1814; -- thevoidd (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1830; -- thevoidf (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1846; -- thevoidg (80) +UPDATE zone_points SET target_heading = 125 WHERE id = 1748; -- thevoide (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1766; -- thevoida (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1783; -- thevoidb (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1799; -- thevoidc (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1815; -- thevoidd (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1831; -- thevoidf (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1847; -- thevoidg (90) +UPDATE zone_points SET target_heading = 350 WHERE id = 1767; -- thevoida (100) +UPDATE zone_points SET target_heading = 288 WHERE id = 1769; -- thevoida (120) +UPDATE zone_points SET target_heading = 35 WHERE id = 1752; -- thevoide (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1770; -- thevoida (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1787; -- thevoidb (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1803; -- thevoidc (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1819; -- thevoidd (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1835; -- thevoidf (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1851; -- thevoidg (130) +UPDATE zone_points SET target_heading = 220 WHERE id = 1771; -- thevoida (140) +UPDATE zone_points SET target_heading = 175 WHERE id = 1754; -- thevoide (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1772; -- thevoida (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1789; -- thevoidb (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1805; -- thevoidc (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1821; -- thevoidd (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1837; -- thevoidf (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1853; -- thevoidg (150) +UPDATE zone_points SET target_heading = 441 WHERE id = 1773; -- thevoida (160) +UPDATE zone_points SET target_heading = 167 WHERE id = 1775; -- thevoidb (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1741; -- thevoide (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1759; -- thevoida (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1776; -- thevoidb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1792; -- thevoidc (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1808; -- thevoidd (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1824; -- thevoidf (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1840; -- thevoidg (20) +UPDATE zone_points SET target_heading = 225 WHERE id = 1742; -- thevoide (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1760; -- thevoida (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1777; -- thevoidb (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1793; -- thevoidc (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1809; -- thevoidd (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1825; -- thevoidf (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1841; -- thevoidg (30) +UPDATE zone_points SET target_heading = 448 WHERE id = 1778; -- thevoidb (40) +UPDATE zone_points SET target_heading = 25 WHERE id = 1779; -- thevoidb (50) +UPDATE zone_points SET target_heading = 106 WHERE id = 1780; -- thevoidb (60) +UPDATE zone_points SET target_heading = 185 WHERE id = 1781; -- thevoidb (70) +UPDATE zone_points SET target_heading = 270 WHERE id = 1747; -- thevoide (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1765; -- thevoida (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1782; -- thevoidb (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1798; -- thevoidc (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1814; -- thevoidd (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1830; -- thevoidf (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1846; -- thevoidg (80) +UPDATE zone_points SET target_heading = 125 WHERE id = 1748; -- thevoide (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1766; -- thevoida (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1783; -- thevoidb (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1799; -- thevoidc (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1815; -- thevoidd (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1831; -- thevoidf (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1847; -- thevoidg (90) +UPDATE zone_points SET target_heading = 350 WHERE id = 1784; -- thevoidb (100) +UPDATE zone_points SET target_heading = 288 WHERE id = 1786; -- thevoidb (120) +UPDATE zone_points SET target_heading = 35 WHERE id = 1752; -- thevoide (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1770; -- thevoida (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1787; -- thevoidb (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1803; -- thevoidc (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1819; -- thevoidd (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1835; -- thevoidf (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1851; -- thevoidg (130) +UPDATE zone_points SET target_heading = 220 WHERE id = 1788; -- thevoidb (140) +UPDATE zone_points SET target_heading = 175 WHERE id = 1754; -- thevoide (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1772; -- thevoida (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1789; -- thevoidb (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1805; -- thevoidc (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1821; -- thevoidd (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1837; -- thevoidf (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1853; -- thevoidg (150) +UPDATE zone_points SET target_heading = 441 WHERE id = 1790; -- thevoidb (160) +UPDATE zone_points SET target_heading = 167 WHERE id = 1791; -- thevoidc (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1741; -- thevoide (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1759; -- thevoida (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1776; -- thevoidb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1792; -- thevoidc (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1808; -- thevoidd (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1824; -- thevoidf (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1840; -- thevoidg (20) +UPDATE zone_points SET target_heading = 225 WHERE id = 1742; -- thevoide (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1760; -- thevoida (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1777; -- thevoidb (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1793; -- thevoidc (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1809; -- thevoidd (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1825; -- thevoidf (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1841; -- thevoidg (30) +UPDATE zone_points SET target_heading = 448 WHERE id = 1794; -- thevoidc (40) +UPDATE zone_points SET target_heading = 25 WHERE id = 1795; -- thevoidc (50) +UPDATE zone_points SET target_heading = 106 WHERE id = 1796; -- thevoidc (60) +UPDATE zone_points SET target_heading = 185 WHERE id = 1797; -- thevoidc (70) +UPDATE zone_points SET target_heading = 270 WHERE id = 1747; -- thevoide (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1765; -- thevoida (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1782; -- thevoidb (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1798; -- thevoidc (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1814; -- thevoidd (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1830; -- thevoidf (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1846; -- thevoidg (80) +UPDATE zone_points SET target_heading = 125 WHERE id = 1748; -- thevoide (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1766; -- thevoida (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1783; -- thevoidb (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1799; -- thevoidc (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1815; -- thevoidd (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1831; -- thevoidf (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1847; -- thevoidg (90) +UPDATE zone_points SET target_heading = 350 WHERE id = 1800; -- thevoidc (100) +UPDATE zone_points SET target_heading = 288 WHERE id = 1802; -- thevoidc (120) +UPDATE zone_points SET target_heading = 35 WHERE id = 1752; -- thevoide (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1770; -- thevoida (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1787; -- thevoidb (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1803; -- thevoidc (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1819; -- thevoidd (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1835; -- thevoidf (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1851; -- thevoidg (130) +UPDATE zone_points SET target_heading = 220 WHERE id = 1804; -- thevoidc (140) +UPDATE zone_points SET target_heading = 175 WHERE id = 1754; -- thevoide (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1772; -- thevoida (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1789; -- thevoidb (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1805; -- thevoidc (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1821; -- thevoidd (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1837; -- thevoidf (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1853; -- thevoidg (150) +UPDATE zone_points SET target_heading = 441 WHERE id = 1806; -- thevoidc (160) +UPDATE zone_points SET target_heading = 167 WHERE id = 1807; -- thevoidd (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1741; -- thevoide (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1759; -- thevoida (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1776; -- thevoidb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1792; -- thevoidc (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1808; -- thevoidd (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1824; -- thevoidf (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1840; -- thevoidg (20) +UPDATE zone_points SET target_heading = 225 WHERE id = 1742; -- thevoide (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1760; -- thevoida (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1777; -- thevoidb (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1793; -- thevoidc (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1809; -- thevoidd (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1825; -- thevoidf (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1841; -- thevoidg (30) +UPDATE zone_points SET target_heading = 448 WHERE id = 1810; -- thevoidd (40) +UPDATE zone_points SET target_heading = 25 WHERE id = 1811; -- thevoidd (50) +UPDATE zone_points SET target_heading = 106 WHERE id = 1812; -- thevoidd (60) +UPDATE zone_points SET target_heading = 185 WHERE id = 1813; -- thevoidd (70) +UPDATE zone_points SET target_heading = 270 WHERE id = 1747; -- thevoide (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1765; -- thevoida (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1782; -- thevoidb (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1798; -- thevoidc (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1814; -- thevoidd (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1830; -- thevoidf (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1846; -- thevoidg (80) +UPDATE zone_points SET target_heading = 125 WHERE id = 1748; -- thevoide (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1766; -- thevoida (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1783; -- thevoidb (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1799; -- thevoidc (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1815; -- thevoidd (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1831; -- thevoidf (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1847; -- thevoidg (90) +UPDATE zone_points SET target_heading = 350 WHERE id = 1816; -- thevoidd (100) +UPDATE zone_points SET target_heading = 288 WHERE id = 1818; -- thevoidd (120) +UPDATE zone_points SET target_heading = 35 WHERE id = 1752; -- thevoide (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1770; -- thevoida (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1787; -- thevoidb (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1803; -- thevoidc (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1819; -- thevoidd (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1835; -- thevoidf (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1851; -- thevoidg (130) +UPDATE zone_points SET target_heading = 220 WHERE id = 1820; -- thevoidd (140) +UPDATE zone_points SET target_heading = 175 WHERE id = 1754; -- thevoide (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1772; -- thevoida (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1789; -- thevoidb (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1805; -- thevoidc (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1821; -- thevoidd (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1837; -- thevoidf (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1853; -- thevoidg (150) +UPDATE zone_points SET target_heading = 441 WHERE id = 1822; -- thevoidd (160) +UPDATE zone_points SET target_heading = 167 WHERE id = 1740; -- thevoide (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1741; -- thevoide (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1759; -- thevoida (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1776; -- thevoidb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1792; -- thevoidc (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1808; -- thevoidd (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1824; -- thevoidf (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1840; -- thevoidg (20) +UPDATE zone_points SET target_heading = 225 WHERE id = 1742; -- thevoide (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1760; -- thevoida (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1777; -- thevoidb (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1793; -- thevoidc (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1809; -- thevoidd (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1825; -- thevoidf (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1841; -- thevoidg (30) +UPDATE zone_points SET target_heading = 448 WHERE id = 1743; -- thevoide (40) +UPDATE zone_points SET target_heading = 25 WHERE id = 1744; -- thevoide (50) +UPDATE zone_points SET target_heading = 106 WHERE id = 1745; -- thevoide (60) +UPDATE zone_points SET target_heading = 185 WHERE id = 1746; -- thevoide (70) +UPDATE zone_points SET target_heading = 270 WHERE id = 1747; -- thevoide (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1765; -- thevoida (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1782; -- thevoidb (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1798; -- thevoidc (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1814; -- thevoidd (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1830; -- thevoidf (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1846; -- thevoidg (80) +UPDATE zone_points SET target_heading = 125 WHERE id = 1748; -- thevoide (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1766; -- thevoida (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1783; -- thevoidb (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1799; -- thevoidc (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1815; -- thevoidd (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1831; -- thevoidf (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1847; -- thevoidg (90) +UPDATE zone_points SET target_heading = 350 WHERE id = 1749; -- thevoide (100) +UPDATE zone_points SET target_heading = 288 WHERE id = 1751; -- thevoide (120) +UPDATE zone_points SET target_heading = 35 WHERE id = 1752; -- thevoide (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1770; -- thevoida (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1787; -- thevoidb (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1803; -- thevoidc (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1819; -- thevoidd (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1835; -- thevoidf (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1851; -- thevoidg (130) +UPDATE zone_points SET target_heading = 220 WHERE id = 1753; -- thevoide (140) +UPDATE zone_points SET target_heading = 175 WHERE id = 1754; -- thevoide (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1772; -- thevoida (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1789; -- thevoidb (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1805; -- thevoidc (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1821; -- thevoidd (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1837; -- thevoidf (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1853; -- thevoidg (150) +UPDATE zone_points SET target_heading = 441 WHERE id = 1755; -- thevoide (160) +UPDATE zone_points SET target_heading = 167 WHERE id = 1823; -- thevoidf (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1741; -- thevoide (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1759; -- thevoida (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1776; -- thevoidb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1792; -- thevoidc (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1808; -- thevoidd (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1824; -- thevoidf (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1840; -- thevoidg (20) +UPDATE zone_points SET target_heading = 225 WHERE id = 1742; -- thevoide (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1760; -- thevoida (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1777; -- thevoidb (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1793; -- thevoidc (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1809; -- thevoidd (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1825; -- thevoidf (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1841; -- thevoidg (30) +UPDATE zone_points SET target_heading = 448 WHERE id = 1826; -- thevoidf (40) +UPDATE zone_points SET target_heading = 25 WHERE id = 1827; -- thevoidf (50) +UPDATE zone_points SET target_heading = 106 WHERE id = 1828; -- thevoidf (60) +UPDATE zone_points SET target_heading = 185 WHERE id = 1829; -- thevoidf (70) +UPDATE zone_points SET target_heading = 270 WHERE id = 1747; -- thevoide (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1765; -- thevoida (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1782; -- thevoidb (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1798; -- thevoidc (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1814; -- thevoidd (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1830; -- thevoidf (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1846; -- thevoidg (80) +UPDATE zone_points SET target_heading = 125 WHERE id = 1748; -- thevoide (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1766; -- thevoida (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1783; -- thevoidb (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1799; -- thevoidc (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1815; -- thevoidd (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1831; -- thevoidf (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1847; -- thevoidg (90) +UPDATE zone_points SET target_heading = 350 WHERE id = 1832; -- thevoidf (100) +UPDATE zone_points SET target_heading = 288 WHERE id = 1834; -- thevoidf (120) +UPDATE zone_points SET target_heading = 35 WHERE id = 1752; -- thevoide (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1770; -- thevoida (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1787; -- thevoidb (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1803; -- thevoidc (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1819; -- thevoidd (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1835; -- thevoidf (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1851; -- thevoidg (130) +UPDATE zone_points SET target_heading = 220 WHERE id = 1836; -- thevoidf (140) +UPDATE zone_points SET target_heading = 175 WHERE id = 1754; -- thevoide (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1772; -- thevoida (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1789; -- thevoidb (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1805; -- thevoidc (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1821; -- thevoidd (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1837; -- thevoidf (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1853; -- thevoidg (150) +UPDATE zone_points SET target_heading = 441 WHERE id = 1838; -- thevoidf (160) +UPDATE zone_points SET target_heading = 167 WHERE id = 1839; -- thevoidg (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1741; -- thevoide (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1759; -- thevoida (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1776; -- thevoidb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1792; -- thevoidc (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1808; -- thevoidd (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1824; -- thevoidf (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1840; -- thevoidg (20) +UPDATE zone_points SET target_heading = 225 WHERE id = 1742; -- thevoide (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1760; -- thevoida (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1777; -- thevoidb (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1793; -- thevoidc (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1809; -- thevoidd (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1825; -- thevoidf (30) +UPDATE zone_points SET target_heading = 225 WHERE id = 1841; -- thevoidg (30) +UPDATE zone_points SET target_heading = 448 WHERE id = 1842; -- thevoidg (40) +UPDATE zone_points SET target_heading = 25 WHERE id = 1843; -- thevoidg (50) +UPDATE zone_points SET target_heading = 106 WHERE id = 1844; -- thevoidg (60) +UPDATE zone_points SET target_heading = 185 WHERE id = 1845; -- thevoidg (70) +UPDATE zone_points SET target_heading = 270 WHERE id = 1747; -- thevoide (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1765; -- thevoida (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1782; -- thevoidb (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1798; -- thevoidc (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1814; -- thevoidd (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1830; -- thevoidf (80) +UPDATE zone_points SET target_heading = 270 WHERE id = 1846; -- thevoidg (80) +UPDATE zone_points SET target_heading = 125 WHERE id = 1748; -- thevoide (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1766; -- thevoida (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1783; -- thevoidb (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1799; -- thevoidc (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1815; -- thevoidd (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1831; -- thevoidf (90) +UPDATE zone_points SET target_heading = 125 WHERE id = 1847; -- thevoidg (90) +UPDATE zone_points SET target_heading = 350 WHERE id = 1848; -- thevoidg (100) +UPDATE zone_points SET target_heading = 288 WHERE id = 1850; -- thevoidg (120) +UPDATE zone_points SET target_heading = 35 WHERE id = 1752; -- thevoide (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1770; -- thevoida (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1787; -- thevoidb (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1803; -- thevoidc (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1819; -- thevoidd (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1835; -- thevoidf (130) +UPDATE zone_points SET target_heading = 35 WHERE id = 1851; -- thevoidg (130) +UPDATE zone_points SET target_heading = 220 WHERE id = 1852; -- thevoidg (140) +UPDATE zone_points SET target_heading = 175 WHERE id = 1754; -- thevoide (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1772; -- thevoida (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1789; -- thevoidb (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1805; -- thevoidc (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1821; -- thevoidd (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1837; -- thevoidf (150) +UPDATE zone_points SET target_heading = 175 WHERE id = 1853; -- thevoidg (150) +UPDATE zone_points SET target_heading = 441 WHERE id = 1854; -- thevoidg (160) +UPDATE zone_points SET target_heading = 375 WHERE id = 1712; -- oceangreenhills (20) +UPDATE zone_points SET target_heading = 292 WHERE id = 1713; -- oceangreenhills (21) +UPDATE zone_points SET target_heading = 90 WHERE id = 1714; -- oceangreenhills (30) +UPDATE zone_points SET target_heading = 385 WHERE id = 1716; -- oceangreenvillage (20) +UPDATE zone_points SET target_heading = 6 WHERE id = 1705; -- bertoxtemple (10) +UPDATE zone_points SET target_heading = 95 WHERE id = 1708; -- discord (26) +UPDATE zone_points SET target_heading = 256 WHERE id = 1717; -- oldbloodfield (10) +UPDATE zone_points SET target_heading = 222 WHERE id = 1718; -- oldbloodfield (20) +UPDATE zone_points SET target_heading = 434 WHERE id = 1719; -- oldbloodfield (25) +UPDATE zone_points SET target_heading = 261 WHERE id = 1720; -- olddranik (10) +UPDATE zone_points SET target_heading = 507 WHERE id = 1756; -- toskirakk (20) +UPDATE zone_points SET target_heading = 408 WHERE id = 1757; -- toskirakk (24) +UPDATE zone_points SET target_heading = 160 WHERE id = 1709; -- korascian (10) +UPDATE zone_points SET target_heading = 384 WHERE id = 1710; -- korascian (20) +UPDATE zone_points SET target_heading = 128 WHERE id = 1739; -- rathechamber (10) +UPDATE zone_points SET target_heading = 45 WHERE id = 1858; -- brellsrest (40) +UPDATE zone_points SET target_heading = 240 WHERE id = 1859; -- brellsrest (50) +UPDATE zone_points SET target_heading = 380 WHERE id = 1865; -- arthicrex (10) +UPDATE zone_points SET target_heading = 332 WHERE id = 1863; -- pellucid (370) +UPDATE zone_points SET target_heading = 383 WHERE id = 1232; -- firiona (77) +UPDATE zone_points SET target_heading = 340 WHERE id = 804; -- blackburrow (7) +UPDATE zone_points SET target_heading = 506 WHERE id = 1476; -- nektulos (10) +UPDATE zone_points SET target_heading = 257 WHERE id = 1447; -- nektulos (77) +UPDATE zone_points SET target_heading = 257 WHERE id = 1480; -- nektulos (77) +UPDATE zone_points SET target_heading = 322 WHERE id = 689; -- nro (4) +UPDATE zone_points SET target_heading = 384 WHERE id = 1240; -- hole (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 1241; -- hole (4) +UPDATE zone_points SET target_heading = 384 WHERE id = 1242; -- hole (5) +UPDATE zone_points SET target_heading = 165 WHERE id = 858; -- gukbottom (2) +UPDATE zone_points SET target_heading = 0 WHERE id = 617; -- greatdivide (2) +UPDATE zone_points SET target_heading = 254 WHERE id = 618; -- greatdivide (3) +UPDATE zone_points SET target_heading = 810 WHERE id = 620; -- greatdivide (77) +UPDATE zone_points SET target_heading = 204 WHERE id = 1886; -- sleeper (10) +UPDATE zone_points SET target_heading = 204 WHERE id = 1886; -- sleeper (10) +UPDATE zone_points SET target_heading = 0 WHERE id = 634; -- hollowshade (2) +UPDATE zone_points SET target_heading = 264 WHERE id = 635; -- hollowshade (3) +UPDATE zone_points SET target_heading = 8 WHERE id = 1986; -- feerrott2 (0) +UPDATE zone_points SET target_heading = 8 WHERE id = 2057; -- feerrott2 (0) +UPDATE zone_points SET target_heading = 255 WHERE id = 1988; -- feerrott2 (25) +UPDATE zone_points SET target_heading = 455 WHERE id = 1989; -- feerrott2 (30) +UPDATE zone_points SET target_heading = 292 WHERE id = 1998; -- thulehouse1 (10) +UPDATE zone_points SET target_heading = 201 WHERE id = 1999; -- thulehouse1 (19) +UPDATE zone_points SET target_heading = 216 WHERE id = 2000; -- thulehouse1 (20) +UPDATE zone_points SET target_heading = 382 WHERE id = 2001; -- thulehouse1 (21) +UPDATE zone_points SET target_heading = 462 WHERE id = 2003; -- thulehouse1 (41) +UPDATE zone_points SET target_heading = 511 WHERE id = 2004; -- thulehouse1 (51) +UPDATE zone_points SET target_heading = 54 WHERE id = 1934; -- thulehouse2 (10) +UPDATE zone_points SET target_heading = 54 WHERE id = 1935; -- thulehouse2 (20) +UPDATE zone_points SET target_heading = 54 WHERE id = 1936; -- thulehouse2 (30) +UPDATE zone_points SET target_heading = 128 WHERE id = 1937; -- thulehouse2 (51) +UPDATE zone_points SET target_heading = 440 WHERE id = 1938; -- thulehouse2 (61) +UPDATE zone_points SET target_heading = 82 WHERE id = 1939; -- thulehouse2 (72) +UPDATE zone_points SET target_heading = 498 WHERE id = 1940; -- thulehouse2 (82) +UPDATE zone_points SET target_heading = 255 WHERE id = 1926; -- housegarden (1) +UPDATE zone_points SET target_heading = 383 WHERE id = 2005; -- thulelibrary (11) +UPDATE zone_points SET target_heading = 495 WHERE id = 1941; -- well (9) +UPDATE zone_points SET target_heading = 127 WHERE id = 1923; -- fallen (23) +UPDATE zone_points SET target_heading = 510 WHERE id = 1924; -- fallen (32) +UPDATE zone_points SET target_heading = 127 WHERE id = 1916; -- morellcastle (40) +UPDATE zone_points SET target_heading = 127 WHERE id = 1921; -- morellcastle (40) +UPDATE zone_points SET target_heading = 127 WHERE id = 1932; -- morellcastle (40) +UPDATE zone_points SET target_heading = 326 WHERE id = 1994; -- somnium (10) +UPDATE zone_points SET target_heading = 132 WHERE id = 1995; -- somnium (20) +UPDATE zone_points SET target_heading = 383 WHERE id = 1922; -- alkabormare (11) +UPDATE zone_points SET target_heading = 383 WHERE id = 1992; -- miragulmare (31) +UPDATE zone_points SET target_heading = 254 WHERE id = 1942; -- neighborhood (1) +UPDATE zone_points SET target_heading = 254 WHERE id = 1943; -- neighborhood (10) +UPDATE zone_points SET target_heading = 374 WHERE id = 1944; -- neighborhood (12) +UPDATE zone_points SET target_heading = 119 WHERE id = 1945; -- neighborhood (13) +UPDATE zone_points SET target_heading = 67 WHERE id = 1946; -- neighborhood (14) +UPDATE zone_points SET target_heading = 356 WHERE id = 1947; -- neighborhood (15) +UPDATE zone_points SET target_heading = 392 WHERE id = 1948; -- neighborhood (16) +UPDATE zone_points SET target_heading = 69 WHERE id = 1949; -- neighborhood (17) +UPDATE zone_points SET target_heading = 27 WHERE id = 1950; -- neighborhood (21) +UPDATE zone_points SET target_heading = 119 WHERE id = 1951; -- neighborhood (23) +UPDATE zone_points SET target_heading = 67 WHERE id = 1952; -- neighborhood (24) +UPDATE zone_points SET target_heading = 356 WHERE id = 1953; -- neighborhood (25) +UPDATE zone_points SET target_heading = 392 WHERE id = 1954; -- neighborhood (26) +UPDATE zone_points SET target_heading = 69 WHERE id = 1955; -- neighborhood (27) +UPDATE zone_points SET target_heading = 27 WHERE id = 1956; -- neighborhood (31) +UPDATE zone_points SET target_heading = 374 WHERE id = 1957; -- neighborhood (32) +UPDATE zone_points SET target_heading = 67 WHERE id = 1958; -- neighborhood (34) +UPDATE zone_points SET target_heading = 356 WHERE id = 1959; -- neighborhood (35) +UPDATE zone_points SET target_heading = 392 WHERE id = 1960; -- neighborhood (36) +UPDATE zone_points SET target_heading = 69 WHERE id = 1961; -- neighborhood (37) +UPDATE zone_points SET target_heading = 27 WHERE id = 1962; -- neighborhood (41) +UPDATE zone_points SET target_heading = 374 WHERE id = 1963; -- neighborhood (42) +UPDATE zone_points SET target_heading = 119 WHERE id = 1964; -- neighborhood (43) +UPDATE zone_points SET target_heading = 356 WHERE id = 1965; -- neighborhood (45) +UPDATE zone_points SET target_heading = 392 WHERE id = 1966; -- neighborhood (46) +UPDATE zone_points SET target_heading = 69 WHERE id = 1967; -- neighborhood (47) +UPDATE zone_points SET target_heading = 27 WHERE id = 1968; -- neighborhood (51) +UPDATE zone_points SET target_heading = 374 WHERE id = 1969; -- neighborhood (52) +UPDATE zone_points SET target_heading = 119 WHERE id = 1970; -- neighborhood (53) +UPDATE zone_points SET target_heading = 67 WHERE id = 1971; -- neighborhood (54) +UPDATE zone_points SET target_heading = 392 WHERE id = 1972; -- neighborhood (56) +UPDATE zone_points SET target_heading = 69 WHERE id = 1973; -- neighborhood (57) +UPDATE zone_points SET target_heading = 27 WHERE id = 1974; -- neighborhood (61) +UPDATE zone_points SET target_heading = 374 WHERE id = 1975; -- neighborhood (62) +UPDATE zone_points SET target_heading = 119 WHERE id = 1976; -- neighborhood (63) +UPDATE zone_points SET target_heading = 67 WHERE id = 1977; -- neighborhood (64) +UPDATE zone_points SET target_heading = 356 WHERE id = 1978; -- neighborhood (65) +UPDATE zone_points SET target_heading = 69 WHERE id = 1979; -- neighborhood (67) +UPDATE zone_points SET target_heading = 27 WHERE id = 1980; -- neighborhood (71) +UPDATE zone_points SET target_heading = 374 WHERE id = 1981; -- neighborhood (72) +UPDATE zone_points SET target_heading = 119 WHERE id = 1982; -- neighborhood (73) +UPDATE zone_points SET target_heading = 67 WHERE id = 1983; -- neighborhood (74) +UPDATE zone_points SET target_heading = 356 WHERE id = 1984; -- neighborhood (75) +UPDATE zone_points SET target_heading = 392 WHERE id = 1985; -- neighborhood (76) +UPDATE zone_points SET target_heading = 204 WHERE id = 1886; -- sleeper (10) +UPDATE zone_points SET target_heading = 204 WHERE id = 1886; -- sleeper (10) +UPDATE zone_points SET target_heading = 125 WHERE id = 922; -- skyshrine (1) +UPDATE zone_points SET target_heading = 125 WHERE id = 2262; -- skyshrine (1) +UPDATE zone_points SET target_heading = 250 WHERE id = 925; -- skyshrine (4) +UPDATE zone_points SET target_heading = 250 WHERE id = 2265; -- skyshrine (4) +UPDATE zone_points SET target_heading = 250 WHERE id = 926; -- skyshrine (5) +UPDATE zone_points SET target_heading = 250 WHERE id = 2266; -- skyshrine (5) +UPDATE zone_points SET target_heading = 250 WHERE id = 927; -- skyshrine (6) +UPDATE zone_points SET target_heading = 250 WHERE id = 2267; -- skyshrine (6) +UPDATE zone_points SET target_heading = 125 WHERE id = 928; -- skyshrine (7) +UPDATE zone_points SET target_heading = 125 WHERE id = 2268; -- skyshrine (7) +UPDATE zone_points SET target_heading = 125 WHERE id = 929; -- skyshrine (8) +UPDATE zone_points SET target_heading = 125 WHERE id = 2269; -- skyshrine (8) +UPDATE zone_points SET target_heading = 250 WHERE id = 931; -- skyshrine (10) +UPDATE zone_points SET target_heading = 250 WHERE id = 2271; -- skyshrine (10) +UPDATE zone_points SET target_heading = 250 WHERE id = 932; -- skyshrine (11) +UPDATE zone_points SET target_heading = 250 WHERE id = 2272; -- skyshrine (11) +UPDATE zone_points SET target_heading = 125 WHERE id = 933; -- skyshrine (12) +UPDATE zone_points SET target_heading = 125 WHERE id = 2273; -- skyshrine (12) +UPDATE zone_points SET target_heading = 250 WHERE id = 935; -- skyshrine (14) +UPDATE zone_points SET target_heading = 250 WHERE id = 2275; -- skyshrine (14) +UPDATE zone_points SET target_heading = 250 WHERE id = 938; -- skyshrine (17) +UPDATE zone_points SET target_heading = 250 WHERE id = 2278; -- skyshrine (17) +UPDATE zone_points SET target_heading = 385 WHERE id = 939; -- skyshrine (18) +UPDATE zone_points SET target_heading = 385 WHERE id = 2279; -- skyshrine (18) +UPDATE zone_points SET target_heading = 250 WHERE id = 941; -- skyshrine (20) +UPDATE zone_points SET target_heading = 250 WHERE id = 2281; -- skyshrine (20) +UPDATE zone_points SET target_heading = 372 WHERE id = 946; -- skyshrine (30) +UPDATE zone_points SET target_heading = 372 WHERE id = 2286; -- skyshrine (30) +UPDATE zone_points SET target_heading = 5 WHERE id = 947; -- skyshrine (40) +UPDATE zone_points SET target_heading = 5 WHERE id = 2287; -- skyshrine (40) +UPDATE zone_points SET target_heading = 385 WHERE id = 949; -- skyshrine (42) +UPDATE zone_points SET target_heading = 385 WHERE id = 2289; -- skyshrine (42) +UPDATE zone_points SET target_heading = 254 WHERE id = 954; -- skyshrine (50) +UPDATE zone_points SET target_heading = 254 WHERE id = 2294; -- skyshrine (50) +UPDATE zone_points SET target_heading = 132 WHERE id = 905; -- permafrost (1) +UPDATE zone_points SET target_heading = 384 WHERE id = 644; -- innothule (77) +UPDATE zone_points SET target_heading = 384 WHERE id = 1630; -- innothuleb (77) +UPDATE zone_points SET target_heading = 256 WHERE id = 624; -- grimling (1) +UPDATE zone_points SET target_heading = 256 WHERE id = 625; -- grimling (2) +UPDATE zone_points SET target_heading = 470 WHERE id = 626; -- grimling (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 1155; -- soldungb (9) +UPDATE zone_points SET target_heading = 510 WHERE id = 1872; -- arena (10) +UPDATE zone_points SET target_heading = 250 WHERE id = 477; -- qeynos2 (2) +UPDATE zone_points SET target_heading = 250 WHERE id = 477; -- qeynos2 (2) +UPDATE zone_points SET target_heading = 250 WHERE id = 477; -- qeynos2 (2) +UPDATE zone_points SET target_heading = 380 WHERE id = 864; -- hatesfury (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 867; -- hatesfury (5) +UPDATE zone_points SET target_heading = 380 WHERE id = 868; -- hatesfury (6) +UPDATE zone_points SET target_heading = 128 WHERE id = 869; -- hatesfury (7) +UPDATE zone_points SET target_heading = 380 WHERE id = 864; -- hatesfury (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 867; -- hatesfury (5) +UPDATE zone_points SET target_heading = 380 WHERE id = 868; -- hatesfury (6) +UPDATE zone_points SET target_heading = 128 WHERE id = 869; -- hatesfury (7) +UPDATE zone_points SET target_heading = 380 WHERE id = 864; -- hatesfury (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 867; -- hatesfury (5) +UPDATE zone_points SET target_heading = 380 WHERE id = 868; -- hatesfury (6) +UPDATE zone_points SET target_heading = 128 WHERE id = 869; -- hatesfury (7) +UPDATE zone_points SET target_heading = 380 WHERE id = 864; -- hatesfury (2) +UPDATE zone_points SET target_heading = 256 WHERE id = 867; -- hatesfury (5) +UPDATE zone_points SET target_heading = 380 WHERE id = 868; -- hatesfury (6) +UPDATE zone_points SET target_heading = 128 WHERE id = 869; -- hatesfury (7) +UPDATE zone_points SET target_heading = 56 WHERE id = 1481; -- drachnidhive (10) +UPDATE zone_points SET target_heading = 56 WHERE id = 1481; -- drachnidhive (10) +UPDATE zone_points SET target_heading = 56 WHERE id = 1481; -- drachnidhive (10) +UPDATE zone_points SET target_heading = 128 WHERE id = 1357; -- potimeb (5) +UPDATE zone_points SET target_heading = 128 WHERE id = 1358; -- potimeb (6) +UPDATE zone_points SET target_heading = 348 WHERE id = 1359; -- potimeb (7) +UPDATE zone_points SET target_heading = 48 WHERE id = 1360; -- potimeb (10) +UPDATE zone_points SET target_heading = 5 WHERE id = 1361; -- potimeb (20) +UPDATE zone_points SET target_heading = 1 WHERE id = 1365; -- potimeb (24) +UPDATE zone_points SET target_heading = 506 WHERE id = 1476; -- nektulos (10) +UPDATE zone_points SET target_heading = 257 WHERE id = 1447; -- nektulos (77) +UPDATE zone_points SET target_heading = 257 WHERE id = 1480; -- nektulos (77) +UPDATE zone_points SET target_heading = 506 WHERE id = 1476; -- nektulos (10) +UPDATE zone_points SET target_heading = 257 WHERE id = 1447; -- nektulos (77) +UPDATE zone_points SET target_heading = 257 WHERE id = 1480; -- nektulos (77) +UPDATE zone_points SET target_heading = 506 WHERE id = 1476; -- nektulos (10) +UPDATE zone_points SET target_heading = 257 WHERE id = 1447; -- nektulos (77) +UPDATE zone_points SET target_heading = 257 WHERE id = 1480; -- nektulos (77) +UPDATE zone_points SET target_heading = 326 WHERE id = 1493; -- eastkorlach (10) +UPDATE zone_points SET target_heading = 254 WHERE id = 1494; -- eastkorlach (20) +UPDATE zone_points SET target_heading = 276 WHERE id = 1495; -- eastkorlach (30) +UPDATE zone_points SET target_heading = 326 WHERE id = 1493; -- eastkorlach (10) +UPDATE zone_points SET target_heading = 254 WHERE id = 1494; -- eastkorlach (20) +UPDATE zone_points SET target_heading = 276 WHERE id = 1495; -- eastkorlach (30) +UPDATE zone_points SET target_heading = 326 WHERE id = 1493; -- eastkorlach (10) +UPDATE zone_points SET target_heading = 254 WHERE id = 1494; -- eastkorlach (20) +UPDATE zone_points SET target_heading = 276 WHERE id = 1495; -- eastkorlach (30) +UPDATE zone_points SET target_heading = 172 WHERE id = 1552; -- skylance (10) +UPDATE zone_points SET target_heading = 106 WHERE id = 1553; -- skylance (20) +UPDATE zone_points SET target_heading = 3 WHERE id = 1554; -- skylance (30) +UPDATE zone_points SET target_heading = 510 WHERE id = 1556; -- skylance (50) +UPDATE zone_points SET target_heading = 312 WHERE id = 1557; -- skylance (60) +UPDATE zone_points SET target_heading = 264 WHERE id = 1558; -- skylance (70) +UPDATE zone_points SET target_heading = 506 WHERE id = 1559; -- skylance (80) +UPDATE zone_points SET target_heading = 385 WHERE id = 1560; -- skylance (90) +UPDATE zone_points SET target_heading = 22 WHERE id = 1538; -- takishruins (9) +UPDATE zone_points SET target_heading = 22 WHERE id = 1538; -- takishruins (9) +UPDATE zone_points SET target_heading = 22 WHERE id = 1538; -- takishruins (9) +UPDATE zone_points SET target_heading = 22 WHERE id = 1538; -- takishruins (9) +UPDATE zone_points SET target_heading = 282 WHERE id = 1625; -- vergalid (0) +UPDATE zone_points SET target_heading = 164 WHERE id = 1617; -- ashengate (10) +UPDATE zone_points SET target_heading = 299 WHERE id = 1618; -- ashengate (30) +UPDATE zone_points SET target_heading = 85 WHERE id = 1619; -- ashengate (40) +UPDATE zone_points SET target_heading = 85 WHERE id = 1620; -- ashengate (50) +UPDATE zone_points SET target_heading = 122 WHERE id = 1579; -- frostcrypt (0) +UPDATE zone_points SET target_heading = 307 WHERE id = 1699; -- zhisza (10) +UPDATE zone_points SET target_heading = 76 WHERE id = 1668; -- gyrospireb (20) +UPDATE zone_points SET target_heading = 76 WHERE id = 1670; -- gyrospirez (20) +UPDATE zone_points SET target_heading = 385 WHERE id = 1674; -- mansion (10) +UPDATE zone_points SET target_heading = 433 WHERE id = 1660; -- bloodmoon (0) +UPDATE zone_points SET target_heading = 19 WHERE id = 1663; -- bloodmoon (30) +UPDATE zone_points SET target_heading = 384 WHERE id = 1688; -- steamfactory (10) +UPDATE zone_points SET target_heading = 256 WHERE id = 1689; -- steamfactory (20) +UPDATE zone_points SET target_heading = 260 WHERE id = 1686; -- shipworkshop (10) +UPDATE zone_points SET target_heading = 280 WHERE id = 1687; -- shipworkshop (20) +UPDATE zone_points SET target_heading = 109 WHERE id = 1721; -- oldcommons (10) +UPDATE zone_points SET target_heading = 0 WHERE id = 1575; -- commonlands (20) +UPDATE zone_points SET target_heading = 0 WHERE id = 1722; -- oldcommons (20) +UPDATE zone_points SET target_heading = 320 WHERE id = 1576; -- commonlands (30) +UPDATE zone_points SET target_heading = 320 WHERE id = 1723; -- oldcommons (30) +UPDATE zone_points SET target_heading = 384 WHERE id = 1577; -- commonlands (40) +UPDATE zone_points SET target_heading = 384 WHERE id = 1724; -- oldcommons (40) +UPDATE zone_points SET target_heading = 384 WHERE id = 1578; -- commonlands (50) +UPDATE zone_points SET target_heading = 384 WHERE id = 1725; -- oldcommons (50) +UPDATE zone_points SET target_heading = 160 WHERE id = 1709; -- korascian (10) +UPDATE zone_points SET target_heading = 66 WHERE id = 1707; -- oldkaesoraa (10) +UPDATE zone_points SET target_heading = 487 WHERE id = 1706; -- oldkaesorab (10) +UPDATE zone_points SET target_heading = 262 WHERE id = 1730; -- oldkurn (0) +UPDATE zone_points SET target_heading = 262 WHERE id = 1731; -- oldkurn (10) +UPDATE zone_points SET target_heading = 262 WHERE id = 1730; -- oldkurn (0) +UPDATE zone_points SET target_heading = 262 WHERE id = 1731; -- oldkurn (10) +UPDATE zone_points SET target_heading = 127 WHERE id = 1736; -- oldfieldofbone (200) +UPDATE zone_points SET target_heading = 383 WHERE id = 1737; -- oldfieldofbone (210) +UPDATE zone_points SET target_heading = 255 WHERE id = 1926; -- housegarden (1) +UPDATE zone_points SET target_heading = 255 WHERE id = 1926; -- housegarden (1) +UPDATE zone_points SET target_heading = 136 WHERE id = 905; -- permafrost (1) +UPDATE zone_points SET target_heading = 398 WHERE id = 1626; -- innothuleb (10) +UPDATE zone_points SET target_heading = 500 WHERE id = 1628; -- innothuleb (30) +UPDATE zone_points SET target_heading = 384 WHERE id = 1629; -- innothuleb (40) +UPDATE zone_points SET target_heading = 384 WHERE id = 644; -- innothule (77) +UPDATE zone_points SET target_heading = 384 WHERE id = 1630; -- innothuleb (77) +UPDATE zone_points SET target_heading = 0 WHERE id = 826; -- frozenshadow (2) +UPDATE zone_points SET target_heading = 0 WHERE id = 827; -- frozenshadow (3) +UPDATE zone_points SET target_heading = 256 WHERE id = 828; -- frozenshadow (4) +UPDATE zone_points SET target_heading = 0 WHERE id = 829; -- frozenshadow (5) +UPDATE zone_points SET target_heading = 0 WHERE id = 830; -- frozenshadow (6) +UPDATE zone_points SET target_heading = 256 WHERE id = 831; -- frozenshadow (7) +UPDATE zone_points SET target_heading = 0 WHERE id = 832; -- frozenshadow (8) +UPDATE zone_points SET target_heading = 0 WHERE id = 833; -- frozenshadow (9) +UPDATE zone_points SET target_heading = 0 WHERE id = 834; -- frozenshadow (10) +UPDATE zone_points SET target_heading = 0 WHERE id = 835; -- frozenshadow (11) +UPDATE zone_points SET target_heading = 256 WHERE id = 836; -- frozenshadow (12) +UPDATE zone_points SET target_heading = 0 WHERE id = 838; -- frozenshadow (14) +UPDATE zone_points SET target_heading = 384 WHERE id = 839; -- frozenshadow (15) +UPDATE zone_points SET target_heading = 0 WHERE id = 840; -- frozenshadow (16) +UPDATE zone_points SET target_heading = 0 WHERE id = 841; -- frozenshadow (17) +UPDATE zone_points SET target_heading = 0 WHERE id = 842; -- frozenshadow (18) +UPDATE zone_points SET target_heading = 0 WHERE id = 843; -- frozenshadow (19) + +UPDATE zone_points SET target_heading = 999 where target_heading = 1998; + +UPDATE zone SET safe_heading = 128 where short_name = 'soldungb' and version = 0; +UPDATE zone SET safe_heading = 256 where short_name = 'neriaka' and version = 0; +UPDATE zone SET safe_heading = 10 where short_name = 'neriakd' and version = 0; +UPDATE zone SET safe_heading = 128 where short_name = 'cazicthule' and version = 0; +UPDATE zone SET safe_heading = 256 where short_name = 'gukbottom' and version = 0; +UPDATE zone SET safe_heading = 276 where short_name = 'cauldron' and version = 0; +UPDATE zone SET safe_heading = 256 where short_name = 'permafrost' and version = 0; +UPDATE zone SET safe_heading = 384 where short_name = 'soltemple' and version = 0; +UPDATE zone SET safe_heading = 128 where short_name = 'skyfire' and version = 0; +UPDATE zone SET safe_heading = 128 where short_name = 'wakening' and version = 0; +UPDATE zone SET safe_heading = 128 where short_name = 'paludal' and version = 0; +UPDATE zone SET safe_heading = 128 where short_name = 'shadeweaver' and version = 0; +UPDATE zone SET safe_heading = 280 where short_name = 'powar' and version = 0; +UPDATE zone SET safe_heading = 100 where short_name = 'lopingplains' and version = 0; +UPDATE zone SET safe_heading = 384 where short_name = 'oldkurn' and version = 0; +UPDATE zone SET safe_heading = 237 where short_name = 'oldkithicor' and version = 0; +UPDATE zone SET safe_heading = 261 where short_name = 'oldbloodfield' and version = 0; +UPDATE zone SET safe_heading = 222 where short_name = 'olddranik' and version = 0; +UPDATE zone SET safe_heading = 270 where short_name = 'toskirakk' and version = 0; +UPDATE zone SET safe_heading = 384 where short_name = 'rathechamber' and version = 0; +UPDATE zone SET safe_heading = 358 where short_name = 'fungalforest' and version = 0; +UPDATE zone SET safe_heading = 22 where short_name = 'underquarry' and version = 0; +UPDATE zone SET safe_heading = 368 where short_name = 'coolingchamber' and version = 0; +UPDATE zone SET safe_heading = 64 where short_name = 'shiningcity' and version = 0; +UPDATE zone SET safe_heading = 400 where short_name = 'arthicrex' and version = 0; +UPDATE zone SET safe_heading = 2 where short_name = 'foundation' and version = 0; +UPDATE zone SET safe_heading = 125 where short_name = 'lichencreep' and version = 0; +UPDATE zone SET safe_heading = 153 where short_name = 'pellucid' and version = 0; +UPDATE zone SET safe_heading = 384 where short_name = 'stonesnake' and version = 0; +UPDATE zone SET safe_heading = 45 where short_name = 'convorteum' and version = 0; +UPDATE zone SET safe_heading = 484 where short_name = 'feerrott2' and version = 0; +UPDATE zone SET safe_heading = 365 where short_name = 'housegarden' and version = 0; +UPDATE zone SET safe_heading = 250 where short_name = 'somnium' and version = 0; +UPDATE zone SET safe_heading = 420 where short_name = 'alkabormare' and version = 0; +UPDATE zone SET safe_heading = 353 where short_name = 'arelis' and version = 0; +UPDATE zone SET safe_heading = 237 where short_name = 'rubak' and version = 0; +UPDATE zone SET safe_heading = 449 where short_name = 'pillarsalra' and version = 0; +UPDATE zone SET safe_heading = 55 where short_name = 'windsong' and version = 0; +UPDATE zone SET safe_heading = 425 where short_name = 'shardslanding' and version = 0; +UPDATE zone SET safe_heading = 435 where short_name = 'eviltree' and version = 0; +UPDATE zone SET safe_heading = 511 where short_name = 'grelleth' and version = 0; +UPDATE zone SET safe_heading = 210 where short_name = 'chapterhouse' and version = 0; +UPDATE zone SET safe_heading = 486 where short_name = 'heartoffear' and version = 0; +UPDATE zone SET safe_heading = 481 where short_name = 'heartoffearb' and version = 0; +UPDATE zone SET safe_heading = 78 where short_name = 'heartoffearc' and version = 0; +UPDATE zone SET safe_heading = 42 where short_name = 'bixiewarfront' and version = 0; +UPDATE zone SET safe_heading = 25 where short_name = 'deadhills' and version = 0; +UPDATE zone SET safe_heading = 361 where short_name = 'ethernere' and version = 0; +UPDATE zone SET safe_heading = 358 where short_name = 'thevoidh' and version = 0; +UPDATE zone SET safe_heading = 388 where short_name = 'towerofrot' and version = 0; +UPDATE zone SET safe_heading = 510 where short_name = 'exalted' and version = 0; +UPDATE zone SET safe_heading = 386 where short_name = 'arxmentis' and version = 0; +UPDATE zone SET safe_heading = 94 where short_name = 'kattacastrumb' and version = 0; +UPDATE zone SET safe_heading = 503 where short_name = 'dredge' and version = 0; +UPDATE zone SET safe_heading = 494 where short_name = 'endlesscaverns' and version = 0; +UPDATE zone SET safe_heading = 256 where short_name = 'degmar' and version = 0; +UPDATE zone SET safe_heading = 70 where short_name = 'tempesttemple' and version = 0; +UPDATE zone SET safe_heading = 388 where short_name = 'gnomemtn' and version = 0; +UPDATE zone SET safe_heading = 262 where short_name = 'exaltedb' and version = 0; +UPDATE zone SET safe_heading = 55 where short_name = 'pohealth' and version = 0; +UPDATE zone SET safe_heading = 128 where short_name = 'bazaar' and version = 0; diff --git a/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql b/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql new file mode 100644 index 000000000..05588cfcc --- /dev/null +++ b/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql @@ -0,0 +1,70 @@ +SET SESSION group_concat_max_len = 1048576; +SET collation_connection = latin1_swedish_ci; + +-- backup original(s) +CREATE TABLE `goallists_backup_9_25_2022` LIKE `goallists`; +INSERT INTO `goallists_backup_9_25_2022` SELECT * FROM `goallists`; +CREATE TABLE `tasks_backup_9_25_2022` LIKE `tasks`; +INSERT INTO `tasks_backup_9_25_2022` SELECT * FROM `tasks`; + +-- npc id +UPDATE `task_activities` +SET `task_activities`.`npc_match_list` = CONCAT_WS('|', `npc_match_list`, `npc_id`) +WHERE npc_id != 0; + +-- npc_goal_id goallists +UPDATE `task_activities` +INNER JOIN +( + SELECT `goallists`.`listid`, GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids` + FROM `goallists` + GROUP BY `goallists`.`listid` +) AS `goallist_group` + ON `task_activities`.`npc_goal_id` = `goallist_group`.`listid` +SET `task_activities`.`npc_match_list` = CONCAT_WS('|', `npc_match_list`, `goallist_ids`) +WHERE npc_goal_id != 0; + +-- item id +UPDATE `task_activities` +SET `task_activities`.`item_id_list` = CONCAT_WS('|', `item_id_list`, `item_id`) +WHERE item_id != 0; + +-- item_goal_id goallists +UPDATE `task_activities` +INNER JOIN +( + SELECT `goallists`.`listid`, GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids` + FROM `goallists` + GROUP BY `goallists`.`listid` +) AS `goallist_group` + ON `task_activities`.`item_goal_id` = `goallist_group`.`listid` +SET `task_activities`.`item_id_list` = CONCAT_WS('|', `item_id_list`, `goallist_ids`) +WHERE item_goal_id != 0; + +ALTER TABLE `task_activities` + DROP COLUMN `npc_id`, + DROP COLUMN `npc_goal_id`, + DROP COLUMN `item_id`, + DROP COLUMN `item_goal_id`; + + +-- Reward cleanup and task table cleanup + +ALTER TABLE `tasks` + CHANGE COLUMN `reward` `reward_text` varchar(64) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `description`, + CHANGE COLUMN `rewardid` `reward_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL AFTER `reward_text`, + CHANGE COLUMN `cashreward` `cash_reward` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `reward_id_list`, + CHANGE COLUMN `rewardmethod` `reward_method` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `xpreward`, + CHANGE COLUMN `minlevel` `min_level` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `reward_point_type`, + CHANGE COLUMN `maxlevel` `max_level` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `min_level`; + +ALTER Table `tasks` CHANGE COLUMN `xpreward` `exp_reward` int(10) NOT NULL DEFAULT 0 AFTER `cash_reward`; + +UPDATE tasks SET reward_id_list = + ( + SELECT GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids` FROM `goallists` WHERE listid = reward_id_list) +WHERE +reward_method = 1; + +-- deprecated table +DROP table goallists; diff --git a/utils/sql/git/required/2022_09_28_discord_webhooks.sql b/utils/sql/git/required/2022_09_28_discord_webhooks.sql new file mode 100644 index 000000000..b118c56fd --- /dev/null +++ b/utils/sql/git/required/2022_09_28_discord_webhooks.sql @@ -0,0 +1,4 @@ +ALTER TABLE logsys_categories + ADD log_to_discord smallint(11) default 0 AFTER log_to_gmsay; +ALTER TABLE logsys_categories + ADD discord_webhook_id int(11) default 0 AFTER log_to_discord; diff --git a/utils/sql/git/required/2022_10_11_fix_misty_pok_stone.sql b/utils/sql/git/required/2022_10_11_fix_misty_pok_stone.sql new file mode 100644 index 000000000..9367d2822 --- /dev/null +++ b/utils/sql/git/required/2022_10_11_fix_misty_pok_stone.sql @@ -0,0 +1,2 @@ +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (2040, 37, 'PoKnowledge', 0, 'POKRVPORT500', 908.668, 1228.06, -156.248, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mistythicket', 0, -209, -324, 8, 253, 0, 0, 100, -559.555, 4294967232, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (36669, 158, 'PoKnowledge', 0, 'POKRVPORT500', 908.668, 1228.06, -156.248, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'misty', 0, -1262.71, -546, 8, 2, 0, 0, 100, -559.555, 63, 0, 0, -1, -1, NULL, NULL); diff --git a/utils/sql/git/required/2022_10_14_fix_misty_pok_stone.sql b/utils/sql/git/required/2022_10_14_fix_misty_pok_stone.sql new file mode 100644 index 000000000..4998159a7 --- /dev/null +++ b/utils/sql/git/required/2022_10_14_fix_misty_pok_stone.sql @@ -0,0 +1 @@ +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (2040, 37, 'PoKnowledge', 0, 'POKRVPORT500', 908.668, 1228.06, -156.248, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'misty', 0, -1262.71, -546, 8, 2, 0, 0, 100, -559.555, 4294967232, 0, 0, -1, -1, NULL, NULL); diff --git a/utils/sql/git/required/2022_10_14_fix_neriak_pok_stone.sql b/utils/sql/git/required/2022_10_14_fix_neriak_pok_stone.sql new file mode 100644 index 000000000..38c7322ea --- /dev/null +++ b/utils/sql/git/required/2022_10_14_fix_neriak_pok_stone.sql @@ -0,0 +1,2 @@ +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (2057, 20, 'PoKnowledge', 0, 'POKNRKPORT500', -909.187, 131.793, -156.148, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'nektulos', 1, -840, -809, 9, 999, 0, 0, 100, 733.98, 4294967232, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (17151, 157, 'PoKnowledge', 0, 'POKNRKPORT500', -909.187, 131.793, -156.148, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'nektulos', 0, -840, -809, 9, 999, 0, 0, 100, 733.98, 3, 0, 0, -1, -1, NULL, NULL); diff --git a/utils/sql/git/required/2022_12_24_character_exp_toggle.sql b/utils/sql/git/required/2022_12_24_character_exp_toggle.sql new file mode 100644 index 000000000..9ed26ef8f --- /dev/null +++ b/utils/sql/git/required/2022_12_24_character_exp_toggle.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_data` +ADD COLUMN `exp_enabled` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 AFTER `exp`; diff --git a/utils/sql/git/required/2022_12_24_npc_keeps_sold_items.sql b/utils/sql/git/required/2022_12_24_npc_keeps_sold_items.sql new file mode 100644 index 000000000..33d530203 --- /dev/null +++ b/utils/sql/git/required/2022_12_24_npc_keeps_sold_items.sql @@ -0,0 +1,2 @@ +ALTER TABLE `npc_types` +ADD COLUMN `keeps_sold_items` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 AFTER `faction_amount`; \ No newline at end of file diff --git a/utils/sql/git/required/2023_01_08_zone_max_level.sql b/utils/sql/git/required/2023_01_08_zone_max_level.sql new file mode 100644 index 000000000..4538e5fd1 --- /dev/null +++ b/utils/sql/git/required/2023_01_08_zone_max_level.sql @@ -0,0 +1,2 @@ +ALTER TABLE `zone` +ADD COLUMN `max_level` tinyint(3) UNSIGNED NOT NULL DEFAULT 255 AFTER `min_level`; \ No newline at end of file diff --git a/utils/sql/git/required/2023_01_15_chatchannel_reserved_names.sql b/utils/sql/git/required/2023_01_15_chatchannel_reserved_names.sql new file mode 100644 index 000000000..c39424d8f --- /dev/null +++ b/utils/sql/git/required/2023_01_15_chatchannel_reserved_names.sql @@ -0,0 +1,13 @@ +CREATE TABLE `chatchannel_reserved_names` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(64) NOT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +ALTER TABLE `chatchannels` + ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST, +DROP PRIMARY KEY, +ADD PRIMARY KEY (`id`) USING BTREE, +ADD UNIQUE INDEX(`name`) diff --git a/utils/sql/git/required/2023_01_15_merc_data.sql b/utils/sql/git/required/2023_01_15_merc_data.sql new file mode 100644 index 000000000..c262dc43e --- /dev/null +++ b/utils/sql/git/required/2023_01_15_merc_data.sql @@ -0,0 +1,7069 @@ +SET NAMES utf8; +SET +FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for merc_armorinfo +-- ---------------------------- +DROP TABLE IF EXISTS `merc_armorinfo`; +CREATE TABLE `merc_armorinfo` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `merc_npc_type_id` int(11) UNSIGNED NOT NULL, + `minlevel` tinyint(2) UNSIGNED NOT NULL DEFAULT 1, + `maxlevel` tinyint(2) UNSIGNED NOT NULL DEFAULT 255, + `texture` tinyint(2) UNSIGNED NOT NULL DEFAULT 0, + `helmtexture` tinyint(2) UNSIGNED NOT NULL DEFAULT 0, + `armortint_id` int(10) UNSIGNED NOT NULL DEFAULT 0, + `armortint_red` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, + `armortint_green` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, + `armortint_blue` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 41 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_armorinfo +-- ---------------------------- +INSERT INTO `merc_armorinfo` +VALUES (1, 1, 1, 255, 3, 0, 0, 0, 0, 0), + (2, 2, 1, 255, 3, 0, 0, 0, 0, 0), + (3, 3, 1, 255, 3, 0, 0, 0, 0, 0), + (4, 4, 1, 255, 3, 0, 0, 0, 0, 0), + (5, 5, 1, 255, 3, 0, 0, 0, 0, 0), + (6, 6, 1, 255, 3, 0, 0, 0, 0, 0), + (7, 7, 1, 255, 3, 0, 0, 0, 0, 0), + (8, 8, 1, 255, 3, 0, 0, 0, 0, 0), + (9, 9, 1, 255, 3, 0, 0, 0, 0, 0), + (10, 10, 1, 255, 3, 0, 0, 0, 0, 0), + (11, 11, 1, 255, 3, 0, 0, 0, 0, 0), + (12, 12, 1, 255, 3, 0, 0, 0, 0, 0), + (13, 13, 1, 255, 3, 0, 0, 0, 0, 0), + (14, 14, 1, 255, 3, 0, 0, 0, 0, 0), + (15, 15, 1, 255, 3, 0, 0, 0, 0, 0), + (16, 16, 1, 255, 3, 0, 0, 0, 0, 0), + (17, 17, 1, 255, 3, 0, 0, 0, 0, 0), + (18, 18, 1, 255, 3, 0, 0, 0, 0, 0), + (19, 19, 1, 255, 3, 0, 0, 0, 0, 0), + (20, 20, 1, 255, 3, 0, 0, 0, 0, 0), + (21, 21, 1, 255, 2, 0, 0, 0, 0, 0), + (22, 22, 1, 255, 2, 0, 0, 0, 0, 0), + (23, 23, 1, 255, 2, 0, 0, 0, 0, 0), + (24, 24, 1, 255, 2, 0, 0, 0, 0, 0), + (25, 25, 1, 255, 2, 0, 0, 0, 0, 0), + (26, 26, 1, 255, 2, 0, 0, 0, 0, 0), + (27, 27, 1, 255, 2, 0, 0, 0, 0, 0), + (28, 28, 1, 255, 2, 0, 0, 0, 0, 0), + (29, 29, 1, 255, 2, 0, 0, 0, 0, 0), + (30, 30, 1, 255, 2, 0, 0, 0, 0, 0), + (31, 31, 1, 255, 10, 0, 0, 0, 0, 0), + (32, 32, 1, 255, 10, 0, 0, 0, 0, 0), + (33, 33, 1, 255, 10, 0, 0, 0, 0, 0), + (34, 34, 1, 255, 10, 0, 0, 0, 0, 0), + (35, 35, 1, 255, 10, 0, 0, 0, 0, 0), + (36, 36, 1, 255, 10, 0, 0, 0, 0, 0), + (37, 37, 1, 255, 10, 0, 0, 0, 0, 0), + (38, 38, 1, 255, 10, 0, 0, 0, 0, 0), + (39, 39, 1, 255, 10, 0, 0, 0, 0, 0), + (40, 40, 1, 255, 10, 0, 0, 0, 0, 0); + +-- ---------------------------- +-- Table structure for merc_buffs +-- ---------------------------- +DROP TABLE IF EXISTS `merc_buffs`; +CREATE TABLE `merc_buffs` +( + `MercBuffId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `MercId` int(10) UNSIGNED NOT NULL DEFAULT 0, + `SpellId` int(10) UNSIGNED NOT NULL DEFAULT 0, + `CasterLevel` int(10) UNSIGNED NOT NULL DEFAULT 0, + `DurationFormula` int(10) UNSIGNED NOT NULL DEFAULT 0, + `TicsRemaining` int(11) NOT NULL DEFAULT 0, + `PoisonCounters` int(11) UNSIGNED NOT NULL DEFAULT 0, + `DiseaseCounters` int(11) UNSIGNED NOT NULL DEFAULT 0, + `CurseCounters` int(11) UNSIGNED NOT NULL DEFAULT 0, + `CorruptionCounters` int(11) UNSIGNED NOT NULL DEFAULT 0, + `HitCount` int(10) UNSIGNED NOT NULL DEFAULT 0, + `MeleeRune` int(10) UNSIGNED NOT NULL DEFAULT 0, + `MagicRune` int(10) UNSIGNED NOT NULL DEFAULT 0, + `dot_rune` int(10) NOT NULL DEFAULT 0, + `caston_x` int(10) NOT NULL DEFAULT 0, + `Persistent` tinyint(1) NOT NULL DEFAULT 0, + `caston_y` int(10) NOT NULL DEFAULT 0, + `caston_z` int(10) NOT NULL DEFAULT 0, + `ExtraDIChance` int(10) NOT NULL DEFAULT 0, + PRIMARY KEY (`MercBuffId`) USING BTREE, + INDEX `FK_mercbuff_1`(`MercId`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Table structure for merc_inventory +-- ---------------------------- +DROP TABLE IF EXISTS `merc_inventory`; +CREATE TABLE `merc_inventory` +( + `merc_inventory_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `merc_subtype_id` int(10) UNSIGNED NOT NULL DEFAULT 0, + `item_id` int(11) UNSIGNED NOT NULL DEFAULT 0, + `min_level` int(10) UNSIGNED NOT NULL DEFAULT 0, + `max_level` int(10) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`merc_inventory_id`) USING BTREE, + INDEX `FK_merc_inventory_1`(`merc_subtype_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 42 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_inventory +-- ---------------------------- +INSERT INTO `merc_inventory` +VALUES (1, 6, 51735, 1, 85), + (2, 7, 51736, 1, 85), + (3, 8, 51737, 1, 85), + (4, 9, 51738, 1, 85), + (5, 10, 51739, 1, 85), + (6, 6, 51740, 1, 85), + (7, 7, 51741, 1, 85), + (8, 8, 51742, 1, 85), + (9, 9, 51743, 1, 85), + (10, 10, 51744, 1, 85), + (11, 6, 51745, 1, 85), + (12, 7, 51746, 1, 85), + (13, 8, 51747, 1, 85), + (14, 9, 51748, 1, 85), + (15, 10, 51749, 1, 85), + (16, 6, 51750, 1, 85), + (17, 7, 51751, 1, 85), + (18, 8, 51752, 1, 85), + (19, 9, 51753, 1, 85), + (20, 10, 51754, 1, 85), + (21, 16, 51735, 1, 85), + (22, 17, 51736, 1, 85), + (23, 18, 51737, 1, 85), + (24, 19, 51738, 1, 85), + (25, 20, 51739, 1, 85), + (26, 10, 51739, 1, 85), + (27, 16, 51740, 1, 85), + (28, 17, 51741, 1, 85), + (29, 18, 51742, 1, 85), + (30, 19, 51743, 1, 85), + (31, 20, 51744, 1, 85), + (32, 16, 51745, 1, 85), + (33, 17, 51746, 1, 85), + (34, 18, 51747, 1, 85), + (35, 19, 51748, 1, 85), + (36, 20, 51749, 1, 85), + (37, 16, 51750, 1, 85), + (38, 17, 51751, 1, 85), + (39, 18, 51752, 1, 85), + (40, 19, 51753, 1, 85), + (41, 20, 51754, 1, 85); + +-- ---------------------------- +-- Table structure for merc_merchant_entries +-- ---------------------------- +DROP TABLE IF EXISTS `merc_merchant_entries`; +CREATE TABLE `merc_merchant_entries` +( + `merc_merchant_entry_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `merc_merchant_template_id` int(10) UNSIGNED NOT NULL, + `merchant_id` int(11) UNSIGNED NOT NULL, + PRIMARY KEY (`merc_merchant_entry_id`) USING BTREE, + INDEX `FK_merc_merchant_entries_1`(`merc_merchant_template_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 57 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_merchant_entries +-- ---------------------------- +INSERT INTO `merc_merchant_entries` +VALUES (1, 2, 202030), + (2, 22, 202030), + (3, 2, 202031), + (4, 22, 202031), + (5, 7, 202100), + (6, 22, 202100), + (7, 7, 202032), + (8, 22, 202032), + (9, 3, 202113), + (10, 14, 202113), + (11, 3, 202097), + (12, 14, 202097), + (13, 19, 202114), + (14, 19, 202053), + (15, 12, 202103), + (16, 12, 202111), + (17, 17, 202028), + (18, 21, 202028), + (19, 17, 202052), + (20, 21, 202052), + (21, 8, 202101), + (22, 20, 202101), + (23, 8, 202102), + (24, 20, 202102), + (25, 16, 202107), + (26, 13, 202107), + (27, 18, 202107), + (28, 16, 202116), + (29, 13, 202116), + (30, 18, 202116), + (31, 5, 202099), + (32, 24, 202099), + (33, 5, 202108), + (34, 24, 202108), + (35, 4, 202109), + (36, 4, 202035), + (37, 6, 202104), + (38, 6, 202119), + (39, 1, 202115), + (40, 1, 202096), + (41, 23, 202112), + (42, 23, 202098), + (43, 10, 202118), + (44, 15, 202118), + (45, 10, 202106), + (46, 15, 202106), + (47, 9, 202117), + (48, 13, 202117), + (49, 22, 202117), + (50, 9, 202105), + (51, 13, 202105), + (52, 22, 202105), + (53, 11, 202027), + (54, 11, 202110), + (55, 23, 394050), + (56, 23, 394148); + +-- ---------------------------- +-- Table structure for merc_merchant_template_entries +-- ---------------------------- +DROP TABLE IF EXISTS `merc_merchant_template_entries`; +CREATE TABLE `merc_merchant_template_entries` +( + `merc_merchant_template_entry_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `merc_merchant_template_id` int(10) UNSIGNED NOT NULL, + `merc_template_id` int(10) UNSIGNED NOT NULL, + PRIMARY KEY (`merc_merchant_template_entry_id`) USING BTREE, + INDEX `FK_merc_merchant_template_entries_1`(`merc_merchant_template_id`) USING BTREE, + INDEX `FK_merc_merchant_template_entries_2`(`merc_template_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 554 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_merchant_template_entries +-- ---------------------------- +INSERT INTO `merc_merchant_template_entries` +VALUES (1, 1, 1), + (2, 1, 2), + (3, 1, 3), + (4, 1, 4), + (5, 1, 5), + (6, 1, 6), + (7, 1, 7), + (8, 1, 8), + (9, 1, 9), + (10, 1, 10), + (11, 1, 11), + (12, 1, 12), + (13, 1, 13), + (14, 1, 14), + (15, 1, 15), + (16, 1, 16), + (17, 1, 17), + (18, 1, 18), + (19, 1, 19), + (20, 1, 20), + (21, 1, 21), + (22, 1, 22), + (23, 1, 23), + (24, 1, 24), + (25, 1, 25), + (26, 1, 26), + (27, 1, 27), + (28, 1, 28), + (29, 2, 29), + (30, 2, 30), + (31, 2, 31), + (32, 2, 32), + (33, 2, 33), + (34, 2, 34), + (35, 2, 35), + (36, 2, 36), + (37, 2, 37), + (38, 2, 38), + (39, 2, 39), + (40, 2, 40), + (41, 2, 41), + (42, 2, 42), + (43, 2, 43), + (44, 2, 44), + (45, 2, 45), + (46, 2, 46), + (47, 2, 47), + (48, 2, 48), + (49, 2, 49), + (50, 2, 50), + (51, 2, 51), + (52, 2, 52), + (53, 2, 53), + (54, 2, 54), + (55, 2, 55), + (56, 2, 56), + (57, 3, 57), + (58, 3, 58), + (59, 3, 59), + (60, 3, 60), + (61, 3, 61), + (62, 3, 62), + (63, 3, 63), + (64, 3, 64), + (65, 3, 65), + (66, 3, 66), + (67, 3, 67), + (68, 3, 68), + (69, 3, 69), + (70, 3, 70), + (71, 3, 71), + (72, 3, 72), + (73, 3, 73), + (74, 3, 74), + (75, 3, 75), + (76, 3, 76), + (77, 3, 77), + (78, 4, 78), + (79, 4, 79), + (80, 4, 80), + (81, 4, 81), + (82, 4, 82), + (83, 4, 83), + (84, 4, 84), + (85, 4, 85), + (86, 4, 86), + (87, 4, 87), + (88, 4, 88), + (89, 4, 89), + (90, 4, 90), + (91, 4, 91), + (92, 4, 92), + (93, 4, 93), + (94, 4, 94), + (95, 4, 95), + (96, 4, 96), + (97, 4, 97), + (98, 4, 98), + (99, 4, 99), + (100, 4, 100), + (101, 4, 101), + (102, 4, 102), + (103, 4, 103), + (104, 4, 104), + (105, 4, 105), + (106, 5, 106), + (107, 5, 107), + (108, 5, 108), + (109, 5, 109), + (110, 5, 110), + (111, 5, 111), + (112, 5, 112), + (113, 5, 113), + (114, 5, 114), + (115, 5, 115), + (116, 5, 116), + (117, 5, 117), + (118, 5, 118), + (119, 5, 119), + (120, 5, 120), + (121, 5, 121), + (122, 5, 122), + (123, 5, 123), + (124, 5, 124), + (125, 5, 125), + (126, 5, 126), + (127, 6, 127), + (128, 6, 128), + (129, 6, 129), + (130, 6, 130), + (131, 6, 131), + (132, 6, 132), + (133, 6, 133), + (134, 6, 134), + (135, 6, 135), + (136, 6, 136), + (137, 6, 137), + (138, 6, 138), + (139, 6, 139), + (140, 6, 140), + (141, 6, 141), + (142, 6, 142), + (143, 6, 143), + (144, 6, 144), + (145, 6, 145), + (146, 6, 146), + (147, 6, 147), + (148, 6, 148), + (149, 6, 149), + (150, 6, 150), + (151, 6, 151), + (152, 6, 152), + (153, 6, 153), + (154, 6, 154), + (155, 7, 155), + (156, 7, 156), + (157, 7, 157), + (158, 7, 158), + (159, 7, 159), + (160, 7, 160), + (161, 7, 161), + (162, 7, 162), + (163, 7, 163), + (164, 7, 164), + (165, 7, 165), + (166, 7, 166), + (167, 7, 167), + (168, 7, 168), + (169, 7, 169), + (170, 7, 170), + (171, 7, 171), + (172, 7, 172), + (173, 7, 173), + (174, 7, 174), + (175, 7, 175), + (176, 7, 176), + (177, 7, 177), + (178, 7, 178), + (179, 7, 179), + (180, 7, 180), + (181, 7, 181), + (182, 7, 182), + (183, 8, 183), + (184, 8, 184), + (185, 8, 185), + (186, 8, 186), + (187, 8, 187), + (188, 8, 188), + (189, 8, 189), + (190, 8, 190), + (191, 8, 191), + (192, 8, 192), + (193, 8, 193), + (194, 8, 194), + (195, 8, 195), + (196, 8, 196), + (197, 8, 197), + (198, 8, 198), + (199, 8, 199), + (200, 8, 200), + (201, 8, 201), + (202, 8, 202), + (203, 8, 203), + (204, 8, 204), + (205, 8, 205), + (206, 8, 206), + (207, 8, 207), + (208, 8, 208), + (209, 8, 209), + (210, 8, 210), + (211, 9, 211), + (212, 9, 212), + (213, 9, 213), + (214, 9, 214), + (215, 9, 215), + (216, 9, 216), + (217, 9, 217), + (218, 9, 218), + (219, 9, 219), + (220, 9, 220), + (221, 9, 221), + (222, 9, 222), + (223, 9, 223), + (224, 9, 224), + (225, 9, 225), + (226, 9, 226), + (227, 9, 227), + (228, 9, 228), + (229, 9, 229), + (230, 9, 230), + (231, 9, 231), + (232, 10, 232), + (233, 10, 233), + (234, 10, 234), + (235, 10, 235), + (236, 10, 236), + (237, 10, 237), + (238, 10, 238), + (239, 10, 239), + (240, 10, 240), + (241, 10, 241), + (242, 10, 242), + (243, 10, 243), + (244, 10, 244), + (245, 10, 245), + (246, 10, 246), + (247, 10, 247), + (248, 10, 248), + (249, 10, 249), + (250, 10, 250), + (251, 10, 251), + (252, 10, 252), + (253, 11, 253), + (254, 11, 254), + (255, 11, 255), + (256, 11, 256), + (257, 11, 257), + (258, 11, 258), + (259, 11, 259), + (260, 11, 260), + (261, 11, 261), + (262, 11, 262), + (263, 11, 263), + (264, 11, 264), + (265, 11, 265), + (266, 11, 266), + (267, 11, 267), + (268, 11, 268), + (269, 11, 269), + (270, 11, 270), + (271, 11, 271), + (272, 11, 272), + (273, 11, 273), + (274, 11, 274), + (275, 11, 275), + (276, 11, 276), + (277, 11, 277), + (278, 11, 278), + (279, 11, 279), + (280, 11, 280), + (281, 12, 281), + (282, 12, 282), + (283, 12, 283), + (284, 12, 284), + (285, 12, 285), + (286, 12, 286), + (287, 12, 287), + (288, 12, 288), + (289, 12, 289), + (290, 12, 290), + (291, 12, 291), + (292, 12, 292), + (293, 12, 293), + (294, 12, 294), + (295, 12, 295), + (296, 12, 296), + (297, 12, 297), + (298, 12, 298), + (299, 12, 299), + (300, 12, 300), + (301, 12, 301), + (302, 12, 302), + (303, 12, 303), + (304, 12, 304), + (305, 12, 305), + (306, 12, 306), + (307, 12, 307), + (308, 12, 308), + (309, 14, 309), + (310, 14, 310), + (311, 14, 311), + (312, 14, 312), + (313, 14, 313), + (314, 14, 314), + (315, 14, 315), + (316, 15, 316), + (317, 15, 317), + (318, 15, 318), + (319, 15, 319), + (320, 15, 320), + (321, 15, 321), + (322, 15, 322), + (323, 15, 323), + (324, 15, 324), + (325, 15, 325), + (326, 15, 326), + (327, 15, 327), + (328, 15, 328), + (329, 15, 329), + (330, 15, 330), + (331, 15, 331), + (332, 15, 332), + (333, 15, 333), + (334, 15, 334), + (335, 15, 335), + (336, 15, 336), + (337, 15, 337), + (338, 15, 338), + (339, 15, 339), + (340, 15, 340), + (341, 15, 341), + (342, 15, 342), + (343, 15, 343), + (344, 16, 344), + (345, 16, 345), + (346, 16, 346), + (347, 16, 347), + (348, 16, 348), + (349, 16, 349), + (350, 16, 350), + (351, 16, 351), + (352, 16, 352), + (353, 16, 353), + (354, 16, 354), + (355, 16, 355), + (356, 16, 356), + (357, 16, 357), + (358, 16, 358), + (359, 16, 359), + (360, 16, 360), + (361, 16, 361), + (362, 16, 362), + (363, 16, 363), + (364, 16, 364), + (365, 17, 365), + (366, 17, 366), + (367, 17, 367), + (368, 17, 368), + (369, 17, 369), + (370, 17, 370), + (371, 17, 371), + (372, 17, 372), + (373, 17, 373), + (374, 17, 374), + (375, 17, 375), + (376, 17, 376), + (377, 17, 377), + (378, 17, 378), + (379, 17, 379), + (380, 17, 380), + (381, 17, 381), + (382, 17, 382), + (383, 17, 383), + (384, 17, 384), + (385, 17, 385), + (386, 17, 386), + (387, 17, 387), + (388, 17, 388), + (389, 17, 389), + (390, 17, 390), + (391, 17, 391), + (392, 17, 392), + (393, 19, 393), + (394, 19, 394), + (395, 19, 395), + (396, 19, 396), + (397, 19, 397), + (398, 19, 398), + (399, 19, 399), + (400, 19, 400), + (401, 19, 401), + (402, 19, 402), + (403, 19, 403), + (404, 19, 404), + (405, 19, 405), + (406, 19, 406), + (407, 19, 407), + (408, 19, 408), + (409, 19, 409), + (410, 19, 410), + (411, 19, 411), + (412, 19, 412), + (413, 19, 413), + (414, 19, 414), + (415, 19, 415), + (416, 19, 416), + (417, 19, 417), + (418, 19, 418), + (419, 19, 419), + (420, 19, 420), + (421, 20, 421), + (422, 20, 422), + (423, 20, 423), + (424, 20, 424), + (425, 20, 425), + (426, 20, 426), + (427, 20, 427), + (428, 20, 428), + (429, 20, 429), + (430, 20, 430), + (431, 20, 431), + (432, 20, 432), + (433, 20, 433), + (434, 20, 434), + (435, 20, 435), + (436, 20, 436), + (437, 20, 437), + (438, 20, 438), + (439, 20, 439), + (440, 20, 440), + (441, 20, 441), + (442, 20, 442), + (443, 20, 443), + (444, 20, 444), + (445, 20, 445), + (446, 20, 446), + (447, 20, 447), + (448, 20, 448), + (449, 21, 449), + (450, 21, 450), + (451, 21, 451), + (452, 21, 452), + (453, 21, 453), + (454, 21, 454), + (455, 21, 455), + (456, 21, 456), + (457, 21, 457), + (458, 21, 458), + (459, 21, 459), + (460, 21, 460), + (461, 21, 461), + (462, 21, 462), + (463, 21, 463), + (464, 21, 464), + (465, 21, 465), + (466, 21, 466), + (467, 21, 467), + (468, 21, 468), + (469, 21, 469), + (470, 22, 470), + (471, 22, 471), + (472, 22, 472), + (473, 22, 473), + (474, 22, 474), + (475, 22, 475), + (476, 22, 476), + (477, 22, 477), + (478, 22, 478), + (479, 22, 479), + (480, 22, 480), + (481, 22, 481), + (482, 22, 482), + (483, 22, 483), + (484, 22, 484), + (485, 22, 485), + (486, 22, 486), + (487, 22, 487), + (488, 22, 488), + (489, 22, 489), + (490, 22, 490), + (491, 22, 491), + (492, 22, 492), + (493, 22, 493), + (494, 22, 494), + (495, 22, 495), + (496, 22, 496), + (497, 22, 497), + (498, 23, 498), + (499, 23, 499), + (500, 23, 500), + (501, 23, 501), + (502, 23, 502), + (503, 23, 503), + (504, 23, 504), + (505, 23, 505), + (506, 23, 506), + (507, 23, 507), + (508, 23, 508), + (509, 23, 509), + (510, 23, 510), + (511, 23, 511), + (512, 23, 512), + (513, 23, 513), + (514, 23, 514), + (515, 23, 515), + (516, 23, 516), + (517, 23, 517), + (518, 23, 518), + (519, 23, 519), + (520, 23, 520), + (521, 23, 521), + (522, 23, 522), + (523, 23, 523), + (524, 23, 524), + (525, 23, 525), + (526, 24, 526), + (527, 24, 527), + (528, 24, 528), + (529, 24, 529), + (530, 24, 530), + (531, 24, 531), + (532, 24, 532), + (533, 24, 533), + (534, 24, 534), + (535, 24, 535), + (536, 24, 536), + (537, 24, 537), + (538, 24, 538), + (539, 24, 539), + (540, 24, 540), + (541, 24, 541), + (542, 24, 542), + (543, 24, 543), + (544, 24, 544), + (545, 24, 545), + (546, 24, 546), + (547, 24, 547), + (548, 24, 548), + (549, 24, 549), + (550, 24, 550), + (551, 24, 551), + (552, 24, 552), + (553, 24, 553); + +-- ---------------------------- +-- Table structure for merc_merchant_templates +-- ---------------------------- +DROP TABLE IF EXISTS `merc_merchant_templates`; +CREATE TABLE `merc_merchant_templates` +( + `merc_merchant_template_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(50) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, + `qglobal` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, + PRIMARY KEY (`merc_merchant_template_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_merchant_templates +-- ---------------------------- +INSERT INTO `merc_merchant_templates` +VALUES (1, 'Default Human Mercenaries', ''), + (2, 'Default Barbarian Mercenaries', ''), + (3, 'Default Erudite Mercenaries', ''), + (4, 'Default Wood Elf Mercenaries', ''), + (5, 'Default High Elf Mercenaries', ''), + (6, 'Default Dark Elf Mercenaries', ''), + (7, 'Default Half Elf Mercenaries', ''), + (8, 'Default Dwarf Mercenaries', ''), + (9, 'Default Troll Mercenaries', ''), + (10, 'Default Ogre Mercenaries', ''), + (11, 'Default Halfling Mercenaries', ''), + (12, 'Default Gnome Mercenaries', ''), + (13, 'Default Froglok Mercenaries', ''), + (14, 'Default Kobold Mercenaries', ''), + (15, 'Default Lizard Man Mercenaries', ''), + (16, 'Default Iksar Mercenaries', ''), + (17, 'Default Vah Shir Mercenaries', ''), + (18, 'Default Kunark Goblin Mercenaries', ''), + (19, 'Default Guktan Mercenaries', ''), + (20, 'Default Goblin Mercenaries', ''), + (21, 'Default Sporali Mercenaries', ''), + (22, 'Default Orc Mercenaries', ''), + (23, 'Default Drakkin Mercenaries', ''), + (24, 'Default Brownie Mercenaries', ''); + +-- ---------------------------- +-- Table structure for merc_name_types +-- ---------------------------- +DROP TABLE IF EXISTS `merc_name_types`; +CREATE TABLE `merc_name_types` +( + `name_type_id` int(10) UNSIGNED NOT NULL, + `class_id` int(10) UNSIGNED NOT NULL, + `prefix` varchar(25) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, + `suffix` varchar(25) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, + PRIMARY KEY (`name_type_id`, `class_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_name_types +-- ---------------------------- +INSERT INTO `merc_name_types` +VALUES (1, 0, '', 'mercenary'), + (2, 0, '', 'hireling'), + (3, 0, 'hired', ''), + (4, 1, '', 'defender'), + (4, 2, '', 'soother'), + (4, 4, '', 'fighter'), + (4, 12, '', 'caster'), + (5, 1, '', 'brawler'), + (5, 2, '', 'mender'), + (5, 4, '', ''), + (5, 12, '', ''), + (6, 2, '', 'acolyte'), + (7, 1, '', 'nightlord'), + (8, 2, '', 'mendicant'); + +-- ---------------------------- +-- Table structure for merc_npc_types +-- ---------------------------- +DROP TABLE IF EXISTS `merc_npc_types`; +CREATE TABLE `merc_npc_types` +( + `merc_npc_type_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `proficiency_id` tinyint(3) UNSIGNED NOT NULL, + `tier_id` tinyint(3) UNSIGNED NOT NULL, + `class_id` int(10) UNSIGNED NOT NULL, + `name` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, + PRIMARY KEY (`merc_npc_type_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 41 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_npc_types +-- ---------------------------- +INSERT INTO `merc_npc_types` +VALUES (1, 1, 1, 1, 'Apprentice Tank - Tier I'), + (2, 1, 2, 1, 'Apprentice Tank - Tier II'), + (3, 1, 3, 1, 'Apprentice Tank - Tier III'), + (4, 1, 4, 1, 'Apprentice Tank - Tier IV'), + (5, 1, 5, 1, 'Apprentice Tank - Tier V'), + (6, 2, 1, 1, 'Journeyman Tank - Tier I'), + (7, 2, 2, 1, 'Journeyman Tank - Tier II'), + (8, 2, 3, 1, 'Journeyman Tank - Tier III'), + (9, 2, 4, 1, 'Journeyman Tank - Tier IV'), + (10, 2, 5, 1, 'Journeyman Tank - Tier V'), + (11, 1, 1, 2, 'Apprentice Healer - Tier I'), + (12, 1, 2, 2, 'Apprentice Healer - Tier II'), + (13, 1, 3, 2, 'Apprentice Healer - Tier III'), + (14, 1, 4, 2, 'Apprentice Healer - Tier IV'), + (15, 1, 5, 2, 'Apprentice Healer - Tier V'), + (16, 2, 1, 2, 'Journeyman Healer - Tier I'), + (17, 2, 2, 2, 'Journeyman Healer - Tier II'), + (18, 2, 3, 2, 'Journeyman Healer - Tier III'), + (19, 2, 4, 2, 'Journeyman Healer - Tier IV'), + (20, 2, 5, 2, 'Journeyman Healer - Tier V'), + (21, 1, 1, 9, 'Apprentice Melee DPS - Tier I'), + (22, 1, 2, 9, 'Apprentice Melee DPS - Tier II'), + (23, 1, 3, 9, 'Apprentice Melee DPS - Tier III'), + (24, 1, 4, 9, 'Apprentice Melee DPS - Tier IV'), + (25, 1, 5, 9, 'Apprentice Melee DPS - Tier V'), + (26, 2, 1, 9, 'Journeyman Melee DPS - Tier I'), + (27, 2, 2, 9, 'Journeyman Melee DPS - Tier II'), + (28, 2, 3, 9, 'Journeyman Melee DPS - Tier III'), + (29, 2, 4, 9, 'Journeyman Melee DPS - Tier IV'), + (30, 2, 5, 9, 'Journeyman Melee DPS - Tier V'), + (31, 1, 1, 12, 'Apprentice Caster DPS - Tier I'), + (32, 1, 2, 12, 'Apprentice Caster DPS - Tier II'), + (33, 1, 3, 12, 'Apprentice Caster DPS - Tier III'), + (34, 1, 4, 12, 'Apprentice Caster DPS - Tier IV'), + (35, 1, 5, 12, 'Apprentice Caster DPS - Tier V'), + (36, 2, 1, 12, 'Journeyman Caster DPS - Tier I'), + (37, 2, 2, 12, 'Journeyman Caster DPS - Tier II'), + (38, 2, 3, 12, 'Journeyman Caster DPS - Tier III'), + (39, 2, 4, 12, 'Journeyman Caster DPS - Tier IV'), + (40, 2, 5, 12, 'Journeyman Caster DPS - Tier V'); + +-- ---------------------------- +-- Table structure for merc_spell_list_entries +-- ---------------------------- +DROP TABLE IF EXISTS `merc_spell_list_entries`; +CREATE TABLE `merc_spell_list_entries` +( + `merc_spell_list_entry_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `merc_spell_list_id` int(10) UNSIGNED NOT NULL, + `spell_id` int(10) UNSIGNED NOT NULL, + `spell_type` int(10) UNSIGNED NOT NULL DEFAULT 0, + `stance_id` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, + `minlevel` tinyint(3) UNSIGNED NOT NULL DEFAULT 1, + `maxlevel` tinyint(3) UNSIGNED NOT NULL DEFAULT 255, + `slot` tinyint(4) NOT NULL DEFAULT -1, + `procChance` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`merc_spell_list_entry_id`) USING BTREE, + INDEX `FK_merc_spell_lists_1`(`merc_spell_list_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 730 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_spell_list_entries +-- ---------------------------- +INSERT INTO `merc_spell_list_entries` +VALUES (293, 1, 17189, 1, 0, 1, 255, 1, 0), + (294, 1, 4608, 1, 0, 20, 51, 2, 0), + (295, 1, 4681, 1, 0, 52, 55, 2, 0), + (296, 1, 4682, 1, 0, 56, 62, 2, 0), + (297, 1, 17188, 1, 0, 59, 255, 1, 0), + (298, 1, 4697, 1, 0, 63, 64, 2, 0), + (299, 1, 5015, 1, 0, 65, 69, 2, 0), + (300, 1, 7266, 1, 0, 69, 80, 3, 0), + (301, 1, 20939, 1, 0, 70, 74, 2, 0), + (302, 1, 15296, 1, 0, 75, 79, 2, 0), + (303, 1, 0, 1, 0, 80, 84, 2, 0), + (304, 1, 19537, 1, 0, 81, 85, 3, 0), + (305, 1, 19531, 1, 0, 85, 89, 2, 0), + (306, 2, 17189, 1, 0, 1, 255, 1, 0), + (307, 2, 4608, 1, 0, 20, 51, 2, 0), + (308, 2, 4681, 1, 0, 52, 55, 2, 0), + (309, 2, 4682, 1, 0, 56, 62, 2, 0), + (310, 2, 17188, 1, 0, 59, 255, 1, 0), + (311, 2, 4697, 1, 0, 63, 64, 2, 0), + (312, 2, 5016, 1, 0, 65, 69, 2, 0), + (313, 2, 7266, 1, 0, 69, 80, 3, 0), + (314, 2, 20939, 1, 0, 70, 74, 2, 0), + (315, 2, 15297, 1, 0, 75, 79, 2, 0), + (316, 2, 0, 1, 0, 80, 84, 2, 0), + (317, 2, 19538, 1, 0, 81, 85, 3, 0), + (318, 2, 19532, 1, 0, 85, 89, 2, 0), + (319, 3, 200, 2, 0, 1, 3, 1, 0), + (320, 3, 202, 8, 0, 1, 6, 1, 0), + (321, 3, 203, 32768, 0, 1, 21, 2, 0), + (322, 3, 17, 2, 0, 4, 9, 1, 0), + (323, 3, 213, 32768, 0, 4, 27, 2, 0), + (324, 3, 219, 8, 0, 7, 21, 1, 0), + (325, 3, 4056, 32768, 0, 8, 22, 2, 0), + (326, 3, 12, 2, 0, 10, 19, 2, 0), + (327, 3, 485, 8, 0, 11, 20, 2, 0), + (328, 3, 2168, 65536, 0, 12, 17, 1, 0), + (329, 3, 3575, 8, 0, 15, 34, 3, 0), + (330, 3, 89, 8, 0, 17, 20, 1, 0), + (331, 3, 2169, 65536, 0, 18, 21, 1, 0), + (332, 3, 2502, 2, 0, 19, 28, 1, 0), + (333, 3, 17397, 2, 0, 20, 29, 2, 0), + (334, 3, 4088, 8, 0, 20, 39, 4, 0), + (335, 3, 486, 8, 0, 21, 30, 2, 0), + (336, 3, 244, 8, 0, 22, 31, 1, 0), + (337, 3, 95, 32768, 0, 22, 47, 2, 0), + (338, 3, 2170, 65536, 0, 22, 26, 1, 0), + (339, 3, 4057, 32768, 0, 23, 37, 2, 0), + (340, 3, 391, 65536, 0, 27, 31, 1, 0), + (341, 3, 96, 32768, 0, 28, 50, 2, 0), + (342, 3, 2175, 2, 0, 29, 43, 1, 0), + (343, 3, 135, 2, 0, 30, 44, 2, 0), + (344, 3, 9, 2, 0, 30, 52, 2, 0), + (345, 3, 487, 8, 0, 31, 40, 2, 0), + (346, 3, 312, 8, 0, 32, 39, 1, 0), + (347, 3, 4175, 65536, 0, 32, 36, 1, 0), + (348, 3, 3576, 8, 0, 35, 61, 3, 0), + (349, 3, 388, 65536, 0, 37, 41, 1, 0), + (350, 3, 2946, 32768, 0, 38, 53, 2, 0), + (351, 3, 13, 2, 0, 39, 75, 2, 0), + (352, 3, 3692, 8, 0, 40, 59, 1, 0), + (353, 3, 4089, 8, 0, 40, 53, 4, 0), + (354, 3, 488, 8, 0, 41, 53, 2, 0), + (355, 3, 2172, 65536, 0, 42, 46, 1, 0), + (356, 3, 1444, 2, 0, 44, 58, 1, 0), + (357, 3, 136, 2, 0, 45, 51, 2, 0), + (358, 3, 4053, 8, 0, 45, 59, 1, 0), + (359, 3, 392, 65536, 0, 47, 255, 1, 0), + (360, 3, 97, 32768, 0, 48, 57, 2, 0), + (361, 3, 1518, 2, 0, 51, 58, 2, 0), + (362, 3, 3693, 32768, 0, 51, 83, 3, 0), + (363, 3, 1520, 2, 0, 52, 56, 2, 0), + (364, 3, 1519, 2, 0, 53, 57, 2, 0), + (365, 3, 1535, 8, 0, 54, 60, 2, 0), + (366, 3, 4090, 8, 0, 54, 61, 4, 0), + (367, 3, 2880, 32768, 0, 54, 93, 2, 0), + (368, 3, 1521, 2, 0, 57, 63, 2, 0), + (369, 3, 1774, 8, 0, 58, 59, 6, 0), + (370, 3, 2182, 2, 0, 58, 62, 2, 0), + (371, 3, 1525, 32768, 0, 58, 83, 2, 0), + (372, 3, 1522, 2, 0, 59, 61, 1, 0), + (373, 3, 2462, 8, 0, 59, 60, 6, 0), + (374, 3, 2893, 8, 0, 60, 62, 6, 0), + (375, 3, 1447, 8, 0, 60, 61, 1, 0), + (376, 3, 2510, 8, 0, 60, 61, 1, 0), + (377, 3, 2122, 8, 0, 60, 61, 1, 0), + (378, 3, 2180, 2, 0, 60, 64, 1, 0), + (379, 3, 1523, 2, 0, 60, 75, 2, 0), + (380, 3, 3465, 2, 0, 61, 65, 2, 0), + (381, 3, 3466, 2, 0, 61, 65, 2, 0), + (382, 3, 3475, 2, 0, 62, 64, 1, 0), + (383, 3, 3467, 8, 0, 62, 66, 1, 0), + (384, 3, 3472, 8, 0, 62, 66, 3, 0), + (385, 3, 4091, 8, 0, 62, 66, 4, 0), + (386, 3, 3047, 2, 0, 63, 69, 1, 0), + (387, 3, 3480, 2, 0, 63, 64, 2, 0), + (388, 3, 3471, 2, 0, 64, 68, 2, 0), + (389, 3, 4108, 8, 0, 64, 66, 3, 0), + (390, 3, 3479, 8, 0, 65, 66, 1, 0), + (391, 3, 4882, 2, 0, 65, 66, 1, 0), + (392, 3, 4880, 2, 0, 65, 67, 2, 0), + (393, 3, 5252, 2, 0, 66, 71, 2, 0), + (394, 3, 5251, 2, 0, 66, 255, 2, 0), + (395, 3, 5257, 8, 0, 67, 71, 1, 0), + (396, 3, 5259, 2, 0, 67, 255, 1, 0), + (397, 3, 5258, 8, 0, 67, 70, 3, 0), + (398, 3, 5261, 8, 0, 67, 72, 4, 0), + (399, 3, 5265, 2, 0, 68, 72, 2, 0), + (400, 3, 5272, 8, 0, 69, 255, 7, 0), + (401, 3, 5270, 2, 0, 69, 79, 2, 0), + (402, 3, 5278, 8, 0, 70, 71, 1, 0), + (403, 3, 5277, 8, 0, 70, 74, 1, 0), + (404, 3, 8493, 2, 0, 70, 74, 1, 0), + (405, 3, 14195, 8, 0, 71, 75, 2, 0), + (406, 3, 14192, 2, 0, 71, 75, 2, 0), + (407, 3, 14189, 8, 0, 71, 0, 3, 0), + (408, 3, 14207, 8, 0, 72, 76, 1, 0), + (409, 3, 14213, 2, 0, 72, 76, 1, 0), + (410, 3, 14252, 8, 0, 72, 75, 3, 0), + (411, 3, 14222, 2, 0, 73, 77, 2, 0), + (412, 3, 14231, 2, 0, 73, 77, 2, 0), + (413, 3, 14219, 8, 0, 73, 77, 4, 0), + (414, 3, 14267, 32768, 0, 74, 78, 2, 0), + (415, 3, 14282, 8, 0, 75, 76, 1, 0), + (416, 3, 14279, 8, 0, 75, 79, 2, 0), + (417, 3, 14285, 2, 0, 75, 79, 1, 0), + (418, 3, 14288, 8, 0, 75, 77, 4, 0), + (419, 3, 0, 2, 0, 76, 80, 2, 0), + (420, 3, 0, 8, 0, 76, 80, 2, 0), + (421, 3, 0, 8, 0, 76, 80, 3, 0), + (422, 3, 0, 8, 0, 77, 81, 1, 0), + (423, 3, 0, 2, 0, 77, 81, 1, 0), + (424, 3, 0, 2, 0, 77, 81, 2, 0), + (425, 3, 0, 8, 0, 77, 80, 3, 0), + (426, 3, 0, 2, 0, 78, 82, 2, 0), + (427, 3, 0, 2, 0, 78, 82, 2, 0), + (428, 3, 0, 8, 0, 78, 82, 4, 0), + (429, 3, 0, 32768, 0, 79, 83, 2, 0), + (430, 3, 0, 8, 0, 80, 81, 1, 0), + (431, 3, 0, 8, 0, 80, 84, 2, 0), + (432, 3, 0, 2, 0, 80, 84, 1, 0), + (433, 3, 0, 2, 0, 80, 84, 2, 0), + (434, 3, 0, 8, 0, 80, 82, 4, 0), + (435, 3, 18234, 8, 0, 81, 85, 2, 0), + (436, 3, 18231, 2, 0, 81, 85, 2, 0), + (437, 3, 18228, 8, 0, 81, 85, 3, 0), + (438, 3, 18246, 8, 0, 82, 86, 1, 0), + (439, 3, 18252, 2, 0, 82, 86, 1, 0), + (440, 3, 18352, 2, 0, 82, 86, 2, 0), + (441, 3, 18291, 8, 0, 82, 85, 3, 0), + (442, 3, 18261, 2, 0, 83, 87, 2, 0), + (443, 3, 18270, 2, 0, 83, 87, 2, 0), + (444, 3, 18258, 8, 0, 83, 87, 4, 0), + (445, 3, 18306, 32768, 0, 84, 86, 2, 0), + (446, 3, 18389, 32768, 0, 84, 88, 2, 0), + (447, 3, 18321, 8, 0, 85, 86, 1, 0), + (448, 3, 18318, 8, 0, 85, 89, 2, 0), + (449, 3, 18364, 2, 0, 85, 89, 2, 0), + (450, 3, 18327, 8, 0, 85, 87, 4, 0), + (451, 4, 200, 2, 0, 1, 3, 1, 0), + (452, 4, 202, 8, 0, 1, 6, 1, 0), + (453, 4, 203, 32768, 0, 1, 21, 2, 0), + (454, 4, 17, 2, 0, 4, 9, 1, 0), + (455, 4, 213, 32768, 0, 4, 27, 2, 0), + (456, 4, 219, 8, 0, 7, 21, 1, 0), + (457, 4, 4056, 32768, 0, 8, 22, 2, 0), + (458, 4, 12, 2, 0, 10, 19, 2, 0), + (459, 4, 485, 8, 0, 11, 20, 2, 0), + (460, 4, 2168, 65536, 0, 12, 17, 1, 0), + (461, 4, 3575, 8, 0, 15, 34, 3, 0), + (462, 4, 89, 8, 0, 17, 20, 1, 0), + (463, 4, 2169, 65536, 0, 18, 21, 1, 0), + (464, 4, 2502, 2, 0, 19, 28, 1, 0), + (465, 4, 17397, 2, 0, 20, 29, 2, 0), + (466, 4, 4088, 8, 0, 20, 39, 4, 0), + (467, 4, 486, 8, 0, 21, 30, 2, 0), + (468, 4, 244, 8, 0, 22, 31, 1, 0), + (469, 4, 95, 32768, 0, 22, 47, 2, 0), + (470, 4, 2170, 65536, 0, 22, 26, 1, 0), + (471, 4, 4057, 32768, 0, 23, 37, 2, 0), + (472, 4, 391, 65536, 0, 27, 31, 1, 0), + (473, 4, 96, 32768, 0, 28, 50, 2, 0), + (474, 4, 2175, 2, 0, 29, 43, 1, 0), + (475, 4, 135, 2, 0, 30, 44, 2, 0), + (476, 4, 9, 2, 0, 30, 52, 2, 0), + (477, 4, 487, 8, 0, 31, 40, 2, 0), + (478, 4, 312, 8, 0, 32, 39, 1, 0), + (479, 4, 4175, 65536, 0, 32, 36, 1, 0), + (480, 4, 3576, 8, 0, 35, 61, 3, 0), + (481, 4, 388, 65536, 0, 37, 41, 1, 0), + (482, 4, 2946, 32768, 0, 38, 53, 2, 0), + (483, 4, 13, 2, 0, 39, 75, 2, 0), + (484, 4, 3692, 8, 0, 40, 59, 1, 0), + (485, 4, 4089, 8, 0, 40, 53, 4, 0), + (486, 4, 488, 8, 0, 41, 53, 2, 0), + (487, 4, 2172, 65536, 0, 42, 46, 1, 0), + (488, 4, 1444, 2, 0, 44, 58, 1, 0), + (489, 4, 136, 2, 0, 45, 51, 2, 0), + (490, 4, 4053, 8, 0, 45, 59, 1, 0), + (491, 4, 392, 65536, 0, 47, 55, 1, 0), + (492, 4, 97, 32768, 0, 48, 57, 2, 0), + (493, 4, 1518, 2, 0, 51, 58, 2, 0), + (494, 4, 3693, 32768, 0, 51, 83, 3, 0), + (495, 4, 1520, 2, 0, 52, 56, 2, 0), + (496, 4, 1519, 2, 0, 53, 57, 2, 0), + (497, 4, 1535, 8, 0, 54, 60, 2, 0), + (498, 4, 4090, 8, 0, 54, 61, 4, 0), + (499, 4, 2880, 32768, 0, 54, 93, 2, 0), + (500, 4, 1524, 65536, 0, 56, 255, 1, 0), + (501, 4, 1521, 2, 0, 57, 63, 2, 0), + (502, 4, 1774, 8, 0, 58, 59, 6, 0), + (503, 4, 2182, 2, 0, 58, 62, 2, 0), + (504, 4, 1525, 32768, 0, 58, 83, 2, 0), + (505, 4, 1522, 2, 0, 59, 61, 1, 0), + (506, 4, 2462, 8, 0, 59, 60, 6, 0), + (507, 4, 2893, 8, 0, 60, 62, 6, 0), + (508, 4, 1447, 8, 0, 60, 61, 1, 0), + (509, 4, 2510, 8, 0, 60, 61, 1, 0), + (510, 4, 2122, 8, 0, 60, 61, 1, 0), + (511, 4, 2180, 2, 0, 60, 64, 1, 0), + (512, 4, 1523, 2, 0, 60, 75, 2, 0), + (513, 4, 3465, 2, 0, 61, 65, 2, 0), + (514, 4, 3466, 2, 0, 61, 65, 2, 0), + (515, 4, 3475, 2, 0, 62, 64, 1, 0), + (516, 4, 3467, 8, 0, 62, 66, 1, 0), + (517, 4, 3472, 8, 0, 62, 66, 3, 0), + (518, 4, 4091, 8, 0, 62, 66, 4, 0), + (519, 4, 3047, 2, 0, 63, 69, 1, 0), + (520, 4, 3480, 2, 0, 63, 64, 2, 0), + (521, 4, 3471, 2, 0, 64, 68, 2, 0), + (522, 4, 4108, 8, 0, 64, 66, 3, 0), + (523, 4, 3479, 8, 0, 65, 66, 1, 0), + (524, 4, 4882, 2, 0, 65, 66, 1, 0), + (525, 4, 4880, 2, 0, 65, 67, 2, 0), + (526, 4, 5252, 2, 0, 66, 71, 2, 0), + (527, 4, 5251, 2, 0, 66, 255, 2, 0), + (528, 4, 5257, 8, 0, 67, 71, 1, 0), + (529, 4, 5259, 2, 0, 67, 255, 1, 0), + (530, 4, 5258, 8, 0, 67, 70, 3, 0), + (531, 4, 5261, 8, 0, 67, 72, 4, 0), + (532, 4, 5265, 2, 0, 68, 69, 2, 0), + (533, 4, 5272, 8, 0, 69, 255, 7, 0), + (534, 4, 5270, 2, 0, 69, 79, 2, 0), + (535, 4, 5278, 8, 0, 70, 71, 1, 0), + (536, 4, 5277, 8, 0, 70, 74, 1, 0), + (537, 4, 8493, 2, 0, 70, 74, 1, 0), + (538, 4, 6140, 2, 0, 70, 72, 2, 0), + (539, 4, 14196, 8, 0, 71, 75, 2, 0), + (540, 4, 14193, 2, 0, 71, 75, 2, 0), + (541, 4, 14190, 8, 0, 71, 0, 3, 0), + (542, 4, 14208, 8, 0, 72, 76, 1, 0), + (543, 4, 14214, 2, 0, 72, 76, 1, 0), + (544, 4, 14253, 8, 0, 72, 75, 3, 0), + (545, 4, 14223, 2, 0, 73, 77, 2, 0), + (546, 4, 14232, 2, 0, 73, 77, 2, 0), + (547, 4, 14220, 8, 0, 73, 77, 4, 0), + (548, 4, 14268, 32768, 0, 74, 78, 2, 0), + (549, 4, 14283, 8, 0, 75, 76, 1, 0), + (550, 4, 14280, 8, 0, 75, 79, 2, 0), + (551, 4, 14286, 2, 0, 75, 79, 1, 0), + (552, 4, 14289, 8, 0, 75, 77, 4, 0), + (553, 4, 0, 2, 0, 76, 80, 2, 0), + (554, 4, 0, 8, 0, 76, 80, 2, 0), + (555, 4, 0, 8, 0, 76, 80, 3, 0), + (556, 4, 0, 8, 0, 77, 81, 1, 0), + (557, 4, 0, 2, 0, 77, 81, 1, 0), + (558, 4, 0, 2, 0, 77, 81, 2, 0), + (559, 4, 0, 8, 0, 77, 80, 3, 0), + (560, 4, 0, 2, 0, 78, 82, 2, 0), + (561, 4, 0, 2, 0, 78, 82, 2, 0), + (562, 4, 0, 8, 0, 78, 82, 4, 0), + (563, 4, 0, 32768, 0, 79, 83, 2, 0), + (564, 4, 0, 8, 0, 80, 81, 1, 0), + (565, 4, 0, 8, 0, 80, 84, 2, 0), + (566, 4, 0, 2, 0, 80, 84, 1, 0), + (567, 4, 0, 2, 0, 80, 84, 2, 0), + (568, 4, 0, 8, 0, 80, 82, 4, 0), + (569, 4, 18235, 8, 0, 81, 85, 2, 0), + (570, 4, 18232, 2, 0, 81, 85, 2, 0), + (571, 4, 18229, 8, 0, 81, 85, 3, 0), + (572, 4, 18247, 8, 0, 82, 86, 1, 0), + (573, 4, 18253, 2, 0, 82, 86, 1, 0), + (574, 4, 18353, 2, 0, 82, 86, 2, 0), + (575, 4, 18292, 8, 0, 82, 85, 3, 0), + (576, 4, 18262, 2, 0, 83, 87, 2, 0), + (577, 4, 18271, 2, 0, 83, 87, 2, 0), + (578, 4, 18259, 8, 0, 83, 87, 4, 0), + (579, 4, 18307, 32768, 0, 84, 86, 2, 0), + (580, 4, 18390, 32768, 0, 84, 88, 2, 0), + (581, 4, 18322, 8, 0, 85, 86, 1, 0), + (582, 4, 18319, 8, 0, 85, 89, 2, 0), + (583, 4, 18365, 2, 0, 85, 89, 2, 0), + (584, 4, 18328, 8, 0, 85, 87, 4, 0), + (585, 7, 372, 1, 0, 1, 7, 1, 0), + (586, 7, 377, 1, 0, 6, 11, 2, 0), + (587, 7, 656, 1, 0, 8, 23, 1, 0), + (588, 7, 85, 1, 0, 12, 22, 2, 0), + (589, 7, 467, 1, 0, 23, 25, 2, 0), + (590, 7, 464, 1, 0, 24, 33, 1, 0), + (591, 7, 468, 1, 0, 26, 31, 2, 0), + (592, 7, 469, 1, 0, 32, 40, 2, 0), + (593, 7, 658, 1, 0, 34, 48, 1, 0), + (594, 7, 752, 1, 0, 37, 70, 1, 0), + (595, 7, 660, 1, 0, 41, 57, 2, 0), + (596, 7, 732, 1, 0, 49, 60, 1, 0), + (597, 7, 1649, 1, 0, 52, 54, 2, 0), + (598, 7, 1648, 1, 0, 55, 57, 2, 0), + (599, 7, 1647, 1, 0, 58, 64, 2, 0), + (600, 7, 6737, 1, 0, 61, 65, 1, 0), + (601, 7, 3327, 1, 0, 61, 64, 2, 0), + (602, 7, 3332, 1, 0, 65, 69, 2, 0), + (603, 7, 5444, 1, 0, 66, 69, 2, 0), + (604, 7, 5442, 1, 0, 66, 70, 1, 0), + (605, 7, 5461, 1, 0, 70, 74, 2, 0), + (606, 7, 15320, 1, 0, 71, 73, 1, 0), + (607, 7, 15326, 1, 0, 71, 74, 2, 0), + (608, 7, 15329, 1, 0, 71, 75, 1, 0), + (609, 7, 15381, 1, 0, 74, 78, 1, 0), + (610, 7, 15401, 1, 0, 75, 79, 2, 0), + (611, 7, 26523, 1, 0, 76, 80, 1, 0), + (612, 7, 0, 1, 0, 76, 79, 2, 0), + (613, 7, 0, 1, 0, 79, 83, 1, 0), + (614, 7, 15465, 1, 0, 80, 84, 2, 0), + (615, 7, 19570, 1, 0, 81, 84, 2, 0), + (616, 7, 19573, 1, 0, 81, 85, 1, 0), + (617, 7, 19629, 1, 0, 84, 88, 1, 0), + (618, 7, 19653, 1, 0, 85, 89, 2, 0), + (619, 8, 372, 1, 0, 1, 7, 1, 0), + (620, 8, 377, 1, 0, 6, 11, 2, 0), + (621, 8, 656, 1, 0, 8, 23, 1, 0), + (622, 8, 85, 1, 0, 12, 22, 2, 0), + (623, 8, 467, 1, 0, 23, 25, 2, 0), + (624, 8, 464, 1, 0, 24, 33, 1, 0), + (625, 8, 468, 1, 0, 26, 31, 2, 0), + (626, 8, 469, 1, 0, 32, 40, 2, 0), + (627, 8, 658, 1, 0, 34, 48, 1, 0), + (628, 8, 752, 1, 0, 37, 59, 1, 0), + (629, 8, 660, 1, 0, 41, 57, 2, 0), + (630, 8, 732, 1, 0, 49, 60, 1, 0), + (631, 8, 1649, 1, 0, 52, 54, 2, 0), + (632, 8, 1648, 1, 0, 55, 57, 2, 0), + (633, 8, 1647, 1, 0, 58, 64, 2, 0), + (634, 8, 2117, 1, 0, 60, 70, 1, 0), + (635, 8, 6737, 1, 0, 61, 65, 1, 0), + (636, 8, 3327, 1, 0, 61, 64, 2, 0), + (637, 8, 3332, 1, 0, 65, 69, 2, 0), + (638, 8, 5444, 1, 0, 66, 69, 2, 0), + (639, 8, 5442, 1, 0, 66, 70, 1, 0), + (640, 8, 5461, 1, 0, 70, 74, 2, 0), + (641, 8, 15321, 1, 0, 71, 73, 1, 0), + (642, 8, 15327, 1, 0, 71, 74, 2, 0), + (643, 8, 15330, 1, 0, 71, 75, 1, 0), + (644, 8, 15382, 1, 0, 74, 8, 1, 0), + (645, 8, 15402, 1, 0, 75, 79, 2, 0), + (646, 8, 26524, 1, 0, 76, 80, 1, 0), + (647, 8, 0, 1, 0, 76, 79, 2, 0), + (648, 8, 0, 1, 0, 79, 83, 1, 0), + (649, 8, 15466, 1, 0, 80, 84, 2, 0), + (650, 8, 19571, 1, 0, 81, 84, 2, 0), + (651, 8, 19574, 1, 0, 81, 85, 1, 0), + (652, 8, 19630, 1, 0, 84, 88, 1, 0), + (653, 8, 19654, 1, 0, 85, 89, 2, 0), + (654, 5, 23181, 16, 0, 1, 9, 1, 0), + (655, 5, 23182, 16, 0, 10, 19, 1, 0), + (656, 5, 23183, 16, 0, 20, 24, 1, 0), + (657, 5, 23184, 16, 0, 25, 29, 1, 0), + (658, 5, 23185, 16, 0, 30, 34, 1, 0), + (659, 5, 23186, 16, 0, 35, 39, 1, 0), + (660, 5, 23187, 16, 0, 40, 44, 1, 0), + (661, 5, 23188, 16, 0, 45, 49, 1, 0), + (662, 5, 23189, 16, 0, 50, 54, 1, 0), + (663, 5, 23190, 16, 0, 55, 59, 1, 0), + (664, 5, 23191, 16, 0, 60, 64, 1, 0), + (665, 5, 23192, 16, 0, 65, 69, 1, 0), + (666, 5, 23193, 16, 0, 70, 74, 1, 0), + (667, 5, 23194, 16, 0, 75, 79, 1, 0), + (668, 5, 23195, 16, 0, 80, 80, 1, 0), + (669, 5, 23196, 16, 0, 81, 81, 1, 0), + (670, 5, 23197, 16, 0, 82, 82, 1, 0), + (671, 5, 23198, 16, 0, 83, 83, 1, 0), + (672, 5, 23199, 16, 0, 84, 84, 1, 0), + (673, 5, 23200, 16, 0, 85, 95, 1, 0), + (674, 5, 37747, 16, 0, 96, 255, 1, 0), + (675, 5, 12954, 8, 0, 1, 255, 1, 0), + (676, 5, 4659, 1024, 0, 20, 51, 1, 0), + (677, 5, 4685, 1024, 0, 52, 62, 1, 0), + (678, 5, 4686, 1024, 0, 63, 64, 1, 0), + (679, 5, 5017, 1024, 0, 65, 68, 1, 0), + (680, 5, 8001, 1024, 0, 68, 255, 1, 0), + (681, 5, 6174, 1024, 0, 69, 69, 1, 0), + (682, 5, 8470, 1024, 0, 70, 79, 1, 0), + (683, 5, 0, 1024, 0, 80, 84, 1, 0), + (684, 5, 0, 1024, 0, 80, 84, 1, 0), + (685, 5, 0, 1024, 0, 80, 84, 1, 0), + (686, 5, 19280, 1024, 0, 85, 89, 1, 0), + (687, 5, 19281, 1024, 0, 85, 89, 1, 0), + (688, 5, 19282, 1024, 0, 85, 89, 1, 0), + (689, 5, 26148, 1024, 0, 90, 94, 1, 0), + (690, 5, 26149, 1024, 0, 90, 94, 1, 0), + (691, 5, 26150, 1024, 0, 90, 94, 1, 0), + (692, 6, 23181, 16, 0, 1, 9, 1, 0), + (693, 6, 23182, 16, 0, 10, 19, 1, 0), + (694, 6, 23183, 16, 0, 20, 24, 1, 0), + (695, 6, 23184, 16, 0, 25, 29, 1, 0), + (696, 6, 23185, 16, 0, 30, 34, 1, 0), + (697, 6, 23186, 16, 0, 35, 39, 1, 0), + (698, 6, 23187, 16, 0, 40, 44, 1, 0), + (699, 6, 23188, 16, 0, 45, 49, 1, 0), + (700, 6, 23189, 16, 0, 50, 54, 1, 0), + (701, 6, 23190, 16, 0, 55, 59, 1, 0), + (702, 6, 23191, 16, 0, 60, 64, 1, 0), + (703, 6, 23192, 16, 0, 65, 69, 1, 0), + (704, 6, 23193, 16, 0, 70, 74, 1, 0), + (705, 6, 23194, 16, 0, 75, 79, 1, 0), + (706, 6, 23195, 16, 0, 80, 80, 1, 0), + (707, 6, 23196, 16, 0, 81, 81, 1, 0), + (708, 6, 23197, 16, 0, 82, 82, 1, 0), + (709, 6, 23198, 16, 0, 83, 83, 1, 0), + (710, 6, 23199, 16, 0, 84, 84, 1, 0), + (711, 6, 23200, 16, 0, 85, 95, 1, 0), + (712, 6, 37747, 16, 0, 96, 255, 1, 0), + (713, 6, 12954, 8, 0, 1, 255, 1, 0), + (714, 6, 4659, 1024, 0, 20, 51, 1, 0), + (715, 6, 4685, 1024, 0, 52, 62, 1, 0), + (716, 6, 4686, 1024, 0, 63, 64, 1, 0), + (717, 6, 5018, 1024, 0, 65, 68, 1, 0), + (718, 6, 8001, 1024, 0, 68, 255, 1, 0), + (719, 6, 6174, 1024, 0, 69, 69, 1, 0), + (720, 6, 8470, 1024, 0, 70, 79, 1, 0), + (721, 6, 0, 1024, 0, 80, 84, 1, 0), + (722, 6, 0, 1024, 0, 80, 84, 1, 0), + (723, 6, 0, 1024, 0, 80, 84, 1, 0), + (724, 6, 19280, 1024, 0, 85, 89, 1, 0), + (725, 6, 19281, 1024, 0, 85, 89, 1, 0), + (726, 6, 19282, 1024, 0, 85, 89, 1, 0), + (727, 6, 26148, 1024, 0, 90, 94, 1, 0), + (728, 6, 26149, 1024, 0, 90, 94, 1, 0), + (729, 6, 26150, 1024, 0, 90, 94, 1, 0); + +-- ---------------------------- +-- Table structure for merc_spell_lists +-- ---------------------------- +DROP TABLE IF EXISTS `merc_spell_lists`; +CREATE TABLE `merc_spell_lists` +( + `merc_spell_list_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `class_id` int(10) UNSIGNED NOT NULL, + `proficiency_id` tinyint(3) UNSIGNED NOT NULL, + `name` varchar(50) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, + PRIMARY KEY (`merc_spell_list_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_spell_lists +-- ---------------------------- +INSERT INTO `merc_spell_lists` +VALUES (1, 1, 1, 'Apprentice Tank Disciplines'), + (2, 1, 2, 'Journeyman Tank Disciplines'), + (3, 2, 1, 'Apprentice Healer Spells'), + (4, 2, 2, 'Journeyman Healer Spells'), + (5, 9, 1, 'Apprentice Melee DPS Disciplines'), + (6, 9, 2, 'Journeyman Melee DPS Disciplines'), + (7, 12, 1, 'Apprentice Caster DPS Spells'), + (8, 12, 2, 'Journeyman Caster DPS Spells'); + +-- ---------------------------- +-- Table structure for merc_stance_entries +-- ---------------------------- +DROP TABLE IF EXISTS `merc_stance_entries`; +CREATE TABLE `merc_stance_entries` +( + `merc_stance_entry_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `class_id` int(10) UNSIGNED NOT NULL, + `proficiency_id` tinyint(3) UNSIGNED NOT NULL, + `stance_id` tinyint(3) UNSIGNED NOT NULL, + `isdefault` tinyint(1) NOT NULL, + PRIMARY KEY (`merc_stance_entry_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_stance_entries +-- ---------------------------- +INSERT INTO `merc_stance_entries` +VALUES (1, 1, 1, 1, 0), + (2, 1, 1, 5, 0), + (3, 1, 2, 1, 0), + (4, 1, 2, 5, 0), + (5, 1, 2, 6, 0), + (6, 2, 1, 1, 0), + (7, 2, 1, 2, 0), + (8, 2, 2, 1, 0), + (9, 2, 2, 2, 0), + (10, 2, 2, 3, 0), + (11, 2, 2, 4, 0), + (12, 9, 1, 1, 0), + (13, 9, 1, 2, 0), + (14, 9, 2, 1, 0), + (15, 9, 2, 2, 0), + (16, 9, 2, 7, 0), + (17, 12, 1, 1, 0), + (18, 12, 1, 2, 0), + (19, 12, 2, 1, 0), + (20, 12, 2, 2, 0), + (21, 12, 2, 7, 0), + (22, 12, 2, 9, 0); + +-- ---------------------------- +-- Table structure for merc_stats +-- ---------------------------- +DROP TABLE IF EXISTS `merc_stats`; +CREATE TABLE `merc_stats` +( + `merc_npc_type_id` int(11) UNSIGNED NOT NULL, + `clientlevel` tinyint(2) UNSIGNED NOT NULL DEFAULT 1, + `level` tinyint(2) UNSIGNED NOT NULL DEFAULT 1, + `hp` int(11) NOT NULL DEFAULT 1, + `mana` int(11) NOT NULL DEFAULT 0, + `AC` smallint(5) NOT NULL DEFAULT 1, + `ATK` mediumint(9) NOT NULL DEFAULT 1, + `STR` mediumint(8) UNSIGNED NOT NULL DEFAULT 75, + `STA` mediumint(8) UNSIGNED NOT NULL DEFAULT 75, + `DEX` mediumint(8) UNSIGNED NOT NULL DEFAULT 75, + `AGI` mediumint(8) UNSIGNED NOT NULL DEFAULT 75, + `_INT` mediumint(8) UNSIGNED NOT NULL DEFAULT 80, + `WIS` mediumint(8) UNSIGNED NOT NULL DEFAULT 80, + `CHA` mediumint(8) UNSIGNED NOT NULL DEFAULT 75, + `MR` smallint(5) NOT NULL DEFAULT 15, + `CR` smallint(5) NOT NULL DEFAULT 15, + `DR` smallint(5) NOT NULL DEFAULT 15, + `FR` smallint(5) NOT NULL DEFAULT 15, + `PR` smallint(5) NOT NULL DEFAULT 15, + `Corrup` smallint(5) NOT NULL DEFAULT 15, + `mindmg` int(10) UNSIGNED NOT NULL DEFAULT 1, + `maxdmg` int(10) UNSIGNED NOT NULL DEFAULT 1, + `attack_count` smallint(6) NOT NULL DEFAULT 0, + `attack_speed` tinyint(3) NOT NULL DEFAULT 0, + `attack_delay` tinyint(3) UNSIGNED NOT NULL DEFAULT 30, + `special_abilities` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL, + `Accuracy` mediumint(9) NOT NULL DEFAULT 0, + `hp_regen_rate` int(11) UNSIGNED NOT NULL DEFAULT 1, + `mana_regen_rate` int(11) UNSIGNED NOT NULL DEFAULT 1, + `runspeed` float NOT NULL DEFAULT 0, + `statscale` int(11) NOT NULL DEFAULT 100, + `spellscale` float NOT NULL DEFAULT 100, + `healscale` float NOT NULL DEFAULT 100, + PRIMARY KEY (`merc_npc_type_id`, `clientlevel`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_stats +-- ---------------------------- +INSERT INTO `merc_stats` +VALUES (1, 1, 1, 50, 0, 35, 28, 66, 66, 66, 66, 75, 75, 66, 15, 15, 15, 15, 15, 15, 3, 10, 1, -18, 30, '', 0, 13, 0, + 1.25, 100, 100, 100), + (1, 2, 2, 90, 0, 69, 56, 67, 67, 67, 67, 78, 78, 67, 17, 17, 17, 17, 17, 17, 3, 11, 1, -18, 30, '', 0, 13, 0, + 1.25, 100, 100, 100), + (1, 3, 3, 130, 0, 104, 84, 67, 67, 67, 67, 81, 81, 67, 19, 19, 19, 19, 19, 19, 3, 12, 1, -18, 30, '', 0, 14, 0, + 1.25, 100, 100, 100), + (1, 4, 4, 170, 0, 138, 112, 68, 68, 68, 68, 84, 84, 68, 22, 22, 22, 22, 22, 22, 4, 14, 1, -18, 30, '', 0, 14, 0, + 1.25, 100, 100, 100), + (1, 5, 5, 211, 0, 173, 140, 69, 69, 69, 69, 87, 87, 69, 24, 24, 24, 24, 24, 24, 4, 15, 1, -18, 30, '', 0, 14, 0, + 1.25, 100, 100, 100), + (1, 6, 6, 253, 0, 207, 168, 70, 70, 70, 70, 90, 90, 70, 26, 26, 26, 26, 26, 26, 4, 17, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (1, 7, 7, 294, 0, 242, 196, 71, 71, 71, 71, 93, 93, 71, 28, 28, 28, 28, 28, 28, 4, 18, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (1, 8, 8, 337, 0, 276, 224, 73, 73, 73, 73, 96, 96, 73, 31, 31, 31, 31, 31, 31, 5, 19, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (1, 9, 9, 380, 0, 311, 252, 74, 74, 74, 74, 99, 99, 74, 33, 33, 33, 33, 33, 33, 5, 21, 1, -18, 30, '', 0, 16, 0, + 1.25, 100, 100, 100), + (1, 10, 10, 424, 0, 345, 280, 77, 77, 77, 77, 102, 102, 77, 35, 35, 35, 35, 35, 35, 5, 22, 1, -18, 30, '', 0, 16, + 0, 1.25, 100, 100, 100), + (1, 11, 11, 469, 0, 380, 308, 78, 78, 78, 78, 105, 105, 78, 37, 37, 37, 37, 37, 37, 5, 24, 1, -18, 30, '', 0, 16, + 0, 1.25, 100, 100, 100), + (1, 12, 12, 514, 0, 414, 336, 80, 80, 80, 80, 108, 108, 80, 40, 40, 40, 40, 40, 40, 6, 25, 1, -18, 30, '', 0, 17, + 0, 1.25, 100, 100, 100), + (1, 13, 13, 561, 0, 449, 364, 81, 81, 81, 81, 111, 111, 81, 42, 42, 42, 42, 42, 42, 6, 26, 1, -18, 30, '', 0, 17, + 0, 1.25, 100, 100, 100), + (1, 14, 14, 609, 0, 483, 392, 83, 83, 83, 83, 114, 114, 83, 44, 44, 44, 44, 44, 44, 6, 28, 1, -18, 30, '', 0, 17, + 0, 1.25, 100, 100, 100), + (1, 15, 15, 658, 0, 518, 420, 85, 85, 85, 85, 117, 117, 85, 46, 46, 46, 46, 46, 46, 6, 29, 1, -18, 30, '', 0, 18, + 0, 1.25, 100, 100, 100), + (1, 16, 16, 708, 0, 552, 448, 87, 87, 87, 87, 120, 120, 87, 49, 49, 49, 49, 49, 49, 7, 31, 1, -18, 30, '', 0, 18, + 0, 1.25, 100, 100, 100), + (1, 17, 17, 760, 0, 587, 476, 89, 89, 89, 89, 123, 123, 89, 51, 51, 51, 51, 51, 51, 7, 32, 2, -18, 30, '', 0, 18, + 0, 1.25, 100, 100, 100), + (1, 18, 18, 813, 0, 621, 504, 92, 92, 92, 92, 126, 126, 92, 53, 53, 53, 53, 53, 53, 7, 33, 2, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (1, 19, 19, 867, 0, 656, 532, 94, 94, 94, 94, 129, 129, 94, 55, 55, 55, 55, 55, 55, 7, 35, 2, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (1, 20, 20, 924, 0, 690, 560, 98, 98, 98, 98, 132, 132, 98, 58, 58, 58, 58, 58, 58, 8, 36, 2, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (1, 21, 21, 982, 0, 725, 588, 100, 100, 100, 100, 135, 135, 100, 60, 60, 60, 60, 60, 60, 8, 38, 2, -18, 30, '', + 0, 20, 0, 1.25, 100, 100, 100), + (1, 22, 22, 1042, 0, 759, 616, 103, 103, 103, 103, 138, 138, 103, 62, 62, 62, 62, 62, 62, 8, 39, 2, -18, 30, '', + 0, 20, 0, 1.25, 100, 100, 100), + (1, 23, 23, 1103, 0, 794, 644, 105, 105, 105, 105, 141, 141, 105, 64, 64, 64, 64, 64, 64, 8, 40, 2, -18, 30, '', + 0, 20, 0, 1.25, 100, 100, 100), + (1, 24, 24, 1167, 0, 828, 672, 108, 108, 108, 108, 144, 144, 108, 67, 67, 67, 67, 67, 67, 9, 42, 2, -18, 30, '', + 0, 21, 0, 1.25, 100, 100, 100), + (1, 25, 25, 1233, 0, 863, 700, 111, 111, 111, 111, 147, 147, 111, 69, 69, 69, 69, 69, 69, 9, 43, 2, -18, 30, '', + 0, 21, 0, 1.25, 100, 100, 100), + (1, 26, 26, 1301, 0, 897, 728, 114, 114, 114, 114, 150, 150, 114, 71, 71, 71, 71, 71, 71, 9, 45, 2, -18, 30, '', + 0, 21, 0, 1.25, 100, 100, 100), + (1, 27, 27, 1371, 0, 932, 756, 117, 117, 117, 117, 153, 153, 117, 73, 73, 73, 73, 73, 73, 9, 46, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (1, 28, 28, 1443, 0, 966, 784, 121, 121, 121, 121, 156, 156, 121, 76, 76, 76, 76, 76, 76, 10, 47, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (1, 29, 29, 1518, 0, 1001, 812, 124, 124, 124, 124, 159, 159, 124, 78, 78, 78, 78, 78, 78, 10, 49, 2, -18, 30, + '', 0, 22, 0, 1.25, 100, 100, 100), + (1, 30, 30, 1595, 0, 1035, 840, 129, 129, 129, 129, 162, 162, 129, 80, 80, 80, 80, 80, 80, 10, 50, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (1, 31, 31, 1675, 0, 1070, 868, 132, 132, 132, 132, 165, 165, 132, 82, 82, 82, 82, 82, 82, 10, 52, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (1, 32, 32, 1758, 0, 1104, 896, 136, 136, 136, 136, 168, 168, 136, 85, 85, 85, 85, 85, 85, 11, 53, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (1, 33, 33, 1843, 0, 1139, 924, 139, 139, 139, 139, 171, 171, 139, 87, 87, 87, 87, 87, 87, 11, 54, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (1, 34, 34, 1931, 0, 1173, 952, 143, 143, 143, 143, 174, 174, 143, 89, 89, 89, 89, 89, 89, 11, 56, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (1, 35, 35, 2022, 0, 1208, 980, 147, 147, 147, 147, 177, 177, 147, 91, 91, 91, 91, 91, 91, 11, 57, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (1, 36, 36, 2116, 0, 1242, 1008, 151, 151, 151, 151, 180, 180, 151, 94, 94, 94, 94, 94, 94, 12, 59, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (1, 37, 37, 2213, 0, 1277, 1036, 155, 155, 155, 155, 183, 183, 155, 96, 96, 96, 96, 96, 96, 12, 60, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (1, 38, 38, 2313, 0, 1311, 1064, 160, 160, 160, 160, 186, 186, 160, 98, 98, 98, 98, 98, 98, 12, 61, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (1, 39, 39, 2417, 0, 1346, 1092, 164, 164, 164, 164, 189, 189, 164, 100, 100, 100, 100, 100, 100, 12, 63, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (1, 40, 40, 2524, 0, 1380, 1120, 170, 170, 170, 170, 192, 192, 170, 103, 103, 103, 103, 103, 103, 13, 64, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (1, 41, 41, 2634, 0, 1415, 1148, 174, 174, 174, 174, 195, 195, 174, 105, 105, 105, 105, 105, 105, 13, 66, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (1, 42, 42, 2748, 0, 1449, 1176, 179, 179, 179, 179, 198, 198, 179, 107, 107, 107, 107, 107, 107, 13, 67, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (1, 43, 43, 2865, 0, 1484, 1204, 183, 183, 183, 183, 201, 201, 183, 109, 109, 109, 109, 109, 109, 13, 68, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (1, 44, 44, 2986, 0, 1518, 1232, 188, 188, 188, 188, 204, 204, 188, 112, 112, 112, 112, 112, 112, 14, 70, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (1, 45, 45, 3111, 0, 1553, 1260, 193, 193, 193, 193, 207, 207, 193, 114, 114, 114, 114, 114, 114, 14, 71, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (1, 46, 46, 3240, 0, 1587, 1288, 198, 198, 198, 198, 210, 210, 198, 116, 116, 116, 116, 116, 116, 14, 73, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (1, 47, 47, 3373, 0, 1622, 1316, 203, 203, 203, 203, 213, 213, 203, 118, 118, 118, 118, 118, 118, 14, 74, 3, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (1, 48, 48, 3509, 0, 1656, 1344, 209, 209, 209, 209, 216, 216, 209, 121, 121, 121, 121, 121, 121, 15, 75, 3, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (1, 49, 49, 3650, 0, 1691, 1372, 214, 214, 214, 214, 219, 219, 214, 123, 123, 123, 123, 123, 123, 15, 77, 3, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (1, 50, 50, 3795, 0, 1725, 1400, 221, 221, 221, 221, 222, 222, 221, 125, 125, 125, 125, 125, 125, 15, 78, 3, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (1, 51, 51, 3945, 0, 1760, 1428, 226, 226, 226, 226, 225, 225, 226, 127, 127, 127, 127, 127, 127, 15, 80, 3, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (1, 52, 52, 4098, 0, 1794, 1456, 232, 232, 232, 232, 228, 228, 232, 130, 130, 130, 130, 130, 130, 16, 81, 3, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (1, 53, 53, 4256, 0, 1829, 1484, 237, 237, 237, 237, 231, 231, 237, 132, 132, 132, 132, 132, 132, 16, 82, 3, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (1, 54, 54, 4419, 0, 1863, 1512, 243, 243, 243, 243, 234, 234, 243, 134, 134, 134, 134, 134, 134, 16, 84, 3, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (1, 55, 55, 4586, 0, 1898, 1540, 249, 249, 249, 249, 237, 237, 249, 136, 136, 136, 136, 136, 136, 16, 85, 3, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (1, 56, 56, 4758, 0, 1932, 1568, 255, 255, 255, 255, 240, 240, 255, 139, 139, 139, 139, 139, 139, 17, 87, 3, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (1, 57, 57, 4935, 0, 1967, 1596, 261, 261, 261, 261, 243, 243, 261, 141, 141, 141, 141, 141, 141, 17, 88, 3, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (1, 58, 58, 5117, 0, 2001, 1624, 268, 268, 268, 268, 246, 246, 268, 143, 143, 143, 143, 143, 143, 17, 89, 3, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (1, 59, 59, 5303, 0, 2036, 1652, 274, 274, 274, 274, 249, 249, 274, 145, 145, 145, 145, 145, 145, 17, 91, 3, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (1, 60, 60, 5495, 0, 2070, 1680, 282, 282, 282, 282, 252, 252, 282, 148, 148, 148, 148, 148, 148, 18, 92, 3, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (1, 61, 61, 5692, 0, 2105, 1708, 288, 288, 288, 288, 255, 255, 288, 150, 150, 150, 150, 150, 150, 21, 109, 4, + -20, 29, '', 0, 33, 0, 1.25, 100, 100, 100), + (1, 62, 62, 5894, 0, 2139, 1736, 295, 295, 295, 295, 258, 258, 295, 152, 152, 152, 152, 152, 152, 24, 125, 4, + -21, 28, '', 0, 33, 0, 1.25, 100, 100, 100), + (1, 63, 63, 6102, 0, 2174, 1764, 301, 301, 301, 301, 261, 261, 301, 154, 154, 154, 154, 154, 154, 27, 141, 4, + -21, 28, '', 0, 34, 0, 1.25, 100, 100, 100), + (1, 64, 64, 6314, 0, 2208, 1792, 308, 308, 308, 308, 264, 264, 308, 157, 157, 157, 157, 157, 157, 31, 158, 4, + -22, 28, '', 0, 34, 0, 1.25, 100, 100, 100), + (1, 65, 65, 6533, 0, 2243, 1820, 315, 315, 315, 315, 267, 267, 315, 159, 159, 159, 159, 159, 159, 34, 174, 4, + -22, 28, '', 0, 34, 0, 1.25, 100, 100, 100), + (1, 66, 66, 6757, 0, 2277, 1848, 352, 352, 352, 352, 300, 300, 352, 161, 161, 161, 161, 161, 161, 37, 191, 4, + -23, 28, '', 0, 35, 0, 1.25, 100, 100, 100), + (1, 67, 67, 6986, 0, 2312, 1876, 364, 364, 364, 364, 308, 308, 364, 163, 163, 163, 163, 163, 163, 40, 207, 4, + -23, 28, '', 0, 35, 0, 1.25, 100, 100, 100), + (1, 68, 68, 7221, 0, 2346, 1904, 377, 377, 377, 377, 316, 316, 377, 166, 166, 166, 166, 166, 166, 44, 223, 4, + -24, 27, '', 0, 35, 0, 1.25, 100, 100, 100), + (1, 69, 69, 7462, 0, 2381, 1932, 389, 389, 389, 389, 324, 324, 389, 168, 168, 168, 168, 168, 168, 47, 240, 4, + -24, 27, '', 0, 36, 0, 1.25, 100, 100, 100), + (1, 70, 70, 7710, 0, 2415, 1960, 403, 403, 403, 403, 332, 332, 403, 170, 170, 170, 170, 170, 170, 50, 256, 4, + -25, 27, '', 0, 36, 0, 1.25, 100, 100, 100), + (1, 71, 71, 7963, 0, 2450, 1988, 415, 415, 415, 415, 340, 340, 415, 172, 172, 172, 172, 172, 172, 53, 273, 4, + -25, 27, '', 0, 36, 0, 1.25, 100, 100, 100), + (1, 72, 72, 8222, 0, 2484, 2016, 428, 428, 428, 428, 348, 348, 428, 175, 175, 175, 175, 175, 175, 57, 289, 4, + -26, 27, '', 0, 37, 0, 1.25, 100, 100, 100), + (1, 73, 73, 8487, 0, 2519, 2044, 440, 440, 440, 440, 356, 356, 440, 177, 177, 177, 177, 177, 177, 60, 305, 4, + -26, 27, '', 0, 37, 0, 1.25, 100, 100, 100), + (1, 74, 74, 8758, 0, 2553, 2072, 453, 453, 453, 453, 364, 364, 453, 179, 179, 179, 179, 179, 179, 63, 322, 4, + -27, 26, '', 0, 37, 0, 1.25, 100, 100, 100), + (1, 75, 75, 9036, 0, 2588, 2100, 466, 466, 466, 466, 372, 372, 466, 181, 181, 181, 181, 181, 181, 66, 338, 4, + -27, 26, '', 0, 38, 0, 1.25, 100, 100, 100), + (1, 76, 76, 9321, 0, 2622, 2128, 479, 479, 479, 479, 380, 380, 479, 184, 184, 184, 184, 184, 184, 70, 355, 4, + -28, 26, '', 0, 38, 0, 1.25, 100, 100, 100), + (1, 77, 77, 9611, 0, 2657, 2156, 492, 492, 492, 492, 388, 388, 492, 186, 186, 186, 186, 186, 186, 73, 371, 4, + -28, 26, '', 0, 38, 0, 1.25, 100, 100, 100), + (1, 78, 78, 9909, 0, 2691, 2184, 506, 506, 506, 506, 396, 396, 506, 188, 188, 188, 188, 188, 188, 76, 387, 4, + -29, 26, '', 0, 39, 0, 1.25, 100, 100, 100), + (1, 79, 79, 10213, 0, 2726, 2212, 519, 519, 519, 519, 404, 404, 519, 190, 190, 190, 190, 190, 190, 79, 404, 4, + -29, 26, '', 0, 39, 0, 1.25, 100, 100, 100), + (1, 80, 80, 10524, 0, 2760, 2240, 534, 534, 534, 534, 412, 412, 534, 193, 193, 193, 193, 193, 193, 83, 420, 4, + -30, 25, '', 0, 39, 0, 1.25, 100, 100, 100), + (1, 81, 81, 10842, 0, 2795, 2268, 547, 547, 547, 547, 420, 420, 547, 195, 195, 195, 195, 195, 195, 86, 437, 4, + -30, 25, '', 0, 40, 0, 1.25, 100, 100, 100), + (1, 82, 82, 11166, 0, 2829, 2296, 561, 561, 561, 561, 428, 428, 561, 197, 197, 197, 197, 197, 197, 89, 453, 4, + -31, 25, '', 0, 40, 0, 1.25, 100, 100, 100), + (1, 83, 83, 11498, 0, 2864, 2324, 574, 574, 574, 574, 436, 436, 574, 199, 199, 199, 199, 199, 199, 92, 469, 4, + -31, 25, '', 0, 40, 0, 1.25, 100, 100, 100), + (1, 84, 84, 11837, 0, 2898, 2352, 588, 588, 588, 588, 444, 444, 588, 202, 202, 202, 202, 202, 202, 96, 486, 4, + -32, 24, '', 0, 41, 0, 1.25, 100, 100, 100), + (1, 85, 85, 12183, 0, 2933, 2380, 602, 602, 602, 602, 452, 452, 602, 204, 204, 204, 204, 204, 204, 99, 502, 4, + -34, 24, '', 0, 41, 0, 1.25, 100, 100, 100), + (2, 1, 1, 55, 0, 36, 29, 67, 67, 67, 67, 77, 77, 67, 18, 18, 18, 18, 18, 18, 3, 12, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (2, 2, 2, 100, 0, 72, 57, 68, 68, 68, 68, 80, 80, 68, 20, 20, 20, 20, 20, 20, 4, 14, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (2, 3, 3, 145, 0, 108, 86, 68, 68, 68, 68, 83, 83, 68, 22, 22, 22, 22, 22, 22, 4, 15, 1, -18, 30, '', 0, 16, 0, + 1.25, 100, 100, 100), + (2, 4, 4, 190, 0, 144, 114, 69, 69, 69, 69, 86, 86, 69, 26, 26, 26, 26, 26, 26, 4, 17, 1, -18, 30, '', 0, 16, 0, + 1.25, 100, 100, 100), + (2, 5, 5, 236, 0, 180, 143, 70, 70, 70, 70, 89, 89, 70, 28, 28, 28, 28, 28, 28, 4, 18, 1, -18, 30, '', 0, 16, 0, + 1.25, 100, 100, 100), + (2, 6, 6, 283, 0, 216, 171, 71, 71, 71, 71, 92, 92, 71, 30, 30, 30, 30, 30, 30, 5, 19, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (2, 7, 7, 329, 0, 252, 200, 72, 72, 72, 72, 95, 95, 72, 32, 32, 32, 32, 32, 32, 5, 21, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (2, 8, 8, 377, 0, 288, 228, 74, 74, 74, 74, 98, 98, 74, 36, 36, 36, 36, 36, 36, 5, 22, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (2, 9, 9, 425, 0, 324, 257, 75, 75, 75, 75, 101, 101, 75, 38, 38, 38, 38, 38, 38, 5, 24, 1, -18, 30, '', 0, 18, + 0, 1.25, 100, 100, 100), + (2, 10, 10, 474, 0, 360, 285, 79, 79, 79, 79, 104, 104, 79, 40, 40, 40, 40, 40, 40, 6, 25, 1, -18, 30, '', 0, 18, + 0, 1.25, 100, 100, 100), + (2, 11, 11, 524, 0, 396, 314, 80, 80, 80, 80, 107, 107, 80, 42, 42, 42, 42, 42, 42, 6, 26, 1, -18, 30, '', 0, 18, + 0, 1.25, 100, 100, 100), + (2, 12, 12, 574, 0, 432, 342, 82, 82, 82, 82, 110, 110, 82, 46, 46, 46, 46, 46, 46, 6, 28, 1, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (2, 13, 13, 626, 0, 468, 371, 83, 83, 83, 83, 113, 113, 83, 48, 48, 48, 48, 48, 48, 6, 29, 1, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (2, 14, 14, 679, 0, 504, 399, 85, 85, 85, 85, 116, 116, 85, 50, 50, 50, 50, 50, 50, 7, 31, 1, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (2, 15, 15, 733, 0, 540, 428, 87, 87, 87, 87, 119, 119, 87, 52, 52, 52, 52, 52, 52, 7, 32, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (2, 16, 16, 788, 0, 576, 456, 89, 89, 89, 89, 122, 122, 89, 56, 56, 56, 56, 56, 56, 7, 33, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (2, 17, 17, 845, 0, 612, 485, 91, 91, 91, 91, 125, 125, 91, 58, 58, 58, 58, 58, 58, 7, 35, 2, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (2, 18, 18, 903, 0, 648, 513, 94, 94, 94, 94, 128, 128, 94, 60, 60, 60, 60, 60, 60, 8, 36, 2, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (2, 19, 19, 962, 0, 684, 542, 96, 96, 96, 96, 131, 131, 96, 62, 62, 62, 62, 62, 62, 8, 38, 2, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (2, 20, 20, 1024, 0, 720, 570, 101, 101, 101, 101, 134, 134, 101, 66, 66, 66, 66, 66, 66, 8, 39, 2, -18, 30, '', + 0, 21, 0, 1.25, 100, 100, 100), + (2, 21, 21, 1087, 0, 756, 599, 103, 103, 103, 103, 137, 137, 103, 68, 68, 68, 68, 68, 68, 8, 40, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (2, 22, 22, 1152, 0, 792, 627, 106, 106, 106, 106, 140, 140, 106, 70, 70, 70, 70, 70, 70, 9, 42, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (2, 23, 23, 1218, 0, 828, 656, 108, 108, 108, 108, 143, 143, 108, 72, 72, 72, 72, 72, 72, 9, 43, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (2, 24, 24, 1287, 0, 864, 684, 111, 111, 111, 111, 146, 146, 111, 76, 76, 76, 76, 76, 76, 9, 45, 2, -18, 30, '', + 0, 23, 0, 1.25, 100, 100, 100), + (2, 25, 25, 1358, 0, 900, 713, 114, 114, 114, 114, 149, 149, 114, 78, 78, 78, 78, 78, 78, 9, 46, 2, -18, 30, '', + 0, 23, 0, 1.25, 100, 100, 100), + (2, 26, 26, 1431, 0, 936, 741, 117, 117, 117, 117, 152, 152, 117, 80, 80, 80, 80, 80, 80, 10, 47, 2, -18, 30, '', + 0, 23, 0, 1.25, 100, 100, 100), + (2, 27, 27, 1506, 0, 972, 770, 120, 120, 120, 120, 155, 155, 120, 82, 82, 82, 82, 82, 82, 10, 49, 2, -18, 30, '', + 0, 24, 0, 1.25, 100, 100, 100), + (2, 28, 28, 1583, 0, 1008, 798, 124, 124, 124, 124, 158, 158, 124, 86, 86, 86, 86, 86, 86, 10, 50, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (2, 29, 29, 1663, 0, 1044, 827, 127, 127, 127, 127, 161, 161, 127, 88, 88, 88, 88, 88, 88, 10, 52, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (2, 30, 30, 1745, 0, 1080, 855, 133, 133, 133, 133, 164, 164, 133, 90, 90, 90, 90, 90, 90, 11, 53, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (2, 31, 31, 1830, 0, 1116, 884, 136, 136, 136, 136, 167, 167, 136, 92, 92, 92, 92, 92, 92, 11, 54, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (2, 32, 32, 1918, 0, 1152, 912, 140, 140, 140, 140, 170, 170, 140, 96, 96, 96, 96, 96, 96, 11, 56, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (2, 33, 33, 2008, 0, 1188, 941, 143, 143, 143, 143, 173, 173, 143, 98, 98, 98, 98, 98, 98, 11, 57, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (2, 34, 34, 2101, 0, 1224, 969, 147, 147, 147, 147, 176, 176, 147, 100, 100, 100, 100, 100, 100, 12, 59, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (2, 35, 35, 2197, 0, 1260, 998, 151, 151, 151, 151, 179, 179, 151, 102, 102, 102, 102, 102, 102, 12, 60, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (2, 36, 36, 2296, 0, 1296, 1026, 155, 155, 155, 155, 182, 182, 155, 106, 106, 106, 106, 106, 106, 12, 61, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (2, 37, 37, 2398, 0, 1332, 1055, 159, 159, 159, 159, 185, 185, 159, 108, 108, 108, 108, 108, 108, 12, 63, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (2, 38, 38, 2503, 0, 1368, 1083, 164, 164, 164, 164, 188, 188, 164, 110, 110, 110, 110, 110, 110, 13, 64, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (2, 39, 39, 2612, 0, 1404, 1112, 168, 168, 168, 168, 191, 191, 168, 112, 112, 112, 112, 112, 112, 13, 66, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (2, 40, 40, 2724, 0, 1440, 1140, 175, 175, 175, 175, 194, 194, 175, 116, 116, 116, 116, 116, 116, 13, 67, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (2, 41, 41, 2839, 0, 1476, 1169, 179, 179, 179, 179, 197, 197, 179, 118, 118, 118, 118, 118, 118, 13, 68, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (2, 42, 42, 2958, 0, 1512, 1197, 184, 184, 184, 184, 200, 200, 184, 120, 120, 120, 120, 120, 120, 14, 70, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (2, 43, 43, 3080, 0, 1548, 1226, 188, 188, 188, 188, 203, 203, 188, 122, 122, 122, 122, 122, 122, 14, 71, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (2, 44, 44, 3206, 0, 1584, 1254, 193, 193, 193, 193, 206, 206, 193, 126, 126, 126, 126, 126, 126, 14, 73, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (2, 45, 45, 3336, 0, 1620, 1283, 198, 198, 198, 198, 209, 209, 198, 128, 128, 128, 128, 128, 128, 14, 74, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (2, 46, 46, 3470, 0, 1656, 1311, 203, 203, 203, 203, 212, 212, 203, 130, 130, 130, 130, 130, 130, 15, 75, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (2, 47, 47, 3608, 0, 1692, 1340, 208, 208, 208, 208, 215, 215, 208, 132, 132, 132, 132, 132, 132, 15, 77, 3, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (2, 48, 48, 3749, 0, 1728, 1368, 214, 214, 214, 214, 218, 218, 214, 136, 136, 136, 136, 136, 136, 15, 78, 3, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (2, 49, 49, 3895, 0, 1764, 1397, 219, 219, 219, 219, 221, 221, 219, 138, 138, 138, 138, 138, 138, 15, 80, 3, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (2, 50, 50, 4045, 0, 1800, 1425, 227, 227, 227, 227, 224, 224, 227, 140, 140, 140, 140, 140, 140, 16, 81, 3, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (2, 51, 51, 4200, 0, 1836, 1454, 232, 232, 232, 232, 227, 227, 232, 142, 142, 142, 142, 142, 142, 16, 82, 3, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (2, 52, 52, 4358, 0, 1872, 1482, 238, 238, 238, 238, 230, 230, 238, 146, 146, 146, 146, 146, 146, 16, 84, 3, -18, + 30, '', 0, 32, 0, 1.31, 100, 100, 100), + (2, 53, 53, 4521, 0, 1908, 1511, 243, 243, 243, 243, 233, 233, 243, 148, 148, 148, 148, 148, 148, 16, 85, 3, -18, + 30, '', 0, 32, 0, 1.31, 100, 100, 100), + (2, 54, 54, 4689, 0, 1944, 1539, 249, 249, 249, 249, 236, 236, 249, 150, 150, 150, 150, 150, 150, 17, 87, 3, -18, + 30, '', 0, 33, 0, 1.31, 100, 100, 100), + (2, 55, 55, 4861, 0, 1980, 1568, 255, 255, 255, 255, 239, 239, 255, 152, 152, 152, 152, 152, 152, 17, 88, 3, -18, + 30, '', 0, 33, 0, 1.31, 100, 100, 100), + (2, 56, 56, 5038, 0, 2016, 1596, 261, 261, 261, 261, 242, 242, 261, 156, 156, 156, 156, 156, 156, 17, 89, 3, -18, + 30, '', 0, 33, 0, 1.31, 100, 100, 100), + (2, 57, 57, 5220, 0, 2052, 1625, 267, 267, 267, 267, 245, 245, 267, 158, 158, 158, 158, 158, 158, 17, 91, 3, -18, + 30, '', 0, 34, 0, 1.31, 100, 100, 100), + (2, 58, 58, 5407, 0, 2088, 1653, 274, 274, 274, 274, 248, 248, 274, 160, 160, 160, 160, 160, 160, 18, 92, 3, -18, + 30, '', 0, 34, 0, 1.31, 100, 100, 100), + (2, 59, 59, 5598, 0, 2124, 1682, 280, 280, 280, 280, 251, 251, 280, 162, 162, 162, 162, 162, 162, 18, 94, 3, -18, + 30, '', 0, 34, 0, 1.31, 100, 100, 100), + (2, 60, 60, 5795, 0, 2160, 1710, 289, 289, 289, 289, 254, 254, 289, 166, 166, 166, 166, 166, 166, 18, 95, 3, -18, + 30, '', 0, 35, 0, 1.31, 100, 100, 100), + (2, 61, 61, 5997, 0, 2196, 1739, 295, 295, 295, 295, 257, 257, 295, 168, 168, 168, 168, 168, 168, 21, 111, 4, + -21, 28, '', 0, 35, 0, 1.31, 100, 100, 100), + (2, 62, 62, 6204, 0, 2232, 1767, 302, 302, 302, 302, 260, 260, 302, 170, 170, 170, 170, 170, 170, 25, 128, 4, + -22, 28, '', 0, 35, 0, 1.31, 100, 100, 100), + (2, 63, 63, 6417, 0, 2268, 1796, 308, 308, 308, 308, 263, 263, 308, 172, 172, 172, 172, 172, 172, 28, 144, 4, + -22, 28, '', 0, 36, 0, 1.31, 100, 100, 100), + (2, 64, 64, 6634, 0, 2304, 1824, 315, 315, 315, 315, 266, 266, 315, 176, 176, 176, 176, 176, 176, 31, 161, 4, + -23, 28, '', 0, 36, 0, 1.31, 100, 100, 100), + (2, 65, 65, 6858, 0, 2340, 1853, 322, 322, 322, 322, 269, 269, 322, 178, 178, 178, 178, 178, 178, 34, 177, 4, + -23, 28, '', 0, 36, 0, 1.31, 100, 100, 100), + (2, 66, 66, 7087, 0, 2376, 1881, 359, 359, 359, 359, 302, 302, 359, 180, 180, 180, 180, 180, 180, 38, 193, 4, + -24, 27, '', 0, 37, 0, 1.31, 100, 100, 100), + (2, 67, 67, 7321, 0, 2412, 1910, 371, 371, 371, 371, 310, 310, 371, 182, 182, 182, 182, 182, 182, 41, 210, 4, + -24, 27, '', 0, 37, 0, 1.31, 100, 100, 100), + (2, 68, 68, 7561, 0, 2448, 1938, 384, 384, 384, 384, 318, 318, 384, 186, 186, 186, 186, 186, 186, 44, 226, 4, + -25, 27, '', 0, 37, 0, 1.31, 100, 100, 100), + (2, 69, 69, 7807, 0, 2484, 1967, 396, 396, 396, 396, 326, 326, 396, 188, 188, 188, 188, 188, 188, 47, 243, 4, + -25, 27, '', 0, 38, 0, 1.31, 100, 100, 100), + (2, 70, 70, 8060, 0, 2520, 1995, 411, 411, 411, 411, 334, 334, 411, 190, 190, 190, 190, 190, 190, 51, 259, 4, + -26, 27, '', 0, 38, 0, 1.31, 100, 100, 100), + (2, 71, 71, 8318, 0, 2556, 2024, 423, 423, 423, 423, 342, 342, 423, 192, 192, 192, 192, 192, 192, 54, 275, 4, + -26, 27, '', 0, 38, 0, 1.31, 100, 100, 100), + (2, 72, 72, 8582, 0, 2592, 2052, 436, 436, 436, 436, 350, 350, 436, 196, 196, 196, 196, 196, 196, 57, 292, 4, + -27, 26, '', 0, 39, 0, 1.31, 100, 100, 100), + (2, 73, 73, 8852, 0, 2628, 2081, 448, 448, 448, 448, 358, 358, 448, 198, 198, 198, 198, 198, 198, 60, 308, 4, + -27, 26, '', 0, 39, 0, 1.31, 100, 100, 100), + (2, 74, 74, 9128, 0, 2664, 2109, 461, 461, 461, 461, 366, 366, 461, 200, 200, 200, 200, 200, 200, 64, 325, 4, + -28, 26, '', 0, 39, 0, 1.31, 100, 100, 100), + (2, 75, 75, 9411, 0, 2700, 2138, 474, 474, 474, 474, 374, 374, 474, 202, 202, 202, 202, 202, 202, 67, 341, 4, + -28, 26, '', 0, 40, 0, 1.31, 100, 100, 100), + (2, 76, 76, 9701, 0, 2736, 2166, 487, 487, 487, 487, 382, 382, 487, 206, 206, 206, 206, 206, 206, 70, 357, 4, + -29, 26, '', 0, 40, 0, 1.31, 100, 100, 100), + (2, 77, 77, 9996, 0, 2772, 2195, 500, 500, 500, 500, 390, 390, 500, 208, 208, 208, 208, 208, 208, 73, 374, 4, + -29, 26, '', 0, 40, 0, 1.31, 100, 100, 100), + (2, 78, 78, 10299, 0, 2808, 2223, 514, 514, 514, 514, 398, 398, 514, 210, 210, 210, 210, 210, 210, 77, 390, 4, + -30, 25, '', 0, 41, 0, 1.31, 100, 100, 100), + (2, 79, 79, 10608, 0, 2844, 2252, 527, 527, 527, 527, 406, 406, 527, 212, 212, 212, 212, 212, 212, 80, 407, 4, + -30, 25, '', 0, 41, 0, 1.31, 100, 100, 100), + (2, 80, 80, 10924, 0, 2880, 2280, 543, 543, 543, 543, 414, 414, 543, 216, 216, 216, 216, 216, 216, 83, 423, 4, + -31, 25, '', 0, 41, 0, 1.31, 100, 100, 100), + (2, 81, 81, 11247, 0, 2916, 2309, 556, 556, 556, 556, 422, 422, 556, 218, 218, 218, 218, 218, 218, 86, 439, 4, + -31, 25, '', 0, 42, 0, 1.31, 100, 100, 100), + (2, 82, 82, 11576, 0, 2952, 2337, 570, 570, 570, 570, 430, 430, 570, 220, 220, 220, 220, 220, 220, 90, 456, 4, + -32, 24, '', 0, 42, 0, 1.31, 100, 100, 100), + (2, 83, 83, 11913, 0, 2988, 2366, 583, 583, 583, 583, 438, 438, 583, 222, 222, 222, 222, 222, 222, 93, 472, 4, + -32, 24, '', 0, 42, 0, 1.31, 100, 100, 100), + (2, 84, 84, 12257, 0, 3024, 2394, 597, 597, 597, 597, 446, 446, 597, 226, 226, 226, 226, 226, 226, 96, 489, 4, + -33, 24, '', 0, 43, 0, 1.31, 100, 100, 100), + (2, 85, 85, 12608, 0, 3060, 2423, 611, 611, 611, 611, 454, 454, 611, 228, 228, 228, 228, 228, 228, 99, 505, 4, + -35, 23, '', 0, 43, 0, 1.31, 100, 100, 100), + (3, 1, 1, 60, 0, 38, 29, 68, 68, 68, 68, 79, 79, 68, 21, 21, 21, 21, 21, 21, 4, 15, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (3, 2, 2, 110, 0, 75, 58, 69, 69, 69, 69, 82, 82, 69, 23, 23, 23, 23, 23, 23, 4, 17, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (3, 3, 3, 160, 0, 113, 87, 69, 69, 69, 69, 85, 85, 69, 25, 25, 25, 25, 25, 25, 4, 18, 1, -18, 30, '', 0, 18, 0, + 1.25, 100, 100, 100), + (3, 4, 4, 210, 0, 150, 116, 70, 70, 70, 70, 88, 88, 70, 30, 30, 30, 30, 30, 30, 5, 19, 1, -18, 30, '', 0, 18, 0, + 1.25, 100, 100, 100), + (3, 5, 5, 261, 0, 188, 145, 71, 71, 71, 71, 91, 91, 71, 32, 32, 32, 32, 32, 32, 5, 21, 1, -18, 30, '', 0, 18, 0, + 1.25, 100, 100, 100), + (3, 6, 6, 313, 0, 225, 174, 72, 72, 72, 72, 94, 94, 72, 34, 34, 34, 34, 34, 34, 5, 22, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (3, 7, 7, 364, 0, 263, 203, 73, 73, 73, 73, 97, 97, 73, 36, 36, 36, 36, 36, 36, 5, 24, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (3, 8, 8, 417, 0, 300, 232, 75, 75, 75, 75, 100, 100, 75, 41, 41, 41, 41, 41, 41, 6, 25, 1, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (3, 9, 9, 470, 0, 338, 261, 76, 76, 76, 76, 103, 103, 76, 43, 43, 43, 43, 43, 43, 6, 26, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (3, 10, 10, 524, 0, 375, 290, 81, 81, 81, 81, 106, 106, 81, 45, 45, 45, 45, 45, 45, 6, 28, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (3, 11, 11, 579, 0, 413, 319, 82, 82, 82, 82, 109, 109, 82, 47, 47, 47, 47, 47, 47, 6, 29, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (3, 12, 12, 634, 0, 450, 348, 84, 84, 84, 84, 112, 112, 84, 52, 52, 52, 52, 52, 52, 7, 31, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (3, 13, 13, 691, 0, 488, 377, 85, 85, 85, 85, 115, 115, 85, 54, 54, 54, 54, 54, 54, 7, 32, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (3, 14, 14, 749, 0, 525, 406, 87, 87, 87, 87, 118, 118, 87, 56, 56, 56, 56, 56, 56, 7, 33, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (3, 15, 15, 808, 0, 563, 435, 89, 89, 89, 89, 121, 121, 89, 58, 58, 58, 58, 58, 58, 7, 35, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (3, 16, 16, 868, 0, 600, 464, 91, 91, 91, 91, 124, 124, 91, 63, 63, 63, 63, 63, 63, 8, 36, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (3, 17, 17, 930, 0, 638, 493, 93, 93, 93, 93, 127, 127, 93, 65, 65, 65, 65, 65, 65, 8, 38, 2, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (3, 18, 18, 993, 0, 675, 522, 96, 96, 96, 96, 130, 130, 96, 67, 67, 67, 67, 67, 67, 8, 39, 2, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (3, 19, 19, 1057, 0, 713, 551, 98, 98, 98, 98, 133, 133, 98, 69, 69, 69, 69, 69, 69, 8, 40, 2, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (3, 20, 20, 1124, 0, 750, 580, 104, 104, 104, 104, 136, 136, 104, 74, 74, 74, 74, 74, 74, 9, 42, 2, -18, 30, '', + 0, 23, 0, 1.25, 100, 100, 100), + (3, 21, 21, 1192, 0, 788, 609, 106, 106, 106, 106, 139, 139, 106, 76, 76, 76, 76, 76, 76, 9, 43, 2, -18, 30, '', + 0, 24, 0, 1.25, 100, 100, 100), + (3, 22, 22, 1262, 0, 825, 638, 109, 109, 109, 109, 142, 142, 109, 78, 78, 78, 78, 78, 78, 9, 45, 2, -18, 30, '', + 0, 24, 0, 1.25, 100, 100, 100), + (3, 23, 23, 1333, 0, 863, 667, 111, 111, 111, 111, 145, 145, 111, 80, 80, 80, 80, 80, 80, 9, 46, 2, -18, 30, '', + 0, 24, 0, 1.25, 100, 100, 100), + (3, 24, 24, 1407, 0, 900, 696, 114, 114, 114, 114, 148, 148, 114, 85, 85, 85, 85, 85, 85, 10, 47, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (3, 25, 25, 1483, 0, 938, 725, 117, 117, 117, 117, 151, 151, 117, 87, 87, 87, 87, 87, 87, 10, 49, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (3, 26, 26, 1561, 0, 975, 754, 120, 120, 120, 120, 154, 154, 120, 89, 89, 89, 89, 89, 89, 10, 50, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (3, 27, 27, 1641, 0, 1013, 783, 123, 123, 123, 123, 157, 157, 123, 91, 91, 91, 91, 91, 91, 10, 52, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (3, 28, 28, 1723, 0, 1050, 812, 127, 127, 127, 127, 160, 160, 127, 96, 96, 96, 96, 96, 96, 11, 53, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (3, 29, 29, 1808, 0, 1088, 841, 130, 130, 130, 130, 163, 163, 130, 98, 98, 98, 98, 98, 98, 11, 54, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (3, 30, 30, 1895, 0, 1125, 870, 137, 137, 137, 137, 166, 166, 137, 100, 100, 100, 100, 100, 100, 11, 56, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (3, 31, 31, 1985, 0, 1163, 899, 140, 140, 140, 140, 169, 169, 140, 102, 102, 102, 102, 102, 102, 11, 57, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (3, 32, 32, 2078, 0, 1200, 928, 144, 144, 144, 144, 172, 172, 144, 107, 107, 107, 107, 107, 107, 12, 59, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (3, 33, 33, 2173, 0, 1238, 957, 147, 147, 147, 147, 175, 175, 147, 109, 109, 109, 109, 109, 109, 12, 60, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (3, 34, 34, 2271, 0, 1275, 986, 151, 151, 151, 151, 178, 178, 151, 111, 111, 111, 111, 111, 111, 12, 61, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (3, 35, 35, 2372, 0, 1313, 1015, 155, 155, 155, 155, 181, 181, 155, 113, 113, 113, 113, 113, 113, 12, 63, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (3, 36, 36, 2476, 0, 1350, 1044, 159, 159, 159, 159, 184, 184, 159, 118, 118, 118, 118, 118, 118, 13, 64, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (3, 37, 37, 2583, 0, 1388, 1073, 163, 163, 163, 163, 187, 187, 163, 120, 120, 120, 120, 120, 120, 13, 66, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (3, 38, 38, 2693, 0, 1425, 1102, 168, 168, 168, 168, 190, 190, 168, 122, 122, 122, 122, 122, 122, 13, 67, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (3, 39, 39, 2807, 0, 1463, 1131, 172, 172, 172, 172, 193, 193, 172, 124, 124, 124, 124, 124, 124, 13, 68, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (3, 40, 40, 2924, 0, 1500, 1160, 180, 180, 180, 180, 196, 196, 180, 129, 129, 129, 129, 129, 129, 14, 70, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (3, 41, 41, 3044, 0, 1538, 1189, 184, 184, 184, 184, 199, 199, 184, 131, 131, 131, 131, 131, 131, 14, 71, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (3, 42, 42, 3168, 0, 1575, 1218, 189, 189, 189, 189, 202, 202, 189, 133, 133, 133, 133, 133, 133, 14, 73, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (3, 43, 43, 3295, 0, 1613, 1247, 193, 193, 193, 193, 205, 205, 193, 135, 135, 135, 135, 135, 135, 14, 74, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (3, 44, 44, 3426, 0, 1650, 1276, 198, 198, 198, 198, 208, 208, 198, 140, 140, 140, 140, 140, 140, 15, 75, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (3, 45, 45, 3561, 0, 1688, 1305, 203, 203, 203, 203, 211, 211, 203, 142, 142, 142, 142, 142, 142, 15, 77, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (3, 46, 46, 3700, 0, 1725, 1334, 208, 208, 208, 208, 214, 214, 208, 144, 144, 144, 144, 144, 144, 15, 78, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (3, 47, 47, 3843, 0, 1763, 1363, 213, 213, 213, 213, 217, 217, 213, 146, 146, 146, 146, 146, 146, 15, 80, 3, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (3, 48, 48, 3989, 0, 1800, 1392, 219, 219, 219, 219, 220, 220, 219, 151, 151, 151, 151, 151, 151, 16, 81, 3, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (3, 49, 49, 4140, 0, 1838, 1421, 224, 224, 224, 224, 223, 223, 224, 153, 153, 153, 153, 153, 153, 16, 82, 3, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (3, 50, 50, 4295, 0, 1875, 1450, 233, 233, 233, 233, 226, 226, 233, 155, 155, 155, 155, 155, 155, 16, 84, 3, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (3, 51, 51, 4455, 0, 1913, 1479, 238, 238, 238, 238, 229, 229, 238, 157, 157, 157, 157, 157, 157, 16, 85, 3, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (3, 52, 52, 4618, 0, 1950, 1508, 244, 244, 244, 244, 232, 232, 244, 162, 162, 162, 162, 162, 162, 17, 87, 3, -18, + 30, '', 0, 34, 0, 1.37, 100, 100, 100), + (3, 53, 53, 4786, 0, 1988, 1537, 249, 249, 249, 249, 235, 235, 249, 164, 164, 164, 164, 164, 164, 17, 88, 3, -18, + 30, '', 0, 34, 0, 1.37, 100, 100, 100), + (3, 54, 54, 4959, 0, 2025, 1566, 255, 255, 255, 255, 238, 238, 255, 166, 166, 166, 166, 166, 166, 17, 89, 3, -18, + 30, '', 0, 35, 0, 1.37, 100, 100, 100), + (3, 55, 55, 5136, 0, 2063, 1595, 261, 261, 261, 261, 241, 241, 261, 168, 168, 168, 168, 168, 168, 17, 91, 3, -18, + 30, '', 0, 35, 0, 1.37, 100, 100, 100), + (3, 56, 56, 5318, 0, 2100, 1624, 267, 267, 267, 267, 244, 244, 267, 173, 173, 173, 173, 173, 173, 18, 92, 3, -18, + 30, '', 0, 35, 0, 1.37, 100, 100, 100), + (3, 57, 57, 5505, 0, 2138, 1653, 273, 273, 273, 273, 247, 247, 273, 175, 175, 175, 175, 175, 175, 18, 94, 3, -18, + 30, '', 0, 36, 0, 1.37, 100, 100, 100), + (3, 58, 58, 5697, 0, 2175, 1682, 280, 280, 280, 280, 250, 250, 280, 177, 177, 177, 177, 177, 177, 18, 95, 3, -18, + 30, '', 0, 36, 0, 1.37, 100, 100, 100), + (3, 59, 59, 5893, 0, 2213, 1711, 286, 286, 286, 286, 253, 253, 286, 179, 179, 179, 179, 179, 179, 18, 96, 3, -18, + 30, '', 0, 36, 0, 1.37, 100, 100, 100), + (3, 60, 60, 6095, 0, 2250, 1740, 296, 296, 296, 296, 256, 256, 296, 184, 184, 184, 184, 184, 184, 19, 98, 3, -18, + 30, '', 0, 37, 0, 1.37, 100, 100, 100), + (3, 61, 61, 6302, 0, 2288, 1769, 302, 302, 302, 302, 259, 259, 302, 186, 186, 186, 186, 186, 186, 22, 114, 4, + -22, 28, '', 0, 37, 0, 1.37, 100, 100, 100), + (3, 62, 62, 6514, 0, 2325, 1798, 309, 309, 309, 309, 262, 262, 309, 188, 188, 188, 188, 188, 188, 25, 131, 4, + -23, 28, '', 0, 37, 0, 1.37, 100, 100, 100), + (3, 63, 63, 6732, 0, 2363, 1827, 315, 315, 315, 315, 265, 265, 315, 190, 190, 190, 190, 190, 190, 28, 147, 4, + -23, 28, '', 0, 38, 0, 1.37, 100, 100, 100), + (3, 64, 64, 6954, 0, 2400, 1856, 322, 322, 322, 322, 268, 268, 322, 195, 195, 195, 195, 195, 195, 32, 163, 4, + -24, 27, '', 0, 38, 0, 1.37, 100, 100, 100), + (3, 65, 65, 7183, 0, 2438, 1885, 329, 329, 329, 329, 271, 271, 329, 197, 197, 197, 197, 197, 197, 35, 180, 4, + -24, 27, '', 0, 38, 0, 1.37, 100, 100, 100), + (3, 66, 66, 7417, 0, 2475, 1914, 366, 366, 366, 366, 304, 304, 366, 199, 199, 199, 199, 199, 199, 38, 196, 4, + -25, 27, '', 0, 39, 0, 1.37, 100, 100, 100), + (3, 67, 67, 7656, 0, 2513, 1943, 378, 378, 378, 378, 312, 312, 378, 201, 201, 201, 201, 201, 201, 41, 213, 4, + -25, 27, '', 0, 39, 0, 1.37, 100, 100, 100), + (3, 68, 68, 7901, 0, 2550, 1972, 391, 391, 391, 391, 320, 320, 391, 206, 206, 206, 206, 206, 206, 45, 229, 4, + -26, 27, '', 0, 39, 0, 1.37, 100, 100, 100), + (3, 69, 69, 8152, 0, 2588, 2001, 403, 403, 403, 403, 328, 328, 403, 208, 208, 208, 208, 208, 208, 48, 245, 4, + -26, 27, '', 0, 40, 0, 1.37, 100, 100, 100), + (3, 70, 70, 8410, 0, 2625, 2030, 419, 419, 419, 419, 336, 336, 419, 210, 210, 210, 210, 210, 210, 51, 262, 4, + -27, 26, '', 0, 40, 0, 1.37, 100, 100, 100), + (3, 71, 71, 8673, 0, 2663, 2059, 431, 431, 431, 431, 344, 344, 431, 212, 212, 212, 212, 212, 212, 54, 278, 4, + -27, 26, '', 0, 40, 0, 1.37, 100, 100, 100), + (3, 72, 72, 8942, 0, 2700, 2088, 444, 444, 444, 444, 352, 352, 444, 217, 217, 217, 217, 217, 217, 58, 295, 4, + -28, 26, '', 0, 41, 0, 1.37, 100, 100, 100), + (3, 73, 73, 9217, 0, 2738, 2117, 456, 456, 456, 456, 360, 360, 456, 219, 219, 219, 219, 219, 219, 61, 311, 4, + -28, 26, '', 0, 41, 0, 1.37, 100, 100, 100), + (3, 74, 74, 9498, 0, 2775, 2146, 469, 469, 469, 469, 368, 368, 469, 221, 221, 221, 221, 221, 221, 64, 327, 4, + -29, 26, '', 0, 41, 0, 1.37, 100, 100, 100), + (3, 75, 75, 9786, 0, 2813, 2175, 482, 482, 482, 482, 376, 376, 482, 223, 223, 223, 223, 223, 223, 67, 344, 4, + -29, 26, '', 0, 42, 0, 1.37, 100, 100, 100), + (3, 76, 76, 10081, 0, 2850, 2204, 495, 495, 495, 495, 384, 384, 495, 228, 228, 228, 228, 228, 228, 71, 360, 4, + -30, 25, '', 0, 42, 0, 1.37, 100, 100, 100), + (3, 77, 77, 10381, 0, 2888, 2233, 508, 508, 508, 508, 392, 392, 508, 230, 230, 230, 230, 230, 230, 74, 377, 4, + -30, 25, '', 0, 42, 0, 1.37, 100, 100, 100), + (3, 78, 78, 10689, 0, 2925, 2262, 522, 522, 522, 522, 400, 400, 522, 232, 232, 232, 232, 232, 232, 77, 393, 4, + -31, 25, '', 0, 43, 0, 1.37, 100, 100, 100), + (3, 79, 79, 11003, 0, 2963, 2291, 535, 535, 535, 535, 408, 408, 535, 234, 234, 234, 234, 234, 234, 80, 409, 4, + -31, 25, '', 0, 43, 0, 1.37, 100, 100, 100), + (3, 80, 80, 11324, 0, 3000, 2320, 552, 552, 552, 552, 416, 416, 552, 239, 239, 239, 239, 239, 239, 84, 426, 4, + -32, 24, '', 0, 43, 0, 1.37, 100, 100, 100), + (3, 81, 81, 11652, 0, 3038, 2349, 565, 565, 565, 565, 424, 424, 565, 241, 241, 241, 241, 241, 241, 87, 442, 4, + -32, 24, '', 0, 44, 0, 1.37, 100, 100, 100), + (3, 82, 82, 11986, 0, 3075, 2378, 579, 579, 579, 579, 432, 432, 579, 243, 243, 243, 243, 243, 243, 90, 459, 4, + -33, 24, '', 0, 44, 0, 1.37, 100, 100, 100), + (3, 83, 83, 12328, 0, 3113, 2407, 592, 592, 592, 592, 440, 440, 592, 245, 245, 245, 245, 245, 245, 93, 475, 4, + -33, 24, '', 0, 44, 0, 1.37, 100, 100, 100), + (3, 84, 84, 12677, 0, 3150, 2436, 606, 606, 606, 606, 448, 448, 606, 250, 250, 250, 250, 250, 250, 97, 491, 4, + -34, 24, '', 0, 45, 0, 1.37, 100, 100, 100), + (3, 85, 85, 13033, 0, 3188, 2465, 620, 620, 620, 620, 456, 456, 620, 252, 252, 252, 252, 252, 252, 100, 508, 4, + -36, 23, '', 0, 45, 0, 1.37, 100, 100, 100), + (4, 1, 1, 65, 0, 39, 30, 69, 69, 69, 69, 81, 81, 69, 24, 24, 24, 24, 24, 24, 4, 18, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (4, 2, 2, 120, 0, 78, 59, 70, 70, 70, 70, 84, 84, 70, 26, 26, 26, 26, 26, 26, 5, 19, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (4, 3, 3, 175, 0, 117, 89, 70, 70, 70, 70, 87, 87, 70, 28, 28, 28, 28, 28, 28, 5, 21, 1, -18, 30, '', 0, 20, 0, + 1.25, 100, 100, 100), + (4, 4, 4, 230, 0, 156, 118, 71, 71, 71, 71, 90, 90, 71, 34, 34, 34, 34, 34, 34, 5, 22, 1, -18, 30, '', 0, 20, 0, + 1.25, 100, 100, 100), + (4, 5, 5, 286, 0, 195, 148, 72, 72, 72, 72, 93, 93, 72, 36, 36, 36, 36, 36, 36, 5, 24, 1, -18, 30, '', 0, 20, 0, + 1.25, 100, 100, 100), + (4, 6, 6, 343, 0, 234, 177, 73, 73, 73, 73, 96, 96, 73, 38, 38, 38, 38, 38, 38, 6, 25, 1, -18, 30, '', 0, 21, 0, + 1.25, 100, 100, 100), + (4, 7, 7, 399, 0, 273, 207, 74, 74, 74, 74, 99, 99, 74, 40, 40, 40, 40, 40, 40, 6, 26, 1, -18, 30, '', 0, 21, 0, + 1.25, 100, 100, 100), + (4, 8, 8, 457, 0, 312, 236, 76, 76, 76, 76, 102, 102, 76, 46, 46, 46, 46, 46, 46, 6, 28, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (4, 9, 9, 515, 0, 351, 266, 77, 77, 77, 77, 105, 105, 77, 48, 48, 48, 48, 48, 48, 6, 29, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (4, 10, 10, 574, 0, 390, 295, 83, 83, 83, 83, 108, 108, 83, 50, 50, 50, 50, 50, 50, 7, 31, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (4, 11, 11, 634, 0, 429, 325, 84, 84, 84, 84, 111, 111, 84, 52, 52, 52, 52, 52, 52, 7, 32, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (4, 12, 12, 694, 0, 468, 354, 86, 86, 86, 86, 114, 114, 86, 58, 58, 58, 58, 58, 58, 7, 33, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (4, 13, 13, 756, 0, 507, 384, 87, 87, 87, 87, 117, 117, 87, 60, 60, 60, 60, 60, 60, 7, 35, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (4, 14, 14, 819, 0, 546, 413, 89, 89, 89, 89, 120, 120, 89, 62, 62, 62, 62, 62, 62, 8, 36, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (4, 15, 15, 883, 0, 585, 443, 91, 91, 91, 91, 123, 123, 91, 64, 64, 64, 64, 64, 64, 8, 38, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (4, 16, 16, 948, 0, 624, 472, 93, 93, 93, 93, 126, 126, 93, 70, 70, 70, 70, 70, 70, 8, 39, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (4, 17, 17, 1015, 0, 663, 502, 95, 95, 95, 95, 129, 129, 95, 72, 72, 72, 72, 72, 72, 8, 40, 2, -18, 30, '', 0, + 24, 0, 1.25, 100, 100, 100), + (4, 18, 18, 1083, 0, 702, 531, 98, 98, 98, 98, 132, 132, 98, 74, 74, 74, 74, 74, 74, 9, 42, 2, -18, 30, '', 0, + 25, 0, 1.25, 100, 100, 100), + (4, 19, 19, 1152, 0, 741, 561, 100, 100, 100, 100, 135, 135, 100, 76, 76, 76, 76, 76, 76, 9, 43, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (4, 20, 20, 1224, 0, 780, 590, 107, 107, 107, 107, 138, 138, 107, 82, 82, 82, 82, 82, 82, 9, 45, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (4, 21, 21, 1297, 0, 819, 620, 109, 109, 109, 109, 141, 141, 109, 84, 84, 84, 84, 84, 84, 9, 46, 2, -18, 30, '', + 0, 26, 0, 1.25, 100, 100, 100), + (4, 22, 22, 1372, 0, 858, 649, 112, 112, 112, 112, 144, 144, 112, 86, 86, 86, 86, 86, 86, 10, 47, 2, -18, 30, '', + 0, 26, 0, 1.25, 100, 100, 100), + (4, 23, 23, 1448, 0, 897, 679, 114, 114, 114, 114, 147, 147, 114, 88, 88, 88, 88, 88, 88, 10, 49, 2, -18, 30, '', + 0, 26, 0, 1.25, 100, 100, 100), + (4, 24, 24, 1527, 0, 936, 708, 117, 117, 117, 117, 150, 150, 117, 94, 94, 94, 94, 94, 94, 10, 50, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (4, 25, 25, 1608, 0, 975, 738, 120, 120, 120, 120, 153, 153, 120, 96, 96, 96, 96, 96, 96, 10, 52, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (4, 26, 26, 1691, 0, 1014, 767, 123, 123, 123, 123, 156, 156, 123, 98, 98, 98, 98, 98, 98, 11, 53, 2, -18, 30, + '', 0, 27, 0, 1.25, 100, 100, 100), + (4, 27, 27, 1776, 0, 1053, 797, 126, 126, 126, 126, 159, 159, 126, 100, 100, 100, 100, 100, 100, 11, 54, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (4, 28, 28, 1863, 0, 1092, 826, 130, 130, 130, 130, 162, 162, 130, 106, 106, 106, 106, 106, 106, 11, 56, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (4, 29, 29, 1953, 0, 1131, 856, 133, 133, 133, 133, 165, 165, 133, 108, 108, 108, 108, 108, 108, 11, 57, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (4, 30, 30, 2045, 0, 1170, 885, 141, 141, 141, 141, 168, 168, 141, 110, 110, 110, 110, 110, 110, 12, 59, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (4, 31, 31, 2140, 0, 1209, 915, 144, 144, 144, 144, 171, 171, 144, 112, 112, 112, 112, 112, 112, 12, 60, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (4, 32, 32, 2238, 0, 1248, 944, 148, 148, 148, 148, 174, 174, 148, 118, 118, 118, 118, 118, 118, 12, 61, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (4, 33, 33, 2338, 0, 1287, 974, 151, 151, 151, 151, 177, 177, 151, 120, 120, 120, 120, 120, 120, 12, 63, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (4, 34, 34, 2441, 0, 1326, 1003, 155, 155, 155, 155, 180, 180, 155, 122, 122, 122, 122, 122, 122, 13, 64, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (4, 35, 35, 2547, 0, 1365, 1033, 159, 159, 159, 159, 183, 183, 159, 124, 124, 124, 124, 124, 124, 13, 66, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (4, 36, 36, 2656, 0, 1404, 1062, 163, 163, 163, 163, 186, 186, 163, 130, 130, 130, 130, 130, 130, 13, 67, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (4, 37, 37, 2768, 0, 1443, 1092, 167, 167, 167, 167, 189, 189, 167, 132, 132, 132, 132, 132, 132, 13, 68, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (4, 38, 38, 2883, 0, 1482, 1121, 172, 172, 172, 172, 192, 192, 172, 134, 134, 134, 134, 134, 134, 14, 70, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (4, 39, 39, 3002, 0, 1521, 1151, 176, 176, 176, 176, 195, 195, 176, 136, 136, 136, 136, 136, 136, 14, 71, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (4, 40, 40, 3124, 0, 1560, 1180, 185, 185, 185, 185, 198, 198, 185, 142, 142, 142, 142, 142, 142, 14, 73, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (4, 41, 41, 3249, 0, 1599, 1210, 189, 189, 189, 189, 201, 201, 189, 144, 144, 144, 144, 144, 144, 14, 74, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (4, 42, 42, 3378, 0, 1638, 1239, 194, 194, 194, 194, 204, 204, 194, 146, 146, 146, 146, 146, 146, 15, 75, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (4, 43, 43, 3510, 0, 1677, 1269, 198, 198, 198, 198, 207, 207, 198, 148, 148, 148, 148, 148, 148, 15, 77, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (4, 44, 44, 3646, 0, 1716, 1298, 203, 203, 203, 203, 210, 210, 203, 154, 154, 154, 154, 154, 154, 15, 78, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (4, 45, 45, 3786, 0, 1755, 1328, 208, 208, 208, 208, 213, 213, 208, 156, 156, 156, 156, 156, 156, 15, 80, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (4, 46, 46, 3930, 0, 1794, 1357, 213, 213, 213, 213, 216, 216, 213, 158, 158, 158, 158, 158, 158, 16, 81, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (4, 47, 47, 4078, 0, 1833, 1387, 218, 218, 218, 218, 219, 219, 218, 160, 160, 160, 160, 160, 160, 16, 82, 3, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (4, 48, 48, 4229, 0, 1872, 1416, 224, 224, 224, 224, 222, 222, 224, 166, 166, 166, 166, 166, 166, 16, 84, 3, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (4, 49, 49, 4385, 0, 1911, 1446, 229, 229, 229, 229, 225, 225, 229, 168, 168, 168, 168, 168, 168, 16, 85, 3, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (4, 50, 50, 4545, 0, 1950, 1475, 239, 239, 239, 239, 228, 228, 239, 170, 170, 170, 170, 170, 170, 17, 87, 3, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (4, 51, 51, 4710, 0, 1989, 1505, 244, 244, 244, 244, 231, 231, 244, 172, 172, 172, 172, 172, 172, 17, 88, 3, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (4, 52, 52, 4878, 0, 2028, 1534, 250, 250, 250, 250, 234, 234, 250, 178, 178, 178, 178, 178, 178, 17, 89, 3, -18, + 30, '', 0, 36, 0, 1.43, 100, 100, 100), + (4, 53, 53, 5051, 0, 2067, 1564, 255, 255, 255, 255, 237, 237, 255, 180, 180, 180, 180, 180, 180, 17, 91, 3, -18, + 30, '', 0, 36, 0, 1.43, 100, 100, 100), + (4, 54, 54, 5229, 0, 2106, 1593, 261, 261, 261, 261, 240, 240, 261, 182, 182, 182, 182, 182, 182, 18, 92, 3, -18, + 30, '', 0, 37, 0, 1.43, 100, 100, 100), + (4, 55, 55, 5411, 0, 2145, 1623, 267, 267, 267, 267, 243, 243, 267, 184, 184, 184, 184, 184, 184, 18, 94, 3, -18, + 30, '', 0, 37, 0, 1.43, 100, 100, 100), + (4, 56, 56, 5598, 0, 2184, 1652, 273, 273, 273, 273, 246, 246, 273, 190, 190, 190, 190, 190, 190, 18, 95, 3, -18, + 30, '', 0, 37, 0, 1.43, 100, 100, 100), + (4, 57, 57, 5790, 0, 2223, 1682, 279, 279, 279, 279, 249, 249, 279, 192, 192, 192, 192, 192, 192, 18, 96, 3, -18, + 30, '', 0, 38, 0, 1.43, 100, 100, 100), + (4, 58, 58, 5987, 0, 2262, 1711, 286, 286, 286, 286, 252, 252, 286, 194, 194, 194, 194, 194, 194, 19, 98, 3, -18, + 30, '', 0, 38, 0, 1.43, 100, 100, 100), + (4, 59, 59, 6188, 0, 2301, 1741, 292, 292, 292, 292, 255, 255, 292, 196, 196, 196, 196, 196, 196, 19, 99, 3, -18, + 30, '', 0, 38, 0, 1.43, 100, 100, 100), + (4, 60, 60, 6395, 0, 2340, 1770, 303, 303, 303, 303, 258, 258, 303, 202, 202, 202, 202, 202, 202, 19, 101, 3, + -18, 30, '', 0, 39, 0, 1.43, 100, 100, 100), + (4, 61, 61, 6607, 0, 2379, 1800, 309, 309, 309, 309, 261, 261, 309, 204, 204, 204, 204, 204, 204, 22, 117, 4, + -23, 28, '', 0, 39, 0, 1.43, 100, 100, 100), + (4, 62, 62, 6824, 0, 2418, 1829, 316, 316, 316, 316, 264, 264, 316, 206, 206, 206, 206, 206, 206, 26, 133, 4, + -24, 27, '', 0, 39, 0, 1.43, 100, 100, 100), + (4, 63, 63, 7047, 0, 2457, 1859, 322, 322, 322, 322, 267, 267, 322, 208, 208, 208, 208, 208, 208, 29, 150, 4, + -24, 27, '', 0, 40, 0, 1.43, 100, 100, 100), + (4, 64, 64, 7274, 0, 2496, 1888, 329, 329, 329, 329, 270, 270, 329, 214, 214, 214, 214, 214, 214, 32, 166, 4, + -25, 27, '', 0, 40, 0, 1.43, 100, 100, 100), + (4, 65, 65, 7508, 0, 2535, 1918, 336, 336, 336, 336, 273, 273, 336, 216, 216, 216, 216, 216, 216, 35, 183, 4, + -25, 27, '', 0, 40, 0, 1.43, 100, 100, 100), + (4, 66, 66, 7747, 0, 2574, 1947, 373, 373, 373, 373, 306, 306, 373, 218, 218, 218, 218, 218, 218, 39, 199, 4, + -26, 27, '', 0, 41, 0, 1.43, 100, 100, 100), + (4, 67, 67, 7991, 0, 2613, 1977, 385, 385, 385, 385, 314, 314, 385, 220, 220, 220, 220, 220, 220, 42, 215, 4, + -26, 27, '', 0, 41, 0, 1.43, 100, 100, 100), + (4, 68, 68, 8241, 0, 2652, 2006, 398, 398, 398, 398, 322, 322, 398, 226, 226, 226, 226, 226, 226, 45, 232, 4, + -27, 26, '', 0, 41, 0, 1.43, 100, 100, 100), + (4, 69, 69, 8497, 0, 2691, 2036, 410, 410, 410, 410, 330, 330, 410, 228, 228, 228, 228, 228, 228, 48, 248, 4, + -27, 26, '', 0, 42, 0, 1.43, 100, 100, 100), + (4, 70, 70, 8760, 0, 2730, 2065, 427, 427, 427, 427, 338, 338, 427, 230, 230, 230, 230, 230, 230, 52, 265, 4, + -28, 26, '', 0, 42, 0, 1.43, 100, 100, 100), + (4, 71, 71, 9028, 0, 2769, 2095, 439, 439, 439, 439, 346, 346, 439, 232, 232, 232, 232, 232, 232, 55, 281, 4, + -28, 26, '', 0, 42, 0, 1.43, 100, 100, 100), + (4, 72, 72, 9302, 0, 2808, 2124, 452, 452, 452, 452, 354, 354, 452, 238, 238, 238, 238, 238, 238, 58, 297, 4, + -29, 26, '', 0, 43, 0, 1.43, 100, 100, 100), + (4, 73, 73, 9582, 0, 2847, 2154, 464, 464, 464, 464, 362, 362, 464, 240, 240, 240, 240, 240, 240, 61, 314, 4, + -29, 26, '', 0, 43, 0, 1.43, 100, 100, 100), + (4, 74, 74, 9868, 0, 2886, 2183, 477, 477, 477, 477, 370, 370, 477, 242, 242, 242, 242, 242, 242, 65, 330, 4, + -30, 25, '', 0, 43, 0, 1.43, 100, 100, 100), + (4, 75, 75, 10161, 0, 2925, 2213, 490, 490, 490, 490, 378, 378, 490, 244, 244, 244, 244, 244, 244, 68, 347, 4, + -30, 25, '', 0, 44, 0, 1.43, 100, 100, 100), + (4, 76, 76, 10461, 0, 2964, 2242, 503, 503, 503, 503, 386, 386, 503, 250, 250, 250, 250, 250, 250, 71, 363, 4, + -31, 25, '', 0, 44, 0, 1.43, 100, 100, 100), + (4, 77, 77, 10766, 0, 3003, 2272, 516, 516, 516, 516, 394, 394, 516, 252, 252, 252, 252, 252, 252, 74, 379, 4, + -31, 25, '', 0, 44, 0, 1.43, 100, 100, 100), + (4, 78, 78, 11079, 0, 3042, 2301, 530, 530, 530, 530, 402, 402, 530, 254, 254, 254, 254, 254, 254, 78, 396, 4, + -32, 24, '', 0, 45, 0, 1.43, 100, 100, 100), + (4, 79, 79, 11398, 0, 3081, 2331, 543, 543, 543, 543, 410, 410, 543, 256, 256, 256, 256, 256, 256, 81, 412, 4, + -32, 24, '', 0, 45, 0, 1.43, 100, 100, 100), + (4, 80, 80, 11724, 0, 3120, 2360, 561, 561, 561, 561, 418, 418, 561, 262, 262, 262, 262, 262, 262, 84, 429, 4, + -33, 24, '', 0, 45, 0, 1.43, 100, 100, 100), + (4, 81, 81, 12057, 0, 3159, 2390, 574, 574, 574, 574, 426, 426, 574, 264, 264, 264, 264, 264, 264, 87, 445, 4, + -33, 24, '', 0, 46, 0, 1.43, 100, 100, 100), + (4, 82, 82, 12396, 0, 3198, 2419, 588, 588, 588, 588, 434, 434, 588, 266, 266, 266, 266, 266, 266, 91, 461, 4, + -34, 24, '', 0, 46, 0, 1.43, 100, 100, 100), + (4, 83, 83, 12743, 0, 3237, 2449, 601, 601, 601, 601, 442, 442, 601, 268, 268, 268, 268, 268, 268, 94, 478, 4, + -34, 24, '', 0, 46, 0, 1.43, 100, 100, 100), + (4, 84, 84, 13097, 0, 3276, 2478, 615, 615, 615, 615, 450, 450, 615, 274, 274, 274, 274, 274, 274, 97, 494, 4, + -35, 23, '', 0, 47, 0, 1.43, 100, 100, 100), + (4, 85, 85, 13458, 0, 3315, 2508, 629, 629, 629, 629, 458, 458, 629, 276, 276, 276, 276, 276, 276, 100, 511, 4, + -37, 23, '', 0, 47, 0, 1.43, 100, 100, 100), + (5, 1, 1, 70, 0, 41, 30, 70, 70, 70, 70, 83, 83, 70, 27, 27, 27, 27, 27, 27, 5, 21, 1, -18, 30, '', 0, 21, 0, + 1.25, 100, 100, 100), + (5, 2, 2, 130, 0, 81, 60, 71, 71, 71, 71, 86, 86, 71, 29, 29, 29, 29, 29, 29, 5, 22, 1, -18, 30, '', 0, 21, 0, + 1.25, 100, 100, 100), + (5, 3, 3, 190, 0, 122, 90, 71, 71, 71, 71, 89, 89, 71, 31, 31, 31, 31, 31, 31, 5, 24, 1, -18, 30, '', 0, 22, 0, + 1.25, 100, 100, 100), + (5, 4, 4, 250, 0, 162, 120, 72, 72, 72, 72, 92, 92, 72, 38, 38, 38, 38, 38, 38, 6, 25, 1, -18, 30, '', 0, 22, 0, + 1.25, 100, 100, 100), + (5, 5, 5, 311, 0, 203, 150, 73, 73, 73, 73, 95, 95, 73, 40, 40, 40, 40, 40, 40, 6, 26, 1, -18, 30, '', 0, 22, 0, + 1.25, 100, 100, 100), + (5, 6, 6, 373, 0, 243, 180, 74, 74, 74, 74, 98, 98, 74, 42, 42, 42, 42, 42, 42, 6, 28, 1, -18, 30, '', 0, 23, 0, + 1.25, 100, 100, 100), + (5, 7, 7, 434, 0, 284, 210, 75, 75, 75, 75, 101, 101, 75, 44, 44, 44, 44, 44, 44, 6, 29, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (5, 8, 8, 497, 0, 324, 240, 77, 77, 77, 77, 104, 104, 77, 51, 51, 51, 51, 51, 51, 7, 31, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (5, 9, 9, 560, 0, 365, 270, 78, 78, 78, 78, 107, 107, 78, 53, 53, 53, 53, 53, 53, 7, 32, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (5, 10, 10, 624, 0, 405, 300, 85, 85, 85, 85, 110, 110, 85, 55, 55, 55, 55, 55, 55, 7, 33, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (5, 11, 11, 689, 0, 446, 330, 86, 86, 86, 86, 113, 113, 86, 57, 57, 57, 57, 57, 57, 7, 35, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (5, 12, 12, 754, 0, 486, 360, 88, 88, 88, 88, 116, 116, 88, 64, 64, 64, 64, 64, 64, 8, 36, 1, -18, 30, '', 0, 25, + 0, 1.25, 100, 100, 100), + (5, 13, 13, 821, 0, 527, 390, 89, 89, 89, 89, 119, 119, 89, 66, 66, 66, 66, 66, 66, 8, 38, 1, -18, 30, '', 0, 25, + 0, 1.25, 100, 100, 100), + (5, 14, 14, 889, 0, 567, 420, 91, 91, 91, 91, 122, 122, 91, 68, 68, 68, 68, 68, 68, 8, 39, 1, -18, 30, '', 0, 25, + 0, 1.25, 100, 100, 100), + (5, 15, 15, 958, 0, 608, 450, 93, 93, 93, 93, 125, 125, 93, 70, 70, 70, 70, 70, 70, 8, 40, 1, -18, 30, '', 0, 26, + 0, 1.25, 100, 100, 100), + (5, 16, 16, 1028, 0, 648, 480, 95, 95, 95, 95, 128, 128, 95, 77, 77, 77, 77, 77, 77, 9, 42, 1, -18, 30, '', 0, + 26, 0, 1.25, 100, 100, 100), + (5, 17, 17, 1100, 0, 689, 510, 97, 97, 97, 97, 131, 131, 97, 79, 79, 79, 79, 79, 79, 9, 43, 2, -18, 30, '', 0, + 26, 0, 1.25, 100, 100, 100), + (5, 18, 18, 1173, 0, 729, 540, 100, 100, 100, 100, 134, 134, 100, 81, 81, 81, 81, 81, 81, 9, 45, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (5, 19, 19, 1247, 0, 770, 570, 102, 102, 102, 102, 137, 137, 102, 83, 83, 83, 83, 83, 83, 9, 46, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (5, 20, 20, 1324, 0, 810, 600, 110, 110, 110, 110, 140, 140, 110, 90, 90, 90, 90, 90, 90, 10, 47, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (5, 21, 21, 1402, 0, 851, 630, 112, 112, 112, 112, 143, 143, 112, 92, 92, 92, 92, 92, 92, 10, 49, 2, -18, 30, '', + 0, 28, 0, 1.25, 100, 100, 100), + (5, 22, 22, 1482, 0, 891, 660, 115, 115, 115, 115, 146, 146, 115, 94, 94, 94, 94, 94, 94, 10, 50, 2, -18, 30, '', + 0, 28, 0, 1.25, 100, 100, 100), + (5, 23, 23, 1563, 0, 932, 690, 117, 117, 117, 117, 149, 149, 117, 96, 96, 96, 96, 96, 96, 10, 52, 2, -18, 30, '', + 0, 28, 0, 1.25, 100, 100, 100), + (5, 24, 24, 1647, 0, 972, 720, 120, 120, 120, 120, 152, 152, 120, 103, 103, 103, 103, 103, 103, 11, 53, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (5, 25, 25, 1733, 0, 1013, 750, 123, 123, 123, 123, 155, 155, 123, 105, 105, 105, 105, 105, 105, 11, 54, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (5, 26, 26, 1821, 0, 1053, 780, 126, 126, 126, 126, 158, 158, 126, 107, 107, 107, 107, 107, 107, 11, 56, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (5, 27, 27, 1911, 0, 1094, 810, 129, 129, 129, 129, 161, 161, 129, 109, 109, 109, 109, 109, 109, 11, 57, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (5, 28, 28, 2003, 0, 1134, 840, 133, 133, 133, 133, 164, 164, 133, 116, 116, 116, 116, 116, 116, 12, 59, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (5, 29, 29, 2098, 0, 1175, 870, 136, 136, 136, 136, 167, 167, 136, 118, 118, 118, 118, 118, 118, 12, 60, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (5, 30, 30, 2195, 0, 1215, 900, 145, 145, 145, 145, 170, 170, 145, 120, 120, 120, 120, 120, 120, 12, 61, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (5, 31, 31, 2295, 0, 1256, 930, 148, 148, 148, 148, 173, 173, 148, 122, 122, 122, 122, 122, 122, 12, 63, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (5, 32, 32, 2398, 0, 1296, 960, 152, 152, 152, 152, 176, 176, 152, 129, 129, 129, 129, 129, 129, 13, 64, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (5, 33, 33, 2503, 0, 1337, 990, 155, 155, 155, 155, 179, 179, 155, 131, 131, 131, 131, 131, 131, 13, 66, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (5, 34, 34, 2611, 0, 1377, 1020, 159, 159, 159, 159, 182, 182, 159, 133, 133, 133, 133, 133, 133, 13, 67, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (5, 35, 35, 2722, 0, 1418, 1050, 163, 163, 163, 163, 185, 185, 163, 135, 135, 135, 135, 135, 135, 13, 68, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (5, 36, 36, 2836, 0, 1458, 1080, 167, 167, 167, 167, 188, 188, 167, 142, 142, 142, 142, 142, 142, 14, 70, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (5, 37, 37, 2953, 0, 1499, 1110, 171, 171, 171, 171, 191, 191, 171, 144, 144, 144, 144, 144, 144, 14, 71, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (5, 38, 38, 3073, 0, 1539, 1140, 176, 176, 176, 176, 194, 194, 176, 146, 146, 146, 146, 146, 146, 14, 73, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (5, 39, 39, 3197, 0, 1580, 1170, 180, 180, 180, 180, 197, 197, 180, 148, 148, 148, 148, 148, 148, 14, 74, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (5, 40, 40, 3324, 0, 1620, 1200, 190, 190, 190, 190, 200, 200, 190, 155, 155, 155, 155, 155, 155, 15, 75, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (5, 41, 41, 3454, 0, 1661, 1230, 194, 194, 194, 194, 203, 203, 194, 157, 157, 157, 157, 157, 157, 15, 77, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (5, 42, 42, 3588, 0, 1701, 1260, 199, 199, 199, 199, 206, 206, 199, 159, 159, 159, 159, 159, 159, 15, 78, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (5, 43, 43, 3725, 0, 1742, 1290, 203, 203, 203, 203, 209, 209, 203, 161, 161, 161, 161, 161, 161, 15, 80, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (5, 44, 44, 3866, 0, 1782, 1320, 208, 208, 208, 208, 212, 212, 208, 168, 168, 168, 168, 168, 168, 16, 81, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (5, 45, 45, 4011, 0, 1823, 1350, 213, 213, 213, 213, 215, 215, 213, 170, 170, 170, 170, 170, 170, 16, 82, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (5, 46, 46, 4160, 0, 1863, 1380, 218, 218, 218, 218, 218, 218, 218, 172, 172, 172, 172, 172, 172, 16, 84, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (5, 47, 47, 4313, 0, 1904, 1410, 223, 223, 223, 223, 221, 221, 223, 174, 174, 174, 174, 174, 174, 16, 85, 3, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (5, 48, 48, 4469, 0, 1944, 1440, 229, 229, 229, 229, 224, 224, 229, 181, 181, 181, 181, 181, 181, 17, 87, 3, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (5, 49, 49, 4630, 0, 1985, 1470, 234, 234, 234, 234, 227, 227, 234, 183, 183, 183, 183, 183, 183, 17, 88, 3, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (5, 50, 50, 4795, 0, 2025, 1500, 245, 245, 245, 245, 230, 230, 245, 185, 185, 185, 185, 185, 185, 17, 89, 3, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (5, 51, 51, 4965, 0, 2066, 1530, 250, 250, 250, 250, 233, 233, 250, 187, 187, 187, 187, 187, 187, 17, 91, 3, -18, + 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (5, 52, 52, 5138, 0, 2106, 1560, 256, 256, 256, 256, 236, 236, 256, 194, 194, 194, 194, 194, 194, 18, 92, 3, -18, + 30, '', 0, 38, 0, 1.49, 100, 100, 100), + (5, 53, 53, 5316, 0, 2147, 1590, 261, 261, 261, 261, 239, 239, 261, 196, 196, 196, 196, 196, 196, 18, 94, 3, -18, + 30, '', 0, 38, 0, 1.49, 100, 100, 100), + (5, 54, 54, 5499, 0, 2187, 1620, 267, 267, 267, 267, 242, 242, 267, 198, 198, 198, 198, 198, 198, 18, 95, 3, -18, + 30, '', 0, 39, 0, 1.49, 100, 100, 100), + (5, 55, 55, 5686, 0, 2228, 1650, 273, 273, 273, 273, 245, 245, 273, 200, 200, 200, 200, 200, 200, 18, 96, 3, -18, + 30, '', 0, 39, 0, 1.49, 100, 100, 100), + (5, 56, 56, 5878, 0, 2268, 1680, 279, 279, 279, 279, 248, 248, 279, 207, 207, 207, 207, 207, 207, 19, 98, 3, -18, + 30, '', 0, 39, 0, 1.49, 100, 100, 100), + (5, 57, 57, 6075, 0, 2309, 1710, 285, 285, 285, 285, 251, 251, 285, 209, 209, 209, 209, 209, 209, 19, 99, 3, -18, + 30, '', 0, 40, 0, 1.49, 100, 100, 100), + (5, 58, 58, 6277, 0, 2349, 1740, 292, 292, 292, 292, 254, 254, 292, 211, 211, 211, 211, 211, 211, 19, 101, 3, + -18, 30, '', 0, 40, 0, 1.49, 100, 100, 100), + (5, 59, 59, 6483, 0, 2390, 1770, 298, 298, 298, 298, 257, 257, 298, 213, 213, 213, 213, 213, 213, 19, 102, 3, + -18, 30, '', 0, 40, 0, 1.49, 100, 100, 100), + (5, 60, 60, 6695, 0, 2430, 1800, 310, 310, 310, 310, 260, 260, 310, 220, 220, 220, 220, 220, 220, 20, 103, 3, + -18, 30, '', 0, 41, 0, 1.49, 100, 100, 100), + (5, 61, 61, 6912, 0, 2471, 1830, 316, 316, 316, 316, 263, 263, 316, 222, 222, 222, 222, 222, 222, 23, 120, 4, + -24, 27, '', 0, 41, 0, 1.49, 100, 100, 100), + (5, 62, 62, 7134, 0, 2511, 1860, 323, 323, 323, 323, 266, 266, 323, 224, 224, 224, 224, 224, 224, 26, 136, 4, + -25, 27, '', 0, 41, 0, 1.49, 100, 100, 100), + (5, 63, 63, 7362, 0, 2552, 1890, 329, 329, 329, 329, 269, 269, 329, 226, 226, 226, 226, 226, 226, 29, 153, 4, + -25, 27, '', 0, 42, 0, 1.49, 100, 100, 100), + (5, 64, 64, 7594, 0, 2592, 1920, 336, 336, 336, 336, 272, 272, 336, 233, 233, 233, 233, 233, 233, 33, 169, 4, + -26, 27, '', 0, 42, 0, 1.49, 100, 100, 100), + (5, 65, 65, 7833, 0, 2633, 1950, 343, 343, 343, 343, 275, 275, 343, 235, 235, 235, 235, 235, 235, 36, 185, 4, + -26, 27, '', 0, 42, 0, 1.49, 100, 100, 100), + (5, 66, 66, 8077, 0, 2673, 1980, 380, 380, 380, 380, 308, 308, 380, 237, 237, 237, 237, 237, 237, 39, 202, 4, + -27, 26, '', 0, 43, 0, 1.49, 100, 100, 100), + (5, 67, 67, 8326, 0, 2714, 2010, 392, 392, 392, 392, 316, 316, 392, 239, 239, 239, 239, 239, 239, 42, 218, 4, + -27, 26, '', 0, 43, 0, 1.49, 100, 100, 100), + (5, 68, 68, 8581, 0, 2754, 2040, 405, 405, 405, 405, 324, 324, 405, 246, 246, 246, 246, 246, 246, 46, 235, 4, + -28, 26, '', 0, 43, 0, 1.49, 100, 100, 100), + (5, 69, 69, 8842, 0, 2795, 2070, 417, 417, 417, 417, 332, 332, 417, 248, 248, 248, 248, 248, 248, 49, 251, 4, + -28, 26, '', 0, 44, 0, 1.49, 100, 100, 100), + (5, 70, 70, 9110, 0, 2835, 2100, 435, 435, 435, 435, 340, 340, 435, 250, 250, 250, 250, 250, 250, 52, 267, 4, + -29, 26, '', 0, 44, 0, 1.49, 100, 100, 100), + (5, 71, 71, 9383, 0, 2876, 2130, 447, 447, 447, 447, 348, 348, 447, 252, 252, 252, 252, 252, 252, 55, 284, 4, + -29, 26, '', 0, 44, 0, 1.49, 100, 100, 100), + (5, 72, 72, 9662, 0, 2916, 2160, 460, 460, 460, 460, 356, 356, 460, 259, 259, 259, 259, 259, 259, 59, 300, 4, + -30, 25, '', 0, 45, 0, 1.49, 100, 100, 100), + (5, 73, 73, 9947, 0, 2957, 2190, 472, 472, 472, 472, 364, 364, 472, 261, 261, 261, 261, 261, 261, 62, 317, 4, + -30, 25, '', 0, 45, 0, 1.49, 100, 100, 100), + (5, 74, 74, 10238, 0, 2997, 2220, 485, 485, 485, 485, 372, 372, 485, 263, 263, 263, 263, 263, 263, 65, 333, 4, + -31, 25, '', 0, 45, 0, 1.49, 100, 100, 100), + (5, 75, 75, 10536, 0, 3038, 2250, 498, 498, 498, 498, 380, 380, 498, 265, 265, 265, 265, 265, 265, 68, 349, 4, + -31, 25, '', 0, 46, 0, 1.49, 100, 100, 100), + (5, 76, 76, 10841, 0, 3078, 2280, 511, 511, 511, 511, 388, 388, 511, 272, 272, 272, 272, 272, 272, 72, 366, 4, + -32, 24, '', 0, 46, 0, 1.49, 100, 100, 100), + (5, 77, 77, 11151, 0, 3119, 2310, 524, 524, 524, 524, 396, 396, 524, 274, 274, 274, 274, 274, 274, 75, 382, 4, + -32, 24, '', 0, 46, 0, 1.49, 100, 100, 100), + (5, 78, 78, 11469, 0, 3159, 2340, 538, 538, 538, 538, 404, 404, 538, 276, 276, 276, 276, 276, 276, 78, 399, 4, + -33, 24, '', 0, 47, 0, 1.49, 100, 100, 100), + (5, 79, 79, 11793, 0, 3200, 2370, 551, 551, 551, 551, 412, 412, 551, 278, 278, 278, 278, 278, 278, 81, 415, 4, + -33, 24, '', 0, 47, 0, 1.49, 100, 100, 100), + (5, 80, 80, 12124, 0, 3240, 2400, 570, 570, 570, 570, 420, 420, 570, 285, 285, 285, 285, 285, 285, 85, 431, 4, + -34, 24, '', 0, 47, 0, 1.49, 100, 100, 100), + (5, 81, 81, 12462, 0, 3281, 2430, 583, 583, 583, 583, 428, 428, 583, 287, 287, 287, 287, 287, 287, 88, 448, 4, + -34, 24, '', 0, 48, 0, 1.49, 100, 100, 100), + (5, 82, 82, 12806, 0, 3321, 2460, 597, 597, 597, 597, 436, 436, 597, 289, 289, 289, 289, 289, 289, 91, 464, 4, + -35, 23, '', 0, 48, 0, 1.49, 100, 100, 100), + (5, 83, 83, 13158, 0, 3362, 2490, 610, 610, 610, 610, 444, 444, 610, 291, 291, 291, 291, 291, 291, 94, 481, 4, + -35, 23, '', 0, 48, 0, 1.49, 100, 100, 100), + (5, 84, 84, 13517, 0, 3402, 2520, 624, 624, 624, 624, 452, 452, 624, 298, 298, 298, 298, 298, 298, 98, 497, 4, + -36, 23, '', 0, 49, 0, 1.49, 100, 100, 100), + (5, 85, 85, 13883, 0, 3443, 2550, 638, 638, 638, 638, 460, 460, 638, 300, 300, 300, 300, 300, 300, 101, 513, 4, + -38, 22, '', 0, 49, 0, 1.49, 100, 100, 100), + (6, 1, 1, 85, 0, 43, 30, 71, 71, 71, 71, 95, 95, 71, 31, 31, 31, 31, 31, 31, 4, 17, 1, -18, 30, '', 0, 23, 0, + 1.25, 100, 100, 100), + (6, 2, 2, 160, 0, 85, 61, 73, 73, 73, 73, 98, 98, 73, 35, 35, 35, 35, 35, 35, 4, 18, 1, -18, 30, '', 0, 23, 0, + 1.25, 100, 100, 100), + (6, 3, 3, 235, 0, 128, 91, 73, 73, 73, 73, 101, 101, 73, 37, 37, 37, 37, 37, 37, 5, 19, 1, -18, 30, '', 0, 24, 0, + 1.25, 100, 100, 100), + (6, 4, 4, 310, 0, 170, 122, 75, 75, 75, 75, 104, 104, 75, 40, 40, 40, 40, 40, 40, 5, 21, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (6, 5, 5, 386, 0, 213, 152, 76, 76, 76, 76, 107, 107, 76, 44, 44, 44, 44, 44, 44, 5, 22, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (6, 6, 6, 463, 0, 255, 183, 78, 78, 78, 78, 110, 110, 78, 46, 46, 46, 46, 46, 46, 5, 24, 1, -18, 30, '', 0, 25, + 0, 1.25, 100, 100, 100), + (6, 7, 7, 539, 0, 298, 213, 79, 79, 79, 79, 113, 113, 79, 48, 48, 48, 48, 48, 48, 6, 25, 1, -18, 30, '', 0, 25, + 0, 1.25, 100, 100, 100), + (6, 8, 8, 617, 0, 340, 244, 82, 82, 82, 82, 116, 116, 82, 53, 53, 53, 53, 53, 53, 6, 26, 1, -18, 30, '', 0, 25, + 0, 1.25, 100, 100, 100), + (6, 9, 9, 695, 0, 383, 274, 83, 83, 83, 83, 119, 119, 83, 55, 55, 55, 55, 55, 55, 6, 28, 1, -18, 30, '', 0, 26, + 0, 1.25, 100, 100, 100), + (6, 10, 10, 774, 0, 425, 305, 87, 87, 87, 87, 122, 122, 87, 57, 57, 57, 57, 57, 57, 6, 29, 1, -18, 30, '', 0, 26, + 0, 1.25, 100, 100, 100), + (6, 11, 11, 854, 0, 468, 335, 88, 88, 88, 88, 125, 125, 88, 61, 61, 61, 61, 61, 61, 7, 31, 1, -18, 30, '', 0, 26, + 0, 1.25, 100, 100, 100), + (6, 12, 12, 934, 0, 510, 366, 91, 91, 91, 91, 128, 128, 91, 64, 64, 64, 64, 64, 64, 7, 32, 1, -18, 30, '', 0, 27, + 0, 1.25, 100, 100, 100), + (6, 13, 13, 1016, 0, 553, 396, 92, 92, 92, 92, 131, 131, 92, 66, 66, 66, 66, 66, 66, 7, 33, 1, -18, 30, '', 0, + 27, 0, 1.25, 100, 100, 100), + (6, 14, 14, 1099, 0, 595, 427, 95, 95, 95, 95, 134, 134, 95, 70, 70, 70, 70, 70, 70, 7, 35, 1, -18, 30, '', 0, + 27, 0, 1.25, 100, 100, 100), + (6, 15, 15, 1183, 0, 638, 457, 97, 97, 97, 97, 137, 137, 97, 72, 72, 72, 72, 72, 72, 8, 36, 1, -18, 30, '', 0, + 28, 0, 1.25, 100, 100, 100), + (6, 16, 16, 1268, 0, 680, 488, 100, 100, 100, 100, 140, 140, 100, 75, 75, 75, 75, 75, 75, 8, 38, 1, -18, 30, '', + 0, 28, 0, 1.25, 100, 100, 100), + (6, 17, 17, 1355, 0, 723, 518, 102, 102, 102, 102, 143, 143, 102, 79, 79, 79, 79, 79, 79, 8, 39, 2, -18, 30, '', + 0, 28, 0, 1.25, 100, 100, 100), + (6, 18, 18, 1443, 0, 765, 549, 106, 106, 106, 106, 146, 146, 106, 81, 81, 81, 81, 81, 81, 8, 40, 2, -18, 30, '', + 0, 29, 0, 1.25, 100, 100, 100), + (6, 19, 19, 1532, 0, 808, 579, 108, 108, 108, 108, 149, 149, 108, 83, 83, 83, 83, 83, 83, 9, 42, 2, -18, 30, '', + 0, 29, 0, 1.25, 100, 100, 100), + (6, 20, 20, 1624, 0, 850, 610, 113, 113, 113, 113, 152, 152, 113, 88, 88, 88, 88, 88, 88, 9, 43, 2, -18, 30, '', + 0, 29, 0, 1.25, 100, 100, 100), + (6, 21, 21, 1717, 0, 893, 640, 115, 115, 115, 115, 155, 155, 115, 90, 90, 90, 90, 90, 90, 9, 45, 2, -18, 30, '', + 0, 30, 0, 1.25, 100, 100, 100), + (6, 22, 22, 1812, 0, 935, 671, 119, 119, 119, 119, 158, 158, 119, 92, 92, 92, 92, 92, 92, 9, 46, 2, -18, 30, '', + 0, 30, 0, 1.25, 100, 100, 100), + (6, 23, 23, 1908, 0, 978, 701, 121, 121, 121, 121, 161, 161, 121, 96, 96, 96, 96, 96, 96, 10, 47, 2, -18, 30, '', + 0, 30, 0, 1.25, 100, 100, 100), + (6, 24, 24, 2007, 0, 1020, 732, 125, 125, 125, 125, 164, 164, 125, 99, 99, 99, 99, 99, 99, 10, 49, 2, -18, 30, + '', 0, 31, 0, 1.25, 100, 100, 100), + (6, 25, 25, 2108, 0, 1063, 762, 128, 128, 128, 128, 167, 167, 128, 101, 101, 101, 101, 101, 101, 10, 50, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (6, 26, 26, 2211, 0, 1105, 793, 132, 132, 132, 132, 170, 170, 132, 105, 105, 105, 105, 105, 105, 10, 52, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (6, 27, 27, 2316, 0, 1148, 823, 135, 135, 135, 135, 173, 173, 135, 107, 107, 107, 107, 107, 107, 11, 53, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (6, 28, 28, 2423, 0, 1190, 854, 140, 140, 140, 140, 176, 176, 140, 110, 110, 110, 110, 110, 110, 11, 54, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (6, 29, 29, 2533, 0, 1233, 884, 143, 143, 143, 143, 179, 179, 143, 114, 114, 114, 114, 114, 114, 11, 56, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (6, 30, 30, 2645, 0, 1275, 915, 149, 149, 149, 149, 182, 182, 149, 116, 116, 116, 116, 116, 116, 11, 57, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (6, 31, 31, 2760, 0, 1318, 945, 152, 152, 152, 152, 185, 185, 152, 118, 118, 118, 118, 118, 118, 12, 59, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (6, 32, 32, 2878, 0, 1360, 976, 157, 157, 157, 157, 188, 188, 157, 123, 123, 123, 123, 123, 123, 12, 60, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (6, 33, 33, 2998, 0, 1403, 1006, 160, 160, 160, 160, 191, 191, 160, 125, 125, 125, 125, 125, 125, 12, 61, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (6, 34, 34, 3121, 0, 1445, 1037, 165, 165, 165, 165, 194, 194, 165, 127, 127, 127, 127, 127, 127, 12, 63, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (6, 35, 35, 3247, 0, 1488, 1067, 169, 169, 169, 169, 197, 197, 169, 131, 131, 131, 131, 131, 131, 13, 64, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (6, 36, 36, 3376, 0, 1530, 1098, 174, 174, 174, 174, 200, 200, 174, 134, 134, 134, 134, 134, 134, 13, 66, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (6, 37, 37, 3508, 0, 1573, 1128, 178, 178, 178, 178, 203, 203, 178, 136, 136, 136, 136, 136, 136, 13, 67, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (6, 38, 38, 3643, 0, 1615, 1159, 184, 184, 184, 184, 206, 206, 184, 140, 140, 140, 140, 140, 140, 13, 68, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (6, 39, 39, 3782, 0, 1658, 1189, 188, 188, 188, 188, 209, 209, 188, 142, 142, 142, 142, 142, 142, 14, 70, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (6, 40, 40, 3924, 0, 1700, 1220, 195, 195, 195, 195, 212, 212, 195, 145, 145, 145, 145, 145, 145, 14, 71, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (6, 41, 41, 4069, 0, 1743, 1250, 199, 199, 199, 199, 215, 215, 199, 149, 149, 149, 149, 149, 149, 14, 73, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (6, 42, 42, 4218, 0, 1785, 1281, 205, 205, 205, 205, 218, 218, 205, 151, 151, 151, 151, 151, 151, 14, 74, 2, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (6, 43, 43, 4370, 0, 1828, 1311, 209, 209, 209, 209, 221, 221, 209, 153, 153, 153, 153, 153, 153, 15, 75, 2, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (6, 44, 44, 4526, 0, 1870, 1342, 215, 215, 215, 215, 224, 224, 215, 158, 158, 158, 158, 158, 158, 15, 77, 2, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (6, 45, 45, 4686, 0, 1913, 1372, 220, 220, 220, 220, 227, 227, 220, 160, 160, 160, 160, 160, 160, 15, 78, 2, -18, + 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (6, 46, 46, 4850, 0, 1955, 1403, 226, 226, 226, 226, 230, 230, 226, 162, 162, 162, 162, 162, 162, 15, 80, 2, -18, + 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (6, 47, 47, 5018, 0, 1998, 1433, 231, 231, 231, 231, 233, 233, 231, 166, 166, 166, 166, 166, 166, 16, 81, 3, -18, + 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (6, 48, 48, 5189, 0, 2040, 1464, 238, 238, 238, 238, 236, 236, 238, 169, 169, 169, 169, 169, 169, 16, 82, 3, -18, + 30, '', 0, 39, 0, 1.25, 100, 100, 100), + (6, 49, 49, 5365, 0, 2083, 1494, 243, 243, 243, 243, 239, 239, 243, 171, 171, 171, 171, 171, 171, 16, 84, 3, -18, + 30, '', 0, 39, 0, 1.25, 100, 100, 100), + (6, 50, 50, 5545, 0, 2125, 1525, 251, 251, 251, 251, 242, 242, 251, 175, 175, 175, 175, 175, 175, 16, 85, 3, -18, + 30, '', 0, 39, 0, 1.25, 100, 100, 100), + (6, 51, 51, 5730, 0, 2168, 1555, 256, 256, 256, 256, 245, 245, 256, 177, 177, 177, 177, 177, 177, 17, 87, 3, -18, + 30, '', 0, 40, 0, 1.25, 100, 100, 100), + (6, 52, 52, 5918, 0, 2210, 1586, 263, 263, 263, 263, 248, 248, 263, 180, 180, 180, 180, 180, 180, 17, 88, 3, -18, + 30, '', 0, 40, 0, 1.55, 100, 100, 100), + (6, 53, 53, 6111, 0, 2253, 1616, 268, 268, 268, 268, 251, 251, 268, 184, 184, 184, 184, 184, 184, 17, 89, 3, -18, + 30, '', 0, 40, 0, 1.55, 100, 100, 100), + (6, 54, 54, 6309, 0, 2295, 1647, 275, 275, 275, 275, 254, 254, 275, 186, 186, 186, 186, 186, 186, 17, 91, 3, -18, + 30, '', 0, 41, 0, 1.55, 100, 100, 100), + (6, 55, 55, 6511, 0, 2338, 1677, 281, 281, 281, 281, 257, 257, 281, 188, 188, 188, 188, 188, 188, 18, 92, 3, -18, + 30, '', 0, 41, 0, 1.55, 100, 100, 100), + (6, 56, 56, 6718, 0, 2380, 1708, 288, 288, 288, 288, 260, 260, 288, 193, 193, 193, 193, 193, 193, 18, 94, 3, -18, + 30, '', 0, 41, 0, 1.55, 100, 100, 100), + (6, 57, 57, 6930, 0, 2423, 1738, 294, 294, 294, 294, 263, 263, 294, 195, 195, 195, 195, 195, 195, 18, 95, 3, -18, + 30, '', 0, 42, 0, 1.55, 100, 100, 100), + (6, 58, 58, 7147, 0, 2465, 1769, 302, 302, 302, 302, 266, 266, 302, 197, 197, 197, 197, 197, 197, 18, 96, 3, -18, + 30, '', 0, 42, 0, 1.55, 100, 100, 100), + (6, 59, 59, 7368, 0, 2508, 1799, 308, 308, 308, 308, 269, 269, 308, 201, 201, 201, 201, 201, 201, 19, 98, 3, -18, + 30, '', 0, 42, 0, 1.55, 100, 100, 100), + (6, 60, 60, 7595, 0, 2550, 1830, 317, 317, 317, 317, 272, 272, 317, 204, 204, 204, 204, 204, 204, 19, 99, 3, -18, + 30, '', 0, 43, 0, 1.55, 100, 100, 100), + (6, 61, 61, 7827, 0, 2593, 1860, 323, 323, 323, 323, 275, 275, 323, 206, 206, 206, 206, 206, 206, 22, 116, 4, + -25, 27, '', 0, 43, 0, 1.55, 100, 100, 100), + (6, 62, 62, 8064, 0, 2635, 1891, 331, 331, 331, 331, 278, 278, 331, 210, 210, 210, 210, 210, 210, 25, 132, 4, + -26, 27, '', 0, 43, 0, 1.55, 100, 100, 100), + (6, 63, 63, 8307, 0, 2678, 1921, 337, 337, 337, 337, 281, 281, 337, 212, 212, 212, 212, 212, 212, 29, 148, 4, + -26, 27, '', 0, 44, 0, 1.55, 100, 100, 100), + (6, 64, 64, 8554, 0, 2720, 1952, 345, 345, 345, 345, 284, 284, 345, 215, 215, 215, 215, 215, 215, 32, 165, 4, + -27, 26, '', 0, 44, 0, 1.55, 100, 100, 100), + (6, 65, 65, 8808, 0, 2763, 1982, 352, 352, 352, 352, 287, 287, 352, 219, 219, 219, 219, 219, 219, 35, 181, 4, + -27, 26, '', 0, 44, 0, 1.55, 100, 100, 100), + (6, 66, 66, 9067, 0, 2805, 2013, 390, 390, 390, 390, 320, 320, 390, 221, 221, 221, 221, 221, 221, 38, 198, 4, + -28, 26, '', 0, 45, 0, 1.55, 100, 100, 100), + (6, 67, 67, 9331, 0, 2848, 2043, 402, 402, 402, 402, 328, 328, 402, 223, 223, 223, 223, 223, 223, 42, 214, 4, + -28, 26, '', 0, 45, 0, 1.55, 100, 100, 100), + (6, 68, 68, 9601, 0, 2890, 2074, 416, 416, 416, 416, 336, 336, 416, 228, 228, 228, 228, 228, 228, 45, 230, 4, + -29, 26, '', 0, 45, 0, 1.55, 100, 100, 100), + (6, 69, 69, 9877, 0, 2933, 2104, 428, 428, 428, 428, 344, 344, 428, 230, 230, 230, 230, 230, 230, 48, 247, 4, + -29, 26, '', 0, 46, 0, 1.55, 100, 100, 100), + (6, 70, 70, 10160, 0, 2975, 2135, 443, 443, 443, 443, 352, 352, 443, 232, 232, 232, 232, 232, 232, 51, 263, 4, + -30, 25, '', 0, 46, 0, 1.55, 100, 100, 100), + (6, 71, 71, 10448, 0, 3018, 2165, 455, 455, 455, 455, 360, 360, 455, 236, 236, 236, 236, 236, 236, 55, 280, 4, + -30, 25, '', 0, 46, 0, 1.55, 100, 100, 100), + (6, 72, 72, 10742, 0, 3060, 2196, 469, 469, 469, 469, 368, 368, 469, 239, 239, 239, 239, 239, 239, 58, 296, 4, + -31, 25, '', 0, 47, 0, 1.55, 100, 100, 100), + (6, 73, 73, 11042, 0, 3103, 2226, 481, 481, 481, 481, 376, 376, 481, 241, 241, 241, 241, 241, 241, 61, 312, 4, + -31, 25, '', 0, 47, 0, 1.55, 100, 100, 100), + (6, 74, 74, 11348, 0, 3145, 2257, 495, 495, 495, 495, 384, 384, 495, 245, 245, 245, 245, 245, 245, 64, 329, 4, + -32, 24, '', 0, 47, 0, 1.55, 100, 100, 100), + (6, 75, 75, 11661, 0, 3188, 2287, 508, 508, 508, 508, 392, 392, 508, 247, 247, 247, 247, 247, 247, 68, 345, 4, + -32, 24, '', 0, 48, 0, 1.55, 100, 100, 100), + (6, 76, 76, 11981, 0, 3230, 2318, 522, 522, 522, 522, 400, 400, 522, 250, 250, 250, 250, 250, 250, 71, 362, 4, + -33, 24, '', 0, 48, 0, 1.55, 100, 100, 100), + (6, 77, 77, 12306, 0, 3273, 2348, 535, 535, 535, 535, 408, 408, 535, 254, 254, 254, 254, 254, 254, 74, 378, 4, + -33, 24, '', 0, 48, 0, 1.55, 100, 100, 100), + (6, 78, 78, 12639, 0, 3315, 2379, 550, 550, 550, 550, 416, 416, 550, 256, 256, 256, 256, 256, 256, 77, 394, 4, + -34, 24, '', 0, 49, 0, 1.55, 100, 100, 100), + (6, 79, 79, 12978, 0, 3358, 2409, 563, 563, 563, 563, 424, 424, 563, 258, 258, 258, 258, 258, 258, 81, 411, 4, + -34, 24, '', 0, 49, 0, 1.55, 100, 100, 100), + (6, 80, 80, 13324, 0, 3400, 2440, 579, 579, 579, 579, 432, 432, 579, 263, 263, 263, 263, 263, 263, 84, 427, 4, + -35, 23, '', 0, 49, 0, 1.55, 100, 100, 100), + (6, 81, 81, 13677, 0, 3443, 2470, 592, 592, 592, 592, 440, 440, 592, 265, 265, 265, 265, 265, 265, 87, 444, 4, + -35, 23, '', 0, 50, 0, 1.55, 100, 100, 100), + (6, 82, 82, 14036, 0, 3485, 2501, 607, 607, 607, 607, 448, 448, 607, 267, 267, 267, 267, 267, 267, 90, 460, 4, + -36, 23, '', 0, 50, 0, 1.55, 100, 100, 100), + (6, 83, 83, 14403, 0, 3528, 2531, 620, 620, 620, 620, 456, 456, 620, 271, 271, 271, 271, 271, 271, 94, 476, 4, + -36, 23, '', 0, 50, 0, 1.55, 100, 100, 100), + (6, 84, 84, 14777, 0, 3570, 2562, 635, 635, 635, 635, 464, 464, 635, 274, 274, 274, 274, 274, 274, 97, 493, 4, + -37, 23, '', 0, 51, 0, 1.55, 100, 100, 100), + (6, 85, 85, 15158, 0, 3613, 2592, 649, 649, 649, 649, 472, 472, 649, 276, 276, 276, 276, 276, 276, 100, 509, 4, + -39, 22, '', 0, 51, 0, 1.55, 100, 100, 100), + (7, 1, 1, 90, 0, 44, 31, 72, 72, 72, 72, 97, 97, 72, 34, 34, 34, 34, 34, 34, 5, 19, 1, -18, 30, '', 0, 25, 0, + 1.25, 100, 100, 100), + (7, 2, 2, 170, 0, 88, 62, 74, 74, 74, 74, 100, 100, 74, 38, 38, 38, 38, 38, 38, 5, 21, 1, -18, 30, '', 0, 25, 0, + 1.25, 100, 100, 100), + (7, 3, 3, 250, 0, 132, 93, 74, 74, 74, 74, 103, 103, 74, 40, 40, 40, 40, 40, 40, 5, 22, 1, -18, 30, '', 0, 26, 0, + 1.25, 100, 100, 100), + (7, 4, 4, 330, 0, 176, 124, 76, 76, 76, 76, 106, 106, 76, 44, 44, 44, 44, 44, 44, 5, 24, 1, -18, 30, '', 0, 26, + 0, 1.25, 100, 100, 100), + (7, 5, 5, 411, 0, 220, 155, 77, 77, 77, 77, 109, 109, 77, 48, 48, 48, 48, 48, 48, 6, 25, 1, -18, 30, '', 0, 26, + 0, 1.25, 100, 100, 100), + (7, 6, 6, 493, 0, 264, 186, 79, 79, 79, 79, 112, 112, 79, 50, 50, 50, 50, 50, 50, 6, 26, 1, -18, 30, '', 0, 27, + 0, 1.25, 100, 100, 100), + (7, 7, 7, 574, 0, 308, 217, 80, 80, 80, 80, 115, 115, 80, 52, 52, 52, 52, 52, 52, 6, 28, 1, -18, 30, '', 0, 27, + 0, 1.25, 100, 100, 100), + (7, 8, 8, 657, 0, 352, 248, 83, 83, 83, 83, 118, 118, 83, 58, 58, 58, 58, 58, 58, 6, 29, 1, -18, 30, '', 0, 27, + 0, 1.25, 100, 100, 100), + (7, 9, 9, 740, 0, 396, 279, 84, 84, 84, 84, 121, 121, 84, 60, 60, 60, 60, 60, 60, 7, 31, 1, -18, 30, '', 0, 28, + 0, 1.25, 100, 100, 100), + (7, 10, 10, 824, 0, 440, 310, 89, 89, 89, 89, 124, 124, 89, 62, 62, 62, 62, 62, 62, 7, 32, 1, -18, 30, '', 0, 28, + 0, 1.25, 100, 100, 100), + (7, 11, 11, 909, 0, 484, 341, 90, 90, 90, 90, 127, 127, 90, 66, 66, 66, 66, 66, 66, 7, 33, 1, -18, 30, '', 0, 28, + 0, 1.25, 100, 100, 100), + (7, 12, 12, 994, 0, 528, 372, 93, 93, 93, 93, 130, 130, 93, 70, 70, 70, 70, 70, 70, 7, 35, 1, -18, 30, '', 0, 29, + 0, 1.25, 100, 100, 100), + (7, 13, 13, 1081, 0, 572, 403, 94, 94, 94, 94, 133, 133, 94, 72, 72, 72, 72, 72, 72, 8, 36, 1, -18, 30, '', 0, + 29, 0, 1.25, 100, 100, 100), + (7, 14, 14, 1169, 0, 616, 434, 97, 97, 97, 97, 136, 136, 97, 76, 76, 76, 76, 76, 76, 8, 38, 1, -18, 30, '', 0, + 29, 0, 1.25, 100, 100, 100), + (7, 15, 15, 1258, 0, 660, 465, 99, 99, 99, 99, 139, 139, 99, 78, 78, 78, 78, 78, 78, 8, 39, 1, -18, 30, '', 0, + 30, 0, 1.25, 100, 100, 100), + (7, 16, 16, 1348, 0, 704, 496, 102, 102, 102, 102, 142, 142, 102, 82, 82, 82, 82, 82, 82, 8, 40, 1, -18, 30, '', + 0, 30, 0, 1.25, 100, 100, 100), + (7, 17, 17, 1440, 0, 748, 527, 104, 104, 104, 104, 145, 145, 104, 86, 86, 86, 86, 86, 86, 9, 42, 2, -18, 30, '', + 0, 30, 0, 1.25, 100, 100, 100), + (7, 18, 18, 1533, 0, 792, 558, 108, 108, 108, 108, 148, 148, 108, 88, 88, 88, 88, 88, 88, 9, 43, 2, -18, 30, '', + 0, 31, 0, 1.25, 100, 100, 100), + (7, 19, 19, 1627, 0, 836, 589, 110, 110, 110, 110, 151, 151, 110, 90, 90, 90, 90, 90, 90, 9, 45, 2, -18, 30, '', + 0, 31, 0, 1.25, 100, 100, 100), + (7, 20, 20, 1724, 0, 880, 620, 116, 116, 116, 116, 154, 154, 116, 96, 96, 96, 96, 96, 96, 9, 46, 2, -18, 30, '', + 0, 31, 0, 1.25, 100, 100, 100), + (7, 21, 21, 1822, 0, 924, 651, 118, 118, 118, 118, 157, 157, 118, 98, 98, 98, 98, 98, 98, 10, 47, 2, -18, 30, '', + 0, 32, 0, 1.25, 100, 100, 100), + (7, 22, 22, 1922, 0, 968, 682, 122, 122, 122, 122, 160, 160, 122, 100, 100, 100, 100, 100, 100, 10, 49, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (7, 23, 23, 2023, 0, 1012, 713, 124, 124, 124, 124, 163, 163, 124, 104, 104, 104, 104, 104, 104, 10, 50, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (7, 24, 24, 2127, 0, 1056, 744, 128, 128, 128, 128, 166, 166, 128, 108, 108, 108, 108, 108, 108, 10, 52, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (7, 25, 25, 2233, 0, 1100, 775, 131, 131, 131, 131, 169, 169, 131, 110, 110, 110, 110, 110, 110, 11, 53, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (7, 26, 26, 2341, 0, 1144, 806, 135, 135, 135, 135, 172, 172, 135, 114, 114, 114, 114, 114, 114, 11, 54, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (7, 27, 27, 2451, 0, 1188, 837, 138, 138, 138, 138, 175, 175, 138, 116, 116, 116, 116, 116, 116, 11, 56, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (7, 28, 28, 2563, 0, 1232, 868, 143, 143, 143, 143, 178, 178, 143, 120, 120, 120, 120, 120, 120, 11, 57, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (7, 29, 29, 2678, 0, 1276, 899, 146, 146, 146, 146, 181, 181, 146, 124, 124, 124, 124, 124, 124, 12, 59, 2, -18, + 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (7, 30, 30, 2795, 0, 1320, 930, 153, 153, 153, 153, 184, 184, 153, 126, 126, 126, 126, 126, 126, 12, 60, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (7, 31, 31, 2915, 0, 1364, 961, 156, 156, 156, 156, 187, 187, 156, 128, 128, 128, 128, 128, 128, 12, 61, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (7, 32, 32, 3038, 0, 1408, 992, 161, 161, 161, 161, 190, 190, 161, 134, 134, 134, 134, 134, 134, 12, 63, 2, -18, + 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (7, 33, 33, 3163, 0, 1452, 1023, 164, 164, 164, 164, 193, 193, 164, 136, 136, 136, 136, 136, 136, 13, 64, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (7, 34, 34, 3291, 0, 1496, 1054, 169, 169, 169, 169, 196, 196, 169, 138, 138, 138, 138, 138, 138, 13, 66, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (7, 35, 35, 3422, 0, 1540, 1085, 173, 173, 173, 173, 199, 199, 173, 142, 142, 142, 142, 142, 142, 13, 67, 2, -18, + 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (7, 36, 36, 3556, 0, 1584, 1116, 178, 178, 178, 178, 202, 202, 178, 146, 146, 146, 146, 146, 146, 13, 68, 2, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (7, 37, 37, 3693, 0, 1628, 1147, 182, 182, 182, 182, 205, 205, 182, 148, 148, 148, 148, 148, 148, 14, 70, 2, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (7, 38, 38, 3833, 0, 1672, 1178, 188, 188, 188, 188, 208, 208, 188, 152, 152, 152, 152, 152, 152, 14, 71, 2, -18, + 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (7, 39, 39, 3977, 0, 1716, 1209, 192, 192, 192, 192, 211, 211, 192, 154, 154, 154, 154, 154, 154, 14, 73, 2, -18, + 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (7, 40, 40, 4124, 0, 1760, 1240, 200, 200, 200, 200, 214, 214, 200, 158, 158, 158, 158, 158, 158, 14, 74, 2, -18, + 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (7, 41, 41, 4274, 0, 1804, 1271, 204, 204, 204, 204, 217, 217, 204, 162, 162, 162, 162, 162, 162, 15, 75, 2, -18, + 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (7, 42, 42, 4428, 0, 1848, 1302, 210, 210, 210, 210, 220, 220, 210, 164, 164, 164, 164, 164, 164, 15, 77, 2, -18, + 30, '', 0, 39, 0, 1.25, 100, 100, 100), + (7, 43, 43, 4585, 0, 1892, 1333, 214, 214, 214, 214, 223, 223, 214, 166, 166, 166, 166, 166, 166, 15, 78, 2, -18, + 30, '', 0, 39, 0, 1.25, 100, 100, 100), + (7, 44, 44, 4746, 0, 1936, 1364, 220, 220, 220, 220, 226, 226, 220, 172, 172, 172, 172, 172, 172, 15, 80, 2, -18, + 30, '', 0, 39, 0, 1.25, 100, 100, 100), + (7, 45, 45, 4911, 0, 1980, 1395, 225, 225, 225, 225, 229, 229, 225, 174, 174, 174, 174, 174, 174, 16, 81, 2, -18, + 30, '', 0, 40, 0, 1.25, 100, 100, 100), + (7, 46, 46, 5080, 0, 2024, 1426, 231, 231, 231, 231, 232, 232, 231, 176, 176, 176, 176, 176, 176, 16, 82, 2, -18, + 30, '', 0, 40, 0, 1.25, 100, 100, 100), + (7, 47, 47, 5253, 0, 2068, 1457, 236, 236, 236, 236, 235, 235, 236, 180, 180, 180, 180, 180, 180, 16, 84, 3, -18, + 30, '', 0, 40, 0, 1.25, 100, 100, 100), + (7, 48, 48, 5429, 0, 2112, 1488, 243, 243, 243, 243, 238, 238, 243, 184, 184, 184, 184, 184, 184, 16, 85, 3, -18, + 30, '', 0, 41, 0, 1.25, 100, 100, 100), + (7, 49, 49, 5610, 0, 2156, 1519, 248, 248, 248, 248, 241, 241, 248, 186, 186, 186, 186, 186, 186, 17, 87, 3, -18, + 30, '', 0, 41, 0, 1.25, 100, 100, 100), + (7, 50, 50, 5795, 0, 2200, 1550, 257, 257, 257, 257, 244, 244, 257, 190, 190, 190, 190, 190, 190, 17, 88, 3, -18, + 30, '', 0, 41, 0, 1.25, 100, 100, 100), + (7, 51, 51, 5985, 0, 2244, 1581, 262, 262, 262, 262, 247, 247, 262, 192, 192, 192, 192, 192, 192, 17, 89, 3, -18, + 30, '', 0, 42, 0, 1.25, 100, 100, 100), + (7, 52, 52, 6178, 0, 2288, 1612, 269, 269, 269, 269, 250, 250, 269, 196, 196, 196, 196, 196, 196, 17, 91, 3, -18, + 30, '', 0, 42, 0, 1.61, 100, 100, 100), + (7, 53, 53, 6376, 0, 2332, 1643, 274, 274, 274, 274, 253, 253, 274, 200, 200, 200, 200, 200, 200, 18, 92, 3, -18, + 30, '', 0, 42, 0, 1.61, 100, 100, 100), + (7, 54, 54, 6579, 0, 2376, 1674, 281, 281, 281, 281, 256, 256, 281, 202, 202, 202, 202, 202, 202, 18, 94, 3, -18, + 30, '', 0, 43, 0, 1.61, 100, 100, 100), + (7, 55, 55, 6786, 0, 2420, 1705, 287, 287, 287, 287, 259, 259, 287, 204, 204, 204, 204, 204, 204, 18, 95, 3, -18, + 30, '', 0, 43, 0, 1.61, 100, 100, 100), + (7, 56, 56, 6998, 0, 2464, 1736, 294, 294, 294, 294, 262, 262, 294, 210, 210, 210, 210, 210, 210, 18, 96, 3, -18, + 30, '', 0, 43, 0, 1.61, 100, 100, 100), + (7, 57, 57, 7215, 0, 2508, 1767, 300, 300, 300, 300, 265, 265, 300, 212, 212, 212, 212, 212, 212, 19, 98, 3, -18, + 30, '', 0, 44, 0, 1.61, 100, 100, 100), + (7, 58, 58, 7437, 0, 2552, 1798, 308, 308, 308, 308, 268, 268, 308, 214, 214, 214, 214, 214, 214, 19, 99, 3, -18, + 30, '', 0, 44, 0, 1.61, 100, 100, 100), + (7, 59, 59, 7663, 0, 2596, 1829, 314, 314, 314, 314, 271, 271, 314, 218, 218, 218, 218, 218, 218, 19, 101, 3, + -18, 30, '', 0, 44, 0, 1.61, 100, 100, 100), + (7, 60, 60, 7895, 0, 2640, 1860, 324, 324, 324, 324, 274, 274, 324, 222, 222, 222, 222, 222, 222, 19, 102, 3, + -18, 30, '', 0, 45, 0, 1.61, 100, 100, 100), + (7, 61, 61, 8132, 0, 2684, 1891, 330, 330, 330, 330, 277, 277, 330, 224, 224, 224, 224, 224, 224, 23, 118, 4, + -26, 27, '', 0, 45, 0, 1.61, 100, 100, 100), + (7, 62, 62, 8374, 0, 2728, 1922, 338, 338, 338, 338, 280, 280, 338, 228, 228, 228, 228, 228, 228, 26, 135, 4, + -27, 26, '', 0, 45, 0, 1.61, 100, 100, 100), + (7, 63, 63, 8622, 0, 2772, 1953, 344, 344, 344, 344, 283, 283, 344, 230, 230, 230, 230, 230, 230, 29, 151, 4, + -27, 26, '', 0, 46, 0, 1.61, 100, 100, 100), + (7, 64, 64, 8874, 0, 2816, 1984, 352, 352, 352, 352, 286, 286, 352, 234, 234, 234, 234, 234, 234, 32, 168, 4, + -28, 26, '', 0, 46, 0, 1.61, 100, 100, 100), + (7, 65, 65, 9133, 0, 2860, 2015, 359, 359, 359, 359, 289, 289, 359, 238, 238, 238, 238, 238, 238, 36, 184, 4, + -28, 26, '', 0, 46, 0, 1.61, 100, 100, 100), + (7, 66, 66, 9397, 0, 2904, 2046, 397, 397, 397, 397, 322, 322, 397, 240, 240, 240, 240, 240, 240, 39, 200, 4, + -29, 26, '', 0, 47, 0, 1.61, 100, 100, 100), + (7, 67, 67, 9666, 0, 2948, 2077, 409, 409, 409, 409, 330, 330, 409, 242, 242, 242, 242, 242, 242, 42, 217, 4, + -29, 26, '', 0, 47, 0, 1.61, 100, 100, 100), + (7, 68, 68, 9941, 0, 2992, 2108, 423, 423, 423, 423, 338, 338, 423, 248, 248, 248, 248, 248, 248, 45, 233, 4, + -30, 25, '', 0, 47, 0, 1.61, 100, 100, 100), + (7, 69, 69, 10222, 0, 3036, 2139, 435, 435, 435, 435, 346, 346, 435, 250, 250, 250, 250, 250, 250, 49, 250, 4, + -30, 25, '', 0, 48, 0, 1.61, 100, 100, 100), + (7, 70, 70, 10510, 0, 3080, 2170, 451, 451, 451, 451, 354, 354, 451, 252, 252, 252, 252, 252, 252, 52, 266, 4, + -31, 25, '', 0, 48, 0, 1.61, 100, 100, 100), + (7, 71, 71, 10803, 0, 3124, 2201, 463, 463, 463, 463, 362, 362, 463, 256, 256, 256, 256, 256, 256, 55, 282, 4, + -31, 25, '', 0, 48, 0, 1.61, 100, 100, 100), + (7, 72, 72, 11102, 0, 3168, 2232, 477, 477, 477, 477, 370, 370, 477, 260, 260, 260, 260, 260, 260, 58, 299, 4, + -32, 24, '', 0, 49, 0, 1.61, 100, 100, 100), + (7, 73, 73, 11407, 0, 3212, 2263, 489, 489, 489, 489, 378, 378, 489, 262, 262, 262, 262, 262, 262, 62, 315, 4, + -32, 24, '', 0, 49, 0, 1.61, 100, 100, 100), + (7, 74, 74, 11718, 0, 3256, 2294, 503, 503, 503, 503, 386, 386, 503, 266, 266, 266, 266, 266, 266, 65, 332, 4, + -33, 24, '', 0, 49, 0, 1.61, 100, 100, 100), + (7, 75, 75, 12036, 0, 3300, 2325, 516, 516, 516, 516, 394, 394, 516, 268, 268, 268, 268, 268, 268, 68, 348, 4, + -33, 24, '', 0, 50, 0, 1.61, 100, 100, 100), + (7, 76, 76, 12361, 0, 3344, 2356, 530, 530, 530, 530, 402, 402, 530, 272, 272, 272, 272, 272, 272, 71, 364, 4, + -34, 24, '', 0, 50, 0, 1.61, 100, 100, 100), + (7, 77, 77, 12691, 0, 3388, 2387, 543, 543, 543, 543, 410, 410, 543, 276, 276, 276, 276, 276, 276, 75, 381, 4, + -34, 24, '', 0, 50, 0, 1.61, 100, 100, 100), + (7, 78, 78, 13029, 0, 3432, 2418, 558, 558, 558, 558, 418, 418, 558, 278, 278, 278, 278, 278, 278, 78, 397, 4, + -35, 23, '', 0, 51, 0, 1.61, 100, 100, 100), + (7, 79, 79, 13373, 0, 3476, 2449, 571, 571, 571, 571, 426, 426, 571, 280, 280, 280, 280, 280, 280, 81, 414, 4, + -35, 23, '', 0, 51, 0, 1.61, 100, 100, 100), + (7, 80, 80, 13724, 0, 3520, 2480, 588, 588, 588, 588, 434, 434, 588, 286, 286, 286, 286, 286, 286, 84, 430, 4, + -36, 23, '', 0, 51, 0, 1.61, 100, 100, 100), + (7, 81, 81, 14082, 0, 3564, 2511, 601, 601, 601, 601, 442, 442, 601, 288, 288, 288, 288, 288, 288, 88, 446, 4, + -36, 23, '', 0, 52, 0, 1.61, 100, 100, 100), + (7, 82, 82, 14446, 0, 3608, 2542, 616, 616, 616, 616, 450, 450, 616, 290, 290, 290, 290, 290, 290, 91, 463, 4, + -37, 23, '', 0, 52, 0, 1.61, 100, 100, 100), + (7, 83, 83, 14818, 0, 3652, 2573, 629, 629, 629, 629, 458, 458, 629, 294, 294, 294, 294, 294, 294, 94, 479, 4, + -37, 23, '', 0, 52, 0, 1.61, 100, 100, 100), + (7, 84, 84, 15197, 0, 3696, 2604, 644, 644, 644, 644, 466, 466, 644, 298, 298, 298, 298, 298, 298, 97, 496, 4, + -38, 22, '', 0, 53, 0, 1.61, 100, 100, 100), + (7, 85, 85, 15583, 0, 3740, 2635, 658, 658, 658, 658, 474, 474, 658, 300, 300, 300, 300, 300, 300, 101, 512, 4, + -40, 22, '', 0, 53, 0, 1.61, 100, 100, 100), + (11, 1, 1, 43, 29, 27, 17, 56, 56, 56, 56, 106, 106, 56, 15, 15, 15, 15, 15, 15, 1, 8, 1, -18, 30, '', 0, 8, 5, + 1.25, 100, 100, 100), + (11, 2, 2, 76, 59, 54, 33, 57, 57, 57, 57, 110, 110, 57, 17, 17, 17, 17, 17, 17, 1, 10, 1, -18, 30, '', 0, 8, 5, + 1.25, 100, 100, 100), + (11, 3, 3, 109, 91, 81, 51, 57, 57, 57, 57, 113, 113, 57, 19, 19, 19, 19, 19, 19, 2, 11, 1, -18, 30, '', 0, 8, 5, + 1.25, 100, 100, 100), + (11, 4, 4, 142, 125, 108, 67, 58, 58, 58, 58, 117, 117, 58, 22, 22, 22, 22, 22, 22, 2, 13, 1, -18, 30, '', 0, 9, + 5, 1.25, 100, 100, 100), + (11, 5, 5, 176, 160, 135, 84, 59, 59, 59, 59, 120, 120, 59, 24, 24, 24, 24, 24, 24, 2, 14, 1, -18, 30, '', 0, 9, + 6, 1.25, 100, 100, 100), + (11, 6, 6, 210, 197, 162, 101, 60, 60, 60, 60, 124, 124, 60, 26, 26, 26, 26, 26, 26, 2, 15, 1, -18, 30, '', 0, 9, + 6, 1.25, 100, 100, 100), + (11, 7, 7, 245, 235, 189, 118, 61, 61, 61, 61, 127, 127, 61, 28, 28, 28, 28, 28, 28, 3, 17, 1, -18, 30, '', 0, 9, + 6, 1.25, 100, 100, 100), + (11, 8, 8, 280, 275, 216, 134, 62, 62, 62, 62, 131, 131, 62, 31, 31, 31, 31, 31, 31, 3, 18, 1, -18, 30, '', 0, + 10, 6, 1.25, 100, 100, 100), + (11, 9, 9, 315, 317, 243, 152, 63, 63, 63, 63, 134, 134, 63, 33, 33, 33, 33, 33, 33, 3, 20, 1, -18, 30, '', 0, + 10, 6, 1.25, 100, 100, 100), + (11, 10, 10, 351, 360, 270, 168, 66, 66, 66, 66, 138, 138, 66, 35, 35, 35, 35, 35, 35, 3, 21, 1, -18, 30, '', 0, + 10, 7, 1.25, 100, 100, 100), + (11, 11, 11, 388, 405, 297, 185, 67, 67, 67, 67, 141, 141, 67, 37, 37, 37, 37, 37, 37, 4, 22, 1, -18, 30, '', 0, + 10, 7, 1.25, 100, 100, 100), + (11, 12, 12, 426, 451, 324, 202, 69, 69, 69, 69, 145, 145, 69, 40, 40, 40, 40, 40, 40, 4, 24, 1, -18, 30, '', 0, + 11, 7, 1.25, 100, 100, 100), + (11, 13, 13, 464, 499, 351, 219, 70, 70, 70, 70, 148, 148, 70, 42, 42, 42, 42, 42, 42, 4, 25, 1, -18, 30, '', 0, + 11, 7, 1.25, 100, 100, 100), + (11, 14, 14, 504, 549, 378, 235, 72, 72, 72, 72, 152, 152, 72, 44, 44, 44, 44, 44, 44, 4, 27, 1, -18, 30, '', 0, + 11, 7, 1.25, 100, 100, 100), + (11, 15, 15, 544, 600, 405, 253, 74, 74, 74, 74, 155, 155, 74, 46, 46, 46, 46, 46, 46, 5, 28, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (11, 16, 16, 586, 653, 432, 269, 76, 76, 76, 76, 159, 159, 76, 49, 49, 49, 49, 49, 49, 5, 29, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (11, 17, 17, 628, 707, 459, 286, 78, 78, 78, 78, 162, 162, 78, 51, 51, 51, 51, 51, 51, 5, 31, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (11, 18, 18, 672, 763, 486, 303, 80, 80, 80, 80, 166, 166, 80, 53, 53, 53, 53, 53, 53, 5, 32, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (11, 19, 19, 717, 821, 513, 320, 82, 82, 82, 82, 169, 169, 82, 55, 55, 55, 55, 55, 55, 6, 34, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (11, 20, 20, 764, 880, 540, 336, 86, 86, 86, 86, 173, 173, 86, 58, 58, 58, 58, 58, 58, 6, 35, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (11, 21, 21, 811, 941, 567, 354, 88, 88, 88, 88, 176, 176, 88, 60, 60, 60, 60, 60, 60, 6, 36, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (11, 22, 22, 861, 1003, 594, 370, 91, 91, 91, 91, 180, 180, 91, 62, 62, 62, 62, 62, 62, 6, 38, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (11, 23, 23, 912, 1067, 621, 387, 93, 93, 93, 93, 183, 183, 93, 64, 64, 64, 64, 64, 64, 7, 39, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (11, 24, 24, 964, 1133, 648, 404, 96, 96, 96, 96, 187, 187, 96, 67, 67, 67, 67, 67, 67, 7, 41, 1, -18, 30, '', 0, + 14, 9, 1.25, 100, 100, 100), + (11, 25, 25, 1018, 1200, 675, 421, 98, 98, 98, 98, 190, 190, 98, 69, 69, 69, 69, 69, 69, 7, 42, 1, -18, 30, '', + 0, 14, 10, 1.25, 100, 100, 100), + (11, 26, 26, 1074, 1269, 702, 437, 101, 101, 101, 101, 194, 194, 101, 71, 71, 71, 71, 71, 71, 7, 43, 1, -18, 30, + '', 0, 14, 10, 1.25, 100, 100, 100), + (11, 27, 27, 1132, 1339, 729, 455, 104, 104, 104, 104, 197, 197, 104, 73, 73, 73, 73, 73, 73, 8, 45, 1, -18, 30, + '', 0, 14, 10, 1.25, 100, 100, 100), + (11, 28, 28, 1192, 1411, 756, 471, 107, 107, 107, 107, 201, 201, 107, 76, 76, 76, 76, 76, 76, 8, 46, 1, -18, 30, + '', 0, 15, 10, 1.25, 100, 100, 100), + (11, 29, 29, 1253, 1485, 783, 488, 110, 110, 110, 110, 204, 204, 110, 78, 78, 78, 78, 78, 78, 8, 48, 1, -18, 30, + '', 0, 15, 10, 1.25, 100, 100, 100), + (11, 30, 30, 1317, 1560, 810, 505, 114, 114, 114, 114, 208, 208, 114, 80, 80, 80, 80, 80, 80, 8, 49, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (11, 31, 31, 1383, 1637, 837, 522, 117, 117, 117, 117, 211, 211, 117, 82, 82, 82, 82, 82, 82, 9, 50, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (11, 32, 32, 1451, 1715, 864, 538, 121, 121, 121, 121, 215, 215, 121, 85, 85, 85, 85, 85, 85, 9, 52, 1, -18, 30, + '', 0, 16, 11, 1.25, 100, 100, 100), + (11, 33, 33, 1521, 1795, 891, 556, 124, 124, 124, 124, 218, 218, 124, 87, 87, 87, 87, 87, 87, 9, 53, 1, -18, 30, + '', 0, 16, 11, 1.25, 100, 100, 100), + (11, 34, 34, 1594, 1877, 918, 572, 128, 128, 128, 128, 222, 222, 128, 89, 89, 89, 89, 89, 89, 9, 55, 1, -18, 30, + '', 0, 16, 11, 1.25, 100, 100, 100), + (11, 35, 35, 1669, 1960, 945, 589, 131, 131, 131, 131, 225, 225, 131, 91, 91, 91, 91, 91, 91, 10, 56, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (11, 36, 36, 1746, 2045, 972, 606, 135, 135, 135, 135, 229, 229, 135, 94, 94, 94, 94, 94, 94, 10, 57, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (11, 37, 37, 1826, 2131, 999, 623, 139, 139, 139, 139, 232, 232, 139, 96, 96, 96, 96, 96, 96, 10, 59, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (11, 38, 38, 1909, 2219, 1026, 639, 143, 143, 143, 143, 236, 236, 143, 98, 98, 98, 98, 98, 98, 10, 60, 1, -18, + 30, '', 0, 17, 12, 1.25, 100, 100, 100), + (11, 39, 39, 1994, 2309, 1053, 657, 147, 147, 147, 147, 239, 239, 147, 100, 100, 100, 100, 100, 100, 11, 62, 1, + -18, 30, '', 0, 17, 12, 1.25, 100, 100, 100), + (11, 40, 40, 2082, 2400, 1080, 673, 152, 152, 152, 152, 243, 243, 152, 103, 103, 103, 103, 103, 103, 11, 63, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (11, 41, 41, 2173, 2493, 1107, 690, 156, 156, 156, 156, 246, 246, 156, 105, 105, 105, 105, 105, 105, 11, 64, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (11, 42, 42, 2267, 2587, 1134, 707, 161, 161, 161, 161, 250, 250, 161, 107, 107, 107, 107, 107, 107, 11, 66, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (11, 43, 43, 2364, 2683, 1161, 724, 165, 165, 165, 165, 253, 253, 165, 109, 109, 109, 109, 109, 109, 12, 67, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (11, 44, 44, 2464, 2781, 1188, 740, 170, 170, 170, 170, 257, 257, 170, 112, 112, 112, 112, 112, 112, 12, 69, 1, + -18, 30, '', 0, 19, 13, 1.25, 100, 100, 100), + (11, 45, 45, 2567, 2880, 1215, 758, 174, 174, 174, 174, 260, 260, 174, 114, 114, 114, 114, 114, 114, 12, 70, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (11, 46, 46, 2673, 2981, 1242, 774, 179, 179, 179, 179, 264, 264, 179, 116, 116, 116, 116, 116, 116, 12, 71, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (11, 47, 47, 2782, 3083, 1269, 791, 183, 183, 183, 183, 267, 267, 183, 118, 118, 118, 118, 118, 118, 13, 73, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (11, 48, 48, 2895, 3187, 1296, 808, 188, 188, 188, 188, 271, 271, 188, 121, 121, 121, 121, 121, 121, 13, 74, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (11, 49, 49, 3011, 3293, 1323, 825, 193, 193, 193, 193, 274, 274, 193, 123, 123, 123, 123, 123, 123, 13, 76, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (11, 50, 50, 3130, 3400, 1350, 841, 199, 199, 199, 199, 278, 278, 199, 125, 125, 125, 125, 125, 125, 13, 77, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (11, 51, 51, 3253, 3509, 1377, 859, 204, 204, 204, 204, 281, 281, 204, 127, 127, 127, 127, 127, 127, 14, 78, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (11, 52, 52, 3380, 3619, 1404, 875, 209, 209, 209, 209, 285, 285, 209, 130, 130, 130, 130, 130, 130, 14, 80, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (11, 53, 53, 3510, 3731, 1431, 892, 214, 214, 214, 214, 288, 288, 214, 132, 132, 132, 132, 132, 132, 14, 81, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (11, 54, 54, 3644, 3845, 1458, 909, 220, 220, 220, 220, 292, 292, 220, 134, 134, 134, 134, 134, 134, 14, 83, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (11, 55, 55, 3782, 3960, 1485, 926, 225, 225, 225, 225, 295, 295, 225, 136, 136, 136, 136, 136, 136, 15, 84, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (11, 56, 56, 3924, 4077, 1512, 942, 231, 231, 231, 231, 299, 299, 231, 139, 139, 139, 139, 139, 139, 15, 85, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (11, 57, 57, 4069, 4195, 1539, 960, 236, 236, 236, 236, 302, 302, 236, 141, 141, 141, 141, 141, 141, 15, 87, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (11, 58, 58, 4219, 4315, 1566, 976, 242, 242, 242, 242, 306, 306, 242, 143, 143, 143, 143, 143, 143, 15, 88, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (11, 59, 59, 4373, 4437, 1593, 993, 248, 248, 248, 248, 309, 309, 248, 145, 145, 145, 145, 145, 145, 16, 90, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (11, 60, 60, 4531, 4560, 1620, 1010, 255, 255, 255, 255, 313, 313, 255, 148, 148, 148, 148, 148, 148, 16, 91, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (11, 61, 61, 4693, 4685, 1647, 1027, 261, 261, 261, 261, 316, 316, 261, 150, 150, 150, 150, 150, 150, 16, 92, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (11, 62, 62, 4859, 4811, 1674, 1043, 267, 267, 267, 267, 320, 320, 267, 152, 152, 152, 152, 152, 152, 16, 94, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (11, 63, 63, 5030, 4939, 1701, 1061, 273, 273, 273, 273, 323, 323, 273, 154, 154, 154, 154, 154, 154, 17, 95, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (11, 64, 64, 5206, 5069, 1728, 1077, 280, 280, 280, 280, 327, 327, 280, 157, 157, 157, 157, 157, 157, 17, 97, 1, + -18, 30, '', 0, 24, 17, 1.25, 100, 100, 100), + (11, 65, 65, 5385, 5200, 1755, 1094, 286, 286, 286, 286, 330, 330, 286, 159, 159, 159, 159, 159, 159, 17, 98, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (11, 66, 66, 5570, 5333, 1782, 1111, 323, 323, 323, 323, 364, 364, 323, 161, 161, 161, 161, 161, 161, 17, 99, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (11, 67, 67, 5759, 5467, 1809, 1128, 334, 334, 334, 334, 372, 372, 334, 163, 163, 163, 163, 163, 163, 18, 101, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (11, 68, 68, 5953, 5603, 1836, 1144, 346, 346, 346, 346, 381, 381, 346, 166, 166, 166, 166, 166, 166, 18, 102, 1, + -18, 30, '', 0, 25, 18, 1.25, 100, 100, 100), + (11, 69, 69, 6151, 5741, 1863, 1162, 357, 357, 357, 357, 389, 389, 357, 168, 168, 168, 168, 168, 168, 18, 104, 1, + -18, 30, '', 0, 25, 18, 1.25, 100, 100, 100), + (11, 70, 70, 6355, 5880, 1890, 1178, 370, 370, 370, 370, 398, 398, 370, 170, 170, 170, 170, 170, 170, 18, 105, 1, + -18, 30, '', 0, 25, 19, 1.25, 100, 100, 100), + (11, 71, 71, 6563, 6021, 1917, 1195, 382, 382, 382, 382, 406, 406, 382, 172, 172, 172, 172, 172, 172, 19, 106, 1, + -18, 30, '', 0, 25, 19, 1.25, 100, 100, 100), + (11, 72, 72, 6777, 6163, 1944, 1212, 394, 394, 394, 394, 415, 415, 394, 175, 175, 175, 175, 175, 175, 19, 108, 1, + -18, 30, '', 0, 26, 19, 1.25, 100, 100, 100), + (11, 73, 73, 6995, 6307, 1971, 1229, 406, 406, 406, 406, 423, 423, 406, 177, 177, 177, 177, 177, 177, 19, 109, 1, + -18, 30, '', 0, 26, 19, 1.25, 100, 100, 100), + (11, 74, 74, 7219, 6453, 1998, 1245, 418, 418, 418, 418, 432, 432, 418, 179, 179, 179, 179, 179, 179, 19, 111, 1, + -18, 30, '', 0, 26, 19, 1.25, 100, 100, 100), + (11, 75, 75, 7448, 6600, 2025, 1263, 430, 430, 430, 430, 440, 440, 430, 181, 181, 181, 181, 181, 181, 20, 112, 1, + -18, 30, '', 0, 26, 20, 1.25, 100, 100, 100), + (11, 76, 76, 7682, 6749, 2052, 1279, 443, 443, 443, 443, 449, 449, 443, 184, 184, 184, 184, 184, 184, 20, 113, 1, + -18, 30, '', 0, 27, 20, 1.25, 100, 100, 100), + (11, 77, 77, 7921, 6899, 2079, 1296, 455, 455, 455, 455, 457, 457, 455, 186, 186, 186, 186, 186, 186, 20, 115, 1, + -18, 30, '', 0, 27, 20, 1.25, 100, 100, 100), + (11, 78, 78, 8166, 7051, 2106, 1313, 468, 468, 468, 468, 466, 466, 468, 188, 188, 188, 188, 188, 188, 20, 116, 1, + -18, 30, '', 0, 27, 20, 1.25, 100, 100, 100), + (11, 79, 79, 8417, 7205, 2133, 1330, 480, 480, 480, 480, 474, 474, 480, 190, 190, 190, 190, 190, 190, 21, 118, 1, + -18, 30, '', 0, 27, 20, 1.25, 100, 100, 100), + (11, 80, 80, 8673, 7360, 2160, 1346, 494, 494, 494, 494, 483, 483, 494, 193, 193, 193, 193, 193, 193, 21, 119, 1, + -18, 30, '', 0, 28, 21, 1.25, 100, 100, 100), + (11, 81, 81, 8935, 7517, 2187, 1364, 507, 507, 507, 507, 491, 491, 507, 195, 195, 195, 195, 195, 195, 21, 120, 1, + -18, 30, '', 0, 28, 21, 1.25, 100, 100, 100), + (11, 82, 82, 9202, 7675, 2214, 1380, 520, 520, 520, 520, 500, 500, 520, 197, 197, 197, 197, 197, 197, 21, 122, 1, + -18, 30, '', 0, 28, 21, 1.25, 100, 100, 100), + (11, 83, 83, 9475, 7835, 2241, 1397, 533, 533, 533, 533, 508, 508, 533, 199, 199, 199, 199, 199, 199, 22, 123, 1, + -18, 30, '', 0, 28, 21, 1.25, 100, 100, 100), + (11, 84, 84, 9754, 7997, 2268, 1414, 546, 546, 546, 546, 517, 517, 546, 202, 202, 202, 202, 202, 202, 22, 125, 1, + -18, 30, '', 0, 29, 21, 1.25, 100, 100, 100), + (11, 85, 85, 10040, 8160, 2295, 1431, 559, 559, 559, 559, 525, 525, 559, 204, 204, 204, 204, 204, 204, 22, 126, + 1, -18, 30, '', 0, 29, 22, 1.25, 100, 100, 100), + (12, 1, 1, 46, 32, 28, 17, 57, 57, 57, 57, 109, 109, 57, 18, 18, 18, 18, 18, 18, 1, 10, 1, -18, 30, '', 0, 9, 6, + 1.25, 100, 100, 100), + (12, 2, 2, 82, 65, 56, 34, 58, 58, 58, 58, 113, 113, 58, 20, 20, 20, 20, 20, 20, 2, 11, 1, -18, 30, '', 0, 9, 6, + 1.25, 100, 100, 100), + (12, 3, 3, 118, 100, 84, 52, 58, 58, 58, 58, 116, 116, 58, 22, 22, 22, 22, 22, 22, 2, 13, 1, -18, 30, '', 0, 9, + 6, 1.25, 100, 100, 100), + (12, 4, 4, 154, 137, 112, 68, 59, 59, 59, 59, 120, 120, 59, 26, 26, 26, 26, 26, 26, 2, 14, 1, -18, 30, '', 0, 10, + 6, 1.25, 100, 100, 100), + (12, 5, 5, 191, 175, 140, 86, 60, 60, 60, 60, 123, 123, 60, 28, 28, 28, 28, 28, 28, 2, 15, 1, -18, 30, '', 0, 10, + 7, 1.25, 100, 100, 100), + (12, 6, 6, 228, 215, 168, 103, 61, 61, 61, 61, 127, 127, 61, 30, 30, 30, 30, 30, 30, 3, 17, 1, -18, 30, '', 0, + 10, 7, 1.25, 100, 100, 100), + (12, 7, 7, 266, 256, 196, 120, 62, 62, 62, 62, 130, 130, 62, 32, 32, 32, 32, 32, 32, 3, 18, 1, -18, 30, '', 0, + 10, 7, 1.25, 100, 100, 100), + (12, 8, 8, 304, 299, 224, 137, 63, 63, 63, 63, 134, 134, 63, 36, 36, 36, 36, 36, 36, 3, 20, 1, -18, 30, '', 0, + 11, 7, 1.25, 100, 100, 100), + (12, 9, 9, 342, 344, 252, 155, 64, 64, 64, 64, 137, 137, 64, 38, 38, 38, 38, 38, 38, 3, 21, 1, -18, 30, '', 0, + 11, 7, 1.25, 100, 100, 100), + (12, 10, 10, 381, 390, 280, 171, 68, 68, 68, 68, 141, 141, 68, 40, 40, 40, 40, 40, 40, 4, 22, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (12, 11, 11, 421, 438, 308, 189, 69, 69, 69, 69, 144, 144, 69, 42, 42, 42, 42, 42, 42, 4, 24, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (12, 12, 12, 462, 487, 336, 206, 71, 71, 71, 71, 148, 148, 71, 46, 46, 46, 46, 46, 46, 4, 25, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (12, 13, 13, 503, 538, 364, 223, 72, 72, 72, 72, 151, 151, 72, 48, 48, 48, 48, 48, 48, 4, 27, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (12, 14, 14, 546, 591, 392, 240, 74, 74, 74, 74, 155, 155, 74, 50, 50, 50, 50, 50, 50, 5, 28, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (12, 15, 15, 589, 645, 420, 258, 76, 76, 76, 76, 158, 158, 76, 52, 52, 52, 52, 52, 52, 5, 29, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (12, 16, 16, 634, 701, 448, 274, 78, 78, 78, 78, 162, 162, 78, 56, 56, 56, 56, 56, 56, 5, 31, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (12, 17, 17, 679, 758, 476, 292, 80, 80, 80, 80, 165, 165, 80, 58, 58, 58, 58, 58, 58, 5, 32, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (12, 18, 18, 726, 817, 504, 309, 82, 82, 82, 82, 169, 169, 82, 60, 60, 60, 60, 60, 60, 6, 34, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (12, 19, 19, 774, 878, 532, 326, 84, 84, 84, 84, 172, 172, 84, 62, 62, 62, 62, 62, 62, 6, 35, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (12, 20, 20, 824, 940, 560, 343, 89, 89, 89, 89, 176, 176, 89, 66, 66, 66, 66, 66, 66, 6, 36, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (12, 21, 21, 874, 1004, 588, 361, 91, 91, 91, 91, 179, 179, 91, 68, 68, 68, 68, 68, 68, 6, 38, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (12, 22, 22, 927, 1069, 616, 377, 94, 94, 94, 94, 183, 183, 94, 70, 70, 70, 70, 70, 70, 7, 39, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (12, 23, 23, 981, 1136, 644, 395, 96, 96, 96, 96, 186, 186, 96, 72, 72, 72, 72, 72, 72, 7, 41, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (12, 24, 24, 1036, 1205, 672, 412, 99, 99, 99, 99, 190, 190, 99, 76, 76, 76, 76, 76, 76, 7, 42, 1, -18, 30, '', + 0, 15, 10, 1.25, 100, 100, 100), + (12, 25, 25, 1093, 1275, 700, 429, 101, 101, 101, 101, 193, 193, 101, 78, 78, 78, 78, 78, 78, 7, 43, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (12, 26, 26, 1152, 1347, 728, 446, 104, 104, 104, 104, 197, 197, 104, 80, 80, 80, 80, 80, 80, 8, 45, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (12, 27, 27, 1213, 1420, 756, 464, 107, 107, 107, 107, 200, 200, 107, 82, 82, 82, 82, 82, 82, 8, 46, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (12, 28, 28, 1276, 1495, 784, 480, 110, 110, 110, 110, 204, 204, 110, 86, 86, 86, 86, 86, 86, 8, 48, 1, -18, 30, + '', 0, 16, 11, 1.25, 100, 100, 100), + (12, 29, 29, 1340, 1572, 812, 498, 113, 113, 113, 113, 207, 207, 113, 88, 88, 88, 88, 88, 88, 8, 49, 1, -18, 30, + '', 0, 16, 11, 1.25, 100, 100, 100), + (12, 30, 30, 1407, 1650, 840, 515, 118, 118, 118, 118, 211, 211, 118, 90, 90, 90, 90, 90, 90, 9, 50, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (12, 31, 31, 1476, 1730, 868, 532, 121, 121, 121, 121, 214, 214, 121, 92, 92, 92, 92, 92, 92, 9, 52, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (12, 32, 32, 1547, 1811, 896, 549, 125, 125, 125, 125, 218, 218, 125, 96, 96, 96, 96, 96, 96, 9, 53, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (12, 33, 33, 1620, 1894, 924, 567, 128, 128, 128, 128, 221, 221, 128, 98, 98, 98, 98, 98, 98, 9, 55, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (12, 34, 34, 1696, 1979, 952, 583, 132, 132, 132, 132, 225, 225, 132, 100, 100, 100, 100, 100, 100, 10, 56, 1, + -18, 30, '', 0, 17, 12, 1.25, 100, 100, 100), + (12, 35, 35, 1774, 2065, 980, 601, 135, 135, 135, 135, 228, 228, 135, 102, 102, 102, 102, 102, 102, 10, 57, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (12, 36, 36, 1854, 2153, 1008, 618, 139, 139, 139, 139, 232, 232, 139, 106, 106, 106, 106, 106, 106, 10, 59, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (12, 37, 37, 1937, 2242, 1036, 635, 143, 143, 143, 143, 235, 235, 143, 108, 108, 108, 108, 108, 108, 10, 60, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (12, 38, 38, 2023, 2333, 1064, 652, 147, 147, 147, 147, 239, 239, 147, 110, 110, 110, 110, 110, 110, 11, 62, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (12, 39, 39, 2111, 2426, 1092, 670, 151, 151, 151, 151, 242, 242, 151, 112, 112, 112, 112, 112, 112, 11, 63, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (12, 40, 40, 2202, 2520, 1120, 686, 157, 157, 157, 157, 246, 246, 157, 116, 116, 116, 116, 116, 116, 11, 64, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (12, 41, 41, 2296, 2616, 1148, 704, 161, 161, 161, 161, 249, 249, 161, 118, 118, 118, 118, 118, 118, 11, 66, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (12, 42, 42, 2393, 2713, 1176, 721, 166, 166, 166, 166, 253, 253, 166, 120, 120, 120, 120, 120, 120, 12, 67, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (12, 43, 43, 2493, 2812, 1204, 738, 170, 170, 170, 170, 256, 256, 170, 122, 122, 122, 122, 122, 122, 12, 69, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (12, 44, 44, 2596, 2913, 1232, 755, 175, 175, 175, 175, 260, 260, 175, 126, 126, 126, 126, 126, 126, 12, 70, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (12, 45, 45, 2702, 3015, 1260, 773, 179, 179, 179, 179, 263, 263, 179, 128, 128, 128, 128, 128, 128, 12, 71, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (12, 46, 46, 2811, 3119, 1288, 789, 184, 184, 184, 184, 267, 267, 184, 130, 130, 130, 130, 130, 130, 13, 73, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (12, 47, 47, 2923, 3224, 1316, 807, 188, 188, 188, 188, 270, 270, 188, 132, 132, 132, 132, 132, 132, 13, 74, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (12, 48, 48, 3039, 3331, 1344, 824, 193, 193, 193, 193, 274, 274, 193, 136, 136, 136, 136, 136, 136, 13, 76, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (12, 49, 49, 3158, 3440, 1372, 841, 198, 198, 198, 198, 277, 277, 198, 138, 138, 138, 138, 138, 138, 13, 77, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (12, 50, 50, 3280, 3550, 1400, 858, 205, 205, 205, 205, 281, 281, 205, 140, 140, 140, 140, 140, 140, 14, 78, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (12, 51, 51, 3406, 3662, 1428, 876, 210, 210, 210, 210, 284, 284, 210, 142, 142, 142, 142, 142, 142, 14, 80, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (12, 52, 52, 3536, 3775, 1456, 892, 215, 215, 215, 215, 288, 288, 215, 146, 146, 146, 146, 146, 146, 14, 81, 1, + -18, 30, '', 0, 22, 16, 1.31, 100, 100, 100), + (12, 53, 53, 3669, 3890, 1484, 910, 220, 220, 220, 220, 291, 291, 220, 148, 148, 148, 148, 148, 148, 14, 83, 1, + -18, 30, '', 0, 22, 16, 1.31, 100, 100, 100), + (12, 54, 54, 3806, 4007, 1512, 927, 226, 226, 226, 226, 295, 295, 226, 150, 150, 150, 150, 150, 150, 15, 84, 1, + -18, 30, '', 0, 22, 16, 1.31, 100, 100, 100), + (12, 55, 55, 3947, 4125, 1540, 944, 231, 231, 231, 231, 298, 298, 231, 152, 152, 152, 152, 152, 152, 15, 85, 1, + -18, 30, '', 0, 22, 17, 1.31, 100, 100, 100), + (12, 56, 56, 4092, 4245, 1568, 961, 237, 237, 237, 237, 302, 302, 237, 156, 156, 156, 156, 156, 156, 15, 87, 1, + -18, 30, '', 0, 23, 17, 1.31, 100, 100, 100), + (12, 57, 57, 4240, 4366, 1596, 979, 242, 242, 242, 242, 305, 305, 242, 158, 158, 158, 158, 158, 158, 15, 88, 1, + -18, 30, '', 0, 23, 17, 1.31, 100, 100, 100), + (12, 58, 58, 4393, 4489, 1624, 995, 248, 248, 248, 248, 309, 309, 248, 160, 160, 160, 160, 160, 160, 16, 90, 1, + -18, 30, '', 0, 23, 17, 1.31, 100, 100, 100), + (12, 59, 59, 4550, 4614, 1652, 1013, 254, 254, 254, 254, 312, 312, 254, 162, 162, 162, 162, 162, 162, 16, 91, 1, + -18, 30, '', 0, 23, 17, 1.31, 100, 100, 100), + (12, 60, 60, 4711, 4740, 1680, 1030, 262, 262, 262, 262, 316, 316, 262, 166, 166, 166, 166, 166, 166, 16, 92, 1, + -18, 30, '', 0, 24, 18, 1.31, 100, 100, 100), + (12, 61, 61, 4876, 4868, 1708, 1047, 268, 268, 268, 268, 319, 319, 268, 168, 168, 168, 168, 168, 168, 16, 94, 1, + -18, 30, '', 0, 24, 18, 1.31, 100, 100, 100), + (12, 62, 62, 5045, 4997, 1736, 1064, 274, 274, 274, 274, 323, 323, 274, 170, 170, 170, 170, 170, 170, 17, 95, 1, + -18, 30, '', 0, 24, 18, 1.31, 100, 100, 100), + (12, 63, 63, 5219, 5128, 1764, 1082, 280, 280, 280, 280, 326, 326, 280, 172, 172, 172, 172, 172, 172, 17, 97, 1, + -18, 30, '', 0, 24, 18, 1.31, 100, 100, 100), + (12, 64, 64, 5398, 5261, 1792, 1098, 287, 287, 287, 287, 330, 330, 287, 176, 176, 176, 176, 176, 176, 17, 98, 1, + -18, 30, '', 0, 25, 18, 1.31, 100, 100, 100), + (12, 65, 65, 5580, 5395, 1820, 1116, 293, 293, 293, 293, 333, 333, 293, 178, 178, 178, 178, 178, 178, 17, 99, 1, + -18, 30, '', 0, 25, 19, 1.31, 100, 100, 100), + (12, 66, 66, 5768, 5531, 1848, 1133, 330, 330, 330, 330, 367, 367, 330, 180, 180, 180, 180, 180, 180, 18, 101, 1, + -18, 30, '', 0, 25, 19, 1.31, 100, 100, 100), + (12, 67, 67, 5960, 5668, 1876, 1150, 341, 341, 341, 341, 375, 375, 341, 182, 182, 182, 182, 182, 182, 18, 102, 1, + -18, 30, '', 0, 25, 19, 1.31, 100, 100, 100), + (12, 68, 68, 6157, 5807, 1904, 1167, 353, 353, 353, 353, 384, 384, 353, 186, 186, 186, 186, 186, 186, 18, 104, 1, + -18, 30, '', 0, 26, 19, 1.31, 100, 100, 100), + (12, 69, 69, 6358, 5948, 1932, 1185, 364, 364, 364, 364, 392, 392, 364, 188, 188, 188, 188, 188, 188, 18, 105, 1, + -18, 30, '', 0, 26, 19, 1.31, 100, 100, 100), + (12, 70, 70, 6565, 6090, 1960, 1201, 378, 378, 378, 378, 401, 401, 378, 190, 190, 190, 190, 190, 190, 19, 106, 1, + -18, 30, '', 0, 26, 20, 1.31, 100, 100, 100), + (12, 71, 71, 6776, 6234, 1988, 1219, 390, 390, 390, 390, 409, 409, 390, 192, 192, 192, 192, 192, 192, 19, 108, 1, + -18, 30, '', 0, 26, 20, 1.31, 100, 100, 100), + (12, 72, 72, 6993, 6379, 2016, 1236, 402, 402, 402, 402, 418, 418, 402, 196, 196, 196, 196, 196, 196, 19, 109, 1, + -18, 30, '', 0, 27, 20, 1.31, 100, 100, 100), + (12, 73, 73, 7214, 6526, 2044, 1253, 414, 414, 414, 414, 426, 426, 414, 198, 198, 198, 198, 198, 198, 19, 111, 1, + -18, 30, '', 0, 27, 20, 1.31, 100, 100, 100), + (12, 74, 74, 7441, 6675, 2072, 1270, 426, 426, 426, 426, 435, 435, 426, 200, 200, 200, 200, 200, 200, 20, 112, 1, + -18, 30, '', 0, 27, 20, 1.31, 100, 100, 100), + (12, 75, 75, 7673, 6825, 2100, 1288, 438, 438, 438, 438, 443, 443, 438, 202, 202, 202, 202, 202, 202, 20, 113, 1, + -18, 30, '', 0, 27, 21, 1.31, 100, 100, 100), + (12, 76, 76, 7910, 6977, 2128, 1304, 451, 451, 451, 451, 452, 452, 451, 206, 206, 206, 206, 206, 206, 20, 115, 1, + -18, 30, '', 0, 28, 21, 1.31, 100, 100, 100), + (12, 77, 77, 8152, 7130, 2156, 1322, 463, 463, 463, 463, 460, 460, 463, 208, 208, 208, 208, 208, 208, 20, 116, 1, + -18, 30, '', 0, 28, 21, 1.31, 100, 100, 100), + (12, 78, 78, 8400, 7285, 2184, 1339, 476, 476, 476, 476, 469, 469, 476, 210, 210, 210, 210, 210, 210, 21, 118, 1, + -18, 30, '', 0, 28, 21, 1.31, 100, 100, 100), + (12, 79, 79, 8654, 7442, 2212, 1356, 488, 488, 488, 488, 477, 477, 488, 212, 212, 212, 212, 212, 212, 21, 119, 1, + -18, 30, '', 0, 28, 21, 1.31, 100, 100, 100), + (12, 80, 80, 8913, 7600, 2240, 1373, 503, 503, 503, 503, 486, 486, 503, 216, 216, 216, 216, 216, 216, 21, 120, 1, + -18, 30, '', 0, 29, 22, 1.31, 100, 100, 100), + (12, 81, 81, 9178, 7760, 2268, 1391, 516, 516, 516, 516, 494, 494, 516, 218, 218, 218, 218, 218, 218, 21, 122, 1, + -18, 30, '', 0, 29, 22, 1.31, 100, 100, 100), + (12, 82, 82, 9448, 7921, 2296, 1407, 529, 529, 529, 529, 503, 503, 529, 220, 220, 220, 220, 220, 220, 22, 123, 1, + -18, 30, '', 0, 29, 22, 1.31, 100, 100, 100), + (12, 83, 83, 9724, 8084, 2324, 1425, 542, 542, 542, 542, 511, 511, 542, 222, 222, 222, 222, 222, 222, 22, 125, 1, + -18, 30, '', 0, 29, 22, 1.31, 100, 100, 100), + (12, 84, 84, 10006, 8249, 2352, 1442, 555, 555, 555, 555, 520, 520, 555, 226, 226, 226, 226, 226, 226, 22, 126, + 1, -18, 30, '', 0, 30, 22, 1.31, 100, 100, 100), + (12, 85, 85, 10295, 8415, 2380, 1459, 568, 568, 568, 568, 528, 528, 568, 228, 228, 228, 228, 228, 228, 22, 127, + 1, -18, 30, '', 0, 30, 23, 1.31, 100, 100, 100), + (13, 1, 1, 49, 35, 29, 18, 58, 58, 58, 58, 112, 112, 58, 21, 21, 21, 21, 21, 21, 2, 11, 1, -18, 30, '', 0, 10, 7, + 1.25, 100, 100, 100), + (13, 2, 2, 88, 71, 58, 35, 59, 59, 59, 59, 116, 116, 59, 23, 23, 23, 23, 23, 23, 2, 13, 1, -18, 30, '', 0, 10, 7, + 1.25, 100, 100, 100), + (13, 3, 3, 127, 109, 87, 53, 59, 59, 59, 59, 119, 119, 59, 25, 25, 25, 25, 25, 25, 2, 14, 1, -18, 30, '', 0, 10, + 7, 1.25, 100, 100, 100), + (13, 4, 4, 166, 149, 116, 70, 60, 60, 60, 60, 123, 123, 60, 30, 30, 30, 30, 30, 30, 2, 15, 1, -18, 30, '', 0, 11, + 7, 1.25, 100, 100, 100), + (13, 5, 5, 206, 190, 145, 88, 61, 61, 61, 61, 126, 126, 61, 32, 32, 32, 32, 32, 32, 3, 17, 1, -18, 30, '', 0, 11, + 8, 1.25, 100, 100, 100), + (13, 6, 6, 246, 233, 174, 105, 62, 62, 62, 62, 130, 130, 62, 34, 34, 34, 34, 34, 34, 3, 18, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (13, 7, 7, 287, 277, 203, 123, 63, 63, 63, 63, 133, 133, 63, 36, 36, 36, 36, 36, 36, 3, 20, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (13, 8, 8, 328, 323, 232, 140, 64, 64, 64, 64, 137, 137, 64, 41, 41, 41, 41, 41, 41, 3, 21, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (13, 9, 9, 369, 371, 261, 158, 65, 65, 65, 65, 140, 140, 65, 43, 43, 43, 43, 43, 43, 4, 22, 1, -18, 30, '', 0, + 12, 8, 1.25, 100, 100, 100), + (13, 10, 10, 411, 420, 290, 175, 70, 70, 70, 70, 144, 144, 70, 45, 45, 45, 45, 45, 45, 4, 24, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (13, 11, 11, 454, 471, 319, 193, 71, 71, 71, 71, 147, 147, 71, 47, 47, 47, 47, 47, 47, 4, 25, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (13, 12, 12, 498, 523, 348, 210, 73, 73, 73, 73, 151, 151, 73, 52, 52, 52, 52, 52, 52, 4, 27, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (13, 13, 13, 542, 577, 377, 228, 74, 74, 74, 74, 154, 154, 74, 54, 54, 54, 54, 54, 54, 5, 28, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (13, 14, 14, 588, 633, 406, 245, 76, 76, 76, 76, 158, 158, 76, 56, 56, 56, 56, 56, 56, 5, 29, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (13, 15, 15, 634, 690, 435, 263, 78, 78, 78, 78, 161, 161, 78, 58, 58, 58, 58, 58, 58, 5, 31, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (13, 16, 16, 682, 749, 464, 280, 80, 80, 80, 80, 165, 165, 80, 63, 63, 63, 63, 63, 63, 5, 32, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (13, 17, 17, 730, 809, 493, 298, 82, 82, 82, 82, 168, 168, 82, 65, 65, 65, 65, 65, 65, 6, 34, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (13, 18, 18, 780, 871, 522, 315, 84, 84, 84, 84, 172, 172, 84, 67, 67, 67, 67, 67, 67, 6, 35, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (13, 19, 19, 831, 935, 551, 333, 86, 86, 86, 86, 175, 175, 86, 69, 69, 69, 69, 69, 69, 6, 36, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (13, 20, 20, 884, 1000, 580, 350, 92, 92, 92, 92, 179, 179, 92, 74, 74, 74, 74, 74, 74, 6, 38, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (13, 21, 21, 937, 1067, 609, 368, 94, 94, 94, 94, 182, 182, 94, 76, 76, 76, 76, 76, 76, 7, 39, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (13, 22, 22, 993, 1135, 638, 385, 97, 97, 97, 97, 186, 186, 97, 78, 78, 78, 78, 78, 78, 7, 41, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (13, 23, 23, 1050, 1205, 667, 403, 99, 99, 99, 99, 189, 189, 99, 80, 80, 80, 80, 80, 80, 7, 42, 1, -18, 30, '', + 0, 15, 11, 1.25, 100, 100, 100), + (13, 24, 24, 1108, 1277, 696, 420, 102, 102, 102, 102, 193, 193, 102, 85, 85, 85, 85, 85, 85, 7, 43, 1, -18, 30, + '', 0, 16, 11, 1.25, 100, 100, 100), + (13, 25, 25, 1168, 1350, 725, 438, 104, 104, 104, 104, 196, 196, 104, 87, 87, 87, 87, 87, 87, 8, 45, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (13, 26, 26, 1230, 1425, 754, 455, 107, 107, 107, 107, 200, 200, 107, 89, 89, 89, 89, 89, 89, 8, 46, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (13, 27, 27, 1294, 1501, 783, 473, 110, 110, 110, 110, 203, 203, 110, 91, 91, 91, 91, 91, 91, 8, 48, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (13, 28, 28, 1360, 1579, 812, 490, 113, 113, 113, 113, 207, 207, 113, 96, 96, 96, 96, 96, 96, 8, 49, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (13, 29, 29, 1427, 1659, 841, 508, 116, 116, 116, 116, 210, 210, 116, 98, 98, 98, 98, 98, 98, 9, 50, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (13, 30, 30, 1497, 1740, 870, 525, 122, 122, 122, 122, 214, 214, 122, 100, 100, 100, 100, 100, 100, 9, 52, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (13, 31, 31, 1569, 1823, 899, 543, 125, 125, 125, 125, 217, 217, 125, 102, 102, 102, 102, 102, 102, 9, 53, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (13, 32, 32, 1643, 1907, 928, 560, 129, 129, 129, 129, 221, 221, 129, 107, 107, 107, 107, 107, 107, 9, 55, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (13, 33, 33, 1719, 1993, 957, 578, 132, 132, 132, 132, 224, 224, 132, 109, 109, 109, 109, 109, 109, 10, 56, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (13, 34, 34, 1798, 2081, 986, 595, 136, 136, 136, 136, 228, 228, 136, 111, 111, 111, 111, 111, 111, 10, 57, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (13, 35, 35, 1879, 2170, 1015, 613, 139, 139, 139, 139, 231, 231, 139, 113, 113, 113, 113, 113, 113, 10, 59, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (13, 36, 36, 1962, 2261, 1044, 630, 143, 143, 143, 143, 235, 235, 143, 118, 118, 118, 118, 118, 118, 10, 60, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (13, 37, 37, 2048, 2353, 1073, 648, 147, 147, 147, 147, 238, 238, 147, 120, 120, 120, 120, 120, 120, 11, 62, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (13, 38, 38, 2137, 2447, 1102, 665, 151, 151, 151, 151, 242, 242, 151, 122, 122, 122, 122, 122, 122, 11, 63, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (13, 39, 39, 2228, 2543, 1131, 683, 155, 155, 155, 155, 245, 245, 155, 124, 124, 124, 124, 124, 124, 11, 64, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (13, 40, 40, 2322, 2640, 1160, 700, 162, 162, 162, 162, 249, 249, 162, 129, 129, 129, 129, 129, 129, 11, 66, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (13, 41, 41, 2419, 2739, 1189, 718, 166, 166, 166, 166, 252, 252, 166, 131, 131, 131, 131, 131, 131, 12, 67, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (13, 42, 42, 2519, 2839, 1218, 735, 171, 171, 171, 171, 256, 256, 171, 133, 133, 133, 133, 133, 133, 12, 69, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (13, 43, 43, 2622, 2941, 1247, 753, 175, 175, 175, 175, 259, 259, 175, 135, 135, 135, 135, 135, 135, 12, 70, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (13, 44, 44, 2728, 3045, 1276, 770, 180, 180, 180, 180, 263, 263, 180, 140, 140, 140, 140, 140, 140, 12, 71, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (13, 45, 45, 2837, 3150, 1305, 788, 184, 184, 184, 184, 266, 266, 184, 142, 142, 142, 142, 142, 142, 13, 73, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (13, 46, 46, 2949, 3257, 1334, 805, 189, 189, 189, 189, 270, 270, 189, 144, 144, 144, 144, 144, 144, 13, 74, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (13, 47, 47, 3064, 3365, 1363, 823, 193, 193, 193, 193, 273, 273, 193, 146, 146, 146, 146, 146, 146, 13, 76, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (13, 48, 48, 3183, 3475, 1392, 840, 198, 198, 198, 198, 277, 277, 198, 151, 151, 151, 151, 151, 151, 13, 77, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (13, 49, 49, 3305, 3587, 1421, 858, 203, 203, 203, 203, 280, 280, 203, 153, 153, 153, 153, 153, 153, 14, 78, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (13, 50, 50, 3430, 3700, 1450, 875, 211, 211, 211, 211, 284, 284, 211, 155, 155, 155, 155, 155, 155, 14, 80, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (13, 51, 51, 3559, 3815, 1479, 893, 216, 216, 216, 216, 287, 287, 216, 157, 157, 157, 157, 157, 157, 14, 81, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (13, 52, 52, 3692, 3931, 1508, 910, 221, 221, 221, 221, 291, 291, 221, 162, 162, 162, 162, 162, 162, 14, 83, 1, + -18, 30, '', 0, 23, 17, 1.37, 100, 100, 100), + (13, 53, 53, 3828, 4049, 1537, 928, 226, 226, 226, 226, 294, 294, 226, 164, 164, 164, 164, 164, 164, 15, 84, 1, + -18, 30, '', 0, 23, 17, 1.37, 100, 100, 100), + (13, 54, 54, 3968, 4169, 1566, 945, 232, 232, 232, 232, 298, 298, 232, 166, 166, 166, 166, 166, 166, 15, 85, 1, + -18, 30, '', 0, 23, 17, 1.37, 100, 100, 100), + (13, 55, 55, 4112, 4290, 1595, 963, 237, 237, 237, 237, 301, 301, 237, 168, 168, 168, 168, 168, 168, 15, 87, 1, + -18, 30, '', 0, 23, 18, 1.37, 100, 100, 100), + (13, 56, 56, 4260, 4413, 1624, 980, 243, 243, 243, 243, 305, 305, 243, 173, 173, 173, 173, 173, 173, 15, 88, 1, + -18, 30, '', 0, 24, 18, 1.37, 100, 100, 100), + (13, 57, 57, 4411, 4537, 1653, 998, 248, 248, 248, 248, 308, 308, 248, 175, 175, 175, 175, 175, 175, 16, 90, 1, + -18, 30, '', 0, 24, 18, 1.37, 100, 100, 100), + (13, 58, 58, 4567, 4663, 1682, 1015, 254, 254, 254, 254, 312, 312, 254, 177, 177, 177, 177, 177, 177, 16, 91, 1, + -18, 30, '', 0, 24, 18, 1.37, 100, 100, 100), + (13, 59, 59, 4727, 4791, 1711, 1033, 260, 260, 260, 260, 315, 315, 260, 179, 179, 179, 179, 179, 179, 16, 92, 1, + -18, 30, '', 0, 24, 18, 1.37, 100, 100, 100), + (13, 60, 60, 4891, 4920, 1740, 1050, 269, 269, 269, 269, 319, 319, 269, 184, 184, 184, 184, 184, 184, 16, 94, 1, + -18, 30, '', 0, 25, 19, 1.37, 100, 100, 100), + (13, 61, 61, 5059, 5051, 1769, 1068, 275, 275, 275, 275, 322, 322, 275, 186, 186, 186, 186, 186, 186, 17, 95, 1, + -18, 30, '', 0, 25, 19, 1.37, 100, 100, 100), + (13, 62, 62, 5231, 5183, 1798, 1085, 281, 281, 281, 281, 326, 326, 281, 188, 188, 188, 188, 188, 188, 17, 97, 1, + -18, 30, '', 0, 25, 19, 1.37, 100, 100, 100), + (13, 63, 63, 5408, 5317, 1827, 1103, 287, 287, 287, 287, 329, 329, 287, 190, 190, 190, 190, 190, 190, 17, 98, 1, + -18, 30, '', 0, 25, 19, 1.37, 100, 100, 100), + (13, 64, 64, 5590, 5453, 1856, 1120, 294, 294, 294, 294, 333, 333, 294, 195, 195, 195, 195, 195, 195, 17, 99, 1, + -18, 30, '', 0, 26, 19, 1.37, 100, 100, 100), + (13, 65, 65, 5775, 5590, 1885, 1138, 300, 300, 300, 300, 336, 336, 300, 197, 197, 197, 197, 197, 197, 18, 101, 1, + -18, 30, '', 0, 26, 20, 1.37, 100, 100, 100), + (13, 66, 66, 5966, 5729, 1914, 1155, 337, 337, 337, 337, 370, 370, 337, 199, 199, 199, 199, 199, 199, 18, 102, 1, + -18, 30, '', 0, 26, 20, 1.37, 100, 100, 100), + (13, 67, 67, 6161, 5869, 1943, 1173, 348, 348, 348, 348, 378, 378, 348, 201, 201, 201, 201, 201, 201, 18, 104, 1, + -18, 30, '', 0, 26, 20, 1.37, 100, 100, 100), + (13, 68, 68, 6361, 6011, 1972, 1190, 360, 360, 360, 360, 387, 387, 360, 206, 206, 206, 206, 206, 206, 18, 105, 1, + -18, 30, '', 0, 27, 20, 1.37, 100, 100, 100), + (13, 69, 69, 6565, 6155, 2001, 1208, 371, 371, 371, 371, 395, 395, 371, 208, 208, 208, 208, 208, 208, 19, 106, 1, + -18, 30, '', 0, 27, 20, 1.37, 100, 100, 100), + (13, 70, 70, 6775, 6300, 2030, 1225, 386, 386, 386, 386, 404, 404, 386, 210, 210, 210, 210, 210, 210, 19, 108, 1, + -18, 30, '', 0, 27, 21, 1.37, 100, 100, 100), + (13, 71, 71, 6989, 6447, 2059, 1243, 398, 398, 398, 398, 412, 412, 398, 212, 212, 212, 212, 212, 212, 19, 109, 1, + -18, 30, '', 0, 27, 21, 1.37, 100, 100, 100), + (13, 72, 72, 7209, 6595, 2088, 1260, 410, 410, 410, 410, 421, 421, 410, 217, 217, 217, 217, 217, 217, 19, 111, 1, + -18, 30, '', 0, 28, 21, 1.37, 100, 100, 100), + (13, 73, 73, 7433, 6745, 2117, 1278, 422, 422, 422, 422, 429, 429, 422, 219, 219, 219, 219, 219, 219, 20, 112, 1, + -18, 30, '', 0, 28, 21, 1.37, 100, 100, 100), + (13, 74, 74, 7663, 6897, 2146, 1295, 434, 434, 434, 434, 438, 438, 434, 221, 221, 221, 221, 221, 221, 20, 113, 1, + -18, 30, '', 0, 28, 21, 1.37, 100, 100, 100), + (13, 75, 75, 7898, 7050, 2175, 1313, 446, 446, 446, 446, 446, 446, 446, 223, 223, 223, 223, 223, 223, 20, 115, 1, + -18, 30, '', 0, 28, 22, 1.37, 100, 100, 100), + (13, 76, 76, 8138, 7205, 2204, 1330, 459, 459, 459, 459, 455, 455, 459, 228, 228, 228, 228, 228, 228, 20, 116, 1, + -18, 30, '', 0, 29, 22, 1.37, 100, 100, 100), + (13, 77, 77, 8383, 7361, 2233, 1348, 471, 471, 471, 471, 463, 463, 471, 230, 230, 230, 230, 230, 230, 21, 118, 1, + -18, 30, '', 0, 29, 22, 1.37, 100, 100, 100), + (13, 78, 78, 8634, 7519, 2262, 1365, 484, 484, 484, 484, 472, 472, 484, 232, 232, 232, 232, 232, 232, 21, 119, 1, + -18, 30, '', 0, 29, 22, 1.37, 100, 100, 100), + (13, 79, 79, 8891, 7679, 2291, 1383, 496, 496, 496, 496, 480, 480, 496, 234, 234, 234, 234, 234, 234, 21, 120, 1, + -18, 30, '', 0, 29, 22, 1.37, 100, 100, 100), + (13, 80, 80, 9153, 7840, 2320, 1400, 512, 512, 512, 512, 489, 489, 512, 239, 239, 239, 239, 239, 239, 21, 122, 1, + -18, 30, '', 0, 30, 23, 1.37, 100, 100, 100), + (13, 81, 81, 9421, 8003, 2349, 1418, 525, 525, 525, 525, 497, 497, 525, 241, 241, 241, 241, 241, 241, 22, 123, 1, + -18, 30, '', 0, 30, 23, 1.37, 100, 100, 100), + (13, 82, 82, 9694, 8167, 2378, 1435, 538, 538, 538, 538, 506, 506, 538, 243, 243, 243, 243, 243, 243, 22, 125, 1, + -18, 30, '', 0, 30, 23, 1.37, 100, 100, 100), + (13, 83, 83, 9973, 8333, 2407, 1453, 551, 551, 551, 551, 514, 514, 551, 245, 245, 245, 245, 245, 245, 22, 126, 1, + -18, 30, '', 0, 30, 23, 1.37, 100, 100, 100), + (13, 84, 84, 10258, 8501, 2436, 1470, 564, 564, 564, 564, 523, 523, 564, 250, 250, 250, 250, 250, 250, 22, 127, + 1, -18, 30, '', 0, 31, 23, 1.37, 100, 100, 100), + (13, 85, 85, 10550, 8670, 2465, 1488, 577, 577, 577, 577, 531, 531, 577, 252, 252, 252, 252, 252, 252, 23, 129, + 1, -18, 30, '', 0, 31, 24, 1.37, 100, 100, 100), + (14, 1, 1, 52, 38, 30, 18, 59, 59, 59, 59, 115, 115, 59, 24, 24, 24, 24, 24, 24, 2, 13, 1, -18, 30, '', 0, 11, 8, + 1.25, 100, 100, 100), + (14, 2, 2, 94, 77, 60, 35, 60, 60, 60, 60, 119, 119, 60, 26, 26, 26, 26, 26, 26, 2, 14, 1, -18, 30, '', 0, 11, 8, + 1.25, 100, 100, 100), + (14, 3, 3, 136, 118, 90, 54, 60, 60, 60, 60, 122, 122, 60, 28, 28, 28, 28, 28, 28, 2, 15, 1, -18, 30, '', 0, 11, + 8, 1.25, 100, 100, 100), + (14, 4, 4, 178, 161, 120, 71, 61, 61, 61, 61, 126, 126, 61, 34, 34, 34, 34, 34, 34, 3, 17, 1, -18, 30, '', 0, 12, + 8, 1.25, 100, 100, 100), + (14, 5, 5, 221, 205, 150, 89, 62, 62, 62, 62, 129, 129, 62, 36, 36, 36, 36, 36, 36, 3, 18, 1, -18, 30, '', 0, 12, + 9, 1.25, 100, 100, 100), + (14, 6, 6, 264, 251, 180, 107, 63, 63, 63, 63, 133, 133, 63, 38, 38, 38, 38, 38, 38, 3, 20, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (14, 7, 7, 308, 298, 210, 125, 64, 64, 64, 64, 136, 136, 64, 40, 40, 40, 40, 40, 40, 3, 21, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (14, 8, 8, 352, 347, 240, 142, 65, 65, 65, 65, 140, 140, 65, 46, 46, 46, 46, 46, 46, 4, 22, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (14, 9, 9, 396, 398, 270, 161, 66, 66, 66, 66, 143, 143, 66, 48, 48, 48, 48, 48, 48, 4, 24, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (14, 10, 10, 441, 450, 300, 178, 72, 72, 72, 72, 147, 147, 72, 50, 50, 50, 50, 50, 50, 4, 25, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (14, 11, 11, 487, 504, 330, 196, 73, 73, 73, 73, 150, 150, 73, 52, 52, 52, 52, 52, 52, 4, 27, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (14, 12, 12, 534, 559, 360, 214, 75, 75, 75, 75, 154, 154, 75, 58, 58, 58, 58, 58, 58, 5, 28, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (14, 13, 13, 581, 616, 390, 232, 76, 76, 76, 76, 157, 157, 76, 60, 60, 60, 60, 60, 60, 5, 29, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (14, 14, 14, 630, 675, 420, 249, 78, 78, 78, 78, 161, 161, 78, 62, 62, 62, 62, 62, 62, 5, 31, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (14, 15, 15, 679, 735, 450, 268, 80, 80, 80, 80, 164, 164, 80, 64, 64, 64, 64, 64, 64, 5, 32, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (14, 16, 16, 730, 797, 480, 285, 82, 82, 82, 82, 168, 168, 82, 70, 70, 70, 70, 70, 70, 6, 34, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (14, 17, 17, 781, 860, 510, 303, 84, 84, 84, 84, 171, 171, 84, 72, 72, 72, 72, 72, 72, 6, 35, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (14, 18, 18, 834, 925, 540, 321, 86, 86, 86, 86, 175, 175, 86, 74, 74, 74, 74, 74, 74, 6, 36, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (14, 19, 19, 888, 992, 570, 339, 88, 88, 88, 88, 178, 178, 88, 76, 76, 76, 76, 76, 76, 6, 38, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (14, 20, 20, 944, 1060, 600, 356, 95, 95, 95, 95, 182, 182, 95, 82, 82, 82, 82, 82, 82, 7, 39, 1, -18, 30, '', 0, + 16, 12, 1.25, 100, 100, 100), + (14, 21, 21, 1000, 1130, 630, 375, 97, 97, 97, 97, 185, 185, 97, 84, 84, 84, 84, 84, 84, 7, 41, 1, -18, 30, '', + 0, 16, 12, 1.25, 100, 100, 100), + (14, 22, 22, 1059, 1201, 660, 392, 100, 100, 100, 100, 189, 189, 100, 86, 86, 86, 86, 86, 86, 7, 42, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (14, 23, 23, 1119, 1274, 690, 410, 102, 102, 102, 102, 192, 192, 102, 88, 88, 88, 88, 88, 88, 7, 43, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (14, 24, 24, 1180, 1349, 720, 428, 105, 105, 105, 105, 196, 196, 105, 94, 94, 94, 94, 94, 94, 8, 45, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (14, 25, 25, 1243, 1425, 750, 446, 107, 107, 107, 107, 199, 199, 107, 96, 96, 96, 96, 96, 96, 8, 46, 1, -18, 30, + '', 0, 17, 13, 1.25, 100, 100, 100), + (14, 26, 26, 1308, 1503, 780, 463, 110, 110, 110, 110, 203, 203, 110, 98, 98, 98, 98, 98, 98, 8, 48, 1, -18, 30, + '', 0, 17, 13, 1.25, 100, 100, 100), + (14, 27, 27, 1375, 1582, 810, 482, 113, 113, 113, 113, 206, 206, 113, 100, 100, 100, 100, 100, 100, 8, 49, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (14, 28, 28, 1444, 1663, 840, 499, 116, 116, 116, 116, 210, 210, 116, 106, 106, 106, 106, 106, 106, 9, 50, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (14, 29, 29, 1514, 1746, 870, 517, 119, 119, 119, 119, 213, 213, 119, 108, 108, 108, 108, 108, 108, 9, 52, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (14, 30, 30, 1587, 1830, 900, 535, 126, 126, 126, 126, 217, 217, 126, 110, 110, 110, 110, 110, 110, 9, 53, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (14, 31, 31, 1662, 1916, 930, 553, 129, 129, 129, 129, 220, 220, 129, 112, 112, 112, 112, 112, 112, 9, 55, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (14, 32, 32, 1739, 2003, 960, 570, 133, 133, 133, 133, 224, 224, 133, 118, 118, 118, 118, 118, 118, 10, 56, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (14, 33, 33, 1818, 2092, 990, 589, 136, 136, 136, 136, 227, 227, 136, 120, 120, 120, 120, 120, 120, 10, 57, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (14, 34, 34, 1900, 2183, 1020, 606, 140, 140, 140, 140, 231, 231, 140, 122, 122, 122, 122, 122, 122, 10, 59, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (14, 35, 35, 1984, 2275, 1050, 624, 143, 143, 143, 143, 234, 234, 143, 124, 124, 124, 124, 124, 124, 10, 60, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (14, 36, 36, 2070, 2369, 1080, 642, 147, 147, 147, 147, 238, 238, 147, 130, 130, 130, 130, 130, 130, 11, 62, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (14, 37, 37, 2159, 2464, 1110, 660, 151, 151, 151, 151, 241, 241, 151, 132, 132, 132, 132, 132, 132, 11, 63, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (14, 38, 38, 2251, 2561, 1140, 677, 155, 155, 155, 155, 245, 245, 155, 134, 134, 134, 134, 134, 134, 11, 64, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (14, 39, 39, 2345, 2660, 1170, 696, 159, 159, 159, 159, 248, 248, 159, 136, 136, 136, 136, 136, 136, 11, 66, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (14, 40, 40, 2442, 2760, 1200, 713, 167, 167, 167, 167, 252, 252, 167, 142, 142, 142, 142, 142, 142, 12, 67, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (14, 41, 41, 2542, 2862, 1230, 731, 171, 171, 171, 171, 255, 255, 171, 144, 144, 144, 144, 144, 144, 12, 69, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (14, 42, 42, 2645, 2965, 1260, 749, 176, 176, 176, 176, 259, 259, 176, 146, 146, 146, 146, 146, 146, 12, 70, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (14, 43, 43, 2751, 3070, 1290, 767, 180, 180, 180, 180, 262, 262, 180, 148, 148, 148, 148, 148, 148, 12, 71, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (14, 44, 44, 2860, 3177, 1320, 784, 185, 185, 185, 185, 266, 266, 185, 154, 154, 154, 154, 154, 154, 13, 73, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (14, 45, 45, 2972, 3285, 1350, 803, 189, 189, 189, 189, 269, 269, 189, 156, 156, 156, 156, 156, 156, 13, 74, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (14, 46, 46, 3087, 3395, 1380, 820, 194, 194, 194, 194, 273, 273, 194, 158, 158, 158, 158, 158, 158, 13, 76, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (14, 47, 47, 3205, 3506, 1410, 838, 198, 198, 198, 198, 276, 276, 198, 160, 160, 160, 160, 160, 160, 13, 77, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (14, 48, 48, 3327, 3619, 1440, 856, 203, 203, 203, 203, 280, 280, 203, 166, 166, 166, 166, 166, 166, 14, 78, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (14, 49, 49, 3452, 3734, 1470, 874, 208, 208, 208, 208, 283, 283, 208, 168, 168, 168, 168, 168, 168, 14, 80, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (14, 50, 50, 3580, 3850, 1500, 891, 217, 217, 217, 217, 287, 287, 217, 170, 170, 170, 170, 170, 170, 14, 81, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (14, 51, 51, 3712, 3968, 1530, 910, 222, 222, 222, 222, 290, 290, 222, 172, 172, 172, 172, 172, 172, 14, 83, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (14, 52, 52, 3848, 4087, 1560, 927, 227, 227, 227, 227, 294, 294, 227, 178, 178, 178, 178, 178, 178, 15, 84, 1, + -18, 30, '', 0, 24, 18, 1.43, 100, 100, 100), + (14, 53, 53, 3987, 4208, 1590, 945, 232, 232, 232, 232, 297, 297, 232, 180, 180, 180, 180, 180, 180, 15, 85, 1, + -18, 30, '', 0, 24, 18, 1.43, 100, 100, 100), + (14, 54, 54, 4130, 4331, 1620, 963, 238, 238, 238, 238, 301, 301, 238, 182, 182, 182, 182, 182, 182, 15, 87, 1, + -18, 30, '', 0, 24, 18, 1.43, 100, 100, 100), + (14, 55, 55, 4277, 4455, 1650, 981, 243, 243, 243, 243, 304, 304, 243, 184, 184, 184, 184, 184, 184, 15, 88, 1, + -18, 30, '', 0, 24, 19, 1.43, 100, 100, 100), + (14, 56, 56, 4428, 4581, 1680, 998, 249, 249, 249, 249, 308, 308, 249, 190, 190, 190, 190, 190, 190, 16, 90, 1, + -18, 30, '', 0, 25, 19, 1.43, 100, 100, 100), + (14, 57, 57, 4582, 4708, 1710, 1017, 254, 254, 254, 254, 311, 311, 254, 192, 192, 192, 192, 192, 192, 16, 91, 1, + -18, 30, '', 0, 25, 19, 1.43, 100, 100, 100), + (14, 58, 58, 4741, 4837, 1740, 1034, 260, 260, 260, 260, 315, 315, 260, 194, 194, 194, 194, 194, 194, 16, 92, 1, + -18, 30, '', 0, 25, 19, 1.43, 100, 100, 100), + (14, 59, 59, 4904, 4968, 1770, 1052, 266, 266, 266, 266, 318, 318, 266, 196, 196, 196, 196, 196, 196, 16, 94, 1, + -18, 30, '', 0, 25, 19, 1.43, 100, 100, 100), + (14, 60, 60, 5071, 5100, 1800, 1070, 276, 276, 276, 276, 322, 322, 276, 202, 202, 202, 202, 202, 202, 17, 95, 1, + -18, 30, '', 0, 26, 20, 1.43, 100, 100, 100), + (14, 61, 61, 5242, 5234, 1830, 1088, 282, 282, 282, 282, 325, 325, 282, 204, 204, 204, 204, 204, 204, 17, 97, 1, + -18, 30, '', 0, 26, 20, 1.43, 100, 100, 100), + (14, 62, 62, 5417, 5369, 1860, 1105, 288, 288, 288, 288, 329, 329, 288, 206, 206, 206, 206, 206, 206, 17, 98, 1, + -18, 30, '', 0, 26, 20, 1.43, 100, 100, 100), + (14, 63, 63, 5597, 5506, 1890, 1124, 294, 294, 294, 294, 332, 332, 294, 208, 208, 208, 208, 208, 208, 17, 99, 1, + -18, 30, '', 0, 26, 20, 1.43, 100, 100, 100), + (14, 64, 64, 5782, 5645, 1920, 1141, 301, 301, 301, 301, 336, 336, 301, 214, 214, 214, 214, 214, 214, 18, 101, 1, + -18, 30, '', 0, 27, 20, 1.43, 100, 100, 100), + (14, 65, 65, 5970, 5785, 1950, 1159, 307, 307, 307, 307, 339, 339, 307, 216, 216, 216, 216, 216, 216, 18, 102, 1, + -18, 30, '', 0, 27, 21, 1.43, 100, 100, 100), + (14, 66, 66, 6164, 5927, 1980, 1177, 344, 344, 344, 344, 373, 373, 344, 218, 218, 218, 218, 218, 218, 18, 104, 1, + -18, 30, '', 0, 27, 21, 1.43, 100, 100, 100), + (14, 67, 67, 6362, 6070, 2010, 1195, 355, 355, 355, 355, 381, 381, 355, 220, 220, 220, 220, 220, 220, 18, 105, 1, + -18, 30, '', 0, 27, 21, 1.43, 100, 100, 100), + (14, 68, 68, 6565, 6215, 2040, 1212, 367, 367, 367, 367, 390, 390, 367, 226, 226, 226, 226, 226, 226, 19, 106, 1, + -18, 30, '', 0, 28, 21, 1.43, 100, 100, 100), + (14, 69, 69, 6772, 6362, 2070, 1231, 378, 378, 378, 378, 398, 398, 378, 228, 228, 228, 228, 228, 228, 19, 108, 1, + -18, 30, '', 0, 28, 21, 1.43, 100, 100, 100), + (14, 70, 70, 6985, 6510, 2100, 1248, 394, 394, 394, 394, 407, 407, 394, 230, 230, 230, 230, 230, 230, 19, 109, 1, + -18, 30, '', 0, 28, 22, 1.43, 100, 100, 100), + (14, 71, 71, 7202, 6660, 2130, 1266, 406, 406, 406, 406, 415, 415, 406, 232, 232, 232, 232, 232, 232, 19, 111, 1, + -18, 30, '', 0, 28, 22, 1.43, 100, 100, 100), + (14, 72, 72, 7425, 6811, 2160, 1284, 418, 418, 418, 418, 424, 424, 418, 238, 238, 238, 238, 238, 238, 20, 112, 1, + -18, 30, '', 0, 29, 22, 1.43, 100, 100, 100), + (14, 73, 73, 7652, 6964, 2190, 1302, 430, 430, 430, 430, 432, 432, 430, 240, 240, 240, 240, 240, 240, 20, 113, 1, + -18, 30, '', 0, 29, 22, 1.43, 100, 100, 100), + (14, 74, 74, 7885, 7119, 2220, 1319, 442, 442, 442, 442, 441, 441, 442, 242, 242, 242, 242, 242, 242, 20, 115, 1, + -18, 30, '', 0, 29, 22, 1.43, 100, 100, 100), + (14, 75, 75, 8123, 7275, 2250, 1338, 454, 454, 454, 454, 449, 449, 454, 244, 244, 244, 244, 244, 244, 20, 116, 1, + -18, 30, '', 0, 29, 23, 1.43, 100, 100, 100), + (14, 76, 76, 8366, 7433, 2280, 1355, 467, 467, 467, 467, 458, 458, 467, 250, 250, 250, 250, 250, 250, 21, 118, 1, + -18, 30, '', 0, 30, 23, 1.43, 100, 100, 100), + (14, 77, 77, 8614, 7592, 2310, 1373, 479, 479, 479, 479, 466, 466, 479, 252, 252, 252, 252, 252, 252, 21, 119, 1, + -18, 30, '', 0, 30, 23, 1.43, 100, 100, 100), + (14, 78, 78, 8868, 7753, 2340, 1391, 492, 492, 492, 492, 475, 475, 492, 254, 254, 254, 254, 254, 254, 21, 120, 1, + -18, 30, '', 0, 30, 23, 1.43, 100, 100, 100), + (14, 79, 79, 9128, 7916, 2370, 1409, 504, 504, 504, 504, 483, 483, 504, 256, 256, 256, 256, 256, 256, 21, 122, 1, + -18, 30, '', 0, 30, 23, 1.43, 100, 100, 100), + (14, 80, 80, 9393, 8080, 2400, 1426, 521, 521, 521, 521, 492, 492, 521, 262, 262, 262, 262, 262, 262, 22, 123, 1, + -18, 30, '', 0, 31, 24, 1.43, 100, 100, 100), + (14, 81, 81, 9664, 8246, 2430, 1445, 534, 534, 534, 534, 500, 500, 534, 264, 264, 264, 264, 264, 264, 22, 125, 1, + -18, 30, '', 0, 31, 24, 1.43, 100, 100, 100), + (14, 82, 82, 9940, 8413, 2460, 1462, 547, 547, 547, 547, 509, 509, 547, 266, 266, 266, 266, 266, 266, 22, 126, 1, + -18, 30, '', 0, 31, 24, 1.43, 100, 100, 100), + (14, 83, 83, 10222, 8582, 2490, 1480, 560, 560, 560, 560, 517, 517, 560, 268, 268, 268, 268, 268, 268, 22, 127, + 1, -18, 30, '', 0, 31, 24, 1.43, 100, 100, 100), + (14, 84, 84, 10510, 8753, 2520, 1498, 573, 573, 573, 573, 526, 526, 573, 274, 274, 274, 274, 274, 274, 23, 129, + 1, -18, 30, '', 0, 32, 24, 1.43, 100, 100, 100), + (14, 85, 85, 10805, 8925, 2550, 1516, 586, 586, 586, 586, 534, 534, 586, 276, 276, 276, 276, 276, 276, 23, 130, + 1, -18, 30, '', 0, 32, 25, 1.43, 100, 100, 100), + (15, 1, 1, 55, 41, 31, 18, 60, 60, 60, 60, 118, 118, 60, 27, 27, 27, 27, 27, 27, 2, 14, 1, -18, 30, '', 0, 12, 9, + 1.25, 100, 100, 100), + (15, 2, 2, 100, 83, 62, 36, 61, 61, 61, 61, 122, 122, 61, 29, 29, 29, 29, 29, 29, 2, 15, 1, -18, 30, '', 0, 12, + 9, 1.25, 100, 100, 100), + (15, 3, 3, 145, 127, 93, 55, 61, 61, 61, 61, 125, 125, 61, 31, 31, 31, 31, 31, 31, 3, 17, 1, -18, 30, '', 0, 12, + 9, 1.25, 100, 100, 100), + (15, 4, 4, 190, 173, 124, 72, 62, 62, 62, 62, 129, 129, 62, 38, 38, 38, 38, 38, 38, 3, 18, 1, -18, 30, '', 0, 13, + 9, 1.25, 100, 100, 100), + (15, 5, 5, 236, 220, 155, 91, 63, 63, 63, 63, 132, 132, 63, 40, 40, 40, 40, 40, 40, 3, 20, 1, -18, 30, '', 0, 13, + 10, 1.25, 100, 100, 100), + (15, 6, 6, 282, 269, 186, 109, 64, 64, 64, 64, 136, 136, 64, 42, 42, 42, 42, 42, 42, 3, 21, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (15, 7, 7, 329, 319, 217, 127, 65, 65, 65, 65, 139, 139, 65, 44, 44, 44, 44, 44, 44, 4, 22, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (15, 8, 8, 376, 371, 248, 145, 66, 66, 66, 66, 143, 143, 66, 51, 51, 51, 51, 51, 51, 4, 24, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (15, 9, 9, 423, 425, 279, 164, 67, 67, 67, 67, 146, 146, 67, 53, 53, 53, 53, 53, 53, 4, 25, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (15, 10, 10, 471, 480, 310, 181, 74, 74, 74, 74, 150, 150, 74, 55, 55, 55, 55, 55, 55, 4, 27, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (15, 11, 11, 520, 537, 341, 200, 75, 75, 75, 75, 153, 153, 75, 57, 57, 57, 57, 57, 57, 5, 28, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (15, 12, 12, 570, 595, 372, 218, 77, 77, 77, 77, 157, 157, 77, 64, 64, 64, 64, 64, 64, 5, 29, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (15, 13, 13, 620, 655, 403, 236, 78, 78, 78, 78, 160, 160, 78, 66, 66, 66, 66, 66, 66, 5, 31, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (15, 14, 14, 672, 717, 434, 254, 80, 80, 80, 80, 164, 164, 80, 68, 68, 68, 68, 68, 68, 5, 32, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (15, 15, 15, 724, 780, 465, 273, 82, 82, 82, 82, 167, 167, 82, 70, 70, 70, 70, 70, 70, 6, 34, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (15, 16, 16, 778, 845, 496, 290, 84, 84, 84, 84, 171, 171, 84, 77, 77, 77, 77, 77, 77, 6, 35, 1, -18, 30, '', 0, + 16, 12, 1.25, 100, 100, 100), + (15, 17, 17, 832, 911, 527, 309, 86, 86, 86, 86, 174, 174, 86, 79, 79, 79, 79, 79, 79, 6, 36, 1, -18, 30, '', 0, + 16, 12, 1.25, 100, 100, 100), + (15, 18, 18, 888, 979, 558, 327, 88, 88, 88, 88, 178, 178, 88, 81, 81, 81, 81, 81, 81, 6, 38, 1, -18, 30, '', 0, + 16, 12, 1.25, 100, 100, 100), + (15, 19, 19, 945, 1049, 589, 345, 90, 90, 90, 90, 181, 181, 90, 83, 83, 83, 83, 83, 83, 7, 39, 1, -18, 30, '', 0, + 16, 12, 1.25, 100, 100, 100), + (15, 20, 20, 1004, 1120, 620, 363, 98, 98, 98, 98, 185, 185, 98, 90, 90, 90, 90, 90, 90, 7, 41, 1, -18, 30, '', + 0, 17, 13, 1.25, 100, 100, 100), + (15, 21, 21, 1063, 1193, 651, 382, 100, 100, 100, 100, 188, 188, 100, 92, 92, 92, 92, 92, 92, 7, 42, 1, -18, 30, + '', 0, 17, 13, 1.25, 100, 100, 100), + (15, 22, 22, 1125, 1267, 682, 399, 103, 103, 103, 103, 192, 192, 103, 94, 94, 94, 94, 94, 94, 7, 43, 1, -18, 30, + '', 0, 17, 13, 1.25, 100, 100, 100), + (15, 23, 23, 1188, 1343, 713, 418, 105, 105, 105, 105, 195, 195, 105, 96, 96, 96, 96, 96, 96, 8, 45, 1, -18, 30, + '', 0, 17, 13, 1.25, 100, 100, 100), + (15, 24, 24, 1252, 1421, 744, 436, 108, 108, 108, 108, 199, 199, 108, 103, 103, 103, 103, 103, 103, 8, 46, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (15, 25, 25, 1318, 1500, 775, 454, 110, 110, 110, 110, 202, 202, 110, 105, 105, 105, 105, 105, 105, 8, 48, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (15, 26, 26, 1386, 1581, 806, 472, 113, 113, 113, 113, 206, 206, 113, 107, 107, 107, 107, 107, 107, 8, 49, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (15, 27, 27, 1456, 1663, 837, 491, 116, 116, 116, 116, 209, 209, 116, 109, 109, 109, 109, 109, 109, 9, 50, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (15, 28, 28, 1528, 1747, 868, 508, 119, 119, 119, 119, 213, 213, 119, 116, 116, 116, 116, 116, 116, 9, 52, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (15, 29, 29, 1601, 1833, 899, 527, 122, 122, 122, 122, 216, 216, 122, 118, 118, 118, 118, 118, 118, 9, 53, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (15, 30, 30, 1677, 1920, 930, 545, 130, 130, 130, 130, 220, 220, 130, 120, 120, 120, 120, 120, 120, 9, 55, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (15, 31, 31, 1755, 2009, 961, 563, 133, 133, 133, 133, 223, 223, 133, 122, 122, 122, 122, 122, 122, 10, 56, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (15, 32, 32, 1835, 2099, 992, 581, 137, 137, 137, 137, 227, 227, 137, 129, 129, 129, 129, 129, 129, 10, 57, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (15, 33, 33, 1917, 2191, 1023, 600, 140, 140, 140, 140, 230, 230, 140, 131, 131, 131, 131, 131, 131, 10, 59, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (15, 34, 34, 2002, 2285, 1054, 617, 144, 144, 144, 144, 234, 234, 144, 133, 133, 133, 133, 133, 133, 10, 60, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (15, 35, 35, 2089, 2380, 1085, 636, 147, 147, 147, 147, 237, 237, 147, 135, 135, 135, 135, 135, 135, 11, 62, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (15, 36, 36, 2178, 2477, 1116, 654, 151, 151, 151, 151, 241, 241, 151, 142, 142, 142, 142, 142, 142, 11, 63, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (15, 37, 37, 2270, 2575, 1147, 672, 155, 155, 155, 155, 244, 244, 155, 144, 144, 144, 144, 144, 144, 11, 64, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (15, 38, 38, 2365, 2675, 1178, 690, 159, 159, 159, 159, 248, 248, 159, 146, 146, 146, 146, 146, 146, 11, 66, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (15, 39, 39, 2462, 2777, 1209, 709, 163, 163, 163, 163, 251, 251, 163, 148, 148, 148, 148, 148, 148, 12, 67, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (15, 40, 40, 2562, 2880, 1240, 726, 172, 172, 172, 172, 255, 255, 172, 155, 155, 155, 155, 155, 155, 12, 69, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (15, 41, 41, 2665, 2985, 1271, 745, 176, 176, 176, 176, 258, 258, 176, 157, 157, 157, 157, 157, 157, 12, 70, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (15, 42, 42, 2771, 3091, 1302, 763, 181, 181, 181, 181, 262, 262, 181, 159, 159, 159, 159, 159, 159, 12, 71, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (15, 43, 43, 2880, 3199, 1333, 781, 185, 185, 185, 185, 265, 265, 185, 161, 161, 161, 161, 161, 161, 13, 73, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (15, 44, 44, 2992, 3309, 1364, 799, 190, 190, 190, 190, 269, 269, 190, 168, 168, 168, 168, 168, 168, 13, 74, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (15, 45, 45, 3107, 3420, 1395, 818, 194, 194, 194, 194, 272, 272, 194, 170, 170, 170, 170, 170, 170, 13, 76, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (15, 46, 46, 3225, 3533, 1426, 835, 199, 199, 199, 199, 276, 276, 199, 172, 172, 172, 172, 172, 172, 13, 77, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (15, 47, 47, 3346, 3647, 1457, 854, 203, 203, 203, 203, 279, 279, 203, 174, 174, 174, 174, 174, 174, 14, 78, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (15, 48, 48, 3471, 3763, 1488, 872, 208, 208, 208, 208, 283, 283, 208, 181, 181, 181, 181, 181, 181, 14, 80, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (15, 49, 49, 3599, 3881, 1519, 890, 213, 213, 213, 213, 286, 286, 213, 183, 183, 183, 183, 183, 183, 14, 81, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (15, 50, 50, 3730, 4000, 1550, 908, 223, 223, 223, 223, 290, 290, 223, 185, 185, 185, 185, 185, 185, 14, 83, 1, + -18, 30, '', 0, 24, 19, 1.25, 100, 100, 100), + (15, 51, 51, 3865, 4121, 1581, 927, 228, 228, 228, 228, 293, 293, 228, 187, 187, 187, 187, 187, 187, 15, 84, 1, + -18, 30, '', 0, 24, 19, 1.25, 100, 100, 100), + (15, 52, 52, 4004, 4243, 1612, 944, 233, 233, 233, 233, 297, 297, 233, 194, 194, 194, 194, 194, 194, 15, 85, 1, + -18, 30, '', 0, 25, 19, 1.49, 100, 100, 100), + (15, 53, 53, 4146, 4367, 1643, 963, 238, 238, 238, 238, 300, 300, 238, 196, 196, 196, 196, 196, 196, 15, 87, 1, + -18, 30, '', 0, 25, 19, 1.49, 100, 100, 100), + (15, 54, 54, 4292, 4493, 1674, 981, 244, 244, 244, 244, 304, 304, 244, 198, 198, 198, 198, 198, 198, 15, 88, 1, + -18, 30, '', 0, 25, 19, 1.49, 100, 100, 100), + (15, 55, 55, 4442, 4620, 1705, 999, 249, 249, 249, 249, 307, 307, 249, 200, 200, 200, 200, 200, 200, 16, 90, 1, + -18, 30, '', 0, 25, 20, 1.49, 100, 100, 100), + (15, 56, 56, 4596, 4749, 1736, 1017, 255, 255, 255, 255, 311, 311, 255, 207, 207, 207, 207, 207, 207, 16, 91, 1, + -18, 30, '', 0, 26, 20, 1.49, 100, 100, 100), + (15, 57, 57, 4753, 4879, 1767, 1036, 260, 260, 260, 260, 314, 314, 260, 209, 209, 209, 209, 209, 209, 16, 92, 1, + -18, 30, '', 0, 26, 20, 1.49, 100, 100, 100), + (15, 58, 58, 4915, 5011, 1798, 1053, 266, 266, 266, 266, 318, 318, 266, 211, 211, 211, 211, 211, 211, 16, 94, 1, + -18, 30, '', 0, 26, 20, 1.49, 100, 100, 100), + (15, 59, 59, 5081, 5145, 1829, 1072, 272, 272, 272, 272, 321, 321, 272, 213, 213, 213, 213, 213, 213, 17, 95, 1, + -18, 30, '', 0, 26, 20, 1.49, 100, 100, 100), + (15, 60, 60, 5251, 5280, 1860, 1090, 283, 283, 283, 283, 325, 325, 283, 220, 220, 220, 220, 220, 220, 17, 97, 1, + -18, 30, '', 0, 27, 21, 1.49, 100, 100, 100), + (15, 61, 61, 5425, 5417, 1891, 1108, 289, 289, 289, 289, 328, 328, 289, 222, 222, 222, 222, 222, 222, 17, 98, 1, + -18, 30, '', 0, 27, 21, 1.49, 100, 100, 100), + (15, 62, 62, 5603, 5555, 1922, 1126, 295, 295, 295, 295, 332, 332, 295, 224, 224, 224, 224, 224, 224, 17, 99, 1, + -18, 30, '', 0, 27, 21, 1.49, 100, 100, 100), + (15, 63, 63, 5786, 5695, 1953, 1145, 301, 301, 301, 301, 335, 335, 301, 226, 226, 226, 226, 226, 226, 18, 101, 1, + -18, 30, '', 0, 27, 21, 1.49, 100, 100, 100), + (15, 64, 64, 5974, 5837, 1984, 1162, 308, 308, 308, 308, 339, 339, 308, 233, 233, 233, 233, 233, 233, 18, 102, 1, + -18, 30, '', 0, 28, 21, 1.49, 100, 100, 100), + (15, 65, 65, 6165, 5980, 2015, 1181, 314, 314, 314, 314, 342, 342, 314, 235, 235, 235, 235, 235, 235, 18, 104, 1, + -18, 30, '', 0, 28, 22, 1.49, 100, 100, 100), + (15, 66, 66, 6362, 6125, 2046, 1199, 351, 351, 351, 351, 376, 376, 351, 237, 237, 237, 237, 237, 237, 18, 105, 1, + -18, 30, '', 0, 28, 22, 1.49, 100, 100, 100), + (15, 67, 67, 6563, 6271, 2077, 1217, 362, 362, 362, 362, 384, 384, 362, 239, 239, 239, 239, 239, 239, 19, 106, 1, + -18, 30, '', 0, 28, 22, 1.49, 100, 100, 100), + (15, 68, 68, 6769, 6419, 2108, 1235, 374, 374, 374, 374, 393, 393, 374, 246, 246, 246, 246, 246, 246, 19, 108, 1, + -18, 30, '', 0, 29, 22, 1.49, 100, 100, 100), + (15, 69, 69, 6979, 6569, 2139, 1254, 385, 385, 385, 385, 401, 401, 385, 248, 248, 248, 248, 248, 248, 19, 109, 1, + -18, 30, '', 0, 29, 22, 1.49, 100, 100, 100), + (15, 70, 70, 7195, 6720, 2170, 1271, 402, 402, 402, 402, 410, 410, 402, 250, 250, 250, 250, 250, 250, 19, 111, 1, + -18, 30, '', 0, 29, 23, 1.49, 100, 100, 100), + (15, 71, 71, 7415, 6873, 2201, 1290, 414, 414, 414, 414, 418, 418, 414, 252, 252, 252, 252, 252, 252, 20, 112, 1, + -18, 30, '', 0, 29, 23, 1.49, 100, 100, 100), + (15, 72, 72, 7641, 7027, 2232, 1308, 426, 426, 426, 426, 427, 427, 426, 259, 259, 259, 259, 259, 259, 20, 113, 1, + -18, 30, '', 0, 30, 23, 1.49, 100, 100, 100), + (15, 73, 73, 7871, 7183, 2263, 1326, 438, 438, 438, 438, 435, 435, 438, 261, 261, 261, 261, 261, 261, 20, 115, 1, + -18, 30, '', 0, 30, 23, 1.49, 100, 100, 100), + (15, 74, 74, 8107, 7341, 2294, 1344, 450, 450, 450, 450, 444, 444, 450, 263, 263, 263, 263, 263, 263, 20, 116, 1, + -18, 30, '', 0, 30, 23, 1.49, 100, 100, 100), + (15, 75, 75, 8348, 7500, 2325, 1363, 462, 462, 462, 462, 452, 452, 462, 265, 265, 265, 265, 265, 265, 21, 118, 1, + -18, 30, '', 0, 30, 24, 1.49, 100, 100, 100), + (15, 76, 76, 8594, 7661, 2356, 1380, 475, 475, 475, 475, 461, 461, 475, 272, 272, 272, 272, 272, 272, 21, 119, 1, + -18, 30, '', 0, 31, 24, 1.49, 100, 100, 100), + (15, 77, 77, 8845, 7823, 2387, 1399, 487, 487, 487, 487, 469, 469, 487, 274, 274, 274, 274, 274, 274, 21, 120, 1, + -18, 30, '', 0, 31, 24, 1.49, 100, 100, 100), + (15, 78, 78, 9102, 7987, 2418, 1417, 500, 500, 500, 500, 478, 478, 500, 276, 276, 276, 276, 276, 276, 21, 122, 1, + -18, 30, '', 0, 31, 24, 1.49, 100, 100, 100), + (15, 79, 79, 9365, 8153, 2449, 1435, 512, 512, 512, 512, 486, 486, 512, 278, 278, 278, 278, 278, 278, 22, 123, 1, + -18, 30, '', 0, 31, 24, 1.49, 100, 100, 100), + (15, 80, 80, 9633, 8320, 2480, 1453, 530, 530, 530, 530, 495, 495, 530, 285, 285, 285, 285, 285, 285, 22, 125, 1, + -18, 30, '', 0, 32, 25, 1.49, 100, 100, 100), + (15, 81, 81, 9907, 8489, 2511, 1472, 543, 543, 543, 543, 503, 503, 543, 287, 287, 287, 287, 287, 287, 22, 126, 1, + -18, 30, '', 0, 32, 25, 1.49, 100, 100, 100), + (15, 82, 82, 10186, 8659, 2542, 1489, 556, 556, 556, 556, 512, 512, 556, 289, 289, 289, 289, 289, 289, 22, 127, + 1, -18, 30, '', 0, 32, 25, 1.49, 100, 100, 100), + (15, 83, 83, 10471, 8831, 2573, 1508, 569, 569, 569, 569, 520, 520, 569, 291, 291, 291, 291, 291, 291, 23, 129, + 1, -18, 30, '', 0, 32, 25, 1.49, 100, 100, 100), + (15, 84, 84, 10762, 9005, 2604, 1526, 582, 582, 582, 582, 529, 529, 582, 298, 298, 298, 298, 298, 298, 23, 130, + 1, -18, 30, '', 0, 33, 25, 1.49, 100, 100, 100), + (15, 85, 85, 11060, 9180, 2635, 1544, 595, 595, 595, 595, 537, 537, 595, 300, 300, 300, 300, 300, 300, 23, 132, + 1, -18, 30, '', 0, 33, 26, 1.49, 100, 100, 100), + (16, 1, 1, 73, 54, 33, 18, 61, 61, 61, 61, 131, 131, 61, 31, 31, 31, 31, 31, 31, 2, 13, 1, -18, 30, '', 0, 14, 8, + 1.25, 100, 100, 100), + (16, 2, 2, 136, 109, 66, 36, 63, 63, 63, 63, 135, 135, 63, 35, 35, 35, 35, 35, 35, 2, 14, 1, -18, 30, '', 0, 14, + 8, 1.25, 100, 100, 100), + (16, 3, 3, 199, 166, 99, 55, 63, 63, 63, 63, 138, 138, 63, 37, 37, 37, 37, 37, 37, 2, 15, 1, -18, 30, '', 0, 14, + 8, 1.25, 100, 100, 100), + (16, 4, 4, 262, 225, 132, 73, 65, 65, 65, 65, 142, 142, 65, 40, 40, 40, 40, 40, 40, 3, 17, 1, -18, 30, '', 0, 15, + 8, 1.25, 100, 100, 100), + (16, 5, 5, 326, 285, 165, 91, 66, 66, 66, 66, 145, 145, 66, 44, 44, 44, 44, 44, 44, 3, 18, 1, -18, 30, '', 0, 15, + 9, 1.25, 100, 100, 100), + (16, 6, 6, 390, 347, 198, 110, 68, 68, 68, 68, 149, 149, 68, 46, 46, 46, 46, 46, 46, 3, 20, 1, -18, 30, '', 0, + 15, 9, 1.25, 100, 100, 100), + (16, 7, 7, 455, 410, 231, 128, 69, 69, 69, 69, 152, 152, 69, 48, 48, 48, 48, 48, 48, 3, 21, 1, -18, 30, '', 0, + 15, 9, 1.25, 100, 100, 100), + (16, 8, 8, 520, 475, 264, 146, 71, 71, 71, 71, 156, 156, 71, 53, 53, 53, 53, 53, 53, 4, 22, 1, -18, 30, '', 0, + 16, 9, 1.25, 100, 100, 100), + (16, 9, 9, 585, 542, 297, 165, 72, 72, 72, 72, 159, 159, 72, 55, 55, 55, 55, 55, 55, 4, 24, 1, -18, 30, '', 0, + 16, 9, 1.25, 100, 100, 100), + (16, 10, 10, 651, 610, 330, 183, 76, 76, 76, 76, 163, 163, 76, 57, 57, 57, 57, 57, 57, 4, 25, 1, -18, 30, '', 0, + 16, 10, 1.25, 100, 100, 100), + (16, 11, 11, 718, 680, 363, 201, 77, 77, 77, 77, 166, 166, 77, 61, 61, 61, 61, 61, 61, 4, 27, 1, -18, 30, '', 0, + 16, 10, 1.25, 100, 100, 100), + (16, 12, 12, 786, 751, 396, 220, 80, 80, 80, 80, 170, 170, 80, 64, 64, 64, 64, 64, 64, 5, 28, 1, -18, 30, '', 0, + 17, 10, 1.25, 100, 100, 100), + (16, 13, 13, 854, 824, 429, 238, 81, 81, 81, 81, 173, 173, 81, 66, 66, 66, 66, 66, 66, 5, 29, 1, -18, 30, '', 0, + 17, 10, 1.25, 100, 100, 100), + (16, 14, 14, 924, 899, 462, 256, 84, 84, 84, 84, 177, 177, 84, 70, 70, 70, 70, 70, 70, 5, 31, 1, -18, 30, '', 0, + 17, 10, 1.25, 100, 100, 100), + (16, 15, 15, 994, 975, 495, 275, 86, 86, 86, 86, 180, 180, 86, 72, 72, 72, 72, 72, 72, 5, 32, 1, -18, 30, '', 0, + 17, 11, 1.25, 100, 100, 100), + (16, 16, 16, 1066, 1053, 528, 293, 89, 89, 89, 89, 184, 184, 89, 75, 75, 75, 75, 75, 75, 6, 34, 1, -18, 30, '', + 0, 18, 11, 1.25, 100, 100, 100), + (16, 17, 17, 1138, 1132, 561, 311, 91, 91, 91, 91, 187, 187, 91, 79, 79, 79, 79, 79, 79, 6, 35, 1, -18, 30, '', + 0, 18, 11, 1.25, 100, 100, 100), + (16, 18, 18, 1212, 1213, 594, 330, 94, 94, 94, 94, 191, 191, 94, 81, 81, 81, 81, 81, 81, 6, 36, 1, -18, 30, '', + 0, 18, 11, 1.25, 100, 100, 100), + (16, 19, 19, 1287, 1296, 627, 348, 96, 96, 96, 96, 194, 194, 96, 83, 83, 83, 83, 83, 83, 6, 38, 1, -18, 30, '', + 0, 18, 11, 1.25, 100, 100, 100), + (16, 20, 20, 1364, 1380, 660, 366, 101, 101, 101, 101, 198, 198, 101, 88, 88, 88, 88, 88, 88, 7, 39, 1, -18, 30, + '', 0, 19, 12, 1.25, 100, 100, 100), + (16, 21, 21, 1441, 1466, 693, 385, 103, 103, 103, 103, 201, 201, 103, 90, 90, 90, 90, 90, 90, 7, 41, 1, -18, 30, + '', 0, 19, 12, 1.25, 100, 100, 100), + (16, 22, 22, 1521, 1553, 726, 403, 107, 107, 107, 107, 205, 205, 107, 92, 92, 92, 92, 92, 92, 7, 42, 1, -18, 30, + '', 0, 19, 12, 1.25, 100, 100, 100), + (16, 23, 23, 1602, 1642, 759, 421, 109, 109, 109, 109, 208, 208, 109, 96, 96, 96, 96, 96, 96, 7, 43, 1, -18, 30, + '', 0, 19, 12, 1.25, 100, 100, 100), + (16, 24, 24, 1684, 1733, 792, 440, 113, 113, 113, 113, 212, 212, 113, 99, 99, 99, 99, 99, 99, 8, 45, 1, -18, 30, + '', 0, 20, 12, 1.25, 100, 100, 100), + (16, 25, 25, 1768, 1825, 825, 458, 115, 115, 115, 115, 215, 215, 115, 101, 101, 101, 101, 101, 101, 8, 46, 1, + -18, 30, '', 0, 20, 13, 1.25, 100, 100, 100), + (16, 26, 26, 1854, 1919, 858, 476, 119, 119, 119, 119, 219, 219, 119, 105, 105, 105, 105, 105, 105, 8, 48, 1, + -18, 30, '', 0, 20, 13, 1.25, 100, 100, 100), + (16, 27, 27, 1942, 2014, 891, 495, 122, 122, 122, 122, 222, 222, 122, 107, 107, 107, 107, 107, 107, 8, 49, 1, + -18, 30, '', 0, 20, 13, 1.25, 100, 100, 100), + (16, 28, 28, 2032, 2111, 924, 513, 126, 126, 126, 126, 226, 226, 126, 110, 110, 110, 110, 110, 110, 9, 50, 1, + -18, 30, '', 0, 21, 13, 1.25, 100, 100, 100), + (16, 29, 29, 2123, 2210, 957, 531, 129, 129, 129, 129, 229, 229, 129, 114, 114, 114, 114, 114, 114, 9, 52, 1, + -18, 30, '', 0, 21, 13, 1.25, 100, 100, 100), + (16, 30, 30, 2217, 2310, 990, 550, 134, 134, 134, 134, 233, 233, 134, 116, 116, 116, 116, 116, 116, 9, 53, 1, + -18, 30, '', 0, 21, 14, 1.25, 100, 100, 100), + (16, 31, 31, 2313, 2412, 1023, 568, 137, 137, 137, 137, 236, 236, 137, 118, 118, 118, 118, 118, 118, 9, 55, 1, + -18, 30, '', 0, 21, 14, 1.25, 100, 100, 100), + (16, 32, 32, 2411, 2515, 1056, 586, 142, 142, 142, 142, 240, 240, 142, 123, 123, 123, 123, 123, 123, 10, 56, 1, + -18, 30, '', 0, 22, 14, 1.25, 100, 100, 100), + (16, 33, 33, 2511, 2620, 1089, 605, 145, 145, 145, 145, 243, 243, 145, 125, 125, 125, 125, 125, 125, 10, 57, 1, + -18, 30, '', 0, 22, 14, 1.25, 100, 100, 100), + (16, 34, 34, 2614, 2727, 1122, 623, 150, 150, 150, 150, 247, 247, 150, 127, 127, 127, 127, 127, 127, 10, 59, 1, + -18, 30, '', 0, 22, 14, 1.25, 100, 100, 100), + (16, 35, 35, 2719, 2835, 1155, 641, 153, 153, 153, 153, 250, 250, 153, 131, 131, 131, 131, 131, 131, 10, 60, 1, + -18, 30, '', 0, 22, 15, 1.25, 100, 100, 100), + (16, 36, 36, 2826, 2945, 1188, 660, 158, 158, 158, 158, 254, 254, 158, 134, 134, 134, 134, 134, 134, 11, 62, 1, + -18, 30, '', 0, 23, 15, 1.25, 100, 100, 100), + (16, 37, 37, 2936, 3056, 1221, 678, 162, 162, 162, 162, 257, 257, 162, 136, 136, 136, 136, 136, 136, 11, 63, 1, + -18, 30, '', 0, 23, 15, 1.25, 100, 100, 100), + (16, 38, 38, 3049, 3169, 1254, 696, 167, 167, 167, 167, 261, 261, 167, 140, 140, 140, 140, 140, 140, 11, 64, 1, + -18, 30, '', 0, 23, 15, 1.25, 100, 100, 100), + (16, 39, 39, 3164, 3284, 1287, 715, 171, 171, 171, 171, 264, 264, 171, 142, 142, 142, 142, 142, 142, 11, 66, 1, + -18, 30, '', 0, 23, 15, 1.25, 100, 100, 100), + (16, 40, 40, 3282, 3400, 1320, 733, 177, 177, 177, 177, 268, 268, 177, 145, 145, 145, 145, 145, 145, 12, 67, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (16, 41, 41, 3403, 3518, 1353, 751, 181, 181, 181, 181, 271, 271, 181, 149, 149, 149, 149, 149, 149, 12, 69, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (16, 42, 42, 3527, 3637, 1386, 770, 187, 187, 187, 187, 275, 275, 187, 151, 151, 151, 151, 151, 151, 12, 70, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (16, 43, 43, 3654, 3758, 1419, 788, 191, 191, 191, 191, 278, 278, 191, 153, 153, 153, 153, 153, 153, 12, 71, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (16, 44, 44, 3784, 3881, 1452, 806, 197, 197, 197, 197, 282, 282, 197, 158, 158, 158, 158, 158, 158, 13, 73, 1, + -18, 30, '', 0, 25, 16, 1.25, 100, 100, 100), + (16, 45, 45, 3917, 4005, 1485, 825, 201, 201, 201, 201, 285, 285, 201, 160, 160, 160, 160, 160, 160, 13, 74, 1, + -18, 30, '', 0, 25, 17, 1.25, 100, 100, 100), + (16, 46, 46, 4053, 4131, 1518, 843, 207, 207, 207, 207, 289, 289, 207, 162, 162, 162, 162, 162, 162, 13, 76, 1, + -18, 30, '', 0, 25, 17, 1.25, 100, 100, 100), + (16, 47, 47, 4192, 4258, 1551, 861, 211, 211, 211, 211, 292, 292, 211, 166, 166, 166, 166, 166, 166, 13, 77, 1, + -18, 30, '', 0, 25, 17, 1.25, 100, 100, 100), + (16, 48, 48, 4335, 4387, 1584, 880, 217, 217, 217, 217, 296, 296, 217, 169, 169, 169, 169, 169, 169, 14, 78, 1, + -18, 30, '', 0, 26, 17, 1.25, 100, 100, 100), + (16, 49, 49, 4481, 4518, 1617, 898, 222, 222, 222, 222, 299, 299, 222, 171, 171, 171, 171, 171, 171, 14, 80, 1, + -18, 30, '', 0, 26, 17, 1.25, 100, 100, 100), + (16, 50, 50, 4630, 4650, 1650, 916, 229, 229, 229, 229, 303, 303, 229, 175, 175, 175, 175, 175, 175, 14, 81, 1, + -18, 30, '', 0, 26, 18, 1.25, 100, 100, 100), + (16, 51, 51, 4783, 4784, 1683, 935, 234, 234, 234, 234, 306, 306, 234, 177, 177, 177, 177, 177, 177, 14, 83, 1, + -18, 30, '', 0, 26, 18, 1.25, 100, 100, 100), + (16, 52, 52, 4940, 4919, 1716, 953, 240, 240, 240, 240, 310, 310, 240, 180, 180, 180, 180, 180, 180, 15, 84, 1, + -18, 30, '', 0, 27, 18, 1.55, 100, 100, 100), + (16, 53, 53, 5100, 5056, 1749, 971, 245, 245, 245, 245, 313, 313, 245, 184, 184, 184, 184, 184, 184, 15, 85, 1, + -18, 30, '', 0, 27, 18, 1.55, 100, 100, 100), + (16, 54, 54, 5264, 5195, 1782, 990, 252, 252, 252, 252, 317, 317, 252, 186, 186, 186, 186, 186, 186, 15, 87, 1, + -18, 30, '', 0, 27, 18, 1.55, 100, 100, 100), + (16, 55, 55, 5432, 5335, 1815, 1008, 257, 257, 257, 257, 320, 320, 257, 188, 188, 188, 188, 188, 188, 15, 88, 1, + -18, 30, '', 0, 27, 19, 1.55, 100, 100, 100), + (16, 56, 56, 5604, 5477, 1848, 1026, 264, 264, 264, 264, 324, 324, 264, 193, 193, 193, 193, 193, 193, 16, 90, 1, + -18, 30, '', 0, 28, 19, 1.55, 100, 100, 100), + (16, 57, 57, 5779, 5620, 1881, 1045, 269, 269, 269, 269, 327, 327, 269, 195, 195, 195, 195, 195, 195, 16, 91, 1, + -18, 30, '', 0, 28, 19, 1.55, 100, 100, 100), + (16, 58, 58, 5959, 5765, 1914, 1063, 276, 276, 276, 276, 331, 331, 276, 197, 197, 197, 197, 197, 197, 16, 92, 1, + -18, 30, '', 0, 28, 19, 1.55, 100, 100, 100), + (16, 59, 59, 6143, 5912, 1947, 1081, 282, 282, 282, 282, 334, 334, 282, 201, 201, 201, 201, 201, 201, 16, 94, 1, + -18, 30, '', 0, 28, 19, 1.55, 100, 100, 100), + (16, 60, 60, 6331, 6060, 1980, 1100, 290, 290, 290, 290, 338, 338, 290, 204, 204, 204, 204, 204, 204, 17, 95, 1, + -18, 30, '', 0, 29, 20, 1.55, 100, 100, 100), + (16, 61, 61, 6523, 6210, 2013, 1118, 296, 296, 296, 296, 341, 341, 296, 206, 206, 206, 206, 206, 206, 17, 97, 1, + -18, 30, '', 0, 29, 20, 1.55, 100, 100, 100), + (16, 62, 62, 6719, 6361, 2046, 1136, 303, 303, 303, 303, 345, 345, 303, 210, 210, 210, 210, 210, 210, 17, 98, 1, + -18, 30, '', 0, 29, 20, 1.55, 100, 100, 100), + (16, 63, 63, 6920, 6514, 2079, 1155, 309, 309, 309, 309, 348, 348, 309, 212, 212, 212, 212, 212, 212, 17, 99, 1, + -18, 30, '', 0, 29, 20, 1.55, 100, 100, 100), + (16, 64, 64, 7126, 6669, 2112, 1173, 317, 317, 317, 317, 352, 352, 317, 215, 215, 215, 215, 215, 215, 18, 101, 1, + -18, 30, '', 0, 30, 20, 1.55, 100, 100, 100), + (16, 65, 65, 7335, 6825, 2145, 1191, 323, 323, 323, 323, 355, 355, 323, 219, 219, 219, 219, 219, 219, 18, 102, 1, + -18, 30, '', 0, 30, 21, 1.55, 100, 100, 100), + (16, 66, 66, 7550, 6983, 2178, 1210, 361, 361, 361, 361, 389, 389, 361, 221, 221, 221, 221, 221, 221, 18, 104, 1, + -18, 30, '', 0, 30, 21, 1.55, 100, 100, 100), + (16, 67, 67, 7769, 7142, 2211, 1228, 372, 372, 372, 372, 397, 397, 372, 223, 223, 223, 223, 223, 223, 18, 105, 1, + -18, 30, '', 0, 30, 21, 1.55, 100, 100, 100), + (16, 68, 68, 7993, 7303, 2244, 1246, 385, 385, 385, 385, 406, 406, 385, 228, 228, 228, 228, 228, 228, 19, 106, 1, + -18, 30, '', 0, 31, 21, 1.55, 100, 100, 100), + (16, 69, 69, 8221, 7466, 2277, 1265, 396, 396, 396, 396, 414, 414, 396, 230, 230, 230, 230, 230, 230, 19, 108, 1, + -18, 30, '', 0, 31, 21, 1.55, 100, 100, 100), + (16, 70, 70, 8455, 7630, 2310, 1283, 410, 410, 410, 410, 423, 423, 410, 232, 232, 232, 232, 232, 232, 19, 109, 1, + -18, 30, '', 0, 31, 22, 1.55, 100, 100, 100), + (16, 71, 71, 8693, 7796, 2343, 1301, 422, 422, 422, 422, 431, 431, 422, 236, 236, 236, 236, 236, 236, 19, 111, 1, + -18, 30, '', 0, 31, 22, 1.55, 100, 100, 100), + (16, 72, 72, 8937, 7963, 2376, 1320, 435, 435, 435, 435, 440, 440, 435, 239, 239, 239, 239, 239, 239, 20, 112, 1, + -18, 30, '', 0, 32, 22, 1.55, 100, 100, 100), + (16, 73, 73, 9185, 8132, 2409, 1338, 447, 447, 447, 447, 448, 448, 447, 241, 241, 241, 241, 241, 241, 20, 113, 1, + -18, 30, '', 0, 32, 22, 1.55, 100, 100, 100), + (16, 74, 74, 9439, 8303, 2442, 1356, 460, 460, 460, 460, 457, 457, 460, 245, 245, 245, 245, 245, 245, 20, 115, 1, + -18, 30, '', 0, 32, 22, 1.55, 100, 100, 100), + (16, 75, 75, 9698, 8475, 2475, 1375, 472, 472, 472, 472, 465, 465, 472, 247, 247, 247, 247, 247, 247, 20, 116, 1, + -18, 30, '', 0, 32, 23, 1.55, 100, 100, 100), + (16, 76, 76, 9962, 8649, 2508, 1393, 486, 486, 486, 486, 474, 474, 486, 250, 250, 250, 250, 250, 250, 21, 118, 1, + -18, 30, '', 0, 33, 23, 1.55, 100, 100, 100), + (16, 77, 77, 10231, 8824, 2541, 1411, 498, 498, 498, 498, 482, 482, 498, 254, 254, 254, 254, 254, 254, 21, 119, + 1, -18, 30, '', 0, 33, 23, 1.55, 100, 100, 100), + (16, 78, 78, 10506, 9001, 2574, 1430, 512, 512, 512, 512, 491, 491, 512, 256, 256, 256, 256, 256, 256, 21, 120, + 1, -18, 30, '', 0, 33, 23, 1.55, 100, 100, 100), + (16, 79, 79, 10787, 9180, 2607, 1448, 524, 524, 524, 524, 499, 499, 524, 258, 258, 258, 258, 258, 258, 21, 122, + 1, -18, 30, '', 0, 33, 23, 1.55, 100, 100, 100), + (16, 80, 80, 11073, 9360, 2640, 1466, 539, 539, 539, 539, 508, 508, 539, 263, 263, 263, 263, 263, 263, 22, 123, + 1, -18, 30, '', 0, 34, 24, 1.55, 100, 100, 100), + (16, 81, 81, 11365, 9542, 2673, 1485, 552, 552, 552, 552, 516, 516, 552, 265, 265, 265, 265, 265, 265, 22, 125, + 1, -18, 30, '', 0, 34, 24, 1.55, 100, 100, 100), + (16, 82, 82, 11662, 9725, 2706, 1503, 566, 566, 566, 566, 525, 525, 566, 267, 267, 267, 267, 267, 267, 22, 126, + 1, -18, 30, '', 0, 34, 24, 1.55, 100, 100, 100), + (16, 83, 83, 11965, 9910, 2739, 1521, 579, 579, 579, 579, 533, 533, 579, 271, 271, 271, 271, 271, 271, 22, 127, + 1, -18, 30, '', 0, 34, 24, 1.55, 100, 100, 100), + (16, 84, 84, 12274, 10097, 2772, 1540, 593, 593, 593, 593, 542, 542, 593, 274, 274, 274, 274, 274, 274, 23, 129, + 1, -18, 30, '', 0, 35, 24, 1.55, 100, 100, 100), + (16, 85, 85, 12590, 10285, 2805, 1558, 606, 606, 606, 606, 550, 550, 606, 276, 276, 276, 276, 276, 276, 23, 130, + 1, -18, 30, '', 0, 35, 25, 1.55, 100, 100, 100), + (17, 1, 1, 76, 57, 34, 18, 62, 62, 62, 62, 134, 134, 62, 34, 34, 34, 34, 34, 34, 2, 14, 1, -18, 30, '', 0, 15, 9, + 1.25, 100, 100, 100), + (17, 2, 2, 142, 115, 68, 37, 64, 64, 64, 64, 138, 138, 64, 38, 38, 38, 38, 38, 38, 2, 15, 1, -18, 30, '', 0, 15, + 9, 1.25, 100, 100, 100), + (17, 3, 3, 208, 175, 102, 56, 64, 64, 64, 64, 141, 141, 64, 40, 40, 40, 40, 40, 40, 3, 17, 1, -18, 30, '', 0, 15, + 9, 1.25, 100, 100, 100), + (17, 4, 4, 274, 237, 136, 74, 66, 66, 66, 66, 145, 145, 66, 44, 44, 44, 44, 44, 44, 3, 18, 1, -18, 30, '', 0, 16, + 9, 1.25, 100, 100, 100), + (17, 5, 5, 341, 300, 170, 93, 67, 67, 67, 67, 148, 148, 67, 48, 48, 48, 48, 48, 48, 3, 20, 1, -18, 30, '', 0, 16, + 10, 1.25, 100, 100, 100), + (17, 6, 6, 408, 365, 204, 112, 69, 69, 69, 69, 152, 152, 69, 50, 50, 50, 50, 50, 50, 3, 21, 1, -18, 30, '', 0, + 16, 10, 1.25, 100, 100, 100), + (17, 7, 7, 476, 431, 238, 130, 70, 70, 70, 70, 155, 155, 70, 52, 52, 52, 52, 52, 52, 4, 22, 1, -18, 30, '', 0, + 16, 10, 1.25, 100, 100, 100), + (17, 8, 8, 544, 499, 272, 149, 72, 72, 72, 72, 159, 159, 72, 58, 58, 58, 58, 58, 58, 4, 24, 1, -18, 30, '', 0, + 17, 10, 1.25, 100, 100, 100), + (17, 9, 9, 612, 569, 306, 168, 73, 73, 73, 73, 162, 162, 73, 60, 60, 60, 60, 60, 60, 4, 25, 1, -18, 30, '', 0, + 17, 10, 1.25, 100, 100, 100), + (17, 10, 10, 681, 640, 340, 186, 78, 78, 78, 78, 166, 166, 78, 62, 62, 62, 62, 62, 62, 4, 27, 1, -18, 30, '', 0, + 17, 11, 1.25, 100, 100, 100), + (17, 11, 11, 751, 713, 374, 205, 79, 79, 79, 79, 169, 169, 79, 66, 66, 66, 66, 66, 66, 5, 28, 1, -18, 30, '', 0, + 17, 11, 1.25, 100, 100, 100), + (17, 12, 12, 822, 787, 408, 224, 82, 82, 82, 82, 173, 173, 82, 70, 70, 70, 70, 70, 70, 5, 29, 1, -18, 30, '', 0, + 18, 11, 1.25, 100, 100, 100), + (17, 13, 13, 893, 863, 442, 242, 83, 83, 83, 83, 176, 176, 83, 72, 72, 72, 72, 72, 72, 5, 31, 1, -18, 30, '', 0, + 18, 11, 1.25, 100, 100, 100), + (17, 14, 14, 966, 941, 476, 261, 86, 86, 86, 86, 180, 180, 86, 76, 76, 76, 76, 76, 76, 5, 32, 1, -18, 30, '', 0, + 18, 11, 1.25, 100, 100, 100), + (17, 15, 15, 1039, 1020, 510, 280, 88, 88, 88, 88, 183, 183, 88, 78, 78, 78, 78, 78, 78, 6, 34, 1, -18, 30, '', + 0, 18, 12, 1.25, 100, 100, 100), + (17, 16, 16, 1114, 1101, 544, 298, 91, 91, 91, 91, 187, 187, 91, 82, 82, 82, 82, 82, 82, 6, 35, 1, -18, 30, '', + 0, 19, 12, 1.25, 100, 100, 100), + (17, 17, 17, 1189, 1183, 578, 317, 93, 93, 93, 93, 190, 190, 93, 86, 86, 86, 86, 86, 86, 6, 36, 1, -18, 30, '', + 0, 19, 12, 1.25, 100, 100, 100), + (17, 18, 18, 1266, 1267, 612, 336, 96, 96, 96, 96, 194, 194, 96, 88, 88, 88, 88, 88, 88, 6, 38, 1, -18, 30, '', + 0, 19, 12, 1.25, 100, 100, 100), + (17, 19, 19, 1344, 1353, 646, 354, 98, 98, 98, 98, 197, 197, 98, 90, 90, 90, 90, 90, 90, 7, 39, 1, -18, 30, '', + 0, 19, 12, 1.25, 100, 100, 100), + (17, 20, 20, 1424, 1440, 680, 373, 104, 104, 104, 104, 201, 201, 104, 96, 96, 96, 96, 96, 96, 7, 41, 1, -18, 30, + '', 0, 20, 13, 1.25, 100, 100, 100), + (17, 21, 21, 1504, 1529, 714, 392, 106, 106, 106, 106, 204, 204, 106, 98, 98, 98, 98, 98, 98, 7, 42, 1, -18, 30, + '', 0, 20, 13, 1.25, 100, 100, 100), + (17, 22, 22, 1587, 1619, 748, 410, 110, 110, 110, 110, 208, 208, 110, 100, 100, 100, 100, 100, 100, 7, 43, 1, + -18, 30, '', 0, 20, 13, 1.25, 100, 100, 100), + (17, 23, 23, 1671, 1711, 782, 429, 112, 112, 112, 112, 211, 211, 112, 104, 104, 104, 104, 104, 104, 8, 45, 1, + -18, 30, '', 0, 20, 13, 1.25, 100, 100, 100), + (17, 24, 24, 1756, 1805, 816, 448, 116, 116, 116, 116, 215, 215, 116, 108, 108, 108, 108, 108, 108, 8, 46, 1, + -18, 30, '', 0, 21, 13, 1.25, 100, 100, 100), + (17, 25, 25, 1843, 1900, 850, 466, 118, 118, 118, 118, 218, 218, 118, 110, 110, 110, 110, 110, 110, 8, 48, 1, + -18, 30, '', 0, 21, 14, 1.25, 100, 100, 100), + (17, 26, 26, 1932, 1997, 884, 485, 122, 122, 122, 122, 222, 222, 122, 114, 114, 114, 114, 114, 114, 8, 49, 1, + -18, 30, '', 0, 21, 14, 1.25, 100, 100, 100), + (17, 27, 27, 2023, 2095, 918, 504, 125, 125, 125, 125, 225, 225, 125, 116, 116, 116, 116, 116, 116, 9, 50, 1, + -18, 30, '', 0, 21, 14, 1.25, 100, 100, 100), + (17, 28, 28, 2116, 2195, 952, 522, 129, 129, 129, 129, 229, 229, 129, 120, 120, 120, 120, 120, 120, 9, 52, 1, + -18, 30, '', 0, 22, 14, 1.25, 100, 100, 100), + (17, 29, 29, 2210, 2297, 986, 541, 132, 132, 132, 132, 232, 232, 132, 124, 124, 124, 124, 124, 124, 9, 53, 1, + -18, 30, '', 0, 22, 14, 1.25, 100, 100, 100), + (17, 30, 30, 2307, 2400, 1020, 560, 138, 138, 138, 138, 236, 236, 138, 126, 126, 126, 126, 126, 126, 9, 55, 1, + -18, 30, '', 0, 22, 15, 1.25, 100, 100, 100), + (17, 31, 31, 2406, 2505, 1054, 578, 141, 141, 141, 141, 239, 239, 141, 128, 128, 128, 128, 128, 128, 10, 56, 1, + -18, 30, '', 0, 22, 15, 1.25, 100, 100, 100), + (17, 32, 32, 2507, 2611, 1088, 597, 146, 146, 146, 146, 243, 243, 146, 134, 134, 134, 134, 134, 134, 10, 57, 1, + -18, 30, '', 0, 23, 15, 1.25, 100, 100, 100), + (17, 33, 33, 2610, 2719, 1122, 616, 149, 149, 149, 149, 246, 246, 149, 136, 136, 136, 136, 136, 136, 10, 59, 1, + -18, 30, '', 0, 23, 15, 1.25, 100, 100, 100), + (17, 34, 34, 2716, 2829, 1156, 634, 154, 154, 154, 154, 250, 250, 154, 138, 138, 138, 138, 138, 138, 10, 60, 1, + -18, 30, '', 0, 23, 15, 1.25, 100, 100, 100), + (17, 35, 35, 2824, 2940, 1190, 653, 157, 157, 157, 157, 253, 253, 157, 142, 142, 142, 142, 142, 142, 11, 62, 1, + -18, 30, '', 0, 23, 16, 1.25, 100, 100, 100), + (17, 36, 36, 2934, 3053, 1224, 672, 162, 162, 162, 162, 257, 257, 162, 146, 146, 146, 146, 146, 146, 11, 63, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (17, 37, 37, 3047, 3167, 1258, 690, 166, 166, 166, 166, 260, 260, 166, 148, 148, 148, 148, 148, 148, 11, 64, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (17, 38, 38, 3163, 3283, 1292, 709, 171, 171, 171, 171, 264, 264, 171, 152, 152, 152, 152, 152, 152, 11, 66, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (17, 39, 39, 3281, 3401, 1326, 728, 175, 175, 175, 175, 267, 267, 175, 154, 154, 154, 154, 154, 154, 12, 67, 1, + -18, 30, '', 0, 24, 16, 1.25, 100, 100, 100), + (17, 40, 40, 3402, 3520, 1360, 746, 182, 182, 182, 182, 271, 271, 182, 158, 158, 158, 158, 158, 158, 12, 69, 1, + -18, 30, '', 0, 25, 17, 1.25, 100, 100, 100), + (17, 41, 41, 3526, 3641, 1394, 765, 186, 186, 186, 186, 274, 274, 186, 162, 162, 162, 162, 162, 162, 12, 70, 1, + -18, 30, '', 0, 25, 17, 1.25, 100, 100, 100), + (17, 42, 42, 3653, 3763, 1428, 784, 192, 192, 192, 192, 278, 278, 192, 164, 164, 164, 164, 164, 164, 12, 71, 1, + -18, 30, '', 0, 25, 17, 1.25, 100, 100, 100), + (17, 43, 43, 3783, 3887, 1462, 802, 196, 196, 196, 196, 281, 281, 196, 166, 166, 166, 166, 166, 166, 13, 73, 1, + -18, 30, '', 0, 25, 17, 1.25, 100, 100, 100), + (17, 44, 44, 3916, 4013, 1496, 821, 202, 202, 202, 202, 285, 285, 202, 172, 172, 172, 172, 172, 172, 13, 74, 1, + -18, 30, '', 0, 26, 17, 1.25, 100, 100, 100), + (17, 45, 45, 4052, 4140, 1530, 840, 206, 206, 206, 206, 288, 288, 206, 174, 174, 174, 174, 174, 174, 13, 76, 1, + -18, 30, '', 0, 26, 18, 1.25, 100, 100, 100), + (17, 46, 46, 4191, 4269, 1564, 858, 212, 212, 212, 212, 292, 292, 212, 176, 176, 176, 176, 176, 176, 13, 77, 1, + -18, 30, '', 0, 26, 18, 1.25, 100, 100, 100), + (17, 47, 47, 4333, 4399, 1598, 877, 216, 216, 216, 216, 295, 295, 216, 180, 180, 180, 180, 180, 180, 14, 78, 1, + -18, 30, '', 0, 26, 18, 1.25, 100, 100, 100), + (17, 48, 48, 4479, 4531, 1632, 896, 222, 222, 222, 222, 299, 299, 222, 184, 184, 184, 184, 184, 184, 14, 80, 1, + -18, 30, '', 0, 27, 18, 1.25, 100, 100, 100), + (17, 49, 49, 4628, 4665, 1666, 914, 227, 227, 227, 227, 302, 302, 227, 186, 186, 186, 186, 186, 186, 14, 81, 1, + -18, 30, '', 0, 27, 18, 1.25, 100, 100, 100), + (17, 50, 50, 4780, 4800, 1700, 933, 235, 235, 235, 235, 306, 306, 235, 190, 190, 190, 190, 190, 190, 14, 83, 1, + -18, 30, '', 0, 27, 19, 1.25, 100, 100, 100), + (17, 51, 51, 4936, 4937, 1734, 952, 240, 240, 240, 240, 309, 309, 240, 192, 192, 192, 192, 192, 192, 15, 84, 1, + -18, 30, '', 0, 27, 19, 1.25, 100, 100, 100), + (17, 52, 52, 5096, 5075, 1768, 970, 246, 246, 246, 246, 313, 313, 246, 196, 196, 196, 196, 196, 196, 15, 85, 1, + -18, 30, '', 0, 28, 19, 1.61, 100, 100, 100), + (17, 53, 53, 5259, 5215, 1802, 989, 251, 251, 251, 251, 316, 316, 251, 200, 200, 200, 200, 200, 200, 15, 87, 1, + -18, 30, '', 0, 28, 19, 1.61, 100, 100, 100), + (17, 54, 54, 5426, 5357, 1836, 1008, 258, 258, 258, 258, 320, 320, 258, 202, 202, 202, 202, 202, 202, 15, 88, 1, + -18, 30, '', 0, 28, 19, 1.61, 100, 100, 100), + (17, 55, 55, 5597, 5500, 1870, 1026, 263, 263, 263, 263, 323, 323, 263, 204, 204, 204, 204, 204, 204, 16, 90, 1, + -18, 30, '', 0, 28, 20, 1.61, 100, 100, 100), + (17, 56, 56, 5772, 5645, 1904, 1045, 270, 270, 270, 270, 327, 327, 270, 210, 210, 210, 210, 210, 210, 16, 91, 1, + -18, 30, '', 0, 29, 20, 1.61, 100, 100, 100), + (17, 57, 57, 5950, 5791, 1938, 1064, 275, 275, 275, 275, 330, 330, 275, 212, 212, 212, 212, 212, 212, 16, 92, 1, + -18, 30, '', 0, 29, 20, 1.61, 100, 100, 100), + (17, 58, 58, 6133, 5939, 1972, 1082, 282, 282, 282, 282, 334, 334, 282, 214, 214, 214, 214, 214, 214, 16, 94, 1, + -18, 30, '', 0, 29, 20, 1.61, 100, 100, 100), + (17, 59, 59, 6320, 6089, 2006, 1101, 288, 288, 288, 288, 337, 337, 288, 218, 218, 218, 218, 218, 218, 17, 95, 1, + -18, 30, '', 0, 29, 20, 1.61, 100, 100, 100), + (17, 60, 60, 6511, 6240, 2040, 1120, 297, 297, 297, 297, 341, 341, 297, 222, 222, 222, 222, 222, 222, 17, 97, 1, + -18, 30, '', 0, 30, 21, 1.61, 100, 100, 100), + (17, 61, 61, 6706, 6393, 2074, 1138, 303, 303, 303, 303, 344, 344, 303, 224, 224, 224, 224, 224, 224, 17, 98, 1, + -18, 30, '', 0, 30, 21, 1.61, 100, 100, 100), + (17, 62, 62, 6905, 6547, 2108, 1157, 310, 310, 310, 310, 348, 348, 310, 228, 228, 228, 228, 228, 228, 17, 99, 1, + -18, 30, '', 0, 30, 21, 1.61, 100, 100, 100), + (17, 63, 63, 7109, 6703, 2142, 1176, 316, 316, 316, 316, 351, 351, 316, 230, 230, 230, 230, 230, 230, 18, 101, 1, + -18, 30, '', 0, 30, 21, 1.61, 100, 100, 100), + (17, 64, 64, 7318, 6861, 2176, 1194, 324, 324, 324, 324, 355, 355, 324, 234, 234, 234, 234, 234, 234, 18, 102, 1, + -18, 30, '', 0, 31, 21, 1.61, 100, 100, 100), + (17, 65, 65, 7530, 7020, 2210, 1213, 330, 330, 330, 330, 358, 358, 330, 238, 238, 238, 238, 238, 238, 18, 104, 1, + -18, 30, '', 0, 31, 22, 1.61, 100, 100, 100), + (17, 66, 66, 7748, 7181, 2244, 1232, 368, 368, 368, 368, 392, 392, 368, 240, 240, 240, 240, 240, 240, 18, 105, 1, + -18, 30, '', 0, 31, 22, 1.61, 100, 100, 100), + (17, 67, 67, 7970, 7343, 2278, 1250, 379, 379, 379, 379, 400, 400, 379, 242, 242, 242, 242, 242, 242, 19, 106, 1, + -18, 30, '', 0, 31, 22, 1.61, 100, 100, 100), + (17, 68, 68, 8197, 7507, 2312, 1269, 392, 392, 392, 392, 409, 409, 392, 248, 248, 248, 248, 248, 248, 19, 108, 1, + -18, 30, '', 0, 32, 22, 1.61, 100, 100, 100), + (17, 69, 69, 8428, 7673, 2346, 1288, 403, 403, 403, 403, 417, 417, 403, 250, 250, 250, 250, 250, 250, 19, 109, 1, + -18, 30, '', 0, 32, 22, 1.61, 100, 100, 100), + (17, 70, 70, 8665, 7840, 2380, 1306, 418, 418, 418, 418, 426, 426, 418, 252, 252, 252, 252, 252, 252, 19, 111, 1, + -18, 30, '', 0, 32, 23, 1.61, 100, 100, 100), + (17, 71, 71, 8906, 8009, 2414, 1325, 430, 430, 430, 430, 434, 434, 430, 256, 256, 256, 256, 256, 256, 20, 112, 1, + -18, 30, '', 0, 32, 23, 1.61, 100, 100, 100), + (17, 72, 72, 9153, 8179, 2448, 1344, 443, 443, 443, 443, 443, 443, 443, 260, 260, 260, 260, 260, 260, 20, 113, 1, + -18, 30, '', 0, 33, 23, 1.61, 100, 100, 100), + (17, 73, 73, 9404, 8351, 2482, 1362, 455, 455, 455, 455, 451, 451, 455, 262, 262, 262, 262, 262, 262, 20, 115, 1, + -18, 30, '', 0, 33, 23, 1.61, 100, 100, 100), + (17, 74, 74, 9661, 8525, 2516, 1381, 468, 468, 468, 468, 460, 460, 468, 266, 266, 266, 266, 266, 266, 20, 116, 1, + -18, 30, '', 0, 33, 23, 1.61, 100, 100, 100), + (17, 75, 75, 9923, 8700, 2550, 1400, 480, 480, 480, 480, 468, 468, 480, 268, 268, 268, 268, 268, 268, 21, 118, 1, + -18, 30, '', 0, 33, 24, 1.61, 100, 100, 100), + (17, 76, 76, 10190, 8877, 2584, 1418, 494, 494, 494, 494, 477, 477, 494, 272, 272, 272, 272, 272, 272, 21, 119, + 1, -18, 30, '', 0, 34, 24, 1.61, 100, 100, 100), + (17, 77, 77, 10462, 9055, 2618, 1437, 506, 506, 506, 506, 485, 485, 506, 276, 276, 276, 276, 276, 276, 21, 120, + 1, -18, 30, '', 0, 34, 24, 1.61, 100, 100, 100), + (17, 78, 78, 10740, 9235, 2652, 1456, 520, 520, 520, 520, 494, 494, 520, 278, 278, 278, 278, 278, 278, 21, 122, + 1, -18, 30, '', 0, 34, 24, 1.61, 100, 100, 100), + (17, 79, 79, 11024, 9417, 2686, 1474, 532, 532, 532, 532, 502, 502, 532, 280, 280, 280, 280, 280, 280, 22, 123, + 1, -18, 30, '', 0, 34, 24, 1.61, 100, 100, 100), + (17, 80, 80, 11313, 9600, 2720, 1493, 548, 548, 548, 548, 511, 511, 548, 286, 286, 286, 286, 286, 286, 22, 125, + 1, -18, 30, '', 0, 35, 25, 1.61, 100, 100, 100), + (17, 81, 81, 11608, 9785, 2754, 1512, 561, 561, 561, 561, 519, 519, 561, 288, 288, 288, 288, 288, 288, 22, 126, + 1, -18, 30, '', 0, 35, 25, 1.61, 100, 100, 100), + (17, 82, 82, 11908, 9971, 2788, 1530, 575, 575, 575, 575, 528, 528, 575, 290, 290, 290, 290, 290, 290, 22, 127, + 1, -18, 30, '', 0, 35, 25, 1.61, 100, 100, 100), + (17, 83, 83, 12214, 10159, 2822, 1549, 588, 588, 588, 588, 536, 536, 588, 294, 294, 294, 294, 294, 294, 23, 129, + 1, -18, 30, '', 0, 35, 25, 1.61, 100, 100, 100), + (17, 84, 84, 12526, 10349, 2856, 1568, 602, 602, 602, 602, 545, 545, 602, 298, 298, 298, 298, 298, 298, 23, 130, + 1, -18, 30, '', 0, 36, 25, 1.61, 100, 100, 100), + (17, 85, 85, 12845, 10540, 2890, 1586, 615, 615, 615, 615, 553, 553, 615, 300, 300, 300, 300, 300, 300, 23, 132, + 1, -18, 30, '', 0, 36, 26, 1.61, 100, 100, 100), + (21, 1, 1, 44, 0, 20, 28, 66, 66, 66, 66, 75, 75, 66, 15, 15, 15, 15, 15, 15, 3, 9, 1, -18, 30, '', 0, 11, 0, + 1.25, 100, 100, 100), + (21, 2, 2, 78, 0, 41, 57, 67, 67, 67, 67, 78, 78, 67, 17, 17, 17, 17, 17, 17, 3, 10, 1, -18, 30, '', 0, 11, 0, + 1.25, 100, 100, 100), + (21, 3, 3, 112, 0, 61, 85, 67, 67, 67, 67, 81, 81, 67, 19, 19, 19, 19, 19, 19, 3, 11, 1, -18, 30, '', 0, 12, 0, + 1.25, 100, 100, 100), + (21, 4, 4, 146, 0, 82, 114, 68, 68, 68, 68, 84, 84, 68, 22, 22, 22, 22, 22, 22, 4, 13, 1, -18, 30, '', 0, 12, 0, + 1.25, 100, 100, 100), + (21, 5, 5, 181, 0, 102, 142, 69, 69, 69, 69, 87, 87, 69, 24, 24, 24, 24, 24, 24, 4, 14, 1, -18, 30, '', 0, 12, 0, + 1.25, 100, 100, 100), + (21, 6, 6, 216, 0, 123, 171, 70, 70, 70, 70, 90, 90, 70, 26, 26, 26, 26, 26, 26, 4, 15, 1, -18, 30, '', 0, 13, 0, + 1.25, 100, 100, 100), + (21, 7, 7, 252, 0, 143, 199, 71, 71, 71, 71, 93, 93, 71, 28, 28, 28, 28, 28, 28, 4, 17, 1, -18, 30, '', 0, 13, 0, + 1.25, 100, 100, 100), + (21, 8, 8, 288, 0, 164, 228, 73, 73, 73, 73, 96, 96, 73, 31, 31, 31, 31, 31, 31, 5, 18, 1, -18, 30, '', 0, 13, 0, + 1.25, 100, 100, 100), + (21, 9, 9, 325, 0, 184, 256, 74, 74, 74, 74, 99, 99, 74, 33, 33, 33, 33, 33, 33, 5, 19, 1, -18, 30, '', 0, 14, 0, + 1.25, 100, 100, 100), + (21, 10, 10, 362, 0, 205, 285, 77, 77, 77, 77, 102, 102, 77, 35, 35, 35, 35, 35, 35, 5, 20, 1, -18, 30, '', 0, + 14, 0, 1.25, 100, 100, 100), + (21, 11, 11, 400, 0, 225, 313, 78, 78, 78, 78, 105, 105, 78, 37, 37, 37, 37, 37, 37, 5, 22, 1, -18, 30, '', 0, + 14, 0, 1.25, 100, 100, 100), + (21, 12, 12, 439, 0, 246, 342, 80, 80, 80, 80, 108, 108, 80, 40, 40, 40, 40, 40, 40, 6, 23, 1, -18, 30, '', 0, + 15, 0, 1.25, 100, 100, 100), + (21, 13, 13, 479, 0, 266, 370, 81, 81, 81, 81, 111, 111, 81, 42, 42, 42, 42, 42, 42, 6, 24, 1, -18, 30, '', 0, + 15, 0, 1.25, 100, 100, 100), + (21, 14, 14, 520, 0, 287, 399, 83, 83, 83, 83, 114, 114, 83, 44, 44, 44, 44, 44, 44, 6, 26, 1, -18, 30, '', 0, + 15, 0, 1.25, 100, 100, 100), + (21, 15, 15, 562, 0, 307, 427, 85, 85, 85, 85, 117, 117, 85, 46, 46, 46, 46, 46, 46, 6, 27, 1, -18, 30, '', 0, + 16, 0, 1.25, 100, 100, 100), + (21, 16, 16, 605, 0, 328, 456, 87, 87, 87, 87, 120, 120, 87, 49, 49, 49, 49, 49, 49, 7, 28, 1, -18, 30, '', 0, + 16, 0, 1.25, 100, 100, 100), + (21, 17, 17, 649, 0, 348, 484, 89, 89, 89, 89, 123, 123, 89, 51, 51, 51, 51, 51, 51, 7, 30, 2, -18, 30, '', 0, + 16, 0, 1.25, 100, 100, 100), + (21, 18, 18, 694, 0, 369, 513, 92, 92, 92, 92, 126, 126, 92, 53, 53, 53, 53, 53, 53, 7, 31, 2, -18, 30, '', 0, + 17, 0, 1.25, 100, 100, 100), + (21, 19, 19, 741, 0, 389, 541, 94, 94, 94, 94, 129, 129, 94, 55, 55, 55, 55, 55, 55, 7, 32, 2, -18, 30, '', 0, + 17, 0, 1.25, 100, 100, 100), + (21, 20, 20, 790, 0, 410, 570, 98, 98, 98, 98, 132, 132, 98, 58, 58, 58, 58, 58, 58, 8, 33, 2, -18, 30, '', 0, + 17, 0, 1.25, 100, 100, 100), + (21, 21, 21, 839, 0, 430, 598, 100, 100, 100, 100, 135, 135, 100, 60, 60, 60, 60, 60, 60, 8, 35, 2, -18, 30, '', + 0, 18, 0, 1.25, 100, 100, 100), + (21, 22, 22, 891, 0, 451, 627, 103, 103, 103, 103, 138, 138, 103, 62, 62, 62, 62, 62, 62, 8, 36, 2, -18, 30, '', + 0, 18, 0, 1.25, 100, 100, 100), + (21, 23, 23, 944, 0, 471, 655, 105, 105, 105, 105, 141, 141, 105, 64, 64, 64, 64, 64, 64, 8, 37, 2, -18, 30, '', + 0, 18, 0, 1.25, 100, 100, 100), + (21, 24, 24, 998, 0, 492, 684, 108, 108, 108, 108, 144, 144, 108, 67, 67, 67, 67, 67, 67, 9, 39, 2, -18, 30, '', + 0, 19, 0, 1.25, 100, 100, 100), + (21, 25, 25, 1055, 0, 512, 712, 111, 111, 111, 111, 147, 147, 111, 69, 69, 69, 69, 69, 69, 9, 40, 2, -18, 30, '', + 0, 19, 0, 1.25, 100, 100, 100), + (21, 26, 26, 1113, 0, 533, 741, 114, 114, 114, 114, 150, 150, 114, 71, 71, 71, 71, 71, 71, 9, 41, 2, -18, 30, '', + 0, 19, 0, 1.25, 100, 100, 100), + (21, 27, 27, 1174, 0, 553, 769, 117, 117, 117, 117, 153, 153, 117, 73, 73, 73, 73, 73, 73, 9, 43, 2, -18, 30, '', + 0, 20, 0, 1.25, 100, 100, 100), + (21, 28, 28, 1236, 0, 574, 798, 121, 121, 121, 121, 156, 156, 121, 76, 76, 76, 76, 76, 76, 10, 44, 2, -18, 30, + '', 0, 20, 0, 1.25, 100, 100, 100), + (21, 29, 29, 1300, 0, 594, 826, 124, 124, 124, 124, 159, 159, 124, 78, 78, 78, 78, 78, 78, 10, 45, 2, -18, 30, + '', 0, 20, 0, 1.25, 100, 100, 100), + (21, 30, 30, 1367, 0, 615, 855, 129, 129, 129, 129, 162, 162, 129, 80, 80, 80, 80, 80, 80, 10, 46, 2, -18, 30, + '', 0, 21, 0, 1.25, 100, 100, 100), + (21, 31, 31, 1436, 0, 635, 883, 132, 132, 132, 132, 165, 165, 132, 82, 82, 82, 82, 82, 82, 10, 48, 2, -18, 30, + '', 0, 21, 0, 1.25, 100, 100, 100), + (21, 32, 32, 1507, 0, 656, 912, 136, 136, 136, 136, 168, 168, 136, 85, 85, 85, 85, 85, 85, 11, 49, 2, -18, 30, + '', 0, 21, 0, 1.25, 100, 100, 100), + (21, 33, 33, 1581, 0, 676, 940, 139, 139, 139, 139, 171, 171, 139, 87, 87, 87, 87, 87, 87, 11, 50, 2, -18, 30, + '', 0, 22, 0, 1.25, 100, 100, 100), + (21, 34, 34, 1657, 0, 697, 969, 143, 143, 143, 143, 174, 174, 143, 89, 89, 89, 89, 89, 89, 11, 52, 2, -18, 30, + '', 0, 22, 0, 1.25, 100, 100, 100), + (21, 35, 35, 1735, 0, 717, 997, 147, 147, 147, 147, 177, 177, 147, 91, 91, 91, 91, 91, 91, 11, 53, 2, -18, 30, + '', 0, 22, 0, 1.25, 100, 100, 100), + (21, 36, 36, 1817, 0, 738, 1026, 151, 151, 151, 151, 180, 180, 151, 94, 94, 94, 94, 94, 94, 12, 54, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (21, 37, 37, 1901, 0, 758, 1054, 155, 155, 155, 155, 183, 183, 155, 96, 96, 96, 96, 96, 96, 12, 56, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (21, 38, 38, 1987, 0, 779, 1083, 160, 160, 160, 160, 186, 186, 160, 98, 98, 98, 98, 98, 98, 12, 57, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (21, 39, 39, 2077, 0, 799, 1111, 164, 164, 164, 164, 189, 189, 164, 100, 100, 100, 100, 100, 100, 12, 58, 2, -18, + 30, '', 0, 24, 0, 1.25, 100, 100, 100), + (21, 40, 40, 2170, 0, 820, 1140, 170, 170, 170, 170, 192, 192, 170, 103, 103, 103, 103, 103, 103, 13, 59, 2, -18, + 30, '', 0, 24, 0, 1.25, 100, 100, 100), + (21, 41, 41, 2265, 0, 840, 1168, 174, 174, 174, 174, 195, 195, 174, 105, 105, 105, 105, 105, 105, 13, 61, 2, -18, + 30, '', 0, 24, 0, 1.25, 100, 100, 100), + (21, 42, 42, 2364, 0, 861, 1197, 179, 179, 179, 179, 198, 198, 179, 107, 107, 107, 107, 107, 107, 13, 62, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (21, 43, 43, 2465, 0, 881, 1225, 183, 183, 183, 183, 201, 201, 183, 109, 109, 109, 109, 109, 109, 13, 63, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (21, 44, 44, 2570, 0, 902, 1254, 188, 188, 188, 188, 204, 204, 188, 112, 112, 112, 112, 112, 112, 14, 65, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (21, 45, 45, 2679, 0, 922, 1282, 193, 193, 193, 193, 207, 207, 193, 114, 114, 114, 114, 114, 114, 14, 66, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (21, 46, 46, 2790, 0, 943, 1311, 198, 198, 198, 198, 210, 210, 198, 116, 116, 116, 116, 116, 116, 14, 67, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (21, 47, 47, 2905, 0, 963, 1339, 203, 203, 203, 203, 213, 213, 203, 118, 118, 118, 118, 118, 118, 14, 69, 3, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (21, 48, 48, 3024, 0, 984, 1368, 209, 209, 209, 209, 216, 216, 209, 121, 121, 121, 121, 121, 121, 15, 70, 3, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (21, 49, 49, 3146, 0, 1004, 1396, 214, 214, 214, 214, 219, 219, 214, 123, 123, 123, 123, 123, 123, 15, 71, 3, + -18, 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (21, 50, 50, 3272, 0, 1025, 1425, 221, 221, 221, 221, 222, 222, 221, 125, 125, 125, 125, 125, 125, 15, 72, 3, + -18, 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (21, 51, 51, 3402, 0, 1045, 1453, 226, 226, 226, 226, 225, 225, 226, 127, 127, 127, 127, 127, 127, 15, 74, 3, + -18, 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (21, 52, 52, 3535, 0, 1066, 1482, 232, 232, 232, 232, 228, 228, 232, 130, 130, 130, 130, 130, 130, 16, 75, 3, + -18, 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (21, 53, 53, 3672, 0, 1086, 1510, 237, 237, 237, 237, 231, 231, 237, 132, 132, 132, 132, 132, 132, 16, 76, 3, + -18, 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (21, 54, 54, 3814, 0, 1107, 1539, 243, 243, 243, 243, 234, 234, 243, 134, 134, 134, 134, 134, 134, 16, 78, 3, + -18, 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (21, 55, 55, 3959, 0, 1127, 1567, 249, 249, 249, 249, 237, 237, 249, 136, 136, 136, 136, 136, 136, 16, 79, 3, + -18, 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (21, 56, 56, 4109, 0, 1148, 1596, 255, 255, 255, 255, 240, 240, 255, 139, 139, 139, 139, 139, 139, 17, 80, 3, + -18, 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (21, 57, 57, 4262, 0, 1168, 1624, 261, 261, 261, 261, 243, 243, 261, 141, 141, 141, 141, 141, 141, 17, 82, 3, + -18, 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (21, 58, 58, 4420, 0, 1189, 1653, 268, 268, 268, 268, 246, 246, 268, 143, 143, 143, 143, 143, 143, 17, 83, 3, + -18, 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (21, 59, 59, 4583, 0, 1209, 1681, 274, 274, 274, 274, 249, 249, 274, 145, 145, 145, 145, 145, 145, 17, 84, 3, + -18, 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (21, 60, 60, 4750, 0, 1230, 1710, 282, 282, 282, 282, 252, 252, 282, 148, 148, 148, 148, 148, 148, 18, 85, 3, + -18, 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (21, 61, 61, 4921, 0, 1250, 1738, 288, 288, 288, 288, 255, 255, 288, 150, 150, 150, 150, 150, 150, 21, 102, 4, + -20, 29, '', 0, 31, 0, 1.25, 100, 100, 100), + (21, 62, 62, 5097, 0, 1271, 1767, 295, 295, 295, 295, 258, 258, 295, 152, 152, 152, 152, 152, 152, 24, 118, 4, + -21, 28, '', 0, 31, 0, 1.25, 100, 100, 100), + (21, 63, 63, 5277, 0, 1291, 1795, 301, 301, 301, 301, 261, 261, 301, 154, 154, 154, 154, 154, 154, 27, 134, 4, + -21, 28, '', 0, 32, 0, 1.25, 100, 100, 100), + (21, 64, 64, 5462, 0, 1312, 1824, 308, 308, 308, 308, 264, 264, 308, 157, 157, 157, 157, 157, 157, 31, 151, 4, + -22, 28, '', 0, 32, 0, 1.25, 100, 100, 100), + (21, 65, 65, 5652, 0, 1332, 1852, 315, 315, 315, 315, 267, 267, 315, 159, 159, 159, 159, 159, 159, 34, 167, 4, + -22, 28, '', 0, 32, 0, 1.25, 100, 100, 100), + (21, 66, 66, 5847, 0, 1353, 1881, 352, 352, 352, 352, 300, 300, 352, 161, 161, 161, 161, 161, 161, 37, 183, 4, + -23, 28, '', 0, 33, 0, 1.25, 100, 100, 100), + (21, 67, 67, 6047, 0, 1373, 1909, 364, 364, 364, 364, 308, 308, 364, 163, 163, 163, 163, 163, 163, 40, 200, 4, + -23, 28, '', 0, 33, 0, 1.25, 100, 100, 100), + (21, 68, 68, 6252, 0, 1394, 1938, 377, 377, 377, 377, 316, 316, 377, 166, 166, 166, 166, 166, 166, 44, 216, 4, + -24, 27, '', 0, 33, 0, 1.25, 100, 100, 100), + (21, 69, 69, 6462, 0, 1414, 1966, 389, 389, 389, 389, 324, 324, 389, 168, 168, 168, 168, 168, 168, 47, 232, 4, + -24, 27, '', 0, 34, 0, 1.25, 100, 100, 100), + (21, 70, 70, 6677, 0, 1435, 1995, 403, 403, 403, 403, 332, 332, 403, 170, 170, 170, 170, 170, 170, 50, 248, 4, + -25, 27, '', 0, 34, 0, 1.25, 100, 100, 100), + (21, 71, 71, 6897, 0, 1455, 2023, 415, 415, 415, 415, 340, 340, 415, 172, 172, 172, 172, 172, 172, 53, 265, 4, + -25, 27, '', 0, 34, 0, 1.25, 100, 100, 100), + (21, 72, 72, 7123, 0, 1476, 2052, 428, 428, 428, 428, 348, 348, 428, 175, 175, 175, 175, 175, 175, 57, 281, 4, + -26, 27, '', 0, 35, 0, 1.25, 100, 100, 100), + (21, 73, 73, 7354, 0, 1496, 2080, 440, 440, 440, 440, 356, 356, 440, 177, 177, 177, 177, 177, 177, 60, 297, 4, + -26, 27, '', 0, 35, 0, 1.25, 100, 100, 100), + (21, 74, 74, 7591, 0, 1517, 2109, 453, 453, 453, 453, 364, 364, 453, 179, 179, 179, 179, 179, 179, 63, 314, 4, + -27, 26, '', 0, 35, 0, 1.25, 100, 100, 100), + (21, 75, 75, 7833, 0, 1537, 2137, 466, 466, 466, 466, 372, 372, 466, 181, 181, 181, 181, 181, 181, 66, 330, 4, + -27, 26, '', 0, 36, 0, 1.25, 100, 100, 100), + (21, 76, 76, 8081, 0, 1558, 2166, 479, 479, 479, 479, 380, 380, 479, 184, 184, 184, 184, 184, 184, 70, 346, 4, + -28, 26, '', 0, 36, 0, 1.25, 100, 100, 100), + (21, 77, 77, 8334, 0, 1578, 2194, 492, 492, 492, 492, 388, 388, 492, 186, 186, 186, 186, 186, 186, 73, 363, 4, + -28, 26, '', 0, 36, 0, 1.25, 100, 100, 100), + (21, 78, 78, 8593, 0, 1599, 2223, 506, 506, 506, 506, 396, 396, 506, 188, 188, 188, 188, 188, 188, 76, 379, 4, + -29, 26, '', 0, 37, 0, 1.25, 100, 100, 100), + (21, 79, 79, 8858, 0, 1619, 2251, 519, 519, 519, 519, 404, 404, 519, 190, 190, 190, 190, 190, 190, 79, 395, 4, + -29, 26, '', 0, 37, 0, 1.25, 100, 100, 100), + (21, 80, 80, 9130, 0, 1640, 2280, 534, 534, 534, 534, 412, 412, 534, 193, 193, 193, 193, 193, 193, 83, 411, 4, + -34, 24, '', 0, 37, 0, 1.25, 100, 100, 100), + (21, 81, 81, 9407, 0, 1660, 2308, 547, 547, 547, 547, 420, 420, 547, 195, 195, 195, 195, 195, 195, 86, 428, 4, + -34, 24, '', 0, 38, 0, 1.25, 100, 100, 100), + (21, 82, 82, 9690, 0, 1681, 2337, 561, 561, 561, 561, 428, 428, 561, 197, 197, 197, 197, 197, 197, 89, 444, 4, + -34, 24, '', 0, 38, 0, 1.25, 100, 100, 100), + (21, 83, 83, 9979, 0, 1701, 2365, 574, 574, 574, 574, 436, 436, 574, 199, 199, 199, 199, 199, 199, 92, 460, 4, + -34, 24, '', 0, 38, 0, 1.25, 100, 100, 100), + (21, 84, 84, 10274, 0, 1722, 2394, 588, 588, 588, 588, 444, 444, 588, 202, 202, 202, 202, 202, 202, 96, 477, 4, + -34, 24, '', 0, 39, 0, 1.25, 100, 100, 100), + (21, 85, 85, 10576, 0, 1742, 2422, 602, 602, 602, 602, 452, 452, 602, 204, 204, 204, 204, 204, 204, 99, 493, 4, + -34, 24, '', 0, 39, 0, 1.25, 100, 100, 100), + (22, 1, 1, 48, 0, 21, 29, 67, 67, 67, 67, 77, 77, 67, 18, 18, 18, 18, 18, 18, 3, 11, 1, -18, 30, '', 0, 13, 0, + 1.25, 100, 100, 100), + (22, 2, 2, 86, 0, 42, 58, 68, 68, 68, 68, 80, 80, 68, 20, 20, 20, 20, 20, 20, 4, 13, 1, -18, 30, '', 0, 13, 0, + 1.25, 100, 100, 100), + (22, 3, 3, 124, 0, 63, 87, 68, 68, 68, 68, 83, 83, 68, 22, 22, 22, 22, 22, 22, 4, 14, 1, -18, 30, '', 0, 14, 0, + 1.25, 100, 100, 100), + (22, 4, 4, 162, 0, 84, 116, 69, 69, 69, 69, 86, 86, 69, 26, 26, 26, 26, 26, 26, 4, 15, 1, -18, 30, '', 0, 14, 0, + 1.25, 100, 100, 100), + (22, 5, 5, 201, 0, 105, 145, 70, 70, 70, 70, 89, 89, 70, 28, 28, 28, 28, 28, 28, 4, 17, 1, -18, 30, '', 0, 14, 0, + 1.25, 100, 100, 100), + (22, 6, 6, 240, 0, 126, 174, 71, 71, 71, 71, 92, 92, 71, 30, 30, 30, 30, 30, 30, 5, 18, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (22, 7, 7, 280, 0, 147, 203, 72, 72, 72, 72, 95, 95, 72, 32, 32, 32, 32, 32, 32, 5, 19, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (22, 8, 8, 320, 0, 168, 232, 74, 74, 74, 74, 98, 98, 74, 36, 36, 36, 36, 36, 36, 5, 20, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (22, 9, 9, 361, 0, 189, 261, 75, 75, 75, 75, 101, 101, 75, 38, 38, 38, 38, 38, 38, 5, 22, 1, -18, 30, '', 0, 16, + 0, 1.25, 100, 100, 100), + (22, 10, 10, 402, 0, 210, 290, 79, 79, 79, 79, 104, 104, 79, 40, 40, 40, 40, 40, 40, 6, 23, 1, -18, 30, '', 0, + 16, 0, 1.25, 100, 100, 100), + (22, 11, 11, 444, 0, 231, 319, 80, 80, 80, 80, 107, 107, 80, 42, 42, 42, 42, 42, 42, 6, 24, 1, -18, 30, '', 0, + 16, 0, 1.25, 100, 100, 100), + (22, 12, 12, 487, 0, 252, 348, 82, 82, 82, 82, 110, 110, 82, 46, 46, 46, 46, 46, 46, 6, 26, 1, -18, 30, '', 0, + 17, 0, 1.25, 100, 100, 100), + (22, 13, 13, 531, 0, 273, 377, 83, 83, 83, 83, 113, 113, 83, 48, 48, 48, 48, 48, 48, 6, 27, 1, -18, 30, '', 0, + 17, 0, 1.25, 100, 100, 100), + (22, 14, 14, 576, 0, 294, 406, 85, 85, 85, 85, 116, 116, 85, 50, 50, 50, 50, 50, 50, 7, 28, 1, -18, 30, '', 0, + 17, 0, 1.25, 100, 100, 100), + (22, 15, 15, 622, 0, 315, 435, 87, 87, 87, 87, 119, 119, 87, 52, 52, 52, 52, 52, 52, 7, 30, 1, -18, 30, '', 0, + 18, 0, 1.25, 100, 100, 100), + (22, 16, 16, 669, 0, 336, 464, 89, 89, 89, 89, 122, 122, 89, 56, 56, 56, 56, 56, 56, 7, 31, 1, -18, 30, '', 0, + 18, 0, 1.25, 100, 100, 100), + (22, 17, 17, 717, 0, 357, 493, 91, 91, 91, 91, 125, 125, 91, 58, 58, 58, 58, 58, 58, 7, 32, 2, -18, 30, '', 0, + 18, 0, 1.25, 100, 100, 100), + (22, 18, 18, 766, 0, 378, 522, 94, 94, 94, 94, 128, 128, 94, 60, 60, 60, 60, 60, 60, 8, 33, 2, -18, 30, '', 0, + 19, 0, 1.25, 100, 100, 100), + (22, 19, 19, 817, 0, 399, 551, 96, 96, 96, 96, 131, 131, 96, 62, 62, 62, 62, 62, 62, 8, 35, 2, -18, 30, '', 0, + 19, 0, 1.25, 100, 100, 100), + (22, 20, 20, 870, 0, 420, 580, 101, 101, 101, 101, 134, 134, 101, 66, 66, 66, 66, 66, 66, 8, 36, 2, -18, 30, '', + 0, 19, 0, 1.25, 100, 100, 100), + (22, 21, 21, 923, 0, 441, 609, 103, 103, 103, 103, 137, 137, 103, 68, 68, 68, 68, 68, 68, 8, 37, 2, -18, 30, '', + 0, 20, 0, 1.25, 100, 100, 100), + (22, 22, 22, 979, 0, 462, 638, 106, 106, 106, 106, 140, 140, 106, 70, 70, 70, 70, 70, 70, 9, 39, 2, -18, 30, '', + 0, 20, 0, 1.25, 100, 100, 100), + (22, 23, 23, 1036, 0, 483, 667, 108, 108, 108, 108, 143, 143, 108, 72, 72, 72, 72, 72, 72, 9, 40, 2, -18, 30, '', + 0, 20, 0, 1.25, 100, 100, 100), + (22, 24, 24, 1094, 0, 504, 696, 111, 111, 111, 111, 146, 146, 111, 76, 76, 76, 76, 76, 76, 9, 41, 2, -18, 30, '', + 0, 21, 0, 1.25, 100, 100, 100), + (22, 25, 25, 1155, 0, 525, 725, 114, 114, 114, 114, 149, 149, 114, 78, 78, 78, 78, 78, 78, 9, 43, 2, -18, 30, '', + 0, 21, 0, 1.25, 100, 100, 100), + (22, 26, 26, 1217, 0, 546, 754, 117, 117, 117, 117, 152, 152, 117, 80, 80, 80, 80, 80, 80, 10, 44, 2, -18, 30, + '', 0, 21, 0, 1.25, 100, 100, 100), + (22, 27, 27, 1282, 0, 567, 783, 120, 120, 120, 120, 155, 155, 120, 82, 82, 82, 82, 82, 82, 10, 45, 2, -18, 30, + '', 0, 22, 0, 1.25, 100, 100, 100), + (22, 28, 28, 1348, 0, 588, 812, 124, 124, 124, 124, 158, 158, 124, 86, 86, 86, 86, 86, 86, 10, 46, 2, -18, 30, + '', 0, 22, 0, 1.25, 100, 100, 100), + (22, 29, 29, 1416, 0, 609, 841, 127, 127, 127, 127, 161, 161, 127, 88, 88, 88, 88, 88, 88, 10, 48, 2, -18, 30, + '', 0, 22, 0, 1.25, 100, 100, 100), + (22, 30, 30, 1487, 0, 630, 870, 133, 133, 133, 133, 164, 164, 133, 90, 90, 90, 90, 90, 90, 11, 49, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (22, 31, 31, 1560, 0, 651, 899, 136, 136, 136, 136, 167, 167, 136, 92, 92, 92, 92, 92, 92, 11, 50, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (22, 32, 32, 1635, 0, 672, 928, 140, 140, 140, 140, 170, 170, 140, 96, 96, 96, 96, 96, 96, 11, 52, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (22, 33, 33, 1713, 0, 693, 957, 143, 143, 143, 143, 173, 173, 143, 98, 98, 98, 98, 98, 98, 11, 53, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (22, 34, 34, 1793, 0, 714, 986, 147, 147, 147, 147, 176, 176, 147, 100, 100, 100, 100, 100, 100, 12, 54, 2, -18, + 30, '', 0, 24, 0, 1.25, 100, 100, 100), + (22, 35, 35, 1875, 0, 735, 1015, 151, 151, 151, 151, 179, 179, 151, 102, 102, 102, 102, 102, 102, 12, 56, 2, -18, + 30, '', 0, 24, 0, 1.25, 100, 100, 100), + (22, 36, 36, 1961, 0, 756, 1044, 155, 155, 155, 155, 182, 182, 155, 106, 106, 106, 106, 106, 106, 12, 57, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (22, 37, 37, 2049, 0, 777, 1073, 159, 159, 159, 159, 185, 185, 159, 108, 108, 108, 108, 108, 108, 12, 58, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (22, 38, 38, 2139, 0, 798, 1102, 164, 164, 164, 164, 188, 188, 164, 110, 110, 110, 110, 110, 110, 13, 59, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (22, 39, 39, 2233, 0, 819, 1131, 168, 168, 168, 168, 191, 191, 168, 112, 112, 112, 112, 112, 112, 13, 61, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (22, 40, 40, 2330, 0, 840, 1160, 175, 175, 175, 175, 194, 194, 175, 116, 116, 116, 116, 116, 116, 13, 62, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (22, 41, 41, 2429, 0, 861, 1189, 179, 179, 179, 179, 197, 197, 179, 118, 118, 118, 118, 118, 118, 13, 63, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (22, 42, 42, 2532, 0, 882, 1218, 184, 184, 184, 184, 200, 200, 184, 120, 120, 120, 120, 120, 120, 14, 65, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (22, 43, 43, 2637, 0, 903, 1247, 188, 188, 188, 188, 203, 203, 188, 122, 122, 122, 122, 122, 122, 14, 66, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (22, 44, 44, 2746, 0, 924, 1276, 193, 193, 193, 193, 206, 206, 193, 126, 126, 126, 126, 126, 126, 14, 67, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (22, 45, 45, 2859, 0, 945, 1305, 198, 198, 198, 198, 209, 209, 198, 128, 128, 128, 128, 128, 128, 14, 69, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (22, 46, 46, 2974, 0, 966, 1334, 203, 203, 203, 203, 212, 212, 203, 130, 130, 130, 130, 130, 130, 15, 70, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (22, 47, 47, 3093, 0, 987, 1363, 208, 208, 208, 208, 215, 215, 208, 132, 132, 132, 132, 132, 132, 15, 71, 3, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (22, 48, 48, 3216, 0, 1008, 1392, 214, 214, 214, 214, 218, 218, 214, 136, 136, 136, 136, 136, 136, 15, 72, 3, + -18, 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (22, 49, 49, 3342, 0, 1029, 1421, 219, 219, 219, 219, 221, 221, 219, 138, 138, 138, 138, 138, 138, 15, 74, 3, + -18, 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (22, 50, 50, 3472, 0, 1050, 1450, 227, 227, 227, 227, 224, 224, 227, 140, 140, 140, 140, 140, 140, 16, 75, 3, + -18, 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (22, 51, 51, 3606, 0, 1071, 1479, 232, 232, 232, 232, 227, 227, 232, 142, 142, 142, 142, 142, 142, 16, 76, 3, + -18, 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (22, 52, 52, 3743, 0, 1092, 1508, 238, 238, 238, 238, 230, 230, 238, 146, 146, 146, 146, 146, 146, 16, 78, 3, + -18, 30, '', 0, 30, 0, 1.31, 100, 100, 100), + (22, 53, 53, 3884, 0, 1113, 1537, 243, 243, 243, 243, 233, 233, 243, 148, 148, 148, 148, 148, 148, 16, 79, 3, + -18, 30, '', 0, 30, 0, 1.31, 100, 100, 100), + (22, 54, 54, 4030, 0, 1134, 1566, 249, 249, 249, 249, 236, 236, 249, 150, 150, 150, 150, 150, 150, 17, 80, 3, + -18, 30, '', 0, 31, 0, 1.31, 100, 100, 100), + (22, 55, 55, 4179, 0, 1155, 1595, 255, 255, 255, 255, 239, 239, 255, 152, 152, 152, 152, 152, 152, 17, 82, 3, + -18, 30, '', 0, 31, 0, 1.31, 100, 100, 100), + (22, 56, 56, 4333, 0, 1176, 1624, 261, 261, 261, 261, 242, 242, 261, 156, 156, 156, 156, 156, 156, 17, 83, 3, + -18, 30, '', 0, 31, 0, 1.31, 100, 100, 100), + (22, 57, 57, 4490, 0, 1197, 1653, 267, 267, 267, 267, 245, 245, 267, 158, 158, 158, 158, 158, 158, 17, 84, 3, + -18, 30, '', 0, 32, 0, 1.31, 100, 100, 100), + (22, 58, 58, 4652, 0, 1218, 1682, 274, 274, 274, 274, 248, 248, 274, 160, 160, 160, 160, 160, 160, 18, 85, 3, + -18, 30, '', 0, 32, 0, 1.31, 100, 100, 100), + (22, 59, 59, 4819, 0, 1239, 1711, 280, 280, 280, 280, 251, 251, 280, 162, 162, 162, 162, 162, 162, 18, 87, 3, + -18, 30, '', 0, 32, 0, 1.31, 100, 100, 100), + (22, 60, 60, 4990, 0, 1260, 1740, 289, 289, 289, 289, 254, 254, 289, 166, 166, 166, 166, 166, 166, 18, 88, 3, + -18, 30, '', 0, 33, 0, 1.31, 100, 100, 100), + (22, 61, 61, 5165, 0, 1281, 1769, 295, 295, 295, 295, 257, 257, 295, 168, 168, 168, 168, 168, 168, 21, 104, 4, + -21, 28, '', 0, 33, 0, 1.31, 100, 100, 100), + (22, 62, 62, 5345, 0, 1302, 1798, 302, 302, 302, 302, 260, 260, 302, 170, 170, 170, 170, 170, 170, 25, 121, 4, + -22, 28, '', 0, 33, 0, 1.31, 100, 100, 100), + (22, 63, 63, 5529, 0, 1323, 1827, 308, 308, 308, 308, 263, 263, 308, 172, 172, 172, 172, 172, 172, 28, 137, 4, + -22, 28, '', 0, 34, 0, 1.31, 100, 100, 100), + (22, 64, 64, 5718, 0, 1344, 1856, 315, 315, 315, 315, 266, 266, 315, 176, 176, 176, 176, 176, 176, 31, 153, 4, + -23, 28, '', 0, 34, 0, 1.31, 100, 100, 100), + (22, 65, 65, 5912, 0, 1365, 1885, 322, 322, 322, 322, 269, 269, 322, 178, 178, 178, 178, 178, 178, 34, 170, 4, + -23, 28, '', 0, 34, 0, 1.31, 100, 100, 100), + (22, 66, 66, 6111, 0, 1386, 1914, 359, 359, 359, 359, 302, 302, 359, 180, 180, 180, 180, 180, 180, 38, 186, 4, + -24, 27, '', 0, 35, 0, 1.31, 100, 100, 100), + (22, 67, 67, 6315, 0, 1407, 1943, 371, 371, 371, 371, 310, 310, 371, 182, 182, 182, 182, 182, 182, 41, 202, 4, + -24, 27, '', 0, 35, 0, 1.31, 100, 100, 100), + (22, 68, 68, 6524, 0, 1428, 1972, 384, 384, 384, 384, 318, 318, 384, 186, 186, 186, 186, 186, 186, 44, 218, 4, + -25, 27, '', 0, 35, 0, 1.31, 100, 100, 100), + (22, 69, 69, 6738, 0, 1449, 2001, 396, 396, 396, 396, 326, 326, 396, 188, 188, 188, 188, 188, 188, 47, 235, 4, + -25, 27, '', 0, 36, 0, 1.31, 100, 100, 100), + (22, 70, 70, 6957, 0, 1470, 2030, 411, 411, 411, 411, 334, 334, 411, 190, 190, 190, 190, 190, 190, 51, 251, 4, + -26, 27, '', 0, 36, 0, 1.31, 100, 100, 100), + (22, 71, 71, 7181, 0, 1491, 2059, 423, 423, 423, 423, 342, 342, 423, 192, 192, 192, 192, 192, 192, 54, 267, 4, + -26, 27, '', 0, 36, 0, 1.31, 100, 100, 100), + (22, 72, 72, 7411, 0, 1512, 2088, 436, 436, 436, 436, 350, 350, 436, 196, 196, 196, 196, 196, 196, 57, 284, 4, + -27, 26, '', 0, 37, 0, 1.31, 100, 100, 100), + (22, 73, 73, 7646, 0, 1533, 2117, 448, 448, 448, 448, 358, 358, 448, 198, 198, 198, 198, 198, 198, 60, 300, 4, + -27, 26, '', 0, 37, 0, 1.31, 100, 100, 100), + (22, 74, 74, 7887, 0, 1554, 2146, 461, 461, 461, 461, 366, 366, 461, 200, 200, 200, 200, 200, 200, 64, 316, 4, + -28, 26, '', 0, 37, 0, 1.31, 100, 100, 100), + (22, 75, 75, 8133, 0, 1575, 2175, 474, 474, 474, 474, 374, 374, 474, 202, 202, 202, 202, 202, 202, 67, 333, 4, + -28, 26, '', 0, 38, 0, 1.31, 100, 100, 100), + (22, 76, 76, 8385, 0, 1596, 2204, 487, 487, 487, 487, 382, 382, 487, 206, 206, 206, 206, 206, 206, 70, 349, 4, + -29, 26, '', 0, 38, 0, 1.31, 100, 100, 100), + (22, 77, 77, 8642, 0, 1617, 2233, 500, 500, 500, 500, 390, 390, 500, 208, 208, 208, 208, 208, 208, 73, 365, 4, + -29, 26, '', 0, 38, 0, 1.31, 100, 100, 100), + (22, 78, 78, 8905, 0, 1638, 2262, 514, 514, 514, 514, 398, 398, 514, 210, 210, 210, 210, 210, 210, 77, 381, 4, + -30, 25, '', 0, 39, 0, 1.31, 100, 100, 100), + (22, 79, 79, 9174, 0, 1659, 2291, 527, 527, 527, 527, 406, 406, 527, 212, 212, 212, 212, 212, 212, 80, 398, 4, + -30, 25, '', 0, 39, 0, 1.31, 100, 100, 100), + (22, 80, 80, 9450, 0, 1680, 2320, 543, 543, 543, 543, 414, 414, 543, 216, 216, 216, 216, 216, 216, 83, 414, 4, + -35, 23, '', 0, 39, 0, 1.31, 100, 100, 100), + (22, 81, 81, 9731, 0, 1701, 2349, 556, 556, 556, 556, 422, 422, 556, 218, 218, 218, 218, 218, 218, 86, 430, 4, + -35, 23, '', 0, 40, 0, 1.31, 100, 100, 100), + (22, 82, 82, 10018, 0, 1722, 2378, 570, 570, 570, 570, 430, 430, 570, 220, 220, 220, 220, 220, 220, 90, 447, 4, + -35, 23, '', 0, 40, 0, 1.31, 100, 100, 100), + (22, 83, 83, 10311, 0, 1743, 2407, 583, 583, 583, 583, 438, 438, 583, 222, 222, 222, 222, 222, 222, 93, 463, 4, + -35, 23, '', 0, 40, 0, 1.31, 100, 100, 100), + (22, 84, 84, 10610, 0, 1764, 2436, 597, 597, 597, 597, 446, 446, 597, 226, 226, 226, 226, 226, 226, 96, 479, 4, + -35, 23, '', 0, 41, 0, 1.31, 100, 100, 100), + (22, 85, 85, 10916, 0, 1785, 2465, 611, 611, 611, 611, 454, 454, 611, 228, 228, 228, 228, 228, 228, 99, 496, 4, + -35, 23, '', 0, 41, 0, 1.31, 100, 100, 100), + (23, 1, 1, 52, 0, 21, 29, 68, 68, 68, 68, 79, 79, 68, 21, 21, 21, 21, 21, 21, 4, 14, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (23, 2, 2, 94, 0, 43, 59, 69, 69, 69, 69, 82, 82, 69, 23, 23, 23, 23, 23, 23, 4, 15, 1, -18, 30, '', 0, 15, 0, + 1.25, 100, 100, 100), + (23, 3, 3, 136, 0, 64, 88, 69, 69, 69, 69, 85, 85, 69, 25, 25, 25, 25, 25, 25, 4, 17, 1, -18, 30, '', 0, 16, 0, + 1.25, 100, 100, 100), + (23, 4, 4, 178, 0, 86, 118, 70, 70, 70, 70, 88, 88, 70, 30, 30, 30, 30, 30, 30, 5, 18, 1, -18, 30, '', 0, 16, 0, + 1.25, 100, 100, 100), + (23, 5, 5, 221, 0, 107, 147, 71, 71, 71, 71, 91, 91, 71, 32, 32, 32, 32, 32, 32, 5, 19, 1, -18, 30, '', 0, 16, 0, + 1.25, 100, 100, 100), + (23, 6, 6, 264, 0, 129, 177, 72, 72, 72, 72, 94, 94, 72, 34, 34, 34, 34, 34, 34, 5, 20, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (23, 7, 7, 308, 0, 150, 206, 73, 73, 73, 73, 97, 97, 73, 36, 36, 36, 36, 36, 36, 5, 22, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (23, 8, 8, 352, 0, 172, 236, 75, 75, 75, 75, 100, 100, 75, 41, 41, 41, 41, 41, 41, 6, 23, 1, -18, 30, '', 0, 17, + 0, 1.25, 100, 100, 100), + (23, 9, 9, 397, 0, 193, 265, 76, 76, 76, 76, 103, 103, 76, 43, 43, 43, 43, 43, 43, 6, 24, 1, -18, 30, '', 0, 18, + 0, 1.25, 100, 100, 100), + (23, 10, 10, 442, 0, 215, 295, 81, 81, 81, 81, 106, 106, 81, 45, 45, 45, 45, 45, 45, 6, 26, 1, -18, 30, '', 0, + 18, 0, 1.25, 100, 100, 100), + (23, 11, 11, 488, 0, 236, 324, 82, 82, 82, 82, 109, 109, 82, 47, 47, 47, 47, 47, 47, 6, 27, 1, -18, 30, '', 0, + 18, 0, 1.25, 100, 100, 100), + (23, 12, 12, 535, 0, 258, 354, 84, 84, 84, 84, 112, 112, 84, 52, 52, 52, 52, 52, 52, 7, 28, 1, -18, 30, '', 0, + 19, 0, 1.25, 100, 100, 100), + (23, 13, 13, 583, 0, 279, 383, 85, 85, 85, 85, 115, 115, 85, 54, 54, 54, 54, 54, 54, 7, 30, 1, -18, 30, '', 0, + 19, 0, 1.25, 100, 100, 100), + (23, 14, 14, 632, 0, 301, 413, 87, 87, 87, 87, 118, 118, 87, 56, 56, 56, 56, 56, 56, 7, 31, 1, -18, 30, '', 0, + 19, 0, 1.25, 100, 100, 100), + (23, 15, 15, 682, 0, 322, 442, 89, 89, 89, 89, 121, 121, 89, 58, 58, 58, 58, 58, 58, 7, 32, 1, -18, 30, '', 0, + 20, 0, 1.25, 100, 100, 100), + (23, 16, 16, 733, 0, 344, 472, 91, 91, 91, 91, 124, 124, 91, 63, 63, 63, 63, 63, 63, 8, 33, 1, -18, 30, '', 0, + 20, 0, 1.25, 100, 100, 100), + (23, 17, 17, 785, 0, 365, 501, 93, 93, 93, 93, 127, 127, 93, 65, 65, 65, 65, 65, 65, 8, 35, 2, -18, 30, '', 0, + 20, 0, 1.25, 100, 100, 100), + (23, 18, 18, 838, 0, 387, 531, 96, 96, 96, 96, 130, 130, 96, 67, 67, 67, 67, 67, 67, 8, 36, 2, -18, 30, '', 0, + 21, 0, 1.25, 100, 100, 100), + (23, 19, 19, 893, 0, 408, 560, 98, 98, 98, 98, 133, 133, 98, 69, 69, 69, 69, 69, 69, 8, 37, 2, -18, 30, '', 0, + 21, 0, 1.25, 100, 100, 100), + (23, 20, 20, 950, 0, 430, 590, 104, 104, 104, 104, 136, 136, 104, 74, 74, 74, 74, 74, 74, 9, 39, 2, -18, 30, '', + 0, 21, 0, 1.25, 100, 100, 100), + (23, 21, 21, 1007, 0, 451, 619, 106, 106, 106, 106, 139, 139, 106, 76, 76, 76, 76, 76, 76, 9, 40, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (23, 22, 22, 1067, 0, 473, 649, 109, 109, 109, 109, 142, 142, 109, 78, 78, 78, 78, 78, 78, 9, 41, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (23, 23, 23, 1128, 0, 494, 678, 111, 111, 111, 111, 145, 145, 111, 80, 80, 80, 80, 80, 80, 9, 43, 2, -18, 30, '', + 0, 22, 0, 1.25, 100, 100, 100), + (23, 24, 24, 1190, 0, 516, 708, 114, 114, 114, 114, 148, 148, 114, 85, 85, 85, 85, 85, 85, 10, 44, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (23, 25, 25, 1255, 0, 537, 737, 117, 117, 117, 117, 151, 151, 117, 87, 87, 87, 87, 87, 87, 10, 45, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (23, 26, 26, 1321, 0, 559, 767, 120, 120, 120, 120, 154, 154, 120, 89, 89, 89, 89, 89, 89, 10, 46, 2, -18, 30, + '', 0, 23, 0, 1.25, 100, 100, 100), + (23, 27, 27, 1390, 0, 580, 796, 123, 123, 123, 123, 157, 157, 123, 91, 91, 91, 91, 91, 91, 10, 48, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (23, 28, 28, 1460, 0, 602, 826, 127, 127, 127, 127, 160, 160, 127, 96, 96, 96, 96, 96, 96, 11, 49, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (23, 29, 29, 1532, 0, 623, 855, 130, 130, 130, 130, 163, 163, 130, 98, 98, 98, 98, 98, 98, 11, 50, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (23, 30, 30, 1607, 0, 645, 885, 137, 137, 137, 137, 166, 166, 137, 100, 100, 100, 100, 100, 100, 11, 52, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (23, 31, 31, 1684, 0, 666, 914, 140, 140, 140, 140, 169, 169, 140, 102, 102, 102, 102, 102, 102, 11, 53, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (23, 32, 32, 1763, 0, 688, 944, 144, 144, 144, 144, 172, 172, 144, 107, 107, 107, 107, 107, 107, 12, 54, 2, -18, + 30, '', 0, 25, 0, 1.25, 100, 100, 100), + (23, 33, 33, 1845, 0, 709, 973, 147, 147, 147, 147, 175, 175, 147, 109, 109, 109, 109, 109, 109, 12, 56, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (23, 34, 34, 1929, 0, 731, 1003, 151, 151, 151, 151, 178, 178, 151, 111, 111, 111, 111, 111, 111, 12, 57, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (23, 35, 35, 2015, 0, 752, 1032, 155, 155, 155, 155, 181, 181, 155, 113, 113, 113, 113, 113, 113, 12, 58, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (23, 36, 36, 2105, 0, 774, 1062, 159, 159, 159, 159, 184, 184, 159, 118, 118, 118, 118, 118, 118, 13, 59, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (23, 37, 37, 2197, 0, 795, 1091, 163, 163, 163, 163, 187, 187, 163, 120, 120, 120, 120, 120, 120, 13, 61, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (23, 38, 38, 2291, 0, 817, 1121, 168, 168, 168, 168, 190, 190, 168, 122, 122, 122, 122, 122, 122, 13, 62, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (23, 39, 39, 2389, 0, 838, 1150, 172, 172, 172, 172, 193, 193, 172, 124, 124, 124, 124, 124, 124, 13, 63, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (23, 40, 40, 2490, 0, 860, 1180, 180, 180, 180, 180, 196, 196, 180, 129, 129, 129, 129, 129, 129, 14, 65, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (23, 41, 41, 2593, 0, 881, 1209, 184, 184, 184, 184, 199, 199, 184, 131, 131, 131, 131, 131, 131, 14, 66, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (23, 42, 42, 2700, 0, 903, 1239, 189, 189, 189, 189, 202, 202, 189, 133, 133, 133, 133, 133, 133, 14, 67, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (23, 43, 43, 2809, 0, 924, 1268, 193, 193, 193, 193, 205, 205, 193, 135, 135, 135, 135, 135, 135, 14, 69, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (23, 44, 44, 2922, 0, 946, 1298, 198, 198, 198, 198, 208, 208, 198, 140, 140, 140, 140, 140, 140, 15, 70, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (23, 45, 45, 3039, 0, 967, 1327, 203, 203, 203, 203, 211, 211, 203, 142, 142, 142, 142, 142, 142, 15, 71, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (23, 46, 46, 3158, 0, 989, 1357, 208, 208, 208, 208, 214, 214, 208, 144, 144, 144, 144, 144, 144, 15, 72, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (23, 47, 47, 3281, 0, 1010, 1386, 213, 213, 213, 213, 217, 217, 213, 146, 146, 146, 146, 146, 146, 15, 74, 3, + -18, 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (23, 48, 48, 3408, 0, 1032, 1416, 219, 219, 219, 219, 220, 220, 219, 151, 151, 151, 151, 151, 151, 16, 75, 3, + -18, 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (23, 49, 49, 3538, 0, 1053, 1445, 224, 224, 224, 224, 223, 223, 224, 153, 153, 153, 153, 153, 153, 16, 76, 3, + -18, 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (23, 50, 50, 3672, 0, 1075, 1475, 233, 233, 233, 233, 226, 226, 233, 155, 155, 155, 155, 155, 155, 16, 78, 3, + -18, 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (23, 51, 51, 3810, 0, 1096, 1504, 238, 238, 238, 238, 229, 229, 238, 157, 157, 157, 157, 157, 157, 16, 79, 3, + -18, 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (23, 52, 52, 3951, 0, 1118, 1534, 244, 244, 244, 244, 232, 232, 244, 162, 162, 162, 162, 162, 162, 17, 80, 3, + -18, 30, '', 0, 32, 0, 1.37, 100, 100, 100), + (23, 53, 53, 4096, 0, 1139, 1563, 249, 249, 249, 249, 235, 235, 249, 164, 164, 164, 164, 164, 164, 17, 82, 3, + -18, 30, '', 0, 32, 0, 1.37, 100, 100, 100), + (23, 54, 54, 4246, 0, 1161, 1593, 255, 255, 255, 255, 238, 238, 255, 166, 166, 166, 166, 166, 166, 17, 83, 3, + -18, 30, '', 0, 33, 0, 1.37, 100, 100, 100), + (23, 55, 55, 4399, 0, 1182, 1622, 261, 261, 261, 261, 241, 241, 261, 168, 168, 168, 168, 168, 168, 17, 84, 3, + -18, 30, '', 0, 33, 0, 1.37, 100, 100, 100), + (23, 56, 56, 4557, 0, 1204, 1652, 267, 267, 267, 267, 244, 244, 267, 173, 173, 173, 173, 173, 173, 18, 85, 3, + -18, 30, '', 0, 33, 0, 1.37, 100, 100, 100), + (23, 57, 57, 4718, 0, 1225, 1681, 273, 273, 273, 273, 247, 247, 273, 175, 175, 175, 175, 175, 175, 18, 87, 3, + -18, 30, '', 0, 34, 0, 1.37, 100, 100, 100), + (23, 58, 58, 4884, 0, 1247, 1711, 280, 280, 280, 280, 250, 250, 280, 177, 177, 177, 177, 177, 177, 18, 88, 3, + -18, 30, '', 0, 34, 0, 1.37, 100, 100, 100), + (23, 59, 59, 5055, 0, 1268, 1740, 286, 286, 286, 286, 253, 253, 286, 179, 179, 179, 179, 179, 179, 18, 89, 3, + -18, 30, '', 0, 34, 0, 1.37, 100, 100, 100), + (23, 60, 60, 5230, 0, 1290, 1770, 296, 296, 296, 296, 256, 256, 296, 184, 184, 184, 184, 184, 184, 19, 91, 3, + -18, 30, '', 0, 35, 0, 1.37, 100, 100, 100), + (23, 61, 61, 5409, 0, 1311, 1799, 302, 302, 302, 302, 259, 259, 302, 186, 186, 186, 186, 186, 186, 22, 107, 4, + -22, 28, '', 0, 35, 0, 1.37, 100, 100, 100), + (23, 62, 62, 5593, 0, 1333, 1829, 309, 309, 309, 309, 262, 262, 309, 188, 188, 188, 188, 188, 188, 25, 123, 4, + -23, 28, '', 0, 35, 0, 1.37, 100, 100, 100), + (23, 63, 63, 5781, 0, 1354, 1858, 315, 315, 315, 315, 265, 265, 315, 190, 190, 190, 190, 190, 190, 28, 140, 4, + -23, 28, '', 0, 36, 0, 1.37, 100, 100, 100), + (23, 64, 64, 5974, 0, 1376, 1888, 322, 322, 322, 322, 268, 268, 322, 195, 195, 195, 195, 195, 195, 32, 156, 4, + -24, 27, '', 0, 36, 0, 1.37, 100, 100, 100), + (23, 65, 65, 6172, 0, 1397, 1917, 329, 329, 329, 329, 271, 271, 329, 197, 197, 197, 197, 197, 197, 35, 172, 4, + -24, 27, '', 0, 36, 0, 1.37, 100, 100, 100), + (23, 66, 66, 6375, 0, 1419, 1947, 366, 366, 366, 366, 304, 304, 366, 199, 199, 199, 199, 199, 199, 38, 188, 4, + -25, 27, '', 0, 37, 0, 1.37, 100, 100, 100), + (23, 67, 67, 6583, 0, 1440, 1976, 378, 378, 378, 378, 312, 312, 378, 201, 201, 201, 201, 201, 201, 41, 205, 4, + -25, 27, '', 0, 37, 0, 1.37, 100, 100, 100), + (23, 68, 68, 6796, 0, 1462, 2006, 391, 391, 391, 391, 320, 320, 391, 206, 206, 206, 206, 206, 206, 45, 221, 4, + -26, 27, '', 0, 37, 0, 1.37, 100, 100, 100), + (23, 69, 69, 7014, 0, 1483, 2035, 403, 403, 403, 403, 328, 328, 403, 208, 208, 208, 208, 208, 208, 48, 237, 4, + -26, 27, '', 0, 38, 0, 1.37, 100, 100, 100), + (23, 70, 70, 7237, 0, 1505, 2065, 419, 419, 419, 419, 336, 336, 419, 210, 210, 210, 210, 210, 210, 51, 254, 4, + -27, 26, '', 0, 38, 0, 1.37, 100, 100, 100), + (23, 71, 71, 7465, 0, 1526, 2094, 431, 431, 431, 431, 344, 344, 431, 212, 212, 212, 212, 212, 212, 54, 270, 4, + -27, 26, '', 0, 38, 0, 1.37, 100, 100, 100), + (23, 72, 72, 7699, 0, 1548, 2124, 444, 444, 444, 444, 352, 352, 444, 217, 217, 217, 217, 217, 217, 58, 286, 4, + -28, 26, '', 0, 39, 0, 1.37, 100, 100, 100), + (23, 73, 73, 7938, 0, 1569, 2153, 456, 456, 456, 456, 360, 360, 456, 219, 219, 219, 219, 219, 219, 61, 303, 4, + -28, 26, '', 0, 39, 0, 1.37, 100, 100, 100), + (23, 74, 74, 8183, 0, 1591, 2183, 469, 469, 469, 469, 368, 368, 469, 221, 221, 221, 221, 221, 221, 64, 319, 4, + -29, 26, '', 0, 39, 0, 1.37, 100, 100, 100), + (23, 75, 75, 8433, 0, 1612, 2212, 482, 482, 482, 482, 376, 376, 482, 223, 223, 223, 223, 223, 223, 67, 335, 4, + -29, 26, '', 0, 40, 0, 1.37, 100, 100, 100), + (23, 76, 76, 8689, 0, 1634, 2242, 495, 495, 495, 495, 384, 384, 495, 228, 228, 228, 228, 228, 228, 71, 351, 4, + -30, 25, '', 0, 40, 0, 1.37, 100, 100, 100), + (23, 77, 77, 8950, 0, 1655, 2271, 508, 508, 508, 508, 392, 392, 508, 230, 230, 230, 230, 230, 230, 74, 368, 4, + -30, 25, '', 0, 40, 0, 1.37, 100, 100, 100), + (23, 78, 78, 9217, 0, 1677, 2301, 522, 522, 522, 522, 400, 400, 522, 232, 232, 232, 232, 232, 232, 77, 384, 4, + -31, 25, '', 0, 41, 0, 1.37, 100, 100, 100), + (23, 79, 79, 9490, 0, 1698, 2330, 535, 535, 535, 535, 408, 408, 535, 234, 234, 234, 234, 234, 234, 80, 400, 4, + -31, 25, '', 0, 41, 0, 1.37, 100, 100, 100), + (23, 80, 80, 9770, 0, 1720, 2360, 552, 552, 552, 552, 416, 416, 552, 239, 239, 239, 239, 239, 239, 84, 417, 4, + -36, 23, '', 0, 41, 0, 1.37, 100, 100, 100), + (23, 81, 81, 10055, 0, 1741, 2389, 565, 565, 565, 565, 424, 424, 565, 241, 241, 241, 241, 241, 241, 87, 433, 4, + -36, 23, '', 0, 42, 0, 1.37, 100, 100, 100), + (23, 82, 82, 10346, 0, 1763, 2419, 579, 579, 579, 579, 432, 432, 579, 243, 243, 243, 243, 243, 243, 90, 449, 4, + -36, 23, '', 0, 42, 0, 1.37, 100, 100, 100), + (23, 83, 83, 10643, 0, 1784, 2448, 592, 592, 592, 592, 440, 440, 592, 245, 245, 245, 245, 245, 245, 93, 466, 4, + -36, 23, '', 0, 42, 0, 1.37, 100, 100, 100), + (23, 84, 84, 10946, 0, 1806, 2478, 606, 606, 606, 606, 448, 448, 606, 250, 250, 250, 250, 250, 250, 97, 482, 4, + -36, 23, '', 0, 43, 0, 1.37, 100, 100, 100), + (23, 85, 85, 11256, 0, 1827, 2507, 620, 620, 620, 620, 456, 456, 620, 252, 252, 252, 252, 252, 252, 100, 498, 4, + -36, 23, '', 0, 43, 0, 1.37, 100, 100, 100), + (24, 1, 1, 56, 0, 22, 30, 69, 69, 69, 69, 81, 81, 69, 24, 24, 24, 24, 24, 24, 4, 17, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (24, 2, 2, 102, 0, 44, 60, 70, 70, 70, 70, 84, 84, 70, 26, 26, 26, 26, 26, 26, 5, 18, 1, -18, 30, '', 0, 17, 0, + 1.25, 100, 100, 100), + (24, 3, 3, 148, 0, 66, 90, 70, 70, 70, 70, 87, 87, 70, 28, 28, 28, 28, 28, 28, 5, 19, 1, -18, 30, '', 0, 18, 0, + 1.25, 100, 100, 100), + (24, 4, 4, 194, 0, 88, 120, 71, 71, 71, 71, 90, 90, 71, 34, 34, 34, 34, 34, 34, 5, 20, 1, -18, 30, '', 0, 18, 0, + 1.25, 100, 100, 100), + (24, 5, 5, 241, 0, 110, 150, 72, 72, 72, 72, 93, 93, 72, 36, 36, 36, 36, 36, 36, 5, 22, 1, -18, 30, '', 0, 18, 0, + 1.25, 100, 100, 100), + (24, 6, 6, 288, 0, 132, 180, 73, 73, 73, 73, 96, 96, 73, 38, 38, 38, 38, 38, 38, 6, 23, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (24, 7, 7, 336, 0, 154, 210, 74, 74, 74, 74, 99, 99, 74, 40, 40, 40, 40, 40, 40, 6, 24, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (24, 8, 8, 384, 0, 176, 240, 76, 76, 76, 76, 102, 102, 76, 46, 46, 46, 46, 46, 46, 6, 26, 1, -18, 30, '', 0, 19, + 0, 1.25, 100, 100, 100), + (24, 9, 9, 433, 0, 198, 270, 77, 77, 77, 77, 105, 105, 77, 48, 48, 48, 48, 48, 48, 6, 27, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (24, 10, 10, 482, 0, 220, 300, 83, 83, 83, 83, 108, 108, 83, 50, 50, 50, 50, 50, 50, 7, 28, 1, -18, 30, '', 0, + 20, 0, 1.25, 100, 100, 100), + (24, 11, 11, 532, 0, 242, 330, 84, 84, 84, 84, 111, 111, 84, 52, 52, 52, 52, 52, 52, 7, 30, 1, -18, 30, '', 0, + 20, 0, 1.25, 100, 100, 100), + (24, 12, 12, 583, 0, 264, 360, 86, 86, 86, 86, 114, 114, 86, 58, 58, 58, 58, 58, 58, 7, 31, 1, -18, 30, '', 0, + 21, 0, 1.25, 100, 100, 100), + (24, 13, 13, 635, 0, 286, 390, 87, 87, 87, 87, 117, 117, 87, 60, 60, 60, 60, 60, 60, 7, 32, 1, -18, 30, '', 0, + 21, 0, 1.25, 100, 100, 100), + (24, 14, 14, 688, 0, 308, 420, 89, 89, 89, 89, 120, 120, 89, 62, 62, 62, 62, 62, 62, 8, 33, 1, -18, 30, '', 0, + 21, 0, 1.25, 100, 100, 100), + (24, 15, 15, 742, 0, 330, 450, 91, 91, 91, 91, 123, 123, 91, 64, 64, 64, 64, 64, 64, 8, 35, 1, -18, 30, '', 0, + 22, 0, 1.25, 100, 100, 100), + (24, 16, 16, 797, 0, 352, 480, 93, 93, 93, 93, 126, 126, 93, 70, 70, 70, 70, 70, 70, 8, 36, 1, -18, 30, '', 0, + 22, 0, 1.25, 100, 100, 100), + (24, 17, 17, 853, 0, 374, 510, 95, 95, 95, 95, 129, 129, 95, 72, 72, 72, 72, 72, 72, 8, 37, 2, -18, 30, '', 0, + 22, 0, 1.25, 100, 100, 100), + (24, 18, 18, 910, 0, 396, 540, 98, 98, 98, 98, 132, 132, 98, 74, 74, 74, 74, 74, 74, 9, 39, 2, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (24, 19, 19, 969, 0, 418, 570, 100, 100, 100, 100, 135, 135, 100, 76, 76, 76, 76, 76, 76, 9, 40, 2, -18, 30, '', + 0, 23, 0, 1.25, 100, 100, 100), + (24, 20, 20, 1030, 0, 440, 600, 107, 107, 107, 107, 138, 138, 107, 82, 82, 82, 82, 82, 82, 9, 41, 2, -18, 30, '', + 0, 23, 0, 1.25, 100, 100, 100), + (24, 21, 21, 1091, 0, 462, 630, 109, 109, 109, 109, 141, 141, 109, 84, 84, 84, 84, 84, 84, 9, 43, 2, -18, 30, '', + 0, 24, 0, 1.25, 100, 100, 100), + (24, 22, 22, 1155, 0, 484, 660, 112, 112, 112, 112, 144, 144, 112, 86, 86, 86, 86, 86, 86, 10, 44, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (24, 23, 23, 1220, 0, 506, 690, 114, 114, 114, 114, 147, 147, 114, 88, 88, 88, 88, 88, 88, 10, 45, 2, -18, 30, + '', 0, 24, 0, 1.25, 100, 100, 100), + (24, 24, 24, 1286, 0, 528, 720, 117, 117, 117, 117, 150, 150, 117, 94, 94, 94, 94, 94, 94, 10, 46, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (24, 25, 25, 1355, 0, 550, 750, 120, 120, 120, 120, 153, 153, 120, 96, 96, 96, 96, 96, 96, 10, 48, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (24, 26, 26, 1425, 0, 572, 780, 123, 123, 123, 123, 156, 156, 123, 98, 98, 98, 98, 98, 98, 11, 49, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (24, 27, 27, 1498, 0, 594, 810, 126, 126, 126, 126, 159, 159, 126, 100, 100, 100, 100, 100, 100, 11, 50, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (24, 28, 28, 1572, 0, 616, 840, 130, 130, 130, 130, 162, 162, 130, 106, 106, 106, 106, 106, 106, 11, 52, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (24, 29, 29, 1648, 0, 638, 870, 133, 133, 133, 133, 165, 165, 133, 108, 108, 108, 108, 108, 108, 11, 53, 2, -18, + 30, '', 0, 26, 0, 1.25, 100, 100, 100), + (24, 30, 30, 1727, 0, 660, 900, 141, 141, 141, 141, 168, 168, 141, 110, 110, 110, 110, 110, 110, 12, 54, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (24, 31, 31, 1808, 0, 682, 930, 144, 144, 144, 144, 171, 171, 144, 112, 112, 112, 112, 112, 112, 12, 56, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (24, 32, 32, 1891, 0, 704, 960, 148, 148, 148, 148, 174, 174, 148, 118, 118, 118, 118, 118, 118, 12, 57, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (24, 33, 33, 1977, 0, 726, 990, 151, 151, 151, 151, 177, 177, 151, 120, 120, 120, 120, 120, 120, 12, 58, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (24, 34, 34, 2065, 0, 748, 1020, 155, 155, 155, 155, 180, 180, 155, 122, 122, 122, 122, 122, 122, 13, 59, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (24, 35, 35, 2155, 0, 770, 1050, 159, 159, 159, 159, 183, 183, 159, 124, 124, 124, 124, 124, 124, 13, 61, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (24, 36, 36, 2249, 0, 792, 1080, 163, 163, 163, 163, 186, 186, 163, 130, 130, 130, 130, 130, 130, 13, 62, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (24, 37, 37, 2345, 0, 814, 1110, 167, 167, 167, 167, 189, 189, 167, 132, 132, 132, 132, 132, 132, 13, 63, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (24, 38, 38, 2443, 0, 836, 1140, 172, 172, 172, 172, 192, 192, 172, 134, 134, 134, 134, 134, 134, 14, 65, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (24, 39, 39, 2545, 0, 858, 1170, 176, 176, 176, 176, 195, 195, 176, 136, 136, 136, 136, 136, 136, 14, 66, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (24, 40, 40, 2650, 0, 880, 1200, 185, 185, 185, 185, 198, 198, 185, 142, 142, 142, 142, 142, 142, 14, 67, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (24, 41, 41, 2757, 0, 902, 1230, 189, 189, 189, 189, 201, 201, 189, 144, 144, 144, 144, 144, 144, 14, 69, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (24, 42, 42, 2868, 0, 924, 1260, 194, 194, 194, 194, 204, 204, 194, 146, 146, 146, 146, 146, 146, 15, 70, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (24, 43, 43, 2981, 0, 946, 1290, 198, 198, 198, 198, 207, 207, 198, 148, 148, 148, 148, 148, 148, 15, 71, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (24, 44, 44, 3098, 0, 968, 1320, 203, 203, 203, 203, 210, 210, 203, 154, 154, 154, 154, 154, 154, 15, 72, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (24, 45, 45, 3219, 0, 990, 1350, 208, 208, 208, 208, 213, 213, 208, 156, 156, 156, 156, 156, 156, 15, 74, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (24, 46, 46, 3342, 0, 1012, 1380, 213, 213, 213, 213, 216, 216, 213, 158, 158, 158, 158, 158, 158, 16, 75, 2, + -18, 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (24, 47, 47, 3469, 0, 1034, 1410, 218, 218, 218, 218, 219, 219, 218, 160, 160, 160, 160, 160, 160, 16, 76, 3, + -18, 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (24, 48, 48, 3600, 0, 1056, 1440, 224, 224, 224, 224, 222, 222, 224, 166, 166, 166, 166, 166, 166, 16, 78, 3, + -18, 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (24, 49, 49, 3734, 0, 1078, 1470, 229, 229, 229, 229, 225, 225, 229, 168, 168, 168, 168, 168, 168, 16, 79, 3, + -18, 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (24, 50, 50, 3872, 0, 1100, 1500, 239, 239, 239, 239, 228, 228, 239, 170, 170, 170, 170, 170, 170, 17, 80, 3, + -18, 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (24, 51, 51, 4014, 0, 1122, 1530, 244, 244, 244, 244, 231, 231, 244, 172, 172, 172, 172, 172, 172, 17, 82, 3, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (24, 52, 52, 4159, 0, 1144, 1560, 250, 250, 250, 250, 234, 234, 250, 178, 178, 178, 178, 178, 178, 17, 83, 3, + -18, 30, '', 0, 34, 0, 1.43, 100, 100, 100), + (24, 53, 53, 4308, 0, 1166, 1590, 255, 255, 255, 255, 237, 237, 255, 180, 180, 180, 180, 180, 180, 17, 84, 3, + -18, 30, '', 0, 34, 0, 1.43, 100, 100, 100), + (24, 54, 54, 4462, 0, 1188, 1620, 261, 261, 261, 261, 240, 240, 261, 182, 182, 182, 182, 182, 182, 18, 85, 3, + -18, 30, '', 0, 35, 0, 1.43, 100, 100, 100), + (24, 55, 55, 4619, 0, 1210, 1650, 267, 267, 267, 267, 243, 243, 267, 184, 184, 184, 184, 184, 184, 18, 87, 3, + -18, 30, '', 0, 35, 0, 1.43, 100, 100, 100), + (24, 56, 56, 4781, 0, 1232, 1680, 273, 273, 273, 273, 246, 246, 273, 190, 190, 190, 190, 190, 190, 18, 88, 3, + -18, 30, '', 0, 35, 0, 1.43, 100, 100, 100), + (24, 57, 57, 4946, 0, 1254, 1710, 279, 279, 279, 279, 249, 249, 279, 192, 192, 192, 192, 192, 192, 18, 89, 3, + -18, 30, '', 0, 36, 0, 1.43, 100, 100, 100), + (24, 58, 58, 5116, 0, 1276, 1740, 286, 286, 286, 286, 252, 252, 286, 194, 194, 194, 194, 194, 194, 19, 91, 3, + -18, 30, '', 0, 36, 0, 1.43, 100, 100, 100), + (24, 59, 59, 5291, 0, 1298, 1770, 292, 292, 292, 292, 255, 255, 292, 196, 196, 196, 196, 196, 196, 19, 92, 3, + -18, 30, '', 0, 36, 0, 1.43, 100, 100, 100), + (24, 60, 60, 5470, 0, 1320, 1800, 303, 303, 303, 303, 258, 258, 303, 202, 202, 202, 202, 202, 202, 19, 93, 3, + -18, 30, '', 0, 37, 0, 1.43, 100, 100, 100), + (24, 61, 61, 5653, 0, 1342, 1830, 309, 309, 309, 309, 261, 261, 309, 204, 204, 204, 204, 204, 204, 22, 110, 4, + -23, 28, '', 0, 37, 0, 1.43, 100, 100, 100), + (24, 62, 62, 5841, 0, 1364, 1860, 316, 316, 316, 316, 264, 264, 316, 206, 206, 206, 206, 206, 206, 26, 126, 4, + -24, 27, '', 0, 37, 0, 1.43, 100, 100, 100), + (24, 63, 63, 6033, 0, 1386, 1890, 322, 322, 322, 322, 267, 267, 322, 208, 208, 208, 208, 208, 208, 29, 142, 4, + -24, 27, '', 0, 38, 0, 1.43, 100, 100, 100), + (24, 64, 64, 6230, 0, 1408, 1920, 329, 329, 329, 329, 270, 270, 329, 214, 214, 214, 214, 214, 214, 32, 158, 4, + -25, 27, '', 0, 38, 0, 1.43, 100, 100, 100), + (24, 65, 65, 6432, 0, 1430, 1950, 336, 336, 336, 336, 273, 273, 336, 216, 216, 216, 216, 216, 216, 35, 175, 4, + -25, 27, '', 0, 38, 0, 1.43, 100, 100, 100), + (24, 66, 66, 6639, 0, 1452, 1980, 373, 373, 373, 373, 306, 306, 373, 218, 218, 218, 218, 218, 218, 39, 191, 4, + -26, 27, '', 0, 39, 0, 1.43, 100, 100, 100), + (24, 67, 67, 6851, 0, 1474, 2010, 385, 385, 385, 385, 314, 314, 385, 220, 220, 220, 220, 220, 220, 42, 207, 4, + -26, 27, '', 0, 39, 0, 1.43, 100, 100, 100), + (24, 68, 68, 7068, 0, 1496, 2040, 398, 398, 398, 398, 322, 322, 398, 226, 226, 226, 226, 226, 226, 45, 224, 4, + -27, 26, '', 0, 39, 0, 1.43, 100, 100, 100), + (24, 69, 69, 7290, 0, 1518, 2070, 410, 410, 410, 410, 330, 330, 410, 228, 228, 228, 228, 228, 228, 48, 240, 4, + -27, 26, '', 0, 40, 0, 1.43, 100, 100, 100), + (24, 70, 70, 7517, 0, 1540, 2100, 427, 427, 427, 427, 338, 338, 427, 230, 230, 230, 230, 230, 230, 52, 256, 4, + -28, 26, '', 0, 40, 0, 1.43, 100, 100, 100), + (24, 71, 71, 7749, 0, 1562, 2130, 439, 439, 439, 439, 346, 346, 439, 232, 232, 232, 232, 232, 232, 55, 273, 4, + -28, 26, '', 0, 40, 0, 1.43, 100, 100, 100), + (24, 72, 72, 7987, 0, 1584, 2160, 452, 452, 452, 452, 354, 354, 452, 238, 238, 238, 238, 238, 238, 58, 289, 4, + -29, 26, '', 0, 41, 0, 1.43, 100, 100, 100), + (24, 73, 73, 8230, 0, 1606, 2190, 464, 464, 464, 464, 362, 362, 464, 240, 240, 240, 240, 240, 240, 61, 305, 4, + -29, 26, '', 0, 41, 0, 1.43, 100, 100, 100), + (24, 74, 74, 8479, 0, 1628, 2220, 477, 477, 477, 477, 370, 370, 477, 242, 242, 242, 242, 242, 242, 65, 321, 4, + -30, 25, '', 0, 41, 0, 1.43, 100, 100, 100), + (24, 75, 75, 8733, 0, 1650, 2250, 490, 490, 490, 490, 378, 378, 490, 244, 244, 244, 244, 244, 244, 68, 338, 4, + -30, 25, '', 0, 42, 0, 1.43, 100, 100, 100), + (24, 76, 76, 8993, 0, 1672, 2280, 503, 503, 503, 503, 386, 386, 503, 250, 250, 250, 250, 250, 250, 71, 354, 4, + -31, 25, '', 0, 42, 0, 1.43, 100, 100, 100), + (24, 77, 77, 9258, 0, 1694, 2310, 516, 516, 516, 516, 394, 394, 516, 252, 252, 252, 252, 252, 252, 74, 370, 4, + -31, 25, '', 0, 42, 0, 1.43, 100, 100, 100), + (24, 78, 78, 9529, 0, 1716, 2340, 530, 530, 530, 530, 402, 402, 530, 254, 254, 254, 254, 254, 254, 78, 387, 4, + -32, 24, '', 0, 43, 0, 1.43, 100, 100, 100), + (24, 79, 79, 9806, 0, 1738, 2370, 543, 543, 543, 543, 410, 410, 543, 256, 256, 256, 256, 256, 256, 81, 403, 4, + -32, 24, '', 0, 43, 0, 1.43, 100, 100, 100), + (24, 80, 80, 10090, 0, 1760, 2400, 561, 561, 561, 561, 418, 418, 561, 262, 262, 262, 262, 262, 262, 84, 419, 4, + -37, 23, '', 0, 43, 0, 1.43, 100, 100, 100), + (24, 81, 81, 10379, 0, 1782, 2430, 574, 574, 574, 574, 426, 426, 574, 264, 264, 264, 264, 264, 264, 87, 436, 4, + -37, 23, '', 0, 44, 0, 1.43, 100, 100, 100), + (24, 82, 82, 10674, 0, 1804, 2460, 588, 588, 588, 588, 434, 434, 588, 266, 266, 266, 266, 266, 266, 91, 452, 4, + -37, 23, '', 0, 44, 0, 1.43, 100, 100, 100), + (24, 83, 83, 10975, 0, 1826, 2490, 601, 601, 601, 601, 442, 442, 601, 268, 268, 268, 268, 268, 268, 94, 468, 4, + -37, 23, '', 0, 44, 0, 1.43, 100, 100, 100), + (24, 84, 84, 11282, 0, 1848, 2520, 615, 615, 615, 615, 450, 450, 615, 274, 274, 274, 274, 274, 274, 97, 484, 4, + -37, 23, '', 0, 45, 0, 1.43, 100, 100, 100), + (24, 85, 85, 11596, 0, 1870, 2550, 629, 629, 629, 629, 458, 458, 629, 276, 276, 276, 276, 276, 276, 100, 501, 4, + -37, 23, '', 0, 45, 0, 1.43, 100, 100, 100), + (25, 1, 1, 60, 0, 22, 30, 70, 70, 70, 70, 83, 83, 70, 27, 27, 27, 27, 27, 27, 5, 19, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (25, 2, 2, 110, 0, 45, 61, 71, 71, 71, 71, 86, 86, 71, 29, 29, 29, 29, 29, 29, 5, 20, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (25, 3, 3, 160, 0, 67, 91, 71, 71, 71, 71, 89, 89, 71, 31, 31, 31, 31, 31, 31, 5, 22, 1, -18, 30, '', 0, 20, 0, + 1.25, 100, 100, 100), + (25, 4, 4, 210, 0, 90, 122, 72, 72, 72, 72, 92, 92, 72, 38, 38, 38, 38, 38, 38, 6, 23, 1, -18, 30, '', 0, 20, 0, + 1.25, 100, 100, 100), + (25, 5, 5, 261, 0, 112, 152, 73, 73, 73, 73, 95, 95, 73, 40, 40, 40, 40, 40, 40, 6, 24, 1, -18, 30, '', 0, 20, 0, + 1.25, 100, 100, 100), + (25, 6, 6, 312, 0, 135, 183, 74, 74, 74, 74, 98, 98, 74, 42, 42, 42, 42, 42, 42, 6, 26, 1, -18, 30, '', 0, 21, 0, + 1.25, 100, 100, 100), + (25, 7, 7, 364, 0, 157, 213, 75, 75, 75, 75, 101, 101, 75, 44, 44, 44, 44, 44, 44, 6, 27, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (25, 8, 8, 416, 0, 180, 244, 77, 77, 77, 77, 104, 104, 77, 51, 51, 51, 51, 51, 51, 7, 28, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (25, 9, 9, 469, 0, 202, 274, 78, 78, 78, 78, 107, 107, 78, 53, 53, 53, 53, 53, 53, 7, 30, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (25, 10, 10, 522, 0, 225, 305, 85, 85, 85, 85, 110, 110, 85, 55, 55, 55, 55, 55, 55, 7, 31, 1, -18, 30, '', 0, + 22, 0, 1.25, 100, 100, 100), + (25, 11, 11, 576, 0, 247, 335, 86, 86, 86, 86, 113, 113, 86, 57, 57, 57, 57, 57, 57, 7, 32, 1, -18, 30, '', 0, + 22, 0, 1.25, 100, 100, 100), + (25, 12, 12, 631, 0, 270, 366, 88, 88, 88, 88, 116, 116, 88, 64, 64, 64, 64, 64, 64, 8, 33, 1, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (25, 13, 13, 687, 0, 292, 396, 89, 89, 89, 89, 119, 119, 89, 66, 66, 66, 66, 66, 66, 8, 35, 1, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (25, 14, 14, 744, 0, 315, 427, 91, 91, 91, 91, 122, 122, 91, 68, 68, 68, 68, 68, 68, 8, 36, 1, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (25, 15, 15, 802, 0, 337, 457, 93, 93, 93, 93, 125, 125, 93, 70, 70, 70, 70, 70, 70, 8, 37, 1, -18, 30, '', 0, + 24, 0, 1.25, 100, 100, 100), + (25, 16, 16, 861, 0, 360, 488, 95, 95, 95, 95, 128, 128, 95, 77, 77, 77, 77, 77, 77, 9, 39, 1, -18, 30, '', 0, + 24, 0, 1.25, 100, 100, 100), + (25, 17, 17, 921, 0, 382, 518, 97, 97, 97, 97, 131, 131, 97, 79, 79, 79, 79, 79, 79, 9, 40, 2, -18, 30, '', 0, + 24, 0, 1.25, 100, 100, 100), + (25, 18, 18, 982, 0, 405, 549, 100, 100, 100, 100, 134, 134, 100, 81, 81, 81, 81, 81, 81, 9, 41, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (25, 19, 19, 1045, 0, 427, 579, 102, 102, 102, 102, 137, 137, 102, 83, 83, 83, 83, 83, 83, 9, 43, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (25, 20, 20, 1110, 0, 450, 610, 110, 110, 110, 110, 140, 140, 110, 90, 90, 90, 90, 90, 90, 10, 44, 2, -18, 30, + '', 0, 25, 0, 1.25, 100, 100, 100), + (25, 21, 21, 1175, 0, 472, 640, 112, 112, 112, 112, 143, 143, 112, 92, 92, 92, 92, 92, 92, 10, 45, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (25, 22, 22, 1243, 0, 495, 671, 115, 115, 115, 115, 146, 146, 115, 94, 94, 94, 94, 94, 94, 10, 46, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (25, 23, 23, 1312, 0, 517, 701, 117, 117, 117, 117, 149, 149, 117, 96, 96, 96, 96, 96, 96, 10, 48, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (25, 24, 24, 1382, 0, 540, 732, 120, 120, 120, 120, 152, 152, 120, 103, 103, 103, 103, 103, 103, 11, 49, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (25, 25, 25, 1455, 0, 562, 762, 123, 123, 123, 123, 155, 155, 123, 105, 105, 105, 105, 105, 105, 11, 50, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (25, 26, 26, 1529, 0, 585, 793, 126, 126, 126, 126, 158, 158, 126, 107, 107, 107, 107, 107, 107, 11, 52, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (25, 27, 27, 1606, 0, 607, 823, 129, 129, 129, 129, 161, 161, 129, 109, 109, 109, 109, 109, 109, 11, 53, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (25, 28, 28, 1684, 0, 630, 854, 133, 133, 133, 133, 164, 164, 133, 116, 116, 116, 116, 116, 116, 12, 54, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (25, 29, 29, 1764, 0, 652, 884, 136, 136, 136, 136, 167, 167, 136, 118, 118, 118, 118, 118, 118, 12, 56, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (25, 30, 30, 1847, 0, 675, 915, 145, 145, 145, 145, 170, 170, 145, 120, 120, 120, 120, 120, 120, 12, 57, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (25, 31, 31, 1932, 0, 697, 945, 148, 148, 148, 148, 173, 173, 148, 122, 122, 122, 122, 122, 122, 12, 58, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (25, 32, 32, 2019, 0, 720, 976, 152, 152, 152, 152, 176, 176, 152, 129, 129, 129, 129, 129, 129, 13, 59, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (25, 33, 33, 2109, 0, 742, 1006, 155, 155, 155, 155, 179, 179, 155, 131, 131, 131, 131, 131, 131, 13, 61, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (25, 34, 34, 2201, 0, 765, 1037, 159, 159, 159, 159, 182, 182, 159, 133, 133, 133, 133, 133, 133, 13, 62, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (25, 35, 35, 2295, 0, 787, 1067, 163, 163, 163, 163, 185, 185, 163, 135, 135, 135, 135, 135, 135, 13, 63, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (25, 36, 36, 2393, 0, 810, 1098, 167, 167, 167, 167, 188, 188, 167, 142, 142, 142, 142, 142, 142, 14, 65, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (25, 37, 37, 2493, 0, 832, 1128, 171, 171, 171, 171, 191, 191, 171, 144, 144, 144, 144, 144, 144, 14, 66, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (25, 38, 38, 2595, 0, 855, 1159, 176, 176, 176, 176, 194, 194, 176, 146, 146, 146, 146, 146, 146, 14, 67, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (25, 39, 39, 2701, 0, 877, 1189, 180, 180, 180, 180, 197, 197, 180, 148, 148, 148, 148, 148, 148, 14, 69, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (25, 40, 40, 2810, 0, 900, 1220, 190, 190, 190, 190, 200, 200, 190, 155, 155, 155, 155, 155, 155, 15, 70, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (25, 41, 41, 2921, 0, 922, 1250, 194, 194, 194, 194, 203, 203, 194, 157, 157, 157, 157, 157, 157, 15, 71, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (25, 42, 42, 3036, 0, 945, 1281, 199, 199, 199, 199, 206, 206, 199, 159, 159, 159, 159, 159, 159, 15, 72, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (25, 43, 43, 3153, 0, 967, 1311, 203, 203, 203, 203, 209, 209, 203, 161, 161, 161, 161, 161, 161, 15, 74, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (25, 44, 44, 3274, 0, 990, 1342, 208, 208, 208, 208, 212, 212, 208, 168, 168, 168, 168, 168, 168, 16, 75, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (25, 45, 45, 3399, 0, 1012, 1372, 213, 213, 213, 213, 215, 215, 213, 170, 170, 170, 170, 170, 170, 16, 76, 2, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (25, 46, 46, 3526, 0, 1035, 1403, 218, 218, 218, 218, 218, 218, 218, 172, 172, 172, 172, 172, 172, 16, 78, 2, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (25, 47, 47, 3657, 0, 1057, 1433, 223, 223, 223, 223, 221, 221, 223, 174, 174, 174, 174, 174, 174, 16, 79, 3, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (25, 48, 48, 3792, 0, 1080, 1464, 229, 229, 229, 229, 224, 224, 229, 181, 181, 181, 181, 181, 181, 17, 80, 3, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (25, 49, 49, 3930, 0, 1102, 1494, 234, 234, 234, 234, 227, 227, 234, 183, 183, 183, 183, 183, 183, 17, 82, 3, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (25, 50, 50, 4072, 0, 1125, 1525, 245, 245, 245, 245, 230, 230, 245, 185, 185, 185, 185, 185, 185, 17, 83, 3, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (25, 51, 51, 4218, 0, 1147, 1555, 250, 250, 250, 250, 233, 233, 250, 187, 187, 187, 187, 187, 187, 17, 84, 3, + -18, 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (25, 52, 52, 4367, 0, 1170, 1586, 256, 256, 256, 256, 236, 236, 256, 194, 194, 194, 194, 194, 194, 18, 85, 3, + -18, 30, '', 0, 36, 0, 1.49, 100, 100, 100), + (25, 53, 53, 4520, 0, 1192, 1616, 261, 261, 261, 261, 239, 239, 261, 196, 196, 196, 196, 196, 196, 18, 87, 3, + -18, 30, '', 0, 36, 0, 1.49, 100, 100, 100), + (25, 54, 54, 4678, 0, 1215, 1647, 267, 267, 267, 267, 242, 242, 267, 198, 198, 198, 198, 198, 198, 18, 88, 3, + -18, 30, '', 0, 37, 0, 1.49, 100, 100, 100), + (25, 55, 55, 4839, 0, 1237, 1677, 273, 273, 273, 273, 245, 245, 273, 200, 200, 200, 200, 200, 200, 18, 89, 3, + -18, 30, '', 0, 37, 0, 1.49, 100, 100, 100), + (25, 56, 56, 5005, 0, 1260, 1708, 279, 279, 279, 279, 248, 248, 279, 207, 207, 207, 207, 207, 207, 19, 91, 3, + -18, 30, '', 0, 37, 0, 1.49, 100, 100, 100), + (25, 57, 57, 5174, 0, 1282, 1738, 285, 285, 285, 285, 251, 251, 285, 209, 209, 209, 209, 209, 209, 19, 92, 3, + -18, 30, '', 0, 38, 0, 1.49, 100, 100, 100), + (25, 58, 58, 5348, 0, 1305, 1769, 292, 292, 292, 292, 254, 254, 292, 211, 211, 211, 211, 211, 211, 19, 93, 3, + -18, 30, '', 0, 38, 0, 1.49, 100, 100, 100), + (25, 59, 59, 5527, 0, 1327, 1799, 298, 298, 298, 298, 257, 257, 298, 213, 213, 213, 213, 213, 213, 19, 95, 3, + -18, 30, '', 0, 38, 0, 1.49, 100, 100, 100), + (25, 60, 60, 5710, 0, 1350, 1830, 310, 310, 310, 310, 260, 260, 310, 220, 220, 220, 220, 220, 220, 20, 96, 3, + -18, 30, '', 0, 39, 0, 1.49, 100, 100, 100), + (25, 61, 61, 5897, 0, 1372, 1860, 316, 316, 316, 316, 263, 263, 316, 222, 222, 222, 222, 222, 222, 23, 112, 4, + -24, 27, '', 0, 39, 0, 1.49, 100, 100, 100), + (25, 62, 62, 6089, 0, 1395, 1891, 323, 323, 323, 323, 266, 266, 323, 224, 224, 224, 224, 224, 224, 26, 128, 4, + -25, 27, '', 0, 39, 0, 1.49, 100, 100, 100), + (25, 63, 63, 6285, 0, 1417, 1921, 329, 329, 329, 329, 269, 269, 329, 226, 226, 226, 226, 226, 226, 29, 145, 4, + -25, 27, '', 0, 40, 0, 1.49, 100, 100, 100), + (25, 64, 64, 6486, 0, 1440, 1952, 336, 336, 336, 336, 272, 272, 336, 233, 233, 233, 233, 233, 233, 33, 161, 4, + -26, 27, '', 0, 40, 0, 1.49, 100, 100, 100), + (25, 65, 65, 6692, 0, 1462, 1982, 343, 343, 343, 343, 275, 275, 343, 235, 235, 235, 235, 235, 235, 36, 177, 4, + -26, 27, '', 0, 40, 0, 1.49, 100, 100, 100), + (25, 66, 66, 6903, 0, 1485, 2013, 380, 380, 380, 380, 308, 308, 380, 237, 237, 237, 237, 237, 237, 39, 194, 4, + -27, 26, '', 0, 41, 0, 1.49, 100, 100, 100), + (25, 67, 67, 7119, 0, 1507, 2043, 392, 392, 392, 392, 316, 316, 392, 239, 239, 239, 239, 239, 239, 42, 210, 4, + -27, 26, '', 0, 41, 0, 1.49, 100, 100, 100), + (25, 68, 68, 7340, 0, 1530, 2074, 405, 405, 405, 405, 324, 324, 405, 246, 246, 246, 246, 246, 246, 46, 226, 4, + -28, 26, '', 0, 41, 0, 1.49, 100, 100, 100), + (25, 69, 69, 7566, 0, 1552, 2104, 417, 417, 417, 417, 332, 332, 417, 248, 248, 248, 248, 248, 248, 49, 243, 4, + -28, 26, '', 0, 42, 0, 1.49, 100, 100, 100), + (25, 70, 70, 7797, 0, 1575, 2135, 435, 435, 435, 435, 340, 340, 435, 250, 250, 250, 250, 250, 250, 52, 259, 4, + -29, 26, '', 0, 42, 0, 1.49, 100, 100, 100), + (25, 71, 71, 8033, 0, 1597, 2165, 447, 447, 447, 447, 348, 348, 447, 252, 252, 252, 252, 252, 252, 55, 275, 4, + -29, 26, '', 0, 42, 0, 1.49, 100, 100, 100), + (25, 72, 72, 8275, 0, 1620, 2196, 460, 460, 460, 460, 356, 356, 460, 259, 259, 259, 259, 259, 259, 59, 291, 4, + -30, 25, '', 0, 43, 0, 1.49, 100, 100, 100), + (25, 73, 73, 8522, 0, 1642, 2226, 472, 472, 472, 472, 364, 364, 472, 261, 261, 261, 261, 261, 261, 62, 308, 4, + -30, 25, '', 0, 43, 0, 1.49, 100, 100, 100), + (25, 74, 74, 8775, 0, 1665, 2257, 485, 485, 485, 485, 372, 372, 485, 263, 263, 263, 263, 263, 263, 65, 324, 4, + -31, 25, '', 0, 43, 0, 1.49, 100, 100, 100), + (25, 75, 75, 9033, 0, 1687, 2287, 498, 498, 498, 498, 380, 380, 498, 265, 265, 265, 265, 265, 265, 68, 340, 4, + -31, 25, '', 0, 44, 0, 1.49, 100, 100, 100), + (25, 76, 76, 9297, 0, 1710, 2318, 511, 511, 511, 511, 388, 388, 511, 272, 272, 272, 272, 272, 272, 72, 357, 4, + -32, 24, '', 0, 44, 0, 1.49, 100, 100, 100), + (25, 77, 77, 9566, 0, 1732, 2348, 524, 524, 524, 524, 396, 396, 524, 274, 274, 274, 274, 274, 274, 75, 373, 4, + -32, 24, '', 0, 44, 0, 1.49, 100, 100, 100), + (25, 78, 78, 9841, 0, 1755, 2379, 538, 538, 538, 538, 404, 404, 538, 276, 276, 276, 276, 276, 276, 78, 389, 4, + -33, 24, '', 0, 45, 0, 1.49, 100, 100, 100), + (25, 79, 79, 10122, 0, 1777, 2409, 551, 551, 551, 551, 412, 412, 551, 278, 278, 278, 278, 278, 278, 81, 406, 4, + -33, 24, '', 0, 45, 0, 1.49, 100, 100, 100), + (25, 80, 80, 10410, 0, 1800, 2440, 570, 570, 570, 570, 420, 420, 570, 285, 285, 285, 285, 285, 285, 85, 422, 4, + -38, 22, '', 0, 45, 0, 1.49, 100, 100, 100), + (25, 81, 81, 10703, 0, 1822, 2470, 583, 583, 583, 583, 428, 428, 583, 287, 287, 287, 287, 287, 287, 88, 438, 4, + -38, 22, '', 0, 46, 0, 1.49, 100, 100, 100), + (25, 82, 82, 11002, 0, 1845, 2501, 597, 597, 597, 597, 436, 436, 597, 289, 289, 289, 289, 289, 289, 91, 454, 4, + -38, 22, '', 0, 46, 0, 1.49, 100, 100, 100), + (25, 83, 83, 11307, 0, 1867, 2531, 610, 610, 610, 610, 444, 444, 610, 291, 291, 291, 291, 291, 291, 94, 471, 4, + -38, 22, '', 0, 46, 0, 1.49, 100, 100, 100), + (25, 84, 84, 11618, 0, 1890, 2562, 624, 624, 624, 624, 452, 452, 624, 298, 298, 298, 298, 298, 298, 98, 487, 4, + -38, 22, '', 0, 47, 0, 1.49, 100, 100, 100), + (25, 85, 85, 11936, 0, 1912, 2592, 638, 638, 638, 638, 460, 460, 638, 300, 300, 300, 300, 300, 300, 101, 503, 4, + -38, 22, '', 0, 47, 0, 1.49, 100, 100, 100), + (26, 1, 1, 74, 0, 25, 31, 71, 71, 71, 71, 95, 95, 71, 31, 31, 31, 31, 31, 31, 4, 15, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (26, 2, 2, 138, 0, 51, 63, 73, 73, 73, 73, 98, 98, 73, 35, 35, 35, 35, 35, 35, 4, 17, 1, -18, 30, '', 0, 19, 0, + 1.25, 100, 100, 100), + (26, 3, 3, 202, 0, 76, 94, 73, 73, 73, 73, 101, 101, 73, 37, 37, 37, 37, 37, 37, 5, 18, 1, -18, 30, '', 0, 20, 0, + 1.25, 100, 100, 100), + (26, 4, 4, 266, 0, 102, 126, 75, 75, 75, 75, 104, 104, 75, 40, 40, 40, 40, 40, 40, 5, 19, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (26, 5, 5, 331, 0, 127, 157, 76, 76, 76, 76, 107, 107, 76, 44, 44, 44, 44, 44, 44, 5, 20, 1, -18, 30, '', 0, 20, + 0, 1.25, 100, 100, 100), + (26, 6, 6, 396, 0, 153, 189, 78, 78, 78, 78, 110, 110, 78, 46, 46, 46, 46, 46, 46, 5, 22, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (26, 7, 7, 462, 0, 178, 220, 79, 79, 79, 79, 113, 113, 79, 48, 48, 48, 48, 48, 48, 6, 23, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (26, 8, 8, 528, 0, 204, 252, 82, 82, 82, 82, 116, 116, 82, 53, 53, 53, 53, 53, 53, 6, 24, 1, -18, 30, '', 0, 21, + 0, 1.25, 100, 100, 100), + (26, 9, 9, 595, 0, 229, 283, 83, 83, 83, 83, 119, 119, 83, 55, 55, 55, 55, 55, 55, 6, 26, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (26, 10, 10, 662, 0, 255, 315, 87, 87, 87, 87, 122, 122, 87, 57, 57, 57, 57, 57, 57, 6, 27, 1, -18, 30, '', 0, + 22, 0, 1.25, 100, 100, 100), + (26, 11, 11, 730, 0, 280, 346, 88, 88, 88, 88, 125, 125, 88, 61, 61, 61, 61, 61, 61, 7, 28, 1, -18, 30, '', 0, + 22, 0, 1.25, 100, 100, 100), + (26, 12, 12, 799, 0, 306, 378, 91, 91, 91, 91, 128, 128, 91, 64, 64, 64, 64, 64, 64, 7, 30, 1, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (26, 13, 13, 869, 0, 331, 409, 92, 92, 92, 92, 131, 131, 92, 66, 66, 66, 66, 66, 66, 7, 31, 1, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (26, 14, 14, 940, 0, 357, 441, 95, 95, 95, 95, 134, 134, 95, 70, 70, 70, 70, 70, 70, 7, 32, 1, -18, 30, '', 0, + 23, 0, 1.25, 100, 100, 100), + (26, 15, 15, 1012, 0, 382, 472, 97, 97, 97, 97, 137, 137, 97, 72, 72, 72, 72, 72, 72, 8, 33, 1, -18, 30, '', 0, + 24, 0, 1.25, 100, 100, 100), + (26, 16, 16, 1085, 0, 408, 504, 100, 100, 100, 100, 140, 140, 100, 75, 75, 75, 75, 75, 75, 8, 35, 1, -18, 30, '', + 0, 24, 0, 1.25, 100, 100, 100), + (26, 17, 17, 1159, 0, 433, 535, 102, 102, 102, 102, 143, 143, 102, 79, 79, 79, 79, 79, 79, 8, 36, 2, -18, 30, '', + 0, 24, 0, 1.25, 100, 100, 100), + (26, 18, 18, 1234, 0, 459, 567, 106, 106, 106, 106, 146, 146, 106, 81, 81, 81, 81, 81, 81, 8, 37, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (26, 19, 19, 1311, 0, 484, 598, 108, 108, 108, 108, 149, 149, 108, 83, 83, 83, 83, 83, 83, 9, 39, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (26, 20, 20, 1390, 0, 510, 630, 113, 113, 113, 113, 152, 152, 113, 88, 88, 88, 88, 88, 88, 9, 40, 2, -18, 30, '', + 0, 25, 0, 1.25, 100, 100, 100), + (26, 21, 21, 1469, 0, 535, 661, 115, 115, 115, 115, 155, 155, 115, 90, 90, 90, 90, 90, 90, 9, 41, 2, -18, 30, '', + 0, 26, 0, 1.25, 100, 100, 100), + (26, 22, 22, 1551, 0, 561, 693, 119, 119, 119, 119, 158, 158, 119, 92, 92, 92, 92, 92, 92, 9, 43, 2, -18, 30, '', + 0, 26, 0, 1.25, 100, 100, 100), + (26, 23, 23, 1634, 0, 586, 724, 121, 121, 121, 121, 161, 161, 121, 96, 96, 96, 96, 96, 96, 10, 44, 2, -18, 30, + '', 0, 26, 0, 1.25, 100, 100, 100), + (26, 24, 24, 1718, 0, 612, 756, 125, 125, 125, 125, 164, 164, 125, 99, 99, 99, 99, 99, 99, 10, 45, 2, -18, 30, + '', 0, 27, 0, 1.25, 100, 100, 100), + (26, 25, 25, 1805, 0, 637, 787, 128, 128, 128, 128, 167, 167, 128, 101, 101, 101, 101, 101, 101, 10, 46, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (26, 26, 26, 1893, 0, 663, 819, 132, 132, 132, 132, 170, 170, 132, 105, 105, 105, 105, 105, 105, 10, 48, 2, -18, + 30, '', 0, 27, 0, 1.25, 100, 100, 100), + (26, 27, 27, 1984, 0, 688, 850, 135, 135, 135, 135, 173, 173, 135, 107, 107, 107, 107, 107, 107, 11, 49, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (26, 28, 28, 2076, 0, 714, 882, 140, 140, 140, 140, 176, 176, 140, 110, 110, 110, 110, 110, 110, 11, 50, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (26, 29, 29, 2170, 0, 739, 913, 143, 143, 143, 143, 179, 179, 143, 114, 114, 114, 114, 114, 114, 11, 52, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (26, 30, 30, 2267, 0, 765, 945, 149, 149, 149, 149, 182, 182, 149, 116, 116, 116, 116, 116, 116, 11, 53, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (26, 31, 31, 2366, 0, 790, 976, 152, 152, 152, 152, 185, 185, 152, 118, 118, 118, 118, 118, 118, 12, 54, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (26, 32, 32, 2467, 0, 816, 1008, 157, 157, 157, 157, 188, 188, 157, 123, 123, 123, 123, 123, 123, 12, 56, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (26, 33, 33, 2571, 0, 841, 1039, 160, 160, 160, 160, 191, 191, 160, 125, 125, 125, 125, 125, 125, 12, 57, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (26, 34, 34, 2677, 0, 867, 1071, 165, 165, 165, 165, 194, 194, 165, 127, 127, 127, 127, 127, 127, 12, 58, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (26, 35, 35, 2785, 0, 892, 1102, 169, 169, 169, 169, 197, 197, 169, 131, 131, 131, 131, 131, 131, 13, 59, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (26, 36, 36, 2897, 0, 918, 1134, 174, 174, 174, 174, 200, 200, 174, 134, 134, 134, 134, 134, 134, 13, 61, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (26, 37, 37, 3011, 0, 943, 1165, 178, 178, 178, 178, 203, 203, 178, 136, 136, 136, 136, 136, 136, 13, 62, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (26, 38, 38, 3127, 0, 969, 1197, 184, 184, 184, 184, 206, 206, 184, 140, 140, 140, 140, 140, 140, 13, 63, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (26, 39, 39, 3247, 0, 994, 1228, 188, 188, 188, 188, 209, 209, 188, 142, 142, 142, 142, 142, 142, 14, 65, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (26, 40, 40, 3370, 0, 1020, 1260, 195, 195, 195, 195, 212, 212, 195, 145, 145, 145, 145, 145, 145, 14, 66, 2, + -18, 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (26, 41, 41, 3495, 0, 1045, 1291, 199, 199, 199, 199, 215, 215, 199, 149, 149, 149, 149, 149, 149, 14, 67, 2, + -18, 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (26, 42, 42, 3624, 0, 1071, 1323, 205, 205, 205, 205, 218, 218, 205, 151, 151, 151, 151, 151, 151, 14, 69, 2, + -18, 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (26, 43, 43, 3755, 0, 1096, 1354, 209, 209, 209, 209, 221, 221, 209, 153, 153, 153, 153, 153, 153, 15, 70, 2, + -18, 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (26, 44, 44, 3890, 0, 1122, 1386, 215, 215, 215, 215, 224, 224, 215, 158, 158, 158, 158, 158, 158, 15, 71, 2, + -18, 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (26, 45, 45, 4029, 0, 1147, 1417, 220, 220, 220, 220, 227, 227, 220, 160, 160, 160, 160, 160, 160, 15, 72, 2, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (26, 46, 46, 4170, 0, 1173, 1449, 226, 226, 226, 226, 230, 230, 226, 162, 162, 162, 162, 162, 162, 15, 74, 2, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (26, 47, 47, 4315, 0, 1198, 1480, 231, 231, 231, 231, 233, 233, 231, 166, 166, 166, 166, 166, 166, 16, 75, 3, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (26, 48, 48, 4464, 0, 1224, 1512, 238, 238, 238, 238, 236, 236, 238, 169, 169, 169, 169, 169, 169, 16, 76, 3, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (26, 49, 49, 4616, 0, 1249, 1543, 243, 243, 243, 243, 239, 239, 243, 171, 171, 171, 171, 171, 171, 16, 78, 3, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (26, 50, 50, 4772, 0, 1275, 1575, 251, 251, 251, 251, 242, 242, 251, 175, 175, 175, 175, 175, 175, 16, 79, 3, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (26, 51, 51, 4932, 0, 1300, 1606, 256, 256, 256, 256, 245, 245, 256, 177, 177, 177, 177, 177, 177, 17, 80, 3, + -18, 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (26, 52, 52, 5095, 0, 1326, 1638, 263, 263, 263, 263, 248, 248, 263, 180, 180, 180, 180, 180, 180, 17, 82, 3, + -18, 30, '', 0, 36, 0, 1.55, 100, 100, 100), + (26, 53, 53, 5262, 0, 1351, 1669, 268, 268, 268, 268, 251, 251, 268, 184, 184, 184, 184, 184, 184, 17, 83, 3, + -18, 30, '', 0, 36, 0, 1.55, 100, 100, 100), + (26, 54, 54, 5434, 0, 1377, 1701, 275, 275, 275, 275, 254, 254, 275, 186, 186, 186, 186, 186, 186, 17, 84, 3, + -18, 30, '', 0, 37, 0, 1.55, 100, 100, 100), + (26, 55, 55, 5609, 0, 1402, 1732, 281, 281, 281, 281, 257, 257, 281, 188, 188, 188, 188, 188, 188, 18, 85, 3, + -18, 30, '', 0, 37, 0, 1.55, 100, 100, 100), + (26, 56, 56, 5789, 0, 1428, 1764, 288, 288, 288, 288, 260, 260, 288, 193, 193, 193, 193, 193, 193, 18, 87, 3, + -18, 30, '', 0, 37, 0, 1.55, 100, 100, 100), + (26, 57, 57, 5972, 0, 1453, 1795, 294, 294, 294, 294, 263, 263, 294, 195, 195, 195, 195, 195, 195, 18, 88, 3, + -18, 30, '', 0, 38, 0, 1.55, 100, 100, 100), + (26, 58, 58, 6160, 0, 1479, 1827, 302, 302, 302, 302, 266, 266, 302, 197, 197, 197, 197, 197, 197, 18, 89, 3, + -18, 30, '', 0, 38, 0, 1.55, 100, 100, 100), + (26, 59, 59, 6353, 0, 1504, 1858, 308, 308, 308, 308, 269, 269, 308, 201, 201, 201, 201, 201, 201, 19, 91, 3, + -18, 30, '', 0, 38, 0, 1.55, 100, 100, 100), + (26, 60, 60, 6550, 0, 1530, 1890, 317, 317, 317, 317, 272, 272, 317, 204, 204, 204, 204, 204, 204, 19, 92, 3, + -18, 30, '', 0, 39, 0, 1.55, 100, 100, 100), + (26, 61, 61, 6751, 0, 1555, 1921, 323, 323, 323, 323, 275, 275, 323, 206, 206, 206, 206, 206, 206, 22, 108, 4, + -25, 27, '', 0, 39, 0, 1.55, 100, 100, 100), + (26, 62, 62, 6957, 0, 1581, 1953, 331, 331, 331, 331, 278, 278, 331, 210, 210, 210, 210, 210, 210, 25, 125, 4, + -26, 27, '', 0, 39, 0, 1.55, 100, 100, 100), + (26, 63, 63, 7167, 0, 1606, 1984, 337, 337, 337, 337, 281, 281, 337, 212, 212, 212, 212, 212, 212, 29, 141, 4, + -26, 27, '', 0, 40, 0, 1.55, 100, 100, 100), + (26, 64, 64, 7382, 0, 1632, 2016, 345, 345, 345, 345, 284, 284, 345, 215, 215, 215, 215, 215, 215, 32, 157, 4, + -27, 26, '', 0, 40, 0, 1.55, 100, 100, 100), + (26, 65, 65, 7602, 0, 1657, 2047, 352, 352, 352, 352, 287, 287, 352, 219, 219, 219, 219, 219, 219, 35, 173, 4, + -27, 26, '', 0, 40, 0, 1.55, 100, 100, 100), + (26, 66, 66, 7827, 0, 1683, 2079, 390, 390, 390, 390, 320, 320, 390, 221, 221, 221, 221, 221, 221, 38, 190, 4, + -28, 26, '', 0, 41, 0, 1.55, 100, 100, 100), + (26, 67, 67, 8057, 0, 1708, 2110, 402, 402, 402, 402, 328, 328, 402, 223, 223, 223, 223, 223, 223, 42, 206, 4, + -28, 26, '', 0, 41, 0, 1.55, 100, 100, 100), + (26, 68, 68, 8292, 0, 1734, 2142, 416, 416, 416, 416, 336, 336, 416, 228, 228, 228, 228, 228, 228, 45, 222, 4, + -29, 26, '', 0, 41, 0, 1.55, 100, 100, 100), + (26, 69, 69, 8532, 0, 1759, 2173, 428, 428, 428, 428, 344, 344, 428, 230, 230, 230, 230, 230, 230, 48, 239, 4, + -29, 26, '', 0, 42, 0, 1.55, 100, 100, 100), + (26, 70, 70, 8777, 0, 1785, 2205, 443, 443, 443, 443, 352, 352, 443, 232, 232, 232, 232, 232, 232, 51, 255, 4, + -30, 25, '', 0, 42, 0, 1.55, 100, 100, 100), + (26, 71, 71, 9027, 0, 1810, 2236, 455, 455, 455, 455, 360, 360, 455, 236, 236, 236, 236, 236, 236, 55, 271, 4, + -30, 25, '', 0, 42, 0, 1.55, 100, 100, 100), + (26, 72, 72, 9283, 0, 1836, 2268, 469, 469, 469, 469, 368, 368, 469, 239, 239, 239, 239, 239, 239, 58, 288, 4, + -31, 25, '', 0, 43, 0, 1.55, 100, 100, 100), + (26, 73, 73, 9544, 0, 1861, 2299, 481, 481, 481, 481, 376, 376, 481, 241, 241, 241, 241, 241, 241, 61, 304, 4, + -31, 25, '', 0, 43, 0, 1.55, 100, 100, 100), + (26, 74, 74, 9811, 0, 1887, 2331, 495, 495, 495, 495, 384, 384, 495, 245, 245, 245, 245, 245, 245, 64, 320, 4, + -32, 24, '', 0, 43, 0, 1.55, 100, 100, 100), + (26, 75, 75, 10083, 0, 1912, 2362, 508, 508, 508, 508, 392, 392, 508, 247, 247, 247, 247, 247, 247, 68, 336, 4, + -32, 24, '', 0, 44, 0, 1.55, 100, 100, 100), + (26, 76, 76, 10361, 0, 1938, 2394, 522, 522, 522, 522, 400, 400, 522, 250, 250, 250, 250, 250, 250, 71, 353, 4, + -33, 24, '', 0, 44, 0, 1.55, 100, 100, 100), + (26, 77, 77, 10644, 0, 1963, 2425, 535, 535, 535, 535, 408, 408, 535, 254, 254, 254, 254, 254, 254, 74, 369, 4, + -33, 24, '', 0, 44, 0, 1.55, 100, 100, 100), + (26, 78, 78, 10933, 0, 1989, 2457, 550, 550, 550, 550, 416, 416, 550, 256, 256, 256, 256, 256, 256, 77, 385, 4, + -34, 24, '', 0, 45, 0, 1.55, 100, 100, 100), + (26, 79, 79, 11228, 0, 2014, 2488, 563, 563, 563, 563, 424, 424, 563, 258, 258, 258, 258, 258, 258, 81, 402, 4, + -34, 24, '', 0, 45, 0, 1.55, 100, 100, 100), + (26, 80, 80, 11530, 0, 2040, 2520, 579, 579, 579, 579, 432, 432, 579, 263, 263, 263, 263, 263, 263, 84, 418, 4, + -39, 22, '', 0, 45, 0, 1.55, 100, 100, 100), + (26, 81, 81, 11837, 0, 2065, 2551, 592, 592, 592, 592, 440, 440, 592, 265, 265, 265, 265, 265, 265, 87, 434, 4, + -39, 22, '', 0, 46, 0, 1.55, 100, 100, 100), + (26, 82, 82, 12150, 0, 2091, 2583, 607, 607, 607, 607, 448, 448, 607, 267, 267, 267, 267, 267, 267, 90, 451, 4, + -39, 22, '', 0, 46, 0, 1.55, 100, 100, 100), + (26, 83, 83, 12469, 0, 2116, 2614, 620, 620, 620, 620, 456, 456, 620, 271, 271, 271, 271, 271, 271, 94, 467, 4, + -39, 22, '', 0, 46, 0, 1.55, 100, 100, 100), + (26, 84, 84, 12794, 0, 2142, 2646, 635, 635, 635, 635, 464, 464, 635, 274, 274, 274, 274, 274, 274, 97, 483, 4, + -39, 22, '', 0, 47, 0, 1.55, 100, 100, 100), + (26, 85, 85, 13126, 0, 2167, 2677, 649, 649, 649, 649, 472, 472, 649, 276, 276, 276, 276, 276, 276, 100, 499, 4, + -39, 22, '', 0, 47, 0, 1.55, 100, 100, 100), + (27, 1, 1, 78, 0, 26, 32, 72, 72, 72, 72, 97, 97, 72, 34, 34, 34, 34, 34, 34, 5, 18, 1, -18, 30, '', 0, 21, 0, + 1.25, 100, 100, 100), + (27, 2, 2, 146, 0, 52, 64, 74, 74, 74, 74, 100, 100, 74, 38, 38, 38, 38, 38, 38, 5, 19, 1, -18, 30, '', 0, 21, 0, + 1.25, 100, 100, 100), + (27, 3, 3, 214, 0, 78, 96, 74, 74, 74, 74, 103, 103, 74, 40, 40, 40, 40, 40, 40, 5, 20, 1, -18, 30, '', 0, 22, 0, + 1.25, 100, 100, 100), + (27, 4, 4, 282, 0, 104, 128, 76, 76, 76, 76, 106, 106, 76, 44, 44, 44, 44, 44, 44, 5, 22, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (27, 5, 5, 351, 0, 130, 160, 77, 77, 77, 77, 109, 109, 77, 48, 48, 48, 48, 48, 48, 6, 23, 1, -18, 30, '', 0, 22, + 0, 1.25, 100, 100, 100), + (27, 6, 6, 420, 0, 156, 192, 79, 79, 79, 79, 112, 112, 79, 50, 50, 50, 50, 50, 50, 6, 24, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (27, 7, 7, 490, 0, 182, 224, 80, 80, 80, 80, 115, 115, 80, 52, 52, 52, 52, 52, 52, 6, 26, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (27, 8, 8, 560, 0, 208, 256, 83, 83, 83, 83, 118, 118, 83, 58, 58, 58, 58, 58, 58, 6, 27, 1, -18, 30, '', 0, 23, + 0, 1.25, 100, 100, 100), + (27, 9, 9, 631, 0, 234, 288, 84, 84, 84, 84, 121, 121, 84, 60, 60, 60, 60, 60, 60, 7, 28, 1, -18, 30, '', 0, 24, + 0, 1.25, 100, 100, 100), + (27, 10, 10, 702, 0, 260, 320, 89, 89, 89, 89, 124, 124, 89, 62, 62, 62, 62, 62, 62, 7, 30, 1, -18, 30, '', 0, + 24, 0, 1.25, 100, 100, 100), + (27, 11, 11, 774, 0, 286, 352, 90, 90, 90, 90, 127, 127, 90, 66, 66, 66, 66, 66, 66, 7, 31, 1, -18, 30, '', 0, + 24, 0, 1.25, 100, 100, 100), + (27, 12, 12, 847, 0, 312, 384, 93, 93, 93, 93, 130, 130, 93, 70, 70, 70, 70, 70, 70, 7, 32, 1, -18, 30, '', 0, + 25, 0, 1.25, 100, 100, 100), + (27, 13, 13, 921, 0, 338, 416, 94, 94, 94, 94, 133, 133, 94, 72, 72, 72, 72, 72, 72, 8, 33, 1, -18, 30, '', 0, + 25, 0, 1.25, 100, 100, 100), + (27, 14, 14, 996, 0, 364, 448, 97, 97, 97, 97, 136, 136, 97, 76, 76, 76, 76, 76, 76, 8, 35, 1, -18, 30, '', 0, + 25, 0, 1.25, 100, 100, 100), + (27, 15, 15, 1072, 0, 390, 480, 99, 99, 99, 99, 139, 139, 99, 78, 78, 78, 78, 78, 78, 8, 36, 1, -18, 30, '', 0, + 26, 0, 1.25, 100, 100, 100), + (27, 16, 16, 1149, 0, 416, 512, 102, 102, 102, 102, 142, 142, 102, 82, 82, 82, 82, 82, 82, 8, 37, 1, -18, 30, '', + 0, 26, 0, 1.25, 100, 100, 100), + (27, 17, 17, 1227, 0, 442, 544, 104, 104, 104, 104, 145, 145, 104, 86, 86, 86, 86, 86, 86, 9, 39, 2, -18, 30, '', + 0, 26, 0, 1.25, 100, 100, 100), + (27, 18, 18, 1306, 0, 468, 576, 108, 108, 108, 108, 148, 148, 108, 88, 88, 88, 88, 88, 88, 9, 40, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (27, 19, 19, 1387, 0, 494, 608, 110, 110, 110, 110, 151, 151, 110, 90, 90, 90, 90, 90, 90, 9, 41, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (27, 20, 20, 1470, 0, 520, 640, 116, 116, 116, 116, 154, 154, 116, 96, 96, 96, 96, 96, 96, 9, 43, 2, -18, 30, '', + 0, 27, 0, 1.25, 100, 100, 100), + (27, 21, 21, 1553, 0, 546, 672, 118, 118, 118, 118, 157, 157, 118, 98, 98, 98, 98, 98, 98, 10, 44, 2, -18, 30, + '', 0, 28, 0, 1.25, 100, 100, 100), + (27, 22, 22, 1639, 0, 572, 704, 122, 122, 122, 122, 160, 160, 122, 100, 100, 100, 100, 100, 100, 10, 45, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (27, 23, 23, 1726, 0, 598, 736, 124, 124, 124, 124, 163, 163, 124, 104, 104, 104, 104, 104, 104, 10, 46, 2, -18, + 30, '', 0, 28, 0, 1.25, 100, 100, 100), + (27, 24, 24, 1814, 0, 624, 768, 128, 128, 128, 128, 166, 166, 128, 108, 108, 108, 108, 108, 108, 10, 48, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (27, 25, 25, 1905, 0, 650, 800, 131, 131, 131, 131, 169, 169, 131, 110, 110, 110, 110, 110, 110, 11, 49, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (27, 26, 26, 1997, 0, 676, 832, 135, 135, 135, 135, 172, 172, 135, 114, 114, 114, 114, 114, 114, 11, 50, 2, -18, + 30, '', 0, 29, 0, 1.25, 100, 100, 100), + (27, 27, 27, 2092, 0, 702, 864, 138, 138, 138, 138, 175, 175, 138, 116, 116, 116, 116, 116, 116, 11, 52, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (27, 28, 28, 2188, 0, 728, 896, 143, 143, 143, 143, 178, 178, 143, 120, 120, 120, 120, 120, 120, 11, 53, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (27, 29, 29, 2286, 0, 754, 928, 146, 146, 146, 146, 181, 181, 146, 124, 124, 124, 124, 124, 124, 12, 54, 2, -18, + 30, '', 0, 30, 0, 1.25, 100, 100, 100), + (27, 30, 30, 2387, 0, 780, 960, 153, 153, 153, 153, 184, 184, 153, 126, 126, 126, 126, 126, 126, 12, 56, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (27, 31, 31, 2490, 0, 806, 992, 156, 156, 156, 156, 187, 187, 156, 128, 128, 128, 128, 128, 128, 12, 57, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (27, 32, 32, 2595, 0, 832, 1024, 161, 161, 161, 161, 190, 190, 161, 134, 134, 134, 134, 134, 134, 12, 58, 2, -18, + 30, '', 0, 31, 0, 1.25, 100, 100, 100), + (27, 33, 33, 2703, 0, 858, 1056, 164, 164, 164, 164, 193, 193, 164, 136, 136, 136, 136, 136, 136, 13, 59, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (27, 34, 34, 2813, 0, 884, 1088, 169, 169, 169, 169, 196, 196, 169, 138, 138, 138, 138, 138, 138, 13, 61, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (27, 35, 35, 2925, 0, 910, 1120, 173, 173, 173, 173, 199, 199, 173, 142, 142, 142, 142, 142, 142, 13, 62, 2, -18, + 30, '', 0, 32, 0, 1.25, 100, 100, 100), + (27, 36, 36, 3041, 0, 936, 1152, 178, 178, 178, 178, 202, 202, 178, 146, 146, 146, 146, 146, 146, 13, 63, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (27, 37, 37, 3159, 0, 962, 1184, 182, 182, 182, 182, 205, 205, 182, 148, 148, 148, 148, 148, 148, 14, 65, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (27, 38, 38, 3279, 0, 988, 1216, 188, 188, 188, 188, 208, 208, 188, 152, 152, 152, 152, 152, 152, 14, 66, 2, -18, + 30, '', 0, 33, 0, 1.25, 100, 100, 100), + (27, 39, 39, 3403, 0, 1014, 1248, 192, 192, 192, 192, 211, 211, 192, 154, 154, 154, 154, 154, 154, 14, 67, 2, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (27, 40, 40, 3530, 0, 1040, 1280, 200, 200, 200, 200, 214, 214, 200, 158, 158, 158, 158, 158, 158, 14, 69, 2, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (27, 41, 41, 3659, 0, 1066, 1312, 204, 204, 204, 204, 217, 217, 204, 162, 162, 162, 162, 162, 162, 15, 70, 2, + -18, 30, '', 0, 34, 0, 1.25, 100, 100, 100), + (27, 42, 42, 3792, 0, 1092, 1344, 210, 210, 210, 210, 220, 220, 210, 164, 164, 164, 164, 164, 164, 15, 71, 2, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (27, 43, 43, 3927, 0, 1118, 1376, 214, 214, 214, 214, 223, 223, 214, 166, 166, 166, 166, 166, 166, 15, 72, 2, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (27, 44, 44, 4066, 0, 1144, 1408, 220, 220, 220, 220, 226, 226, 220, 172, 172, 172, 172, 172, 172, 15, 74, 2, + -18, 30, '', 0, 35, 0, 1.25, 100, 100, 100), + (27, 45, 45, 4209, 0, 1170, 1440, 225, 225, 225, 225, 229, 229, 225, 174, 174, 174, 174, 174, 174, 16, 75, 2, + -18, 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (27, 46, 46, 4354, 0, 1196, 1472, 231, 231, 231, 231, 232, 232, 231, 176, 176, 176, 176, 176, 176, 16, 76, 2, + -18, 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (27, 47, 47, 4503, 0, 1222, 1504, 236, 236, 236, 236, 235, 235, 236, 180, 180, 180, 180, 180, 180, 16, 78, 3, + -18, 30, '', 0, 36, 0, 1.25, 100, 100, 100), + (27, 48, 48, 4656, 0, 1248, 1536, 243, 243, 243, 243, 238, 238, 243, 184, 184, 184, 184, 184, 184, 16, 79, 3, + -18, 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (27, 49, 49, 4812, 0, 1274, 1568, 248, 248, 248, 248, 241, 241, 248, 186, 186, 186, 186, 186, 186, 17, 80, 3, + -18, 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (27, 50, 50, 4972, 0, 1300, 1600, 257, 257, 257, 257, 244, 244, 257, 190, 190, 190, 190, 190, 190, 17, 82, 3, + -18, 30, '', 0, 37, 0, 1.25, 100, 100, 100), + (27, 51, 51, 5136, 0, 1326, 1632, 262, 262, 262, 262, 247, 247, 262, 192, 192, 192, 192, 192, 192, 17, 83, 3, + -18, 30, '', 0, 38, 0, 1.25, 100, 100, 100), + (27, 52, 52, 5303, 0, 1352, 1664, 269, 269, 269, 269, 250, 250, 269, 196, 196, 196, 196, 196, 196, 17, 84, 3, + -18, 30, '', 0, 38, 0, 1.61, 100, 100, 100), + (27, 53, 53, 5474, 0, 1378, 1696, 274, 274, 274, 274, 253, 253, 274, 200, 200, 200, 200, 200, 200, 18, 85, 3, + -18, 30, '', 0, 38, 0, 1.61, 100, 100, 100), + (27, 54, 54, 5650, 0, 1404, 1728, 281, 281, 281, 281, 256, 256, 281, 202, 202, 202, 202, 202, 202, 18, 87, 3, + -18, 30, '', 0, 39, 0, 1.61, 100, 100, 100), + (27, 55, 55, 5829, 0, 1430, 1760, 287, 287, 287, 287, 259, 259, 287, 204, 204, 204, 204, 204, 204, 18, 88, 3, + -18, 30, '', 0, 39, 0, 1.61, 100, 100, 100), + (27, 56, 56, 6013, 0, 1456, 1792, 294, 294, 294, 294, 262, 262, 294, 210, 210, 210, 210, 210, 210, 18, 89, 3, + -18, 30, '', 0, 39, 0, 1.61, 100, 100, 100), + (27, 57, 57, 6200, 0, 1482, 1824, 300, 300, 300, 300, 265, 265, 300, 212, 212, 212, 212, 212, 212, 19, 91, 3, + -18, 30, '', 0, 40, 0, 1.61, 100, 100, 100), + (27, 58, 58, 6392, 0, 1508, 1856, 308, 308, 308, 308, 268, 268, 308, 214, 214, 214, 214, 214, 214, 19, 92, 3, + -18, 30, '', 0, 40, 0, 1.61, 100, 100, 100), + (27, 59, 59, 6589, 0, 1534, 1888, 314, 314, 314, 314, 271, 271, 314, 218, 218, 218, 218, 218, 218, 19, 93, 3, + -18, 30, '', 0, 40, 0, 1.61, 100, 100, 100), + (27, 60, 60, 6790, 0, 1560, 1920, 324, 324, 324, 324, 274, 274, 324, 222, 222, 222, 222, 222, 222, 19, 95, 3, + -18, 30, '', 0, 41, 0, 1.61, 100, 100, 100), + (27, 61, 61, 6995, 0, 1586, 1952, 330, 330, 330, 330, 277, 277, 330, 224, 224, 224, 224, 224, 224, 23, 111, 4, + -26, 27, '', 0, 41, 0, 1.61, 100, 100, 100), + (27, 62, 62, 7205, 0, 1612, 1984, 338, 338, 338, 338, 280, 280, 338, 228, 228, 228, 228, 228, 228, 26, 127, 4, + -27, 26, '', 0, 41, 0, 1.61, 100, 100, 100), + (27, 63, 63, 7419, 0, 1638, 2016, 344, 344, 344, 344, 283, 283, 344, 230, 230, 230, 230, 230, 230, 29, 143, 4, + -27, 26, '', 0, 42, 0, 1.61, 100, 100, 100), + (27, 64, 64, 7638, 0, 1664, 2048, 352, 352, 352, 352, 286, 286, 352, 234, 234, 234, 234, 234, 234, 32, 160, 4, + -28, 26, '', 0, 42, 0, 1.61, 100, 100, 100), + (27, 65, 65, 7862, 0, 1690, 2080, 359, 359, 359, 359, 289, 289, 359, 238, 238, 238, 238, 238, 238, 36, 176, 4, + -28, 26, '', 0, 42, 0, 1.61, 100, 100, 100), + (27, 66, 66, 8091, 0, 1716, 2112, 397, 397, 397, 397, 322, 322, 397, 240, 240, 240, 240, 240, 240, 39, 192, 4, + -29, 26, '', 0, 43, 0, 1.61, 100, 100, 100), + (27, 67, 67, 8325, 0, 1742, 2144, 409, 409, 409, 409, 330, 330, 409, 242, 242, 242, 242, 242, 242, 42, 209, 4, + -29, 26, '', 0, 43, 0, 1.61, 100, 100, 100), + (27, 68, 68, 8564, 0, 1768, 2176, 423, 423, 423, 423, 338, 338, 423, 248, 248, 248, 248, 248, 248, 45, 225, 4, + -30, 25, '', 0, 43, 0, 1.61, 100, 100, 100), + (27, 69, 69, 8808, 0, 1794, 2208, 435, 435, 435, 435, 346, 346, 435, 250, 250, 250, 250, 250, 250, 49, 241, 4, + -30, 25, '', 0, 44, 0, 1.61, 100, 100, 100), + (27, 70, 70, 9057, 0, 1820, 2240, 451, 451, 451, 451, 354, 354, 451, 252, 252, 252, 252, 252, 252, 52, 258, 4, + -31, 25, '', 0, 44, 0, 1.61, 100, 100, 100), + (27, 71, 71, 9311, 0, 1846, 2272, 463, 463, 463, 463, 362, 362, 463, 256, 256, 256, 256, 256, 256, 55, 274, 4, + -31, 25, '', 0, 44, 0, 1.61, 100, 100, 100), + (27, 72, 72, 9571, 0, 1872, 2304, 477, 477, 477, 477, 370, 370, 477, 260, 260, 260, 260, 260, 260, 58, 290, 4, + -32, 24, '', 0, 45, 0, 1.61, 100, 100, 100), + (27, 73, 73, 9836, 0, 1898, 2336, 489, 489, 489, 489, 378, 378, 489, 262, 262, 262, 262, 262, 262, 62, 306, 4, + -32, 24, '', 0, 45, 0, 1.61, 100, 100, 100), + (27, 74, 74, 10107, 0, 1924, 2368, 503, 503, 503, 503, 386, 386, 503, 266, 266, 266, 266, 266, 266, 65, 323, 4, + -33, 24, '', 0, 45, 0, 1.61, 100, 100, 100), + (27, 75, 75, 10383, 0, 1950, 2400, 516, 516, 516, 516, 394, 394, 516, 268, 268, 268, 268, 268, 268, 68, 339, 4, + -33, 24, '', 0, 46, 0, 1.61, 100, 100, 100), + (27, 76, 76, 10665, 0, 1976, 2432, 530, 530, 530, 530, 402, 402, 530, 272, 272, 272, 272, 272, 272, 71, 355, 4, + -34, 24, '', 0, 46, 0, 1.61, 100, 100, 100), + (27, 77, 77, 10952, 0, 2002, 2464, 543, 543, 543, 543, 410, 410, 543, 276, 276, 276, 276, 276, 276, 75, 372, 4, + -34, 24, '', 0, 46, 0, 1.61, 100, 100, 100), + (27, 78, 78, 11245, 0, 2028, 2496, 558, 558, 558, 558, 418, 418, 558, 278, 278, 278, 278, 278, 278, 78, 388, 4, + -35, 23, '', 0, 47, 0, 1.61, 100, 100, 100), + (27, 79, 79, 11544, 0, 2054, 2528, 571, 571, 571, 571, 426, 426, 571, 280, 280, 280, 280, 280, 280, 81, 404, 4, + -35, 23, '', 0, 47, 0, 1.61, 100, 100, 100), + (27, 80, 80, 11850, 0, 2080, 2560, 588, 588, 588, 588, 434, 434, 588, 286, 286, 286, 286, 286, 286, 84, 421, 4, + -40, 22, '', 0, 47, 0, 1.61, 100, 100, 100), + (27, 81, 81, 12161, 0, 2106, 2592, 601, 601, 601, 601, 442, 442, 601, 288, 288, 288, 288, 288, 288, 88, 437, 4, + -40, 22, '', 0, 48, 0, 1.61, 100, 100, 100), + (27, 82, 82, 12478, 0, 2132, 2624, 616, 616, 616, 616, 450, 450, 616, 290, 290, 290, 290, 290, 290, 91, 453, 4, + -40, 22, '', 0, 48, 0, 1.61, 100, 100, 100), + (27, 83, 83, 12801, 0, 2158, 2656, 629, 629, 629, 629, 458, 458, 629, 294, 294, 294, 294, 294, 294, 94, 469, 4, + -40, 22, '', 0, 48, 0, 1.61, 100, 100, 100), + (27, 84, 84, 13130, 0, 2184, 2688, 644, 644, 644, 644, 466, 466, 644, 298, 298, 298, 298, 298, 298, 97, 486, 4, + -40, 22, '', 0, 49, 0, 1.61, 100, 100, 100), + (27, 85, 85, 13466, 0, 2210, 2720, 658, 658, 658, 658, 474, 474, 658, 300, 300, 300, 300, 300, 300, 101, 502, 4, + -40, 22, '', 0, 49, 0, 1.61, 100, 100, 100), + (31, 1, 1, 37, 29, 13, 8, 56, 56, 56, 56, 106, 106, 56, 15, 15, 15, 15, 15, 15, 1, 8, 1, -18, 30, '', 0, 7, 5, + 1.25, 100, 100, 100), + (31, 2, 2, 64, 59, 26, 16, 57, 57, 57, 57, 110, 110, 57, 17, 17, 17, 17, 17, 17, 1, 10, 1, -18, 30, '', 0, 7, 5, + 1.25, 100, 100, 100), + (31, 3, 3, 91, 91, 40, 24, 57, 57, 57, 57, 113, 113, 57, 19, 19, 19, 19, 19, 19, 2, 11, 1, -18, 30, '', 0, 7, 5, + 1.25, 100, 100, 100), + (31, 4, 4, 118, 125, 53, 33, 58, 58, 58, 58, 117, 117, 58, 22, 22, 22, 22, 22, 22, 2, 13, 1, -18, 30, '', 0, 8, + 5, 1.25, 100, 100, 100), + (31, 5, 5, 146, 160, 66, 41, 59, 59, 59, 59, 120, 120, 59, 24, 24, 24, 24, 24, 24, 2, 14, 1, -18, 30, '', 0, 8, + 6, 1.25, 100, 100, 100), + (31, 6, 6, 174, 197, 80, 49, 60, 60, 60, 60, 124, 124, 60, 26, 26, 26, 26, 26, 26, 2, 15, 1, -18, 30, '', 0, 8, + 6, 1.25, 100, 100, 100), + (31, 7, 7, 202, 235, 93, 57, 61, 61, 61, 61, 127, 127, 61, 28, 28, 28, 28, 28, 28, 3, 17, 1, -18, 30, '', 0, 8, + 6, 1.25, 100, 100, 100), + (31, 8, 8, 231, 275, 106, 66, 62, 62, 62, 62, 131, 131, 62, 31, 31, 31, 31, 31, 31, 3, 18, 1, -18, 30, '', 0, 9, + 6, 1.25, 100, 100, 100), + (31, 9, 9, 261, 317, 120, 74, 63, 63, 63, 63, 134, 134, 63, 33, 33, 33, 33, 33, 33, 3, 20, 1, -18, 30, '', 0, 9, + 6, 1.25, 100, 100, 100), + (31, 10, 10, 291, 360, 133, 82, 66, 66, 66, 66, 138, 138, 66, 35, 35, 35, 35, 35, 35, 3, 21, 1, -18, 30, '', 0, + 9, 7, 1.25, 100, 100, 100), + (31, 11, 11, 321, 405, 146, 90, 67, 67, 67, 67, 141, 141, 67, 37, 37, 37, 37, 37, 37, 4, 22, 1, -18, 30, '', 0, + 9, 7, 1.25, 100, 100, 100), + (31, 12, 12, 353, 451, 160, 99, 69, 69, 69, 69, 145, 145, 69, 40, 40, 40, 40, 40, 40, 4, 24, 1, -18, 30, '', 0, + 10, 7, 1.25, 100, 100, 100), + (31, 13, 13, 385, 499, 173, 107, 70, 70, 70, 70, 148, 148, 70, 42, 42, 42, 42, 42, 42, 4, 25, 1, -18, 30, '', 0, + 10, 7, 1.25, 100, 100, 100), + (31, 14, 14, 418, 549, 186, 115, 72, 72, 72, 72, 152, 152, 72, 44, 44, 44, 44, 44, 44, 4, 27, 1, -18, 30, '', 0, + 10, 7, 1.25, 100, 100, 100), + (31, 15, 15, 452, 600, 200, 123, 73, 73, 73, 73, 155, 155, 73, 46, 46, 46, 46, 46, 46, 5, 28, 1, -18, 30, '', 0, + 10, 8, 1.25, 100, 100, 100), + (31, 16, 16, 487, 653, 213, 132, 76, 76, 76, 76, 159, 159, 76, 49, 49, 49, 49, 49, 49, 5, 29, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (31, 17, 17, 523, 707, 226, 140, 77, 77, 77, 77, 162, 162, 77, 51, 51, 51, 51, 51, 51, 5, 31, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (31, 18, 18, 560, 763, 240, 148, 80, 80, 80, 80, 166, 166, 80, 53, 53, 53, 53, 53, 53, 5, 32, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (31, 19, 19, 599, 821, 253, 156, 81, 81, 81, 81, 169, 169, 81, 55, 55, 55, 55, 55, 55, 6, 34, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (31, 20, 20, 638, 880, 266, 165, 85, 85, 85, 85, 173, 173, 85, 58, 58, 58, 58, 58, 58, 6, 35, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (31, 21, 21, 679, 941, 280, 173, 87, 87, 87, 87, 176, 176, 87, 60, 60, 60, 60, 60, 60, 6, 36, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (31, 22, 22, 722, 1003, 293, 181, 90, 90, 90, 90, 180, 180, 90, 62, 62, 62, 62, 62, 62, 6, 38, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (31, 23, 23, 766, 1067, 306, 189, 92, 92, 92, 92, 183, 183, 92, 64, 64, 64, 64, 64, 64, 7, 39, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (31, 24, 24, 811, 1133, 320, 198, 95, 95, 95, 95, 187, 187, 95, 67, 67, 67, 67, 67, 67, 7, 41, 1, -18, 30, '', 0, + 13, 9, 1.25, 100, 100, 100), + (31, 25, 25, 858, 1200, 333, 206, 97, 97, 97, 97, 190, 190, 97, 69, 69, 69, 69, 69, 69, 7, 42, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (31, 26, 26, 907, 1269, 346, 214, 100, 100, 100, 100, 194, 194, 100, 71, 71, 71, 71, 71, 71, 7, 43, 1, -18, 30, + '', 0, 13, 10, 1.25, 100, 100, 100), + (31, 27, 27, 957, 1339, 360, 222, 102, 102, 102, 102, 197, 197, 102, 73, 73, 73, 73, 73, 73, 8, 45, 1, -18, 30, + '', 0, 13, 10, 1.25, 100, 100, 100), + (31, 28, 28, 1009, 1411, 373, 231, 106, 106, 106, 106, 201, 201, 106, 76, 76, 76, 76, 76, 76, 8, 46, 1, -18, 30, + '', 0, 14, 10, 1.25, 100, 100, 100), + (31, 29, 29, 1063, 1485, 386, 239, 108, 108, 108, 108, 204, 204, 108, 78, 78, 78, 78, 78, 78, 8, 48, 1, -18, 30, + '', 0, 14, 10, 1.25, 100, 100, 100), + (31, 30, 30, 1120, 1560, 400, 247, 113, 113, 113, 113, 208, 208, 113, 80, 80, 80, 80, 80, 80, 8, 49, 1, -18, 30, + '', 0, 14, 11, 1.25, 100, 100, 100), + (31, 31, 31, 1178, 1637, 413, 255, 115, 115, 115, 115, 211, 211, 115, 82, 82, 82, 82, 82, 82, 9, 50, 1, -18, 30, + '', 0, 14, 11, 1.25, 100, 100, 100), + (31, 32, 32, 1238, 1715, 426, 264, 119, 119, 119, 119, 215, 215, 119, 85, 85, 85, 85, 85, 85, 9, 52, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (31, 33, 33, 1300, 1795, 440, 272, 122, 122, 122, 122, 218, 218, 122, 87, 87, 87, 87, 87, 87, 9, 53, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (31, 34, 34, 1364, 1877, 453, 280, 126, 126, 126, 126, 222, 222, 126, 89, 89, 89, 89, 89, 89, 9, 55, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (31, 35, 35, 1431, 1960, 466, 288, 129, 129, 129, 129, 225, 225, 129, 91, 91, 91, 91, 91, 91, 10, 56, 1, -18, 30, + '', 0, 15, 12, 1.25, 100, 100, 100), + (31, 36, 36, 1500, 2045, 480, 297, 133, 133, 133, 133, 229, 229, 133, 94, 94, 94, 94, 94, 94, 10, 57, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (31, 37, 37, 1571, 2131, 493, 305, 136, 136, 136, 136, 232, 232, 136, 96, 96, 96, 96, 96, 96, 10, 59, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (31, 38, 38, 1645, 2219, 506, 313, 140, 140, 140, 140, 236, 236, 140, 98, 98, 98, 98, 98, 98, 10, 60, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (31, 39, 39, 1722, 2309, 520, 321, 144, 144, 144, 144, 239, 239, 144, 100, 100, 100, 100, 100, 100, 11, 62, 1, + -18, 30, '', 0, 16, 12, 1.25, 100, 100, 100), + (31, 40, 40, 1801, 2400, 533, 330, 149, 149, 149, 149, 243, 243, 149, 103, 103, 103, 103, 103, 103, 11, 63, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (31, 41, 41, 1882, 2493, 546, 338, 153, 153, 153, 153, 246, 246, 153, 105, 105, 105, 105, 105, 105, 11, 64, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (31, 42, 42, 1967, 2587, 560, 346, 157, 157, 157, 157, 250, 250, 157, 107, 107, 107, 107, 107, 107, 11, 66, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (31, 43, 43, 2054, 2683, 573, 354, 161, 161, 161, 161, 253, 253, 161, 109, 109, 109, 109, 109, 109, 12, 67, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (31, 44, 44, 2144, 2781, 586, 363, 166, 166, 166, 166, 257, 257, 166, 112, 112, 112, 112, 112, 112, 12, 69, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (31, 45, 45, 2237, 2880, 600, 371, 170, 170, 170, 170, 260, 260, 170, 114, 114, 114, 114, 114, 114, 12, 70, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (31, 46, 46, 2333, 2981, 613, 379, 175, 175, 175, 175, 264, 264, 175, 116, 116, 116, 116, 116, 116, 12, 71, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (31, 47, 47, 2432, 3083, 626, 387, 179, 179, 179, 179, 267, 267, 179, 118, 118, 118, 118, 118, 118, 13, 73, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (31, 48, 48, 2534, 3187, 640, 396, 184, 184, 184, 184, 271, 271, 184, 121, 121, 121, 121, 121, 121, 13, 74, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (31, 49, 49, 2640, 3293, 653, 404, 188, 188, 188, 188, 274, 274, 188, 123, 123, 123, 123, 123, 123, 13, 76, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (31, 50, 50, 2748, 3400, 666, 412, 194, 194, 194, 194, 278, 278, 194, 125, 125, 125, 125, 125, 125, 13, 77, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (31, 51, 51, 2860, 3509, 680, 420, 199, 199, 199, 199, 281, 281, 199, 127, 127, 127, 127, 127, 127, 14, 78, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (31, 52, 52, 2976, 3619, 693, 429, 204, 204, 204, 204, 285, 285, 204, 130, 130, 130, 130, 130, 130, 14, 80, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (31, 53, 53, 3095, 3731, 706, 437, 209, 209, 209, 209, 288, 288, 209, 132, 132, 132, 132, 132, 132, 14, 81, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (31, 54, 54, 3217, 3845, 720, 445, 214, 214, 214, 214, 292, 292, 214, 134, 134, 134, 134, 134, 134, 14, 83, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (31, 55, 55, 3343, 3960, 733, 453, 219, 219, 219, 219, 295, 295, 219, 136, 136, 136, 136, 136, 136, 15, 84, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (31, 56, 56, 3473, 4077, 746, 462, 225, 225, 225, 225, 299, 299, 225, 139, 139, 139, 139, 139, 139, 15, 85, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (31, 57, 57, 3606, 4195, 760, 470, 230, 230, 230, 230, 302, 302, 230, 141, 141, 141, 141, 141, 141, 15, 87, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (31, 58, 58, 3743, 4315, 773, 478, 236, 236, 236, 236, 306, 306, 236, 143, 143, 143, 143, 143, 143, 15, 88, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (31, 59, 59, 3884, 4437, 786, 486, 241, 241, 241, 241, 309, 309, 241, 145, 145, 145, 145, 145, 145, 16, 90, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (31, 60, 60, 4030, 4560, 800, 495, 248, 248, 248, 248, 313, 313, 248, 148, 148, 148, 148, 148, 148, 16, 91, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (31, 61, 61, 4179, 4685, 813, 503, 253, 253, 253, 253, 316, 316, 253, 150, 150, 150, 150, 150, 150, 16, 92, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (31, 62, 62, 4332, 4811, 826, 511, 260, 260, 260, 260, 320, 320, 260, 152, 152, 152, 152, 152, 152, 16, 94, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (31, 63, 63, 4489, 4939, 840, 519, 265, 265, 265, 265, 323, 323, 265, 154, 154, 154, 154, 154, 154, 17, 95, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (31, 64, 64, 4650, 5069, 853, 528, 272, 272, 272, 272, 327, 327, 272, 157, 157, 157, 157, 157, 157, 17, 97, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (31, 65, 65, 4816, 5200, 866, 536, 277, 277, 277, 277, 330, 330, 277, 159, 159, 159, 159, 159, 159, 17, 98, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (31, 66, 66, 4986, 5333, 880, 544, 314, 314, 314, 314, 364, 364, 314, 161, 161, 161, 161, 161, 161, 17, 99, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (31, 67, 67, 5160, 5467, 893, 552, 325, 325, 325, 325, 372, 372, 325, 163, 163, 163, 163, 163, 163, 18, 101, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (31, 68, 68, 5339, 5603, 906, 561, 337, 337, 337, 337, 381, 381, 337, 166, 166, 166, 166, 166, 166, 18, 102, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (31, 69, 69, 5523, 5741, 920, 569, 348, 348, 348, 348, 389, 389, 348, 168, 168, 168, 168, 168, 168, 18, 104, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (31, 70, 70, 5711, 5880, 933, 577, 361, 361, 361, 361, 398, 398, 361, 170, 170, 170, 170, 170, 170, 18, 105, 1, + -18, 30, '', 0, 24, 19, 1.25, 100, 100, 100), + (31, 71, 71, 5903, 6021, 946, 585, 372, 372, 372, 372, 406, 406, 372, 172, 172, 172, 172, 172, 172, 19, 106, 1, + -18, 30, '', 0, 24, 19, 1.25, 100, 100, 100), + (31, 72, 72, 6101, 6163, 960, 594, 384, 384, 384, 384, 415, 415, 384, 175, 175, 175, 175, 175, 175, 19, 108, 1, + -18, 30, '', 0, 25, 19, 1.25, 100, 100, 100), + (31, 73, 73, 6303, 6307, 973, 602, 395, 395, 395, 395, 423, 423, 395, 177, 177, 177, 177, 177, 177, 19, 109, 1, + -18, 30, '', 0, 25, 19, 1.25, 100, 100, 100), + (31, 74, 74, 6510, 6453, 986, 610, 408, 408, 408, 408, 432, 432, 408, 179, 179, 179, 179, 179, 179, 19, 111, 1, + -18, 30, '', 0, 25, 19, 1.25, 100, 100, 100), + (31, 75, 75, 6722, 6600, 1000, 618, 419, 419, 419, 419, 440, 440, 419, 181, 181, 181, 181, 181, 181, 20, 112, 1, + -18, 30, '', 0, 25, 20, 1.25, 100, 100, 100), + (31, 76, 76, 6939, 6749, 1013, 627, 432, 432, 432, 432, 449, 449, 432, 184, 184, 184, 184, 184, 184, 20, 113, 1, + -18, 30, '', 0, 26, 20, 1.25, 100, 100, 100), + (31, 77, 77, 7161, 6899, 1026, 635, 443, 443, 443, 443, 457, 457, 443, 186, 186, 186, 186, 186, 186, 20, 115, 1, + -18, 30, '', 0, 26, 20, 1.25, 100, 100, 100), + (31, 78, 78, 7388, 7051, 1040, 643, 456, 456, 456, 456, 466, 466, 456, 188, 188, 188, 188, 188, 188, 20, 116, 1, + -18, 30, '', 0, 26, 20, 1.25, 100, 100, 100), + (31, 79, 79, 7621, 7205, 1053, 651, 468, 468, 468, 468, 474, 474, 468, 190, 190, 190, 190, 190, 190, 21, 118, 1, + -18, 30, '', 0, 26, 20, 1.25, 100, 100, 100), + (31, 80, 80, 7858, 7360, 1066, 660, 482, 482, 482, 482, 483, 483, 482, 193, 193, 193, 193, 193, 193, 21, 119, 1, + -18, 30, '', 0, 27, 21, 1.25, 100, 100, 100), + (31, 81, 81, 8101, 7517, 1080, 668, 494, 494, 494, 494, 491, 491, 494, 195, 195, 195, 195, 195, 195, 21, 120, 1, + -18, 30, '', 0, 27, 21, 1.25, 100, 100, 100), + (31, 82, 82, 8350, 7675, 1093, 676, 507, 507, 507, 507, 500, 500, 507, 197, 197, 197, 197, 197, 197, 21, 122, 1, + -18, 30, '', 0, 27, 21, 1.25, 100, 100, 100), + (31, 83, 83, 8604, 7835, 1106, 684, 519, 519, 519, 519, 508, 508, 519, 199, 199, 199, 199, 199, 199, 22, 123, 1, + -18, 30, '', 0, 27, 21, 1.25, 100, 100, 100), + (31, 84, 84, 8863, 7997, 1120, 693, 532, 532, 532, 532, 517, 517, 532, 202, 202, 202, 202, 202, 202, 22, 125, 1, + -18, 30, '', 0, 28, 21, 1.25, 100, 100, 100), + (31, 85, 85, 9128, 8160, 1133, 701, 545, 545, 545, 545, 525, 525, 545, 204, 204, 204, 204, 204, 204, 22, 126, 1, + -18, 30, '', 0, 28, 22, 1.25, 100, 100, 100), + (32, 1, 1, 39, 32, 13, 8, 57, 57, 57, 57, 109, 109, 57, 18, 18, 18, 18, 18, 18, 1, 10, 1, -18, 30, '', 0, 8, 6, + 1.25, 100, 100, 100), + (32, 2, 2, 68, 65, 27, 17, 58, 58, 58, 58, 113, 113, 58, 20, 20, 20, 20, 20, 20, 2, 11, 1, -18, 30, '', 0, 8, 6, + 1.25, 100, 100, 100), + (32, 3, 3, 97, 100, 41, 25, 58, 58, 58, 58, 116, 116, 58, 22, 22, 22, 22, 22, 22, 2, 13, 1, -18, 30, '', 0, 8, 6, + 1.25, 100, 100, 100), + (32, 4, 4, 126, 137, 54, 34, 59, 59, 59, 59, 120, 120, 59, 26, 26, 26, 26, 26, 26, 2, 14, 1, -18, 30, '', 0, 9, + 6, 1.25, 100, 100, 100), + (32, 5, 5, 156, 175, 68, 42, 60, 60, 60, 60, 123, 123, 60, 28, 28, 28, 28, 28, 28, 2, 15, 1, -18, 30, '', 0, 9, + 7, 1.25, 100, 100, 100), + (32, 6, 6, 186, 215, 82, 51, 61, 61, 61, 61, 127, 127, 61, 30, 30, 30, 30, 30, 30, 3, 17, 1, -18, 30, '', 0, 9, + 7, 1.25, 100, 100, 100), + (32, 7, 7, 216, 256, 95, 59, 62, 62, 62, 62, 130, 130, 62, 32, 32, 32, 32, 32, 32, 3, 18, 1, -18, 30, '', 0, 9, + 7, 1.25, 100, 100, 100), + (32, 8, 8, 247, 299, 109, 68, 63, 63, 63, 63, 134, 134, 63, 36, 36, 36, 36, 36, 36, 3, 20, 1, -18, 30, '', 0, 10, + 7, 1.25, 100, 100, 100), + (32, 9, 9, 279, 344, 123, 76, 64, 64, 64, 64, 137, 137, 64, 38, 38, 38, 38, 38, 38, 3, 21, 1, -18, 30, '', 0, 10, + 7, 1.25, 100, 100, 100), + (32, 10, 10, 311, 390, 136, 85, 68, 68, 68, 68, 141, 141, 68, 40, 40, 40, 40, 40, 40, 4, 22, 1, -18, 30, '', 0, + 10, 8, 1.25, 100, 100, 100), + (32, 11, 11, 343, 438, 150, 93, 69, 69, 69, 69, 144, 144, 69, 42, 42, 42, 42, 42, 42, 4, 24, 1, -18, 30, '', 0, + 10, 8, 1.25, 100, 100, 100), + (32, 12, 12, 377, 487, 164, 102, 71, 71, 71, 71, 148, 148, 71, 46, 46, 46, 46, 46, 46, 4, 25, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (32, 13, 13, 411, 538, 177, 110, 72, 72, 72, 72, 151, 151, 72, 48, 48, 48, 48, 48, 48, 4, 27, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (32, 14, 14, 446, 591, 191, 119, 74, 74, 74, 74, 155, 155, 74, 50, 50, 50, 50, 50, 50, 5, 28, 1, -18, 30, '', 0, + 11, 8, 1.25, 100, 100, 100), + (32, 15, 15, 482, 645, 205, 127, 75, 75, 75, 75, 158, 158, 75, 52, 52, 52, 52, 52, 52, 5, 29, 1, -18, 30, '', 0, + 11, 9, 1.25, 100, 100, 100), + (32, 16, 16, 519, 701, 218, 136, 78, 78, 78, 78, 162, 162, 78, 56, 56, 56, 56, 56, 56, 5, 31, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (32, 17, 17, 557, 758, 232, 144, 79, 79, 79, 79, 165, 165, 79, 58, 58, 58, 58, 58, 58, 5, 32, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (32, 18, 18, 596, 817, 246, 153, 82, 82, 82, 82, 169, 169, 82, 60, 60, 60, 60, 60, 60, 6, 34, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (32, 19, 19, 637, 878, 259, 161, 83, 83, 83, 83, 172, 172, 83, 62, 62, 62, 62, 62, 62, 6, 35, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (32, 20, 20, 678, 940, 273, 170, 88, 88, 88, 88, 176, 176, 88, 66, 66, 66, 66, 66, 66, 6, 36, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (32, 21, 21, 721, 1004, 287, 178, 90, 90, 90, 90, 179, 179, 90, 68, 68, 68, 68, 68, 68, 6, 38, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (32, 22, 22, 766, 1069, 300, 187, 93, 93, 93, 93, 183, 183, 93, 70, 70, 70, 70, 70, 70, 7, 39, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (32, 23, 23, 812, 1136, 314, 195, 95, 95, 95, 95, 186, 186, 95, 72, 72, 72, 72, 72, 72, 7, 41, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (32, 24, 24, 859, 1205, 328, 204, 98, 98, 98, 98, 190, 190, 98, 76, 76, 76, 76, 76, 76, 7, 42, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (32, 25, 25, 908, 1275, 341, 212, 100, 100, 100, 100, 193, 193, 100, 78, 78, 78, 78, 78, 78, 7, 43, 1, -18, 30, + '', 0, 14, 11, 1.25, 100, 100, 100), + (32, 26, 26, 959, 1347, 355, 221, 103, 103, 103, 103, 197, 197, 103, 80, 80, 80, 80, 80, 80, 8, 45, 1, -18, 30, + '', 0, 14, 11, 1.25, 100, 100, 100), + (32, 27, 27, 1011, 1420, 369, 229, 105, 105, 105, 105, 200, 200, 105, 82, 82, 82, 82, 82, 82, 8, 46, 1, -18, 30, + '', 0, 14, 11, 1.25, 100, 100, 100), + (32, 28, 28, 1065, 1495, 382, 238, 109, 109, 109, 109, 204, 204, 109, 86, 86, 86, 86, 86, 86, 8, 48, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (32, 29, 29, 1121, 1572, 396, 246, 111, 111, 111, 111, 207, 207, 111, 88, 88, 88, 88, 88, 88, 8, 49, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (32, 30, 30, 1180, 1650, 410, 255, 117, 117, 117, 117, 211, 211, 117, 90, 90, 90, 90, 90, 90, 9, 50, 1, -18, 30, + '', 0, 15, 12, 1.25, 100, 100, 100), + (32, 31, 31, 1240, 1730, 423, 263, 119, 119, 119, 119, 214, 214, 119, 92, 92, 92, 92, 92, 92, 9, 52, 1, -18, 30, + '', 0, 15, 12, 1.25, 100, 100, 100), + (32, 32, 32, 1302, 1811, 437, 272, 123, 123, 123, 123, 218, 218, 123, 96, 96, 96, 96, 96, 96, 9, 53, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (32, 33, 33, 1366, 1894, 451, 280, 126, 126, 126, 126, 221, 221, 126, 98, 98, 98, 98, 98, 98, 9, 55, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (32, 34, 34, 1432, 1979, 464, 289, 130, 130, 130, 130, 225, 225, 130, 100, 100, 100, 100, 100, 100, 10, 56, 1, + -18, 30, '', 0, 16, 12, 1.25, 100, 100, 100), + (32, 35, 35, 1501, 2065, 478, 297, 133, 133, 133, 133, 228, 228, 133, 102, 102, 102, 102, 102, 102, 10, 57, 1, + -18, 30, '', 0, 16, 13, 1.25, 100, 100, 100), + (32, 36, 36, 1572, 2153, 492, 306, 137, 137, 137, 137, 232, 232, 137, 106, 106, 106, 106, 106, 106, 10, 59, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (32, 37, 37, 1645, 2242, 505, 314, 140, 140, 140, 140, 235, 235, 140, 108, 108, 108, 108, 108, 108, 10, 60, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (32, 38, 38, 1721, 2333, 519, 323, 144, 144, 144, 144, 239, 239, 144, 110, 110, 110, 110, 110, 110, 11, 62, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (32, 39, 39, 1800, 2426, 533, 331, 148, 148, 148, 148, 242, 242, 148, 112, 112, 112, 112, 112, 112, 11, 63, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (32, 40, 40, 1881, 2520, 546, 340, 154, 154, 154, 154, 246, 246, 154, 116, 116, 116, 116, 116, 116, 11, 64, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (32, 41, 41, 1964, 2616, 560, 348, 158, 158, 158, 158, 249, 249, 158, 118, 118, 118, 118, 118, 118, 11, 66, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (32, 42, 42, 2051, 2713, 574, 357, 162, 162, 162, 162, 253, 253, 162, 120, 120, 120, 120, 120, 120, 12, 67, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (32, 43, 43, 2140, 2812, 587, 365, 166, 166, 166, 166, 256, 256, 166, 122, 122, 122, 122, 122, 122, 12, 69, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (32, 44, 44, 2232, 2913, 601, 374, 171, 171, 171, 171, 260, 260, 171, 126, 126, 126, 126, 126, 126, 12, 70, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (32, 45, 45, 2327, 3015, 615, 382, 175, 175, 175, 175, 263, 263, 175, 128, 128, 128, 128, 128, 128, 12, 71, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (32, 46, 46, 2425, 3119, 628, 391, 180, 180, 180, 180, 267, 267, 180, 130, 130, 130, 130, 130, 130, 13, 73, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (32, 47, 47, 2526, 3224, 642, 399, 184, 184, 184, 184, 270, 270, 184, 132, 132, 132, 132, 132, 132, 13, 74, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (32, 48, 48, 2630, 3331, 656, 408, 189, 189, 189, 189, 274, 274, 189, 136, 136, 136, 136, 136, 136, 13, 76, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (32, 49, 49, 2738, 3440, 669, 416, 193, 193, 193, 193, 277, 277, 193, 138, 138, 138, 138, 138, 138, 13, 77, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (32, 50, 50, 2848, 3550, 683, 425, 200, 200, 200, 200, 281, 281, 200, 140, 140, 140, 140, 140, 140, 14, 78, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (32, 51, 51, 2962, 3662, 697, 433, 205, 205, 205, 205, 284, 284, 205, 142, 142, 142, 142, 142, 142, 14, 80, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (32, 52, 52, 3080, 3775, 710, 442, 210, 210, 210, 210, 288, 288, 210, 146, 146, 146, 146, 146, 146, 14, 81, 1, + -18, 30, '', 0, 21, 16, 1.31, 100, 100, 100), + (32, 53, 53, 3201, 3890, 724, 450, 215, 215, 215, 215, 291, 291, 215, 148, 148, 148, 148, 148, 148, 14, 83, 1, + -18, 30, '', 0, 21, 16, 1.31, 100, 100, 100), + (32, 54, 54, 3325, 4007, 738, 459, 220, 220, 220, 220, 295, 295, 220, 150, 150, 150, 150, 150, 150, 15, 84, 1, + -18, 30, '', 0, 21, 16, 1.31, 100, 100, 100), + (32, 55, 55, 3453, 4125, 751, 467, 225, 225, 225, 225, 298, 298, 225, 152, 152, 152, 152, 152, 152, 15, 85, 1, + -18, 30, '', 0, 21, 17, 1.31, 100, 100, 100), + (32, 56, 56, 3585, 4245, 765, 476, 231, 231, 231, 231, 302, 302, 231, 156, 156, 156, 156, 156, 156, 15, 87, 1, + -18, 30, '', 0, 22, 17, 1.31, 100, 100, 100), + (32, 57, 57, 3720, 4366, 779, 484, 236, 236, 236, 236, 305, 305, 236, 158, 158, 158, 158, 158, 158, 15, 88, 1, + -18, 30, '', 0, 22, 17, 1.31, 100, 100, 100), + (32, 58, 58, 3859, 4489, 792, 493, 242, 242, 242, 242, 309, 309, 242, 160, 160, 160, 160, 160, 160, 16, 90, 1, + -18, 30, '', 0, 22, 17, 1.31, 100, 100, 100), + (32, 59, 59, 4002, 4614, 806, 501, 247, 247, 247, 247, 312, 312, 247, 162, 162, 162, 162, 162, 162, 16, 91, 1, + -18, 30, '', 0, 22, 17, 1.31, 100, 100, 100), + (32, 60, 60, 4150, 4740, 820, 510, 255, 255, 255, 255, 316, 316, 255, 166, 166, 166, 166, 166, 166, 16, 92, 1, + -18, 30, '', 0, 23, 18, 1.31, 100, 100, 100), + (32, 61, 61, 4301, 4868, 833, 518, 260, 260, 260, 260, 319, 319, 260, 168, 168, 168, 168, 168, 168, 16, 94, 1, + -18, 30, '', 0, 23, 18, 1.31, 100, 100, 100), + (32, 62, 62, 4456, 4997, 847, 527, 267, 267, 267, 267, 323, 323, 267, 170, 170, 170, 170, 170, 170, 17, 95, 1, + -18, 30, '', 0, 23, 18, 1.31, 100, 100, 100), + (32, 63, 63, 4615, 5128, 861, 535, 272, 272, 272, 272, 326, 326, 272, 172, 172, 172, 172, 172, 172, 17, 97, 1, + -18, 30, '', 0, 23, 18, 1.31, 100, 100, 100), + (32, 64, 64, 4778, 5261, 874, 544, 279, 279, 279, 279, 330, 330, 279, 176, 176, 176, 176, 176, 176, 17, 98, 1, + -18, 30, '', 0, 24, 18, 1.31, 100, 100, 100), + (32, 65, 65, 4946, 5395, 888, 552, 284, 284, 284, 284, 333, 333, 284, 178, 178, 178, 178, 178, 178, 17, 99, 1, + -18, 30, '', 0, 24, 19, 1.31, 100, 100, 100), + (32, 66, 66, 5118, 5531, 902, 561, 321, 321, 321, 321, 367, 367, 321, 180, 180, 180, 180, 180, 180, 18, 101, 1, + -18, 30, '', 0, 24, 19, 1.31, 100, 100, 100), + (32, 67, 67, 5294, 5668, 915, 569, 332, 332, 332, 332, 375, 375, 332, 182, 182, 182, 182, 182, 182, 18, 102, 1, + -18, 30, '', 0, 24, 19, 1.31, 100, 100, 100), + (32, 68, 68, 5475, 5807, 929, 578, 344, 344, 344, 344, 384, 384, 344, 186, 186, 186, 186, 186, 186, 18, 104, 1, + -18, 30, '', 0, 25, 19, 1.31, 100, 100, 100), + (32, 69, 69, 5661, 5948, 943, 586, 355, 355, 355, 355, 392, 392, 355, 188, 188, 188, 188, 188, 188, 18, 105, 1, + -18, 30, '', 0, 25, 19, 1.31, 100, 100, 100), + (32, 70, 70, 5851, 6090, 956, 595, 369, 369, 369, 369, 401, 401, 369, 190, 190, 190, 190, 190, 190, 19, 106, 1, + -18, 30, '', 0, 25, 20, 1.31, 100, 100, 100), + (32, 71, 71, 6045, 6234, 970, 603, 380, 380, 380, 380, 409, 409, 380, 192, 192, 192, 192, 192, 192, 19, 108, 1, + -18, 30, '', 0, 25, 20, 1.31, 100, 100, 100), + (32, 72, 72, 6245, 6379, 984, 612, 392, 392, 392, 392, 418, 418, 392, 196, 196, 196, 196, 196, 196, 19, 109, 1, + -18, 30, '', 0, 26, 20, 1.31, 100, 100, 100), + (32, 73, 73, 6449, 6526, 997, 620, 403, 403, 403, 403, 426, 426, 403, 198, 198, 198, 198, 198, 198, 19, 111, 1, + -18, 30, '', 0, 26, 20, 1.31, 100, 100, 100), + (32, 74, 74, 6658, 6675, 1011, 629, 416, 416, 416, 416, 435, 435, 416, 200, 200, 200, 200, 200, 200, 20, 112, 1, + -18, 30, '', 0, 26, 20, 1.31, 100, 100, 100), + (32, 75, 75, 6872, 6825, 1025, 637, 427, 427, 427, 427, 443, 443, 427, 202, 202, 202, 202, 202, 202, 20, 113, 1, + -18, 30, '', 0, 26, 21, 1.31, 100, 100, 100), + (32, 76, 76, 7091, 6977, 1038, 646, 440, 440, 440, 440, 452, 452, 440, 206, 206, 206, 206, 206, 206, 20, 115, 1, + -18, 30, '', 0, 27, 21, 1.31, 100, 100, 100), + (32, 77, 77, 7315, 7130, 1052, 654, 451, 451, 451, 451, 460, 460, 451, 208, 208, 208, 208, 208, 208, 20, 116, 1, + -18, 30, '', 0, 27, 21, 1.31, 100, 100, 100), + (32, 78, 78, 7544, 7285, 1066, 663, 464, 464, 464, 464, 469, 469, 464, 210, 210, 210, 210, 210, 210, 21, 118, 1, + -18, 30, '', 0, 27, 21, 1.31, 100, 100, 100), + (32, 79, 79, 7779, 7442, 1079, 671, 476, 476, 476, 476, 477, 477, 476, 212, 212, 212, 212, 212, 212, 21, 119, 1, + -18, 30, '', 0, 27, 21, 1.31, 100, 100, 100), + (32, 80, 80, 8018, 7600, 1093, 680, 491, 491, 491, 491, 486, 486, 491, 216, 216, 216, 216, 216, 216, 21, 120, 1, + -18, 30, '', 0, 28, 22, 1.31, 100, 100, 100), + (32, 81, 81, 8263, 7760, 1107, 688, 503, 503, 503, 503, 494, 494, 503, 218, 218, 218, 218, 218, 218, 21, 122, 1, + -18, 30, '', 0, 28, 22, 1.31, 100, 100, 100), + (32, 82, 82, 8514, 7921, 1120, 697, 516, 516, 516, 516, 503, 503, 516, 220, 220, 220, 220, 220, 220, 22, 123, 1, + -18, 30, '', 0, 28, 22, 1.31, 100, 100, 100), + (32, 83, 83, 8770, 8084, 1134, 705, 528, 528, 528, 528, 511, 511, 528, 222, 222, 222, 222, 222, 222, 22, 125, 1, + -18, 30, '', 0, 28, 22, 1.31, 100, 100, 100), + (32, 84, 84, 9031, 8249, 1148, 714, 541, 541, 541, 541, 520, 520, 541, 226, 226, 226, 226, 226, 226, 22, 126, 1, + -18, 30, '', 0, 29, 22, 1.31, 100, 100, 100), + (32, 85, 85, 9298, 8415, 1161, 722, 554, 554, 554, 554, 528, 528, 554, 228, 228, 228, 228, 228, 228, 22, 127, 1, + -18, 30, '', 0, 29, 23, 1.31, 100, 100, 100), + (33, 1, 1, 41, 35, 14, 8, 58, 58, 58, 58, 112, 112, 58, 21, 21, 21, 21, 21, 21, 2, 11, 1, -18, 30, '', 0, 9, 7, + 1.25, 100, 100, 100), + (33, 2, 2, 72, 71, 28, 17, 59, 59, 59, 59, 116, 116, 59, 23, 23, 23, 23, 23, 23, 2, 13, 1, -18, 30, '', 0, 9, 7, + 1.25, 100, 100, 100), + (33, 3, 3, 103, 109, 42, 26, 59, 59, 59, 59, 119, 119, 59, 25, 25, 25, 25, 25, 25, 2, 14, 1, -18, 30, '', 0, 9, + 7, 1.25, 100, 100, 100), + (33, 4, 4, 134, 149, 56, 35, 60, 60, 60, 60, 123, 123, 60, 30, 30, 30, 30, 30, 30, 2, 15, 1, -18, 30, '', 0, 10, + 7, 1.25, 100, 100, 100), + (33, 5, 5, 166, 190, 70, 43, 61, 61, 61, 61, 126, 126, 61, 32, 32, 32, 32, 32, 32, 3, 17, 1, -18, 30, '', 0, 10, + 8, 1.25, 100, 100, 100), + (33, 6, 6, 198, 233, 84, 52, 62, 62, 62, 62, 130, 130, 62, 34, 34, 34, 34, 34, 34, 3, 18, 1, -18, 30, '', 0, 10, + 8, 1.25, 100, 100, 100), + (33, 7, 7, 230, 277, 98, 61, 63, 63, 63, 63, 133, 133, 63, 36, 36, 36, 36, 36, 36, 3, 20, 1, -18, 30, '', 0, 10, + 8, 1.25, 100, 100, 100), + (33, 8, 8, 263, 323, 112, 70, 64, 64, 64, 64, 137, 137, 64, 41, 41, 41, 41, 41, 41, 3, 21, 1, -18, 30, '', 0, 11, + 8, 1.25, 100, 100, 100), + (33, 9, 9, 297, 371, 126, 78, 65, 65, 65, 65, 140, 140, 65, 43, 43, 43, 43, 43, 43, 4, 22, 1, -18, 30, '', 0, 11, + 8, 1.25, 100, 100, 100), + (33, 10, 10, 331, 420, 140, 87, 70, 70, 70, 70, 144, 144, 70, 45, 45, 45, 45, 45, 45, 4, 24, 1, -18, 30, '', 0, + 11, 9, 1.25, 100, 100, 100), + (33, 11, 11, 365, 471, 154, 96, 71, 71, 71, 71, 147, 147, 71, 47, 47, 47, 47, 47, 47, 4, 25, 1, -18, 30, '', 0, + 11, 9, 1.25, 100, 100, 100), + (33, 12, 12, 401, 523, 168, 105, 73, 73, 73, 73, 151, 151, 73, 52, 52, 52, 52, 52, 52, 4, 27, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (33, 13, 13, 437, 577, 182, 113, 74, 74, 74, 74, 154, 154, 74, 54, 54, 54, 54, 54, 54, 5, 28, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (33, 14, 14, 474, 633, 196, 122, 76, 76, 76, 76, 158, 158, 76, 56, 56, 56, 56, 56, 56, 5, 29, 1, -18, 30, '', 0, + 12, 9, 1.25, 100, 100, 100), + (33, 15, 15, 512, 690, 210, 131, 77, 77, 77, 77, 161, 161, 77, 58, 58, 58, 58, 58, 58, 5, 31, 1, -18, 30, '', 0, + 12, 10, 1.25, 100, 100, 100), + (33, 16, 16, 551, 749, 224, 140, 80, 80, 80, 80, 165, 165, 80, 63, 63, 63, 63, 63, 63, 5, 32, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (33, 17, 17, 591, 809, 238, 148, 81, 81, 81, 81, 168, 168, 81, 65, 65, 65, 65, 65, 65, 6, 34, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (33, 18, 18, 632, 871, 252, 157, 84, 84, 84, 84, 172, 172, 84, 67, 67, 67, 67, 67, 67, 6, 35, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (33, 19, 19, 675, 935, 266, 166, 85, 85, 85, 85, 175, 175, 85, 69, 69, 69, 69, 69, 69, 6, 36, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (33, 20, 20, 718, 1000, 280, 175, 91, 91, 91, 91, 179, 179, 91, 74, 74, 74, 74, 74, 74, 6, 38, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (33, 21, 21, 763, 1067, 294, 183, 93, 93, 93, 93, 182, 182, 93, 76, 76, 76, 76, 76, 76, 7, 39, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (33, 22, 22, 810, 1135, 308, 192, 96, 96, 96, 96, 186, 186, 96, 78, 78, 78, 78, 78, 78, 7, 41, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (33, 23, 23, 858, 1205, 322, 201, 98, 98, 98, 98, 189, 189, 98, 80, 80, 80, 80, 80, 80, 7, 42, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (33, 24, 24, 907, 1277, 336, 210, 101, 101, 101, 101, 193, 193, 101, 85, 85, 85, 85, 85, 85, 7, 43, 1, -18, 30, + '', 0, 15, 11, 1.25, 100, 100, 100), + (33, 25, 25, 958, 1350, 350, 218, 103, 103, 103, 103, 196, 196, 103, 87, 87, 87, 87, 87, 87, 8, 45, 1, -18, 30, + '', 0, 15, 12, 1.25, 100, 100, 100), + (33, 26, 26, 1011, 1425, 364, 227, 106, 106, 106, 106, 200, 200, 106, 89, 89, 89, 89, 89, 89, 8, 46, 1, -18, 30, + '', 0, 15, 12, 1.25, 100, 100, 100), + (33, 27, 27, 1065, 1501, 378, 236, 108, 108, 108, 108, 203, 203, 108, 91, 91, 91, 91, 91, 91, 8, 48, 1, -18, 30, + '', 0, 15, 12, 1.25, 100, 100, 100), + (33, 28, 28, 1121, 1579, 392, 245, 112, 112, 112, 112, 207, 207, 112, 96, 96, 96, 96, 96, 96, 8, 49, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (33, 29, 29, 1179, 1659, 406, 253, 114, 114, 114, 114, 210, 210, 114, 98, 98, 98, 98, 98, 98, 9, 50, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (33, 30, 30, 1240, 1740, 420, 262, 121, 121, 121, 121, 214, 214, 121, 100, 100, 100, 100, 100, 100, 9, 52, 1, + -18, 30, '', 0, 16, 13, 1.25, 100, 100, 100), + (33, 31, 31, 1302, 1823, 434, 271, 123, 123, 123, 123, 217, 217, 123, 102, 102, 102, 102, 102, 102, 9, 53, 1, + -18, 30, '', 0, 16, 13, 1.25, 100, 100, 100), + (33, 32, 32, 1366, 1907, 448, 280, 127, 127, 127, 127, 221, 221, 127, 107, 107, 107, 107, 107, 107, 9, 55, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (33, 33, 33, 1432, 1993, 462, 288, 130, 130, 130, 130, 224, 224, 130, 109, 109, 109, 109, 109, 109, 10, 56, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (33, 34, 34, 1500, 2081, 476, 297, 134, 134, 134, 134, 228, 228, 134, 111, 111, 111, 111, 111, 111, 10, 57, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (33, 35, 35, 1571, 2170, 490, 306, 137, 137, 137, 137, 231, 231, 137, 113, 113, 113, 113, 113, 113, 10, 59, 1, + -18, 30, '', 0, 17, 14, 1.25, 100, 100, 100), + (33, 36, 36, 1644, 2261, 504, 315, 141, 141, 141, 141, 235, 235, 141, 118, 118, 118, 118, 118, 118, 10, 60, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (33, 37, 37, 1719, 2353, 518, 323, 144, 144, 144, 144, 238, 238, 144, 120, 120, 120, 120, 120, 120, 11, 62, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (33, 38, 38, 1797, 2447, 532, 332, 148, 148, 148, 148, 242, 242, 148, 122, 122, 122, 122, 122, 122, 11, 63, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (33, 39, 39, 1878, 2543, 546, 341, 152, 152, 152, 152, 245, 245, 152, 124, 124, 124, 124, 124, 124, 11, 64, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (33, 40, 40, 1961, 2640, 560, 350, 159, 159, 159, 159, 249, 249, 159, 129, 129, 129, 129, 129, 129, 11, 66, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (33, 41, 41, 2046, 2739, 574, 358, 163, 163, 163, 163, 252, 252, 163, 131, 131, 131, 131, 131, 131, 12, 67, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (33, 42, 42, 2135, 2839, 588, 367, 167, 167, 167, 167, 256, 256, 167, 133, 133, 133, 133, 133, 133, 12, 69, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (33, 43, 43, 2226, 2941, 602, 376, 171, 171, 171, 171, 259, 259, 171, 135, 135, 135, 135, 135, 135, 12, 70, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (33, 44, 44, 2320, 3045, 616, 385, 176, 176, 176, 176, 263, 263, 176, 140, 140, 140, 140, 140, 140, 12, 71, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (33, 45, 45, 2417, 3150, 630, 393, 180, 180, 180, 180, 266, 266, 180, 142, 142, 142, 142, 142, 142, 13, 73, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (33, 46, 46, 2517, 3257, 644, 402, 185, 185, 185, 185, 270, 270, 185, 144, 144, 144, 144, 144, 144, 13, 74, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (33, 47, 47, 2620, 3365, 658, 411, 189, 189, 189, 189, 273, 273, 189, 146, 146, 146, 146, 146, 146, 13, 76, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (33, 48, 48, 2726, 3475, 672, 420, 194, 194, 194, 194, 277, 277, 194, 151, 151, 151, 151, 151, 151, 13, 77, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (33, 49, 49, 2836, 3587, 686, 428, 198, 198, 198, 198, 280, 280, 198, 153, 153, 153, 153, 153, 153, 14, 78, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (33, 50, 50, 2948, 3700, 700, 437, 206, 206, 206, 206, 284, 284, 206, 155, 155, 155, 155, 155, 155, 14, 80, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (33, 51, 51, 3064, 3815, 714, 446, 211, 211, 211, 211, 287, 287, 211, 157, 157, 157, 157, 157, 157, 14, 81, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (33, 52, 52, 3184, 3931, 728, 455, 216, 216, 216, 216, 291, 291, 216, 162, 162, 162, 162, 162, 162, 14, 83, 1, + -18, 30, '', 0, 22, 17, 1.37, 100, 100, 100), + (33, 53, 53, 3307, 4049, 742, 463, 221, 221, 221, 221, 294, 294, 221, 164, 164, 164, 164, 164, 164, 15, 84, 1, + -18, 30, '', 0, 22, 17, 1.37, 100, 100, 100), + (33, 54, 54, 3433, 4169, 756, 472, 226, 226, 226, 226, 298, 298, 226, 166, 166, 166, 166, 166, 166, 15, 85, 1, + -18, 30, '', 0, 22, 17, 1.37, 100, 100, 100), + (33, 55, 55, 3563, 4290, 770, 481, 231, 231, 231, 231, 301, 301, 231, 168, 168, 168, 168, 168, 168, 15, 87, 1, + -18, 30, '', 0, 22, 18, 1.37, 100, 100, 100), + (33, 56, 56, 3697, 4413, 784, 490, 237, 237, 237, 237, 305, 305, 237, 173, 173, 173, 173, 173, 173, 15, 88, 1, + -18, 30, '', 0, 23, 18, 1.37, 100, 100, 100), + (33, 57, 57, 3834, 4537, 798, 498, 242, 242, 242, 242, 308, 308, 242, 175, 175, 175, 175, 175, 175, 16, 90, 1, + -18, 30, '', 0, 23, 18, 1.37, 100, 100, 100), + (33, 58, 58, 3975, 4663, 812, 507, 248, 248, 248, 248, 312, 312, 248, 177, 177, 177, 177, 177, 177, 16, 91, 1, + -18, 30, '', 0, 23, 18, 1.37, 100, 100, 100), + (33, 59, 59, 4120, 4791, 826, 516, 253, 253, 253, 253, 315, 315, 253, 179, 179, 179, 179, 179, 179, 16, 92, 1, + -18, 30, '', 0, 23, 18, 1.37, 100, 100, 100), + (33, 60, 60, 4270, 4920, 840, 525, 262, 262, 262, 262, 319, 319, 262, 184, 184, 184, 184, 184, 184, 16, 94, 1, + -18, 30, '', 0, 24, 19, 1.37, 100, 100, 100), + (33, 61, 61, 4423, 5051, 854, 533, 267, 267, 267, 267, 322, 322, 267, 186, 186, 186, 186, 186, 186, 17, 95, 1, + -18, 30, '', 0, 24, 19, 1.37, 100, 100, 100), + (33, 62, 62, 4580, 5183, 868, 542, 274, 274, 274, 274, 326, 326, 274, 188, 188, 188, 188, 188, 188, 17, 97, 1, + -18, 30, '', 0, 24, 19, 1.37, 100, 100, 100), + (33, 63, 63, 4741, 5317, 882, 551, 279, 279, 279, 279, 329, 329, 279, 190, 190, 190, 190, 190, 190, 17, 98, 1, + -18, 30, '', 0, 24, 19, 1.37, 100, 100, 100), + (33, 64, 64, 4906, 5453, 896, 560, 286, 286, 286, 286, 333, 333, 286, 195, 195, 195, 195, 195, 195, 17, 99, 1, + -18, 30, '', 0, 25, 19, 1.37, 100, 100, 100), + (33, 65, 65, 5076, 5590, 910, 568, 291, 291, 291, 291, 336, 336, 291, 197, 197, 197, 197, 197, 197, 18, 101, 1, + -18, 30, '', 0, 25, 20, 1.37, 100, 100, 100), + (33, 66, 66, 5250, 5729, 924, 577, 328, 328, 328, 328, 370, 370, 328, 199, 199, 199, 199, 199, 199, 18, 102, 1, + -18, 30, '', 0, 25, 20, 1.37, 100, 100, 100), + (33, 67, 67, 5428, 5869, 938, 586, 339, 339, 339, 339, 378, 378, 339, 201, 201, 201, 201, 201, 201, 18, 104, 1, + -18, 30, '', 0, 25, 20, 1.37, 100, 100, 100), + (33, 68, 68, 5611, 6011, 952, 595, 351, 351, 351, 351, 387, 387, 351, 206, 206, 206, 206, 206, 206, 18, 105, 1, + -18, 30, '', 0, 26, 20, 1.37, 100, 100, 100), + (33, 69, 69, 5799, 6155, 966, 603, 362, 362, 362, 362, 395, 395, 362, 208, 208, 208, 208, 208, 208, 19, 106, 1, + -18, 30, '', 0, 26, 20, 1.37, 100, 100, 100), + (33, 70, 70, 5991, 6300, 980, 612, 377, 377, 377, 377, 404, 404, 377, 210, 210, 210, 210, 210, 210, 19, 108, 1, + -18, 30, '', 0, 26, 21, 1.37, 100, 100, 100), + (33, 71, 71, 6187, 6447, 994, 621, 388, 388, 388, 388, 412, 412, 388, 212, 212, 212, 212, 212, 212, 19, 109, 1, + -18, 30, '', 0, 26, 21, 1.37, 100, 100, 100), + (33, 72, 72, 6389, 6595, 1008, 630, 400, 400, 400, 400, 421, 421, 400, 217, 217, 217, 217, 217, 217, 19, 111, 1, + -18, 30, '', 0, 27, 21, 1.37, 100, 100, 100), + (33, 73, 73, 6595, 6745, 1022, 638, 411, 411, 411, 411, 429, 429, 411, 219, 219, 219, 219, 219, 219, 20, 112, 1, + -18, 30, '', 0, 27, 21, 1.37, 100, 100, 100), + (33, 74, 74, 6806, 6897, 1036, 647, 424, 424, 424, 424, 438, 438, 424, 221, 221, 221, 221, 221, 221, 20, 113, 1, + -18, 30, '', 0, 27, 21, 1.37, 100, 100, 100), + (33, 75, 75, 7022, 7050, 1050, 656, 435, 435, 435, 435, 446, 446, 435, 223, 223, 223, 223, 223, 223, 20, 115, 1, + -18, 30, '', 0, 27, 22, 1.37, 100, 100, 100), + (33, 76, 76, 7243, 7205, 1064, 665, 448, 448, 448, 448, 455, 455, 448, 228, 228, 228, 228, 228, 228, 20, 116, 1, + -18, 30, '', 0, 28, 22, 1.37, 100, 100, 100), + (33, 77, 77, 7469, 7361, 1078, 673, 459, 459, 459, 459, 463, 463, 459, 230, 230, 230, 230, 230, 230, 21, 118, 1, + -18, 30, '', 0, 28, 22, 1.37, 100, 100, 100), + (33, 78, 78, 7700, 7519, 1092, 682, 472, 472, 472, 472, 472, 472, 472, 232, 232, 232, 232, 232, 232, 21, 119, 1, + -18, 30, '', 0, 28, 22, 1.37, 100, 100, 100), + (33, 79, 79, 7937, 7679, 1106, 691, 484, 484, 484, 484, 480, 480, 484, 234, 234, 234, 234, 234, 234, 21, 120, 1, + -18, 30, '', 0, 28, 22, 1.37, 100, 100, 100), + (33, 80, 80, 8178, 7840, 1120, 700, 500, 500, 500, 500, 489, 489, 500, 239, 239, 239, 239, 239, 239, 21, 122, 1, + -18, 30, '', 0, 29, 23, 1.37, 100, 100, 100), + (33, 81, 81, 8425, 8003, 1134, 708, 512, 512, 512, 512, 497, 497, 512, 241, 241, 241, 241, 241, 241, 22, 123, 1, + -18, 30, '', 0, 29, 23, 1.37, 100, 100, 100), + (33, 82, 82, 8678, 8167, 1148, 717, 525, 525, 525, 525, 506, 506, 525, 243, 243, 243, 243, 243, 243, 22, 125, 1, + -18, 30, '', 0, 29, 23, 1.37, 100, 100, 100), + (33, 83, 83, 8936, 8333, 1162, 726, 537, 537, 537, 537, 514, 514, 537, 245, 245, 245, 245, 245, 245, 22, 126, 1, + -18, 30, '', 0, 29, 23, 1.37, 100, 100, 100), + (33, 84, 84, 9199, 8501, 1176, 735, 550, 550, 550, 550, 523, 523, 550, 250, 250, 250, 250, 250, 250, 22, 127, 1, + -18, 30, '', 0, 30, 23, 1.37, 100, 100, 100), + (33, 85, 85, 9468, 8670, 1190, 743, 563, 563, 563, 563, 531, 531, 563, 252, 252, 252, 252, 252, 252, 23, 129, 1, + -18, 30, '', 0, 30, 24, 1.37, 100, 100, 100), + (34, 1, 1, 43, 38, 14, 9, 59, 59, 59, 59, 115, 115, 59, 24, 24, 24, 24, 24, 24, 2, 13, 1, -18, 30, '', 0, 10, 8, + 1.25, 100, 100, 100), + (34, 2, 2, 76, 77, 28, 18, 60, 60, 60, 60, 119, 119, 60, 26, 26, 26, 26, 26, 26, 2, 14, 1, -18, 30, '', 0, 10, 8, + 1.25, 100, 100, 100), + (34, 3, 3, 109, 118, 43, 27, 60, 60, 60, 60, 122, 122, 60, 28, 28, 28, 28, 28, 28, 2, 15, 1, -18, 30, '', 0, 10, + 8, 1.25, 100, 100, 100), + (34, 4, 4, 142, 161, 57, 36, 61, 61, 61, 61, 126, 126, 61, 34, 34, 34, 34, 34, 34, 3, 17, 1, -18, 30, '', 0, 11, + 8, 1.25, 100, 100, 100), + (34, 5, 5, 176, 205, 71, 45, 62, 62, 62, 62, 129, 129, 62, 36, 36, 36, 36, 36, 36, 3, 18, 1, -18, 30, '', 0, 11, + 9, 1.25, 100, 100, 100), + (34, 6, 6, 210, 251, 86, 54, 63, 63, 63, 63, 133, 133, 63, 38, 38, 38, 38, 38, 38, 3, 20, 1, -18, 30, '', 0, 11, + 9, 1.25, 100, 100, 100), + (34, 7, 7, 244, 298, 100, 63, 64, 64, 64, 64, 136, 136, 64, 40, 40, 40, 40, 40, 40, 3, 21, 1, -18, 30, '', 0, 11, + 9, 1.25, 100, 100, 100), + (34, 8, 8, 279, 347, 114, 72, 65, 65, 65, 65, 140, 140, 65, 46, 46, 46, 46, 46, 46, 4, 22, 1, -18, 30, '', 0, 12, + 9, 1.25, 100, 100, 100), + (34, 9, 9, 315, 398, 129, 81, 66, 66, 66, 66, 143, 143, 66, 48, 48, 48, 48, 48, 48, 4, 24, 1, -18, 30, '', 0, 12, + 9, 1.25, 100, 100, 100), + (34, 10, 10, 351, 450, 143, 90, 72, 72, 72, 72, 147, 147, 72, 50, 50, 50, 50, 50, 50, 4, 25, 1, -18, 30, '', 0, + 12, 10, 1.25, 100, 100, 100), + (34, 11, 11, 387, 504, 157, 99, 73, 73, 73, 73, 150, 150, 73, 52, 52, 52, 52, 52, 52, 4, 27, 1, -18, 30, '', 0, + 12, 10, 1.25, 100, 100, 100), + (34, 12, 12, 425, 559, 172, 108, 75, 75, 75, 75, 154, 154, 75, 58, 58, 58, 58, 58, 58, 5, 28, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (34, 13, 13, 463, 616, 186, 117, 76, 76, 76, 76, 157, 157, 76, 60, 60, 60, 60, 60, 60, 5, 29, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (34, 14, 14, 502, 675, 200, 126, 78, 78, 78, 78, 161, 161, 78, 62, 62, 62, 62, 62, 62, 5, 31, 1, -18, 30, '', 0, + 13, 10, 1.25, 100, 100, 100), + (34, 15, 15, 542, 735, 215, 135, 79, 79, 79, 79, 164, 164, 79, 64, 64, 64, 64, 64, 64, 5, 32, 1, -18, 30, '', 0, + 13, 11, 1.25, 100, 100, 100), + (34, 16, 16, 583, 797, 229, 144, 82, 82, 82, 82, 168, 168, 82, 70, 70, 70, 70, 70, 70, 6, 34, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (34, 17, 17, 625, 860, 243, 153, 83, 83, 83, 83, 171, 171, 83, 72, 72, 72, 72, 72, 72, 6, 35, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (34, 18, 18, 668, 925, 258, 162, 86, 86, 86, 86, 175, 175, 86, 74, 74, 74, 74, 74, 74, 6, 36, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (34, 19, 19, 713, 992, 272, 171, 87, 87, 87, 87, 178, 178, 87, 76, 76, 76, 76, 76, 76, 6, 38, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (34, 20, 20, 758, 1060, 286, 180, 94, 94, 94, 94, 182, 182, 94, 82, 82, 82, 82, 82, 82, 7, 39, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (34, 21, 21, 805, 1130, 301, 189, 96, 96, 96, 96, 185, 185, 96, 84, 84, 84, 84, 84, 84, 7, 41, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (34, 22, 22, 854, 1201, 315, 198, 99, 99, 99, 99, 189, 189, 99, 86, 86, 86, 86, 86, 86, 7, 42, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (34, 23, 23, 904, 1274, 329, 207, 101, 101, 101, 101, 192, 192, 101, 88, 88, 88, 88, 88, 88, 7, 43, 1, -18, 30, + '', 0, 15, 12, 1.25, 100, 100, 100), + (34, 24, 24, 955, 1349, 344, 216, 104, 104, 104, 104, 196, 196, 104, 94, 94, 94, 94, 94, 94, 8, 45, 1, -18, 30, + '', 0, 16, 12, 1.25, 100, 100, 100), + (34, 25, 25, 1008, 1425, 358, 225, 106, 106, 106, 106, 199, 199, 106, 96, 96, 96, 96, 96, 96, 8, 46, 1, -18, 30, + '', 0, 16, 13, 1.25, 100, 100, 100), + (34, 26, 26, 1063, 1503, 372, 234, 109, 109, 109, 109, 203, 203, 109, 98, 98, 98, 98, 98, 98, 8, 48, 1, -18, 30, + '', 0, 16, 13, 1.25, 100, 100, 100), + (34, 27, 27, 1119, 1582, 387, 243, 111, 111, 111, 111, 206, 206, 111, 100, 100, 100, 100, 100, 100, 8, 49, 1, + -18, 30, '', 0, 16, 13, 1.25, 100, 100, 100), + (34, 28, 28, 1177, 1663, 401, 252, 115, 115, 115, 115, 210, 210, 115, 106, 106, 106, 106, 106, 106, 9, 50, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (34, 29, 29, 1237, 1746, 415, 261, 117, 117, 117, 117, 213, 213, 117, 108, 108, 108, 108, 108, 108, 9, 52, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (34, 30, 30, 1300, 1830, 430, 270, 125, 125, 125, 125, 217, 217, 125, 110, 110, 110, 110, 110, 110, 9, 53, 1, + -18, 30, '', 0, 17, 14, 1.25, 100, 100, 100), + (34, 31, 31, 1364, 1916, 444, 279, 127, 127, 127, 127, 220, 220, 127, 112, 112, 112, 112, 112, 112, 9, 55, 1, + -18, 30, '', 0, 17, 14, 1.25, 100, 100, 100), + (34, 32, 32, 1430, 2003, 458, 288, 131, 131, 131, 131, 224, 224, 131, 118, 118, 118, 118, 118, 118, 10, 56, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (34, 33, 33, 1498, 2092, 473, 297, 134, 134, 134, 134, 227, 227, 134, 120, 120, 120, 120, 120, 120, 10, 57, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (34, 34, 34, 1568, 2183, 487, 306, 138, 138, 138, 138, 231, 231, 138, 122, 122, 122, 122, 122, 122, 10, 59, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (34, 35, 35, 1641, 2275, 501, 315, 141, 141, 141, 141, 234, 234, 141, 124, 124, 124, 124, 124, 124, 10, 60, 1, + -18, 30, '', 0, 18, 15, 1.25, 100, 100, 100), + (34, 36, 36, 1716, 2369, 516, 324, 145, 145, 145, 145, 238, 238, 145, 130, 130, 130, 130, 130, 130, 11, 62, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (34, 37, 37, 1793, 2464, 530, 333, 148, 148, 148, 148, 241, 241, 148, 132, 132, 132, 132, 132, 132, 11, 63, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (34, 38, 38, 1873, 2561, 544, 342, 152, 152, 152, 152, 245, 245, 152, 134, 134, 134, 134, 134, 134, 11, 64, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (34, 39, 39, 1956, 2660, 559, 351, 156, 156, 156, 156, 248, 248, 156, 136, 136, 136, 136, 136, 136, 11, 66, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (34, 40, 40, 2041, 2760, 573, 360, 164, 164, 164, 164, 252, 252, 164, 142, 142, 142, 142, 142, 142, 12, 67, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (34, 41, 41, 2128, 2862, 587, 369, 168, 168, 168, 168, 255, 255, 168, 144, 144, 144, 144, 144, 144, 12, 69, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (34, 42, 42, 2219, 2965, 602, 378, 172, 172, 172, 172, 259, 259, 172, 146, 146, 146, 146, 146, 146, 12, 70, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (34, 43, 43, 2312, 3070, 616, 387, 176, 176, 176, 176, 262, 262, 176, 148, 148, 148, 148, 148, 148, 12, 71, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (34, 44, 44, 2408, 3177, 630, 396, 181, 181, 181, 181, 266, 266, 181, 154, 154, 154, 154, 154, 154, 13, 73, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (34, 45, 45, 2507, 3285, 645, 405, 185, 185, 185, 185, 269, 269, 185, 156, 156, 156, 156, 156, 156, 13, 74, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (34, 46, 46, 2609, 3395, 659, 414, 190, 190, 190, 190, 273, 273, 190, 158, 158, 158, 158, 158, 158, 13, 76, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (34, 47, 47, 2714, 3506, 673, 423, 194, 194, 194, 194, 276, 276, 194, 160, 160, 160, 160, 160, 160, 13, 77, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (34, 48, 48, 2822, 3619, 688, 432, 199, 199, 199, 199, 280, 280, 199, 166, 166, 166, 166, 166, 166, 14, 78, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (34, 49, 49, 2934, 3734, 702, 441, 203, 203, 203, 203, 283, 283, 203, 168, 168, 168, 168, 168, 168, 14, 80, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (34, 50, 50, 3048, 3850, 716, 450, 212, 212, 212, 212, 287, 287, 212, 170, 170, 170, 170, 170, 170, 14, 81, 1, + -18, 30, '', 0, 22, 18, 1.25, 100, 100, 100), + (34, 51, 51, 3166, 3968, 731, 459, 217, 217, 217, 217, 290, 290, 217, 172, 172, 172, 172, 172, 172, 14, 83, 1, + -18, 30, '', 0, 22, 18, 1.25, 100, 100, 100), + (34, 52, 52, 3288, 4087, 745, 468, 222, 222, 222, 222, 294, 294, 222, 178, 178, 178, 178, 178, 178, 15, 84, 1, + -18, 30, '', 0, 23, 18, 1.43, 100, 100, 100), + (34, 53, 53, 3413, 4208, 759, 477, 227, 227, 227, 227, 297, 297, 227, 180, 180, 180, 180, 180, 180, 15, 85, 1, + -18, 30, '', 0, 23, 18, 1.43, 100, 100, 100), + (34, 54, 54, 3541, 4331, 774, 486, 232, 232, 232, 232, 301, 301, 232, 182, 182, 182, 182, 182, 182, 15, 87, 1, + -18, 30, '', 0, 23, 18, 1.43, 100, 100, 100), + (34, 55, 55, 3673, 4455, 788, 495, 237, 237, 237, 237, 304, 304, 237, 184, 184, 184, 184, 184, 184, 15, 88, 1, + -18, 30, '', 0, 23, 19, 1.43, 100, 100, 100), + (34, 56, 56, 3809, 4581, 802, 504, 243, 243, 243, 243, 308, 308, 243, 190, 190, 190, 190, 190, 190, 16, 90, 1, + -18, 30, '', 0, 24, 19, 1.43, 100, 100, 100), + (34, 57, 57, 3948, 4708, 817, 513, 248, 248, 248, 248, 311, 311, 248, 192, 192, 192, 192, 192, 192, 16, 91, 1, + -18, 30, '', 0, 24, 19, 1.43, 100, 100, 100), + (34, 58, 58, 4091, 4837, 831, 522, 254, 254, 254, 254, 315, 315, 254, 194, 194, 194, 194, 194, 194, 16, 92, 1, + -18, 30, '', 0, 24, 19, 1.43, 100, 100, 100), + (34, 59, 59, 4238, 4968, 845, 531, 259, 259, 259, 259, 318, 318, 259, 196, 196, 196, 196, 196, 196, 16, 94, 1, + -18, 30, '', 0, 24, 19, 1.43, 100, 100, 100), + (34, 60, 60, 4390, 5100, 860, 540, 269, 269, 269, 269, 322, 322, 269, 202, 202, 202, 202, 202, 202, 17, 95, 1, + -18, 30, '', 0, 25, 20, 1.43, 100, 100, 100), + (34, 61, 61, 4545, 5234, 874, 549, 274, 274, 274, 274, 325, 325, 274, 204, 204, 204, 204, 204, 204, 17, 97, 1, + -18, 30, '', 0, 25, 20, 1.43, 100, 100, 100), + (34, 62, 62, 4704, 5369, 888, 558, 281, 281, 281, 281, 329, 329, 281, 206, 206, 206, 206, 206, 206, 17, 98, 1, + -18, 30, '', 0, 25, 20, 1.43, 100, 100, 100), + (34, 63, 63, 4867, 5506, 903, 567, 286, 286, 286, 286, 332, 332, 286, 208, 208, 208, 208, 208, 208, 17, 99, 1, + -18, 30, '', 0, 25, 20, 1.43, 100, 100, 100), + (34, 64, 64, 5034, 5645, 917, 576, 293, 293, 293, 293, 336, 336, 293, 214, 214, 214, 214, 214, 214, 18, 101, 1, + -18, 30, '', 0, 26, 20, 1.43, 100, 100, 100), + (34, 65, 65, 5206, 5785, 931, 585, 298, 298, 298, 298, 339, 339, 298, 216, 216, 216, 216, 216, 216, 18, 102, 1, + -18, 30, '', 0, 26, 21, 1.43, 100, 100, 100), + (34, 66, 66, 5382, 5927, 946, 594, 335, 335, 335, 335, 373, 373, 335, 218, 218, 218, 218, 218, 218, 18, 104, 1, + -18, 30, '', 0, 26, 21, 1.43, 100, 100, 100), + (34, 67, 67, 5562, 6070, 960, 603, 346, 346, 346, 346, 381, 381, 346, 220, 220, 220, 220, 220, 220, 18, 105, 1, + -18, 30, '', 0, 26, 21, 1.43, 100, 100, 100), + (34, 68, 68, 5747, 6215, 974, 612, 358, 358, 358, 358, 390, 390, 358, 226, 226, 226, 226, 226, 226, 19, 106, 1, + -18, 30, '', 0, 27, 21, 1.43, 100, 100, 100), + (34, 69, 69, 5937, 6362, 989, 621, 369, 369, 369, 369, 398, 398, 369, 228, 228, 228, 228, 228, 228, 19, 108, 1, + -18, 30, '', 0, 27, 21, 1.43, 100, 100, 100), + (34, 70, 70, 6131, 6510, 1003, 630, 385, 385, 385, 385, 407, 407, 385, 230, 230, 230, 230, 230, 230, 19, 109, 1, + -18, 30, '', 0, 27, 22, 1.43, 100, 100, 100), + (34, 71, 71, 6329, 6660, 1017, 639, 396, 396, 396, 396, 415, 415, 396, 232, 232, 232, 232, 232, 232, 19, 111, 1, + -18, 30, '', 0, 27, 22, 1.43, 100, 100, 100), + (34, 72, 72, 6533, 6811, 1032, 648, 408, 408, 408, 408, 424, 424, 408, 238, 238, 238, 238, 238, 238, 20, 112, 1, + -18, 30, '', 0, 28, 22, 1.43, 100, 100, 100), + (34, 73, 73, 6741, 6964, 1046, 657, 419, 419, 419, 419, 432, 432, 419, 240, 240, 240, 240, 240, 240, 20, 113, 1, + -18, 30, '', 0, 28, 22, 1.43, 100, 100, 100), + (34, 74, 74, 6954, 7119, 1060, 666, 432, 432, 432, 432, 441, 441, 432, 242, 242, 242, 242, 242, 242, 20, 115, 1, + -18, 30, '', 0, 28, 22, 1.43, 100, 100, 100), + (34, 75, 75, 7172, 7275, 1075, 675, 443, 443, 443, 443, 449, 449, 443, 244, 244, 244, 244, 244, 244, 20, 116, 1, + -18, 30, '', 0, 28, 23, 1.43, 100, 100, 100), + (34, 76, 76, 7395, 7433, 1089, 684, 456, 456, 456, 456, 458, 458, 456, 250, 250, 250, 250, 250, 250, 21, 118, 1, + -18, 30, '', 0, 29, 23, 1.43, 100, 100, 100), + (34, 77, 77, 7623, 7592, 1103, 693, 467, 467, 467, 467, 466, 466, 467, 252, 252, 252, 252, 252, 252, 21, 119, 1, + -18, 30, '', 0, 29, 23, 1.43, 100, 100, 100), + (34, 78, 78, 7856, 7753, 1118, 702, 480, 480, 480, 480, 475, 475, 480, 254, 254, 254, 254, 254, 254, 21, 120, 1, + -18, 30, '', 0, 29, 23, 1.43, 100, 100, 100), + (34, 79, 79, 8095, 7916, 1132, 711, 492, 492, 492, 492, 483, 483, 492, 256, 256, 256, 256, 256, 256, 21, 122, 1, + -18, 30, '', 0, 29, 23, 1.43, 100, 100, 100), + (34, 80, 80, 8338, 8080, 1146, 720, 509, 509, 509, 509, 492, 492, 509, 262, 262, 262, 262, 262, 262, 22, 123, 1, + -18, 30, '', 0, 30, 24, 1.43, 100, 100, 100), + (34, 81, 81, 8587, 8246, 1161, 729, 521, 521, 521, 521, 500, 500, 521, 264, 264, 264, 264, 264, 264, 22, 125, 1, + -18, 30, '', 0, 30, 24, 1.43, 100, 100, 100), + (34, 82, 82, 8842, 8413, 1175, 738, 534, 534, 534, 534, 509, 509, 534, 266, 266, 266, 266, 266, 266, 22, 126, 1, + -18, 30, '', 0, 30, 24, 1.43, 100, 100, 100), + (34, 83, 83, 9102, 8582, 1189, 747, 546, 546, 546, 546, 517, 517, 546, 268, 268, 268, 268, 268, 268, 22, 127, 1, + -18, 30, '', 0, 30, 24, 1.43, 100, 100, 100), + (34, 84, 84, 9367, 8753, 1204, 756, 559, 559, 559, 559, 526, 526, 559, 274, 274, 274, 274, 274, 274, 23, 129, 1, + -18, 30, '', 0, 31, 24, 1.43, 100, 100, 100), + (34, 85, 85, 9638, 8925, 1218, 765, 572, 572, 572, 572, 534, 534, 572, 276, 276, 276, 276, 276, 276, 23, 130, 1, + -18, 30, '', 0, 31, 25, 1.43, 100, 100, 100), + (35, 1, 1, 45, 41, 14, 9, 60, 60, 60, 60, 118, 118, 60, 27, 27, 27, 27, 27, 27, 2, 14, 1, -18, 30, '', 0, 11, 9, + 1.25, 100, 100, 100), + (35, 2, 2, 80, 83, 29, 18, 61, 61, 61, 61, 122, 122, 61, 29, 29, 29, 29, 29, 29, 2, 15, 1, -18, 30, '', 0, 11, 9, + 1.25, 100, 100, 100), + (35, 3, 3, 115, 127, 44, 27, 61, 61, 61, 61, 125, 125, 61, 31, 31, 31, 31, 31, 31, 3, 17, 1, -18, 30, '', 0, 11, + 9, 1.25, 100, 100, 100), + (35, 4, 4, 150, 173, 58, 37, 62, 62, 62, 62, 129, 129, 62, 38, 38, 38, 38, 38, 38, 3, 18, 1, -18, 30, '', 0, 12, + 9, 1.25, 100, 100, 100), + (35, 5, 5, 186, 220, 73, 46, 63, 63, 63, 63, 132, 132, 63, 40, 40, 40, 40, 40, 40, 3, 20, 1, -18, 30, '', 0, 12, + 10, 1.25, 100, 100, 100), + (35, 6, 6, 222, 269, 88, 55, 64, 64, 64, 64, 136, 136, 64, 42, 42, 42, 42, 42, 42, 3, 21, 1, -18, 30, '', 0, 12, + 10, 1.25, 100, 100, 100), + (35, 7, 7, 258, 319, 102, 64, 65, 65, 65, 65, 139, 139, 65, 44, 44, 44, 44, 44, 44, 4, 22, 1, -18, 30, '', 0, 12, + 10, 1.25, 100, 100, 100), + (35, 8, 8, 295, 371, 117, 74, 66, 66, 66, 66, 143, 143, 66, 51, 51, 51, 51, 51, 51, 4, 24, 1, -18, 30, '', 0, 13, + 10, 1.25, 100, 100, 100), + (35, 9, 9, 333, 425, 132, 83, 67, 67, 67, 67, 146, 146, 67, 53, 53, 53, 53, 53, 53, 4, 25, 1, -18, 30, '', 0, 13, + 10, 1.25, 100, 100, 100), + (35, 10, 10, 371, 480, 146, 92, 74, 74, 74, 74, 150, 150, 74, 55, 55, 55, 55, 55, 55, 4, 27, 1, -18, 30, '', 0, + 13, 11, 1.25, 100, 100, 100), + (35, 11, 11, 409, 537, 161, 101, 75, 75, 75, 75, 153, 153, 75, 57, 57, 57, 57, 57, 57, 5, 28, 1, -18, 30, '', 0, + 13, 11, 1.25, 100, 100, 100), + (35, 12, 12, 449, 595, 176, 111, 77, 77, 77, 77, 157, 157, 77, 64, 64, 64, 64, 64, 64, 5, 29, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (35, 13, 13, 489, 655, 190, 120, 78, 78, 78, 78, 160, 160, 78, 66, 66, 66, 66, 66, 66, 5, 31, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (35, 14, 14, 530, 717, 205, 129, 80, 80, 80, 80, 164, 164, 80, 68, 68, 68, 68, 68, 68, 5, 32, 1, -18, 30, '', 0, + 14, 11, 1.25, 100, 100, 100), + (35, 15, 15, 572, 780, 220, 138, 81, 81, 81, 81, 167, 167, 81, 70, 70, 70, 70, 70, 70, 6, 34, 1, -18, 30, '', 0, + 14, 12, 1.25, 100, 100, 100), + (35, 16, 16, 615, 845, 234, 148, 84, 84, 84, 84, 171, 171, 84, 77, 77, 77, 77, 77, 77, 6, 35, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (35, 17, 17, 659, 911, 249, 157, 85, 85, 85, 85, 174, 174, 85, 79, 79, 79, 79, 79, 79, 6, 36, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (35, 18, 18, 704, 979, 264, 166, 88, 88, 88, 88, 178, 178, 88, 81, 81, 81, 81, 81, 81, 6, 38, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (35, 19, 19, 751, 1049, 278, 175, 89, 89, 89, 89, 181, 181, 89, 83, 83, 83, 83, 83, 83, 7, 39, 1, -18, 30, '', 0, + 15, 12, 1.25, 100, 100, 100), + (35, 20, 20, 798, 1120, 293, 185, 97, 97, 97, 97, 185, 185, 97, 90, 90, 90, 90, 90, 90, 7, 41, 1, -18, 30, '', 0, + 16, 13, 1.25, 100, 100, 100), + (35, 21, 21, 847, 1193, 308, 194, 99, 99, 99, 99, 188, 188, 99, 92, 92, 92, 92, 92, 92, 7, 42, 1, -18, 30, '', 0, + 16, 13, 1.25, 100, 100, 100), + (35, 22, 22, 898, 1267, 322, 203, 102, 102, 102, 102, 192, 192, 102, 94, 94, 94, 94, 94, 94, 7, 43, 1, -18, 30, + '', 0, 16, 13, 1.25, 100, 100, 100), + (35, 23, 23, 950, 1343, 337, 212, 104, 104, 104, 104, 195, 195, 104, 96, 96, 96, 96, 96, 96, 8, 45, 1, -18, 30, + '', 0, 16, 13, 1.25, 100, 100, 100), + (35, 24, 24, 1003, 1421, 352, 222, 107, 107, 107, 107, 199, 199, 107, 103, 103, 103, 103, 103, 103, 8, 46, 1, + -18, 30, '', 0, 17, 13, 1.25, 100, 100, 100), + (35, 25, 25, 1058, 1500, 366, 231, 109, 109, 109, 109, 202, 202, 109, 105, 105, 105, 105, 105, 105, 8, 48, 1, + -18, 30, '', 0, 17, 14, 1.25, 100, 100, 100), + (35, 26, 26, 1115, 1581, 381, 240, 112, 112, 112, 112, 206, 206, 112, 107, 107, 107, 107, 107, 107, 8, 49, 1, + -18, 30, '', 0, 17, 14, 1.25, 100, 100, 100), + (35, 27, 27, 1173, 1663, 396, 249, 114, 114, 114, 114, 209, 209, 114, 109, 109, 109, 109, 109, 109, 9, 50, 1, + -18, 30, '', 0, 17, 14, 1.25, 100, 100, 100), + (35, 28, 28, 1233, 1747, 410, 259, 118, 118, 118, 118, 213, 213, 118, 116, 116, 116, 116, 116, 116, 9, 52, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (35, 29, 29, 1295, 1833, 425, 268, 120, 120, 120, 120, 216, 216, 120, 118, 118, 118, 118, 118, 118, 9, 53, 1, + -18, 30, '', 0, 18, 14, 1.25, 100, 100, 100), + (35, 30, 30, 1360, 1920, 440, 277, 129, 129, 129, 129, 220, 220, 129, 120, 120, 120, 120, 120, 120, 9, 55, 1, + -18, 30, '', 0, 18, 15, 1.25, 100, 100, 100), + (35, 31, 31, 1426, 2009, 454, 286, 131, 131, 131, 131, 223, 223, 131, 122, 122, 122, 122, 122, 122, 10, 56, 1, + -18, 30, '', 0, 18, 15, 1.25, 100, 100, 100), + (35, 32, 32, 1494, 2099, 469, 296, 135, 135, 135, 135, 227, 227, 135, 129, 129, 129, 129, 129, 129, 10, 57, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (35, 33, 33, 1564, 2191, 484, 305, 138, 138, 138, 138, 230, 230, 138, 131, 131, 131, 131, 131, 131, 10, 59, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (35, 34, 34, 1636, 2285, 498, 314, 142, 142, 142, 142, 234, 234, 142, 133, 133, 133, 133, 133, 133, 10, 60, 1, + -18, 30, '', 0, 19, 15, 1.25, 100, 100, 100), + (35, 35, 35, 1711, 2380, 513, 323, 145, 145, 145, 145, 237, 237, 145, 135, 135, 135, 135, 135, 135, 11, 62, 1, + -18, 30, '', 0, 19, 16, 1.25, 100, 100, 100), + (35, 36, 36, 1788, 2477, 528, 333, 149, 149, 149, 149, 241, 241, 149, 142, 142, 142, 142, 142, 142, 11, 63, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (35, 37, 37, 1867, 2575, 542, 342, 152, 152, 152, 152, 244, 244, 152, 144, 144, 144, 144, 144, 144, 11, 64, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (35, 38, 38, 1949, 2675, 557, 351, 156, 156, 156, 156, 248, 248, 156, 146, 146, 146, 146, 146, 146, 11, 66, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (35, 39, 39, 2034, 2777, 572, 360, 160, 160, 160, 160, 251, 251, 160, 148, 148, 148, 148, 148, 148, 12, 67, 1, + -18, 30, '', 0, 20, 16, 1.25, 100, 100, 100), + (35, 40, 40, 2121, 2880, 586, 370, 169, 169, 169, 169, 255, 255, 169, 155, 155, 155, 155, 155, 155, 12, 69, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (35, 41, 41, 2210, 2985, 601, 379, 173, 173, 173, 173, 258, 258, 173, 157, 157, 157, 157, 157, 157, 12, 70, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (35, 42, 42, 2303, 3091, 616, 388, 177, 177, 177, 177, 262, 262, 177, 159, 159, 159, 159, 159, 159, 12, 71, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (35, 43, 43, 2398, 3199, 630, 397, 181, 181, 181, 181, 265, 265, 181, 161, 161, 161, 161, 161, 161, 13, 73, 1, + -18, 30, '', 0, 21, 17, 1.25, 100, 100, 100), + (35, 44, 44, 2496, 3309, 645, 407, 186, 186, 186, 186, 269, 269, 186, 168, 168, 168, 168, 168, 168, 13, 74, 1, + -18, 30, '', 0, 22, 17, 1.25, 100, 100, 100), + (35, 45, 45, 2597, 3420, 660, 416, 190, 190, 190, 190, 272, 272, 190, 170, 170, 170, 170, 170, 170, 13, 76, 1, + -18, 30, '', 0, 22, 18, 1.25, 100, 100, 100), + (35, 46, 46, 2701, 3533, 674, 425, 195, 195, 195, 195, 276, 276, 195, 172, 172, 172, 172, 172, 172, 13, 77, 1, + -18, 30, '', 0, 22, 18, 1.25, 100, 100, 100), + (35, 47, 47, 2808, 3647, 689, 434, 199, 199, 199, 199, 279, 279, 199, 174, 174, 174, 174, 174, 174, 14, 78, 1, + -18, 30, '', 0, 22, 18, 1.25, 100, 100, 100), + (35, 48, 48, 2918, 3763, 704, 444, 204, 204, 204, 204, 283, 283, 204, 181, 181, 181, 181, 181, 181, 14, 80, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (35, 49, 49, 3032, 3881, 718, 453, 208, 208, 208, 208, 286, 286, 208, 183, 183, 183, 183, 183, 183, 14, 81, 1, + -18, 30, '', 0, 23, 18, 1.25, 100, 100, 100), + (35, 50, 50, 3148, 4000, 733, 462, 218, 218, 218, 218, 290, 290, 218, 185, 185, 185, 185, 185, 185, 14, 83, 1, + -18, 30, '', 0, 23, 19, 1.25, 100, 100, 100), + (35, 51, 51, 3268, 4121, 748, 471, 223, 223, 223, 223, 293, 293, 223, 187, 187, 187, 187, 187, 187, 15, 84, 1, + -18, 30, '', 0, 23, 19, 1.25, 100, 100, 100), + (35, 52, 52, 3392, 4243, 762, 481, 228, 228, 228, 228, 297, 297, 228, 194, 194, 194, 194, 194, 194, 15, 85, 1, + -18, 30, '', 0, 24, 19, 1.49, 100, 100, 100), + (35, 53, 53, 3519, 4367, 777, 490, 233, 233, 233, 233, 300, 300, 233, 196, 196, 196, 196, 196, 196, 15, 87, 1, + -18, 30, '', 0, 24, 19, 1.49, 100, 100, 100), + (35, 54, 54, 3649, 4493, 792, 499, 238, 238, 238, 238, 304, 304, 238, 198, 198, 198, 198, 198, 198, 15, 88, 1, + -18, 30, '', 0, 24, 19, 1.49, 100, 100, 100), + (35, 55, 55, 3783, 4620, 806, 508, 243, 243, 243, 243, 307, 307, 243, 200, 200, 200, 200, 200, 200, 16, 90, 1, + -18, 30, '', 0, 24, 20, 1.49, 100, 100, 100), + (35, 56, 56, 3921, 4749, 821, 518, 249, 249, 249, 249, 311, 311, 249, 207, 207, 207, 207, 207, 207, 16, 91, 1, + -18, 30, '', 0, 25, 20, 1.49, 100, 100, 100), + (35, 57, 57, 4062, 4879, 836, 527, 254, 254, 254, 254, 314, 314, 254, 209, 209, 209, 209, 209, 209, 16, 92, 1, + -18, 30, '', 0, 25, 20, 1.49, 100, 100, 100), + (35, 58, 58, 4207, 5011, 850, 536, 260, 260, 260, 260, 318, 318, 260, 211, 211, 211, 211, 211, 211, 16, 94, 1, + -18, 30, '', 0, 25, 20, 1.49, 100, 100, 100), + (35, 59, 59, 4356, 5145, 865, 545, 265, 265, 265, 265, 321, 321, 265, 213, 213, 213, 213, 213, 213, 17, 95, 1, + -18, 30, '', 0, 25, 20, 1.49, 100, 100, 100), + (35, 60, 60, 4510, 5280, 880, 555, 276, 276, 276, 276, 325, 325, 276, 220, 220, 220, 220, 220, 220, 17, 97, 1, + -18, 30, '', 0, 26, 21, 1.49, 100, 100, 100), + (35, 61, 61, 4667, 5417, 894, 564, 281, 281, 281, 281, 328, 328, 281, 222, 222, 222, 222, 222, 222, 17, 98, 1, + -18, 30, '', 0, 26, 21, 1.49, 100, 100, 100), + (35, 62, 62, 4828, 5555, 909, 573, 288, 288, 288, 288, 332, 332, 288, 224, 224, 224, 224, 224, 224, 17, 99, 1, + -18, 30, '', 0, 26, 21, 1.49, 100, 100, 100), + (35, 63, 63, 4993, 5695, 924, 582, 293, 293, 293, 293, 335, 335, 293, 226, 226, 226, 226, 226, 226, 18, 101, 1, + -18, 30, '', 0, 26, 21, 1.49, 100, 100, 100), + (35, 64, 64, 5162, 5837, 938, 592, 300, 300, 300, 300, 339, 339, 300, 233, 233, 233, 233, 233, 233, 18, 102, 1, + -18, 30, '', 0, 27, 21, 1.49, 100, 100, 100), + (35, 65, 65, 5336, 5980, 953, 601, 305, 305, 305, 305, 342, 342, 305, 235, 235, 235, 235, 235, 235, 18, 104, 1, + -18, 30, '', 0, 27, 22, 1.49, 100, 100, 100), + (35, 66, 66, 5514, 6125, 968, 610, 342, 342, 342, 342, 376, 376, 342, 237, 237, 237, 237, 237, 237, 18, 105, 1, + -18, 30, '', 0, 27, 22, 1.49, 100, 100, 100), + (35, 67, 67, 5696, 6271, 982, 619, 353, 353, 353, 353, 384, 384, 353, 239, 239, 239, 239, 239, 239, 19, 106, 1, + -18, 30, '', 0, 27, 22, 1.49, 100, 100, 100), + (35, 68, 68, 5883, 6419, 997, 629, 365, 365, 365, 365, 393, 393, 365, 246, 246, 246, 246, 246, 246, 19, 108, 1, + -18, 30, '', 0, 28, 22, 1.49, 100, 100, 100), + (35, 69, 69, 6075, 6569, 1012, 638, 376, 376, 376, 376, 401, 401, 376, 248, 248, 248, 248, 248, 248, 19, 109, 1, + -18, 30, '', 0, 28, 22, 1.49, 100, 100, 100), + (35, 70, 70, 6271, 6720, 1026, 647, 393, 393, 393, 393, 410, 410, 393, 250, 250, 250, 250, 250, 250, 19, 111, 1, + -18, 30, '', 0, 28, 23, 1.49, 100, 100, 100), + (35, 71, 71, 6471, 6873, 1041, 656, 404, 404, 404, 404, 418, 418, 404, 252, 252, 252, 252, 252, 252, 20, 112, 1, + -18, 30, '', 0, 28, 23, 1.49, 100, 100, 100), + (35, 72, 72, 6677, 7027, 1056, 666, 416, 416, 416, 416, 427, 427, 416, 259, 259, 259, 259, 259, 259, 20, 113, 1, + -18, 30, '', 0, 29, 23, 1.49, 100, 100, 100), + (35, 73, 73, 6887, 7183, 1070, 675, 427, 427, 427, 427, 435, 435, 427, 261, 261, 261, 261, 261, 261, 20, 115, 1, + -18, 30, '', 0, 29, 23, 1.49, 100, 100, 100), + (35, 74, 74, 7102, 7341, 1085, 684, 440, 440, 440, 440, 444, 444, 440, 263, 263, 263, 263, 263, 263, 20, 116, 1, + -18, 30, '', 0, 29, 23, 1.49, 100, 100, 100), + (35, 75, 75, 7322, 7500, 1100, 693, 451, 451, 451, 451, 452, 452, 451, 265, 265, 265, 265, 265, 265, 21, 118, 1, + -18, 30, '', 0, 29, 24, 1.49, 100, 100, 100), + (35, 76, 76, 7547, 7661, 1114, 703, 464, 464, 464, 464, 461, 461, 464, 272, 272, 272, 272, 272, 272, 21, 119, 1, + -18, 30, '', 0, 30, 24, 1.49, 100, 100, 100), + (35, 77, 77, 7777, 7823, 1129, 712, 475, 475, 475, 475, 469, 469, 475, 274, 274, 274, 274, 274, 274, 21, 120, 1, + -18, 30, '', 0, 30, 24, 1.49, 100, 100, 100), + (35, 78, 78, 8012, 7987, 1144, 721, 488, 488, 488, 488, 478, 478, 488, 276, 276, 276, 276, 276, 276, 21, 122, 1, + -18, 30, '', 0, 30, 24, 1.49, 100, 100, 100), + (35, 79, 79, 8253, 8153, 1158, 730, 500, 500, 500, 500, 486, 486, 500, 278, 278, 278, 278, 278, 278, 22, 123, 1, + -18, 30, '', 0, 30, 24, 1.49, 100, 100, 100), + (35, 80, 80, 8498, 8320, 1173, 740, 518, 518, 518, 518, 495, 495, 518, 285, 285, 285, 285, 285, 285, 22, 125, 1, + -18, 30, '', 0, 31, 25, 1.49, 100, 100, 100), + (35, 81, 81, 8749, 8489, 1188, 749, 530, 530, 530, 530, 503, 503, 530, 287, 287, 287, 287, 287, 287, 22, 126, 1, + -18, 30, '', 0, 31, 25, 1.49, 100, 100, 100), + (35, 82, 82, 9006, 8659, 1202, 758, 543, 543, 543, 543, 512, 512, 543, 289, 289, 289, 289, 289, 289, 22, 127, 1, + -18, 30, '', 0, 31, 25, 1.49, 100, 100, 100), + (35, 83, 83, 9268, 8831, 1217, 767, 555, 555, 555, 555, 520, 520, 555, 291, 291, 291, 291, 291, 291, 23, 129, 1, + -18, 30, '', 0, 31, 25, 1.49, 100, 100, 100), + (35, 84, 84, 9535, 9005, 1232, 777, 568, 568, 568, 568, 529, 529, 568, 298, 298, 298, 298, 298, 298, 23, 130, 1, + -18, 30, '', 0, 32, 25, 1.49, 100, 100, 100), + (35, 85, 85, 9808, 9180, 1246, 786, 581, 581, 581, 581, 537, 537, 581, 300, 300, 300, 300, 300, 300, 23, 132, 1, + -18, 30, '', 0, 32, 26, 1.49, 100, 100, 100), + (36, 1, 1, 62, 54, 16, 9, 61, 61, 61, 61, 131, 131, 61, 31, 31, 31, 31, 31, 31, 2, 13, 1, -18, 30, '', 0, 12, 8, + 1.25, 100, 100, 100), + (36, 2, 2, 114, 109, 32, 18, 63, 63, 63, 63, 135, 135, 63, 35, 35, 35, 35, 35, 35, 2, 14, 1, -18, 30, '', 0, 12, + 8, 1.25, 100, 100, 100), + (36, 3, 3, 166, 166, 49, 27, 63, 63, 63, 63, 138, 138, 63, 37, 37, 37, 37, 37, 37, 2, 15, 1, -18, 30, '', 0, 12, + 8, 1.25, 100, 100, 100), + (36, 4, 4, 218, 225, 65, 37, 65, 65, 65, 65, 142, 142, 65, 40, 40, 40, 40, 40, 40, 3, 17, 1, -18, 30, '', 0, 13, + 8, 1.25, 100, 100, 100), + (36, 5, 5, 271, 285, 81, 46, 66, 66, 66, 66, 145, 145, 66, 44, 44, 44, 44, 44, 44, 3, 18, 1, -18, 30, '', 0, 13, + 9, 1.25, 100, 100, 100), + (36, 6, 6, 324, 347, 98, 55, 68, 68, 68, 68, 149, 149, 68, 46, 46, 46, 46, 46, 46, 3, 20, 1, -18, 30, '', 0, 13, + 9, 1.25, 100, 100, 100), + (36, 7, 7, 377, 410, 114, 64, 69, 69, 69, 69, 152, 152, 69, 48, 48, 48, 48, 48, 48, 3, 21, 1, -18, 30, '', 0, 13, + 9, 1.25, 100, 100, 100), + (36, 8, 8, 431, 475, 130, 74, 71, 71, 71, 71, 156, 156, 71, 53, 53, 53, 53, 53, 53, 4, 22, 1, -18, 30, '', 0, 14, + 9, 1.25, 100, 100, 100), + (36, 9, 9, 486, 542, 147, 83, 72, 72, 72, 72, 159, 159, 72, 55, 55, 55, 55, 55, 55, 4, 24, 1, -18, 30, '', 0, 14, + 9, 1.25, 100, 100, 100), + (36, 10, 10, 541, 610, 163, 92, 76, 76, 76, 76, 163, 163, 76, 57, 57, 57, 57, 57, 57, 4, 25, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (36, 11, 11, 596, 680, 179, 101, 77, 77, 77, 77, 166, 166, 77, 61, 61, 61, 61, 61, 61, 4, 27, 1, -18, 30, '', 0, + 14, 10, 1.25, 100, 100, 100), + (36, 12, 12, 653, 751, 196, 111, 80, 80, 80, 80, 170, 170, 80, 64, 64, 64, 64, 64, 64, 5, 28, 1, -18, 30, '', 0, + 15, 10, 1.25, 100, 100, 100), + (36, 13, 13, 710, 824, 212, 120, 81, 81, 81, 81, 173, 173, 81, 66, 66, 66, 66, 66, 66, 5, 29, 1, -18, 30, '', 0, + 15, 10, 1.25, 100, 100, 100), + (36, 14, 14, 768, 899, 228, 129, 84, 84, 84, 84, 177, 177, 84, 70, 70, 70, 70, 70, 70, 5, 31, 1, -18, 30, '', 0, + 15, 10, 1.25, 100, 100, 100), + (36, 15, 15, 827, 975, 245, 138, 85, 85, 85, 85, 180, 180, 85, 72, 72, 72, 72, 72, 72, 5, 32, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (36, 16, 16, 887, 1053, 261, 148, 89, 89, 89, 89, 184, 184, 89, 75, 75, 75, 75, 75, 75, 6, 34, 1, -18, 30, '', 0, + 16, 11, 1.25, 100, 100, 100), + (36, 17, 17, 948, 1132, 277, 157, 90, 90, 90, 90, 187, 187, 90, 79, 79, 79, 79, 79, 79, 6, 35, 1, -18, 30, '', 0, + 16, 11, 1.25, 100, 100, 100), + (36, 18, 18, 1010, 1213, 294, 166, 94, 94, 94, 94, 191, 191, 94, 81, 81, 81, 81, 81, 81, 6, 36, 1, -18, 30, '', + 0, 16, 11, 1.25, 100, 100, 100), + (36, 19, 19, 1074, 1296, 310, 175, 95, 95, 95, 95, 194, 194, 95, 83, 83, 83, 83, 83, 83, 6, 38, 1, -18, 30, '', + 0, 16, 11, 1.25, 100, 100, 100), + (36, 20, 20, 1138, 1380, 326, 185, 100, 100, 100, 100, 198, 198, 100, 88, 88, 88, 88, 88, 88, 7, 39, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (36, 21, 21, 1204, 1466, 343, 194, 102, 102, 102, 102, 201, 201, 102, 90, 90, 90, 90, 90, 90, 7, 41, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (36, 22, 22, 1272, 1553, 359, 203, 106, 106, 106, 106, 205, 205, 106, 92, 92, 92, 92, 92, 92, 7, 42, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (36, 23, 23, 1341, 1642, 375, 212, 108, 108, 108, 108, 208, 208, 108, 96, 96, 96, 96, 96, 96, 7, 43, 1, -18, 30, + '', 0, 17, 12, 1.25, 100, 100, 100), + (36, 24, 24, 1411, 1733, 392, 222, 112, 112, 112, 112, 212, 212, 112, 99, 99, 99, 99, 99, 99, 8, 45, 1, -18, 30, + '', 0, 18, 12, 1.25, 100, 100, 100), + (36, 25, 25, 1483, 1825, 408, 231, 114, 114, 114, 114, 215, 215, 114, 101, 101, 101, 101, 101, 101, 8, 46, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (36, 26, 26, 1557, 1919, 424, 240, 118, 118, 118, 118, 219, 219, 118, 105, 105, 105, 105, 105, 105, 8, 48, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (36, 27, 27, 1632, 2014, 441, 249, 120, 120, 120, 120, 222, 222, 120, 107, 107, 107, 107, 107, 107, 8, 49, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (36, 28, 28, 1709, 2111, 457, 259, 125, 125, 125, 125, 226, 226, 125, 110, 110, 110, 110, 110, 110, 9, 50, 1, + -18, 30, '', 0, 19, 13, 1.25, 100, 100, 100), + (36, 29, 29, 1788, 2210, 473, 268, 127, 127, 127, 127, 229, 229, 127, 114, 114, 114, 114, 114, 114, 9, 52, 1, + -18, 30, '', 0, 19, 13, 1.25, 100, 100, 100), + (36, 30, 30, 1870, 2310, 490, 277, 133, 133, 133, 133, 233, 233, 133, 116, 116, 116, 116, 116, 116, 9, 53, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (36, 31, 31, 1953, 2412, 506, 286, 135, 135, 135, 135, 236, 236, 135, 118, 118, 118, 118, 118, 118, 9, 55, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (36, 32, 32, 2038, 2515, 522, 296, 140, 140, 140, 140, 240, 240, 140, 123, 123, 123, 123, 123, 123, 10, 56, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (36, 33, 33, 2125, 2620, 539, 305, 143, 143, 143, 143, 243, 243, 143, 125, 125, 125, 125, 125, 125, 10, 57, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (36, 34, 34, 2214, 2727, 555, 314, 148, 148, 148, 148, 247, 247, 148, 127, 127, 127, 127, 127, 127, 10, 59, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (36, 35, 35, 2306, 2835, 571, 323, 151, 151, 151, 151, 250, 250, 151, 131, 131, 131, 131, 131, 131, 10, 60, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (36, 36, 36, 2400, 2945, 588, 333, 156, 156, 156, 156, 254, 254, 156, 134, 134, 134, 134, 134, 134, 11, 62, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (36, 37, 37, 2496, 3056, 604, 342, 159, 159, 159, 159, 257, 257, 159, 136, 136, 136, 136, 136, 136, 11, 63, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (36, 38, 38, 2595, 3169, 620, 351, 164, 164, 164, 164, 261, 261, 164, 140, 140, 140, 140, 140, 140, 11, 64, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (36, 39, 39, 2697, 3284, 637, 360, 168, 168, 168, 168, 264, 264, 168, 142, 142, 142, 142, 142, 142, 11, 66, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (36, 40, 40, 2801, 3400, 653, 370, 174, 174, 174, 174, 268, 268, 174, 145, 145, 145, 145, 145, 145, 12, 67, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (36, 41, 41, 2907, 3518, 669, 379, 178, 178, 178, 178, 271, 271, 178, 149, 149, 149, 149, 149, 149, 12, 69, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (36, 42, 42, 3017, 3637, 686, 388, 183, 183, 183, 183, 275, 275, 183, 151, 151, 151, 151, 151, 151, 12, 70, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (36, 43, 43, 3129, 3758, 702, 397, 187, 187, 187, 187, 278, 278, 187, 153, 153, 153, 153, 153, 153, 12, 71, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (36, 44, 44, 3244, 3881, 718, 407, 193, 193, 193, 193, 282, 282, 193, 158, 158, 158, 158, 158, 158, 13, 73, 1, + -18, 30, '', 0, 23, 16, 1.25, 100, 100, 100), + (36, 45, 45, 3362, 4005, 735, 416, 197, 197, 197, 197, 285, 285, 197, 160, 160, 160, 160, 160, 160, 13, 74, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (36, 46, 46, 3483, 4131, 751, 425, 203, 203, 203, 203, 289, 289, 203, 162, 162, 162, 162, 162, 162, 13, 76, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (36, 47, 47, 3607, 4258, 767, 434, 207, 207, 207, 207, 292, 292, 207, 166, 166, 166, 166, 166, 166, 13, 77, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (36, 48, 48, 3734, 4387, 784, 444, 213, 213, 213, 213, 296, 296, 213, 169, 169, 169, 169, 169, 169, 14, 78, 1, + -18, 30, '', 0, 24, 17, 1.25, 100, 100, 100), + (36, 49, 49, 3865, 4518, 800, 453, 217, 217, 217, 217, 299, 299, 217, 171, 171, 171, 171, 171, 171, 14, 80, 1, + -18, 30, '', 0, 24, 17, 1.25, 100, 100, 100), + (36, 50, 50, 3998, 4650, 816, 462, 224, 224, 224, 224, 303, 303, 224, 175, 175, 175, 175, 175, 175, 14, 81, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (36, 51, 51, 4135, 4784, 833, 471, 229, 229, 229, 229, 306, 306, 229, 177, 177, 177, 177, 177, 177, 14, 83, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (36, 52, 52, 4276, 4919, 849, 481, 235, 235, 235, 235, 310, 310, 235, 180, 180, 180, 180, 180, 180, 15, 84, 1, + -18, 30, '', 0, 25, 18, 1.55, 100, 100, 100), + (36, 53, 53, 4420, 5056, 865, 490, 240, 240, 240, 240, 313, 313, 240, 184, 184, 184, 184, 184, 184, 15, 85, 1, + -18, 30, '', 0, 25, 18, 1.55, 100, 100, 100), + (36, 54, 54, 4567, 5195, 882, 499, 246, 246, 246, 246, 317, 317, 246, 186, 186, 186, 186, 186, 186, 15, 87, 1, + -18, 30, '', 0, 25, 18, 1.55, 100, 100, 100), + (36, 55, 55, 4718, 5335, 898, 508, 251, 251, 251, 251, 320, 320, 251, 188, 188, 188, 188, 188, 188, 15, 88, 1, + -18, 30, '', 0, 25, 19, 1.55, 100, 100, 100), + (36, 56, 56, 4873, 5477, 914, 518, 258, 258, 258, 258, 324, 324, 258, 193, 193, 193, 193, 193, 193, 16, 90, 1, + -18, 30, '', 0, 26, 19, 1.55, 100, 100, 100), + (36, 57, 57, 5031, 5620, 931, 527, 263, 263, 263, 263, 327, 327, 263, 195, 195, 195, 195, 195, 195, 16, 91, 1, + -18, 30, '', 0, 26, 19, 1.55, 100, 100, 100), + (36, 58, 58, 5193, 5765, 947, 536, 270, 270, 270, 270, 331, 331, 270, 197, 197, 197, 197, 197, 197, 16, 92, 1, + -18, 30, '', 0, 26, 19, 1.55, 100, 100, 100), + (36, 59, 59, 5359, 5912, 963, 545, 275, 275, 275, 275, 334, 334, 275, 201, 201, 201, 201, 201, 201, 16, 94, 1, + -18, 30, '', 0, 26, 19, 1.55, 100, 100, 100), + (36, 60, 60, 5530, 6060, 980, 555, 283, 283, 283, 283, 338, 338, 283, 204, 204, 204, 204, 204, 204, 17, 95, 1, + -18, 30, '', 0, 27, 20, 1.55, 100, 100, 100), + (36, 61, 61, 5704, 6210, 996, 564, 288, 288, 288, 288, 341, 341, 288, 206, 206, 206, 206, 206, 206, 17, 97, 1, + -18, 30, '', 0, 27, 20, 1.55, 100, 100, 100), + (36, 62, 62, 5882, 6361, 1012, 573, 296, 296, 296, 296, 345, 345, 296, 210, 210, 210, 210, 210, 210, 17, 98, 1, + -18, 30, '', 0, 27, 20, 1.55, 100, 100, 100), + (36, 63, 63, 6064, 6514, 1029, 582, 301, 301, 301, 301, 348, 348, 301, 212, 212, 212, 212, 212, 212, 17, 99, 1, + -18, 30, '', 0, 27, 20, 1.55, 100, 100, 100), + (36, 64, 64, 6250, 6669, 1045, 592, 309, 309, 309, 309, 352, 352, 309, 215, 215, 215, 215, 215, 215, 18, 101, 1, + -18, 30, '', 0, 28, 20, 1.55, 100, 100, 100), + (36, 65, 65, 6441, 6825, 1061, 601, 314, 314, 314, 314, 355, 355, 314, 219, 219, 219, 219, 219, 219, 18, 102, 1, + -18, 30, '', 0, 28, 21, 1.55, 100, 100, 100), + (36, 66, 66, 6636, 6983, 1078, 610, 352, 352, 352, 352, 389, 389, 352, 221, 221, 221, 221, 221, 221, 18, 104, 1, + -18, 30, '', 0, 28, 21, 1.55, 100, 100, 100), + (36, 67, 67, 6835, 7142, 1094, 619, 363, 363, 363, 363, 397, 397, 363, 223, 223, 223, 223, 223, 223, 18, 105, 1, + -18, 30, '', 0, 28, 21, 1.55, 100, 100, 100), + (36, 68, 68, 7039, 7303, 1110, 629, 376, 376, 376, 376, 406, 406, 376, 228, 228, 228, 228, 228, 228, 19, 106, 1, + -18, 30, '', 0, 29, 21, 1.55, 100, 100, 100), + (36, 69, 69, 7248, 7466, 1127, 638, 387, 387, 387, 387, 414, 414, 387, 230, 230, 230, 230, 230, 230, 19, 108, 1, + -18, 30, '', 0, 29, 21, 1.55, 100, 100, 100), + (36, 70, 70, 7461, 7630, 1143, 647, 401, 401, 401, 401, 423, 423, 401, 232, 232, 232, 232, 232, 232, 19, 109, 1, + -18, 30, '', 0, 29, 22, 1.55, 100, 100, 100), + (36, 71, 71, 7678, 7796, 1159, 656, 412, 412, 412, 412, 431, 431, 412, 236, 236, 236, 236, 236, 236, 19, 111, 1, + -18, 30, '', 0, 29, 22, 1.55, 100, 100, 100), + (36, 72, 72, 7901, 7963, 1176, 666, 425, 425, 425, 425, 440, 440, 425, 239, 239, 239, 239, 239, 239, 20, 112, 1, + -18, 30, '', 0, 30, 22, 1.55, 100, 100, 100), + (36, 73, 73, 8128, 8132, 1192, 675, 436, 436, 436, 436, 448, 448, 436, 241, 241, 241, 241, 241, 241, 20, 113, 1, + -18, 30, '', 0, 30, 22, 1.55, 100, 100, 100), + (36, 74, 74, 8360, 8303, 1208, 684, 450, 450, 450, 450, 457, 457, 450, 245, 245, 245, 245, 245, 245, 20, 115, 1, + -18, 30, '', 0, 30, 22, 1.55, 100, 100, 100), + (36, 75, 75, 8597, 8475, 1225, 693, 461, 461, 461, 461, 465, 465, 461, 247, 247, 247, 247, 247, 247, 20, 116, 1, + -18, 30, '', 0, 30, 23, 1.55, 100, 100, 100), + (36, 76, 76, 8839, 8649, 1241, 703, 475, 475, 475, 475, 474, 474, 475, 250, 250, 250, 250, 250, 250, 21, 118, 1, + -18, 30, '', 0, 31, 23, 1.55, 100, 100, 100), + (36, 77, 77, 9086, 8824, 1257, 712, 486, 486, 486, 486, 482, 482, 486, 254, 254, 254, 254, 254, 254, 21, 119, 1, + -18, 30, '', 0, 31, 23, 1.55, 100, 100, 100), + (36, 78, 78, 9338, 9001, 1274, 721, 500, 500, 500, 500, 491, 491, 500, 256, 256, 256, 256, 256, 256, 21, 120, 1, + -18, 30, '', 0, 31, 23, 1.55, 100, 100, 100), + (36, 79, 79, 9596, 9180, 1290, 730, 512, 512, 512, 512, 499, 499, 512, 258, 258, 258, 258, 258, 258, 21, 122, 1, + -18, 30, '', 0, 31, 23, 1.55, 100, 100, 100), + (36, 80, 80, 9858, 9360, 1306, 740, 527, 527, 527, 527, 508, 508, 527, 263, 263, 263, 263, 263, 263, 22, 123, 1, + -18, 30, '', 0, 32, 24, 1.55, 100, 100, 100), + (36, 81, 81, 10126, 9542, 1323, 749, 539, 539, 539, 539, 516, 516, 539, 265, 265, 265, 265, 265, 265, 22, 125, 1, + -18, 30, '', 0, 32, 24, 1.55, 100, 100, 100), + (36, 82, 82, 10400, 9725, 1339, 758, 553, 553, 553, 553, 525, 525, 553, 267, 267, 267, 267, 267, 267, 22, 126, 1, + -18, 30, '', 0, 32, 24, 1.55, 100, 100, 100), + (36, 83, 83, 10679, 9910, 1355, 767, 565, 565, 565, 565, 533, 533, 565, 271, 271, 271, 271, 271, 271, 22, 127, 1, + -18, 30, '', 0, 32, 24, 1.55, 100, 100, 100), + (36, 84, 84, 10963, 10097, 1372, 777, 579, 579, 579, 579, 542, 542, 579, 274, 274, 274, 274, 274, 274, 23, 129, + 1, -18, 30, '', 0, 33, 24, 1.55, 100, 100, 100), + (36, 85, 85, 11253, 10285, 1388, 786, 592, 592, 592, 592, 550, 550, 592, 276, 276, 276, 276, 276, 276, 23, 130, + 1, -18, 30, '', 0, 33, 25, 1.55, 100, 100, 100), + (37, 1, 1, 64, 57, 16, 9, 62, 62, 62, 62, 134, 134, 62, 34, 34, 34, 34, 34, 34, 2, 14, 1, -18, 30, '', 0, 13, 9, + 1.25, 100, 100, 100), + (37, 2, 2, 118, 115, 33, 19, 64, 64, 64, 64, 138, 138, 64, 38, 38, 38, 38, 38, 38, 2, 15, 1, -18, 30, '', 0, 13, + 9, 1.25, 100, 100, 100), + (37, 3, 3, 172, 175, 50, 28, 64, 64, 64, 64, 141, 141, 64, 40, 40, 40, 40, 40, 40, 3, 17, 1, -18, 30, '', 0, 13, + 9, 1.25, 100, 100, 100), + (37, 4, 4, 226, 237, 66, 38, 66, 66, 66, 66, 145, 145, 66, 44, 44, 44, 44, 44, 44, 3, 18, 1, -18, 30, '', 0, 14, + 9, 1.25, 100, 100, 100), + (37, 5, 5, 281, 300, 83, 47, 67, 67, 67, 67, 148, 148, 67, 48, 48, 48, 48, 48, 48, 3, 20, 1, -18, 30, '', 0, 14, + 10, 1.25, 100, 100, 100), + (37, 6, 6, 336, 365, 100, 57, 69, 69, 69, 69, 152, 152, 69, 50, 50, 50, 50, 50, 50, 3, 21, 1, -18, 30, '', 0, 14, + 10, 1.25, 100, 100, 100), + (37, 7, 7, 391, 431, 116, 66, 70, 70, 70, 70, 155, 155, 70, 52, 52, 52, 52, 52, 52, 4, 22, 1, -18, 30, '', 0, 14, + 10, 1.25, 100, 100, 100), + (37, 8, 8, 447, 499, 133, 76, 72, 72, 72, 72, 159, 159, 72, 58, 58, 58, 58, 58, 58, 4, 24, 1, -18, 30, '', 0, 15, + 10, 1.25, 100, 100, 100), + (37, 9, 9, 504, 569, 150, 85, 73, 73, 73, 73, 162, 162, 73, 60, 60, 60, 60, 60, 60, 4, 25, 1, -18, 30, '', 0, 15, + 10, 1.25, 100, 100, 100), + (37, 10, 10, 561, 640, 166, 95, 78, 78, 78, 78, 166, 166, 78, 62, 62, 62, 62, 62, 62, 4, 27, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (37, 11, 11, 618, 713, 183, 104, 79, 79, 79, 79, 169, 169, 79, 66, 66, 66, 66, 66, 66, 5, 28, 1, -18, 30, '', 0, + 15, 11, 1.25, 100, 100, 100), + (37, 12, 12, 677, 787, 200, 114, 82, 82, 82, 82, 173, 173, 82, 70, 70, 70, 70, 70, 70, 5, 29, 1, -18, 30, '', 0, + 16, 11, 1.25, 100, 100, 100), + (37, 13, 13, 736, 863, 216, 123, 83, 83, 83, 83, 176, 176, 83, 72, 72, 72, 72, 72, 72, 5, 31, 1, -18, 30, '', 0, + 16, 11, 1.25, 100, 100, 100), + (37, 14, 14, 796, 941, 233, 133, 86, 86, 86, 86, 180, 180, 86, 76, 76, 76, 76, 76, 76, 5, 32, 1, -18, 30, '', 0, + 16, 11, 1.25, 100, 100, 100), + (37, 15, 15, 857, 1020, 250, 142, 87, 87, 87, 87, 183, 183, 87, 78, 78, 78, 78, 78, 78, 6, 34, 1, -18, 30, '', 0, + 16, 12, 1.25, 100, 100, 100), + (37, 16, 16, 919, 1101, 266, 152, 91, 91, 91, 91, 187, 187, 91, 82, 82, 82, 82, 82, 82, 6, 35, 1, -18, 30, '', 0, + 17, 12, 1.25, 100, 100, 100), + (37, 17, 17, 982, 1183, 283, 161, 92, 92, 92, 92, 190, 190, 92, 86, 86, 86, 86, 86, 86, 6, 36, 1, -18, 30, '', 0, + 17, 12, 1.25, 100, 100, 100), + (37, 18, 18, 1046, 1267, 300, 171, 96, 96, 96, 96, 194, 194, 96, 88, 88, 88, 88, 88, 88, 6, 38, 1, -18, 30, '', + 0, 17, 12, 1.25, 100, 100, 100), + (37, 19, 19, 1112, 1353, 316, 180, 97, 97, 97, 97, 197, 197, 97, 90, 90, 90, 90, 90, 90, 7, 39, 1, -18, 30, '', + 0, 17, 12, 1.25, 100, 100, 100), + (37, 20, 20, 1178, 1440, 333, 190, 103, 103, 103, 103, 201, 201, 103, 96, 96, 96, 96, 96, 96, 7, 41, 1, -18, 30, + '', 0, 18, 13, 1.25, 100, 100, 100), + (37, 21, 21, 1246, 1529, 350, 199, 105, 105, 105, 105, 204, 204, 105, 98, 98, 98, 98, 98, 98, 7, 42, 1, -18, 30, + '', 0, 18, 13, 1.25, 100, 100, 100), + (37, 22, 22, 1316, 1619, 366, 209, 109, 109, 109, 109, 208, 208, 109, 100, 100, 100, 100, 100, 100, 7, 43, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (37, 23, 23, 1387, 1711, 383, 218, 111, 111, 111, 111, 211, 211, 111, 104, 104, 104, 104, 104, 104, 8, 45, 1, + -18, 30, '', 0, 18, 13, 1.25, 100, 100, 100), + (37, 24, 24, 1459, 1805, 400, 228, 115, 115, 115, 115, 215, 215, 115, 108, 108, 108, 108, 108, 108, 8, 46, 1, + -18, 30, '', 0, 19, 13, 1.25, 100, 100, 100), + (37, 25, 25, 1533, 1900, 416, 237, 117, 117, 117, 117, 218, 218, 117, 110, 110, 110, 110, 110, 110, 8, 48, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (37, 26, 26, 1609, 1997, 433, 247, 121, 121, 121, 121, 222, 222, 121, 114, 114, 114, 114, 114, 114, 8, 49, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (37, 27, 27, 1686, 2095, 450, 256, 123, 123, 123, 123, 225, 225, 123, 116, 116, 116, 116, 116, 116, 9, 50, 1, + -18, 30, '', 0, 19, 14, 1.25, 100, 100, 100), + (37, 28, 28, 1765, 2195, 466, 266, 128, 128, 128, 128, 229, 229, 128, 120, 120, 120, 120, 120, 120, 9, 52, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (37, 29, 29, 1846, 2297, 483, 275, 130, 130, 130, 130, 232, 232, 130, 124, 124, 124, 124, 124, 124, 9, 53, 1, + -18, 30, '', 0, 20, 14, 1.25, 100, 100, 100), + (37, 30, 30, 1930, 2400, 500, 285, 137, 137, 137, 137, 236, 236, 137, 126, 126, 126, 126, 126, 126, 9, 55, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (37, 31, 31, 2015, 2505, 516, 294, 139, 139, 139, 139, 239, 239, 139, 128, 128, 128, 128, 128, 128, 10, 56, 1, + -18, 30, '', 0, 20, 15, 1.25, 100, 100, 100), + (37, 32, 32, 2102, 2611, 533, 304, 144, 144, 144, 144, 243, 243, 144, 134, 134, 134, 134, 134, 134, 10, 57, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (37, 33, 33, 2191, 2719, 550, 313, 147, 147, 147, 147, 246, 246, 147, 136, 136, 136, 136, 136, 136, 10, 59, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (37, 34, 34, 2282, 2829, 566, 323, 152, 152, 152, 152, 250, 250, 152, 138, 138, 138, 138, 138, 138, 10, 60, 1, + -18, 30, '', 0, 21, 15, 1.25, 100, 100, 100), + (37, 35, 35, 2376, 2940, 583, 332, 155, 155, 155, 155, 253, 253, 155, 142, 142, 142, 142, 142, 142, 11, 62, 1, + -18, 30, '', 0, 21, 16, 1.25, 100, 100, 100), + (37, 36, 36, 2472, 3053, 600, 342, 160, 160, 160, 160, 257, 257, 160, 146, 146, 146, 146, 146, 146, 11, 63, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (37, 37, 37, 2570, 3167, 616, 351, 163, 163, 163, 163, 260, 260, 163, 148, 148, 148, 148, 148, 148, 11, 64, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (37, 38, 38, 2671, 3283, 633, 361, 168, 168, 168, 168, 264, 264, 168, 152, 152, 152, 152, 152, 152, 11, 66, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (37, 39, 39, 2775, 3401, 650, 370, 172, 172, 172, 172, 267, 267, 172, 154, 154, 154, 154, 154, 154, 12, 67, 1, + -18, 30, '', 0, 22, 16, 1.25, 100, 100, 100), + (37, 40, 40, 2881, 3520, 666, 380, 179, 179, 179, 179, 271, 271, 179, 158, 158, 158, 158, 158, 158, 12, 69, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (37, 41, 41, 2989, 3641, 683, 389, 183, 183, 183, 183, 274, 274, 183, 162, 162, 162, 162, 162, 162, 12, 70, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (37, 42, 42, 3101, 3763, 700, 399, 188, 188, 188, 188, 278, 278, 188, 164, 164, 164, 164, 164, 164, 12, 71, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (37, 43, 43, 3215, 3887, 716, 408, 192, 192, 192, 192, 281, 281, 192, 166, 166, 166, 166, 166, 166, 13, 73, 1, + -18, 30, '', 0, 23, 17, 1.25, 100, 100, 100), + (37, 44, 44, 3332, 4013, 733, 418, 198, 198, 198, 198, 285, 285, 198, 172, 172, 172, 172, 172, 172, 13, 74, 1, + -18, 30, '', 0, 24, 17, 1.25, 100, 100, 100), + (37, 45, 45, 3452, 4140, 750, 427, 202, 202, 202, 202, 288, 288, 202, 174, 174, 174, 174, 174, 174, 13, 76, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (37, 46, 46, 3575, 4269, 766, 437, 208, 208, 208, 208, 292, 292, 208, 176, 176, 176, 176, 176, 176, 13, 77, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (37, 47, 47, 3701, 4399, 783, 446, 212, 212, 212, 212, 295, 295, 212, 180, 180, 180, 180, 180, 180, 14, 78, 1, + -18, 30, '', 0, 24, 18, 1.25, 100, 100, 100), + (37, 48, 48, 3830, 4531, 800, 456, 218, 218, 218, 218, 299, 299, 218, 184, 184, 184, 184, 184, 184, 14, 80, 1, + -18, 30, '', 0, 25, 18, 1.25, 100, 100, 100), + (37, 49, 49, 3963, 4665, 816, 465, 222, 222, 222, 222, 302, 302, 222, 186, 186, 186, 186, 186, 186, 14, 81, 1, + -18, 30, '', 0, 25, 18, 1.25, 100, 100, 100), + (37, 50, 50, 4098, 4800, 833, 475, 230, 230, 230, 230, 306, 306, 230, 190, 190, 190, 190, 190, 190, 14, 83, 1, + -18, 30, '', 0, 25, 19, 1.25, 100, 100, 100), + (37, 51, 51, 4237, 4937, 850, 484, 235, 235, 235, 235, 309, 309, 235, 192, 192, 192, 192, 192, 192, 15, 84, 1, + -18, 30, '', 0, 25, 19, 1.25, 100, 100, 100), + (37, 52, 52, 4380, 5075, 866, 494, 241, 241, 241, 241, 313, 313, 241, 196, 196, 196, 196, 196, 196, 15, 85, 1, + -18, 30, '', 0, 26, 19, 1.61, 100, 100, 100), + (37, 53, 53, 4526, 5215, 883, 503, 246, 246, 246, 246, 316, 316, 246, 200, 200, 200, 200, 200, 200, 15, 87, 1, + -18, 30, '', 0, 26, 19, 1.61, 100, 100, 100), + (37, 54, 54, 4675, 5357, 900, 513, 252, 252, 252, 252, 320, 320, 252, 202, 202, 202, 202, 202, 202, 15, 88, 1, + -18, 30, '', 0, 26, 19, 1.61, 100, 100, 100), + (37, 55, 55, 4828, 5500, 916, 522, 257, 257, 257, 257, 323, 323, 257, 204, 204, 204, 204, 204, 204, 16, 90, 1, + -18, 30, '', 0, 26, 20, 1.61, 100, 100, 100), + (37, 56, 56, 4985, 5645, 933, 532, 264, 264, 264, 264, 327, 327, 264, 210, 210, 210, 210, 210, 210, 16, 91, 1, + -18, 30, '', 0, 27, 20, 1.61, 100, 100, 100), + (37, 57, 57, 5145, 5791, 950, 541, 269, 269, 269, 269, 330, 330, 269, 212, 212, 212, 212, 212, 212, 16, 92, 1, + -18, 30, '', 0, 27, 20, 1.61, 100, 100, 100), + (37, 58, 58, 5309, 5939, 966, 551, 276, 276, 276, 276, 334, 334, 276, 214, 214, 214, 214, 214, 214, 16, 94, 1, + -18, 30, '', 0, 27, 20, 1.61, 100, 100, 100), + (37, 59, 59, 5477, 6089, 983, 560, 281, 281, 281, 281, 337, 337, 281, 218, 218, 218, 218, 218, 218, 17, 95, 1, + -18, 30, '', 0, 27, 20, 1.61, 100, 100, 100), + (37, 60, 60, 5650, 6240, 1000, 570, 290, 290, 290, 290, 341, 341, 290, 222, 222, 222, 222, 222, 222, 17, 97, 1, + -18, 30, '', 0, 28, 21, 1.61, 100, 100, 100), + (37, 61, 61, 5826, 6393, 1016, 579, 295, 295, 295, 295, 344, 344, 295, 224, 224, 224, 224, 224, 224, 17, 98, 1, + -18, 30, '', 0, 28, 21, 1.61, 100, 100, 100), + (37, 62, 62, 6006, 6547, 1033, 589, 303, 303, 303, 303, 348, 348, 303, 228, 228, 228, 228, 228, 228, 17, 99, 1, + -18, 30, '', 0, 28, 21, 1.61, 100, 100, 100), + (37, 63, 63, 6190, 6703, 1050, 598, 308, 308, 308, 308, 351, 351, 308, 230, 230, 230, 230, 230, 230, 18, 101, 1, + -18, 30, '', 0, 28, 21, 1.61, 100, 100, 100), + (37, 64, 64, 6378, 6861, 1066, 608, 316, 316, 316, 316, 355, 355, 316, 234, 234, 234, 234, 234, 234, 18, 102, 1, + -18, 30, '', 0, 29, 21, 1.61, 100, 100, 100), + (37, 65, 65, 6571, 7020, 1083, 617, 321, 321, 321, 321, 358, 358, 321, 238, 238, 238, 238, 238, 238, 18, 104, 1, + -18, 30, '', 0, 29, 22, 1.61, 100, 100, 100), + (37, 66, 66, 6768, 7181, 1100, 627, 359, 359, 359, 359, 392, 392, 359, 240, 240, 240, 240, 240, 240, 18, 105, 1, + -18, 30, '', 0, 29, 22, 1.61, 100, 100, 100), + (37, 67, 67, 6969, 7343, 1116, 636, 370, 370, 370, 370, 400, 400, 370, 242, 242, 242, 242, 242, 242, 19, 106, 1, + -18, 30, '', 0, 29, 22, 1.61, 100, 100, 100), + (37, 68, 68, 7175, 7507, 1133, 646, 383, 383, 383, 383, 409, 409, 383, 248, 248, 248, 248, 248, 248, 19, 108, 1, + -18, 30, '', 0, 30, 22, 1.61, 100, 100, 100), + (37, 69, 69, 7386, 7673, 1150, 655, 394, 394, 394, 394, 417, 417, 394, 250, 250, 250, 250, 250, 250, 19, 109, 1, + -18, 30, '', 0, 30, 22, 1.61, 100, 100, 100), + (37, 70, 70, 7601, 7840, 1166, 665, 409, 409, 409, 409, 426, 426, 409, 252, 252, 252, 252, 252, 252, 19, 111, 1, + -18, 30, '', 0, 30, 23, 1.61, 100, 100, 100), + (37, 71, 71, 7820, 8009, 1183, 674, 420, 420, 420, 420, 434, 434, 420, 256, 256, 256, 256, 256, 256, 20, 112, 1, + -18, 30, '', 0, 30, 23, 1.61, 100, 100, 100), + (37, 72, 72, 8045, 8179, 1200, 684, 433, 433, 433, 433, 443, 443, 433, 260, 260, 260, 260, 260, 260, 20, 113, 1, + -18, 30, '', 0, 31, 23, 1.61, 100, 100, 100), + (37, 73, 73, 8274, 8351, 1216, 693, 444, 444, 444, 444, 451, 451, 444, 262, 262, 262, 262, 262, 262, 20, 115, 1, + -18, 30, '', 0, 31, 23, 1.61, 100, 100, 100), + (37, 74, 74, 8508, 8525, 1233, 703, 458, 458, 458, 458, 460, 460, 458, 266, 266, 266, 266, 266, 266, 20, 116, 1, + -18, 30, '', 0, 31, 23, 1.61, 100, 100, 100), + (37, 75, 75, 8747, 8700, 1250, 712, 469, 469, 469, 469, 468, 468, 469, 268, 268, 268, 268, 268, 268, 21, 118, 1, + -18, 30, '', 0, 31, 24, 1.61, 100, 100, 100), + (37, 76, 76, 8991, 8877, 1266, 722, 483, 483, 483, 483, 477, 477, 483, 272, 272, 272, 272, 272, 272, 21, 119, 1, + -18, 30, '', 0, 32, 24, 1.61, 100, 100, 100), + (37, 77, 77, 9240, 9055, 1283, 731, 494, 494, 494, 494, 485, 485, 494, 276, 276, 276, 276, 276, 276, 21, 120, 1, + -18, 30, '', 0, 32, 24, 1.61, 100, 100, 100), + (37, 78, 78, 9494, 9235, 1300, 741, 508, 508, 508, 508, 494, 494, 508, 278, 278, 278, 278, 278, 278, 21, 122, 1, + -18, 30, '', 0, 32, 24, 1.61, 100, 100, 100), + (37, 79, 79, 9754, 9417, 1316, 750, 520, 520, 520, 520, 502, 502, 520, 280, 280, 280, 280, 280, 280, 22, 123, 1, + -18, 30, '', 0, 32, 24, 1.61, 100, 100, 100), + (37, 80, 80, 10018, 9600, 1333, 760, 536, 536, 536, 536, 511, 511, 536, 286, 286, 286, 286, 286, 286, 22, 125, 1, + -18, 30, '', 0, 33, 25, 1.61, 100, 100, 100), + (37, 81, 81, 10288, 9785, 1350, 769, 548, 548, 548, 548, 519, 519, 548, 288, 288, 288, 288, 288, 288, 22, 126, 1, + -18, 30, '', 0, 33, 25, 1.61, 100, 100, 100), + (37, 82, 82, 10564, 9971, 1366, 779, 562, 562, 562, 562, 528, 528, 562, 290, 290, 290, 290, 290, 290, 22, 127, 1, + -18, 30, '', 0, 33, 25, 1.61, 100, 100, 100), + (37, 83, 83, 10845, 10159, 1383, 788, 574, 574, 574, 574, 536, 536, 574, 294, 294, 294, 294, 294, 294, 23, 129, + 1, -18, 30, '', 0, 33, 25, 1.61, 100, 100, 100), + (37, 84, 84, 11131, 10349, 1400, 798, 588, 588, 588, 588, 545, 545, 588, 298, 298, 298, 298, 298, 298, 23, 130, + 1, -18, 30, '', 0, 34, 25, 1.61, 100, 100, 100), + (37, 85, 85, 11423, 10540, 1416, 807, 601, 601, 601, 601, 553, 553, 601, 300, 300, 300, 300, 300, 300, 23, 132, + 1, -18, 30, '', 0, 34, 26, 1.61, 100, 100, 100); + +-- ---------------------------- +-- Table structure for merc_subtypes +-- ---------------------------- +DROP TABLE IF EXISTS `merc_subtypes`; +CREATE TABLE `merc_subtypes` +( + `merc_subtype_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `class_id` int(10) UNSIGNED NOT NULL, + `tier_id` tinyint(3) UNSIGNED NOT NULL, + `confidence_id` tinyint(3) UNSIGNED NOT NULL, + PRIMARY KEY (`merc_subtype_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_subtypes +-- ---------------------------- +INSERT INTO `merc_subtypes` +VALUES (1, 1, 1, 1), + (2, 1, 2, 2), + (3, 1, 3, 2), + (4, 1, 4, 2), + (5, 1, 5, 3), + (6, 2, 1, 1), + (7, 2, 2, 2), + (8, 2, 3, 2), + (9, 2, 4, 2), + (10, 2, 5, 3), + (11, 9, 1, 1), + (12, 9, 2, 2), + (13, 9, 3, 2), + (14, 9, 4, 2), + (15, 9, 5, 3), + (16, 12, 1, 1), + (17, 12, 2, 2), + (18, 12, 3, 2), + (19, 12, 4, 2), + (20, 12, 5, 3); + +-- ---------------------------- +-- Table structure for merc_templates +-- ---------------------------- +DROP TABLE IF EXISTS `merc_templates`; +CREATE TABLE `merc_templates` +( + `merc_template_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `merc_type_id` int(10) UNSIGNED NOT NULL, + `merc_subtype_id` int(10) UNSIGNED NOT NULL, + `merc_npc_type_id` int(11) UNSIGNED NOT NULL, + `dbstring` varchar(12) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, + `name_type_id` tinyint(4) NOT NULL DEFAULT 0, + `clientversion` int(10) UNSIGNED NOT NULL, + PRIMARY KEY (`merc_template_id`) USING BTREE, + INDEX `FK_merc_templates_1`(`merc_type_id`) USING BTREE, + INDEX `FK_merc_templates_2`(`merc_subtype_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 554 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_templates +-- ---------------------------- +INSERT INTO `merc_templates` +VALUES (1, 1, 1, 1, '1010101', 0, 4), + (2, 1, 2, 2, '1010102', 0, 4), + (3, 1, 3, 3, '1010103', 0, 4), + (4, 1, 4, 4, '1010104', 0, 4), + (5, 1, 5, 5, '1010105', 0, 4), + (6, 1, 6, 11, '1020101', 0, 4), + (7, 1, 7, 12, '1020102', 0, 4), + (8, 1, 8, 13, '1020103', 0, 4), + (9, 1, 9, 14, '1020104', 0, 4), + (10, 1, 10, 15, '1020105', 0, 4), + (11, 1, 11, 21, '1040101', 0, 5), + (12, 1, 12, 22, '1040102', 0, 5), + (13, 1, 13, 23, '1040103', 0, 5), + (14, 1, 14, 24, '1040104', 0, 5), + (15, 1, 15, 25, '1040105', 0, 5), + (16, 1, 16, 31, '1120101', 0, 5), + (17, 1, 17, 32, '1120102', 0, 5), + (18, 1, 18, 33, '1120103', 0, 5), + (19, 1, 19, 34, '1120104', 0, 5), + (20, 1, 20, 35, '1120105', 0, 5), + (21, 2, 1, 6, '1010201', 0, 4), + (22, 2, 2, 7, '1010202', 0, 4), + (23, 2, 6, 16, '1020201', 0, 4), + (24, 2, 7, 17, '1020202', 0, 4), + (25, 2, 11, 26, '1040201', 0, 5), + (26, 2, 12, 27, '1040202', 0, 5), + (27, 2, 16, 36, '1120201', 0, 5), + (28, 2, 17, 37, '1120202', 0, 5), + (29, 3, 1, 1, '2010101', 0, 4), + (30, 3, 2, 2, '2010102', 0, 4), + (31, 3, 3, 3, '2010103', 0, 4), + (32, 3, 4, 4, '2010104', 0, 4), + (33, 3, 5, 5, '2010105', 0, 4), + (34, 3, 6, 11, '2020101', 0, 4), + (35, 3, 7, 12, '2020102', 0, 4), + (36, 3, 8, 13, '2020103', 0, 4), + (37, 3, 9, 14, '2020104', 0, 4), + (38, 3, 10, 15, '2020105', 0, 4), + (39, 3, 11, 21, '2040101', 0, 5), + (40, 3, 12, 22, '2040102', 0, 5), + (41, 3, 13, 23, '2040103', 0, 5), + (42, 3, 14, 24, '2040104', 0, 5), + (43, 3, 15, 25, '2040105', 0, 5), + (44, 3, 16, 31, '2120101', 0, 5), + (45, 3, 17, 32, '2120102', 0, 5), + (46, 3, 18, 33, '2120103', 0, 5), + (47, 3, 19, 34, '2120104', 0, 5), + (48, 3, 20, 35, '2120105', 0, 5), + (49, 4, 1, 6, '2010201', 0, 4), + (50, 4, 2, 7, '2010202', 0, 4), + (51, 4, 6, 16, '2020201', 0, 4), + (52, 4, 7, 17, '2020202', 0, 4), + (53, 4, 11, 26, '2040201', 0, 5), + (54, 4, 12, 27, '2040202', 0, 5), + (55, 4, 16, 36, '2120201', 0, 5), + (56, 4, 17, 37, '2120202', 0, 5), + (57, 5, 1, 1, '3010101', 0, 4), + (58, 5, 2, 2, '3010102', 0, 4), + (59, 5, 3, 3, '3010103', 0, 4), + (60, 5, 4, 4, '3010104', 0, 4), + (61, 5, 5, 5, '3010105', 0, 4), + (62, 5, 6, 11, '3020101', 0, 4), + (63, 5, 7, 12, '3020102', 0, 4), + (64, 5, 8, 13, '3020103', 0, 4), + (65, 5, 9, 14, '3020104', 0, 4), + (66, 5, 10, 15, '3020105', 0, 4), + (67, 5, 16, 31, '3120101', 0, 5), + (68, 5, 17, 32, '3120102', 0, 5), + (69, 5, 18, 33, '3120103', 0, 5), + (70, 5, 19, 34, '3120104', 0, 5), + (71, 5, 20, 35, '3120105', 0, 5), + (72, 6, 1, 6, '3010201', 0, 4), + (73, 6, 2, 7, '3010202', 0, 4), + (74, 6, 6, 16, '3020201', 0, 4), + (75, 6, 7, 17, '3020202', 0, 4), + (76, 6, 16, 36, '3120201', 0, 5), + (77, 6, 17, 37, '3120202', 0, 5), + (78, 7, 1, 1, '4010101', 0, 4), + (79, 7, 2, 2, '4010102', 0, 4), + (80, 7, 3, 3, '4010103', 0, 4), + (81, 7, 4, 4, '4010104', 0, 4), + (82, 7, 5, 5, '4010105', 0, 4), + (83, 7, 6, 11, '4020101', 0, 4), + (84, 7, 7, 12, '4020102', 0, 4), + (85, 7, 8, 13, '4020103', 0, 4), + (86, 7, 9, 14, '4020104', 0, 4), + (87, 7, 10, 15, '4020105', 0, 4), + (88, 7, 11, 21, '4040101', 0, 5), + (89, 7, 12, 22, '4040102', 0, 5), + (90, 7, 13, 23, '4040103', 0, 5), + (91, 7, 14, 24, '4040104', 0, 5), + (92, 7, 15, 25, '4040105', 0, 5), + (93, 7, 16, 31, '4120101', 0, 5), + (94, 7, 17, 32, '4120102', 0, 5), + (95, 7, 18, 33, '4120103', 0, 5), + (96, 7, 19, 34, '4120104', 0, 5), + (97, 7, 20, 35, '4120105', 0, 5), + (98, 8, 1, 6, '4010201', 0, 4), + (99, 8, 2, 7, '4010202', 0, 4), + (100, 8, 6, 16, '4020201', 0, 4), + (101, 8, 7, 17, '4020202', 0, 4), + (102, 8, 11, 26, '4040201', 0, 5), + (103, 8, 12, 27, '4040202', 0, 5), + (104, 8, 16, 36, '4120201', 0, 5), + (105, 8, 17, 37, '4120202', 0, 5), + (106, 9, 1, 1, '5010101', 0, 4), + (107, 9, 2, 2, '5010102', 0, 4), + (108, 9, 3, 3, '5010103', 0, 4), + (109, 9, 4, 4, '5010104', 0, 4), + (110, 9, 5, 5, '5010105', 0, 4), + (111, 9, 6, 11, '5020101', 0, 4), + (112, 9, 7, 12, '5020102', 0, 4), + (113, 9, 8, 13, '5020103', 0, 4), + (114, 9, 9, 14, '5020104', 0, 4), + (115, 9, 10, 15, '5020105', 0, 4), + (116, 9, 16, 31, '5120101', 0, 5), + (117, 9, 17, 32, '5120102', 0, 5), + (118, 9, 18, 33, '5120103', 0, 5), + (119, 9, 19, 34, '5120104', 0, 5), + (120, 9, 20, 35, '5120105', 0, 5), + (121, 10, 1, 6, '5010201', 0, 4), + (122, 10, 2, 7, '5010202', 0, 4), + (123, 10, 6, 16, '5020201', 0, 4), + (124, 10, 7, 17, '5020202', 0, 4), + (125, 10, 16, 36, '5120201', 0, 5), + (126, 10, 17, 37, '5120202', 0, 5), + (127, 11, 1, 1, '6010101', 0, 4), + (128, 11, 2, 2, '6010102', 0, 4), + (129, 11, 3, 3, '6010103', 0, 4), + (130, 11, 4, 4, '6010104', 0, 4), + (131, 11, 5, 5, '6010105', 0, 4), + (132, 11, 6, 11, '6020101', 0, 4), + (133, 11, 7, 12, '6020102', 0, 4), + (134, 11, 8, 13, '6020103', 0, 4), + (135, 11, 9, 14, '6020104', 0, 4), + (136, 11, 10, 15, '6020105', 0, 4), + (137, 11, 11, 21, '6040101', 0, 5), + (138, 11, 12, 22, '6040102', 0, 5), + (139, 11, 13, 23, '6040103', 0, 5), + (140, 11, 14, 24, '6040104', 0, 5), + (141, 11, 15, 25, '6040105', 0, 5), + (142, 11, 16, 31, '6120101', 0, 5), + (143, 11, 17, 32, '6120102', 0, 5), + (144, 11, 18, 33, '6120103', 0, 5), + (145, 11, 19, 34, '6120104', 0, 5), + (146, 11, 20, 35, '6120105', 0, 5), + (147, 12, 1, 6, '6010201', 0, 4), + (148, 12, 2, 7, '6010202', 0, 4), + (149, 12, 6, 16, '6020201', 0, 4), + (150, 12, 7, 17, '6020202', 0, 4), + (151, 12, 11, 26, '6040201', 0, 5), + (152, 12, 12, 27, '6040202', 0, 5), + (153, 12, 16, 36, '6120201', 0, 5), + (154, 12, 17, 37, '6120202', 0, 5), + (155, 13, 1, 1, '7010101', 0, 4), + (156, 13, 2, 2, '7010102', 0, 4), + (157, 13, 3, 3, '7010103', 0, 4), + (158, 13, 4, 4, '7010104', 0, 4), + (159, 13, 5, 5, '7010105', 0, 4), + (160, 13, 6, 11, '7020101', 0, 4), + (161, 13, 7, 12, '7020102', 0, 4), + (162, 13, 8, 13, '7020103', 0, 4), + (163, 13, 9, 14, '7020104', 0, 4), + (164, 13, 10, 15, '7020105', 0, 4), + (165, 13, 11, 21, '7040101', 0, 5), + (166, 13, 12, 22, '7040102', 0, 5), + (167, 13, 13, 23, '7040103', 0, 5), + (168, 13, 14, 24, '7040104', 0, 5), + (169, 13, 15, 25, '7040105', 0, 5), + (170, 13, 16, 31, '7120101', 0, 5), + (171, 13, 17, 32, '7120102', 0, 5), + (172, 13, 18, 33, '7120103', 0, 5), + (173, 13, 19, 34, '7120104', 0, 5), + (174, 13, 20, 35, '7120105', 0, 5), + (175, 14, 1, 6, '7010201', 0, 4), + (176, 14, 2, 7, '7010202', 0, 4), + (177, 14, 6, 16, '7020201', 0, 4), + (178, 14, 7, 17, '7020202', 0, 4), + (179, 14, 11, 26, '7040201', 0, 5), + (180, 14, 12, 27, '7040202', 0, 5), + (181, 14, 16, 36, '7120201', 0, 5), + (182, 14, 17, 37, '7120202', 0, 5), + (183, 15, 1, 1, '8010101', 0, 4), + (184, 15, 2, 2, '8010102', 0, 4), + (185, 15, 3, 3, '8010103', 0, 4), + (186, 15, 4, 4, '8010104', 0, 4), + (187, 15, 5, 5, '8010105', 0, 4), + (188, 15, 6, 11, '8020101', 0, 4), + (189, 15, 7, 12, '8020102', 0, 4), + (190, 15, 8, 13, '8020103', 0, 4), + (191, 15, 9, 14, '8020104', 0, 4), + (192, 15, 10, 15, '8020105', 0, 4), + (193, 15, 11, 21, '8040101', 0, 5), + (194, 15, 12, 22, '8040102', 0, 5), + (195, 15, 13, 23, '8040103', 0, 5), + (196, 15, 14, 24, '8040104', 0, 5), + (197, 15, 15, 25, '8040105', 0, 5), + (198, 15, 16, 31, '8120101', 0, 5), + (199, 15, 17, 32, '8120102', 0, 5), + (200, 15, 18, 33, '8120103', 0, 5), + (201, 15, 19, 34, '8120104', 0, 5), + (202, 15, 20, 35, '8120105', 0, 5), + (203, 16, 1, 6, '8010201', 0, 4), + (204, 16, 2, 7, '8010202', 0, 4), + (205, 16, 6, 16, '8020201', 0, 4), + (206, 16, 7, 17, '8020202', 0, 4), + (207, 16, 11, 26, '8040201', 0, 5), + (208, 16, 12, 27, '8040202', 0, 5), + (209, 16, 16, 36, '8120201', 0, 5), + (210, 16, 17, 37, '8120202', 0, 5), + (211, 17, 1, 1, '9010101', 0, 4), + (212, 17, 2, 2, '9010102', 0, 4), + (213, 17, 3, 3, '9010103', 0, 4), + (214, 17, 4, 4, '9010104', 0, 4), + (215, 17, 5, 5, '9010105', 0, 4), + (216, 17, 6, 11, '9020101', 0, 4), + (217, 17, 7, 12, '9020102', 0, 4), + (218, 17, 8, 13, '9020103', 0, 4), + (219, 17, 9, 14, '9020104', 0, 4), + (220, 17, 10, 15, '9020105', 0, 4), + (221, 17, 16, 31, '9120101', 0, 5), + (222, 17, 17, 32, '9120102', 0, 5), + (223, 17, 18, 33, '9120103', 0, 5), + (224, 17, 19, 34, '9120104', 0, 5), + (225, 17, 20, 35, '9120105', 0, 5), + (226, 18, 1, 6, '9010201', 0, 4), + (227, 18, 2, 7, '9010202', 0, 4), + (228, 18, 6, 16, '9020201', 0, 4), + (229, 18, 7, 17, '9020202', 0, 4), + (230, 18, 16, 36, '9120201', 0, 5), + (231, 18, 17, 37, '9120202', 0, 5), + (232, 19, 1, 1, '10010101', 0, 4), + (233, 19, 2, 2, '10010102', 0, 4), + (234, 19, 3, 3, '10010103', 0, 4), + (235, 19, 4, 4, '10010104', 0, 4), + (236, 19, 5, 5, '10010105', 0, 4), + (237, 19, 6, 11, '10020101', 0, 4), + (238, 19, 7, 12, '10020102', 0, 4), + (239, 19, 8, 13, '10020103', 0, 4), + (240, 19, 9, 14, '10020104', 0, 4), + (241, 19, 10, 15, '10020105', 0, 4), + (242, 19, 16, 31, '10120101', 0, 5), + (243, 19, 17, 32, '10120102', 0, 5), + (244, 19, 18, 33, '10120103', 0, 5), + (245, 19, 19, 34, '10120104', 0, 5), + (246, 19, 20, 35, '10120105', 0, 5), + (247, 20, 1, 6, '10010201', 0, 4), + (248, 20, 2, 7, '10010202', 0, 4), + (249, 20, 6, 16, '10020201', 0, 4), + (250, 20, 7, 17, '10020202', 0, 4), + (251, 20, 16, 36, '10120201', 0, 5), + (252, 20, 17, 37, '10120202', 0, 5), + (253, 21, 1, 1, '11010101', 0, 4), + (254, 21, 2, 2, '11010102', 0, 4), + (255, 21, 3, 3, '11010103', 0, 4), + (256, 21, 4, 4, '11010104', 0, 4), + (257, 21, 5, 5, '11010105', 0, 4), + (258, 21, 6, 11, '11020101', 0, 4), + (259, 21, 7, 12, '11020102', 0, 4), + (260, 21, 8, 13, '11020103', 0, 4), + (261, 21, 9, 14, '11020104', 0, 4), + (262, 21, 10, 15, '11020105', 0, 4), + (263, 21, 11, 21, '11040101', 0, 5), + (264, 21, 12, 22, '11040102', 0, 5), + (265, 21, 13, 23, '11040103', 0, 5), + (266, 21, 14, 24, '11040104', 0, 5), + (267, 21, 15, 25, '11040105', 0, 5), + (268, 21, 16, 31, '11120101', 0, 5), + (269, 21, 17, 32, '11120102', 0, 5), + (270, 21, 18, 33, '11120103', 0, 5), + (271, 21, 19, 34, '11120104', 0, 5), + (272, 21, 20, 35, '11120105', 0, 5), + (273, 22, 1, 6, '11010201', 0, 4), + (274, 22, 2, 7, '11010202', 0, 4), + (275, 22, 6, 16, '11020201', 0, 4), + (276, 22, 7, 17, '11020202', 0, 4), + (277, 22, 11, 26, '11040201', 0, 5), + (278, 22, 12, 27, '11040202', 0, 5), + (279, 22, 16, 36, '11120201', 0, 5), + (280, 22, 17, 37, '11120202', 0, 5), + (281, 23, 1, 1, '12010101', 0, 4), + (282, 23, 2, 2, '12010102', 0, 4), + (283, 23, 3, 3, '12010103', 0, 4), + (284, 23, 4, 4, '12010104', 0, 4), + (285, 23, 5, 5, '12010105', 0, 4), + (286, 23, 6, 11, '12020101', 0, 4), + (287, 23, 7, 12, '12020102', 0, 4), + (288, 23, 8, 13, '12020103', 0, 4), + (289, 23, 9, 14, '12020104', 0, 4), + (290, 23, 10, 15, '12020105', 0, 4), + (291, 23, 11, 21, '12040101', 0, 5), + (292, 23, 12, 22, '12040102', 0, 5), + (293, 23, 13, 23, '12040103', 0, 5), + (294, 23, 14, 24, '12040104', 0, 5), + (295, 23, 15, 25, '12040105', 0, 5), + (296, 23, 16, 31, '12120101', 0, 5), + (297, 23, 17, 32, '12120102', 0, 5), + (298, 23, 18, 33, '12120103', 0, 5), + (299, 23, 19, 34, '12120104', 0, 5), + (300, 23, 20, 35, '12120105', 0, 5), + (301, 24, 1, 6, '12010201', 0, 4), + (302, 24, 2, 7, '12010202', 0, 4), + (303, 24, 6, 16, '12020201', 0, 4), + (304, 24, 7, 17, '12020202', 0, 4), + (305, 24, 11, 26, '12040201', 0, 5), + (306, 24, 12, 27, '12040202', 0, 5), + (307, 24, 16, 36, '12120201', 0, 5), + (308, 24, 17, 37, '12120202', 0, 5), + (309, 35, 11, 21, '48040101', 1, 5), + (310, 35, 12, 22, '48040102', 1, 5), + (311, 35, 13, 23, '48040103', 1, 5), + (312, 35, 14, 24, '48040104', 1, 5), + (313, 35, 15, 25, '48040105', 1, 5), + (314, 36, 11, 26, '48040201', 1, 5), + (315, 36, 12, 27, '48040202', 1, 5), + (316, 37, 1, 1, '51010101', 1, 4), + (317, 37, 2, 2, '51010102', 1, 4), + (318, 37, 3, 3, '51010103', 1, 4), + (319, 37, 4, 4, '51010104', 1, 4), + (320, 37, 5, 5, '51010105', 1, 4), + (321, 37, 6, 11, '51020101', 1, 4), + (322, 37, 7, 12, '51020102', 1, 4), + (323, 37, 8, 13, '51020103', 1, 4), + (324, 37, 9, 14, '51020104', 1, 4), + (325, 37, 10, 15, '51020105', 1, 4), + (326, 37, 11, 21, '51040101', 1, 5), + (327, 37, 12, 22, '51040102', 1, 5), + (328, 37, 13, 23, '51040103', 1, 5), + (329, 37, 14, 24, '51040104', 1, 5), + (330, 37, 15, 25, '51040105', 1, 5), + (331, 37, 16, 31, '51120101', 1, 5), + (332, 37, 17, 32, '51120102', 1, 5), + (333, 37, 18, 33, '51120103', 1, 5), + (334, 37, 19, 34, '51120104', 1, 5), + (335, 37, 20, 35, '51120105', 1, 5), + (336, 38, 1, 6, '51010201', 1, 4), + (337, 38, 2, 7, '51010202', 1, 4), + (338, 38, 6, 16, '51020201', 1, 4), + (339, 38, 7, 17, '51020202', 1, 4), + (340, 38, 11, 26, '51040201', 1, 5), + (341, 38, 12, 27, '51040202', 1, 5), + (342, 38, 16, 36, '51120201', 1, 5), + (343, 38, 17, 37, '51120202', 1, 5), + (344, 25, 1, 1, '128010101', 0, 4), + (345, 25, 2, 2, '128010102', 0, 4), + (346, 25, 3, 3, '128010103', 0, 4), + (347, 25, 4, 4, '128010104', 0, 4), + (348, 25, 5, 5, '128010105', 0, 4), + (349, 25, 6, 11, '128020101', 0, 4), + (350, 25, 7, 12, '128020102', 0, 4), + (351, 25, 8, 13, '128020103', 0, 4), + (352, 25, 9, 14, '128020104', 0, 4), + (353, 25, 10, 15, '128020105', 0, 4), + (354, 25, 16, 31, '128120101', 0, 5), + (355, 25, 17, 32, '128120102', 0, 5), + (356, 25, 18, 33, '128120103', 0, 5), + (357, 25, 19, 34, '128120104', 0, 5), + (358, 25, 20, 35, '128120105', 0, 5), + (359, 26, 1, 6, '128010201', 0, 4), + (360, 26, 2, 7, '128010202', 0, 4), + (361, 26, 6, 16, '128020201', 0, 4), + (362, 26, 7, 17, '128020202', 0, 4), + (363, 26, 16, 36, '128120201', 0, 5), + (364, 26, 17, 37, '128120202', 0, 5), + (365, 27, 1, 1, '130010101', 0, 4), + (366, 27, 2, 2, '130010102', 0, 4), + (367, 27, 3, 3, '130010103', 0, 4), + (368, 27, 4, 4, '130010104', 0, 4), + (369, 27, 5, 5, '130010105', 0, 4), + (370, 27, 6, 11, '130020101', 0, 4), + (371, 27, 7, 12, '130020102', 0, 4), + (372, 27, 8, 13, '130020103', 0, 4), + (373, 27, 9, 14, '130020104', 0, 4), + (374, 27, 10, 15, '130020105', 0, 4), + (375, 27, 11, 21, '130040101', 0, 5), + (376, 27, 12, 22, '130040102', 0, 5), + (377, 27, 13, 23, '130040103', 0, 5), + (378, 27, 14, 24, '130040104', 0, 5), + (379, 27, 15, 25, '130040105', 0, 5), + (380, 27, 16, 31, '130120101', 0, 5), + (381, 27, 17, 32, '130120102', 0, 5), + (382, 27, 18, 33, '130120103', 0, 5), + (383, 27, 19, 34, '130120104', 0, 5), + (384, 27, 20, 35, '130120105', 0, 5), + (385, 28, 1, 6, '130010201', 0, 4), + (386, 28, 2, 7, '130010202', 0, 4), + (387, 28, 6, 16, '130020201', 0, 4), + (388, 28, 7, 17, '130020202', 0, 4), + (389, 28, 11, 26, '130040201', 0, 5), + (390, 28, 12, 27, '130040202', 0, 5), + (391, 28, 16, 36, '130120201', 0, 5), + (392, 28, 17, 37, '130120202', 0, 5), + (393, 29, 1, 1, '330010101', 0, 4), + (394, 29, 2, 2, '330010102', 0, 4), + (395, 29, 3, 3, '330010103', 0, 4), + (396, 29, 4, 4, '330010104', 0, 4), + (397, 29, 5, 5, '330010105', 0, 4), + (398, 29, 6, 11, '330020101', 0, 4), + (399, 29, 7, 12, '330020102', 0, 4), + (400, 29, 8, 13, '330020103', 0, 4), + (401, 29, 9, 14, '330020104', 0, 4), + (402, 29, 10, 15, '330020105', 0, 4), + (403, 29, 11, 21, '330040101', 0, 5), + (404, 29, 12, 22, '330040102', 0, 5), + (405, 29, 13, 23, '330040103', 0, 5), + (406, 29, 14, 24, '330040104', 0, 5), + (407, 29, 15, 25, '330040105', 0, 5), + (408, 29, 16, 31, '330120101', 0, 5), + (409, 29, 17, 32, '330120102', 0, 5), + (410, 29, 18, 33, '330120103', 0, 5), + (411, 29, 19, 34, '330120104', 0, 5), + (412, 29, 20, 35, '330120105', 0, 5), + (413, 30, 1, 6, '330010201', 0, 4), + (414, 30, 2, 7, '330010202', 0, 4), + (415, 30, 6, 16, '330020201', 0, 4), + (416, 30, 7, 17, '330020202', 0, 4), + (417, 30, 11, 26, '330040201', 0, 5), + (418, 30, 12, 27, '330040202', 0, 5), + (419, 30, 16, 36, '330120201', 0, 5), + (420, 30, 17, 37, '330120202', 0, 5), + (421, 41, 1, 1, '433010101', 1, 4), + (422, 41, 2, 2, '433010102', 1, 4), + (423, 41, 3, 3, '433010103', 1, 4), + (424, 41, 4, 4, '433010104', 1, 4), + (425, 41, 5, 5, '433010105', 1, 4), + (426, 41, 6, 11, '433020101', 1, 4), + (427, 41, 7, 12, '433020102', 1, 4), + (428, 41, 8, 13, '433020103', 1, 4), + (429, 41, 9, 14, '433020104', 1, 4), + (430, 41, 10, 15, '433020105', 1, 4), + (431, 41, 11, 21, '433040101', 1, 5), + (432, 41, 12, 22, '433040102', 1, 5), + (433, 41, 13, 23, '433040103', 1, 5), + (434, 41, 14, 24, '433040104', 1, 5), + (435, 41, 15, 25, '433040105', 1, 5), + (436, 41, 16, 31, '433120101', 1, 5), + (437, 41, 17, 32, '433120102', 1, 5), + (438, 41, 18, 33, '433120103', 1, 5), + (439, 41, 19, 34, '433120104', 1, 5), + (440, 41, 20, 35, '433120105', 1, 5), + (441, 42, 1, 6, '433010201', 1, 4), + (442, 42, 2, 7, '433010202', 1, 4), + (443, 42, 6, 16, '433020201', 1, 4), + (444, 42, 7, 17, '433020202', 1, 4), + (445, 42, 11, 26, '433040201', 1, 5), + (446, 42, 12, 27, '433040202', 1, 5), + (447, 42, 16, 36, '433120201', 1, 5), + (448, 42, 17, 37, '433120202', 1, 5), + (449, 43, 1, 1, '456010101', 1, 4), + (450, 43, 2, 2, '456010102', 1, 4), + (451, 43, 3, 3, '456010103', 1, 4), + (452, 43, 4, 4, '456010104', 1, 4), + (453, 43, 5, 5, '456010105', 1, 4), + (454, 43, 6, 11, '456020101', 1, 4), + (455, 43, 7, 12, '456020102', 1, 4), + (456, 43, 8, 13, '456020103', 1, 4), + (457, 43, 9, 14, '456020104', 1, 4), + (458, 43, 10, 15, '456020105', 1, 4), + (459, 43, 16, 31, '456120101', 1, 5), + (460, 43, 17, 32, '456120102', 1, 5), + (461, 43, 18, 33, '456120103', 1, 5), + (462, 43, 19, 34, '456120104', 1, 5), + (463, 43, 20, 35, '456120105', 1, 5), + (464, 44, 1, 6, '456010201', 1, 4), + (465, 44, 2, 7, '456010202', 1, 4), + (466, 44, 6, 16, '456020201', 1, 4), + (467, 44, 7, 17, '456020202', 1, 4), + (468, 44, 16, 36, '456120201', 1, 5), + (469, 44, 17, 37, '456120202', 1, 5), + (470, 45, 1, 1, '458010101', 1, 4), + (471, 45, 2, 2, '458010102', 1, 4), + (472, 45, 3, 3, '458010103', 1, 4), + (473, 45, 4, 4, '458010104', 1, 4), + (474, 45, 5, 5, '458010105', 1, 4), + (475, 45, 6, 11, '458020101', 1, 4), + (476, 45, 7, 12, '458020102', 1, 4), + (477, 45, 8, 13, '458020103', 1, 4), + (478, 45, 9, 14, '458020104', 1, 4), + (479, 45, 10, 15, '458020105', 1, 4), + (480, 45, 11, 21, '458040101', 1, 5), + (481, 45, 12, 22, '458040102', 1, 5), + (482, 45, 13, 23, '458040103', 1, 5), + (483, 45, 14, 24, '458040104', 1, 5), + (484, 45, 15, 25, '458040105', 1, 5), + (485, 45, 16, 31, '458120101', 1, 5), + (486, 45, 17, 32, '458120102', 1, 5), + (487, 45, 18, 33, '458120103', 1, 5), + (488, 45, 19, 34, '458120104', 1, 5), + (489, 45, 20, 35, '458120105', 1, 5), + (490, 46, 1, 6, '458010201', 1, 4), + (491, 46, 2, 7, '458010202', 1, 4), + (492, 46, 6, 16, '458020201', 1, 4), + (493, 46, 7, 17, '458020202', 1, 4), + (494, 46, 11, 26, '458040201', 1, 5), + (495, 46, 12, 27, '458040202', 1, 5), + (496, 46, 16, 36, '458120201', 1, 5), + (497, 46, 17, 37, '458120202', 1, 5), + (498, 31, 1, 1, '522010101', 0, 4), + (499, 31, 2, 2, '522010102', 0, 4), + (500, 31, 3, 3, '522010103', 0, 4), + (501, 31, 4, 4, '522010104', 0, 4), + (502, 31, 5, 5, '522010105', 0, 4), + (503, 31, 6, 11, '522020101', 0, 4), + (504, 31, 7, 12, '522020102', 0, 4), + (505, 31, 8, 13, '522020103', 0, 4), + (506, 31, 9, 14, '522020104', 0, 4), + (507, 31, 10, 15, '522020105', 0, 4), + (508, 31, 11, 21, '522040101', 0, 5), + (509, 31, 12, 22, '522040102', 0, 5), + (510, 31, 13, 23, '522040103', 0, 5), + (511, 31, 14, 24, '522040104', 0, 5), + (512, 31, 15, 25, '522040105', 0, 5), + (513, 31, 16, 31, '522120101', 0, 5), + (514, 31, 17, 32, '522120102', 0, 5), + (515, 31, 18, 33, '522120103', 0, 5), + (516, 31, 19, 34, '522120104', 0, 5), + (517, 31, 20, 35, '522120105', 0, 5), + (518, 32, 1, 6, '522010201', 0, 4), + (519, 32, 2, 7, '522010202', 0, 4), + (520, 32, 6, 16, '522020201', 0, 4), + (521, 32, 7, 17, '522020202', 0, 4), + (522, 32, 11, 26, '522040201', 0, 5), + (523, 32, 12, 27, '522040202', 0, 5), + (524, 32, 16, 36, '522120201', 0, 5), + (525, 32, 17, 37, '522120202', 0, 5), + (526, 47, 1, 1, '568010101', 1, 4), + (527, 47, 2, 2, '568010102', 1, 4), + (528, 47, 3, 3, '568010103', 1, 4), + (529, 47, 4, 4, '568010104', 1, 4), + (530, 47, 5, 5, '568010105', 1, 4), + (531, 47, 6, 11, '568020101', 1, 4), + (532, 47, 7, 12, '568020102', 1, 4), + (533, 47, 8, 13, '568020103', 1, 4), + (534, 47, 9, 14, '568020104', 1, 4), + (535, 47, 10, 15, '568020105', 1, 4), + (536, 47, 11, 21, '568040101', 1, 5), + (537, 47, 12, 22, '568040102', 1, 5), + (538, 47, 13, 23, '568040103', 1, 5), + (539, 47, 14, 24, '568040104', 1, 5), + (540, 47, 15, 25, '568040105', 1, 5), + (541, 47, 16, 31, '568120101', 1, 5), + (542, 47, 17, 32, '568120102', 1, 5), + (543, 47, 18, 33, '568120103', 1, 5), + (544, 47, 19, 34, '568120104', 1, 5), + (545, 47, 20, 35, '568120105', 1, 5), + (546, 48, 1, 6, '568010201', 1, 4), + (547, 48, 2, 7, '568010202', 1, 4), + (548, 48, 6, 16, '568020201', 1, 4), + (549, 48, 7, 17, '568020202', 1, 4), + (550, 48, 11, 26, '568040201', 1, 5), + (551, 48, 12, 27, '568040202', 1, 5), + (552, 48, 16, 36, '568120201', 1, 5), + (553, 48, 17, 37, '568120202', 1, 5); + +-- ---------------------------- +-- Table structure for merc_types +-- ---------------------------- +DROP TABLE IF EXISTS `merc_types`; +CREATE TABLE `merc_types` +( + `merc_type_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `race_id` int(10) UNSIGNED NOT NULL, + `proficiency_id` tinyint(3) UNSIGNED NOT NULL, + `dbstring` varchar(12) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, + `clientversion` int(10) UNSIGNED NOT NULL, + PRIMARY KEY (`merc_type_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 49 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_types +-- ---------------------------- +INSERT INTO `merc_types` +VALUES (1, 1, 1, '1000100', 4), + (2, 1, 2, '1000200', 4), + (3, 2, 1, '2000100', 4), + (4, 2, 2, '2000200', 4), + (5, 3, 1, '3000100', 4), + (6, 3, 2, '3000200', 4), + (7, 4, 1, '4000100', 4), + (8, 4, 2, '4000200', 4), + (9, 5, 1, '5000100', 4), + (10, 5, 2, '5000200', 4), + (11, 6, 1, '6000100', 4), + (12, 6, 2, '6000200', 4), + (13, 7, 1, '7000100', 4), + (14, 7, 2, '7000200', 4), + (15, 8, 1, '8000100', 4), + (16, 8, 2, '8000200', 4), + (17, 9, 1, '9000100', 4), + (18, 9, 2, '9000200', 4), + (19, 10, 1, '10000100', 4), + (20, 10, 2, '10000200', 4), + (21, 11, 1, '11000100', 4), + (22, 11, 2, '11000200', 4), + (23, 12, 1, '12000100', 4), + (24, 12, 2, '12000200', 4), + (25, 128, 1, '128000100', 4), + (26, 128, 2, '128000200', 4), + (27, 130, 1, '130000100', 4), + (28, 130, 2, '130000200', 4), + (29, 330, 1, '330000100', 4), + (30, 330, 2, '330000200', 4), + (31, 522, 1, '522000100', 4), + (32, 522, 2, '522000200', 4), + (33, 26, 1, '26000100', 4), + (34, 26, 2, '26000200', 4), + (35, 48, 1, '48000100', 4), + (36, 48, 2, '48000200', 4), + (37, 51, 1, '51000100', 4), + (38, 51, 2, '51000200', 4), + (39, 137, 1, '137000100', 4), + (40, 137, 2, '137000200', 4), + (41, 433, 1, '433000100', 4), + (42, 433, 2, '433000200', 4), + (43, 456, 1, '456000100', 4), + (44, 456, 2, '456000200', 4), + (45, 458, 1, '458000100', 4), + (46, 458, 2, '458000200', 4), + (47, 568, 1, '568000100', 4), + (48, 568, 2, '568000200', 4); + +-- ---------------------------- +-- Table structure for merc_weaponinfo +-- ---------------------------- +DROP TABLE IF EXISTS `merc_weaponinfo`; +CREATE TABLE `merc_weaponinfo` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `merc_npc_type_id` int(11) NOT NULL, + `minlevel` tinyint(2) UNSIGNED NOT NULL DEFAULT 0, + `maxlevel` tinyint(2) UNSIGNED NOT NULL DEFAULT 0, + `d_melee_texture1` int(11) NOT NULL DEFAULT 0, + `d_melee_texture2` int(11) NOT NULL DEFAULT 0, + `prim_melee_type` tinyint(4) UNSIGNED NOT NULL DEFAULT 28, + `sec_melee_type` tinyint(4) UNSIGNED NOT NULL DEFAULT 28, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 61 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of merc_weaponinfo +-- ---------------------------- +INSERT INTO `merc_weaponinfo` +VALUES (1, 1, 1, 12, 10649, 208, 1, 28), + (2, 1, 13, 255, 10649, 10649, 1, 1), + (3, 2, 1, 12, 10649, 208, 1, 28), + (4, 2, 13, 255, 10649, 10649, 1, 1), + (5, 3, 1, 12, 10649, 208, 1, 28), + (6, 3, 13, 255, 10649, 10649, 1, 1), + (7, 4, 1, 12, 10649, 208, 1, 28), + (8, 4, 13, 255, 10649, 10649, 1, 1), + (9, 5, 1, 12, 10649, 208, 1, 28), + (10, 5, 13, 255, 10649, 10649, 1, 1), + (11, 6, 1, 12, 10649, 208, 1, 28), + (12, 6, 13, 255, 10649, 10649, 1, 1), + (13, 7, 1, 12, 10649, 208, 1, 28), + (14, 7, 13, 255, 10649, 10649, 1, 1), + (15, 8, 1, 12, 10649, 208, 1, 28), + (16, 8, 13, 255, 10649, 10649, 1, 1), + (17, 9, 1, 12, 10649, 208, 1, 28), + (18, 9, 13, 255, 10649, 10649, 1, 1), + (19, 10, 1, 12, 10649, 208, 1, 28), + (20, 10, 13, 255, 10649, 10649, 1, 1), + (21, 11, 1, 255, 10608, 209, 0, 28), + (22, 12, 1, 255, 10608, 209, 0, 28), + (23, 13, 1, 255, 10608, 209, 0, 28), + (24, 14, 1, 255, 10608, 209, 0, 28), + (25, 15, 1, 255, 10608, 209, 0, 28), + (26, 16, 1, 255, 10608, 209, 0, 28), + (27, 17, 1, 255, 10608, 209, 0, 28), + (28, 18, 1, 255, 10608, 209, 0, 28), + (29, 19, 1, 255, 10608, 209, 0, 28), + (30, 20, 1, 255, 10608, 209, 0, 28), + (31, 21, 1, 12, 10650, 208, 36, 28), + (32, 21, 13, 255, 10650, 10650, 36, 36), + (33, 22, 1, 12, 10650, 208, 36, 28), + (34, 22, 13, 255, 10650, 10650, 36, 36), + (35, 23, 1, 12, 10650, 208, 36, 28), + (36, 23, 13, 255, 10650, 10650, 36, 36), + (37, 24, 1, 12, 10650, 208, 36, 28), + (38, 24, 13, 255, 10650, 10650, 36, 36), + (39, 25, 1, 12, 10650, 208, 36, 28), + (40, 25, 13, 255, 10650, 10650, 36, 36), + (41, 26, 1, 12, 10650, 208, 36, 28), + (42, 26, 13, 255, 10650, 10650, 36, 36), + (43, 27, 1, 12, 10650, 208, 36, 28), + (44, 27, 13, 255, 10650, 10650, 36, 36), + (45, 28, 1, 12, 10650, 208, 36, 28), + (46, 28, 13, 255, 10650, 10650, 36, 36), + (47, 29, 1, 12, 10650, 208, 36, 28), + (48, 29, 13, 255, 10650, 10650, 36, 36), + (49, 30, 1, 12, 10650, 208, 36, 28), + (50, 30, 13, 255, 10650, 10650, 36, 36), + (51, 31, 1, 255, 10681, 209, 0, 28), + (52, 32, 1, 255, 10681, 209, 0, 28), + (53, 33, 1, 255, 10681, 209, 0, 28), + (54, 34, 1, 255, 10681, 209, 0, 28), + (55, 35, 1, 255, 10681, 209, 0, 28), + (56, 36, 1, 255, 10681, 209, 0, 28), + (57, 37, 1, 255, 10681, 209, 0, 28), + (58, 38, 1, 255, 10681, 209, 0, 28), + (59, 39, 1, 255, 10681, 209, 0, 28), + (60, 40, 1, 255, 10681, 209, 0, 28); + +-- ---------------------------- +-- Table structure for mercs +-- ---------------------------- +DROP TABLE IF EXISTS `mercs`; +CREATE TABLE `mercs` +( + `MercID` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `OwnerCharacterID` int(10) UNSIGNED NOT NULL, + `Slot` tinyint(1) UNSIGNED NOT NULL DEFAULT 0, + `Name` varchar(64) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, + `TemplateID` int(10) UNSIGNED NOT NULL DEFAULT 0, + `SuspendedTime` int(11) UNSIGNED NOT NULL DEFAULT 0, + `IsSuspended` tinyint(1) UNSIGNED NOT NULL DEFAULT 0, + `TimerRemaining` int(11) UNSIGNED NOT NULL DEFAULT 0, + `Gender` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, + `MercSize` float NOT NULL DEFAULT 5, + `StanceID` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, + `HP` int(11) UNSIGNED NOT NULL DEFAULT 0, + `Mana` int(11) UNSIGNED NOT NULL DEFAULT 0, + `Endurance` int(11) UNSIGNED NOT NULL DEFAULT 0, + `Face` int(10) UNSIGNED NOT NULL DEFAULT 1, + `LuclinHairStyle` int(10) UNSIGNED NOT NULL DEFAULT 1, + `LuclinHairColor` int(10) UNSIGNED NOT NULL DEFAULT 1, + `LuclinEyeColor` int(10) UNSIGNED NOT NULL DEFAULT 1, + `LuclinEyeColor2` int(10) UNSIGNED NOT NULL DEFAULT 1, + `LuclinBeardColor` int(10) UNSIGNED NOT NULL DEFAULT 1, + `LuclinBeard` int(10) UNSIGNED NOT NULL DEFAULT 0, + `DrakkinHeritage` int(10) UNSIGNED NOT NULL DEFAULT 0, + `DrakkinTattoo` int(10) UNSIGNED NOT NULL DEFAULT 0, + `DrakkinDetails` int(10) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`MercID`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; + +SET +FOREIGN_KEY_CHECKS = 1; diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index 650d8f189..c46b68d84 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -1,78 +1,78 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(world_sources - adventure.cpp - adventure_manager.cpp - client.cpp - cliententry.cpp - clientlist.cpp - console.cpp - dynamic_zone.cpp - dynamic_zone_manager.cpp - eql_config.cpp - eqemu_api_world_data_service.cpp - expedition_database.cpp - expedition_message.cpp - launcher_link.cpp - launcher_list.cpp - lfplist.cpp - login_server.cpp - login_server_list.cpp - main.cpp - queryserv.cpp - shared_task_manager.cpp - shared_task_world_messaging.cpp - ucs.cpp - web_interface.cpp - web_interface_eqw.cpp - wguild_mgr.cpp - world_event_scheduler.cpp - world_config.cpp - world_console_connection.cpp - world_server_command_handler.cpp - worlddb.cpp - world_store.cpp - zonelist.cpp - zoneserver.cpp -) + adventure.cpp + adventure_manager.cpp + client.cpp + cliententry.cpp + clientlist.cpp + console.cpp + dynamic_zone.cpp + dynamic_zone_manager.cpp + eql_config.cpp + eqemu_api_world_data_service.cpp + expedition_database.cpp + expedition_message.cpp + launcher_link.cpp + launcher_list.cpp + lfplist.cpp + login_server.cpp + login_server_list.cpp + main.cpp + queryserv.cpp + shared_task_manager.cpp + shared_task_world_messaging.cpp + ucs.cpp + web_interface.cpp + web_interface_eqw.cpp + wguild_mgr.cpp + world_event_scheduler.cpp + world_config.cpp + world_console_connection.cpp + world_server_cli.cpp + worlddb.cpp + world_boot.cpp + zonelist.cpp + zoneserver.cpp + ) SET(world_headers - adventure.h - adventure_manager.h - adventure_template.h - client.h - cliententry.h - clientlist.h - console.h - dynamic_zone.h - dynamic_zone_manager.h - eql_config.h - eqemu_api_world_data_service.h - expedition_database.h - expedition_message.h - launcher_link.h - launcher_list.h - lfplist.h - login_server.h - login_server_list.h - queryserv.h - shared_task_manager.h - shared_task_world_messaging.h - sof_char_create_data.h - ucs.h - web_interface.h - web_interface_eqw.h - wguild_mgr.h - world_config.h - world_console_connection.h - world_tcp_connection.h - world_server_command_handler.h - worlddb.h - world_event_scheduler.h - world_store.h - zonelist.h - zoneserver.h -) + adventure.h + adventure_manager.h + adventure_template.h + client.h + cliententry.h + clientlist.h + console.h + dynamic_zone.h + dynamic_zone_manager.h + eql_config.h + eqemu_api_world_data_service.h + expedition_database.h + expedition_message.h + launcher_link.h + launcher_list.h + lfplist.h + login_server.h + login_server_list.h + queryserv.h + shared_task_manager.h + shared_task_world_messaging.h + sof_char_create_data.h + ucs.h + web_interface.h + web_interface_eqw.h + wguild_mgr.h + world_config.h + world_console_connection.h + world_tcp_connection.h + world_server_cli.h + worlddb.h + world_boot.h + world_event_scheduler.h + zonelist.h + zoneserver.h + ) ADD_EXECUTABLE(world ${world_sources} ${world_headers}) diff --git a/world/adventure.cpp b/world/adventure.cpp index f9bf01882..2e5a58fc1 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -3,7 +3,7 @@ #include "../common/extprofile.h" #include "../common/rulesys.h" #include "../common/misc_functions.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/random.h" #include "adventure.h" #include "adventure_manager.h" @@ -11,7 +11,7 @@ #include "zonelist.h" #include "clientlist.h" #include "cliententry.h" -#include "world_store.h" +#include "../common/zone_store.h" extern ZSList zoneserver_list; extern ClientList client_list; diff --git a/world/adventure_manager.cpp b/world/adventure_manager.cpp index 06ea03bb0..2f894134f 100644 --- a/world/adventure_manager.cpp +++ b/world/adventure_manager.cpp @@ -1,6 +1,6 @@ #include "../common/global_define.h" #include "../common/misc_functions.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/servertalk.h" #include "../common/rulesys.h" #include "../common/random.h" @@ -10,7 +10,7 @@ #include "zonelist.h" #include "clientlist.h" #include "cliententry.h" -#include "world_store.h" +#include "../common/zone_store.h" #include #include diff --git a/world/cli/copy_character.cpp b/world/cli/copy_character.cpp new file mode 100644 index 000000000..7d915ad15 --- /dev/null +++ b/world/cli/copy_character.cpp @@ -0,0 +1,37 @@ +#include "../../common/eqemu_logsys_log_aliases.h" +#include "../worlddb.h" + +void WorldserverCLI::CopyCharacter(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Copies a character into a destination account"; + + std::vector arguments = { + "source_character_name", + "destination_character_name", + "destination_account_name" + }; + std::vector options = {}; + + if (cmd[{"-h", "--help"}]) { + return; + } + + EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); + + std::string source_character_name = cmd(2).str(); + std::string destination_character_name = cmd(3).str(); + std::string destination_account_name = cmd(4).str(); + + LogInfo( + "Attempting to copy character [{}] to [{}] via account [{}]", + source_character_name, + destination_character_name, + destination_account_name + ); + + database.CopyCharacter( + source_character_name, + destination_character_name, + destination_account_name + ); +} diff --git a/world/cli/database_dump.cpp b/world/cli/database_dump.cpp new file mode 100644 index 000000000..b15edeb12 --- /dev/null +++ b/world/cli/database_dump.cpp @@ -0,0 +1,62 @@ +#include "../../common/database/database_dump_service.h" + +void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Dumps server database tables"; + + std::vector arguments = {}; + std::vector options = { + "--all", + "--content-tables", + "--login-tables", + "--player-tables", + "--bot-tables", + "--merc-tables", + "--state-tables", + "--system-tables", + "--query-serv-tables", + "--table-structure-only", + "--table-lock", + "--dump-path=", + "--dump-output-to-console", + "--drop-table-syntax-only", + "--compress" + }; + + if (cmd[{"-h", "--help"}]) { + return; + } + + EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); + + auto s = new DatabaseDumpService(); + bool dump_all = cmd[{"-a", "--all"}]; + + if (!cmd("--dump-path").str().empty()) { + s->SetDumpPath(cmd("--dump-path").str()); + } + + /** + * Set Option + */ + s->SetDumpContentTables(cmd[{"--content-tables"}] || dump_all); + s->SetDumpLoginServerTables(cmd[{"--login-tables"}] || dump_all); + s->SetDumpPlayerTables(cmd[{"--player-tables"}] || dump_all); + s->SetDumpBotTables(cmd[{"--bot-tables"}] || dump_all); + s->SetDumpMercTables(cmd[{"--merc-tables"}] || dump_all); + s->SetDumpStateTables(cmd[{"--state-tables"}] || dump_all); + s->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all); + s->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all); + s->SetDumpAllTables(dump_all); + + s->SetDumpWithNoData(cmd[{"--table-structure-only"}]); + s->SetDumpTableLock(cmd[{"--table-lock"}]); + s->SetDumpWithCompression(cmd[{"--compress"}]); + s->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]); + s->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]); + + /** + * Dump + */ + s->Dump(); +} diff --git a/world/cli/database_get_schema.cpp b/world/cli/database_get_schema.cpp new file mode 100644 index 000000000..b71139358 --- /dev/null +++ b/world/cli/database_get_schema.cpp @@ -0,0 +1,68 @@ +#include "../../common/database_schema.h" +#include "../../common/json/json.h" + +void WorldserverCLI::DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Displays server database schema"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + Json::Value player_tables_json; + std::vector player_tables = DatabaseSchema::GetPlayerTables(); + for (const auto &table: player_tables) { + player_tables_json.append(table); + } + + Json::Value content_tables_json; + std::vector content_tables = DatabaseSchema::GetContentTables(); + for (const auto &table: content_tables) { + content_tables_json.append(table); + } + + Json::Value server_tables_json; + std::vector server_tables = DatabaseSchema::GetServerTables(); + for (const auto &table: server_tables) { + server_tables_json.append(table); + } + + Json::Value login_tables_json; + std::vector login_tables = DatabaseSchema::GetLoginTables(); + for (const auto &table: login_tables) { + login_tables_json.append(table); + } + + Json::Value state_tables_json; + std::vector state_tables = DatabaseSchema::GetStateTables(); + for (const auto &table: state_tables) { + state_tables_json.append(table); + } + + Json::Value version_tables_json; + std::vector version_tables = DatabaseSchema::GetVersionTables(); + for (const auto &table: version_tables) { + version_tables_json.append(table); + } + + Json::Value bot_tables_json; + std::vector bot_tables = DatabaseSchema::GetBotTables(); + for (const auto &table: bot_tables) { + bot_tables_json.append(table); + } + + Json::Value schema; + + schema["content_tables"] = content_tables_json; + schema["login_tables"] = login_tables_json; + schema["player_tables"] = player_tables_json; + schema["server_tables"] = server_tables_json; + schema["state_tables"] = state_tables_json; + schema["version_tables"] = version_tables_json; + schema["bot_tables"] = bot_tables_json; + + std::stringstream payload; + payload << schema; + + std::cout << payload.str() << std::endl; +} diff --git a/world/cli/database_set_account_status.cpp b/world/cli/database_set_account_status.cpp new file mode 100644 index 000000000..52e777bf4 --- /dev/null +++ b/world/cli/database_set_account_status.cpp @@ -0,0 +1,24 @@ +#include "../worlddb.h" + +void WorldserverCLI::DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Sets account status by account name"; + + std::vector arguments = { + "{name}", + "{status}" + }; + + std::vector options = {}; + + if (cmd[{"-h", "--help"}]) { + return; + } + + EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); + + database.SetAccountStatus( + cmd(2).str(), + std::stoi(cmd(3).str()) + ); +} diff --git a/world/cli/database_version.cpp b/world/cli/database_version.cpp new file mode 100644 index 000000000..639e7e1de --- /dev/null +++ b/world/cli/database_version.cpp @@ -0,0 +1,21 @@ +#include "../../common/version.h" +#include "../../common/json/json.h" + +void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Shows database version"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + Json::Value database_version; + + database_version["database_version"] = CURRENT_BINARY_DATABASE_VERSION; + database_version["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION; + + std::stringstream payload; + payload << database_version; + + std::cout << payload.str() << std::endl; +} diff --git a/world/cli/test.cpp b/world/cli/test.cpp new file mode 100644 index 000000000..39a923115 --- /dev/null +++ b/world/cli/test.cpp @@ -0,0 +1,21 @@ +#include "../../common/zone_store.h" + +void WorldserverCLI::TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + zone_store.LoadZones(database); + + const char* zonename = ZoneName(0); + if (zonename == 0) { + LogInfo("Zone name is 0"); + } + if (zonename == nullptr) { + LogInfo("Zone name is nullptr"); + } + +} diff --git a/world/cli/test_colors.cpp b/world/cli/test_colors.cpp new file mode 100644 index 000000000..aeff8d61b --- /dev/null +++ b/world/cli/test_colors.cpp @@ -0,0 +1,94 @@ +#include "../../common/zone_store.h" +#include "../../common/termcolor/rang.hpp" + +void WorldserverCLI::TestColors(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + using namespace std; + using namespace rang; + + // Because rang use static values it means that all redirections should be done + // before calling rang functions. + + // Visual test for background colors + cout << bg::green + << "This text has green background." << bg::reset << endl + << bg::red << "This text has red background." << bg::reset << endl + << bg::black << "This text has black background." << bg::reset << endl + << bg::yellow << "This text has yellow background." << bg::reset + << endl + << bg::blue << "This text has blue background." << bg::reset << endl + << bg::magenta << "This text has magenta background." << bg::reset + << endl + << bg::cyan << "This text has cyan background." << bg::reset << endl + << bg::gray << fg::black << "This text has gray background." + << bg::reset << style::reset << endl + + << endl + + // Visual test for foreground colors + << fg::green << "This text has green color." << fg::reset << endl + << fg::red << "This text has red color." << fg::reset << endl + << fg::black << bg::gray << "This text has black color." << fg::reset + << bg::reset << endl + << fg::yellow << "This text has yellow color." << fg::reset << endl + << fg::blue << "This text has blue color." << fg::reset << endl + << fg::magenta << "This text has magenta color." << fg::reset << endl + << fg::cyan << "This text has cyan color." << fg::reset << endl + << fg::gray << "This text has gray color." << style::reset << endl + + << endl + + // Visual test for bright background colors + << bgB::green << fg::black << "This text has bright green background." + << style::reset << endl + << bgB::red << "This text has bright red background." << style::reset + << endl + << bgB::black << "This text has bright black background." + << style::reset << endl + << bgB::yellow << fg::black + << "This text has bright yellow background." << style::reset << endl + << bgB::blue << "This text has bright blue background." << style::reset + << endl + << bgB::magenta << "This text has bright magenta background." + << style::reset << endl + << bgB::cyan << "This text has bright cyan background." << style::reset + << endl + << bgB::gray << fg::black << "This text has bright gray background." + << style::reset << style::reset << endl + + << endl + + // Visual test for bright foreground colors + << fgB::green << "This text has bright green color." << endl + << fgB::red << "This text has bright red color." << endl + << fgB::black << "This text has bright black color." << endl + << fgB::yellow << "This text has bright yellow color." << endl + << fgB::blue << "This text has bright blue color." << endl + << fgB::magenta << "This text has bright magenta color." << endl + << fgB::cyan << "This text has bright cyan color." << endl + << fgB::gray << "This text has bright gray color." << style::reset + << endl + + << endl + + // Visual test for text effects + << style::bold << "This text is bold." << style::reset << endl + << style::dim << "This text is dim." << style::reset << endl + << style::italic << "This text is italic." << style::reset << endl + << style::underline << "This text is underlined." << style::reset + << endl + << style::blink << "This text text has blink effect." << style::reset + << endl + << style::rblink << "This text text has rapid blink effect." + << style::reset << endl + << style::reversed << "This text is reversed." << style::reset << endl + << style::conceal << "This text is concealed." << style::reset << endl + << style::crossed << "This text is crossed." + << style::reset << endl; +} diff --git a/world/cli/test_expansion.cpp b/world/cli/test_expansion.cpp new file mode 100644 index 000000000..f8028b2da --- /dev/null +++ b/world/cli/test_expansion.cpp @@ -0,0 +1,44 @@ +#include "../../common/rulesys.h" +#include "../../common/repositories/content_flags_repository.h" +#include "../../common/content/world_content_service.h" +#include "../../common/repositories/criteria/content_filter_criteria.h" +#include "../worlddb.h" + +void WorldserverCLI::ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Expansion test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { + LogInfo("No rule set configured, using default rules"); + } + + content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion)); + + std::vector flags = {}; + auto f = ContentFlagsRepository::NewEntity(); + f.enabled = 1; + + std::vector flag_names = { + "hateplane_enabled", + "patch_nerf_7077", + }; + + for (auto &name: flag_names) { + f.flag_name = name; + flags.push_back(f); + } + + content_service.SetContentFlags(flags); + + LogInfo( + "Current expansion is [{}] ({}) is Velious Enabled [{}] Criteria [{}]", + content_service.GetCurrentExpansion(), + content_service.GetCurrentExpansionName(), + content_service.IsTheScarsOfVeliousEnabled() ? "true" : "false", + ContentFilterCriteria::apply() + ); +} diff --git a/world/cli/test_repository.cpp b/world/cli/test_repository.cpp new file mode 100644 index 000000000..a4c8f59b1 --- /dev/null +++ b/world/cli/test_repository.cpp @@ -0,0 +1,100 @@ +#include "../../common/repositories/instance_list_repository.h" +#include "../worlddb.h" + +void WorldserverCLI::TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + /** + * Insert one + */ + auto e = InstanceListRepository::NewEntity(); + + e.zone = 999; + e.version = 1; + e.is_global = 1; + e.start_time = 0; + e.duration = 0; + e.never_expires = 1; + + auto inserted = InstanceListRepository::InsertOne(database, e); + + LogInfo("Inserted ID is [{}] zone [{}]", inserted.id, inserted.zone); + + /** + * Find one + */ + auto f = InstanceListRepository::FindOne(database, inserted.id); + + LogInfo("Found ID is [{}] zone [{}]", f.id, f.zone); + + /** + * Update one + */ + LogInfo("Updating instance id [{}] zone [{}]", f.id, f.zone); + + int update_instance_list_count = InstanceListRepository::UpdateOne(database, f); + + f.zone = 777; + + LogInfo( + "Updated instance id [{}] zone [{}] affected [{}]", + f.id, + f.zone, + update_instance_list_count + ); + + + /** + * Delete one + */ + int deleted = InstanceListRepository::DeleteOne(database, f.id); + + LogInfo("Deleting one instance [{}] deleted count [{}]", f.id, deleted); + + /** + * Insert many + */ + std::vector instance_lists; + + auto b = InstanceListRepository::NewEntity(); + + b.zone = 999; + b.version = 1; + b.is_global = 1; + b.start_time = 0; + b.duration = 0; + b.never_expires = 1; + + for (int i = 0; i < 10; i++) { + instance_lists.push_back(b); + } + + /** + * Insert Many + */ + int inserted_count = InstanceListRepository::InsertMany(database, instance_lists); + + LogInfo("Bulk insertion test, inserted [{}]", inserted_count); + + for (auto &entry: InstanceListRepository::GetWhere(database, fmt::format("zone = {}", 999))) { + LogInfo("Iterating through entry id [{}] zone [{}]", entry.id, entry.zone); + } + + LogInfo("[Max ID] {}", InstanceListRepository::GetMaxId(database)); + LogInfo("[Count] {}", InstanceListRepository::Count(database)); + LogInfo("[Count Where] {}", InstanceListRepository::Count(database, "zone = 999")); + LogInfo("[Count Where] {}", InstanceListRepository::Count(database, "zone = 777")); + + /** + * Delete where + */ + int deleted_count = InstanceListRepository::DeleteWhere(database, fmt::format("zone = {}", 999)); + + LogInfo("Bulk deletion test, deleted [{}]", deleted_count); + +} diff --git a/world/cli/test_repository_2.cpp b/world/cli/test_repository_2.cpp new file mode 100644 index 000000000..06a2a624b --- /dev/null +++ b/world/cli/test_repository_2.cpp @@ -0,0 +1,21 @@ +#include "../../common/repositories/zone_repository.h" + +void WorldserverCLI::TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + auto zones = ZoneRepository::GetWhere(content_db, "short_name = 'anguish'"); + + for (auto &zone: zones) { + LogInfo( + "Zone [{}] long_name [{}] id [{}]", + zone.short_name, + zone.long_name, + zone.id + ); + } +} diff --git a/world/cli/version.cpp b/world/cli/version.cpp new file mode 100644 index 000000000..d03fd5e26 --- /dev/null +++ b/world/cli/version.cpp @@ -0,0 +1,24 @@ +#include "../../common/json/json.h" +#include "../../common/version.h" + +void WorldserverCLI::Version(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Shows server version"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + Json::Value j; + + j["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION; + j["compile_date"] = COMPILE_DATE; + j["compile_time"] = COMPILE_TIME; + j["database_version"] = CURRENT_BINARY_DATABASE_VERSION; + j["server_version"] = CURRENT_VERSION; + + std::stringstream payload; + payload << j; + + std::cout << payload.str() << std::endl; +} diff --git a/world/client.cpp b/world/client.cpp index 50689520c..672a68012 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -31,10 +31,11 @@ #include "../common/languages.h" #include "../common/skills.h" #include "../common/extprofile.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/emu_versions.h" #include "../common/random.h" #include "../common/shareddb.h" +#include "../common/opcodemgr.h" #include "client.h" #include "worlddb.h" @@ -46,7 +47,7 @@ #include "clientlist.h" #include "wguild_mgr.h" #include "sof_char_create_data.h" -#include "world_store.h" +#include "../common/zone_store.h" #include "../common/repositories/account_repository.h" #include @@ -156,13 +157,33 @@ void Client::SendLogServer() if(RuleB(World, IsGMPetitionWindowEnabled)) l->enable_petition_wnd = 1; - if((RuleI(World, FVNoDropFlag) == 1 || RuleI(World, FVNoDropFlag) == 2) && GetAdmin() > RuleI(Character, MinStatusForNoDropExemptions)) + if (CanTradeFVNoDropItem()) { l->enable_FV = 1; + } QueuePacket(outapp); safe_delete(outapp); } +bool Client::CanTradeFVNoDropItem() +{ + const int16 admin_status = GetAdmin(); + const int no_drop_flag = RuleI(World, FVNoDropFlag); + const int no_drop_min_admin_status = RuleI(Character, MinStatusForNoDropExemptions); + switch (no_drop_flag) { + case FVNoDropFlagRule::Disabled: + return false; + case FVNoDropFlagRule::Enabled: + return true; + case FVNoDropFlagRule::AdminOnly: + return admin_status >= no_drop_min_admin_status; + default: + LogWarning("Invalid value {0} set for FVNoDropFlag", no_drop_flag); + return false; + } + return false; +} + void Client::SendEnterWorld(std::string name) { char char_name[64] = { 0 }; @@ -217,7 +238,7 @@ void Client::SendCharInfo() { QueuePacket(outapp); } else { - LogInfo("[Error] Database did not return an OP_SendCharInfo packet for account [{}]", GetAccountID()); + LogError("Database did not return an OP_SendCharInfo packet for account [{}]", GetAccountID()); } safe_delete(outapp); } @@ -436,10 +457,10 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) return false; } - LogClientLogin("[HandleSendLoginInfoPacket] Checking Auth id [{}]", id); + LogClientLogin("Checking authentication id [{}]", id); if ((cle = client_list.CheckAuth(id, password))) { - LogClientLogin("[HandleSendLoginInfoPacket] Checking Auth id [{}] passed", id); + LogClientLogin("Checking authentication id [{}] passed", id); if (!is_player_zoning) { // Track who is in and who is out of the game char *inout= (char *) ""; @@ -721,38 +742,40 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { } bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { - if (GetAccountID() == 0) { - LogInfo("Enter world with no logged in account"); + auto account_id = GetAccountID(); + if (!account_id) { + LogInfo("Enter world with no logged in account."); eqs->Close(); return true; } - if(GetAdmin() < 0) - { - LogInfo("Account banned or suspended"); + if (GetAdmin() < 0) { + LogInfo("Account [{}] is banned or suspended.", account_id); eqs->Close(); return true; } - if (RuleB(World, EnableIPExemptions) || RuleI(World, MaxClientsPerIP) >= 0) { + if ( + RuleB(World, EnableIPExemptions) || + RuleI(World, MaxClientsPerIP) > 0 + ) { client_list.GetCLEIP(GetIP()); //Check current CLE Entry IPs against incoming connection } - EnterWorld_Struct *ew=(EnterWorld_Struct *)app->pBuffer; - strn0cpy(char_name, ew->name, 64); + auto ew = (EnterWorld_Struct *) app->pBuffer; + strn0cpy(char_name, ew->name, sizeof(char_name)); - EQApplicationPacket *outapp; - uint32 tmpaccid = 0; - charid = database.GetCharacterInfo(char_name, &tmpaccid, &zone_id, &instance_id); - if (charid == 0) { + uint32 temporary_account_id = 0; + charid = database.GetCharacterInfo(char_name, &temporary_account_id, &zone_id, &instance_id); + if (!charid) { LogInfo("Could not get CharInfo for [{}]", char_name); eqs->Close(); return true; } // Make sure this account owns this character - if (tmpaccid != GetAccountID()) { - LogInfo("This account does not own the character named [{}]", char_name); + if (temporary_account_id != account_id) { + LogInfo("Account [{}] does not own the character named [{}] from account [{}]", account_id, char_name, temporary_account_id); eqs->Close(); return true; } @@ -761,25 +784,26 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!is_player_zoning) { size_t character_limit = EQ::constants::StaticLookup(eqs->ClientVersion())->CharacterCreationLimit; - if (character_limit > EQ::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQ::constants::CHARACTER_CREATION_LIMIT; } - if (eqs->ClientVersion() == EQ::versions::ClientVersion::Titanium) { character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT; } + if (character_limit > EQ::constants::CHARACTER_CREATION_LIMIT) { + character_limit = EQ::constants::CHARACTER_CREATION_LIMIT; + } - std::string tgh_query = StringFormat( - "SELECT " - "`id`, " - "name, " - "`level`, " - "last_login " - "FROM " - "character_data " - "WHERE `account_id` = %i ORDER BY `name` LIMIT %u", GetAccountID(), character_limit); - auto tgh_results = database.QueryDatabase(tgh_query); + if (eqs->ClientVersion() == EQ::versions::ClientVersion::Titanium) { + character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT; + } + + auto query = fmt::format( + "SELECT `id`, `name`, `level`, `last_login` FROM character_data WHERE `account_id` = {} ORDER BY `name` LIMIT {}", + account_id, + character_limit + ); + auto results = database.QueryDatabase(query); /* Check GoHome */ if (ew->return_home && !ew->tutorial) { bool home_enabled = false; - for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) { - if (strcasecmp(row[1], char_name) == 0) { + for (auto row : results) { + if (!strcasecmp(row[1], char_name)) { if (RuleB(World, EnableReturnHomeButton)) { int now = time(nullptr); if ((now - atoi(row[3])) >= RuleI(World, MinOfflineTimeToReturnHome)) { @@ -792,9 +816,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if (home_enabled) { zone_id = database.MoveCharacterToBind(charid, 4); - } - else { - LogInfo("[{}] is trying to go home before they're able", char_name); + } else { + LogInfo("[{}] is trying to go home before they're able.", char_name); database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able."); eqs->Close(); return true; @@ -804,9 +827,12 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { /* Check Tutorial*/ if (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial)) { bool tutorial_enabled = false; - for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) { - if (strcasecmp(row[1], char_name) == 0) { - if (RuleB(World, EnableTutorialButton) && ((uint8)atoi(row[2]) <= RuleI(World, MaxLevelForTutorial))) { + for (auto row : results) { + if (!strcasecmp(row[1], char_name)) { + if ( + RuleB(World, EnableTutorialButton) && + std::stoi(row[2]) <= RuleI(World, MaxLevelForTutorial) + ) { tutorial_enabled = true; break; } @@ -816,9 +842,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if (tutorial_enabled) { zone_id = RuleI(World, TutorialZoneID); database.MoveCharacterToZone(charid, zone_id); - } - else { - LogInfo("[{}] is trying to go to tutorial but are not allowed", char_name); + } else { + LogInfo("[{}] is trying to go to the Tutorial but they are not allowed.", char_name); database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character."); eqs->Close(); return true; @@ -826,17 +851,17 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } } - if (zone_id == 0 || !ZoneName(zone_id)) { + if (!zone_id || !ZoneName(zone_id)) { // This is to save people in an invalid zone, once it's removed from the DB database.MoveCharacterToZone(charid, ZoneID("arena")); - LogInfo("Zone not found in database zone_id=[{}], moveing char to arena character:[{}]", zone_id, char_name); + LogInfo("Zone [{}] not found, moving [{}] to Arena.", zone_id, char_name); } - if(instance_id > 0) - { - if (!database.VerifyInstanceAlive(instance_id, GetCharID()) || - !database.VerifyZoneInstance(zone_id, instance_id)) - { + if (instance_id) { + if ( + !database.VerifyInstanceAlive(instance_id, GetCharID()) || + !database.VerifyZoneInstance(zone_id, instance_id) + ) { zone_id = database.MoveCharacterToInstanceSafeReturn(charid, zone_id, instance_id); instance_id = 0; } @@ -845,83 +870,80 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if(!is_player_zoning) { database.SetGroupID(char_name, 0, charid); database.SetLoginFlags(charid, false, false, 1); - } - else{ - uint32 groupid = database.GetGroupID(char_name); - if(groupid > 0){ - char* leader = 0; - char leaderbuf[64] = {0}; - if((leader = database.GetGroupLeaderForLogin(char_name, leaderbuf)) && strlen(leader)>1){ - auto outapp3 = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer; + } else { + auto group_id = database.GetGroupID(char_name); + if (group_id) { + auto leader_name = database.GetGroupLeaderForLogin(char_name); + if (!leader_name.empty()) { + auto pack = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); + auto gj = (GroupJoin_Struct*) pack->pBuffer; gj->action=8; - strcpy(gj->yourname, char_name); - strcpy(gj->membername, leader); - QueuePacket(outapp3); - safe_delete(outapp3); + strn0cpy(gj->yourname, char_name, sizeof(gj->yourname)); + strn0cpy(gj->membername, leader_name.c_str(), sizeof(gj->membername)); + QueuePacket(pack); + safe_delete(pack); } } } - outapp = new EQApplicationPacket(OP_MOTD); - std::string tmp; - if (database.GetVariable("MOTD", tmp)) { - outapp->size = tmp.length() + 1; + auto outapp = new EQApplicationPacket(OP_MOTD); + std::string motd_message; + if (database.GetVariable("MOTD", motd_message)) { + outapp->size = motd_message.length() + 1; outapp->pBuffer = new uchar[outapp->size]; - memset(outapp->pBuffer,0,outapp->size); - strcpy((char*)outapp->pBuffer, tmp.c_str()); - - } else { - // Null Message of the Day. :) + memset(outapp->pBuffer, 0, outapp->size); + strcpy((char*)outapp->pBuffer, motd_message.c_str()); + } else { // Null Message of the Day. :) outapp->size = 1; outapp->pBuffer = new uchar[outapp->size]; outapp->pBuffer[0] = 0; } + QueuePacket(outapp); safe_delete(outapp); // set mailkey - used for duration of character session - int MailKey = emu_random.Int(1, INT_MAX); + int mail_key = emu_random.Int(1, INT_MAX); - database.SetMailKey(charid, GetIP(), MailKey); + database.SetMailKey(charid, GetIP(), mail_key); if (UCSServerAvailable_) { - const WorldConfig *Config = WorldConfig::get(); + auto config = WorldConfig::get(); std::string buffer; - EQ::versions::UCSVersion ConnectionType = EQ::versions::ucsUnknown; + auto connection_type = EQ::versions::ucsUnknown; // chat server packet switch (GetClientVersion()) { - case EQ::versions::ClientVersion::Titanium: - ConnectionType = EQ::versions::ucsTitaniumChat; - break; - case EQ::versions::ClientVersion::SoF: - ConnectionType = EQ::versions::ucsSoFCombined; - break; - case EQ::versions::ClientVersion::SoD: - ConnectionType = EQ::versions::ucsSoDCombined; - break; - case EQ::versions::ClientVersion::UF: - ConnectionType = EQ::versions::ucsUFCombined; - break; - case EQ::versions::ClientVersion::RoF: - ConnectionType = EQ::versions::ucsRoFCombined; - break; - case EQ::versions::ClientVersion::RoF2: - ConnectionType = EQ::versions::ucsRoF2Combined; - break; - default: - ConnectionType = EQ::versions::ucsUnknown; - break; + case EQ::versions::ClientVersion::Titanium: + connection_type = EQ::versions::ucsTitaniumChat; + break; + case EQ::versions::ClientVersion::SoF: + connection_type = EQ::versions::ucsSoFCombined; + break; + case EQ::versions::ClientVersion::SoD: + connection_type = EQ::versions::ucsSoDCombined; + break; + case EQ::versions::ClientVersion::UF: + connection_type = EQ::versions::ucsUFCombined; + break; + case EQ::versions::ClientVersion::RoF: + connection_type = EQ::versions::ucsRoFCombined; + break; + case EQ::versions::ClientVersion::RoF2: + connection_type = EQ::versions::ucsRoF2Combined; + break; + default: + connection_type = EQ::versions::ucsUnknown; + break; } - buffer = StringFormat("%s,%i,%s.%s,%c%08X", - Config->ChatHost.c_str(), - Config->ChatPort, - Config->ShortName.c_str(), + buffer = fmt::format("{},{},{}.{},{}{:08X}", + config->ChatHost, + config->ChatPort, + config->ShortName, GetCharName(), - ConnectionType, - MailKey + static_cast(connection_type), + mail_key ); outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1)); @@ -933,21 +955,21 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // mail server packet switch (GetClientVersion()) { - case EQ::versions::ClientVersion::Titanium: - ConnectionType = EQ::versions::ucsTitaniumMail; - break; - default: - // retain value from previous switch - break; + case EQ::versions::ClientVersion::Titanium: + connection_type = EQ::versions::ucsTitaniumMail; + break; + default: + // retain value from previous switch + break; } - buffer = StringFormat("%s,%i,%s.%s,%c%08X", - Config->MailHost.c_str(), - Config->MailPort, - Config->ShortName.c_str(), + buffer = fmt::format("{},{},{}.{},{}{:08X}", + config->MailHost, + config->MailPort, + config->ShortName, GetCharName(), - ConnectionType, - MailKey + static_cast(connection_type), + mail_key ); outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1)); @@ -967,7 +989,7 @@ bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) { uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer); if(char_acct_id == GetAccountID()) { - LogInfo("Delete character: [{}]", app->pBuffer); + LogInfo("Delete character: [{}]", (const char*)app->pBuffer); database.DeleteCharacter((char *)app->pBuffer); SendCharInfo(); } @@ -988,7 +1010,13 @@ bool Client::HandlePacket(const EQApplicationPacket *app) { EmuOpcode opcode = app->GetOpcode(); - LogNetcode("Received EQApplicationPacket [{:#04x}]", opcode); + LogPacketClientServer( + "[{}] [{:#06x}] Size [{}] {}", + OpcodeManager::EmuToName(app->GetOpcode()), + eqs->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + app->Size(), + (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") + ); if (!eqs->CheckState(ESTABLISHED)) { LogInfo("Client disconnected (net inactive on send)"); @@ -1228,7 +1256,7 @@ bool Client::ChecksumVerificationCRCEQGame(uint64 checksum) checksumint = atoll(checksumvar.c_str()); } else { - LogChecksumVerification("[checksum_crc1_eqgame] variable not set in variables table."); + LogChecksumVerification("variable not set in variables table."); return true; } @@ -1274,7 +1302,7 @@ bool Client::ChecksumVerificationCRCBaseData(uint64 checksum) checksumint = atoll(checksumvar.c_str()); } else { - LogChecksumVerification("[checksum_crc3_basedata] variable not set in variables table."); + LogChecksumVerification("variable not set in variables table."); return true; } @@ -1489,14 +1517,6 @@ void Client::TellClientZoneUnavailable() { autobootup_timeout.Disable(); } -bool Client::GenPassKey(char* key) { - char* passKey=nullptr; - *passKey += ((char)('A'+((int)emu_random.Int(0, 25)))); - *passKey += ((char)('A'+((int)emu_random.Int(0, 25)))); - memcpy(key, passKey, strlen(passKey)); - return true; -} - void Client::QueuePacket(const EQApplicationPacket* app, bool ack_req) { LogNetcode("Sending EQApplicationPacket OpCode {:#04x}", app->GetOpcode()); @@ -1511,6 +1531,7 @@ void Client::SendGuildList() { //ask the guild manager to build us a nice guild list packet outapp->pBuffer = guild_mgr.MakeGuildList("", outapp->size); if(outapp->pBuffer == nullptr) { + safe_delete(outapp); return; } @@ -1570,7 +1591,6 @@ void Client::SendApproveWorld() bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) { PlayerProfile_Struct pp; - ExtendedProfile_Struct ext; EQ::InventoryProfile inv; pp.SetPlayerProfileVersion(EQ::versions::ConvertClientVersionToMobVersion(EQ::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit))); @@ -1578,25 +1598,44 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) inv.SetGMInventory(false); // character cannot have gm flag at this point time_t bday = time(nullptr); - char startzone[50]={0}; - uint32 i; - struct in_addr in; + in_addr in; int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA; in.s_addr = GetIP(); - LogInfo("Character creation request from [{}] LS#[{}] ([{}]:[{}]) : ", GetCLE()->LSName(), GetCLE()->LSID(), inet_ntoa(in), GetPort()); - LogInfo("Name: [{}]", name); - Log(Logs::Detail, Logs::WorldServer, "Race: %d Class: %d Gender: %d Deity: %d Start zone: %d Tutorial: %s", - cc->race, cc->class_, cc->gender, cc->deity, cc->start_zone, cc->tutorial ? "true" : "false"); - LogInfo("STR STA AGI DEX WIS INT CHA Total"); - Log(Logs::Detail, Logs::WorldServer, "%3d %3d %3d %3d %3d %3d %3d %3d", - cc->STR, cc->STA, cc->AGI, cc->DEX, cc->WIS, cc->INT, cc->CHA, - stats_sum); - LogInfo("Face: [{}] Eye colors: [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2); - LogInfo("Hairstyle: [{}] Haircolor: [{}]", cc->hairstyle, cc->haircolor); - LogInfo("Beard: [{}] Beardcolor: [{}]", cc->beard, cc->beardcolor); + LogInfo( + "Character creation request from [{}] LS [{}] [{}] [{}]", + GetCLE()->LSName(), + GetCLE()->LSID(), + inet_ntoa(in), + GetPort() + ); + LogInfo("Name [{}]", name); + LogInfo( + "Race [{}] Class [{}] Gender [{}] Deity [{}] Start zone [{}] Tutorial [{}]", + cc->race, + cc->class_, + cc->gender, + cc->deity, + cc->start_zone, + cc->tutorial ? "true" : "false" + ); + LogInfo("STR STA AGI DEX WIS INT CHA Total"); + LogInfo( + " [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]", + cc->STR, + cc->STA, + cc->AGI, + cc->DEX, + cc->WIS, + cc->INT, + cc->CHA, + stats_sum + ); + LogInfo("Face [{}] Eye colors [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2); + LogInfo("Hairstyle [{}] Haircolor [{}]", cc->hairstyle, cc->haircolor); + LogInfo("Beard [{}] Beardcolor [{}]", cc->beard, cc->beardcolor); /* Validate the char creation struct */ if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) { @@ -1659,22 +1698,22 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE)); memset(pp.mem_spells, 0xFF, (sizeof(uint32) * EQ::spells::SPELL_GEM_COUNT)); - for(i = 0; i < BUFF_COUNT; i++) - pp.buffs[i].spellid = 0xFFFF; + for (auto& buff : pp.buffs) + buff.spellid = 0xFFFF; /* If server is PVP by default, make all character set to it. */ pp.pvp = database.GetServerType() == 1 ? 1 : 0; /* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */ if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) { - LogInfo("Found 'SoFStartZoneID' rule setting: [{}]", RuleI(World, SoFStartZoneID)); + LogInfo("Found [SoFStartZoneID] rule setting [{}]", RuleI(World, SoFStartZoneID)); if (RuleI(World, SoFStartZoneID) > 0) { pp.zone_id = RuleI(World, SoFStartZoneID); cc->start_zone = pp.zone_id; } } else { - LogInfo("Found 'TitaniumStartZoneID' rule setting: [{}]", RuleI(World, TitaniumStartZoneID)); + LogInfo("Found [TitaniumStartZoneID] rule setting [{}]", RuleI(World, TitaniumStartZoneID)); if (RuleI(World, TitaniumStartZoneID) > 0) { /* if there's a startzone variable put them in there */ pp.zone_id = RuleI(World, TitaniumStartZoneID); @@ -1722,7 +1761,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) /* Overrides if we have the tutorial flag set! */ if (cc->tutorial && RuleB(World, EnableTutorialButton)) { pp.zone_id = RuleI(World, TutorialZoneID); - content_db.GetSafePoints(ZoneName(pp.zone_id), 0, &pp.x, &pp.y, &pp.z); + auto z = GetZone(pp.zone_id); + if (z) { + pp.x = z->safe_x; + pp.y = z->safe_y; + pp.z = z->safe_z; + } } /* Will either be the same as home or tutorial if enabled. */ @@ -1734,12 +1778,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.binds[0].heading = pp.heading; } - Log(Logs::Detail, Logs::WorldServer, "Current location: %s (%d) %0.2f, %0.2f, %0.2f, %0.2f", - ZoneName(pp.zone_id), pp.zone_id, pp.x, pp.y, pp.z, pp.heading); - Log(Logs::Detail, Logs::WorldServer, "Bind location: %s (%d) %0.2f, %0.2f, %0.2f", - ZoneName(pp.binds[0].zone_id), pp.binds[0].zone_id, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z); - Log(Logs::Detail, Logs::WorldServer, "Home location: %s (%d) %0.2f, %0.2f, %0.2f", - ZoneName(pp.binds[4].zone_id), pp.binds[4].zone_id, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z); + LogInfo("Current location [{}] [{}] [{}] [{}] [{}] [{}]", + ZoneName(pp.zone_id), pp.zone_id, pp.x, pp.y, pp.z, pp.heading); + LogInfo("Bind location [{}] [{}] [{}] [{}] [{}]", + ZoneName(pp.binds[0].zone_id), pp.binds[0].zone_id, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z); + LogInfo("Home location [{}] [{}] [{}] [{}] [{}]", + ZoneName(pp.binds[4].zone_id), pp.binds[4].zone_id, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z); /* Starting Items inventory */ content_db.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin()); @@ -1781,7 +1825,6 @@ bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) return false; } - uint32 max_stats = 0; uint32 allocs = character_create_allocations.size(); RaceClassAllocation allocation = {0}; found = false; @@ -1798,7 +1841,7 @@ bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) return false; } - max_stats = allocation.DefaultPointAllocation[0] + + uint32 max_stats = allocation.DefaultPointAllocation[0] + allocation.DefaultPointAllocation[1] + allocation.DefaultPointAllocation[2] + allocation.DefaultPointAllocation[3] + @@ -1944,16 +1987,16 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc) // if out of range looking it up in the table would crash stuff // so we return from these if (classtemp >= PLAYER_CLASS_COUNT) { - LogInfo(" class is out of range"); + LogInfo(" class is out of range"); return false; } if (racetemp >= _TABLE_RACES) { - LogInfo(" race is out of range"); + LogInfo(" race is out of range"); return false; } if (!ClassRaceLookupTable[classtemp][racetemp]) { //Lookup table better than a bunch of ifs? - LogInfo(" invalid race/class combination"); + LogInfo(" invalid race/class combination"); // we return from this one, since if it's an invalid combination our table // doesn't have meaningful values for the stats return false; @@ -1981,36 +2024,36 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc) // that are messed up not just the first hit if (bTOTAL + stat_points != cTOTAL) { - LogInfo(" stat points total doesn't match expected value: expecting [{}] got [{}]", bTOTAL + stat_points, cTOTAL); + LogInfo(" stat points total doesn't match expected value: expecting [{}] got [{}]", bTOTAL + stat_points, cTOTAL); Charerrors++; } if (cc->STR > bSTR + stat_points || cc->STR < bSTR) { - LogInfo(" stat STR is out of range"); + LogInfo(" stat STR is out of range"); Charerrors++; } if (cc->STA > bSTA + stat_points || cc->STA < bSTA) { - LogInfo(" stat STA is out of range"); + LogInfo(" stat STA is out of range"); Charerrors++; } if (cc->AGI > bAGI + stat_points || cc->AGI < bAGI) { - LogInfo(" stat AGI is out of range"); + LogInfo(" stat AGI is out of range"); Charerrors++; } if (cc->DEX > bDEX + stat_points || cc->DEX < bDEX) { - LogInfo(" stat DEX is out of range"); + LogInfo(" stat DEX is out of range"); Charerrors++; } if (cc->WIS > bWIS + stat_points || cc->WIS < bWIS) { - LogInfo(" stat WIS is out of range"); + LogInfo(" stat WIS is out of range"); Charerrors++; } if (cc->INT > bINT + stat_points || cc->INT < bINT) { - LogInfo(" stat INT is out of range"); + LogInfo(" stat INT is out of range"); Charerrors++; } if (cc->CHA > bCHA + stat_points || cc->CHA < bCHA) { - LogInfo(" stat CHA is out of range"); + LogInfo(" stat CHA is out of range"); Charerrors++; } diff --git a/world/client.h b/world/client.h index d94f5a598..93aacb31d 100644 --- a/world/client.h +++ b/world/client.h @@ -39,7 +39,6 @@ public: ~Client(); bool Process(); - void ReceiveData(uchar* buf, int len); void SendCharInfo(); void SendMaxCharCreate(); void SendMembership(); @@ -54,7 +53,6 @@ public: void SendLogServer(); void SendApproveWorld(); void SendPostEnterWorld(); - bool GenPassKey(char* key); inline uint32 GetIP() { return ip; } inline uint16 GetPort() { return port; } @@ -122,6 +120,7 @@ private: bool ChecksumVerificationCRCBaseData(uint64 checksum); EQStreamInterface* eqs; + bool CanTradeFVNoDropItem(); }; bool CheckCharCreateInfoSoF(CharCreate_Struct *cc); diff --git a/world/cliententry.cpp b/world/cliententry.cpp index 0003e70f1..9609a2df7 100644 --- a/world/cliententry.cpp +++ b/world/cliententry.cpp @@ -25,7 +25,7 @@ #include "zoneserver.h" #include "world_config.h" #include "../common/guilds.h" -#include "../common/string_util.h" +#include "../common/strings.h" extern uint32 numplayers; extern LoginServerList loginserverlist; @@ -58,7 +58,7 @@ ClientListEntry::ClientListEntry( ClearVars(true); LogDebug( - "ClientListEntry in_id [{0}] in_loginserver_id [{1}] in_loginserver_name [{2}] in_login_name [{3}] in_login_key [{4}] " + "in_id [{0}] in_loginserver_id [{1}] in_loginserver_name [{2}] in_login_name [{3}] in_login_key [{4}] " " in_is_world_admin [{5}] ip [{6}] local [{7}]", in_id, in_loginserver_id, @@ -141,7 +141,7 @@ void ClientListEntry::SetOnline(ZoneServer *iZS, CLE_Status iOnline) void ClientListEntry::SetOnline(CLE_Status iOnline) { LogClientLogin( - "ClientListEntry::SetOnline for [{}] ({}) = [{}] ({})", + "Online status [{}] ({}) status [{}] ({})", AccountName(), AccountID(), CLEStatusString[CLE_Status::Online], @@ -325,7 +325,7 @@ bool ClientListEntry::CheckStale() bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_password) { LogDebug( - "ClientListEntry::CheckAuth ls_account_id [{0}] key_password [{1}] plskey [{2}]", + "ls_account_id [{0}] key_password [{1}] plskey [{2}]", loginserver_account_id, key_password, plskey @@ -333,7 +333,7 @@ bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_p if (pLSID == loginserver_account_id && strncmp(plskey, key_password, 10) == 0) { LogDebug( - "ClientListEntry::CheckAuth ls_account_id [{0}] key_password [{1}] plskey [{2}] lsid [{3}] paccountid [{4}]", + "ls_account_id [{0}] key_password [{1}] plskey [{2}] lsid [{3}] paccountid [{4}]", loginserver_account_id, key_password, plskey, diff --git a/world/clientlist.cpp b/world/clientlist.cpp index d2b016af4..8dcf6dd48 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -22,7 +22,7 @@ #include "zonelist.h" #include "client.h" #include "worlddb.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/guilds.h" #include "../common/races.h" #include "../common/classes.h" @@ -33,7 +33,7 @@ #include "../common/event_sub.h" #include "web_interface.h" #include "wguild_mgr.h" -#include "world_store.h" +#include "../common/zone_store.h" #include extern WebInterfaceList web_interface; @@ -100,67 +100,101 @@ ClientListEntry* ClientList::GetCLE(uint32 iID) { //Check current CLE Entry IPs against incoming connection -void ClientList::GetCLEIP(uint32 iIP) { - ClientListEntry* countCLEIPs = 0; +void ClientList::GetCLEIP(uint32 in_ip) { + ClientListEntry* cle = nullptr; LinkedListIterator iterator(clientlist); - int IPInstances = 0; + int count = 0; iterator.Reset(); - while(iterator.MoreElements()) { - countCLEIPs = iterator.GetData(); - if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0))) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) - IPInstances++; // Increment the occurences of this IP address - LogClientLogin("Account ID: [{}] Account Name: [{}] IP: [{}]", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); + while (iterator.MoreElements()) { + cle = iterator.GetData(); + if ( + cle->GetIP() == in_ip && + ( + cle->Admin() < RuleI(World, ExemptMaxClientsStatus) || + RuleI(World, ExemptMaxClientsStatus) < 0 + ) + ) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) + auto ip_string = long2ip(cle->GetIP()); + count++; // Increment the occurences of this IP address + LogClientLogin("Account ID: [{}] Account Name: [{}] IP: [{}]", cle->LSID(), cle->LSName(), ip_string); + if (RuleB(World, EnableIPExemptions)) { - LogClientLogin("Account ID: [{}] Account Name: [{}] IP: [{}] IP Instances: [{}] Max IP Instances: [{}]", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str(), IPInstances, database.GetIPExemption(long2ip(countCLEIPs->GetIP()).c_str())); - if (IPInstances > database.GetIPExemption(long2ip(countCLEIPs->GetIP()).c_str())) { - if(RuleB(World, IPLimitDisconnectAll)) { - LogClientLogin("Disconnect: All accounts on IP [{}]", long2ip(countCLEIPs->GetIP()).c_str()); - DisconnectByIP(iIP); + LogClientLogin( + "Account ID: [{}] Account Name: [{}] IP: [{}] IP Instances: [{}] Max IP Instances: [{}]", + cle->LSID(), + cle->LSName(), + ip_string, + count, + database.GetIPExemption(ip_string) + ); + + auto exemption_amount = database.GetIPExemption(ip_string); + if (exemption_amount > 0 && count > exemption_amount) { + if (RuleB(World, IPLimitDisconnectAll)) { + LogClientLogin("Disconnect: All Accounts on IP [{}]", ip_string); + DisconnectByIP(in_ip); return; } else { - LogClientLogin("Disconnect: Account [{}] on IP [{}]", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); - countCLEIPs->SetOnline(CLE_Status::Offline); + LogClientLogin("Disconnect: Account [{}] on IP [{}]", cle->LSName(), ip_string); + cle->SetOnline(CLE_Status::Offline); iterator.RemoveCurrent(); continue; } } } else { - if (IPInstances > (RuleI(World, MaxClientsPerIP))) { // If the number of connections exceeds the lower limit + if ( + RuleI(World, MaxClientsPerIP) > 0 && + count > RuleI(World, MaxClientsPerIP) + ) { // If the number of connections exceeds the lower limit if (RuleB(World, MaxClientsSetByStatus)) { // If MaxClientsSetByStatus is set to True, override other IP Limit Rules - LogClientLogin("Account ID: [{}] Account Name: [{}] IP: [{}] IP Instances: [{}] Max IP Instances: [{}]", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str(), IPInstances, countCLEIPs->Admin()); - if (IPInstances > countCLEIPs->Admin()) { // The IP Limit is set by the status of the account if status > MaxClientsPerIP - if(RuleB(World, IPLimitDisconnectAll)) { - LogClientLogin("Disconnect: All accounts on IP [{}]", long2ip(countCLEIPs->GetIP()).c_str()); - DisconnectByIP(iIP); + LogClientLogin( + "Account ID: [{}] Account Name: [{}] IP: [{}] IP Instances: [{}] Max IP Instances: [{}]", + cle->LSID(), + cle->LSName(), + ip_string, + count, + cle->Admin() + ); + + if (count > cle->Admin()) { // The IP Limit is set by the status of the account if status > MaxClientsPerIP + if (RuleB(World, IPLimitDisconnectAll)) { + LogClientLogin("Disconnect: All Accounts on IP [{}]", ip_string); + DisconnectByIP(in_ip); return; } else { - LogClientLogin("Disconnect: Account [{}] on IP [{}]", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); - countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection + LogClientLogin("Disconnect: Account [{}] on IP [{}]", cle->LSName(), ip_string); + cle->SetOnline(CLE_Status::Offline); // Remove the connection iterator.RemoveCurrent(); continue; } } - } else if ((countCLEIPs->Admin() < RuleI(World, AddMaxClientsStatus)) || (RuleI(World, AddMaxClientsStatus) < 0)) { // Else if the Admin status of the connection is not eligible for the higher limit, or there is no higher limit (AddMaxClientStatus < 0) - if(RuleB(World, IPLimitDisconnectAll)) { - LogClientLogin("Disconnect: All accounts on IP [{}]", long2ip(countCLEIPs->GetIP()).c_str()); - DisconnectByIP(iIP); + } else if ( + cle->Admin() < RuleI(World, AddMaxClientsStatus) || + RuleI(World, AddMaxClientsStatus) < 0 + ) { // Else if the Admin status of the connection is not eligible for the higher limit, or there is no higher limit (AddMaxClientStatus < 0) + if (RuleB(World, IPLimitDisconnectAll)) { + LogClientLogin("Disconnect: All Accounts on IP [{}]", ip_string); + DisconnectByIP(in_ip); return; } else { - LogClientLogin("Disconnect: Account [{}] on IP [{}]", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); - countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection + LogClientLogin("Disconnect: Account [{}] on IP [{}]", cle->LSName(), ip_string); + cle->SetOnline(CLE_Status::Offline); // Remove the connection iterator.RemoveCurrent(); continue; } - } else if (IPInstances > RuleI(World, AddMaxClientsPerIP)) { // else they are eligible for the higher limit, but if they exceed that - if(RuleB(World, IPLimitDisconnectAll)) { - LogClientLogin("Disconnect: All accounts on IP [{}]", long2ip(countCLEIPs->GetIP()).c_str()); - DisconnectByIP(iIP); + } else if ( + RuleI(World, AddMaxClientsPerIP) > 0 && + count > RuleI(World, AddMaxClientsPerIP) + ) { // else they are eligible for the higher limit, but if they exceed that + if (RuleB(World, IPLimitDisconnectAll)) { + LogClientLogin("Disconnect: All Accounts on IP [{}]", ip_string); + DisconnectByIP(in_ip); return; } else { - LogClientLogin("Disconnect: Account [{}] on IP [{}]", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); - countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection + LogClientLogin("Disconnect: Account [{}] on IP [{}]", cle->LSName(), ip_string); + cle->SetOnline(CLE_Status::Offline); // Remove the connection iterator.RemoveCurrent(); continue; } @@ -168,46 +202,54 @@ void ClientList::GetCLEIP(uint32 iIP) { } } } + iterator.Advance(); } } -uint32 ClientList::GetCLEIPCount(uint32 iIP) { - ClientListEntry* countCLEIPs = 0; +uint32 ClientList::GetCLEIPCount(uint32 in_ip) { + ClientListEntry* cle = nullptr; LinkedListIterator iterator(clientlist); - int IPInstances = 0; + int count = 0; iterator.Reset(); while (iterator.MoreElements()) { - countCLEIPs = iterator.GetData(); - if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status::Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) - IPInstances++; // Increment the occurences of this IP address + cle = iterator.GetData(); + if ( + cle->GetIP() == in_ip && + ( + cle->Admin() < RuleI(World, ExemptMaxClientsStatus) || + RuleI(World, ExemptMaxClientsStatus) < 0 + ) && + cle->Online() >= CLE_Status::Online + ) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) + count++; // Increment the occurences of this IP address } iterator.Advance(); } - return IPInstances; + return count; } -void ClientList::DisconnectByIP(uint32 iIP) { - ClientListEntry* countCLEIPs = 0; +void ClientList::DisconnectByIP(uint32 in_ip) { + ClientListEntry* cle = nullptr; LinkedListIterator iterator(clientlist); iterator.Reset(); - while(iterator.MoreElements()) { - countCLEIPs = iterator.GetData(); - if ((countCLEIPs->GetIP() == iIP)) { - if(strlen(countCLEIPs->name())) { + while (iterator.MoreElements()) { + cle = iterator.GetData(); + if (cle->GetIP() == in_ip) { + if (strlen(cle->name())) { auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); - ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; - strcpy(skp->adminname, "SessionLimit"); - strcpy(skp->name, countCLEIPs->name()); + auto skp = (ServerKickPlayer_Struct*) pack->pBuffer; + strn0cpy(skp->adminname, "SessionLimit", sizeof(skp->adminname)); + strn0cpy(skp->name, cle->name(), sizeof(skp->name)); skp->adminrank = 255; zoneserver_list.SendPacket(pack); safe_delete(pack); } - countCLEIPs->SetOnline(CLE_Status::Offline); + cle->SetOnline(CLE_Status::Offline); iterator.RemoveCurrent(); } iterator.Advance(); @@ -277,7 +319,7 @@ void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnect strcpy(newline, "\r\n"); else strcpy(newline, "^"); - fmt::memory_buffer out; + std::vector out; iterator.Reset(); while(iterator.MoreElements()) { @@ -286,22 +328,21 @@ void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnect struct in_addr in; in.s_addr = cle->GetIP(); if (addnewline) { - fmt::format_to(out, newline); + fmt::format_to(std::back_inserter(out), fmt::runtime(newline)); } - fmt::format_to(out, "ID: {} Acc# {} AccName: {} IP: {}", cle->GetID(), cle->AccountID(), cle->AccountName(), inet_ntoa(in)); - fmt::format_to(out, "{} Stale: {} Online: {} Admin: {}", newline, cle->GetStaleCounter(), cle->Online(), cle->Admin()); + fmt::format_to(std::back_inserter(out), "ID: {} Acc# {} AccName: {} IP: {}", cle->GetID(), cle->AccountID(), cle->AccountName(), inet_ntoa(in)); + fmt::format_to(std::back_inserter(out), "{} Stale: {} Online: {} Admin: {}", newline, cle->GetStaleCounter(), cle->Online(), cle->Admin()); if (cle->LSID()) - fmt::format_to(out, "{} LSID: {} LSName: {} WorldAdmin: {}", newline, cle->LSID(), cle->LSName(), cle->WorldAdmin()); + fmt::format_to(std::back_inserter(out), "{} LSID: {} LSName: {} WorldAdmin: {}", newline, cle->LSID(), cle->LSName(), cle->WorldAdmin()); if (cle->CharID()) - fmt:format_to(out, "{} CharID: {} CharName: {} Zone: {} ({})", newline, cle->CharID(), cle->name(), ZoneName(cle->zone()), cle->zone()); + fmt::format_to(std::back_inserter(out), "{} CharID: {} CharName: {} Zone: {} ({})", newline, cle->CharID(), cle->name(), ZoneName(cle->zone()), cle->zone()); if (out.size() >= 3072) { - auto output = fmt::to_string(out); connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - output.c_str() + out.data() ); addnewline = false; out.clear(); @@ -313,14 +354,13 @@ void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnect iterator.Advance(); x++; } - fmt::format_to(out, "{}{} CLEs in memory. {} CLEs listed. numplayers = {}.", newline, x, y, numplayers); - auto output = fmt::to_string(out); + fmt::format_to(std::back_inserter(out), "{}{} CLEs in memory. {} CLEs listed. numplayers = {}.", newline, x, y, numplayers); connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - output.c_str() + out.data() ); } @@ -644,8 +684,8 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S int idx=-1; while(iterator.MoreElements()) { cle = iterator.GetData(); - const char* tmpZone = ZoneName(cle->zone()); + if ( (cle->Online() >= CLE_Status::Zoning) && (!cle->GetGM() || cle->Anon() != 1 || admin >= cle->Admin()) && @@ -1019,12 +1059,12 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* if (whom) whomlen = strlen(whom->whom); - fmt::memory_buffer out; - fmt::format_to(out, "Players on server:"); + std::vector out; + fmt::format_to(std::back_inserter(out), "Players on server:"); if (connection->IsConsole()) - fmt::format_to(out, "\r\n"); + fmt::format_to(std::back_inserter(out), "\r\n"); else - fmt::format_to(out, "\n"); + fmt::format_to(std::back_inserter(out), "\n"); iterator.Reset(); while (iterator.MoreElements()) { cle = iterator.GetData(); @@ -1120,23 +1160,22 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* else sprintf(line, " %s[%i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(), cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo); - fmt::format_to(out, line); + fmt::format_to(std::back_inserter(out), fmt::runtime(line)); if (out.size() >= 3584) { - auto output = fmt::to_string(out); connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - output.c_str() + out.data() ); out.clear(); } else { if (connection->IsConsole()) - fmt::format_to(out, "\r\n"); + fmt::format_to(std::back_inserter(out), "\r\n"); else - fmt::format_to(out, "\n"); + fmt::format_to(std::back_inserter(out), "\n"); } x++; if (x >= 20 && admin < AccountStatus::QuestTroupe) @@ -1146,24 +1185,24 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* } if (x >= 20 && admin < AccountStatus::QuestTroupe) - fmt::format_to(out, "too many results...20 players shown"); + fmt::format_to(std::back_inserter(out), "too many results...20 players shown"); else - fmt::format_to(out, "{} players online", x); + fmt::format_to(std::back_inserter(out), "{} players online", x); if (admin >= AccountStatus::GMAdmin && (whom == 0 || whom->gmlookup != 0xFFFF)) { if (connection->IsConsole()) - fmt::format_to(out, "\r\n"); + fmt::format_to(std::back_inserter(out), "\r\n"); else - fmt::format_to(out, "\n"); + fmt::format_to(std::back_inserter(out), "\n"); //console_list.SendConsoleWho(connection, to, admin, &output, &outsize, &outlen); } - auto output = fmt::to_string(out); + connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - output.c_str() + out.data() ); } diff --git a/world/clientlist.h b/world/clientlist.h index 2f9583784..2ab6be60d 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -57,9 +57,9 @@ public: ClientListEntry* FindCLEByCharacterID(uint32 iCharID); ClientListEntry* FindCLEByLSID(uint32 iLSID); ClientListEntry* GetCLE(uint32 iID); - void GetCLEIP(uint32 iIP); + void GetCLEIP(uint32 in_ip); uint32 GetCLEIPCount(uint32 iLSAccountID); - void DisconnectByIP(uint32 iIP); + void DisconnectByIP(uint32 in_ip); void CLCheckStale(); void CLEKeepAlive(uint32 numupdates, uint32* wid); void CLEAdd(uint32 iLSID, const char* iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = AccountStatus::Player, uint32 ip = 0, uint8 local=0); diff --git a/world/console.cpp b/world/console.cpp index 7afc0b073..d0d71afdb 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -27,10 +27,10 @@ #include "worlddb.h" #include "zonelist.h" #include "zoneserver.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/md5.h" #include "eqemu_api_world_data_service.h" -#include "world_store.h" +#include "../common/zone_store.h" #include extern ClientList client_list; @@ -164,7 +164,7 @@ void ConsoleWho( if (strcasecmp(arg.c_str(), "gm") == 0) { whom.gmlookup = 1; } - else if (StringIsNumber(arg)) { + else if (Strings::IsNumber(arg)) { if (whom.lvllow == 0xFFFF) { whom.lvllow = atoi(arg.c_str()); whom.lvlhigh = whom.lvllow; @@ -200,7 +200,7 @@ void ConsoleUptime( return; } - if (StringIsNumber(args[0]) && atoi(args[0].c_str()) > 0) { + if (Strings::IsNumber(args[0]) && atoi(args[0].c_str()) > 0) { auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct)); ServerUptime_Struct *sus = (ServerUptime_Struct *) pack->pBuffer; snprintf(sus->adminname, sizeof(sus->adminname), "*%s", connection->UserName().c_str()); @@ -285,7 +285,7 @@ void ConsoleEmote( 0, AccountStatus::Player, atoi(args[1].c_str()), - JoinString(join_args, " ").c_str() + Strings::Join(join_args, " ").c_str() ); } else { @@ -296,7 +296,7 @@ void ConsoleEmote( 0, AccountStatus::Player, atoi(args[1].c_str()), - JoinString(join_args, " ").c_str() + Strings::Join(join_args, " ").c_str() ); } else { @@ -305,7 +305,7 @@ void ConsoleEmote( 0, AccountStatus::Player, atoi(args[1].c_str()), - JoinString(join_args, " ").c_str() + Strings::Join(join_args, " ").c_str() ); } } @@ -361,7 +361,7 @@ void ConsoleTell( auto join_args = args; join_args.erase(join_args.begin(), join_args.begin() + 1); - zoneserver_list.SendChannelMessage(tmpname, to.c_str(), 7, 0, JoinString(join_args, " ").c_str()); + zoneserver_list.SendChannelMessage(tmpname, to.c_str(), 7, 0, Strings::Join(join_args, " ").c_str()); } /** @@ -382,7 +382,7 @@ void ConsoleBroadcast( char tmpname[64]; tmpname[0] = '*'; strcpy(&tmpname[1], connection->UserName().c_str()); - zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, JoinString(args, " ").c_str()); + zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, Strings::Join(args, " ").c_str()); } /** @@ -403,7 +403,40 @@ void ConsoleGMSay( char tmpname[64]; tmpname[0] = '*'; strcpy(&tmpname[1], connection->UserName().c_str()); - zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, JoinString(args, " ").c_str()); + zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, Strings::Join(args, " ").c_str()); +} + +/** + * @param connection + * @param command + * @param args + */ +void ConsoleGuildSay( + EQ::Net::ConsoleServerConnection *connection, + const std::string &command, + const std::vector &args +) +{ + if (args.size() < 1) { + return; + } + + auto from = args[0]; + auto guild_id = Strings::IsNumber(args[1]) ? std::stoul(args[1]) : 0; + if (!guild_id) { + return; + } + + auto join_args = args; + join_args.erase(join_args.begin(), join_args.begin() + 2); + + auto message = fmt::format( + "{} tells the guild, '{}'", + from, + Strings::Join(join_args, " ") + ); + + zoneserver_list.SendEmoteMessage(0, guild_id, AccountStatus::Player, Chat::Guild, message.c_str()); } /** @@ -424,7 +457,7 @@ void ConsoleOOC( char tmpname[64]; tmpname[0] = '*'; strcpy(&tmpname[1], connection->UserName().c_str()); - zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, JoinString(args, " ").c_str()); + zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, Strings::Join(args, " ").c_str()); } /** @@ -445,7 +478,7 @@ void ConsoleAuction( char tmpname[64]; tmpname[0] = '*'; strcpy(&tmpname[1], connection->UserName().c_str()); - zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, JoinString(args, " ").c_str()); + zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, Strings::Join(args, " ").c_str()); } /** @@ -551,7 +584,7 @@ void ConsoleZoneShutdown( ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer; pack->opcode = ServerOP_ZoneShutdown; strcpy(s->adminname, tmpname); - if (StringIsNumber(args[0])) { + if (Strings::IsNumber(args[0])) { s->ZoneServerID = atoi(args[0].c_str()); } else { @@ -595,7 +628,7 @@ void ConsoleZoneBootup( return; } - if (args[1].length() == 0 || !StringIsNumber(args[0])) { + if (args[1].length() == 0 || !Strings::IsNumber(args[0])) { connection->SendLine("Usage: zonebootup ZoneServerID# zoneshortname"); } else { @@ -603,13 +636,6 @@ void ConsoleZoneBootup( tmpname[0] = '*'; strcpy(&tmpname[1], connection->UserName().c_str()); - Log(Logs::Detail, - Logs::WorldServer, - "Console ZoneBootup: %s, %s, %s", - tmpname, - args[1].c_str(), - args[0].c_str()); - if (args.size() > 2) { zoneserver_list.SOPZoneBootup( tmpname, @@ -721,7 +747,7 @@ void ConsoleFlag( return; } - if (args[1].length() == 0 || !StringIsNumber(args[0])) { + if (args[1].length() == 0 || !Strings::IsNumber(args[0])) { connection->SendLine("Usage: flag [status] [accountname]"); } else { @@ -795,7 +821,7 @@ void ConsoleWorldShutdown( { if (args.size() == 2) { int32 time, interval; - if (StringIsNumber(args[0]) && StringIsNumber(args[1]) && ((time = atoi(args[0].c_str())) > 0) && + if (Strings::IsNumber(args[0]) && Strings::IsNumber(args[1]) && ((time = atoi(args[0].c_str())) > 0) && ((interval = atoi(args[1].c_str())) > 0)) { zoneserver_list.WorldShutDown(time, interval); } @@ -868,7 +894,7 @@ void ConsoleSignalCharByName( int update_identifier = 0; CZS->update_type = update_type; CZS->update_identifier = update_identifier; - CZS->signal = atoi(args[1].c_str()); + CZS->signal_id = atoi(args[1].c_str()); strn0cpy(CZS->client_name, (char *) args[0].c_str(), 64); zoneserver_list.SendPacket(pack); safe_delete(pack); @@ -951,6 +977,7 @@ void RegisterConsoleFunctions(std::unique_ptr& console) console->RegisterCall("emote", 50, "emote [zonename or charname or world] [type] [message]", std::bind(ConsoleEmote, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); console->RegisterCall("flag", 200, "flag [status] [accountname]", std::bind(ConsoleFlag, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); console->RegisterCall("gmsay", 50, "gmsay [message]", std::bind(ConsoleGMSay, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + console->RegisterCall("guildsay", 50, "guildsay [Character Name] [Guild ID] [Message]", std::bind(ConsoleGuildSay, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); console->RegisterCall("iplookup", 50, "IPLookup [name]", std::bind(ConsoleIpLookup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); console->RegisterCall("kick", 150, "kick [charname]", std::bind(ConsoleKick, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); console->RegisterCall("lock", 150, "lock", std::bind(ConsoleLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); diff --git a/world/console.old.cpp b/world/console.old.cpp index f2e848e57..59c782512 100644 --- a/world/console.old.cpp +++ b/world/console.old.cpp @@ -38,7 +38,7 @@ #include "../common/opcodemgr.h" #include "../common/rulesys.h" #include "../common/ruletypes.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "world_config.h" #include "zoneserver.h" #include "zonelist.h" diff --git a/world/dynamic_zone.cpp b/world/dynamic_zone.cpp index 945b41ec9..3a23c186d 100644 --- a/world/dynamic_zone.cpp +++ b/world/dynamic_zone.cpp @@ -197,6 +197,17 @@ void DynamicZone::HandleZoneMessage(ServerPacket* pack) zoneserver_list.SendPacket(pack); break; } + case ServerOP_DzSetSwitchID: + { + auto buf = reinterpret_cast(pack->pBuffer); + auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id); + if (dz) + { + dz->ProcessSetSwitchID(buf->dz_switch_id); + } + zoneserver_list.SendPacket(pack); + break; + } case ServerOP_DzAddRemoveMember: { auto buf = reinterpret_cast(pack->pBuffer); @@ -266,6 +277,16 @@ void DynamicZone::HandleZoneMessage(ServerPacket* pack) zoneserver_list.SendPacket(pack); break; } + case ServerOP_DzMovePC: + { + auto buf = reinterpret_cast(pack->pBuffer); + auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id); + if (dz && dz->HasMember(buf->character_id)) + { + zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack); + } + break; + } }; } diff --git a/world/dynamic_zone_manager.cpp b/world/dynamic_zone_manager.cpp index e71ca5cdc..2bed2a97e 100644 --- a/world/dynamic_zone_manager.cpp +++ b/world/dynamic_zone_manager.cpp @@ -164,3 +164,13 @@ void DynamicZoneManager::Process() fmt::format("id IN ({})", fmt::join(dynamic_zone_ids, ","))); } } + +void DynamicZoneManager::LoadTemplates() +{ + m_dz_templates.clear(); + auto dz_templates = DynamicZoneTemplatesRepository::All(content_db); + for (const auto& dz_template : dz_templates) + { + m_dz_templates[dz_template.id] = dz_template; + } +} diff --git a/world/dynamic_zone_manager.h b/world/dynamic_zone_manager.h index ce59f62ee..8db6bfd06 100644 --- a/world/dynamic_zone_manager.h +++ b/world/dynamic_zone_manager.h @@ -2,6 +2,7 @@ #define WORLD_DYNAMIC_ZONE_MANAGER_H #include "../common/timer.h" +#include "../common/repositories/dynamic_zone_templates_repository.h" #include #include #include @@ -20,13 +21,16 @@ public: void CacheAllFromDatabase(); void CacheNewDynamicZone(ServerPacket* pack); DynamicZone* CreateNew(DynamicZone& dz_request, const std::vector& members); + void LoadTemplates(); void Process(); void PurgeExpiredDynamicZones(); + const auto& GetTemplates() const { return m_dz_templates; } std::unordered_map> dynamic_zone_cache; private: Timer m_process_throttle_timer{}; + std::unordered_map m_dz_templates; }; #endif diff --git a/world/eqemu_api_world_data_service.cpp b/world/eqemu_api_world_data_service.cpp index 10bf6dab0..de8e2ffba 100644 --- a/world/eqemu_api_world_data_service.cpp +++ b/world/eqemu_api_world_data_service.cpp @@ -18,19 +18,22 @@ * */ +#include #include "clientlist.h" #include "cliententry.h" #include "eqemu_api_world_data_service.h" #include "zoneserver.h" #include "zonelist.h" #include "../common/database_schema.h" +#include "../common/zone_store.h" +#include "worlddb.h" extern ZSList zoneserver_list; extern ClientList client_list; void callGetZoneList(Json::Value &response) { - for (auto &zone : zoneserver_list.getZoneServerList()) { + for (auto &zone: zoneserver_list.getZoneServerList()) { Json::Value row; if (!zone->IsConnected()) { @@ -64,44 +67,44 @@ void callGetZoneList(Json::Value &response) void callGetDatabaseSchema(Json::Value &response) { Json::Value player_tables_json; - std::vector player_tables = DatabaseSchema::GetPlayerTables(); - for (const auto &table : player_tables) { + std::vector player_tables = DatabaseSchema::GetPlayerTables(); + for (const auto &table: player_tables) { player_tables_json.append(table); } Json::Value content_tables_json; std::vector content_tables = DatabaseSchema::GetContentTables(); - for (const auto &table : content_tables) { + for (const auto &table: content_tables) { content_tables_json.append(table); } Json::Value server_tables_json; - std::vector server_tables = DatabaseSchema::GetServerTables(); - for (const auto &table : server_tables) { + std::vector server_tables = DatabaseSchema::GetServerTables(); + for (const auto &table: server_tables) { server_tables_json.append(table); } Json::Value login_tables_json; - std::vector login_tables = DatabaseSchema::GetLoginTables(); - for (const auto &table : login_tables) { + std::vector login_tables = DatabaseSchema::GetLoginTables(); + for (const auto &table: login_tables) { login_tables_json.append(table); } Json::Value state_tables_json; - std::vector state_tables = DatabaseSchema::GetStateTables(); - for (const auto &table : state_tables) { + std::vector state_tables = DatabaseSchema::GetStateTables(); + for (const auto &table: state_tables) { state_tables_json.append(table); } Json::Value version_tables_json; std::vector version_tables = DatabaseSchema::GetVersionTables(); - for (const auto &table : version_tables) { + for (const auto &table: version_tables) { version_tables_json.append(table); } Json::Value character_table_columns_json; std::map character_table = DatabaseSchema::GetCharacterTables(); - for (const auto &ctc : character_table) { + for (const auto &ctc: character_table) { character_table_columns_json[ctc.first] = ctc.second; } @@ -123,17 +126,143 @@ void callGetClientList(Json::Value &response) client_list.GetClientList(response); } -void EQEmuApiWorldDataService::get(Json::Value &response, const std::vector &args) -{ - std::string method = args[0]; - if (method == "get_zone_list") { - callGetZoneList(response); - } - if (method == "get_database_schema") { - callGetDatabaseSchema(response); - } - if (method == "get_client_list") { - callGetClientList(response); +struct Reload { + std::string command{}; + uint16 opcode; + std::string desc{}; +}; + +std::vector reload_types = { + Reload{.command = "aa", .opcode = ServerOP_ReloadAAData, .desc = "Alternate Advancement"}, + Reload{.command = "alternate_currencies", .opcode = ServerOP_ReloadAlternateCurrencies, .desc = "Alternate Currencies"}, + Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"}, + Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"}, + Reload{.command = "doors", .opcode = ServerOP_ReloadDoors, .desc = "Doors"}, + Reload{.command = "dztemplates", .opcode = ServerOP_ReloadDzTemplates, .desc = "Dynamic Zone Templates"}, + Reload{.command = "ground_spawns", .opcode = ServerOP_ReloadGroundSpawns, .desc = "Ground Spawns"}, + Reload{.command = "level_mods", .opcode = ServerOP_ReloadLevelEXPMods, .desc = "Level Mods"}, + Reload{.command = "logs", .opcode = ServerOP_ReloadLogs, .desc = "Log Settings"}, + Reload{.command = "merchants", .opcode = ServerOP_ReloadMerchants, .desc = "Merchants"}, + Reload{.command = "npc_emotes", .opcode = ServerOP_ReloadNPCEmotes, .desc = "NPC Emotes"}, + Reload{.command = "objects", .opcode = ServerOP_ReloadObjects, .desc = "Objects"}, + Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"}, + Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"}, + Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"}, + Reload{.command = "tasks", .opcode = ServerOP_ReloadTasks, .desc = "Tasks"}, + Reload{.command = "titles", .opcode = ServerOP_ReloadTitles, .desc = "Titles"}, + Reload{.command = "traps", .opcode = ServerOP_ReloadTraps, .desc = "Traps"}, + Reload{.command = "variables", .opcode = ServerOP_ReloadVariables, .desc = "Variables"}, + Reload{.command = "veteran_rewards", .opcode = ServerOP_ReloadVeteranRewards, .desc = "Veteran Rewards"}, + Reload{.command = "world", .opcode = ServerOP_ReloadWorld, .desc = "World"}, + Reload{.command = "zone_points", .opcode = ServerOP_ReloadZonePoints, .desc = "Zone Points"}, +}; + +void getReloadTypes(Json::Value &response) +{ + for (auto &c: reload_types) { + Json::Value v; + + v["command"] = c.command; + v["opcode"] = c.opcode; + v["description"] = c.desc; + response.append(v); + } +} + + +void EQEmuApiWorldDataService::reload(Json::Value &r, const std::vector &args) +{ + std::vector commands{}; + commands.reserve(reload_types.size()); + for (auto &c: reload_types) { + commands.emplace_back(c.command); + } + + std::string command = !args[1].empty() ? args[1] : ""; + if (command.empty()) { + message(r, fmt::format("Need to provide a type to reload. Example(s) [{}]", Strings::Implode("|", commands))); + return; + } + + ServerPacket *pack = nullptr; + + bool found_command = false; + for (auto &c: reload_types) { + if (command == c.command) { + if (c.command == "world") { + uint8 global_repop = ReloadWorld::NoRepop; + + if (Strings::IsNumber(args[2])) { + global_repop = static_cast(std::stoul(args[2])); + + if (global_repop > ReloadWorld::ForceRepop) { + global_repop = ReloadWorld::ForceRepop; + } + } + + message( + r, + fmt::format( + "Attempting to reload Quests {}worldwide.", + ( + global_repop ? + ( + global_repop == ReloadWorld::Repop ? + "and repop NPCs " : + "and forcefully repop NPCs " + ) : + "" + ) + ) + ); + + pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); + auto RW = (ReloadWorld_Struct *) pack->pBuffer; + RW->global_repop = global_repop; + } + else { + pack = new ServerPacket(c.opcode, 0); + message(r, fmt::format("Reloading [{}] globally", c.desc)); + } + + found_command = true; + } + } + + if (!found_command) { + message(r, fmt::format("Need to provide a type to reload. Example(s) [{}]", Strings::Implode("|", commands))); + return; + } + + if (pack) { + zoneserver_list.SendPacket(pack); + } + + safe_delete(pack); +} + +void EQEmuApiWorldDataService::message(Json::Value &r, const std::string &message) +{ + r["message"] = message; +} + +void EQEmuApiWorldDataService::get(Json::Value &r, const std::vector &args) +{ + const std::string &m = args[0]; + if (m == "get_zone_list") { + callGetZoneList(r); + } + if (m == "get_database_schema") { + callGetDatabaseSchema(r); + } + if (m == "get_client_list") { + callGetClientList(r); + } + if (m == "get_reload_types") { + getReloadTypes(r); + } + if (m == "reload") { + reload(r, args); } } diff --git a/world/eqemu_api_world_data_service.h b/world/eqemu_api_world_data_service.h index 522e72a3f..b1bc7bbbc 100644 --- a/world/eqemu_api_world_data_service.h +++ b/world/eqemu_api_world_data_service.h @@ -25,7 +25,9 @@ class EQEmuApiWorldDataService { public: - static void get(Json::Value &response, const std::vector &args); + static void get(Json::Value &r, const std::vector &args); + static void reload(Json::Value &r, const std::vector &args); + static void message(Json::Value &r, const std::string &message); }; diff --git a/world/eql_config.cpp b/world/eql_config.cpp index 2b536c666..d35429aae 100644 --- a/world/eql_config.cpp +++ b/world/eql_config.cpp @@ -20,8 +20,8 @@ #include "worlddb.h" #include "launcher_link.h" #include "launcher_list.h" -#include "../common/string_util.h" -#include "world_store.h" +#include "../common/strings.h" +#include "../common/zone_store.h" #include #include diff --git a/world/eqw.cpp b/world/eqw.cpp index 3b480836d..7c37f3e45 100644 --- a/world/eqw.cpp +++ b/world/eqw.cpp @@ -25,7 +25,7 @@ #include "../common/races.h" #include "../common/classes.h" #include "../common/misc.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "zoneserver.h" #include "zonelist.h" #include "clientlist.h" diff --git a/world/expedition_database.cpp b/world/expedition_database.cpp index a3c4ca4d0..670418a87 100644 --- a/world/expedition_database.cpp +++ b/world/expedition_database.cpp @@ -60,9 +60,8 @@ void ExpeditionDatabase::PurgeExpiredExpeditions() if (!expedition_ids.empty()) { - auto joined_expedition_ids = fmt::join(expedition_ids, ","); - ExpeditionsRepository::DeleteWhere(database, fmt::format("id IN ({})", joined_expedition_ids)); - ExpeditionLockoutsRepository::DeleteWhere(database, fmt::format("expedition_id IN ({})", joined_expedition_ids)); + ExpeditionsRepository::DeleteWhere(database, fmt::format("id IN ({})", fmt::join(expedition_ids, ","))); + ExpeditionLockoutsRepository::DeleteWhere(database, fmt::format("expedition_id IN ({})", fmt::join(expedition_ids, ","))); DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids); } } diff --git a/world/launcher_link.cpp b/world/launcher_link.cpp index 8f3fa1aaf..0517d522f 100644 --- a/world/launcher_link.cpp +++ b/world/launcher_link.cpp @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/md5.h" #include "../common/packet_dump.h" #include "../common/servertalk.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/misc_functions.h" #include "worlddb.h" #include "eql_config.h" @@ -111,7 +111,7 @@ void LauncherLink::ProcessMessage(uint16 opcode, EQ::Net::Packet &p) zs.port = cur->port; zs.up = false; zs.starts = 0; - LogInfo("[{}]: Loaded zone [{}] on port [{}]", m_name.c_str(), cur->name.c_str(), zs.port); + LogInfo("[{}] Loaded zone [{}] on port [{}]", m_name.c_str(), cur->name.c_str(), zs.port); m_states[cur->name] = zs; } @@ -127,10 +127,10 @@ void LauncherLink::ProcessMessage(uint16 opcode, EQ::Net::Packet &p) std::map::iterator res; res = m_states.find(it->short_name); if (res == m_states.end()) { - LogInfo("[{}]: reported state for zone [{}] which it does not have", m_name.c_str(), it->short_name); + LogInfo("[{}] reported state for zone [{}] which it does not have", m_name.c_str(), it->short_name); break; } - LogInfo("[{}]: [{}] reported state [{}] ([{}] starts)", m_name.c_str(), it->short_name, it->running ? "STARTED" : "STOPPED", it->start_count); + LogInfo("[{}] [{}] reported state [{}] ([{}] starts)", m_name.c_str(), it->short_name, it->running ? "STARTED" : "STOPPED", it->start_count); res->second.up = it->running; res->second.starts = it->start_count; break; @@ -153,7 +153,7 @@ void LauncherLink::BootZone(const char *short_name, uint16 port) { zs.port = port; zs.up = false; zs.starts = 0; - LogInfo("[{}]: Loaded zone [{}] on port [{}]", m_name.c_str(), short_name, zs.port); + LogInfo("[{}] Loaded zone [{}] on port [{}]", m_name.c_str(), short_name, zs.port); m_states[short_name] = zs; StartZone(short_name, port); diff --git a/world/lfplist.cpp b/world/lfplist.cpp index 07e8c73ae..897fd9ab2 100644 --- a/world/lfplist.cpp +++ b/world/lfplist.cpp @@ -23,6 +23,7 @@ #include "zonelist.h" #include "../common/misc_functions.h" +#include "../common/classes.h" extern ClientList client_list; extern ZSList zoneserver_list; @@ -32,7 +33,7 @@ GroupLFP::GroupLFP(uint32 inLeaderID) { LeaderID = inLeaderID; for (auto &member : Members) { member.Name[0] = '\0'; - member.Class = 0; + member.Class = NO_CLASS; member.Level = 0; member.Zone = 0; } @@ -76,7 +77,7 @@ void GroupLFP::SetDetails(ServerLFPUpdate_Struct *Update) { Members[i].GuildID = CLE->GuildID(); } else { - Members[i].Class = 0; + Members[i].Class = NO_CLASS; Members[i].Level = 0; Members[i].Zone = 0; Members[i].GuildID = 0xFFFF; diff --git a/world/login_server.cpp b/world/login_server.cpp index edcdacf23..671fbad59 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/misc_functions.h" #include "../common/eq_packet_structs.h" #include "../common/packet_dump.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/eqemu_logsys.h" #include "login_server.h" #include "login_server_list.h" @@ -62,14 +62,14 @@ LoginServer::~LoginServer() void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) { const WorldConfig *Config = WorldConfig::get(); - LogNetcode("[ProcessUsertoWorldReqLeg] Received ServerPacket from LS OpCode {:#04x}", opcode); + LogNetcode("Received ServerPacket from LS OpCode {:#04x}", opcode); UsertoWorldRequestLegacy_Struct *utwr = (UsertoWorldRequestLegacy_Struct *) p.Data(); uint32 id = database.GetAccountIDFromLSID("eqemu", utwr->lsaccountid); int16 status = database.CheckStatus(id); LogDebug( - "[ProcessUsertoWorldReqLeg] id [{}] status [{}] account_id [{}] world_id [{}] from_id [{}] to_id [{}] ip [{}]", + "id [{}] status [{}] account_id [{}] world_id [{}] from_id [{}] to_id [{}] ip [{}]", id, status, utwr->lsaccountid, @@ -94,7 +94,7 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) if (Config->Locked) { if (status < (RuleI(GM, MinStatusToBypassLockedServer))) { LogDebug( - "[ProcessUsertoWorldReqLeg] Server locked and status is not high enough for account_id [{0}]", + "Server locked and status is not high enough for account_id [{0}]", utwr->lsaccountid ); utwrs->response = UserToWorldStatusWorldUnavail; @@ -105,21 +105,21 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) int32 x = Config->MaxClients; if ((int32) numplayers >= x && x != -1 && x != 255 && status < (RuleI(GM, MinStatusToBypassLockedServer))) { - LogDebug("[ProcessUsertoWorldReqLeg] World at capacity account_id [{0}]", utwr->lsaccountid); + LogDebug("World at capacity account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusWorldAtCapacity; SendPacket(&outpack); return; } if (status == -1) { - LogDebug("[ProcessUsertoWorldReqLeg] User suspended account_id [{0}]", utwr->lsaccountid); + LogDebug("User suspended account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusSuspended; SendPacket(&outpack); return; } if (status == -2) { - LogDebug("[ProcessUsertoWorldReqLeg] User banned account_id [{0}]", utwr->lsaccountid); + LogDebug("User banned account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusBanned; SendPacket(&outpack); return; @@ -127,14 +127,14 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) if (RuleB(World, EnforceCharacterLimitAtLogin)) { if (client_list.IsAccountInGame(utwr->lsaccountid)) { - LogDebug("[ProcessUsertoWorldReqLeg] User already online account_id [{0}]", utwr->lsaccountid); + LogDebug("User already online account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusAlreadyOnline; SendPacket(&outpack); return; } } - LogDebug("[ProcessUsertoWorldReqLeg] Sent response to account_id [{0}]", utwr->lsaccountid); + LogDebug("Sent response to account_id [{0}]", utwr->lsaccountid); SendPacket(&outpack); } @@ -142,14 +142,14 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) { const WorldConfig *Config = WorldConfig::get(); - LogNetcode("[ProcessUsertoWorldReq] Received ServerPacket from LS OpCode {:#04x}", opcode); + LogNetcode("Received ServerPacket from LS OpCode {:#04x}", opcode); UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct *) p.Data(); uint32 id = database.GetAccountIDFromLSID(utwr->login, utwr->lsaccountid); int16 status = database.CheckStatus(id); LogDebug( - "[ProcessUsertoWorldReq] id [{}] status [{}] account_id [{}] world_id [{}] from_id [{}] to_id [{}] ip [{}]", + "id [{}] status [{}] account_id [{}] world_id [{}] from_id [{}] to_id [{}] ip [{}]", id, status, utwr->lsaccountid, @@ -175,7 +175,7 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) if (Config->Locked == true) { if (status < (RuleI(GM, MinStatusToBypassLockedServer))) { LogDebug( - "[ProcessUsertoWorldReq] Server locked and status is not high enough for account_id [{0}]", + "Server locked and status is not high enough for account_id [{0}]", utwr->lsaccountid ); utwrs->response = UserToWorldStatusWorldUnavail; @@ -186,21 +186,21 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) int32 x = Config->MaxClients; if ((int32) numplayers >= x && x != -1 && x != 255 && status < (RuleI(GM, MinStatusToBypassLockedServer))) { - LogDebug("[ProcessUsertoWorldReq] World at capacity account_id [{0}]", utwr->lsaccountid); + LogDebug("World at capacity account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusWorldAtCapacity; SendPacket(&outpack); return; } if (status == -1) { - LogDebug("[ProcessUsertoWorldReq] User suspended account_id [{0}]", utwr->lsaccountid); + LogDebug("User suspended account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusSuspended; SendPacket(&outpack); return; } if (status == -2) { - LogDebug("[ProcessUsertoWorldReq] User banned account_id [{0}]", utwr->lsaccountid); + LogDebug("User banned account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusBanned; SendPacket(&outpack); return; @@ -208,14 +208,14 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) if (RuleB(World, EnforceCharacterLimitAtLogin)) { if (client_list.IsAccountInGame(utwr->lsaccountid)) { - LogDebug("[ProcessUsertoWorldReq] User already online account_id [{0}]", utwr->lsaccountid); + LogDebug("User already online account_id [{0}]", utwr->lsaccountid); utwrs->response = UserToWorldStatusAlreadyOnline; SendPacket(&outpack); return; } } - LogDebug("[ProcessUsertoWorldReq] Sent response to account_id [{0}]", utwr->lsaccountid); + LogDebug("Sent response to account_id [{0}]", utwr->lsaccountid); SendPacket(&outpack); } @@ -294,10 +294,27 @@ void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p) const WorldConfig *Config = WorldConfig::get(); LogNetcode("Received ServerPacket from LS OpCode {:#04x}", opcode); - LogInfo("Login server responded with FatalError"); + std::string error; + std::string reason; + if (p.Length() > 1) { - LogError("Error [{}]", (const char *) p.Data()); + error = fmt::format("{}", (const char *) p.Data()); } + + if (error.find("Worldserver Account / Password INVALID") != std::string::npos) { + reason = "Usually this indicates you do not have a valid [account] and [password] (worldserver) account associated with your loginserver configuration. "; + if (fmt::format("{}", m_loginserver_address).find("login.eqemulator.net") != std::string::npos) { + reason += "For Legacy EQEmulator connections, you need to register your server @ http://www.eqemulator.org/account/?LS"; + } + } + + LogInfo( + "Login server [{}:{}] responded with fatal error [{}] {}\n", + m_loginserver_address, + m_loginserver_port, + error, + reason + ); } void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p) @@ -473,7 +490,7 @@ bool LoginServer::Connect() [this](EQ::Net::ServertalkClient *client) { if (client) { LogInfo( - "Connected to Loginserver: [{0}:{1}]", + "Connected to Loginserver [{0}:{1}]", m_loginserver_address, m_loginserver_port ); @@ -482,7 +499,6 @@ bool LoginServer::Connect() zoneserver_list.SendLSZones(); m_statusupdate_timer = std::make_unique( - LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) { SendStatus(); } @@ -610,7 +626,7 @@ void LoginServer::SendInfo() } LogInfo( - "[LoginServer::SendInfo] protocol_version [{}] server_version [{}] long_name [{}] short_name [{}] account_name [{}] remote_ip_address [{}] local_ip [{}]", + "protocol_version [{}] server_version [{}] long_name [{}] short_name [{}] account_name [{}] remote_ip_address [{}] local_ip [{}]", l->protocol_version, l->server_version, l->server_long_name, diff --git a/world/main.cpp b/world/main.cpp index ee9f12705..b27ab7684 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -28,7 +28,7 @@ #include #include -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/eqemu_logsys.h" #include "../common/queue.h" #include "../common/timer.h" @@ -44,6 +44,7 @@ #include "../common/rulesys.h" #include "../common/platform.h" #include "../common/crash.h" +#include "../common/misc.h" #include "client.h" #include "worlddb.h" @@ -55,36 +56,29 @@ #include #else -#include #include "../common/unix.h" -#include -#include #include -#include #if not defined (FREEBSD) && not defined (DARWIN) union semun { - int val; + int val; struct semid_ds *buf; - ushort *array; - struct seminfo *__buf; - void *__pad; + ushort *array; + struct seminfo *__buf; + void *__pad; }; #endif #endif #include "../common/patches/patches.h" -#include "../common/random.h" #include "zoneserver.h" #include "login_server.h" #include "login_server_list.h" #include "world_config.h" -#include "zoneserver.h" #include "zonelist.h" #include "clientlist.h" #include "launcher_list.h" -#include "wguild_mgr.h" #include "lfplist.h" #include "adventure_manager.h" #include "ucs.h" @@ -94,17 +88,17 @@ union semun { #include "dynamic_zone_manager.h" #include "expedition_database.h" -#include "../common/net/servertalk_server.h" -#include "../zone/data_bucket.h" -#include "world_server_command_handler.h" +#include "world_server_cli.h" #include "../common/content/world_content_service.h" #include "../common/repositories/character_task_timers_repository.h" -#include "../common/repositories/merchantlist_temp_repository.h" -#include "world_store.h" +#include "../common/zone_store.h" #include "world_event_scheduler.h" #include "shared_task_manager.h" +#include "world_boot.h" +#include "../common/path_manager.h" -WorldStore world_store; + +ZoneStore zone_store; ClientList client_list; GroupLFPList LFPGroupList; ZSList zoneserver_list; @@ -123,9 +117,9 @@ const WorldConfig *Config; EQEmuLogSys LogSys; WorldContentService content_service; WebInterfaceList web_interface; +PathManager path; void CatchSignal(int sig_num); -void CheckForServerScript(bool force_download = false); inline void UpdateWindowTitle(std::string new_title) { @@ -134,148 +128,6 @@ inline void UpdateWindowTitle(std::string new_title) #endif } -void LoadDatabaseConnections() -{ - LogInfo( - "Connecting to MySQL [{}]@[{}]:[{}]", - Config->DatabaseUsername.c_str(), - Config->DatabaseHost.c_str(), - Config->DatabasePort - ); - - if (!database.Connect( - Config->DatabaseHost.c_str(), - Config->DatabaseUsername.c_str(), - Config->DatabasePassword.c_str(), - Config->DatabaseDB.c_str(), - Config->DatabasePort - )) { - LogError("Cannot continue without a database connection"); - - std::exit(1); - } - - /** - * Multi-tenancy: Content database - */ - if (!Config->ContentDbHost.empty()) { - if (!content_db.Connect( - Config->ContentDbHost.c_str(), - Config->ContentDbUsername.c_str(), - Config->ContentDbPassword.c_str(), - Config->ContentDbName.c_str(), - Config->ContentDbPort, - "content" - )) { - LogError("Cannot continue without a content database connection"); - std::exit(1); - } - } - else { - content_db.SetMysql(database.getMySQL()); - } - -} - -void CheckForXMLConfigUpgrade() -{ - if (!std::ifstream("eqemu_config.json") && std::ifstream("eqemu_config.xml")) { - CheckForServerScript(true); - if (system("perl eqemu_server.pl convert_xml")) {} - } - else { - CheckForServerScript(); - } -} - -void LoadServerConfig() -{ - LogInfo("Loading server configuration"); - if (!WorldConfig::LoadConfig()) { - LogError("Loading server configuration failed"); - std::exit(1); - } -} - -void RegisterLoginservers() -{ - if (Config->LoginCount == 0) { - if (Config->LoginHost.length()) { - loginserverlist.Add( - Config->LoginHost.c_str(), - Config->LoginPort, - Config->LoginAccount.c_str(), - Config->LoginPassword.c_str(), - Config->LoginLegacy - ); - LogInfo("Added loginserver [{}]:[{}]", Config->LoginHost.c_str(), Config->LoginPort); - } - } - else { - LinkedList loginlist = Config->loginlist; - LinkedListIterator iterator(loginlist); - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->LoginHost.length()) { - loginserverlist.Add( - iterator.GetData()->LoginHost.c_str(), - iterator.GetData()->LoginPort, - iterator.GetData()->LoginAccount.c_str(), - iterator.GetData()->LoginPassword.c_str(), - iterator.GetData()->LoginLegacy - ); - - LogInfo( - "Added loginserver [{}]:[{}]", - iterator.GetData()->LoginHost.c_str(), - iterator.GetData()->LoginPort - ); - } - iterator.Advance(); - } - } -} - -static void GMSayHookCallBackProcessWorld(uint16 log_category, std::string message) -{ - // Cut messages down to 4000 max to prevent client crash - if (!message.empty()) { - message = message.substr(0, 4000); - } - - // Replace Occurrences of % or MessageStatus will crash - find_replace(message, std::string("%"), std::string(".")); - - if (message.find('\n') != std::string::npos) { - auto message_split = SplitString(message, '\n'); - - for (size_t iter = 0; iter < message_split.size(); ++iter) { - zoneserver_list.SendEmoteMessage( - 0, - 0, - AccountStatus::QuestTroupe, - LogSys.GetGMSayColorFromCategory(log_category), - fmt::format( - " {}{}", - (iter == 0 ? " ---" : ""), - message_split[iter] - ).c_str() - ); - } - - return; - } - - zoneserver_list.SendEmoteMessage( - 0, - 0, - AccountStatus::QuestTroupe, - LogSys.GetGMSayColorFromCategory(log_category), - "%s", - message.c_str() - ); -} - /** * World process entrypoint * @@ -289,39 +141,21 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); set_exception_handler(); - /** - * Database version - */ - uint32 database_version = CURRENT_BINARY_DATABASE_VERSION; - uint32 bots_database_version = CURRENT_BINARY_BOTS_DATABASE_VERSION; - if (argc >= 2) { - if (strcasecmp(argv[1], "db_version") == 0) { - std::cout << "Binary Database Version: " << database_version << " : " << bots_database_version << std::endl; - return 0; - } + if (WorldBoot::HandleCommandInput(argc, argv)) { + return 0; } - /** - * Command handler - */ - if (argc > 1) { - LogSys.SilenceConsoleLogging(); + path.LoadPaths(); - WorldConfig::LoadConfig(); - Config = WorldConfig::get(); - - LoadDatabaseConnections(); - LogSys.EnableConsoleLogging(); - - WorldserverCommandHandler::CommandHandler(argc, argv); + if (!WorldBoot::LoadServerConfig()) { + return 0; } - CheckForXMLConfigUpgrade(); - LoadServerConfig(); + WorldBoot::CheckForXMLConfigUpgrade(); Config = WorldConfig::get(); - LogInfo("CURRENT_VERSION: [{}]", CURRENT_VERSION); + LogInfo("CURRENT_VERSION [{}]", CURRENT_VERSION); if (signal(SIGINT, CatchSignal) == SIG_ERR) { LogError("Could not set signal handler"); @@ -340,190 +174,30 @@ int main(int argc, char **argv) } #endif - RegisterLoginservers(); - LoadDatabaseConnections(); - - guild_mgr.SetDatabase(&database); - - // logging system init - auto logging = LogSys.SetDatabase(&database) - ->LoadLogDatabaseSettings(); - - if (RuleB(Logging, WorldGMSayLogging)) { - logging->SetGMSayHandler(&GMSayHookCallBackProcessWorld); + WorldBoot::RegisterLoginservers(); + WorldBoot::LoadDatabaseConnections(); + if (!WorldBoot::DatabaseLoadRoutines(argc, argv)) { + return 1; } - logging->StartFileLogs(); - - /** - * Parse simple CLI passes - */ - bool ignore_db = false; - if (argc >= 2) { - if (strcasecmp(argv[1], "ignore_db") == 0) { - ignore_db = true; - } - else { - std::cerr << "Error, unknown command line option" << std::endl; - return 1; - } - } - - if (!ignore_db) { - LogInfo("Checking Database Conversions"); - database.CheckDatabaseConversions(); - } - LogInfo("Loading variables"); - database.LoadVariables(); - - std::string hotfix_name; - if (database.GetVariable("hotfix_name", hotfix_name)) { - if (!hotfix_name.empty()) { - LogInfo("Current hotfix in use: [{}]", hotfix_name.c_str()); - } - } - - LogInfo("Purging expired data buckets"); - database.PurgeAllDeletedDataBuckets(); - - LogInfo("Loading zones"); - - world_store.LoadZones(); - - LogInfo("Clearing groups"); - database.ClearGroup(); - LogInfo("Clearing raids"); - database.ClearRaid(); - database.ClearRaidDetails(); - database.ClearRaidLeader(); - LogInfo("Clearing inventory snapshots"); - database.ClearInvSnapshots(); - LogInfo("Loading items"); - - if (!content_db.LoadItems(hotfix_name)) { - LogError("Error: Could not load item data. But ignoring"); - } - - LogInfo("Loading skill caps"); - if (!content_db.LoadSkillCaps(std::string(hotfix_name))) { - LogError("Error: Could not load skill cap data. But ignoring"); - } - - LogInfo("Loading guilds"); - guild_mgr.LoadGuilds(); - - //rules: - { - if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) { - LogInfo("Failed to process 'Orphaned Rules' update operation."); - } - - if (!RuleManager::Instance()->UpdateInjectedRules(&database, "default")) { - LogInfo("Failed to process 'Injected Rules' for ruleset 'default' update operation."); - } - - std::string tmp; - if (database.GetVariable("RuleSet", tmp)) { - LogInfo("Loading rule set [{}]", tmp.c_str()); - - if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) { - LogInfo("Failed to load ruleset [{}], falling back to defaults", tmp.c_str()); - } - } - else { - - if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { - LogInfo("No rule set configured, using default rules"); - } - else { - LogInfo("Loaded default rule set [default]", tmp.c_str()); - } - } - - if (!RuleManager::Instance()->RestoreRuleNotes(&database)) { - LogInfo("Failed to process 'Restore Rule Notes' update operation."); - } - } - - EQ::InitializeDynamicLookups(); - LogInfo("Initialized dynamic dictionary entries"); - - if (RuleB(World, ClearTempMerchantlist)) { - LogInfo("Clearing temporary merchant lists"); - database.ClearMerchantTemp(); - } - - LogInfo("Loading EQ time of day"); - TimeOfDay_Struct eqTime; - time_t realtime; - eqTime = database.LoadTime(realtime); - zoneserver_list.worldclock.SetCurrentEQTimeOfDay(eqTime, realtime); + // timers + Timer PurgeInstanceTimer(450000); + PurgeInstanceTimer.Start(450000); Timer EQTimeTimer(600000); EQTimeTimer.Start(600000); + // global loads LogInfo("Loading launcher list"); launcher_list.LoadList(); - - LogInfo("Deleted [{}] stale player corpses from database", database.DeleteStalePlayerCorpses()); - - LogInfo("Loading adventures"); - if (!adventure_manager.LoadAdventureTemplates()) { - LogInfo("Unable to load adventure templates"); - } - - if (!adventure_manager.LoadAdventureEntries()) { - LogInfo("Unable to load adventure templates"); - } - - adventure_manager.LoadLeaderboardInfo(); - - LogInfo("Purging expired dynamic zones and members"); - dynamic_zone_manager.PurgeExpiredDynamicZones(); - - LogInfo("Purging expired expeditions"); - ExpeditionDatabase::PurgeExpiredExpeditions(); - ExpeditionDatabase::PurgeExpiredCharacterLockouts(); - - LogInfo("Purging expired character task timers"); - CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()"); - - LogInfo("Purging expired instances"); - database.PurgeExpiredInstances(); - - Timer PurgeInstanceTimer(450000); - PurgeInstanceTimer.Start(450000); - - LogInfo("Loading dynamic zones"); - dynamic_zone_manager.CacheAllFromDatabase(); - - LogInfo("Loading char create info"); - content_db.LoadCharacterCreateAllocations(); - content_db.LoadCharacterCreateCombos(); - - LogInfo("Initializing [EventScheduler]"); - event_scheduler.SetDatabase(&database)->LoadScheduledEvents(); - - LogInfo("Initializing [WorldContentService]"); - content_service.SetDatabase(&database) - ->SetExpansionContext() - ->ReloadContentFlags(); - - LogInfo("Initializing [SharedTaskManager]"); - shared_task_manager.SetDatabase(&database) - ->SetContentDatabase(&content_db) - ->LoadTaskData() - ->LoadSharedTaskState(); - - shared_task_manager.PurgeExpiredSharedTasks(); + zoneserver_list.Init(); std::unique_ptr console; if (Config->TelnetEnabled) { - LogInfo("Console (TCP) listener started"); + LogInfo("Console (TCP) listener started on [{}:{}]", Config->TelnetIP, Config->TelnetTCPPort); console = std::make_unique(Config->TelnetIP, Config->TelnetTCPPort); RegisterConsoleFunctions(console); } - zoneserver_list.Init(); std::unique_ptr server_connection; server_connection = std::make_unique(); @@ -532,32 +206,44 @@ int main(int argc, char **argv) server_opts.ipv6 = false; server_opts.credentials = Config->SharedKey; server_connection->Listen(server_opts); - LogInfo("Server (TCP) listener started"); + LogInfo("Server (TCP) listener started on port [{}]", Config->WorldTCPPort); server_connection->OnConnectionIdentified( "Zone", [&console](std::shared_ptr connection) { - LogInfo("New Zone Server connection from [{2}] at [{0}:{1}]", - connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); - numzones++; zoneserver_list.Add(new ZoneServer(connection, console.get())); + + LogInfo( + "New Zone Server connection from [{}] at [{}:{}] zone_count [{}]", + connection->Handle()->RemoteIP(), + connection->Handle()->RemotePort(), + connection->GetUUID(), + numzones + ); } ); server_connection->OnConnectionRemoved( "Zone", [](std::shared_ptr connection) { - LogInfo("Removed Zone Server connection from [{0}]", - connection->GetUUID()); - numzones--; zoneserver_list.Remove(connection->GetUUID()); + + LogInfo( + "Removed Zone Server connection from [{}] total zone_count [{}]", + connection->GetUUID(), + numzones + ); } ); server_connection->OnConnectionIdentified( "Launcher", [](std::shared_ptr connection) { - LogInfo("New Launcher connection from [{2}] at [{0}:{1}]", - connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); + LogInfo( + "New Launcher connection from [{}] at [{}:{}]", + connection->Handle()->RemoteIP(), + connection->Handle()->RemotePort(), + connection->GetUUID() + ); launcher_list.Add(connection); } @@ -565,8 +251,10 @@ int main(int argc, char **argv) server_connection->OnConnectionRemoved( "Launcher", [](std::shared_ptr connection) { - LogInfo("Removed Launcher connection from [{0}]", - connection->GetUUID()); + LogInfo( + "Removed Launcher connection from [{0}]", + connection->GetUUID() + ); launcher_list.Remove(connection); } @@ -574,8 +262,11 @@ int main(int argc, char **argv) server_connection->OnConnectionIdentified( "QueryServ", [](std::shared_ptr connection) { - LogInfo("New Query Server connection from [{2}] at [{0}:{1}]", - connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); + LogInfo( + "New Query Server connection from [{}] at [{}:{}]", + connection->Handle()->RemoteIP(), + connection->Handle()->RemotePort(), + connection->GetUUID()); QSLink.AddConnection(connection); } @@ -583,8 +274,10 @@ int main(int argc, char **argv) server_connection->OnConnectionRemoved( "QueryServ", [](std::shared_ptr connection) { - LogInfo("Removed Query Server connection from [{0}]", - connection->GetUUID()); + LogInfo( + "Removed Query Server connection from [{}]", + connection->GetUUID() + ); QSLink.RemoveConnection(connection); } @@ -592,8 +285,12 @@ int main(int argc, char **argv) server_connection->OnConnectionIdentified( "UCS", [](std::shared_ptr connection) { - LogInfo("New UCS Server connection from [{2}] at [{0}:{1}]", - connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); + LogInfo( + "New UCS Server connection from [{}] at [{}:{}]", + connection->Handle()->RemoteIP(), + connection->Handle()->RemotePort(), + connection->GetUUID() + ); UCSLink.SetConnection(connection); @@ -603,7 +300,7 @@ int main(int argc, char **argv) server_connection->OnConnectionRemoved( "UCS", [](std::shared_ptr connection) { - LogInfo("Connection lost from UCS Server [{0}]", connection->GetUUID()); + LogInfo("Connection lost from UCS Server [{}]", connection->GetUUID()); auto ucs_connection = UCSLink.GetConnection(); @@ -617,8 +314,12 @@ int main(int argc, char **argv) server_connection->OnConnectionIdentified( "WebInterface", [](std::shared_ptr connection) { - LogInfo("New WebInterface Server connection from [{2}] at [{0}:{1}]", - connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); + LogInfo( + "New WebInterface Server connection from [{}] at [{}:{}]", + connection->Handle()->RemoteIP(), + connection->Handle()->RemotePort(), + connection->GetUUID() + ); web_interface.AddConnection(connection); } @@ -626,13 +327,17 @@ int main(int argc, char **argv) server_connection->OnConnectionRemoved( "WebInterface", [](std::shared_ptr connection) { - LogInfo("Removed WebInterface Server connection from [{0}]", - connection->GetUUID()); + LogInfo( + "Removed WebInterface Server connection from [{}]", + connection->GetUUID() + ); web_interface.RemoveConnection(connection); } ); + WorldBoot::CheckForPossibleConfigurationIssues(); + EQStreamManagerInterfaceOptions opts(9000, false, false); opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); @@ -658,12 +363,22 @@ int main(int argc, char **argv) eqsm.OnNewConnection( [&stream_identifier](std::shared_ptr stream) { stream_identifier.AddStream(stream); - LogInfo("New connection from IP {0}:{1}", stream->GetRemoteIP(), ntohs(stream->GetRemotePort())); + LogInfo( + "New [EverQuest Client] connection from IP [{}:{}]", + long2ip(stream->GetRemoteIP()), + ntohs(stream->GetRemotePort()) + ); } ); - while (RunLoops) { + auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); + + if (!RunLoops) { + EQ::EventLoop::Get().Shutdown(); + return; + } + eqs = nullptr; //give the stream identifier a chance to do its work.... @@ -672,7 +387,7 @@ int main(int argc, char **argv) //check the stream identifier for any now-identified streams while ((eqsi = stream_identifier.PopIdentified())) { //now that we know what patch they are running, start up their client object - struct in_addr in{}; + struct in_addr in {}; in.s_addr = eqsi->GetRemoteIP(); if (RuleB(World, UseBannedIPsTable)) { //Lieka: Check to see if we have the responsibility for blocking IPs. LogInfo("Checking inbound connection [{}] against BannedIPs table", inet_ntoa(in)); @@ -723,6 +438,7 @@ int main(int argc, char **argv) launcher_list.Process(); LFPGroupList.Process(); adventure_manager.Process(); + shared_task_manager.Process(); dynamic_zone_manager.Process(); if (InterserverTimer.Check()) { @@ -730,17 +446,20 @@ int main(int argc, char **argv) database.ping(); content_db.ping(); - std::string window_title = StringFormat( - "World: %s Clients: %i", - Config->LongName.c_str(), + std::string window_title = fmt::format( + "World [{}] Clients [{}]", + Config->LongName, client_list.GetClientCount() ); UpdateWindowTitle(window_title); } + }; + + EQ::Timer process_timer(loop_fn); + process_timer.Start(32, true); + + EQ::EventLoop::Get().Run(); - EQ::EventLoop::Get().Process(); - Sleep(5); - } LogInfo("World main loop completed"); LogInfo("Shutting down zone connections (if any)"); zoneserver_list.KillAll(); @@ -756,38 +475,3 @@ void CatchSignal(int sig_num) LogInfo("Caught signal [{}]", sig_num); RunLoops = false; } - -void UpdateWindowTitle(char *iNewTitle) -{ -#ifdef _WINDOWS - char tmp[500]; - if (iNewTitle) { - snprintf(tmp, sizeof(tmp), "World: %s", iNewTitle); - } - else { - snprintf(tmp, sizeof(tmp), "World"); - } - SetConsoleTitle(tmp); -#endif -} - -void CheckForServerScript(bool force_download) -{ - /* Fetch EQEmu Server script */ - if (!std::ifstream("eqemu_server.pl") || force_download) { - - if (force_download) { - std::remove("eqemu_server.pl"); - } /* Delete local before fetch */ - - std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl; -#ifdef _WIN32 - if(system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\"")); -#else - if (system( - "wget -N --no-check-certificate --quiet -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl" - )) {} -#endif - } -} - diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index 541f35712..1c539805a 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -6,6 +6,7 @@ #include "zonelist.h" #include "zoneserver.h" #include "shared_task_world_messaging.h" +#include "../common/rulesys.h" #include "../common/repositories/character_data_repository.h" #include "../common/repositories/character_task_timers_repository.h" #include "../common/repositories/shared_task_members_repository.h" @@ -19,6 +20,11 @@ extern ClientList client_list; extern ZSList zoneserver_list; +SharedTaskManager::SharedTaskManager() + : m_process_timer{ static_cast(RuleI(TaskSystem, SharedTasksWorldProcessRate)) } +{ +} + SharedTaskManager *SharedTaskManager::SetDatabase(Database *db) { SharedTaskManager::m_database = db; @@ -33,30 +39,6 @@ SharedTaskManager *SharedTaskManager::SetContentDatabase(Database *db) return this; } -std::vector SharedTaskManager::GetRequestMembers( - uint32 requestor_character_id, - const std::vector &characters -) -{ - std::vector request_members = {}; - request_members.reserve(characters.size()); - - for (const auto &character : characters) { - SharedTaskMember member = {}; - member.character_id = character.id; - member.character_name = character.name; - - // if the solo/raid/group member is a leader, make sure we tag it as such - if (character.id == requestor_character_id) { - member.is_leader = true; - } - - request_members.emplace_back(member); - } - - return request_members; -} - void SharedTaskManager::AttemptSharedTaskCreation( uint32 requested_task_id, uint32 requested_character_id, @@ -66,32 +48,23 @@ void SharedTaskManager::AttemptSharedTaskCreation( auto task = GetSharedTaskDataByTaskId(requested_task_id); if (task.id != 0 && task.type == TASK_TYPE_SHARED) { LogTasksDetail( - "[AttemptSharedTaskCreation] Found Shared Task ({}) [{}]", + "Found Shared Task ({}) [{}]", requested_task_id, task.title ); } // shared task validation + // todo: this should be online group/raid members only (avoid queries) auto request = SharedTask::GetRequestCharacters(*m_database, requested_character_id); - if (!CanRequestSharedTask(task.id, requested_character_id, request)) { - LogTasksDetail("[AttemptSharedTaskCreation] Shared task validation failed"); + if (!CanRequestSharedTask(task.id, request)) { + LogTasksDetail("Shared task validation failed"); return; } - auto request_members = GetRequestMembers(requested_character_id, request.characters); - if (!request_members.empty()) { - for (auto &m: request_members) { - LogTasksDetail( - "[AttemptSharedTaskCreation] Request Members ({})", - m.character_id - ); - } - } - - if (request_members.empty()) { - LogTasksDetail("[AttemptSharedTaskCreation] No additional request members found... Just leader"); - } + for (auto& m: request.members) { + LogTasksDetail("Request Members [{}]", m.character_name); + } // new shared task instance auto new_shared_task = SharedTask{}; @@ -110,12 +83,12 @@ void SharedTaskManager::AttemptSharedTaskCreation( // request timer lockouts std::vector task_timers; - task_timers.reserve(request_members.size()); + task_timers.reserve(request.members.size()); // persist members std::vector shared_task_db_members = {}; - shared_task_db_members.reserve(request_members.size()); - for (auto &m: request_members) { + shared_task_db_members.reserve(request.members.size()); + for (auto &m: request.members) { auto e = SharedTaskMembersRepository::NewEntity(); e.character_id = m.character_id; @@ -131,6 +104,7 @@ void SharedTaskManager::AttemptSharedTaskCreation( timer.character_id = m.character_id; timer.task_id = task.id; timer.timer_type = static_cast(TaskTimerType::Request); + timer.timer_group = task.request_timer_group; timer.expire_time = shared_task_entity.accepted_time + task.request_timer_seconds; task_timers.emplace_back(timer); @@ -153,6 +127,10 @@ void SharedTaskManager::AttemptSharedTaskCreation( e.activity_id = a.activityid; e.done_count = 0; e.max_done_count = a.goalcount; + e.step = a.step; + e.optional = a.optional; + e.req_activity_id = a.req_activity_id; + e.activity_state = ActivityState::ActivityHidden; shared_task_activity_state.emplace_back(e); } @@ -179,13 +157,13 @@ void SharedTaskManager::AttemptSharedTaskCreation( // set database data in memory to make it easier for any later referencing new_shared_task.SetTaskData(task); new_shared_task.SetTaskActivityData(activities); - new_shared_task.SetMembers(request_members); + new_shared_task.SetMembers(request.members); // add to shared tasks list - m_shared_tasks.emplace_back(new_shared_task); + auto& inserted = m_shared_tasks.emplace_back(new_shared_task); // send accept to members - for (auto &m: request_members) { + for (auto &m: request.members) { // only requester (leader) receives back the npc context to trigger task accept event uint32_t npc_context_id = m.character_id == requested_character_id ? npc_type_id : 0; SendAcceptNewSharedTaskPacket( @@ -197,84 +175,64 @@ void SharedTaskManager::AttemptSharedTaskCreation( } SendSharedTaskMemberListToAllMembers(&new_shared_task); + // check if task should immediately lock + HandleCompletedActivities(&inserted); + + LoadDynamicZoneTemplate(&inserted); + LogTasks( - "[AttemptSharedTaskCreation] shared_task_id [{}] created successfully | task_id [{}] member_count [{}] activity_count [{}] current tasks in state [{}]", + "shared_task_id [{}] created successfully | task_id [{}] member_count [{}] activity_count [{}] current tasks in state [{}]", new_shared_task.GetDbSharedTask().id, task.id, - request_members.size(), + request.members.size(), shared_task_activity_state.size(), m_shared_tasks.size() ); } -void SharedTaskManager::AttemptSharedTaskRemoval( - uint32 requested_task_id, - uint32 requested_character_id, - bool remove_from_db // inherited from zone logic - we're just passing through -) +void SharedTaskManager::RemoveMember(SharedTask* s, const SharedTaskMember& member, bool remove_from_db) { - auto task = GetSharedTaskDataByTaskId(requested_task_id); - if (task.id != 0 && task.type == TASK_TYPE_SHARED) { - LogTasksDetail( - "[AttemptSharedTaskRemoval] Found Shared Task data ({}) [{}]", - requested_task_id, - task.title - ); + LogTasksDetail("shared_task_id [{}] member [{}]", s->GetDbSharedTask().id, member.character_name); + + RemovePlayerFromSharedTask(s, member.character_id); + SendRemovePlayerFromSharedTaskPacket(member.character_id, s->GetDbSharedTask().task_id, remove_from_db); + + SendSharedTaskMemberRemovedToAllMembers(s, member.character_name); + + client_list.SendCharacterMessageID(member.character_id, Chat::Yellow, + TaskStr::PLAYER_REMOVED, {member.character_name, s->GetTaskData().title}); + + if (member.is_leader) { + ChooseNewLeader(s); } - auto t = FindSharedTaskByTaskIdAndCharacterId(requested_task_id, requested_character_id); - if (t) { - auto removed = t->FindMemberFromCharacterID(requested_character_id); - - // remove self - RemovePlayerFromSharedTask(t, requested_character_id); - SendRemovePlayerFromSharedTaskPacket( - requested_character_id, - requested_task_id, - remove_from_db - ); - - // inform clients of removal of self - SendSharedTaskMemberRemovedToAllMembers(t, removed.character_name); - - client_list.SendCharacterMessageID( - requested_character_id, Chat::Yellow, - SharedTaskMessage::PLAYER_HAS_BEEN_REMOVED, {removed.character_name, task.title} - ); - - if (removed.is_leader) { - ChooseNewLeader(t); - } + // todo: filter requirements + if (s->GetMembers().size() < s->GetTaskData().min_players) + { + SendMembersMessageID(s, Chat::Red, TaskStr::MIN_PLAYERS); + StartTerminateTimer(s); } } void SharedTaskManager::RemoveEveryoneFromSharedTask(SharedTask *t, uint32 requested_character_id) { // caller validates leader - LogTasksDetail("[RemoveEveryoneFromSharedTask] Leader [{}]", requested_character_id); + LogTasksDetail("Leader [{}]", requested_character_id); // inform clients of removal for (auto &m: t->GetMembers()) { LogTasksDetail( - "[RemoveEveryoneFromSharedTask] Sending removal to [{}] task_id [{}]", + "Sending removal to [{}] task_id [{}]", m.character_id, t->GetTaskData().id ); SendRemovePlayerFromSharedTaskPacket(m.character_id, t->GetTaskData().id, true); - client_list.SendCharacterMessageID( - m.character_id, Chat::Yellow, - SharedTaskMessage::YOU_HAVE_BEEN_REMOVED, {t->GetTaskData().title} - ); + client_list.SendCharacterMessageID(m.character_id, Chat::Yellow, TaskStr::YOU_REMOVED, {t->GetTaskData().title}); } - client_list.SendCharacterMessageID( - requested_character_id, - Chat::Red, - SharedTaskMessage::PLAYER_HAS_BEEN_REMOVED, - {"Everyone", t->GetTaskData().title} - ); + client_list.SendCharacterMessageID(requested_character_id, Chat::Red, TaskStr::PLAYER_REMOVED, {"Everyone", t->GetTaskData().title}); RemoveAllMembersFromDynamicZones(t); @@ -284,10 +242,31 @@ void SharedTaskManager::RemoveEveryoneFromSharedTask(SharedTask *t, uint32 reque PrintSharedTaskState(); } +void SharedTaskManager::Terminate(SharedTask& s, bool send_fail, bool erase) +{ + LogTasksDetail("shared task [{}]", s.GetDbSharedTask().id); + for (const auto& member : s.GetMembers()) + { + if (send_fail) + { + SendSharedTaskFailed(member.character_id, s.GetTaskData().id); + } + SendRemovePlayerFromSharedTaskPacket(member.character_id, s.GetTaskData().id, true); + client_list.SendCharacterMessageID(member.character_id, Chat::Yellow, TaskStr::HAS_ENDED, {s.GetTaskData().title}); + } + + RemoveAllMembersFromDynamicZones(&s); + + if (erase) + { + DeleteSharedTask(s.GetDbSharedTask().id); + } +} + void SharedTaskManager::DeleteSharedTask(int64 shared_task_id) { LogTasksDetail( - "[DeleteSharedTask] shared_task_id [{}]", + "shared_task_id [{}]", shared_task_id ); @@ -312,7 +291,7 @@ void SharedTaskManager::DeleteSharedTask(int64 shared_task_id) void SharedTaskManager::LoadSharedTaskState() { - LogTasksDetail("[LoadSharedTaskState] Restoring state from the database"); + LogTasksDetail("Restoring state from the database"); // load shared tasks std::vector shared_tasks = {}; @@ -346,7 +325,7 @@ void SharedTaskManager::LoadSharedTaskState() SharedTask ns = {}; LogTasksDetail( - "[LoadSharedTaskState] Loading shared_task_id [{}] task_id [{}]", + "Loading shared_task_id [{}] task_id [{}]", s.id, s.task_id ); @@ -357,7 +336,7 @@ void SharedTaskManager::LoadSharedTaskState() // set database task data for internal referencing auto task_data = GetSharedTaskDataByTaskId(s.task_id); - LogTasksDetail("[LoadSharedTaskState] [GetSharedTaskDataByTaskId] task_id [{}]", task_data.id); + LogTasksDetail("[GetSharedTaskDataByTaskId] task_id [{}]", task_data.id); ns.SetTaskData(task_data); @@ -384,7 +363,7 @@ void SharedTaskManager::LoadSharedTaskState() for (auto &ad: activities_data) { if (ad.taskid == s.task_id && ad.activityid == sta.activity_id) { LogTasksDetail( - "[LoadSharedTaskState] shared_task_id [{}] task_id [{}] activity_id [{}] done_count [{}] max_done_count (goalcount) [{}]", + "shared_task_id [{}] task_id [{}] activity_id [{}] done_count [{}] max_done_count (goalcount) [{}]", s.id, s.task_id, sta.activity_id, @@ -395,6 +374,10 @@ void SharedTaskManager::LoadSharedTaskState() e.max_done_count = ad.goalcount; e.completed_time = sta.completed_time; e.updated_time = sta.updated_time; + e.step = ad.step; + e.optional = ad.optional; + e.req_activity_id = ad.req_activity_id; + e.activity_state = sta.completed_time > 0 ? ActivityCompleted : ActivityHidden; } } @@ -426,7 +409,7 @@ void SharedTaskManager::LoadSharedTaskState() shared_task_members.emplace_back(member); LogTasksDetail( - "[LoadSharedTaskState] shared_task_id [{}] adding member character_id [{}] character_name [{}] is_leader [{}]", + "shared_task_id [{}] adding member character_id [{}] character_name [{}] is_leader [{}]", s.id, member.character_id, member.character_name, @@ -446,7 +429,7 @@ void SharedTaskManager::LoadSharedTaskState() ns.dynamic_zone_ids.emplace_back(static_cast(dz_entry.dynamic_zone_id)); LogTasksDetail( - "[LoadSharedTaskState] shared_task_id [{}] adding dynamic_zone_id [{}]", + "shared_task_id [{}] adding dynamic_zone_id [{}]", s.id, dz_entry.dynamic_zone_id ); @@ -454,7 +437,7 @@ void SharedTaskManager::LoadSharedTaskState() } LogTasks( - "[LoadSharedTaskState] Loaded shared task state | shared_task_id [{}] task_id [{}] task_title [{}] member_count [{}] state_activity_count [{}]", + "Loaded shared task state | shared_task_id [{}] task_id [{}] task_title [{}] member_count [{}] state_activity_count [{}]", s.id, task_data.id, task_data.title, @@ -468,7 +451,7 @@ void SharedTaskManager::LoadSharedTaskState() SetSharedTasks(shared_tasks); LogTasks( - "[LoadSharedTaskState] Loaded [{}] shared tasks", + "Loaded [{}] shared tasks", m_shared_tasks.size() ); @@ -480,7 +463,7 @@ SharedTaskManager *SharedTaskManager::LoadTaskData() m_task_data = TasksRepository::All(*m_content_database); m_task_activity_data = TaskActivitiesRepository::All(*m_content_database); - LogTasks("[LoadTaskData] Loaded tasks [{}] activities [{}]", m_task_data.size(), m_task_activity_data.size()); + LogTasks("Loaded tasks [{}] activities [{}]", m_task_data.size(), m_task_activity_data.size()); return this; } @@ -521,7 +504,7 @@ void SharedTaskManager::SharedTaskActivityUpdate( auto shared_task = FindSharedTaskByTaskIdAndCharacterId(task_id, source_character_id); if (shared_task) { LogTasksDetail( - "[SharedTaskActivityUpdate] shared_task_id [{}] character_id [{}] task_id [{}] activity_id [{}] done_count [{}]", + "shared_task_id [{}] character_id [{}] task_id [{}] activity_id [{}] done_count [{}]", shared_task->GetDbSharedTask().id, source_character_id, task_id, @@ -535,7 +518,7 @@ void SharedTaskManager::SharedTaskActivityUpdate( // discard updates out of bounds if (a.done_count == a.max_done_count) { LogTasksDetail( - "[SharedTaskActivityUpdate] done_count [{}] is greater than max [{}] discarding...", + "done_count [{}] is greater than max [{}] discarding...", done_count, a.max_done_count ); @@ -545,7 +528,7 @@ void SharedTaskManager::SharedTaskActivityUpdate( // if we are progressing if (a.done_count < done_count) { LogTasksDetail( - "[SharedTaskActivityUpdate] Propagating update for shared_task_id [{}] character_id [{}] task_id [{}] activity_id [{}] old_done_count [{}] new_done_count [{}]", + "Propagating update for shared_task_id [{}] character_id [{}] task_id [{}] activity_id [{}] old_done_count [{}] new_done_count [{}]", shared_task->GetDbSharedTask().id, source_character_id, task_id, @@ -565,6 +548,7 @@ void SharedTaskManager::SharedTaskActivityUpdate( // if the activity is done, lets mark it as such if (a.done_count == a.max_done_count) { a.completed_time = std::time(nullptr); + a.activity_state = ActivityState::ActivityCompleted; } // sync state as each update comes in (for now) @@ -576,7 +560,7 @@ void SharedTaskManager::SharedTaskActivityUpdate( shared_task->SetSharedTaskActivityState(shared_task->m_shared_task_activity_state); LogTasksDetail( - "[SharedTaskActivityUpdate] Debug done_count [{}]", + "Debug done_count [{}]", a.done_count ); @@ -607,7 +591,7 @@ void SharedTaskManager::SharedTaskActivityUpdate( } LogTasksDetail( - "[SharedTaskActivityUpdate] Discarding duplicate update for shared_task_id [{}] character_id [{}] task_id [{}] activity_id [{}] done_count [{}] ignore_quest_update [{}]", + "Discarding duplicate update for shared_task_id [{}] character_id [{}] task_id [{}] activity_id [{}] done_count [{}] ignore_quest_update [{}]", shared_task->GetDbSharedTask().id, source_character_id, task_id, @@ -618,35 +602,10 @@ void SharedTaskManager::SharedTaskActivityUpdate( } } - // check if completed - bool is_shared_task_completed = true; - for (auto &a : shared_task->m_shared_task_activity_state) { - if (a.done_count != a.max_done_count) { - is_shared_task_completed = false; - } - } - - // mark completed + // handle task locking and completion + bool is_shared_task_completed = HandleCompletedActivities(shared_task); if (is_shared_task_completed) { - auto t = shared_task->GetDbSharedTask(); - if (t.id > 0) { - LogTasksDetail( - "[SharedTaskActivityUpdate] Marking shared task [{}] completed", - shared_task->GetDbSharedTask().id - ); - - // set record - t.completion_time = std::time(nullptr); - t.is_locked = true; - // update database - SharedTasksRepository::UpdateOne(*m_database, t); - // update internally - shared_task->SetDbSharedTask(t); - // record completion - RecordSharedTaskCompletion(shared_task); - // replay timer lockouts - AddReplayTimers(shared_task); - } + HandleCompletedTask(shared_task); } } } @@ -737,14 +696,11 @@ void SharedTaskManager::SendRemovePlayerFromSharedTaskPacket( ) { // confirm shared task request: inform clients - auto p = std::make_unique( - ServerOP_SharedTaskAttemptRemove, - sizeof(ServerSharedTaskAttemptRemove_Struct) - ); + auto p = std::make_unique(ServerOP_SharedTaskQuit, sizeof(ServerSharedTaskQuit_Struct)); - auto d = reinterpret_cast(p->pBuffer); + auto d = reinterpret_cast(p->pBuffer); d->requested_character_id = character_id; - d->requested_task_id = task_id; + d->task_id = task_id; d->remove_from_db = remove_from_db; // get requested character zone server @@ -754,6 +710,20 @@ void SharedTaskManager::SendRemovePlayerFromSharedTaskPacket( } } +void SharedTaskManager::SendSharedTaskFailed(uint32_t character_id, uint32_t task_id) +{ + ServerPacket pack(ServerOP_SharedTaskFailed, sizeof(ServerSharedTaskCharacterTask_Struct)); + auto buf = reinterpret_cast(pack.pBuffer); + buf->character_id = character_id; + buf->task_id = task_id; + + ClientListEntry* cle = client_list.FindCLEByCharacterID(character_id); + if (cle && cle->Server()) + { + cle->Server()->SendPacket(&pack); + } +} + void SharedTaskManager::SendSharedTaskMemberList(uint32 character_id, const std::vector &members) { EQ::Net::DynamicPacket dyn_pack; @@ -840,10 +810,10 @@ void SharedTaskManager::PrintSharedTaskState() for (auto &s: m_shared_tasks) { auto task = GetSharedTaskDataByTaskId(s.GetDbSharedTask().task_id); - LogTasksDetail("[PrintSharedTaskState] # Shared Task"); + LogTasksDetail("# Shared Task"); LogTasksDetail( - "[PrintSharedTaskState] shared_task_id [{}] task_id [{}] task_title [{}] member_count [{}] state_activity_count [{}]", + "shared_task_id [{}] task_id [{}] task_title [{}] member_count [{}] state_activity_count [{}]", s.GetDbSharedTask().id, task.id, task.title, @@ -851,12 +821,12 @@ void SharedTaskManager::PrintSharedTaskState() s.GetActivityState().size() ); - LogTasksDetail("[PrintSharedTaskState] # Activities"); + LogTasksDetail("# Activities"); // activity state for (auto &a: s.m_shared_task_activity_state) { LogTasksDetail( - "[PrintSharedTaskState] -- activity_id [{}] done_count [{}] max_done_count [{}] completed_time [{}]", + "-- activity_id [{}] done_count [{}] max_done_count [{}] completed_time [{}]", a.activity_id, a.done_count, a.max_done_count, @@ -864,70 +834,28 @@ void SharedTaskManager::PrintSharedTaskState() ); } - LogTasksDetail("[PrintSharedTaskState] # Members"); + LogTasksDetail("# Members"); // members for (auto &m: s.m_members) { LogTasksDetail( - "[PrintSharedTaskState] -- character_id [{}] is_leader [{}]", + "-- character_id [{}] is_leader [{}]", m.character_id, m.is_leader ); } - LogTasksDetail("[PrintSharedTaskState] # Dynamic Zones"); + LogTasksDetail("# Dynamic Zones"); for (auto &dz_id: s.dynamic_zone_ids) { LogTasksDetail( - "[PrintSharedTaskState] -- dynamic_zone_id [{}]", + "-- dynamic_zone_id [{}]", dz_id ); } } } -void SharedTaskManager::RemovePlayerFromSharedTaskByPlayerName(SharedTask *s, const std::string &character_name) -{ - auto member = s->FindMemberFromCharacterName(character_name); - if (member.character_id == 0) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::IS_NOT_MEMBER, {character_name}); - return; - } - - LogTasksDetail( - "[RemovePlayerFromSharedTaskByPlayerName] shared_task_id [{}] character_name [{}]", - s->GetDbSharedTask().id, - character_name - ); - - auto leader = s->GetLeader(); // get leader now for msg in case leader is one removed - - RemovePlayerFromSharedTask(s, member.character_id); - SendRemovePlayerFromSharedTaskPacket( - member.character_id, - s->GetDbSharedTask().task_id, - true - ); - - SendSharedTaskMemberRemovedToAllMembers(s, member.character_name); - - // leader and removed player get server messages (leader sees two messages) - // results in double messages if leader removed self (live behavior) - client_list.SendCharacterMessageID( - leader.character_id, Chat::Yellow, - SharedTaskMessage::PLAYER_HAS_BEEN_REMOVED, {member.character_name, s->GetTaskData().title} - ); - - client_list.SendCharacterMessageID( - member.character_id, Chat::Yellow, - SharedTaskMessage::PLAYER_HAS_BEEN_REMOVED, {member.character_name, s->GetTaskData().title} - ); - - if (member.is_leader) { - ChooseNewLeader(s); - } -} - void SharedTaskManager::SendSharedTaskMemberListToAllMembers(SharedTask *s) { // serialize once so we don't re-serialize it for every member @@ -960,7 +888,7 @@ void SharedTaskManager::MakeLeaderByPlayerName(SharedTask *s, const std::string { auto new_leader = s->FindMemberFromCharacterName(character_name); if (new_leader.character_id == 0) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::IS_NOT_MEMBER, {character_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::IS_NOT_MEMBER, {character_name}); return; } @@ -969,7 +897,7 @@ void SharedTaskManager::MakeLeaderByPlayerName(SharedTask *s, const std::string std::vector members = s->GetMembers(); for (auto &m: members) { LogTasksDetail( - "[MakeLeaderByPlayerName] character_id [{}] m.character_id [{}]", + "character_id [{}] m.character_id [{}]", new_leader.character_id, m.character_id ); @@ -980,7 +908,7 @@ void SharedTaskManager::MakeLeaderByPlayerName(SharedTask *s, const std::string if (new_leader.character_id == m.character_id) { found_new_leader = true; LogTasksDetail( - "[MakeLeaderByPlayerName] shared_task_id [{}] character_name [{}]", + "shared_task_id [{}] character_name [{}]", s->GetDbSharedTask().id, character_name ); @@ -993,10 +921,7 @@ void SharedTaskManager::MakeLeaderByPlayerName(SharedTask *s, const std::string s->SetMembers(members); SaveMembers(s, members); SendSharedTaskMemberListToAllMembers(s); - SendMembersMessageID( - s, Chat::Yellow, SharedTaskMessage::PLAYER_NOW_LEADER, - {new_leader.character_name, s->GetTaskData().title} - ); + SendMembersMessageID(s, Chat::Yellow, TaskStr::PLAYER_NOW_LEADER, {new_leader.character_name, s->GetTaskData().title}); for (const auto &dz_id : s->dynamic_zone_ids) { auto dz = DynamicZone::FindDynamicZoneByID(dz_id); @@ -1029,7 +954,7 @@ void SharedTaskManager::InvitePlayerByPlayerName(SharedTask *s, const std::strin { auto character = CharacterDataRepository::GetWhere( *m_database, - fmt::format("`name` = '{}' LIMIT 1", EscapeString(player_name)) + fmt::format("`name` = '{}' LIMIT 1", Strings::Escape(player_name)) ); auto character_id = !character.empty() ? character.front().id : 0; @@ -1067,7 +992,7 @@ void SharedTaskManager::SendSharedTaskInvitePacket(SharedTask *s, int64 invited_ // get requested character zone server ClientListEntry *cle = client_list.FindCLEByCharacterID(invited_character_id); if (cle && cle->Server()) { - SendLeaderMessageID(s, Chat::Yellow, SharedTaskMessage::SEND_INVITE_TO, {cle->name()}); + SendLeaderMessageID(s, Chat::Yellow, TaskStr::SEND_INVITE_TO, {cle->name()}); cle->Server()->SendPacket(p.get()); } } @@ -1107,6 +1032,7 @@ void SharedTaskManager::AddPlayerByCharacterIdAndName( timer.character_id = character_id; timer.task_id = s->GetDbSharedTask().task_id; timer.timer_type = static_cast(TaskTimerType::Request); + timer.timer_group = s->GetTaskData().request_timer_group; timer.expire_time = expire_time; CharacterTaskTimersRepository::InsertOne(*m_database, timer); @@ -1123,6 +1049,12 @@ void SharedTaskManager::AddPlayerByCharacterIdAndName( SendSharedTaskMemberList(character_id, s->GetMembers()); // new member gets full member list s->AddCharacterToMemberHistory(character_id); + // min players should be the only thing to check, other failed reqs prevent player add + if (s->GetMembers().size() >= s->GetTaskData().min_players) + { + s->terminate_timer.Disable(); + } + // add to dzs tied to shared task for (const auto &dz_id : s->dynamic_zone_ids) { auto dz = DynamicZone::FindDynamicZoneByID(dz_id); @@ -1145,10 +1077,22 @@ SharedTask *SharedTaskManager::FindSharedTaskById(int64 shared_task_id) return nullptr; } +SharedTask* SharedTaskManager::FindSharedTaskByDzId(uint32_t dz_id) +{ + for (auto& s: m_shared_tasks) { + auto it = std::find(s.dynamic_zone_ids.begin(), s.dynamic_zone_ids.end(), dz_id); + if (it != s.dynamic_zone_ids.end()) { + return &s; + } + } + + return nullptr; +} + void SharedTaskManager::QueueActiveInvitation(int64 shared_task_id, int64 character_id) { LogTasksDetail( - "[QueueActiveInvitation] shared_task_id [{}] character_id [{}]", + "shared_task_id [{}] character_id [{}]", shared_task_id, character_id ); @@ -1163,7 +1107,7 @@ void SharedTaskManager::QueueActiveInvitation(int64 shared_task_id, int64 charac bool SharedTaskManager::IsInvitationActive(uint32 shared_task_id, uint32 character_id) { LogTasksDetail( - "[IsInvitationActive] shared_task_id [{}] character_id [{}]", + "shared_task_id [{}] character_id [{}]", shared_task_id, character_id ); @@ -1180,7 +1124,7 @@ bool SharedTaskManager::IsInvitationActive(uint32 shared_task_id, uint32 charact void SharedTaskManager::RemoveActiveInvitation(int64 shared_task_id, int64 character_id) { LogTasksDetail( - "[RemoveActiveInvitation] shared_task_id [{}] character_id [{}] pre_removal_count [{}]", + "shared_task_id [{}] character_id [{}] pre_removal_count [{}]", shared_task_id, character_id, m_active_invitations.size() @@ -1199,7 +1143,7 @@ void SharedTaskManager::RemoveActiveInvitation(int64 shared_task_id, int64 chara ); LogTasksDetail( - "[RemoveActiveInvitation] shared_task_id [{}] character_id [{}] post_removal_count [{}]", + "shared_task_id [{}] character_id [{}] post_removal_count [{}]", shared_task_id, character_id, m_active_invitations.size() @@ -1240,6 +1184,27 @@ void SharedTaskManager::CreateDynamicZone(SharedTask *shared_task, DynamicZone & } } +void SharedTaskManager::LoadDynamicZoneTemplate(SharedTask* s) +{ + const auto& task = s->GetTaskData(); + if (task.dz_template_id != 0) + { + auto it = dynamic_zone_manager.GetTemplates().find(task.dz_template_id); + if (it != dynamic_zone_manager.GetTemplates().end()) + { + DynamicZone dz(DynamicZoneType::Mission); + dz.LoadTemplate(it->second); + dz.SetMinPlayers(task.min_players); + dz.SetMaxPlayers(task.max_players); + if (task.duration > dz.GetDuration()) + { + dz.SetDuration(task.duration); + } + CreateDynamicZone(s, dz); + } + } +} + void SharedTaskManager::SendLeaderMessage(SharedTask *shared_task, int chat_type, const std::string &message) { if (!shared_task) { @@ -1317,11 +1282,30 @@ void SharedTaskManager::SendMembersMessageID( } } -bool SharedTaskManager::CanRequestSharedTask( - uint32_t task_id, - uint32_t character_id, - const SharedTaskRequestCharacters &request -) +std::vector SharedTaskManager::GetCharacterTimers( + const std::vector& character_ids, const TasksRepository::Tasks& task) +{ + // todo: consider caching character timers in world and zone to avoid queries + auto task_timers = CharacterTaskTimersRepository::GetWhere(*m_database, fmt::format( + SQL( + character_id IN ({}) + AND (task_id = {} + OR (timer_group > 0 AND timer_type = {} AND timer_group = {}) + OR (timer_group > 0 AND timer_type = {} AND timer_group = {})) + AND expire_time > NOW() ORDER BY timer_type ASC LIMIT 1 + ), + fmt::join(character_ids, ","), + task.id, + static_cast(TaskTimerType::Replay), + task.replay_timer_group, + static_cast(TaskTimerType::Request), + task.request_timer_group + )); + + return task_timers; +} + +bool SharedTaskManager::CanRequestSharedTask(uint32_t task_id, const SharedTaskRequest& request) { auto task = GetSharedTaskDataByTaskId(task_id); if (task.id == 0) { @@ -1334,38 +1318,15 @@ bool SharedTaskManager::CanRequestSharedTask( auto shared_task_members = FindCharactersInSharedTasks(request.character_ids); if (!shared_task_members.empty()) { // messages for every character already in a shared task - for (const auto &member : shared_task_members) { - auto it = std::find_if( - request.characters.begin(), request.characters.end(), - [&](const CharacterDataRepository::CharacterData &char_data) { - return char_data.id == member; - } - ); - - if (it != request.characters.end()) { - if (it->id == character_id) { - client_list.SendCharacterMessageID( - character_id, - Chat::Red, - SharedTaskMessage::NO_REQUEST_BECAUSE_HAVE_ONE - ); - } - else if (request.group_type == SharedTaskRequestGroupType::Group) { - client_list.SendCharacterMessageID( - character_id, - Chat::Red, - SharedTaskMessage::NO_REQUEST_BECAUSE_GROUP_HAS_ONE, - {it->name} - ); - } - else { - client_list.SendCharacterMessageID( - character_id, - Chat::Red, - SharedTaskMessage::NO_REQUEST_BECAUSE_RAID_HAS_ONE, - {it->name} - ); - } + for (const auto& it : shared_task_members) { + if (it.character_id == request.leader_id) { + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, TaskStr::REQUEST_HAVE); + } + else if (request.group_type == SharedTaskRequestGroupType::Group) { + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, TaskStr::REQUEST_GROUP_HAS, {it.character_name}); + } + else { + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, TaskStr::REQUEST_RAID_HAS, {it.character_name}); } } @@ -1373,51 +1334,42 @@ bool SharedTaskManager::CanRequestSharedTask( } // check if any party member's minimum level is too low (pre-2014 this was average level) - if (task.minlevel > 0 && request.lowest_level < task.minlevel) { - client_list.SendCharacterMessageID(character_id, Chat::Red, SharedTaskMessage::AVG_LVL_LOW); + if (task.min_level > 0 && request.lowest_level < task.min_level) { + client_list.SendCharacterMessage(request.leader_id, Chat::Red, TaskStr::Get(TaskStr::LVL_TOO_LOW)); return false; } // check if any party member's maximum level is too high (pre-2014 this was average level) - if (task.maxlevel > 0 && request.highest_level > task.maxlevel) { - client_list.SendCharacterMessageID(character_id, Chat::Red, SharedTaskMessage::AVG_LVL_HIGH); + if (task.max_level > 0 && request.highest_level > task.max_level) { + client_list.SendCharacterMessage(request.leader_id, Chat::Red, TaskStr::Get(TaskStr::LVL_TOO_HIGH)); return false; } // allow gm/dev bypass for minimum player count requirements - auto requester = client_list.FindCLEByCharacterID(character_id); + auto requester = client_list.FindCLEByCharacterID(request.leader_id); bool is_gm = (requester && requester->GetGM()); // check if party member count is below the minimum - if (!is_gm && task.min_players > 0 && request.characters.size() < task.min_players) { - client_list.SendCharacterMessageID( - character_id, - Chat::Red, - SharedTaskMessage::SHARED_TASK_NOT_MEET_MIN_NUM_PLAYER - ); + if (!is_gm && task.min_players > 0 && request.members.size() < task.min_players) { + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, TaskStr::MIN_PLAYERS); return false; } // check if party member count is above the maximum // todo: live creates the shared task but truncates members if it exceeds max (sorted by leader and raid group numbers) - if (task.max_players > 0 && request.characters.size() > task.max_players) { - client_list.SendCharacterMessageID(character_id, Chat::Red, SharedTaskMessage::PARTY_EXCEED_MAX_PLAYER); + if (task.max_players > 0 && request.members.size() > task.max_players) { + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, TaskStr::MAX_PLAYERS); return false; } // check if party level spread exceeds task's maximum if (task.level_spread > 0 && (request.highest_level - request.lowest_level) > task.level_spread) { - client_list.SendCharacterMessageID(character_id, Chat::Red, SharedTaskMessage::LVL_SPREAD_HIGH); + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, TaskStr::LVL_SPREAD_HIGH); return false; } // check if any party members have a replay or request timer for the task (limit 1, replay checked first) - auto character_task_timers = CharacterTaskTimersRepository::GetWhere( - *m_database, fmt::format( - "character_id IN ({}) AND task_id = {} AND expire_time > NOW() ORDER BY timer_type ASC LIMIT 1", - fmt::join(request.character_ids, ","), task_id - ) - ); + auto character_task_timers = GetCharacterTimers(request.character_ids, task); if (!character_task_timers.empty()) { auto timer_type = static_cast(character_task_timers.front().timer_type); @@ -1426,51 +1378,28 @@ bool SharedTaskManager::CanRequestSharedTask( auto hours = fmt::format_int((seconds / 3600) % 24).str(); auto mins = fmt::format_int((seconds / 60) % 60).str(); - if (character_task_timers.front().character_id == character_id) { + if (character_task_timers.front().character_id == request.leader_id) { if (timer_type == TaskTimerType::Replay) { - client_list.SendCharacterMessageID( - character_id, - Chat::Red, - SharedTaskMessage::YOU_MUST_WAIT_REPLAY_TIMER, {days, hours, mins} - ); + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, TaskStr::YOU_REPLAY_TIMER, {days, hours, mins}); } else if (timer_type == TaskTimerType::Request) { - client_list.SendCharacterMessage( - character_id, - Chat::Red, fmt::format( - SharedTaskMessage::GetEQStr(SharedTaskMessage::YOU_MUST_WAIT_REQUEST_TIMER), days, hours, mins - ) - ); + client_list.SendCharacterMessage(request.leader_id, Chat::Red, fmt::format( + TaskStr::Get(TaskStr::YOU_REQUEST_TIMER), days, hours, mins)); } } else { - auto it = std::find_if( - request.characters.begin(), request.characters.end(), - [&](const CharacterDataRepository::CharacterData &char_data) { - return char_data.id == character_task_timers.front().character_id; - } - ); + auto it = std::find_if(request.members.begin(), request.members.end(), + [&](const SharedTaskMember& member) { + return member.character_id == character_task_timers.front().character_id; + }); - if (it != request.characters.end() && timer_type == TaskTimerType::Replay) { - client_list.SendCharacterMessageID( - character_id, - Chat::Red, - SharedTaskMessage::PLAYER_MUST_WAIT_REPLAY_TIMER, - {it->name, days, hours, mins} - ); + if (it != request.members.end() && timer_type == TaskTimerType::Replay) { + client_list.SendCharacterMessageID(request.leader_id, Chat::Red, + TaskStr::PLAYER_REPLAY_TIMER, {it->character_name, days, hours, mins}); } - else if (it != request.characters.end() && timer_type == TaskTimerType::Request) { - client_list.SendCharacterMessage( - character_id, - Chat::Red, - fmt::format( - SharedTaskMessage::GetEQStr(SharedTaskMessage::PLAYER_MUST_WAIT_REQUEST_TIMER), - it->name, - days, - hours, - mins - ) - ); + else if (it != request.members.end() && timer_type == TaskTimerType::Request) { + client_list.SendCharacterMessage(request.leader_id, Chat::Red, fmt::format( + TaskStr::Get(TaskStr::PLAYER_REQUEST_TIMER), it->character_name, days, hours, mins)); } } @@ -1488,21 +1417,22 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: // check if task is locked if (s->GetDbSharedTask().is_locked) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::TASK_NOT_ALLOWING_PLAYERS_AT_TIME); + SendLeaderMessageID(s, Chat::Red, TaskStr::NOT_ALLOWING_PLAYERS); allow_invite = false; } // check if player is online and in cle (other checks require online) auto cle = client_list.FindCLEByCharacterID(character_id); if (!cle || !cle->Server()) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::PLAYER_NOT_ONLINE_TO_ADD, {player_name}); - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::COULD_NOT_BE_INVITED, {player_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::PLAYER_NOT_ONLINE, {player_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::COULD_NOT_BE_INVITED, {player_name}); return false; } player_name = cle->name(); // check if player is already in a shared task + // todo: do a memory search instead of query here auto shared_task_members = SharedTaskMembersRepository::GetWhere( *m_database, fmt::format("character_id = {} LIMIT 1", character_id) @@ -1511,10 +1441,10 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: if (!shared_task_members.empty()) { auto shared_task_id = shared_task_members.front().shared_task_id; if (shared_task_id == s->GetDbSharedTask().id) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::CANT_ADD_PLAYER_ALREADY_MEMBER, {player_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::PLAYER_ALREADY_MEMBER, {player_name}); } else { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::CANT_ADD_PLAYER_ALREADY_ASSIGNED, {player_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::PLAYER_ALREADY_ASSIGNED, {player_name}); } allow_invite = false; } @@ -1523,15 +1453,10 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: for (const auto &invite : m_active_invitations) { if (invite.character_id == character_id) { if (invite.shared_task_id == s->GetDbSharedTask().id) { - SendLeaderMessageID( - s, - Chat::Red, - SharedTaskMessage::PLAYER_ALREADY_OUTSTANDING_INVITATION_THIS, - {player_name} - ); + SendLeaderMessageID(s, Chat::Red, TaskStr::PLAYER_INVITED, {player_name}); } else { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::PLAYER_ALREADY_OUTSTANDING_ANOTHER, {player_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::PLAYER_INVITED_OTHER, {player_name}); } allow_invite = false; break; @@ -1540,11 +1465,7 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: // check if player has a replay or request timer lockout // todo: live allows characters with a request timer to be re-invited if they quit, but only until they zone? (investigate/edge case) - auto task_timers = CharacterTaskTimersRepository::GetWhere( - *m_database, fmt::format( - "character_id = {} AND task_id = {} AND expire_time > NOW() ORDER BY timer_type ASC LIMIT 1", - character_id, s->GetDbSharedTask().task_id - )); + auto task_timers = GetCharacterTimers({ character_id }, s->GetTaskData()); if (!task_timers.empty()) { auto timer_type = static_cast(task_timers.front().timer_type); @@ -1554,24 +1475,11 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: auto mins = fmt::format_int((seconds / 60) % 60).str(); if (timer_type == TaskTimerType::Replay) { - SendLeaderMessageID( - s, - Chat::Red, - SharedTaskMessage::CANT_ADD_PLAYER_REPLAY_TIMER, {player_name, days, hours, mins} - ); + SendLeaderMessageID(s, Chat::Red, TaskStr::CANT_ADD_PLAYER_REPLAY_TIMER, {player_name, days, hours, mins}); } else { - SendLeaderMessage( - s, - Chat::Red, - fmt::format( - SharedTaskMessage::GetEQStr(SharedTaskMessage::CANT_ADD_PLAYER_REQUEST_TIMER), - player_name, - days, - hours, - mins - ) - ); + SendLeaderMessage(s, Chat::Red, fmt::format( + TaskStr::Get(TaskStr::CANT_ADD_PLAYER_REQUEST_TIMER), player_name, days, hours, mins)); } allow_invite = false; @@ -1580,11 +1488,12 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: // check if task has maximum players if (s->GetTaskData().max_players > 0 && s->GetMembers().size() >= s->GetTaskData().max_players) { auto max = fmt::format_int(s->GetTaskData().max_players).str(); - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::CANT_ADD_PLAYER_MAX_PLAYERS, {max}); + SendLeaderMessageID(s, Chat::Red, TaskStr::CANT_ADD_MAX_PLAYERS, {max}); allow_invite = false; } // check if task would exceed max level spread + // todo: cache low/high levels on SharedTask to avoid query for offline members (also usable by RemoveMember) if (s->GetTaskData().level_spread > 0) { auto characters = CharacterDataRepository::GetWhere( *m_database, @@ -1594,8 +1503,8 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: ) ); - int lowest_level = cle->level(); - int highest_level = cle->level(); + auto lowest_level = static_cast(cle->level()); + auto highest_level = lowest_level; for (const auto &character : characters) { lowest_level = std::min(lowest_level, character.level); @@ -1604,29 +1513,29 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: if ((highest_level - lowest_level) > s->GetTaskData().level_spread) { auto max_spread = fmt::format_int(s->GetTaskData().level_spread).str(); - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::CANT_ADD_PLAYER_MAX_LEVEL_SPREAD, {max_spread}); + SendLeaderMessageID(s, Chat::Red, TaskStr::CANT_ADD_LVL_SPREAD, {max_spread}); allow_invite = false; } } // check if player is below minimum level of task (pre-2014 this was average level) - if (s->GetTaskData().minlevel > 0 && cle->level() < s->GetTaskData().minlevel) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::CANT_ADD_PLAYER_FALL_MIN_AVG_LEVEL); + if (s->GetTaskData().min_level > 0 && cle->level() < s->GetTaskData().min_level) { + SendLeaderMessage(s, Chat::Red, TaskStr::Get(TaskStr::CANT_ADD_MIN_LEVEL)); allow_invite = false; } // check if player is above maximum level of task (pre-2014 this was average level) - if (s->GetTaskData().maxlevel > 0 && cle->level() > s->GetTaskData().maxlevel) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::CANT_ADD_PLAYER_MAX_AVERAGE_LEVEL); + if (s->GetTaskData().max_level > 0 && cle->level() > s->GetTaskData().max_level) { + SendLeaderMessage(s, Chat::Red, TaskStr::Get(TaskStr::CANT_ADD_MAX_LEVEL)); allow_invite = false; } if (!allow_invite) { if (!accepted) { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::COULD_NOT_BE_INVITED, {player_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::COULD_NOT_BE_INVITED, {player_name}); } else { - SendLeaderMessageID(s, Chat::Red, SharedTaskMessage::ACCEPTED_OFFER_TO_JOIN_BUT_COULD_NOT, {player_name}); + SendLeaderMessageID(s, Chat::Red, TaskStr::COULD_NOT_JOIN, {player_name}); } } @@ -1685,57 +1594,56 @@ void SharedTaskManager::RecordSharedTaskCompletion(SharedTask *s) void SharedTaskManager::AddReplayTimers(SharedTask *s) { if (s->GetTaskData().replay_timer_seconds > 0) { - auto expire_time = s->GetDbSharedTask().accepted_time + s->GetTaskData().replay_timer_seconds; - auto seconds = expire_time - std::time(nullptr); - if (seconds > 0) // not already expired - { - std::vector task_timers; + auto seconds = s->GetTaskData().replay_timer_seconds; + auto expire_time = std::time(nullptr) + seconds; - // on live past members of the shared task also receive lockouts (use member history) - for (const auto &member_id : s->member_id_history) { - auto timer = CharacterTaskTimersRepository::NewEntity(); - timer.character_id = member_id; - timer.task_id = s->GetTaskData().id; - timer.timer_type = static_cast(TaskTimerType::Replay); - timer.expire_time = expire_time; + std::vector task_timers; - task_timers.emplace_back(timer); + // on live past members of the shared task also receive lockouts (use member history) + for (const auto &member_id : s->member_id_history) { + auto timer = CharacterTaskTimersRepository::NewEntity(); + timer.character_id = member_id; + timer.task_id = s->GetTaskData().id; + timer.timer_type = static_cast(TaskTimerType::Replay); + timer.timer_group = s->GetTaskData().replay_timer_group; + timer.expire_time = expire_time; - client_list.SendCharacterMessage( - member_id, - Chat::Yellow, - fmt::format( - SharedTaskMessage::GetEQStr(SharedTaskMessage::RECEIVED_REPLAY_TIMER), - s->GetTaskData().title, - fmt::format_int(seconds / 86400).c_str(), // days - fmt::format_int((seconds / 3600) % 24).c_str(), // hours - fmt::format_int((seconds / 60) % 60).c_str() // minutes - ) - ); - } + task_timers.emplace_back(timer); - if (!task_timers.empty()) { - // replay timers replace any existing timer (even if it expires sooner) - // this can occur if a player has a timer for being a past member of - // a shared task but joined another before the first was completed - CharacterTaskTimersRepository::DeleteWhere( - *m_database, - fmt::format( - "task_id = {} AND character_id IN ({})", - s->GetTaskData().id, fmt::join(s->member_id_history, ",") - ) - ); + client_list.SendCharacterMessage( + member_id, + Chat::Yellow, + fmt::format( + TaskStr::Get(TaskStr::RECEIVED_REPLAY_TIMER), + s->GetTaskData().title, + fmt::format_int(seconds / 86400).c_str(), // days + fmt::format_int((seconds / 3600) % 24).c_str(), // hours + fmt::format_int((seconds / 60) % 60).c_str() // minutes + ) + ); + } - CharacterTaskTimersRepository::InsertMany(*m_database, task_timers); - } + if (!task_timers.empty()) { + // replay timers replace any existing timer (even if it expires sooner) + // this can occur if a player has a timer for being a past member of + // a shared task but joined another before the first was completed + CharacterTaskTimersRepository::DeleteWhere(*m_database, fmt::format( + "(task_id = {} OR (timer_group > 0 AND timer_group = {})) AND timer_type = {} AND character_id IN ({})", + s->GetTaskData().id, + s->GetTaskData().replay_timer_group, + static_cast(TaskTimerType::Replay), + fmt::join(s->member_id_history, ",") + )); + + CharacterTaskTimersRepository::InsertMany(*m_database, task_timers); } } } // memory search -std::vector SharedTaskManager::FindCharactersInSharedTasks(const std::vector &find_characters) +std::vector SharedTaskManager::FindCharactersInSharedTasks(const std::vector &find_characters) { - std::vector characters = {}; + std::vector characters = {}; for (auto &s: m_shared_tasks) { // loop through members @@ -1744,7 +1652,7 @@ std::vector SharedTaskManager::FindCharactersInSharedTasks(const std:: for (auto &find_character_id: find_characters) { // found character, add to list if (find_character_id == m.character_id) { - characters.emplace_back(m.character_id); + characters.emplace_back(m); } } } @@ -1808,13 +1716,105 @@ void SharedTaskManager::SetSharedTasks(const std::vector &shared_tas SharedTaskManager *SharedTaskManager::PurgeExpiredSharedTasks() { + std::vector delete_tasks; + auto now = std::time(nullptr); for (auto &s: m_shared_tasks) { if (s.GetDbSharedTask().expire_time > 0 && s.GetDbSharedTask().expire_time <= now) { - LogTasksDetail("[PurgeExpiredSharedTasks] Deleting expired task [{}]", s.GetDbSharedTask().id); - DeleteSharedTask(s.GetDbSharedTask().id); + LogTasksDetail("Deleting expired task [{}]", s.GetDbSharedTask().id); + delete_tasks.push_back(s.GetDbSharedTask().id); } } + for (int64_t shared_task_id : delete_tasks) + { + DeleteSharedTask(shared_task_id); + } + return this; } + +void SharedTaskManager::LockTask(SharedTask* s, bool lock) +{ + bool is_locked = (s->GetDbSharedTask().is_locked != 0); + if (is_locked != lock) + { + auto db_task = s->GetDbSharedTask(); + db_task.is_locked = lock; + SharedTasksRepository::UpdateOne(*m_database, db_task); + s->SetDbSharedTask(db_task); + + if (lock) + { + SendLeaderMessageID(s, Chat::Yellow, TaskStr::TASK_LOCKED); + } + } +} + +bool SharedTaskManager::HandleCompletedActivities(SharedTask* s) +{ + auto states = s->GetActivityState(); + + // activity state holds both source data and current state + auto res = Tasks::GetActiveElements(states, states, states.size()); + + // completion locks are silent + auto it = std::find(res.active.begin(), res.active.end(), s->GetTaskData().lock_activity_id); + if (!res.is_task_complete && it != res.active.end()) + { + LockTask(s, true); + } + + return res.is_task_complete; +} + +void SharedTaskManager::HandleCompletedTask(SharedTask* s) +{ + auto db_task = s->GetDbSharedTask(); + if (db_task.completion_time > 0) + { + LogTasksDetail("shared task [{}] already completed", db_task.id); + return; + } + + LogTasksDetail("Marking shared task [{}] completed", db_task.id); + db_task.completion_time = std::time(nullptr); + db_task.is_locked = true; + SharedTasksRepository::UpdateOne(*m_database, db_task); + s->SetDbSharedTask(db_task); + + RecordSharedTaskCompletion(s); + + AddReplayTimers(s); +} + +void SharedTaskManager::StartTerminateTimer(SharedTask* s) +{ + s->terminate_timer.Start(RuleI(TaskSystem, SharedTasksTerminateTimerMS)); + SendMembersMessageID(s, Chat::Red, TaskStr::REQS_TWO_MIN); +} + +void SharedTaskManager::Process() +{ + if (!m_process_timer.Check()) + { + return; + } + + std::vector delete_tasks; + for (auto& shared_task : m_shared_tasks) + { + if (shared_task.GetMembers().empty() || shared_task.terminate_timer.Check() || shared_task.IsExpired()) + { + Terminate(shared_task, false, false); + + // avoid erasing from m_shared_tasks while iterating it + delete_tasks.push_back(shared_task.GetDbSharedTask().id); + } + } + + for (int64_t shared_task_id : delete_tasks) + { + DeleteSharedTask(shared_task_id); + } +} diff --git a/world/shared_task_manager.h b/world/shared_task_manager.h index 1bbd071cd..3f41ef7be 100644 --- a/world/shared_task_manager.h +++ b/world/shared_task_manager.h @@ -3,6 +3,8 @@ #include "../common/database.h" #include "../common/shared_tasks.h" +#include "../common/timer.h" +#include "../common/repositories/character_task_timers_repository.h" class DynamicZone; @@ -19,6 +21,8 @@ struct SharedTaskActiveInvitation { class SharedTaskManager { public: + SharedTaskManager(); + SharedTaskManager *SetDatabase(Database *db); SharedTaskManager *SetContentDatabase(Database *db); @@ -32,15 +36,8 @@ public: TasksRepository::Tasks GetSharedTaskDataByTaskId(uint32 task_id); std::vector GetSharedTaskActivityDataByTaskId(uint32 task_id); - // gets group / raid members belonging to requested character - std::vector GetRequestMembers( - uint32 requestor_character_id, - const std::vector &characters - ); - // client attempting to create a shared task void AttemptSharedTaskCreation(uint32 requested_task_id, uint32 requested_character_id, uint32 npc_type_id); - void AttemptSharedTaskRemoval(uint32 requested_task_id, uint32 requested_character_id, bool remove_from_db); // shared task activity update middleware void SharedTaskActivityUpdate( @@ -53,13 +50,16 @@ public: SharedTask *FindSharedTaskByTaskIdAndCharacterId(uint32 task_id, uint32 character_id); SharedTask *FindSharedTaskById(int64 shared_task_id); + SharedTask* FindSharedTaskByDzId(uint32_t dz_id); void DeleteSharedTask(int64 shared_task_id); void SaveSharedTaskActivityState(int64 shared_task_id, std::vector activity_state); bool IsSharedTaskLeader(SharedTask *s, uint32 character_id); + void LockTask(SharedTask* s, bool lock); void SendAcceptNewSharedTaskPacket(uint32 character_id, uint32 task_id, uint32_t npc_context_id, int accept_time); void SendRemovePlayerFromSharedTaskPacket(uint32 character_id, uint32 task_id, bool remove_from_db); + void SendSharedTaskFailed(uint32_t character_id, uint32_t task_id); void SendSharedTaskMemberList(uint32 character_id, const std::vector &members); void SendSharedTaskMemberList(uint32 character_id, const EQ::Net::DynamicPacket &serialized_members); void SendSharedTaskMemberChange( @@ -70,9 +70,13 @@ public: ); void RemovePlayerFromSharedTask(SharedTask *s, uint32 character_id); void PrintSharedTaskState(); - void RemovePlayerFromSharedTaskByPlayerName(SharedTask *s, const std::string &character_name); + void Process(); + void RemoveMember(SharedTask* s, const SharedTaskMember& member, bool remove_from_db); void RemoveEveryoneFromSharedTask(SharedTask *s, uint32 requested_character_id); + // caller is responsible for removing from db/cache if erase is false + void Terminate(SharedTask& s, bool send_fail, bool erase); + void MakeLeaderByPlayerName(SharedTask *s, const std::string &character_name); void AddPlayerByCharacterIdAndName(SharedTask *s, int64 character_id, const std::string &character_name); void InvitePlayerByPlayerName(SharedTask *s, const std::string &player_name); @@ -113,10 +117,18 @@ protected: // store a reference of active invitations that have been sent to players std::vector m_active_invitations{}; + Timer m_process_timer; + + std::vector GetCharacterTimers( + const std::vector& character_ids, const TasksRepository::Tasks& task); + void AddReplayTimers(SharedTask *s); bool CanAddPlayer(SharedTask *s, uint32_t character_id, std::string player_name, bool accepted); - bool CanRequestSharedTask(uint32_t task_id, uint32_t character_id, const SharedTaskRequestCharacters &request); + bool CanRequestSharedTask(uint32_t task_id, const SharedTaskRequest& request); void ChooseNewLeader(SharedTask *s); + bool HandleCompletedActivities(SharedTask* s); + void HandleCompletedTask(SharedTask* s); + void LoadDynamicZoneTemplate(SharedTask* s); void SendSharedTaskMemberListToAllMembers(SharedTask *s); void SendSharedTaskMemberAddedToAllMembers(SharedTask *s, const std::string &player_name); void SendSharedTaskMemberRemovedToAllMembers(SharedTask *s, const std::string &player_name); @@ -124,9 +136,10 @@ protected: void SendSharedTaskInvitePacket(SharedTask *s, int64 invited_character_id); void RecordSharedTaskCompletion(SharedTask *s); void RemoveAllMembersFromDynamicZones(SharedTask *s); + void StartTerminateTimer(SharedTask* s); // memory search - std::vector FindCharactersInSharedTasks(const std::vector &find_characters); + std::vector FindCharactersInSharedTasks(const std::vector &find_characters); }; #endif //EQEMU_SHARED_TASK_MANAGER_H diff --git a/world/shared_task_world_messaging.cpp b/world/shared_task_world_messaging.cpp index 26da007f2..a9f513592 100644 --- a/world/shared_task_world_messaging.cpp +++ b/world/shared_task_world_messaging.cpp @@ -38,21 +38,22 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) break; } - case ServerOP_SharedTaskAttemptRemove: { - auto *r = (ServerSharedTaskAttemptRemove_Struct *) pack->pBuffer; + case ServerOP_SharedTaskQuit: { + auto *r = (ServerSharedTaskQuit_Struct *) pack->pBuffer; LogTasksDetail( - "[ServerOP_SharedTaskAttemptRemove] Received request from character [{}] task_id [{}] remove_from_db [{}]", - r->requested_character_id, - r->requested_task_id, - r->remove_from_db - ); - - shared_task_manager.AttemptSharedTaskRemoval( - r->requested_task_id, + "[ServerOP_SharedTaskQuit] Received request from character [{}] task_id [{}] remove_from_db [{}]", r->requested_character_id, + r->task_id, r->remove_from_db ); + auto s = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(r->task_id, r->requested_character_id); + if (s) { + auto member = s->FindMemberFromCharacterID(r->requested_character_id); + if (member.character_id != 0) { + shared_task_manager.RemoveMember(s, member, r->remove_from_db); + } + } break; } case ServerOP_SharedTaskKickPlayers: { @@ -67,10 +68,7 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) if (t) { auto leader = t->GetLeader(); if (leader.character_id != r->source_character_id) { - client_list.SendCharacterMessageID( - r->source_character_id, Chat::Red, - SharedTaskMessage::YOU_ARE_NOT_LEADER_COMMAND_ISSUE, {leader.character_name} - ); + client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name}); } else { shared_task_manager.RemoveEveryoneFromSharedTask(t, r->source_character_id); @@ -146,10 +144,7 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) auto leader = t->GetLeader(); if (leader.character_id != r->source_character_id) { - client_list.SendCharacterMessageID( - r->source_character_id, Chat::Red, - SharedTaskMessage::YOU_ARE_NOT_LEADER_COMMAND_ISSUE, {leader.character_name} - ); + client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name}); } else { LogTasksDetail( @@ -158,8 +153,14 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) t->GetDbSharedTask().id ); - std::string character_name = r->player_name; - shared_task_manager.RemovePlayerFromSharedTaskByPlayerName(t, character_name); + auto member = t->FindMemberFromCharacterName(r->player_name); + if (member.character_id == 0) { + shared_task_manager.SendLeaderMessageID(t, Chat::Red, TaskStr::IS_NOT_MEMBER, {r->player_name}); + } + else { + shared_task_manager.RemoveMember(t, member, true); + shared_task_manager.SendLeaderMessageID(t, Chat::Yellow, TaskStr::PLAYER_REMOVED, {member.character_name, t->GetTaskData().title}); + } } } @@ -185,17 +186,10 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) auto leader = t->GetLeader(); if (leader.character_id != r->source_character_id) { - client_list.SendCharacterMessageID( - r->source_character_id, Chat::Red, - SharedTaskMessage::YOU_ARE_NOT_LEADER_COMMAND_ISSUE, {leader.character_name} - ); + client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name}); } else if (strcasecmp(leader.character_name.c_str(), r->player_name) == 0) { - client_list.SendCharacterMessageID( - r->source_character_id, - Chat::Red, - SharedTaskMessage::YOU_ALREADY_LEADER - ); + client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::YOU_ALREADY_LEADER); } else { LogTasksDetail( @@ -232,10 +226,7 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) auto leader = t->GetLeader(); if (leader.character_id != r->source_character_id) { // taskadd is client sided with System color in newer clients, server side might still be red - client_list.SendCharacterMessageID( - r->source_character_id, Chat::Red, - SharedTaskMessage::YOU_ARE_NOT_LEADER_COMMAND_ISSUE, {leader.character_name} - ); + client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name}); } else { LogTasksDetail( @@ -275,12 +266,7 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) shared_task_manager.AddPlayerByCharacterIdAndName(t, r->source_character_id, r->player_name); } else { - shared_task_manager.SendLeaderMessageID( - t, - Chat::Red, - SharedTaskMessage::PLAYER_DECLINED_OFFER, - {r->player_name} - ); + shared_task_manager.SendLeaderMessageID(t, Chat::Red, TaskStr::PLAYER_DECLINED_OFFER, {r->player_name}); } } break; @@ -333,22 +319,43 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) player_names.emplace_back(member.character_name); if (member.is_leader) { - client_list.SendCharacterMessageID( - buf->source_character_id, Chat::Yellow, - SharedTaskMessage::LEADER_PRINT, {member.character_name} - ); + client_list.SendCharacterMessageID(buf->source_character_id, Chat::Yellow, TaskStr::LEADER_PRINT, {member.character_name}); } } std::string player_list = fmt::format("{}", fmt::join(player_names, ", ")); - client_list.SendCharacterMessageID( - buf->source_character_id, Chat::Yellow, - SharedTaskMessage::MEMBERS_PRINT, {player_list} - ); + client_list.SendCharacterMessageID(buf->source_character_id, Chat::Yellow, TaskStr::MEMBERS_PRINT, {player_list}); } break; } + case ServerOP_SharedTaskLock: { + auto buf = reinterpret_cast(pack->pBuffer); + auto shared_task = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->source_character_id); + if (shared_task) + { + shared_task_manager.LockTask(shared_task, buf->lock); + } + break; + } + case ServerOP_SharedTaskEndByDz: { + auto buf = reinterpret_cast(pack->pBuffer); + auto shared_task = shared_task_manager.FindSharedTaskByDzId(buf->dz_id); + if (shared_task) + { + shared_task_manager.Terminate(*shared_task, buf->send_fail, true); + } + break; + } + case ServerOP_SharedTaskEnd: { + auto buf = reinterpret_cast(pack->pBuffer); + auto shared_task = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->character_id); + if (shared_task) + { + shared_task_manager.Terminate(*shared_task, buf->send_fail, true); + } + break; + } default: break; } diff --git a/world/world_boot.cpp b/world/world_boot.cpp new file mode 100644 index 000000000..c53730be8 --- /dev/null +++ b/world/world_boot.cpp @@ -0,0 +1,654 @@ +#include "../common/content/world_content_service.h" +#include "../common/emu_constants.h" +#include "../common/eqemu_logsys.h" +#include "../common/http/httplib.h" +#include "../common/http/uri.h" +#include "../common/net/console_server.h" +#include "../common/net/servertalk_server.h" +#include "../common/repositories/character_task_timers_repository.h" +#include "../common/rulesys.h" +#include "../common/strings.h" +#include "adventure_manager.h" +#include "dynamic_zone_manager.h" +#include "expedition_database.h" +#include "login_server_list.h" +#include "shared_task_manager.h" +#include "ucs.h" +#include "wguild_mgr.h" +#include "world_boot.h" +#include "world_config.h" +#include "world_event_scheduler.h" +#include "world_server_cli.h" +#include "../common/zone_store.h" +#include "worlddb.h" +#include "zonelist.h" +#include "zoneserver.h" +#include "../common/ip_util.h" +#include "../common/zone_store.h" +#include "../common/path_manager.h" + +extern ZSList zoneserver_list; +extern WorldConfig Config; + +void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message) +{ + // we don't want to loop up with chat messages + if (message.find("OP_SpecialMesg") != std::string::npos) { + return; + } + + // Cut messages down to 4000 max to prevent client crash + if (!message.empty()) { + message = message.substr(0, 4000); + } + + // Replace Occurrences of % or MessageStatus will crash + Strings::FindReplace(message, std::string("%"), std::string(".")); + + if (message.find('\n') != std::string::npos) { + auto message_split = Strings::Split(message, '\n'); + + for (size_t iter = 0; iter < message_split.size(); ++iter) { + zoneserver_list.SendEmoteMessage( + 0, + 0, + AccountStatus::QuestTroupe, + LogSys.GetGMSayColorFromCategory(log_category), + fmt::format( + " {}{}", + (iter == 0 ? " ---" : ""), + message_split[iter] + ).c_str() + ); + } + + return; + } + + zoneserver_list.SendEmoteMessage( + 0, + 0, + AccountStatus::QuestTroupe, + LogSys.GetGMSayColorFromCategory(log_category), + "%s", + fmt::format("[{}] [{}] {}", Logs::LogCategoryName[log_category], func, message).c_str() + ); +} + +bool WorldBoot::HandleCommandInput(int argc, char **argv) +{ + // command handler + if (argc > 1) { + LogSys.SilenceConsoleLogging(); + path.LoadPaths(); + WorldConfig::LoadConfig(); + LoadDatabaseConnections(); + RuleManager::Instance()->LoadRules(&database, "default", false); + LogSys.EnableConsoleLogging(); + WorldserverCLI::CommandHandler(argc, argv); + } + + // database version + uint32 database_version = CURRENT_BINARY_DATABASE_VERSION; + uint32 bots_database_version = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0; + if (argc >= 2) { + if (strcasecmp(argv[1], "db_version") == 0) { + std::cout << "Binary Database Version: " << database_version << " : " << bots_database_version << std::endl; + return true; + } + } + + return false; +} + +bool WorldBoot::LoadServerConfig() +{ + LogInfo("Loading server configuration"); + if (!WorldConfig::LoadConfig()) { + LogError("Loading server configuration failed"); + return false; + } + + return true; +} + + +bool WorldBoot::LoadDatabaseConnections() +{ + const auto c = EQEmuConfig::get(); + + LogInfo( + "Connecting to MySQL [{}]@[{}]:[{}]", + c->DatabaseUsername.c_str(), + c->DatabaseHost.c_str(), + c->DatabasePort + ); + + if (!database.Connect( + c->DatabaseHost.c_str(), + c->DatabaseUsername.c_str(), + c->DatabasePassword.c_str(), + c->DatabaseDB.c_str(), + c->DatabasePort + )) { + LogError("Cannot continue without a database connection"); + + return false; + } + + /** + * Multi-tenancy: Content database + */ + if (!c->ContentDbHost.empty()) { + if (!content_db.Connect( + c->ContentDbHost.c_str(), + c->ContentDbUsername.c_str(), + c->ContentDbPassword.c_str(), + c->ContentDbName.c_str(), + c->ContentDbPort, + "content" + )) { + LogError("Cannot continue without a content database connection"); + return false; + } + } + else { + content_db.SetMysql(database.getMySQL()); + } + + return true; +} + +int get_file_size(const std::string &filename) // path to file +{ + FILE *p_file = NULL; + p_file = fopen(filename.c_str(), "rb"); + fseek(p_file, 0, SEEK_END); + int size = ftell(p_file); + fclose(p_file); + return size; +} + + +void WorldBoot::CheckForServerScript(bool force_download) +{ + const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath()); + std::ifstream f(file); + + /* Fetch EQEmu Server script */ + if (!f || get_file_size(file) < 100 || force_download) { + + if (force_download) { + std::remove(fmt::format("{}/eqemu_server.pl", path.GetServerPath()).c_str()); + } /* Delete local before fetch */ + + std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl; + + // http get request + uri u("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); + + httplib::Client r( + fmt::format( + "{}://{}", + u.get_scheme(), + u.get_host() + ).c_str() + ); + + r.set_connection_timeout(1, 0); + r.set_read_timeout(1, 0); + r.set_write_timeout(1, 0); + + if (auto res = r.Get(u.get_path().c_str())) { + if (res->status == 200) { + // write file + + std::string script = fmt::format("{}/eqemu_server.pl", path.GetServerPath()); + std::ofstream out(script); + out << res->body; + out.close(); +#ifdef _WIN32 +#else + system(fmt::format("chmod 755 {}", script).c_str()); + system(fmt::format("chmod +x {}", script).c_str()); +#endif + } + } + } +} + +void WorldBoot::CheckForXMLConfigUpgrade() +{ + if (!std::ifstream("eqemu_config.json") && std::ifstream("eqemu_config.xml")) { + CheckForServerScript(true); + std::string command = fmt::format("perl {}/eqemu_server.pl convert_xml", path.GetServerPath()); + if (system(command.c_str())) {} + } + else { + CheckForServerScript(); + } +} + +extern LoginServerList loginserverlist; + +void WorldBoot::RegisterLoginservers() +{ + const auto c = EQEmuConfig::get(); + + if (c->LoginCount == 0) { + if (c->LoginHost.length()) { + loginserverlist.Add( + c->LoginHost.c_str(), + c->LoginPort, + c->LoginAccount.c_str(), + c->LoginPassword.c_str(), + c->LoginLegacy + ); + LogInfo("Added loginserver [{}]:[{}]", c->LoginHost.c_str(), c->LoginPort); + } + } + else { + LinkedList loginlist = c->loginlist; + LinkedListIterator iterator(loginlist); + iterator.Reset(); + while (iterator.MoreElements()) { + if (iterator.GetData()->LoginHost.length()) { + loginserverlist.Add( + iterator.GetData()->LoginHost.c_str(), + iterator.GetData()->LoginPort, + iterator.GetData()->LoginAccount.c_str(), + iterator.GetData()->LoginPassword.c_str(), + iterator.GetData()->LoginLegacy + ); + + LogInfo( + "Added loginserver [{}]:[{}]", + iterator.GetData()->LoginHost.c_str(), + iterator.GetData()->LoginPort + ); + } + iterator.Advance(); + } + } +} + +extern SharedTaskManager shared_task_manager; +extern AdventureManager adventure_manager; +extern WorldEventScheduler event_scheduler; + +bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv) +{ + // ignore + bool ignore_db = false; + if (argc >= 2) { + if (strcasecmp(argv[1], "ignore_db") == 0) { + ignore_db = true; + } + else { + std::cerr << "Error, unknown command line option" << std::endl; + return false; + } + } + + if (!ignore_db) { + LogInfo("Checking Database Conversions"); + database.CheckDatabaseConversions(); + } + + // logging system init + auto logging = LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) + ->LoadLogDatabaseSettings(); + + if (RuleB(Logging, WorldGMSayLogging)) { + logging->SetGMSayHandler(&WorldBoot::GMSayHookCallBackProcessWorld); + } + + logging->StartFileLogs(); + + LogInfo("Loading variables"); + database.LoadVariables(); + + std::string hotfix_name; + if (database.GetVariable("hotfix_name", hotfix_name)) { + if (!hotfix_name.empty()) { + LogInfo("Current hotfix in use: [{}]", hotfix_name.c_str()); + } + } + + guild_mgr.SetDatabase(&database); + + LogInfo("Purging expired data buckets"); + database.PurgeAllDeletedDataBuckets(); + + LogInfo("Loading zones"); + + zone_store.LoadZones(content_db); + + if (zone_store.GetZones().empty()) { + LogError("Failed to load zones data, check your schema for possible errors"); + return 1; + } + + LogInfo("Clearing groups"); + database.ClearGroup(); + LogInfo("Clearing raids"); + database.ClearRaid(); + database.ClearRaidDetails(); + database.ClearRaidLeader(); + LogInfo("Clearing inventory snapshots"); + database.ClearInvSnapshots(); + LogInfo("Loading items"); + + if (!content_db.LoadItems(hotfix_name)) { + LogError("Error: Could not load item data. But ignoring"); + } + + if (!content_db.LoadSkillCaps(std::string(hotfix_name))) { + LogError("Error: Could not load skill cap data. But ignoring"); + } + + guild_mgr.LoadGuilds(); + + //rules: + { + if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) { + LogInfo("Failed to process 'Orphaned Rules' update operation."); + } + + if (!RuleManager::Instance()->UpdateInjectedRules(&database, "default")) { + LogInfo("Failed to process 'Injected Rules' for ruleset 'default' update operation."); + } + + std::string tmp; + if (database.GetVariable("RuleSet", tmp)) { + LogInfo("Loading rule set [{}]", tmp.c_str()); + + if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) { + LogInfo("Failed to load ruleset [{}], falling back to defaults", tmp.c_str()); + } + } + else { + + if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { + LogInfo("No rule set configured, using default rules"); + } + } + + if (!RuleManager::Instance()->RestoreRuleNotes(&database)) { + LogInfo("Failed to process 'Restore Rule Notes' update operation."); + } + } + + EQ::InitializeDynamicLookups(); + + if (RuleB(World, ClearTempMerchantlist)) { + LogInfo("Clearing temporary merchant lists"); + database.ClearMerchantTemp(); + } + + LogInfo("Loading EQ time of day"); + TimeOfDay_Struct eqTime{}; + time_t realtime; + eqTime = database.LoadTime(realtime); + zoneserver_list.worldclock.SetCurrentEQTimeOfDay(eqTime, realtime); + + LogInfo("Deleted [{}] stale player corpses from database", database.DeleteStalePlayerCorpses()); + + LogInfo("Loading adventures"); + if (!adventure_manager.LoadAdventureTemplates()) { + LogInfo("Unable to load adventure templates"); + } + + if (!adventure_manager.LoadAdventureEntries()) { + LogInfo("Unable to load adventure templates"); + } + + adventure_manager.LoadLeaderboardInfo(); + + LogInfo("Purging expired dynamic zones and members"); + dynamic_zone_manager.PurgeExpiredDynamicZones(); + + LogInfo("Purging expired expeditions"); + ExpeditionDatabase::PurgeExpiredExpeditions(); + ExpeditionDatabase::PurgeExpiredCharacterLockouts(); + + LogInfo("Purging expired character task timers"); + CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()"); + + LogInfo("Purging expired instances"); + database.PurgeExpiredInstances(); + + LogInfo("Loading dynamic zones"); + dynamic_zone_manager.LoadTemplates(); + dynamic_zone_manager.CacheAllFromDatabase(); + + LogInfo("Loading char create info"); + content_db.LoadCharacterCreateAllocations(); + content_db.LoadCharacterCreateCombos(); + + LogInfo("Initializing [EventScheduler]"); + event_scheduler.SetDatabase(&database)->LoadScheduledEvents(); + + LogInfo("Initializing [WorldContentService]"); + content_service.SetDatabase(&database) + ->SetExpansionContext() + ->ReloadContentFlags(); + + LogInfo("Initializing [SharedTaskManager]"); + shared_task_manager.SetDatabase(&database) + ->SetContentDatabase(&content_db) + ->LoadTaskData() + ->LoadSharedTaskState(); + + shared_task_manager.PurgeExpiredSharedTasks(); + + return true; +} + +void WorldBoot::CheckForPossibleConfigurationIssues() +{ + const auto c = EQEmuConfig::get(); + + if (c->DisableConfigChecks) { + LogInfo("Configuration checking [disabled]"); + return; + } + + const std::string local_address = IpUtil::GetLocalIPAddress(); + const std::string public_address = IpUtil::GetPublicIPAddress(); + const std::string config_file = "eqemu_config.json"; + const std::ifstream is_in_docker("/.dockerenv"); + + if (local_address.empty() && public_address.empty()) { + LogInfo("Configuration check, probes failed for local and public address, returning"); + return; + } + + LogInfo("Checking for possible configuration issues"); + LogInfo("To disable configuration checks, set [server.disable_config_checks] to [true] in [{}]", config_file); + + std::string config_address = c->WorldAddress; + if (!IpUtil::IsIPAddress(config_address)) { + config_address = IpUtil::DNSLookupSync(c->WorldAddress, 9000); + LogInfo( + "World config address using DNS [{}] resolves to [{}]", + c->WorldAddress, + config_address + ); + } + + std::cout << std::endl; + + // lan detection + if (local_address != public_address + && IpUtil::IsIpInPrivateRfc1918(local_address) + && local_address != c->LocalAddress + && !is_in_docker + ) { + LogWarning("# LAN detection (Configuration)"); + LogWarning(""); + LogWarning("You appear to be on a LAN and your localaddress may not be properly set!"); + LogWarning("This can prevent local clients from properly connecting to your server"); + LogWarning(""); + LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]"); + LogWarning(""); + LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file); + LogWarning(""); + LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address); + std::cout << std::endl; + } + + // docker configuration + if ( + ( + (c->LocalAddress.empty() && config_address.empty()) || + (config_address != public_address) + ) + && is_in_docker + ) { + LogWarning("# Docker Configuration (Configuration)"); + LogWarning(""); + LogWarning("You appear to running EQEmu in a docker container"); + LogWarning("In order for networking to work properly you will need to properly configure your server"); + LogWarning(""); + LogWarning( + "If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to"); + LogWarning( + "be set to your LAN address on the host, not the container address. [address] will need to be your public address"); + LogWarning(""); + LogWarning( + "If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]." + ); + LogWarning(""); + LogWarning("[address] will need to be your public address"); + LogWarning(""); + LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]"); + LogWarning(""); + LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file); + LogWarning(""); + LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address); + LogWarning( + "Public address (eqemu_config) value [{}] detected value [{}]", + config_address, + public_address + ); + std::cout << std::endl; + } + + // docker LAN not set + if (c->LocalAddress.empty() && is_in_docker) { + LogWarning("# Docker LAN (Configuration)"); + LogWarning(""); + LogWarning("You appear to running EQEmu in a docker container"); + LogWarning( + "Your local address does not appear to be set, this may not be an issue if your deployment is not on a LAN" + ); + LogWarning(""); + LogWarning( + "If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to"); + LogWarning( + "be set to your LAN address on the host, not the container address. [address] will need to be your public address"); + LogWarning(""); + LogWarning( + "If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]." + ); + LogWarning(""); + LogWarning("[address] will need to be your public address"); + LogWarning(""); + LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]"); + LogWarning(""); + LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file); + LogWarning(""); + LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address); + LogWarning( + "Public address (eqemu_config) value [{}] detected value [{}]", + config_address, + public_address + ); + std::cout << std::endl; + } + + // public address different from configuration + if (!config_address.empty() && public_address != config_address) { + LogWarning("# Public address (Configuration)"); + LogWarning(""); + LogWarning("Your configured public address appears to be different from what's detected!"); + LogWarning(""); + LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]"); + LogWarning(""); + LogWarning("Config file [{}] path [server.world] variable [address]", config_file); + LogWarning(""); + LogWarning( + "Public address (eqemu_config) value [{}] detected value [{}]", + config_address, + public_address + ); + std::cout << std::endl; + } + + // public address set to meta-address + if (config_address == "0.0.0.0") { + LogWarning("# Public meta-address (Configuration)"); + LogWarning(""); + LogWarning("Your configured public address is set to a meta-address (0.0.0.0) (all-interfaces)"); + LogWarning( + "The meta-address may not work properly and it is recommended you configure your public address explicitly"); + LogWarning(""); + LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]"); + LogWarning(""); + LogWarning("Config file [{}] path [server.world] variable [address]", config_file); + LogWarning(""); + LogWarning( + "Public address (eqemu_config) value [{}] detected value [{}]", + config_address, + public_address + ); + std::cout << std::endl; + } + + // local address set to meta-address + if (c->LocalAddress == "0.0.0.0") { + LogWarning("# Local meta-address (Configuration)"); + LogWarning(""); + LogWarning("Your configured local address is set to a meta-address (0.0.0.0) (all-interfaces)"); + LogWarning( + "The meta-address may not work properly and it is recommended you configure your local address explicitly" + ); + LogWarning(""); + LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]"); + LogWarning(""); + LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file); + LogWarning(""); + LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address); + std::cout << std::endl; + } + + // ucs (public) + if ( + (!config_address.empty() && c->MailHost != config_address) || + (!config_address.empty() && c->ChatHost != config_address) + ) { + LogWarning("# UCS Address Mailhost (Configuration)"); + LogWarning(""); + LogWarning( + "UCS (Universal Chat Service) mail or chat appears to use a different address from your main world address" + ); + LogWarning("This can result in a chat service that doesn't network properly"); + LogWarning(""); + LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]"); + LogWarning(""); + LogWarning( + "[server.world.address] value [{}] [server.chatserver.host] [{}]", + config_address, + c->ChatHost + ); + LogWarning( + "[server.world.address] value [{}] [server.mailserver.host] [{}]", + config_address, + c->MailHost + ); + std::cout << std::endl; + } +} + diff --git a/world/world_boot.h b/world/world_boot.h new file mode 100644 index 000000000..9e6f9b655 --- /dev/null +++ b/world/world_boot.h @@ -0,0 +1,21 @@ +#ifndef EQEMU_WORLD_BOOT_H +#define EQEMU_WORLD_BOOT_H + +#include +#include "../common/types.h" + +class WorldBoot { +public: + static void GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message); + static bool HandleCommandInput(int argc, char **argv); + static bool LoadServerConfig(); + static bool LoadDatabaseConnections(); + static void CheckForServerScript(bool force_download = false); + static void CheckForXMLConfigUpgrade(); + static void RegisterLoginservers(); + static bool DatabaseLoadRoutines(int argc, char **argv); + static void CheckForPossibleConfigurationIssues(); +}; + + +#endif //EQEMU_WORLD_BOOT_H diff --git a/world/world_config.cpp b/world/world_config.cpp index f57368a10..d49884740 100644 --- a/world/world_config.cpp +++ b/world/world_config.cpp @@ -16,39 +16,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "../common/global_define.h" +#include "../common/eqemu_logsys.h" #include "world_config.h" WorldConfig *WorldConfig::_world_config = nullptr; - -std::string WorldConfig::GetByName(const std::string &var_name) const { - if(var_name == "UpdateStats") - return(UpdateStats?"true":"false"); - if(var_name == "LoginDisabled") - return(LoginDisabled?"true":"false"); - return(EQEmuConfig::GetByName(var_name)); +std::string WorldConfig::GetByName(const std::string &var_name) const +{ + if (var_name == "UpdateStats") { + return (UpdateStats ? "true" : "false"); + } + if (var_name == "LoginDisabled") { + return (LoginDisabled ? "true" : "false"); + } + return (EQEmuConfig::GetByName(var_name)); } - - - - - - - - - - - - - - - - - - - - - - - diff --git a/world/world_config.h b/world/world_config.h index 2a274ed29..73b618b74 100644 --- a/world/world_config.h +++ b/world/world_config.h @@ -46,13 +46,13 @@ public: } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_world_config != nullptr) delete _world_config; _world_config=new WorldConfig; _config=_world_config; - return _config->parseFile(); + return _config->parseFile(path); } // Accessors for the static private object diff --git a/world/world_server_cli.cpp b/world/world_server_cli.cpp new file mode 100644 index 000000000..787c3b90e --- /dev/null +++ b/world/world_server_cli.cpp @@ -0,0 +1,48 @@ +#include "world_server_cli.h" + +/** + * @param argc + * @param argv + */ +void WorldserverCLI::CommandHandler(int argc, char **argv) +{ + if (argc == 1) { return; } + + argh::parser cmd; + cmd.parse(argc, argv, argh::parser::PREFER_PARAM_FOR_UNREG_OPTION); + EQEmuCommand::DisplayDebug(cmd); + + /** + * Declare command mapping + */ + auto function_map = EQEmuCommand::function_map; + + /** + * Register commands + */ + function_map["world:version"] = &WorldserverCLI::Version; + function_map["character:copy-character"] = &WorldserverCLI::CopyCharacter; + function_map["database:version"] = &WorldserverCLI::DatabaseVersion; + function_map["database:set-account-status"] = &WorldserverCLI::DatabaseSetAccountStatus; + function_map["database:schema"] = &WorldserverCLI::DatabaseGetSchema; + function_map["database:dump"] = &WorldserverCLI::DatabaseDump; + function_map["test:test"] = &WorldserverCLI::TestCommand; + function_map["test:colors"] = &WorldserverCLI::TestColors; + function_map["test:expansion"] = &WorldserverCLI::ExpansionTestCommand; + function_map["test:repository"] = &WorldserverCLI::TestRepository; + function_map["test:repository2"] = &WorldserverCLI::TestRepository2; + + EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); +} + +#include "cli/copy_character.cpp" +#include "cli/database_dump.cpp" +#include "cli/database_get_schema.cpp" +#include "cli/database_set_account_status.cpp" +#include "cli/database_version.cpp" +#include "cli/test.cpp" +#include "cli/test_colors.cpp" +#include "cli/test_expansion.cpp" +#include "cli/test_repository.cpp" +#include "cli/test_repository_2.cpp" +#include "cli/version.cpp" diff --git a/world/world_server_cli.h b/world/world_server_cli.h new file mode 100644 index 000000000..954c36cd1 --- /dev/null +++ b/world/world_server_cli.h @@ -0,0 +1,24 @@ +#include "iostream" +#include "../common/cli/eqemu_command_handler.h" + +#ifndef EQEMU_WORLD_SERVER_COMMAND_HANDLER_H +#define EQEMU_WORLD_SERVER_COMMAND_HANDLER_H + +class WorldserverCLI { +public: + static void CommandHandler(int argc, char **argv); + static void Version(int argc, char **argv, argh::parser &cmd, std::string &description); + static void CopyCharacter(int argc, char **argv, argh::parser &cmd, std::string &description); + static void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description); + static void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description); + static void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description); + static void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description); + static void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description); + static void TestColors(int argc, char **argv, argh::parser &cmd, std::string &description); + static void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description); + static void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description); + static void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description); +}; + + +#endif //EQEMU_WORLD_SERVER_COMMAND_HANDLER_H diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp deleted file mode 100644 index 0eade4f43..000000000 --- a/world/world_server_command_handler.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "world_server_command_handler.h" -#include "../common/eqemu_logsys.h" -#include "../common/json/json.h" -#include "../common/version.h" -#include "worlddb.h" -#include "../common/database_schema.h" -#include "../common/database/database_dump_service.h" -#include "../common/content/world_content_service.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/rulesys.h" -#include "../common/repositories/instance_list_repository.h" -#include "../common/repositories/zone_repository.h" - -namespace WorldserverCommandHandler { - - /** - * @param argc - * @param argv - */ - void CommandHandler(int argc, char **argv) - { - if (argc == 1) { return; } - - argh::parser cmd; - cmd.parse(argc, argv, argh::parser::PREFER_PARAM_FOR_UNREG_OPTION); - EQEmuCommand::DisplayDebug(cmd); - - /** - * Declare command mapping - */ - auto function_map = EQEmuCommand::function_map; - - /** - * Register commands - */ - function_map["world:version"] = &WorldserverCommandHandler::Version; - function_map["character:copy-character"] = &WorldserverCommandHandler::CopyCharacter; - function_map["database:version"] = &WorldserverCommandHandler::DatabaseVersion; - function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus; - function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema; - function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump; - function_map["test:test"] = &WorldserverCommandHandler::TestCommand; - function_map["test:expansion"] = &WorldserverCommandHandler::ExpansionTestCommand; - function_map["test:repository"] = &WorldserverCommandHandler::TestRepository; - function_map["test:repository2"] = &WorldserverCommandHandler::TestRepository2; - - EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Shows database version"; - - if (cmd[{"-h", "--help"}]) { - return; - } - - Json::Value database_version; - - database_version["database_version"] = CURRENT_BINARY_DATABASE_VERSION; - database_version["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION; - - std::stringstream payload; - payload << database_version; - - std::cout << payload.str() << std::endl; - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void Version(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Shows server version"; - - if (cmd[{"-h", "--help"}]) { - return; - } - - Json::Value database_version; - - database_version["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION; - database_version["compile_date"] = COMPILE_DATE; - database_version["compile_time"] = COMPILE_TIME; - database_version["database_version"] = CURRENT_BINARY_DATABASE_VERSION; - database_version["server_version"] = CURRENT_VERSION; - - std::stringstream payload; - payload << database_version; - - std::cout << payload.str() << std::endl; - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Sets account status by account name"; - - std::vector arguments = { - "{name}", - "{status}" - }; - - std::vector options = {}; - - if (cmd[{"-h", "--help"}]) { - return; - } - - EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); - - database.SetAccountStatus( - cmd(2).str(), - std::stoi(cmd(3).str()) - ); - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Displays server database schema"; - - if (cmd[{"-h", "--help"}]) { - return; - } - - Json::Value player_tables_json; - std::vector player_tables = DatabaseSchema::GetPlayerTables(); - for (const auto &table: player_tables) { - player_tables_json.append(table); - } - - Json::Value content_tables_json; - std::vector content_tables = DatabaseSchema::GetContentTables(); - for (const auto &table: content_tables) { - content_tables_json.append(table); - } - - Json::Value server_tables_json; - std::vector server_tables = DatabaseSchema::GetServerTables(); - for (const auto &table: server_tables) { - server_tables_json.append(table); - } - - Json::Value login_tables_json; - std::vector login_tables = DatabaseSchema::GetLoginTables(); - for (const auto &table: login_tables) { - login_tables_json.append(table); - } - - Json::Value state_tables_json; - std::vector state_tables = DatabaseSchema::GetStateTables(); - for (const auto &table: state_tables) { - state_tables_json.append(table); - } - - Json::Value version_tables_json; - std::vector version_tables = DatabaseSchema::GetVersionTables(); - for (const auto &table: version_tables) { - version_tables_json.append(table); - } - - Json::Value schema; - - schema["content_tables"] = content_tables_json; - schema["login_tables"] = login_tables_json; - schema["player_tables"] = player_tables_json; - schema["server_tables"] = server_tables_json; - schema["state_tables"] = state_tables_json; - schema["version_tables"] = version_tables_json; - - std::stringstream payload; - payload << schema; - - std::cout << payload.str() << std::endl; - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Dumps server database tables"; - - std::vector arguments = {}; - std::vector options = { - "--all", - "--content-tables", - "--login-tables", - "--player-tables", - "--state-tables", - "--system-tables", - "--query-serv-tables", - "--table-structure-only", - "--table-lock", - "--dump-path=", - "--dump-output-to-console", - "--drop-table-syntax-only", - "--compress" - }; - - if (cmd[{"-h", "--help"}]) { - return; - } - - EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); - - auto database_dump_service = new DatabaseDumpService(); - bool dump_all = cmd[{"-a", "--all"}]; - - if (!cmd("--dump-path").str().empty()) { - database_dump_service->SetDumpPath(cmd("--dump-path").str()); - } - - /** - * Set Option - */ - database_dump_service->SetDumpContentTables(cmd[{"--content-tables"}] || dump_all); - database_dump_service->SetDumpLoginServerTables(cmd[{"--login-tables"}] || dump_all); - database_dump_service->SetDumpPlayerTables(cmd[{"--player-tables"}] || dump_all); - database_dump_service->SetDumpStateTables(cmd[{"--state-tables"}] || dump_all); - database_dump_service->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all); - database_dump_service->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all); - database_dump_service->SetDumpAllTables(dump_all); - - database_dump_service->SetDumpWithNoData(cmd[{"--table-structure-only"}]); - database_dump_service->SetDumpTableLock(cmd[{"--table-lock"}]); - database_dump_service->SetDumpWithCompression(cmd[{"--compress"}]); - database_dump_service->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]); - database_dump_service->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]); - - /** - * Dump - */ - database_dump_service->Dump(); - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Test command"; - - if (cmd[{"-h", "--help"}]) { - return; - } - - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Expansion test command"; - - if (cmd[{"-h", "--help"}]) { - return; - } - - if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { - LogInfo("No rule set configured, using default rules"); - } - - content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion)); - - std::vector flags = {}; - auto f = ContentFlagsRepository::NewEntity(); - f.enabled = 1; - - std::vector flag_names = { - "hateplane_enabled", - "patch_nerf_7077", - }; - - for (auto &name: flag_names) { - f.flag_name = name; - flags.push_back(f); - } - - content_service.SetContentFlags(flags); - - LogInfo( - "Current expansion is [{}] ({}) is Velious Enabled [{}] Criteria [{}]", - content_service.GetCurrentExpansion(), - content_service.GetCurrentExpansionName(), - content_service.IsTheScarsOfVeliousEnabled() ? "true" : "false", - ContentFilterCriteria::apply() - ); - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Test command"; - - if (cmd[{"-h", "--help"}]) { - return; - } - - /** - * Insert one - */ - auto instance_list_entry = InstanceListRepository::NewEntity(); - - instance_list_entry.zone = 999; - instance_list_entry.version = 1; - instance_list_entry.is_global = 1; - instance_list_entry.start_time = 0; - instance_list_entry.duration = 0; - instance_list_entry.never_expires = 1; - - auto instance_list_inserted = InstanceListRepository::InsertOne(database, instance_list_entry); - - LogInfo("Inserted ID is [{}] zone [{}]", instance_list_inserted.id, instance_list_inserted.zone); - - /** - * Find one - */ - auto found_instance_list = InstanceListRepository::FindOne(database, instance_list_inserted.id); - - LogInfo("Found ID is [{}] zone [{}]", found_instance_list.id, found_instance_list.zone); - - /** - * Update one - */ - LogInfo("Updating instance id [{}] zone [{}]", found_instance_list.id, found_instance_list.zone); - - int update_instance_list_count = InstanceListRepository::UpdateOne(database, found_instance_list); - - found_instance_list.zone = 777; - - LogInfo( - "Updated instance id [{}] zone [{}] affected [{}]", - found_instance_list.id, - found_instance_list.zone, - update_instance_list_count - ); - - - /** - * Delete one - */ - int deleted = InstanceListRepository::DeleteOne(database, found_instance_list.id); - - LogInfo("Deleting one instance [{}] deleted count [{}]", found_instance_list.id, deleted); - - /** - * Insert many - */ - std::vector instance_lists; - - auto instance_list_entry_bulk = InstanceListRepository::NewEntity(); - - instance_list_entry_bulk.zone = 999; - instance_list_entry_bulk.version = 1; - instance_list_entry_bulk.is_global = 1; - instance_list_entry_bulk.start_time = 0; - instance_list_entry_bulk.duration = 0; - instance_list_entry_bulk.never_expires = 1; - - for (int i = 0; i < 10; i++) { - instance_lists.push_back(instance_list_entry_bulk); - } - - /** - * Fetch all - */ - int inserted_count = InstanceListRepository::InsertMany(database, instance_lists); - - LogInfo("Bulk insertion test, inserted [{}]", inserted_count); - - for (auto &entry: InstanceListRepository::GetWhere(database, fmt::format("zone = {}", 999))) { - LogInfo("Iterating through entry id [{}] zone [{}]", entry.id, entry.zone); - } - - /** - * Delete where - */ - int deleted_count = InstanceListRepository::DeleteWhere(database, fmt::format("zone = {}", 999)); - - LogInfo("Bulk deletion test, deleted [{}]", deleted_count); - - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Test command"; - - if (cmd[{"-h", "--help"}]) { - return; - } - - auto zones = ZoneRepository::GetWhere(content_db, "short_name = 'anguish'"); - - for (auto &zone: zones) { - LogInfo( - "Zone [{}] long_name [{}] id [{}]", - zone.short_name, - zone.long_name, - zone.id - ); - } - } - - /** - * @param argc - * @param argv - * @param cmd - * @param description - */ - void CopyCharacter(int argc, char **argv, argh::parser &cmd, std::string &description) - { - description = "Copies a character into a destination account"; - - std::vector arguments = { - "source_character_name", - "destination_character_name", - "destination_account_name" - }; - std::vector options = {}; - - if (cmd[{"-h", "--help"}]) { - return; - } - - EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); - - std::string source_character_name = cmd(2).str(); - std::string destination_character_name = cmd(3).str(); - std::string destination_account_name = cmd(4).str(); - - LogInfo( - "Attempting to copy character [{}] to [{}] via account [{}]", - source_character_name, - destination_character_name, - destination_account_name - ); - - database.CopyCharacter( - source_character_name, - destination_character_name, - destination_account_name - ); - } - -} diff --git a/world/world_server_command_handler.h b/world/world_server_command_handler.h deleted file mode 100644 index 2d7c59f8e..000000000 --- a/world/world_server_command_handler.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "iostream" -#include "../common/cli/eqemu_command_handler.h" - -#ifndef EQEMU_WORLD_SERVER_COMMAND_HANDLER_H -#define EQEMU_WORLD_SERVER_COMMAND_HANDLER_H - -namespace WorldserverCommandHandler { - void CommandHandler(int argc, char **argv); - void Version(int argc, char **argv, argh::parser &cmd, std::string &description); - void CopyCharacter(int argc, char **argv, argh::parser &cmd, std::string &description); - void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description); - void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description); - void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description); - void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description); - void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description); - void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description); - void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description); - void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description); -}; - - -#endif //EQEMU_WORLD_SERVER_COMMAND_HANDLER_H diff --git a/world/world_store.cpp b/world/world_store.cpp deleted file mode 100644 index 62c484172..000000000 --- a/world/world_store.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "world_store.h" - -WorldStore::WorldStore() = default; -WorldStore::~WorldStore() = default; - -void WorldStore::LoadZones() -{ - zones = ZoneRepository::All(content_db); -} - -uint32 WorldStore::GetZoneID(const char *in_zone_name) -{ - if (in_zone_name == nullptr) { - return 0; - } - - std::string zone_name = str_tolower(in_zone_name); - - return GetZoneID(zone_name); -} - -uint32 WorldStore::GetZoneID(std::string zone_name) -{ - for (auto &z: zones) { - if (z.short_name == zone_name) { - return z.zoneidnumber; - } - } - - return 0; -} - -/** - * @param zone_id - * @param error_unknown - * @return - */ -const char *WorldStore::GetZoneName(uint32 zone_id, bool error_unknown) -{ - for (auto &z: zones) { - if (z.zoneidnumber == zone_id) { - return z.short_name.c_str(); - } - } - - if (error_unknown) { - return "UNKNOWN"; - } - - return nullptr; -} - -/** - * @param zone_id - * @return - */ -std::string WorldStore::GetZoneName(uint32 zone_id) -{ - for (auto &z: zones) { - if (z.zoneidnumber == zone_id) { - return z.short_name; - } - } - - return std::string(); -} - -/** - * @param zone_id - * @param error_unknown - * @return - */ -const char *WorldStore::GetZoneLongName(uint32 zone_id, bool error_unknown) -{ - for (auto &z: zones) { - if (z.zoneidnumber == zone_id) { - return z.long_name.c_str(); - } - } - - if (error_unknown) { - return "UNKNOWN"; - } - - return nullptr; -} - -/** - * @param zone_id - * @return - */ -std::string WorldStore::GetZoneLongName(uint32 zone_id) -{ - for (auto &z: zones) { - if (z.zoneidnumber == zone_id) { - return z.long_name; - } - } - - return std::string(); -} - -/** - * @param zone_id - * @param version - * @return - */ -ZoneRepository::Zone WorldStore::GetZone(uint32 zone_id, int version) -{ - for (auto &z: zones) { - if (z.zoneidnumber == zone_id && z.version == version) { - return z; - } - } - - return ZoneRepository::Zone(); -} - -/** - * @param in_zone_name - * @return - */ -ZoneRepository::Zone WorldStore::GetZone(const char *in_zone_name) -{ - for (auto &z: zones) { - if (z.short_name == in_zone_name) { - return z; - } - } - - return ZoneRepository::Zone(); -} diff --git a/world/world_store.h b/world/world_store.h deleted file mode 100644 index ecbba4b5e..000000000 --- a/world/world_store.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef EQEMU_WORLD_STORE_H -#define EQEMU_WORLD_STORE_H - -#include "worlddb.h" -#include "../common/repositories/zone_repository.h" - -class WorldStore { -public: - WorldStore(); - virtual ~WorldStore(); - - std::vector zones{}; - - void LoadZones(); - - ZoneRepository::Zone GetZone(uint32 zone_id, int version = 0); - ZoneRepository::Zone GetZone(const char *in_zone_name); - uint32 GetZoneID(const char *in_zone_name); - uint32 GetZoneID(std::string zone_name); - std::string GetZoneName(uint32 zone_id); - std::string GetZoneLongName(uint32 zone_id); - const char *GetZoneName(uint32 zone_id, bool error_unknown = false); - const char *GetZoneLongName(uint32 zone_id, bool error_unknown = false); -}; - -extern WorldStore world_store; - -/** - * Global helpers - */ -inline uint32 ZoneID(const char *in_zone_name) { return world_store.GetZoneID(in_zone_name); } -inline uint32 ZoneID(std::string zone_name) { return world_store.GetZoneID(zone_name); } -inline const char *ZoneName(uint32 zone_id, bool error_unknown = false) -{ - return world_store.GetZoneName( - zone_id, - error_unknown - ); -} -inline const char *ZoneLongName(uint32 zone_id, bool error_unknown = false) -{ - return world_store.GetZoneLongName( - zone_id, - error_unknown - ); -} -inline ZoneRepository::Zone GetZone(uint32 zone_id, int version = 0) { return world_store.GetZone(zone_id, version); }; -inline ZoneRepository::Zone GetZone(const char *in_zone_name) { return world_store.GetZone(in_zone_name); }; - -#endif //EQEMU_WORLD_STORE_H diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 7e6490d0b..70033d988 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -17,7 +17,7 @@ */ #include "worlddb.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/eq_packet_structs.h" #include "../common/inventory_profile.h" #include "../common/rulesys.h" @@ -27,7 +27,7 @@ #include "sof_char_create_data.h" #include "../common/repositories/character_instance_safereturns_repository.h" #include "../common/repositories/criteria/content_filter_criteria.h" -#include "world_store.h" +#include "../common/zone_store.h" WorldDatabase database; WorldDatabase content_db; @@ -113,10 +113,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o buff_ptr += sizeof(CharacterSelect_Struct); for (auto row = results.begin(); row != results.end(); ++row) { CharacterSelectEntry_Struct *p_character_select_entry_struct = (CharacterSelectEntry_Struct *) buff_ptr; - PlayerProfile_Struct player_profile_struct; - EQ::InventoryProfile inventory_profile; + PlayerProfile_Struct pp; + EQ::InventoryProfile inventory_profile; - player_profile_struct.SetPlayerProfileVersion(EQ::versions::ConvertClientVersionToMobVersion(client_version)); + pp.SetPlayerProfileVersion(EQ::versions::ConvertClientVersionToMobVersion(client_version)); inventory_profile.SetInventoryVersion(client_version); inventory_profile.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support @@ -124,7 +124,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o uint8 has_home = 0; uint8 has_bind = 0; - memset(&player_profile_struct, 0, sizeof(PlayerProfile_Struct)); + memset(&pp, 0, sizeof(PlayerProfile_Struct)); memset(p_character_select_entry_struct->Name, 0, sizeof(p_character_select_entry_struct->Name)); strcpy(p_character_select_entry_struct->Name, row[1]); p_character_select_entry_struct->Class = (uint8) atoi(row[4]); @@ -198,12 +198,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o has_home = 1; // If our bind count is less than 5, we need to actually make use of this data so lets parse it if (bind_count < 5) { - player_profile_struct.binds[4].zone_id = atoi(row_b[0]); - player_profile_struct.binds[4].instance_id = atoi(row_b[1]); - player_profile_struct.binds[4].x = atof(row_b[2]); - player_profile_struct.binds[4].y = atof(row_b[3]); - player_profile_struct.binds[4].z = atof(row_b[4]); - player_profile_struct.binds[4].heading = atof(row_b[5]); + pp.binds[4].zone_id = atoi(row_b[0]); + pp.binds[4].instance_id = atoi(row_b[1]); + pp.binds[4].x = atof(row_b[2]); + pp.binds[4].y = atof(row_b[3]); + pp.binds[4].z = atof(row_b[4]); + pp.binds[4].heading = atof(row_b[5]); } } @@ -234,40 +234,39 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) { /* If a bind_id is specified, make them start there */ if (atoi(row_d[1]) != 0) { - player_profile_struct.binds[4].zone_id = (uint32) atoi(row_d[1]); - content_db.GetSafePoints( - ZoneName(player_profile_struct.binds[4].zone_id, true), - 0, - &player_profile_struct.binds[4].x, - &player_profile_struct.binds[4].y, - &player_profile_struct.binds[4].z, - &player_profile_struct.binds[4].heading - ); + pp.binds[4].zone_id = (uint32) atoi(row_d[1]); + + auto z = GetZone(pp.binds[4].zone_id); + if (z) { + pp.binds[4].x = z->safe_x; + pp.binds[4].y = z->safe_y; + pp.binds[4].z = z->safe_z; + pp.binds[4].heading = z->safe_heading; + } } /* Otherwise, use the zone and coordinates given */ else { - player_profile_struct.binds[4].zone_id = (uint32) atoi(row_d[0]); + pp.binds[4].zone_id = (uint32) atoi(row_d[0]); float x = atof(row_d[2]); float y = atof(row_d[3]); float z = atof(row_d[4]); float heading = atof(row_d[5]); if (x == 0 && y == 0 && z == 0 && heading == 0) { - content_db.GetSafePoints( - ZoneName(player_profile_struct.binds[4].zone_id, true), - 0, - &x, - &y, - &z, - &heading - ); + auto zone = GetZone(pp.binds[4].zone_id); + if (zone) { + x = zone->safe_x; + y = zone->safe_y; + z = zone->safe_z; + heading = zone->safe_heading; + } } - player_profile_struct.binds[4].x = x; - player_profile_struct.binds[4].y = y; - player_profile_struct.binds[4].z = z; - player_profile_struct.binds[4].heading = heading; + pp.binds[4].x = x; + pp.binds[4].y = y; + pp.binds[4].z = z; + pp.binds[4].heading = heading; } } - player_profile_struct.binds[0] = player_profile_struct.binds[4]; + pp.binds[0] = pp.binds[4]; /* If no home bind set, set it */ if (has_home == 0) { std::string query = fmt::format( @@ -278,12 +277,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o VALUES ({}, {}, {}, {}, {}, {}, {}, {}) ), character_id, - player_profile_struct.binds[4].zone_id, + pp.binds[4].zone_id, 0, - player_profile_struct.binds[4].x, - player_profile_struct.binds[4].y, - player_profile_struct.binds[4].z, - player_profile_struct.binds[4].heading, + pp.binds[4].x, + pp.binds[4].y, + pp.binds[4].z, + pp.binds[4].heading, 4 ); auto results_bset = QueryDatabase(query); @@ -298,12 +297,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o VALUES ({}, {}, {}, {}, {}, {}, {}, {}) ), character_id, - player_profile_struct.binds[0].zone_id, + pp.binds[0].zone_id, 0, - player_profile_struct.binds[0].x, - player_profile_struct.binds[0].y, - player_profile_struct.binds[0].z, - player_profile_struct.binds[0].heading, + pp.binds[0].x, + pp.binds[0].y, + pp.binds[0].z, + pp.binds[0].heading, 0 ); auto results_bset = QueryDatabase(query); @@ -314,7 +313,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o // we know that home and main bind must be valid here, so we don't check those // we also use home to fill in the null data like live does. for (int i = 1; i < 4; i++) { - if (player_profile_struct.binds[i].zone_id != 0) // we assume 0 is the only invalid one ... + if (pp.binds[i].zone_id != 0) // we assume 0 is the only invalid one ... continue; std::string query = fmt::format( @@ -325,12 +324,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o VALUES ({}, {}, {}, {}, {}, {}, {}, {}) ), character_id, - player_profile_struct.binds[4].zone_id, + pp.binds[4].zone_id, 0, - player_profile_struct.binds[4].x, - player_profile_struct.binds[4].y, - player_profile_struct.binds[4].z, - player_profile_struct.binds[4].heading, + pp.binds[4].x, + pp.binds[4].y, + pp.binds[4].z, + pp.binds[4].heading, i ); auto results_bset = QueryDatabase(query); @@ -352,10 +351,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o uint8 slot = 0; for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) { slot = atoi(row_b[0]); - player_profile_struct.item_tint.Slot[slot].Red = atoi(row_b[1]); - player_profile_struct.item_tint.Slot[slot].Green = atoi(row_b[2]); - player_profile_struct.item_tint.Slot[slot].Blue = atoi(row_b[3]); - player_profile_struct.item_tint.Slot[slot].UseTint = atoi(row_b[4]); + pp.item_tint.Slot[slot].Red = atoi(row_b[1]); + pp.item_tint.Slot[slot].Green = atoi(row_b[2]); + pp.item_tint.Slot[slot].Blue = atoi(row_b[3]); + pp.item_tint.Slot[slot].UseTint = atoi(row_b[4]); } if (GetCharSelInventory(account_id, p_character_select_entry_struct->Name, &inventory_profile)) { @@ -394,8 +393,8 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o } else { // Armor Materials/Models uint32 color = ( - player_profile_struct.item_tint.Slot[matslot].UseTint ? - player_profile_struct.item_tint.Slot[matslot].Color : + pp.item_tint.Slot[matslot].UseTint ? + pp.item_tint.Slot[matslot].Color : inst->GetColor() ); p_character_select_entry_struct->Equip[matslot].Material = item->Material; @@ -527,7 +526,7 @@ int WorldDatabase::MoveCharacterToInstanceSafeReturn( } bool WorldDatabase::GetStartZone( - PlayerProfile_Struct *p_player_profile_struct, + PlayerProfile_Struct *pp, CharCreate_Struct *p_char_create_struct, bool is_titanium ) @@ -539,20 +538,20 @@ bool WorldDatabase::GetStartZone( // For now, if no row matching row is found, send them to Crescent Reach, as that is probably the most likely // reason for no match being found. // - if (!p_player_profile_struct || !p_char_create_struct) { + if (!pp || !p_char_create_struct) { return false; } - p_player_profile_struct->x = 0; - p_player_profile_struct->y = 0; - p_player_profile_struct->z = 0; - p_player_profile_struct->heading = 0; - p_player_profile_struct->zone_id = 0; - p_player_profile_struct->binds[0].x = 0; - p_player_profile_struct->binds[0].y = 0; - p_player_profile_struct->binds[0].z = 0; - p_player_profile_struct->binds[0].zone_id = 0; - p_player_profile_struct->binds[0].instance_id = 0; + pp->x = 0; + pp->y = 0; + pp->z = 0; + pp->heading = 0; + pp->zone_id = 0; + pp->binds[0].x = 0; + pp->binds[0].y = 0; + pp->binds[0].z = 0; + pp->binds[0].zone_id = 0; + pp->binds[0].instance_id = 0; // see if we have an entry for start_zone. We can support both titanium & SOF+ by having two entries per class/race/deity combo with different zone_ids std::string query; @@ -592,53 +591,51 @@ bool WorldDatabase::GetStartZone( if (results.RowCount() == 0) { printf("No start_zones entry in database, using defaults\n"); - is_titanium ? SetTitaniumDefaultStartZone(p_player_profile_struct, p_char_create_struct) : SetSoFDefaultStartZone(p_player_profile_struct, p_char_create_struct); + is_titanium ? SetTitaniumDefaultStartZone(pp, p_char_create_struct) : SetSoFDefaultStartZone(pp, p_char_create_struct); } else { LogInfo("Found starting location in start_zones"); auto row = results.begin(); - p_player_profile_struct->x = atof(row[0]); - p_player_profile_struct->y = atof(row[1]); - p_player_profile_struct->z = atof(row[2]); - p_player_profile_struct->heading = atof(row[3]); - p_player_profile_struct->zone_id = atoi(row[4]); - p_player_profile_struct->binds[0].zone_id = atoi(row[5]); - p_player_profile_struct->binds[0].x = atof(row[6]); - p_player_profile_struct->binds[0].y = atof(row[7]); - p_player_profile_struct->binds[0].z = atof(row[8]); - p_player_profile_struct->binds[0].heading = atof(row[3]); + pp->x = atof(row[0]); + pp->y = atof(row[1]); + pp->z = atof(row[2]); + pp->heading = atof(row[3]); + pp->zone_id = atoi(row[4]); + pp->binds[0].zone_id = atoi(row[5]); + pp->binds[0].x = atof(row[6]); + pp->binds[0].y = atof(row[7]); + pp->binds[0].z = atof(row[8]); + pp->binds[0].heading = atof(row[3]); } if ( - p_player_profile_struct->x == 0 && - p_player_profile_struct->y == 0 && - p_player_profile_struct->z == 0 && - p_player_profile_struct->heading == 0 + pp->x == 0 && + pp->y == 0 && + pp->z == 0 && + pp->heading == 0 ) { - content_db.GetSafePoints( - ZoneName(p_player_profile_struct->zone_id, true), - 0, - &p_player_profile_struct->x, - &p_player_profile_struct->y, - &p_player_profile_struct->z, - &p_player_profile_struct->heading - ); + auto zone = GetZone(pp->zone_id); + if (zone) { + pp->x = zone->safe_x; + pp->y = zone->safe_y; + pp->z = zone->safe_z; + pp->heading = zone->safe_heading; + } } if ( - p_player_profile_struct->binds[0].x == 0 && - p_player_profile_struct->binds[0].y == 0 && - p_player_profile_struct->binds[0].z == 0 && - p_player_profile_struct->binds[0].heading == 0 + pp->binds[0].x == 0 && + pp->binds[0].y == 0 && + pp->binds[0].z == 0 && + pp->binds[0].heading == 0 ) { - content_db.GetSafePoints( - ZoneName(p_player_profile_struct->binds[0].zone_id, true), - 0, - &p_player_profile_struct->binds[0].x, - &p_player_profile_struct->binds[0].y, - &p_player_profile_struct->binds[0].z, - &p_player_profile_struct->binds[0].heading - ); + auto zone = GetZone(pp->binds[0].zone_id); + if (zone) { + pp->binds[0].x = zone->safe_x; + pp->binds[0].y = zone->safe_y; + pp->binds[0].z = zone->safe_z; + pp->binds[0].heading = zone->safe_heading; + } } return true; diff --git a/world/worlddb.h b/world/worlddb.h index ae26b0ff7..d5bfdf3f5 100644 --- a/world/worlddb.h +++ b/world/worlddb.h @@ -29,7 +29,7 @@ struct CharacterSelect_Struct; class WorldDatabase : public SharedDatabase { public: - bool GetStartZone(PlayerProfile_Struct* p_player_profile_struct, CharCreate_Struct* p_char_create_struct, bool is_titanium); + bool GetStartZone(PlayerProfile_Struct* pp, CharCreate_Struct* p_char_create_struct, bool is_titanium); void GetCharSelectInfo(uint32 account_id, EQApplicationPacket **out_app, uint32 client_version_bit); int MoveCharacterToBind(int character_id, uint8 bind_number = 0); int MoveCharacterToInstanceSafeReturn(int character_id, int instance_zone_id, int instance_id); diff --git a/world/zonelist.cpp b/world/zonelist.cpp index b548fa94a..7ba848929 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -22,12 +22,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "world_config.h" #include "../common/misc_functions.h" #include "../common/servertalk.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/random.h" #include "../common/json/json.h" #include "../common/event_sub.h" #include "web_interface.h" -#include "world_store.h" +#include "../common/zone_store.h" extern uint32 numzones; extern EQ::Random emu_random; @@ -50,7 +50,7 @@ ZSList::~ZSList() { void ZSList::ShowUpTime(WorldTCPConnection* con, const char* adminname) { uint32 ms = Timer::GetCurrentTime(); - std::string time_string = ConvertMillisecondsToTime(ms); + std::string time_string = Strings::MillisecondsToTime(ms); con->SendEmoteMessage( adminname, 0, @@ -311,19 +311,19 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con strcpy(locked, "No"); } - fmt::memory_buffer out; + std::vector out; if (connection->IsConsole()) { - fmt::format_to(out, "World Locked: {}\r\n", locked); + fmt::format_to(std::back_inserter(out), "World Locked: {}\r\n", locked); } else { - fmt::format_to(out, "World Locked: {}^", locked); + fmt::format_to(std::back_inserter(out), "World Locked: {}^", locked); } if (connection->IsConsole()) { - fmt::format_to(out, "Zoneservers online:\r\n"); + fmt::format_to(std::back_inserter(out), "Zoneservers online:\r\n"); } else { - fmt::format_to(out, "Zoneservers online:^"); + fmt::format_to(std::back_inserter(out), "Zoneservers online:^"); } int v = 0, w = 0, x = 0, y = 0, z = 0; @@ -363,7 +363,7 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con zone_data_string[0] = 0; } - fmt::format_to(out, + fmt::format_to(std::back_inserter(out), "#{:<3} :: {} :: {}:{:<5} :: {:2} :: {}:{} :: {} :: ({})", zone_server_data->GetID(), is_static_string, @@ -377,21 +377,20 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con ); if (out.size() >= 3584) { - auto output = fmt::to_string(out); connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - output.c_str() + out.data() ); out.clear(); } else { if (connection->IsConsole()) - fmt::format_to(out, "\r\n"); + fmt::format_to(std::back_inserter(out), "\r\n"); else - fmt::format_to(out, "^"); + fmt::format_to(std::back_inserter(out), "^"); } x++; } @@ -400,24 +399,23 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con strcpy(zone_data_string, zone_server_data->GetZoneName()); else zone_data_string[0] = 0; - fmt::format_to(out, " #{} {} {}", zone_server_data->GetID(), is_static_string, zone_data_string); + fmt::format_to(std::back_inserter(out), " #{} {} {}", zone_server_data->GetID(), is_static_string, zone_data_string); if (out.size() >= 3584) { - auto output = fmt::to_string(out); connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - output.c_str() + out.data() ); out.clear(); } else { if (connection->IsConsole()) { - fmt::format_to(out, "\r\n"); + fmt::format_to(std::back_inserter(out), "\r\n"); } else { - fmt::format_to(out, "^"); + fmt::format_to(std::back_inserter(out), "^"); } } x++; @@ -427,21 +425,20 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con } if (connection->IsConsole()) { - fmt::format_to(out, "{} servers listed. {} servers online.\r\n", x, y); + fmt::format_to(std::back_inserter(out), "{} servers listed. {} servers online.\r\n", x, y); } else { - fmt::format_to(out, "{} servers listed. {} servers online.^", x, y); + fmt::format_to(std::back_inserter(out), "{} servers listed. {} servers online.^", x, y); } - fmt::format_to(out, "{} zones are static zones, {} zones are booted zones, {} zones available.", z, w, v); + fmt::format_to(std::back_inserter(out), "{} zones are static zones, {} zones are booted zones, {} zones available.", z, w, v); - auto output = fmt::to_string(out); connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - output.c_str() + out.data() ); } diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 88e3dfcf0..0edd6e88f 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -28,15 +28,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/guilds.h" #include "../common/packet_dump.h" #include "../common/misc.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "cliententry.h" #include "wguild_mgr.h" #include "lfplist.h" #include "adventure_manager.h" #include "ucs.h" #include "queryserv.h" -#include "world_store.h" +#include "../common/zone_store.h" #include "dynamic_zone.h" +#include "dynamic_zone_manager.h" #include "expedition_message.h" #include "shared_task_world_messaging.h" #include "../common/shared_tasks.h" @@ -93,7 +94,7 @@ ZoneServer::~ZoneServer() { } } -bool ZoneServer::SetZone(uint32 in_zone_id, uint32 in_instance_id, bool is_static_zone) { +bool ZoneServer::SetZone(uint32 in_zone_id, uint32 in_instance_id, bool in_is_static_zone) { is_booting_up = false; std::string zone_short_name = ZoneName(in_zone_id, true); @@ -101,7 +102,7 @@ bool ZoneServer::SetZone(uint32 in_zone_id, uint32 in_instance_id, bool is_stati if (in_zone_id) { LogInfo( - "Setting zone process to Zone: {} ({}) ID: {}{}{}", + "Setting zone process to Zone [{}] [{}] zone_id [{}] {}{}", zone_long_name, zone_short_name, in_zone_id, @@ -113,7 +114,7 @@ bool ZoneServer::SetZone(uint32 in_zone_id, uint32 in_instance_id, bool is_stati ) : "" ), - is_static_zone ? " (Static)" : "" + in_is_static_zone ? " (Static)" : "" ); } @@ -129,7 +130,7 @@ bool ZoneServer::SetZone(uint32 in_zone_id, uint32 in_instance_id, bool is_stati LSSleepUpdate(GetPrevZoneID()); } - is_static_zone = is_static_zone; + is_static_zone = in_is_static_zone; strn0cpy(zone_name, zone_short_name.c_str(), sizeof(zone_name)); strn0cpy(long_name, zone_long_name.c_str(), sizeof(long_name)); @@ -457,27 +458,25 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { ( cle->TellsOff() && ( - ( - cle->Anon() == 1 && - scm->fromadmin < cle->Admin() - ) || - scm->fromadmin < AccountStatus::QuestTroupe + scm->fromadmin < cle->Admin() + || scm->fromadmin < AccountStatus::QuestTroupe ) ) - ) { + ) { if (!scm->noreply) { auto sender = client_list.FindCharacter(scm->from); if (!sender || !sender->Server()) { break; } - scm->noreply = true; - scm->queued = 3; // offline + scm->noreply = true; + scm->queued = 3; // offline scm->chan_num = ChatChannel_TellEcho; strcpy(scm->deliverto, scm->from); sender->Server()->SendPacket(pack); } - } else if (cle->Online() == CLE_Status::Zoning) { + } + else if (cle->Online() == CLE_Status::Zoning) { if (!scm->noreply) { auto sender = client_list.FindCharacter(scm->from); if (cle->TellQueueFull()) { @@ -527,6 +526,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { } } else { if ( + scm->chan_num == ChatChannel_Guild || + scm->chan_num == ChatChannel_Auction || scm->chan_num == ChatChannel_OOC || scm->chan_num == ChatChannel_Broadcast || scm->chan_num == ChatChannel_GMSAY @@ -818,7 +819,12 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { ingress_server->SendPacket(pack); // inform target server } } else { - LogInfo("Processing ZTZ for ingress to zone for client [{}]", ztz->name); + LogInfo( + "Processing ZTZ for ingress to zone for client [{}] instance_id [{}] zone_id [{}]", + ztz->name, + ztz->current_instance_id, + ztz->current_zone_id + ); auto egress_server = ( ztz->current_instance_id ? zoneserver_list.FindByInstanceID(ztz->current_instance_id) : @@ -826,6 +832,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { ); if (egress_server) { + LogInfo("Found egress server, forwarding client"); egress_server->SendPacket(pack); } } @@ -972,8 +979,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { break; } - auto slock = (ServerLock_Struct*) pack->pBuffer; - if (slock->mode >= 1) { + auto l = (ServerLock_Struct*) pack->pBuffer; + if (l->is_locked) { WorldConfig::LockWorld(); } else { WorldConfig::UnlockWorld(); @@ -982,24 +989,24 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { if (loginserverlist.Connected()) { loginserverlist.SendStatus(); SendEmoteMessage( - slock->myname, + l->character_name, 0, AccountStatus::Player, - Chat::Red, + Chat::Yellow, fmt::format( "World {}.", - slock->mode ? "locked" : "unlocked" + l->is_locked ? "locked" : "unlocked" ).c_str() ); } else { SendEmoteMessage( - slock->myname, + l->character_name, 0, AccountStatus::Player, - Chat::Red, + Chat::Yellow, fmt::format( "World {}, but login server not connected.", - slock->mode ? "locked" : "unlocked" + l->is_locked ? "locked" : "unlocked" ).c_str() ); } @@ -1245,6 +1252,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { loginserverlist.SendAccountUpdate(pack); break; } + case ServerOP_DiscordWebhookMessage: case ServerOP_UCSMailMessage: { UCSLink.SendPacket(pack); break; @@ -1306,6 +1314,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { case ServerOP_ReloadAAData: case ServerOP_ReloadAlternateCurrencies: case ServerOP_ReloadBlockedSpells: + case ServerOP_ReloadCommands: case ServerOP_ReloadDoors: case ServerOP_ReloadGroundSpawns: case ServerOP_ReloadLevelEXPMods: @@ -1321,6 +1330,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { case ServerOP_ReloadVeteranRewards: case ServerOP_ReloadWorld: case ServerOP_ReloadZonePoints: + case ServerOP_ReloadZoneData: case ServerOP_RezzPlayerAccept: case ServerOP_SpawnStatusChange: case ServerOP_UpdateSpawn: @@ -1341,9 +1351,10 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { zoneserver_list.SendPacket(pack); content_service.SetExpansionContext()->ReloadContentFlags(); break; - } + } case ServerOP_ReloadLogs: { zoneserver_list.SendPacket(pack); + UCSLink.SendPacket(pack); LogSys.LoadLogDatabaseSettings(); break; } @@ -1352,6 +1363,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { zoneserver_list.SendPacket(pack); break; } + case ServerOP_ReloadDzTemplates: { + dynamic_zone_manager.LoadTemplates(); + zoneserver_list.SendPacket(pack); + break; + } case ServerOP_ChangeSharedMem: { auto hotfix_name = std::string((char*) pack->pBuffer); @@ -1385,7 +1401,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { } case ServerOP_SharedTaskRequest: case ServerOP_SharedTaskAddPlayer: - case ServerOP_SharedTaskAttemptRemove: + case ServerOP_SharedTaskQuit: case ServerOP_SharedTaskUpdate: case ServerOP_SharedTaskRequestMemberlist: case ServerOP_SharedTaskRemovePlayer: @@ -1394,6 +1410,9 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { case ServerOP_SharedTaskCreateDynamicZone: case ServerOP_SharedTaskPurgeAllCommand: case ServerOP_SharedTaskPlayerList: + case ServerOP_SharedTaskLock: + case ServerOP_SharedTaskEndByDz: + case ServerOP_SharedTaskEnd: case ServerOP_SharedTaskKickPlayers: { SharedTaskWorldMessaging::HandleZoneMessage(pack); break; @@ -1416,6 +1435,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { case ServerOP_DzSetCompass: case ServerOP_DzSetSafeReturn: case ServerOP_DzSetZoneIn: + case ServerOP_DzSetSwitchID: + case ServerOP_DzMovePC: case ServerOP_DzUpdateMemberStatus: { DynamicZone::HandleZoneMessage(pack); break; diff --git a/world/zoneserver.h b/world/zoneserver.h index 07fe96e60..f7b5ea3ac 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -40,7 +40,7 @@ public: void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...); void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message); void SendKeepAlive(); - bool SetZone(uint32 in_zone_id, uint32 in_instance_id = 0, bool is_static_zone = false); + bool SetZone(uint32 in_zone_id, uint32 in_instance_id = 0, bool in_is_static_zone = false); void TriggerBootup(uint32 in_zone_id = 0, uint32 in_instance_id = 0, const char* admin_name = 0, bool is_static_zone = false); void Disconnect() { auto handle = tcpc->Handle(); if (handle) { handle->Disconnect(); } } void IncomingClient(Client* client); diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 51fc7f875..90a3b350b 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) SET(zone_sources aa.cpp @@ -16,6 +16,7 @@ SET(zone_sources botspellsai.cpp cheat_manager.cpp client.cpp + client_bot.cpp client_mods.cpp client_packet.cpp client_process.cpp @@ -140,9 +141,7 @@ SET(zone_sources spell_effects.cpp spells.cpp task_client_state.cpp - task_goal_list_manager.cpp task_manager.cpp - task_proximity_manager.cpp tasks.cpp titles.cpp tradeskills.cpp @@ -161,7 +160,6 @@ SET(zone_sources zonedb.cpp zone_event_scheduler.cpp zone_reload.cpp - zone_store.cpp zoning.cpp ) @@ -171,7 +169,6 @@ SET(zone_headers aggromanager.h api_service.h aura.h - basic_functions.h beacon.h bot.h bot_command.h @@ -235,7 +232,6 @@ SET(zone_headers lua_stat_bonuses.h map.h masterentity.h - maxskill.h message.h merc.h mob.h @@ -267,9 +263,7 @@ SET(zone_headers spawngroup.h string_ids.h task_client_state.h - task_goal_list_manager.h task_manager.h - task_proximity_manager.h tasks.h titles.h trap.h @@ -284,7 +278,6 @@ SET(zone_headers zonedb.h zonedump.h zone_reload.h - zone_store.h ) ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers}) diff --git a/zone/aa.cpp b/zone/aa.cpp index b6a106bdc..f3ee4e0ee 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -22,18 +22,21 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) #include "../common/eq_packet_structs.h" #include "../common/races.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "aa.h" #include "client.h" #include "corpse.h" #include "groups.h" #include "mob.h" #include "queryserv.h" +#include "quest_parser_collection.h" #include "raids.h" #include "string_ids.h" #include "titles.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" + +#include "bot.h" extern QueryServ* QServ; @@ -310,7 +313,7 @@ void Mob::WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *target, uint3 //pet.duration += GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000; //TODO: Does WTD use pet focus? pet.npc_id = WAKE_THE_DEAD_NPCTYPEID; - + NPCType *made_npc = nullptr; const NPCType *npc_type = content_db.LoadNPCTypesData(WAKE_THE_DEAD_NPCTYPEID); @@ -545,7 +548,7 @@ void Client::ResetAA() { m_pp.raid_leadership_points = 0; m_pp.group_leadership_exp = 0; m_pp.raid_leadership_exp = 0; - + database.DeleteCharacterAAs(CharacterID()); database.DeleteCharacterLeadershipAAs(CharacterID()); } @@ -1147,65 +1150,95 @@ bool Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore } void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost) { - int rank_id = rank->base_ability->first_rank_id; + auto rank_id = rank->base_ability->first_rank_id; - if(rank->base_ability->charges > 0) { + if (rank->base_ability->charges) { uint32 charges = 0; GetAA(rank_id, &charges); - if(charges > 0) { + if (charges) { return; } SetAA(rank_id, rank->current_value, rank->base_ability->charges); - } - else { + } else { SetAA(rank_id, rank->current_value, 0); //if not max then send next aa - if(rank->next) { + if (rank->next) { SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); } } - int cost = !ignore_cost ? rank->cost : 0; + auto cost = !ignore_cost ? rank->cost : 0; - m_pp.aapoints -= cost ; + m_pp.aapoints -= static_cast(cost); SaveAA(); SendAlternateAdvancementPoints(); SendAlternateAdvancementStats(); - if(rank->prev) { - MessageString(Chat::Yellow, AA_IMPROVE, - std::to_string(rank->title_sid).c_str(), - std::to_string(rank->prev->current_value).c_str(), - std::to_string(cost).c_str(), - cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); + if (rank->prev) { + MessageString( + Chat::Yellow, + AA_IMPROVE, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->prev->current_value).c_str(), + std::to_string(cost).c_str(), + cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str() + ); /* QS: Player_Log_AA_Purchases */ - if(RuleB(QueryServ, PlayerLogAAPurchases)) { - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); + if (RuleB(QueryServ, PlayerLogAAPurchases)) { + const auto event_desc = fmt::format( + "Ranked AA Purchase :: aa_id:{} at cost:{} in zoneid:{} instid:{}", + rank->id, + cost, + GetZoneID(), + GetInstanceID() + ); + QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } - } - else { - MessageString(Chat::Yellow, AA_GAIN_ABILITY, - std::to_string(rank->title_sid).c_str(), - std::to_string(cost).c_str(), - cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); + } else { + MessageString( + Chat::Yellow, + AA_GAIN_ABILITY, + std::to_string(rank->title_sid).c_str(), + std::to_string(cost).c_str(), + cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str() + ); + /* QS: Player_Log_AA_Purchases */ - if(RuleB(QueryServ, PlayerLogAAPurchases)) { - std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); + if (RuleB(QueryServ, PlayerLogAAPurchases)) { + const auto event_desc = fmt::format( + "Initial AA Purchase :: aa_id:{} at cost:{} in zoneid:{} instid:{}", + rank->id, + cost, + GetZoneID(), + GetInstanceID() + ); + QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } } + const auto export_string = fmt::format( + "{} {} {} {}", + cost, + rank->id, + rank->prev_id, + rank->next_id + ); + + parse->EventPlayer(EVENT_AA_BUY, this, export_string, 0); + CalcBonuses(); - if(cost > 0) { - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + if (cost) { + if (title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) { NotifyNewTitlesAvailable(); + } } } @@ -1561,13 +1594,11 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return false; } } -#ifdef BOTS else if (IsBot()) { - if (rank->expansion && !(RuleI(Bots, BotExpansionSettings) & (1 << (rank->expansion - 1)))) { + if (rank->expansion && !(CastToBot()->GetExpansionBitmask() & (1 << (rank->expansion - 1)))) { return false; } } -#endif else { if (rank->expansion && !(RuleI(World, ExpansionSettings) & (1 << (rank->expansion - 1)))) { return false; @@ -1665,7 +1696,6 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, } void Zone::LoadAlternateAdvancement() { - LogInfo("Loading Alternate Advancement Data"); if(!content_db.LoadAlternateAdvancementAbilities(aa_abilities, aa_ranks)) { @@ -1675,7 +1705,6 @@ void Zone::LoadAlternateAdvancement() { return; } - LogInfo("Processing Alternate Advancement Data"); for(const auto &ability : aa_abilities) { ability.second->first = GetAlternateAdvancementRank(ability.second->first_rank_id); @@ -1725,14 +1754,11 @@ void Zone::LoadAlternateAdvancement() { current = current->next; } } - - LogInfo("Loaded Alternate Advancement Data"); } bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, std::unordered_map> &ranks) { - LogInfo("Loading Alternate Advancement Abilities"); abilities.clear(); std::string query = "SELECT id, name, category, classes, races, deities, drakkin_heritage, status, type, charges, " "grant_only, reset_on_death, first_rank_id FROM aa_ability WHERE enabled = 1"; @@ -1763,11 +1789,10 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map= 0) { query = fmt::format("SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, " @@ -1805,9 +1830,8 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapGetAlternateAdvancementRank(rank.next_id); - + //Add checks for any special cases for toggle. if (IsEffectinAlternateAdvancementRankEffects(*rank_next, SE_Weapon_Stance)) { weaponstance.aabonus_enabled = true; @@ -1990,7 +2013,7 @@ bool Client::IsEffectinAlternateAdvancementRankEffects(const AA::Rank &rank, int } void Client::ResetAlternateAdvancementRank(uint32 aa_id) { - + /* Resets your AA to baseline */ @@ -2010,7 +2033,7 @@ void Client::ResetAlternateAdvancementRank(uint32 aa_id) { } void Client::TogglePurchaseAlternativeAdvancementRank(int rank_id){ - + /* Stripped down version of purchasing AA. Will give no messages. Used with toggle hotkey functions. diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 4d020ce3d..d9a03d94c 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -27,9 +27,7 @@ #include "entity.h" #include "mob.h" -#ifdef BOTS #include "bot.h" -#endif #include "map.h" #include "water_map.h" @@ -43,7 +41,7 @@ void EntityList::DescribeAggro(Client *to_who, NPC *from_who, float d, bool verb to_who->Message( Chat::White, fmt::format( - "Describing aggro for {} ({}).", + "Describing aggro for {}.", to_who->GetTargetDescription(from_who) ).c_str() ); @@ -818,14 +816,15 @@ type', in which case, the answer is yes. } } -#ifdef BOTS - // this is HIGHLY inefficient - bool HasRuleDefined = false; - bool IsBotAttackAllowed = false; - IsBotAttackAllowed = Bot::IsBotAttackAllowed(mob1, mob2, HasRuleDefined); - if(HasRuleDefined) - return IsBotAttackAllowed; -#endif //BOTS + if (RuleB(Bots, Enabled)) { + // this is HIGHLY inefficient + bool HasRuleDefined = false; + bool IsBotAttackAllowed = false; + IsBotAttackAllowed = Bot::IsBotAttackAllowed(mob1, mob2, HasRuleDefined); + if (HasRuleDefined) { + return IsBotAttackAllowed; + } + } // we fell through, now we swap the 2 mobs and run through again once more tempmob = mob1; @@ -905,10 +904,8 @@ bool Mob::IsBeneficialAllowed(Mob *target) { return false; } -#ifdef BOTS else if(mob2->IsBot()) return true; -#endif } else if(_NPC(mob1)) { @@ -980,24 +977,28 @@ bool Mob::IsBeneficialAllowed(Mob *target) bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage) { - if(!other) + if (!other) { return(false); + } float size_mod = GetSize(); float other_size_mod = other->GetSize(); - if(GetRace() == 49 || GetRace() == 158 || GetRace() == 196) //For races with a fixed size + if (GetRace() == RACE_LAVA_DRAGON_49 || GetRace() == RACE_WURM_158 || GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size size_mod = 60.0f; - else if (size_mod < 6.0) + } + else if (size_mod < 6.0) { size_mod = 8.0f; + } - if(other->GetRace() == 49 || other->GetRace() == 158 || other->GetRace() == 196) //For races with a fixed size + if (other->GetRace() == RACE_LAVA_DRAGON_49 || other->GetRace() == RACE_WURM_158 || other->GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size other_size_mod = 60.0f; - else if (other_size_mod < 6.0) + } + else if (other_size_mod < 6.0) { other_size_mod = 8.0f; + } - if (other_size_mod > size_mod) - { + if (other_size_mod > size_mod) { size_mod = other_size_mod; } @@ -1011,11 +1012,11 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage) size_mod *= size_mod * 4; } - if (other->GetRace() == 184) // Lord Vyemm and other velious dragons + if (other->GetRace() == RACE_VELIOUS_DRAGON_184) // Lord Vyemm and other velious dragons { size_mod *= 1.75; } - if (other->GetRace() == 122) // Dracoliche in Fear. Skeletal Dragon + if (other->GetRace() == RACE_DRAGON_SKELETON_122) // Dracoliche in Fear. Skeletal Dragon { size_mod *= 2.25; } @@ -1029,44 +1030,48 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage) // improved playability and "you are too far away" while chasing // a fleeing mob. The Blind check is to make sure that this does not // apply to disoriented fleeing mobs who need proximity to turn and fight. - if (other->currently_fleeing && !other->IsBlind()) - { + if (other->currently_fleeing && !other->IsBlind()) { size_mod *= 3; } // prevention of ridiculously sized hit boxes - if (size_mod > 10000) + if (size_mod > 10000) { size_mod = size_mod / 7; + } float _DistNoRoot = DistanceSquaredNoZ(m_Position, other->GetPosition()); float _zDist = m_Position.z - other->GetZ(); _zDist *= _zDist; - if (GetSpecialAbility(NPC_CHASE_DISTANCE)){ + if (GetSpecialAbility(NPC_CHASE_DISTANCE)) { bool DoLoSCheck = true; float max_dist = static_cast(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 0)); float min_distance = static_cast(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 1)); - if (GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 2)) + if (GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 2)) { DoLoSCheck = false; //Ignore line of sight check + } - if (max_dist == 1) + if (max_dist == 1) { max_dist = 250.0f; //Default it to 250 if you forget to put a value + } max_dist = max_dist * max_dist; - if (!min_distance) + if (!min_distance) { min_distance = size_mod; //Default to melee range - else + } else { min_distance = min_distance * min_distance; + } - if ((DoLoSCheck && CheckLastLosState()) && (_DistNoRoot >= min_distance && _DistNoRoot <= max_dist)) + if ((DoLoSCheck && CheckLastLosState()) && (_DistNoRoot >= min_distance && _DistNoRoot <= max_dist)) { SetPseudoRoot(true); - else + } else { SetPseudoRoot(false); + } } - if(aeRampage) { + if (aeRampage) { float multiplyer = GetSize() * RuleR(Combat, AERampageSafeZone); float ramp_range = (size_mod * multiplyer); if (_DistNoRoot <= ramp_range) { @@ -1372,11 +1377,19 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib break; } } - if (GetOwner() && IsPet()) - AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100; - if (!ignore_default_buff && IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) + if (GetOwner() && IsPet()) { + AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100; + } + + if (!ignore_default_buff && IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { AggroAmount = IsBardSong(spell_id) ? 2 : 9; + } + + // overrides the hate (ex. Healing Splash), can be negative (but function will return 0). + if (spells[spell_id].hate_added != 0) { + AggroAmount = spells[spell_id].hate_added; + } if (AggroAmount > 0) { int HateMod = RuleI(Aggro, SpellAggroMod); @@ -1385,7 +1398,7 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib AggroAmount = (AggroAmount * HateMod) / 100; } - return std::max(0, AggroAmount); + return std::max(0, AggroAmount + spells[spell_id].bonus_hate); //Bonus Hate from spells like Aurora of Morrow } void Mob::AddFeignMemory(Mob* attacker) { @@ -1510,7 +1523,7 @@ bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) { void Mob::RogueEvade(Mob *other) { int64 amount = other->GetHateAmount(this) * zone->random.Int(40, 70) / 100; - other->SetHateAmountOnEnt(this, std::max((int64)100, amount)); + other->SetHateAmountOnEnt(this, std::max(static_cast(100), amount)); return; } diff --git a/zone/api_service.cpp b/zone/api_service.cpp index 109ef3de8..2b2119533 100644 --- a/zone/api_service.cpp +++ b/zone/api_service.cpp @@ -22,7 +22,7 @@ #include "../common/net/websocket_server.h" #include "../common/eqemu_logsys.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "client.h" #include "entity.h" #include "corpse.h" @@ -829,7 +829,7 @@ Json::Value ApiGetZoneAttributes(EQ::Net::WebsocketServerConnection *connection, Json::Value ApiGetLogsysCategories(EQ::Net::WebsocketServerConnection *connection, Json::Value params) { - if (zone->GetZoneID() == 0) { + if (!zone || (zone && zone->GetZoneID() == 0)) { throw EQ::Net::WebsocketException("Zone must be loaded to invoke this call"); } @@ -888,9 +888,8 @@ Json::Value ApiSetLoggingLevel(EQ::Net::WebsocketServerConnection *connection, J void RegisterApiLogEvent(std::unique_ptr &server) { LogSys.SetConsoleHandler( - [&](uint16 debug_level, uint16 log_category, const std::string &msg) { + [&](uint16 log_category, const std::string &msg) { Json::Value data; - data["debug_level"] = debug_level; data["log_category"] = log_category; data["msg"] = msg; server->DispatchEvent(EQ::Net::SubscriptionEventLog, data, 50); diff --git a/zone/attack.cpp b/zone/attack.cpp index 58019b238..5d6d2350b 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/data_verification.h" #include "../common/misc_functions.h" #include "queryserv.h" @@ -36,15 +36,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "mob.h" #include "npc.h" - -#include -#include #include -#include -#ifdef BOTS #include "bot.h" -#endif extern QueryServ* QServ; extern WorldServer worldserver; @@ -385,7 +379,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) * * Formula (all int math) * (posted for parry, assume rest at the same) - * Chance = (((SKILL + 100) + [((SKILL+100) * SPA(175).Base1) / 100]) / 45) + [(hDex / 25) - min([hDex / 25], hStrikethrough)]. + * Chance = (((SKILL + 100) + [((SKILL+100) * SPA(175).Base1) / 100]) / 45) + [(hDex / 25) - min([hStrikethrough, hDex / 25])]. * hStrikethrough is a mob stat that was added to counter the bonuses of heroic stats * Number rolled against 100, if the chance is greater than 100 it happens 100% of time * @@ -398,8 +392,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) /* This special ability adds a negative modifer to the defenders riposte/block/parry/chance - therefore reducing the defenders chance to successfully avoid the melee attack. At present - time this is the only way to fine tune counter these mods on players. This may + therefore reducing the defenders chance to successfully avoid the melee attack. Works in tandem with Heroic Strikethrough. This may ultimately end up being more useful as fields in npc_types. */ @@ -431,6 +424,24 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) modify_dodge = GetSpecialAbilityParam(MODIFY_AVOID_DAMAGE, 4); } + /* Heroic Strikethrough Implementation per Dev Quotes (2018): + * https://forums.daybreakgames.com/eq/index.php?threads/illusions-benefit-neza-10-dodge.246757/#post-3622670 + * Step1 = HeroicStrikethrough(NPC) + * Step2 = HeroicAgility / 25 + * Step3 = MIN( Step1, Step2 ) + * Step4 = DodgeSkill + 100 + * Step5 = Step4 + ( DodgeSkill * DodgeSPA ) / 100 + * Step6 = Step5 / 45 + * DodgeChance = Step6 + ( Step2 - Step3 ) + + * Formula (all int math) + * (posted for parry, dodge appears to be the same as confirmed per Dev, assuming Riposte/Block are the same) + * Chance = (((SKILL + 100) + [((SKILL+100) * SPA(175).Base1) / 100]) / 45) + [(hDex / 25) - min([hStrikethrough, hDex / 25])]. + If an NPC's Heroic Strikethrough is higher than your character's Heroic Agility bonus, you are disqualified from the "bonus" you would have gotten at the end. + */ + + int hstrikethrough = attacker->GetHeroicStrikethrough(); + // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo bool ImmuneRipo = false; if (!RuleB(Combat, UseLiveRiposteMechanics)) { @@ -465,7 +476,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) int chance = GetSkill(EQ::skills::SkillRiposte) + 100; chance += (chance * (aabonuses.RiposteChance + spellbonuses.RiposteChance + itembonuses.RiposteChance)) / 100; chance /= 50; - chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter + chance += (itembonuses.HeroicDEX / 25) - std::min(hstrikethrough,(itembonuses.HeroicDEX / 25)); // "Heroic Strikethrough" subtracted here to counter HeroicDEX if (counter_riposte || counter_all) { float counter = (counter_riposte + counter_all) / 100.0f; chance -= chance * counter; @@ -508,7 +519,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) int chance = GetSkill(EQ::skills::SkillBlock) + 100; chance += (chance * (aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + itembonuses.IncreaseBlockChance)) / 100; chance /= 25; - chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter + chance += (itembonuses.HeroicDEX / 25) - std::min(hstrikethrough,(itembonuses.HeroicDEX / 25)); // "Heroic Strikethrough" subtracted here to counter HeroicDEX if (counter_block || counter_all) { float counter = (counter_block + counter_all) / 100.0f; chance -= chance * counter; @@ -535,7 +546,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) int chance = GetSkill(EQ::skills::SkillParry) + 100; chance += (chance * (aabonuses.ParryChance + spellbonuses.ParryChance + itembonuses.ParryChance)) / 100; chance /= 45; - chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter + chance += (itembonuses.HeroicDEX / 25) - std::min(hstrikethrough,(itembonuses.HeroicDEX / 25)); // "Heroic Strikethrough" subtracted here to counter HeroicDEX if (counter_parry || counter_all) { float counter = (counter_parry + counter_all) / 100.0f; chance -= chance * counter; @@ -562,7 +573,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) int chance = GetSkill(EQ::skills::SkillDodge) + 100; chance += (chance * (aabonuses.DodgeChance + spellbonuses.DodgeChance + itembonuses.DodgeChance)) / 100; chance /= 45; - chance += itembonuses.HeroicAGI / 25; // live has "heroic strickthrough" here to counter + chance += (itembonuses.HeroicAGI / 25) - std::min(hstrikethrough,(itembonuses.HeroicAGI / 25)); // "Heroic Strikethrough" subtracted here to counter HeroicAGI if (counter_dodge || counter_all) { float counter = (counter_dodge + counter_all) / 100.0f; chance -= chance * counter; @@ -904,11 +915,7 @@ int Mob::ACSum(bool skip_caps) if (ac < 0) ac = 0; - if (!skip_caps && (IsClient() -#ifdef BOTS - || IsBot() -#endif - )) { + if (!skip_caps && (IsClient() || IsBot())) { auto softcap = GetACSoftcap(); auto returns = GetSoftcapReturns(); int total_aclimitmod = aabonuses.CombatStability + itembonuses.CombatStability + spellbonuses.CombatStability; @@ -1268,7 +1275,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in return std::max((int64)0, dmg); } -int64 Client::DoDamageCaps(int64 base_damage) +int64 Mob::DoDamageCaps(int64 base_damage) { // this is based on a client function that caps melee base_damage auto level = GetLevel(); @@ -1397,8 +1404,8 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo // check to see if we hit.. if (!FromRiposte && other->AvoidDamage(this, hit)) { - int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - if (strike_through && zone->random.Roll(strike_through)) { + if (int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; + strike_through && zone->random.Roll(strike_through)) { MessageString(Chat::StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! hit.damage_done = 1; // set to one, we will check this to continue @@ -1437,6 +1444,15 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo LogCombat("Attack missed. Damage set to 0"); hit.damage_done = 0; } + + if (IsBot()) { + const auto export_string = fmt::format( + "{} {}", + hit.skill, + GetSkill(hit.skill) + ); + parse->EventBot(EVENT_USE_SKILL, CastToBot(), nullptr, export_string, 0); + } } } @@ -1444,71 +1460,77 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo //stop the attack calculations // IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) //SYNC WITH: tune.cpp, mob.h TuneClientAttack -bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) +bool Mob::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { if (!other) { SetTarget(nullptr); - LogError("A null Mob object was passed to Client::Attack() for evaluation!"); + LogError("A null Mob object was passed for evaluation!"); return false; } - if (!GetTarget()) + if (!GetTarget()) { SetTarget(other); + } - LogCombat("Attacking [{}] with hand [{}] [{}]", other ? other->GetName() : "(nullptr)", Hand, bRiposte ? "(this is a riposte)" : ""); + LogCombatDetail("Attacking [{}] with hand [{}] [{}]", other ? other->GetName() : "nullptr", Hand, bRiposte ? "this is a riposte" : ""); - //SetAttackTimer(); if ( (IsCasting() && GetClass() != BARD && !IsFromSpell) || other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || (GetHP() < 0) || (!IsAttackAllowed(other)) + || (IsBot() && GetAppearance() == eaDead) ) { LogCombat("Attack cancelled, invalid circumstances"); return false; // Only bards can attack while casting } - if (DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm + if (DivineAura() && !CastToClient()->GetGM()) { //cant attack while invulnerable unless your a gm LogCombat("Attack cancelled, Divine Aura is in effect"); - MessageString(Chat::DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable + MessageString(Chat::DefaultText, DIVINE_AURA_NO_ATK); return false; } - if (GetFeigned()) + if (GetFeigned()) { return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. + } - EQ::ItemInstance* weapon = nullptr; - if (Hand == EQ::invslot::slotSecondary) { // Kaiyodo - Pick weapon from the attacking hand - weapon = GetInv().GetItem(EQ::invslot::slotSecondary); + const EQ::ItemInstance* weapon = nullptr; + + + if (IsBot()) { + FaceTarget(GetTarget()); + } + + if (Hand == EQ::invslot::slotSecondary) { + weapon = (IsClient()) ? GetInv().GetItem(EQ::invslot::slotSecondary) : CastToBot()->GetBotItem(EQ::invslot::slotPrimary); OffHandAtk(true); } else { - weapon = GetInv().GetItem(EQ::invslot::slotPrimary); + weapon = (IsClient()) ? GetInv().GetItem(EQ::invslot::slotPrimary) : CastToBot()->GetBotItem(EQ::invslot::slotPrimary); OffHandAtk(false); } - if (weapon != nullptr) { if (!weapon->IsWeapon()) { LogCombat("Attack cancelled, Item [{}] ([{}]) is not a weapon", weapon->GetItem()->Name, weapon->GetID()); return(false); } - LogCombat("Attacking with weapon: [{}] ([{}])", weapon->GetItem()->Name, weapon->GetID()); + LogCombatDetail("Attacking with weapon: [{}] ([{}])", weapon->GetItem()->Name, weapon->GetID()); } else { - LogCombat("Attacking without a weapon"); + LogCombatDetail("Attacking without a weapon"); } DamageHitInfo my_hit; // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients my_hit.skill = AttackAnimation(Hand, weapon); - LogCombat("Attacking with [{}] in slot [{}] using skill [{}]", weapon ? weapon->GetItem()->Name : "Fist", Hand, my_hit.skill); + LogCombatDetail("Attacking with [{}] in slot [{}] using skill [{}]", weapon ? weapon->GetItem()->Name : "Fist", Hand, my_hit.skill); // Now figure out damage my_hit.damage_done = 1; my_hit.min_damage = 0; - uint8 mylevel = GetLevel() ? GetLevel() : 1; int64 hate = 0; if (weapon) hate = (weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt); @@ -1530,8 +1552,10 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b hate = hate * (100 + shield_inc) / 100; } - CheckIncreaseSkill(my_hit.skill, other, -15); - CheckIncreaseSkill(EQ::skills::SkillOffense, other, -15); + if (IsClient()) { + CastToClient()->CheckIncreaseSkill(my_hit.skill, other, -15); + CastToClient()->CheckIncreaseSkill(EQ::skills::SkillOffense, other, -15); + } // *************************************************************** // *** Calculate the damage bonus, if applicable, for this hit *** @@ -1559,19 +1583,20 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } #endif //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand == EQ::invslot::slotSecondary) { - if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc) { + if (Hand == EQ::invslot::slotSecondary && + ( + aabonuses.SecondaryDmgInc || + itembonuses.SecondaryDmgInc || + spellbonuses.SecondaryDmgInc + ) + ) { + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQ::ItemData*) nullptr, true); - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQ::ItemData*) nullptr, true); - - my_hit.min_damage = ucDamageBonus; - hate += ucDamageBonus; - } + my_hit.min_damage = ucDamageBonus; + hate += ucDamageBonus; } - // damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); - - LogCombat("Damage calculated: base [{}] min damage [{}] skill [{}]", my_hit.base_damage, my_hit.min_damage, my_hit.skill); + LogCombatDetail("Damage calculated base [{}] min damage [{}] skill [{}]", my_hit.base_damage, my_hit.min_damage, my_hit.skill); int hit_chance_bonus = 0; my_hit.offense = offense(my_hit.skill); // we need this a few times @@ -1588,6 +1613,8 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); DoAttack(other, my_hit, opts, bRiposte); + + LogCombatDetail("Final damage after all reductions [{}]", my_hit.damage_done); } else { my_hit.damage_done = DMG_INVULNERABLE; @@ -1599,18 +1626,23 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b other->AddToHateList(this, hate); //Guard Assist Code - if (RuleB(Character, PVPEnableGuardFactionAssist)) { - if (IsClient() && other->IsClient() || (HasOwner() && GetOwner()->IsClient() && other->IsClient() )) { - auto& mob_list = entity_list.GetCloseMobList(other); - for (auto& e : mob_list) { - auto mob = e.second; - if (mob->IsNPC() && mob->CastToNPC()->IsGuard()) { - float distance = Distance(other->CastToClient()->m_Position, mob->GetPosition()); - if ((mob->CheckLosFN(other) || mob->CheckLosFN(this)) && distance <= 70) { - auto petorowner = GetOwnerOrSelf(); - if (other->GetReverseFactionCon(mob) <= petorowner->GetReverseFactionCon(mob)) { - mob->AddToHateList(this); - } + if (RuleB(Character, PVPEnableGuardFactionAssist) && + ( + (IsClient() && other->IsClient()) || + (HasOwner() && GetOwner()->IsClient() && other->IsClient()) + ) + ) { + for (auto const& [id, mob] : entity_list.GetCloseMobList(other)) { + if (!mob) { + continue; + } + + if (mob->IsNPC() && mob->CastToNPC()->IsGuard()) { + float distance = Distance(other->CastToClient()->m_Position, mob->GetPosition()); + if ((mob->CheckLosFN(other) || mob->CheckLosFN(this)) && distance <= 70) { + auto petorowner = GetOwnerOrSelf(); + if (other->GetReverseFactionCon(mob) <= petorowner->GetReverseFactionCon(mob)) { + mob->AddToHateList(this); } } } @@ -1622,7 +1654,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b /////////////////////////////////////////////////////////// other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks); - if (IsDead()) { + if (CastToClient()->IsDead() || (IsBot() && GetAppearance() == eaDead)) { return false; } @@ -1686,22 +1718,26 @@ void Client::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::Skill bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::SkillType attack_skill) { - if (!ClientFinishedLoading()) + if (!ClientFinishedLoading()) { return false; + } - if (dead) + if (dead) { return false; //cant die more than once... + } - if (!spell) + if (!spell) { spell = SPELL_UNKNOWN; + } - std::string export_string = fmt::format( + auto export_string = fmt::format( "{} {} {} {}", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill) ); + if (parse->EventPlayer(EVENT_DEATH, this, export_string, 0) != 0) { if (GetHP() < 0) { SetHP(0); @@ -1772,24 +1808,34 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill GetMerc()->Suspend(); } - if (killerMob != nullptr) - { + if (killerMob) { if (killerMob->IsNPC()) { parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); mod_client_death_npc(killerMob); - uint16 emoteid = killerMob->GetEmoteID(); - if (emoteid != 0) - killerMob->CastToNPC()->DoNPCEmote(KILLEDPC, emoteid); + auto emote_id = killerMob->GetEmoteID(); + if (emote_id) { + killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid); + } + + killerMob->TrySpellOnKill(killed_level, spell); + } else if (killerMob->IsBot()) { + parse->EventBot(EVENT_SLAY, killerMob->CastToBot(), this, "", 0); killerMob->TrySpellOnKill(killed_level, spell); } - if (killerMob->IsClient() && (IsDueling() || killerMob->CastToClient()->IsDueling())) { + if ( + killerMob->IsClient() && + (IsDueling() || killerMob->CastToClient()->IsDueling()) + ) { SetDueling(false); SetDuelTarget(0); - if (killerMob->IsClient() && killerMob->CastToClient()->IsDueling() && killerMob->CastToClient()->GetDuelTarget() == GetID()) - { + if ( + killerMob->IsClient() && + killerMob->CastToClient()->IsDueling() && + killerMob->CastToClient()->GetDuelTarget() == GetID() + ) { //if duel opponent killed us... killerMob->CastToClient()->SetDueling(false); killerMob->CastToClient()->SetDuelTarget(0); @@ -1822,16 +1868,19 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill // figure out if they should lose exp if (RuleB(Character, UseDeathExpLossMult)) { - float GetNum[] = { 0.005f,0.015f,0.025f,0.035f,0.045f,0.055f,0.065f,0.075f,0.085f,0.095f,0.110f }; - int Num = RuleI(Character, DeathExpLossMultiplier); - if ((Num < 0) || (Num > 10)) - Num = 3; - float loss = GetNum[Num]; - exploss = (int)((float)GetEXP() * (loss)); //loose % of total XP pending rule (choose 0-10) + float exp_losses[] = { 0.005f, 0.015f, 0.025f, 0.035f, 0.045f, 0.055f, 0.065f, 0.075f, 0.085f, 0.095f, 0.110f }; + int exp_loss = RuleI(Character, DeathExpLossMultiplier); + if (!EQ::ValueWithin(exp_loss, 0, 10)) { + exp_loss = 3; + } + + auto current_exp_loss = exp_losses[exp_loss]; + + exploss = static_cast(static_cast(GetEXP()) * current_exp_loss); //loose % of total XP pending rule (choose 0-10) } if (!RuleB(Character, UseDeathExpLossMult)) { - exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); + exploss = static_cast(GetLevel() * (GetLevel() / 18.0) * 12000); } if (RuleB(Zone, LevelBasedEXPMods)) { @@ -1843,111 +1892,118 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill exploss *= zone->level_exp_mod[GetLevel()].ExpMod; } - if ((GetLevel() < RuleI(Character, DeathExpLossLevel)) || (GetLevel() > RuleI(Character, DeathExpLossMaxLevel)) || IsBecomeNPC()) - { - exploss = 0; - } - else if (killerMob) - { - if (killerMob->IsClient()) - { - exploss = 0; + if (exploss > 0 && RuleB(Character, DeathKeepLevel)) { + int32 total_exp = GetEXP(); + uint32 level_min_exp = GetEXPForLevel(killed_level); + int32 level_exp = total_exp - level_min_exp; + if (exploss > level_exp) { + exploss = level_exp; } - else if (killerMob->GetOwner() && killerMob->GetOwner()->IsClient()) - { + } + + if ((GetLevel() < RuleI(Character, DeathExpLossLevel)) || (GetLevel() > RuleI(Character, DeathExpLossMaxLevel)) || IsBecomeNPC()) { + exploss = 0; + } else if (killerMob) { + if (killerMob->IsClient()) { + exploss = 0; + } else if (killerMob->GetOwner() && killerMob->GetOwner()->IsClient()) { + exploss = 0; + } else if (killerMob->IsBot()) { exploss = 0; } } - if (spell != SPELL_UNKNOWN) - { + if (spell != SPELL_UNKNOWN) { uint32 buff_count = GetMaxTotalSlots(); - for (uint16 buffIt = 0; buffIt < buff_count; buffIt++) - { - if (buffs[buffIt].spellid == spell && buffs[buffIt].client) - { + for (uint16 buffIt = 0; buffIt < buff_count; buffIt++) { + if (buffs[buffIt].spellid == spell && buffs[buffIt].client) { exploss = 0; // no exp loss for pvp dot break; } } } - bool LeftCorpse = false; + bool leave_corpse = false; + Corpse* new_corpse = nullptr; // now we apply the exp loss, unmem their spells, and make a corpse // unless they're a GM (or less than lvl 10 - if (!GetGM()) - { + if (!GetGM()) { if (exploss > 0) { int32 newexp = GetEXP(); if (exploss > newexp) { //lost more than we have... wtf.. newexp = 1; - } - else { + } else { newexp -= exploss; } SetEXP(newexp, GetAAXP()); //m_epp.perAA = 0; //reset to no AA exp on death. } - int32 illusion_spell_id = spellbonuses.Illusion; + auto illusion_spell_id = spellbonuses.Illusion; //this generates a lot of 'updates' to the client that the client does not need - BuffFadeNonPersistDeath(); - if (RuleB(Character, UnmemSpellsOnDeath)) { - if ((ClientVersionBit() & EQ::versions::maskSoFAndLater) && RuleB(Character, RespawnFromHover)) - UnmemSpellAll(true); - else - UnmemSpellAll(false); + if (RuleB(Spells, BuffsFadeOnDeath)) { + BuffFadeNonPersistDeath(); } - if ((RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) || RuleB(Character, LeaveNakedCorpses)) - { + if (RuleB(Character, UnmemSpellsOnDeath)) { + if ((ClientVersionBit() & EQ::versions::maskSoFAndLater) && RuleB(Character, RespawnFromHover)) { + UnmemSpellAll(true); + } else { + UnmemSpellAll(false); + } + } + + if ( + (RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) || + RuleB(Character, LeaveNakedCorpses) + ) { // creating the corpse takes the cash/items off the player too - auto new_corpse = new Corpse(this, exploss); + new_corpse = new Corpse(this, exploss); std::string tmp; database.GetVariable("ServerType", tmp); - if (tmp[0] == '1' && tmp[1] == '\0' && killerMob != nullptr && killerMob->IsClient()) { + if (tmp[0] == '1' && tmp[1] == '\0' && killerMob && killerMob->IsClient()) { database.GetVariable("PvPreward", tmp); - int reward = atoi(tmp.c_str()); + auto reward = atoi(tmp.c_str()); if (reward == 3) { database.GetVariable("PvPitem", tmp); - int pvpitem = atoi(tmp.c_str()); - if (pvpitem>0 && pvpitem<200000) - new_corpse->SetPlayerKillItemID(pvpitem); - } - else if (reward == 2) + auto pvp_item_id = atoi(tmp.c_str()); + const auto* item = database.GetItem(pvp_item_id); + if (item) { + new_corpse->SetPlayerKillItemID(pvp_item_id); + } + } else if (reward == 2) { new_corpse->SetPlayerKillItemID(-1); - else if (reward == 1) + } else if (reward == 1) { new_corpse->SetPlayerKillItemID(1); - else + } else { new_corpse->SetPlayerKillItemID(0); + } + if (killerMob->CastToClient()->isgrouped) { - Group* group = entity_list.GetGroupByClient(killerMob->CastToClient()); - if (group != 0) - { - for (int i = 0; i<6; i++) - { - if (group->members[i] != nullptr) - { + auto* group = entity_list.GetGroupByClient(killerMob->CastToClient()); + if (group) { + for (int i = 0; i < 6; i++) { + if (group->members[i]) { new_corpse->AllowPlayerLoot(group->members[i], i); } } } } } + entity_list.AddCorpse(new_corpse, GetID()); SetID(0); //send the become corpse packet to everybody else in the zone. entity_list.QueueClients(this, &app2, true); ApplyIllusionToCorpse(illusion_spell_id, new_corpse); - LeftCorpse = true; + leave_corpse = true; } - } - else { + } else { BuffFadeDetrimental(); } @@ -1959,8 +2015,9 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill /* Reset reuse timer for classic skill based Lay on Hands (For tit I guess) */ - if (GetClass() == PALADIN) // we could check if it's not expired I guess, but should be fine not to + if (GetClass() == PALADIN) { // we could check if it's not expired I guess, but should be fine not to p_timers.Clear(&database, pTimerLayHands); + } /* Finally, send em home @@ -1969,25 +2026,23 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill from these and overwrite what we set in pp anyway */ - if (LeftCorpse && (ClientVersionBit() & EQ::versions::maskSoFAndLater) && RuleB(Character, RespawnFromHover)) - { + if (leave_corpse && (ClientVersionBit() & EQ::versions::maskSoFAndLater) && RuleB(Character, RespawnFromHover)) { ClearDraggedCorpses(); RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); SendRespawnBinds(); - } - else - { - if (isgrouped) - { - Group *g = GetGroup(); - if (g) + } else { + if (isgrouped) { + auto* g = GetGroup(); + if (g) { g->MemberZoned(this); + } } - Raid* r = entity_list.GetRaidByClient(this); + auto* r = entity_list.GetRaidByClient(this); - if (r) + if (r) { r->MemberZoned(this); + } dead_timer.Start(5000, true); m_pp.zone_id = m_pp.binds[0].zone_id; @@ -2005,7 +2060,8 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill QServ->PlayerLogEvent(Player_Log_Deaths, CharacterID(), event_desc); } - parse->EventPlayer(EVENT_DEATH_COMPLETE, this, export_string, 0); + std::vector args = { new_corpse }; + parse->EventPlayer(EVENT_DEATH_COMPLETE, this, export_string, 0, &args); return true; } //SYNC WITH: tune.cpp, mob.h TuneNPCAttack @@ -2106,6 +2162,9 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool auto& mob_list = entity_list.GetCloseMobList(other); for (auto& e : mob_list) { auto mob = e.second; + if (!mob) { + continue; + } if (mob->IsNPC() && mob->CastToNPC()->IsGuard()) { float distance = Distance(other->GetPosition(), mob->GetPosition()); if ((mob->CheckLosFN(other) || mob->CheckLosFN(this)) && distance <= 70) { @@ -2282,54 +2341,48 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy LogCombat("Fatal blow dealt by [{}] with [{}] damage, spell [{}], skill [{}]", ((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill); - Mob *oos = nullptr; - if (killer_mob) { - oos = killer_mob->GetOwnerOrSelf(); - std::string export_string = fmt::format( - "{} {} {} {}", - killer_mob->GetID(), - damage, - spell, - static_cast(attack_skill) - ); + Mob *oos = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr; + auto export_string = fmt::format( + "{} {} {} {}", + killer_mob ? killer_mob->GetID() : 0, + damage, + spell, + static_cast(attack_skill) + ); + + if (IsNPC()) { if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) { if (GetHP() < 0) { SetHP(0); } + return false; } - - if ((killer_mob->IsClient() || killer_mob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20] = { 0 }; - - entity_list.MessageCloseString( - this, /* Sender */ - false, /* Skip Sender */ - RuleI(Range, DamageMessages), - Chat::NonMelee, /* 283 */ - HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ - killer_mob->GetCleanName(), /* Message1 */ - GetCleanName(), /* Message2 */ - ConvertArray(damage, val1) /* Message3 */ - ); - } - } - else { - std::string export_string = fmt::format( - "{} {} {} {}", - 0, - damage, - spell, - static_cast(attack_skill) - ); - if (parse->EventNPC(EVENT_DEATH, this, nullptr, export_string, 0) != 0) { + } else if (IsBot()) { + if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0) != 0) { if (GetHP() < 0) { SetHP(0); } + return false; } } + if (killer_mob && (killer_mob->IsClient() || killer_mob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) { + char val1[20] = { 0 }; + + entity_list.MessageCloseString( + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, DamageMessages), + Chat::NonMelee, /* 283 */ + HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ + killer_mob->GetCleanName(), /* Message1 */ + GetCleanName(), /* Message2 */ + ConvertArray(damage, val1) /* Message3 */ + ); + } + if (IsEngaged()) { zone->DelAggroMob(); Log(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount()); @@ -2341,23 +2394,25 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy SetPet(0); if (GetSwarmOwner()) { - Mob* owner = entity_list.GetMobID(GetSwarmOwner()); - if (owner) + auto* owner = entity_list.GetMobID(GetSwarmOwner()); + if (owner) { owner->SetTempPetCount(owner->GetTempPetCount() - 1); + } } - Mob* killer = GetHateDamageTop(this); + auto* killer = GetHateDamageTop(this); entity_list.RemoveFromTargets(this, p_depop); - if (p_depop == true) + if (p_depop) { return false; + } - int32 illusion_spell_id = spellbonuses.Illusion; + const auto illusion_spell_id = spellbonuses.Illusion; HasAISpellEffects = false; BuffFadeAll(); - uint8 killed_level = GetLevel(); + const auto killed_level = GetLevel(); if (GetClass() == LDON_TREASURE) { // open chest auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); @@ -2370,7 +2425,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } auto app = new EQApplicationPacket(OP_Death, sizeof(Death_Struct)); - Death_Struct* d = (Death_Struct*)app->pBuffer; + auto* d = (Death_Struct*) app->pBuffer; d->spawn_id = GetID(); d->killer_id = killer_mob ? killer_mob->GetID() : 0; d->bindzoneid = 0; @@ -2386,16 +2441,17 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy respawn2->DeathReset(1); } - if (killer_mob && GetClass() != LDON_TREASURE) + if (killer_mob && GetClass() != LDON_TREASURE) { hate_list.AddEntToHateList(killer_mob, damage); + } Mob *give_exp = hate_list.GetDamageTopOnHateList(this); - if (give_exp == nullptr) + if (give_exp) { give_exp = killer; + } if (give_exp && give_exp->HasOwner()) { - bool ownerInGroup = false; if ((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) || (give_exp->IsPet() && (give_exp->GetOwner()->IsClient() @@ -2404,11 +2460,9 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy give_exp = give_exp->GetUltimateOwner(); -#ifdef BOTS if (!RuleB(Bots, BotGroupXP) && !ownerInGroup) { give_exp = nullptr; } -#endif //BOTS } if (give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) { @@ -2427,7 +2481,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy //do faction hits even if we are a merchant, so long as a player killed us if (!IsCharmed() && give_exp_client && !RuleB(NPC, EnableMeritBasedFaction)) - hate_list.DoFactionHits(GetNPCFactionID()); + hate_list.DoFactionHits(GetNPCFactionID(), GetPrimaryFaction(), GetFactionAmount()); bool IsLdonTreasure = (GetClass() == LDON_TREASURE); @@ -2435,17 +2489,17 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy Group *kg = entity_list.GetGroupByClient(give_exp_client); Raid *kr = entity_list.GetRaidByClient(give_exp_client); - int32 finalxp = give_exp_client->GetExperienceForKill(this); + int64 finalxp = give_exp_client->GetExperienceForKill(this); finalxp = give_exp_client->mod_client_xp(finalxp, this); // handle task credit on behalf of the killer if (RuleB(TaskSystem, EnableTaskSystem)) { LogTasksDetail( - "[NPC::Death] Triggering HandleUpdateTasksOnKill for [{}] npc [{}]", + "Triggering HandleUpdateTasksOnKill for [{}] npc [{}]", give_exp_client->GetCleanName(), GetNPCTypeID() ); - task_manager->HandleUpdateTasksOnKill(give_exp_client, GetNPCTypeID(), GetCleanName()); + task_manager->HandleUpdateTasksOnKill(give_exp_client, this); } if (kr) { @@ -2581,7 +2635,9 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } bool allow_merchant_corpse = RuleB(Merchant, AllowCorpse); - bool is_merchant = (class_ == MERCHANT || class_ == ADVENTUREMERCHANT || MerchantType != 0); + bool is_merchant = (class_ == MERCHANT || class_ == ADVENTURE_MERCHANT || MerchantType != 0); + + Corpse* corpse = nullptr; if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) && ((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || @@ -2598,8 +2654,8 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy entity_list.RemoveFromAutoXTargets(this); - uint16 emoteid = GetEmoteID(); - auto corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, + uint32 emoteid = GetEmoteID(); + corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, level > 54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS) : RuleI(NPC, MinorNPCCorpseDecayTimeMS)); entity_list.LimitRemoveNPC(this); @@ -2614,7 +2670,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy ApplyIllusionToCorpse(illusion_spell_id, corpse); if (killer != 0 && emoteid != 0) - corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid); + corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid); if (killer != 0 && killer->IsClient()) { corpse->AllowPlayerLoot(killer, 0); if (killer->IsGrouped()) { @@ -2696,18 +2752,29 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy if (oos) { mod_npc_killed(oos); - uint16 emoteid = GetEmoteID(); - if (emoteid != 0) - DoNPCEmote(ONDEATH, emoteid); + if (IsNPC()) { + auto emote_id = GetEmoteID(); + if (emote_id) { + DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid); + } + } + if (oos->IsNPC()) { parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); - uint16 emoteid = oos->GetEmoteID(); - if (emoteid != 0) - oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid); + auto emote_id = oos->GetEmoteID(); + if (emote_id) { + oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id); + } + killer_mob->TrySpellOnKill(killed_level, spell); } } + if (killer_mob->IsBot()) { + parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0); + killer_mob->TrySpellOnKill(killed_level, spell); + } + WipeHateList(); p_depop = true; @@ -2716,35 +2783,13 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy entity_list.UpdateFindableNPCState(this, true); - std::string export_string = fmt::format( - "{} {} {} {}", - killer_mob ? killer_mob->GetID() : 0, - damage, - spell, - static_cast(attack_skill) - ); - parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0); + std::vector args = { corpse }; + parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args); combat_record.Stop(); /* Zone controller process EVENT_DEATH_ZONE (Death events) */ - if (RuleB(Zone, UseZoneController)) { - auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID); - if (controller && GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID) { - export_string = fmt::format( - "{} {} {} {} {} {:.2f} {:.2f} {:.2f} {:.2f}", - killer_mob ? killer_mob->GetID() : 0, - damage, - spell, - static_cast(attack_skill), - GetNPCTypeID(), - GetX(), - GetY(), - GetZ(), - GetHeading() - ); - parse->EventNPC(EVENT_DEATH_ZONE, controller, nullptr, export_string, 0); - } - } + args.push_back(this); + DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args); return true; } @@ -2863,32 +2908,33 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo if (other->IsClient() && !on_hatelist && !IsOnFeignMemory(other)) other->CastToClient()->AddAutoXTarget(this); -#ifdef BOTS // if other is a bot, add the bots client to the hate list - while (other->IsBot()) { + if (RuleB(Bots, Enabled)) { + while (other->IsBot()) { + + auto other_ = other->CastToBot(); + if (!other_ || !other_->GetBotOwner()) { + break; + } + + auto owner_ = other_->GetBotOwner()->CastToClient(); + if (!owner_ || owner_->IsDead() || + !owner_->InZone()) { // added isdead and inzone checks to avoid issues in AddAutoXTarget(...) below + break; + } + + if (owner_->GetFeigned()) { + AddFeignMemory(owner_); + } + else if (!hate_list.IsEntOnHateList(owner_)) { + + hate_list.AddEntToHateList(owner_, 0, 0, false, true); + owner_->AddAutoXTarget(this); // this was being called on dead/out-of-zone clients + } - auto other_ = other->CastToBot(); - if (!other_ || !other_->GetBotOwner()) { break; } - - auto owner_ = other_->GetBotOwner()->CastToClient(); - if (!owner_ || owner_->IsDead() || !owner_->InZone()) { // added isdead and inzone checks to avoid issues in AddAutoXTarget(...) below - break; - } - - if (owner_->GetFeigned()) { - AddFeignMemory(owner_); - } - else if (!hate_list.IsEntOnHateList(owner_)) { - - hate_list.AddEntToHateList(owner_, 0, 0, false, true); - owner_->AddAutoXTarget(this); // this was being called on dead/out-of-zone clients - } - - break; } -#endif //BOTS // if other is a merc, add the merc client to the hate list if (other->IsMerc()) { @@ -3265,14 +3311,14 @@ int64 Mob::ReduceDamage(int64 damage) int64 damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] / 100; if (damage_to_reduce >= buffs[slot].melee_rune) { - LogSpells("Mob::ReduceDamage SE_MeleeThresholdGuard [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].melee_rune); + LogSpellsDetail("SE_MeleeThresholdGuard [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].melee_rune); damage -= buffs[slot].melee_rune; if (!TryFadeEffect(slot)) BuffFadeBySlot(slot); } else { - LogSpells("Mob::ReduceDamage SE_MeleeThresholdGuard [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].melee_rune); + LogSpellsDetail("SE_MeleeThresholdGuard [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].melee_rune); buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); damage -= damage_to_reduce; } @@ -3290,14 +3336,14 @@ int64 Mob::ReduceDamage(int64 damage) if (spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT] && (damage_to_reduce >= buffs[slot].melee_rune)) { - LogSpells("Mob::ReduceDamage SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].melee_rune); + LogSpellsDetail("SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].melee_rune); damage -= buffs[slot].melee_rune; if (!TryFadeEffect(slot)) BuffFadeBySlot(slot); } else { - LogSpells("Mob::ReduceDamage SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].melee_rune); + LogSpellsDetail("SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].melee_rune); if (spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT]) buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); @@ -3416,14 +3462,14 @@ int64 Mob::AffectMagicalDamage(int64 damage, uint16 spell_id, const bool iBuffTi if (spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT] && (damage_to_reduce >= buffs[slot].magic_rune)) { - LogSpells("Mob::ReduceDamage SE_MitigateSpellDamage [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].magic_rune); + LogSpellsDetail("SE_MitigateSpellDamage [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].magic_rune); damage -= buffs[slot].magic_rune; if (!TryFadeEffect(slot)) BuffFadeBySlot(slot); } else { - LogSpells("Mob::ReduceDamage SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].magic_rune); + LogSpellsDetail("SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].magic_rune); if (spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT]) buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); @@ -3489,7 +3535,7 @@ bool Mob::HasProcs() const } } - if (IsClient()) { + if (IsClient() || IsBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.SpellProc[i]) { return true; @@ -3507,7 +3553,7 @@ bool Mob::HasDefensiveProcs() const } } - if (IsClient()) { + if (IsClient() || IsBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.DefensiveProc[i]) { return true; @@ -3543,7 +3589,7 @@ bool Mob::HasRangedProcs() const } } - if (IsClient()) { + if (IsClient() || IsBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.RangedProc[i]) { return true; @@ -3675,7 +3721,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons //we used to do a message to the client, but its gone now. // emote goes with every one ... even npcs - entity_list.MessageClose(this, true, RuleI(Range, SpellMessages), Chat::Emote, "%s beams a smile at %s", attacker->GetCleanName(), GetCleanName()); + entity_list.FilteredMessageClose(this, false, RuleI(Range, SpellMessages), Chat::Emote, FilterSocials, "%s beams a smile at %s", attacker->GetCleanName(), GetCleanName()); } // If a client pet is damaged while sitting, stand, fix sit button, @@ -3829,11 +3875,59 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons can_stun = true; } - if ((GetBaseRace() == OGRE || GetBaseRace() == OGGOK_CITIZEN) && - !attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) + bool is_immune_to_frontal_stun = false; + + if (IsBot() || IsClient() || IsMerc()) { + if ( + IsPlayerClass(GetClass()) && + RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass()) + ) { + is_immune_to_frontal_stun = true; + } + + + if ( + ( + IsPlayerRace(GetBaseRace()) && + RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace()) + ) || + GetBaseRace() == RACE_OGGOK_CITIZEN_93 + ) { + is_immune_to_frontal_stun = true; + } + } else if (IsNPC()) { + if ( + RuleB(Combat, NPCsUseFrontalStunImmunityClasses) && + IsPlayerClass(GetClass()) && + RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass()) + ) { + is_immune_to_frontal_stun = true; + } + + if ( + RuleB(Combat, NPCsUseFrontalStunImmunityRaces) && + ( + ( + IsPlayerRace(GetBaseRace()) && + RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace()) + ) || + GetBaseRace() == RACE_OGGOK_CITIZEN_93 + ) + ) { + is_immune_to_frontal_stun = true; + } + } + + if ( + is_immune_to_frontal_stun && + !attacker->BehindMob(this, attacker->GetX(), attacker->GetY()) + ) { can_stun = false; - if (GetSpecialAbility(UNSTUNABLE)) + } + + if (GetSpecialAbility(UNSTUNABLE)) { can_stun = false; + } } if (can_stun) { int bashsave_roll = zone->random.Int(0, 100); @@ -3973,12 +4067,14 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons attacker->MessageString(Chat::DamageShield, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); } else { - entity_list.MessageCloseString( - this, /* Sender */ - true, /* Skip Sender */ + entity_list.FilteredMessageCloseString( + attacker, /* Sender */ + false, /* Sender is attacker, so do not skip */ RuleI(Range, SpellMessages), Chat::NonMelee, /* 283 */ + FilterSpellDamage, /* FilterType: 13 */ HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ + 0, attacker->GetCleanName(), /* Message1 */ GetCleanName(), /* Message2 */ ConvertArray(damage, val1) /* Message3 */ @@ -4021,20 +4117,47 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons // we don't send them here. if (!FromDamageShield) { - entity_list.QueueCloseClients( - this, /* Sender */ - outapp, /* packet */ - true, /* Skip Sender */ - RuleI(Range, SpellMessages), - skip, /* Skip this mob */ - true, /* Packet ACK */ - filter /* eqFilterType filter */ - ); + // Determine message range based on spell/other-damage + int range; + if (IsValidSpell(spell_id)) { + range = RuleI(Range, SpellMessages); + } + else { + range = RuleI(Range, DamageMessages); + } - //send the damage to ourself if we are a client - if (IsClient()) { + // If an "innate" spell, change to spell type to + // produce a spell message. Send to everyone. + // This fixes issues with npc-procs like 1002 and 918 which + // need to spit out extra spell color. + if (IsValidSpell(spell_id) && skill_used == EQ::skills::SkillTigerClaw) { + a->type = DamageTypeSpell; + entity_list.QueueCloseClients( + this, /* Sender */ + outapp, /* packet */ + false, /* Skip Sender */ + range, /* distance packet travels at the speed of sound */ + 0, /* don't skip anyone on spell */ + true, /* Packet ACK */ + filter /* eqFilterType filter */ + ); + } + else { //I dont think any filters apply to damage affecting us - CastToClient()->QueuePacket(outapp); + if (IsClient()) { + CastToClient()->QueuePacket(outapp); + } + + // Otherwise, send normal spell or melee message to observers. + entity_list.QueueCloseClients( + this, /* Sender */ + outapp, /* packet */ + true, /* Skip Sender */ + range, /* distance packet travels at the speed of sound */ + (IsValidSpell(spell_id) && skill_used != EQ::skills::SkillTigerClaw) ? 0 : skip, + true, /* Packet ACK */ + filter /* eqFilterType filter */ + ); } } @@ -4043,19 +4166,29 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons else { //else, it is a buff tic... // So we can see our dot dmg like live shows it. - if (spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) { + if (spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && !attacker->IsCorpse()) { //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it - attacker->FilteredMessageString(attacker, Chat::DotDamage, FilterDOT, - YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); + if (attacker->IsClient()) { + attacker->FilteredMessageString(attacker, Chat::DotDamage, + FilterDOT, YOUR_HIT_DOT, GetCleanName(), itoa(damage), + spells[spell_id].name); + } + + if (IsClient()) { + FilteredMessageString(this, Chat::DotDamage, FilterDOT, + YOU_TAKE_DOT, itoa(damage), attacker->GetCleanName(), + spells[spell_id].name); + } /* older clients don't have the below String ID, but it will be filtered */ entity_list.FilteredMessageCloseString( - attacker, /* Sender */ + this, /* Sender */ true, /* Skip Sender */ RuleI(Range, SpellMessages), Chat::DotDamage, /* Type: 325 */ FilterDOT, /* FilterType: 19 */ OTHER_HIT_DOT, /* MessageFormat: %1 has taken %2 damage from %3 by %4. */ + attacker, /* sent above */ GetCleanName(), /* Message1 */ itoa(damage), /* Message2 */ attacker->GetCleanName(), /* Message3 */ @@ -4101,7 +4234,7 @@ void Mob::HealDamage(uint64 amount, Mob *caster, uint16 spell_id) // message to target if (IsClient() && caster != this) { if (CastToClient()->ClientVersionBit() & EQ::versions::maskSoFAndLater) - FilteredMessageString(this, Chat::NonMelee, FilterHealOverTime, + FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime, HOT_HEALED_OTHER, caster->GetCleanName(), itoa(acthealed), spells[spell_id].name); else @@ -4117,7 +4250,7 @@ void Mob::HealDamage(uint64 amount, Mob *caster, uint16 spell_id) YOU_HEAL, GetCleanName(), itoa(acthealed)); } } - else { + else if (CastToClient()->GetFilter(FilterHealOverTime) != (FilterShowSelfOnly || FilterHide)) { Message(Chat::NonMelee, "You have been healed for %d points of damage.", acthealed); } } @@ -4225,7 +4358,7 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { } //AA Procs - if (IsClient()){ + if (IsClient() || IsBot()){ for (int i = 0; i < MAX_AA_PROCS; i += 4) { int32 aa_rank_id = aabonuses.DefensiveProc[i + +SBIndex::COMBAT_PROC_ORIGIN_ID]; int32 aa_spell_id = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID]; @@ -4483,7 +4616,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, } //AA Melee and Ranged Procs - if (IsClient()) { + if (IsClient() || IsBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { int32 aa_rank_id = 0; @@ -4599,6 +4732,7 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit) Chat::MeleeCrit, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */ + 0, GetCleanName(), /* Message1 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); @@ -4628,12 +4762,10 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * return; } -#ifdef BOTS if (IsPet() && GetOwner() && GetOwner()->IsBot()) { TryPetCriticalHit(defender, hit); return; } -#endif // BOTS if (IsNPC() && !RuleB(Combat, NPCCanCrit)) return; @@ -4659,6 +4791,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * Chat::MeleeCrit, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ FEMALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses her target!(%2) */ + 0, GetCleanName(), /* Message1 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); @@ -4672,6 +4805,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * Chat::MeleeCrit, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ MALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses his target!(%2) */ + 0, GetCleanName(), /* Message1 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); @@ -4754,6 +4888,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * Chat::MeleeCrit, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */ + 0, GetCleanName(), /* Message1 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); @@ -4782,6 +4917,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * Chat::MeleeCrit, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */ + 0, GetCleanName(), /* Message1 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); @@ -4804,6 +4940,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * Chat::MeleeCrit, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */ + 0, GetCleanName(), /* Message1 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); @@ -4853,6 +4990,7 @@ bool Mob::TryFinishingBlow(Mob *defender, int64 &damage) Chat::MeleeCrit, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ FINISHING_BLOW, /* MessageFormat: %1 scores a Finishing Blow!!) */ + 0, GetCleanName() /* Message1 */ ); @@ -5098,12 +5236,10 @@ void Mob::ApplyDamageTable(DamageHitInfo &hit) #endif // someone may want to add this to custom servers, can remove this if that's the case - if (!IsClient() -#ifdef BOTS - && !IsBot() -#endif - ) + if (!IsClient()&& !IsBot()) { return; + } + // this was parsed, but we do see the min of 10 and the normal minus factor is 105, so makes sense if (hit.offense < 115) return; @@ -5638,17 +5774,17 @@ void Mob::DoShieldDamageOnShielder(Mob *shield_target, int64 hit_damage_done, EQ shielder->shield_timer.Disable(); shield_target->SetShielderID(0); shield_target->SetShieldTargetMitigation(0); - return; //Too far away, no message is given thoughh. + return; //Too far away, no message is given though. } - int mitigation = shielder->GetShielderMitigation(); //Default shielder mitigates 25 pct of damage taken, this can be increased up to max 50 by equiping a shield item + int mitigation = shielder->GetShielderMitigation(); //Default shielder mitigates 25 pct of damage taken, this can be increased up to max 50 by equipping a shield item if (shielder->IsClient() && shielder->HasShieldEquiped()) { EQ::ItemInstance* inst = shielder->CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary); if (inst) { const EQ::ItemData* shield = inst->GetItem(); if (shield && shield->ItemType == EQ::item::ItemTypeShield) { mitigation += shield->AC * 50 / 100; //1% increase per 2 AC - std::min(50, mitigation);//50 pct max mitigation bonus from /shield + mitigation = std::min(50, mitigation);//50 pct max mitigation bonus from /shield } } } diff --git a/zone/aura.cpp b/zone/aura.cpp index 40cf4a481..7f41d1b3a 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -1,4 +1,4 @@ -#include "../common/string_util.h" +#include "../common/strings.h" #include "aura.h" #include "client.h" @@ -77,7 +77,10 @@ void Aura::ProcessOnAllFriendlies(Mob *owner) for (auto &e : mob_list) { auto mob = e.second; - if (mob->IsClient() || mob->IsPetOwnerClient() || mob->IsMerc()) { + if (!mob) { + continue; + } + if (mob->IsClient() || mob->IsPetOwnerClient() || mob->IsMerc() || mob->IsBot()) { auto it = casted_on.find(mob->GetID()); if (it != casted_on.end()) { // we are already on the list, let's check for removal @@ -187,6 +190,9 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) for (auto &e : mob_list) { auto mob = e.second; + if (!mob) { + continue; + } // step 1: check if we're already managing this NPC's buff auto it = casted_on.find(mob->GetID()); if (it != casted_on.end()) { @@ -414,6 +420,9 @@ void Aura::ProcessOnGroupMembersPets(Mob *owner) for (auto &e : mob_list) { auto mob = e.second; + if (!mob) { + continue; + } // step 1: check if we're already managing this NPC's buff auto it = casted_on.find(mob->GetID()); if (it != casted_on.end()) { @@ -572,6 +581,10 @@ void Aura::ProcessTotem(Mob *owner) for (auto &e : mob_list) { auto mob = e.second; + if (!mob) { + continue; + } + if (mob == this) { continue; } @@ -624,11 +637,15 @@ void Aura::ProcessEnterTrap(Mob *owner) for (auto &e : mob_list) { auto mob = e.second; + if (!mob) { + continue; + } + if (mob == this) { continue; } // might need more checks ... - if (owner->IsAttackAllowed(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { + if (mob != owner && owner->IsAttackAllowed(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { SpellFinished(spell_id, mob); owner->RemoveAura(GetID(), false); // if we're a buff (ex. NEC) we don't want to strip :P break; @@ -642,11 +659,15 @@ void Aura::ProcessExitTrap(Mob *owner) for (auto &e : mob_list) { auto mob = e.second; + if (!mob) { + continue; + } + if (mob == this) { continue; } // might need more checks ... - if (owner->IsAttackAllowed(mob)) { + if (mob != owner && owner->IsAttackAllowed(mob)) { bool in_range = DistanceSquared(GetPosition(), mob->GetPosition()) <= distance; auto it = casted_on.find(mob->GetID()); if (it != casted_on.end()) { @@ -669,6 +690,10 @@ void Aura::ProcessSpawns() { const auto &clients = entity_list.GetCloseMobList(this, distance); for (auto &e : clients) { + if (!e.second) { + continue; + } + if (!e.second->IsClient()) { continue; } @@ -939,7 +964,7 @@ bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord &record) void Mob::AddAura(Aura *aura, AuraRecord &record) { LogAura( - "[AddAura] aura owner [{}] spawn_id [{}] aura_name [{}]", + "aura owner [{}] spawn_id [{}] aura_name [{}]", GetCleanName(), aura->GetID(), aura->GetCleanName() @@ -974,7 +999,7 @@ void Mob::AddAura(Aura *aura, AuraRecord &record) void Mob::AddTrap(Aura *aura, AuraRecord &record) { LogAura( - "[AddTrap] aura owner [{}] spawn_id [{}] aura_name [{}]", + "aura owner [{}] spawn_id [{}] aura_name [{}]", GetCleanName(), aura->GetID(), aura->GetCleanName() @@ -1023,7 +1048,7 @@ void Mob::RemoveAllAuras() for (auto &e : aura_mgr.auras) { if (e.aura) { LogAura( - "[RemoveAllAuras] aura owner [{}] spawn_id [{}] aura_name [{}]", + "aura owner [{}] spawn_id [{}] aura_name [{}]", GetCleanName(), e.spawn_id, e.name @@ -1040,7 +1065,7 @@ void Mob::RemoveAllAuras() for (auto &e : trap_mgr.auras) { if (e.aura) { LogAura( - "[RemoveAllAuras] trap owner [{}] spawn_id [{}] aura_name [{}]", + "trap owner [{}] spawn_id [{}] aura_name [{}]", GetCleanName(), e.spawn_id, e.name @@ -1060,7 +1085,7 @@ void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired) auto &aura = aura_mgr.auras[i]; if (aura.spawn_id == spawn_id) { LogAura( - "[RemoveAura] mob [{}] spawn_id [{}] skip_strip [{}] expired [{}]", + "mob [{}] spawn_id [{}] skip_strip [{}] expired [{}]", GetCleanName(), spawn_id, skip_strip ? "true" : "false", diff --git a/zone/basic_functions.h b/zone/basic_functions.h deleted file mode 100644 index 3fa8ba523..000000000 --- a/zone/basic_functions.h +++ /dev/null @@ -1,178 +0,0 @@ -const char *notin = "~.? ,)=!&|<>\""; - -const char * charIn = "`~1234567890-=!@#$%^&*()_+qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP|ASDFGHJKL:ZXCVBNM<>?\"{}"; -const char * charIn2 = "`~1234567890-=!@#$%^&*()_+qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP|ASDFGHJKL:ZXCVBNM<>?\" "; - -char com_list[512]; - -/*char * gettok(const char * string, int chara, int pos) { - static char * pch; - static char temp[100]; - static char ty[100]; - memset(temp, 0, sizeof(temp)); - memset(ty, 0, sizeof(ty)); - ty[0] = chara; - strn0cpy(temp, string, sizeof(temp)); - pch = strtok(temp,ty); - for (int i=0; i < pos; i++) { - if (pos == i) break; - pch = strtok(nullptr,ty); - } - return pch; -}*/ - - -int calc(char * stuff) { - int result = 0; - int i = 0; - int a = 0; - static char temp[100]; - int op = 0; - memset(temp,0x0,100); - //char heh[100]; - while(*stuff) - { - a++; - - if (*stuff >= '0' && *stuff <= '9') { - if (op) { - switch ( op ) { - case 0: - break; - case '+': - result += atoi(stuff); - memset(temp,0x0,100); - i = 0; - break; - case '-': - result -= atoi(stuff); - memset(temp,0x0,100); - i = 0; - break; - case '*': - result *= atoi(stuff); - memset(temp,0x0,100); - i = 0; - break; - case '/': - result /= atoi(stuff); - memset(temp,0x0,100); - i = 0; - break; - } - } - temp[i] = *stuff; - } - else if (*stuff == '+' || *stuff == '-' || *stuff == '/' || *stuff == '*') { - op = *stuff; - if (!result) result = atoi(temp); - memset(temp,0x0,100); - i=0; - } - i++; - stuff++; - } - return result; -} - -char * postring (char * string, int pos) { - static char temp[1024]; - memset(temp, 0, sizeof(temp)); - int p=0; - int tmpStringLen = strlen(string); - for (int i=pos; i < tmpStringLen; i++) { - temp[p] = string[i]; - p++; - } - return temp; -} - -int g_id ( char * string ) -{ - char temp[100]; - int i=0; - while (*string) - { - if (*string >= '0' && *string <= '9') temp[i++] = *string++; - else string++; - } - return atoi(temp); -} - -int GetArgs(char * string) -{ -#if 1 - char temp[255]; - char c_name[255]; - int params = 0; - //char *buffer = new char[512]; // this is never deleted, causes zone to crash - char *buffer = com_list; - memset(temp,0x0,255); - //memset(buffer,0x0,512); - //#ifdef WIN32 - //strcpy(buffer,com_list); - //#else - //strncpy(buffer,com_list,sizeof(buffer)-1); - //#endif - int i=0; - while (*buffer) - { - if (*buffer != '|' && *buffer != ' ') temp[i++] = *buffer++; - else buffer++; - if (*buffer == '|') { - params = atoi(temp); - if (!strcmp(c_name,string)) { - return params; - } - memset(temp,0x0,255); - i=0; - } - if (*buffer == ' ') { - memset(c_name,0x0,255); - strcpy(c_name,temp); - memset(temp,0x0,255); - i=0; - } - } - return 0; -#else - if (strstr(string,"if")) { return 0; } - if (strstr(string,"sfollow")) { return 0; } - if (strstr(string,"save")) { return 0; } - if (strstr(string,"while")) { return 0; } - if (strstr(string,"break")) { return 1; } - if (strstr(string,"follow")) { return 1; } - if (strstr(string,"setallskill")) { return 1; } - if (strstr(string,"me")) { return 1; } - if (strstr(string,"flagcheck")) { return 1; } - if (strstr(string,"echo")) { return 1; } - if (strstr(string,"summonitem")) { return 1; } - if (strstr(string,"say")) { return 1; } - if (strstr(string,"emote")) { return 1; } - if (strstr(string,"shout")) { return 1; } - if (strstr(string,"depop")) { return 1; } - if (strstr(string,"cumflag")) { return 1; } - if (strstr(string,"exp")) { return 1; } - if (strstr(string,"level")) { return 1; } - if (strstr(string,"safemove")) { return 1; } - if (strstr(string,"rain")) { return 1; } - if (strstr(string,"snow")) { return 1; } - if (strstr(string,"pvp")) { return 1; } - if (strstr(string,"doanim")) { return 1; } - if (strstr(string,"dbspawnadd")) { return 2; } - if (strstr(string,"castspell")) { return 2; } - if (strstr(string,"flagcheck")) { return 2; } - if (strstr(string,"addskill")) { return 2; } - if (strstr(string,"write")) { return 2; } - if (strstr(string,"settarget")) { return 2; } - if (strstr(string,"givecash")) { return 4; } - if (strstr(string,"movepc")) { return 4; } - if (strstr(string,"spawn")) { return 6; } - return 0; -#endif // 0 -} - -Client* gClient = 0; - -uint32 Line_Number = 0; - diff --git a/zone/beacon.cpp b/zone/beacon.cpp index c9eb703fd..4ccaa7d36 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -39,27 +39,71 @@ class Zone; #include "entity.h" #include "mob.h" - -#ifdef BOTS -#include "bot.h" -#endif - - -#include "../common/spdat.h" - extern EntityList entity_list; extern Zone* zone; // if lifetime is 0 this is a permanent beacon.. not sure if that'll be // useful for anything -Beacon::Beacon(const glm::vec4 &in_pos, int lifetime) -:Mob -( - nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, in_pos, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQ::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false +Beacon::Beacon(const glm::vec4 &in_pos, int lifetime) : Mob( + nullptr, // in_name + nullptr, // in_lastname + 0, // in_cur_hp + 0, // in_max_hp + MALE, // in_gender + INVISIBLE_MAN, // in_race + 0, // in_class + BT_NoTarget, // in_bodytype + 0, // in_deity + 0, // in_level + 0, // in_npctype_id + 0.0f, // in_size + 0.0f, // in_runspeed + in_pos, // position + 0, // in_light + 0, // in_texture + 0, // in_helmtexture + 0, // in_ac + 0, // in_atk + 0, // in_str + 0, // in_sta + 0, // in_dex + 0, // in_agi + 0, // in_int + 0, // in_wis + 0, // in_cha + 0, // in_haircolor + 0, // in_beardcolor + 0, // in_eyecolor1 + 0, // in_eyecolor2 + 0, // in_hairstyle + 0, // in_luclinface + 0, // in_beard + 0, // in_drakkin_heritage + 0, // in_drakkin_tattoo + 0, // in_drakkin_details + EQ::TintProfile(), // in_armor_tint + 0, // in_aa_title + 0, // in_see_invis + 0, // in_see_invis_undead + 0, // in_see_hide + 0, // in_see_improved_hide + 0, // in_hp_regen + 0, // in_mana_regen + 0, // in_qglobal + 0, // in_maxlevel + 0, // in_scalerate + 0, // in_armtexture + 0, // in_bracertexture + 0, // in_handtexture + 0, // in_legtexture + 0, // in_feettexture + 0, // in_usemodel + false, // in_always_aggros_foes + 0, //in_heroic_strikethrough + false // in_keeps_sold_items ), - remove_timer(lifetime), - spell_timer(0) + remove_timer(lifetime), + spell_timer(0) { remove_timer.Disable(); spell_timer.Disable(); diff --git a/zone/beacon.h b/zone/beacon.h index 4c3a10081..2954edc90 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -36,12 +36,12 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) { return true; } virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; } - virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } virtual Group* GetGroup() { return 0; } + bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + ExtraAttackOptions *opts = nullptr) override { return false; } bool IsBeacon() const { return true; } bool Process(); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 4d212a4f2..a6664f55b 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -26,9 +26,7 @@ #include "entity.h" #include "mob.h" -#ifdef BOTS #include "bot.h" -#endif #include "quest_parser_collection.h" @@ -353,7 +351,7 @@ void Client::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses *newbon, b } // FatherNitwit: New style haste, shields, and regens - if (newbon->haste < (int32)item->Haste) { + if (newbon->haste < item->Haste) { newbon->haste = item->Haste; } if (item->Regen > 0) @@ -1932,7 +1930,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne effect_value = se_base; limit_value = se_limit; max_value = se_max; - i = EFFECT_COUNT; //End the loop + i = (EFFECT_COUNT - 1); // AISpellEffects do a single pass } switch (spell_effect_id) diff --git a/zone/bot.cpp b/zone/bot.cpp index 8e656617a..e7684358c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -16,15 +16,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef BOTS - #include "bot.h" #include "object.h" #include "doors.h" #include "quest_parser_collection.h" #include "lua_parser.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/say_link.h" +#include "../common/repositories/bot_spell_settings_repository.h" +#include "../common/data_verification.h" extern volatile bool is_zone_loaded; @@ -68,10 +68,12 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; + m_enforce_spell_settings = 0; + m_bot_archery_setting = 0; + m_expansion_bitmask = -1; SetBotID(0); SetBotSpellID(0); SetSpawnStatus(false); - SetBotArcher(false); SetBotCharmer(false); SetPetChooser(false); SetRangerAutoWeaponSelect(false); @@ -166,16 +168,30 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetBotID(botID); SetBotSpellID(botSpellsID); SetSpawnStatus(false); - SetBotArcher(false); SetBotCharmer(false); SetPetChooser(false); SetRangerAutoWeaponSelect(false); bool stance_flag = false; - if (!database.botdb.LoadStance(this, stance_flag) && bot_owner) - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadStance(), GetCleanName()); - if (!stance_flag && bot_owner) - bot_owner->Message(Chat::Red, "Could not locate stance for '%s'", GetCleanName()); + if (!database.botdb.LoadStance(this, stance_flag) && bot_owner) { + bot_owner->Message( + Chat::White, + fmt::format( + "Failed to load stance for '{}'.", + GetCleanName() + ).c_str() + ); + } + + if (!stance_flag && bot_owner) { + bot_owner->Message( + Chat::White, + fmt::format( + "Could not locate stance for '{}'.", + GetCleanName() + ).c_str() + ); + } SetTaunting((GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) && (GetBotStance() == EQ::constants::stanceAggressive)); SetPauseAI(false); @@ -205,17 +221,14 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); if (!database.botdb.LoadInspectMessage(GetBotID(), _botInspectMessage) && bot_owner) - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadInspectMessage(), GetCleanName()); - - if (!database.botdb.LoadGuildMembership(GetBotID(), _guildId, _guildRank, _guildName) && bot_owner) - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadGuildMembership(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for '%s'", BotDatabase::fail::LoadInspectMessage(), GetCleanName()); std::string error_message; EquipBot(&error_message); if(!error_message.empty()) { if(bot_owner) - bot_owner->Message(Chat::Red, error_message.c_str()); + bot_owner->Message(Chat::White, error_message.c_str()); error_message.clear(); } @@ -234,7 +247,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to GenerateBaseStats(); if (!database.botdb.LoadTimers(this) && bot_owner) - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadTimers(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for '%s'", BotDatabase::fail::LoadTimers(), GetCleanName()); LoadAAs(); @@ -245,15 +258,17 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to //reapply some buffs uint32 buff_count = GetMaxTotalSlots(); for (uint32 j1 = 0; j1 < buff_count; j1++) { - if (!IsValidSpell(buffs[j1].spellid)) + if (!IsValidSpell(buffs[j1].spellid)) { continue; + } const SPDat_Spell_Struct& spell = spells[buffs[j1].spellid]; int NimbusEffect = GetNimbusEffect(buffs[j1].spellid); if (NimbusEffect) { - if (!IsNimbusEffectActive(NimbusEffect)) + if (!IsNimbusEffectActive(NimbusEffect)) { SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true); + } } for (int x1 = 0; x1 < EFFECT_COUNT; x1++) { @@ -269,8 +284,9 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to } else if (spell.base_value[x1] == -2) // WTF IS THIS { - if (GetRace() == 128 || GetRace() == 130 || GetRace() <= 12) + if (GetRace() == IKSAR || GetRace() == VAHSHIR || GetRace() <= GNOME) { SendIllusionPacket(GetRace(), GetGender(), spell.limit_value[x1], spell.max_value[x1]); + } } else if (spell.max_value[x1] > 0) { @@ -345,7 +361,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to //{ SendAppearancePacket(AT_Levitate, 0); BuffFadeByEffect(SE_Levitate); - //Message(Chat::Red, "You can't levitate in this zone."); + //Message(Chat::White, "You can't levitate in this zone."); //} } else { @@ -383,11 +399,9 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to } } } - - } else { - bot_owner->Message(Chat::Red, "&s for '%s'", BotDatabase::fail::LoadBuffs(), GetCleanName()); + bot_owner->Message(Chat::White, "&s for '%s'", BotDatabase::fail::LoadBuffs(), GetCleanName()); } CalcBotStats(false); @@ -398,7 +412,10 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to current_hp = max_hp; if(current_hp <= 0) { - BuffFadeNonPersistDeath(); + if (RuleB(Spells, BuffsFadeOnDeath)) { + BuffFadeNonPersistDeath(); + } + if (RuleB(Bots, ResurrectionSickness)) { int resurrection_sickness_spell_id = ( RuleB(Bots, OldRaceRezEffects) && @@ -570,253 +587,284 @@ bool Bot::IsStanding() { return result; } -NPCType *Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack) { - auto bot_npc_type = new NPCType{ 0 }; - int copy_length = 0; +NPCType *Bot::FillNPCTypeStruct( + uint32 botSpellsID, + std::string botName, + std::string botLastName, + uint8 botLevel, + uint16 botRace, + uint8 botClass, + uint8 gender, + float size, + uint32 face, + uint32 hairStyle, + uint32 hairColor, + uint32 eyeColor, + uint32 eyeColor2, + uint32 beard, + uint32 beardColor, + uint32 drakkinHeritage, + uint32 drakkinTattoo, + uint32 drakkinDetails, + int32 hp, + int32 mana, + int32 mr, + int32 cr, + int32 dr, + int32 fr, + int32 pr, + int32 corrup, + int32 ac, + uint32 str, + uint32 sta, + uint32 dex, + uint32 agi, + uint32 _int, + uint32 wis, + uint32 cha, + uint32 attack +) { + auto n = new NPCType{ 0 }; - copy_length = botName.copy(bot_npc_type->name, 63); - bot_npc_type->name[copy_length] = '\0'; - copy_length = 0; + strn0cpy(n->name, botName.c_str(), sizeof(n->name)); + strn0cpy(n->lastname, botLastName.c_str(), sizeof(n->lastname)); - copy_length = botLastName.copy(bot_npc_type->lastname, 69); - bot_npc_type->lastname[copy_length] = '\0'; - copy_length = 0; + n->current_hp = hp; + n->max_hp = hp; + n->size = size; + n->runspeed = 0.7f; + n->gender = gender; + n->race = botRace; + n->class_ = botClass; + n->bodytype = 1; + n->deity = EQ::deity::DeityAgnostic; + n->level = botLevel; + //n->npc_id = 0; + //n->texture = 0; + //n->helmtexture = 0; + //n->herosforgemodel = 0; + //n->loottable_id = 0; + n->npc_spells_id = botSpellsID; + //n->npc_spells_effects_id = 0; + //n->npc_faction_id = 0; + //n->merchanttype = 0; + //n->alt_currency_type = 0; + //n->adventure_template = 0; + //n->trap_template = 0; + //n->light = 0; + n->AC = ac; + n->Mana = mana; + n->ATK = attack; + n->STR = str; + n->STA = sta; + n->DEX = dex; + n->AGI = agi; + n->INT = _int; + n->WIS = wis; + n->CHA = cha; + n->MR = mr; + n->FR = fr; + n->CR = cr; + n->PR = pr; + n->DR = dr; + n->Corrup = corrup; + //n->PhR = 0; + n->haircolor = hairColor; + n->beardcolor = beardColor; + n->eyecolor1 = eyeColor; + n->eyecolor2 = eyeColor2; + n->hairstyle = hairStyle; + n->luclinface = face; + n->beard = beard; + n->drakkin_heritage = drakkinHeritage; + n->drakkin_tattoo = drakkinTattoo; + n->drakkin_details = drakkinDetails; + //n->armor_tint = { 0 }; + //n->min_dmg = 0; + //n->max_dmg = 0; + //n->charm_ac = 0; + //n->charm_min_dmg = 0; + //n->charm_max_dmg = 0; + //n->charm_attack_delay = 0; + //n->charm_accuracy_rating = 0; + //n->charm_avoidance_rating = 0; + //n->charm_atk = 0; + //n->attack_count = 0; + //*n->special_abilities = { 0 }; + //n->d_melee_texture1 = 0; + //n->d_melee_texture2 = 0; + //*n->ammo_idfile = { 0 }; + //n->prim_melee_type = 0; + //n->sec_melee_type = 0; + //n->ranged_type = 0; + n->hp_regen = 1; + n->mana_regen = 1; + //n->aggroradius = 0; + //n->assistradius = 0; + //n->see_invis = 0; + //n->see_invis_undead = false; + //n->see_hide = false; + //n->see_improved_hide = false; + //n->qglobal = false; + //n->npc_aggro = false; + //n->spawn_limit = 0; + //n->mount_color = 0; + //n->attack_speed = 0.0f; + //n->attack_delay = 0; + //n->accuracy_rating = 0; + //n->avoidance_rating = 0; + //n->findable = false; + n->trackable = true; + //n->slow_mitigation = 0; + n->maxlevel = botLevel; + //n->scalerate = 0; + //n->private_corpse = false; + //n->unique_spawn_by_name = false; + //n->underwater = false; + //n->emoteid = 0; + //n->spellscale = 0.0f; + //n->healscale = 0.0f; + //n->no_target_hotkey = false; + //n->raid_target = false; + //n->armtexture = 0; + //n->bracertexture = 0; + //n->handtexture = 0; + //n->legtexture = 0; + //n->feettexture = 0; + //n->ignore_despawn = false; + n->show_name = true; + //n->untargetable = false; + n->skip_global_loot = true; + //n->rare_spawn = false; + n->stuck_behavior = Ground; + n->skip_auto_scale = true; - bot_npc_type->current_hp = hp; - bot_npc_type->max_hp = hp; - bot_npc_type->size = size; - bot_npc_type->runspeed = 0.7f; - bot_npc_type->gender = gender; - bot_npc_type->race = botRace; - bot_npc_type->class_ = botClass; - bot_npc_type->bodytype = 1; - bot_npc_type->deity = EQ::deity::DeityAgnostic; - bot_npc_type->level = botLevel; - //bot_npc_type->npc_id = 0; - //bot_npc_type->texture = 0; - //bot_npc_type->helmtexture = 0; - //bot_npc_type->herosforgemodel = 0; - //bot_npc_type->loottable_id = 0; - bot_npc_type->npc_spells_id = botSpellsID; - //bot_npc_type->npc_spells_effects_id = 0; - //bot_npc_type->npc_faction_id = 0; - //bot_npc_type->merchanttype = 0; - //bot_npc_type->alt_currency_type = 0; - //bot_npc_type->adventure_template = 0; - //bot_npc_type->trap_template = 0; - //bot_npc_type->light = 0; - bot_npc_type->AC = ac; - bot_npc_type->Mana = mana; - bot_npc_type->ATK = attack; - bot_npc_type->STR = str; - bot_npc_type->STA = sta; - bot_npc_type->DEX = dex; - bot_npc_type->AGI = agi; - bot_npc_type->INT = _int; - bot_npc_type->WIS = wis; - bot_npc_type->CHA = cha; - bot_npc_type->MR = mr; - bot_npc_type->FR = fr; - bot_npc_type->CR = cr; - bot_npc_type->PR = pr; - bot_npc_type->DR = dr; - bot_npc_type->Corrup = corrup; - //bot_npc_type->PhR = 0; - bot_npc_type->haircolor = hairColor; - bot_npc_type->beardcolor = beardColor; - bot_npc_type->eyecolor1 = eyeColor; - bot_npc_type->eyecolor2 = eyeColor2; - bot_npc_type->hairstyle = hairStyle; - bot_npc_type->luclinface = face; - bot_npc_type->beard = beard; - bot_npc_type->drakkin_heritage = drakkinHeritage; - bot_npc_type->drakkin_tattoo = drakkinTattoo; - bot_npc_type->drakkin_details = drakkinDetails; - //bot_npc_type->armor_tint = { 0 }; - //bot_npc_type->min_dmg = 0; - //bot_npc_type->max_dmg = 0; - //bot_npc_type->charm_ac = 0; - //bot_npc_type->charm_min_dmg = 0; - //bot_npc_type->charm_max_dmg = 0; - //bot_npc_type->charm_attack_delay = 0; - //bot_npc_type->charm_accuracy_rating = 0; - //bot_npc_type->charm_avoidance_rating = 0; - //bot_npc_type->charm_atk = 0; - //bot_npc_type->attack_count = 0; - //*bot_npc_type->special_abilities = { 0 }; - //bot_npc_type->d_melee_texture1 = 0; - //bot_npc_type->d_melee_texture2 = 0; - //*bot_npc_type->ammo_idfile = { 0 }; - //bot_npc_type->prim_melee_type = 0; - //bot_npc_type->sec_melee_type = 0; - //bot_npc_type->ranged_type = 0; - bot_npc_type->hp_regen = 1; - bot_npc_type->mana_regen = 1; - //bot_npc_type->aggroradius = 0; - //bot_npc_type->assistradius = 0; - //bot_npc_type->see_invis = 0; - //bot_npc_type->see_invis_undead = false; - //bot_npc_type->see_hide = false; - //bot_npc_type->see_improved_hide = false; - //bot_npc_type->qglobal = false; - //bot_npc_type->npc_aggro = false; - //bot_npc_type->spawn_limit = 0; - //bot_npc_type->mount_color = 0; - //bot_npc_type->attack_speed = 0.0f; - //bot_npc_type->attack_delay = 0; - //bot_npc_type->accuracy_rating = 0; - //bot_npc_type->avoidance_rating = 0; - //bot_npc_type->findable = false; - bot_npc_type->trackable = true; - //bot_npc_type->slow_mitigation = 0; - bot_npc_type->maxlevel = botLevel; - //bot_npc_type->scalerate = 0; - //bot_npc_type->private_corpse = false; - //bot_npc_type->unique_spawn_by_name = false; - //bot_npc_type->underwater = false; - //bot_npc_type->emoteid = 0; - //bot_npc_type->spellscale = 0.0f; - //bot_npc_type->healscale = 0.0f; - //bot_npc_type->no_target_hotkey = false; - //bot_npc_type->raid_target = false; - //bot_npc_type->armtexture = 0; - //bot_npc_type->bracertexture = 0; - //bot_npc_type->handtexture = 0; - //bot_npc_type->legtexture = 0; - //bot_npc_type->feettexture = 0; - //bot_npc_type->ignore_despawn = false; - bot_npc_type->show_name = true; - //bot_npc_type->untargetable = false; - bot_npc_type->skip_global_loot = true; - //bot_npc_type->rare_spawn = false; - bot_npc_type->stuck_behavior = Ground; - bot_npc_type->skip_auto_scale = true; - - return bot_npc_type; + return n; } -NPCType *Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender) { - auto bot_npc_type = new NPCType{ 0 }; - int copy_length = 0; +NPCType *Bot::CreateDefaultNPCTypeStructForBot( + std::string botName, + std::string botLastName, + uint8 botLevel, + uint16 botRace, + uint8 botClass, + uint8 gender +) { + auto n = new NPCType{ 0 }; - copy_length = botName.copy(bot_npc_type->name, 63); - bot_npc_type->name[copy_length] = '\0'; - copy_length = 0; + strn0cpy(n->name, botName.c_str(), sizeof(n->name)); + strn0cpy(n->lastname, botLastName.c_str(), sizeof(n->lastname)); - copy_length = botLastName.copy(bot_npc_type->lastname, 69); - bot_npc_type->lastname[copy_length] = '\0'; - copy_length = 0; + //n->current_hp = 0; + //n->max_hp = 0; + n->size = 6.0f; + n->runspeed = 0.7f; + n->gender = gender; + n->race = botRace; + n->class_ = botClass; + n->bodytype = 1; + n->deity = EQ::deity::DeityAgnostic; + n->level = botLevel; + //n->npc_id = 0; + //n->texture = 0; + //n->helmtexture = 0; + //n->herosforgemodel = 0; + //n->loottable_id = 0; + //n->npc_spells_id = 0; + //n->npc_spells_effects_id = 0; + //n->npc_faction_id = 0; + //n->merchanttype = 0; + //n->alt_currency_type = 0; + //n->adventure_template = 0; + //n->trap_template = 0; + //n->light = 0; + n->AC = 12; + //n->Mana = 0; + n->ATK = 75; + n->STR = 75; + n->STA = 75; + n->DEX = 75; + n->AGI = 75; + n->INT = 75; + n->WIS = 75; + n->CHA = 75; + n->MR = 25; + n->FR = 25; + n->CR = 25; + n->PR = 15; + n->DR = 15; + n->Corrup = 15; + //n->PhR = 0; + //n->haircolor = 0; + //n->beardcolor = 0; + //n->eyecolor1 = 0; + //n->eyecolor2 = 0; + //n->hairstyle = 0; + //n->luclinface = 0; + //n->beard = 0; + //n->drakkin_heritage = 0; + //n->drakkin_tattoo = 0; + //n->drakkin_details = 0; + //n->armor_tint = { 0 }; + //n->min_dmg = 0; + //n->max_dmg = 0; + //n->charm_ac = 0; + //n->charm_min_dmg = 0; + //n->charm_max_dmg = 0; + //n->charm_attack_delay = 0; + //n->charm_accuracy_rating = 0; + //n->charm_avoidance_rating = 0; + //n->charm_atk = 0; + //n->attack_count = 0; + //*n->special_abilities = { 0 }; + //n->d_melee_texture1 = 0; + //n->d_melee_texture2 = 0; + //*n->ammo_idfile = { 0 }; + //n->prim_melee_type = 0; + //n->sec_melee_type = 0; + //n->ranged_type = 0; + n->hp_regen = 1; + n->mana_regen = 1; + //n->aggroradius = 0; + //n->assistradius = 0; + //n->see_invis = 0; + //n->see_invis_undead = false; + //n->see_hide = false; + //n->see_improved_hide = false; + //n->qglobal = false; + //n->npc_aggro = false; + //n->spawn_limit = 0; + //n->mount_color = 0; + //n->attack_speed = 0.0f; + //n->attack_delay = 0; + //n->accuracy_rating = 0; + //n->avoidance_rating = 0; + //n->findable = false; + n->trackable = true; + //n->slow_mitigation = 0; + n->maxlevel = botLevel; + //n->scalerate = 0; + //n->private_corpse = false; + //n->unique_spawn_by_name = false; + //n->underwater = false; + //n->emoteid = 0; + //n->spellscale = 0.0f; + //n->healscale = 0.0f; + //n->no_target_hotkey = false; + //n->raid_target = false; + //n->armtexture = 0; + //n->bracertexture = 0; + //n->handtexture = 0; + //n->legtexture = 0; + //n->feettexture = 0; + //n->ignore_despawn = false; + n->show_name = true; + //n->untargetable = false; + n->skip_global_loot = true; + //n->rare_spawn = false; + n->stuck_behavior = Ground; - //bot_npc_type->current_hp = 0; - //bot_npc_type->max_hp = 0; - bot_npc_type->size = 6.0f; - bot_npc_type->runspeed = 0.7f; - bot_npc_type->gender = gender; - bot_npc_type->race = botRace; - bot_npc_type->class_ = botClass; - bot_npc_type->bodytype = 1; - bot_npc_type->deity = EQ::deity::DeityAgnostic; - bot_npc_type->level = botLevel; - //bot_npc_type->npc_id = 0; - //bot_npc_type->texture = 0; - //bot_npc_type->helmtexture = 0; - //bot_npc_type->herosforgemodel = 0; - //bot_npc_type->loottable_id = 0; - //bot_npc_type->npc_spells_id = 0; - //bot_npc_type->npc_spells_effects_id = 0; - //bot_npc_type->npc_faction_id = 0; - //bot_npc_type->merchanttype = 0; - //bot_npc_type->alt_currency_type = 0; - //bot_npc_type->adventure_template = 0; - //bot_npc_type->trap_template = 0; - //bot_npc_type->light = 0; - bot_npc_type->AC = 12; - //bot_npc_type->Mana = 0; - bot_npc_type->ATK = 75; - bot_npc_type->STR = 75; - bot_npc_type->STA = 75; - bot_npc_type->DEX = 75; - bot_npc_type->AGI = 75; - bot_npc_type->INT = 75; - bot_npc_type->WIS = 75; - bot_npc_type->CHA = 75; - bot_npc_type->MR = 25; - bot_npc_type->FR = 25; - bot_npc_type->CR = 25; - bot_npc_type->PR = 15; - bot_npc_type->DR = 15; - bot_npc_type->Corrup = 15; - //bot_npc_type->PhR = 0; - //bot_npc_type->haircolor = 0; - //bot_npc_type->beardcolor = 0; - //bot_npc_type->eyecolor1 = 0; - //bot_npc_type->eyecolor2 = 0; - //bot_npc_type->hairstyle = 0; - //bot_npc_type->luclinface = 0; - //bot_npc_type->beard = 0; - //bot_npc_type->drakkin_heritage = 0; - //bot_npc_type->drakkin_tattoo = 0; - //bot_npc_type->drakkin_details = 0; - //bot_npc_type->armor_tint = { 0 }; - //bot_npc_type->min_dmg = 0; - //bot_npc_type->max_dmg = 0; - //bot_npc_type->charm_ac = 0; - //bot_npc_type->charm_min_dmg = 0; - //bot_npc_type->charm_max_dmg = 0; - //bot_npc_type->charm_attack_delay = 0; - //bot_npc_type->charm_accuracy_rating = 0; - //bot_npc_type->charm_avoidance_rating = 0; - //bot_npc_type->charm_atk = 0; - //bot_npc_type->attack_count = 0; - //*bot_npc_type->special_abilities = { 0 }; - //bot_npc_type->d_melee_texture1 = 0; - //bot_npc_type->d_melee_texture2 = 0; - //*bot_npc_type->ammo_idfile = { 0 }; - //bot_npc_type->prim_melee_type = 0; - //bot_npc_type->sec_melee_type = 0; - //bot_npc_type->ranged_type = 0; - bot_npc_type->hp_regen = 1; - bot_npc_type->mana_regen = 1; - //bot_npc_type->aggroradius = 0; - //bot_npc_type->assistradius = 0; - //bot_npc_type->see_invis = 0; - //bot_npc_type->see_invis_undead = false; - //bot_npc_type->see_hide = false; - //bot_npc_type->see_improved_hide = false; - //bot_npc_type->qglobal = false; - //bot_npc_type->npc_aggro = false; - //bot_npc_type->spawn_limit = 0; - //bot_npc_type->mount_color = 0; - //bot_npc_type->attack_speed = 0.0f; - //bot_npc_type->attack_delay = 0; - //bot_npc_type->accuracy_rating = 0; - //bot_npc_type->avoidance_rating = 0; - //bot_npc_type->findable = false; - bot_npc_type->trackable = true; - //bot_npc_type->slow_mitigation = 0; - bot_npc_type->maxlevel = botLevel; - //bot_npc_type->scalerate = 0; - //bot_npc_type->private_corpse = false; - //bot_npc_type->unique_spawn_by_name = false; - //bot_npc_type->underwater = false; - //bot_npc_type->emoteid = 0; - //bot_npc_type->spellscale = 0.0f; - //bot_npc_type->healscale = 0.0f; - //bot_npc_type->no_target_hotkey = false; - //bot_npc_type->raid_target = false; - //bot_npc_type->armtexture = 0; - //bot_npc_type->bracertexture = 0; - //bot_npc_type->handtexture = 0; - //bot_npc_type->legtexture = 0; - //bot_npc_type->feettexture = 0; - //bot_npc_type->ignore_despawn = false; - bot_npc_type->show_name = true; - //bot_npc_type->untargetable = false; - bot_npc_type->skip_global_loot = true; - //bot_npc_type->rare_spawn = false; - bot_npc_type->stuck_behavior = Ground; - - return bot_npc_type; + return n; } void Bot::GenerateBaseStats() @@ -840,7 +888,7 @@ void Bot::GenerateBaseStats() int32 CorruptionResist = _baseCorrup; // pulling fixed values from an auto-increment field is dangerous... - switch(GetClass()) { + switch (GetClass()) { case WARRIOR: BotSpellID = 3001; Strength += 10; @@ -1153,21 +1201,25 @@ void Bot::GenerateBaseStats() void Bot::GenerateAppearance() { // Randomize facial appearance int iFace = 0; - if(GetRace() == 2) // Barbarian w/Tatoo + if (GetRace() == BARBARIAN) // Barbarian w/Tatoo + { iFace = zone->random.Int(0, 79); + } else + { iFace = zone->random.Int(0, 7); + } int iHair = 0; int iBeard = 0; int iBeardColor = 1; - if(GetRace() == 522) { + if (GetRace() == DRAKKIN) { iHair = zone->random.Int(0, 8); iBeard = zone->random.Int(0, 11); iBeardColor = zone->random.Int(0, 3); - } else if(GetGender()) { + } else if (GetGender()) { iHair = zone->random.Int(0, 2); - if(GetRace() == 8) { // Dwarven Females can have a beard + if (GetRace() == DWARF) { // Dwarven Females can have a beard if(zone->random.Int(1, 100) < 50) iFace += 10; } @@ -1178,24 +1230,26 @@ void Bot::GenerateAppearance() { } int iHairColor = 0; - if(GetRace() == 522) + if (GetRace() == DRAKKIN) { iHairColor = zone->random.Int(0, 3); - else + } else { iHairColor = zone->random.Int(0, 19); + } uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9); uint8 iEyeColor2 = 0; - if(GetRace() == 522) + if (GetRace() == DRAKKIN) { iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11); - else if(zone->random.Int(1, 100) > 96) + } else if(zone->random.Int(1, 100) > 96) { iEyeColor2 = zone->random.Int(0, 9); - else + } else { iEyeColor2 = iEyeColor1; + } int iHeritage = 0; int iTattoo = 0; int iDetails = 0; - if(GetRace() == 522) { + if (GetRace() == DRAKKIN) { iHeritage = zone->random.Int(0, 6); iTattoo = zone->random.Int(0, 7); iDetails = zone->random.Int(0, 7); @@ -1562,9 +1616,8 @@ int32 Bot::acmod() { } else return (65 + ((agility - 300) / 21)); -#if EQDEBUG >= 11 - LogError("Error in Bot::acmod(): Agility: [{}], Level: [{}]",agility,level); -#endif + + LogError("Agility [{}] Level [{}]",agility,level); return 0; } @@ -1761,28 +1814,36 @@ bool Bot::Save() if(!GetBotID()) { // New bot record uint32 bot_id = 0; if (!database.botdb.SaveNewBot(this, bot_id) || !bot_id) { - bot_owner->Message(Chat::Red, "%s '%s'", BotDatabase::fail::SaveNewBot(), GetCleanName()); + bot_owner->Message(Chat::White, "%s '%s'", BotDatabase::fail::SaveNewBot(), GetCleanName()); return false; } SetBotID(bot_id); } else { // Update existing bot record if (!database.botdb.SaveBot(this)) { - bot_owner->Message(Chat::Red, "%s '%s'", BotDatabase::fail::SaveBot(), GetCleanName()); + bot_owner->Message(Chat::White, "%s '%s'", BotDatabase::fail::SaveBot(), GetCleanName()); return false; } } // All of these continue to process if any fail if (!database.botdb.SaveBuffs(this)) - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveBuffs(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for '%s'", BotDatabase::fail::SaveBuffs(), GetCleanName()); if (!database.botdb.SaveTimers(this)) - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveTimers(), GetCleanName()); - if (!database.botdb.SaveStance(this)) - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveStance(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for '%s'", BotDatabase::fail::SaveTimers(), GetCleanName()); + + if (!database.botdb.SaveStance(this)) { + bot_owner->Message( + Chat::White, + fmt::format( + "Failed to save stance for '{}'.", + GetCleanName() + ).c_str() + ); + } if (!SavePet()) - bot_owner->Message(Chat::Red, "Failed to save pet for '%s'", GetCleanName()); + bot_owner->Message(Chat::White, "Failed to save pet for '%s'", GetCleanName()); return true; } @@ -1790,30 +1851,31 @@ bool Bot::Save() bool Bot::DeleteBot() { auto bot_owner = GetBotOwner(); - if (!bot_owner) + if (!bot_owner) { return false; + } if (!database.botdb.DeleteHealRotation(GetBotID())) { - bot_owner->Message(Chat::Red, "%s", BotDatabase::fail::DeleteHealRotation()); + bot_owner->Message(Chat::White, "%s", BotDatabase::fail::DeleteHealRotation()); return false; } std::string query = StringFormat("DELETE FROM `bot_heal_rotation_members` WHERE `bot_id` = '%u'", GetBotID()); auto results = database.QueryDatabase(query); if (!results.Success()) { - bot_owner->Message(Chat::Red, "Failed to delete heal rotation member '%s'", GetCleanName()); + bot_owner->Message(Chat::White, "Failed to delete heal rotation member '%s'", GetCleanName()); return false; } query = StringFormat("DELETE FROM `bot_heal_rotation_targets` WHERE `target_name` LIKE '%s'", GetCleanName()); results = database.QueryDatabase(query); if (!results.Success()) { - bot_owner->Message(Chat::Red, "Failed to delete heal rotation target '%s'", GetCleanName()); + bot_owner->Message(Chat::White, "Failed to delete heal rotation target '%s'", GetCleanName()); return false; } if (!DeletePet()) { - bot_owner->Message(Chat::Red, "Failed to delete pet for '%s'", GetCleanName()); + bot_owner->Message(Chat::White, "Failed to delete pet for '%s'", GetCleanName()); return false; } @@ -1823,32 +1885,73 @@ bool Bot::DeleteBot() std::string error_message; if (!database.botdb.RemoveMemberFromBotGroup(GetBotID())) { - bot_owner->Message(Chat::Red, "%s - '%s'", BotDatabase::fail::RemoveMemberFromBotGroup(), GetCleanName()); + bot_owner->Message( + Chat::White, + fmt::format( + "Failed to remove {} from their bot-group.", + GetCleanName() + ).c_str() + ); return false; } if (!database.botdb.DeleteItems(GetBotID())) { - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteItems(), GetCleanName()); + bot_owner->Message( + Chat::White, + fmt::format( + "{} for '{}'.", + BotDatabase::fail::DeleteItems(), + GetCleanName() + ).c_str() + ); return false; } if (!database.botdb.DeleteTimers(GetBotID())) { - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteTimers(), GetCleanName()); + bot_owner->Message( + Chat::White, + fmt::format( + "{} for '{}'.", + BotDatabase::fail::DeleteTimers(), + GetCleanName() + ).c_str() + ); return false; } if (!database.botdb.DeleteBuffs(GetBotID())) { - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteBuffs(), GetCleanName()); + bot_owner->Message( + Chat::White, + fmt::format( + "{} for '{}'.", + BotDatabase::fail::DeleteBuffs(), + GetCleanName() + ).c_str() + ); return false; } if (!database.botdb.DeleteStance(GetBotID())) { - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteStance(), GetCleanName()); + bot_owner->Message( + Chat::White, + fmt::format( + "{} for '{}'.", + BotDatabase::fail::DeleteStance(), + GetCleanName() + ).c_str() + ); return false; } if (!database.botdb.DeleteBot(GetBotID())) { - bot_owner->Message(Chat::Red, "%s '%s'", BotDatabase::fail::DeleteBot(), GetCleanName()); + bot_owner->Message( + Chat::White, + fmt::format( + "{} '{}'", + BotDatabase::fail::DeleteBot(), + GetCleanName() + ).c_str() + ); return false; } @@ -1892,7 +1995,7 @@ bool Bot::LoadPet() uint32 pet_index = 0; if (!database.botdb.LoadPetIndex(GetBotID(), pet_index)) { - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetIndex(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::LoadPetIndex(), GetCleanName()); return false; } if (!pet_index) @@ -1900,10 +2003,10 @@ bool Bot::LoadPet() uint32 saved_pet_spell_id = 0; if (!database.botdb.LoadPetSpellID(GetBotID(), saved_pet_spell_id)) { - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetSpellID(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::LoadPetSpellID(), GetCleanName()); } if (!IsValidSpell(saved_pet_spell_id)) { - bot_owner->Message(Chat::Red, "Invalid spell id for %s's pet", GetCleanName()); + bot_owner->Message(Chat::White, "Invalid spell id for %s's pet", GetCleanName()); DeletePet(); return false; } @@ -1914,7 +2017,7 @@ bool Bot::LoadPet() uint32 pet_spell_id = 0; if (!database.botdb.LoadPetStats(GetBotID(), pet_name, pet_mana, pet_hp, pet_spell_id)) { - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetStats(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::LoadPetStats(), GetCleanName()); return false; } @@ -1929,12 +2032,12 @@ bool Bot::LoadPet() SpellBuff_Struct pet_buffs[PET_BUFF_COUNT]; memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * PET_BUFF_COUNT)); if (!database.botdb.LoadPetBuffs(GetBotID(), pet_buffs)) - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); uint32 pet_items[EQ::invslot::EQUIPMENT_COUNT]; memset(pet_items, 0, (sizeof(uint32) * EQ::invslot::EQUIPMENT_COUNT)); if (!database.botdb.LoadPetItems(GetBotID(), pet_items)) - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName()); pet_inst->SetPetState(pet_buffs, pet_items); pet_inst->CalcBonuses(); @@ -1973,14 +2076,14 @@ bool Bot::SavePet() std::string error_message; if (!database.botdb.SavePetStats(GetBotID(), pet_name_str, pet_inst->GetMana(), pet_inst->GetHP(), pet_inst->GetPetSpellID())) { - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::SavePetStats(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::SavePetStats(), GetCleanName()); return false; } if (!database.botdb.SavePetBuffs(GetBotID(), pet_buffs)) - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::SavePetBuffs(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::SavePetBuffs(), GetCleanName()); if (!database.botdb.SavePetItems(GetBotID(), pet_items)) - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::SavePetItems(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::SavePetItems(), GetCleanName()); return true; } @@ -1994,15 +2097,15 @@ bool Bot::DeletePet() std::string error_message; if (!database.botdb.DeletePetItems(GetBotID())) { - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::DeletePetItems(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::DeletePetItems(), GetCleanName()); return false; } if (!database.botdb.DeletePetBuffs(GetBotID())) { - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::DeletePetBuffs(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::DeletePetBuffs(), GetCleanName()); return false; } if (!database.botdb.DeletePetStats(GetBotID())) { - bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::DeletePetStats(), GetCleanName()); + bot_owner->Message(Chat::White, "%s for %s's pet", BotDatabase::fail::DeletePetStats(), GetCleanName()); return false; } @@ -2037,7 +2140,7 @@ bool Bot::Process() } if (mob_close_scan_timer.Check()) { - LogAIScanClose( + LogAIScanCloseDetail( "is_moving [{}] bot [{}] timer [{}]", moving ? "true" : "false", GetCleanName(), @@ -2049,16 +2152,12 @@ bool Bot::Process() SpellProcess(); - if(tic_timer.Check()) { + if (tic_timer.Check()) { // 6 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting - if(!IsMoving() && !IsEngaged()) { - - if(IsSitting()) { - - if (!rest_timer.Enabled()) { - rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } + if (!IsEngaged()) { + if (!rest_timer.Enabled()) { + rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); } } @@ -2128,6 +2227,46 @@ bool Bot::Process() return true; } +void Bot::AI_Bot_Start(uint32 iMoveDelay) { + Mob::AI_Start(iMoveDelay); + if (!pAIControlled) { + return; + } + + if (AIBot_spells.empty()) { + AIautocastspell_timer = std::make_unique(1000); + AIautocastspell_timer->Disable(); + } else { + AIautocastspell_timer = std::make_unique(500); + AIautocastspell_timer->Start(RandomTimer(0, 300), false); + } + + if (NPCTypedata) { + ProcessSpecialAbilities(NPCTypedata->special_abilities); + AI_AddNPCSpellsEffects(NPCTypedata->npc_spells_effects_id); + } + + SendTo(GetX(), GetY(), GetZ()); + SaveGuardSpot(GetPosition()); +} + +void Bot::AI_Bot_Init() +{ + AIautocastspell_timer.reset(nullptr); + casting_spell_AIindex = static_cast(AIBot_spells.size()); + + roambox_max_x = 0; + roambox_max_y = 0; + roambox_min_x = 0; + roambox_min_y = 0; + roambox_distance = 0; + roambox_destination_x = 0; + roambox_destination_y = 0; + roambox_destination_z = 0; + roambox_min_delay = 2500; + roambox_delay = 2500; +} + void Bot::SpellProcess() { if(spellend_timer.Check(false)) { NPC::SpellProcess(); @@ -2139,32 +2278,28 @@ void Bot::SpellProcess() { } void Bot::BotMeditate(bool isSitting) { - if(isSitting) { - if(GetManaRatio() < 99.0f || GetHPRatio() < 99.0f) { - if (!IsEngaged() && !IsSitting()) + if (isSitting) { + if (GetManaRatio() < 99.0f || GetHPRatio() < 99.0f) { + if (!IsEngaged() && !IsSitting()) { Sit(); + } } else { - if(IsSitting()) + if (IsSitting()) { Stand(); + } } } else { - if(IsSitting()) + if (IsSitting()) { Stand(); + } } - - if(IsSitting()) { - if(!rest_timer.Enabled()) - rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } - else - rest_timer.Disable(); } void Bot::BotRangedAttack(Mob* other) { //make sure the attack and ranged timers are up //if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())) { - LogCombat("Bot Archery attack canceled. Timer not up. Attack [{}], ranged [{}]", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); + LogCombatDetail("Bot Archery attack canceled. Timer not up. Attack [{}] ranged [{}]", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); return; } @@ -2182,7 +2317,7 @@ void Bot::BotRangedAttack(Mob* other) { if(!RangeWeapon || !Ammo) return; - LogCombat("Shooting [{}] with bow [{}] ([{}]) and arrow [{}] ([{}])", other->GetCleanName(), RangeWeapon->Name, RangeWeapon->ID, Ammo->Name, Ammo->ID); + LogCombatDetail("Shooting [{}] with bow [{}] ([{}]) and arrow [{}] ([{}])", other->GetCleanName(), RangeWeapon->Name, RangeWeapon->ID, Ammo->Name, Ammo->ID); if(!IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) return; @@ -2192,21 +2327,21 @@ void Bot::BotRangedAttack(Mob* other) { //break invis when you attack if(invisible) { - LogCombat("Removing invisibility due to melee attack"); + LogCombatDetail("Removing invisibility due to melee attack"); BuffFadeByEffect(SE_Invisibility); BuffFadeByEffect(SE_Invisibility2); invisible = false; } if(invisible_undead) { - LogCombat("Removing invisibility vs. undead due to melee attack"); + LogCombatDetail("Removing invisibility vs. undead due to melee attack"); BuffFadeByEffect(SE_InvisVsUndead); BuffFadeByEffect(SE_InvisVsUndead2); invisible_undead = false; } if(invisible_animals) { - LogCombat("Removing invisibility vs. animals due to melee attack"); + LogCombatDetail("Removing invisibility vs. animals due to melee attack"); BuffFadeByEffect(SE_InvisVsAnimals); invisible_animals = false; } @@ -2214,7 +2349,7 @@ void Bot::BotRangedAttack(Mob* other) { if (spellbonuses.NegateIfCombat) BuffFadeByEffect(SE_NegateIfCombat); - if(hidden || improved_hidden){ + if (hidden || improved_hidden) { hidden = false; improved_hidden = false; EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); @@ -2524,7 +2659,13 @@ void Bot::AI_Process() auto pull_target = bot_owner->GetTarget(); if (pull_target) { - Bot::BotGroupSay(this, "Pulling %s to the group..", pull_target->GetCleanName()); + BotGroupSay( + this, + fmt::format( + "Pulling {}.", + pull_target->GetCleanName() + ).c_str() + ); InterruptSpell(); WipeHateList(); AddToHateList(pull_target, 1); @@ -2683,14 +2824,20 @@ void Bot::AI_Process() bool find_target = true; if (assist_mob) { - if (assist_mob->GetTarget()) { - if (assist_mob != this) { + if (GetTarget() != assist_mob->GetTarget()) { + SetTarget(assist_mob->GetTarget()); + } - SetTarget(assist_mob->GetTarget()); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - + if ( + HasPet() && + ( + GetClass() != ENCHANTER || + GetPet()->GetPetType() != petAnimation || + GetAA(aaAnimationEmpathy) >= 2 + ) + ) { // This artificially inflates pet's target aggro..but, less expensive than checking hate each AI process GetPet()->AddToHateList(assist_mob->GetTarget(), 1); GetPet()->SetTarget(assist_mob->GetTarget()); @@ -2698,12 +2845,19 @@ void Bot::AI_Process() } find_target = false; - } - else if (assist_mob != this) { - - SetTarget(nullptr); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { + } else if (assist_mob != this) { + if (GetTarget()) { + SetTarget(nullptr); + } + if ( + HasPet() && + ( + GetClass() != ENCHANTER || + GetPet()->GetPetType() != petAnimation || + GetAA(aaAnimationEmpathy) >= 1 + ) + ) { GetPet()->WipeHateList(); GetPet()->SetTarget(nullptr); } @@ -2713,16 +2867,23 @@ void Bot::AI_Process() } if (find_target) { - if (IsRooted()) { - SetTarget(hate_list.GetClosestEntOnHateList(this, true)); - } - else { - + auto closest = hate_list.GetClosestEntOnHateList(this, true); + if (closest) { + SetTarget(closest); + } + } else { // This will keep bots on target for now..but, future updates will allow for rooting/stunning - SetTarget(hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance)); + auto escaping = hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance); + if (escaping) { + SetTarget(escaping); + } + if (!GetTarget()) { - SetTarget(hate_list.GetEntWithMostHateOnList(this, nullptr, true)); + auto most_hate = hate_list.GetEntWithMostHateOnList(this, nullptr, true); + if (most_hate) { + SetTarget(most_hate); + } } } } @@ -2745,8 +2906,10 @@ void Bot::AI_Process() Mob* tar = GetTarget(); // We should have a target..if not, we're awaiting new orders if (!tar || PASSIVE) { + if (GetTarget()) { + SetTarget(nullptr); + } - SetTarget(nullptr); WipeHateList(); SetAttackFlag(false); SetAttackingFlag(false); @@ -2996,12 +3159,12 @@ void Bot::AI_Process() if (atArcheryRange && !IsBotArcher()) { - SetBotArcher(true); + SetBotArcherySetting(true); changeWeapons = true; } else if (!atArcheryRange && IsBotArcher()) { - SetBotArcher(false); + SetBotArcherySetting(false); changeWeapons = true; } @@ -3259,8 +3422,8 @@ void Bot::AI_Process() TEST_COMBATANTS(); auto ExtraAttackChanceBonus = - (spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] + - aabonuses.ExtraAttackChance[0]); + (spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] + + aabonuses.ExtraAttackChance[0]); if (ExtraAttackChanceBonus) { if (p_item && p_item->GetItem()->IsType2HWeapon()) { @@ -3338,7 +3501,7 @@ void Bot::AI_Process() if (GetTarget() && !IsRooted()) { - LogAI("Pursuing [{}] while engaged", GetTarget()->GetCleanName()); + LogAIDetail("Pursuing [{}] while engaged", GetTarget()->GetCleanName()); Goal = GetTarget()->GetPosition(); if (DistanceSquared(m_Position, Goal) <= leash_distance) { RunTo(Goal.x, Goal.y, Goal.z); @@ -3724,7 +3887,7 @@ void Bot::PetAIProcess() { else if (botPet->GetTarget() && botPet->GetAIMovementTimer()->Check()) { botPet->SetRunAnimSpeed(0); if(!botPet->IsRooted()) { - LogAI("Pursuing [{}] while engaged", botPet->GetTarget()->GetCleanName()); + LogAIDetail("Pursuing [{}] while engaged", botPet->GetTarget()->GetCleanName()); botPet->RunTo(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ()); return; } else { @@ -3817,7 +3980,7 @@ bool Bot::Spawn(Client* botCharacterOwner) { ); } else { GetBotOwner()->CastToClient()->Message( - Chat::Red, + Chat::White, fmt::format( "{} save failed!", GetCleanName() @@ -3837,17 +4000,31 @@ bool Bot::Spawn(Client* botCharacterOwner) { m_targetable = true; entity_list.AddBot(this, true, true); + + GetBotOwnerDataBuckets(); + GetBotDataBuckets(); + LoadBotSpellSettings(); + if (!AI_AddBotSpells(GetBotSpellID())) { + GetBotOwner()->CastToClient()->Message( + Chat::White, + fmt::format( + "Failed to load spells for '{}' (ID {}).", + GetCleanName(), + GetBotID() + ).c_str() + ); + } + // Load pet LoadPet(); SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0); ping_timer.Start(8000); // there is something askew with spawn struct appearance fields... // I re-enabled this until I can sort it out - uint32 item_id = 0; + const auto& m = GetBotItemSlots(); uint8 material_from_slot = 0xFF; for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) { - item_id = GetBotItemBySlot(slot_id); - if (item_id != 0) { + if (m.find(slot_id) != m.end()) { material_from_slot = EQ::InventoryProfile::CalcMaterialFromSlot(slot_id); if (material_from_slot != 0xFF) { SendWearChange(material_from_slot); @@ -3865,14 +4042,14 @@ bool Bot::Spawn(Client* botCharacterOwner) { void Bot::RemoveBotItemBySlot(uint16 slot_id, std::string *error_message) { if (!GetBotID()) { - return; + return; } - if (!database.botdb.DeleteItemBySlot(GetBotID(), slot_id)) { - *error_message = BotDatabase::fail::DeleteItemBySlot(); + if (!database.botdb.DeleteItemBySlot(GetBotID(), slot_id)) { + *error_message = BotDatabase::fail::DeleteItemBySlot(); } - m_inv.DeleteItem(slot_id); + m_inv.DeleteItem(slot_id); UpdateEquipmentLight(); } @@ -3891,21 +4068,42 @@ void Bot::GetBotItems(EQ::InventoryProfile &inv, std::string* error_message) UpdateEquipmentLight(); } +std::map Bot::GetBotItemSlots() +{ + std::map m; + if (!GetBotID()) { + return m; + } + + if (!database.botdb.LoadItemSlots(GetBotID(), m)) { + GetBotOwner()->CastToClient()->Message( + Chat::White, + fmt::format( + "Failed to load inventory slots for {}.", + GetCleanName() + ).c_str() + ); + } + + return m; +} + // Returns the inventory record for this bot from the database for the specified equipment slot. uint32 Bot::GetBotItemBySlot(uint16 slot_id) { uint32 item_id = 0; if (!GetBotID()) { - return item_id; + return item_id; } if (!database.botdb.LoadItemBySlot(GetBotID(), slot_id, item_id)) { if (GetBotOwner() && GetBotOwner()->IsClient()) { GetBotOwner()->CastToClient()->Message( - Chat::Red, + Chat::White, fmt::format( - "{}", - BotDatabase::fail::LoadItemBySlot() + "Failed to load slot ID {} for {}.", + slot_id, + GetCleanName() ).c_str() ); } @@ -4005,40 +4203,91 @@ Bot* Bot::LoadBot(uint32 botID) } // Load and spawn all zoned bots by bot owner character -void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { - if(botOwner) { - if(botOwner->HasGroup()) { - Group* g = botOwner->GetGroup(); - if(g) { - uint32 TempGroupId = g->GetID(); - std::list ActiveBots; - // Modified LoadGroupedBotsByGroupID to require a CharacterID - if (!database.botdb.LoadGroupedBotsByGroupID(botOwner->CharacterID(), TempGroupId, ActiveBots)) { - botOwner->Message(Chat::Red, "%s", BotDatabase::fail::LoadGroupedBotsByGroupID()); +void Bot::LoadAndSpawnAllZonedBots(Client* bot_owner) { + if (bot_owner) { + std::list> auto_spawn_botgroups; + if (bot_owner->HasGroup()) { + std::vector bot_class_spawn_limits; + std::vector bot_class_spawned_count = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + for (uint8 class_id = WARRIOR; class_id <= BERSERKER; class_id++) { + auto bot_class_limit = bot_owner->GetBotSpawnLimit(class_id); + bot_class_spawn_limits.push_back(bot_class_limit); + } + + auto* g = bot_owner->GetGroup(); + if (g) { + uint32 group_id = g->GetID(); + std::list active_bots; + + auto spawned_bots_count = 0; + auto bot_spawn_limit = bot_owner->GetBotSpawnLimit(); + + if (!database.botdb.LoadAutoSpawnBotGroupsByOwnerID(bot_owner->CharacterID(), auto_spawn_botgroups)) { + bot_owner->Message(Chat::White, "Failed to load auto spawn bot groups by group ID."); return; } - if(!ActiveBots.empty()) { - for(std::list::iterator itr = ActiveBots.begin(); itr != ActiveBots.end(); ++itr) { - Bot* activeBot = Bot::LoadBot(*itr); - if (!activeBot) - continue; + for (const auto& botgroup : auto_spawn_botgroups) { + Bot::SpawnBotGroupByName(bot_owner, botgroup.second, botgroup.first); + } - if (!activeBot->Spawn(botOwner)) { - safe_delete(activeBot); + if (!database.botdb.LoadGroupedBotsByGroupID(bot_owner->CharacterID(), group_id, active_bots)) { + bot_owner->Message(Chat::White, "Failed to load grouped bots by group ID."); + return; + } + + if (!active_bots.empty()) { + for (const auto& bot_id : active_bots) { + auto* b = Bot::LoadBot(bot_id); + if (!b) { continue; } - g->UpdatePlayer(activeBot); - // follow the bot owner, not the group leader we just zoned with our owner. - if (g->IsGroupMember(botOwner) && g->IsGroupMember(activeBot)) - activeBot->SetFollowID(botOwner->GetID()); + if (bot_spawn_limit >= 0 && spawned_bots_count >= bot_spawn_limit) { + database.SetGroupID(b->GetCleanName(), 0, b->GetBotID()); + g->UpdatePlayer(bot_owner); + continue; + } - if(!botOwner->HasGroup()) - database.SetGroupID(activeBot->GetCleanName(), 0, activeBot->GetBotID()); + auto spawned_bot_count_class = bot_class_spawned_count[b->GetClass() - 1]; + auto bot_spawn_limit_class = bot_class_spawn_limits[b->GetClass() - 1]; + + if (bot_spawn_limit_class >= 0 && spawned_bot_count_class >= bot_spawn_limit_class) { + database.SetGroupID(b->GetCleanName(), 0, b->GetBotID()); + g->UpdatePlayer(bot_owner); + continue; + } + + if (!b->Spawn(bot_owner)) { + safe_delete(b); + continue; + } + + spawned_bots_count++; + bot_class_spawned_count[b->GetClass() - 1]++; + + g->UpdatePlayer(b); + + if (g->IsGroupMember(bot_owner) && g->IsGroupMember(b)) { + b->SetFollowID(bot_owner->GetID()); + } + + if (!bot_owner->HasGroup()) { + database.SetGroupID(b->GetCleanName(), 0, b->GetBotID()); + } } } } + } else { + if (!database.botdb.LoadAutoSpawnBotGroupsByOwnerID(bot_owner->CharacterID(), auto_spawn_botgroups)) { + bot_owner->Message(Chat::White, "Failed to load auto spawn bot groups by group ID."); + return; + } + + for (const auto& botgroup : auto_spawn_botgroups) { + Bot::SpawnBotGroupByName(bot_owner, botgroup.second, botgroup.first); + } } } } @@ -4060,13 +4309,15 @@ bool Bot::GroupHasBot(Group* group) { return Result; } -uint32 Bot::SpawnedBotCount(uint32 botOwnerCharacterID) { - uint32 Result = 0; - if(botOwnerCharacterID > 0) { - std::list SpawnedBots = entity_list.GetBotsByBotOwnerCharacterID(botOwnerCharacterID); - Result = SpawnedBots.size(); +uint32 Bot::SpawnedBotCount(const uint32 owner_id, uint8 class_id) { + uint32 spawned_bot_count = 0; + + if (owner_id) { + const auto& sbl = entity_list.GetBotListByCharacterID(owner_id, class_id); + spawned_bot_count = sbl.size(); } - return Result; + + return spawned_bot_count; } void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) { @@ -4214,10 +4465,12 @@ void Bot::AddBotItem( if (!database.botdb.SaveItemBySlot(this, slot_id, inst)) { LogError("Failed to save item by slot to slot [{}] for [{}].", slot_id, GetCleanName()); + safe_delete(inst); return; } m_inv.PutItem(slot_id, *inst); + safe_delete(inst); BotAddEquipItem(slot_id, item_id); } @@ -4275,7 +4528,7 @@ void Bot::RemoveBotItem(uint32 item_id) { if (!error_message.empty()) { if (GetOwner()) { GetOwner()->CastToClient()->Message( - Chat::Magenta, + Chat::White, fmt::format( "Database Error: {}", error_message @@ -4376,11 +4629,11 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* using namespace EQ; struct ClientTrade { - const ItemInstance* trade_item_instance; + ItemInstance* trade_item_instance; int16 from_client_slot; int16 to_bot_slot; - ClientTrade(const ItemInstance* item, int16 from) : trade_item_instance(item), from_client_slot(from), to_bot_slot(invslot::SLOT_INVALID) { } + ClientTrade(ItemInstance* item, int16 from) : trade_item_instance(item), from_client_slot(from), to_bot_slot(invslot::SLOT_INVALID) { } }; struct ClientReturn { @@ -4408,31 +4661,31 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* } if (client != GetOwner()) { - client->Message(Chat::Red, "You are not the owner of this bot, the trade has been cancelled."); + client->Message(Chat::White, "You are not the owner of this bot, the trade has been cancelled."); client->ResetTrade(); return; } if (begin_slot_id != invslot::TRADE_BEGIN && begin_slot_id != invslot::slotCursor) { - client->Message(Chat::Red, "Trade request processing from illegal 'begin' slot, the trade has been cancelled."); + client->Message(Chat::White, "Trade request processing from illegal 'begin' slot, the trade has been cancelled."); client->ResetTrade(); return; } if (end_slot_id != invslot::TRADE_END && end_slot_id != invslot::slotCursor) { - client->Message(Chat::Red, "Trade request processing from illegal 'end' slot, the trade has been cancelled."); + client->Message(Chat::White, "Trade request processing from illegal 'end' slot, the trade has been cancelled."); client->ResetTrade(); return; } if ((begin_slot_id == invslot::slotCursor && end_slot_id != invslot::slotCursor) || (begin_slot_id != invslot::slotCursor && end_slot_id == invslot::slotCursor)) { - client->Message(Chat::Red, "Trade request processing illegal slot range, the trade has been cancelled."); + client->Message(Chat::White, "Trade request processing illegal slot range, the trade has been cancelled."); client->ResetTrade(); return; } if (end_slot_id < begin_slot_id) { - client->Message(Chat::Red, "Trade request processing in reverse slot order, the trade has been cancelled."); + client->Message(Chat::White, "Trade request processing in reverse slot order, the trade has been cancelled."); client->ResetTrade(); return; } @@ -4444,19 +4697,27 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* } std::list client_trade; + std::list event_trade; std::list client_return; + bool trade_event_exists = false; + if (parse->BotHasQuestSub(EVENT_TRADE)) { + // There is a EVENT_TRADE, we will let the Event handle returning of items. + trade_event_exists = true; + } + // pre-checks for incoming illegal transfers + EQ::InventoryProfile& user_inv = client->GetInv(); for (int16 trade_index = begin_slot_id; trade_index <= end_slot_id; ++trade_index) { - auto trade_instance = client->GetInv()[trade_index]; + auto trade_instance = user_inv.GetItem(trade_index); if (!trade_instance) { continue; } if (!trade_instance->GetItem()) { - LogError("Bot::PerformTradeWithClient could not find item from instance in trade for {} with {} in slot {}.", client->GetCleanName(), GetCleanName(), trade_index); + LogError("could not find item from instance in trade for [{}] with [{}] in slot [{}].", client->GetCleanName(), GetCleanName(), trade_index); client->Message( - Chat::Red, + Chat::White, fmt::format( "A server error was encountered while processing client slot {}, the trade has been cancelled.", trade_index @@ -4473,44 +4734,72 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* auto item_link = linker.GenerateLink(); if (trade_index != invslot::slotCursor && !trade_instance->IsDroppable()) { - LogError("Bot::PerformTradeWithClient trade hack detected by {} with {}.", client->GetCleanName(), GetCleanName()); - client->Message(Chat::Red, "Trade hack detected, the trade has been cancelled."); + LogError("trade hack detected by [{}] with [{}].", client->GetCleanName(), GetCleanName()); + client->Message(Chat::White, "Trade hack detected, the trade has been cancelled."); client->ResetTrade(); return; } if (trade_instance->IsStackable() && trade_instance->GetCharges() < trade_instance->GetItem()->StackSize) { // temp until partial stacks are implemented - client->Message( - Chat::Yellow, - fmt::format( - "{} is only a partially stacked item, the trade has been cancelled!", - item_link - ).c_str() - ); - client->ResetTrade(); - return; + if (trade_event_exists) { + event_trade.push_back(ClientTrade(trade_instance, trade_index)); + continue; + } + else { + client->Message( + Chat::Yellow, + fmt::format( + "{} is only a partially stacked item, the trade has been cancelled!", + item_link + ).c_str() + ); + client->ResetTrade(); + return; + } } if (CheckLoreConflict(trade_instance->GetItem())) { - client->Message( - Chat::Yellow, - fmt::format( - "This bot already has {}, the trade has been cancelled!", - item_link - ).c_str() - ); - client->ResetTrade(); - return; + if (trade_event_exists) { + event_trade.push_back(ClientTrade(trade_instance, trade_index)); + continue; + } + else { + client->Message( + Chat::Yellow, + fmt::format( + "This bot already has {}, the trade has been cancelled!", + item_link + ).c_str() + ); + client->ResetTrade(); + return; + } } if (!trade_instance->IsType(item::ItemClassCommon)) { - client_return.push_back(ClientReturn(trade_instance, trade_index)); - continue; + if (trade_event_exists) { + event_trade.push_back(ClientTrade(trade_instance, trade_index)); + continue; + } + else { + client->ResetTrade(); + return; + } } - if (!trade_instance->IsEquipable(GetBaseRace(), GetClass()) || (GetLevel() < trade_instance->GetItem()->ReqLevel)) { // deity checks will be handled within IsEquipable() - client_return.push_back(ClientReturn(trade_instance, trade_index)); - continue; + if ( + !trade_instance->IsClassEquipable(GetClass()) || + GetLevel() < trade_instance->GetItem()->ReqLevel || + (!trade_instance->IsRaceEquipable(GetBaseRace()) && !RuleB(Bots, AllowBotEquipAnyRaceGear)) + ) { + if (trade_event_exists) { + event_trade.push_back(ClientTrade(trade_instance, trade_index)); + continue; + } + else { + client->ResetTrade(); + return; + } } client_trade.push_back(ClientTrade(trade_instance, trade_index)); @@ -4518,7 +4807,9 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* // check for incoming lore hacks for (auto& trade_iterator : client_trade) { - if (!trade_iterator.trade_item_instance->GetItem()->LoreFlag) { + auto trade_instance = trade_iterator.trade_item_instance; + auto trade_index = trade_iterator.from_client_slot; + if (!trade_instance->GetItem()->LoreFlag) { continue; } @@ -4531,16 +4822,16 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* continue; } - if (trade_iterator.trade_item_instance->GetItem()->LoreGroup == -1 && check_iterator.trade_item_instance->GetItem()->ID == trade_iterator.trade_item_instance->GetItem()->ID) { - LogError("Bot::PerformTradeWithClient trade hack detected by {} with {}.", client->GetCleanName(), GetCleanName()); - client->Message(Chat::Red, "Trade hack detected, the trade has been cancelled."); + if (trade_instance->GetItem()->LoreGroup == -1 && check_iterator.trade_item_instance->GetItem()->ID == trade_instance->GetItem()->ID) { + LogError("trade hack detected by [{}] with [{}].", client->GetCleanName(), GetCleanName()); + client->Message(Chat::White, "Trade hack detected, the trade has been cancelled."); client->ResetTrade(); return; } - if ((trade_iterator.trade_item_instance->GetItem()->LoreGroup > 0) && (check_iterator.trade_item_instance->GetItem()->LoreGroup == trade_iterator.trade_item_instance->GetItem()->LoreGroup)) { - LogError("Bot::PerformTradeWithClient trade hack detected by {} with {}.", client->GetCleanName(), GetCleanName()); - client->Message(Chat::Red, "Trade hack detected, the trade has been cancelled."); + if ((trade_instance->GetItem()->LoreGroup > 0) && (check_iterator.trade_item_instance->GetItem()->LoreGroup == trade_instance->GetItem()->LoreGroup)) { + LogError("trade hack detected by [{}] with [{}].", client->GetCleanName(), GetCleanName()); + client->Message(Chat::White, "Trade hack detected, the trade has been cancelled."); client->ResetTrade(); return; } @@ -4638,12 +4929,19 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* } } - // move unassignable items from trade list to return list + // move unassignable items from trade list to event list for (std::list::iterator trade_iterator = client_trade.begin(); trade_iterator != client_trade.end();) { if (trade_iterator->to_bot_slot == invslot::SLOT_INVALID) { - client_return.push_back(ClientReturn(trade_iterator->trade_item_instance, trade_iterator->from_client_slot)); - trade_iterator = client_trade.erase(trade_iterator); - continue; + if (trade_event_exists) { + event_trade.push_back(ClientTrade(trade_iterator->trade_item_instance, trade_iterator->from_client_slot)); + trade_iterator = client_trade.erase(trade_iterator); + continue; + } + else { + client_return.push_back(ClientReturn(trade_iterator->trade_item_instance, trade_iterator->from_client_slot)); + trade_iterator = client_trade.erase(trade_iterator); + continue; + } } ++trade_iterator; } @@ -4656,9 +4954,9 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* } if (!return_instance->GetItem()) { - LogError("Bot::PerformTradeWithClient error processing bot slot {} for {} in trade with {}.", return_iterator.from_bot_slot, GetCleanName(), client->GetCleanName()); + LogError("error processing bot slot [{}] for [{}] in trade with [{}].", return_iterator.from_bot_slot, GetCleanName(), client->GetCleanName()); client->Message( - Chat::Red, + Chat::White, fmt::format( "A server error was encountered while processing bot slot {}, the trade has been cancelled.", return_iterator.from_bot_slot @@ -4762,12 +5060,10 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* //} if (!database.botdb.DeleteItemBySlot(GetBotID(), return_iterator.from_bot_slot)) { - client->Message( - Chat::Red, + OwnerMessage( fmt::format( - "Failed to delete item by slot from slot {} for {}.", - return_iterator.from_bot_slot, - GetCleanName() + "Failed to delete item by slot from slot {}.", + return_iterator.from_bot_slot ).c_str() ); } @@ -4780,13 +5076,11 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* linker.SetItemInst(return_instance); auto item_link = linker.GenerateLink(); - client->Message( - Chat::Tell, + OwnerMessage( fmt::format( - "{} tells you, 'I have returned {}.'", - GetCleanName(), + "I have returned {}.", item_link - ).c_str() + ) ); client->PutItemInInventory(return_iterator.to_client_slot, *return_instance, true); @@ -4802,12 +5096,10 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* // TODO: code for stackables if (!database.botdb.SaveItemBySlot(this, trade_iterator.to_bot_slot, trade_iterator.trade_item_instance)) { - client->Message( - Chat::Red, + OwnerMessage( fmt::format( - "Failed to save item by slot to slot {} for {}.", - trade_iterator.to_bot_slot, - GetCleanName() + "Failed to save item by slot to slot {}.", + trade_iterator.to_bot_slot ).c_str() ); } @@ -4817,13 +5109,11 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* linker.SetItemInst(trade_iterator.trade_item_instance); auto item_link = linker.GenerateLink(); - client->Message( - Chat::Tell, + OwnerMessage( fmt::format( - "{} tells you, 'I have accepted {}.'", - GetCleanName(), + "I have accepted {}.", item_link - ).c_str() + ) ); m_inv.PutItem(trade_iterator.to_bot_slot, *trade_iterator.trade_item_instance); @@ -4848,6 +5138,42 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* if (accepted_count) { CalcBotStats(client->GetBotOption(Client::booStatsUpdate)); } + + if (event_trade.size()) { + // Get Traded Items + + // Accept Items from Cursor to support bot command ^inventorygive + if (begin_slot_id == invslot::slotCursor && end_slot_id == invslot::slotCursor) { + EQ::ItemInstance* insts[1] = { 0 }; + EQ::InventoryProfile& user_inv = client->GetInv(); + insts[0] = user_inv.GetItem(invslot::slotCursor); + client->DeleteItemInInventory(invslot::slotCursor); + + // copy to be filtered by task updates, null trade slots preserved for quest event arg + std::vector items(insts, insts + std::size(insts)); + + // Check if EVENT_TRADE accepts any items + std::vector item_list(items.begin(), items.end()); + parse->EventBot(EVENT_TRADE, this, client, "", 0, &item_list); + CalcBotStats(false); + + } else { + EQ::ItemInstance* insts[8] = { 0 }; + EQ::InventoryProfile& user_inv = client->GetInv(); + for (int i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; ++i) { + insts[i - EQ::invslot::TRADE_BEGIN] = user_inv.GetItem(i); + client->DeleteItemInInventory(i); + } + + // copy to be filtered by task updates, null trade slots preserved for quest event arg + std::vector items(insts, insts + std::size(insts)); + + // Check if EVENT_TRADE accepts any items + std::vector item_list(items.begin(), items.end()); + parse->EventBot(EVENT_TRADE, this, client, "", 0, &item_list); + CalcBotStats(false); + } + } } bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) { @@ -4859,9 +5185,9 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill Mob *my_owner = GetBotOwner(); if (my_owner && my_owner->IsClient() && my_owner->CastToClient()->GetBotOption(Client::booDeathMarquee)) { if (killerMob) - my_owner->CastToClient()->SendMarqueeMessage(Chat::Red, 510, 0, 1000, 3000, StringFormat("%s has been slain by %s", GetCleanName(), killerMob->GetCleanName())); + my_owner->CastToClient()->SendMarqueeMessage(Chat::White, 510, 0, 1000, 3000, StringFormat("%s has been slain by %s", GetCleanName(), killerMob->GetCleanName())); else - my_owner->CastToClient()->SendMarqueeMessage(Chat::Red, 510, 0, 1000, 3000, StringFormat("%s has been slain", GetCleanName())); + my_owner->CastToClient()->SendMarqueeMessage(Chat::White, 510, 0, 1000, 3000, StringFormat("%s has been slain", GetCleanName())); } Mob *give_exp = hate_list.GetDamageTopOnHateList(this); @@ -4934,6 +5260,16 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill my_owner->CastToClient()->SetBotPulling(false); } + const auto export_string = fmt::format( + "{} {} {} {}", + killerMob ? killerMob->GetID() : 0, + damage, + spell_id, + static_cast(attack_skill) + ); + + parse->EventBot(EVENT_DEATH_COMPLETE, this, killerMob, export_string, 0); + entity_list.RemoveBot(GetID()); return true; } @@ -4945,16 +5281,16 @@ void Bot::Damage(Mob *from, int64 damage, uint16 spell_id, EQ::skills::SkillType //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds if(attacked_timer.Check()) { LogCombat("Triggering EVENT_ATTACK due to attack by [{}]", from->GetName()); - parse->EventNPC(EVENT_ATTACK, this, from, "", 0); + parse->EventBot(EVENT_ATTACK, this, from, "", 0); } attacked_timer.Start(CombatEventTimer_expire); // if spell is lifetap add hp to the caster if (spell_id != SPELL_UNKNOWN && IsLifetapSpell(spell_id)) { int64 healed = GetActSpellHealing(spell_id, damage); - LogCombat("Applying lifetap heal of [{}] to [{}]", healed, GetCleanName()); + LogCombatDetail("Applying lifetap heal of [{}] to [{}]", healed, GetCleanName()); HealDamage(healed); - entity_list.MessageClose(this, true, 300, Chat::Spells, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() ); + entity_list.FilteredMessageClose(this, true, RuleI(Range, SpellMessages), Chat::Emote, FilterSocials, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() ); } CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); @@ -4980,1006 +5316,6 @@ void Bot::Damage(Mob *from, int64 damage, uint16 spell_id, EQ::skills::SkillType } } -//void Bot::AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false) -void Bot::AddToHateList(Mob* other, int64 hate, int64 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic, bool pet_command) { - Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic, pet_command); -} - -bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { - if (!other) { - SetTarget(nullptr); - LogError("A null Mob object was passed to Bot::Attack for evaluation!"); - return false; - } - - if ((GetHP() <= 0) || (GetAppearance() == eaDead)) { - SetTarget(nullptr); - LogCombat("Attempted to attack [{}] while unconscious or, otherwise, appearing dead", other->GetCleanName()); - return false; - } - - //if(!GetTarget() || GetTarget() != other) // NPC::Attack() doesn't do this - // SetTarget(other); - - // apparently, we always want our target to be 'other'..why not just set it? - SetTarget(other); - // takes more to compare a call result, load for a call, load a compare to address and compare, and finally - // push a value to an address than to just load for a call and push a value to an address. - - LogCombat("Attacking [{}] with hand [{}] [{}]", other->GetCleanName(), Hand, (FromRiposte ? "(this is a riposte)" : "")); - if ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) || (!IsAttackAllowed(other))) { - if(GetOwnerID()) - entity_list.MessageClose(this, 1, 200, 10, "%s says, '%s is not a legal target master.'", GetCleanName(), GetTarget()->GetCleanName()); - - if(other) { - RemoveFromHateList(other); - LogCombat("I am not allowed to attack [{}]", other->GetCleanName()); - } - return false; - } - - if(DivineAura()) {//cant attack while invulnerable - LogCombat("Attack canceled, Divine Aura is in effect"); - return false; - } - - FaceTarget(GetTarget()); - EQ::ItemInstance* weapon = nullptr; - if (Hand == EQ::invslot::slotPrimary) { - weapon = GetBotItem(EQ::invslot::slotPrimary); - OffHandAtk(false); - } - - if (Hand == EQ::invslot::slotSecondary) { - weapon = GetBotItem(EQ::invslot::slotSecondary); - OffHandAtk(true); - } - - if(weapon != nullptr) { - if (!weapon->IsWeapon()) { - LogCombat("Attack canceled, Item [{}] ([{}]) is not a weapon", weapon->GetItem()->Name, weapon->GetID()); - return false; - } - LogCombat("Attacking with weapon: [{}] ([{}])", weapon->GetItem()->Name, weapon->GetID()); - } - else - LogCombat("Attacking without a weapon"); - - // calculate attack_skill and skillinuse depending on hand and weapon - // also send Packet to near clients - DamageHitInfo my_hit; - my_hit.skill = AttackAnimation(Hand, weapon); - LogCombat("Attacking with [{}] in slot [{}] using skill [{}]", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); - - // Now figure out damage - my_hit.damage_done = 1; - my_hit.min_damage = 0; - uint8 mylevel = GetLevel() ? GetLevel() : 1; - int64 hate = 0; - if (weapon) - hate = (weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt); - - my_hit.base_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && my_hit.base_damage > 1) - hate = my_hit.base_damage; - - //if weapon damage > 0 then we know we can hit the target with this weapon - //otherwise we cannot and we set the damage to -5 later on - if (my_hit.base_damage > 0) { - my_hit.min_damage = 0; - - // *************************************************************** - // *** Calculate the damage bonus, if applicable, for this hit *** - // *************************************************************** - -#ifndef EQEMU_NO_WEAPON_DAMAGE_BONUS - - // If you include the preprocessor directive "#define EQEMU_NO_WEAPON_DAMAGE_BONUS", that indicates that you do not - // want damage bonuses added to weapon damage at all. This feature was requested by ChaosSlayer on the EQEmu Forums. - // - // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output - // of weapons wielded by higher-level melee characters (especially for two-handed weapons). - int ucDamageBonus = 0; - if (Hand == EQ::invslot::slotPrimary && GetLevel() >= 28 && IsWarriorClass()) { - // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above - // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQ::ItemData*) nullptr); - my_hit.min_damage = ucDamageBonus; - hate += ucDamageBonus; - } -#endif - //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand == EQ::invslot::slotSecondary) { - if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQ::ItemData*) nullptr); - my_hit.min_damage = ucDamageBonus; - hate += ucDamageBonus; - } - } - - LogCombat("Damage calculated: base [{}] min damage [{}] skill [{}]", my_hit.base_damage, my_hit.min_damage, my_hit.skill); - - int hit_chance_bonus = 0; - my_hit.offense = offense(my_hit.skill); - my_hit.hand = Hand; - - if (opts) { - my_hit.base_damage *= opts->damage_percent; - my_hit.base_damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - hit_chance_bonus += opts->hit_chance; - } - - my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); - - DoAttack(other, my_hit, opts, FromRiposte); - - LogCombat("Final damage after all reductions: [{}]", my_hit.damage_done); - } else { - my_hit.damage_done = DMG_INVULNERABLE; - } - - // Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same. - // If we are this far, this means we are atleast making a swing. - other->AddToHateList(this, hate); - - /////////////////////////////////////////////////////////// - ////// Send Attack Damage - /////////////////////////////////////////////////////////// - other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill); - - if (GetHP() < 0) - return false; - - MeleeLifeTap(my_hit.damage_done); - - if (my_hit.damage_done > 0) - CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); - - CommonBreakInvisibleFromCombat(); - if (spellbonuses.NegateIfCombat) - BuffFadeByEffect(SE_NegateIfCombat); - - if(GetTarget()) - TriggerDefensiveProcs(other, Hand, true, my_hit.damage_done); - - if (my_hit.damage_done > 0) - return true; - else - return false; -} - -int32 Bot::CalcBotAAFocus(focusType type, uint32 aa_ID, uint32 points, uint16 spell_id) -{ - const SPDat_Spell_Struct &spell = spells[spell_id]; - int32 value = 0; - int lvlModifier = 100; - int spell_level = 0; - int lvldiff = 0; - bool LimitSpellSkill = false; - bool SpellSkill_Found = false; - uint32 effect = 0; - int32 base_value = 0; - int32 limit_value = 0; - uint32 slot = 0; - bool LimitFound = false; - int FocusCount = 0; - - auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_ID, points); - auto ability = ability_rank.first; - auto rank = ability_rank.second; - - if(!ability) { - return 0; - } - - for(auto &eff : rank->effects) { - effect = eff.effect_id; - base_value = eff.base_value; - limit_value = eff.limit_value; - slot = eff.slot; - - //AA Foci's can contain multiple focus effects within the same AA. - //To handle this we will not automatically return zero if a limit is found. - //Instead if limit is found and multiple effects, we will reset the limit check - //when the next valid focus effect is found. - if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)) { - FocusCount++; - //If limit found on prior check next, else end loop. - if (FocusCount > 1) { - if (LimitFound) { - value = 0; - LimitFound = false; - } - else - break; - } - } - - - switch (effect) { - case SE_Blank: - break; - case SE_LimitResist: - if(base_value) { - if(spell.resist_type != base_value) - LimitFound = true; - } - break; - case SE_LimitInstant: - if(spell.buff_duration) - LimitFound = true; - break; - case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass() % 17) - 1]; - lvldiff = spell_level - base_value; - //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { - if(limit_value > 0) { - lvlModifier -= (limit_value * lvldiff); - if(lvlModifier < 1) - LimitFound = true; - } - else - LimitFound = true; - } - break; - case SE_LimitMinLevel: - if((spell.classes[(GetClass() % 17) - 1]) < base_value) - LimitFound = true; - break; - case SE_LimitCastTimeMin: - if (spell.cast_time < base_value) - LimitFound = true; - break; - case SE_LimitSpell: - if(base_value < 0) { - if (spell_id == (base_value*-1)) - LimitFound = true; - } else { - if (spell_id != base_value) - LimitFound = true; - } - break; - case SE_LimitMinDur: - if (base_value > CalcBuffDuration_formula(GetLevel(), spell.buff_duration_formula, spell.buff_duration)) - LimitFound = true; - break; - case SE_LimitEffect: - if(base_value < 0) { - if(IsEffectInSpell(spell_id,(base_value*-1))) - LimitFound = true; - } else { - if(!IsEffectInSpell(spell_id,base_value)) - LimitFound = true; - } - break; - case SE_LimitSpellType: - switch(base_value) { - case 0: - if (!IsDetrimentalSpell(spell_id)) - LimitFound = true; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) - LimitFound = true; - break; - } - break; - - case SE_LimitManaMin: - if(spell.mana < base_value) - LimitFound = true; - break; - case SE_LimitTarget: - if(base_value < 0) { - if(-base_value == spell.target_type) - LimitFound = true; - } else { - if(base_value != spell.target_type) - LimitFound = true; - } - break; - case SE_LimitCombatSkills: - if((base_value == 1 && !IsDiscipline(spell_id)) || (base_value == 0 && IsDiscipline(spell_id))) - LimitFound = true; - break; - case SE_LimitSpellGroup: - if((base_value > 0 && base_value != spell.spell_group) || (base_value < 0 && base_value == spell.spell_group)) - LimitFound = true; - break; - case SE_LimitCastingSkill: - LimitSpellSkill = true; - if(base_value == spell.skill) - SpellSkill_Found = true; - break; - case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(base_value, GetClass())) - LimitFound = true; - break; - //Handle Focus Effects - case SE_ImprovedDamage: - if (type == focusImprovedDamage && base_value > value) - value = base_value; - break; - case SE_ImprovedDamage2: - if (type == focusImprovedDamage2 && base_value > value) - value = base_value; - break; - case SE_ImprovedHeal: - if (type == focusImprovedHeal && base_value > value) - value = base_value; - break; - case SE_ReduceManaCost: - if (type == focusManaCost) - value = base_value; - break; - case SE_IncreaseSpellHaste: - if (type == focusSpellHaste && base_value > value) - value = base_value; - break; - case SE_IncreaseSpellDuration: - if (type == focusSpellDuration && base_value > value) - value = base_value; - break; - case SE_SpellDurationIncByTic: - if (type == focusSpellDurByTic && base_value > value) - value = base_value; - break; - case SE_SwarmPetDuration: - if (type == focusSwarmPetDuration && base_value > value) - value = base_value; - break; - case SE_IncreaseRange: - if (type == focusRange && base_value > value) - value = base_value; - break; - case SE_ReduceReagentCost: - if (type == focusReagentCost && base_value > value) - value = base_value; - break; - case SE_PetPowerIncrease: - if (type == focusPetPower && base_value > value) - value = base_value; - break; - case SE_SpellResistReduction: - if (type == focusResistRate && base_value > value) - value = base_value; - break; - case SE_SpellHateMod: - if (type == focusSpellHateMod) { - if(value != 0) { - if(value > 0) { - if(base_value > value) - value = base_value; - } else { - if(base_value < value) - value = base_value; - } - } - else - value = base_value; - } - break; - - case SE_ReduceReuseTimer: { - if(type == focusReduceRecastTime) - value = (base_value / 1000); - break; - } - case SE_TriggerOnCast: { - if(type == focusTriggerOnCast) { - if(zone->random.Int(0, 100) <= base_value) - value = limit_value; - else { - value = 0; - LimitFound = true; - } - } - break; - } - case SE_FcSpellVulnerability: { - if(type == focusSpellVulnerability) - value = base_value; - break; - } - case SE_BlockNextSpellFocus: { - if(type == focusBlockNextSpell) { - if(zone->random.Int(1, 100) <= base_value) - value = 1; - } - break; - } - case SE_FcTwincast: { - if(type == focusTwincast) - value = base_value; - break; - } - //case SE_SympatheticProc: - //{ - // if(type == focusSympatheticProc) - // { - // float ProcChance, ProcBonus; - // int16 ProcRateMod = base1; //Baseline is 100 for most Sympathetic foci - // int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); - // GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); - - // if(zone->random.Real(0, 1) <= ProcChance) - // value = focus_id; - - // else - // value = 0; - // } - // break; - //} - case SE_FcDamageAmt: { - if(type == focusFcDamageAmt) - value = base_value; - break; - } - case SE_FcDamageAmt2: { - if(type == focusFcDamageAmt2) - value = base_value; - break; - } - case SE_FcDamageAmtCrit: { - if(type == focusFcDamageAmtCrit) - value = base_value; - break; - } - case SE_FcDamageAmtIncoming: { - if(type == focusFcDamageAmtIncoming) - value = base_value; - break; - } - case SE_FcHealAmtIncoming: - if(type == focusFcHealAmtIncoming) - value = base_value; - break; - case SE_FcHealPctCritIncoming: - if (type == focusFcHealPctCritIncoming) - value = base_value; - break; - case SE_FcHealAmtCrit: - if(type == focusFcHealAmtCrit) - value = base_value; - break; - case SE_FcHealAmt: - if(type == focusFcHealAmt) - value = base_value; - break; - case SE_FcHealPctIncoming: - if(type == focusFcHealPctIncoming) - value = base_value; - break; - case SE_FcBaseEffects: { - if (type == focusFcBaseEffects) - value = base_value; - break; - } - case SE_FcDamagePctCrit: { - if(type == focusFcDamagePctCrit) - value = base_value; - break; - } - case SE_FcIncreaseNumHits: { - if(type == focusIncreaseNumHits) - value = base_value; - break; - } - - //Check for spell skill limits. - if ((LimitSpellSkill) && (!SpellSkill_Found)) - return 0; - } - } - - if (LimitFound) - return 0; - - return (value * lvlModifier / 100); -} - -int32 Bot::GetBotFocusEffect(focusType bottype, uint16 spell_id, bool from_buff_tic) { - if (IsBardSong(spell_id) && bottype != focusFcBaseEffects) - return 0; - - int32 realTotal = 0; - int32 realTotal2 = 0; - int32 realTotal3 = 0; - bool rand_effectiveness = false; - //Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages - //In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance - if(RuleB(Spells, LiveLikeFocusEffects) && (bottype == focusManaCost || bottype == focusImprovedHeal || bottype == focusImprovedDamage || bottype == focusImprovedDamage2 || bottype == focusResistRate)) - rand_effectiveness = true; - - //Check if item focus effect exists for the client. - if (itembonuses.FocusEffects[bottype]) { - const EQ::ItemData* TempItem = nullptr; - const EQ::ItemData* UsedItem = nullptr; - const EQ::ItemInstance* TempInst = nullptr; - uint16 UsedFocusID = 0; - int32 Total = 0; - int32 focus_max = 0; - int32 focus_max_real = 0; - //item focus - // are focus effects the same as bonus? (slotAmmo-excluded) - for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++) { - TempItem = nullptr; - EQ::ItemInstance* ins = GetBotItem(x); - if (!ins) - continue; - - TempItem = ins->GetItem(); - if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { - if(rand_effectiveness) { - focus_max = CalcBotFocusEffect(bottype, TempItem->Focus.Effect, spell_id, true); - if ((focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) || (focus_max < 0 && focus_max < focus_max_real)) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } - } else { - Total = CalcBotFocusEffect(bottype, TempItem->Focus.Effect, spell_id); - if ((Total > 0 && realTotal >= 0 && Total > realTotal) || (Total < 0 && Total < realTotal)) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } - } - } - - for (int y = EQ::invaug::SOCKET_BEGIN; y <= EQ::invaug::SOCKET_END; ++y) { - EQ::ItemInstance *aug = nullptr; - aug = ins->GetAugment(y); - if(aug) { - const EQ::ItemData* TempItemAug = aug->GetItem(); - if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { - if(rand_effectiveness) { - focus_max = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id, true); - if ((focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) || (focus_max < 0 && focus_max < focus_max_real)) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItemAug->Focus.Effect; - } - } else { - Total = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id); - if ((Total > 0 && realTotal >= 0 && Total > realTotal) || (Total < 0 && Total < realTotal)) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItemAug->Focus.Effect; - } - } - } - } - } - } - - if(UsedItem && rand_effectiveness && focus_max_real != 0) - realTotal = CalcBotFocusEffect(bottype, UsedFocusID, spell_id); - } - - //Check if spell focus effect exists for the client. - if (spellbonuses.FocusEffects[bottype]) { - //Spell Focus - int32 Total2 = 0; - int32 focus_max2 = 0; - int32 focus_max_real2 = 0; - int buff_tracker = -1; - int buff_slot = 0; - uint32 focusspellid = 0; - uint32 focusspell_tracker = 0; - uint32 buff_max = GetMaxTotalSlots(); - for (buff_slot = 0; buff_slot < buff_max; buff_slot++) { - focusspellid = buffs[buff_slot].spellid; - if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS) - continue; - - if(rand_effectiveness) { - focus_max2 = CalcBotFocusEffect(bottype, focusspellid, spell_id, true); - if ((focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) || (focus_max2 < 0 && focus_max2 < focus_max_real2)) { - focus_max_real2 = focus_max2; - buff_tracker = buff_slot; - focusspell_tracker = focusspellid; - } - } else { - Total2 = CalcBotFocusEffect(bottype, focusspellid, spell_id); - if ((Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) || (Total2 < 0 && Total2 < realTotal2)) { - realTotal2 = Total2; - buff_tracker = buff_slot; - focusspell_tracker = focusspellid; - } - } - } - - if(focusspell_tracker && rand_effectiveness && focus_max_real2 != 0) - realTotal2 = CalcBotFocusEffect(bottype, focusspell_tracker, spell_id); - - if (!from_buff_tic && buff_tracker >= 0 && buffs[buff_tracker].hit_number > 0) { - CheckNumHitsRemaining(NumHit::MatchingSpells, buff_tracker); - } - } - - // AA Focus - if (aabonuses.FocusEffects[bottype]) { - int32 Total3 = 0; - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - - for(auto &aa : aa_ranks) { - auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); - auto ability = ability_rank.first; - auto rank = ability_rank.second; - - if(!ability) { - continue; - } - - aa_AA = ability->id; - aa_value = aa.second.first; - if (aa_AA < 1 || aa_value < 1) - continue; - - Total3 = CalcBotAAFocus(bottype, aa_AA, aa_value, spell_id); - if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { - realTotal3 = Total3; - } - else if (Total3 < 0 && Total3 < realTotal3) { - realTotal3 = Total3; - } - } - } - - if(bottype == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) - return 100; - - if(bottype == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) - return 0; - - return (realTotal + realTotal2); -} - -int32 Bot::CalcBotFocusEffect(focusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus) { - if(!IsValidSpell(focus_id) || !IsValidSpell(spell_id)) - return 0; - - const SPDat_Spell_Struct &focus_spell = spells[focus_id]; - const SPDat_Spell_Struct &spell = spells[spell_id]; - int32 value = 0; - int lvlModifier = 100; - int spell_level = 0; - int lvldiff = 0; - bool LimitSpellSkill = false; - bool SpellSkill_Found = false; - for (int i = 0; i < EFFECT_COUNT; i++) { - switch (focus_spell.effect_id[i]) { - case SE_Blank: - break; - case SE_LimitResist:{ - if(focus_spell.base_value[i]) { - if(spell.resist_type != focus_spell.base_value[i]) - return 0; - } - break; - } - case SE_LimitInstant: { - if(spell.buff_duration) - return 0; - break; - } - case SE_LimitMaxLevel:{ - if (IsNPC()) - break; - spell_level = spell.classes[(GetClass() % 17) - 1]; - lvldiff = (spell_level - focus_spell.base_value[i]); - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { - if(focus_spell.limit_value[i] > 0) { - lvlModifier -= (focus_spell.limit_value[i] * lvldiff); - if(lvlModifier < 1) - return 0; - } - else - return 0; - } - break; - } - case SE_LimitMinLevel: - if (IsNPC()) - break; - if (spell.classes[(GetClass() % 17) - 1] < focus_spell.base_value[i]) - return 0; - break; - - case SE_LimitCastTimeMin: - if (spells[spell_id].cast_time < (uint32)focus_spell.base_value[i]) - return 0; - break; - case SE_LimitSpell: - if(focus_spell.base_value[i] < 0) { - if (spell_id == (focus_spell.base_value[i] * -1)) - return 0; - } else { - if (spell_id != focus_spell.base_value[i]) - return 0; - } - break; - case SE_LimitMinDur: - if (focus_spell.base_value[i] > CalcBuffDuration_formula(GetLevel(), spell.buff_duration_formula, spell.buff_duration)) - return 0; - break; - case SE_LimitEffect: - if(focus_spell.base_value[i] < 0) { - if(IsEffectInSpell(spell_id,focus_spell.base_value[i])) - return 0; - } else { - if(focus_spell.base_value[i] == SE_SummonPet) { - if(!IsEffectInSpell(spell_id, SE_SummonPet) && !IsEffectInSpell(spell_id, SE_NecPet) && !IsEffectInSpell(spell_id, SE_SummonBSTPet)) { - return 0; - } - } else if(!IsEffectInSpell(spell_id,focus_spell.base_value[i])) - return 0; - } - break; - - - case SE_LimitSpellType: - switch(focus_spell.base_value[i]) { - case 0: - if (!IsDetrimentalSpell(spell_id)) - return 0; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) - return 0; - break; - default: - LogInfo("CalcFocusEffect: unknown limit spelltype [{}]", focus_spell.base_value[i]); - } - break; - - case SE_LimitManaMin: - if(spell.mana < focus_spell.base_value[i]) - return 0; - break; - case SE_LimitTarget: - if((focus_spell.base_value[i] < 0) && -focus_spell.base_value[i] == spell.target_type) - return 0; - else if (focus_spell.base_value[i] > 0 && focus_spell.base_value[i] != spell.target_type) - return 0; - break; - case SE_LimitCombatSkills: - if(focus_spell.base_value[i] == 1 && !IsDiscipline(spell_id)) - return 0; - else if(focus_spell.base_value[i] == 0 && IsDiscipline(spell_id)) - return 0; - break; - case SE_LimitSpellGroup: - if(focus_spell.base_value[i] > 0 && focus_spell.base_value[i] != spell.spell_group) - return 0; - else if(focus_spell.base_value[i] < 0 && focus_spell.base_value[i] == spell.spell_group) - return 0; - break; - case SE_LimitCastingSkill: - LimitSpellSkill = true; - if(focus_spell.base_value[i] == spell.skill) - SpellSkill_Found = true; - break; - case SE_LimitClass: - if (!PassLimitClass(focus_spell.base_value[i], GetClass())) - return 0; - break; - case SE_ImprovedDamage: - if (bottype == focusImprovedDamage) { - if(best_focus) { - if (focus_spell.limit_value[i] != 0) - value = focus_spell.limit_value[i]; - else - value = focus_spell.base_value[i]; - } - else if (focus_spell.limit_value[i] == 0 || focus_spell.base_value[i] == focus_spell.limit_value[i]) - value = focus_spell.base_value[i]; - else - value = zone->random.Int(focus_spell.base_value[i], focus_spell.limit_value[i]); - } - break; - case SE_ImprovedDamage2: - if (bottype == focusImprovedDamage2) { - if(best_focus) { - if (focus_spell.limit_value[i] != 0) - value = focus_spell.limit_value[i]; - else - value = focus_spell.base_value[i]; - } - else if (focus_spell.limit_value[i] == 0 || focus_spell.base_value[i] == focus_spell.limit_value[i]) - value = focus_spell.base_value[i]; - else - value = zone->random.Int(focus_spell.base_value[i], focus_spell.limit_value[i]); - } - break; - case SE_ImprovedHeal: - if (bottype == focusImprovedHeal) { - if(best_focus) { - if (focus_spell.limit_value[i] != 0) - value = focus_spell.limit_value[i]; - else - value = focus_spell.base_value[i]; - } - else if (focus_spell.limit_value[i] == 0 || focus_spell.base_value[i] == focus_spell.limit_value[i]) - value = focus_spell.base_value[i]; - else - value = zone->random.Int(focus_spell.base_value[i], focus_spell.limit_value[i]); - } - break; - case SE_ReduceManaCost: - if (bottype == focusManaCost) { - if(best_focus) { - if (focus_spell.limit_value[i] != 0) - value = focus_spell.limit_value[i]; - else - value = focus_spell.base_value[i]; - } - else if (focus_spell.limit_value[i] == 0 || focus_spell.base_value[i] == focus_spell.limit_value[i]) - value = focus_spell.base_value[i]; - else - value = zone->random.Int(focus_spell.base_value[i], focus_spell.limit_value[i]); - } - break; - case SE_IncreaseSpellHaste: - if (bottype == focusSpellHaste && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_IncreaseSpellDuration: - if (bottype == focusSpellDuration && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_SpellDurationIncByTic: - if (bottype == focusSpellDurByTic && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_SwarmPetDuration: - if (bottype == focusSwarmPetDuration && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_IncreaseRange: - if (bottype == focusRange && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_ReduceReagentCost: - if (bottype == focusReagentCost && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_PetPowerIncrease: - if (bottype == focusPetPower && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_SpellResistReduction: - if (bottype == focusResistRate && focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - break; - case SE_SpellHateMod: - if (bottype == focusSpellHateMod) { - if(value != 0) { - if(value > 0) { - if(focus_spell.base_value[i] > value) - value = focus_spell.base_value[i]; - } - else { - if(focus_spell.base_value[i] < value) - value = focus_spell.base_value[i]; - } - } else - value = focus_spell.base_value[i]; - } - break; - case SE_ReduceReuseTimer: { - if(bottype == focusReduceRecastTime) - value = (focus_spell.base_value[i] / 1000); - break; - } - case SE_TriggerOnCast: { - if(bottype == focusTriggerOnCast) { - if(zone->random.Int(0, 100) <= focus_spell.base_value[i]) - value = focus_spell.limit_value[i]; - else - value = 0; - } - break; - } - case SE_FcSpellVulnerability: { - if(bottype == focusSpellVulnerability) - value = focus_spell.base_value[i]; - break; - } - case SE_BlockNextSpellFocus: { - if(bottype == focusBlockNextSpell) { - if(zone->random.Int(1, 100) <= focus_spell.base_value[i]) - value = 1; - } - break; - } - case SE_FcTwincast: { - if(bottype == focusTwincast) - value = focus_spell.base_value[i]; - break; - } - case SE_SympatheticProc: { - if(bottype == focusSympatheticProc) { - float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base_value[i]); - if(zone->random.Real(0, 1) <= ProcChance) - value = focus_id; - else - value = 0; - } - break; - } - case SE_FcDamageAmt: { - if(bottype == focusFcDamageAmt) - value = focus_spell.base_value[i]; - break; - } - case SE_FcDamageAmt2: { - if(bottype == focusFcDamageAmt2) - value = focus_spell.base_value[i]; - break; - } - case SE_FcDamageAmtCrit: { - if(bottype == focusFcDamageAmtCrit) - value = focus_spell.base_value[i]; - break; - } - case SE_FcHealAmtIncoming: - if(bottype == focusFcHealAmtIncoming) - value = focus_spell.base_value[i]; - break; - case SE_FcHealPctCritIncoming: - if (bottype == focusFcHealPctCritIncoming) - value = focus_spell.base_value[i]; - break; - case SE_FcHealAmtCrit: - if(bottype == focusFcHealAmtCrit) - value = focus_spell.base_value[i]; - break; - case SE_FcHealAmt: - if(bottype == focusFcHealAmt) - value = focus_spell.base_value[i]; - break; - case SE_FcHealPctIncoming: - if(bottype == focusFcHealPctIncoming) - value = focus_spell.base_value[i]; - break; - case SE_FcBaseEffects: { - if (bottype == focusFcBaseEffects) - value = focus_spell.base_value[i]; - - break; - } - case SE_FcDamagePctCrit: { - if(bottype == focusFcDamagePctCrit) - value = focus_spell.base_value[i]; - - break; - } - case SE_FcIncreaseNumHits: { - if(bottype == focusIncreaseNumHits) - value = focus_spell.base_value[i]; - - break; - } - default: - LogSpells("CalcFocusEffect: unknown effectid [{}]", focus_spell.effect_id[i]); - break; - } - } - //Check for spell skill limits. - if ((LimitSpellSkill) && (!SpellSkill_Found)) - return 0; - - return(value * lvlModifier / 100); -} - //proc chance includes proc bonus float Bot::GetProcChances(float ProcBonus, uint16 hand) { int mydex = GetDEX(); @@ -6063,13 +5399,13 @@ bool Bot::TryFinishingBlow(Mob *defender, int64 &damage) int fb_damage = aabonuses.FinishingBlow[1]; int levelreq = aabonuses.FinishingBlowLvl[0]; if (defender->GetLevel() <= levelreq && (chance >= zone->random.Int(1, 1000))) { - LogCombat("Landed a finishing blow: levelreq at [{}], other level [{}]", + LogCombat("Landed a finishing blow: levelreq at [{}] other level [{}]", levelreq, defender->GetLevel()); entity_list.MessageCloseString(this, false, 200, Chat::MeleeCrit, FINISHING_BLOW, GetName()); damage = fb_damage; return true; } else { - LogCombat("failed a finishing blow: levelreq at [{}], other level [{}]", + LogCombat("failed a finishing blow: levelreq at [{}] other level [{}]", levelreq, defender->GetLevel()); return false; } @@ -6078,14 +5414,14 @@ bool Bot::TryFinishingBlow(Mob *defender, int64 &damage) } void Bot::DoRiposte(Mob* defender) { - LogCombat("Preforming a riposte"); + LogCombatDetail("Preforming a riposte"); if (!defender) return; defender->Attack(this, EQ::invslot::slotPrimary, true); int32 DoubleRipChance = (defender->GetAABonuses().GiveDoubleRiposte[0] + defender->GetSpellBonuses().GiveDoubleRiposte[0] + defender->GetItemBonuses().GiveDoubleRiposte[0]); if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { - LogCombat("Preforming a double riposte ([{}] percent chance)", DoubleRipChance); + LogCombatDetail("Preforming a double riposte ([{}] percent chance)", DoubleRipChance); defender->Attack(this, EQ::invslot::slotPrimary, true); } @@ -6359,9 +5695,9 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { return; } - if(ka_time){ + if (ka_time) { - switch(GetClass()){ + switch (GetClass()) { case SHADOWKNIGHT: { CastSpell(SPELL_NPC_HARM_TOUCH, target->GetID()); knightattack_timer.Start(HarmTouchReuseTime * 1000); @@ -6387,7 +5723,13 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(taunting && target && target->IsNPC() && taunt_time) { if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { - BotGroupSay(this, "Taunting %s", target->GetCleanName()); + BotGroupSay( + this, + fmt::format( + "Taunting {}.", + target->GetCleanName() + ).c_str() + ); Taunt(target->CastToNPC(), false); taunt_timer.Start(TauntReuseTime * 1000); } @@ -6459,9 +5801,9 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { int level = GetLevel(); int reuse = (TauntReuseTime * 1000); bool did_attack = false; - switch(GetClass()) { + switch (GetClass()) { case WARRIOR: - if(level >= RuleI(Combat, NPCBashKickLevel)){ + if (level >= RuleI(Combat, NPCBashKickLevel)) { bool canBash = false; if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQ::invslot::slotSecondary) && m_inv.GetItem(EQ::invslot::slotSecondary)->GetItem()->ItemType == EQ::item::ItemTypeShield) || (m_inv.GetItem(EQ::invslot::slotPrimary) && m_inv.GetItem(EQ::invslot::slotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) canBash = true; @@ -6481,7 +5823,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case CLERIC: case SHADOWKNIGHT: case PALADIN: - if(level >= RuleI(Combat, NPCBashKickLevel)){ + if (level >= RuleI(Combat, NPCBashKickLevel)) { if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQ::invslot::slotSecondary) && m_inv.GetItem(EQ::invslot::slotSecondary)->GetItem()->ItemType == EQ::item::ItemTypeShield) || (m_inv.GetItem(EQ::invslot::slotPrimary) && m_inv.GetItem(EQ::invslot::slotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) skill_to_use = EQ::skills::SkillBash; } @@ -6618,20 +5960,6 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { classattack_timer.Start(reuse / HasteModifier); } -int32 Bot::CheckAggroAmount(uint16 spellid) { - int32 AggroAmount = Mob::CheckAggroAmount(spellid, nullptr); - int32 focusAggro = GetBotFocusEffect(focusSpellHateMod, spellid); - AggroAmount = (AggroAmount * (100 + focusAggro) / 100); - return AggroAmount; -} - -int32 Bot::CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible) { - int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, target, heal_possible); - int32 focusAggro = GetBotFocusEffect(focusSpellHateMod, spellid); - AggroAmount = (AggroAmount * (100 + focusAggro) / 100); - return AggroAmount; -} - void Bot::MakePet(uint16 spell_id, const char* pettype, const char *petname) { Mob::MakePet(spell_id, pettype, petname); } @@ -6730,11 +6058,14 @@ void Bot::EquipBot(std::string* error_message) { UpdateEquipmentLight(); } -void Bot::BotOrderCampAll(Client* c) { - if(c) { - std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) - (*botListItr)->Camp(); +void Bot::BotOrderCampAll(Client* c, uint8 class_id) { + if (c) { + const auto& l = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); + for (const auto& b : l) { + if (!class_id || b->GetClass() == class_id) { + b->Camp(); + } + } } } @@ -6755,65 +6086,6 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) { } } -void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { - if(guildOfficer && botToGuild) { - if(!botToGuild->IsInAGuild()) { - if (!guild_mgr.CheckPermission(guildOfficer->GuildID(), guildOfficer->GuildRank(), GUILD_INVITE)) { - guildOfficer->Message(Chat::Red, "You dont have permission to invite."); - return; - } - - if (!database.botdb.SaveGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER)) { - guildOfficer->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveGuildMembership(), botToGuild->GetCleanName()); - return; - } - - ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct)); - ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer; - s->guild_id = guildOfficer->GuildID(); - s->old_guild_id = GUILD_NONE; - s->char_id = botToGuild->GetBotID(); - worldserver.SendPacket(pack); - - safe_delete(pack); - } else { - guildOfficer->Message(Chat::Red, "Bot is in a guild."); - return; - } - } -} - -bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) { - bool Result = false; - if(guildOfficer && !botName.empty()) { - Bot* botToUnGuild = entity_list.GetBotByBotName(botName); - if(botToUnGuild) { - if (database.botdb.SaveGuildMembership(botToUnGuild->GetBotID(), 0, 0)) - Result = true; - } else { - uint32 ownerId = 0; - if (!database.botdb.LoadOwnerID(botName, ownerId)) - guildOfficer->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadOwnerID(), botName.c_str()); - uint32 botId = 0; - if (!database.botdb.LoadBotID(ownerId, botName, botId)) - guildOfficer->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotID(), botName.c_str()); - if (botId && database.botdb.SaveGuildMembership(botId, 0, 0)) - Result = true; - } - - if(Result) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildManageRemove, sizeof(GuildManageRemove_Struct)); - GuildManageRemove_Struct* gm = (GuildManageRemove_Struct*) outapp->pBuffer; - gm->guildeqid = guildOfficer->GuildID(); - strcpy(gm->member, botName.c_str()); - guildOfficer->Message(Chat::White, "%s successfully removed from your guild.", botName.c_str()); - entity_list.QueueClientsGuild(guildOfficer, outapp, false, gm->guildeqid); - safe_delete(outapp); - } - } - return Result; -} - int64 Bot::CalcMaxMana() { switch(GetCasterClass()) { case 'I': @@ -6896,390 +6168,11 @@ void Bot::SetAttackTimer() { } } -int64 Bot::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { - if (spells[spell_id].target_type == ST_Self) - return value; - - bool Critical = false; - int32 base_value = value; - int chance = 0; - - // Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40. - if ((spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40) - value -= (GetLevel() - 40) * 20; - - //This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch. - if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm Touch - value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch - - chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level) - chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance; - chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation; - - //Crtical Hit Calculation pathway - if (chance > 0 || (GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) { - - int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals. - - //Improved Harm Touch is a guaranteed crit if you have at least one level of SCF. - if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) - chance = 100; - - if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance) - chance = spells[spell_id].override_crit_chance; - - if (zone->random.Roll(chance)) { - Critical = true; - ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease; - ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack; - } - - else if (GetClass() == WIZARD || (IsMerc() && GetClass() == CASTERDPS)) { - if ((GetLevel() >= RuleI(Spells, WizCritLevel)) && zone->random.Roll(RuleI(Spells, WizCritChance))){ - //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed) - ratio += zone->random.Int(20,70); - Critical = true; - } - } - - if (GetClass() == WIZARD) - ratio += RuleI(Spells, WizCritRatio); //Default is zero - - if (Critical) { - - value = base_value*ratio/100; - - value += base_value*GetBotFocusEffect(focusImprovedDamage, spell_id)/100; - value += base_value*GetBotFocusEffect(focusImprovedDamage2, spell_id)/100; - - value += int(base_value*GetBotFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100; - value += int(base_value*GetBotFocusEffect(focusFcAmplifyMod, spell_id) / 100)*ratio / 100; - - if (target) { - value += int(base_value*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; - value -= target->GetFcDamageAmtIncoming(this, spell_id); - } - - value -= GetBotFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100; - - value -= GetBotFocusEffect(focusFcDamageAmt, spell_id); - value -= GetBotFocusEffect(focusFcDamageAmt2, spell_id); - value -= GetBotFocusEffect(focusFcAmplifyAmt, spell_id); - - if ((RuleB(Spells, IgnoreSpellDmgLvlRestriction) || spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) - value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value) * ratio / 100; - - entity_list.MessageCloseString( - this, true, 100, Chat::SpellCrit, - OTHER_CRIT_BLAST, GetName(), itoa(-value)); - - return value; - } - } - //Non Crtical Hit Calculation pathway - value = base_value; - - value += base_value*GetBotFocusEffect(focusImprovedDamage, spell_id)/100; - value += base_value*GetBotFocusEffect(focusImprovedDamage2, spell_id)/100; - - value += base_value*GetBotFocusEffect(focusFcDamagePctCrit, spell_id)/100; - value += base_value*GetBotFocusEffect(focusFcAmplifyMod, spell_id)/100; - - if (target) { - value += base_value*target->GetVulnerability(this, spell_id, 0)/100; - value -= target->GetFcDamageAmtIncoming(this, spell_id); - } - - value -= GetBotFocusEffect(focusFcDamageAmtCrit, spell_id); - value -= GetBotFocusEffect(focusFcDamageAmt, spell_id); - value -= GetBotFocusEffect(focusFcDamageAmt2, spell_id); - value -= GetBotFocusEffect(focusFcAmplifyAmt, spell_id); - - if ((RuleB(Spells, IgnoreSpellDmgLvlRestriction) || spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) - value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value); - - return value; -} - -int64 Bot::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target) { - if (target == nullptr) - target = this; - - int32 base_value = value; - int16 critical_chance = 0; - int8 critical_modifier = 1; - - if (spells[spell_id].buff_duration < 1) { - critical_chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance; - - if (spellbonuses.CriticalHealDecay) { - critical_chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - } - } - else { - critical_chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime; - - if (spellbonuses.CriticalRegenDecay) { - critical_chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); - } - } - - if (critical_chance) { - - if (spells[spell_id].override_crit_chance > 0 && critical_chance > spells[spell_id].override_crit_chance) { - critical_chance = spells[spell_id].override_crit_chance; - } - - if (zone->random.Roll(critical_chance)) { - critical_modifier = 2; //At present time no critical heal amount modifier SPA exists. - } - } - - if (GetClass() == CLERIC) { - value += int(base_value*RuleI(Spells, ClericInnateHealFocus) / 100); //confirmed on live parsing clerics get an innate 5 pct heal focus - } - value += int(base_value*GetBotFocusEffect(focusImprovedHeal, spell_id) / 100); - value += int(base_value*GetBotFocusEffect(focusFcAmplifyMod, spell_id) / 100); - - // Instant Heals - if (spells[spell_id].buff_duration < 1) { - - /* Mob::GetFocusEffect is not accessible from this context. This focus effect was not accounted for in previous version of this method at all, either - if (target) { - value += int(base_value * target->GetFocusEffect(focusFcHealPctIncoming, spell_id, this)/100,nullptr); //SPA 393 Add before critical - value += int(base_value * target->GetFocusEffect(focusFcHealPctCritIncoming, spell_id, this)/100,nullptr); //SPA 395 Add before critical (?) - } - */ - - value += GetBotFocusEffect(focusFcHealAmtCrit, spell_id); //SPA 396 Add before critical - - //Using IgnoreSpellDmgLvlRestriction to also allow healing to scale - if ((RuleB(Spells, IgnoreSpellDmgLvlRestriction) || spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt) { - value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, base_value);//Item Heal Amt Add before critical - } - - if (target) { - value += value * target->GetHealRate() / 100; //SPA 120 modifies value after Focus Applied but before critical - } - - /* - Apply critical hit modifier - */ - - value *= critical_modifier; - value += GetBotFocusEffect(focusFcHealAmt, spell_id); //SPA 392 Add after critical - value += GetBotFocusEffect(focusFcAmplifyAmt, spell_id); //SPA 508 ? Add after critical - - /* - if (target) { - value += target->GetBotFocusEffect(focusFcHealAmtIncoming, spell_id, this); //SPA 394 Add after critical - } - */ - - if (critical_modifier > 1) { - entity_list.MessageCloseString( - this, true, 100, Chat::SpellCrit, - OTHER_CRIT_HEAL, GetName(), itoa(value)); - } - - return value; - } - - //Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value] - else { - //Using IgnoreSpellDmgLvlRestriction to also allow healing to scale - if (RuleB(Spells, HOTsScaleWithHealAmt)) { - int duration = CalcBuffDuration(this, target, spell_id); - int32 extra_heal = 0; - if ((RuleB(Spells, IgnoreSpellDmgLvlRestriction) || spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt) { - extra_heal += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, base_value); - } - - if (duration > 0 && extra_heal > 0) { - extra_heal /= duration; - value += extra_heal; - } - } - - if (critical_chance && zone->random.Roll(critical_chance)) - value *= critical_modifier; - } - - return value; -} - -int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) { - int32 cast_reducer = GetBotFocusEffect(focusSpellHaste, spell_id); - auto min_cap = casttime / 2; - uint8 botlevel = GetLevel(); - uint8 botclass = GetClass(); - if (botlevel >= 51 && casttime >= 3000 && !spells[spell_id].good_effect && - (botclass == SHADOWKNIGHT || botclass == RANGER || botclass == PALADIN || botclass == BEASTLORD)) { - int level_mod = std::min(15, botlevel - 50); - cast_reducer += level_mod * 3; - } - - if((casttime >= 4000) && BeneficialSpell(spell_id) && IsBuffSpell(spell_id)) { - switch (GetAA(aaSpellCastingDeftness)) { - case 1: - cast_reducer += 5; - break; - case 2: - cast_reducer += 10; - break; - case 3: - cast_reducer += 25; - break; - } - - switch (GetAA(aaQuickBuff)) { - case 1: - cast_reducer += 10; - break; - case 2: - cast_reducer += 25; - break; - case 3: - cast_reducer += 50; - break; - } - } - - if(IsSummonSpell(spell_id)) { - switch (GetAA(aaQuickSummoning)) { - case 1: - cast_reducer += 10; - break; - case 2: - cast_reducer += 25; - break; - case 3: - cast_reducer += 50; - break; - } - } - - if(IsEvacSpell(spell_id)) { - switch (GetAA(aaQuickEvacuation)) { - case 1: - cast_reducer += 10; - break; - case 2: - cast_reducer += 25; - break; - case 3: - cast_reducer += 50; - break; - } - } - - if(IsDamageSpell(spell_id) && spells[spell_id].cast_time >= 4000) { - switch (GetAA(aaQuickDamage)) { - case 1: - cast_reducer += 2; - break; - case 2: - cast_reducer += 5; - break; - case 3: - cast_reducer += 10; - break; - } - } - - casttime = casttime * (100 - cast_reducer) / 100; - return std::max(casttime, min_cap); -} - -int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { - if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { - int32 mana_back = (itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100); - if(mana_back > cost) - mana_back = cost; - - cost -= mana_back; - } - - float PercentManaReduction = 0; - float SpecializeSkill = GetSpecializeSkillValue(spell_id); - int SuccessChance = zone->random.Int(0, 100); - float bonus = 1.0; - switch(GetAA(aaSpellCastingMastery)) { - case 1: - bonus += 0.05; - break; - case 2: - bonus += 0.15; - break; - case 3: - bonus += 0.30; - break; - } - - bonus += (0.05 * GetAA(aaAdvancedSpellCastingMastery)); - - if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) { - PercentManaReduction = (1 + 0.05 * SpecializeSkill); - switch(GetAA(aaSpellCastingMastery)) { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; - } - - switch(GetAA(aaAdvancedSpellCastingMastery)) { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; - } - } - - int32 focus_redux = GetBotFocusEffect(focusManaCost, spell_id); - - if(focus_redux > 0) - PercentManaReduction += zone->random.Real(1, (double)focus_redux); - - cost -= (cost * (PercentManaReduction / 100)); - if(focus_redux >= 100) { - uint32 buff_max = GetMaxTotalSlots(); - for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) { - if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS) - continue; - - if(IsEffectInSpell(buffs[buffSlot].spellid, SE_ReduceManaCost)) { - if(CalcFocusEffect(focusManaCost, buffs[buffSlot].spellid, spell_id) == 100) - cost = 1; - } - } - } - - if(cost < 0) - cost = 0; - - return cost; -} - -float Bot::GetActSpellRange(uint16 spell_id, float range) { - float extrange = 100; - extrange += GetBotFocusEffect(focusRange, spell_id); - return ((range * extrange) / 100); -} - int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { int increase = 100; - increase += GetBotFocusEffect(focusSpellDuration, spell_id); - int tic_inc = 0; tic_inc = GetBotFocusEffect(focusSpellDurByTic, spell_id); + increase += GetFocusEffect(focusSpellDuration, spell_id); + int64 tic_inc = 0; + tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id); if(IsBeneficialSpell(spell_id)) { switch (GetAA(aaSpellCastingReinforcement)) { @@ -7345,58 +6238,83 @@ void Bot::DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster) { Mob::DoBuffTic(buff, slot, caster); } -bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot, int32 cast_time, int32 mana_cost, - uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust, uint32 aa_id) { +bool Bot::CastSpell( + uint16 spell_id, + uint16 target_id, + EQ::spells::CastingSlot slot, + int32 cast_time, + int32 mana_cost, + uint32* oSpellWillFinish, + uint32 item_slot, + int16 *resist_adjust, + uint32 aa_id +) { bool Result = false; - if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { + if (zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { // LogSpells("CastSpell called for spell [{}] ([{}]) on entity [{}], slot [{}], time [{}], mana [{}], from item slot [{}]", spells[spell_id].name, spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot); - if(casting_spell_id == spell_id) + if (casting_spell_id == spell_id) { ZeroCastingVars(); + } - if(GetClass() != BARD) { - if(!IsValidSpell(spell_id) || casting_spell_id || delaytimer || spellend_timer.Enabled() || IsStunned() || IsFeared() || IsMezzed() || (IsSilenced() && !IsDiscipline(spell_id)) || (IsAmnesiad() && IsDiscipline(spell_id))) { - LogSpells("Spell casting canceled: not able to cast now. Valid? [{}], casting [{}], waiting? [{}], spellend? [{}], stunned? [{}], feared? [{}], mezed? [{}], silenced? [{}]", IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() ); - if(IsSilenced() && !IsDiscipline(spell_id)) - MessageString(Chat::Red, SILENCED_STRING); + if (GetClass() != BARD) { + if ( + !IsValidSpell(spell_id) || + casting_spell_id || + delaytimer || + spellend_timer.Enabled() || + IsStunned() || + IsFeared() || + IsMezzed() || + (IsSilenced() && !IsDiscipline(spell_id)) || + (IsAmnesiad() && IsDiscipline(spell_id)) + ) { + LogSpellsDetail("Spell casting canceled: not able to cast now. Valid? [{}] casting [{}] waiting? [{}] spellend? [{}] stunned? [{}] feared? [{}] mezed? [{}] silenced? [{}]", + IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() + ); + if (IsSilenced() && !IsDiscipline(spell_id)) { + MessageString(Chat::White, SILENCED_STRING); + } - if(IsAmnesiad() && IsDiscipline(spell_id)) + if (IsAmnesiad() && IsDiscipline(spell_id)) { + MessageString(Chat::White, MELEE_SILENCE); + } - MessageString(Chat::Red, MELEE_SILENCE); - - if(casting_spell_id) - AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); + if (casting_spell_id) { + AI_Bot_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); + } return false; } } - if(IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()){ - MessageString(Chat::Red, SPELL_WOULDNT_HOLD); - if(casting_spell_id) - AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); + if (IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()) { + MessageString(Chat::White, SPELL_WOULDNT_HOLD); + if (casting_spell_id) { + AI_Bot_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); + } return false; } - if(DivineAura()) { - LogSpells("Spell casting canceled: cannot cast while Divine Aura is in effect"); + if (DivineAura()) { + LogSpellsDetail("Spell casting canceled: cannot cast while Divine Aura is in effect"); InterruptSpell(173, 0x121, false); return false; } - if(slot < EQ::spells::CastingSlot::MaxGems && !CheckFizzle(spell_id)) { + if (slot < EQ::spells::CastingSlot::MaxGems && !CheckFizzle(spell_id)) { int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; InterruptSpell(fizzle_msg, 0x121, spell_id); uint32 use_mana = ((spells[spell_id].mana) / 4); - LogSpells("Spell casting canceled: fizzled. [{}] mana has been consumed", use_mana); + LogSpellsDetail("Spell casting canceled: fizzled. [{}] mana has been consumed", use_mana); SetMana(GetMana() - use_mana); return false; } if (HasActiveSong()) { - LogSpells("Casting a new spell/song while singing a song. Killing old song [{}]", bardsong); + LogSpellsDetail("Casting a new spell/song while singing a song. Killing old song [{}]", bardsong); bardsong = 0; bardsong_target_id = 0; bardsong_slot = EQ::spells::CastingSlot::Gem1; @@ -7410,94 +6328,31 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot s } bool Bot::SpellOnTarget(uint16 spell_id, Mob* spelltar) { - bool Result = false; - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) { return false; - - if(spelltar) { - if(spelltar->IsBot() && (spells[spell_id].target_type == ST_GroupTeleport)) { - switch(spell_id) { - // Paladin - case 3577: // Wave of Life - case 4065: // Blessing of Austerity - case 1455: // Wave of Healing - case 2589: // Healing Wave of Prexus - case 3427: // Wave of Marr - case 3683: // Ethereal Cleansing - case 1283: // Celestial Cleansing - case 3485: // Supernal Cleansing - case 5293: // Pious Cleansing - case 4893: // Wave of Trushar - case 5295: // Jeron's Mark - case 5296: // Wave of Piety - // Bard - case 4085: // Forpar's Aria of Affliction - case 4083: // Rizlona's Embers - case 4086: // Forpar's Psalm of Pain - case 4084: // Rizlona's Fire - case 6734: // Song of the Storm - case 3651: // Wind of Marr - case 4087: // Forpar's Verse of Venom - case 3362: // Rizlona's Call of Flame - case 4112: // Call of the Muse - case 4872: // Echo of the Trusik - case 4873: // Dark Echo - case 5377: // Cantata of Life - case 5380: // Yelhun's Mystic Call - case 5382: // Eriki's Psalm of Power - case 6666: // Storm Blade - case 5388: // Ancient Call of Power - // Cleric - case 134: // Word of Health - case 136: // Word of Healing - case 1520: // Word of Vigor - case 1521: // Word of Restoration - case 1523: // Word of Redemption - case 3471: // Word of Replenishment - case 5270: // Word of Vivification - case 2502: // Celestial Remedy - case 2175: // Celestial Health - case 1444: // Celestial Healing - case 1522: // Celestial Elixir - case 2180: // Etherial Elixir - case 3047: // Kazad's Mark - case 3475: // Supernal Elixir - case 4053: // Blessing of Temperance - case 4108: // Aura of Reverence - case 4882: // Holy Elixir - case 5259: // Pious Elixir - case 5272: // Aura of Devotion - case 5277: // Balikor's Mark - // Enchanter - case 5517: // Circle of Alendar - case 6671: // Rune of Rikkukin - case 6739: // Rune of the Scale - // Shaman - case 2521: // Talisman of the Beast - case 4055: // Pack Shrew - case 3842: // Blood of Nadox - case 5417: // Champion - // Druid - case 4058: // Feral Pack - case 2520: // Natures Recovery - break; - default: - return false; - } - } - - if(((IsDetrimentalSpell(spell_id) && spelltar->IsBot()) || (IsDetrimentalSpell(spell_id) && spelltar->IsClient())) && !IsResurrectionEffects(spell_id)) - return false; - - if(spelltar->IsPet()) { - for(int i= 0; i < EFFECT_COUNT; ++i) { - if(spells[spell_id].effect_id[i] == SE_Illusion) - return false; - } - } - Result = Mob::SpellOnTarget(spell_id, spelltar); } - return Result; + + if (spelltar) { + if ( + IsDetrimentalSpell(spell_id) && + (spelltar->IsBot() || spelltar->IsClient()) && + !IsResurrectionEffects(spell_id) + ) { + return false; + } + + if (spelltar->IsPet()) { + for (int i = 0; i < EFFECT_COUNT; ++i) { + if (spells[spell_id].effect_id[i] == SE_Illusion) { + return false; + } + } + } + + return Mob::SpellOnTarget(spell_id, spelltar); + } + + return false; } bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { @@ -7511,19 +6366,19 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { if(caster->IsBot()) { if(spells[spell_id].target_type == ST_Undead) { if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Undead) && (GetBodyType() != BT_Vampire)) { - LogSpells("Bot's target is not an undead"); + LogSpellsDetail("Bot's target is not an undead"); return true; } } if(spells[spell_id].target_type == ST_Summoned) { if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Summoned) && (GetBodyType() != BT_Summoned2) && (GetBodyType() != BT_Summoned3)) { - LogSpells("Bot's target is not a summoned creature"); + LogSpellsDetail("Bot's target is not a summoned creature"); return true; } } } - LogSpells("No bot immunities to spell [{}] found", spell_id); + LogSpellsDetail("No bot immunities to spell [{}] found", spell_id); } } @@ -7662,7 +6517,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spe if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, GroupBuffing)) { bool noGroupSpell = false; uint16 thespell = spell_id; - for(int i = 0; i < AIspells.size(); i++) { + for (int i = 0; i < AIBot_spells.size(); i++) { int j = BotGetSpells(i); int spelltype = BotGetSpellType(i); bool spellequal = (j == thespell); @@ -7674,7 +6529,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spe if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { if(((spells[thespell].effect_id[0] == 0) && (spells[thespell].base_value[0] < 0)) && (spellTarget->GetHP() < ((spells[thespell].base_value[0] * (-1)) + 100))) { - LogSpells("Bot::DoFinishedSpellSingleTarget - GroupBuffing failure"); + LogSpells("GroupBuffing failure"); return false; } @@ -7711,7 +6566,13 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spe bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) { bool isMainGroupMGB = false; if(isMainGroupMGB && (GetClass() != BARD)) { - BotGroupSay(this, "MGB %s", spells[spell_id].name); + BotGroupSay( + this, + fmt::format( + "Casting {} as a Mass Group Buff.", + spells[spell_id].name + ).c_str() + ); SpellOnTarget(spell_id, this); entity_list.AESpell(this, this, spell_id, true); } else { @@ -7762,7 +6623,7 @@ void Bot::CalcBonuses() { end_regen = CalcEnduranceRegen(); } -int64 Bot::CalcHPRegenCap(){ +int64 Bot::CalcHPRegenCap() { int level = GetLevel(); int64 hpregen_cap = 0; hpregen_cap = (RuleI(Character, ItemHealthRegenCap) + itembonuses.HeroicSTA / 25); @@ -7770,7 +6631,7 @@ int64 Bot::CalcHPRegenCap(){ return (hpregen_cap * RuleI(Character, HPRegenMultiplier) / 100); } -int64 Bot::CalcManaRegenCap(){ +int64 Bot::CalcManaRegenCap() { int64 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap; switch(GetCasterClass()) { case 'I': @@ -8113,9 +6974,9 @@ void Bot::CalcRestState() { } } - RestRegenHP = 6 * (GetMaxHP() / zone->newzone_data.FastRegenHP); - RestRegenMana = 6 * (GetMaxMana() / zone->newzone_data.FastRegenMana); - RestRegenEndurance = 6 * (GetMaxEndurance() / zone->newzone_data.FastRegenEndurance); + RestRegenHP = 6 * (GetMaxHP() / zone->newzone_data.fast_regen_hp); + RestRegenMana = 6 * (GetMaxMana() / zone->newzone_data.fast_regen_mana); + RestRegenEndurance = 6 * (GetMaxEndurance() / zone->newzone_data.fast_regen_endurance); } int32 Bot::LevelRegen() { @@ -8207,7 +7068,7 @@ int64 Bot::CalcManaRegen() { uint64 Bot::GetClassHPFactor() { uint32 factor; - switch(GetClass()) { + switch (GetClass()) { case BEASTLORD: case BERSERKER: case MONK: @@ -8379,21 +7240,18 @@ void Bot::DoEnduranceUpkeep() { SetEndurance(GetEndurance() - upkeep_sum); } -void Bot::Camp(bool databaseSave) { +void Bot::Camp(bool save_to_database) { Sit(); - //auto group = GetGroup(); - if(GetGroup()) + if (GetGroup()) { RemoveBotFromGroup(this, GetGroup()); - - // RemoveBotFromGroup() code is too complicated for this to work as-is (still needs to be addressed to prevent memory leaks) - //if (group->GroupCount() < 2) - // group->DisbandGroup(); + } LeaveHealRotationMemberPool(); - if(databaseSave) + if (save_to_database) { Save(); + } Depop(); } @@ -8726,6 +7584,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { strcpy(insr->text, inspectedBot->GetInspectMessage().text); client->QueuePacket(outapp); // Send answer to requester + safe_delete(outapp); } } @@ -9029,7 +7888,7 @@ void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool } } - if (item->SkillModValue != 0 && item->SkillModType <= EQ::skills::HIGHEST_SKILL){ + if (item->SkillModValue != 0 && item->SkillModType <= EQ::skills::HIGHEST_SKILL) { if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { @@ -9118,12 +7977,10 @@ void Bot::CalcBotStats(bool showtext) { //if(Save()) // GetBotOwner()->CastToClient()->Message(Chat::White, "%s saved.", GetCleanName()); //else - // GetBotOwner()->CastToClient()->Message(Chat::Red, "%s save failed!", GetCleanName()); + // GetBotOwner()->CastToClient()->Message(Chat::White, "%s save failed!", GetCleanName()); CalcBonuses(); - AI_AddNPCSpells(GetBotSpellID()); - if(showtext) { GetBotOwner()->Message(Chat::Yellow, "%s has been updated.", GetCleanName()); GetBotOwner()->Message(Chat::Yellow, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), max_hp, GetAC(), max_mana, GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); @@ -9154,7 +8011,7 @@ bool Bot::CheckLoreConflict(const EQ::ItemData* item) { bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes) { if((iSpellTypes & SPELL_TYPES_DETRIMENTAL) != 0) { - LogError("Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); + LogError("[EntityList::Bot_AICheckCloseBeneficialSpells] detrimental spells requested"); return false; } @@ -9254,16 +8111,16 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } - if( iSpellTypes == SpellType_Buff) { + if (iSpellTypes == SpellType_Buff) { uint8 chanceToCast = caster->IsEngaged() ? caster->GetChanceToCastBySpellType(SpellType_Buff) : 100; - if(botCasterClass == BARD) { + if (botCasterClass == BARD) { if(caster->AICastSpell(caster, chanceToCast, SpellType_Buff)) return true; else return false; } - if(caster->HasGroup()) { + if (caster->HasGroup()) { Group *g = caster->GetGroup(); if(g) { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { @@ -9331,6 +8188,30 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } + if (iSpellTypes == SpellType_InCombatBuff) { + if (botCasterClass == BARD) { + if (caster->AICastSpell(caster, iChance, SpellType_InCombatBuff)) { + return true; + } + else { + return false; + } + } + + if (caster->HasGroup()) { + Group* g = caster->GetGroup(); + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i]) { + if (caster->AICastSpell(g->members[i], iChance, SpellType_InCombatBuff) || caster->AICastSpell(g->members[i]->GetPet(), iChance, SpellType_InCombatBuff)) { + return true; + } + } + } + } + } + } + return false; } @@ -9380,42 +8261,58 @@ Bot* EntityList::GetBotByBotName(std::string botName) { return Result; } -Client* EntityList::GetBotOwnerByBotEntityID(uint16 entityID) { - Client* Result = nullptr; - if (entityID > 0) { - for (std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if (tempBot && tempBot->GetID() == entityID) { - Result = tempBot->GetBotOwner()->CastToClient(); +Client* EntityList::GetBotOwnerByBotEntityID(uint32 entity_id) { + Client* c = nullptr; + + if (entity_id) { + for (const auto& b : bot_list) { + if (b && b->GetID() == entity_id) { + c = b->GetBotOwner()->CastToClient(); break; } } } - return Result; + + return c; } -void EntityList::AddBot(Bot *newBot, bool SendSpawnPacket, bool dontqueue) { - if(newBot) { - newBot->SetID(GetFreeID()); - newBot->SetSpawned(); - if(SendSpawnPacket) { - if(dontqueue) { +Client* EntityList::GetBotOwnerByBotID(const uint32 bot_id) { + Client* c = nullptr; + + if (bot_id) { + const auto owner_id = database.botdb.GetOwnerID(bot_id); + if (owner_id) { + c = GetClientByCharID(owner_id); + } + } + + return c; +} + +void EntityList::AddBot(Bot *new_bot, bool send_spawn_packet, bool dont_queue) { + if (new_bot) { + new_bot->SetID(GetFreeID()); + bot_list.push_back(new_bot); + mob_list.insert(std::pair(new_bot->GetID(), new_bot)); + parse->EventBot(EVENT_SPAWN, new_bot, nullptr, "", 0); + new_bot->SetSpawned(); + if (send_spawn_packet) { + if (dont_queue) { EQApplicationPacket* outapp = new EQApplicationPacket(); - newBot->CreateSpawnPacket(outapp); + new_bot->CreateSpawnPacket(outapp); outapp->priority = 6; - QueueClients(newBot, outapp, true); + QueueClients(new_bot, outapp, true); safe_delete(outapp); } else { NewSpawn_Struct* ns = new NewSpawn_Struct; memset(ns, 0, sizeof(NewSpawn_Struct)); - newBot->FillSpawnStruct(ns, newBot); - AddToSpawnQueue(newBot->GetID(), &ns); + new_bot->FillSpawnStruct(ns, new_bot); + AddToSpawnQueue(new_bot->GetID(), &ns); safe_delete(ns); } - parse->EventNPC(EVENT_SPAWN, newBot, nullptr, "", 0); } - bot_list.push_back(newBot); - mob_list.insert(std::pair(newBot->GetID(), newBot)); + + new_bot->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, new_bot, "", 0, nullptr); } } @@ -9586,7 +8483,7 @@ void EntityList::ScanCloseClientMobs(std::unordered_map& close_mob } } - LogAIScanClose("Close Client Mob List Size [{}] for mob [{}]", close_mobs.size(), scanning_mob->GetCleanName()); + LogAIScanCloseDetail("Close Client Mob List Size [{}] for mob [{}]", close_mobs.size(), scanning_mob->GetCleanName()); } uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { @@ -9857,7 +8754,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { fmt::format( "{} can use this discipline in {}.", GetCleanName(), - ConvertSecondsToTime(remaining_time) + Strings::SecondsToTime(remaining_time) ).c_str() ); return false; @@ -10061,7 +8958,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) if (!database.botdb.SaveEquipmentColor(GetBotID(), save_slot, rgb)) { if (GetBotOwner() && GetBotOwner()->IsClient()) - GetBotOwner()->CastToClient()->Message(Chat::Red, "%s", BotDatabase::fail::SaveEquipmentColor()); + GetBotOwner()->CastToClient()->Message(Chat::White, "%s", BotDatabase::fail::SaveEquipmentColor()); return false; } } @@ -10107,6 +9004,744 @@ void Bot::StopMoving(float new_heading) Mob::StopMoving(new_heading); } -uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 }; +void Bot::SpawnBotGroupByName(Client* c, std::string botgroup_name, uint32 leader_id) +{ + auto leader = Bot::LoadBot(leader_id); + if (!leader) { + c->Message( + Chat::White, + fmt::format( + "Could not load bot-group leader for '{}'.", + botgroup_name + ).c_str() + ); + safe_delete(leader); + return; + } -#endif + if (!leader->Spawn(c)) { + c->Message( + Chat::White, + fmt::format( + "Could not spawn bot-group leader {} for '{}'.", + leader->GetName(), + botgroup_name + ).c_str() + ); + safe_delete(leader); + return; + } + + auto* g = new Group(leader); + + entity_list.AddGroup(g); + database.SetGroupID(leader->GetCleanName(), g->GetID(), leader->GetBotID()); + database.SetGroupLeaderName(g->GetID(), leader->GetCleanName()); + leader->SetFollowID(c->GetID()); + + uint32 botgroup_id = 0; + database.botdb.LoadBotGroupIDByBotGroupName(botgroup_name, botgroup_id); + + std::map> member_list; + if (!database.botdb.LoadBotGroup(botgroup_name, member_list)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group '{}'.", + botgroup_name + ).c_str() + ); + return; + } + + if (member_list.find(botgroup_id) == member_list.end() || member_list[botgroup_id].empty()) { + c->Message( + Chat::White, + fmt::format( + "Could not locate member list for bot-group '{}'.", + botgroup_name + ).c_str() + ); + return; + } + + member_list[botgroup_id].remove(0); + member_list[botgroup_id].remove(leader->GetBotID()); + + auto bot_spawn_limit = c->GetBotSpawnLimit(); + auto spawned_bot_count = 0; + + std::vector bot_class_spawn_limits; + std::vector bot_class_spawned_count = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + for (uint8 class_id = WARRIOR; class_id <= BERSERKER; class_id++) { + auto bot_class_limit = c->GetBotSpawnLimit(class_id); + bot_class_spawn_limits.push_back(bot_class_limit); + } + + for (const auto& member_iter : member_list[botgroup_id]) { + auto member = Bot::LoadBot(member_iter); + if (!member) { + c->Message( + Chat::White, + fmt::format( + "Could not load bot id {}.", + member_iter + ).c_str() + ); + safe_delete(member); + return; + } + + if (bot_spawn_limit >= 0 && spawned_bot_count >= bot_spawn_limit) { + c->Message( + Chat::White, + fmt::format( + "Failed to spawn {} because you have a max of {} bot{} spawned.", + member->GetCleanName(), + bot_spawn_limit, + bot_spawn_limit != 1 ? "s" : "" + ).c_str() + ); + return; + } + + auto spawned_bot_count_class = bot_class_spawned_count[member->GetClass() - 1]; + auto bot_spawn_limit_class = bot_class_spawn_limits[member->GetClass() - 1]; + + if (bot_spawn_limit_class >= 0 && spawned_bot_count_class >= bot_spawn_limit_class) { + c->Message( + Chat::White, + fmt::format( + "Failed to spawn {} because you have a max of {} {} bot{} spawned.", + member->GetCleanName(), + bot_spawn_limit_class, + GetClassIDName(member->GetClass()), + bot_spawn_limit_class != 1 ? "s" : "" + ).c_str() + ); + continue; + } + + if (!member->Spawn(c)) { + c->Message( + Chat::White, + fmt::format( + "Could not spawn bot '{}' (ID {}).", + member->GetName(), + member_iter + ).c_str() + ); + safe_delete(member); + return; + } + + spawned_bot_count++; + bot_class_spawned_count[member->GetClass() - 1]++; + + Bot::AddBotToGroup(member, g); + } + + c->Message( + Chat::White, + fmt::format( + "Successfully loaded bot-group {}.", + botgroup_name + ).c_str() + ); +} + +void Bot::Signal(int signal_id) +{ + const auto export_string = fmt::format("{}", signal_id); + parse->EventBot(EVENT_SIGNAL, this, nullptr, export_string, 0); +} + +void Bot::SendPayload(int payload_id, std::string payload_value) +{ + const auto export_string = fmt::format("{} {}", payload_id, payload_value); + parse->EventBot(EVENT_PAYLOAD, this, nullptr, export_string, 0); +} + +void Bot::OwnerMessage(std::string message) +{ + if (!GetBotOwner() || !GetBotOwner()->IsClient()) { + return; + } + + GetBotOwner()->Message( + Chat::Tell, + fmt::format( + "{} tells you, '{}'", + GetCleanName(), + message + ).c_str() + ); +} + +bool Bot::GetBotOwnerDataBuckets() +{ + auto bot_owner = GetBotOwner(); + if (!bot_owner) { + return false; + } + + const auto query = fmt::format( + "SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'", + Strings::Escape(bot_owner->GetBucketKey()) + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + bot_owner_data_buckets.clear(); + + if (!results.RowCount()) { + return true; + } + + for (auto row : results) { + bot_owner_data_buckets.insert(std::pair(row[0], row[1])); + } + + return true; +} + +bool Bot::GetBotDataBuckets() +{ + const auto query = fmt::format( + "SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'", + Strings::Escape(GetBucketKey()) + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + bot_data_buckets.clear(); + + if (!results.RowCount()) { + return true; + } + + for (auto row : results) { + bot_data_buckets.insert(std::pair(row[0], row[1])); + } + + return true; +} + +bool Bot::CheckDataBucket(std::string bucket_name, std::string bucket_value, uint8 bucket_comparison) +{ + if (!bucket_name.empty() && !bucket_value.empty()) { + auto full_name = fmt::format( + "{}-{}", + GetBucketKey(), + bucket_name + ); + + auto player_value = bot_data_buckets[full_name]; + if (player_value.empty() && GetBotOwner()) { + full_name = fmt::format( + "{}-{}", + GetBotOwner()->GetBucketKey(), + bucket_name + ); + + player_value = bot_owner_data_buckets[full_name]; + if (player_value.empty()) { + return false; + } + } + + if (zone->CheckDataBucket(bucket_comparison, bucket_value, player_value)) { + return true; + } + } + + return false; +} + +int Bot::GetExpansionBitmask() +{ + if (m_expansion_bitmask >= 0) { + return m_expansion_bitmask; + } + + return RuleI(Bots, BotExpansionSettings); +} + +void Bot::SetExpansionBitmask(int expansion_bitmask, bool save) +{ + m_expansion_bitmask = expansion_bitmask; + + if (save) { + if (!database.botdb.SaveExpansionBitmask(GetBotID(), expansion_bitmask)) { + if (GetBotOwner() && GetBotOwner()->IsClient()) { + GetBotOwner()->CastToClient()->Message( + Chat::White, + fmt::format( + "Failed to save expansion bitmask for {}.", + GetCleanName() + ).c_str() + ); + } + } + } + + LoadAAs(); +} + +void Bot::SetBotEnforceSpellSetting(bool enforce_spell_settings, bool save) +{ + m_enforce_spell_settings = enforce_spell_settings; + + if (save) { + if (!database.botdb.SaveEnforceSpellSetting(GetBotID(), enforce_spell_settings)) { + if (GetBotOwner() && GetBotOwner()->IsClient()) { + GetBotOwner()->CastToClient()->Message( + Chat::White, + fmt::format( + "Failed to save enforce spell settings for {}.", + GetCleanName() + ).c_str() + ); + } + } + } + LoadBotSpellSettings(); + AI_AddBotSpells(GetBotSpellID()); +} + +bool Bot::AddBotSpellSetting(uint16 spell_id, BotSpellSetting* bs) +{ + if (!IsValidSpell(spell_id) || !bs) { + return false; + } + + auto obs = GetBotSpellSetting(spell_id); + if (obs) { + return false; + } + + auto s = BotSpellSettingsRepository::NewEntity(); + + s.spell_id = spell_id; + s.bot_id = GetBotID(); + + s.priority = bs->priority; + s.min_hp = bs->min_hp; + s.max_hp = bs->max_hp; + s.is_enabled = bs->is_enabled; + + const auto& nbs = BotSpellSettingsRepository::InsertOne(content_db, s); + if (!nbs.id) { + return false; + } + + LoadBotSpellSettings(); + return true; +} + +bool Bot::DeleteBotSpellSetting(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) { + return false; + } + + auto bs = GetBotSpellSetting(spell_id); + if (!bs) { + return false; + } + + BotSpellSettingsRepository::DeleteWhere( + content_db, + fmt::format( + "bot_id = {} AND spell_id = {}", + GetBotID(), + spell_id + ) + ); + LoadBotSpellSettings(); + return true; +} + +BotSpellSetting* Bot::GetBotSpellSetting(uint16 spell_id) +{ + if (!IsValidSpell(spell_id) || !bot_spell_settings.count(spell_id)) { + return nullptr; + } + + auto b = bot_spell_settings.find(spell_id); + if (b != bot_spell_settings.end()) { + return &b->second; + } + + return nullptr; +} + +void Bot::ListBotSpells(uint8 min_level) +{ + auto bot_owner = GetBotOwner(); + if (!bot_owner) { + return; + } + + if (AIBot_spells.empty() && AIBot_spells_enforced.empty()) { + bot_owner->Message( + Chat::White, + fmt::format( + "{} has no AI Spells.", + GetCleanName() + ).c_str() + ); + return; + } + + auto spell_count = 0; + auto spell_number = 1; + + for (const auto& s : (AIBot_spells.size() > AIBot_spells_enforced.size()) ? AIBot_spells : AIBot_spells_enforced) { + auto b = bot_spell_settings.find(s.spellid); + if (b == bot_spell_settings.end() && s.minlevel >= min_level) { + bot_owner->Message( + Chat::White, + fmt::format( + "Spell {} | Spell: {} | Add Spell: {}", + spell_number, + Saylink::Silent( + fmt::format("^spellinfo {}", s.spellid), + spells[s.spellid].name + ), + Saylink::Silent( + fmt::format("^spellsettingsadd {} {} {} {}", s.spellid, s.priority, s.min_hp, s.max_hp), "Add") + ).c_str() + ); + + spell_count++; + spell_number++; + } + } + + bot_owner->Message( + Chat::White, + fmt::format( + "{} has {} AI Spell{}.", + GetCleanName(), + spell_count, + spell_count != 1 ? "s" :"" + ).c_str() + ); +} + +void Bot::ListBotSpellSettings() +{ + auto bot_owner = GetBotOwner(); + if (!bot_owner) { + return; + } + + if (!bot_spell_settings.size()) { + bot_owner->Message( + Chat::White, + fmt::format( + "{} does not have any spell settings.", + GetCleanName() + ).c_str() + ); + return; + } + + auto setting_count = 0; + auto setting_number = 1; + + for (const auto& bs : bot_spell_settings) { + bot_owner->Message( + Chat::White, + fmt::format( + "Setting {} | Spell: {} | State: {} | {}", + setting_number, + Saylink::Silent(fmt::format("^spellinfo {}", bs.first), spells[bs.first].name), + Saylink::Silent( + fmt::format("^spellsettingstoggle {} {}", + bs.first, bs.second.is_enabled ? "False" : "True"), + bs.second.is_enabled ? "Enabled" : "Disabled" + ), + Saylink::Silent(fmt::format("^spellsettingsdelete {}", bs.first), "Remove") + ).c_str() + ); + + setting_count++; + setting_number++; + } + + bot_owner->Message( + Chat::White, + fmt::format( + "{} has {} spell setting{}.", + GetCleanName(), + setting_count, + setting_count != 1 ? "s" : "" + ).c_str() + ); +} + +void Bot::LoadBotSpellSettings() +{ + bot_spell_settings.clear(); + + auto s = BotSpellSettingsRepository::GetWhere(content_db, fmt::format("bot_id = {}", GetBotID())); + if (s.empty()) { + return; + } + + for (const auto& e : s) { + BotSpellSetting b; + + b.priority = e.priority; + b.min_hp = e.min_hp; + b.max_hp = e.max_hp; + b.is_enabled = e.is_enabled; + bot_spell_settings[e.spell_id] = b; + } +} + +bool Bot::UpdateBotSpellSetting(uint16 spell_id, BotSpellSetting* bs) +{ + if (!IsValidSpell(spell_id) || !bs) { + return false; + } + + auto s = BotSpellSettingsRepository::NewEntity(); + + s.spell_id = spell_id; + s.bot_id = GetBotID(); + s.priority = bs->priority; + s.min_hp = bs->min_hp; + s.max_hp = bs->max_hp; + s.is_enabled = bs->is_enabled; + + auto obs = GetBotSpellSetting(spell_id); + if (!obs) { + return false; + } + + if (!BotSpellSettingsRepository::UpdateSpellSetting(content_db, s)) { + return false; + } + + LoadBotSpellSettings(); + return true; +} + +std::string Bot::GetHPString(int8 min_hp, int8 max_hp) +{ + std::string hp_string = "Any"; + if (min_hp && max_hp) { + hp_string = fmt::format( + "{}%% to {}%%", + min_hp, + max_hp + ); + } else if (min_hp && !max_hp) { + hp_string = fmt::format( + "{}%% to 100%%", + min_hp + ); + } else if (!min_hp && max_hp) { + hp_string = fmt::format( + "1%% to {}%%", + max_hp + ); + } + + return hp_string; +} + +void Bot::SetBotArcherySetting(bool bot_archer_setting, bool save) +{ + m_bot_archery_setting = bot_archer_setting; + if (save) { + if (!database.botdb.SaveBotArcherSetting(GetBotID(), bot_archer_setting)) { + if (GetBotOwner() && GetBotOwner()->IsClient()) { + GetBotOwner()->CastToClient()->Message( + Chat::White, + fmt::format( + "Failed to save archery settings for {}.", + GetCleanName() + ).c_str() + ); + } + } + } +} + +std::vector Bot::GetApplySpellList( + ApplySpellType apply_type, + bool allow_pets, + bool is_raid_group_only +) { + std::vector l; + + if (apply_type == ApplySpellType::Raid && IsRaidGrouped()) { + auto* r = GetRaid(); + auto group_id = r->GetGroup(this->GetCleanName()); + if (r && EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) { + for (auto i = 0; i < MAX_RAID_MEMBERS; i++) { + auto* m = r->members[i].member; + if (m && m->IsClient() && (!is_raid_group_only || r->GetGroup(m) == group_id)) { + l.push_back(m); + + if (allow_pets && m->HasPet()) { + l.push_back(m->GetPet()); + } + + const auto& sbl = entity_list.GetBotListByCharacterID(m->CharacterID()); + for (const auto& b : sbl) { + l.push_back(b); + } + } + } + } + } else if (apply_type == ApplySpellType::Group && IsGrouped()) { + auto* g = GetGroup(); + if (g) { + for (auto i = 0; i < MAX_GROUP_MEMBERS; i++) { + auto* m = g->members[i]; + if (m && m->IsClient()) { + l.push_back(m->CastToClient()); + + if (allow_pets && m->HasPet()) { + l.push_back(m->GetPet()); + } + const auto& sbl = entity_list.GetBotListByCharacterID(m->CastToClient()->CharacterID()); + for (const auto& b : sbl) { + l.push_back(b); + } + } + } + } + } else { + l.push_back(this); + + if (allow_pets && HasPet()) { + l.push_back(GetPet()); + } + const auto& sbl = entity_list.GetBotListByCharacterID(CharacterID()); + for (const auto& b : sbl) { + l.push_back(b); + } + } + + return l; +} + +void Bot::ApplySpell( + int spell_id, + int duration, + ApplySpellType apply_type, + bool allow_pets, + bool is_raid_group_only +) { + const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only); + + for (const auto& m : l) { + m->ApplySpellBuff(spell_id, duration); + } +} + +void Bot::SetSpellDuration( + int spell_id, + int duration, + ApplySpellType apply_type, + bool allow_pets, + bool is_raid_group_only +) { + const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only); + + for (const auto& m : l) { + m->SetBuffDuration(spell_id, duration); + } +} + +void Bot::Escape() +{ + entity_list.RemoveFromTargets(this, true); + SetInvisible(Invisibility::Invisible); +} + +void Bot::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls, bool calculate_speed) { + BuffFadeByEffect(SE_Levitate); + if (CheckLosFN(target_x, target_y, target_z, 6.0f) || ignore_los) { + auto p = new EQApplicationPacket(OP_Fling, sizeof(fling_struct)); + auto* f = (fling_struct*) p->pBuffer; + + if (!calculate_speed) { + f->speed_z = value; + } else { + auto speed = 1.0f; + const auto distance = CalculateDistance(target_x, target_y, target_z); + + auto z_diff = target_z - GetZ(); + if (z_diff != 0.0f) { + speed += std::abs(z_diff) / 12.0f; + } + + speed += distance / 200.0f; + + speed++; + + speed = std::abs(speed); + + f->speed_z = speed; + } + + f->collision = clip_through_walls ? 0 : -1; + f->travel_time = -1; + f->unk3 = 1; + f->disable_fall_damage = 1; + f->new_y = target_y; + f->new_x = target_x; + f->new_z = target_z; + p->priority = 6; + GetBotOwner()->CastToClient()->FastQueuePacket(&p); + } +} + +// This should return the combined AC of all the items the Bot is wearing. +int32 Bot::GetRawItemAC() +{ + int32 Total = 0; + // this skips MainAmmo..add an '=' conditional if that slot is required (original behavior) + for (int16 slot_id = EQ::invslot::BONUS_BEGIN; slot_id <= EQ::invslot::BONUS_STAT_END; slot_id++) { + const EQ::ItemInstance* inst = m_inv[slot_id]; + if (inst && inst->IsClassCommon()) { + Total += inst->GetItem()->AC; + } + } + return Total; +} + +void Bot::SendSpellAnim(uint16 target_id, uint16 spell_id) +{ + if (!target_id || !IsValidSpell(spell_id)) { + return; + } + + EQApplicationPacket app(OP_Action, sizeof(Action_Struct)); + auto* a = (Action_Struct*) app.pBuffer; + + a->target = target_id; + a->source = GetID(); + a->type = 231; + a->spell = spell_id; + a->hit_heading = GetHeading(); + + app.priority = 1; + entity_list.QueueCloseClients(this, &app, false, RuleI(Range, SpellParticles)); +} + +uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 }; diff --git a/zone/bot.h b/zone/bot.h index fa64ae5da..3dffea1a1 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -19,8 +19,6 @@ #ifndef BOT_H #define BOT_H -#ifdef BOTS - #include "bot_structs.h" #include "mob.h" #include "client.h" @@ -29,7 +27,7 @@ #include "groups.h" #include "corpse.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "string_ids.h" #include "../common/misc_functions.h" #include "../common/global_define.h" @@ -38,9 +36,9 @@ #include -constexpr float BOT_FOLLOW_DISTANCE_DEFAULT = 184.0f; // as DSq value (~13.565 units) -constexpr float BOT_FOLLOW_DISTANCE_DEFAULT_MAX = 2500.0f; // as DSq value (50 units) -constexpr float BOT_FOLLOW_DISTANCE_WALK = 1000.0f; // as DSq value (~31.623 units) +constexpr uint32 BOT_FOLLOW_DISTANCE_DEFAULT = 184; // as DSq value (~13.565 units) +constexpr uint32 BOT_FOLLOW_DISTANCE_DEFAULT_MAX = 2500; // as DSq value (50 units) +constexpr uint32 BOT_FOLLOW_DISTANCE_WALK = 1000; // as DSq value (~31.623 units) constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds @@ -144,15 +142,15 @@ public: Bot(NPCType *npcTypeData, Client* botOwner); Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData); - //abstract virtual function implementations requird by base abstract class - virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill); - virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); - virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr); - virtual bool HasRaid() { return (GetRaid() ? true : false); } - virtual bool HasGroup() { return (GetGroup() ? true : false); } - virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); } - virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); } + //abstract virtual override function implementations requird by base abstract class + bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) override; + void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, + bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) override; + + bool HasRaid() override { return (GetRaid() ? true : false); } + bool HasGroup() override { return (GetGroup() ? true : false); } + Raid* GetRaid() override { return entity_list.GetRaidByMob(this); } + Group* GetGroup() override { return entity_list.GetGroupByMob(this); } // Common, but informal "interfaces" with Client object uint32 CharacterID() { return GetBotID(); } // Just returns the Bot Id @@ -167,72 +165,68 @@ public: bool IsValidName(); static bool IsValidName(std::string& name); bool Spawn(Client* botCharacterOwner); - virtual void SetLevel(uint8 in_level, bool command = false); - virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); - virtual bool Process(); + void SetLevel(uint8 in_level, bool command = false) override; + void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) override; + bool Process() override; void FinishTrade(Client* client, BotTradeType trade_type); - virtual bool Save(); - virtual void Depop(); + bool Save() override; + void Depop(); void CalcBotStats(bool showtext = true); - uint16 BotGetSpells(int spellslot) { return AIspells[spellslot].spellid; } - uint32 BotGetSpellType(int spellslot) { return AIspells[spellslot].type; } - uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; } - virtual float GetProcChances(float ProcBonus, uint16 hand); - virtual int GetHandToHandDamage(void); - virtual bool TryFinishingBlow(Mob *defender, int64 &damage); - virtual void DoRiposte(Mob* defender); - inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQ::skills::SkillOffense)) * 9 / 10); } - inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } + uint16 BotGetSpells(int spellslot) { return AIBot_spells[spellslot].spellid; } + uint32 BotGetSpellType(int spellslot) { return AIBot_spells[spellslot].type; } + uint16 BotGetSpellPriority(int spellslot) { return AIBot_spells[spellslot].priority; } + float GetProcChances(float ProcBonus, uint16 hand) override; + int GetHandToHandDamage(void) override; + bool TryFinishingBlow(Mob *defender, int64 &damage) override; + void DoRiposte(Mob* defender) override; + inline int32 GetATK() const override { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQ::skills::SkillOffense)) * 9 / 10); } + inline int32 GetATKBonus() const override { return itembonuses.ATK + spellbonuses.ATK; } uint32 GetTotalATK(); uint32 GetATKRating(); uint16 GetPrimarySkillValue(); uint16 MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const; inline uint16 MaxSkill(EQ::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } - virtual int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr); - virtual void DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false); - virtual void TryBackstab(Mob *other,int ReuseTime = 10); - virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10); - virtual void RogueAssassinate(Mob* other); - virtual void DoClassAttacks(Mob *target, bool IsRiposte=false); + int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr) override; + void DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false); + void TryBackstab(Mob *other,int ReuseTime = 10) override; + void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10) override; + void RogueAssassinate(Mob* other) override; + void DoClassAttacks(Mob *target, bool IsRiposte=false); bool CanDoSpecialAttack(Mob *other); - virtual int32 CheckAggroAmount(uint16 spellid); - virtual void CalcBonuses(); + void CalcBonuses() override; void CalcItemBonuses(StatBonuses* newbon); void AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); - virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); - virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther); - inline virtual bool IsPet() { return false; } - virtual bool IsNPC() const { return false; } - virtual Mob* GetOwner(); - virtual Mob* GetOwnerOrSelf(); - inline virtual bool HasOwner() { return (GetBotOwner() ? true : false); } - virtual int32 CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible = 0); - virtual int64 CalcMaxMana(); - virtual void SetAttackTimer(); + void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr) override; + FACTION_VALUE GetReverseFactionCon(Mob* iOther) override; + inline bool IsPet() override { return false; } + bool IsNPC() const override { return false; } + Mob* GetOwner() override; + Mob* GetOwnerOrSelf() override; + inline bool HasOwner() override { return (GetBotOwner() ? true : false); } + int64 CalcMaxMana() override; + void SetAttackTimer() override; uint64 GetClassHPFactor(); - virtual int64 CalcMaxHP(); + int64 CalcMaxHP() override; bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic); bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic); bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic); void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color); - void Camp(bool databaseSave = true); - virtual void AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false); - virtual void SetTarget(Mob* mob); - virtual void Zone(); - std::vector GetBotSpells() { return AIspells; } + void Camp(bool save_to_database = true); + void SetTarget(Mob* mob) override; + void Zone(); bool IsArcheryRange(Mob* target); void ChangeBotArcherWeapons(bool isArcher); void Sit(); void Stand(); bool IsSitting(); bool IsStanding(); - virtual int GetWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.785714285f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 - virtual int GetRunspeed() const { return (int)((float)_GetRunSpeed() * 1.785714285f); } - virtual void WalkTo(float x, float y, float z); - virtual void RunTo(float x, float y, float z); - virtual void StopMoving(); - virtual void StopMoving(float new_heading); + int GetWalkspeed() const override { return (int)((float)_GetWalkSpeed() * 1.785714285f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 + int GetRunspeed() const override { return (int)((float)_GetRunSpeed() * 1.785714285f); } + void WalkTo(float x, float y, float z) override; + void RunTo(float x, float y, float z) override; + void StopMoving() override; + void StopMoving(float new_heading) override; //bool GetCombatJitterFlag() { return m_combat_jitter_flag; } bool GetGuardFlag() { return m_guard_flag; } void SetGuardFlag(bool flag = true) { m_guard_flag = flag; } @@ -308,11 +302,45 @@ public: void DoEnduranceRegen(); //This Regenerates endurance void DoEnduranceUpkeep(); //does the endurance upkeep + bool AI_AddBotSpells(uint32 bot_spell_id); + void AddSpellToBotList( + int16 iPriority, + uint16 iSpellID, + uint32 iType, + int16 iManaCost, + int32 iRecastDelay, + int16 iResistAdjust, + uint8 min_level, + uint8 max_level, + int8 min_hp, + int8 max_hp, + std::string bucket_name, + std::string bucket_value, + uint8 bucket_comparison + ); + + void AddSpellToBotEnforceList( + int16 iPriority, + uint16 iSpellID, + uint32 iType, + int16 iManaCost, + int32 iRecastDelay, + int16 iResistAdjust, + uint8 min_level, + uint8 max_level, + int8 min_hp, + int8 max_hp, + std::string bucket_name, + std::string bucket_value, + uint8 bucket_comparison + ); + + void AI_Bot_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot); // AI Methods - virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes); - virtual bool AI_EngagedCastCheck(); - virtual bool AI_PursueCastCheck(); - virtual bool AI_IdleCastCheck(); + bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes); + bool AI_EngagedCastCheck() override; + bool AI_PursueCastCheck() override; + bool AI_IdleCastCheck() override; bool AIHealRotation(Mob* tar, bool useFastHeals); bool GetPauseAI() { return _pauseAI; } void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; } @@ -321,48 +349,57 @@ public: void SetGuardMode(); void SetHoldMode(); + // Bot AI Methods + void AI_Bot_Init(); + void AI_Bot_Start(uint32 iMoveDelay = 0); + // Mob AI Virtual Override Methods - virtual void AI_Process(); - virtual void AI_Stop(); + void AI_Process() override; + void AI_Stop() override; // Mob Spell Virtual Override Methods - virtual void SpellProcess(); - virtual int64 GetActSpellDamage(uint16 spell_id, int64 value, Mob* target = nullptr); - virtual int64 GetActSpellHealing(uint16 spell_id, int64 value, Mob* target = nullptr); - virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); - virtual int32 GetActSpellCost(uint16 spell_id, int32 cost); - virtual float GetActSpellRange(uint16 spell_id, float range); - virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration); - virtual float GetAOERange(uint16 spell_id); + void SpellProcess() override; + int32 GetActSpellDuration(uint16 spell_id, int32 duration) override; + float GetAOERange(uint16 spell_id) override; virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); - virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr); + void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr) override; virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, - uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0); + uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar); - virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); + bool IsImmuneToSpell(uint16 spell_id, Mob *caster) override; virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQ::spells::CastingSlot slot); - virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); + virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, + uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); + inline int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false) override + { return Mob::GetFocusEffect(type, spell_id, caster, from_buff_tic); } + inline bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override + { return Mob::Attack(other, Hand, FromRiposte, IsStrikethrough, IsFromSpell, opts); } + + bool GetBotOwnerDataBuckets(); + bool GetBotDataBuckets(); + bool CheckDataBucket(std::string bucket_name, std::string bucket_value, uint8 bucket_comparison); // Bot Equipment & Inventory Class Methods void BotTradeAddItem(const EQ::ItemInstance* inst, uint16 slot_id, std::string* error_message, bool save_to_database = true); void EquipBot(std::string* error_message); bool CheckLoreConflict(const EQ::ItemData* item); - virtual void UpdateEquipmentLight() { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); } - const EQ::InventoryProfile& GetBotInv() const { return m_inv; } + void UpdateEquipmentLight() override { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); } + inline EQ::InventoryProfile& GetInv() { return m_inv; } // Static Class Methods //static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped static Bot* LoadBot(uint32 botID); - static uint32 SpawnedBotCount(uint32 botOwnerCharacterID); + static uint32 SpawnedBotCount(const uint32 owner_id, uint8 class_id = NO_CLASS); static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp); //static bool SetBotOwnerCharacterID(uint32 botID, uint32 botOwnerCharacterID, std::string* error_message); static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined); static Bot* GetBotByBotClientOwnerAndBotName(Client* c, std::string botName); static void ProcessBotGroupInvite(Client* c, std::string botName); static void ProcessBotGroupDisband(Client* c, std::string botName); - static void BotOrderCampAll(Client* c); + static void BotOrderCampAll(Client* c, uint8 class_id = NO_CLASS); static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client); - static void LoadAndSpawnAllZonedBots(Client* botOwner); + static void LoadAndSpawnAllZonedBots(Client* bot_owner); static bool GroupHasBot(Group* group); static Bot* GetFirstBotInGroup(Group* group); static void ProcessClientZoneChange(Client* botOwner); @@ -403,7 +440,14 @@ public: static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target); static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target); - static NPCType *CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender); + static NPCType *CreateDefaultNPCTypeStructForBot( + std::string botName, + std::string botLastName, + uint8 botLevel, + uint16 botRace, + uint8 botClass, + uint8 gender + ); // Static Bot Group Methods static bool AddBotToGroup(Bot* bot, Group* group); @@ -417,16 +461,17 @@ public: Mob* GetBotOwner() { return this->_botOwner; } uint32 GetBotArcheryRange(); EQ::ItemInstance* GetBotItem(uint16 slot_id); - virtual bool GetSpawnStatus() { return _spawnStatus; } + bool GetSpawnStatus() { return _spawnStatus; } uint8 GetPetChooserID() { return _petChooserID; } bool IsPetChooser() { return _petChooser; } - bool IsBotArcher() { return _botArcher; } + bool IsBotArcher() { return m_bot_archery_setting; } bool IsBotCharmer() { return _botCharmer; } - virtual bool IsBot() const { return true; } + bool IsBot() const override { return true; } bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; } BotRoleType GetBotRole() { return _botRole; } EQ::constants::StanceType GetBotStance() { return _botStance; } uint8 GetChanceToCastBySpellType(uint32 spellType); + bool GetBotEnforceSpellSetting() { return m_enforce_spell_settings; } bool IsGroupHealer() { return m_CastingRoles.GroupHealer; } bool IsGroupSlower() { return m_CastingRoles.GroupSlower; } @@ -441,11 +486,13 @@ public: //static void UpdateRaidCastingRoles(const Raid* raid, bool disband = false); bool IsBotCaster() { return IsCasterClass(GetClass()); } + bool IsBotHybrid() { return IsHybridClass(GetClass()); } bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); } bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); } bool IsBotSpellFighter() { return IsSpellFighterClass(GetClass()); } bool IsBotFighter() { return IsFighterClass(GetClass()); } bool IsBotNonSpellFighter() { return IsNonSpellFighterClass(GetClass()); } + uint8 GetBotClass() { return GetClass(); } bool CanHeal(); int GetRawACNoShield(int &shield_ac); @@ -474,32 +521,32 @@ public: bool GetAltOutOfCombatBehavior() { return _altoutofcombatbehavior;} bool GetShowHelm() { return _showhelm; } - inline virtual int32 GetSTR() const { return STR; } - inline virtual int32 GetSTA() const { return STA; } - inline virtual int32 GetDEX() const { return DEX; } - inline virtual int32 GetAGI() const { return AGI; } - inline virtual int32 GetINT() const { return INT; } - inline virtual int32 GetWIS() const { return WIS; } - inline virtual int32 GetCHA() const { return CHA; } - inline virtual int32 GetMR() const { return MR; } - inline virtual int32 GetFR() const { return FR; } - inline virtual int32 GetDR() const { return DR; } - inline virtual int32 GetPR() const { return PR; } - inline virtual int32 GetCR() const { return CR; } - inline virtual int32 GetCorrup() const { return Corrup; } + inline int32 GetSTR() const override { return STR; } + inline int32 GetSTA() const override { return STA; } + inline int32 GetDEX() const override { return DEX; } + inline int32 GetAGI() const override { return AGI; } + inline int32 GetINT() const override { return INT; } + inline int32 GetWIS() const override { return WIS; } + inline int32 GetCHA() const override { return CHA; } + inline int32 GetMR() const override { return MR; } + inline int32 GetFR() const override { return FR; } + inline int32 GetDR() const override { return DR; } + inline int32 GetPR() const override { return PR; } + inline int32 GetCR() const override { return CR; } + inline int32 GetCorrup() const override { return Corrup; } //Heroic - inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; } - inline virtual int32 GetHeroicSTA() const { return itembonuses.HeroicSTA; } - inline virtual int32 GetHeroicDEX() const { return itembonuses.HeroicDEX; } - inline virtual int32 GetHeroicAGI() const { return itembonuses.HeroicAGI; } - inline virtual int32 GetHeroicINT() const { return itembonuses.HeroicINT; } - inline virtual int32 GetHeroicWIS() const { return itembonuses.HeroicWIS; } - inline virtual int32 GetHeroicCHA() const { return itembonuses.HeroicCHA; } - inline virtual int32 GetHeroicMR() const { return itembonuses.HeroicMR; } - inline virtual int32 GetHeroicFR() const { return itembonuses.HeroicFR; } - inline virtual int32 GetHeroicDR() const { return itembonuses.HeroicDR; } - inline virtual int32 GetHeroicPR() const { return itembonuses.HeroicPR; } - inline virtual int32 GetHeroicCR() const { return itembonuses.HeroicCR; } + inline int32 GetHeroicSTR() const override { return itembonuses.HeroicSTR; } + inline int32 GetHeroicSTA() const override { return itembonuses.HeroicSTA; } + inline int32 GetHeroicDEX() const override { return itembonuses.HeroicDEX; } + inline int32 GetHeroicAGI() const override { return itembonuses.HeroicAGI; } + inline int32 GetHeroicINT() const override { return itembonuses.HeroicINT; } + inline int32 GetHeroicWIS() const override { return itembonuses.HeroicWIS; } + inline int32 GetHeroicCHA() const override { return itembonuses.HeroicCHA; } + inline int32 GetHeroicMR() const override { return itembonuses.HeroicMR; } + inline int32 GetHeroicFR() const override { return itembonuses.HeroicFR; } + inline int32 GetHeroicDR() const override { return itembonuses.HeroicDR; } + inline int32 GetHeroicPR() const override { return itembonuses.HeroicPR; } + inline int32 GetHeroicCR() const override { return itembonuses.HeroicCR; } inline virtual int32 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; } // Mod2 inline virtual int32 GetShielding() const { return itembonuses.MeleeMitigation; } @@ -528,11 +575,24 @@ public: inline InspectMessage_Struct& GetInspectMessage() { return _botInspectMessage; } inline const InspectMessage_Struct& GetInspectMessage() const { return _botInspectMessage; } + // "Quest API" Methods + bool HasBotSpellEntry(uint16 spellid); + void ApplySpell(int spell_id, int duration = 0, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true); + void BreakInvis(); + void Escape(); + void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clip_through_walls = false, bool calculate_speed = false); + std::vector GetApplySpellList(ApplySpellType apply_type, bool allow_pets, bool is_raid_group_only); + int32 GetItemIDAt(int16 slot_id); + int32 GetAugmentIDAt(int16 slot_id, uint8 augslot); + int32 GetRawItemAC(); + void SendSpellAnim(uint16 targetid, uint16 spell_id); + void SetSpellDuration(int spell_id, int duration = 0, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true); + // "SET" Class Methods void SetBotSpellID(uint32 newSpellID); - virtual void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; } + void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; } void SetPetChooserID(uint8 id) { _petChooserID = id; } - void SetBotArcher(bool a) { _botArcher = a; } + void SetBotArcherySetting(bool bot_archer_setting, bool save = false); void SetBotCharmer(bool c) { _botCharmer = c; } void SetPetChooser(bool p) { _petChooser = p; } void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; } @@ -561,16 +621,70 @@ public: void SetDrakkinTattoo(uint32 value) { drakkin_tattoo = value; } bool DyeArmor(int16 slot_id, uint32 rgb, bool all_flag = false, bool save_flag = true); + int GetExpansionBitmask(); + void SetExpansionBitmask(int expansion_bitmask, bool save = true); + + void ListBotSpells(uint8 min_level); + + std::string GetHPString(int8 min_hp, int8 max_hp); + + bool AddBotSpellSetting(uint16 spell_id, BotSpellSetting* bs); + bool DeleteBotSpellSetting(uint16 spell_id); + BotSpellSetting* GetBotSpellSetting(uint16 spell_id); + void ListBotSpellSettings(); + void LoadBotSpellSettings(); + bool UpdateBotSpellSetting(uint16 spell_id, BotSpellSetting* bs); + void SetBotEnforceSpellSetting(bool enforcespellsettings, bool save = false); + bool GetBotEnforceSpellSetting() const { return m_enforce_spell_settings; } + + static void SpawnBotGroupByName(Client* c, std::string botgroup_name, uint32 leader_id); + std::string CreateSayLink(Client* botOwner, const char* message, const char* name); // Class Destructors - virtual ~Bot(); + ~Bot() override; // Publicized protected functions - virtual void BotRangedAttack(Mob* other); + void BotRangedAttack(Mob* other); // Publicized private functions - static NPCType *FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack); + static NPCType *FillNPCTypeStruct( + uint32 botSpellsID, + std::string botName, + std::string botLastName, + uint8 botLevel, + uint16 botRace, + uint8 botClass, + uint8 gender, + float size, + uint32 face, + uint32 hairStyle, + uint32 hairColor, + uint32 eyeColor, + uint32 eyeColor2, + uint32 beard, + uint32 beardColor, + uint32 drakkinHeritage, + uint32 drakkinTattoo, + uint32 drakkinDetails, + int32 hp, + int32 mana, + int32 mr, + int32 cr, + int32 dr, + int32 fr, + int32 pr, + int32 corrup, + int32 ac, + uint32 str, + uint32 sta, + uint32 dex, + uint32 agi, + uint32 _int, + uint32 wis, + uint32 cha, + uint32 attack + ); void BotRemoveEquipItem(uint16 slot_id); void RemoveBotItemBySlot(uint16 slot_id, std::string* error_message); void AddBotItem( @@ -586,6 +700,8 @@ public: uint32 augment_six = 0 ); uint32 CountBotItem(uint32 item_id); + std::map GetBotItemSlots(); + uint32 GetBotItemBySlot(uint16 slot_id); bool HasBotItem(uint32 item_id); void RemoveBotItem(uint32 item_id); uint32 GetTotalPlayTime(); @@ -610,15 +726,16 @@ public: int32 GetBaseDR() { return _baseDR; } int32 GetBaseCorrup() { return _baseCorrup; } + void Signal(int signal_id); + void SendPayload(int payload_id, std::string payload_value = std::string()); + void OwnerMessage(std::string message); + protected: - virtual void PetAIProcess(); - virtual void BotMeditate(bool isSitting); - virtual bool CheckBotDoubleAttack(bool Triple = false); - virtual int32 GetBotFocusEffect(focusType bottype, uint16 spell_id, bool from_buff_tic = false); - virtual int32 CalcBotFocusEffect(focusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false); - virtual int32 CalcBotAAFocus(focusType type, uint32 aa_ID, uint32 points, uint16 spell_id); - virtual void PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client); - virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); + void PetAIProcess(); + void BotMeditate(bool isSitting); + bool CheckBotDoubleAttack(bool Triple = false); + void PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client); + bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0) override; BotCastingRoles& GetCastingRoles() { return m_CastingRoles; } void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; } @@ -629,16 +746,19 @@ protected: //void SetRaidSlower(bool flag = true) { m_CastingRoles.RaidSlower = flag; } //void SetRaidNuker(bool flag = true) { m_CastingRoles.RaidNuker = flag; } //void SetRaidDoter(bool flag = true) { m_CastingRoles.RaidDoter = flag; } + std::deque bot_signal_q; + + std::vector AIBot_spells; + std::vector AIBot_spells_enforced; private: // Class Members uint32 _botID; uint32 _botOwnerCharacterID; - //uint32 _botSpellID; bool _spawnStatus; Mob* _botOwner; bool _botOrderAttack; - bool _botArcher; + bool m_bot_archery_setting; bool _botCharmer; bool _petChooser; uint8 _petChooserID; @@ -684,6 +804,10 @@ private: eStandingPetOrder m_previous_pet_order; BotCastingRoles m_CastingRoles; + std::map bot_data_buckets; + std::map bot_owner_data_buckets; + + std::map bot_spell_settings; std::shared_ptr m_member_of_heal_rotation; @@ -693,6 +817,8 @@ private: bool _showhelm; bool _pauseAI; uint8 _stopMeleeLevel; + int m_expansion_bitmask; + bool m_enforce_spell_settings; // Private "base stats" Members int32 _baseMR; @@ -731,7 +857,6 @@ private: // Private "Inventory" Methods void GetBotItems(EQ::InventoryProfile &inv, std::string* error_message); void BotAddEquipItem(uint16 slot_id, uint32 item_id); - uint32 GetBotItemBySlot(uint16 slot_id); // Private "Pet" Methods bool LoadPet(); // Load and spawn bot pet if there is one @@ -742,6 +867,6 @@ private: static uint8 spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND]; }; -#endif // BOTS +bool IsSpellInBotList(DBbotspells_Struct* spell_list, uint16 iSpellID); #endif // BOT_H diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 5f174320c..b85d4f1e4 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -32,8 +32,6 @@ */ -#ifdef BOTS - #include #include #include @@ -45,6 +43,7 @@ #define strcasecmp _stricmp #endif +#include "../common/data_verification.h" #include "../common/global_define.h" #include "../common/eq_packet.h" #include "../common/features.h" @@ -53,14 +52,15 @@ #include "../common/ptimer.h" #include "../common/rulesys.h" #include "../common/serverinfo.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/say_link.h" #include "../common/eqemu_logsys.h" +#include "../common/emu_constants.h" #include "bot_command.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "guild_mgr.h" #include "map.h" #include "doors.h" @@ -71,6 +71,7 @@ #include "titles.h" #include "water_map.h" #include "worldserver.h" +#include "dialogue_window.h" #include @@ -1261,7 +1262,7 @@ LinkedList cleanup_bot_command_list; */ int bot_command_not_avail(Client *c, const char *message) { - c->Message(Chat::Red, "Bot commands not available."); + c->Message(Chat::White, "Bot commands not available."); return -1; } @@ -1309,116 +1310,125 @@ int bot_command_init(void) bot_command_aliases.clear(); if ( - bot_command_add("actionable", "Lists actionable command arguments and use descriptions", 0, bot_command_actionable) || - bot_command_add("aggressive", "Orders a bot to use a aggressive discipline", 0, bot_command_aggressive) || - bot_command_add("applypoison", "Applies cursor-held poison to a rogue bot's weapon", 0, bot_command_apply_poison) || - bot_command_add("applypotion", "Applies cursor-held potion to a bot's effects", 0, bot_command_apply_potion) || - bot_command_add("attack", "Orders bots to attack a designated target", 0, bot_command_attack) || - bot_command_add("bindaffinity", "Orders a bot to attempt an affinity binding", 0, bot_command_bind_affinity) || - bot_command_add("bot", "Lists the available bot management [subcommands]", 0, bot_command_bot) || - bot_command_add("botappearance", "Lists the available bot appearance [subcommands]", 0, bot_subcommand_bot_appearance) || - bot_command_add("botbeardcolor", "Changes the beard color of a bot", 0, bot_subcommand_bot_beard_color) || - bot_command_add("botbeardstyle", "Changes the beard style of a bot", 0, bot_subcommand_bot_beard_style) || - bot_command_add("botcamp", "Orders a bot(s) to camp", 0, bot_subcommand_bot_camp) || - bot_command_add("botclone", "Creates a copy of a bot", 200, bot_subcommand_bot_clone) || - bot_command_add("botcreate", "Creates a new bot", 0, bot_subcommand_bot_create) || - bot_command_add("botdelete", "Deletes all record of a bot", 0, bot_subcommand_bot_delete) || - bot_command_add("botdetails", "Changes the Drakkin details of a bot", 0, bot_subcommand_bot_details) || - bot_command_add("botdyearmor", "Changes the color of a bot's (bots') armor", 0, bot_subcommand_bot_dye_armor) || - bot_command_add("boteyes", "Changes the eye colors of a bot", 0, bot_subcommand_bot_eyes) || - bot_command_add("botface", "Changes the facial appearance of your bot", 0, bot_subcommand_bot_face) || - bot_command_add("botfollowdistance", "Changes the follow distance(s) of a bot(s)", 0, bot_subcommand_bot_follow_distance) || - bot_command_add("botgroup", "Lists the available bot-group [subcommands]", 0, bot_command_botgroup) || - bot_command_add("botgroupaddmember", "Adds a member to a bot-group", 0, bot_subcommand_botgroup_add_member) || - bot_command_add("botgroupcreate", "Creates a bot-group and designates a leader", 0, bot_subcommand_botgroup_create) || - bot_command_add("botgroupdelete", "Deletes a bot-group and releases its members", 0, bot_subcommand_botgroup_delete) || - bot_command_add("botgrouplist", "Lists all of your existing bot-groups", 0, bot_subcommand_botgroup_list) || - bot_command_add("botgroupload", "Loads all members of a bot-group", 0, bot_subcommand_botgroup_load) || - bot_command_add("botgroupremovemember", "Removes a bot from its bot-group", 0, bot_subcommand_botgroup_remove_member) || - bot_command_add("bothaircolor", "Changes the hair color of a bot", 0, bot_subcommand_bot_hair_color) || - bot_command_add("bothairstyle", "Changes the hairstyle of a bot", 0, bot_subcommand_bot_hairstyle) || - bot_command_add("botheritage", "Changes the Drakkin heritage of a bot", 0, bot_subcommand_bot_heritage) || - bot_command_add("botinspectmessage", "Changes the inspect message of a bot", 0, bot_subcommand_bot_inspect_message) || - bot_command_add("botlist", "Lists the bots that you own", 0, bot_subcommand_bot_list) || - bot_command_add("botoutofcombat", "Toggles your bot between standard and out-of-combat spell/skill use - if any specialized behaviors exist", 0, bot_subcommand_bot_out_of_combat) || - bot_command_add("botreport", "Orders a bot to report its readiness", 0, bot_subcommand_bot_report) || - bot_command_add("botspawn", "Spawns a created bot", 0, bot_subcommand_bot_spawn) || - bot_command_add("botstance", "Changes the stance of a bot", 0, bot_subcommand_bot_stance) || - bot_command_add("botstopmeleelevel", "Sets the level a caster or spell-casting fighter bot will stop melee combat", 0, bot_subcommand_bot_stop_melee_level) || - bot_command_add("botsuffix", "Sets a bots suffix", 0, bot_subcommand_bot_suffix) || - bot_command_add("botsummon", "Summons bot(s) to your location", 0, bot_subcommand_bot_summon) || - bot_command_add("botsurname", "Sets a bots surname (last name)", 0, bot_subcommand_bot_surname) || - bot_command_add("bottattoo", "Changes the Drakkin tattoo of a bot", 0, bot_subcommand_bot_tattoo) || - bot_command_add("bottogglearcher", "Toggles a archer bot between melee and ranged weapon use", 0, bot_subcommand_bot_toggle_archer) || - bot_command_add("bottogglehelm", "Toggles the helm visibility of a bot between shown and hidden", 0, bot_subcommand_bot_toggle_helm) || - bot_command_add("bottitle", "Sets a bots title", 0, bot_subcommand_bot_title) || - bot_command_add("botupdate", "Updates a bot to reflect any level changes that you have experienced", 0, bot_subcommand_bot_update) || - bot_command_add("botwoad", "Changes the Barbarian woad of a bot", 0, bot_subcommand_bot_woad) || - bot_command_add("charm", "Attempts to have a bot charm your target", 0, bot_command_charm) || - bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", 0, bot_subcommand_circle) || - bot_command_add("cure", "Orders a bot to remove any ailments", 0, bot_command_cure) || - bot_command_add("defensive", "Orders a bot to use a defensive discipline", 0, bot_command_defensive) || - bot_command_add("depart", "Orders a bot to open a magical doorway to a specified destination", 0, bot_command_depart) || - bot_command_add("escape", "Orders a bot to send a target group to a safe location within the zone", 0, bot_command_escape) || - bot_command_add("findaliases", "Find available aliases for a bot command", 0, bot_command_find_aliases) || - bot_command_add("follow", "Orders bots to follow a designated target (option 'chain' auto-links eligible spawned bots)", 0, bot_command_follow) || - bot_command_add("guard", "Orders bots to guard their current positions", 0, bot_command_guard) || - bot_command_add("healrotation", "Lists the available bot heal rotation [subcommands]", 0, bot_command_heal_rotation) || - bot_command_add("healrotationadaptivetargeting", "Enables or disables adaptive targeting within the heal rotation instance", 0, bot_subcommand_heal_rotation_adaptive_targeting) || - bot_command_add("healrotationaddmember", "Adds a bot to a heal rotation instance", 0, bot_subcommand_heal_rotation_add_member) || - bot_command_add("healrotationaddtarget", "Adds target to a heal rotation instance", 0, bot_subcommand_heal_rotation_add_target) || - bot_command_add("healrotationadjustcritical", "Adjusts the critial HP limit of the heal rotation instance's Class Armor Type criteria", 0, bot_subcommand_heal_rotation_adjust_critical) || - bot_command_add("healrotationadjustsafe", "Adjusts the safe HP limit of the heal rotation instance's Class Armor Type criteria", 0, bot_subcommand_heal_rotation_adjust_safe) || - bot_command_add("healrotationcastingoverride", "Enables or disables casting overrides within the heal rotation instance", 0, bot_subcommand_heal_rotation_casting_override) || - bot_command_add("healrotationchangeinterval", "Changes casting interval between members within the heal rotation instance", 0, bot_subcommand_heal_rotation_change_interval) || - bot_command_add("healrotationclearhot", "Clears the HOT of a heal rotation instance", 0, bot_subcommand_heal_rotation_clear_hot) || - bot_command_add("healrotationcleartargets", "Removes all targets from a heal rotation instance", 0, bot_subcommand_heal_rotation_clear_targets) || - bot_command_add("healrotationcreate", "Creates a bot heal rotation instance and designates a leader", 0, bot_subcommand_heal_rotation_create) || - bot_command_add("healrotationdelete", "Deletes a bot heal rotation entry by leader", 0, bot_subcommand_heal_rotation_delete) || - bot_command_add("healrotationfastheals", "Enables or disables fast heals within the heal rotation instance", 0, bot_subcommand_heal_rotation_fast_heals) || - bot_command_add("healrotationlist", "Reports heal rotation instance(s) information", 0, bot_subcommand_heal_rotation_list) || - bot_command_add("healrotationremovemember", "Removes a bot from a heal rotation instance", 0, bot_subcommand_heal_rotation_remove_member) || - bot_command_add("healrotationremovetarget", "Removes target from a heal rotations instance", 0, bot_subcommand_heal_rotation_remove_target) || - bot_command_add("healrotationresetlimits", "Resets all Class Armor Type HP limit criteria in a heal rotation to its default value", 0, bot_subcommand_heal_rotation_reset_limits) || - bot_command_add("healrotationsave", "Saves a bot heal rotation entry by leader", 0, bot_subcommand_heal_rotation_save) || - bot_command_add("healrotationsethot", "Sets the HOT in a heal rotation instance", 0, bot_subcommand_heal_rotation_set_hot) || - bot_command_add("healrotationstart", "Starts a heal rotation", 0, bot_subcommand_heal_rotation_start) || - bot_command_add("healrotationstop", "Stops a heal rotation", 0, bot_subcommand_heal_rotation_stop) || - bot_command_add("help", "List available commands and their description - specify partial command as argument to search", 0, bot_command_help) || - bot_command_add("hold", "Prevents a bot from attacking until released", 0, bot_command_hold) || - bot_command_add("identify", "Orders a bot to cast an item identification spell", 0, bot_command_identify) || - bot_command_add("inventory", "Lists the available bot inventory [subcommands]", 0, bot_command_inventory) || - bot_command_add("inventorygive", "Gives the item on your cursor to a bot", 0, bot_subcommand_inventory_give) || - bot_command_add("inventorylist", "Lists all items in a bot's inventory", 0, bot_subcommand_inventory_list) || - bot_command_add("inventoryremove", "Removes an item from a bot's inventory", 0, bot_subcommand_inventory_remove) || - bot_command_add("inventorywindow", "Displays all items in a bot's inventory in a pop-up window", 0, bot_subcommand_inventory_window) || - bot_command_add("invisibility", "Orders a bot to cast a cloak of invisibility, or allow them to be seen", 0, bot_command_invisibility) || - bot_command_add("itemuse", "Elicits a report from spawned bots that can use the item on your cursor (option 'empty' yields only empty slots)", 0, bot_command_item_use) || - bot_command_add("levitation", "Orders a bot to cast a levitation spell", 0, bot_command_levitation) || - bot_command_add("lull", "Orders a bot to cast a pacification spell", 0, bot_command_lull) || - bot_command_add("mesmerize", "Orders a bot to cast a mesmerization spell", 0, bot_command_mesmerize) || - bot_command_add("movementspeed", "Orders a bot to cast a movement speed enhancement spell", 0, bot_command_movement_speed) || - bot_command_add("owneroption", "Sets options available to bot owners", 0, bot_command_owner_option) || - bot_command_add("pet", "Lists the available bot pet [subcommands]", 0, bot_command_pet) || - bot_command_add("petgetlost", "Orders a bot to remove its summoned pet", 0, bot_subcommand_pet_get_lost) || - bot_command_add("petremove", "Orders a bot to remove its charmed pet", 0, bot_subcommand_pet_remove) || - bot_command_add("petsettype", "Orders a Magician bot to use a specified pet type", 0, bot_subcommand_pet_set_type) || - bot_command_add("picklock", "Orders a capable bot to pick the lock of the closest door", 0, bot_command_pick_lock) || - bot_command_add("precombat", "Sets flag used to determine pre-combat behavior", 0, bot_command_precombat) || - bot_command_add("portal", "Orders a Wizard bot to open a magical doorway to a specified destination", 0, bot_subcommand_portal) || - bot_command_add("pull", "Orders a designated bot to 'pull' an enemy", 0, bot_command_pull) || - bot_command_add("release", "Releases a suspended bot's AI processing (with hate list wipe)", 0, bot_command_release) || - bot_command_add("resistance", "Orders a bot to cast a specified resistance buff", 0, bot_command_resistance) || - bot_command_add("resurrect", "Orders a bot to resurrect a player's (players') corpse(s)", 0, bot_command_resurrect) || - bot_command_add("rune", "Orders a bot to cast a rune of protection", 0, bot_command_rune) || - bot_command_add("sendhome", "Orders a bot to open a magical doorway home", 0, bot_command_send_home) || - bot_command_add("size", "Orders a bot to change a player's size", 0, bot_command_size) || - bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", 0, bot_command_summon_corpse) || - bot_command_add("suspend", "Suspends a bot's AI processing until released", 0, bot_command_suspend) || - bot_command_add("taunt", "Toggles taunt use by a bot", 0, bot_command_taunt) || - bot_command_add("track", "Orders a capable bot to track enemies", 0, bot_command_track) || - bot_command_add("viewcombos", "Views bot race class combinations", 0, bot_command_view_combos) || - bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", 0, bot_command_water_breathing) + bot_command_add("actionable", "Lists actionable command arguments and use descriptions", AccountStatus::Player, bot_command_actionable) || + bot_command_add("aggressive", "Orders a bot to use a aggressive discipline", AccountStatus::Player, bot_command_aggressive) || + bot_command_add("applypoison", "Applies cursor-held poison to a rogue bot's weapon", AccountStatus::Player, bot_command_apply_poison) || + bot_command_add("applypotion", "Applies cursor-held potion to a bot's effects", AccountStatus::Player, bot_command_apply_potion) || + bot_command_add("attack", "Orders bots to attack a designated target", AccountStatus::Player, bot_command_attack) || + bot_command_add("bindaffinity", "Orders a bot to attempt an affinity binding", AccountStatus::Player, bot_command_bind_affinity) || + bot_command_add("bot", "Lists the available bot management [subcommands]", AccountStatus::Player, bot_command_bot) || + bot_command_add("botappearance", "Lists the available bot appearance [subcommands]", AccountStatus::Player, bot_subcommand_bot_appearance) || + bot_command_add("botbeardcolor", "Changes the beard color of a bot", AccountStatus::Player, bot_subcommand_bot_beard_color) || + bot_command_add("botbeardstyle", "Changes the beard style of a bot", AccountStatus::Player, bot_subcommand_bot_beard_style) || + bot_command_add("botcamp", "Orders a bot(s) to camp", AccountStatus::Player, bot_subcommand_bot_camp) || + bot_command_add("botclone", "Creates a copy of a bot", AccountStatus::GMMgmt, bot_subcommand_bot_clone) || + bot_command_add("botcreate", "Creates a new bot", AccountStatus::Player, bot_subcommand_bot_create) || + bot_command_add("botdelete", "Deletes all record of a bot", AccountStatus::Player, bot_subcommand_bot_delete) || + bot_command_add("botdetails", "Changes the Drakkin details of a bot", AccountStatus::Player, bot_subcommand_bot_details) || + bot_command_add("botdyearmor", "Changes the color of a bot's (bots') armor", AccountStatus::Player, bot_subcommand_bot_dye_armor) || + bot_command_add("boteyes", "Changes the eye colors of a bot", AccountStatus::Player, bot_subcommand_bot_eyes) || + bot_command_add("botface", "Changes the facial appearance of your bot", AccountStatus::Player, bot_subcommand_bot_face) || + bot_command_add("botfollowdistance", "Changes the follow distance(s) of a bot(s)", AccountStatus::Player, bot_subcommand_bot_follow_distance) || + bot_command_add("botgroup", "Lists the available bot-group [subcommands]", AccountStatus::Player, bot_command_botgroup) || + bot_command_add("botgroupaddmember", "Adds a member to a bot-group", AccountStatus::Player, bot_subcommand_botgroup_add_member) || + bot_command_add("botgroupautospawn", "Toggles auto spawning for a bot-group, spawning the bot group when you zone automatically", AccountStatus::Player, bot_subcommand_botgroup_auto_spawn) || + bot_command_add("botgroupcreate", "Creates a bot-group and designates a leader", AccountStatus::Player, bot_subcommand_botgroup_create) || + bot_command_add("botgroupdelete", "Deletes a bot-group and releases its members", AccountStatus::Player, bot_subcommand_botgroup_delete) || + bot_command_add("botgrouplist", "Lists all of your existing bot-groups", AccountStatus::Player, bot_subcommand_botgroup_list) || + bot_command_add("botgroupload", "Loads all members of a bot-group", AccountStatus::Player, bot_subcommand_botgroup_load) || + bot_command_add("botgroupremovemember", "Removes a bot from its bot-group", AccountStatus::Player, bot_subcommand_botgroup_remove_member) || + bot_command_add("bothaircolor", "Changes the hair color of a bot", AccountStatus::Player, bot_subcommand_bot_hair_color) || + bot_command_add("bothairstyle", "Changes the hairstyle of a bot", AccountStatus::Player, bot_subcommand_bot_hairstyle) || + bot_command_add("botheritage", "Changes the Drakkin heritage of a bot", AccountStatus::Player, bot_subcommand_bot_heritage) || + bot_command_add("botinspectmessage", "Changes the inspect message of a bot", AccountStatus::Player, bot_subcommand_bot_inspect_message) || + bot_command_add("botlist", "Lists the bots that you own", AccountStatus::Player, bot_subcommand_bot_list) || + bot_command_add("botoutofcombat", "Toggles your bot between standard and out-of-combat spell/skill use - if any specialized behaviors exist", AccountStatus::Player, bot_subcommand_bot_out_of_combat) || + bot_command_add("botreport", "Orders a bot to report its readiness", AccountStatus::Player, bot_subcommand_bot_report) || + bot_command_add("botspawn", "Spawns a created bot", AccountStatus::Player, bot_subcommand_bot_spawn) || + bot_command_add("botstance", "Changes the stance of a bot", AccountStatus::Player, bot_subcommand_bot_stance) || + bot_command_add("botstopmeleelevel", "Sets the level a caster or spell-casting fighter bot will stop melee combat", AccountStatus::Player, bot_subcommand_bot_stop_melee_level) || + bot_command_add("botsuffix", "Sets a bots suffix", AccountStatus::Player, bot_subcommand_bot_suffix) || + bot_command_add("botsummon", "Summons bot(s) to your location", AccountStatus::Player, bot_subcommand_bot_summon) || + bot_command_add("botsurname", "Sets a bots surname (last name)", AccountStatus::Player, bot_subcommand_bot_surname) || + bot_command_add("bottattoo", "Changes the Drakkin tattoo of a bot", AccountStatus::Player, bot_subcommand_bot_tattoo) || + bot_command_add("bottogglearcher", "Toggles a archer bot between melee and ranged weapon use", AccountStatus::Player, bot_subcommand_bot_toggle_archer) || + bot_command_add("bottogglehelm", "Toggles the helm visibility of a bot between shown and hidden", AccountStatus::Player, bot_subcommand_bot_toggle_helm) || + bot_command_add("bottitle", "Sets a bots title", AccountStatus::Player, bot_subcommand_bot_title) || + bot_command_add("botupdate", "Updates a bot to reflect any level changes that you have experienced", AccountStatus::Player, bot_subcommand_bot_update) || + bot_command_add("botwoad", "Changes the Barbarian woad of a bot", AccountStatus::Player, bot_subcommand_bot_woad) || + bot_command_add("charm", "Attempts to have a bot charm your target", AccountStatus::Player, bot_command_charm) || + bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_subcommand_circle) || + bot_command_add("cure", "Orders a bot to remove any ailments", AccountStatus::Player, bot_command_cure) || + bot_command_add("defensive", "Orders a bot to use a defensive discipline", AccountStatus::Player, bot_command_defensive) || + bot_command_add("depart", "Orders a bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_command_depart) || + bot_command_add("enforcespellsettings", "Toggles your Bot to cast only spells in their spell settings list.", AccountStatus::Player, bot_command_enforce_spell_list) || + bot_command_add("escape", "Orders a bot to send a target group to a safe location within the zone", AccountStatus::Player, bot_command_escape) || + bot_command_add("findaliases", "Find available aliases for a bot command", AccountStatus::Player, bot_command_find_aliases) || + bot_command_add("follow", "Orders bots to follow a designated target (option 'chain' auto-links eligible spawned bots)", AccountStatus::Player, bot_command_follow) || + bot_command_add("guard", "Orders bots to guard their current positions", AccountStatus::Player, bot_command_guard) || + bot_command_add("healrotation", "Lists the available bot heal rotation [subcommands]", AccountStatus::Player, bot_command_heal_rotation) || + bot_command_add("healrotationadaptivetargeting", "Enables or disables adaptive targeting within the heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_adaptive_targeting) || + bot_command_add("healrotationaddmember", "Adds a bot to a heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_add_member) || + bot_command_add("healrotationaddtarget", "Adds target to a heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_add_target) || + bot_command_add("healrotationadjustcritical", "Adjusts the critial HP limit of the heal rotation instance's Class Armor Type criteria", AccountStatus::Player, bot_subcommand_heal_rotation_adjust_critical) || + bot_command_add("healrotationadjustsafe", "Adjusts the safe HP limit of the heal rotation instance's Class Armor Type criteria", AccountStatus::Player, bot_subcommand_heal_rotation_adjust_safe) || + bot_command_add("healrotationcastingoverride", "Enables or disables casting overrides within the heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_casting_override) || + bot_command_add("healrotationchangeinterval", "Changes casting interval between members within the heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_change_interval) || + bot_command_add("healrotationclearhot", "Clears the HOT of a heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_clear_hot) || + bot_command_add("healrotationcleartargets", "Removes all targets from a heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_clear_targets) || + bot_command_add("healrotationcreate", "Creates a bot heal rotation instance and designates a leader", AccountStatus::Player, bot_subcommand_heal_rotation_create) || + bot_command_add("healrotationdelete", "Deletes a bot heal rotation entry by leader", AccountStatus::Player, bot_subcommand_heal_rotation_delete) || + bot_command_add("healrotationfastheals", "Enables or disables fast heals within the heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_fast_heals) || + bot_command_add("healrotationlist", "Reports heal rotation instance(s) information", AccountStatus::Player, bot_subcommand_heal_rotation_list) || + bot_command_add("healrotationremovemember", "Removes a bot from a heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_remove_member) || + bot_command_add("healrotationremovetarget", "Removes target from a heal rotations instance", AccountStatus::Player, bot_subcommand_heal_rotation_remove_target) || + bot_command_add("healrotationresetlimits", "Resets all Class Armor Type HP limit criteria in a heal rotation to its default value", AccountStatus::Player, bot_subcommand_heal_rotation_reset_limits) || + bot_command_add("healrotationsave", "Saves a bot heal rotation entry by leader", AccountStatus::Player, bot_subcommand_heal_rotation_save) || + bot_command_add("healrotationsethot", "Sets the HOT in a heal rotation instance", AccountStatus::Player, bot_subcommand_heal_rotation_set_hot) || + bot_command_add("healrotationstart", "Starts a heal rotation", AccountStatus::Player, bot_subcommand_heal_rotation_start) || + bot_command_add("healrotationstop", "Stops a heal rotation", AccountStatus::Player, bot_subcommand_heal_rotation_stop) || + bot_command_add("help", "List available commands and their description - specify partial command as argument to search", AccountStatus::Player, bot_command_help) || + bot_command_add("hold", "Prevents a bot from attacking until released", AccountStatus::Player, bot_command_hold) || + bot_command_add("identify", "Orders a bot to cast an item identification spell", AccountStatus::Player, bot_command_identify) || + bot_command_add("inventory", "Lists the available bot inventory [subcommands]", AccountStatus::Player, bot_command_inventory) || + bot_command_add("inventorygive", "Gives the item on your cursor to a bot", AccountStatus::Player, bot_subcommand_inventory_give) || + bot_command_add("inventorylist", "Lists all items in a bot's inventory", AccountStatus::Player, bot_subcommand_inventory_list) || + bot_command_add("inventoryremove", "Removes an item from a bot's inventory", AccountStatus::Player, bot_subcommand_inventory_remove) || + bot_command_add("inventorywindow", "Displays all items in a bot's inventory in a pop-up window", AccountStatus::Player, bot_subcommand_inventory_window) || + bot_command_add("invisibility", "Orders a bot to cast a cloak of invisibility, or allow them to be seen", AccountStatus::Player, bot_command_invisibility) || + bot_command_add("itemuse", "Elicits a report from spawned bots that can use the item on your cursor (option 'empty' yields only empty slots)", AccountStatus::Player, bot_command_item_use) || + bot_command_add("levitation", "Orders a bot to cast a levitation spell", AccountStatus::Player, bot_command_levitation) || + bot_command_add("lull", "Orders a bot to cast a pacification spell", AccountStatus::Player, bot_command_lull) || + bot_command_add("mesmerize", "Orders a bot to cast a mesmerization spell", AccountStatus::Player, bot_command_mesmerize) || + bot_command_add("movementspeed", "Orders a bot to cast a movement speed enhancement spell", AccountStatus::Player, bot_command_movement_speed) || + bot_command_add("owneroption", "Sets options available to bot owners", AccountStatus::Player, bot_command_owner_option) || + bot_command_add("pet", "Lists the available bot pet [subcommands]", AccountStatus::Player, bot_command_pet) || + bot_command_add("petgetlost", "Orders a bot to remove its summoned pet", AccountStatus::Player, bot_subcommand_pet_get_lost) || + bot_command_add("petremove", "Orders a bot to remove its charmed pet", AccountStatus::Player, bot_subcommand_pet_remove) || + bot_command_add("petsettype", "Orders a Magician bot to use a specified pet type", AccountStatus::Player, bot_subcommand_pet_set_type) || + bot_command_add("picklock", "Orders a capable bot to pick the lock of the closest door", AccountStatus::Player, bot_command_pick_lock) || + bot_command_add("precombat", "Sets flag used to determine pre-combat behavior", AccountStatus::Player, bot_command_precombat) || + bot_command_add("portal", "Orders a Wizard bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_subcommand_portal) || + bot_command_add("pull", "Orders a designated bot to 'pull' an enemy", AccountStatus::Player, bot_command_pull) || + bot_command_add("release", "Releases a suspended bot's AI processing (with hate list wipe)", AccountStatus::Player, bot_command_release) || + bot_command_add("resistance", "Orders a bot to cast a specified resistance buff", AccountStatus::Player, bot_command_resistance) || + bot_command_add("resurrect", "Orders a bot to resurrect a player's (players') corpse(s)", AccountStatus::Player, bot_command_resurrect) || + bot_command_add("rune", "Orders a bot to cast a rune of protection", AccountStatus::Player, bot_command_rune) || + bot_command_add("sendhome", "Orders a bot to open a magical doorway home", AccountStatus::Player, bot_command_send_home) || + bot_command_add("size", "Orders a bot to change a player's size", AccountStatus::Player, bot_command_size) || + bot_command_add("spellinfo", "Opens a dialogue window with spell info", AccountStatus::Player, bot_spell_info_dialogue_window) || + bot_command_add("spells", "Lists all Spells learned by the Bot.", AccountStatus::Player, bot_command_spell_list) || + bot_command_add("spellsettings", "Lists a bot's spell setting entries", AccountStatus::Player, bot_command_spell_settings_list) || + bot_command_add("spellsettingsadd", "Add a bot spell setting entry", AccountStatus::Player, bot_command_spell_settings_add) || + bot_command_add("spellsettingsdelete", "Delete a bot spell setting entry", AccountStatus::Player, bot_command_spell_settings_delete) || + bot_command_add("spellsettingstoggle", "Toggle a bot spell use", AccountStatus::Player, bot_command_spell_settings_toggle) || + bot_command_add("spellsettingsupdate", "Update a bot spell setting entry", AccountStatus::Player, bot_command_spell_settings_update) || + bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", AccountStatus::Player, bot_command_summon_corpse) || + bot_command_add("suspend", "Suspends a bot's AI processing until released", AccountStatus::Player, bot_command_suspend) || + bot_command_add("taunt", "Toggles taunt use by a bot", AccountStatus::Player, bot_command_taunt) || + bot_command_add("track", "Orders a capable bot to track enemies", AccountStatus::Player, bot_command_track) || + bot_command_add("viewcombos", "Views bot race class combinations", AccountStatus::Player, bot_command_view_combos) || + bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", AccountStatus::Player, bot_command_water_breathing) ) { bot_command_deinit(); return -1; @@ -1614,7 +1624,7 @@ int bot_command_real_dispatch(Client *c, const char *message) BotCommandRecord *cur = bot_command_list[cstr]; if(c->Admin() < cur->access){ - c->Message(Chat::Red, "Your access level is not high enough to use this bot command."); + c->Message(Chat::White, "Your access level is not high enough to use this bot command."); return(-1); } @@ -2295,11 +2305,11 @@ namespace ActionableBots return ABT_None; if (!ab_mask) - bot_owner->Message(Chat::Red, "Command passed null 'ActionableBot' criteria"); + bot_owner->Message(Chat::White, "Command passed null 'ActionableBot' criteria"); else if (ab_mask & ab_type) - bot_owner->Message(Chat::Red, "You have no spawned bots meeting this criteria - type: '%s', name: '%s'", ab_type_arg.c_str(), ((name) ? (name) : (""))); + bot_owner->Message(Chat::White, "You have no spawned bots meeting this criteria - type: '%s', name: '%s'", ab_type_arg.c_str(), ((name) ? (name) : (""))); else - bot_owner->Message(Chat::Red, "This command does not allow 'ActionableBot' criteria '%s'", ab_type_arg.c_str()); + bot_owner->Message(Chat::White, "This command does not allow 'ActionableBot' criteria '%s'", ab_type_arg.c_str()); return ABT_None; } @@ -2526,17 +2536,17 @@ void bot_command_actionable(Client *c, const Seperator *sep) c->Message(Chat::White, "Actionable command arguments:"); - c->Message(Chat::Cyan, "target - selects target as single bot .. use ^command [target] or imply by empty actionable argument"); - c->Message(Chat::Cyan, "byname [name] - selects single bot by name"); - c->Message(Chat::Cyan, "ownergroup - selects all bots in the owner's group"); - c->Message(Chat::Cyan, "botgroup [name] - selects members of a bot-group by its name"); - c->Message(Chat::Cyan, "targetgroup - selects all bots in target's group"); - c->Message(Chat::Cyan, "namesgroup [name] - selects all bots in name's group"); - c->Message(Chat::Cyan, "healrotation [name] - selects all member and target bots of a heal rotation where name is a member"); - c->Message(Chat::Cyan, "healrotationmembers [name] - selects all member bots of a heal rotation where name is a member"); - c->Message(Chat::Cyan, "healrotationtargets [name] - selects all target bots of a heal rotation where name is a member"); - c->Message(Chat::Cyan, "spawned - selects all spawned bots"); - c->Message(Chat::Cyan, "all - selects all spawned bots .. argument use indicates en masse database updating"); + c->Message(Chat::White, "target - selects target as single bot .. use ^command [target] or imply by empty actionable argument"); + c->Message(Chat::White, "byname [name] - selects single bot by name"); + c->Message(Chat::White, "ownergroup - selects all bots in the owner's group"); + c->Message(Chat::White, "botgroup [name] - selects members of a bot-group by its name"); + c->Message(Chat::White, "targetgroup - selects all bots in target's group"); + c->Message(Chat::White, "namesgroup [name] - selects all bots in name's group"); + c->Message(Chat::White, "healrotation [name] - selects all member and target bots of a heal rotation where name is a member"); + c->Message(Chat::White, "healrotationmembers [name] - selects all member bots of a heal rotation where name is a member"); + c->Message(Chat::White, "healrotationtargets [name] - selects all target bots of a heal rotation where name is a member"); + c->Message(Chat::White, "spawned - selects all spawned bots"); + c->Message(Chat::White, "all - selects all spawned bots .. argument use indicates en masse database updating"); c->Message(Chat::White, "You may only select your bots as actionable"); } @@ -2547,7 +2557,7 @@ void bot_command_aggressive(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_aggressive", sep->arg[0], "aggressive")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Stance); return; } @@ -2582,8 +2592,16 @@ void bot_command_aggressive(Client *c, const Seperator *sep) } my_bot->InterruptSpell(); - if (candidate_count == 1) - Bot::BotGroupSay(my_bot, "Using '%s'", spells[local_entry->spell_id].name); + if (candidate_count == 1) { + Bot::BotGroupSay( + my_bot, + fmt::format( + "Using {}.", + spells[local_entry->spell_id].name + ).c_str() + ); + } + my_bot->UseDiscipline(local_entry->spell_id, my_bot->GetID()); ++success_count; @@ -2591,7 +2609,7 @@ void bot_command_aggressive(Client *c, const Seperator *sep) } } - c->Message(Chat::Yellow, "%i of %i bots have used aggressive disciplines", success_count, candidate_count); + c->Message(Chat::White, "%i of %i bots have used aggressive disciplines", success_count, candidate_count); } void bot_command_apply_poison(Client *c, const Seperator *sep) @@ -2604,7 +2622,7 @@ void bot_command_apply_poison(Client *c, const Seperator *sep) } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); return; } @@ -2614,26 +2632,26 @@ void bot_command_apply_poison(Client *c, const Seperator *sep) } if (!my_rogue_bot) { - c->Message(Chat::Red, "You must target a rogue bot that you own to use this command!"); + c->Message(Chat::White, "You must target a rogue bot that you own to use this command!"); return; } if (my_rogue_bot->GetLevel() < 18) { - c->Message(Chat::Red, "Your rogue bot must be level 18 before %s can apply poison!", (my_rogue_bot->GetGender() == 1 ? "she" : "he")); + c->Message(Chat::White, "Your rogue bot must be level 18 before %s can apply poison!", (my_rogue_bot->GetGender() == 1 ? "she" : "he")); return; } const auto poison_instance = c->GetInv().GetItem(EQ::invslot::slotCursor); if (!poison_instance) { - c->Message(Chat::Red, "No item found on cursor!"); + c->Message(Chat::White, "No item found on cursor!"); return; } auto poison_data = poison_instance->GetItem(); if (!poison_data) { - c->Message(Chat::Red, "No data found for cursor item!"); + c->Message(Chat::White, "No data found for cursor item!"); return; } @@ -2641,13 +2659,13 @@ void bot_command_apply_poison(Client *c, const Seperator *sep) if ((~poison_data->Races) & GetPlayerRaceBit(my_rogue_bot->GetRace())) { - c->Message(Chat::Red, "Invalid race for weapon poison!"); + c->Message(Chat::White, "Invalid race for weapon poison!"); return; } if (poison_data->Proc.Level2 > my_rogue_bot->GetLevel()) { - c->Message(Chat::Red, "This poison is too powerful for your intended target!"); + c->Message(Chat::White, "This poison is too powerful for your intended target!"); return; } @@ -2660,17 +2678,17 @@ void bot_command_apply_poison(Client *c, const Seperator *sep) bool apply_poison_chance = (ChanceRoll < (.75 + poison_skill / 1000)); if (apply_poison_chance && my_rogue_bot->AddProcToWeapon(poison_data->Proc.Effect, false, (my_rogue_bot->GetDEX() / 100) + 103, POISON_PROC)) { - c->Message(Chat::Yellow, "Successfully applied %s to %s's weapon.", poison_data->Name, my_rogue_bot->GetCleanName()); + c->Message(Chat::White, "Successfully applied %s to %s's weapon.", poison_data->Name, my_rogue_bot->GetCleanName()); } else { - c->Message(Chat::Red, "Failed to apply %s to %s's weapon.", poison_data->Name, my_rogue_bot->GetCleanName()); + c->Message(Chat::White, "Failed to apply %s to %s's weapon.", poison_data->Name, my_rogue_bot->GetCleanName()); } c->DeleteItemInInventory(EQ::invslot::slotCursor, 1, true); } else { - c->Message(Chat::Red, "Item on cursor is not a weapon poison!"); + c->Message(Chat::White, "Item on cursor is not a weapon poison!"); return; } } @@ -2685,7 +2703,7 @@ void bot_command_apply_potion(Client* c, const Seperator* sep) } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); return; } @@ -2695,21 +2713,21 @@ void bot_command_apply_potion(Client* c, const Seperator* sep) } if (!my_bot) { - c->Message(Chat::Red, "You must target a bot that you own to use this command!"); + c->Message(Chat::White, "You must target a bot that you own to use this command!"); return; } const auto potion_instance = c->GetInv().GetItem(EQ::invslot::slotCursor); if (!potion_instance) { - c->Message(Chat::Red, "No item found on cursor!"); + c->Message(Chat::White, "No item found on cursor!"); return; } auto potion_data = potion_instance->GetItem(); if (!potion_data) { - c->Message(Chat::Red, "No data found for cursor item!"); + c->Message(Chat::White, "No data found for cursor item!"); return; } @@ -2717,39 +2735,39 @@ void bot_command_apply_potion(Client* c, const Seperator* sep) if (RuleB(Bots, RestrictApplyPotionToRogue) && potion_data->Classes != PLAYER_CLASS_ROGUE_BIT) { - c->Message(Chat::Red, "This command is restricted to rogue poison potions only!"); + c->Message(Chat::White, "This command is restricted to rogue poison potions only!"); return; } if ((~potion_data->Races) & GetPlayerRaceBit(my_bot->GetRace())) { - c->Message(Chat::Red, "Invalid race for potion!"); + c->Message(Chat::White, "Invalid race for potion!"); return; } if ((~potion_data->Classes) & GetPlayerClassBit(my_bot->GetClass())) { - c->Message(Chat::Red, "Invalid class for potion!"); + c->Message(Chat::White, "Invalid class for potion!"); return; } if (potion_data->Click.Level2 > my_bot->GetLevel()) { - c->Message(Chat::Red, "This potion is too powerful for your intended target!"); + c->Message(Chat::White, "This potion is too powerful for your intended target!"); return; } // TODO: figure out best way to handle casting time/animation if (my_bot->SpellFinished(potion_data->Click.Effect, my_bot, EQ::spells::CastingSlot::Item, 0)) { - c->Message(Chat::Yellow, "Successfully applied %s to %s's buff effects.", potion_data->Name, my_bot->GetCleanName()); + c->Message(Chat::White, "Successfully applied %s to %s's buff effects.", potion_data->Name, my_bot->GetCleanName()); } else { - c->Message(Chat::Red, "Failed to apply %s to %s's buff effects.", potion_data->Name, my_bot->GetCleanName()); + c->Message(Chat::White, "Failed to apply %s to %s's buff effects.", potion_data->Name, my_bot->GetCleanName()); } c->DeleteItemInInventory(EQ::invslot::slotCursor, 1, true); } else { - c->Message(Chat::Red, "Item on cursor is not a potion!"); + c->Message(Chat::White, "Item on cursor is not a potion!"); return; } } @@ -2761,7 +2779,7 @@ void bot_command_attack(Client *c, const Seperator *sep) } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | default: spawned] ([actionable_name])", sep->arg[0]); + c->Message(Chat::White, "usage: %s [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | default: spawned] ([actionable_name])", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_Type2; @@ -2769,7 +2787,7 @@ void bot_command_attack(Client *c, const Seperator *sep) Mob* target_mob = ActionableTarget::AsSingle_ByAttackable(c); if (!target_mob) { - c->Message(Chat::Red, "You must an enemy to use this command"); + c->Message(Chat::White, "You must an enemy to use this command"); return; } @@ -2800,10 +2818,22 @@ void bot_command_attack(Client *c, const Seperator *sep) } if (attacker_count == 1 && first_attacker) { - Bot::BotGroupSay(first_attacker, "Attacking %s!", target_mob->GetCleanName()); - } - else { - c->Message(Chat::Yellow, "%i of your bots are attacking %s!", sbl.size(), target_mob->GetCleanName()); + Bot::BotGroupSay( + first_attacker, + fmt::format( + "Attacking {}.", + target_mob->GetCleanName() + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "{} of your bots are attacking {}.", + sbl.size(), + target_mob->GetCleanName() + ).c_str() + ); } } @@ -2813,7 +2843,7 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_BindAffinity) || helper_command_alias_fail(c, "bot_command_bind_affinity", sep->arg[0], "bindaffinity")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s", sep->arg[0]); + c->Message(Chat::White, "usage: () %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_BindAffinity); return; } @@ -2838,9 +2868,9 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep) // Cast effect message is not being generated if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id)) - c->Message(Chat::Yellow, "Successfully bound %s to this location", target_mob->GetCleanName()); + c->Message(Chat::White, "Successfully bound %s to this location", target_mob->GetCleanName()); else - c->Message(Chat::Red, "Failed to bind %s to this location", target_mob->GetCleanName()); + c->Message(Chat::White, "Failed to bind %s to this location", target_mob->GetCleanName()); break; } @@ -2887,24 +2917,13 @@ void bot_command_bot(Client *c, const Seperator *sep) void bot_command_botgroup(Client *c, const Seperator *sep) { - /* VS2012 code - begin */ - std::list subcommand_list; - subcommand_list.push_back("botgroupaddmember"); - subcommand_list.push_back("botgroupcreate"); - subcommand_list.push_back("botgroupdelete"); - subcommand_list.push_back("botgrouplist"); - subcommand_list.push_back("botgroupload"); - subcommand_list.push_back("botgroupremovemember"); - /* VS2012 code - end */ - - /* VS2013 code const std::list subcommand_list = { "botgroupaddmember", "botgroupcreate", "botgroupdelete", "botgrouplist", "botgroupload", "botgroupremovemember" }; - */ - if (helper_command_alias_fail(c, "bot_command_botgroup", sep->arg[0], "botgroup")) + if (helper_command_alias_fail(c, "bot_command_botgroup", sep->arg[0], "botgroup")) { return; + } helper_send_available_subcommands(c, "bot-group", subcommand_list); } @@ -2915,7 +2934,7 @@ void bot_command_charm(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Charm) || helper_command_alias_fail(c, "bot_command_charm", sep->arg[0], "charm")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([option: dire])", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([option: dire])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Charm); return; } @@ -2941,7 +2960,7 @@ void bot_command_charm(Client *c, const Seperator *sep) if (!target_mob) continue; if (target_mob->IsCharmed()) { - c->Message(Chat::Red, "Your is already charmed"); + c->Message(Chat::White, "Your is already charmed"); return; } @@ -2968,7 +2987,7 @@ void bot_command_cure(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Cure) || helper_command_alias_fail(c, "bot_command_cure", sep->arg[0], "cure")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [ailment: blindness | disease | poison | curse | corruption]", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [ailment: blindness | disease | poison | curse | corruption]", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Cure); return; } @@ -2988,7 +3007,7 @@ void bot_command_cure(Client *c, const Seperator *sep) ailment_type = BCEnum::AT_Corruption; if (ailment_type == BCEnum::AT_None) { - c->Message(Chat::Red, "You must specify a cure [ailment] to use this command"); + c->Message(Chat::White, "You must specify a cure [ailment] to use this command"); return; } @@ -3038,7 +3057,7 @@ void bot_command_defensive(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_defensive", sep->arg[0], "defensive")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Stance); return; } @@ -3073,8 +3092,16 @@ void bot_command_defensive(Client *c, const Seperator *sep) } my_bot->InterruptSpell(); - if (candidate_count == 1) - Bot::BotGroupSay(my_bot, "Using '%s'", spells[local_entry->spell_id].name); + if (candidate_count == 1) { + Bot::BotGroupSay( + my_bot, + fmt::format( + "Using {}.", + spells[local_entry->spell_id].name + ).c_str() + ); + } + my_bot->UseDiscipline(local_entry->spell_id, my_bot->GetID()); ++success_count; @@ -3082,7 +3109,7 @@ void bot_command_defensive(Client *c, const Seperator *sep) } } - c->Message(Chat::Yellow, "%i of %i bots have used defensive disciplines", success_count, candidate_count); + c->Message(Chat::White, "%i of %i bots have used defensive disciplines", success_count, candidate_count); } void bot_command_depart(Client *c, const Seperator *sep) @@ -3091,7 +3118,7 @@ void bot_command_depart(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Depart) || helper_command_alias_fail(c, "bot_command_depart", sep->arg[0], "depart")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [list | destination] ([option: single])", sep->arg[0]); + c->Message(Chat::White, "usage: %s [list | destination] ([option: single])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Depart); return; } @@ -3109,7 +3136,7 @@ void bot_command_depart(Client *c, const Seperator *sep) return; } else if (destination.empty()) { - c->Message(Chat::Red, "A [destination] or [list] argument is required to use this command"); + c->Message(Chat::White, "A [destination] or [list] argument is required to use this command"); return; } @@ -3149,7 +3176,7 @@ void bot_command_escape(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Escape) || helper_command_alias_fail(c, "bot_command_escape", sep->arg[0], "escape")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([option: lesser])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([option: lesser])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Escape); return; } @@ -3191,19 +3218,19 @@ void bot_command_find_aliases(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_command_find_aliases", sep->arg[0], "findaliases")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [alias | command]", sep->arg[0]); + c->Message(Chat::White, "usage: %s [alias | command]", sep->arg[0]); return; } auto find_iter = bot_command_aliases.find(sep->arg[1]); if (find_iter == bot_command_aliases.end()) { - c->Message(Chat::Red, "No bot commands or aliases match '%s'", sep->arg[1]); + c->Message(Chat::White, "No bot commands or aliases match '%s'", sep->arg[1]); return; } auto command_iter = bot_command_list.find(find_iter->second); if (find_iter->second.empty() || command_iter == bot_command_list.end()) { - c->Message(Chat::Magenta, "An unknown condition has occurred..."); + c->Message(Chat::White, "An unknown condition has occurred..."); return; } @@ -3214,7 +3241,7 @@ void bot_command_find_aliases(Client *c, const Seperator *sep) if (strcasecmp(find_iter->second.c_str(), alias_iter.second.c_str()) || c->Admin() < command_iter->second->access) continue; - c->Message(Chat::Cyan, "%c%s", BOT_COMMAND_CHAR, alias_iter.first.c_str()); + c->Message(Chat::White, "%c%s", BOT_COMMAND_CHAR, alias_iter.first.c_str()); ++bot_command_aliases_shown; } c->Message(Chat::White, "%d bot command alias%s listed.", bot_command_aliases_shown, bot_command_aliases_shown != 1 ? "es" : ""); @@ -3225,8 +3252,8 @@ void bot_command_follow(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_command_follow", sep->arg[0], "follow")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([option: reset]) [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); - c->Message(Chat::Cyan, "usage: %s chain", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([option: reset]) [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); + c->Message(Chat::White, "usage: %s chain", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_Type2; @@ -3240,7 +3267,7 @@ void bot_command_follow(Client *c, const Seperator *sep) if (!optional_arg.compare("chain")) { auto chain_count = helper_bot_follow_option_chain(c); - c->Message(Chat::Yellow, "%i of your bots %s now chain following you", chain_count, (chain_count == 1 ? "is" : "are")); + c->Message(Chat::White, "%i of your bots %s now chain following you", chain_count, (chain_count == 1 ? "is" : "are")); return; } @@ -3252,7 +3279,7 @@ void bot_command_follow(Client *c, const Seperator *sep) else { target_mob = ActionableTarget::VerifyFriendly(c, BCEnum::TT_Single); if (!target_mob) { - c->Message(Chat::Red, "You must a friendly mob to use this command"); + c->Message(Chat::White, "You must a friendly mob to use this command"); return; } } @@ -3293,15 +3320,35 @@ void bot_command_follow(Client *c, const Seperator *sep) bot_iter->GetPet()->WipeHateList(); bot_iter->GetPet()->SetFollowID(bot_iter->GetID()); } + if (sbl.size() == 1) { Mob* follow_mob = entity_list.GetMob(sbl.front()->GetFollowID()); - Bot::BotGroupSay(sbl.front(), "Following %s", ((follow_mob) ? (follow_mob->GetCleanName()) : ("'nullptr'"))); - } - else { - if (reset) - c->Message(Chat::Yellow, "%i of your bots are following their default assignments", sbl.size()); - else - c->Message(Chat::Yellow, "%i of your bots are following %s", sbl.size(), target_mob->GetCleanName()); + Bot::BotGroupSay( + sbl.front(), + fmt::format( + "Following {}.", + follow_mob ? follow_mob->GetCleanName() : "no one" + ).c_str() + ); + } else { + if (reset) { + c->Message( + Chat::White, + fmt::format( + "{} of your bots are following their default assignments.", + sbl.size() + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "{} of your bots are following {}.", + sbl.size(), + target_mob->GetCleanName() + ).c_str() + ); + } } } @@ -3312,7 +3359,7 @@ void bot_command_guard(Client *c, const Seperator *sep) } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); return; } const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2); @@ -3346,10 +3393,15 @@ void bot_command_guard(Client *c, const Seperator *sep) } if (sbl.size() == 1) { - Bot::BotGroupSay(sbl.front(), "%suarding this position.", (clear ? "No longer g" : "G")); - } - else { - c->Message(Chat::Yellow, "%i of your bots are %sguarding their positions.", sbl.size(), (clear ? "no longer " : "")); + Bot::BotGroupSay( + sbl.front(), + fmt::format( + "{}uarding this position.", + clear ? "No longer g" : "G" + ).c_str() + ); + } else { + c->Message(Chat::White, "%i of your bots are %sguarding their positions.", sbl.size(), (clear ? "no longer " : "")); } } @@ -3423,7 +3475,7 @@ void bot_command_help(Client *c, const Seperator *sep) if (c->Admin() < command_iter.second->access) continue; - c->Message(Chat::Cyan, "%c%s - %s", BOT_COMMAND_CHAR, command_iter.first.c_str(), command_iter.second->desc == nullptr ? "[no description]" : command_iter.second->desc); + c->Message(Chat::White, "%c%s - %s", BOT_COMMAND_CHAR, command_iter.first.c_str(), command_iter.second->desc == nullptr ? "[no description]" : command_iter.second->desc); ++bot_commands_shown; } if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) { @@ -3433,7 +3485,7 @@ void bot_command_help(Client *c, const Seperator *sep) } } c->Message(Chat::White, "%d bot command%s listed.", bot_commands_shown, bot_commands_shown != 1 ? "s" : ""); - c->Message(Chat::Gray, "type %ccommand [help | usage] for more information", BOT_COMMAND_CHAR); + c->Message(Chat::White, "type %ccommand [help | usage] for more information", BOT_COMMAND_CHAR); } void bot_command_hold(Client *c, const Seperator *sep) @@ -3443,7 +3495,7 @@ void bot_command_hold(Client *c, const Seperator *sep) } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: target | byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); return; } const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2); @@ -3477,10 +3529,22 @@ void bot_command_hold(Client *c, const Seperator *sep) } if (sbl.size() == 1) { - Bot::BotGroupSay(sbl.front(), "%solding my attacks.", (clear ? "No longer h" : "H")); - } - else { - c->Message(Chat::Yellow, "%i of your bots are %sholding their attacks.", sbl.size(), (clear ? "no longer " : "")); + Bot::BotGroupSay( + sbl.front(), + fmt::format( + "{}olding my attacks.", + clear ? "No longer h" : "H" + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "{} of your bots are {}holding their attacks.", + sbl.size(), + clear ? "no longer " : "" + ).c_str() + ); } } @@ -3490,7 +3554,7 @@ void bot_command_identify(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Identify) || helper_command_alias_fail(c, "bot_command_identify", sep->arg[0], "identify")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s", sep->arg[0]); + c->Message(Chat::White, "usage: () %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Identify); return; } @@ -3547,7 +3611,7 @@ void bot_command_invisibility(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Invisibility) || helper_command_alias_fail(c, "bot_command_invisibility", sep->arg[0], "invisibility")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [invisibility: living | undead | animal | see]", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [invisibility: living | undead | animal | see]", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Invisibility); return; } @@ -3565,7 +3629,7 @@ void bot_command_invisibility(Client *c, const Seperator *sep) invisibility_type = BCEnum::IT_See; if (invisibility_type == BCEnum::IT_None) { - c->Message(Chat::Red, "You must specify an [invisibility]"); + c->Message(Chat::White, "You must specify an [invisibility]"); return; } @@ -3600,8 +3664,7 @@ void bot_command_invisibility(Client *c, const Seperator *sep) void bot_command_item_use(Client* c, const Seperator* sep) { if (helper_is_help_or_usage(sep->arg[1])) { - - c->Message(Chat::Cyan, "usage: %s ([empty])", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([empty])", sep->arg[0]); return; } @@ -3613,21 +3676,18 @@ void bot_command_item_use(Client* c, const Seperator* sep) const auto item_instance = c->GetInv().GetItem(EQ::invslot::slotCursor); if (!item_instance) { - - c->Message(Chat::Red, "No item found on cursor!"); + c->Message(Chat::White, "No item found on cursor!"); return; } auto item_data = item_instance->GetItem(); if (!item_data) { - - c->Message(Chat::Red, "No data found for cursor item!"); + c->Message(Chat::White, "No data found for cursor item!"); return; } if (item_data->ItemClass != EQ::item::ItemClassCommon || item_data->Slots == 0) { - - c->Message(Chat::Red, "'%s' is not an equipable item!", item_data->Name); + c->Message(Chat::White, "'%s' is not an equipable item!", item_data->Name); return; } @@ -3647,8 +3707,7 @@ void bot_command_item_use(Client* c, const Seperator* sep) std::list sbl; MyBots::PopulateSBL_BySpawnedBots(c, sbl); - for (auto bot_iter : sbl) { - + for (const auto& bot_iter : sbl) { if (!bot_iter) { continue; } @@ -3661,35 +3720,53 @@ void bot_command_item_use(Client* c, const Seperator* sep) text_link = bot_iter->CreateSayLink(c, msg.c_str(), bot_iter->GetCleanName()); for (auto slot_iter : equipable_slot_list) { - // needs more failure criteria - this should cover the bulk for now if (slot_iter == EQ::invslot::slotSecondary && item_data->Damage && !bot_iter->CanThisClassDualWield()) { continue; } - auto equipped_item = bot_iter->GetBotInv()[slot_iter]; + auto equipped_item = bot_iter->GetInv()[slot_iter]; if (equipped_item && !empty_only) { - linker.SetItemInst(equipped_item); c->Message( Chat::Say, - "[%s] says, 'I can use that for my %s! (replaces: [%s])'", - text_link.c_str(), - EQ::invslot::GetInvPossessionsSlotName(slot_iter), - linker.GenerateLink().c_str() + fmt::format( + "{} says, 'I can use that for my {} instead of my {}! Would you like to {} my {}?'", + text_link, + EQ::invslot::GetInvPossessionsSlotName(slot_iter), + linker.GenerateLink(), + Saylink::Silent( + fmt::format( + "^inventoryremove {} byname {}", + slot_iter, + bot_iter->GetCleanName() + ), + "remove" + ), + linker.GenerateLink() + ).c_str() ); - bot_iter->DoAnim(29); - } - else if (!equipped_item) { + bot_iter->DoAnim(29); + } else if (!equipped_item) { c->Message( Chat::Say, - "[%s] says, 'I can use that for my %s!'", - text_link.c_str(), - EQ::invslot::GetInvPossessionsSlotName(slot_iter) + fmt::format( + "{} says, 'I can use that for my {}! Would you like to {} it to me?'", + text_link, + EQ::invslot::GetInvPossessionsSlotName(slot_iter), + Saylink::Silent( + fmt::format( + "^inventorygive byname {}", + bot_iter->GetCleanName() + ), + "give" + ) + ).c_str() ); + bot_iter->DoAnim(29); } } @@ -3702,7 +3779,7 @@ void bot_command_levitation(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Levitation) || helper_command_alias_fail(c, "bot_command_levitation", sep->arg[0], "levitation")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s", sep->arg[0]); + c->Message(Chat::White, "usage: () %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Levitation); return; } @@ -3739,7 +3816,7 @@ void bot_command_lull(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Lull) || helper_command_alias_fail(c, "bot_command_lull", sep->arg[0], "lull")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Lull); return; } @@ -3781,7 +3858,7 @@ void bot_command_mesmerize(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Mesmerize) || helper_command_alias_fail(c, "bot_command_mesmerize", sep->arg[0], "mesmerize")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Mesmerize); return; } @@ -3823,7 +3900,7 @@ void bot_command_movement_speed(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_MovementSpeed) || helper_command_alias_fail(c, "bot_command_movement_speed", sep->arg[0], "movementspeed")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([group | sow])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([group | sow])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_MovementSpeed); return; } @@ -3870,7 +3947,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) { if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [option] [argument]", sep->arg[0]); + c->Message(Chat::White, "usage: %s [option] [argument]", sep->arg[0]); std::string window_title = "Bot Owner Options"; std::string window_text = @@ -3979,7 +4056,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booDeathMarquee, c->GetBotOption(Client::booDeathMarquee)); - c->Message(Chat::Yellow, "Bot 'death marquee' is now %s.", (c->GetBotOption(Client::booDeathMarquee) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'death marquee' is now %s.", (c->GetBotOption(Client::booDeathMarquee) == true ? "enabled" : "disabled")); } else if (!owner_option.compare("statsupdate")) { @@ -3995,7 +4072,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booStatsUpdate, c->GetBotOption(Client::booStatsUpdate)); - c->Message(Chat::Yellow, "Bot 'stats update' is now %s.", (c->GetBotOption(Client::booStatsUpdate) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'stats update' is now %s.", (c->GetBotOption(Client::booStatsUpdate) == true ? "enabled" : "disabled")); } else if (!owner_option.compare("spawnmessage")) { @@ -4031,7 +4108,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) } else { - c->Message(Chat::Red, "Owner option '%s' argument '%s' is not recognized.", owner_option.c_str(), argument.c_str()); + c->Message(Chat::White, "Owner option '%s' argument '%s' is not recognized.", owner_option.c_str(), argument.c_str()); return; } @@ -4059,11 +4136,11 @@ void bot_command_owner_option(Client *c, const Seperator *sep) } else { - c->Message(Chat::Yellow, "Bot 'spawn message' is now ERROR."); + c->Message(Chat::White, "Bot 'spawn message' is now ERROR."); return; } - c->Message(Chat::Yellow, "Bot 'spawn message' is now %s.", argument.c_str()); + c->Message(Chat::White, "Bot 'spawn message' is now %s.", argument.c_str()); } else if (!owner_option.compare("altcombat")) { @@ -4081,10 +4158,10 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booAltCombat, c->GetBotOption(Client::booAltCombat)); - c->Message(Chat::Yellow, "Bot 'alt combat' is now %s.", (c->GetBotOption(Client::booAltCombat) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'alt combat' is now %s.", (c->GetBotOption(Client::booAltCombat) == true ? "enabled" : "disabled")); } else { - c->Message(Chat::Red, "Bot owner option 'altcombat' is not allowed on this server."); + c->Message(Chat::White, "Bot owner option 'altcombat' is not allowed on this server."); } } else if (!owner_option.compare("autodefend")) { @@ -4103,10 +4180,10 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booAutoDefend, c->GetBotOption(Client::booAutoDefend)); - c->Message(Chat::Yellow, "Bot 'auto defend' is now %s.", (c->GetBotOption(Client::booAutoDefend) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'auto defend' is now %s.", (c->GetBotOption(Client::booAutoDefend) == true ? "enabled" : "disabled")); } else { - c->Message(Chat::Red, "Bot owner option 'autodefend' is not allowed on this server."); + c->Message(Chat::White, "Bot owner option 'autodefend' is not allowed on this server."); } } else if (!owner_option.compare("buffcounter")) { @@ -4123,7 +4200,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booBuffCounter, c->GetBotOption(Client::booBuffCounter)); - c->Message(Chat::Yellow, "Bot 'buff counter' is now %s.", (c->GetBotOption(Client::booBuffCounter) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'buff counter' is now %s.", (c->GetBotOption(Client::booBuffCounter) == true ? "enabled" : "disabled")); } else if (!owner_option.compare("monkwumessage")) { @@ -4139,7 +4216,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booMonkWuMessage, c->GetBotOption(Client::booMonkWuMessage)); - c->Message(Chat::Yellow, "Bot 'monk wu message' is now %s.", (c->GetBotOption(Client::booMonkWuMessage) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'monk wu message' is now %s.", (c->GetBotOption(Client::booMonkWuMessage) == true ? "enabled" : "disabled")); } else if (!owner_option.compare("current")) { @@ -4172,7 +4249,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) c->SendPopupToClient(window_title.c_str(), window_text.c_str()); } else { - c->Message(Chat::Red, "Owner option '%s' is not recognized.", owner_option.c_str()); + c->Message(Chat::White, "Owner option '%s' is not recognized.", owner_option.c_str()); } } @@ -4200,8 +4277,8 @@ void bot_command_pick_lock(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_command_pick_lock", sep->arg[0], "picklock")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); - c->Message(Chat::Gray, "requires one of the following bot classes:"); + c->Message(Chat::White, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "requires one of the following bot classes:"); c->Message(Chat::White, "Rogue(5) or Bard(40)"); return; } @@ -4212,14 +4289,14 @@ void bot_command_pick_lock(Client *c, const Seperator *sep) float pick_lock_value = 0.0f; ActionableBots::Filter_ByHighestPickLock(c, sbl, pick_lock_value); if (sbl.empty()) { - c->Message(Chat::Red, "No bots are capable of performing this action"); + c->Message(Chat::White, "No bots are capable of performing this action"); return; } Bot* my_bot = sbl.front(); my_bot->InterruptSpell(); - Bot::BotGroupSay(my_bot, "Attempting to pick the lock.."); + Bot::BotGroupSay(my_bot, "Attempting to pick the lock."); std::list door_list; entity_list.GetDoorsList(door_list); @@ -4246,10 +4323,10 @@ void bot_command_pick_lock(Client *c, const Seperator *sep) ++open_count; } else { - Bot::BotGroupSay(my_bot, "I am not skilled enough for this lock..."); + Bot::BotGroupSay(my_bot, "I am not skilled enough for this lock."); } } - c->Message(Chat::Yellow, "%i door%s attempted - %i door%s successful", door_count, ((door_count != 1) ? ("s") : ("")), open_count, ((open_count != 1) ? ("s") : (""))); + c->Message(Chat::White, "%i door%s attempted - %i door%s successful", door_count, ((door_count != 1) ? ("s") : ("")), open_count, ((open_count != 1) ? ("s") : (""))); } void bot_command_precombat(Client* c, const Seperator* sep) @@ -4259,13 +4336,13 @@ void bot_command_precombat(Client* c, const Seperator* sep) } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([set | clear])", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([set | clear])", sep->arg[0]); return; } if (!c->GetTarget() || !c->IsAttackAllowed(c->GetTarget())) { - c->Message(Chat::Red, "This command requires an attackable target."); + c->Message(Chat::White, "This command requires an attackable target."); return; } @@ -4281,7 +4358,7 @@ void bot_command_precombat(Client* c, const Seperator* sep) c->SetBotPrecombat(!c->GetBotPrecombat()); } - c->Message(Chat::Yellow, "Precombat flag is now %s.", (c->GetBotPrecombat() == true ? "set" : "clear")); + c->Message(Chat::White, "Precombat flag is now %s.", (c->GetBotPrecombat() == true ? "set" : "clear")); } // TODO: Rework to allow owner specificed criteria for puller @@ -4292,7 +4369,7 @@ void bot_command_pull(Client *c, const Seperator *sep) } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); return; } int ab_mask = ActionableBots::ABM_OwnerGroup; // existing behavior - need to add c->IsGrouped() check and modify code if different behavior is desired @@ -4306,13 +4383,13 @@ void bot_command_pull(Client *c, const Seperator *sep) auto target_mob = ActionableTarget::VerifyEnemy(c, BCEnum::TT_Single); if (!target_mob) { - c->Message(Chat::Red, "Your current target is not attackable!"); + c->Message(Chat::White, "Your current target is not attackable!"); return; } if (target_mob->IsNPC() && target_mob->GetHateList().size()) { - c->Message(Chat::Red, "Your current target is already engaged!"); + c->Message(Chat::White, "Your current target is already engaged!"); return; } @@ -4406,7 +4483,7 @@ void bot_command_release(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_command_release", sep->arg[0], "release")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: ] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: ] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_NoFilter; @@ -4421,7 +4498,7 @@ void bot_command_release(Client *c, const Seperator *sep) bot_iter->SetPauseAI(false); } - c->Message(Chat::Yellow, "%i of your bots %s released.", sbl.size(), ((sbl.size() != 1) ? ("are") : ("is"))); + c->Message(Chat::White, "%i of your bots %s released.", sbl.size(), ((sbl.size() != 1) ? ("are") : ("is"))); } void bot_command_resistance(Client *c, const Seperator *sep) @@ -4430,7 +4507,7 @@ void bot_command_resistance(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Resistance) || helper_command_alias_fail(c, "bot_command_resistance", sep->arg[0], "resistance")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [resistance: fire | cold | poison | disease | magic | corruption]", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [resistance: fire | cold | poison | disease | magic | corruption]", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Resistance); return; } @@ -4452,7 +4529,7 @@ void bot_command_resistance(Client *c, const Seperator *sep) resistance_type = BCEnum::RT_Corruption; if (resistance_type == BCEnum::RT_None) { - c->Message(Chat::Red, "You must specify a [resistance]"); + c->Message(Chat::White, "You must specify a [resistance]"); return; } @@ -4504,8 +4581,8 @@ void bot_command_resurrect(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Resurrect) || helper_command_alias_fail(c, "bot_command_resurrect", sep->arg[0], "resurrect")) return; if (helper_is_help_or_usage(sep->arg[1])) { - //c->Message(Chat::Cyan, "usage: %s ([option: aoe])", sep->arg[0]); - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + //c->Message(Chat::White, "usage: %s ([option: aoe])", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Resurrect); return; } @@ -4558,7 +4635,7 @@ void bot_command_rune(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Rune) || helper_command_alias_fail(c, "bot_command_rune", sep->arg[0], "rune")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s", sep->arg[0]); + c->Message(Chat::White, "usage: () %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Rune); return; } @@ -4597,7 +4674,7 @@ void bot_command_send_home(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_SendHome) || helper_command_alias_fail(c, "bot_command_send_home", sep->arg[0], "sendhome")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([option: group])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([option: group])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_SendHome); return; } @@ -4641,7 +4718,7 @@ void bot_command_size(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Size) || helper_command_alias_fail(c, "bot_command_size", sep->arg[0], "size")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [grow | shrink]", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [grow | shrink]", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Size); return; } @@ -4652,7 +4729,7 @@ void bot_command_size(Client *c, const Seperator *sep) size_type = BCEnum::SzT_Enlarge; } else if (size_arg.compare("shrink")) { - c->Message(Chat::Red, "This command requires a [grow | shrink] argument"); + c->Message(Chat::White, "This command requires a [grow | shrink] argument"); return; } @@ -4689,14 +4766,14 @@ void bot_command_summon_corpse(Client *c, const Seperator *sep) // Same methodology as old command..but, does not appear to work... (note: didn't work there, either...) // temp - c->Message(Chat::Red, "This command is currently unavailable..."); + c->Message(Chat::White, "This command is currently unavailable..."); return; bcst_list* local_list = &bot_command_spells[BCEnum::SpT_SummonCorpse]; if (helper_spell_list_fail(c, local_list, BCEnum::SpT_SummonCorpse) || helper_command_alias_fail(c, "bot_command_summon_corpse", sep->arg[0], "summoncorpse")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_SummonCorpse); return; } @@ -4736,7 +4813,7 @@ void bot_command_suspend(Client *c, const Seperator *sep) return; } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: ] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: ] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_NoFilter; @@ -4751,7 +4828,7 @@ void bot_command_suspend(Client *c, const Seperator *sep) bot_iter->SetPauseAI(true); } - c->Message(Chat::Yellow, "%i of your bots %s suspended.", sbl.size(), ((sbl.size() != 1) ? ("are") : ("is"))); + c->Message(Chat::White, "%i of your bots %s suspended.", sbl.size(), ((sbl.size() != 1) ? ("are") : ("is"))); } void bot_command_taunt(Client *c, const Seperator *sep) @@ -4759,7 +4836,7 @@ void bot_command_taunt(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_command_taunt", sep->arg[0], "taunt")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_Type1; @@ -4786,41 +4863,81 @@ void bot_command_taunt(Client *c, const Seperator *sep) int taunting_count = 0; for (auto bot_iter : sbl) { - if (!bot_iter->GetSkill(EQ::skills::SkillTaunt)) + if (!bot_iter->GetSkill(EQ::skills::SkillTaunt)) { continue; + } - if (toggle_taunt) + if (toggle_taunt) { bot_iter->SetTaunting(!bot_iter->IsTaunting()); - else + } else { bot_iter->SetTaunting(taunt_state); + } - if (sbl.size() == 1) - Bot::BotGroupSay(bot_iter, "I am %s taunting", bot_iter->IsTaunting() ? "now" : "no longer"); + if (sbl.size() == 1) { + Bot::BotGroupSay( + bot_iter, + fmt::format( + "I am {} taunting.", + bot_iter->IsTaunting() ? "now" : "no longer" + ).c_str() + ); + } ++taunting_count; } + for (auto bot_iter : sbl) { - if (!bot_iter->HasPet()) + if (!bot_iter->HasPet()) { continue; - if (!bot_iter->GetPet()->GetSkill(EQ::skills::SkillTaunt)) + } + + if (!bot_iter->GetPet()->GetSkill(EQ::skills::SkillTaunt)) { continue; - if (toggle_taunt) + } + + if (toggle_taunt) { bot_iter->GetPet()->CastToNPC()->SetTaunting(!bot_iter->GetPet()->CastToNPC()->IsTaunting()); - else + } else { bot_iter->GetPet()->CastToNPC()->SetTaunting(taunt_state); - if (sbl.size() == 1) - Bot::BotGroupSay(bot_iter, "My Pet is %s taunting", bot_iter->GetPet()->CastToNPC()->IsTaunting() ? "now" : "no longer"); + } + + if (sbl.size() == 1) { + Bot::BotGroupSay( + bot_iter, + fmt::format( + "My Pet is {} taunting.", + bot_iter->GetPet()->CastToNPC()->IsTaunting() ? "now" : "no longer" + ).c_str() + ); + } + ++taunting_count; } if (taunting_count) { - if (toggle_taunt) - c->Message(Chat::Yellow, "%i of your bots and their pets %s toggled their taunting state", taunting_count, ((taunting_count != 1) ? ("have") : ("has"))); - else - c->Message(Chat::Yellow, "%i of your bots and their pets %s %s taunting", taunting_count, ((taunting_count != 1) ? ("have") : ("has")), ((taunt_state) ? ("started") : ("stopped"))); + if (toggle_taunt) { + c->Message( + Chat::White, + fmt::format( + "{} of your bots and their pets {} toggled their taunting state", + taunting_count, + taunting_count != 1 ? "have" : "has" + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "{} of your bots and their pets {} {} taunting.", + taunting_count, + taunting_count != 1 ? "have" : "has", + taunt_state ? "started" : "stopped" + ).c_str() + ); + } } else { - c->Message(Chat::Red, "None of your bots are capable of taunting"); + c->Message(Chat::White, "None of your bots are capable of taunting"); } } @@ -4829,8 +4946,8 @@ void bot_command_track(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_command_track", sep->arg[0], "track")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s (Ranger: [option=all: all | rare | local])", sep->arg[0]); - c->Message(Chat::Gray, "requires one of the following bot classes:"); + c->Message(Chat::White, "usage: %s (Ranger: [option=all: all | rare | local])", sep->arg[0]); + c->Message(Chat::White, "requires one of the following bot classes:"); c->Message(Chat::White, "Ranger(1), Druid(20) or Bard(35)"); return; } @@ -4851,7 +4968,7 @@ void bot_command_track(Client *c, const Seperator *sep) my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 35, BARD); } if (!my_bot) { - c->Message(Chat::Red, "No bots are capable of performing this action"); + c->Message(Chat::White, "No bots are capable of performing this action"); return; } @@ -4886,7 +5003,7 @@ void bot_command_track(Client *c, const Seperator *sep) return; } if (!base_distance) { - c->Message(Chat::Magenta, "An unknown codition has occurred"); + c->Message(Chat::White, "An unknown codition has occurred"); return; } @@ -4901,7 +5018,7 @@ void bot_command_water_breathing(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_WaterBreathing) || helper_command_alias_fail(c, "bot_command_water_breathing", sep->arg[0], "waterbreathing")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s", sep->arg[0]); + c->Message(Chat::White, "usage: () %s", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_WaterBreathing); return; } @@ -4970,19 +5087,19 @@ void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_beard_color", sep->arg[0], "botbeardcolor")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n] (Dwarves or male bots only)", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n] (Dwarves or male bots only)", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5007,19 +5124,19 @@ void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_beard_style", sep->arg[0], "botbeardstyle")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n] (Dwarves or male bots only)", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n] (Dwarves or male bots only)", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5044,7 +5161,7 @@ void bot_subcommand_bot_camp(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_camp", sep->arg[0], "botcamp")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_NoFilter; @@ -5059,33 +5176,63 @@ void bot_subcommand_bot_camp(Client *c, const Seperator *sep) void bot_subcommand_bot_clone(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_bot_clone", sep->arg[0], "botclone")) + if (helper_command_alias_fail(c, "bot_subcommand_bot_clone", sep->arg[0], "botclone")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [clone_name]", sep->arg[0]); + c->Message( + Chat::White, + fmt::format( + "Usage: {} [clone_name]", + sep->arg[0] + ).c_str() + ); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must target a bot that you own to use this command!"); return; } + if (!my_bot->GetBotID()) { - c->Message(Chat::Magenta, "An unknown error has occured - BotName: %s, BotID: %u", my_bot->GetCleanName(), my_bot->GetBotID()); - LogCommands("bot_command_clone(): - Error: Active bot reported invalid ID (BotName: [{}], BotID: [{}], OwnerName: [{}], OwnerID: [{}], AcctName: [{}], AcctID: [{}])", - my_bot->GetCleanName(), my_bot->GetBotID(), c->GetCleanName(), c->CharacterID(), c->AccountName(), c->AccountID()); + c->Message( + Chat::White, + fmt::format( + "An unknown error has occured with {} (Bot ID {}).", + my_bot->GetCleanName(), + my_bot->GetBotID() + ).c_str() + ); + LogCommands( + "bot_command_clone(): - Error: Active bot reported invalid ID (BotName: [{}], BotID: [{}], OwnerName: [{}], OwnerID: [{}], AcctName: [{}], AcctID: [{}])", + my_bot->GetCleanName(), + my_bot->GetBotID(), + c->GetCleanName(), + c->CharacterID(), + c->AccountName(), + c->AccountID() + ); return; } if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { - c->Message(Chat::Red, "You must [name] your bot clone"); + c->Message(Chat::White, "You must name your bot clone."); return; } + std::string bot_name = sep->arg[1]; if (!Bot::IsValidName(bot_name)) { - c->Message(Chat::Red, "'%s' is an invalid name. You may only use characters 'A-Z', 'a-z' and '_'", bot_name.c_str()); + c->Message( + Chat::White, + fmt::format( + "'{}' is an invalid name. You may only use characters 'A-Z', 'a-z' and '_'.", + bot_name + ).c_str() + ); return; } @@ -5093,46 +5240,130 @@ void bot_subcommand_bot_clone(Client *c, const Seperator *sep) bool available_flag = false; if (!database.botdb.QueryNameAvailablity(bot_name, available_flag)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::QueryNameAvailablity()); - return; - } - if (!available_flag) { - c->Message(Chat::Red, "The name %s is already being used. Please choose a different name", bot_name.c_str()); + c->Message( + Chat::White, + fmt::format( + "Failed to query name availability for '{}'.", + bot_name + ).c_str() + ); return; } - uint32 max_bot_count = RuleI(Bots, CreationLimit); + if (!available_flag) { + c->Message( + Chat::White, + fmt::format( + "The name '{}' is already being used. Please choose a different name.", + bot_name + ).c_str() + ); + return; + } + + auto bot_creation_limit = c->GetBotCreationLimit(); + auto bot_creation_limit_class = c->GetBotCreationLimit(my_bot->GetClass()); uint32 bot_count = 0; - if (!database.botdb.QueryBotCount(c->CharacterID(), bot_count)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::QueryBotCount()); + uint32 bot_class_count = 0; + if (!database.botdb.QueryBotCount(c->CharacterID(), my_bot->GetClass(), bot_count, bot_class_count)) { + c->Message(Chat::White, "Failed to query bot count."); return; } - if (bot_count >= max_bot_count) { - c->Message(Chat::Red, "You have reached the maximum limit of %i bots", max_bot_count); + + if (bot_creation_limit >= 0 && bot_count >= bot_creation_limit) { + std::string message; + + if (bot_creation_limit) { + message = fmt::format( + "You have reached the maximum limit of {} bot{}.", + bot_creation_limit, + bot_creation_limit != 1 ? "s" : "" + ); + } else { + message = "You cannot create any bots."; + } + + c->Message(Chat::White, message.c_str()); + return; + } + + if (bot_creation_limit_class >= 0 && bot_class_count >= bot_creation_limit_class) { + std::string message; + + if (bot_creation_limit_class) { + message = fmt::format( + "You cannot create anymore than {} {} bot{}.", + bot_creation_limit_class, + GetClassIDName(my_bot->GetClass()), + bot_creation_limit_class != 1 ? "s" : "" + ); + } else { + message = fmt::format( + "You cannot create any {} bots.", + GetClassIDName(my_bot->GetClass()) + ); + } + + c->Message(Chat::White, message.c_str()); return; } uint32 clone_id = 0; if (!database.botdb.CreateCloneBot(c->CharacterID(), my_bot->GetBotID(), bot_name, clone_id) || !clone_id) { - c->Message(Chat::Red, "%s '%s'", BotDatabase::fail::CreateCloneBot(), bot_name.c_str()); + c->Message( + Chat::White, + fmt::format( + "Failed to create clone bot '{}'.", + bot_name + ).c_str() + ); return; } int clone_stance = EQ::constants::stancePassive; - if (!database.botdb.LoadStance(my_bot->GetBotID(), clone_stance)) - c->Message(Chat::Red, "%s for bot '%s'", BotDatabase::fail::LoadStance(), my_bot->GetCleanName()); - if (!database.botdb.SaveStance(clone_id, clone_stance)) - c->Message(Chat::Red, "%s for clone '%s'", BotDatabase::fail::SaveStance(), bot_name.c_str()); + if (!database.botdb.LoadStance(my_bot->GetBotID(), clone_stance)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load stance from '{}'.", + my_bot->GetCleanName() + ).c_str() + ); + } - if (!database.botdb.CreateCloneBotInventory(c->CharacterID(), my_bot->GetBotID(), clone_id)) - c->Message(Chat::Red, "%s for clone '%s'", BotDatabase::fail::CreateCloneBotInventory(), bot_name.c_str()); + if (!database.botdb.SaveStance(clone_id, clone_stance)) { + c->Message( + Chat::White, + fmt::format( + "Failed to save stance for clone '{}'.", + bot_name + ).c_str() + ); + } - c->Message(Chat::Yellow, "Bot '%s' was successfully cloned to bot '%s'", my_bot->GetCleanName(), bot_name.c_str()); + if (!database.botdb.CreateCloneBotInventory(c->CharacterID(), my_bot->GetBotID(), clone_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to create clone bot inventory for clone '{}'.", + bot_name + ).c_str() + ); + } + + c->Message( + Chat::White, + fmt::format( + "Bot Cloned | From: {} To: {}", + my_bot->GetCleanName(), + bot_name + ).c_str() + ); } void bot_command_view_combos(Client *c, const Seperator *sep) -{ +{ const std::string class_substrs[17] = { "", "%u (WAR)", "%u (CLR)", "%u (PAL)", "%u (RNG)", "%u (SHD)", "%u (DRU)", "%u (MNK)", "%u (BRD)", @@ -5159,7 +5390,7 @@ void bot_command_view_combos(Client *c, const Seperator *sep) std::string window_title = "Bot Races"; std::string window_text; std::string message_separator = " "; - c->Message(Chat::Cyan, "Usage: %s [bot_race]", sep->arg[0]); + c->Message(Chat::White, "Usage: %s [bot_race]", sep->arg[0]); window_text.append("Races:"); for (int race_id = 0; race_id <= 15; ++race_id) { window_text.append(message_separator); @@ -5171,7 +5402,7 @@ void bot_command_view_combos(Client *c, const Seperator *sep) } if (sep->arg[1][0] == '\0' || !sep->IsNumber(1)) { - c->Message(Chat::Red, "Invalid Race!"); + c->Message(Chat::White, "Invalid Race!"); return; } uint16 bot_race = atoi(sep->arg[1]); @@ -5180,7 +5411,7 @@ void bot_command_view_combos(Client *c, const Seperator *sep) std::string window_title = "Bot Classes"; std::string window_text; std::string message_separator = " "; - c->Message(Chat::Cyan, "%s can be these classes.", race_name); + c->Message(Chat::White, "%s can be these classes.", race_name); window_text.append("Classes:"); for (int class_id = 0; class_id <= 15; ++class_id) { if (classes_bitmask & GetPlayerClassBit(class_id)) { @@ -5195,21 +5426,24 @@ void bot_command_view_combos(Client *c, const Seperator *sep) void bot_subcommand_bot_create(Client *c, const Seperator *sep) { - const std::string class_substrs[17] = { "", - "%u (WAR)", "%u (CLR)", "%u (PAL)", "%u (RNG)", - "%u (SHD)", "%u (DRU)", "%u (MNK)", "%u (BRD)", - "%u (ROG)", "%u (SHM)", "%u (NEC)", "%u (WIZ)", - "%u (MAG)", "%u (ENC)", "%u (BST)", "%u (BER)" + const std::string class_substrs[17] = { + "", + "{} (WAR)", "{} (CLR)", "{} (PAL)", "{} (RNG)", + "{} (SHD)", "{} (DRU)", "{} (MNK)", "{} (BRD)", + "{} (ROG)", "{} (SHM)", "{} (NEC)", "{} (WIZ)", + "{} (MAG)", "{} (ENC)", "{} (BST)", "{} (BER)" }; - const std::string race_substrs[17] = { "", - "%u (HUM)", "%u (BAR)", "%u (ERU)", "%u (ELF)", - "%u (HIE)", "%u (DEF)", "%u (HEF)", "%u (DWF)", - "%u (TRL)", "%u (OGR)", "%u (HFL)", "%u (GNM)", - "%u (IKS)", "%u (VAH)", "%u (FRG)", "%u (DRK)" + const std::string race_substrs[17] = { + "", + "{} (HUM)", "{} (BAR)", "{} (ERU)", "{} (ELF)", + "{} (HIE)", "{} (DEF)", "{} (HEF)", "{} (DWF)", + "{} (TRL)", "{} (OGR)", "{} (HFL)", "{} (GNM)", + "{} (IKS)", "{} (VAH)", "{} (FRG)", "{} (DRK)" }; - const uint16 race_values[17] = { 0, + const uint16 race_values[17] = { + 0, HUMAN, BARBARIAN, ERUDITE, WOOD_ELF, HIGH_ELF, DARK_ELF, HALF_ELF, DWARF, TROLL, OGRE, HALFLING, GNOME, @@ -5217,86 +5451,137 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep) }; const std::string gender_substrs[2] = { - "%u (M)", "%u (F)", + "{} (M)", "{} (F)", }; - if (helper_command_alias_fail(c, "bot_subcommand_bot_create", sep->arg[0], "botcreate")) + if (helper_command_alias_fail(c, "bot_subcommand_bot_create", sep->arg[0], "botcreate")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [bot_name] [bot_class] [bot_race] [bot_gender]", sep->arg[0]); - std::string window_title = "Bot Create Options"; + c->Message( + Chat::White, + fmt::format( + "Usage: {} [bot_name] [bot_class] [bot_race] [bot_gender]", + sep->arg[0] + ).c_str() + ); + std::string window_text; std::string message_separator; int object_count = 0; const int object_max = 5; window_text.append("Classes:"); + message_separator = " "; object_count = 1; for (int i = 0; i <= 15; ++i) { window_text.append(message_separator); + if (object_count >= object_max) { window_text.append("
"); object_count = 0; } - window_text.append(StringFormat(class_substrs[i + 1].c_str(), (i + 1))); + + window_text.append( + fmt::format("{} {}", + class_substrs[i + 1], + (i + 1) + ) + ); + ++object_count; message_separator = ", "; } + window_text.append("

"); window_text.append("Races:"); + message_separator = " "; object_count = 1; for (int i = 0; i <= 15; ++i) { window_text.append(message_separator); + if (object_count >= object_max) { window_text.append("
"); object_count = 0; } - window_text.append(StringFormat(race_substrs[i + 1].c_str(), race_values[i + 1])); + + window_text.append( + fmt::format("{}, {}", + race_substrs[i + 1], + race_values[i + 1] + ) + ); + ++object_count; message_separator = ", "; } + window_text.append("

"); window_text.append("Genders:"); + message_separator = " "; for (int i = 0; i <= 1; ++i) { window_text.append(message_separator); - window_text.append(StringFormat(gender_substrs[i].c_str(), i)); + + window_text.append( + fmt::format("{}, {}", + gender_substrs[i], + i + ) + ); + message_separator = ", "; } - - c->SendPopupToClient(window_title.c_str(), window_text.c_str()); + c->SendPopupToClient("Bot Create Options", window_text.c_str()); return; } - if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { - c->Message(Chat::Red, "You must [name] your bot"); + auto arguments = sep->argnum; + + if (!arguments || sep->IsNumber(1)) { + c->Message(Chat::White, "You must name your bot!"); return; } + std::string bot_name = sep->arg[1]; - bot_name = ucfirst(bot_name); - if (sep->arg[2][0] == '\0' || !sep->IsNumber(2)) { - c->Message(Chat::Red, "Invalid Class!"); + bot_name = Strings::UcFirst(bot_name); + if (arguments < 2 || !sep->IsNumber(2)) { + c->Message(Chat::White, "Invalid class!"); return; } - uint8 bot_class = atoi(sep->arg[2]); - if (sep->arg[3][0] == '\0' || !sep->IsNumber(3)) { - c->Message(Chat::Red, "Invalid Race!"); - return; - } - uint16 bot_race = atoi(sep->arg[3]); + auto bot_class = static_cast(std::stoul(sep->arg[2])); - if (sep->arg[4][0] == '\0') { - c->Message(Chat::Red, "Invalid Gender!"); + if (arguments < 3 || !sep->IsNumber(3)) { + c->Message(Chat::White, "Invalid race!"); return; } - uint8 bot_gender = atoi(sep->arg[4]); + + auto bot_race = static_cast(std::stoul(sep->arg[3])); + + if (arguments < 4) { + c->Message(Chat::White, "Invalid gender!"); + return; + } + + auto bot_gender = 0; + + if (sep->IsNumber(4)) { + bot_gender = static_cast(std::stoul(sep->arg[4])); + } else { + if (!strcasecmp(sep->arg[4], "m") || !strcasecmp(sep->arg[4], "male")) { + bot_gender = 0; + } else if (!strcasecmp(sep->arg[4], "f") || !strcasecmp(sep->arg[4], "female")) { + bot_gender = 1; + } + } helper_bot_create(c, bot_name, bot_class, bot_race, bot_gender); } @@ -5306,20 +5591,20 @@ void bot_subcommand_bot_delete(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_delete", sep->arg[0], "botdelete")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } std::string error_message; if (!my_bot->DeleteBot()) { - c->Message(Chat::Magenta, "Failed to delete '%s' due to database error", my_bot->GetCleanName()); + c->Message(Chat::White, "Failed to delete '%s' due to database error", my_bot->GetCleanName()); return; } @@ -5328,7 +5613,7 @@ void bot_subcommand_bot_delete(Client *c, const Seperator *sep) my_bot->Camp(false); - c->Message(Chat::Yellow, "Successfully deleted bot '%s' (id: %i)", bot_name.c_str(), bid); + c->Message(Chat::White, "Successfully deleted bot '%s' (id: %i)", bot_name.c_str(), bid); } void bot_subcommand_bot_details(Client *c, const Seperator *sep) @@ -5338,19 +5623,19 @@ void bot_subcommand_bot_details(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_details", sep->arg[0], "botdetails")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5384,20 +5669,20 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) EQ::textures::armorLegs, EQ::textures::armorFeet ); - + if (helper_command_alias_fail(c, "bot_subcommand_bot_dye_armor", sep->arg[0], "botdyearmor")) { return; } if (helper_is_help_or_usage(sep->arg[1])) { c->Message( - Chat::Cyan, + Chat::White, fmt::format( "Usage: {} [Material Slot] [Red: 0-255] [Green: 0-255] [Blue: 0-255] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0] ).c_str() ); - c->Message(Chat::Gray, material_slot_message.c_str()); + c->Message(Chat::White, material_slot_message.c_str()); return; } const int ab_mask = ActionableBots::ABM_NoFilter; @@ -5411,14 +5696,14 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) slot_id = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot); if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQ::textures::LastTintableTexture) { - c->Message(Chat::Red, "Valid material slots for this command are:"); - c->Message(Chat::Red, material_slot_message.c_str()); + c->Message(Chat::White, "Valid material slots for this command are:"); + c->Message(Chat::White, material_slot_message.c_str()); return; } } if (!sep->IsNumber(2)) { - c->Message(Chat::Red, "Valid Red values for this command are 0 to 255."); + c->Message(Chat::White, "Valid Red values for this command are 0 to 255."); return; } @@ -5428,7 +5713,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } if (!sep->IsNumber(3)) { - c->Message(Chat::Red, "Valid Green values for this command are 0 to 255."); + c->Message(Chat::White, "Valid Green values for this command are 0 to 255."); return; } @@ -5438,7 +5723,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } if (!sep->IsNumber(4)) { - c->Message(Chat::Red, "Valid Blue values for this command are 0 to 255."); + c->Message(Chat::White, "Valid Blue values for this command are 0 to 255."); return; } @@ -5462,7 +5747,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) if (!bot_iter->DyeArmor(slot_id, rgb_value, dye_all, (ab_type != ActionableBots::ABT_All))) { c->Message( - Chat::Red, + Chat::White, fmt::format( "Failed to change armor color for {} due to unknown cause.", bot_iter->GetCleanName() @@ -5476,7 +5761,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) if (dye_all) { if (!database.botdb.SaveAllArmorColors(c->CharacterID(), rgb_value)) { c->Message( - Chat::Red, + Chat::White, fmt::format( "{}", BotDatabase::fail::SaveAllArmorColors() @@ -5486,7 +5771,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } else { if (!database.botdb.SaveAllArmorColorBySlot(c->CharacterID(), slot_id, rgb_value)) { c->Message( - Chat::Red, + Chat::White, fmt::format( "{}", BotDatabase::fail::SaveAllArmorColorBySlot() @@ -5505,20 +5790,20 @@ void bot_subcommand_bot_eyes(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_eyes", sep->arg[0], "boteyes")) return; if (helper_is_help_or_usage(sep->arg[1])) { - //c->Message(Chat::Cyan, "usage: %s [value:0-n] ([option: left | right])", sep->arg[0]); - c->Message(Chat::Cyan, "usage: %s [value: 0-n]", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + //c->Message(Chat::White, "usage: %s [value:0-n] ([option: left | right])", sep->arg[0]); + c->Message(Chat::White, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5551,7 +5836,7 @@ void bot_subcommand_bot_eyes(Client *c, const Seperator *sep) if (helper_bot_appearance_fail(c, my_bot, fail_type, "eyes")) return; - c->Message(Chat::Yellow, "This feature will update the next time your bot is spawned"); + c->Message(Chat::White, "This feature will update the next time your bot is spawned"); //helper_bot_appearance_form_final(c, my_bot); } @@ -5560,19 +5845,19 @@ void bot_subcommand_bot_face(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_face", sep->arg[0], "botface")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n]", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5600,8 +5885,8 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_follow_distance", sep->arg[0], "botfollowdistance")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [set] [distance] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); - c->Message(Chat::Cyan, "usage: %s [clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s [set] [distance] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s [clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_NoFilter; @@ -5612,7 +5897,7 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) if (!strcasecmp(sep->arg[1], "set")) { if (!sep->IsNumber(2)) { - c->Message(Chat::Red, "A numeric [distance] is required to use this command"); + c->Message(Chat::White, "A numeric [distance] is required to use this command"); return; } @@ -5625,7 +5910,7 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) ab_arg = 3; } else if (strcasecmp(sep->arg[1], "clear")) { - c->Message(Chat::Red, "This command requires a [set | clear] argument"); + c->Message(Chat::White, "This command requires a [set | clear] argument"); return; } @@ -5641,7 +5926,7 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) bot_iter->SetFollowDistance(bfd); if (ab_type != ActionableBots::ABT_All && !database.botdb.SaveFollowDistance(c->CharacterID(), bot_iter->GetBotID(), bfd)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveFollowDistance(), bot_iter->GetCleanName()); + c->Message(Chat::White, "%s for '%s'", BotDatabase::fail::SaveFollowDistance(), bot_iter->GetCleanName()); return; } @@ -5650,14 +5935,14 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) if (ab_type == ActionableBots::ABT_All) { if (!database.botdb.SaveAllFollowDistances(c->CharacterID(), bfd)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::SaveAllFollowDistances()); + c->Message(Chat::White, "%s", BotDatabase::fail::SaveAllFollowDistances()); return; } - c->Message(Chat::Yellow, "%s all of your bot follow distances", set_flag ? "Set" : "Cleared"); + c->Message(Chat::White, "%s all of your bot follow distances", set_flag ? "Set" : "Cleared"); } else { - c->Message(Chat::Yellow, "%s %i of your spawned bot follow distances", (set_flag ? "Set" : "Cleared"), bot_count); + c->Message(Chat::White, "%s %i of your spawned bot follow distances", (set_flag ? "Set" : "Cleared"), bot_count); } } @@ -5666,19 +5951,19 @@ void bot_subcommand_bot_hair_color(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_hair_color", sep->arg[0], "bothaircolor")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n]", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5701,19 +5986,19 @@ void bot_subcommand_bot_hairstyle(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_hairstyle", sep->arg[0], "bothairstyle")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n]", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5738,19 +6023,19 @@ void bot_subcommand_bot_heritage(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_heritage", sep->arg[0], "botheritage")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -5775,8 +6060,8 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_inspect_message", sep->arg[0], "botinspectmessage")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); - c->Message(Chat::Gray, "Notes:"); + c->Message(Chat::White, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "Notes:"); if (c->ClientVersion() >= EQ::versions::ClientVersion::SoF) { c->Message(Chat::White, "- Self-inspect and type your bot's inspect message"); c->Message(Chat::White, "- Close the self-inspect window to update the server"); @@ -5797,7 +6082,7 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep) set_flag = true; } else if (strcasecmp(sep->arg[1], "clear")) { - c->Message(Chat::Yellow, "This command requires a [set | clear] argument"); + c->Message(Chat::White, "This command requires a [set | clear] argument"); return; } @@ -5819,7 +6104,7 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep) memcpy(bot_message_struct, client_message_struct, sizeof(InspectMessage_Struct)); if (ab_type != ActionableBots::ABT_All && !database.botdb.SaveInspectMessage(bot_iter->GetBotID(), *bot_message_struct)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveInspectMessage(), bot_iter->GetCleanName()); + c->Message(Chat::White, "%s for '%s'", BotDatabase::fail::SaveInspectMessage(), bot_iter->GetCleanName()); return; } @@ -5833,30 +6118,45 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep) memcpy(&bot_message_struct, client_message_struct, sizeof(InspectMessage_Struct)); if (!database.botdb.SaveAllInspectMessages(c->CharacterID(), bot_message_struct)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::SaveAllInspectMessages()); + c->Message(Chat::White, "%s", BotDatabase::fail::SaveAllInspectMessages()); return; } - c->Message(Chat::Yellow, "%s all of your bot inspect messages", set_flag ? "Set" : "Cleared"); + c->Message(Chat::White, "%s all of your bot inspect messages", set_flag ? "Set" : "Cleared"); } else { - c->Message(Chat::Yellow, "%s %i of your spawned bot inspect messages", set_flag ? "Set" : "Cleared", bot_count); + c->Message(Chat::White, "%s %i of your spawned bot inspect messages", set_flag ? "Set" : "Cleared", bot_count); } } void bot_subcommand_bot_list(Client *c, const Seperator *sep) { - // TODO: Consider re-working to use player race values instead of actual race + enum { + FilterClass, + FilterRace, + FilterName, + FilterCount, + MaskClass = (1 << FilterClass), + MaskRace = (1 << FilterRace), + MaskName = (1 << FilterName) + }; - enum { FilterClass, FilterRace, FilterName, FilterCount, MaskClass = (1 << FilterClass), MaskRace = (1 << FilterRace), MaskName = (1 << FilterName) }; - - if (helper_command_alias_fail(c, "bot_subcommand_bot_list", sep->arg[0], "botlist")) - return; - if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s (account) ([class] [value]) ([race] [value]) ([name] [partial-full])", sep->arg[0]); - c->Message(Chat::Gray, "note: filter criteria is orderless and optional"); + if (helper_command_alias_fail(c, "bot_subcommand_bot_list", sep->arg[0], "botlist")) { return; } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} (account) ([class] [value]) ([race] [value]) ([name] [partial-full])", + sep->arg[0] + ).c_str() + ); + c->Message(Chat::White, "Note: Filter criteria is orderless and optional."); + return; + } + bool Account = false; int seps = 1; uint32 filter_value[FilterCount]; @@ -5864,81 +6164,150 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep) memset(&filter_value, 0, sizeof(uint32) * FilterCount); int filter_mask = 0; - if (strcasecmp(sep->arg[1], "account") == 0) { + if (!strcasecmp(sep->arg[1], "account")) { Account = true; seps = 2; } + for (int i = seps; i < (FilterCount * 2); i += 2) { - if (sep->arg[i][0] == '\0') + if (sep->arg[i][0] == '\0') { break; + } if (!strcasecmp(sep->arg[i], "class")) { filter_mask |= MaskClass; filter_value[FilterClass] = atoi(sep->arg[i + 1]); continue; } + if (!strcasecmp(sep->arg[i], "race")) { filter_mask |= MaskRace; filter_value[FilterRace] = atoi(sep->arg[i + 1]); continue; } + if (!strcasecmp(sep->arg[i], "name")) { filter_mask |= MaskName; name_criteria_arg = (i + 1); continue; } - c->Message(Chat::Red, "A numeric value or name is required to use the filter property of this command (f: '%s', v: '%s')", sep->arg[i], sep->arg[i + 1]); + c->Message(Chat::White, "A numeric value or name is required to use the filter property of this command (f: '%s', v: '%s')", sep->arg[i], sep->arg[i + 1]); return; } std::list bots_list; if (!database.botdb.LoadBotsList(c->CharacterID(), bots_list, Account)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadBotsList()); - return; - } - if (bots_list.empty()) { - c->Message(Chat::Red, "You have no bots"); + c->Message(Chat::White, "%s", BotDatabase::fail::LoadBotsList()); return; } - int bot_count = 0; - int bots_owned = 0; + if (bots_list.empty()) { + c->Message(Chat::White, "You have no bots."); + return; + } + + auto bot_count = 0; + auto bots_owned = 0; + auto bot_number = 1; for (auto bots_iter : bots_list) { if (filter_mask) { - if ((filter_mask & MaskClass) && filter_value[FilterClass] != bots_iter.Class) + if ((filter_mask & MaskClass) && filter_value[FilterClass] != bots_iter.Class) { continue; - if ((filter_mask & MaskRace) && filter_value[FilterRace] != bots_iter.Race) + } + + if ((filter_mask & MaskRace) && filter_value[FilterRace] != bots_iter.Race) { continue; + } + if (filter_mask & MaskName) { std::string name_criteria = sep->arg[name_criteria_arg]; std::transform(name_criteria.begin(), name_criteria.end(), name_criteria.begin(), ::tolower); std::string name_check = bots_iter.Name; std::transform(name_check.begin(), name_check.end(), name_check.begin(), ::tolower); - if (name_check.find(name_criteria) == std::string::npos) + if (name_check.find(name_criteria) == std::string::npos) { continue; + } } } - Bot * botCheckNotOnline = entity_list.GetBotByBotName(bots_iter.Name); - std::string botspawn_saylink = StringFormat("^botspawn %s", bots_iter.Name); - c->Message(Chat::White, "[%s] is a level %u %s %s %s who is owned by %s", - ((c->CharacterID() == bots_iter.Owner_ID) && (!botCheckNotOnline) ? (EQ::SayLinkEngine::GenerateQuestSaylink(botspawn_saylink, false, bots_iter.Name).c_str()) : (bots_iter.Name)), - bots_iter.Level, - GetRaceIDName(bots_iter.Race), - ((bots_iter.Gender == FEMALE) ? ("Female") : ((bots_iter.Gender == MALE) ? ("Male") : ("Neuter"))), - GetClassIDName(bots_iter.Class), - bots_iter.Owner + + auto* bot = entity_list.GetBotByBotName(bots_iter.Name); + + c->Message( + Chat::White, + fmt::format( + "Bot {} | {} is a Level {} {} {} {} owned by {}.", + bot_number, + ( + (c->CharacterID() == bots_iter.Owner_ID && !bot) ? + Saylink::Silent( + fmt::format("^spawn {}", bots_iter.Name), + bots_iter.Name + ) : + bots_iter.Name + ), + bots_iter.Level, + GetGenderName(bots_iter.Gender), + GetRaceIDName(bots_iter.Race), + GetClassIDName(bots_iter.Class), + bots_iter.Owner + ).c_str() ); - if (c->CharacterID() == bots_iter.Owner_ID) { ++bots_owned; } - ++bot_count; + + if (c->CharacterID() == bots_iter.Owner_ID) { + bots_owned++; + } + + bot_count++; + bot_number++; } + if (!bot_count) { - c->Message(Chat::Red, "You have no bots meeting this criteria"); - } - else { - c->Message(Chat::Yellow, "%i of %i bot%s shown.", bot_count, bots_list.size(), ((bot_count != 1) ? ("s") : (""))); - c->Message(Chat::Yellow, "%i of %i bot%s are owned by you. (You may spawn any available by clicking name)", bots_owned, bot_count, ((bot_count != 1) ? ("s") : (""))); - c->Message(Chat::White, "Your limit is %i bot%s", RuleI(Bots, CreationLimit), ((RuleI(Bots, CreationLimit) != 1) ? ("s") : (""))); + c->Message(Chat::White, "You have no bots meeting this criteria."); + return; + } else { + c->Message( + Chat::White, + fmt::format( + "{} Of {} bot{} shown, {} {} owned by you.", + bot_count, + bots_list.size(), + bot_count != 1 ? "s" : "", + bots_owned, + bots_owned != 1 ? "are" : "is" + ).c_str() + ); + + c->Message(Chat::White, "Note: You can spawn any owned bots by clicking their name if they are not already spawned."); + + c->Message(Chat::White, "Your bot creation limits are as follows:"); + + const auto overall_bot_creation_limit = c->GetBotCreationLimit(); + + c->Message( + Chat::White, + fmt::format( + "Overall | {} Bot{}", + overall_bot_creation_limit, + overall_bot_creation_limit != 1 ? "s" : "" + ).c_str() + ); + + for (uint8 class_id = WARRIOR; class_id <= BERSERKER; class_id++) { + auto class_creation_limit = c->GetBotCreationLimit(class_id); + + if (class_creation_limit != overall_bot_creation_limit) { + c->Message( + Chat::White, + fmt::format( + "{} | {} Bot{}", + GetClassIDName(class_id), + class_creation_limit, + class_creation_limit != 1 ? "s" : "" + ).c_str() + ); + } + } } } @@ -5947,7 +6316,7 @@ void bot_subcommand_bot_out_of_combat(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_out_of_combat", sep->arg[0], "botoutofcombat")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); @@ -5987,16 +6356,16 @@ void bot_subcommand_bot_out_of_combat(Client *c, const Seperator *sep) void bot_subcommand_bot_surname(Client *c, const Seperator *sep) { if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { - c->Message(Chat::Red, "You must specify a [surname] to use this command (use _ to define spaces or -remove to clear.)"); + c->Message(Chat::White, "You must specify a [surname] to use this command (use _ to define spaces or -remove to clear.)"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (strlen(sep->arg[1]) > 31) { - c->Message(Chat::Red, "Surname must be 31 characters or less."); + c->Message(Chat::White, "Surname must be 31 characters or less."); return; } std::string bot_surname = sep->arg[1]; @@ -6005,26 +6374,26 @@ void bot_subcommand_bot_surname(Client *c, const Seperator *sep) my_bot->SetSurname(bot_surname); if (!database.botdb.SaveBot(my_bot)) { - c->Message(Chat::Red, BotDatabase::fail::SaveBot()); + c->Message(Chat::White, BotDatabase::fail::SaveBot()); } else { - c->Message(Chat::Yellow, "Bot Surname Saved."); + c->Message(Chat::White, "Bot Surname Saved."); } } void bot_subcommand_bot_title(Client *c, const Seperator *sep) { if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { - c->Message(Chat::Red, "You must specify a [title] to use this command. (use _ to define spaces or -remove to clear.)"); + c->Message(Chat::White, "You must specify a [title] to use this command. (use _ to define spaces or -remove to clear.)"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (strlen(sep->arg[1]) > 31) { - c->Message(Chat::Red, "Title must be 31 characters or less."); + c->Message(Chat::White, "Title must be 31 characters or less."); return; } std::string bot_title = sep->arg[1]; @@ -6033,26 +6402,26 @@ void bot_subcommand_bot_title(Client *c, const Seperator *sep) my_bot->SetTitle(bot_title); if (!database.botdb.SaveBot(my_bot)) { - c->Message(Chat::Red, BotDatabase::fail::SaveBot()); + c->Message(Chat::White, BotDatabase::fail::SaveBot()); } else { - c->Message(Chat::Yellow, "Bot Title Saved."); + c->Message(Chat::White, "Bot Title Saved."); } } void bot_subcommand_bot_suffix(Client *c, const Seperator *sep) { if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { - c->Message(Chat::Red, "You must specify a [suffix] to use this command. (use _ to define spaces or -remove to clear.)"); + c->Message(Chat::White, "You must specify a [suffix] to use this command. (use _ to define spaces or -remove to clear.)"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (strlen(sep->arg[1]) > 31) { - c->Message(Chat::Red, "Suffix must be 31 characters or less."); + c->Message(Chat::White, "Suffix must be 31 characters or less."); return; } std::string bot_suffix = sep->arg[1]; @@ -6061,10 +6430,10 @@ void bot_subcommand_bot_suffix(Client *c, const Seperator *sep) my_bot->SetSuffix(bot_suffix); if (!database.botdb.SaveBot(my_bot)) { - c->Message(Chat::Red, BotDatabase::fail::SaveBot()); + c->Message(Chat::White, BotDatabase::fail::SaveBot()); } else { - c->Message(Chat::Yellow, "Bot Suffix Saved."); + c->Message(Chat::White, "Bot Suffix Saved."); } } @@ -6073,7 +6442,7 @@ void bot_subcommand_bot_report(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_report", sep->arg[0], "botreport")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_NoFilter; @@ -6110,66 +6479,149 @@ void bot_subcommand_bot_report(Client *c, const Seperator *sep) void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_bot_spawn", sep->arg[0], "botspawn")) - return; - if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [bot_name]", sep->arg[0]); + if (helper_command_alias_fail(c, "bot_subcommand_bot_spawn", sep->arg[0], "botspawn")) { return; } - int rule_level = RuleI(Bots, BotCharacterLevel); - if (c->GetLevel() < rule_level) { - c->Message(Chat::Red, "You must be level %i to use bots", rule_level); + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [bot_name]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto bot_character_level = c->GetBotRequiredLevel(); + if ( + bot_character_level >= 0 && + c->GetLevel() < bot_character_level && + !c->GetGM() + ) { + c->Message( + Chat::White, + fmt::format( + "You must be level {} to spawn bots.", + bot_character_level + ).c_str() + ); return; } if (c->GetFeigned()) { - c->Message(Chat::Red, "You can not spawn a bot while feigned"); + c->Message(Chat::White, "You cannot spawn a bot while feigned."); return; } - int spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID()); + auto bot_spawn_limit = c->GetBotSpawnLimit(); + auto spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID()); - int rule_limit = RuleI(Bots, SpawnLimit); - if (spawned_bot_count >= rule_limit && !c->GetGM()) { - c->Message(Chat::Red, "You can not have more than %i spawned bots", rule_limit); + if ( + bot_spawn_limit >= 0 && + spawned_bot_count >= bot_spawn_limit && + !c->GetGM() + ) { + std::string message; + if (bot_spawn_limit) { + message = fmt::format( + "You cannot have more than {} spawned bot{}.", + bot_spawn_limit, + bot_spawn_limit != 1 ? "s" : "" + ); + } else { + message = "You are not currently allowed to spawn any bots."; + } + + c->Message(Chat::White, message.c_str()); return; } - if (RuleB(Bots, QuestableSpawnLimit) && !c->GetGM()) { - int allowed_bot_count = 0; - if (!database.botdb.LoadQuestableSpawnCount(c->CharacterID(), allowed_bot_count)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadQuestableSpawnCount()); - return; - } - if (!allowed_bot_count) { - c->Message(Chat::Red, "You are not currently allowed any spawned bots"); - return; - } - if (spawned_bot_count >= allowed_bot_count) { - c->Message(Chat::Red, "You have reached your current limit of %i spawned bots", allowed_bot_count); - return; - } - } - if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { - c->Message(Chat::Red, "You must specify a [name] to use this command"); + c->Message(Chat::White, "You must specify a name to use this command."); return; } + std::string bot_name = sep->arg[1]; uint32 bot_id = 0; - if (!database.botdb.LoadBotID(c->CharacterID(), bot_name, bot_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotID(), bot_name.c_str()); + uint8 bot_class = NO_CLASS; + if (!database.botdb.LoadBotID(c->CharacterID(), bot_name, bot_id, bot_class)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot ID for '{}'.", + bot_name + ).c_str() + ); return; } + + auto bot_spawn_limit_class = c->GetBotSpawnLimit(bot_class); + auto spawned_bot_count_class = Bot::SpawnedBotCount(c->CharacterID(), bot_class); + + if ( + bot_spawn_limit_class >= 0 && + spawned_bot_count_class >= bot_spawn_limit_class && + !c->GetGM() + ) { + std::string message; + + if (bot_spawn_limit_class) { + message = fmt::format( + "You cannot have more than {} spawned {} bot{}.", + bot_spawn_limit_class, + GetClassIDName(bot_class), + bot_spawn_limit_class != 1 ? "s" : "" + ); + } else { + message = fmt::format( + "You are not currently allowed to spawn any {} bots.", + GetClassIDName(bot_class) + ); + } + + c->Message(Chat::White, message.c_str()); + return; + } + + auto bot_character_level_class = c->GetBotRequiredLevel(bot_class); + if ( + bot_character_level_class >= 0 && + c->GetLevel() < bot_character_level_class && + !c->GetGM() + ) { + c->Message( + Chat::White, + fmt::format( + "You must be level {} to spawn {} bots.", + bot_character_level_class, + GetClassIDName(bot_class) + ).c_str() + ); + return; + } + if (!bot_id) { - c->Message(Chat::Red, "You don't own a bot named '%s'", bot_name.c_str()); + c->Message( + Chat::White, + fmt::format( + "You don't own a bot named '{}'.", + bot_name + ).c_str() + ); return; } if (entity_list.GetMobByBotID(bot_id)) { - c->Message(Chat::Red, "'%s' is already spawned in zone", bot_name.c_str()); + c->Message( + Chat::White, + fmt::format( + "'{}' is already spawned.", + bot_name + ).c_str() + ); return; } @@ -6178,39 +6630,61 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) std::list group_list; c->GetGroup()->GetMemberList(group_list); for (auto member_iter : group_list) { - if (!member_iter) + if (!member_iter) { continue; - if (member_iter->qglobal) // what is this?? really should have had a message to describe failure... (can't spawn bots if you are assigned to a task/instance?) + } + + if (member_iter->qglobal) { // what is this?? really should have had a message to describe failure... (can't spawn bots if you are assigned to a task/instance?) return; - if (!member_iter->qglobal && (member_iter->GetAppearance() != eaDead) && (member_iter->IsEngaged() || (member_iter->IsClient() && member_iter->CastToClient()->GetAggroCount()))) { - c->Message(Chat::Red, "You can't summon bots while you are engaged."); + } + + if ( + !member_iter->qglobal && + member_iter->GetAppearance() != eaDead && + ( + member_iter->IsEngaged() || + ( + member_iter->IsClient() && + member_iter->CastToClient()->GetAggroCount() + ) + ) + ) { + c->Message(Chat::White, "You cannot summon bots while you are engaged."); return; } } - } - else if (c->GetAggroCount() > 0) { - c->Message(Chat::Red, "You can't spawn bots while you are engaged."); + } else if (c->GetAggroCount()) { + c->Message(Chat::White, "You cannot spawn bots while you are engaged."); return; } - //if (c->IsEngaged()) { - // c->Message(Chat::Red, "You can't spawn bots while you are engaged."); - // return; - //} - auto my_bot = Bot::LoadBot(bot_id); if (!my_bot) { - c->Message(Chat::Red, "No valid bot '%s' (id: %i) exists", bot_name.c_str(), bot_id); + c->Message( + Chat::White, + fmt::format( + "Invalid bot '{}' (ID {})", + bot_name, + bot_id + ).c_str() + ); return; } if (!my_bot->Spawn(c)) { - c->Message(Chat::Red, "Failed to spawn bot '%s' (id: %i)", bot_name.c_str(), bot_id); + c->Message( + Chat::White, + fmt::format( + "Failed to spawn '{}' (ID {})", + bot_name, + bot_id + ).c_str() + ); safe_delete(my_bot); return; } - static const char* bot_spawn_message[17] = { + static std::string bot_spawn_message[17] = { "I am ready to fight!", // DEFAULT "A solid weapon is my ally!", // WARRIOR "The pious shall never die!", // CLERIC @@ -6236,10 +6710,9 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) } if (c->GetBotOption(Client::booSpawnMessageSay)) { - Bot::BotGroupSay(my_bot, "%s", bot_spawn_message[message_index]); - } - else if (c->GetBotOption(Client::booSpawnMessageTell)) { - c->Message(Chat::Tell, "%s tells you, \"%s\"", my_bot->GetCleanName(), bot_spawn_message[message_index]); + Bot::BotGroupSay(my_bot, bot_spawn_message[message_index].c_str()); + } else if (c->GetBotOption(Client::booSpawnMessageTell)) { + my_bot->OwnerMessage(bot_spawn_message[message_index]); } } @@ -6248,8 +6721,8 @@ void bot_subcommand_bot_stance(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_stance", sep->arg[0], "botstance")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [current | value: 1-9] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); - c->Message(Chat::Gray, "value: %u(%s), %u(%s), %u(%s), %u(%s), %u(%s), %u(%s), %u(%s)", + c->Message(Chat::White, "usage: %s [current | value: 1-9] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "value: %u(%s), %u(%s), %u(%s), %u(%s), %u(%s), %u(%s), %u(%s)", EQ::constants::stancePassive, EQ::constants::GetStanceName(EQ::constants::stancePassive), EQ::constants::stanceBalanced, EQ::constants::GetStanceName(EQ::constants::stanceBalanced), EQ::constants::stanceEfficient, EQ::constants::GetStanceName(EQ::constants::stanceEfficient), @@ -6266,7 +6739,7 @@ void bot_subcommand_bot_stance(Client *c, const Seperator *sep) bool current_flag = false; auto bst = EQ::constants::stanceUnknown; - + if (!strcasecmp(sep->arg[1], "current")) current_flag = true; else if (sep->IsNumber(1)) { @@ -6276,7 +6749,7 @@ void bot_subcommand_bot_stance(Client *c, const Seperator *sep) } if (!current_flag && bst == EQ::constants::stanceUnknown) { - c->Message(Chat::Red, "A [current] argument or valid numeric [value] is required to use this command"); + c->Message(Chat::White, "A [current] argument or valid numeric [value] is required to use this command"); return; } @@ -6295,9 +6768,11 @@ void bot_subcommand_bot_stance(Client *c, const Seperator *sep) Bot::BotGroupSay( bot_iter, - "My current stance is '%s' (%i)", - EQ::constants::GetStanceName(bot_iter->GetBotStance()), - bot_iter->GetBotStance() + fmt::format( + "My current stance is {} ({}).", + EQ::constants::GetStanceName(bot_iter->GetBotStance()), + bot_iter->GetBotStance() + ).c_str() ); } } @@ -6307,20 +6782,20 @@ void bot_subcommand_bot_stop_melee_level(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_stop_melee_level", sep->arg[0], "botstopmeleelevel")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [current | reset | sync | value: 0-255]", sep->arg[0]); - c->Message(Chat::Gray, "note: Only caster or hybrid class bots may be modified"); - c->Message(Chat::Gray, "note: Use [reset] to set stop melee level to server rule"); - c->Message(Chat::Gray, "note: Use [sync] to set stop melee level to current bot level"); + c->Message(Chat::White, "usage: %s [current | reset | sync | value: 0-255]", sep->arg[0]); + c->Message(Chat::White, "note: Only caster or hybrid class bots may be modified"); + c->Message(Chat::White, "note: Use [reset] to set stop melee level to server rule"); + c->Message(Chat::White, "note: Use [sync] to set stop melee level to current bot level"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!IsCasterClass(my_bot->GetClass()) && !IsHybridClass(my_bot->GetClass())) { - c->Message(Chat::Red, "You must a caster or hybrid class bot to use this command"); + c->Message(Chat::White, "You must a caster or hybrid class bot to use this command"); return; } @@ -6337,55 +6812,77 @@ void bot_subcommand_bot_stop_melee_level(Client *c, const Seperator *sep) return; } else if (strcasecmp(sep->arg[1], "reset")) { - c->Message(Chat::Red, "A [current] or [reset] argument, or numeric [value] is required to use this command"); + c->Message(Chat::White, "A [current] or [reset] argument, or numeric [value] is required to use this command"); return; } // [reset] falls through with initialization value my_bot->SetStopMeleeLevel(sml); if (!database.botdb.SaveStopMeleeLevel(c->CharacterID(), my_bot->GetBotID(), sml)) - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveStopMeleeLevel(), my_bot->GetCleanName()); + c->Message(Chat::White, "%s for '%s'", BotDatabase::fail::SaveStopMeleeLevel(), my_bot->GetCleanName()); - c->Message(Chat::Yellow, "Successfully set stop melee level for %s to %u", my_bot->GetCleanName(), sml); + c->Message(Chat::White, "Successfully set stop melee level for %s to %u", my_bot->GetCleanName(), sml); } void bot_subcommand_bot_summon(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_bot_summon", sep->arg[0], "botsummon")) + if (helper_command_alias_fail(c, "bot_subcommand_bot_summon", sep->arg[0], "botsummon")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message( + Chat::White, + fmt::format( + "Usage: {} ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", + sep->arg[0] + ).c_str() + ); return; } const int ab_mask = ActionableBots::ABM_NoFilter; std::list sbl; - if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) { return; + } for (auto bot_iter : sbl) { - if (!bot_iter) + if (!bot_iter) { continue; - - //Bot::BotGroupSay(bot_iter, "Whee!"); + } bot_iter->WipeHateList(); bot_iter->SetTarget(nullptr); bot_iter->Teleport(c->GetPosition()); bot_iter->DoAnim(0); - if (!bot_iter->HasPet()) + if (!bot_iter->HasPet()) { continue; + } bot_iter->GetPet()->WipeHateList(); bot_iter->GetPet()->SetTarget(nullptr); bot_iter->GetPet()->Teleport(c->GetPosition()); } - if (sbl.size() == 1) - c->Message(Chat::Yellow, "Summoned %s to you", ((sbl.front()) ? (sbl.front()->GetCleanName()) : ("'nullptr'"))); - else - c->Message(Chat::Yellow, "Summoned %i bots to you", sbl.size()); + if (sbl.size() == 1) { + c->Message( + Chat::White, + fmt::format( + "Summoned {} to you.", + sbl.front() ? sbl.front()->GetCleanName() : "no one" + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "Summoned {} bots to you.", + sbl.size() + ).c_str() + ); + } } void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep) @@ -6395,19 +6892,19 @@ void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_tattoo", sep->arg[0], "bottattoo")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -6429,10 +6926,11 @@ void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep) void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_archer", sep->arg[0], "bottogglearcher")) + if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_archer", sep->arg[0], "bottogglearcher")) { return; + } if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); @@ -6453,21 +6951,26 @@ void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep) } std::list sbl; - if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) + if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) { return; + } for (auto bot_iter : sbl) { - if (!bot_iter) + if (!bot_iter) { continue; + } - if (toggle_archer) - bot_iter->SetBotArcher(!bot_iter->IsBotArcher()); - else - bot_iter->SetBotArcher(archer_state); + if (toggle_archer) { + bot_iter->SetBotArcherySetting(!bot_iter->IsBotArcher(), true); + } + else { + bot_iter->SetBotArcherySetting(archer_state, true); + } bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher()); - if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61) + if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61) { bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher()); + } } } @@ -6476,7 +6979,7 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_helm", sep->arg[0], "bottogglehelm")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); return; } const int ab_mask = ActionableBots::ABM_NoFilter; @@ -6513,7 +7016,7 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep) if (ab_type != ActionableBots::ABT_All) { if (!database.botdb.SaveHelmAppearance(c->CharacterID(), bot_iter->GetBotID(), bot_iter->GetShowHelm())) { - c->Message(Chat::Magenta, "%s for '%s'", bot_iter->GetCleanName()); + c->Message(Chat::White, "%s for '%s'", bot_iter->GetCleanName()); return; } @@ -6535,17 +7038,17 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep) std::string query; if (toggle_helm) { if (!database.botdb.ToggleAllHelmAppearances(c->CharacterID())) - c->Message(Chat::Red, "%s", BotDatabase::fail::ToggleAllHelmAppearances()); + c->Message(Chat::White, "%s", BotDatabase::fail::ToggleAllHelmAppearances()); } else { if (!database.botdb.SaveAllHelmAppearances(c->CharacterID(), helm_state)) - c->Message(Chat::Red, "%s", BotDatabase::fail::SaveAllHelmAppearances()); + c->Message(Chat::White, "%s", BotDatabase::fail::SaveAllHelmAppearances()); } - c->Message(Chat::Yellow, "%s all of your bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared")); + c->Message(Chat::White, "%s all of your bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared")); } else { - c->Message(Chat::Yellow, "%s %i of your spawned bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared"), bot_count); + c->Message(Chat::White, "%s %i of your spawned bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared"), bot_count); } // Notes: @@ -6603,14 +7106,14 @@ void bot_subcommand_bot_update(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_update", sep->arg[0], "botupdate")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message(Chat::White, "usage: %s", sep->arg[0]); return; } std::list sbl; MyBots::PopulateSBL_BySpawnedBots(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You currently have no spawned bots"); + c->Message(Chat::White, "You currently have no spawned bots"); return; } @@ -6625,7 +7128,7 @@ void bot_subcommand_bot_update(Client *c, const Seperator *sep) ++bot_count; } - c->Message(Chat::Yellow, "Updated %i of your %i spawned bots", bot_count, sbl.size()); + c->Message(Chat::White, "Updated %i of your %i spawned bots", bot_count, sbl.size()); } void bot_subcommand_bot_woad(Client *c, const Seperator *sep) @@ -6633,19 +7136,19 @@ void bot_subcommand_bot_woad(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_bot_woad", sep->arg[0], "botwoad")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [value: 0-n] (Barbarian bots only)", sep->arg[0]); - c->Message(Chat::Gray, "note: Actual limit is filter-based"); + c->Message(Chat::White, "usage: %s [value: 0-n] (Barbarian bots only)", sep->arg[0]); + c->Message(Chat::White, "note: Actual limit is filter-based"); return; } auto my_bot = ActionableBots::AsTarget_ByBot(c); if (!my_bot) { - c->Message(Chat::Red, "You must a bot that you own to use this command"); + c->Message(Chat::White, "You must a bot that you own to use this command"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "A numeric [value] is required to use this command"); + c->Message(Chat::White, "A numeric [value] is required to use this command"); return; } @@ -6671,208 +7174,468 @@ void bot_subcommand_bot_woad(Client *c, const Seperator *sep) void bot_subcommand_botgroup_add_member(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_botgroup_add_member", sep->arg[0], "botgroupaddmember")) + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_add_member", sep->arg[0], "botgroupaddmember")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [member_name] ([leader_name])", sep->arg[0]); + c->Message( + Chat::White, + fmt::format( + "Usage: () {} [member_name] ([leader_name])", + sep->arg[0] + ).c_str() + ); return; } std::list sbl; MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); if (sbl.empty()) { - c->Message(Chat::Red, "You must [name] a new member as a bot that you own to use this command"); + c->Message(Chat::White, "You must name a new member as a bot that you own to use this command."); return; } auto new_member = sbl.front(); if (!new_member) { - c->Message(Chat::Magenta, "Error: New member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: New member bot dereferenced to nullptr"); return; } if (new_member->HasGroup()) { - c->Message(Chat::Red, "%s is already a current member of a group and can not join another one", new_member->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "{} is already member of a group.", + new_member->GetCleanName() + ).c_str() + ); return; } uint32 botgroup_id = 0; if (!database.botdb.LoadBotGroupIDByMemberID(new_member->GetBotID(), botgroup_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByMemberID(), new_member->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group id by member ID for '{}'.", + new_member->GetCleanName() + ).c_str() + ); return; } + if (botgroup_id) { - c->Message(Chat::Red, "%s is already a current member of a bot-group", new_member->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "{} is already a member of a bot-group.", + new_member->GetCleanName() + ).c_str() + ); return; } MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); - if (sbl.empty()) - MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a group leader as a bot that you own to use this command"); + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + } + + if (sbl.empty()) { + c->Message(Chat::White, "You must target or name a group leader as a bot that you own to use this command."); return; } - auto botgroup_leader = sbl.front(); - if (!botgroup_leader) { - c->Message(Chat::Magenta, "Error: Group leader bot dereferenced to nullptr"); + auto leader = sbl.front(); + if (!leader) { + c->Message(Chat::White, "Error: Group leader bot dereferenced to nullptr."); return; } - Group* group_inst = botgroup_leader->GetGroup(); - if (!group_inst || group_inst->GetLeader() != botgroup_leader) { - c->Message(Chat::Red, "%s is not the current leader of a group", botgroup_leader->GetCleanName()); + auto* g = leader->GetGroup(); + if (!g || g->GetLeader() != leader) { + c->Message( + Chat::White, + fmt::format( + "{} is not the leader of a group.", + leader->GetCleanName() + ).c_str() + ); return; } botgroup_id = 0; - if (!database.botdb.LoadBotGroupIDByLeaderID(botgroup_leader->GetBotID(), botgroup_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByLeaderID(), botgroup_leader->GetCleanName()); + if (!database.botdb.LoadBotGroupIDByLeaderID(leader->GetBotID(), botgroup_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group ID by leader ID for '{}'.", + leader->GetCleanName() + ).c_str() + ); return; } + if (!botgroup_id) { - c->Message(Chat::Red, "%s is not the current leader of a bot-group", botgroup_leader->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "{} is not the leader of a bot-group.", + leader->GetCleanName() + ).c_str() + ); return; } - if (!Bot::AddBotToGroup(new_member, group_inst)) { - c->Message(Chat::Red, "Could not add %s as a new member to %s's group", new_member->GetCleanName(), botgroup_leader->GetCleanName()); + if (!Bot::AddBotToGroup(new_member, g)) { + c->Message( + Chat::White, + fmt::format( + "Could not add {} as a new member to a group with {}.", + new_member->GetCleanName(), + leader->GetCleanName() + ).c_str() + ); return; } - database.SetGroupID(new_member->GetName(), group_inst->GetID(), new_member->GetBotID()); + database.SetGroupID(new_member->GetName(), g->GetID(), new_member->GetBotID()); - if (!database.botdb.AddMemberToBotGroup(botgroup_leader->GetBotID(), new_member->GetBotID())) { - c->Message(Chat::Red, "%s - %s->%s", BotDatabase::fail::AddMemberToBotGroup(), new_member->GetCleanName(), botgroup_leader->GetCleanName()); - Bot::RemoveBotFromGroup(new_member, botgroup_leader->GetGroup()); + if (!database.botdb.AddMemberToBotGroup(leader->GetBotID(), new_member->GetBotID())) { + c->Message( + Chat::White, + fmt::format( + "Failed to add member to bot-group, {} could not be added to a group with {}.", + new_member->GetCleanName(), + leader->GetCleanName() + ).c_str() + ); + Bot::RemoveBotFromGroup(new_member, leader->GetGroup()); return; } std::string botgroup_name; - if (!database.botdb.LoadBotGroupNameByLeaderID(botgroup_leader->GetBotID(), botgroup_name)) - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadBotGroupNameByLeaderID()); + if (!database.botdb.LoadBotGroupNameByLeaderID(leader->GetBotID(), botgroup_name)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group name by leader ID for bot ID {}.", + leader->GetBotID() + ).c_str() + ); + } - c->Message(Chat::Yellow, "Successfully added %s to bot-group %s", new_member->GetCleanName(), botgroup_name.c_str()); + c->Message( + Chat::White, + fmt::format( + "Successfully added {} to bot-group {}.", + new_member->GetCleanName(), + botgroup_name + ).c_str() + ); +} + +void bot_subcommand_botgroup_auto_spawn(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_auto_spawn", sep->arg[0], "botgroupautospawn")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: () {} ([leader_name])", + sep->arg[0] + ).c_str() + ); + return; + } + + std::list sbl; + + if (sbl.empty()) { + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + } + + if (sbl.empty()) { + c->Message(Chat::White, "You must target or name a group leader as a bot that you own to use this command."); + return; + } + + auto leader = sbl.front(); + if (!leader) { + c->Message(Chat::White, "Error: Group leader bot dereferenced to nullptr."); + return; + } + + auto* g = leader->GetGroup(); + if (!g || g->GetLeader() != leader) { + c->Message( + Chat::White, + fmt::format( + "{} is not the leader of a group.", + leader->GetCleanName() + ).c_str() + ); + return; + } + + uint32 botgroup_id = 0; + if (!database.botdb.LoadBotGroupIDByLeaderID(leader->GetBotID(), botgroup_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group ID by leader ID for '{}'.", + leader->GetCleanName() + ).c_str() + ); + return; + } + + if (!botgroup_id) { + c->Message( + Chat::White, + fmt::format( + "{} is not the leader of a bot-group.", + leader->GetCleanName() + ).c_str() + ); + return; + } + + std::string botgroup_name; + if (!database.botdb.LoadBotGroupNameByLeaderID(leader->GetBotID(), botgroup_name)) { + c->Message(Chat::White, "Failed to load bot-group name by leader ID."); + return; + } + + if (!database.botdb.ToggleBotGroupAutoSpawn(botgroup_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to toggle auto spawn for bot-group '{}'.", + botgroup_name + ).c_str() + ); + return; + } + + bool auto_spawn = database.botdb.IsBotGroupAutoSpawn(botgroup_name); + + c->Message( + Chat::White, + fmt::format( + "Auto spawn is now {}active bot-group '{}'.", + !auto_spawn ? "in" : "", + botgroup_name + ).c_str() + ); } void bot_subcommand_botgroup_create(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_botgroup_create", sep->arg[0], "botgroupcreate")) + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_create", sep->arg[0], "botgroupcreate")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [group_name] ([leader_name])", sep->arg[0]); + c->Message( + Chat::White, + fmt::format( + "Usage: () {} [group_name] ([leader_name])", + sep->arg[0] + ).c_str() + ); return; } - std::string botgroup_name_arg = sep->arg[1]; - if (botgroup_name_arg.empty()) { - c->Message(Chat::Red, "You must specify a [name] for this bot-group to use this command"); + std::string botgroup_name = sep->argplus[1]; + if (botgroup_name.empty()) { + c->Message(Chat::White, "You must specify a name for this bot-group to use this command."); return; } - bool extant_flag = false; - if (!database.botdb.QueryBotGroupExistence(botgroup_name_arg, extant_flag)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::QueryBotGroupExistence(), botgroup_name_arg.c_str()); - return; - } - if (extant_flag) { - c->Message(Chat::Red, "The [name] %s already exists for a bot-group. Please choose another", botgroup_name_arg.c_str()); + if (database.botdb.QueryBotGroupExistence(botgroup_name)) { + c->Message( + Chat::White, + fmt::format( + "The name '{}' already exists for a bot-group. Please choose another.", + botgroup_name + ).c_str() + ); return; } std::list sbl; MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); - if (sbl.empty()) - MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a group leader as a bot that you own to use this command"); + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + } + + if (sbl.empty()) { + c->Message(Chat::White, "You must target or name a group leader as a bot that you own to use this command."); return; } - auto botgroup_leader = sbl.front(); - if (!botgroup_leader) { - c->Message(Chat::Magenta, "Error: Group leader bot dereferenced to nullptr"); + auto leader = sbl.front(); + if (!leader) { + c->Message(Chat::White, "Error: Group leader bot dereferenced to nullptr."); return; } - if (botgroup_leader->HasGroup()) { - c->Message(Chat::Red, "%s is already a current member of a group", botgroup_leader->GetCleanName()); + if (leader->HasGroup()) { + c->Message( + Chat::White, + fmt::format( + "{} is already a current member of a group.", + leader->GetCleanName() + ).c_str() + ); return; } uint32 botgroup_id = 0; - if (!database.botdb.LoadBotGroupIDByLeaderID(botgroup_leader->GetBotID(), botgroup_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByLeaderID(), botgroup_leader->GetCleanName()); + if (!database.botdb.LoadBotGroupIDByLeaderID(leader->GetBotID(), botgroup_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group ID by leader ID for '{}'.", + leader->GetCleanName() + ).c_str() + ); return; } + if (botgroup_id) { - c->Message(Chat::Red, "%s is already the current leader of a bot-group", botgroup_leader->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "{} is already the current leader of a bot-group.", + leader->GetCleanName() + ).c_str() + ); return; } botgroup_id = 0; - if (!database.botdb.LoadBotGroupIDByMemberID(botgroup_leader->GetBotID(), botgroup_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByMemberID(), botgroup_leader->GetCleanName()); + if (!database.botdb.LoadBotGroupIDByMemberID(leader->GetBotID(), botgroup_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group id by member ID for '{}'.", + leader->GetCleanName() + ).c_str() + ); return; } + if (botgroup_id) { - c->Message(Chat::Red, "%s is already a current member of a bot-group", botgroup_leader->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "{} is already a current member of a bot-group.", + leader->GetCleanName() + ).c_str() + ); return; } - Group* group_inst = new Group(botgroup_leader); - if (!group_inst) { - c->Message(Chat::Magenta, "Could not create a new group instance"); + auto* g = new Group(leader); + if (!g) { + c->Message(Chat::White, "Could not create a new group instance."); return; } - if (!database.botdb.CreateBotGroup(botgroup_name_arg, botgroup_leader->GetBotID())) { - c->Message(Chat::Red, "%s '%s'", BotDatabase::fail::CreateBotGroup(), botgroup_name_arg.c_str()); - safe_delete(group_inst); + if (!database.botdb.CreateBotGroup(botgroup_name, leader->GetBotID())) { + c->Message( + Chat::White, + fmt::format( + "Failed to create bot-group '{}'.", + botgroup_name + ).c_str() + ); + safe_delete(g); return; } - entity_list.AddGroup(group_inst); - database.SetGroupID(botgroup_leader->GetCleanName(), group_inst->GetID(), botgroup_leader->GetBotID()); - database.SetGroupLeaderName(group_inst->GetID(), botgroup_leader->GetCleanName()); - botgroup_leader->SetFollowID(c->GetID()); + entity_list.AddGroup(g); + database.SetGroupID(leader->GetCleanName(), g->GetID(), leader->GetBotID()); + database.SetGroupLeaderName(g->GetID(), leader->GetCleanName()); + leader->SetFollowID(c->GetID()); - c->Message(Chat::Yellow, "Successfully created bot-group '%s' with '%s' as its leader", botgroup_name_arg.c_str(), botgroup_leader->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "Successfully created bot-group '{}' with '{}' as its leader.", + botgroup_name, + leader->GetCleanName() + ).c_str() + ); } void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_botgroup_delete", sep->arg[0], "botgroupdelete")) - return; - if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [botgroup_name]", sep->arg[0]); + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_delete", sep->arg[0], "botgroupdelete")) { return; } - std::string botgroup_name_arg = sep->arg[1]; - if (botgroup_name_arg.empty()) { - c->Message(Chat::Red, "You must specify a [name] for this bot-group to use this command"); + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(Chat::White, "usage: %s [botgroup_name]", sep->arg[0]); + return; + } + + std::string botgroup_name = sep->argplus[1]; + if (botgroup_name.empty()) { + c->Message(Chat::White, "You must specify a [name] for this bot-group to use this command"); return; } uint32 botgroup_id = 0; - if (!database.botdb.LoadBotGroupIDForLoadBotGroup(c->CharacterID(), botgroup_name_arg, botgroup_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDForLoadBotGroup(), botgroup_name_arg.c_str()); + if (!database.botdb.LoadBotGroupIDForLoadBotGroup(c->CharacterID(), botgroup_name, botgroup_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group ID for load bot-group for '{}'.", + botgroup_name + ).c_str() + ); return; } + if (!botgroup_id) { - c->Message(Chat::Red, "Could not locate group id for '%s'", botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Could not locate group ID for '{}'.", + botgroup_name + ).c_str() + ); return; } uint32 leader_id = 0; if (!database.botdb.LoadLeaderIDByBotGroupID(botgroup_id, leader_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadLeaderIDByBotGroupID(), botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Failed to load leader ID by bot-group ID for '{}'.", + botgroup_name + ).c_str() + ); return; } + if (!leader_id) { - c->Message(Chat::Red, "Could not locate leader id for '%s'", botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Could not locate leader ID for '{}'.", + botgroup_name + ).c_str() + ); return; } @@ -6881,12 +7644,25 @@ void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep) MyBots::PopulateSBL_BySpawnedBots(c, sbl); std::map> member_list; - if (!database.botdb.LoadBotGroup(botgroup_name_arg, member_list)) { - c->Message(Chat::Red, "%s '%s'", BotDatabase::fail::LoadBotGroup(), botgroup_name_arg.c_str()); + if (!database.botdb.LoadBotGroup(botgroup_name, member_list)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group '{}'.", + botgroup_name + ).c_str() + ); return; } + if (member_list.find(botgroup_id) == member_list.end() || member_list[botgroup_id].empty()) { - c->Message(Chat::Red, "Could not locate member list for bot-group '%s'", botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Could not locate member list for bot-group '{}'.", + botgroup_name + ).c_str() + ); return; } @@ -6898,73 +7674,134 @@ void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep) } } } + gbl.unique(); for (auto group_member : gbl) { - if (group_member->HasGroup()) + if (group_member->HasGroup()) { Bot::RemoveBotFromGroup(group_member, group_member->GetGroup()); + } } if (!database.botdb.DeleteBotGroup(leader_id)) { - c->Message(Chat::Red, "%s '%s'", BotDatabase::fail::DeleteBotGroup(), botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Failed to delete bot-group '{}'.", + botgroup_name + ).c_str() + ); return; } - c->Message(Chat::Yellow, "Successfully deleted bot-group %s", botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Successfully deleted bot-group '{}'.", + botgroup_name + ).c_str() + ); } void bot_subcommand_botgroup_list(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_botgroup_list", sep->arg[0], "botgrouplist")) + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_list", sep->arg[0], "botgrouplist")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s", sep->arg[0]); + c->Message( + Chat::White, + fmt::format( + "Usage: {}", + sep->arg[0] + ).c_str() + ); return; } std::list> botgroups_list; if (!database.botdb.LoadBotGroupsListByOwnerID(c->CharacterID(), botgroups_list)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadBotGroupsListByOwnerID()); + c->Message(Chat::White, "Failed to load bot-group."); return; } + if (botgroups_list.empty()) { - c->Message(Chat::Red, "You have no saved bot-groups"); + c->Message(Chat::White, "You have no saved bot-groups."); return; } - int botgroup_count = 0; - for (auto botgroups_iter : botgroups_list) - c->Message(Chat::White, "(%i) Bot-group name: %s | Leader: %s", (++botgroup_count), botgroups_iter.first.c_str(), botgroups_iter.second.c_str()); + uint32 botgroup_count = 0; - c->Message(Chat::Yellow, "%i bot-groups listed", botgroup_count); + for (auto botgroups_iter : botgroups_list) { + c->Message( + Chat::White, + fmt::format( + "Bot-group {} | Name: {} | Leader: {}{} | {}", + (botgroup_count + 1), + botgroups_iter.first, + botgroups_iter.second, + database.botdb.IsBotGroupAutoSpawn(botgroups_iter.first) ? " (Auto Spawn)" : "", + Saylink::Silent( + fmt::format("^botgroupload {}", botgroups_iter.first), + "Load" + ) + ).c_str() + ); + + botgroup_count++; + } + + c->Message( + Chat::White, + fmt::format( + "{} Bot-group{} listed.", + botgroup_count, + botgroup_count != 1 ? "s" : "" + ).c_str() + ); } void bot_subcommand_botgroup_load(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_botgroup_load", sep->arg[0], "botgroupload")) + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_load", sep->arg[0], "botgroupload")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [botgroup_name]", sep->arg[0]); + c->Message( + Chat::White, + fmt::format( + "Usage: {} [botgroup_name]", + sep->arg[0] + ).c_str() + ); return; } - std::string botgroup_name_arg = sep->arg[1]; - if (botgroup_name_arg.empty()) { - c->Message(Chat::Red, "You must specify the [name] of a bot-group to load to use this command"); + std::string botgroup_name = sep->argplus[1]; + if (botgroup_name.empty()) { + c->Message(Chat::White, "You must specify the name of a bot-group to load to use this command."); return; } - bool extant_flag = false; - if (!database.botdb.QueryBotGroupExistence(botgroup_name_arg, extant_flag)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::QueryBotGroupExistence(), botgroup_name_arg.c_str()); - return; - } - if (!extant_flag) { - c->Message(Chat::Red, "Bot-group %s does not exist", botgroup_name_arg.c_str()); + if (!database.botdb.QueryBotGroupExistence(botgroup_name)) { + c->Message( + Chat::White, + fmt::format( + "Failed to query bot-group existence for '{}'.", + botgroup_name + ).c_str() + ); return; } - Group* owner_group = c->GetGroup(); + if (c->GetFeigned()) { + c->Message(Chat::White, "You cannot spawn a bot-group while feigned."); + return; + } + + auto* owner_group = c->GetGroup(); if (owner_group) { std::list member_list; owner_group->GetClientList(member_list); @@ -6972,152 +7809,178 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep) for (auto member_iter : member_list) { if (member_iter->IsEngaged() || member_iter->GetAggroCount() > 0) { - c->Message(Chat::Red, "You can't spawn bots while your group is engaged"); + c->Message(Chat::White, "You cannot spawn bots while your group is engaged,"); return; } } - } - else { + } else { if (c->GetAggroCount() > 0) { - c->Message(Chat::Red, "You can't spawn bots while you are engaged"); + c->Message(Chat::White, "You cannot spawn bots while you are engaged,"); return; } } uint32 botgroup_id = 0; - if (!database.botdb.LoadBotGroupIDForLoadBotGroup(c->CharacterID(), botgroup_name_arg, botgroup_id) || !botgroup_id) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDForLoadBotGroup(), botgroup_name_arg.c_str()); + if (!database.botdb.LoadBotGroupIDForLoadBotGroup(c->CharacterID(), botgroup_name, botgroup_id) || !botgroup_id) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group ID for load bot-group for '{}'.", + botgroup_name + ).c_str() + ); return; } std::map> member_list; - if (!database.botdb.LoadBotGroup(botgroup_name_arg, member_list)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotGroup(), botgroup_name_arg.c_str()); + if (!database.botdb.LoadBotGroup(botgroup_name, member_list)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load bot-group for '{}'.", + botgroup_name + ).c_str() + ); return; } + if (member_list.find(botgroup_id) == member_list.end() || member_list[botgroup_id].empty()) { - c->Message(Chat::Red, "Database returned an empty list for bot-group '%s'", botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Database returned an empty list for bot-group '{}'.", + botgroup_name + ).c_str() + ); return; } - int spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID()); + auto spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID()); - if (RuleB(Bots, QuestableSpawnLimit)) { - int allowed_bot_count = 0; - if (!database.botdb.LoadQuestableSpawnCount(c->CharacterID(), allowed_bot_count)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadQuestableSpawnCount()); - return; + auto bot_spawn_limit = c->GetBotSpawnLimit(); + if ( + bot_spawn_limit >= 0 && + ( + spawned_bot_count >= bot_spawn_limit || + (spawned_bot_count + member_list.begin()->second.size()) > bot_spawn_limit + ) + ) { + std::string message; + if (bot_spawn_limit) { + message = fmt::format( + "You cannot have more than {} spawned bot{}.", + bot_spawn_limit, + bot_spawn_limit != 1 ? "s" : "" + ); + } else { + message = "You are not currently allowed to spawn any bots."; } - if (!allowed_bot_count) { - c->Message(Chat::Red, "You can not spawn any bots"); - return; - } - - if (spawned_bot_count >= allowed_bot_count || (spawned_bot_count + member_list.begin()->second.size()) > allowed_bot_count) { - c->Message(Chat::Red, "You can not spawn more than %i bot%s (quest-limit)", allowed_bot_count, ((allowed_bot_count == 1) ? ("") : ("s"))); - return; - } - } - - const int allowed_bot_limit = RuleI(Bots, SpawnLimit); - if (spawned_bot_count >= allowed_bot_limit || (spawned_bot_count + member_list.begin()->second.size()) > allowed_bot_limit) { - c->Message(Chat::Red, "You can not spawn more than %i bot%s (hard-limit)", allowed_bot_limit, ((allowed_bot_limit == 1) ? ("") : ("s"))); + c->Message(Chat::White, message.c_str()); return; } uint32 leader_id = 0; - if (!database.botdb.LoadLeaderIDByBotGroupName(botgroup_name_arg, leader_id)) { - c->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadLeaderIDByBotGroupName(), botgroup_name_arg.c_str()); + if (!database.botdb.LoadLeaderIDByBotGroupName(botgroup_name, leader_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to load leader ID by bot-group name for '{}'.", + botgroup_name + ).c_str() + ); return; } + if (!leader_id) { - c->Message(Chat::Red, "Cannot locate bot-group leader id for '%s'", botgroup_name_arg.c_str()); + c->Message( + Chat::White, + fmt::format( + "Cannot locate bot-group leader ID for '{}'.", + botgroup_name + ).c_str() + ); return; } - auto botgroup_leader = Bot::LoadBot(leader_id); - if (!botgroup_leader) { - c->Message(Chat::Red, "Could not load bot-group leader for '%s'", botgroup_name_arg.c_str()); - safe_delete(botgroup_leader); - return; - } - - if (!botgroup_leader->Spawn(c)) { - c->Message(Chat::Red, "Could not spawn bot-group leader %s for '%s'", botgroup_leader->GetName(), botgroup_name_arg.c_str()); - safe_delete(botgroup_leader); - return; - } - - Group* group_inst = new Group(botgroup_leader); - - entity_list.AddGroup(group_inst); - database.SetGroupID(botgroup_leader->GetCleanName(), group_inst->GetID(), botgroup_leader->GetBotID()); - database.SetGroupLeaderName(group_inst->GetID(), botgroup_leader->GetCleanName()); - botgroup_leader->SetFollowID(c->GetID()); - - member_list[botgroup_id].remove(0); - member_list[botgroup_id].remove(botgroup_leader->GetBotID()); - for (auto member_iter : member_list[botgroup_id]) { - auto botgroup_member = Bot::LoadBot(member_iter); - if (!botgroup_member) { - c->Message(Chat::Red, "Could not load bot id %i", member_iter); - safe_delete(botgroup_member); - return; - } - - if (!botgroup_member->Spawn(c)) { - c->Message(Chat::Red, "Could not spawn bot '%s' (id: %i)", botgroup_member->GetName(), member_iter); - safe_delete(botgroup_member); - return; - } - - Bot::AddBotToGroup(botgroup_member, group_inst); - } - - c->Message(Chat::Yellow, "Successfully loaded bot-group %s", botgroup_name_arg.c_str()); + Bot::SpawnBotGroupByName(c, botgroup_name, leader_id); } void bot_subcommand_botgroup_remove_member(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_botgroup_remove_member", sep->arg[0], "botgroupremovemember")) + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_remove_member", sep->arg[0], "botgroupremovemember")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message( + Chat::White, + fmt::format( + "Usage: () {} ([member_name])", + sep->arg[0] + ).c_str() + ); return; } std::list sbl; MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); - if (sbl.empty()) - MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a group member as a bot that you own to use this command"); + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + } + + if (sbl.empty()) { + c->Message(Chat::White, "You must target or name a group member as a bot that you own to use this command."); return; } auto group_member = sbl.front(); if (!group_member) { - c->Message(Chat::Magenta, "Error: Group member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Group member bot dereferenced to nullptr."); return; } if (!group_member->HasGroup()) { - c->Message(Chat::Red, "%s is not a current member of a group", group_member->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "{} is not a current member of a group.", + group_member->GetCleanName() + ).c_str() + ); return; } if (!Bot::RemoveBotFromGroup(group_member, group_member->GetGroup())) { - c->Message(Chat::Red, "Could not remove %s from their group", group_member->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "Could not remove {} from their group.", + group_member->GetCleanName() + ).c_str() + ); return; } if (!database.botdb.RemoveMemberFromBotGroup(group_member->GetBotID())) { - c->Message(Chat::Red, "%s - '%s'", BotDatabase::fail::RemoveMemberFromBotGroup(), group_member->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "Could not remove {} from their bot-group.", + group_member->GetCleanName() + ).c_str() + ); return; } - c->Message(Chat::Yellow, "Successfully removed %s from their bot-group", group_member->GetCleanName()); + c->Message( + Chat::White, + fmt::format( + "Successfully removed {} from their bot-group.", + group_member->GetCleanName() + ).c_str() + ); } void bot_subcommand_circle(Client *c, const Seperator *sep) @@ -7126,7 +7989,7 @@ void bot_subcommand_circle(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Depart) || helper_command_alias_fail(c, "bot_subcommand_circle", sep->arg[0], "circle")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [list | destination] ([option: single])", sep->arg[0]); + c->Message(Chat::White, "usage: %s [list | destination] ([option: single])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Depart, DRUID); return; } @@ -7143,7 +8006,7 @@ void bot_subcommand_circle(Client *c, const Seperator *sep) return; } else if (destination.empty()) { - c->Message(Chat::Red, "A [destination] or [list] argument is required to use this command"); + c->Message(Chat::White, "A [destination] or [list] argument is required to use this command"); return; } @@ -7184,7 +8047,7 @@ void bot_subcommand_heal_rotation_adaptive_targeting(Client *c, const Seperator if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_adaptive_targeting", sep->arg[0], "healrotationadaptivetargeting")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); return; } @@ -7201,18 +8064,18 @@ void bot_subcommand_heal_rotation_adaptive_targeting(Client *c, const Seperator } if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } @@ -7222,13 +8085,13 @@ void bot_subcommand_heal_rotation_adaptive_targeting(Client *c, const Seperator hr_adaptive_targeting = true; } else if (adaptive_targeting_arg.compare("off")) { - c->Message(Chat::Yellow, "Adaptive targeting is currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(Chat::White, "Adaptive targeting is currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off")), current_member->GetCleanName()); return; } (*current_member->MemberOfHealRotation())->SetAdaptiveTargeting(hr_adaptive_targeting); - c->Message(Chat::Yellow, "Adaptive targeting is now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(Chat::White, "Adaptive targeting is now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off")), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_add_member(Client *c, const Seperator *sep) @@ -7236,25 +8099,25 @@ void bot_subcommand_heal_rotation_add_member(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_add_member", sep->arg[0], "healrotationaddmember")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [new_member_name] ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [new_member_name] ([member_name])", sep->arg[0]); return; } std::list sbl; MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); if (sbl.empty()) { - c->Message(Chat::Red, "You must [name] a new member as a bot that you own to use this command"); + c->Message(Chat::White, "You must [name] a new member as a bot that you own to use this command"); return; } auto new_member = sbl.front(); if (!new_member) { - c->Message(Chat::Magenta, "Error: New member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: New member bot dereferenced to nullptr"); return; } if (new_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is already a current member of a Heal Rotation and can not join another one", new_member->GetCleanName()); + c->Message(Chat::White, "%s is already a current member of a Heal Rotation and can not join another one", new_member->GetCleanName()); return; } @@ -7262,27 +8125,27 @@ void bot_subcommand_heal_rotation_add_member(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } if (!new_member->JoinHealRotationMemberPool(current_member->MemberOfHealRotation())) { - c->Message(Chat::Red, "Failed to add %s as a current member of this Heal Rotation", new_member->GetCleanName()); + c->Message(Chat::White, "Failed to add %s as a current member of this Heal Rotation", new_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "Successfully added %s as a current member of this Heal Rotation", new_member->GetCleanName()); + c->Message(Chat::White, "Successfully added %s as a current member of this Heal Rotation", new_member->GetCleanName()); } void bot_subcommand_heal_rotation_add_target(Client *c, const Seperator *sep) @@ -7290,7 +8153,7 @@ void bot_subcommand_heal_rotation_add_target(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_add_target", sep->arg[0], "healrotationaddtarget")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [heal_target_name] ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [heal_target_name] ([member_name])", sep->arg[0]); return; } @@ -7299,40 +8162,40 @@ void bot_subcommand_heal_rotation_add_target(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); return; } auto heal_target = entity_list.GetMob(sep->arg[1]); if (!heal_target) { - c->Message(Chat::Red, "No target exists by the name '%s'", sep->arg[1]); + c->Message(Chat::White, "No target exists by the name '%s'", sep->arg[1]); return; } if ((!heal_target->IsClient() && !heal_target->IsBot() && !heal_target->IsPet()) || (heal_target->IsPet() && (!heal_target->GetOwner() || (!heal_target->GetOwner()->IsClient() && !heal_target->GetOwner()->IsBot())))) { - c->Message(Chat::Red, "%s's entity type is not an allowable heal target", heal_target->GetCleanName()); + c->Message(Chat::White, "%s's entity type is not an allowable heal target", heal_target->GetCleanName()); return; } if (!heal_target->JoinHealRotationTargetPool(current_member->MemberOfHealRotation())) { - c->Message(Chat::Red, "Failed to add heal target with a name of '%s'", heal_target->GetCleanName()); + c->Message(Chat::White, "Failed to add heal target with a name of '%s'", heal_target->GetCleanName()); return; } - c->Message(Chat::Yellow, "Successfully added heal target %s to %s's Heal Rotation", heal_target->GetCleanName(), current_member->GetCleanName()); + c->Message(Chat::White, "Successfully added heal target %s to %s's Heal Rotation", heal_target->GetCleanName(), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *sep) @@ -7340,8 +8203,8 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_adjust_critical", sep->arg[0], "healrotationadjustcritical")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [armor_type] [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); - c->Message(Chat::Gray, "armor_types: %u(Base), %u(Cloth), %u(Leather), %u(Chain), %u(Plate)", + c->Message(Chat::White, "usage: () %s [armor_type] [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); + c->Message(Chat::White, "armor_types: %u(Base), %u(Cloth), %u(Leather), %u(Chain), %u(Plate)", ARMOR_TYPE_UNKNOWN, ARMOR_TYPE_CLOTH, ARMOR_TYPE_LEATHER, ARMOR_TYPE_CHAIN, ARMOR_TYPE_PLATE); return; } @@ -7354,7 +8217,7 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se armor_type_value = atoi(armor_type_arg.c_str()); if (armor_type_value > ARMOR_TYPE_LAST) { - c->Message(Chat::Red, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); + c->Message(Chat::White, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); return; } @@ -7363,18 +8226,18 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } @@ -7392,12 +8255,12 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se critical_ratio = CRITICAL_HP_RATIO_ABS; if (!(*current_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(armor_type_value, critical_ratio)) { - c->Message(Chat::Red, "Critical value %3.1f%%(%u) exceeds safe value %3.1f%%(%u) for %s's Heal Rotation", + c->Message(Chat::White, "Critical value %3.1f%%(%u) exceeds safe value %3.1f%%(%u) for %s's Heal Rotation", critical_ratio, armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value), armor_type_value, current_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "Class Armor Type %u critical value %3.1f%% set for %s's Heal Rotation", + c->Message(Chat::White, "Class Armor Type %u critical value %3.1f%% set for %s's Heal Rotation", armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value), current_member->GetCleanName()); } @@ -7406,8 +8269,8 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_adjust_safe", sep->arg[0], "healrotationadjustsafe")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [armor_type] [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); - c->Message(Chat::Gray, "armor_types: %u(Base), %u(Cloth), %u(Leather), %u(Chain), %u(Plate)", + c->Message(Chat::White, "usage: () %s [armor_type] [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); + c->Message(Chat::White, "armor_types: %u(Base), %u(Cloth), %u(Leather), %u(Chain), %u(Plate)", ARMOR_TYPE_UNKNOWN, ARMOR_TYPE_CLOTH, ARMOR_TYPE_LEATHER, ARMOR_TYPE_CHAIN, ARMOR_TYPE_PLATE); return; } @@ -7420,7 +8283,7 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) armor_type_value = atoi(armor_type_arg.c_str()); if (armor_type_value > ARMOR_TYPE_LAST) { - c->Message(Chat::Red, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); + c->Message(Chat::White, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); return; } @@ -7429,18 +8292,18 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } @@ -7458,12 +8321,12 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) safe_ratio = CRITICAL_HP_RATIO_ABS; if (!(*current_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(armor_type_value, safe_ratio)) { - c->Message(Chat::Red, "Safe value %3.1f%%(%u) does not exceed critical value %3.1f%%(%u) for %s's Heal Rotation", + c->Message(Chat::White, "Safe value %3.1f%%(%u) does not exceed critical value %3.1f%%(%u) for %s's Heal Rotation", safe_ratio, armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value), armor_type_value, current_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "Class Armor Type %u safe value %3.1f%% set for %s's Heal Rotation", + c->Message(Chat::White, "Class Armor Type %u safe value %3.1f%% set for %s's Heal Rotation", armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value), current_member->GetCleanName()); } @@ -7472,7 +8335,7 @@ void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *s if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_casting_override", sep->arg[0], "healrotationcastingoverride")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); return; } @@ -7489,18 +8352,18 @@ void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *s } if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } @@ -7510,13 +8373,13 @@ void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *s hr_casting_override = true; } else if (casting_override_arg.compare("off")) { - c->Message(Chat::Yellow, "Casting override is currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(Chat::White, "Casting override is currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); return; } (*current_member->MemberOfHealRotation())->SetCastingOverride(hr_casting_override); - c->Message(Chat::Yellow, "Casting override is now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(Chat::White, "Casting override is now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *sep) @@ -7524,7 +8387,7 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_change_interval", sep->arg[0], "healrotationchangeinterval")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name]) ([interval=%u: %u-%u(seconds)])", + c->Message(Chat::White, "usage: () %s ([member_name]) ([interval=%u: %u-%u(seconds)])", sep->arg[0], CASTING_CYCLE_DEFAULT_INTERVAL_S, CASTING_CYCLE_MINIMUM_INTERVAL_S, CASTING_CYCLE_MAXIMUM_INTERVAL_S); return; } @@ -7542,18 +8405,18 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se } if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } @@ -7564,7 +8427,7 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se } else { hr_change_interval_s = (*current_member->MemberOfHealRotation())->IntervalS(); - c->Message(Chat::Yellow, "Casting interval is currently '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName()); + c->Message(Chat::White, "Casting interval is currently '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName()); return; } @@ -7574,7 +8437,7 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se (*current_member->MemberOfHealRotation())->SetIntervalS(hr_change_interval_s); hr_change_interval_s = (*current_member->MemberOfHealRotation())->IntervalS(); - c->Message(Chat::Yellow, "Casting interval is now '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName()); + c->Message(Chat::White, "Casting interval is now '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_clear_hot(Client *c, const Seperator *sep) @@ -7582,7 +8445,7 @@ void bot_subcommand_heal_rotation_clear_hot(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_clear_hot", sep->arg[0], "healrotationclearhot")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -7591,26 +8454,26 @@ void bot_subcommand_heal_rotation_clear_hot(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } if (!(*current_member->MemberOfHealRotation())->ClearHOTTarget()) { - c->Message(Chat::Red, "Failed to clear %s's Heal Rotation HOT", current_member->GetCleanName()); + c->Message(Chat::White, "Failed to clear %s's Heal Rotation HOT", current_member->GetCleanName()); } - c->Message(Chat::Yellow, "Succeeded in clearing %s's Heal Rotation HOT", current_member->GetCleanName()); + c->Message(Chat::White, "Succeeded in clearing %s's Heal Rotation HOT", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep) @@ -7618,7 +8481,7 @@ void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_clear_targets", sep->arg[0], "healrotationcleartargets")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -7627,27 +8490,27 @@ void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); return; } if (!(*current_member->MemberOfHealRotation())->ClearTargetPool()) { - c->Message(Chat::Red, "Failed to clear all targets from %s's Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "Failed to clear all targets from %s's Heal Rotation", current_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "All targets have been cleared from %s's Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "All targets have been cleared from %s's Heal Rotation", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) @@ -7655,7 +8518,7 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_create", sep->arg[0], "healrotationcreate")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([creator_name]) ([interval=%u: %u-%u(seconds)] [fastheals=off: on | off] [adaptivetargeting=off: on | off] [castingoverride=off: on | off])", + c->Message(Chat::White, "usage: () %s ([creator_name]) ([interval=%u: %u-%u(seconds)] [fastheals=off: on | off] [adaptivetargeting=off: on | off] [castingoverride=off: on | off])", sep->arg[0], CASTING_CYCLE_DEFAULT_INTERVAL_S, CASTING_CYCLE_MINIMUM_INTERVAL_S, CASTING_CYCLE_MAXIMUM_INTERVAL_S); return; } @@ -7682,18 +8545,18 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) } if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a creator as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a creator as a bot that you own to use this command"); return; } auto creator_member = sbl.front(); if (!creator_member) { - c->Message(Chat::Magenta, "Error: Creator bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Creator bot dereferenced to nullptr"); return; } if (creator_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is already a current member of a Heal Rotation", creator_member->GetCleanName()); + c->Message(Chat::White, "%s is already a current member of a Heal Rotation", creator_member->GetCleanName()); return; } @@ -7724,7 +8587,7 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) hr_interval_s *= 1000; // convert to milliseconds for Bot/HealRotation constructor if (!creator_member->CreateHealRotation(hr_interval_s, hr_fast_heals, hr_adaptive_targeting, hr_casting_override)) { - c->Message(Chat::Red, "Failed to add %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); + c->Message(Chat::White, "Failed to add %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); return; } @@ -7735,10 +8598,10 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) bool target_fail = false; if (!database.botdb.LoadHealRotation(creator_member, member_list, target_list, load_flag, member_fail, target_fail)) - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadHealRotation()); + c->Message(Chat::White, "%s", BotDatabase::fail::LoadHealRotation()); if (!load_flag) { - c->Message(Chat::Yellow, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); + c->Message(Chat::White, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); return; } @@ -7754,18 +8617,18 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) continue; if (!bot_iter->JoinHealRotationMemberPool(creator_member->MemberOfHealRotation())) - c->Message(Chat::Red, "Failed to add member '%s'", bot_iter->GetCleanName()); + c->Message(Chat::White, "Failed to add member '%s'", bot_iter->GetCleanName()); member_found = true; break; } if (!member_found) - c->Message(Chat::Red, "Could not locate member with bot id '%u'", member_iter); + c->Message(Chat::White, "Could not locate member with bot id '%u'", member_iter); } } else { - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadHealRotationMembers()); + c->Message(Chat::White, "%s", BotDatabase::fail::LoadHealRotationMembers()); } if (!target_fail) { @@ -7775,19 +8638,19 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) auto target_mob = entity_list.GetMob(target_iter.c_str()); if (!target_mob) { - c->Message(Chat::Red, "Could not locate target '%s'", target_iter.c_str()); + c->Message(Chat::White, "Could not locate target '%s'", target_iter.c_str()); continue; } if (!target_mob->JoinHealRotationTargetPool(creator_member->MemberOfHealRotation())) - c->Message(Chat::Red, "Failed to add target '%s'", target_mob->GetCleanName()); + c->Message(Chat::White, "Failed to add target '%s'", target_mob->GetCleanName()); } } else { - c->Message(Chat::Red, "%s", BotDatabase::fail::LoadHealRotationTargets()); + c->Message(Chat::White, "%s", BotDatabase::fail::LoadHealRotationTargets()); } - c->Message(Chat::Yellow, "Successfully loaded %s's Heal Rotation", creator_member->GetCleanName()); + c->Message(Chat::White, "Successfully loaded %s's Heal Rotation", creator_member->GetCleanName()); } void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep) @@ -7795,7 +8658,7 @@ void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_delete", sep->arg[0], "healrotationdelete")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([option: all]) ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([option: all]) ([member_name])", sep->arg[0]); return; } @@ -7808,9 +8671,9 @@ void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep) if (all_flag) { if (database.botdb.DeleteAllHealRotations(c->CharacterID())) - c->Message(Chat::Yellow, "Succeeded in deleting all heal rotations"); + c->Message(Chat::White, "Succeeded in deleting all heal rotations"); else - c->Message(Chat::Red, "%s", BotDatabase::fail::DeleteAllHealRotations()); + c->Message(Chat::White, "%s", BotDatabase::fail::DeleteAllHealRotations()); return; } @@ -7820,22 +8683,22 @@ void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!database.botdb.DeleteHealRotation(current_member->GetBotID())) { - c->Message(Chat::Red, "%s", BotDatabase::fail::DeleteHealRotation()); + c->Message(Chat::White, "%s", BotDatabase::fail::DeleteHealRotation()); return; } - c->Message(Chat::Yellow, "Succeeded in deleting %s's heal rotation", current_member->GetCleanName()); + c->Message(Chat::White, "Succeeded in deleting %s's heal rotation", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep) @@ -7843,7 +8706,7 @@ void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_fast_heals", sep->arg[0], "healrotationfastheals")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); return; } @@ -7860,18 +8723,18 @@ void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep) } if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } @@ -7881,13 +8744,13 @@ void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep) hr_fast_heals = true; } else if (fast_heals_arg.compare("off")) { - c->Message(Chat::Yellow, "Fast heals are currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(Chat::White, "Fast heals are currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off")), current_member->GetCleanName()); return; } (*current_member->MemberOfHealRotation())->SetFastHeals(hr_fast_heals); - c->Message(Chat::Yellow, "Fast heals are now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(Chat::White, "Fast heals are now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off")), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep) @@ -7895,7 +8758,7 @@ void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_list", sep->arg[0], "healrotationlist")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -7904,22 +8767,22 @@ void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } - c->Message(Chat::Gray, "Heal Rotation Settings:"); + c->Message(Chat::White, "Heal Rotation Settings:"); c->Message(Chat::White, "Current state: %s", (((*current_member->MemberOfHealRotation())->IsActive()) ? ("active") : ("inactive"))); c->Message(Chat::White, "Casting interval: %i seconds", (*current_member->MemberOfHealRotation())->IntervalS()); @@ -7945,7 +8808,7 @@ void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep) (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE), (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE)); - c->Message(Chat::Gray, "Heal Rotation Members:"); + c->Message(Chat::White, "Heal Rotation Members:"); int member_index = 0; auto member_pool = (*current_member->MemberOfHealRotation())->MemberList(); @@ -7956,9 +8819,9 @@ void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep) c->Message(Chat::White, "(%i) %s", (++member_index), member_iter->GetCleanName()); } if (!member_index) - c->Message(Chat::Red, "(0) None"); + c->Message(Chat::White, "(0) None"); - c->Message(Chat::Gray, "Heal Rotation Targets:"); + c->Message(Chat::White, "Heal Rotation Targets:"); int target_index = 0; auto target_pool = (*current_member->MemberOfHealRotation())->TargetList(); @@ -7977,7 +8840,7 @@ void bot_subcommand_heal_rotation_remove_member(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_remove_member", sep->arg[0], "healrotationremovemember")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -7986,27 +8849,27 @@ void bot_subcommand_heal_rotation_remove_member(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } if (!current_member->LeaveHealRotationMemberPool()) { - c->Message(Chat::Red, "Failed to remove %s from their Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "Failed to remove %s from their Heal Rotation", current_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "%s has been removed from their Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s has been removed from their Heal Rotation", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_remove_target(Client *c, const Seperator *sep) @@ -8014,7 +8877,7 @@ void bot_subcommand_heal_rotation_remove_target(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_remove_target", sep->arg[0], "healrotationremovetarget")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [heal_target_name] ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [heal_target_name] ([member_name])", sep->arg[0]); return; } @@ -8023,33 +8886,33 @@ void bot_subcommand_heal_rotation_remove_target(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } auto heal_target = entity_list.GetMob(sep->arg[1]); if (!heal_target) { - c->Message(Chat::Red, "No target exists by the name '%s'", sep->arg[1]); + c->Message(Chat::White, "No target exists by the name '%s'", sep->arg[1]); return; } if (!current_member->MemberOfHealRotation()->get()->IsTargetInPool(heal_target) || !heal_target->LeaveHealRotationTargetPool()) { - c->Message(Chat::Red, "Failed to remove heal target with a name of '%s'", heal_target->GetCleanName()); + c->Message(Chat::White, "Failed to remove heal target with a name of '%s'", heal_target->GetCleanName()); return; } - c->Message(Chat::Yellow, "Successfully removed heal target %s from %s's Heal Rotation", heal_target->GetCleanName(), current_member->GetCleanName()); + c->Message(Chat::White, "Successfully removed heal target %s from %s's Heal Rotation", heal_target->GetCleanName(), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep) @@ -8057,7 +8920,7 @@ void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_reset_limits", sep->arg[0], "healrotationresetlimits")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -8066,24 +8929,24 @@ void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } (*current_member->MemberOfHealRotation())->ResetArmorTypeHPLimits(); - c->Message(Chat::Yellow, "Class Armor Type HP limit criteria has been set to default values for %s's Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "Class Armor Type HP limit criteria has been set to default values for %s's Heal Rotation", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_save(Client *c, const Seperator *sep) @@ -8091,7 +8954,7 @@ void bot_subcommand_heal_rotation_save(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_save", sep->arg[0], "healrotationsave")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -8100,33 +8963,33 @@ void bot_subcommand_heal_rotation_save(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } bool member_fail = false; bool target_fail = false; if (!database.botdb.SaveHealRotation(current_member, member_fail, target_fail)) { - c->Message(Chat::Red, "%s", BotDatabase::fail::SaveHealRotation()); + c->Message(Chat::White, "%s", BotDatabase::fail::SaveHealRotation()); return; } if (member_fail) - c->Message(Chat::Red, "Failed to save heal rotation members"); + c->Message(Chat::White, "Failed to save heal rotation members"); if (target_fail) - c->Message(Chat::Red, "Failed to save heal rotation targets"); + c->Message(Chat::White, "Failed to save heal rotation targets"); - c->Message(Chat::Yellow, "Succeeded in saving %s's heal rotation", current_member->GetCleanName()); + c->Message(Chat::White, "Succeeded in saving %s's heal rotation", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_set_hot(Client *c, const Seperator *sep) @@ -8134,7 +8997,7 @@ void bot_subcommand_heal_rotation_set_hot(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_set_hot", sep->arg[0], "healrotationsethot")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s [heal_override_target_name] ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s [heal_override_target_name] ([member_name])", sep->arg[0]); return; } @@ -8143,38 +9006,38 @@ void bot_subcommand_heal_rotation_set_hot(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); return; } auto hot_target = entity_list.GetMob(sep->arg[1]); if (!hot_target) { - c->Message(Chat::Red, "No target exists by the name '%s'", sep->arg[1]); + c->Message(Chat::White, "No target exists by the name '%s'", sep->arg[1]); return; } if (!(*current_member->MemberOfHealRotation())->IsTargetInPool(hot_target)) { - c->Message(Chat::Red, "%s is not a target in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a target in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); return; } if (!(*current_member->MemberOfHealRotation())->SetHOTTarget(hot_target)) { - c->Message(Chat::Red, "Failed to set %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); + c->Message(Chat::White, "Failed to set %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "Succeeded in setting %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); + c->Message(Chat::White, "Succeeded in setting %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep) @@ -8182,7 +9045,7 @@ void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_start", sep->arg[0], "healrotationstart")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -8191,32 +9054,32 @@ void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } if ((*current_member->MemberOfHealRotation())->IsActive()) { - c->Message(Chat::Red, "%s's Heal Rotation is already active", current_member->GetCleanName()); + c->Message(Chat::White, "%s's Heal Rotation is already active", current_member->GetCleanName()); return; } if (!current_member->MemberOfHealRotation()->get()->Start()) { - c->Message(Chat::Red, "Failed to start %s's Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "Failed to start %s's Heal Rotation", current_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "%s's Heal Rotation is now active", current_member->GetCleanName()); + c->Message(Chat::White, "%s's Heal Rotation is now active", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep) @@ -8224,7 +9087,7 @@ void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_stop", sep->arg[0], "healrotationstop")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: () %s ([member_name])", sep->arg[0]); + c->Message(Chat::White, "usage: () %s ([member_name])", sep->arg[0]); return; } @@ -8233,32 +9096,32 @@ void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep) if (sbl.empty()) MyBots::PopulateSBL_ByTargetedBot(c, sbl); if (sbl.empty()) { - c->Message(Chat::Red, "You must or [name] a current member as a bot that you own to use this command"); + c->Message(Chat::White, "You must or [name] a current member as a bot that you own to use this command"); return; } auto current_member = sbl.front(); if (!current_member) { - c->Message(Chat::Magenta, "Error: Current member bot dereferenced to nullptr"); + c->Message(Chat::White, "Error: Current member bot dereferenced to nullptr"); return; } if (!current_member->IsHealRotationMember()) { - c->Message(Chat::Red, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); return; } if (!(*current_member->MemberOfHealRotation())->IsActive()) { - c->Message(Chat::Red, "%s's Heal Rotation is already inactive", current_member->GetCleanName()); + c->Message(Chat::White, "%s's Heal Rotation is already inactive", current_member->GetCleanName()); return; } if (!current_member->MemberOfHealRotation()->get()->Stop()) { - c->Message(Chat::Red, "Failed to stop %s's Heal Rotation", current_member->GetCleanName()); + c->Message(Chat::White, "Failed to stop %s's Heal Rotation", current_member->GetCleanName()); return; } - c->Message(Chat::Yellow, "%s's Heal Rotation is now inactive", current_member->GetCleanName()); + c->Message(Chat::White, "%s's Heal Rotation is now inactive", current_member->GetCleanName()); } void bot_subcommand_inventory_give(Client *c, const Seperator *sep) @@ -8269,7 +9132,7 @@ void bot_subcommand_inventory_give(Client *c, const Seperator *sep) if (helper_is_help_or_usage(sep->arg[1])) { c->Message( - Chat::Cyan, + Chat::White, fmt::format( "Usage: {} ([actionable: target | byname] ([actionable_name]))", sep->arg[0] @@ -8287,7 +9150,7 @@ void bot_subcommand_inventory_give(Client *c, const Seperator *sep) auto my_bot = sbl.front(); if (!my_bot) { - c->Message(Chat::Magenta, "ActionableBots returned 'nullptr'"); + c->Message(Chat::White, "ActionableBots returned 'nullptr'"); return; } @@ -8302,7 +9165,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) if (helper_is_help_or_usage(sep->arg[1])) { c->Message( - Chat::Cyan, + Chat::White, fmt::format( "Usage: {} ([actionable: target | byname] ([actionable_name]))", sep->arg[0] @@ -8320,7 +9183,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) auto my_bot = sbl.front(); if (!my_bot) { - c->Message(Chat::Magenta, "ActionableBots returned 'nullptr'"); + c->Message(Chat::White, "ActionableBots returned 'nullptr'"); return; } @@ -8359,10 +9222,14 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) c->Message( Chat::White, fmt::format( - "Slot {} ({}) | {}", + "Slot {} ({}) | {} | {}", slot_id, EQ::invslot::GetInvPossessionsSlotName(slot_id), - linker.GenerateLink() + linker.GenerateLink(), + Saylink::Silent( + fmt::format("^inventoryremove {}", slot_id), + "Remove" + ) ).c_str() ); @@ -8372,7 +9239,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) uint32 database_count = 0; if (!database.botdb.QueryInventoryCount(my_bot->GetBotID(), database_count)) { c->Message( - Chat::Magenta, + Chat::White, fmt::format( "{}", BotDatabase::fail::QueryInventoryCount() @@ -8382,7 +9249,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) if (inventory_count != database_count) { c->Message( - Chat::Magenta, + Chat::White, fmt::format( "Inventory-database item count mismatch, inventory has {} item{} and the database has {} item{}.", inventory_count, @@ -8402,7 +9269,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) if (helper_is_help_or_usage(sep->arg[1])) { c->Message( - Chat::Cyan, + Chat::White, fmt::format( "Usage: {} [Slot ID: 0-22] ([actionable: target | byname] ([actionable_name]))", sep->arg[0] @@ -8425,37 +9292,55 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) auto my_bot = sbl.front(); if (!my_bot) { - c->Message(Chat::Magenta, "ActionableBots returned 'nullptr'"); + c->Message(Chat::White, "ActionableBots returned 'nullptr'"); return; } if (!sep->IsNumber(1)) { - c->Message(Chat::Red, "Slot ID must be a number."); + c->Message(Chat::White, "Slot ID must be a number."); return; } auto slot_id = static_cast(std::stoul(sep->arg[1])); if (slot_id > EQ::invslot::EQUIPMENT_END || slot_id < EQ::invslot::EQUIPMENT_BEGIN) { - c->Message(Chat::Red, "Valid slots are 0 to 22."); + c->Message(Chat::White, "Valid slots are 0 to 22."); return; } - const EQ::ItemData* itm = nullptr; - const EQ::ItemInstance* inst = my_bot->GetBotItem(slot_id); - if (inst) { - itm = inst->GetItem(); + const auto* inst = my_bot->GetBotItem(slot_id); + if (!inst) { + std::string slot_message = "is"; + switch (slot_id) { + case EQ::invslot::slotShoulders: + case EQ::invslot::slotArms: + case EQ::invslot::slotHands: + case EQ::invslot::slotLegs: + case EQ::invslot::slotFeet: + slot_message = "are"; + break; + default: + break; + } + + my_bot->OwnerMessage( + fmt::format( + "My {} (Slot {}) {} already unequipped.", + EQ::invslot::GetInvPossessionsSlotName(slot_id), + slot_id, + slot_message + ) + ); + return; } + const auto* itm = inst->GetItem(); + if (inst && itm && c->CheckLoreConflict(itm)) { c->MessageString(Chat::White, PICK_LORE); return; } for (int m = EQ::invaug::SOCKET_BEGIN; m <= EQ::invaug::SOCKET_END; ++m) { - if (!inst) { - break; - } - EQ::ItemInstance *augment = inst->GetAugment(m); if (!augment) { continue; @@ -8471,20 +9356,22 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) std::string error_message; if (itm) { + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemInst); + linker.SetItemInst(inst); + c->PushItemOnCursor(*inst, true); if ( slot_id == EQ::invslot::slotRange || - slot_id == EQ::invslot::slotAmmo || - slot_id == EQ::invslot::slotPrimary || - slot_id == EQ::invslot::slotSecondary + slot_id == EQ::invslot::slotAmmo ) { - my_bot->SetBotArcher(false); + my_bot->SetBotArcherySetting(false, true); } my_bot->RemoveBotItemBySlot(slot_id, &error_message); if (!error_message.empty()) { c->Message( - Chat::Magenta, + Chat::White, fmt::format( "Database Error: {}", error_message @@ -8495,54 +9382,15 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) my_bot->BotRemoveEquipItem(slot_id); my_bot->CalcBotStats(c->GetBotOption(Client::booStatsUpdate)); - } - switch (slot_id) { - case EQ::invslot::slotCharm: - case EQ::invslot::slotEar1: - case EQ::invslot::slotHead: - case EQ::invslot::slotFace: - case EQ::invslot::slotEar2: - case EQ::invslot::slotNeck: - case EQ::invslot::slotBack: - case EQ::invslot::slotWrist1: - case EQ::invslot::slotWrist2: - case EQ::invslot::slotRange: - case EQ::invslot::slotPrimary: - case EQ::invslot::slotSecondary: - case EQ::invslot::slotFinger1: - case EQ::invslot::slotFinger2: - case EQ::invslot::slotChest: - case EQ::invslot::slotWaist: - case EQ::invslot::slotPowerSource: - case EQ::invslot::slotAmmo: - c->Message( - Chat::White, - fmt::format( - "My {} (Slot {}) is {} unequipped.", - EQ::invslot::GetInvPossessionsSlotName(slot_id), - slot_id, - itm ? "now" : "already" - ).c_str() - ); - break; - case EQ::invslot::slotShoulders: - case EQ::invslot::slotArms: - case EQ::invslot::slotHands: - case EQ::invslot::slotLegs: - case EQ::invslot::slotFeet: - c->Message( - Chat::White, - fmt::format( - "My {} (Slot {}) are {} unequipped", - EQ::invslot::GetInvPossessionsSlotName(slot_id), - slot_id, - itm ? "now" : "already" - ).c_str() - ); - break; - default: - break; + my_bot->OwnerMessage( + fmt::format( + "I have unequipped {} from my {} (Slot {}).", + linker.GenerateLink(), + EQ::invslot::GetInvPossessionsSlotName(slot_id), + slot_id + ) + ); } } @@ -8554,7 +9402,7 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) if (helper_is_help_or_usage(sep->arg[1])) { c->Message( - Chat::Cyan, + Chat::White, fmt::format( "Usage: {} [actionable: target]", sep->arg[0] @@ -8572,7 +9420,7 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) auto my_bot = sbl.front(); if (!my_bot) { - c->Message(Chat::Magenta, "ActionableBots returned 'nullptr'"); + c->Message(Chat::White, "ActionableBots returned 'nullptr'"); return; } @@ -8611,7 +9459,7 @@ void bot_subcommand_pet_get_lost(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_pet_get_lost", sep->arg[0], "petgetlost")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); return; } int ab_mask = ActionableBots::ABM_NoFilter; @@ -8634,7 +9482,7 @@ void bot_subcommand_pet_get_lost(Client *c, const Seperator *sep) ++summoned_pet; } - c->Message(Chat::Yellow, "%i of your bots released their summoned pet%s", summoned_pet, (summoned_pet == 1) ? "" : "s"); + c->Message(Chat::White, "%i of your bots released their summoned pet%s", summoned_pet, (summoned_pet == 1) ? "" : "s"); } void bot_subcommand_pet_remove(Client *c, const Seperator *sep) @@ -8642,7 +9490,7 @@ void bot_subcommand_pet_remove(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_pet_remove", sep->arg[0], "petremove")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "usage: %s ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); return; } int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); @@ -8654,7 +9502,7 @@ void bot_subcommand_pet_remove(Client *c, const Seperator *sep) uint16 class_mask = (PLAYER_CLASS_DRUID_BIT | PLAYER_CLASS_NECROMANCER_BIT | PLAYER_CLASS_ENCHANTER_BIT); ActionableBots::Filter_ByClasses(c, sbl, class_mask); if (sbl.empty()) { - c->Message(Chat::Red, "You have no spawned bots capable of charming"); + c->Message(Chat::White, "You have no spawned bots capable of charming"); return; } sbl.remove(nullptr); @@ -8682,7 +9530,7 @@ void bot_subcommand_pet_remove(Client *c, const Seperator *sep) } if (sbl.size() != 1) - c->Message(Chat::Yellow, "%i of your bots set for charming, %i of your bots set for summoned pet use", charmed_pet, summoned_pet); + c->Message(Chat::White, "%i of your bots set for charming, %i of your bots set for summoned pet use", charmed_pet, summoned_pet); } void bot_subcommand_pet_set_type(Client *c, const Seperator *sep) @@ -8690,8 +9538,8 @@ void bot_subcommand_pet_set_type(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_pet_set_type", sep->arg[0], "petsettype")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [type: water | fire | air | earth | monster] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); - c->Message(Chat::Gray, "requires one of the following bot classes:"); + c->Message(Chat::White, "usage: %s [type: water | fire | air | earth | monster] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + c->Message(Chat::White, "requires one of the following bot classes:"); c->Message(Chat::White, "Magician(1)"); return; } @@ -8723,7 +9571,7 @@ void bot_subcommand_pet_set_type(Client *c, const Seperator *sep) } if (pet_type == 255) { - c->Message(Chat::Red, "You must specify a pet [type: water | fire | air | earth | monster]"); + c->Message(Chat::White, "You must specify a pet [type: water | fire | air | earth | monster]"); return; } @@ -8734,13 +9582,13 @@ void bot_subcommand_pet_set_type(Client *c, const Seperator *sep) uint16 class_mask = PLAYER_CLASS_MAGICIAN_BIT; ActionableBots::Filter_ByClasses(c, sbl, class_mask); if (sbl.empty()) { - c->Message(Chat::Red, "You have no spawned Magician bots"); + c->Message(Chat::White, "You have no spawned Magician bots"); return; } ActionableBots::Filter_ByMinLevel(c, sbl, level_req); if (sbl.empty()) { - c->Message(Chat::Red, "You have no spawned Magician bots capable of using this pet type: '%s'", pet_arg.c_str()); + c->Message(Chat::White, "You have no spawned Magician bots capable of using this pet type: '%s'", pet_arg.c_str()); return; } @@ -8765,7 +9613,7 @@ void bot_subcommand_portal(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Depart) || helper_command_alias_fail(c, "bot_subcommand_portal", sep->arg[0], "portal")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::Cyan, "usage: %s [list | destination] ([option: single])", sep->arg[0]); + c->Message(Chat::White, "usage: %s [list | destination] ([option: single])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_Depart, WIZARD); return; } @@ -8782,7 +9630,7 @@ void bot_subcommand_portal(Client *c, const Seperator *sep) return; } else if (destination.empty()) { - c->Message(Chat::Red, "A [destination] or [list] argument is required to use this command"); + c->Message(Chat::White, "A [destination] or [list] argument is required to use this command"); return; } @@ -8826,13 +9674,13 @@ bool helper_bot_appearance_fail(Client *bot_owner, Bot *my_bot, BCEnum::AFType f { switch (fail_type) { case BCEnum::AFT_Value: - bot_owner->Message(Chat::Red, "Failed to change '%s' for %s due to invalid value for this command", type_desc, my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "Failed to change '%s' for %s due to invalid value for this command", type_desc, my_bot->GetCleanName()); return true; case BCEnum::AFT_GenderRace: - bot_owner->Message(Chat::Red, "Failed to change '%s' for %s due to invalid bot gender and/or race for this command", type_desc, my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "Failed to change '%s' for %s due to invalid bot gender and/or race for this command", type_desc, my_bot->GetCleanName()); return true; case BCEnum::AFT_Race: - bot_owner->Message(Chat::Red, "Failed to change '%s' for %s due to invalid bot race for this command", type_desc, my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "Failed to change '%s' for %s due to invalid bot race for this command", type_desc, my_bot->GetCleanName()); return true; default: return false; @@ -8844,12 +9692,12 @@ void helper_bot_appearance_form_final(Client *bot_owner, Bot *my_bot) if (!MyBots::IsMyBot(bot_owner, my_bot)) return; if (!my_bot->Save()) { - bot_owner->Message(Chat::Magenta, "Failed to save appearance change for %s due to unknown cause...", my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "Failed to save appearance change for %s due to unknown cause...", my_bot->GetCleanName()); return; } helper_bot_appearance_form_update(my_bot); - bot_owner->Message(Chat::Yellow, "Successfully changed appearance for %s!", my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "Successfully changed appearance for %s!", my_bot->GetCleanName()); } void helper_bot_appearance_form_update(Bot *my_bot) @@ -8880,29 +9728,54 @@ void helper_bot_appearance_form_update(Bot *my_bot) uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_class, uint16 bot_race, uint8 bot_gender) { uint32 bot_id = 0; - if (!bot_owner) + if (!bot_owner) { return bot_id; + } + if (!Bot::IsValidName(bot_name)) { - bot_owner->Message(Chat::Red, "'%s' is an invalid name. You may only use characters 'A-Z', 'a-z' and '_'", bot_name.c_str()); + bot_owner->Message( + Chat::White, + fmt::format( + "'{}' is an invalid name. You may only use characters 'A-Z', 'a-z' and '_'.", + bot_name + ).c_str() + ); return bot_id; } bool available_flag = false; if (!database.botdb.QueryNameAvailablity(bot_name, available_flag)) { - bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::QueryNameAvailablity(), bot_name.c_str()); - return bot_id; - } - if (!available_flag) { - bot_owner->Message(Chat::Red, "The name %s is already being used. Please choose a different name", bot_name.c_str()); + bot_owner->Message( + Chat::White, + fmt::format( + "Failed to query name availability for '{}'.", + bot_name + ).c_str() + ); return bot_id; } - if (!Bot::IsValidRaceClassCombo(bot_race, bot_class)) { - const char* bot_race_name = GetRaceIDName(bot_race); - const char* bot_class_name = GetClassIDName(bot_class); - std::string view_saylink = EQ::SayLinkEngine::GenerateQuestSaylink(fmt::format("^viewcombos {}", bot_race), false, "view"); + if (!available_flag) { bot_owner->Message( - Chat::Red, + Chat::White, + fmt::format( + "The name '{}' is already being used. Please choose a different name", + bot_name + ).c_str() + ); + return bot_id; + } + + if (!Bot::IsValidRaceClassCombo(bot_race, bot_class) && bot_owner->IsPlayerRace(bot_race)) { + const std::string bot_race_name = GetRaceIDName(bot_race); + const std::string bot_class_name = GetClassIDName(bot_class); + const auto view_saylink = Saylink::Silent( + fmt::format("^viewcombos {}", bot_race), + "view" + ); + + bot_owner->Message( + Chat::White, fmt::format( "{} {} is an invalid race-class combination, would you like to {} proper combinations for {}?", bot_race_name, @@ -8911,36 +9784,144 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas bot_race_name ).c_str() ); + return bot_id; } - if (bot_gender > FEMALE) { - bot_owner->Message(Chat::Red, "gender: %u (M), %u (F)", MALE, FEMALE); + if (!EQ::ValueWithin(bot_gender, MALE, FEMALE)) { + bot_owner->Message( + Chat::White, + fmt::format( + "Gender: {} ({}) or {} ({})", + GetGenderName(MALE), + MALE, + GetGenderName(FEMALE), + FEMALE + ).c_str() + ); return bot_id; } - uint32 max_bot_count = RuleI(Bots, CreationLimit); + auto bot_creation_limit = bot_owner->GetBotCreationLimit(); + auto bot_creation_limit_class = bot_owner->GetBotCreationLimit(bot_class); uint32 bot_count = 0; - if (!database.botdb.QueryBotCount(bot_owner->CharacterID(), bot_count)) { - bot_owner->Message(Chat::Red, "%s", BotDatabase::fail::QueryBotCount()); + uint32 bot_class_count = 0; + if (!database.botdb.QueryBotCount(bot_owner->CharacterID(), bot_class, bot_count, bot_class_count)) { + bot_owner->Message(Chat::White, "Failed to query bot count."); return bot_id; } - if (bot_count >= max_bot_count) { - bot_owner->Message(Chat::Red, "You have reached the maximum limit of %i bots.", max_bot_count); + + if (bot_creation_limit >= 0 && bot_count >= bot_creation_limit) { + std::string message; + + if (bot_creation_limit) { + message = fmt::format( + "You cannot create anymore than {} bot{}.", + bot_creation_limit, + bot_creation_limit != 1 ? "s" : "" + ); + } else { + message = "You cannot create any bots."; + } + + bot_owner->Message(Chat::White, message.c_str()); return bot_id; } + if (bot_creation_limit_class >= 0 && bot_class_count >= bot_creation_limit_class) { + std::string message; + + if (bot_creation_limit_class) { + message = fmt::format( + "You cannot create anymore than {} {} bot{}.", + bot_creation_limit_class, + GetClassIDName(bot_class), + bot_creation_limit_class != 1 ? "s" : "" + ); + } else { + message = fmt::format( + "You cannot create any {} bots.", + GetClassIDName(bot_class) + ); + } + + bot_owner->Message(Chat::White, message.c_str()); + return bot_id; + } + + auto bot_character_level = bot_owner->GetBotRequiredLevel(); + + if ( + bot_character_level >= 0 && + bot_owner->GetLevel() < bot_character_level + ) { + bot_owner->Message( + Chat::White, + fmt::format( + "You must be level {} to use bots.", + bot_character_level + ).c_str() + ); + return bot_id; + } + + auto bot_character_level_class = bot_owner->GetBotRequiredLevel(bot_class); + + if ( + bot_character_level_class >= 0 && + bot_owner->GetLevel() < bot_character_level_class + ) { + bot_owner->Message( + Chat::White, + fmt::format( + "You must be level {} to use {} bots.", + bot_character_level_class, + GetClassIDName(bot_class) + ).c_str() + ); + return bot_id; + } + + auto my_bot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(bot_name.c_str(), "", bot_owner->GetLevel(), bot_race, bot_class, bot_gender), bot_owner); if (!my_bot->Save()) { - bot_owner->Message(Chat::Magenta, "Failed to create '%s' due to unknown cause", my_bot->GetCleanName()); + bot_owner->Message( + Chat::White, + fmt::format( + "Failed to create '{}' due to unknown cause.", + my_bot->GetCleanName() + ).c_str() + ); + safe_delete(my_bot); return bot_id; } - bot_owner->Message(Chat::Yellow, "Successfully created '%s' (id: %u)", my_bot->GetCleanName(), my_bot->GetBotID()); + bot_owner->Message( + Chat::White, + fmt::format( + "Bot Created | Name: {} ID: {} Race: {} Class: {}", + my_bot->GetCleanName(), + my_bot->GetBotID(), + GetRaceIDName(my_bot->GetRace()), + GetClassIDName(my_bot->GetClass()) + ).c_str() + ); bot_id = my_bot->GetBotID(); + + const auto export_string = fmt::format( + "{} {} {} {} {}", + bot_name, + bot_id, + bot_race, + bot_class, + bot_gender + ); + + parse->EventPlayer(EVENT_BOT_CREATE, bot_owner, export_string, 0); + safe_delete(my_bot); return bot_id; @@ -8959,10 +9940,10 @@ void helper_bot_out_of_combat(Client *bot_owner, Bot *my_bot) case SHADOWKNIGHT: case DRUID: case MONK: - bot_owner->Message(Chat::Magenta, "%s has no out-of-combat behavior defined", my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "%s has no out-of-combat behavior defined", my_bot->GetCleanName()); break; case BARD: - bot_owner->Message(Chat::Yellow, "%s will %s use out-of-combat behavior for bard songs", my_bot->GetCleanName(), ((my_bot->GetAltOutOfCombatBehavior()) ? ("now") : ("no longer"))); + bot_owner->Message(Chat::White, "%s will %s use out-of-combat behavior for bard songs", my_bot->GetCleanName(), ((my_bot->GetAltOutOfCombatBehavior()) ? ("now") : ("no longer"))); break; case ROGUE: case SHAMAN: @@ -8972,11 +9953,11 @@ void helper_bot_out_of_combat(Client *bot_owner, Bot *my_bot) case ENCHANTER: case BEASTLORD: case BERSERKER: - bot_owner->Message(Chat::Magenta, "%s has no out-of-combat behavior defined", my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "%s has no out-of-combat behavior defined", my_bot->GetCleanName()); break; default: break; - bot_owner->Message(Chat::Red, "Undefined bot class for %s", my_bot->GetCleanName()); + bot_owner->Message(Chat::White, "Undefined bot class for %s", my_bot->GetCleanName()); } } @@ -9055,8 +10036,16 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, return false; casting_bot->InterruptSpell(); - if (annouce_cast) - Bot::BotGroupSay(casting_bot, "Attempting to cast '%s' on %s", spells[spell_id].name, target_mob->GetCleanName()); + if (annouce_cast) { + Bot::BotGroupSay( + casting_bot, + fmt::format( + "Attempting to cast {} on {}.", + spells[spell_id].name, + target_mob->GetCleanName() + ).c_str() + ); + } return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQ::spells::CastingSlot::Gem2, -1, -1, dont_root_before); } @@ -9064,7 +10053,7 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, bool helper_command_disabled(Client* bot_owner, bool rule_value, const char* command) { if (rule_value == false) { - bot_owner->Message(Chat::Red, "Bot command %s is not enabled on this server.", command); + bot_owner->Message(Chat::White, "Bot command %s is not enabled on this server.", command); return true; } @@ -9075,7 +10064,7 @@ bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, c { auto alias_iter = bot_command_aliases.find(&alias[1]); if (alias_iter == bot_command_aliases.end() || alias_iter->second.compare(command)) { - bot_owner->Message(Chat::Red, "Undefined linker usage in %s (%s)", command_handler, &alias[1]); + bot_owner->Message(Chat::White, "Undefined linker usage in %s (%s)", command_handler, &alias[1]); return true; } @@ -9084,54 +10073,115 @@ bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, c void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_bot, bcst_list* local_list, bool single_flag) { - if (!bot_owner) - return; - - if (!MyBots::IsMyBot(bot_owner, druid_bot)) - druid_bot = nullptr; - if (!MyBots::IsMyBot(bot_owner, wizard_bot)) - wizard_bot = nullptr; - if (!druid_bot && !wizard_bot) { - bot_owner->Message(Chat::Red, "No bots are capable of performing this action"); + if (!bot_owner) { + return; + } + + if (!MyBots::IsMyBot(bot_owner, druid_bot)) { + druid_bot = nullptr; + } + + if (!MyBots::IsMyBot(bot_owner, wizard_bot)) { + wizard_bot = nullptr; + } + + if (!druid_bot && !wizard_bot) { + bot_owner->Message(Chat::White, "No bots are capable of performing this action"); return; } - bot_owner->Message(Chat::White, "The following destinations are available:"); if (!local_list) { - bot_owner->Message(Chat::Red, "None"); + bot_owner->Message(Chat::White, "There are no destinations you can be taken to."); return; } std::string msg; std::string text_link; - int destinations = 0; + auto destination_count = 0; + auto destination_number = 1; for (auto list_iter : *local_list) { auto local_entry = list_iter->SafeCastToDepart(); - if (!local_entry) - continue; - - if (druid_bot && druid_bot->GetClass() == local_entry->caster_class && druid_bot->GetLevel() >= local_entry->spell_level) { - if (local_entry->single != single_flag) - continue; - msg = StringFormat("%ccircle %s%s", BOT_COMMAND_CHAR, spells[local_entry->spell_id].teleport_zone, ((single_flag) ? (" single") : (""))); - text_link = druid_bot->CreateSayLink(bot_owner, msg.c_str(), local_entry->long_name.c_str()); - Bot::BotGroupSay(druid_bot, "dest: '%s' click: %s", spells[local_entry->spell_id].teleport_zone, text_link.c_str()); - ++destinations; + if (!local_entry) { continue; } - if (wizard_bot && wizard_bot->GetClass() == local_entry->caster_class && wizard_bot->GetLevel() >= local_entry->spell_level) { - if (local_entry->single != single_flag) + + if ( + druid_bot && + druid_bot->GetClass() == local_entry->caster_class && + druid_bot->GetLevel() >= local_entry->spell_level + ) { + if (local_entry->single != single_flag) { continue; - msg = StringFormat("%cportal %s%s", BOT_COMMAND_CHAR, spells[local_entry->spell_id].teleport_zone, ((single_flag) ? (" single") : (""))); - text_link = wizard_bot->CreateSayLink(bot_owner, msg.c_str(), local_entry->long_name.c_str()); - Bot::BotGroupSay(wizard_bot, "dest: '%s' click: %s", spells[local_entry->spell_id].teleport_zone, text_link.c_str()); - ++destinations; + } + + msg = fmt::format( + "{}circle {}{}", + std::to_string(BOT_COMMAND_CHAR), + spells[local_entry->spell_id].teleport_zone, + single_flag ? " single" : "" + ); + + text_link = druid_bot->CreateSayLink( + bot_owner, + msg.c_str(), + "Goto" + ); + + druid_bot->OwnerMessage( + fmt::format( + "Destination {} | {} | {}", + destination_number, + local_entry->long_name, + text_link + ).c_str() + ); + + destination_count++; + destination_number++; + continue; + } + + if ( + wizard_bot && + wizard_bot->GetClass() == local_entry->caster_class && + wizard_bot->GetLevel() >= local_entry->spell_level + ) { + if (local_entry->single != single_flag) { + continue; + } + + msg = fmt::format( + "{}portal {}{}", + std::to_string(BOT_COMMAND_CHAR), + spells[local_entry->spell_id].teleport_zone, + single_flag ? " single" : "" + ); + + text_link = wizard_bot->CreateSayLink( + bot_owner, + msg.c_str(), + "Goto" + ); + + wizard_bot->OwnerMessage( + fmt::format( + "Destination {} | {} | {}", + destination_number, + local_entry->long_name, + text_link + ).c_str() + ); + + destination_count++; + destination_number++; continue; } } - if (!destinations) - bot_owner->Message(Chat::Red, "None"); + + if (!destination_count) { + bot_owner->Message(Chat::White, "There are no destinations you can be taken to."); + } } bool helper_is_help_or_usage(const char* arg) @@ -9149,7 +10199,7 @@ bool helper_no_available_bots(Client *bot_owner, Bot *my_bot) if (!bot_owner) return true; if (!my_bot) { - bot_owner->Message(Chat::Red, "No bots are capable of performing this action"); + bot_owner->Message(Chat::White, "No bots are capable of performing this action"); return true; } @@ -9168,7 +10218,7 @@ void helper_send_available_subcommands(Client *bot_owner, const char* command_si if (bot_owner->Admin() < find_iter->second->access) continue; - bot_owner->Message(Chat::Cyan, "%c%s - %s", BOT_COMMAND_CHAR, subcommand_iter, ((find_iter != bot_command_list.end()) ? (find_iter->second->desc) : ("[no description]"))); + bot_owner->Message(Chat::White, "%c%s - %s", BOT_COMMAND_CHAR, subcommand_iter, ((find_iter != bot_command_list.end()) ? (find_iter->second->desc) : ("[no description]"))); ++bot_subcommands_shown; } @@ -9177,7 +10227,7 @@ void helper_send_available_subcommands(Client *bot_owner, const char* command_si void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class) { - bot_owner->Message(Chat::Gray, "requires one of the following bot classes:"); + bot_owner->Message(Chat::White, "requires one of the following bot classes:"); if (bot_class) bot_owner->Message(Chat::White, "%s", required_bots_map_by_class[spell_type][bot_class].c_str()); else @@ -9197,11 +10247,578 @@ bool helper_spell_check_fail(STBaseEntry* local_entry) bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::SpType spell_type) { if (!spell_list || spell_list->empty()) { - bot_owner->Message(Chat::Red, "%s", required_bots_map[spell_type].c_str()); + bot_owner->Message(Chat::White, "%s", required_bots_map[spell_type].c_str()); return true; } return false; } -#endif // BOTS +void bot_command_spell_list(Client* c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_spell_list", sep->arg[0], "spells")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Min Level] (Level is optional)", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + uint8 min_level = 0; + + if (sep->IsNumber(1)) { + min_level = static_cast(std::stoul(sep->arg[1])); + } + + my_bot->ListBotSpells(min_level); +} + +void bot_command_spell_settings_add(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_spell_settings_add", sep->arg[0], "spellsettingsadd")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID] [Priority] [Min HP] [Max HP]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + auto arguments = sep->argnum; + if ( + arguments < 4 || + !sep->IsNumber(1) || + !sep->IsNumber(2) || + !sep->IsNumber(3) || + !sep->IsNumber(4) + ) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID] [Priority] [Min HP] [Max HP]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto spell_id = static_cast(std::stoul(sep->arg[1])); + + if (!IsValidSpell(spell_id)) { + c->Message( + Chat::White, + fmt::format( + "Spell ID {} is invalid or could not be found.", + spell_id + ).c_str() + ); + return; + } + + if (my_bot->GetBotSpellSetting(spell_id)) { + c->Message( + Chat::White, + fmt::format( + "{} already has a spell setting for {} ({}), trying using {} instead.", + my_bot->GetCleanName(), + spells[spell_id].name, + spell_id, + Saylink::Silent("^spellsettingsupdate") + ).c_str() + ); + return; + } + + auto priority = static_cast(std::stoi(sep->arg[2])); + auto min_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[3]), -1, 99)); + auto max_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[4]), -1, 100)); + + BotSpellSetting bs; + + bs.priority = priority; + bs.min_hp = min_hp; + bs.max_hp = max_hp; + + if (!my_bot->AddBotSpellSetting(spell_id, &bs)) { + c->Message( + Chat::White, + fmt::format( + "Failed to add spell setting for {}.", + my_bot->GetCleanName() + ).c_str() + ); + return; + } + + my_bot->AI_AddBotSpells(my_bot->GetBotSpellID()); + + c->Message( + Chat::White, + fmt::format( + "Successfully added spell setting for {}.", + my_bot->GetCleanName() + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spell Setting Added | Spell: {} ({}) ", + spells[spell_id].name, + spell_id + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spell Setting Added | Priority: {} Health: {}", + priority, + my_bot->GetHPString(min_hp, max_hp) + ).c_str() + ); +} + +void bot_command_spell_settings_delete(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_spell_settings_delete", sep->arg[0], "spellsettingsdelete")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + auto arguments = sep->argnum; + if ( + arguments < 1 || + !sep->IsNumber(1) + ) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto spell_id = static_cast(std::stoul(sep->arg[1])); + + if (!IsValidSpell(spell_id)) { + c->Message( + Chat::White, + fmt::format( + "Spell ID {} is invalid or could not be found.", + spell_id + ).c_str() + ); + return; + } + + if (!my_bot->DeleteBotSpellSetting(spell_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to delete spell setting for {}.", + my_bot->GetCleanName() + ).c_str() + ); + return; + } + + my_bot->AI_AddBotSpells(my_bot->GetBotSpellID()); + + c->Message( + Chat::White, + fmt::format( + "Successfully deleted spell setting for {}.", + my_bot->GetCleanName() + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spell Setting Deleted | Spell: {} ({})", + spells[spell_id].name, + spell_id + ).c_str() + ); +} + +void bot_command_spell_settings_list(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_spell_settings_list", sep->arg[0], "spellsettings")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {}", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + my_bot->ListBotSpellSettings(); +} + +void bot_command_spell_settings_toggle(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_spell_settings_toggle", sep->arg[0], "spellsettingstoggle")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID] [Toggle]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + auto arguments = sep->argnum; + if ( + arguments < 2 || + !sep->IsNumber(1) + ) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID] [Toggle]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto spell_id = static_cast(std::stoul(sep->arg[1])); + if (!IsValidSpell(spell_id)) { + c->Message( + Chat::White, + fmt::format( + "Spell ID {} is invalid or could not be found.", + spell_id + ).c_str() + ); + return; + } + + bool toggle = ( + sep->IsNumber(2) ? + (std::stoi(sep->arg[2]) ? true : false) : + atobool(sep->arg[2]) + ); + + auto obs = my_bot->GetBotSpellSetting(spell_id); + if (!obs) { + return; + } + + BotSpellSetting bs; + + bs.priority = obs->priority; + bs.min_hp = obs->min_hp; + bs.max_hp = obs->max_hp; + bs.is_enabled = toggle; + + if (!my_bot->UpdateBotSpellSetting(spell_id, &bs)) { + c->Message( + Chat::White, + fmt::format( + "Failed to {}able spell for {}.", + toggle ? "en" : "dis", + my_bot->GetCleanName() + ).c_str() + ); + return; + } + + my_bot->AI_AddBotSpells(my_bot->GetBotSpellID()); + + c->Message( + Chat::White, + fmt::format( + "Successfully {}abled spell for {}.", + toggle ? "en" : "dis", + my_bot->GetCleanName() + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spell {}abled | Spell: {} ({})", + toggle ? "En" : "Dis", + spells[spell_id].name, + spell_id + ).c_str() + ); +} + +void bot_command_spell_settings_update(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_spell_settings_update", sep->arg[0], "spellsettingsupdate")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID] [Priority] [Min HP] [Max HP]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + auto arguments = sep->argnum; + if ( + arguments < 4 || + !sep->IsNumber(1) || + !sep->IsNumber(2) || + !sep->IsNumber(3) || + !sep->IsNumber(4) + ) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID] [Priority] [Min HP] [Max HP]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto spell_id = static_cast(std::stoul(sep->arg[1])); + + if (!IsValidSpell(spell_id)) { + c->Message( + Chat::White, + fmt::format( + "Spell ID {} is invalid or could not be found.", + spell_id + ).c_str() + ); + return; + } + + auto priority = static_cast(std::stoi(sep->arg[2])); + auto min_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[3]), -1, 99)); + auto max_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[4]), -1, 100)); + + BotSpellSetting bs; + + bs.priority = priority; + bs.min_hp = min_hp; + bs.max_hp = max_hp; + + if (!my_bot->UpdateBotSpellSetting(spell_id, &bs)) { + c->Message( + Chat::White, + fmt::format( + "Failed to update spell setting for {}.", + my_bot->GetCleanName() + ).c_str() + ); + return; + } + + my_bot->AI_AddBotSpells(my_bot->GetBotSpellID()); + + c->Message( + Chat::White, + fmt::format( + "Successfully updated spell setting for {}.", + my_bot->GetCleanName() + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spell Setting Updated | Spell: {} ({})", + spells[spell_id].name, + spell_id + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spell Setting Updated | Priority: {} Health: {}", + priority, + my_bot->GetHPString(min_hp, max_hp) + ).c_str() + ); +} + +void bot_spell_info_dialogue_window(Client* c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_spell_info_dialogue_window", sep->arg[0], "spellinfo")) { + return; + } + + auto arguments = sep->argnum; + if ( + arguments < 1 || + !sep->IsNumber(1) + ) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [Spell ID]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto min_level = spells[spell_id].classes; + auto class_level = min_level[my_bot->GetBotClass() - 1]; + + if (class_level > my_bot->GetLevel()) { + c->Message(Chat::White, "This is not a usable spell by your bot."); + return; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT value FROM db_str WHERE id = {} and type = 6 LIMIT 1", + spells[spell_id].effect_description_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + c->Message(Chat::White, "No Spell Information Available for this."); + return; + } + + auto row = results.begin(); + std::string spell_desc = row[0]; + + auto m = DialogueWindow::TableRow( + DialogueWindow::TableCell("Spell Effect: ") + + DialogueWindow::TableCell(spell_desc) + ); + + m += DialogueWindow::TableRow( + DialogueWindow::TableCell("Spell Level: ") + + DialogueWindow::TableCell(fmt::format("{}", class_level)) + ); + + c->SendPopupToClient( + fmt::format( + "Spell: {}", spells[spell_id].name + ).c_str(), + DialogueWindow::Table(m).c_str() + ); +} + +void bot_command_enforce_spell_list(Client* c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_enforce_spell_list", sep->arg[0], "enforcespellsettings")) { + return; + } + + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message( + Chat::White, + fmt::format( + "Usage: {} [True|False] (Blank to toggle]", + sep->arg[0] + ).c_str() + ); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must target a bot that you own to use this command."); + return; + } + + bool enforce_state = (sep->argnum > 0) ? Strings::ToBool(sep->arg[1]) : !my_bot->GetBotEnforceSpellSetting(); + my_bot->SetBotEnforceSpellSetting(enforce_state, true); + + c->Message( + Chat::White, + fmt::format( + "{}'s Spell Settings List entries are now {}.", + my_bot->GetCleanName(), + my_bot->GetBotEnforceSpellSetting() ? "enforced" : "optional" + ).c_str() + ); +} diff --git a/zone/bot_command.h b/zone/bot_command.h index 29e251ca0..270631ebd 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -20,8 +20,6 @@ #ifndef BOT_COMMAND_H #define BOT_COMMAND_H -#ifdef BOTS - class Client; class Seperator; @@ -526,7 +524,6 @@ typedef std::map> bcst_required_bot typedef std::map bcst_levels; typedef std::map bcst_levels_map; - #define BOT_COMMAND_CHAR '^' typedef void (*BotCmdFuncPtr)(Client *,const Seperator *); @@ -540,8 +537,7 @@ typedef struct { extern int (*bot_command_dispatch)(Client *,char const*); extern int bot_command_count; // number of bot commands loaded - -// the bot command system: +// Bot Command System: int bot_command_init(void); void bot_command_deinit(void); int bot_command_add(std::string bot_command_name, const char *desc, int access, BotCmdFuncPtr function); @@ -549,8 +545,7 @@ int bot_command_not_avail(Client *c, const char *message); int bot_command_real_dispatch(Client *c, char const *message); void bot_command_log_command(Client *c, const char *message); - -// bot commands +// Bot Commands void bot_command_actionable(Client *c, const Seperator *sep); void bot_command_aggressive(Client *c, const Seperator *sep); void bot_command_apply_poison(Client *c, const Seperator *sep); @@ -589,6 +584,14 @@ void bot_command_resurrect(Client *c, const Seperator *sep); void bot_command_rune(Client *c, const Seperator *sep); void bot_command_send_home(Client *c, const Seperator *sep); void bot_command_size(Client *c, const Seperator *sep); +void bot_command_spell_list(Client* c, const Seperator *sep); +void bot_command_spell_settings_add(Client* c, const Seperator *sep); +void bot_command_spell_settings_delete(Client* c, const Seperator *sep); +void bot_command_spell_settings_list(Client* c, const Seperator *sep); +void bot_command_spell_settings_toggle(Client* c, const Seperator *sep); +void bot_command_spell_settings_update(Client* c, const Seperator *sep); +void bot_spell_info_dialogue_window(Client* c, const Seperator *sep); +void bot_command_enforce_spell_list(Client* c, const Seperator* sep); void bot_command_summon_corpse(Client *c, const Seperator *sep); void bot_command_suspend(Client *c, const Seperator *sep); void bot_command_taunt(Client *c, const Seperator *sep); @@ -596,8 +599,7 @@ void bot_command_track(Client *c, const Seperator *sep); void bot_command_view_combos(Client *c, const Seperator *sep); void bot_command_water_breathing(Client *c, const Seperator *sep); - -// bot subcommands +// Bot Subcommands void bot_subcommand_bot_appearance(Client *c, const Seperator *sep); void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep); void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep); @@ -630,6 +632,7 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep); void bot_subcommand_bot_update(Client *c, const Seperator *sep); void bot_subcommand_bot_woad(Client *c, const Seperator *sep); void bot_subcommand_botgroup_add_member(Client *c, const Seperator *sep); +void bot_subcommand_botgroup_auto_spawn(Client *c, const Seperator *sep); void bot_subcommand_botgroup_create(Client *c, const Seperator *sep); void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep); void bot_subcommand_botgroup_list(Client *c, const Seperator *sep); @@ -682,9 +685,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b bool helper_is_help_or_usage(const char* arg); bool helper_no_available_bots(Client *bot_owner, Bot *my_bot = nullptr); void helper_send_available_subcommands(Client *bot_owner, const char* command_simile, const std::list& subcommand_list); -void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class = 0); +void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class = NO_CLASS); bool helper_spell_check_fail(STBaseEntry* local_entry); bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::SpType spell_type); #endif - -#endif // BOTS diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 520f1e5f0..600daab42 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -16,15 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef BOTS - +#include "../common/data_verification.h" #include "../common/global_define.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/eqemu_logsys.h" +#include "../common/repositories/bot_data_repository.h" +#include "../common/repositories/bot_inventories_repository.h" + #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "bot.h" #include "client.h" @@ -45,7 +47,7 @@ bool BotDatabase::LoadBotCommandSettings(std::map('(', ')'), join_pair(",", std::pair('\'', '\''), injected) @@ -72,9 +74,8 @@ bool BotDatabase::UpdateInjectedBotCommandSettings(const std::vector('\'', '\''), orphaned) + Strings::ImplodePair(",", std::pair('\'', '\''), orphaned) ); if (!database.QueryDatabase(query).Success()) { return false; } - Log(Logs::General, - Logs::Status, - "%u Orphaned Bot Command%s Deleted", + LogInfo( + "[{}] Orphaned Bot Command{} Deleted", orphaned.size(), (orphaned.size() == 1 ? "" : "s") ); @@ -167,53 +167,72 @@ bool BotDatabase::LoadBotSpellCastingChances() /* Bot functions */ bool BotDatabase::QueryNameAvailablity(const std::string& bot_name, bool& available_flag) { - if (bot_name.empty() || bot_name.size() > 60 || !database.CheckUsedName(bot_name.c_str())) + if (bot_name.empty() || bot_name.size() > 60 || !database.CheckUsedName(bot_name)) { return false; + } + + query = fmt::format( + "SELECT b.bot_id FROM bot_data b " + "INNER JOIN character_data c ON b.`name` = c.`name` " + "WHERE b.`name` LIKE '{0}' OR c.`name` LIKE '{0}' " + "LIMIT 1", + bot_name + ); - query = StringFormat("SELECT `id` FROM `vw_bot_character_mobs` WHERE `name` LIKE '%s' LIMIT 1", bot_name.c_str()); auto results = database.QueryDatabase(query); - if (!results.Success()) + if (!results.Success()) { return false; - if (results.RowCount()) + } + + if (results.RowCount()) { return true; + } available_flag = true; return true; } -bool BotDatabase::QueryBotCount(const uint32 owner_id, uint32& bot_count) +bool BotDatabase::QueryBotCount(const uint32 owner_id, int class_id, uint32& bot_count, uint32& bot_class_count) { - if (!owner_id) + if (!owner_id) { return false; + } - query = StringFormat("SELECT COUNT(`bot_id`) FROM `bot_data` WHERE `owner_id` = '%i'", owner_id); + query = fmt::format( + "SELECT COUNT(`bot_id`) FROM `bot_data` WHERE `owner_id` = {}", + owner_id + ); auto results = database.QueryDatabase(query); - if (!results.Success()) + if (!results.Success()) { return false; - if (!results.RowCount()) + } + + if (!results.RowCount()) { return true; + } auto row = results.begin(); - bot_count = atoi(row[0]); + bot_count = std::stoul(row[0]); - return true; -} + if (EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) { + query = fmt::format( + "SELECT COUNT(`bot_id`) FROM `bot_data` WHERE `owner_id` = {} AND `class` = {}", + owner_id, + class_id + ); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } -bool BotDatabase::LoadQuestableSpawnCount(const uint32 owner_id, int& spawn_count) -{ - if (!owner_id) - return false; + if (!results.RowCount()) { + return true; + } - query = StringFormat("SELECT `value` FROM `quest_globals` WHERE `name` = 'bot_spawn_limit' AND `charid` = '%i' LIMIT 1", owner_id); - auto results = database.QueryDatabase(query); // use 'database' for non-bot table calls - if (!results.Success()) - return false; - if (!results.RowCount()) - return true; - - auto row = results.begin(); - spawn_count = atoi(row[0]); + auto row = results.begin(); + bot_class_count = std::stoul(row[0]); + } return true; } @@ -301,148 +320,161 @@ bool BotDatabase::LoadOwnerID(const uint32 bot_id, uint32& owner_id) return true; } +uint32 BotDatabase::GetOwnerID(const uint32 bot_id) +{ + if (!bot_id) { + return 0; + } + + const auto& l = BotDataRepository::FindOne(database, bot_id); + if (!l.bot_id) { + return 0; + } + + return l.owner_id; +} + bool BotDatabase::LoadBotID(const uint32 owner_id, const std::string& bot_name, uint32& bot_id) { - if (!owner_id || bot_name.empty()) + if (!owner_id || bot_name.empty()) { return false; + } - query = StringFormat( - "SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = '%u' AND `name` = '%s' LIMIT 1", - owner_id, bot_name.c_str() + query = fmt::format( + "SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = {} AND `name` = '{}' LIMIT 1", + owner_id, + bot_name ); + auto results = database.QueryDatabase(query); - if (!results.Success()) + if (!results.Success()) { return false; - if (!results.RowCount()) + } + + if (!results.RowCount()) { return true; + } auto row = results.begin(); - bot_id = atoi(row[0]); + bot_id = std::stoul(row[0]); + + return true; +} + +bool BotDatabase::LoadBotID(const uint32 owner_id, const std::string& bot_name, uint32& bot_id, uint8& bot_class_id) +{ + if (!owner_id || bot_name.empty()) { + return false; + } + + query = fmt::format( + "SELECT `bot_id`, `class` FROM `bot_data` WHERE `owner_id` = {} AND `name` = '{}' LIMIT 1", + owner_id, + bot_name + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + if (!results.RowCount()) { + return true; + } + + auto row = results.begin(); + bot_id = std::stoul(row[0]); + bot_class_id = static_cast(std::stoul(row[1])); return true; } bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) { - if (!bot_id || loaded_bot) + if (!bot_id || loaded_bot) { return false; + } - query = StringFormat( - "SELECT" - " `owner_id`," - " `spells_id`," - " `name`," - " `last_name`," - " `title`," - " `suffix`," - " `zone_id`," - " `gender`," - " `race`," - " `class`," - " `level`," - " `deity`," /* planned use[11] */ - " `creation_day`," /* not in-use[12] */ - " `last_spawn`," /* not in-use[13] */ - " `time_spawned`," - " `size`," - " `face`," - " `hair_color`," - " `hair_style`," - " `beard`," - " `beard_color`," - " `eye_color_1`," - " `eye_color_2`," - " `drakkin_heritage`," - " `drakkin_tattoo`," - " `drakkin_details`," - " `ac`," /* not in-use[26] */ - " `atk`," /* not in-use[27] */ - " `hp`," - " `mana`," - " `str`," /* not in-use[30] */ - " `sta`," /* not in-use[31] */ - " `cha`," /* not in-use[32] */ - " `dex`," /* not in-use[33] */ - " `int`," /* not in-use[34] */ - " `agi`," /* not in-use[35] */ - " `wis`," /* not in-use[36] */ - " `fire`," /* not in-use[37] */ - " `cold`," /* not in-use[38] */ - " `magic`," /* not in-use[39] */ - " `poison`," /* not in-use[40] */ - " `disease`," /* not in-use[41] */ - " `corruption`," /* not in-use[42] */ - " `show_helm`," // 43 - " `follow_distance`," // 44 - " `stop_melee_level`" // 45 - " FROM `bot_data`" - " WHERE `bot_id` = '%u'" - " LIMIT 1", - bot_id + const auto& l = BotDataRepository::FindOne(database, bot_id); + if (!l.bot_id) { + return false; + } + + auto d = Bot::CreateDefaultNPCTypeStructForBot( + l.name, + l.last_name, + l.level, + l.race, + l.class_, + l.gender ); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return false; - if (!results.RowCount()) - return true; - - // TODO: Consider removing resists and basic attributes from the load query above since we're using defaultNPCType values instead - auto row = results.begin(); - auto defaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7])); - auto tempNPCStruct = Bot::FillNPCTypeStruct( - atoi(row[1]), - std::string(row[2]), - std::string(row[3]), - atoi(row[10]), - atoi(row[8]), - atoi(row[9]), - atoi(row[7]), - atof(row[15]), - atoi(row[16]), - atoi(row[18]), - atoi(row[17]), - atoi(row[21]), - atoi(row[22]), - atoi(row[20]), - atoi(row[19]), - atoi(row[23]), - atoi(row[24]), - atoi(row[25]), - atoi(row[28]), - atoi(row[29]), - defaultNPCTypeStruct->MR, - defaultNPCTypeStruct->CR, - defaultNPCTypeStruct->DR, - defaultNPCTypeStruct->FR, - defaultNPCTypeStruct->PR, - defaultNPCTypeStruct->Corrup, - defaultNPCTypeStruct->AC, - defaultNPCTypeStruct->STR, - defaultNPCTypeStruct->STA, - defaultNPCTypeStruct->DEX, - defaultNPCTypeStruct->AGI, - defaultNPCTypeStruct->INT, - defaultNPCTypeStruct->WIS, - defaultNPCTypeStruct->CHA, - defaultNPCTypeStruct->ATK + auto t = Bot::FillNPCTypeStruct( + l.spells_id, + l.name, + l.last_name, + l.level, + l.race, + l.class_, + l.gender, + l.size, + l.face, + l.hair_style, + l.hair_color, + l.eye_color_1, + l.eye_color_2, + l.beard, + l.beard_color, + l.drakkin_heritage, + l.drakkin_tattoo, + l.drakkin_details, + l.hp, + l.mana, + d->MR, + d->CR, + d->DR, + d->FR, + d->PR, + d->Corrup, + d->AC, + d->STR, + d->STA, + d->DEX, + d->AGI, + d->INT, + d->WIS, + d->CHA, + d->ATK + ); + + safe_delete(d); + + loaded_bot = new Bot( + bot_id, + l.owner_id, + l.spells_id, + l.time_spawned, + l.zone_id, + t ); - loaded_bot = new Bot(bot_id, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct); if (loaded_bot) { - loaded_bot->SetShowHelm((atoi(row[43]) > 0 ? true : false)); - loaded_bot->SetSurname(row[3]);//maintaining outside mob::lastname to cater to spaces - loaded_bot->SetTitle(row[4]); - loaded_bot->SetSuffix(row[5]); - uint32 bfd = atoi(row[44]); - if (bfd < 1) - bfd = 1; - if (bfd > BOT_FOLLOW_DISTANCE_DEFAULT_MAX) - bfd = BOT_FOLLOW_DISTANCE_DEFAULT_MAX; + loaded_bot->SetSurname(l.last_name); + loaded_bot->SetTitle(l.title); + loaded_bot->SetSuffix(l.suffix); + + loaded_bot->SetShowHelm((l.show_helm ? true : false)); + + auto bfd = EQ::Clamp(l.follow_distance, static_cast(1), BOT_FOLLOW_DISTANCE_DEFAULT_MAX); loaded_bot->SetFollowDistance(bfd); - uint8 sml = atoi(row[45]); - loaded_bot->SetStopMeleeLevel(sml); + loaded_bot->SetStopMeleeLevel(l.stop_melee_level); + + loaded_bot->SetExpansionBitmask(l.expansion_bitmask, false); + + loaded_bot->SetBotEnforceSpellSetting((l.enforce_spell_settings ? true : false)); + + loaded_bot->SetBotArcherySetting((l.archery_setting ? true : false)); } return true; @@ -450,263 +482,147 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) bool BotDatabase::SaveNewBot(Bot* bot_inst, uint32& bot_id) { - if (!bot_inst) + if (!bot_inst) { return false; + } - query = StringFormat( - "INSERT INTO `bot_data` (" - " `owner_id`," - " `spells_id`," - " `name`," - " `last_name`," - " `zone_id`," - " `gender`," - " `race`," - " `class`," - " `level`," - " `creation_day`," - " `last_spawn`," - " `time_spawned`," - " `size`," - " `face`," - " `hair_color`," - " `hair_style`," - " `beard`," - " `beard_color`," - " `eye_color_1`," - " `eye_color_2`," - " `drakkin_heritage`," - " `drakkin_tattoo`," - " `drakkin_details`," - " `ac`," - " `atk`," - " `hp`," - " `mana`," - " `str`," - " `sta`," - " `cha`," - " `dex`," - " `int`," - " `agi`," - " `wis`," - " `fire`," - " `cold`," - " `magic`," - " `poison`," - " `disease`," - " `corruption`," - " `show_helm`," - " `follow_distance`," - " `stop_melee_level`" - ")" - " VALUES (" - "'%u'," /* owner_id */ - " '%u'," /* spells_id */ - " '%s'," /* name */ - " '%s'," /* last_name */ - " '%i'," /* zone_id */ - " '%i'," /* gender */ - " '%i'," /* race */ - " '%i'," /* class */ - " '%u'," /* level */ - " UNIX_TIMESTAMP()," /* creation_day */ - " UNIX_TIMESTAMP()," /* last_spawn */ - " 0," /* time_spawned */ - " '%f'," /* size */ - " '%i'," /* face */ - " '%i'," /* hair_color */ - " '%i'," /* hair_style */ - " '%i'," /* beard */ - " '%i'," /* beard_color */ - " '%i'," /* eye_color_1 */ - " '%i'," /* eye_color_2 */ - " '%i'," /* drakkin_heritage */ - " '%i'," /* drakkin_tattoo */ - " '%i'," /* drakkin_details */ - " '%i'," /* ac */ - " '%i'," /* atk */ - " '%i'," /* hp */ - " '%i'," /* mana */ - " '%i'," /* str */ - " '%i'," /* sta */ - " '%i'," /* cha */ - " '%i'," /* dex */ - " '%i'," /* int */ - " '%i'," /* agi */ - " '%i'," /* wis */ - " '%i'," /* fire */ - " '%i'," /* cold */ - " '%i'," /* magic */ - " '%i'," /* poison */ - " '%i'," /* disease */ - " '%i'," /* corruption */ - " '1'," /* show_helm */ - " '%i'," /* follow_distance */ - " '%u'" /* stop_melee_level */ - ")", - bot_inst->GetBotOwnerCharacterID(), - bot_inst->GetBotSpellID(), - bot_inst->GetCleanName(), - bot_inst->GetLastName(), - bot_inst->GetLastZoneID(), - bot_inst->GetGender(), - bot_inst->GetRace(), - bot_inst->GetClass(), - bot_inst->GetLevel(), - bot_inst->GetSize(), - bot_inst->GetLuclinFace(), - bot_inst->GetHairColor(), - bot_inst->GetHairStyle(), - bot_inst->GetBeard(), - bot_inst->GetBeardColor(), - bot_inst->GetEyeColor1(), - bot_inst->GetEyeColor2(), - bot_inst->GetDrakkinHeritage(), - bot_inst->GetDrakkinTattoo(), - bot_inst->GetDrakkinDetails(), - bot_inst->GetAC(), - bot_inst->GetATK(), - bot_inst->GetHP(), - bot_inst->GetMana(), - bot_inst->GetSTR(), - bot_inst->GetSTA(), - bot_inst->GetCHA(), - bot_inst->GetDEX(), - bot_inst->GetINT(), - bot_inst->GetAGI(), - bot_inst->GetWIS(), - bot_inst->GetFR(), - bot_inst->GetCR(), - bot_inst->GetMR(), - bot_inst->GetPR(), - bot_inst->GetDR(), - bot_inst->GetCorrup(), - (uint32)BOT_FOLLOW_DISTANCE_DEFAULT, - (IsCasterClass(bot_inst->GetClass()) ? (uint8)RuleI(Bots, CasterStopMeleeLevel) : 255) - ); - auto results = database.QueryDatabase(query); - if (!results.Success()) + auto e = BotDataRepository::NewEntity(); + + e.owner_id = bot_inst->GetBotOwnerCharacterID(); + e.spells_id = bot_inst->GetBotSpellID(); + e.name = bot_inst->GetCleanName(); + e.last_name = bot_inst->GetLastName(); + e.title = bot_inst->GetTitle(); + e.suffix = bot_inst->GetSuffix(); + e.zone_id = bot_inst->GetLastZoneID(); + e.gender = bot_inst->GetGender(); + e.race = bot_inst->GetBaseRace(); + e.class_ = bot_inst->GetClass(); + e.level = bot_inst->GetLevel(); + e.creation_day = std::time(nullptr); + e.last_spawn = std::time(nullptr); + e.size = bot_inst->GetSize(); + e.face = bot_inst->GetLuclinFace(); + e.hair_color = bot_inst->GetHairColor(); + e.hair_style = bot_inst->GetHairStyle(); + e.beard = bot_inst->GetBeard(); + e.beard_color = bot_inst->GetBeardColor(); + e.eye_color_1 = bot_inst->GetEyeColor1(); + e.eye_color_2 = bot_inst->GetEyeColor2(); + e.drakkin_heritage = bot_inst->GetDrakkinHeritage(); + e.drakkin_tattoo = bot_inst->GetDrakkinTattoo(); + e.drakkin_details = bot_inst->GetDrakkinDetails(); + e.ac = bot_inst->GetBaseAC(); + e.atk = bot_inst->GetBaseATK(); + e.hp = bot_inst->GetHP(); + e.mana = bot_inst->GetMana(); + e.str = bot_inst->GetBaseSTR(); + e.sta = bot_inst->GetBaseSTA(); + e.cha = bot_inst->GetBaseCHA(); + e.dex = bot_inst->GetBaseDEX(); + e.int_ = bot_inst->GetBaseINT(); + e.agi = bot_inst->GetBaseAGI(); + e.wis = bot_inst->GetBaseWIS(); + e.fire = bot_inst->GetBaseFR(); + e.cold = bot_inst->GetBaseCR(); + e.magic = bot_inst->GetBaseMR(); + e.poison = bot_inst->GetBasePR(); + e.disease = bot_inst->GetBaseDR(); + e.corruption = bot_inst->GetBaseCorrup(); + e.show_helm = bot_inst->GetShowHelm() ? 1 : 0; + e.follow_distance = bot_inst->GetFollowDistance(); + e.stop_melee_level = bot_inst->GetStopMeleeLevel(); + e.expansion_bitmask = bot_inst->GetExpansionBitmask(); + e.enforce_spell_settings = bot_inst->GetBotEnforceSpellSetting(); + e.archery_setting = bot_inst->IsBotArcher() ? 1 : 0; + + auto b = BotDataRepository::InsertOne(database, e); + if (!b.bot_id) { return false; + } - bot_id = results.LastInsertedID(); + bot_id = b.bot_id; return true; } bool BotDatabase::SaveBot(Bot* bot_inst) { - if (!bot_inst) + if (!bot_inst) { return false; + } - query = StringFormat( - "UPDATE `bot_data`" - " SET" - " `owner_id` = '%u'," - " `spells_id` = '%u'," - " `name` = '%s'," - " `last_name` = '%s'," - " `zone_id` = '%i'," - " `gender` = '%i'," - " `race` = '%i'," - " `class` = '%i'," - " `level` = '%u'," - " `last_spawn` = UNIX_TIMESTAMP()," - " `time_spawned` = '%u'," - " `size` = '%f'," - " `face` = '%i'," - " `hair_color` = '%i'," - " `hair_style` = '%i'," - " `beard` = '%i'," - " `beard_color` = '%i'," - " `eye_color_1` = '%i'," - " `eye_color_2` = '%i'," - " `drakkin_heritage` = '%i'," - " `drakkin_tattoo` = '%i'," - " `drakkin_details` = '%i'," - " `ac` = '%i'," - " `atk` = '%i'," - " `hp` = '%i'," - " `mana` = '%i'," - " `str` = '%i'," - " `sta` = '%i'," - " `cha` = '%i'," - " `dex` = '%i'," - " `int` = '%i'," - " `agi` = '%i'," - " `wis` = '%i'," - " `fire` = '%i'," - " `cold` = '%i'," - " `magic` = '%i'," - " `poison` = '%i'," - " `disease` = '%i'," - " `corruption` = '%i'," - " `show_helm` = '%i'," - " `follow_distance` = '%i'," - " `stop_melee_level` = '%u'," - " `title` = '%s'," - " `suffix` = '%s'" - " WHERE `bot_id` = '%u'", - bot_inst->GetBotOwnerCharacterID(), - bot_inst->GetBotSpellID(), - bot_inst->GetCleanName(), - bot_inst->GetSurname().c_str(), - bot_inst->GetLastZoneID(), - bot_inst->GetBaseGender(), - bot_inst->GetBaseRace(), - bot_inst->GetClass(), - bot_inst->GetLevel(), - bot_inst->GetTotalPlayTime(), - bot_inst->GetBaseSize(), - bot_inst->GetLuclinFace(), - bot_inst->GetHairColor(), - bot_inst->GetHairStyle(), - bot_inst->GetBeard(), - bot_inst->GetBeardColor(), - bot_inst->GetEyeColor1(), - bot_inst->GetEyeColor2(), - bot_inst->GetDrakkinHeritage(), - bot_inst->GetDrakkinTattoo(), - bot_inst->GetDrakkinDetails(), - bot_inst->GetBaseAC(), - bot_inst->GetBaseATK(), - bot_inst->GetHP(), - bot_inst->GetMana(), - bot_inst->GetBaseSTR(), - bot_inst->GetBaseSTA(), - bot_inst->GetBaseCHA(), - bot_inst->GetBaseDEX(), - bot_inst->GetBaseINT(), - bot_inst->GetBaseAGI(), - bot_inst->GetBaseWIS(), - bot_inst->GetBaseFR(), - bot_inst->GetBaseCR(), - bot_inst->GetBaseMR(), - bot_inst->GetBasePR(), - bot_inst->GetBaseDR(), - bot_inst->GetBaseCorrup(), - ((bot_inst->GetShowHelm()) ? (1) : (0)), - bot_inst->GetFollowDistance(), - bot_inst->GetStopMeleeLevel(), - bot_inst->GetTitle().c_str(), - bot_inst->GetSuffix().c_str(), - bot_inst->GetBotID() - ); - auto results = database.QueryDatabase(query); - if (!results.Success()) + auto l = BotDataRepository::FindOne(database, bot_inst->GetBotID()); + if (!l.bot_id) { return false; + } + + l.owner_id = bot_inst->GetBotOwnerCharacterID(); + l.spells_id = bot_inst->GetBotSpellID(); + l.name = bot_inst->GetCleanName(); + l.last_name = bot_inst->GetLastName(); + l.title = bot_inst->GetTitle(); + l.suffix = bot_inst->GetSuffix(); + l.zone_id = bot_inst->GetLastZoneID(); + l.gender = bot_inst->GetBaseGender(); + l.race = bot_inst->GetBaseRace(); + l.class_ = bot_inst->GetClass(); + l.level = bot_inst->GetLevel(); + l.last_spawn = std::time(nullptr); + l.time_spawned = bot_inst->GetTotalPlayTime(); + l.size = bot_inst->GetSize(); + l.face = bot_inst->GetLuclinFace(); + l.hair_color = bot_inst->GetHairColor(); + l.hair_style = bot_inst->GetHairStyle(); + l.beard = bot_inst->GetBeard(); + l.beard_color = bot_inst->GetBeardColor(); + l.eye_color_1 = bot_inst->GetEyeColor1(); + l.eye_color_2 = bot_inst->GetEyeColor2(); + l.drakkin_heritage = bot_inst->GetDrakkinHeritage(); + l.drakkin_tattoo = bot_inst->GetDrakkinTattoo(); + l.drakkin_details = bot_inst->GetDrakkinDetails(); + l.ac = bot_inst->GetBaseAC(); + l.atk = bot_inst->GetBaseATK(); + l.hp = bot_inst->GetHP(); + l.mana = bot_inst->GetMana(); + l.str = bot_inst->GetBaseSTR(); + l.sta = bot_inst->GetBaseSTA(); + l.cha = bot_inst->GetBaseCHA(); + l.dex = bot_inst->GetBaseDEX(); + l.int_ = bot_inst->GetBaseINT(); + l.agi = bot_inst->GetBaseAGI(); + l.wis = bot_inst->GetBaseWIS(); + l.fire = bot_inst->GetBaseFR(); + l.cold = bot_inst->GetBaseCR(); + l.magic = bot_inst->GetBaseMR(); + l.poison = bot_inst->GetBasePR(); + l.disease = bot_inst->GetBaseDR(); + l.corruption = bot_inst->GetBaseCorrup(); + l.show_helm = bot_inst->GetShowHelm() ? 1 : 0; + l.follow_distance = bot_inst->GetFollowDistance(); + l.stop_melee_level = bot_inst->GetStopMeleeLevel(); + l.expansion_bitmask = bot_inst->GetExpansionBitmask(); + l.enforce_spell_settings = bot_inst->GetBotEnforceSpellSetting(); + l.archery_setting = bot_inst->IsBotArcher() ? 1 : 0; + + const auto updated = BotDataRepository::UpdateOne(database, l); + if (!updated) { + return false; + } return true; } bool BotDatabase::DeleteBot(const uint32 bot_id) { - if (!bot_id) + if (!bot_id) { return false; + } - query = StringFormat("DELETE FROM `bot_data` WHERE `bot_id` = '%u'", bot_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) + const auto deleted = BotDataRepository::DeleteOne(database, bot_id); + if (!deleted) { return false; + } return true; } @@ -796,8 +712,9 @@ bool BotDatabase::SaveBuffs(Bot* bot_inst) return false; for (int buff_index = 0; buff_index < BUFF_COUNT; ++buff_index) { - if (bot_buffs[buff_index].spellid <= 0 || bot_buffs[buff_index].spellid == SPELL_UNKNOWN) + if (!IsValidSpell(bot_buffs[buff_index].spellid)) { continue; + } query = StringFormat( "INSERT INTO `bot_buffs` (" @@ -1059,70 +976,6 @@ bool BotDatabase::DeleteTimers(const uint32 bot_id) return true; } -bool BotDatabase::LoadGuildMembership(const uint32 bot_id, uint32& guild_id, uint8& guild_rank, std::string& guild_name) -{ - if (!bot_id) - return false; - - query = StringFormat( - "SELECT" - " gm.`guild_id`," - " gm.`rank`," - " g.`name`" - " FROM `vw_guild_members` AS gm" - " JOIN `guilds` AS g" - " ON gm.`guild_id` = g.`id`" - " WHERE gm.`char_id` = '%u'" - " AND gm.`mob_type` = 'B'" - " LIMIT 1", - bot_id - ); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return false; - if (!results.RowCount()) - return true; - - auto row = results.begin(); - guild_id = atoi(row[0]); - guild_rank = atoi(row[1]); - guild_name = row[2]; - - return true; -} - -bool BotDatabase::SaveGuildMembership(const uint32 bot_id, const uint32 guild_id, const uint8 guild_rank) -{ - if (!bot_id || !guild_id) - return false; - - if (!DeleteGuildMembership(bot_id)) - return false; - - query = StringFormat("INSERT INTO `bot_guild_members` SET `bot_id` = '%u', `guild_id` = '%u', `rank` = '%u'", bot_id, guild_id, guild_rank); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - DeleteGuildMembership(bot_id); - return false; - } - - return true; -} - -bool BotDatabase::DeleteGuildMembership(const uint32 bot_id) -{ - if (!bot_id) - return false; - - query = StringFormat("DELETE FROM `bot_guild_members` WHERE `bot_id` = '%u'", bot_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return false; - - return true; -} - - /* Bot inventory functions */ bool BotDatabase::QueryInventoryCount(const uint32 bot_id, uint32& item_count) { @@ -1296,6 +1149,29 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint return true; } +bool BotDatabase::LoadItemSlots(const uint32 bot_id, std::map& m) +{ + if (!bot_id) { + return false; + } + + const auto& l = BotInventoriesRepository::GetWhere( + database, + fmt::format( + "bot_id = {}", + bot_id + ) + ); + + if (!l.empty()) { + for (const auto& e : l) { + m.insert(std::pair(e.slot_id, e.item_id)); + } + } + + return true; +} + bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQ::ItemInstance* item_inst) { if (!bot_inst || !bot_inst->GetBotID() || slot_id > EQ::invslot::EQUIPMENT_END) @@ -2320,124 +2196,174 @@ bool BotDatabase::SaveOwnerOption(const uint32 owner_id, const std::pair>& member_list) { - if (group_name.empty()) + if (group_name.empty()) { return false; + } uint32 botgroup_id = 0; - if (!LoadBotGroupIDByBotGroupName(group_name, botgroup_id)) + if (!LoadBotGroupIDByBotGroupName(group_name, botgroup_id)) { return false; - if (!botgroup_id) - return true; + } + + if (!botgroup_id) { + return true; + } + + query = fmt::format( + "SELECT `bot_id` FROM `bot_group_members` WHERE `groups_index` = {} LIMIT 6", + botgroup_id + ); - query = StringFormat("SELECT `bot_id` FROM `bot_group_members` WHERE `groups_index` = '%u' LIMIT 6", botgroup_id); auto results = database.QueryDatabase(query); - if (!results.Success()) + if (!results.Success()) { return false; - if (!results.RowCount()) - return true; + } - for (auto row = results.begin(); row != results.end(); ++row) - member_list[botgroup_id].push_back(atoi(row[0])); + if (!results.RowCount()) { + return true; + } + + for (auto row : results) { + member_list[botgroup_id].push_back(std::stoul(row[0])); + } return true; } bool BotDatabase::LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list>& botgroups_list) { - if (!owner_id) + if (!owner_id) { return false; + } + + + query = fmt::format( + "SELECT group_name, group_leader_name FROM " + "bot_groups bg INNER JOIN bot_group_members bgm " + "ON bg.groups_index = bgm.groups_index " + "WHERE bgm.bot_id IN " + "(SELECT bot_id FROM bot_data WHERE WHERE owner_id = {})", + owner_id + ); - query = StringFormat("SELECT `group_name`, `group_leader_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); auto results = database.QueryDatabase(query); - if (!results.Success()) + if (!results.Success()) { return false; - if (!results.RowCount()) - return true; + } - for (auto row = results.begin(); row != results.end(); ++row) + if (!results.RowCount()) { + return true; + } + + for (auto row : results) { botgroups_list.push_back(std::pair(row[0], row[1])); + } return true; } +bool BotDatabase::IsBotGroupAutoSpawn(const std::string& botgroup_name) +{ + if (botgroup_name.empty()) { + return false; + } + + query = fmt::format( + "SELECT group_name FROM bot_groups WHERE group_name = '{}' AND auto_spawn = 1", + botgroup_name + ); + + auto results = database.QueryDatabase(query); + if (!results.RowCount() || !results.Success()) { + return false; + } + + return true; +} + +bool BotDatabase::ToggleBotGroupAutoSpawn(const uint32 group_id) +{ + if (!group_id) { + return false; + } + + query = fmt::format( + "UPDATE bot_groups SET auto_spawn = 1 - auto_spawn WHERE groups_index = {}", + group_id + ); + + auto results = database.QueryDatabase(query); + if (!results.Success() || !results.RowsAffected()) { + return false; + } + + return true; +} + +bool BotDatabase::LoadAutoSpawnBotGroupsByOwnerID(const uint32 owner_id, std::list>& group_list) +{ + if (!owner_id) { + return false; + } + + query = fmt::format( + SQL( + SELECT group_leader_id, group_name FROM bot_groups WHERE groups_index IN ( + SELECT groups_index FROM bot_group_members WHERE bot_id IN ( + SELECT bot_id FROM bot_data WHERE owner_id = {} + ) + ) AND auto_spawn = 1 + ), + owner_id + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + if (!results.RowCount()) { + return true; + } + + for (auto row : results) { + group_list.push_back( + std::pair(std::stoul(row[0]), row[1]) + ); + } + + return true; +} /* Bot owner group functions */ // added owner ID to this function to fix groups with mulitple players grouped with bots. bool BotDatabase::LoadGroupedBotsByGroupID(const uint32 owner_id, const uint32 group_id, std::list& group_list) { - if (!group_id || !owner_id) + if (!group_id || !owner_id) { return false; + } - query = StringFormat( - "SELECT `charid`" - " FROM `group_id`" - " WHERE `groupid` = '%u'" - " AND `name` IN (" - " SELECT `name`" - " FROM `bot_data`" - " WHERE `owner_id` = '%u'" - " )", + query = fmt::format( + "SELECT `charid` FROM `group_id` WHERE `groupid` = {} AND `name` IN " + "(SELECT `name` FROM `bot_data` WHERE `owner_id` = {})", group_id, owner_id ); auto results = database.QueryDatabase(query); - if (!results.Success()) + if (!results.Success()) { return false; - if (!results.RowCount()) - return true; + } - for (auto row = results.begin(); row != results.end(); ++row) - group_list.push_back(atoi(row[0])); + if (!results.RowCount()) { + return true; + } + + for (auto row : results) { + group_list.push_back(std::stoul(row[0])); + } return true; } @@ -2967,13 +3051,72 @@ uint16 BotDatabase::GetRaceClassBitmask(uint16 bot_race) return classes; } +bool BotDatabase::SaveExpansionBitmask(const uint32 bot_id, const int expansion_bitmask) +{ + if (!bot_id) { + return false; + } + + query = fmt::format( + "UPDATE `bot_data` " + "SET `expansion_bitmask` = {} " + "WHERE `bot_id` = {}", + expansion_bitmask, + bot_id + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + return true; +} + +bool BotDatabase::SaveEnforceSpellSetting(const uint32 bot_id, const bool enforce_spell_setting) +{ + if (!bot_id) { + return false; + } + + query = fmt::format( + "UPDATE `bot_data`" + "SET `enforce_spell_settings` = {} " + "WHERE `bot_id` = {}", + (enforce_spell_setting ? 1 : 0), + bot_id + ); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + return true; +} + +bool BotDatabase::SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting) +{ + if (!bot_id) { + return false; + } + query = fmt::format( + "UPDATE `bot_data`" + "SET `archery_setting` = {} " + "WHERE `bot_id` = {}", + (bot_archer_setting ? 1 : 0), + bot_id + ); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + return true; +} + /* fail::Bot functions */ -const char* BotDatabase::fail::QueryNameAvailablity() { return "Failed to query name availability"; } -const char* BotDatabase::fail::QueryBotCount() { return "Failed to query bot count"; } -const char* BotDatabase::fail::LoadQuestableSpawnCount() { return "Failed to load questable spawn count"; } const char* BotDatabase::fail::LoadBotsList() { return "Failed to bots list"; } -const char* BotDatabase::fail::LoadOwnerID() { return "Failed to load owner id"; } -const char* BotDatabase::fail::LoadBotID() { return "Failed to load bot id"; } +const char* BotDatabase::fail::LoadOwnerID() { return "Failed to load owner ID"; } +const char* BotDatabase::fail::LoadBotID() { return "Failed to load bot ID"; } const char* BotDatabase::fail::LoadBot() { return "Failed to load bot"; } const char* BotDatabase::fail::SaveNewBot() { return "Failed to save new bot"; } const char* BotDatabase::fail::SaveBot() { return "Failed to save bot"; } @@ -2981,22 +3124,16 @@ const char* BotDatabase::fail::DeleteBot() { return "Failed to delete bot"; } const char* BotDatabase::fail::LoadBuffs() { return "Failed to load buffs"; } const char* BotDatabase::fail::SaveBuffs() { return "Failed to save buffs"; } const char* BotDatabase::fail::DeleteBuffs() { return "Failed to delete buffs"; } -const char* BotDatabase::fail::LoadStance() { return "Failed to load stance"; } -const char* BotDatabase::fail::SaveStance() { return "Failed to save stance"; } const char* BotDatabase::fail::DeleteStance() { return "Failed to delete stance"; } const char* BotDatabase::fail::LoadTimers() { return "Failed to load timers"; } const char* BotDatabase::fail::SaveTimers() { return "Failed to save timers"; } const char* BotDatabase::fail::DeleteTimers() { return "Failed to delete timers"; } -const char* BotDatabase::fail::LoadGuildMembership() { return "Failed to load guild membership"; } -const char* BotDatabase::fail::SaveGuildMembership() { return "Failed to save guild membership"; } -const char* BotDatabase::fail::DeleteGuildMembership() { return "Failed to delete guild membership"; } /* fail::Bot inventory functions */ const char* BotDatabase::fail::QueryInventoryCount() { return "Failed to query inventory count"; } const char* BotDatabase::fail::LoadItems() { return "Failed to load items"; } const char* BotDatabase::fail::SaveItems() { return "Failed to save items"; } const char* BotDatabase::fail::DeleteItems() { return "Failed to delete items"; } -const char* BotDatabase::fail::LoadItemBySlot() { return "Failed to load item by slot"; } const char* BotDatabase::fail::SaveItemBySlot() { return "Failed to save item by slot"; } const char* BotDatabase::fail::DeleteItemBySlot() { return "Failed to delete item by slot"; } const char* BotDatabase::fail::LoadEquipmentColor() { return "Failed to load equipment color"; } @@ -3004,7 +3141,7 @@ const char* BotDatabase::fail::SaveEquipmentColor() { return "Failed to save equ /* fail::Bot pet functions */ const char* BotDatabase::fail::LoadPetIndex() { return "Failed to load pet index"; } -const char* BotDatabase::fail::LoadPetSpellID() { return "Failed to load pet spell id"; } +const char* BotDatabase::fail::LoadPetSpellID() { return "Failed to load pet spell ID"; } const char* BotDatabase::fail::LoadPetStats() { return "Failed to load pet stats"; } const char* BotDatabase::fail::SavePetStats() { return "Failed to save pet stats"; } const char* BotDatabase::fail::DeletePetStats() { return "Failed to delete pet stats"; } @@ -3029,32 +3166,10 @@ const char* BotDatabase::fail::ToggleHelmAppearance() { return "Failed to save t const char* BotDatabase::fail::ToggleAllHelmAppearances() { return "Failed to save toggle all helm appearance"; } const char* BotDatabase::fail::SaveFollowDistance() { return "Failed to save follow distance"; } const char* BotDatabase::fail::SaveAllFollowDistances() { return "Failed to save all follow distances"; } -const char* BotDatabase::fail::CreateCloneBot() { return "Failed to create clone bot"; } -const char* BotDatabase::fail::CreateCloneBotInventory() { return "Failed to create clone bot inventory"; } const char* BotDatabase::fail::SaveStopMeleeLevel() { return "Failed to save stop melee level"; } -/* fail::Bot bot-group functions */ -const char* BotDatabase::fail::QueryBotGroupExistence() { return "Failed to query bot-group existence"; } -const char* BotDatabase::fail::LoadBotGroupIDByBotGroupName() { return "Failed to load bot-group id by bot-group name"; } -const char* BotDatabase::fail::LoadBotGroupIDByLeaderID() { return "Failed to load bot-group id by leader id"; } -const char* BotDatabase::fail::LoadBotGroupIDByMemberID() { return "Failed to load bot-group id by member id"; } -const char* BotDatabase::fail::LoadLeaderIDByBotGroupName() { return "Failed to load leader id by bot-group name"; } -const char* BotDatabase::fail::LoadLeaderIDByBotGroupID() { return "Failed to load leader id by bot-group id"; } -const char* BotDatabase::fail::LoadBotGroupNameByBotGroupID() { return "Failed to load bot-group name by bot-group id"; } -const char* BotDatabase::fail::LoadBotGroupNameByLeaderID() { return "Failed to load bot-group name by leader id"; } -const char* BotDatabase::fail::CreateBotGroup() { return "Failed to create bot-group"; } -const char* BotDatabase::fail::DeleteBotGroup() { return "Failed to delete bot-group"; } -const char* BotDatabase::fail::AddMemberToBotGroup() { return "Failed to add member to bot-group"; } -const char* BotDatabase::fail::RemoveMemberFromBotGroup() { return "Failed to remove member from bot-group"; } -const char* BotDatabase::fail::LoadBotGroupIDForLoadBotGroup() { return "Failed to load bot-group id for load bot-group"; } -const char* BotDatabase::fail::LoadBotGroup() { return "Failed to load bot-group"; } -const char* BotDatabase::fail::LoadBotGroupsListByOwnerID() { return "Failed to load bot-groups list by owner id"; } - -/* fail::Bot group functions */ -const char* BotDatabase::fail::LoadGroupedBotsByGroupID() { return "Failed to load grouped bots by group id"; } - /* fail::Bot heal rotation functions */ -const char* BotDatabase::fail::LoadHealRotationIDByBotID() { return "Failed to load heal rotation id by bot id"; } +const char* BotDatabase::fail::LoadHealRotationIDByBotID() { return "Failed to load heal rotation ID by bot ID"; } const char* BotDatabase::fail::LoadHealRotation() { return "Failed to load heal rotation"; } const char* BotDatabase::fail::LoadHealRotationMembers() { return "Failed to load heal rotation members"; } const char* BotDatabase::fail::LoadHealRotationTargets() { return "Failed to load heal rotation targets"; } @@ -3063,5 +3178,3 @@ const char* BotDatabase::fail::DeleteHealRotation() { return "Failed to delete h const char* BotDatabase::fail::DeleteAllHealRotations() { return "Failed to delete all heal rotations"; } /* fail::Bot miscellaneous functions */ - -#endif // BOTS diff --git a/zone/bot_database.h b/zone/bot_database.h index 9ebb2b0c5..dcc3af0ad 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -20,7 +20,6 @@ #ifndef BOT_DATABASE_H #define BOT_DATABASE_H -#ifdef BOTS #include #include @@ -50,13 +49,14 @@ public: /* Bot functions */ bool QueryNameAvailablity(const std::string& bot_name, bool& available_flag); - bool QueryBotCount(const uint32 owner_id, uint32& bot_count); - bool LoadQuestableSpawnCount(const uint32 owner_id, int& spawn_count); + bool QueryBotCount(const uint32 owner_id, int class_id, uint32& bot_count, uint32& bot_class_count); bool LoadBotsList(const uint32 owner_id, std::list& bots_list, bool ByAccount = false); bool LoadOwnerID(const std::string& bot_name, uint32& owner_id); bool LoadOwnerID(const uint32 bot_id, uint32& owner_id); + uint32 GetOwnerID(const uint32 bot_id); bool LoadBotID(const uint32 owner_id, const std::string& bot_name, uint32& bot_id); + bool LoadBotID(const uint32 owner_id, const std::string& bot_name, uint32& bot_id, uint8& bot_class_id); bool LoadBot(const uint32 bot_id, Bot*& loaded_bot); bool SaveNewBot(Bot* bot_inst, uint32& bot_id); @@ -77,10 +77,6 @@ public: bool SaveTimers(Bot* bot_inst); bool DeleteTimers(const uint32 bot_id); - bool LoadGuildMembership(const uint32 bot_id, uint32& guild_id, uint8& guild_rank, std::string& guild_name); - bool SaveGuildMembership(const uint32 bot_id, const uint32 guild_id, const uint8 guild_rank); - bool DeleteGuildMembership(const uint32 bot_id); - /* Bot inventory functions */ bool QueryInventoryCount(const uint32 bot_id, uint32& item_count); @@ -89,6 +85,7 @@ public: bool SaveItems(Bot* bot_inst); bool DeleteItems(const uint32 bot_id); + bool LoadItemSlots(const uint32 bot_id, std::map& m); bool LoadItemBySlot(Bot* bot_inst); bool LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id); bool SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQ::ItemInstance* item_inst); @@ -97,11 +94,14 @@ public: bool LoadEquipmentColor(const uint32 bot_id, const uint8 material_slot_id, uint32& rgb); bool SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, const uint32 rgb); + bool SaveExpansionBitmask(const uint32 bot_id, const int expansion_bitmask); + bool SaveEnforceSpellSetting(const uint32 bot_id, const bool enforce_spell_setting); + /* Bot pet functions */ bool LoadPetIndex(const uint32 bot_id, uint32& pet_index); bool LoadPetSpellID(const uint32 bot_id, uint32& pet_spell_id); - + bool LoadPetStats(const uint32 bot_id, std::string& pet_name, uint32& pet_mana, uint32& pet_hp, uint32& pet_spell_id); bool SavePetStats(const uint32 bot_id, const std::string& pet_name, const uint32 pet_mana, const uint32 pet_hp, const uint32 pet_spell_id); bool DeletePetStats(const uint32 bot_id); @@ -119,7 +119,7 @@ public: bool LoadInspectMessage(const uint32 bot_id, InspectMessage_Struct& inspect_message); bool SaveInspectMessage(const uint32 bot_id, const InspectMessage_Struct& inspect_message); bool DeleteInspectMessage(const uint32 bot_id); - + bool SaveAllInspectMessages(const uint32 owner_id, const InspectMessage_Struct& inspect_message); bool DeleteAllInspectMessages(const uint32 owner_id); @@ -140,12 +140,14 @@ public: bool SaveStopMeleeLevel(const uint32 owner_id, const uint32 bot_id, const uint8 sml_value); + bool SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting); + bool LoadOwnerOptions(Client *owner); bool SaveOwnerOption(const uint32 owner_id, size_t type, const bool flag); bool SaveOwnerOption(const uint32 owner_id, const std::pair type, const std::pair flag); - + /* Bot bot-group functions */ - bool QueryBotGroupExistence(const std::string& botgroup_name, bool& extant_flag); + bool QueryBotGroupExistence(const std::string& botgroup_name); bool LoadBotGroupIDByBotGroupName(const std::string& botgroup_name, uint32& botgroup_id); bool LoadBotGroupIDByLeaderID(const uint32 leader_id, uint32& botgroup_id); @@ -156,7 +158,7 @@ public: bool LoadBotGroupNameByBotGroupID(const uint32 botgroup_id, std::string& botgroup_name); bool LoadBotGroupNameByLeaderID(const uint32 leader_id, std::string& botgroup_name); - + bool CreateBotGroup(const std::string& botgroup_name, const uint32 leader_id); bool DeleteBotGroup(const uint32 leader_id); bool AddMemberToBotGroup(const uint32 leader_id, const uint32 member_id); @@ -164,12 +166,15 @@ public: bool LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std::string& botgroup_name, uint32& botgroup_id); bool LoadBotGroup(const std::string& botgroup_name, std::map>& member_list); - + bool LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list>& botgroups_list); /* Bot group functions */ + bool IsBotGroupAutoSpawn(const std::string& botgroup_name); + bool LoadAutoSpawnBotGroupsByOwnerID(const uint32 owner_id, std::list>& group_list); bool LoadGroupedBotsByGroupID(const uint32 owner_id, const uint32 group_id, std::list& group_list); + bool ToggleBotGroupAutoSpawn(const uint32 group_id); /* Bot heal rotation functions */ @@ -191,9 +196,6 @@ public: class fail { public: /* fail::Bot functions */ - static const char* QueryNameAvailablity(); - static const char* QueryBotCount(); - static const char* LoadQuestableSpawnCount(); static const char* LoadBotsList(); static const char* LoadOwnerID(); static const char* LoadBotID(); @@ -204,22 +206,16 @@ public: static const char* LoadBuffs(); static const char* SaveBuffs(); static const char* DeleteBuffs(); - static const char* LoadStance(); - static const char* SaveStance(); static const char* DeleteStance(); static const char* LoadTimers(); static const char* SaveTimers(); static const char* DeleteTimers(); - static const char* LoadGuildMembership(); - static const char* SaveGuildMembership(); - static const char* DeleteGuildMembership(); /* fail::Bot inventory functions */ static const char* QueryInventoryCount(); static const char* LoadItems(); static const char* SaveItems(); static const char* DeleteItems(); - static const char* LoadItemBySlot(); static const char* SaveItemBySlot(); static const char* DeleteItemBySlot(); static const char* LoadEquipmentColor(); @@ -252,8 +248,6 @@ public: static const char* ToggleAllHelmAppearances(); static const char* SaveFollowDistance(); static const char* SaveAllFollowDistances(); - static const char* CreateCloneBot(); - static const char* CreateCloneBotInventory(); static const char* SaveStopMeleeLevel(); /* fail::Bot bot-group functions */ @@ -293,5 +287,3 @@ public: }; #endif - -#endif // BOTS diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 7ba32349b..3328c637d 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -19,8 +19,6 @@ #ifndef BOT_STRUCTS #define BOT_STRUCTS -#ifdef BOTS - #include "../common/types.h" #include @@ -79,6 +77,30 @@ struct BotAA { uint8 total_levels; }; -#endif // BOTS +struct BotSpellSetting { + int16 priority; + uint8 min_level; + uint8 max_level; + int8 min_hp; + int8 max_hp; + bool is_enabled = true; +}; + +struct BotSpells_Struct { + uint32 type; // 0 = never, must be one (and only one) of the defined values + int16 spellid; // <= 0 = no spell + int16 manacost; // -1 = use spdat, -2 = no cast time + uint32 time_cancast; // when we can cast this spell next + int32 recast_delay; + int16 priority; + int16 resist_adjust; + uint8 minlevel; + uint8 maxlevel; + int16 min_hp; // >0 won't cast if HP is below + int16 max_hp; // >0 won't cast if HP is above + std::string bucket_name; + std::string bucket_value; + uint8 bucket_comparison; +}; #endif // BOT_STRUCTS diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 2653af032..570ba072f 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -16,10 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef BOTS - #include "bot.h" -#include "../common/string_util.h" +#include "../common/data_verification.h" +#include "../common/strings.h" +#include "../common/repositories/bot_spells_entries_repository.h" +#include "../common/repositories/npc_spells_repository.h" #if EQDEBUG >= 12 #define BotAI_DEBUG_Spells 25 @@ -35,17 +36,18 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { return false; } - if(!AI_HasSpells()) + if (!AI_HasSpells()) { return false; + } if (iChance < 100) { - if (zone->random.Int(0, 100) > iChance){ + if (zone->random.Int(0, 100) > iChance) { return false; } } - if(tar->GetAppearance() == eaDead) { - if((tar->IsClient() && tar->CastToClient()->GetFeigned()) || tar->IsBot()) { + if (tar->GetAppearance() == eaDead) { + if ((tar->IsClient() && tar->CastToClient()->GetFeigned()) || tar->IsBot()) { // do nothing } else { @@ -68,10 +70,10 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { switch (iSpellTypes) { case SpellType_Mez: { if (tar->GetBodyType() != BT_Giant) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (!checked_los) { + if (!CheckLosFN(tar)) { break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - + } checked_los = true; } @@ -82,22 +84,32 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { botSpell = GetBestBotSpellForMez(this); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { break; + } Mob* addMob = GetFirstIncomingMobToMez(this, botSpell); - if(!addMob){ + if (!addMob) { //Say("!addMob."); - break;} - - if(!(!addMob->IsImmuneToSpell(botSpell.SpellId, this) && addMob->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) break; + } + if (!(!addMob->IsImmuneToSpell(botSpell.SpellId, this) && addMob->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) { + break; + } castedSpell = AIDoSpellCast(botSpell.SpellIndex, addMob, botSpell.ManaCost); - if(castedSpell) - BotGroupSay(this, "Attempting to mez %s.", addMob->GetCleanName()); + if (castedSpell) { + BotGroupSay( + this, + fmt::format( + "Attempting to mesmerize {} with {}.", + addMob->GetCleanName(), + spells[botSpell.SpellId].name + ).c_str() + ); + } } break; } @@ -107,86 +119,94 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { bool hasAggro = false; bool isPrimaryHealer = false; - if(HasGroup()) { + if (HasGroup()) { isPrimaryHealer = IsGroupHealer(); } - if(hpr < 95 || (tar->IsClient() && (hpr < 95)) || (botClass == BARD)) { - if(tar->GetClass() == NECROMANCER) { + if (hpr < 95 || (tar->IsClient() && (hpr < 95)) || (botClass == BARD)) { + if (tar->GetClass() == NECROMANCER) { // Give necromancers a chance to go lifetap something or cleric can spend too much mana on a necro - if(hpr >= 40) { + if (hpr >= 40) { break; } } - if(tar->GetClass() == SHAMAN) { + if (tar->GetClass() == SHAMAN) { // Give shaman the chance to canni without wasting the cleric's mana - if(hpr >= 80) { + if (hpr >= 80) { break; } } // Evaluate the situation - if((IsEngaged()) && ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN))) { - if(tar->GetTarget() && tar->GetTarget()->GetHateTop() && tar->GetTarget()->GetHateTop() == tar) { + if ((IsEngaged()) && ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN))) { + if (tar->GetTarget() && tar->GetTarget()->GetHateTop() && tar->GetTarget()->GetHateTop() == tar) { hasAggro = true; } - if(hpr < 35) { + if (hpr < 35) { botSpell = GetBestBotSpellForFastHeal(this); } - else if(hpr >= 35 && hpr < 70){ - if(GetNumberNeedingHealedInGroup(60, false) >= 3) + else if (hpr >= 35 && hpr < 70) { + if (GetNumberNeedingHealedInGroup(60, false) >= 3) { botSpell = GetBestBotSpellForGroupHeal(this); - - if(botSpell.SpellId == 0) + } + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForPercentageHeal(this); + } } - else if(hpr >= 70 && hpr < 95){ - if(GetNumberNeedingHealedInGroup(80, false) >= 3) + else if (hpr >= 70 && hpr < 95) { + if (GetNumberNeedingHealedInGroup(80, false) >= 3) { botSpell = GetBestBotSpellForGroupHealOverTime(this); - - if(hasAggro) + } + if (hasAggro) { botSpell = GetBestBotSpellForPercentageHeal(this); + } } else { - if(!tar->FindType(SE_HealOverTime)) + if (!tar->FindType(SE_HealOverTime)) { botSpell = GetBestBotSpellForHealOverTime(this); + } } } else if ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN)) { - if(GetNumberNeedingHealedInGroup(40, true) >= 2){ + if (GetNumberNeedingHealedInGroup(40, true) >= 2) { botSpell = GetBestBotSpellForGroupCompleteHeal(this); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForGroupHeal(this); - - if(botSpell.SpellId == 0) + } + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForGroupHealOverTime(this); - - if(hpr < 40) { - if(botSpell.SpellId == 0) + } + if (hpr < 40) { + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForPercentageHeal(this); + } } } - else if(GetNumberNeedingHealedInGroup(60, true) >= 2){ + else if (GetNumberNeedingHealedInGroup(60, true) >= 2) { botSpell = GetBestBotSpellForGroupHeal(this); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForGroupHealOverTime(this); - - if(hpr < 40) { - if(botSpell.SpellId == 0) + } + if (hpr < 40) { + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForPercentageHeal(this); + } } } - else if(hpr < 40) + else if (hpr < 40) { botSpell = GetBestBotSpellForPercentageHeal(this); - else if(hpr >= 40 && hpr < 75) + } + else if (hpr >= 40 && hpr < 75) { botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); + } else { - if(hpr < 90 && !tar->FindType(SE_HealOverTime)) + if (hpr < 90 && !tar->FindType(SE_HealOverTime)) { botSpell = GetBestBotSpellForHealOverTime(this); + } } } else { @@ -213,42 +233,44 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } //If we're at specified mana % or below, don't heal as hybrid - if(tar->GetHPRatio() <= hpRatioToCast) + if (tar->GetHPRatio() <= hpRatioToCast) { botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); + } } - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - - if(botSpell.SpellId == 0) + } + if (botSpell.SpellId == 0) { botSpell = GetFirstBotSpellForSingleTargetHeal(this); - - if(botSpell.SpellId == 0 && botClass == BARD){ + } + if (botSpell.SpellId == 0 && botClass == BARD) { botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); } // If there is still no spell id, then there isn't going to be one so we are done - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { break; - + } // Can we cast this spell on this target? - if(!(spells[botSpell.SpellId].target_type==ST_GroupTeleport || spells[botSpell.SpellId].target_type == ST_Target || tar == this) - && !(tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) + if (!(spells[botSpell.SpellId].target_type==ST_GroupTeleport || spells[botSpell.SpellId].target_type == ST_Target || tar == this) + && !(tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) { break; + } uint32 TempDontHealMeBeforeTime = tar->DontHealMeBefore(); castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); - if(castedSpell) { - /*if(TempDontHealMeBeforeTime != tar->DontHealMeBefore()) + if (castedSpell) { + /*if (TempDontHealMeBeforeTime != tar->DontHealMeBefore()) tar->SetDontHealMeBefore(TempDontHealMeBeforeTime); // For non-HoT heals, do a 4 second delay // TODO: Replace this code with logic that calculates the delay based on number of clerics in rotation // and ignores heals for anyone except the main tank - if(!IsHealOverTimeSpell(botSpell.SpellId)) { - if(IsCompleteHealSpell(botSpell.SpellId)) { + if (!IsHealOverTimeSpell(botSpell.SpellId)) { + if (IsCompleteHealSpell(botSpell.SpellId)) { // Complete Heal 4 second rotation tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 4000); } @@ -256,25 +278,38 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); } }*/ - if(botClass != BARD) { - if(IsGroupSpell(botSpell.SpellId)){ - if(HasGroup()) { + if (botClass != BARD) { + if (IsGroupSpell(botSpell.SpellId)) { + if (HasGroup()) { Group *g = GetGroup(); - if(g) { - BotGroupSay(this, "Casting %s.", spells[botSpell.SpellId].name); + if (g) { + BotGroupSay( + this, + fmt::format( + "Casting {}.", + spells[botSpell.SpellId].name + ).c_str() + ); for( int i = 0; imembers[i] && !g->members[i]->qglobal) { + if (g->members[i] && !g->members[i]->qglobal) { g->members[i]->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); } } } } - } - else { - if(tar != this) //we don't need spam of bots healing themselves - BotGroupSay(this, "Casting %s on %s", spells[botSpell.SpellId].name, tar->GetCleanName()); + } else { + if (tar != this) { //we don't need spam of bots healing themselves + BotGroupSay( + this, + fmt::format( + "Casting {} on {}.", + spells[botSpell.SpellId].name, + tar->GetCleanName() + ).c_str() + ); + } tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 2000); } @@ -286,29 +321,30 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } case SpellType_Root: { if (!tar->IsRooted() && tar->DontRootMeBefore() < Timer::GetCurrentTime()) { - if(!checked_los) { - if(!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; + if (!checked_los) { + if (!CheckLosFN(tar)) { + break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call } + checked_los = true; + } - // TODO: If there is a ranger in the group then don't allow root spells + // TODO: If there is a ranger in the group then don't allow root spells - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); + botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - if(botSpell.SpellId == 0) - break; + if (botSpell.SpellId == 0) { + break; + } + if (tar->CanBuffStack(botSpell.SpellId, botLevel, true) == 0) { + break; + } + uint32 TempDontRootMeBefore = tar->DontRootMeBefore(); - if(tar->CanBuffStack(botSpell.SpellId, botLevel, true) == 0) - break; + castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontRootMeBefore); - uint32 TempDontRootMeBefore = tar->DontRootMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontRootMeBefore); - - if(TempDontRootMeBefore != tar->DontRootMeBefore()) - tar->SetDontRootMeBefore(TempDontRootMeBefore); + if (TempDontRootMeBefore != tar->DontRootMeBefore()) { + tar->SetDontRootMeBefore(TempDontRootMeBefore); + } } break; } @@ -319,51 +355,60 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { for(std::list::iterator itr = buffSpellList.begin(); itr != buffSpellList.end(); ++itr) { BotSpell selectedBotSpell = *itr; - if(selectedBotSpell.SpellId == 0) + if (selectedBotSpell.SpellId == 0) { continue; - + } // no buffs with illusions.. use #bot command to cast illusions - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) + if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) { continue; - + } //no teleport spells use #bot command to cast teleports - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) + if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) { continue; - + } // can not cast buffs for your own pet only on another pet that isn't yours - if((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != GetPet())) + if ((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != GetPet())) { continue; - + } // Validate target - - if(!((spells[selectedBotSpell.SpellId].target_type == ST_Target || spells[selectedBotSpell.SpellId].target_type == ST_Pet || tar == this || - spells[selectedBotSpell.SpellId].target_type == ST_Group || spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || - (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard)) - && !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) - && (tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0))) { - continue; + // TODO: Add ST_TargetsTarget support for Buffing. + if ( + !( + ( + spells[selectedBotSpell.SpellId].target_type == ST_Target || + spells[selectedBotSpell.SpellId].target_type == ST_Pet || + (tar == this && spells[selectedBotSpell.SpellId].target_type != ST_TargetsTarget) || + spells[selectedBotSpell.SpellId].target_type == ST_Group || + spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || + (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard) + ) && + !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && + tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0 + ) + ) { + continue; } // Put the zone levitate and movement check here since bots are able to bypass the client casting check - if((IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) + if ((IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) || (IsEffectInSpell(selectedBotSpell.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) { - if(botClass != BARD || !IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())){ + if (botClass != BARD || !IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())) { continue; } } - switch(tar->GetArchetype()) + switch (tar->GetArchetype()) { case ARCHETYPE_CASTER: //TODO: probably more caster specific spell effects in here - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || + if (IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS)) { continue; } break; case ARCHETYPE_MELEE: - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || + if (IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || IsEffectInSpell(selectedBotSpell.SpellId, SE_CastingLevel) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaRegen_v2) || IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana)) { @@ -376,7 +421,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { break; } - if(botClass == ENCHANTER && IsEffectInSpell(selectedBotSpell.SpellId, SE_Rune)) + if (botClass == ENCHANTER && IsEffectInSpell(selectedBotSpell.SpellId, SE_Rune)) { float manaRatioToCast = 75.0f; @@ -399,23 +444,25 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } //If we're at specified mana % or below, don't rune as enchanter - if(GetManaRatio() <= manaRatioToCast) + if (GetManaRatio() <= manaRatioToCast) { break; + } } - if(CheckSpellRecastTimers(this, itr->SpellIndex)) + if (CheckSpellRecastTimers(this, itr->SpellIndex)) { uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontBuffMeBefore); - if(TempDontBuffMeBefore != tar->DontBuffMeBefore()) + if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) tar->SetDontBuffMeBefore(TempDontBuffMeBefore); } - if(castedSpell) + if (castedSpell) { break; + } } } break; @@ -427,7 +474,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { #ifdef IPC if (hpr <= 5 || (IsNPC() && CastToNPC()->IsInteractive() && tar != this) ) #else - if(hpr > 15 && ((botClass == WIZARD) || (botClass == ENCHANTER) || (botClass == RANGER))) + if (hpr > 15 && ((botClass == WIZARD) || (botClass == ENCHANTER) || (botClass == RANGER))) mayGetAggro = HasOrMayGetAggro(); //classes have hate reducing spells if (hpr <= 15 || mayGetAggro) @@ -435,27 +482,27 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { { botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { break; - - if(IsInvulnerabilitySpell(botSpell.SpellId)) + } + if (IsInvulnerabilitySpell(botSpell.SpellId)) { tar = this; //target self for invul type spells - + } castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); } break; } case SpellType_Nuke: { - if((tar->GetHPRatio() <= 95.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER))) + if ((tar->GetHPRatio() <= 95.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER) || (botClass == PALADIN) || (botClass == SHADOWKNIGHT) || (botClass == WARRIOR))) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (!checked_los) { + if (!CheckLosFN(tar)) break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call checked_los = true; } - if(botClass == CLERIC || botClass == ENCHANTER) + if (botClass == CLERIC || botClass == ENCHANTER) { float manaRatioToCast = 75.0f; @@ -480,48 +527,49 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } //If we're at specified mana % or below, don't nuke as cleric or enchanter - if(GetManaRatio() <= manaRatioToCast) + if (GetManaRatio() <= manaRatioToCast) break; } - if(botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) { - if(tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire) + if (botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) { + if (tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire) botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Undead); - else if(tar->GetBodyType() == BT_Summoned || tar->GetBodyType() == BT_Summoned2 || tar->GetBodyType() == BT_Summoned3) + else if (tar->GetBodyType() == BT_Summoned || tar->GetBodyType() == BT_Summoned2 || tar->GetBodyType() == BT_Summoned3) botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Summoned); } - if(botClass == PALADIN || botClass == DRUID || botClass == CLERIC || botClass == ENCHANTER || botClass == WIZARD) { - if(botSpell.SpellId == 0) { + if (botClass == PALADIN || botClass == DRUID || botClass == CLERIC || botClass == ENCHANTER || botClass == WIZARD) { + if (botSpell.SpellId == 0) { uint8 stunChance = (tar->IsCasting() ? 30: 15); - if(botClass == PALADIN) + if (botClass == PALADIN) stunChance = 50; - if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) { + if (!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) { botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target); } } } - if(botClass == WIZARD && botSpell.SpellId == 0) { + if (botClass == WIZARD && botSpell.SpellId == 0) { botSpell = GetBestBotWizardNukeSpellByTargetResists(this, tar); } - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Target); - - if(botSpell.SpellId == 0) + } + if (botSpell.SpellId == 0) { break; - - if(!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) + } + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) { break; - - if(IsFearSpell(botSpell.SpellId)) { + } + if (IsFearSpell(botSpell.SpellId)) { // don't let fear cast if the npc isn't snared or rooted - if(tar->GetSnaredAmount() == -1) { - if(!tar->IsRooted()) + if (tar->GetSnaredAmount() == -1) { + if (!tar->IsRooted()) { break; + } } } @@ -530,22 +578,22 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { break; } case SpellType_Dispel: { - if(tar->GetHPRatio() > 95.0f) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (tar->GetHPRatio() > 95.0f) { + if (!checked_los) { + if (!CheckLosFN(tar)) { break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - + } checked_los = true; } botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { break; - + } // TODO: Check target to see if there is anything to dispel - if(tar->CountDispellableBuffs() > 0) { + if (tar->CountDispellableBuffs() > 0) { castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); } } @@ -584,7 +632,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); } - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) break; castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); @@ -592,113 +640,141 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { break; } case SpellType_InCombatBuff: { + // Allow all classes to use InCombatBuffs + if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { + std::list buffSpellList = GetBotSpellsBySpellType(this, SpellType_InCombatBuff); - if(botClass == SHAMAN) { - checked_los = true; - - std::list inCombatBuffList = GetBotSpellsBySpellType(this, SpellType_InCombatBuff); - - for(std::list::iterator itr = inCombatBuffList.begin(); itr != inCombatBuffList.end(); ++itr) { + for (std::list::iterator itr = buffSpellList.begin(); itr != buffSpellList.end(); ++itr) { BotSpell selectedBotSpell = *itr; - if(selectedBotSpell.SpellId == 0) + if (selectedBotSpell.SpellId == 0) { + continue; + } + // no buffs with illusions.. use #bot command to cast illusions + if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) { + continue; + } + //no teleport spells use #bot command to cast teleports + if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) { + continue; + } + // can not cast buffs for your own pet only on another pet that isn't yours + if ((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != GetPet())) { continue; - - if(CheckSpellRecastTimers(this, itr->SpellIndex)) - { - if(!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && (spells[selectedBotSpell.SpellId].buff_duration < 1 || tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0))) - continue; - - //short duration buffs or other buffs only to be cast during combat. - if (IsSelfConversionSpell(selectedBotSpell.SpellId)) { - if(GetManaRatio() > 90.0f || GetHPRatio() < 50.0f || GetHPRatio() < (GetManaRatio() + 10.0f)) - break; //don't cast if low hp, lots of mana, or if mana is higher than hps - } - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost); } - if(castedSpell) - break; - } - } - else if(botClass == BARD) { - if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { - std::list inCombatBuffList = GetBotSpellsBySpellType(this, SpellType_InCombatBuff); + //Conversion Spells + if (IsSelfConversionSpell(selectedBotSpell.SpellId)) { + if (GetManaRatio() > 90.0f || GetHPRatio() < 50.0f || GetHPRatio() < (GetManaRatio() + 10.0f)) { + break; //don't cast if low hp, lots of mana, or if mana is higher than hps + } + } - for(std::list::iterator itr = inCombatBuffList.begin(); itr != inCombatBuffList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; + // Validate target + // TODO: Add ST_TargetsTarget support for Buffing. + if ( + !( + ( + spells[selectedBotSpell.SpellId].target_type == ST_Target || + spells[selectedBotSpell.SpellId].target_type == ST_Pet || + (tar == this && spells[selectedBotSpell.SpellId].target_type != ST_TargetsTarget) || + spells[selectedBotSpell.SpellId].target_type == ST_Group || + spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || + (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard) + ) && + !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && + tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0 + ) + ) { + continue; + } - if(selectedBotSpell.SpellId == 0) + // Put the zone levitate and movement check here since bots are able to bypass the client casting check + if ( + (IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) || + (IsEffectInSpell(selectedBotSpell.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor()) + ) { + if (botClass != BARD || !IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())) { continue; + } + } - if(CheckSpellRecastTimers(this, itr->SpellIndex)) { - uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); - - // no buffs with illusions.. use #bot command to cast illusions - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) - continue; - - //no teleport spells use #bot command to cast teleports - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) - continue; - - // can not cast buffs for your own pet only on another pet that isn't yours - if((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != GetPet())) - continue; - - // Validate target - - if(!((spells[selectedBotSpell.SpellId].target_type == ST_Target || spells[selectedBotSpell.SpellId].target_type == ST_Pet || tar == this || - spells[selectedBotSpell.SpellId].target_type == ST_Group || spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || - (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard)) - && !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) - && (tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0))) { + if (!IsGroupSpell(selectedBotSpell.SpellId)) { + //Only check archetype if spell is not a group spell + switch (tar->GetArchetype()) { + case ARCHETYPE_CASTER: + //TODO: probably more caster specific spell effects in here + if ( + ( + IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_DamageShield) + ) && + spells[selectedBotSpell.SpellId].target_type != ST_Self + ) { continue; - } - - // Put the zone levitate and movement check here since bots are able to bypass the client casting check - if((IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) - || (IsEffectInSpell(selectedBotSpell.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) { - if(!IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())) { - continue; - } - } - - if(!IsGroupSpell(selectedBotSpell.SpellId)) { - //Only check archetype if song is not a group spell - switch(tar->GetArchetype()) { - case ARCHETYPE_CASTER: - //TODO: probably more caster specific spell effects in here - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS)) - { - continue; - } - break; - case ARCHETYPE_MELEE: - if(IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CastingLevel) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaRegen_v2) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana)) - { - continue; - } - break; - case ARCHETYPE_HYBRID: - //Hybrids get all buffs - default: - break; } - } + break; + case ARCHETYPE_MELEE: + if ( + ( + IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_CastingLevel) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaRegen_v2) || + IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana) + ) && + spells[selectedBotSpell.SpellId].target_type != ST_Self + ) { + continue; + } + break; + case ARCHETYPE_HYBRID: + //Hybrids get all buffs + default: + break; + } + } + // TODO: Add TriggerSpell Support for Exchanter Runes + if (botClass == ENCHANTER && IsEffectInSpell(selectedBotSpell.SpellId, SE_Rune)) { + float manaRatioToCast = 75.0f; - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontBuffMeBefore); - - if(TempDontBuffMeBefore != tar->DontBuffMeBefore()) - tar->SetDontBuffMeBefore(TempDontBuffMeBefore); + switch(GetBotStance()) { + case EQ::constants::stanceEfficient: + manaRatioToCast = 90.0f; + break; + case EQ::constants::stanceBalanced: + case EQ::constants::stanceAggressive: + manaRatioToCast = 75.0f; + break; + case EQ::constants::stanceReactive: + case EQ::constants::stanceBurn: + case EQ::constants::stanceBurnAE: + manaRatioToCast = 50.0f; + break; + default: + manaRatioToCast = 75.0f; + break; } - if(castedSpell) + //If we're at specified mana % or below, don't rune as enchanter + if (GetManaRatio() <= manaRatioToCast) { break; + } + } + + if (CheckSpellRecastTimers(this, itr->SpellIndex)) { + uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); + castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontBuffMeBefore); + + if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) + tar->SetDontBuffMeBefore(TempDontBuffMeBefore); + } + + if (castedSpell) { + break; } } } @@ -706,8 +782,8 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } case SpellType_Lifetap: { if (GetHPRatio() < 90.0f) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (!checked_los) { + if (!CheckLosFN(tar)) break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call checked_los = true; @@ -715,10 +791,10 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) break; - if(!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) break; castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); @@ -727,8 +803,8 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } case SpellType_Snare: { if (tar->DontSnareMeBefore() < Timer::GetCurrentTime()) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (!checked_los) { + if (!CheckLosFN(tar)) break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call checked_los = true; @@ -736,25 +812,25 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) break; - if(!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) break; uint32 TempDontSnareMeBefore = tar->DontSnareMeBefore(); castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontSnareMeBefore); - if(TempDontSnareMeBefore != tar->DontSnareMeBefore()) + if (TempDontSnareMeBefore != tar->DontSnareMeBefore()) tar->SetDontSnareMeBefore(TempDontSnareMeBefore); } break; } case SpellType_DOT: { if ((tar->GetHPRatio() <= 98.0f) && (tar->DontDotMeBefore() < Timer::GetCurrentTime()) && (tar->GetHPRatio() > 15.0f)) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (!checked_los) { + if (!CheckLosFN(tar)) break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call checked_los = true; @@ -830,8 +906,8 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { case SpellType_Slow: { if (tar->GetHPRatio() <= 99.0f) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (!checked_los) { + if (!CheckLosFN(tar)) break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call checked_los = true; @@ -868,30 +944,38 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { case BEASTLORD: { botSpell = GetBestBotSpellForDiseaseBasedSlow(this); - if(botSpell.SpellId == 0 || ((tar->GetMR() - 50) < (tar->GetDR() + spells[botSpell.SpellId].resist_difficulty))) + if (botSpell.SpellId == 0 || ((tar->GetMR() - 50) < (tar->GetDR() + spells[botSpell.SpellId].resist_difficulty))) botSpell = GetBestBotSpellForMagicBasedSlow(this); break; } } - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) break; - if(!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) break; castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - if(castedSpell && GetClass() != BARD) - BotGroupSay(this, "Attempting to slow %s.", tar->GetCleanName()); + if (castedSpell && GetClass() != BARD) { + BotGroupSay( + this, + fmt::format( + "Attempting to slow {} with {}.", + tar->GetCleanName(), + spells[botSpell.SpellId].name + ).c_str() + ); + } } break; } case SpellType_Debuff: { - if((tar->GetHPRatio() <= 99.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER) || (botClass == DRUID)) && (tar->GetHPRatio() > 40.0f)) + if ((tar->GetHPRatio() <= 99.0f) && (tar->GetHPRatio() > 20.0f)) { - if(!checked_los) { - if(!CheckLosFN(tar)) + if (!checked_los) { + if (!CheckLosFN(tar)) break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call checked_los = true; @@ -899,13 +983,13 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { botSpell = GetBestBotSpellForResistDebuff(this, tar); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) botSpell = GetDebuffBotSpell(this, tar); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) break; - if(!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) break; castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); @@ -913,29 +997,29 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { break; } case SpellType_Cure: { - if(GetNeedsCured(tar) && (tar->DontCureMeBefore() < Timer::GetCurrentTime()) && !(GetNumberNeedingHealedInGroup(25, false) > 0) && !(GetNumberNeedingHealedInGroup(40, false) > 2)) + if (GetNeedsCured(tar) && (tar->DontCureMeBefore() < Timer::GetCurrentTime()) && !(GetNumberNeedingHealedInGroup(25, false) > 0) && !(GetNumberNeedingHealedInGroup(40, false) > 2)) { botSpell = GetBestBotSpellForCure(this, tar); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) break; uint32 TempDontCureMeBeforeTime = tar->DontCureMeBefore(); castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontCureMeBeforeTime); - if(castedSpell) { - if(botClass != BARD) { - if(IsGroupSpell(botSpell.SpellId)){ + if (castedSpell) { + if (botClass != BARD) { + if (IsGroupSpell(botSpell.SpellId)) { Group *g; - if(HasGroup()) { + if (HasGroup()) { Group *g = GetGroup(); - if(g) { - for( int i = 0; imembers[i] && !g->members[i]->qglobal) { - if(TempDontCureMeBeforeTime != tar->DontCureMeBefore()) + if (g) { + for ( int i = 0; imembers[i] && !g->members[i]->qglobal) { + if (TempDontCureMeBeforeTime != tar->DontCureMeBefore()) g->members[i]->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); } } @@ -943,8 +1027,9 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } } else { - if(TempDontCureMeBeforeTime != tar->DontCureMeBefore()) + if (TempDontCureMeBeforeTime != tar->DontCureMeBefore()) { tar->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); + } } } } @@ -971,7 +1056,14 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); if (castedSpell) { - BotGroupSay(this, "Attempting to reduce hate on %s.", tar->GetCleanName()); + BotGroupSay( + this, + fmt::format( + "Attempting to reduce hate on {} with {}.", + tar->GetCleanName(), + spells[iter.SpellId].name + ).c_str() + ); break; } } @@ -980,9 +1072,9 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { break; } case SpellType_InCombatBuffSong: { - if (GetClass() != BARD || tar != this) // In-Combat songs can be cast Out-of-Combat in preparation for battle + if (tar != this) { // In-Combat songs can be cast Out-of-Combat in preparation for battle break; - + } std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_InCombatBuffSong); for (auto iter : botSongList) { if (!iter.SpellId) @@ -1063,7 +1155,7 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain int32 manaCost = mana_cost; if (manaCost == -1) - manaCost = spells[AIspells[i].spellid].mana; + manaCost = spells[AIBot_spells[i].spellid].mana; else if (manaCost == -2) manaCost = 0; @@ -1071,10 +1163,10 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain int32 hasMana = GetMana(); // Allow bots to cast buff spells even if they are out of mana - if(RuleB(Bots, FinishBuffing)) { - if(manaCost > hasMana) { + if (RuleB(Bots, FinishBuffing)) { + if (manaCost > hasMana) { // Let's have the bots complete the buff time process - if(AIspells[i].type & SpellType_Buff) { + if (AIBot_spells[i].type & SpellType_Buff) { extraMana = manaCost - hasMana; SetMana(manaCost); } @@ -1083,44 +1175,60 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain float dist2 = 0; - if (AIspells[i].type & SpellType_Escape) { + if (AIBot_spells[i].type & SpellType_Escape) { dist2 = 0; } else dist2 = DistanceSquared(m_Position, tar->GetPosition()); - if (((((spells[AIspells[i].spellid].target_type==ST_GroupTeleport && AIspells[i].type==2) - || spells[AIspells[i].spellid].target_type==ST_AECaster - || spells[AIspells[i].spellid].target_type==ST_Group - || spells[AIspells[i].spellid].target_type==ST_AEBard) - && dist2 <= spells[AIspells[i].spellid].aoe_range*spells[AIspells[i].spellid].aoe_range) - || dist2 <= GetActSpellRange(AIspells[i].spellid, spells[AIspells[i].spellid].range)*GetActSpellRange(AIspells[i].spellid, spells[AIspells[i].spellid].range)) && (mana_cost <= GetMana() || GetMana() == GetMaxMana())) - { - result = NPC::AIDoSpellCast(i, tar, mana_cost, oDontDoAgainBefore); + if ( + ( + ( + ( + (spells[AIBot_spells[i].spellid].target_type==ST_GroupTeleport && AIBot_spells[i].type == SpellType_Heal) || + spells[AIBot_spells[i].spellid].target_type ==ST_AECaster || + spells[AIBot_spells[i].spellid].target_type ==ST_Group || + spells[AIBot_spells[i].spellid].target_type ==ST_AEBard || + ( + tar == this && spells[AIBot_spells[i].spellid].target_type != ST_TargetsTarget + ) + ) && + dist2 <= spells[AIBot_spells[i].spellid].aoe_range*spells[AIBot_spells[i].spellid].aoe_range + ) || + dist2 <= GetActSpellRange(AIBot_spells[i].spellid, spells[AIBot_spells[i].spellid].range)*GetActSpellRange(AIBot_spells[i].spellid, spells[AIBot_spells[i].spellid].range) + ) && + ( + mana_cost <= GetMana() || + GetMana() == GetMaxMana() + ) + ) { + casting_spell_AIindex = i; + LogAI("spellid [{}] tar [{}] mana [{}] Name [{}]", AIBot_spells[i].spellid, tar->GetName(), mana_cost, spells[AIBot_spells[i].spellid].name); + result = Mob::CastSpell(AIBot_spells[i].spellid, tar->GetID(), EQ::spells::CastingSlot::Gem2, spells[AIBot_spells[i].spellid].cast_time, AIBot_spells[i].manacost == -2 ? 0 : mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIBot_spells[i].resist_adjust)); - if(IsCasting() && IsSitting()) + if (IsCasting() && IsSitting()) Stand(); } // if the spell wasn't casted, then take back any extra mana that was given to the bot to cast that spell - if(!result) { + if (!result) { SetMana(hasMana); extraMana = false; } else { //handle spell recast and recast timers - //if(GetClass() == BARD && IsGroupSpell(AIspells[i].spellid)) { + //if (GetClass() == BARD && IsGroupSpell(AIBot_spells[i].spellid)) { // // Bard buff songs have been moved to their own npc spell type.. // // Buff stacking is now checked as opposed to manipulating the timer to avoid rapid casting - // //AIspells[i].time_cancast = (spells[AIspells[i].spellid].recast_time > (spells[AIspells[i].spellid].buffduration * 6000)) ? Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time : Timer::GetCurrentTime() + spells[AIspells[i].spellid].buffduration * 6000; - // //spellend_timer.Start(spells[AIspells[i].spellid].cast_time); + // //AIBot_spells[i].time_cancast = (spells[AIBot_spells[i].spellid].recast_time > (spells[AIBot_spells[i].spellid].buffduration * 6000)) ? Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time : Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].buffduration * 6000; + // //spellend_timer.Start(spells[AIBot_spells[i].spellid].cast_time); //} //else - // AIspells[i].time_cancast = Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time; + // AIBot_spells[i].time_cancast = Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time; - AIspells[i].time_cancast = Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time; + AIBot_spells[i].time_cancast = Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time; - if(spells[AIspells[i].spellid].timer_id > 0) { - SetSpellRecastTimer(spells[AIspells[i].spellid].timer_id, spells[AIspells[i].spellid].recast_time); + if (spells[AIBot_spells[i].spellid].timer_id > 0) { + SetSpellRecastTimer(spells[AIBot_spells[i].spellid].timer_id, spells[AIBot_spells[i].spellid].recast_time); } } @@ -1134,11 +1242,11 @@ bool Bot::AI_PursueCastCheck() { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - LogAI("Bot Engaged (pursuing) autocast check triggered. Trying to cast offensive spells"); + LogAIDetail("Bot Engaged (pursuing) autocast check triggered. Trying to cast offensive spells"); - if(!AICastSpell(GetTarget(), 100, SpellType_Snare)) { - if(!AICastSpell(GetTarget(), 100, SpellType_Lifetap)) { - if(!AICastSpell(GetTarget(), 100, SpellType_Nuke)) { + if (!AICastSpell(GetTarget(), 100, SpellType_Snare)) { + if (!AICastSpell(GetTarget(), 100, SpellType_Lifetap)) { + if (!AICastSpell(GetTarget(), 100, SpellType_Nuke)) { /*AIautocastspell_timer->Start(RandomTimer(500, 2000), false); result = true;*/ result = true; @@ -1150,7 +1258,7 @@ bool Bot::AI_PursueCastCheck() { result = true; } - if(!AIautocastspell_timer->Enabled()) + if (!AIautocastspell_timer->Enabled()) AIautocastspell_timer->Start(RandomTimer(100, 250), false); } @@ -1161,9 +1269,7 @@ bool Bot::AI_IdleCastCheck() { bool result = false; if (AIautocastspell_timer->Check(false)) { -#if BotAI_DEBUG_Spells >= 25 - LogAI("Bot Non-Engaged autocast check triggered: [{}]", GetCleanName()); -#endif + LogAIDetail("Bot Non-Engaged autocast check triggered: [{}]", GetCleanName()); AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. bool pre_combat = false; @@ -1185,7 +1291,11 @@ bool Bot::AI_IdleCastCheck() { // Healers WITHOUT pets will check if a heal is needed before buffing. case CLERIC: case PALADIN: - case RANGER: { + case RANGER: + case MONK: + case ROGUE: + case WARRIOR: + case BERSERKER: { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { if (!AICastSpell(this, 100, SpellType_Heal)) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { @@ -1216,7 +1326,6 @@ bool Bot::AI_IdleCastCheck() { if (!AICastSpell(this, 100, SpellType_Buff)) { if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { - // } } } @@ -1238,7 +1347,6 @@ bool Bot::AI_IdleCastCheck() { if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_PreCombatBuff)) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { - // } } } @@ -1256,7 +1364,6 @@ bool Bot::AI_IdleCastCheck() { if (!AICastSpell(this, 100, SpellType_Buff)) { if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { - // } } } @@ -1272,17 +1379,21 @@ bool Bot::AI_IdleCastCheck() { case BARD: { if (pre_combat) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { - if (!AICastSpell(this, 100, SpellType_PreCombatBuffSong)) { - if (!AICastSpell(this, 100, SpellType_InCombatBuffSong)) { - // + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!AICastSpell(this, 100, SpellType_PreCombatBuffSong)) { + if (!AICastSpell(this, 100, SpellType_InCombatBuffSong)) { + } } } } } else { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { - if (!AICastSpell(this, 100, SpellType_OutOfCombatBuffSong)) { - // + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!AICastSpell(this, 100, SpellType_OutOfCombatBuffSong)) { + if (!AICastSpell(this, 100, SpellType_InCombatBuffSong)) { + } + } } } } @@ -1294,7 +1405,7 @@ bool Bot::AI_IdleCastCheck() { break; } - if(!AIautocastspell_timer->Enabled()) + if (!AIautocastspell_timer->Enabled()) AIautocastspell_timer->Start(RandomTimer(500, 2000), false); // avg human response is much less than 5 seconds..even for non-combat situations... } @@ -1313,29 +1424,15 @@ bool Bot::AI_EngagedCastCheck() { EQ::constants::StanceType botStance = GetBotStance(); bool mayGetAggro = HasOrMayGetAggro(); - LogAI("Engaged autocast check triggered (BOTS). Trying to cast healing spells then maybe offensive spells"); + LogAIDetail("Engaged autocast check triggered (BOTS). Trying to cast healing spells then maybe offensive spells"); - if(botClass == CLERIC) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { - if(!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { - if(!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_InCombatBuff), SpellType_InCombatBuff)) { - //AIautocastspell_timer->Start(RandomTimer(100, 250), false); // Do not give healer classes a lot of time off or your tank's die - failedToCast = true; - } - } - } - } - } - } - else if(botClass == DRUID) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { - if(!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + if (botClass == CLERIC) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { - if(!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { //AIautocastspell_timer->Start(RandomTimer(100, 250), false); // Do not give healer classes a lot of time off or your tank's die failedToCast = true; } @@ -1345,16 +1442,34 @@ bool Bot::AI_EngagedCastCheck() { } } } - else if(botClass == SHAMAN) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + else if (botClass == DRUID) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + //AIautocastspell_timer->Start(RandomTimer(100, 250), false); // Do not give healer classes a lot of time off or your tank's die + failedToCast = true; + } + } + } + } + } + } + } + } + else if (botClass == SHAMAN) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) { - if(!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { - if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if(!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), SpellType_InCombatBuff)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { - if(!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { //AIautocastspell_timer->Start(RandomTimer(100, 250), false); // Do not give healer classes a lot of time off or your tank's die failedToCast = true; } @@ -1367,13 +1482,59 @@ bool Bot::AI_EngagedCastCheck() { } } } - else if(botClass == RANGER) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + else if (botClass == RANGER) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - // + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + failedToCast = true; + } + } + } + } + } + } + } + else if (botClass == BEASTLORD) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) { + if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + failedToCast = true; + } + } + } + } + } + } + } + } + } + } + else if (botClass == WIZARD) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + failedToCast = true; + } + } + } + } + } + else if (botClass == PALADIN) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { failedToCast = true; } } @@ -1381,16 +1542,41 @@ bool Bot::AI_EngagedCastCheck() { } } } - else if(botClass == BEASTLORD) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) { - if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { + else if (botClass == SHADOWKNIGHT) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Lifetap), SpellType_Lifetap)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + failedToCast = true; + } + } + } + } + } + } + else if (botClass == MAGICIAN) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + failedToCast = true; + } + } + } + } + } + } + else if (botClass == NECROMANCER) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Lifetap), SpellType_Lifetap)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { - if(!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - // + if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { failedToCast = true; } } @@ -1401,85 +1587,16 @@ bool Bot::AI_EngagedCastCheck() { } } } - else if(botClass == WIZARD) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { - if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - // - failedToCast = true; - } - } - } - else if(botClass == PALADIN) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { - if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_Heal), BotAISpellRange, SpellType_Heal)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_InCombatBuff), SpellType_InCombatBuff)) { - // - failedToCast = true; - } - } - } - } - } - } - else if(botClass == SHADOWKNIGHT) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { - if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Lifetap), SpellType_Lifetap)) { - if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - // - failedToCast = true; - } - } - } - } - } - } - } - } - else if(botClass == MAGICIAN) { - if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) { - if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { - if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - // - failedToCast = true; - } - } - } - } - } - else if(botClass == NECROMANCER) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { - if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Pet), SpellType_Pet)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Lifetap), SpellType_Lifetap)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { - if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { - if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - // - failedToCast = true; - } - } - } - } - } - } - } - } - else if(botClass == ENCHANTER) { + else if (botClass == ENCHANTER) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Mez), SpellType_Mez)) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { - if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { - if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { - // - failedToCast = true; + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + failedToCast = true; + } } } } @@ -1487,14 +1604,83 @@ bool Bot::AI_EngagedCastCheck() { } } } - else if(botClass == BARD) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_HateRedux), BotAISpellRange, SpellType_HateRedux)) { - if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuffSong), SpellType_InCombatBuffSong)) { + else if (botClass == BARD) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {// Bards will use their escape songs + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_HateRedux), BotAISpellRange, SpellType_HateRedux)) { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) { - if (!AICastSpell(GetTarget(), mayGetAggro ? 0 : GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) {// Bards will use their dot songs - if (!AICastSpell(GetTarget(), mayGetAggro ? 0 : GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) {// Bards will use their nuke songs - if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {// Bards will use their escape songs - // + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuffSong), SpellType_InCombatBuffSong)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), mayGetAggro ? 0 : GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) {// Bards will use their dot songs + if (!AICastSpell(GetTarget(), mayGetAggro ? 0 : GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) {// Bards will use their nuke songs + failedToCast = true; + } + } + } + } + } + } + } + } + } + else if (botClass == BERSERKER) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuffSong), SpellType_InCombatBuffSong)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + failedToCast = true; + } + } + } + } + } + } + } + } + else if (botClass == MONK) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuffSong), SpellType_InCombatBuffSong)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + failedToCast = true; + } + } + } + } + } + } + } + } + else if (botClass == ROGUE) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuffSong), SpellType_InCombatBuffSong)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { + failedToCast = true; + } + } + } + } + } + } + } + } + else if (botClass == WARRIOR) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), BotAISpellRange, SpellType_InCombatBuff)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Debuff), SpellType_Debuff)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuffSong), SpellType_InCombatBuffSong)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { failedToCast = true; } } @@ -1504,12 +1690,13 @@ bool Bot::AI_EngagedCastCheck() { } } - if(!AIautocastspell_timer->Enabled()) { + if (!AIautocastspell_timer->Enabled()) { AIautocastspell_timer->Start(RandomTimer(150, 300), false); } - if(!failedToCast) + if (!failedToCast) { result = true; + } } return result; @@ -1524,8 +1711,8 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { if (!AI_HasSpells()) return false; - if(tar->GetAppearance() == eaDead) { - if((tar->IsClient() && tar->CastToClient()->GetFeigned()) || tar->IsBot()) { + if (tar->GetAppearance() == eaDead) { + if ((tar->IsClient() && tar->CastToClient()->GetFeigned()) || tar->IsBot()) { // do nothing } else { @@ -1545,30 +1732,27 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { if (useFastHeals) { botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) botSpell = GetBestBotSpellForFastHeal(this); } else { botSpell = GetBestBotSpellForPercentageHeal(this); - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) { botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - - if(botSpell.SpellId == 0) + } + if (botSpell.SpellId == 0) { botSpell = GetFirstBotSpellForSingleTargetHeal(this); - - if(botSpell.SpellId == 0){ + } + if (botSpell.SpellId == 0) { botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); } } -#if BotAI_DEBUG_Spells >= 10 - LogAI("Bot::AIHealRotation: heal spellid = [{}], fastheals = [{}], casterlevel = [{}]", + LogAIDetail("heal spellid [{}] fastheals [{}] casterlevel [{}]", botSpell.SpellId, ((useFastHeals) ? ('T') : ('F')), GetLevel()); -#endif -#if BotAI_DEBUG_Spells >= 25 - LogAI("Bot::AIHealRotation: target = [{}], current_time = [{}], donthealmebefore = [{}]", tar->GetCleanName(), Timer::GetCurrentTime(), tar->DontHealMeBefore()); -#endif + + LogAIDetail("target [{}] current_time [{}] donthealmebefore [{}]", tar->GetCleanName(), Timer::GetCurrentTime(), tar->DontHealMeBefore()); // If there is still no spell id, then there isn't going to be one so we are done if (botSpell.SpellId == 0) @@ -1583,8 +1767,16 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); - if(castedSpell) - Say("Casting %s on %s, please stay in range!", spells[botSpell.SpellId].name, tar->GetCleanName()); + if (castedSpell) { + BotGroupSay( + this, + fmt::format( + "Casting {} on {}, please stay in range!", + spells[botSpell.SpellId].name, + tar->GetCleanName() + ).c_str() + ); + } return castedSpell; } @@ -1592,17 +1784,22 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { std::list Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect) { std::list result; - if(botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + auto bot_owner = botCaster->GetBotOwner(); + if (!bot_owner) { + return result; + } + + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(IsEffectInSpell(botSpellList[i].spellid, spellEffect)) { + if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) { BotSpell botSpell; botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellIndex = i; @@ -1619,18 +1816,23 @@ std::list Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEff std::list Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType) { std::list result; - if(botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + auto bot_owner = botCaster->GetBotOwner(); + if (!bot_owner) { + return result; + } + + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(IsEffectInSpell(botSpellList[i].spellid, spellEffect)) { - if(spells[botSpellList[i].spellid].target_type == targetType) { + if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) { + if (spells[botSpellList[i].spellid].target_type == targetType) { BotSpell botSpell; botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellIndex = i; @@ -1648,17 +1850,22 @@ std::list Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, std::list Bot::GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType) { std::list result; - if(botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + auto bot_owner = botCaster->GetBotOwner(); + if (!bot_owner) { + return result; + } + + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(botSpellList[i].type & spellType) { + if (botSpellList[i].type & spellType) { BotSpell botSpell; botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellIndex = i; @@ -1676,10 +1883,10 @@ std::list Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCa std::list result; if (botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; @@ -1696,8 +1903,13 @@ std::list Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCa } } - if (result.size() > 1) - result.sort([](BotSpell_wPriority& l, BotSpell_wPriority& r) { return l.Priority < r.Priority; }); + if (result.size() > 1) { + result.sort( + [](BotSpell_wPriority& l, BotSpell_wPriority& r) { + return l.Priority < r.Priority; + } + ); + } } return result; @@ -1710,17 +1922,17 @@ BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if((botSpellList[i].type & spellType) && CheckSpellRecastTimers(botCaster, i)) { + if ((botSpellList[i].type & spellType) && CheckSpellRecastTimers(botCaster, i)) { result.SpellId = botSpellList[i].spellid; result.SpellIndex = i; result.ManaCost = botSpellList[i].manacost; @@ -1740,12 +1952,12 @@ BotSpell Bot::GetBestBotSpellForFastHeal(Bot *botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_CurrentHP); - for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsFastHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if (IsFastHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -1765,22 +1977,25 @@ BotSpell Bot::GetBestBotSpellForHealOverTime(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botHoTSpellList = GetBotSpellsForSpellEffect(botCaster, SE_HealOverTime); - std::vector botSpellList = botCaster->GetBotSpells(); + std::vector botSpellList = botCaster->AIBot_spells; - for(std::list::iterator botSpellListItr = botHoTSpellList.begin(); botSpellListItr != botHoTSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botHoTSpellList.begin(); botSpellListItr != botHoTSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsHealOverTimeSpell(botSpellListItr->SpellId)) { - + if (IsHealOverTimeSpell(botSpellListItr->SpellId)) { for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(botSpellList[i].spellid == botSpellListItr->SpellId && (botSpellList[i].type & SpellType_Heal) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + botSpellList[i].spellid == botSpellListItr->SpellId && + (botSpellList[i].type & SpellType_Heal) && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -1802,21 +2017,20 @@ BotSpell Bot::GetBestBotSpellForPercentageHeal(Bot *botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(IsCompleteHealSpell(botSpellList[i].spellid) && CheckSpellRecastTimers(botCaster, i)) { + if (IsCompleteHealSpell(botSpellList[i].spellid) && CheckSpellRecastTimers(botCaster, i)) { result.SpellId = botSpellList[i].spellid; result.SpellIndex = i; result.ManaCost = botSpellList[i].manacost; - break; } } @@ -1832,16 +2046,15 @@ BotSpell Bot::GetBestBotSpellForRegularSingleTargetHeal(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_CurrentHP); - for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if (IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; - break; } } @@ -1857,16 +2070,21 @@ BotSpell Bot::GetFirstBotSpellForSingleTargetHeal(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_CurrentHP); - for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if((IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) || IsFastHealSpell(botSpellListItr->SpellId)) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + ( + IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) || + IsFastHealSpell(botSpellListItr->SpellId) + ) && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; - break; } } @@ -1882,16 +2100,18 @@ BotSpell Bot::GetBestBotSpellForGroupHeal(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_CurrentHP); - for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsRegularGroupHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + IsRegularGroupHealSpell(botSpellListItr->SpellId) && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; - break; } } @@ -1907,22 +2127,26 @@ BotSpell Bot::GetBestBotSpellForGroupHealOverTime(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botHoTSpellList = GetBotSpellsForSpellEffect(botCaster, SE_HealOverTime); - std::vector botSpellList = botCaster->GetBotSpells(); + std::vector botSpellList = botCaster->AIBot_spells; - for(std::list::iterator botSpellListItr = botHoTSpellList.begin(); botSpellListItr != botHoTSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botHoTSpellList.begin(); botSpellListItr != botHoTSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsGroupHealOverTimeSpell(botSpellListItr->SpellId)) { + if (IsGroupHealOverTimeSpell(botSpellListItr->SpellId)) { for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(botSpellList[i].spellid == botSpellListItr->SpellId && (botSpellList[i].type & SpellType_Heal) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + botSpellList[i].spellid == botSpellListItr->SpellId && + (botSpellList[i].type & SpellType_Heal) && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -1944,16 +2168,18 @@ BotSpell Bot::GetBestBotSpellForGroupCompleteHeal(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_CompleteHeal); for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsGroupCompleteHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + IsGroupCompleteHealSpell(botSpellListItr->SpellId) && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; - break; } } @@ -1969,12 +2195,15 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_Mez); - for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsMezSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + IsMezSpell(botSpellListItr->SpellId) && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -1994,16 +2223,19 @@ BotSpell Bot::GetBestBotSpellForMagicBasedSlow(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_AttackSpeed); for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if (IsSlowSpell(botSpellListItr->SpellId) && spells[botSpellListItr->SpellId].resist_type == RESIST_MAGIC && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + IsSlowSpell(botSpellListItr->SpellId) && + spells[botSpellListItr->SpellId].resist_type == RESIST_MAGIC && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; - break; } } @@ -2019,12 +2251,16 @@ BotSpell Bot::GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_AttackSpeed); - for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsSlowSpell(botSpellListItr->SpellId) && spells[botSpellListItr->SpellId].resist_type == RESIST_DISEASE && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ( + IsSlowSpell(botSpellListItr->SpellId) && + spells[botSpellListItr->SpellId].resist_type == RESIST_DISEASE && + CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + ) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -2040,7 +2276,7 @@ BotSpell Bot::GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster) { Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) { Mob* result = 0; - if(botCaster && IsMezSpell(botSpell.SpellId)) { + if (botCaster && IsMezSpell(botSpell.SpellId)) { std::list npc_list; entity_list.GetNPCList(npc_list); @@ -2048,14 +2284,16 @@ Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) { for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { NPC* npc = *itr; - if(DistanceSquaredNoZ(npc->GetPosition(), botCaster->GetPosition()) <= botCaster->GetActSpellRange(botSpell.SpellId, spells[botSpell.SpellId].range)) { - if(!npc->IsMezzed()) { - if(botCaster->HasGroup()) { + if (DistanceSquaredNoZ(npc->GetPosition(), botCaster->GetPosition()) <= botCaster->GetActSpellRange(botSpell.SpellId, spells[botSpell.SpellId].range)) { + if (!npc->IsMezzed()) { + if (botCaster->HasGroup()) { Group* g = botCaster->GetGroup(); - if(g) { - for(int counter = 0; counter < g->GroupCount(); counter++) { - if(npc->IsOnHatelist(g->members[counter]) && g->members[counter]->GetTarget() != npc && g->members[counter]->IsEngaged()) { + if (g) { + for (int counter = 0; counter < g->GroupCount(); counter++) { + if ( + npc->IsOnHatelist(g->members[counter]) && + g->members[counter]->GetTarget() != npc && g->members[counter]->IsEngaged()) { result = npc; break; } @@ -2065,7 +2303,7 @@ Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) { } } - if(result) + if (result) break; } } @@ -2080,15 +2318,15 @@ BotSpell Bot::GetBestBotMagicianPetSpell(Bot *botCaster) { result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_SummonPet); std::string petType = GetBotMagicianPetType(botCaster); for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsSummonPetSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { - if(!strncmp(spells[botSpellListItr->SpellId].teleport_zone, petType.c_str(), petType.length())) { + if (IsSummonPetSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if (!strncmp(spells[botSpellListItr->SpellId].teleport_zone, petType.c_str(), petType.length())) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -2105,8 +2343,8 @@ BotSpell Bot::GetBestBotMagicianPetSpell(Bot *botCaster) { std::string Bot::GetBotMagicianPetType(Bot* botCaster) { std::string result; - if(botCaster) { - if(botCaster->IsPetChooser()) { + if (botCaster) { + if (botCaster->IsPetChooser()) { switch(botCaster->GetPetChooserID()) { case 0: result = std::string("SumWater"); @@ -2126,15 +2364,15 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) { } } else { - if(botCaster->GetLevel() == 2) + if (botCaster->GetLevel() == 2) result = std::string("SumWater"); - else if(botCaster->GetLevel() == 3) + else if (botCaster->GetLevel() == 3) result = std::string("SumFire"); - else if(botCaster->GetLevel() == 4) + else if (botCaster->GetLevel() == 4) result = std::string("SumAir"); - else if(botCaster->GetLevel() == 5) + else if (botCaster->GetLevel() == 5) result = std::string("SumEarth"); - else if(botCaster->GetLevel() < 30) { + else if (botCaster->GetLevel() < 30) { // Under level 30 int counter = zone->random.Int(0, 3); @@ -2191,12 +2429,12 @@ BotSpell Bot::GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) { + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffectAndTargetType(botCaster, SE_CurrentHP, targetType); for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsPureNukeSpell(botSpellListItr->SpellId) && IsDamageSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if ((IsPureNukeSpell(botSpellListItr->SpellId) || IsDamageSpell(botSpellListItr->SpellId)) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -2217,14 +2455,14 @@ BotSpell Bot::GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster) + if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffectAndTargetType(botCaster, SE_Stun, targetType); for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsStunSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) + if (IsStunSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; @@ -2244,12 +2482,12 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ result.SpellIndex = 0; result.ManaCost = 0; - if(botCaster && target) { + if (botCaster && target) { const int lureResisValue = -100; const int maxTargetResistValue = 300; bool selectLureNuke = false; - if((target->GetMR() > maxTargetResistValue) && (target->GetCR() > maxTargetResistValue) && (target->GetFR() > maxTargetResistValue)) + if ((target->GetMR() > maxTargetResistValue) && (target->GetCR() > maxTargetResistValue) && (target->GetFR() > maxTargetResistValue)) selectLureNuke = true; @@ -2264,27 +2502,27 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ // Assuming all the spells have been loaded into this list by level and in descending order bool spellSelected = false; - if(CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { - if(selectLureNuke && (spells[botSpellListItr->SpellId].resist_difficulty < lureResisValue)) { + if (CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if (selectLureNuke && (spells[botSpellListItr->SpellId].resist_difficulty < lureResisValue)) { spellSelected = true; } - else if(IsPureNukeSpell(botSpellListItr->SpellId)) { - if(((target->GetMR() < target->GetCR()) || (target->GetMR() < target->GetFR())) && (GetSpellResistType(botSpellListItr->SpellId) == RESIST_MAGIC) + else if (IsPureNukeSpell(botSpellListItr->SpellId)) { + if (((target->GetMR() < target->GetCR()) || (target->GetMR() < target->GetFR())) && (GetSpellResistType(botSpellListItr->SpellId) == RESIST_MAGIC) && (spells[botSpellListItr->SpellId].resist_difficulty > lureResisValue)) { spellSelected = true; } - else if(((target->GetCR() < target->GetMR()) || (target->GetCR() < target->GetFR())) && (GetSpellResistType(botSpellListItr->SpellId) == RESIST_COLD) + else if (((target->GetCR() < target->GetMR()) || (target->GetCR() < target->GetFR())) && (GetSpellResistType(botSpellListItr->SpellId) == RESIST_COLD) && (spells[botSpellListItr->SpellId].resist_difficulty > lureResisValue)) { spellSelected = true; } - else if(((target->GetFR() < target->GetCR()) || (target->GetFR() < target->GetMR())) && (GetSpellResistType(botSpellListItr->SpellId) == RESIST_FIRE) + else if (((target->GetFR() < target->GetCR()) || (target->GetFR() < target->GetMR())) && (GetSpellResistType(botSpellListItr->SpellId) == RESIST_FIRE) && (spells[botSpellListItr->SpellId].resist_difficulty > lureResisValue)) { spellSelected = true; } - else if((GetSpellResistType(botSpellListItr->SpellId) == RESIST_MAGIC) && (spells[botSpellListItr->SpellId].resist_difficulty > lureResisValue) && !IsStunSpell(botSpellListItr->SpellId)) { + else if ((GetSpellResistType(botSpellListItr->SpellId) == RESIST_MAGIC) && (spells[botSpellListItr->SpellId].resist_difficulty > lureResisValue) && !IsStunSpell(botSpellListItr->SpellId)) { firstWizardMagicNukeSpellFound.SpellId = botSpellListItr->SpellId; firstWizardMagicNukeSpellFound.SpellIndex = botSpellListItr->SpellIndex; firstWizardMagicNukeSpellFound.ManaCost = botSpellListItr->ManaCost; @@ -2292,7 +2530,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ } } - if(spellSelected) { + if (spellSelected) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -2301,7 +2539,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ } } - if(result.SpellId == 0) { + if (result.SpellId == 0) { result = firstWizardMagicNukeSpellFound; } } @@ -2316,20 +2554,20 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) { result.SpellIndex = 0; result.ManaCost = 0; - if(!tar || !botCaster) + if (!tar || !botCaster) return result; - if(botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(((botSpellList[i].type & SpellType_Debuff) || IsDebuffSpell(botSpellList[i].spellid)) + if (((botSpellList[i].type & SpellType_Debuff) || IsDebuffSpell(botSpellList[i].spellid)) && (!tar->IsImmuneToSpell(botSpellList[i].spellid, botCaster) && tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0) && CheckSpellRecastTimers(botCaster, i)) { @@ -2352,11 +2590,11 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) { result.SpellIndex = 0; result.ManaCost = 0; - if(!tar) + if (!tar) return result; int level_mod = (tar->GetLevel() - botCaster->GetLevel())* (tar->GetLevel() - botCaster->GetLevel()) / 2; - if(tar->GetLevel() - botCaster->GetLevel() < 0) + if (tar->GetLevel() - botCaster->GetLevel() < 0) { level_mod = -level_mod; } @@ -2366,17 +2604,17 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) { bool needsPoisonResistDebuff = (tar->GetPR() + level_mod) > 100 ? true: false; bool needsDiseaseResistDebuff = (tar->GetDR() + level_mod) > 100 ? true: false; - if(botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->GetBotSpells(); + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->AIBot_spells; for (int i = botSpellList.size() - 1; i >= 0; i--) { - if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; } - if(((botSpellList[i].type & SpellType_Debuff) || IsResistDebuffSpell(botSpellList[i].spellid)) + if (((botSpellList[i].type & SpellType_Debuff) || IsResistDebuffSpell(botSpellList[i].spellid)) && ((needsMagicResistDebuff && (IsEffectInSpell(botSpellList[i].spellid, SE_ResistMagic)) || IsEffectInSpell(botSpellList[i].spellid, SE_ResistAll)) || (needsColdResistDebuff && (IsEffectInSpell(botSpellList[i].spellid, SE_ResistCold)) || IsEffectInSpell(botSpellList[i].spellid, SE_ResistAll)) || (needsFireResistDebuff && (IsEffectInSpell(botSpellList[i].spellid, SE_ResistFire)) || IsEffectInSpell(botSpellList[i].spellid, SE_ResistAll)) @@ -2405,7 +2643,7 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { result.SpellIndex = 0; result.ManaCost = 0; - if(!tar) + if (!tar) return result; int countNeedsCured = 0; @@ -2414,16 +2652,16 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { bool isCursed = tar->FindType(SE_CurseCounter); bool isCorrupted = tar->FindType(SE_CorruptionCounter); - if(botCaster && botCaster->AI_HasSpells()) { + if (botCaster && botCaster->AI_HasSpells()) { std::list cureList = GetPrioritizedBotSpellsBySpellType(botCaster, SpellType_Cure); - if(tar->HasGroup()) { + if (tar->HasGroup()) { Group *g = tar->GetGroup(); - if(g) { + if (g) { for( int i = 0; imembers[i] && !g->members[i]->qglobal) { - if(botCaster->GetNeedsCured(g->members[i])) + if (g->members[i] && !g->members[i]->qglobal) { + if (botCaster->GetNeedsCured(g->members[i])) countNeedsCured++; } } @@ -2431,31 +2669,31 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { } //Check for group cure first - if(countNeedsCured > 2) { + if (countNeedsCured > 2) { for (std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { BotSpell selectedBotSpell = *itr; - if(IsGroupSpell(itr->SpellId) && CheckSpellRecastTimers(botCaster, itr->SpellIndex)) { - if(selectedBotSpell.SpellId == 0) + if (IsGroupSpell(itr->SpellId) && CheckSpellRecastTimers(botCaster, itr->SpellIndex)) { + if (selectedBotSpell.SpellId == 0) continue; - if(isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) { + if (isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) { spellSelected = true; } - else if(isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) { + else if (isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) { spellSelected = true; } - else if(isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) { + else if (isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) { spellSelected = true; } - else if(isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) { + else if (isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) { spellSelected = true; } - else if(IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) { + else if (IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) { spellSelected = true; } - if(spellSelected) + if (spellSelected) { result.SpellId = itr->SpellId; result.SpellIndex = itr->SpellIndex; @@ -2468,31 +2706,31 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { } //no group cure for target- try to find single target spell - if(!spellSelected) { + if (!spellSelected) { for(std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { BotSpell selectedBotSpell = *itr; - if(CheckSpellRecastTimers(botCaster, itr->SpellIndex)) { - if(selectedBotSpell.SpellId == 0) + if (CheckSpellRecastTimers(botCaster, itr->SpellIndex)) { + if (selectedBotSpell.SpellId == 0) continue; - if(isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) { + if (isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) { spellSelected = true; } - else if(isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) { + else if (isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) { spellSelected = true; } - else if(isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) { + else if (isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) { spellSelected = true; } - else if(isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) { + else if (isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) { spellSelected = true; } - else if(IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) { + else if (IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) { spellSelected = true; } - if(spellSelected) + if (spellSelected) { result.SpellId = itr->SpellId; result.SpellIndex = itr->SpellIndex; @@ -2509,15 +2747,15 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { } void Bot::SetSpellRecastTimer(int timer_index, int32 recast_delay) { - if(timer_index > 0 && timer_index <= MaxSpellTimer) { + if (timer_index > 0 && timer_index <= MaxSpellTimer) { timers[timer_index - 1] = Timer::GetCurrentTime() + recast_delay; } } int32 Bot::GetSpellRecastTimer(Bot *caster, int timer_index) { int32 result = 0; - if(caster) { - if(timer_index > 0 && timer_index <= MaxSpellTimer) { + if (caster) { + if (timer_index > 0 && timer_index <= MaxSpellTimer) { result = caster->timers[timer_index - 1]; } } @@ -2525,9 +2763,9 @@ int32 Bot::GetSpellRecastTimer(Bot *caster, int timer_index) { } bool Bot::CheckSpellRecastTimers(Bot *caster, int SpellIndex) { - if(caster) { - if(caster->AIspells[SpellIndex].time_cancast < Timer::GetCurrentTime()) { //checks spell recast - if(GetSpellRecastTimer(caster, spells[caster->AIspells[SpellIndex].spellid].timer_id) < Timer::GetCurrentTime()) { //checks for spells on the same timer + if (caster) { + if (caster->AIBot_spells[SpellIndex].time_cancast < Timer::GetCurrentTime()) { //checks spell recast + if (GetSpellRecastTimer(caster, spells[caster->AIBot_spells[SpellIndex].spellid].timer_id) < Timer::GetCurrentTime()) { //checks for spells on the same timer return true; //can cast spell } } @@ -2536,15 +2774,15 @@ bool Bot::CheckSpellRecastTimers(Bot *caster, int SpellIndex) { } void Bot::SetDisciplineRecastTimer(int timer_index, int32 recast_delay) { - if(timer_index > 0 && timer_index <= MaxDisciplineTimer) { + if (timer_index > 0 && timer_index <= MaxDisciplineTimer) { timers[DisciplineReuseStart + timer_index - 1] = Timer::GetCurrentTime() + recast_delay; } } int32 Bot::GetDisciplineRecastTimer(Bot *caster, int timer_index) { int32 result = 0; - if(caster) { - if(timer_index > 0 && timer_index <= MaxDisciplineTimer) { + if (caster) { + if (timer_index > 0 && timer_index <= MaxDisciplineTimer) { result = caster->timers[DisciplineReuseStart + timer_index - 1]; } } @@ -2553,9 +2791,9 @@ int32 Bot::GetDisciplineRecastTimer(Bot *caster, int timer_index) { uint32 Bot::GetDisciplineRemainingTime(Bot *caster, int timer_index) { int32 result = 0; - if(caster) { - if(timer_index > 0 && timer_index <= MaxDisciplineTimer) { - if(GetDisciplineRecastTimer(caster, timer_index) > Timer::GetCurrentTime()) + if (caster) { + if (timer_index > 0 && timer_index <= MaxDisciplineTimer) { + if (GetDisciplineRecastTimer(caster, timer_index) > Timer::GetCurrentTime()) result = GetDisciplineRecastTimer(caster, timer_index) - Timer::GetCurrentTime(); } } @@ -2563,8 +2801,8 @@ uint32 Bot::GetDisciplineRemainingTime(Bot *caster, int timer_index) { } bool Bot::CheckDisciplineRecastTimers(Bot *caster, int timer_index) { - if(caster) { - if(GetDisciplineRecastTimer(caster, timer_index) < Timer::GetCurrentTime()) { //checks for spells on the same timer + if (caster) { + if (GetDisciplineRecastTimer(caster, timer_index) < Timer::GetCurrentTime()) { //checks for spells on the same timer return true; //can cast spell } } @@ -2674,4 +2912,547 @@ uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) return database.botdb.GetSpellCastingChance(spell_type_index, class_index, stance_index, type_index); } -#endif +bool Bot::AI_AddBotSpells(uint32 bot_spell_id) { + // ok, this function should load the list, and the parent list then shove them into the struct and sort + npc_spells_id = bot_spell_id; + AIBot_spells.clear(); + AIBot_spells_enforced.clear(); + if (!bot_spell_id) { + AIautocastspell_timer->Disable(); + return false; + } + + auto* spell_list = content_db.GetBotSpells(bot_spell_id); + if (!spell_list) { + AIautocastspell_timer->Disable(); + return false; + } + + auto* parentlist = content_db.GetBotSpells(spell_list->parent_list); + + auto debug_msg = fmt::format( + "Loading Bot spells onto {}: dbspellsid={}, level={}", + GetName(), + bot_spell_id, + GetLevel() + ); + + if (spell_list) { + debug_msg.append( + fmt::format( + " (found, {})", + spell_list->entries.size() + ) + ); + + LogAI("[{}]", debug_msg); + for (const auto &iter : spell_list->entries) { + LogAIDetail("([{}]) [{}]", iter.spellid, spells[iter.spellid].name); + } + } + else + { + debug_msg.append(" (not found)"); + LogAI("[{}]", debug_msg); + } + + LogAI("fin (spell list)"); + + uint16 attack_proc_spell = -1; + int8 proc_chance = 3; + uint16 range_proc_spell = -1; + int16 rproc_chance = 0; + uint16 defensive_proc_spell = -1; + int16 dproc_chance = 0; + uint32 _fail_recast = 0; + uint32 _engaged_no_sp_recast_min = 0; + uint32 _engaged_no_sp_recast_max = 0; + uint8 _engaged_beneficial_self_chance = 0; + uint8 _engaged_beneficial_other_chance = 0; + uint8 _engaged_detrimental_chance = 0; + uint32 _pursue_no_sp_recast_min = 0; + uint32 _pursue_no_sp_recast_max = 0; + uint8 _pursue_detrimental_chance = 0; + uint32 _idle_no_sp_recast_min = 0; + uint32 _idle_no_sp_recast_max = 0; + uint8 _idle_beneficial_chance = 0; + + if (parentlist) { + attack_proc_spell = parentlist->attack_proc; + proc_chance = parentlist->proc_chance; + range_proc_spell = parentlist->range_proc; + rproc_chance = parentlist->rproc_chance; + defensive_proc_spell = parentlist->defensive_proc; + dproc_chance = parentlist->dproc_chance; + _fail_recast = parentlist->fail_recast; + _engaged_no_sp_recast_min = parentlist->engaged_no_sp_recast_min; + _engaged_no_sp_recast_max = parentlist->engaged_no_sp_recast_max; + _engaged_beneficial_self_chance = parentlist->engaged_beneficial_self_chance; + _engaged_beneficial_other_chance = parentlist->engaged_beneficial_other_chance; + _engaged_detrimental_chance = parentlist->engaged_detrimental_chance; + _pursue_no_sp_recast_min = parentlist->pursue_no_sp_recast_min; + _pursue_no_sp_recast_max = parentlist->pursue_no_sp_recast_max; + _pursue_detrimental_chance = parentlist->pursue_detrimental_chance; + _idle_no_sp_recast_min = parentlist->idle_no_sp_recast_min; + _idle_no_sp_recast_max = parentlist->idle_no_sp_recast_max; + _idle_beneficial_chance = parentlist->idle_beneficial_chance; + for (auto &e : parentlist->entries) { + if ( + EQ::ValueWithin(GetLevel(), e.minlevel, e.maxlevel) && + e.spellid && + !IsSpellInBotList(spell_list, e.spellid) + ) { + if (!e.bucket_name.empty() && !e.bucket_value.empty()) { + if (!CheckDataBucket(e.bucket_name, e.bucket_value, e.bucket_comparison)) { + continue; + } + } + + const auto& bs = GetBotSpellSetting(e.spellid); + if (bs) { + if (!bs->is_enabled) { + continue; + } + + AddSpellToBotList( + bs->priority, + e.spellid, + e.type, + e.manacost, + e.recast_delay, + e.resist_adjust, + e.minlevel, + e.maxlevel, + bs->min_hp, + bs->max_hp, + e.bucket_name, + e.bucket_value, + e.bucket_comparison + ); + continue; + } + + if (!GetBotEnforceSpellSetting()) { + AddSpellToBotList( + e.priority, + e.spellid, + e.type, + e.manacost, + e.recast_delay, + e.resist_adjust, + e.minlevel, + e.maxlevel, + e.min_hp, + e.max_hp, + e.bucket_name, + e.bucket_value, + e.bucket_comparison + ); + } else { + AddSpellToBotEnforceList( + e.priority, + e.spellid, + e.type, + e.manacost, + e.recast_delay, + e.resist_adjust, + e.minlevel, + e.maxlevel, + e.min_hp, + e.max_hp, + e.bucket_name, + e.bucket_value, + e.bucket_comparison + ); + } + } + } + } + + if (spell_list->attack_proc >= 0) { + attack_proc_spell = spell_list->attack_proc; + proc_chance = spell_list->proc_chance; + } + + if (spell_list->range_proc >= 0) { + range_proc_spell = spell_list->range_proc; + rproc_chance = spell_list->rproc_chance; + } + + if (spell_list->defensive_proc >= 0) { + defensive_proc_spell = spell_list->defensive_proc; + dproc_chance = spell_list->dproc_chance; + } + + //If any casting variables are defined in the current list, ignore those in the parent list. + if ( + spell_list->fail_recast || + spell_list->engaged_no_sp_recast_min || + spell_list->engaged_no_sp_recast_max || + spell_list->engaged_beneficial_self_chance || + spell_list->engaged_beneficial_other_chance || + spell_list->engaged_detrimental_chance || + spell_list->pursue_no_sp_recast_min || + spell_list->pursue_no_sp_recast_max || + spell_list->pursue_detrimental_chance || + spell_list->idle_no_sp_recast_min || + spell_list->idle_no_sp_recast_max || + spell_list->idle_beneficial_chance + ) { + _fail_recast = spell_list->fail_recast; + _engaged_no_sp_recast_min = spell_list->engaged_no_sp_recast_min; + _engaged_no_sp_recast_max = spell_list->engaged_no_sp_recast_max; + _engaged_beneficial_self_chance = spell_list->engaged_beneficial_self_chance; + _engaged_beneficial_other_chance = spell_list->engaged_beneficial_other_chance; + _engaged_detrimental_chance = spell_list->engaged_detrimental_chance; + _pursue_no_sp_recast_min = spell_list->pursue_no_sp_recast_min; + _pursue_no_sp_recast_max = spell_list->pursue_no_sp_recast_max; + _pursue_detrimental_chance = spell_list->pursue_detrimental_chance; + _idle_no_sp_recast_min = spell_list->idle_no_sp_recast_min; + _idle_no_sp_recast_max = spell_list->idle_no_sp_recast_max; + _idle_beneficial_chance = spell_list->idle_beneficial_chance; + } + + for (auto &e : spell_list->entries) { + if (EQ::ValueWithin(GetLevel(), e.minlevel, e.maxlevel) && e.spellid) { + if (!e.bucket_name.empty() && !e.bucket_value.empty()) { + if (!CheckDataBucket(e.bucket_name, e.bucket_value, e.bucket_comparison)) { + continue; + } + } + + const auto& bs = GetBotSpellSetting(e.spellid); + if (bs) { + if (!bs->is_enabled) { + continue; + } + + AddSpellToBotList( + bs->priority, + e.spellid, + e.type, + e.manacost, + e.recast_delay, + e.resist_adjust, + e.minlevel, + e.maxlevel, + bs->min_hp, + bs->max_hp, + e.bucket_name, + e.bucket_value, + e.bucket_comparison + ); + continue; + } + + if (!GetBotEnforceSpellSetting()) { + AddSpellToBotList( + e.priority, + e.spellid, + e.type, + e.manacost, + e.recast_delay, + e.resist_adjust, + e.minlevel, + e.maxlevel, + e.min_hp, + e.max_hp, + e.bucket_name, + e.bucket_value, + e.bucket_comparison + ); + } else { + AddSpellToBotEnforceList( + e.priority, + e.spellid, + e.type, + e.manacost, + e.recast_delay, + e.resist_adjust, + e.minlevel, + e.maxlevel, + e.min_hp, + e.max_hp, + e.bucket_name, + e.bucket_value, + e.bucket_comparison + ); + } + } + } + + std::sort(AIBot_spells.begin(), AIBot_spells.end(), [](const BotSpells_Struct& a, const BotSpells_Struct& b) { + return a.priority > b.priority; + }); + + if (IsValidSpell(attack_proc_spell)) { + AddProcToWeapon(attack_proc_spell, true, proc_chance); + + if (RuleB(Spells, NPCInnateProcOverride)) { + innate_proc_spell_id = attack_proc_spell; + } + } + + if (IsValidSpell(range_proc_spell)) { + AddRangedProc(range_proc_spell, (rproc_chance + 100)); + } + + if (IsValidSpell(defensive_proc_spell)) { + AddDefensiveProc(defensive_proc_spell, (dproc_chance + 100)); + } + + //Set AI casting variables + + AISpellVar.fail_recast = (_fail_recast) ? _fail_recast : RuleI(Spells, AI_SpellCastFinishedFailRecast); + AISpellVar.engaged_no_sp_recast_min = (_engaged_no_sp_recast_min) ? _engaged_no_sp_recast_min : RuleI(Spells, AI_EngagedNoSpellMinRecast); + AISpellVar.engaged_no_sp_recast_max = (_engaged_no_sp_recast_max) ? _engaged_no_sp_recast_max : RuleI(Spells, AI_EngagedNoSpellMaxRecast); + AISpellVar.engaged_beneficial_self_chance = (_engaged_beneficial_self_chance) ? _engaged_beneficial_self_chance : RuleI(Spells, AI_EngagedBeneficialSelfChance); + AISpellVar.engaged_beneficial_other_chance = (_engaged_beneficial_other_chance) ? _engaged_beneficial_other_chance : RuleI(Spells, AI_EngagedBeneficialOtherChance); + AISpellVar.engaged_detrimental_chance = (_engaged_detrimental_chance) ? _engaged_detrimental_chance : RuleI(Spells, AI_EngagedDetrimentalChance); + AISpellVar.pursue_no_sp_recast_min = (_pursue_no_sp_recast_min) ? _pursue_no_sp_recast_min : RuleI(Spells, AI_PursueNoSpellMinRecast); + AISpellVar.pursue_no_sp_recast_max = (_pursue_no_sp_recast_max) ? _pursue_no_sp_recast_max : RuleI(Spells, AI_PursueNoSpellMaxRecast); + AISpellVar.pursue_detrimental_chance = (_pursue_detrimental_chance) ? _pursue_detrimental_chance : RuleI(Spells, AI_PursueDetrimentalChance); + AISpellVar.idle_no_sp_recast_min = (_idle_no_sp_recast_min) ? _idle_no_sp_recast_min : RuleI(Spells, AI_IdleNoSpellMinRecast); + AISpellVar.idle_no_sp_recast_max = (_idle_no_sp_recast_max) ? _idle_no_sp_recast_max : RuleI(Spells, AI_IdleNoSpellMaxRecast); + AISpellVar.idle_beneficial_chance = (_idle_beneficial_chance) ? _idle_beneficial_chance : RuleI(Spells, AI_IdleBeneficialChance); + + if (AIBot_spells.empty()) { + AIautocastspell_timer->Disable(); + } else { + AIautocastspell_timer->Trigger(); + } + return true; +} + +bool IsSpellInBotList(DBbotspells_Struct* spell_list, uint16 iSpellID) { + auto it = std::find_if ( + spell_list->entries.begin(), + spell_list->entries.end(), + [iSpellID](const DBbotspells_entries_Struct &a) { + return a.spellid == iSpellID; + } + ); + + return it != spell_list->entries.end(); +} + +DBbotspells_Struct* ZoneDatabase::GetBotSpells(uint32 bot_spell_id) +{ + if (!bot_spell_id) { + return nullptr; + } + + auto c = bot_spells_cache.find(bot_spell_id); + if (c != bot_spells_cache.end()) { // it's in the cache, easy =) + return &c->second; + } + + if (!bot_spells_loadtried.count(bot_spell_id)) { // no reason to ask the DB again if we have failed once already + bot_spells_loadtried.insert(bot_spell_id); + + auto n = NpcSpellsRepository::FindOne(content_db, bot_spell_id); + if (!n.id) { + return nullptr; + } + + DBbotspells_Struct spell_set; + + spell_set.parent_list = n.parent_list; + spell_set.attack_proc = n.attack_proc; + spell_set.proc_chance = n.proc_chance; + spell_set.range_proc = n.range_proc; + spell_set.rproc_chance = n.rproc_chance; + spell_set.defensive_proc = n.defensive_proc; + spell_set.dproc_chance = n.dproc_chance; + spell_set.fail_recast = n.fail_recast; + spell_set.engaged_no_sp_recast_min = n.engaged_no_sp_recast_min; + spell_set.engaged_no_sp_recast_max = n.engaged_no_sp_recast_max; + spell_set.engaged_beneficial_self_chance = n.engaged_b_self_chance; + spell_set.engaged_beneficial_other_chance = n.engaged_b_other_chance; + spell_set.engaged_detrimental_chance = n.engaged_d_chance; + spell_set.pursue_no_sp_recast_min = n.pursue_no_sp_recast_min; + spell_set.pursue_no_sp_recast_max = n.pursue_no_sp_recast_max; + spell_set.pursue_detrimental_chance = n.pursue_d_chance; + spell_set.idle_no_sp_recast_min = n.idle_no_sp_recast_min; + spell_set.idle_no_sp_recast_max = n.idle_no_sp_recast_max; + spell_set.idle_beneficial_chance = n.idle_b_chance; + + auto bse = BotSpellsEntriesRepository::GetWhere( + content_db, + fmt::format( + "npc_spells_id = {}", + bot_spell_id + ) + ); + + if (!bse.empty()) { + for (const auto& e : bse) { + DBbotspells_entries_Struct entry; + entry.spellid = e.spellid; + entry.type = e.type; + entry.minlevel = e.minlevel; + entry.maxlevel = e.maxlevel; + entry.manacost = e.manacost; + entry.recast_delay = e.recast_delay; + entry.priority = e.priority; + entry.min_hp = e.min_hp; + entry.max_hp = e.max_hp; + entry.resist_adjust = e.resist_adjust; + entry.bucket_name = e.bucket_name; + entry.bucket_value = e.bucket_value; + entry.bucket_comparison = e.bucket_comparison; + + // some spell types don't make much since to be priority 0, so fix that + if (!(entry.type & SPELL_TYPES_INNATE) && entry.priority == 0) { + entry.priority = 1; + } + + if (e.resist_adjust) { + entry.resist_adjust = e.resist_adjust; + } else if (IsValidSpell(e.spellid)) { + entry.resist_adjust = spells[e.spellid].resist_difficulty; + } + + spell_set.entries.push_back(entry); + } + } + + bot_spells_cache.insert(std::make_pair(bot_spell_id, spell_set)); + + return &bot_spells_cache[bot_spell_id]; + } + + return nullptr; +} + +// adds a spell to the list, taking into account priority and resorting list as needed. +void Bot::AddSpellToBotList( + int16 iPriority, + uint16 iSpellID, + uint32 iType, + int16 iManaCost, + int32 iRecastDelay, + int16 iResistAdjust, + uint8 min_level, + uint8 max_level, + int8 min_hp, + int8 max_hp, + std::string bucket_name, + std::string bucket_value, + uint8 bucket_comparison +) { + if (!IsValidSpell(iSpellID)) { + return; + } + + HasAISpell = true; + BotSpells_Struct t; + + t.priority = iPriority; + t.spellid = iSpellID; + t.type = iType; + t.manacost = iManaCost; + t.recast_delay = iRecastDelay; + t.time_cancast = 0; + t.resist_adjust = iResistAdjust; + t.minlevel = min_level; + t.maxlevel = maxlevel; + t.min_hp = min_hp; + t.max_hp = max_hp; + t.bucket_name = bucket_name; + t.bucket_value = bucket_value; + t.bucket_comparison = bucket_comparison; + + AIBot_spells.push_back(t); + + // If we're going from an empty list, we need to start the timer + if (AIBot_spells.empty()) { + AIautocastspell_timer->Start(RandomTimer(0, 300), false); + } +} + +// adds spells to the list ^spells that are returned if ^enforce is enabled +void Bot::AddSpellToBotEnforceList( + int16 iPriority, + uint16 iSpellID, + uint32 iType, + int16 iManaCost, + int32 iRecastDelay, + int16 iResistAdjust, + uint8 min_level, + uint8 max_level, + int8 min_hp, + int8 max_hp, + std::string bucket_name, + std::string bucket_value, + uint8 bucket_comparison +) { + if (!IsValidSpell(iSpellID)) { + return; + } + + HasAISpell = true; + BotSpells_Struct t; + + t.priority = iPriority; + t.spellid = iSpellID; + t.type = iType; + t.manacost = iManaCost; + t.recast_delay = iRecastDelay; + t.time_cancast = 0; + t.resist_adjust = iResistAdjust; + t.minlevel = min_level; + t.maxlevel = maxlevel; + t.min_hp = min_hp; + t.max_hp = max_hp; + t.bucket_name = bucket_name; + t.bucket_value = bucket_value; + t.bucket_comparison = bucket_comparison; + + AIBot_spells_enforced.push_back(t); +} + +//this gets called from InterruptSpell() for failure or SpellFinished() for success +void Bot::AI_Bot_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot) { + if (slot == 1) { + uint32 recovery_time = 0; + if (iCastSucceeded) { + if (casting_spell_AIindex < AIBot_spells.size()) { + recovery_time += spells[AIBot_spells[casting_spell_AIindex].spellid].recovery_time; + if (AIBot_spells[casting_spell_AIindex].recast_delay >= 0) { + if (AIBot_spells[casting_spell_AIindex].recast_delay < 10000) { + AIBot_spells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + (AIBot_spells[casting_spell_AIindex].recast_delay*1000); + } + } + else { + AIBot_spells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + spells[AIBot_spells[casting_spell_AIindex].spellid].recast_time; + } + } + if (recovery_time < AIautocastspell_timer->GetSetAtTrigger()) { + recovery_time = AIautocastspell_timer->GetSetAtTrigger(); + } + AIautocastspell_timer->Start(recovery_time, false); + } + else { + AIautocastspell_timer->Start(AISpellVar.fail_recast, false); + } + casting_spell_AIindex = AIBot_spells.size(); + } +} + +bool Bot::HasBotSpellEntry(uint16 spellid) { + auto* spell_list = content_db.GetBotSpells(GetBotSpellID()); + + if (!spell_list) { + return false; + } + + // Check if Spell ID is found in Bot Spell Entries + for (auto& e : spell_list->entries) { + if (spellid == e.spellid) { + return true; + } + } + + return false; +} diff --git a/zone/cheat_manager.cpp b/zone/cheat_manager.cpp index 30ec922be..f780bb5f1 100644 --- a/zone/cheat_manager.cpp +++ b/zone/cheat_manager.cpp @@ -42,7 +42,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); std::string export_string = fmt::format( "{} {} {}", position1.x, @@ -71,7 +71,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); std::string export_string = fmt::format( "{} {} {}", position1.x, @@ -97,7 +97,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); } break; case MQWarpKnockBack: @@ -115,7 +115,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); } break; @@ -135,7 +135,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); } } break; @@ -155,7 +155,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); } break; case MQZoneUnknownDest: @@ -173,7 +173,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); } break; case MQGate: @@ -191,7 +191,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); } break; case MQGhost: @@ -228,7 +228,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); } break; default: @@ -244,7 +244,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 message.c_str(), zone->GetShortName() ); - LogCheat(message); + LogCheat(fmt::runtime(message)); break; } } diff --git a/zone/client.cpp b/zone/client.cpp index 6324db2a0..ada87526e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -36,7 +36,7 @@ extern volatile bool RunLoops; #include "../common/spdat.h" #include "../common/guilds.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/data_verification.h" #include "../common/profanity_manager.h" #include "data_bucket.h" @@ -46,13 +46,11 @@ extern volatile bool RunLoops; #include "position.h" #include "worldserver.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "petitions.h" #include "command.h" #include "water_map.h" -#ifdef BOTS #include "bot_command.h" -#endif #include "string_ids.h" #include "guild_mgr.h" @@ -63,8 +61,11 @@ extern volatile bool RunLoops; #include "../common/expedition_lockout_timer.h" #include "cheat_manager.h" +#include "../common/repositories/bug_reports_repository.h" +#include "../common/repositories/char_recipe_list_repository.h" #include "../common/repositories/character_spells_repository.h" #include "../common/repositories/character_disciplines_repository.h" +#include "../common/repositories/character_data_repository.h" extern QueryServ* QServ; @@ -79,62 +80,64 @@ char entirecommand[255]; void UpdateWindowTitle(char* iNewTitle); -Client::Client(EQStreamInterface* ieqs) -: Mob("No name", // name - "", // lastname - 0, // cur_hp - 0, // max_hp - 0, // gender - 0, // race - 0, // class - BT_Humanoid, // bodytype - 0, // deity - 0, // level - 0, // npctypeid - 0, // size - 0.7, // runspeed - glm::vec4(), - 0, // light - verified for client innate_light value - 0xFF, // texture - 0xFF, // helmtexture - 0, // ac - 0, // atk - 0, // str - 0, // sta - 0, // dex - 0, // agi - 0, // int - 0, // wis - 0, // cha - 0, // Luclin Hair Colour - 0, // Luclin Beard Color - 0, // Luclin Eye1 - 0, // Luclin Eye2 - 0, // Luclin Hair Style - 0, // Luclin Face - 0, // Luclin Beard - 0, // Drakkin Heritage - 0, // Drakkin Tattoo - 0, // Drakkin Details - EQ::TintProfile(), // Armor Tint - 0xff, // AA Title - 0, // see_invis - 0, // see_invis_undead - 0, - 0, - 0, - 0, - 0, // qglobal - 0, // maxlevel - 0, // scalerate - 0, - 0, - 0, - 0, - 0, - 0, - false - ), +Client::Client(EQStreamInterface *ieqs) : Mob( + "No name", // in_name + "", // in_lastname + 0, // in_cur_hp + 0, // in_max_hp + 0, // in_gender + 0, // in_race + 0, // in_class + BT_Humanoid, // in_bodytype + 0, // in_deity + 0, // in_level + 0, // in_npctype_id + 0.0f, // in_size + 0.7f, // in_runspeed + glm::vec4(), // position + 0, // in_light + 0xFF, // in_texture + 0xFF, // in_helmtexture + 0, // in_ac + 0, // in_atk + 0, // in_str + 0, // in_sta + 0, // in_dex + 0, // in_agi + 0, // in_int + 0, // in_wis + 0, // in_cha + 0, // in_haircolor + 0, // in_beardcolor + 0, // in_eyecolor1 + 0, // in_eyecolor2 + 0, // in_hairstyle + 0, // in_luclinface + 0, // in_beard + 0, // in_drakkin_heritage + 0, // in_drakkin_tattoo + 0, // in_drakkin_details + EQ::TintProfile(), // in_armor_tint + 0xff, // in_aa_title + 0, // in_see_invis + 0, // in_see_invis_undead + 0, // in_see_hide + 0, // in_see_improved_hide + 0, // in_hp_regen + 0, // in_mana_regen + 0, // in_qglobal + 0, // in_maxlevel + 0, // in_scalerate + 0, // in_armtexture + 0, // in_bracertexture + 0, // in_handtexture + 0, // in_legtexture + 0, // in_feettexture + 0, // in_usemodel + false, // in_always_aggros_foes + 0, // in_heroic_strikethrough + false // in_keeps_sold_items +), hpupdate_timer(2000), camp_timer(29000), process_timer(100), @@ -220,6 +223,7 @@ Client::Client(EQStreamInterface* ieqs) LFGComments[0] = '\0'; LFP = false; gmspeed = 0; + gminvul = false; playeraction = 0; SetTarget(0); auto_attack = false; @@ -228,8 +232,9 @@ Client::Client(EQStreamInterface* ieqs) linkdead_timer.Disable(); zonesummon_id = 0; zonesummon_ignorerestrictions = 0; - bZoning = false; - zone_mode = ZoneUnsolicited; + bZoning = false; + m_lock_save_position = false; + zone_mode = ZoneUnsolicited; casting_spell_id = 0; npcflag = false; npclevel = 0; @@ -282,11 +287,9 @@ Client::Client(EQStreamInterface* ieqs) if (!RuleB(Character, PerCharacterQglobalMaxLevel) && !RuleB(Character, PerCharacterBucketMaxLevel)) { SetClientMaxLevel(0); } else if (RuleB(Character, PerCharacterQglobalMaxLevel)) { - int client_max_level = GetCharMaxLevelFromQGlobal(); - SetClientMaxLevel(client_max_level); + SetClientMaxLevel(GetCharMaxLevelFromQGlobal()); } else if (RuleB(Character, PerCharacterBucketMaxLevel)) { - int client_max_level = GetCharMaxLevelFromBucket(); - SetClientMaxLevel(client_max_level); + SetClientMaxLevel(GetCharMaxLevelFromBucket()); } KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS)); @@ -351,7 +354,8 @@ Client::Client(EQStreamInterface* ieqs) m_pp.InnateSkills[i] = InnateDisabled; temp_pvp = false; - is_client_moving = false; + + moving = false; environment_damage_modifier = 0; invulnerable_environment_damage = false; @@ -363,7 +367,6 @@ Client::Client(EQStreamInterface* ieqs) SetDisplayMobInfoWindow(true); SetDevToolsEnabled(true); -#ifdef BOTS bot_owner_options[booDeathMarquee] = false; bot_owner_options[booStatsUpdate] = false; bot_owner_options[booSpawnMessageSay] = false; @@ -376,7 +379,6 @@ Client::Client(EQStreamInterface* ieqs) SetBotPulling(false); SetBotPrecombat(false); -#endif AI_Init(); } @@ -384,9 +386,10 @@ Client::Client(EQStreamInterface* ieqs) Client::~Client() { mMovementManager->RemoveClient(this); -#ifdef BOTS - Bot::ProcessBotOwnerRefDelete(this); -#endif + if (RuleB(Bots, Enabled)) { + Bot::ProcessBotOwnerRefDelete(this); + } + if(IsInAGuild()) guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr)); @@ -631,22 +634,31 @@ bool Client::Save(uint8 iCommitNow) { return false; /* Wrote current basics to PP for saves */ - m_pp.x = m_Position.x; - m_pp.y = m_Position.y; - m_pp.z = m_Position.z; + if (!m_lock_save_position) { + m_pp.x = m_Position.x; + m_pp.y = m_Position.y; + m_pp.z = m_Position.z; + m_pp.heading = m_Position.w; + } + m_pp.guildrank = guildrank; - m_pp.heading = m_Position.w; - /* Mana and HP */ - if (GetHP() <= 0) { + if (dead && GetHP() <= 0) { m_pp.cur_hp = GetMaxHP(); - } - else { - m_pp.cur_hp = GetHP(); - } + m_pp.mana = current_mana; + if (RuleB(Character, FullManaOnDeath)) { + m_pp.mana = GetMaxMana(); + } - m_pp.mana = current_mana; - m_pp.endurance = current_endurance; + m_pp.endurance = current_endurance; + if (RuleB(Character, FullEndurOnDeath)) { + m_pp.endurance = GetMaxEndurance(); + } + } else { // Otherwise, no changes. + m_pp.cur_hp = GetHP(); + m_pp.mana = current_mana; + m_pp.endurance = current_endurance; + } /* Save Character Currency */ database.SaveCharacterCurrency(CharacterID(), &m_pp); @@ -723,7 +735,7 @@ bool Client::Save(uint8 iCommitNow) { } } - database.SaveCharacterData(CharacterID(), AccountID(), &m_pp, &m_epp); /* Save Character Data */ + database.SaveCharacterData(this, &m_pp, &m_epp); /* Save Character Data */ return true; } @@ -785,7 +797,6 @@ bool Client::SendAllPackets() { if(eqs) eqs->FastQueuePacket((EQApplicationPacket **)&cp->app, cp->ack_req); clientpackets.pop_front(); - Log(Logs::Moderate, Logs::PacketClientServer, "Transmitting a packet"); } return true; } @@ -829,7 +840,7 @@ void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CON return; } -void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname) { +void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname, bool is_silent) { char message[4096]; strn0cpy(message, orig_message, sizeof(message)); @@ -1111,8 +1122,8 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s break; } case ChatChannel_Say: { /* Say */ - if(message[0] == COMMAND_CHAR) { - if(command_dispatch(this, message) == -2) { + if (message[0] == COMMAND_CHAR) { + if (command_dispatch(this, message, false) == -2) { if (parse->PlayerHasQuestSub(EVENT_COMMAND)) { int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0); if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) { @@ -1134,72 +1145,92 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s break; } -#ifdef BOTS if (message[0] == BOT_COMMAND_CHAR) { - if (bot_command_dispatch(this, message) == -2) { - if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) { - int i = parse->EventPlayer(EVENT_BOT_COMMAND, this, message, 0); - if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) { - Message(Chat::Red, "Bot command '%s' not recognized.", message); - } - } - else if (parse->PlayerHasQuestSub(EVENT_SAY)) { - int i = parse->EventPlayer(EVENT_SAY, this, message, 0); - if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) { - Message(Chat::Red, "Bot command '%s' not recognized.", message); - } - } - else { - if (!RuleB(Chat, SuppressCommandErrors)) { - Message(Chat::Red, "Bot command '%s' not recognized.", message); + if (RuleB(Bots, Enabled)) { + if (bot_command_dispatch(this, message) == -2) { + if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) { + int i = parse->EventPlayer(EVENT_BOT_COMMAND, this, message, 0); + if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) { + Message(Chat::Red, "Bot command '%s' not recognized.", message); + } + } + else if (parse->PlayerHasQuestSub(EVENT_SAY)) { + int i = parse->EventPlayer(EVENT_SAY, this, message, 0); + if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) { + Message(Chat::Red, "Bot command '%s' not recognized.", message); + } + } + else { + if (!RuleB(Chat, SuppressCommandErrors)) { + Message(Chat::Red, "Bot command '%s' not recognized.", message); + } } } + } else { + Message(Chat::Red, "Bots are disabled on this server."); } break; } -#endif if (EQ::ProfanityManager::IsCensorshipActive()) { EQ::ProfanityManager::RedactMessage(message); } Mob* sender = this; - if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) { sender = GetPet(); + } + + if (!is_silent) { + entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); + } - entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); parse->EventPlayer(EVENT_SAY, this, message, language); - if (sender != this) + if (sender != this) { break; + } - if(quest_manager.ProximitySayInUse()) + if (quest_manager.ProximitySayInUse()) { entity_list.ProcessProximitySay(message, this, language); + } - if (GetTarget() != 0 && GetTarget()->IsNPC() && - !IsInvisible(GetTarget())) { - if(!GetTarget()->CastToNPC()->IsEngaged()) { - CheckLDoNHail(GetTarget()); - CheckEmoteHail(GetTarget(), message); + if ( + GetTarget() && + GetTarget()->IsNPC() && + !IsInvisible(GetTarget()) + ) { + auto* t = GetTarget()->CastToNPC(); + if (!t->IsEngaged()) { + CheckLDoNHail(t); + CheckEmoteHail(t, message); - if(DistanceNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) { - NPC *tar = GetTarget()->CastToNPC(); - parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language); + if (DistanceNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)) { - if(RuleB(TaskSystem, EnableTaskSystem)) { - if(UpdateTasksOnSpeakWith(tar->GetNPCTypeID())) { - tar->DoQuestPause(this); + parse->EventNPC(EVENT_SAY, t, this, message, language); + + if (RuleB(TaskSystem, EnableTaskSystem)) { + if (UpdateTasksOnSpeakWith(t)) { + t->DoQuestPause(this); } } } - } - else { - if (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) { - parse->EventNPC(EVENT_AGGRO_SAY, GetTarget()->CastToNPC(), this, message, language); + } else { + if (DistanceSquaredNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)) { + parse->EventNPC(EVENT_AGGRO_SAY, t, this, message, language); } } } + else if (GetTarget() && GetTarget()->IsBot() && !IsInvisible(GetTarget())) { + if (DistanceNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) { + if (GetTarget()->IsEngaged()) { + parse->EventBot(EVENT_AGGRO_SAY, GetTarget()->CastToBot(), this, message, language); + } else { + parse->EventBot(EVENT_SAY, GetTarget()->CastToBot(), this, message, language); + } + } + } break; } case ChatChannel_UCSRelay: @@ -1293,7 +1324,7 @@ void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num if (senderCanTrainSelf || weAreNotSender) { if ((chan_num == ChatChannel_Group) && (ListenerSkill < 100)) { // group message in unmastered language, check for skill up - if (m_pp.languages[language] <= lang_skill) + if (language < MAX_PP_LANGUAGE && m_pp.languages[language] <= lang_skill) CheckLanguageSkillIncrease(language, lang_skill); } } @@ -1655,19 +1686,18 @@ void Client::FriendsWho(char *FriendsString) { } } -void Client::UpdateAdmin(bool iFromDB) { +void Client::UpdateAdmin(bool from_database) { int16 tmp = admin; - if (iFromDB) + if (from_database) { admin = database.CheckStatus(account_id); - if (tmp == admin && iFromDB) - return; + } - if(m_pp.gm) - { + if (tmp == admin && from_database) { + return; + } + + if (m_pp.gm) { LogInfo("[{}] - [{}] is a GM", __FUNCTION__ , GetName()); -// no need for this, having it set in pp you already start as gm -// and it's also set in your spawn packet so other people see it too -// SendAppearancePacket(AT_GM, 1, false); petition_list.UpdateGMQueue(); } @@ -2020,20 +2050,22 @@ void Client::Sit() { SetAppearance(eaSitting, false); } -void Client::ChangeLastName(const char* in_lastname) { +void Client::ChangeLastName(std::string last_name) { memset(m_pp.last_name, 0, sizeof(m_pp.last_name)); - strn0cpy(m_pp.last_name, in_lastname, sizeof(m_pp.last_name)); + strn0cpy(m_pp.last_name, last_name.c_str(), sizeof(m_pp.last_name)); auto outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); - GMLastName_Struct* gmn = (GMLastName_Struct*)outapp->pBuffer; - strcpy(gmn->name, name); - strcpy(gmn->gmname, name); - strcpy(gmn->lastname, in_lastname); - gmn->unknown[0]=1; - gmn->unknown[1]=1; - gmn->unknown[2]=1; - gmn->unknown[3]=1; + auto gmn = (GMLastName_Struct*) outapp->pBuffer; + strn0cpy(gmn->name, name, sizeof(gmn->name)); + strn0cpy(gmn->gmname, name, sizeof(gmn->gmname)); + strn0cpy(gmn->lastname, last_name.c_str(), sizeof(gmn->lastname)); + + gmn->unknown[0] = 1; + gmn->unknown[1] = 1; + gmn->unknown[2] = 1; + gmn->unknown[3] = 1; + entity_list.QueueClients(this, outapp, false); - // Send name update packet here... once know what it is + safe_delete(outapp); } @@ -3145,10 +3177,9 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ if (ClientVersionBit() & EQ::versions::maskSoDAndLater) { if (filter->filters[FilterHealOverTime] == 0) ClientFilters[FilterHealOverTime] = FilterShow; - // This is called 'Show Mine Only' in the clients, but functions the same as show - // so instead of apply special logic, just set to show + // This is called 'Show Mine Only' in the clients else if (filter->filters[FilterHealOverTime] == 1) - ClientFilters[FilterHealOverTime] = FilterShow; + ClientFilters[FilterHealOverTime] = FilterShowSelfOnly; else ClientFilters[FilterHealOverTime] = FilterHide; } else { @@ -3199,6 +3230,8 @@ void Client::MessageString(uint32 type, uint32 string_id, const char* message1, return; if (GetFilter(FilterDamageShields) == FilterHide && type == Chat::DamageShield) return; + if (GetFilter(FilterFocusEffects) == FilterHide && type == Chat::FocusEffect) + return; if (type == Chat::Emote) type = 4; @@ -3264,14 +3297,12 @@ bool Client::FilteredMessageCheck(Mob *sender, eqFilterType filter) else if (mode == FilterHide) return false; - if (!sender && mode == FilterHide) { + if (sender != this && (mode == FilterHide || mode == FilterShowSelfOnly)) { return false; } else if (sender) { if (this == sender) { if (mode == FilterHide) // don't need to check others return false; - } else if (mode == FilterShowSelfOnly) { // we know sender isn't us - return false; } else if (mode == FilterShowGroupOnly) { Group *g = GetGroup(); Raid *r = GetRaid(); @@ -3383,21 +3414,23 @@ void Client::SetHideMe(bool flag) gm_hide_me = flag; - if(gm_hide_me) - { - database.SetHideMe(AccountID(),true); + if (gm_hide_me) { + database.SetHideMe(AccountID(), true); CreateDespawnPacket(&app, false); entity_list.RemoveFromTargets(this); trackable = false; - } - else - { - database.SetHideMe(AccountID(),false); + if (RuleB(Command, HideMeCommandDisablesTells)) { + tellsoff = true; + } + } else { + database.SetHideMe(AccountID(), false); CreateSpawnPacket(&app); trackable = true; + tellsoff = false; } - entity_list.QueueClientsStatus(this, &app, true, 0, Admin()-1); + entity_list.QueueClientsStatus(this, &app, true, 0, Admin() - 1); + UpdateWho(); } void Client::SetLanguageSkill(int langid, int value) @@ -3557,336 +3590,6 @@ float Client::CalcPriceMod(Mob* other, bool reverse) return chaformula; //Returns 1.10, expensive stuff! } -//neat idea from winter's roar, not implemented -void Client::Insight(uint32 t_id) -{ - Mob* who = entity_list.GetMob(t_id); - if (!who) - return; - if (!who->IsNPC()) - { - Message(0,"This ability can only be used on NPCs."); - return; - } - if (Distance(static_cast(m_Position), static_cast(who->GetPosition())) > 200) - { - Message(0,"You must get closer to your target!"); - return; - } - if (!CheckLosFN(who)) - { - Message(0,"You must be able to see your target!"); - return; - } - char hitpoints[64]; - char resists[320]; - char dmg[64]; - memset(hitpoints,0,sizeof(hitpoints)); - memset(resists,0,sizeof(resists)); - memset(dmg,0,sizeof(dmg)); - //Start with HP blah - int avg_hp = GetLevelHP(who->GetLevel()); - int cur_hp = who->GetHP(); - if (cur_hp == avg_hp) - { - strn0cpy(hitpoints,"averagely tough",32); - } - else if (cur_hp >= avg_hp*5) - { - strn0cpy(hitpoints,"extremely tough",32); - } - else if (cur_hp >= avg_hp*4) - { - strn0cpy(hitpoints,"exceptionally tough",32); - } - else if (cur_hp >= avg_hp*3) - { - strn0cpy(hitpoints,"very tough",32); - } - else if (cur_hp >= avg_hp*2) - { - strn0cpy(hitpoints,"quite tough",32); - } - else if (cur_hp >= avg_hp*1.25) - { - strn0cpy(hitpoints,"rather tough",32); - } - else if (cur_hp > avg_hp) - { - strn0cpy(hitpoints,"slightly tough",32); - } - else if (cur_hp <= avg_hp*0.20) - { - strn0cpy(hitpoints,"extremely frail",32); - } - else if (cur_hp <= avg_hp*0.25) - { - strn0cpy(hitpoints,"exceptionally frail",32); - } - else if (cur_hp <= avg_hp*0.33) - { - strn0cpy(hitpoints,"very frail",32); - } - else if (cur_hp <= avg_hp*0.50) - { - strn0cpy(hitpoints,"quite frail",32); - } - else if (cur_hp <= avg_hp*0.75) - { - strn0cpy(hitpoints,"rather frail",32); - } - else if (cur_hp < avg_hp) - { - strn0cpy(hitpoints,"slightly frail",32); - } - - int avg_dmg = who->CastToNPC()->GetMaxDamage(who->GetLevel()); - int cur_dmg = who->CastToNPC()->GetMaxDMG(); - if (cur_dmg == avg_dmg) - { - strn0cpy(dmg,"averagely strong",32); - } - else if (cur_dmg >= avg_dmg*4) - { - strn0cpy(dmg,"extremely strong",32); - } - else if (cur_dmg >= avg_dmg*3) - { - strn0cpy(dmg,"exceptionally strong",32); - } - else if (cur_dmg >= avg_dmg*2) - { - strn0cpy(dmg,"very strong",32); - } - else if (cur_dmg >= avg_dmg*1.25) - { - strn0cpy(dmg,"quite strong",32); - } - else if (cur_dmg >= avg_dmg*1.10) - { - strn0cpy(dmg,"rather strong",32); - } - else if (cur_dmg > avg_dmg) - { - strn0cpy(dmg,"slightly strong",32); - } - else if (cur_dmg <= avg_dmg*0.20) - { - strn0cpy(dmg,"extremely weak",32); - } - else if (cur_dmg <= avg_dmg*0.25) - { - strn0cpy(dmg,"exceptionally weak",32); - } - else if (cur_dmg <= avg_dmg*0.33) - { - strn0cpy(dmg,"very weak",32); - } - else if (cur_dmg <= avg_dmg*0.50) - { - strn0cpy(dmg,"quite weak",32); - } - else if (cur_dmg <= avg_dmg*0.75) - { - strn0cpy(dmg,"rather weak",32); - } - else if (cur_dmg < avg_dmg) - { - strn0cpy(dmg,"slightly weak",32); - } - - //Resists - int res; - int i = 1; - - //MR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to magic, "); - - //FR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to fire, "); - - //CR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to cold, "); - - //PR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to poison, and "); - - //MR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to disease."); - - Message(0,"Your target is a level %i %s. It appears %s and %s for its level. It seems %s",who->GetLevel(),GetClassIDName(who->GetClass(),1),dmg,hitpoints,resists); -} - void Client::GetGroupAAs(GroupLeadershipAA_Struct *into) const { memcpy(into, &m_pp.leader_abilities.group, sizeof(GroupLeadershipAA_Struct)); } @@ -3901,9 +3604,8 @@ void Client::EnteringMessages(Client* client) if (database.GetVariable("Rules", rules)) { uint8 flag = database.GetAgreementFlag(client->AccountID()); if (!flag) { - auto rules_link = EQ::SayLinkEngine::GenerateQuestSaylink( + auto rules_link = Saylink::Silent( "#serverrules", - false, "rules" ); @@ -3928,7 +3630,7 @@ void Client::SendRules() return; } - auto lines = split_string(rules, "|"); + auto lines = Strings::Split(rules, "|"); auto line_number = 1; for (auto&& line : lines) { Message( @@ -4383,7 +4085,7 @@ void Client::UpdateLFP() { for(unsigned int i=0; iGetSpecialAbility(IMMUNE_OPEN)) + { + LogDebug("[{}] tried to open [{}] but it was immune", GetName(), target->GetName()); + return; + } + if(DistanceSquaredNoZ(m_Position, target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { LogDebug("[{}] tried to open [{}] but [{}] was out of range", @@ -5362,14 +5070,13 @@ void Client::SetStartZone(uint32 zoneid, float x, float y, float z, float headin } if (x == 0 && y == 0 && z == 0) { - content_db.GetSafePoints( - ZoneName(m_pp.binds[4].zone_id), - 0, - &m_pp.binds[4].x, - &m_pp.binds[4].y, - &m_pp.binds[4].z, - &m_pp.binds[4].heading - ); + auto zd = GetZone(m_pp.binds[4].zone_id); + if (zd) { + m_pp.binds[4].x = zd->safe_x; + m_pp.binds[4].y = zd->safe_y; + m_pp.binds[4].z = zd->safe_z; + m_pp.binds[4].heading = zd->safe_heading; + } } else { m_pp.binds[4].x = x; @@ -5454,12 +5161,18 @@ void Client::ShowSkillsWindow() ); } -void Client::Signal(uint32 data) +void Client::Signal(int signal_id) { - std::string export_string = fmt::format("{}", data); + const auto export_string = fmt::format("{}", signal_id); parse->EventPlayer(EVENT_SIGNAL, this, export_string, 0); } +void Client::SendPayload(int payload_id, std::string payload_value) +{ + const auto export_string = fmt::format("{} {}", payload_id, payload_value); + parse->EventPlayer(EVENT_PAYLOAD, this, export_string, 0); +} + void Client::SendRewards() { std::vector rewards; @@ -5531,7 +5244,6 @@ bool Client::TryReward(uint32 claim_id) if (free_slot == 0xFFFFFFFF) return false; - char errbuf[MYSQL_ERRMSG_SIZE]; std::string query = StringFormat("SELECT amount FROM account_rewards " "WHERE account_id = %i AND reward_id = %i", AccountID(), claim_id); @@ -6232,9 +5944,9 @@ void Client::CheckEmoteHail(Mob *target, const char* message) { return; } - uint16 emoteid = target->GetEmoteID(); + uint32 emoteid = target->GetEmoteID(); if(emoteid != 0) - target->CastToNPC()->DoNPCEmote(HAILED,emoteid); + target->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emoteid); } void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count) @@ -6338,7 +6050,7 @@ void Client::NPCSpawn(NPC *target_npc, const char *identifier, uint32 extra) return; } - std::string spawn_type = str_tolower(identifier); + std::string spawn_type = Strings::ToLower(identifier); bool is_add = spawn_type.find("add") != std::string::npos; bool is_create = spawn_type.find("create") != std::string::npos; bool is_delete = spawn_type.find("delete") != std::string::npos; @@ -6518,10 +6230,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid } made_npc->loottable_id = 0; - npc_type = made_npc; - - int summon_count = 0; - summon_count = pet.count; + int summon_count = pet.count; if(summon_count > MAX_SWARM_PETS) summon_count = MAX_SWARM_PETS; @@ -6533,16 +6242,13 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid }; while(summon_count > 0) { - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } + auto npc_type_copy = new NPCType; + memcpy(npc_type_copy, made_npc, sizeof(NPCType)); NPC* swarm_pet_npc = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer + npc_type_copy, 0, - GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), + GetPosition() + glm::vec4(swarmPetLocations[summon_count - 1], 0.0f, 0.0f), GravityBehavior::Water); if(!swarm_pet_npc->GetSwarmInfo()){ @@ -6565,12 +6271,13 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid swarm_pet_npc->GetSwarmInfo()->target = 0; //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - swarm_pet_npc->GiveNPCTypeData(npc_dup); + swarm_pet_npc->GiveNPCTypeData(npc_type_copy); entity_list.AddNPC(swarm_pet_npc); summon_count--; } + + safe_delete(made_npc); } void Client::AssignToInstance(uint16 instance_id) @@ -7097,11 +6804,12 @@ void Client::SendStatsWindow(Client* client, bool use_window) client->Message(Chat::White, " compute_tohit: %i TotalToHit: %i", compute_tohit(skill), GetTotalToHit(skill, 0)); client->Message(Chat::White, " compute_defense: %i TotalDefense: %i", compute_defense(), GetTotalDefense()); client->Message(Chat::White, " offense: %i mitigation ac: %i", offense(skill), GetMitigationAC()); + client->Message(Chat::White, " AFK: %i LFG: %i Anon: %i PVP: %i GM: %i Flymode: %i GMSpeed: %i Hideme: %i GMInvul: %d LD: %i ClientVersion: %i TellsOff: %i", AFK, LFG, GetAnon(), GetPVP(), GetGM(), flymode, GetGMSpeed(), GetHideMe(), GetGMInvul(), IsLD(), ClientVersionBit(), tellsoff); if(CalcMaxMana() > 0) client->Message(Chat::White, " Mana: %i/%i Mana Regen: %i/%i", GetMana(), GetMaxMana(), CalcManaRegen(), CalcManaRegenCap()); client->Message(Chat::White, " End.: %i/%i End. Regen: %i/%i",GetEndurance(), GetMaxEndurance(), CalcEnduranceRegen(), CalcEnduranceRegenCap()); client->Message(Chat::White, " ATK: %i Worn/Spell ATK %i/%i Server Side ATK: %i", GetTotalATK(), RuleI(Character, ItemATKCap), GetATKBonus(), GetATK()); - client->Message(Chat::White, " Haste: %i / %i (Item: %i + Spell: %i + Over: %i)", GetHaste(), RuleI(Character, HasteCap), itembonuses.haste, spellbonuses.haste + spellbonuses.hastetype2, spellbonuses.hastetype3 + ExtraHaste); + client->Message(Chat::White, " Haste: %i / %i (Item: %i + Spell: %i + Over: %i) Run speed: %i", GetHaste(), RuleI(Character, HasteCap), itembonuses.haste, spellbonuses.haste + spellbonuses.hastetype2, spellbonuses.hastetype3 + ExtraHaste, GetRunspeed()); client->Message(Chat::White, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); client->Message(Chat::White, " hSTR: %i hSTA: %i hDEX: %i hAGI: %i hINT: %i hWIS: %i hCHA: %i", GetHeroicSTR(), GetHeroicSTA(), GetHeroicDEX(), GetHeroicAGI(), GetHeroicINT(), GetHeroicWIS(), GetHeroicCHA()); client->Message(Chat::White, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i PhR: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup(), GetPhR()); @@ -7472,21 +7180,53 @@ void Client::RemoveAutoXTargets() void Client::ShowXTargets(Client *c) { - if(!c) + if (!c) { return; + } + + auto xtarget_count = 0; + + for (int i = 0; i < GetMaxXTargets(); ++i) { + c->Message( + Chat::White, + fmt::format( + "xtarget slot [{}] type [{}] ID [{}] name [{}]", + i, + XTargets[i].Type, + XTargets[i].ID, + strlen(XTargets[i].Name) ? XTargets[i].Name : "No Name" + ).c_str() + ); + + xtarget_count++; + } - for(int i = 0; i < GetMaxXTargets(); ++i) - c->Message(Chat::White, "Xtarget Slot: %i, Type: %2i, ID: %4i, Name: %s", i, XTargets[i].Type, XTargets[i].ID, XTargets[i].Name); auto &list = GetXTargetAutoMgr()->get_list(); // yeah, I kept having to do something for debugging to tell if managers were the same object or not :P // so lets use the address as an "ID" - c->Message(Chat::White, "XTargetAutoMgr ID %p size %d", GetXTargetAutoMgr(), list.size()); + c->Message( + Chat::White, + fmt::format( + "XTargetAutoMgr ID [{}] size [{}]", + fmt::ptr(GetXTargetAutoMgr()), + list.size() + ).c_str() + ); + int count = 0; for (auto &e : list) { - c->Message(Chat::White, "spawn id %d count %d", e.spawn_id, e.count); + c->Message( + Chat::White, + fmt::format( + "Spawn ID: {} Count: {}", + e.spawn_id, + e.count + ).c_str() + ); + count++; - if (count == 20) { // lets not spam too many ... - c->Message(Chat::White, " ... "); + + if (count == 20) { break; } } @@ -7872,13 +7612,9 @@ void Client::GarbleMessage(char *message, uint8 variance) int delimiter_count = 0; // Don't garble # commands - if (message[0] == COMMAND_CHAR) + if (message[0] == COMMAND_CHAR || message[0] == BOT_COMMAND_CHAR) { return; - -#ifdef BOTS - if (message[0] == BOT_COMMAND_CHAR) - return; -#endif + } for (size_t i = 0; i < strlen(message); i++) { // Client expects hex values inside of a text link body @@ -7997,7 +7733,6 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui for (int i = 0; i < MAX_NPC_FACTIONS; i++) { int32 faction_before_hit; - int32 faction_to_use_for_messaging; FactionMods fm; int32 this_faction_max; int32 this_faction_min; @@ -8626,14 +8361,35 @@ void Client::Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto } } -void Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg) +void Client::SendMarqueeMessage(uint32 type, std::string message, uint32 duration) { - if(duration == 0 || msg.length() == 0) { + if (!duration || !message.length()) { return; } - EQApplicationPacket outapp(OP_Marquee, sizeof(ClientMarqueeMessage_Struct) + msg.length()); - ClientMarqueeMessage_Struct *cms = (ClientMarqueeMessage_Struct*)outapp.pBuffer; + EQApplicationPacket outapp(OP_Marquee, sizeof(ClientMarqueeMessage_Struct) + message.length()); + ClientMarqueeMessage_Struct* cms = (ClientMarqueeMessage_Struct*) outapp.pBuffer; + + cms->type = type; + cms->unk04 = 10; + cms->priority = 510; + cms->fade_in_time = 0; + cms->fade_out_time = 3000; + cms->duration = duration; + + strcpy(cms->msg, message.c_str()); + + QueuePacket(&outapp); +} + +void Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) +{ + if (!duration || !message.length()) { + return; + } + + EQApplicationPacket outapp(OP_Marquee, sizeof(ClientMarqueeMessage_Struct) + message.length()); + ClientMarqueeMessage_Struct* cms = (ClientMarqueeMessage_Struct*) outapp.pBuffer; cms->type = type; cms->unk04 = 10; @@ -8641,7 +8397,8 @@ void Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, ui cms->fade_in_time = fade_in; cms->fade_out_time = fade_out; cms->duration = duration; - strcpy(cms->msg, msg.c_str()); + + strcpy(cms->msg, message.c_str()); QueuePacket(&outapp); } @@ -8758,7 +8515,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, int32 nfl_id = target->CastToNPC()->GetNPCFactionID(); SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true); qr->faction = target->CastToNPC()->GetPrimaryFaction(); - qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow. + qr->faction_mod = 1; // Too lazy to get real value, not even used by client anyhow. } } @@ -8778,15 +8535,21 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac memcpy(qr, &reward, sizeof(QuestReward_Struct)); // not set in caller because reasons - qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name + qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name, tasks won't set this if (reward.copper > 0 || reward.silver > 0 || reward.gold > 0 || reward.platinum > 0) AddMoneyToPP(reward.copper, reward.silver, reward.gold, reward.platinum); for (int i = 0; i < QUESTREWARD_COUNT; ++i) if (reward.item_id[i] > 0) - SummonItem(reward.item_id[i], 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor); + SummonItem(reward.item_id[i], -1, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor); + // only process if both are valid + // if we don't have a target here, we want to just reward, but if there is a target, need to check charm + if (reward.faction && reward.faction_mod && (target == nullptr || !target->IsCharmed())) + RewardFaction(reward.faction, reward.faction_mod); + + // legacy support if (faction) { if (target && target->IsNPC() && !target->IsCharmed()) @@ -8794,17 +8557,61 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac int32 nfl_id = target->CastToNPC()->GetNPCFactionID(); SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true); qr->faction = target->CastToNPC()->GetPrimaryFaction(); - qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow. + qr->faction_mod = 1; // Too lazy to get real value, not even used by client anyhow. } } - if (reward.exp_reward> 0) + if (reward.exp_reward > 0) AddEXP(reward.exp_reward); QueuePacket(outapp, true, Client::CLIENT_CONNECTED); safe_delete(outapp); } +void Client::CashReward(uint32 copper, uint32 silver, uint32 gold, uint32 platinum) +{ + auto outapp = std::make_unique(OP_CashReward, sizeof(CashReward_Struct)); + auto outbuf = reinterpret_cast(outapp->pBuffer); + outbuf->copper = copper; + outbuf->silver = silver; + outbuf->gold = gold; + outbuf->platinum = platinum; + + AddMoneyToPP(copper, silver, gold, platinum); + + QueuePacket(outapp.get()); +} + +void Client::RewardFaction(int id, int amount) +{ + // first we hit the primary faction, even without any associations + SetFactionLevel2(CharacterID(), id, GetClass(), GetBaseRace(), GetDeity(), amount, false); + + auto faction_assoc = content_db.GetFactionAssociationHit(id); + // We could log here, but since it's actually expected for some not to have entries, it would be noisy. + if (!faction_assoc) { + return; + } + + // now hit them in order + for (int i = 0; i < MAX_FACTION_ASSOC; ++i) { + if (faction_assoc->hits[i].id <= 0) // we don't allow later entries + break; + if (faction_assoc->hits[i].multiplier == 0.0f) { + LogFaction("Bad association multiplier for ID {} entry {}", id, i + 1); + continue; + } + + // value is truncated and min clamped to 1 (or -1) + float temp = faction_assoc->hits[i].multiplier * amount; + int sign = temp < 0.0f ? -1 : 1; + int32 new_amount = std::max(1, static_cast(std::abs(temp))) * sign; + + SetFactionLevel2(CharacterID(), faction_assoc->hits[i].id, GetClass(), GetBaseRace(), GetDeity(), + new_amount, false); + } +} + void Client::SendHPUpdateMarquee(){ if (!this || !IsClient() || !current_hp || !max_hp) return; @@ -9308,9 +9115,36 @@ bool Client::IsDevToolsEnabled() const void Client::SetDevToolsEnabled(bool in_dev_tools_enabled) { + const auto dev_tools_key = fmt::format("{}-dev-tools-disabled", AccountID()); + + if (in_dev_tools_enabled) { + DataBucket::DeleteData(dev_tools_key); + } else { + DataBucket::SetData(dev_tools_key, "true"); + } + Client::dev_tools_enabled = in_dev_tools_enabled; } +bool Client::IsEXPEnabled() const { + return m_exp_enabled; +} + +void Client::SetEXPEnabled(bool is_exp_enabled) +{ + auto c = CharacterDataRepository::FindOne(database, CharacterID()); + + c.exp_enabled = is_exp_enabled; + + auto updated = CharacterDataRepository::UpdateOne(database, c); + + if (!updated) { + return; + } + + m_exp_enabled = is_exp_enabled; +} + /** * @param model_id */ @@ -9364,44 +9198,22 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id) */ bool Client::GotoPlayer(std::string player_name) { - std::string query = StringFormat( - "SELECT" - " character_data.zone_id," - " character_data.zone_instance," - " character_data.x," - " character_data.y," - " character_data.z," - " character_data.heading " - "FROM" - " character_data " - "WHERE" - " TRUE" - " AND character_data.name = '%s'" - " AND character_data.last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name.c_str()); + auto characters = CharacterDataRepository::GetWhere( + database, + fmt::format("name = '{}' AND last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name) + ); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - auto zone_id = static_cast(atoi(row[0])); - auto instance_id = static_cast(atoi(row[1])); - auto x = static_cast(atof(row[2])); - auto y = static_cast(atof(row[3])); - auto z = static_cast(atof(row[4])); - auto heading = static_cast(atof(row[5])); - - if (instance_id > 0 && !database.CheckInstanceExists(instance_id)) { + for (auto &c: characters) { + if (c.zone_instance > 0 && !database.CheckInstanceExists(c.zone_instance)) { Message(Chat::Yellow, "Instance no longer exists..."); return false; } - if (instance_id > 0) { - database.AddClientToInstance(instance_id, CharacterID()); + if (c.zone_instance > 0) { + database.AddClientToInstance(c.zone_instance, CharacterID()); } - MovePC(zone_id, instance_id, x, y, z, heading); + MovePC(c.zone_id, c.zone_instance, c.x, c.y, c.z, c.heading); return true; } @@ -9409,6 +9221,42 @@ bool Client::GotoPlayer(std::string player_name) return false; } +bool Client::GotoPlayerGroup(const std::string& player_name) +{ + if (!GetGroup()) { + return GotoPlayer(player_name); + } + + for (auto &m: GetGroup()->members) { + if (m && m->IsClient()) { + auto c = m->CastToClient(); + if (!c->GotoPlayer(player_name)) { + return false; + } + } + } + + return true; +} + +bool Client::GotoPlayerRaid(const std::string& player_name) +{ + if (!GetRaid()) { + return GotoPlayer(player_name); + } + + for (auto &m: GetRaid()->members) { + if (m.member && m.member->IsClient()) { + auto c = m.member->CastToClient(); + if (!c->GotoPlayer(player_name)) { + return false; + } + } + } + + return true; +} + glm::vec4 &Client::GetLastPositionBeforeBulkUpdate() { return last_position_before_bulk_update; @@ -9422,26 +9270,6 @@ void Client::SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_b Client::last_position_before_bulk_update = in_last_position_before_bulk_update; } -#ifdef BOTS - -bool Client::GetBotOption(BotOwnerOption boo) const { - - if (boo < _booCount) { - return bot_owner_options[boo]; - } - - return false; -} - -void Client::SetBotOption(BotOwnerOption boo, bool flag) { - - if (boo < _booCount) { - bot_owner_options[boo] = flag; - } -} - -#endif - void Client::SendToGuildHall() { std::string zone_short_name = "guildhall"; @@ -9524,65 +9352,68 @@ void Client::ShowDevToolsMenu() std::string menu_reload_six; std::string menu_reload_seven; std::string menu_reload_eight; + std::string menu_reload_nine; std::string menu_toggle; /** * Search entity commands */ - menu_search += EQ::SayLinkEngine::GenerateQuestSaylink("#list corpses", false, "Corpses"); - menu_search += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#list doors", false, "Doors"); - menu_search += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#finditem", false, "Items"); - menu_search += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#list npcs", false, "NPC"); - menu_search += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#list objects", false, "Objects"); - menu_search += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#list players", false, "Players"); - menu_search += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#findzone", false, "Zones"); + menu_search += Saylink::Silent("#list corpses", "Corpses"); + menu_search += " | " + Saylink::Silent("#list doors", "Doors"); + menu_search += " | " + Saylink::Silent("#finditem", "Items"); + menu_search += " | " + Saylink::Silent("#list npcs", "NPC"); + menu_search += " | " + Saylink::Silent("#list objects", "Objects"); + menu_search += " | " + Saylink::Silent("#list players", "Players"); + menu_search += " | " + Saylink::Silent("#findzone", "Zones"); /** * Show */ - menu_show += EQ::SayLinkEngine::GenerateQuestSaylink("#showzonepoints", false, "Zone Points"); - menu_show += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#showzonegloballoot", false, "Zone Global Loot"); + menu_show += Saylink::Silent("#showzonepoints", "Zone Points"); + menu_show += " | " + Saylink::Silent("#showzonegloballoot", "Zone Global Loot"); /** * Reload */ - menu_reload_one += EQ::SayLinkEngine::GenerateQuestSaylink("#reload aa", false, "AAs"); - menu_reload_one += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload alternate_currencies", false, "Alternate Currencies"); - menu_reload_one += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload blocked_spells", false, "Blocked Spells"); - menu_reload_one += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload content_flags", false, "Content Flags"); + menu_reload_one += Saylink::Silent("#reload aa", "AAs"); + menu_reload_one += " | " + Saylink::Silent("#reload alternate_currencies", "Alternate Currencies"); + menu_reload_one += " | " + Saylink::Silent("#reload blocked_spells", "Blocked Spells"); - menu_reload_two += EQ::SayLinkEngine::GenerateQuestSaylink("#reload doors", false, "Doors"); - menu_reload_two += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload ground_spawns", false, "Ground Spawns"); + menu_reload_two += Saylink::Silent("#reload commands", "Commands"); + menu_reload_two += " | " + Saylink::Silent("#reload content_flags", "Content Flags"); - menu_reload_three += EQ::SayLinkEngine::GenerateQuestSaylink("#reload logs", false, "Level Based Experience Modifiers"); - menu_reload_three += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload logs", false, "Log Settings"); + menu_reload_three += Saylink::Silent("#reload doors", "Doors"); + menu_reload_three += " | " + Saylink::Silent("#reload ground_spawns", "Ground Spawns"); - menu_reload_four += EQ::SayLinkEngine::GenerateQuestSaylink("#reload merchants", false, "Merchants"); - menu_reload_four += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload npc_emotes", false, "NPC Emotes"); - menu_reload_four += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload objects", false, "Objects"); + menu_reload_four += Saylink::Silent("#reload logs", "Level Based Experience Modifiers"); + menu_reload_four += " | " + Saylink::Silent("#reload logs", "Log Settings"); - menu_reload_five += EQ::SayLinkEngine::GenerateQuestSaylink("#reload perl_export", false, "Perl Event Export Settings"); - menu_reload_five += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload quest", false, "Quests"); + menu_reload_five += Saylink::Silent("#reload merchants", "Merchants"); + menu_reload_five += " | " + Saylink::Silent("#reload npc_emotes", "NPC Emotes"); + menu_reload_five += " | " + Saylink::Silent("#reload objects", "Objects"); - menu_reload_six += EQ::SayLinkEngine::GenerateQuestSaylink("#reload rules", false, "Rules"); - menu_reload_six += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload static", false, "Static Zone Data"); - menu_reload_six += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload tasks", false, "Tasks"); - - menu_reload_seven += EQ::SayLinkEngine::GenerateQuestSaylink("#reload titles", false, "Titles"); - menu_reload_seven += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload traps 1", false, "Traps"); - menu_reload_seven += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload variables", false, "Variables"); - menu_reload_seven += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload veteran_rewards", false, "Veteran Rewards"); - - menu_reload_eight += EQ::SayLinkEngine::GenerateQuestSaylink("#reload world", false, "World"); - menu_reload_eight += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload zone", false, "Zone"); - menu_reload_eight += " | " + EQ::SayLinkEngine::GenerateQuestSaylink("#reload zone_points", false, "Zone Points"); + menu_reload_six += Saylink::Silent("#reload perl_export", "Perl Event Export Settings"); + menu_reload_six += " | " + Saylink::Silent("#reload quest", "Quests"); + + menu_reload_seven += Saylink::Silent("#reload rules", "Rules"); + menu_reload_seven += " | " + Saylink::Silent("#reload static", "Static Zone Data"); + menu_reload_seven += " | " + Saylink::Silent("#reload tasks", "Tasks"); + + menu_reload_eight += Saylink::Silent("#reload titles", "Titles"); + menu_reload_eight += " | " + Saylink::Silent("#reload traps 1", "Traps"); + menu_reload_eight += " | " + Saylink::Silent("#reload variables", "Variables"); + menu_reload_eight += " | " + Saylink::Silent("#reload veteran_rewards", "Veteran Rewards"); + + menu_reload_nine += Saylink::Silent("#reload world", "World"); + menu_reload_nine += " | " + Saylink::Silent("#reload zone", "Zone"); + menu_reload_nine += " | " + Saylink::Silent("#reload zone_points", "Zone Points"); /** * Show window status */ - menu_toggle = EQ::SayLinkEngine::GenerateQuestSaylink("#devtools enable", false, "Enable"); + menu_toggle = Saylink::Silent("#devtools enable", "Enable"); if (IsDevToolsEnabled()) { - menu_toggle = EQ::SayLinkEngine::GenerateQuestSaylink("#devtools disable", false, "Disable"); + menu_toggle = Saylink::Silent("#devtools disable", "Disable"); } /** @@ -9604,7 +9435,7 @@ void Client::ShowDevToolsMenu() Chat::White, fmt::format( "Show Menu | {}", - EQ::SayLinkEngine::GenerateQuestSaylink("#dev", false, "#dev") + Saylink::Silent("#dev") ).c_str() ); @@ -9696,12 +9527,16 @@ void Client::ShowDevToolsMenu() ).c_str() ); - auto help_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#help", - false, - "#help" + Message( + Chat::White, + fmt::format( + "Reload | {}", + menu_reload_nine + ).c_str() ); + auto help_link = Saylink::Silent("#help"); + Message( Chat::White, fmt::format( @@ -9833,6 +9668,19 @@ Expedition* Client::CreateExpedition( return Expedition::TryCreate(this, dz, disable_messages); } +Expedition* Client::CreateExpeditionFromTemplate(uint32_t dz_template_id) +{ + Expedition* expedition = nullptr; + auto it = zone->dz_template_cache.find(dz_template_id); + if (it != zone->dz_template_cache.end()) + { + DynamicZone dz(DynamicZoneType::Expedition); + dz.LoadTemplate(it->second); + expedition = Expedition::TryCreate(this, dz, false); + } + return expedition; +} + void Client::CreateTaskDynamicZone(int task_id, DynamicZone& dz_request) { if (task_state) @@ -10094,12 +9942,23 @@ void Client::SendDzCompassUpdate() // client may be associated with multiple dynamic zone compasses in this zone std::vector compass_entries; + // need to sort by local doorid in case multiple have same dz switch id (live only sends first) + // todo: just store zone's door list ordered and ditch this + std::vector switches; + switches.reserve(entity_list.GetDoorsList().size()); + for (const auto& door_pair : entity_list.GetDoorsList()) + { + switches.push_back(door_pair.second); + } + std::sort(switches.begin(), switches.end(), + [](Doors* lhs, Doors* rhs) { return lhs->GetDoorID() < rhs->GetDoorID(); }); + for (const auto& client_dz : GetDynamicZones()) { auto compass = client_dz->GetCompassLocation(); if (zone && zone->IsZone(compass.zone_id, 0)) { - DynamicZoneCompassEntry_Struct entry; + DynamicZoneCompassEntry_Struct entry{}; entry.dz_zone_id = client_dz->GetZoneID(); entry.dz_instance_id = client_dz->GetInstanceID(); entry.dz_type = static_cast(client_dz->GetType()); @@ -10109,12 +9968,36 @@ void Client::SendDzCompassUpdate() compass_entries.emplace_back(entry); } + + // if client has a dz with a switch id add compass to any switch locs that share it + if (client_dz->GetSwitchID() != 0) + { + // live only sends one if multiple in zone have the same switch id + auto it = std::find_if(switches.begin(), switches.end(), + [&](const auto& eqswitch) { + return eqswitch->GetDzSwitchID() == client_dz->GetSwitchID(); + }); + + if (it != switches.end()) + { + DynamicZoneCompassEntry_Struct entry{}; + entry.dz_zone_id = client_dz->GetZoneID(); + entry.dz_instance_id = client_dz->GetInstanceID(); + entry.dz_type = static_cast(client_dz->GetType()); + entry.dz_switch_id = client_dz->GetSwitchID(); + entry.x = (*it)->GetX(); + entry.y = (*it)->GetY(); + entry.z = (*it)->GetZ(); + + compass_entries.emplace_back(entry); + } + } } // compass set via MarkSingleCompassLocation() if (m_has_quest_compass) { - DynamicZoneCompassEntry_Struct entry; + DynamicZoneCompassEntry_Struct entry{}; entry.dz_zone_id = 0; entry.dz_instance_id = 0; entry.dz_type = 0; @@ -10244,6 +10127,27 @@ void Client::MovePCDynamicZone(uint32 zone_id, int zone_version, bool msg_if_inv } } +bool Client::TryMovePCDynamicZoneSwitch(int dz_switch_id) +{ + auto client_dzs = GetDynamicZones(); + + std::vector switch_dzs; + auto it = std::copy_if(client_dzs.begin(), client_dzs.end(), std::back_inserter(switch_dzs), + [&](const DynamicZone* dz) { return dz->GetSwitchID() == dz_switch_id; }); + + if (switch_dzs.size() == 1) + { + LogDynamicZonesDetail("Moving client [{}] to dz with switch id [{}]", GetName(), dz_switch_id); + switch_dzs.front()->MovePCInto(this, true); + } + else if (switch_dzs.size() > 1) + { + QueuePacket(CreateDzSwitchListPacket(switch_dzs).get()); + } + + return !switch_dzs.empty(); +} + std::unique_ptr Client::CreateDzSwitchListPacket( const std::vector& client_dzs) { @@ -10270,65 +10174,84 @@ void Client::MovePCDynamicZone(const std::string& zone_name, int zone_version, b MovePCDynamicZone(zone_id, zone_version, msg_if_invalid); } -void Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clipping) { +void Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls, bool calculate_speed) { BuffFadeByEffect(SE_Levitate); if (CheckLosFN(target_x, target_y, target_z, 6.0f) || ignore_los) { - auto outapp_fling = new EQApplicationPacket(OP_Fling, sizeof(fling_struct)); - fling_struct* flingTo = (fling_struct*)outapp_fling->pBuffer; - if(clipping) - flingTo->collision = 0; - else - flingTo->collision = -1; + auto p = new EQApplicationPacket(OP_Fling, sizeof(fling_struct)); + auto* f = (fling_struct*) p->pBuffer; - flingTo->travel_time = -1; - flingTo->unk3 = 1; - flingTo->disable_fall_damage = 1; - flingTo->speed_z = value; - flingTo->new_y = target_y; - flingTo->new_x = target_x; - flingTo->new_z = target_z; - outapp_fling->priority = 6; - FastQueuePacket(&outapp_fling); + if (!calculate_speed) { + f->speed_z = value; + } else { + auto speed = 1.0f; + const auto distance = CalculateDistance(target_x, target_y, target_z); + + auto z_diff = target_z - GetZ(); + if (z_diff != 0.0f) { + speed += std::abs(z_diff) / 12.0f; + } + + speed += distance / 200.0f; + + speed++; + + speed = std::abs(speed); + + f->speed_z = speed; + } + + f->collision = clip_through_walls ? 0 : -1; + f->travel_time = -1; + f->unk3 = 1; + f->disable_fall_damage = 1; + f->new_y = target_y; + f->new_x = target_x; + f->new_z = target_z; + p->priority = 6; + FastQueuePacket(&p); } } std::vector Client::GetLearnableDisciplines(uint8 min_level, uint8 max_level) { - bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals); - bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets); - bool SpellGlobalCheckResult = false; - bool SpellBucketCheckResult = false; std::vector learnable_disciplines; - for (int spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { - bool learnable = false; - if (!IsValidSpell(spell_id)) - continue; - if (!IsDiscipline(spell_id)) - continue; - if (spells[spell_id].classes[WARRIOR] == 0) - continue; - if (max_level > 0 && spells[spell_id].classes[m_pp.class_ - 1] > max_level) - continue; - if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) - continue; - if (spells[spell_id].skill == 52) - continue; - if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == 10) - continue; - if (HasDisciplineLearned(spell_id)) + for (uint16 spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { + bool learnable = true; + if (!IsValidSpell(spell_id)) { continue; + } - if (SpellGlobalRule) { - SpellGlobalCheckResult = SpellGlobalCheck(spell_id, CharacterID()); - if (SpellGlobalCheckResult) { - learnable = true; - } - } else if (SpellBucketRule) { - SpellBucketCheckResult = SpellBucketCheck(spell_id, CharacterID()); - if (SpellBucketCheckResult) { - learnable = true; - } - } else { - learnable = true; + if (!IsDiscipline(spell_id)) { + continue; + } + + if (spells[spell_id].classes[WARRIOR] == 0) { + continue; + } + + if (max_level && spells[spell_id].classes[m_pp.class_ - 1] > max_level) { + continue; + } + + if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) { + continue; + } + + if (spells[spell_id].skill == EQ::skills::SkillTigerClaw) { + continue; + } + + if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) { + continue; + } + + if (HasDisciplineLearned(spell_id)) { + continue; + } + + if (RuleB(Spells, EnableSpellGlobals) && !SpellGlobalCheck(spell_id, CharacterID())) { + learnable = false; + } else if (RuleB(Spells, EnableSpellBuckets) && !SpellBucketCheck(spell_id, CharacterID())) { + learnable = false; } if (learnable) { @@ -10359,45 +10282,70 @@ std::vector Client::GetMemmedSpells() { } std::vector Client::GetScribeableSpells(uint8 min_level, uint8 max_level) { - bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals); - bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets); - bool SpellGlobalCheckResult = false; - bool SpellBucketCheckResult = false; std::vector scribeable_spells; - for (int spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { - bool scribeable = false; - if (!IsValidSpell(spell_id)) - continue; - if (IsDiscipline(spell_id)) - continue; - if (spells[spell_id].classes[WARRIOR] == 0) - continue; - if (max_level > 0 && spells[spell_id].classes[m_pp.class_ - 1] > max_level) - continue; - if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) - continue; - if (spells[spell_id].skill == 52) - continue; - if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == 10) - continue; - if (HasSpellScribed(spell_id)) - continue; + std::unordered_map> spell_group_cache = LoadSpellGroupCache(min_level, max_level); - if (SpellGlobalRule) { - SpellGlobalCheckResult = SpellGlobalCheck(spell_id, CharacterID()); - if (SpellGlobalCheckResult) { - scribeable = true; - } - } else if (SpellBucketRule) { - SpellBucketCheckResult = SpellBucketCheck(spell_id, CharacterID()); - if (SpellBucketCheckResult) { - scribeable = true; - } - } else { - scribeable = true; + for (uint16 spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { + bool scribeable = true; + if (!IsValidSpell(spell_id)) { + continue; } - if (scribeable) { + if (IsDiscipline(spell_id)) { + continue; + } + + if (spells[spell_id].classes[WARRIOR] == 0) { + continue; + } + + if (max_level && spells[spell_id].classes[m_pp.class_ - 1] > max_level) { + continue; + } + + if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) { + continue; + } + + if (spells[spell_id].skill == EQ::skills::SkillTigerClaw) { + continue; + } + + if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) { + continue; + } + + if (HasSpellScribed(spell_id)) { + continue; + } + + if ( + RuleB(Spells, EnableSpellGlobals) && + !SpellGlobalCheck(spell_id, CharacterID()) + ) { + scribeable = false; + } else if ( + RuleB(Spells, EnableSpellBuckets) && + !SpellBucketCheck(spell_id, CharacterID()) + ) { + scribeable = false; + } + + if (spells[spell_id].spell_group) { + const auto& g = spell_group_cache.find(spells[spell_id].spell_group); + if (g != spell_group_cache.end()) { + for (const auto& s : g->second) { + if ( + EQ::ValueWithin(spells[s].classes[m_pp.class_ - 1], min_level, max_level) && + s == spell_id && + scribeable + ) { + scribeable_spells.push_back(spell_id); + } + continue; + } + } + } else if (scribeable) { scribeable_spells.push_back(spell_id); } } @@ -10406,7 +10354,7 @@ std::vector Client::GetScribeableSpells(uint8 min_level, uint8 max_level) { std::vector Client::GetScribedSpells() { std::vector scribed_spells; - for(int index = 0; index < EQ::spells::SPELLBOOK_SIZE; index++) { + for (int index = 0; index < EQ::spells::SPELLBOOK_SIZE; index++) { if (IsValidSpell(m_pp.spell_book[index])) { scribed_spells.push_back(m_pp.spell_book[index]); } @@ -10440,7 +10388,7 @@ void Client::SetAFK(uint8 afk_flag) { void Client::SendToInstance(std::string instance_type, std::string zone_short_name, uint32 instance_version, float x, float y, float z, float heading, std::string instance_identifier, uint32 duration) { uint32 zone_id = ZoneID(zone_short_name); - std::string current_instance_type = str_tolower(instance_type); + std::string current_instance_type = Strings::ToLower(instance_type); std::string instance_type_name = "public"; if (current_instance_type.find("solo") != std::string::npos) { instance_type_name = GetCleanName(); @@ -10550,9 +10498,11 @@ void Client::RemoveItem(uint32 item_id, uint32 quantity) } } -void Client::SetGMStatus(int newStatus) { - if (Admin() != newStatus) - database.UpdateGMStatus(AccountID(), newStatus); +void Client::SetGMStatus(int16 new_status) { + if (Admin() != new_status) { + database.UpdateGMStatus(AccountID(), new_status); + UpdateAdmin(); + } } void Client::ApplyWeaponsStance() @@ -11191,11 +11141,7 @@ void Client::ReconnectUCS() void Client::SendReloadCommandMessages() { SendChatLineBreak(); - auto aa_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload aa", - false, - "#reload aa" - ); + auto aa_link = Saylink::Silent("#reload aa"); Message( Chat::White, @@ -11205,11 +11151,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto alternate_currencies_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload alternate_currencies", - false, - "#reload alternate_currencies" - ); + auto alternate_currencies_link = Saylink::Silent("#reload alternate_currencies"); Message( Chat::White, @@ -11219,11 +11161,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto blocked_spells_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload blocked_spells", - false, - "#reload blocked_spells" - ); + auto blocked_spells_link = Saylink::Silent("#reload blocked_spells"); Message( Chat::White, @@ -11233,12 +11171,18 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto content_flags_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload content_flags", - false, - "#reload content_flags" + auto commands_link = Saylink::Silent("#reload commands"); + + Message( + Chat::White, + fmt::format( + "Usage: {} - Reloads Commands globally", + commands_link + ).c_str() ); + auto content_flags_link = Saylink::Silent("#reload content_flags"); + Message( Chat::White, fmt::format( @@ -11247,11 +11191,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto doors_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload doors", - false, - "#reload doors" - ); + auto doors_link = Saylink::Silent("#reload doors"); Message( Chat::White, @@ -11261,11 +11201,10 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto ground_spawns_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload ground_spawns", - false, - "#reload ground_spawns" - ); + auto dztemplates_link = Saylink::Silent("#reload dztemplates"); + Message(Chat::White, fmt::format("Usage: {} - Reloads Dynamic Zone Templates globally", dztemplates_link).c_str()); + + auto ground_spawns_link = Saylink::Silent("#reload ground_spawns"); Message( Chat::White, @@ -11275,11 +11214,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto level_mods_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload level_mods", - false, - "#reload level_mods" - ); + auto level_mods_link = Saylink::Silent("#reload level_mods"); Message( Chat::White, @@ -11289,11 +11224,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto logs_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload logs", - false, - "#reload logs" - ); + auto logs_link = Saylink::Silent("#reload logs"); Message( Chat::White, @@ -11303,11 +11234,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto merchants_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload merchants", - false, - "#reload merchants" - ); + auto merchants_link = Saylink::Silent("#reload merchants"); Message( Chat::White, @@ -11317,11 +11244,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto npc_emotes_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload npc_emotes", - false, - "#reload npc_emotes" - ); + auto npc_emotes_link = Saylink::Silent("#reload npc_emotes"); Message( Chat::White, @@ -11331,11 +11254,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto objects_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload objects", - false, - "#reload objects" - ); + auto objects_link = Saylink::Silent("#reload objects"); Message( Chat::White, @@ -11345,11 +11264,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto perl_export_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload perl_export", - false, - "#reload perl_export" - ); + auto perl_export_link = Saylink::Silent("#reload perl_export"); Message( Chat::White, @@ -11359,23 +11274,9 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto quest_link_one = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload quest", - false, - "#reload quest" - ); - - auto quest_link_two = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload quest", - false, - "0" - ); - - auto quest_link_three = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload quest 1", - false, - "1" - ); + auto quest_link_one = Saylink::Silent("#reload quest"); + auto quest_link_two = Saylink::Silent("#reload quest", "0"); + auto quest_link_three = Saylink::Silent("#reload quest 1", "1"); Message( Chat::White, @@ -11387,11 +11288,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto rules_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload rules", - false, - "#reload rules" - ); + auto rules_link = Saylink::Silent("#reload rules"); Message( Chat::White, @@ -11401,11 +11298,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto static_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload static", - false, - "#reload static" - ); + auto static_link = Saylink::Silent("#reload static"); Message( Chat::White, @@ -11415,11 +11308,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto tasks_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload tasks", - false, - "#reload tasks" - ); + auto tasks_link = Saylink::Silent("#reload tasks"); Message( Chat::White, @@ -11429,11 +11318,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto titles_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload titles", - false, - "#reload titles" - ); + auto titles_link = Saylink::Silent("#reload titles"); Message( Chat::White, @@ -11443,23 +11328,9 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto traps_link_one = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload traps", - false, - "#reload traps" - ); - - auto traps_link_two = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload traps", - false, - "0" - ); - - auto traps_link_three = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload traps 1", - false, - "1" - ); + auto traps_link_one = Saylink::Silent("#reload traps"); + auto traps_link_two = Saylink::Silent("#reload traps", "0"); + auto traps_link_three = Saylink::Silent("#reload traps 1", "1"); Message( Chat::White, @@ -11471,11 +11342,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto variables_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload variables", - false, - "#reload variables" - ); + auto variables_link = Saylink::Silent("#reload variables"); Message( Chat::White, @@ -11485,11 +11352,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto veteran_rewards_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload veteran_rewards", - false, - "#reload veteran_rewards" - ); + auto veteran_rewards_link = Saylink::Silent("#reload veteran_rewards"); Message( Chat::White, @@ -11499,29 +11362,10 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto world_link_one = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload world", - false, - "#reload world" - ); - - auto world_link_two = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload world", - false, - "0" - ); - - auto world_link_three = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload world 1", - false, - "1" - ); - - auto world_link_four = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload world 2", - false, - "2" - ); + auto world_link_one = Saylink::Silent("#reload world"); + auto world_link_two = Saylink::Silent("#reload world", "0"); + auto world_link_three = Saylink::Silent("#reload world 1", "1"); + auto world_link_four = Saylink::Silent("#reload world 2", "2"); Message( Chat::White, @@ -11534,11 +11378,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto zone_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload zone", - false, - "#reload zone" - ); + auto zone_link = Saylink::Silent("#reload zone"); Message( Chat::White, @@ -11548,11 +11388,7 @@ void Client::SendReloadCommandMessages() { ).c_str() ); - auto zone_points_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload zone_points", - false, - "#reload zone_points" - ); + auto zone_points_link = Saylink::Silent("#reload zone_points"); Message( Chat::White, @@ -11565,156 +11401,13 @@ void Client::SendReloadCommandMessages() { SendChatLineBreak(); } -bool Client::CheckMerchantDataBucket(uint8 bucket_comparison, std::string bucket_value, std::string player_value) -{ - std::vector bucket_checks; - bool found = false; - bool passes = false; - - switch (bucket_comparison) { - case MerchantBucketComparison::BucketEqualTo: - { - if (player_value != bucket_value) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketNotEqualTo: - { - if (player_value == bucket_value) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketGreaterThanOrEqualTo: - { - if (player_value < bucket_value) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketLesserThanOrEqualTo: - { - if (player_value > bucket_value) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketGreaterThan: - { - if (player_value <= bucket_value) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketLesserThan: - { - if (player_value >= bucket_value) { - break; - } - - passes = true; - - break; - } - case MerchantBucketComparison::BucketIsAny: - { - bucket_checks = split_string(bucket_value, "|"); - if (bucket_checks.empty()) { - break; - } - - for (const auto &bucket : bucket_checks) { - if (player_value == bucket) { - found = true; - break; - } - } - - if (!found) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketIsNotAny: - { - bucket_checks = split_string(bucket_value, "|"); - if (bucket_checks.empty()) { - break; - } - - for (const auto &bucket : bucket_checks) { - if (player_value == bucket) { - found = true; - break; - } - } - - if (found) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketIsBetween: - { - bucket_checks = split_string(bucket_value, "|"); - if (bucket_checks.empty()) { - break; - } - - if ( - std::stoll(player_value) < std::stoll(bucket_checks[0]) || - std::stoll(player_value) > std::stoll(bucket_checks[1]) - ) { - break; - } - - passes = true; - break; - } - case MerchantBucketComparison::BucketIsNotBetween: - { - bucket_checks = split_string(bucket_value, "|"); - if (bucket_checks.empty()) { - break; - } - - if ( - std::stoll(player_value) >= std::stoll(bucket_checks[0]) && - std::stoll(player_value) <= std::stoll(bucket_checks[1]) - ) { - break; - } - - passes = true; - break; - } - } - - return passes; -} - std::map Client::GetMerchantDataBuckets() { std::map merchant_data_buckets; auto query = fmt::format( "SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'", - EscapeString(GetBucketKey()) + Strings::Escape(GetBucketKey()) ); auto results = database.QueryDatabase(query); @@ -11728,3 +11421,415 @@ std::map Client::GetMerchantDataBuckets() return merchant_data_buckets; } + +void Client::Undye() +{ + for (uint8 slot = EQ::textures::textureBegin; slot <= EQ::textures::LastTexture; slot++) { + auto inventory_slot = SlotConvert(slot); + auto inst = m_inv.GetItem(inventory_slot); + + if (inst) { + inst->SetColor(inst->GetItem()->Color); + database.SaveInventory(CharacterID(), inst, inventory_slot); + } + + m_pp.item_tint.Slot[slot].Color = 0; + SendWearChange(slot); + } + + database.DeleteCharacterDye(CharacterID()); +} + +void Client::SetTrackingID(uint32 entity_id) +{ + if (!entity_id) { + TrackingID = 0; + return; + } + + auto *m = entity_list.GetMob(entity_id); + if (!m) { + TrackingID = 0; + return; + } + + TrackingID = entity_id; + + MessageString(Chat::Skills, TRACKING_BEGIN, m->GetCleanName()); +} + +int Client::GetRecipeMadeCount(uint32 recipe_id) +{ + auto r = CharRecipeListRepository::GetWhere( + database, + fmt::format("char_id = {} AND recipe_id = {}", CharacterID(), recipe_id) + ); + + if (!r.empty() && r[0].recipe_id) { + return r[0].madecount; + } + + return 0; +} + +bool Client::HasRecipeLearned(uint32 recipe_id) +{ + auto r = CharRecipeListRepository::GetWhere( + database, + fmt::format("char_id = {} AND recipe_id = {}", CharacterID(), recipe_id) + ); + + if (!r.empty() && r[0].recipe_id) { + return true; + } + + return false; +} + +bool Client::IsLockSavePosition() const +{ + return m_lock_save_position; +} + +void Client::SetLockSavePosition(bool lock_save_position) +{ + Client::m_lock_save_position = lock_save_position; +} + +void Client::AddAAPoints(uint32 points) +{ + m_pp.aapoints += points; + + if (points == 1 && m_pp.aapoints == 1) + { + MessageString(Chat::Yellow, GAIN_SINGLE_AA_SINGLE_AA, fmt::format_int(m_pp.aapoints).c_str()); + } + else if (points == 1 && m_pp.aapoints > 1) + { + MessageString(Chat::Yellow, GAIN_SINGLE_AA_MULTI_AA, fmt::format_int(m_pp.aapoints).c_str()); + } + else + { + MessageString(Chat::Yellow, GAIN_MULTI_AA_MULTI_AA, fmt::format_int(points).c_str(), fmt::format_int(m_pp.aapoints).c_str()); + } + + SendAlternateAdvancementStats(); +} + +bool Client::SendGMCommand(std::string message, bool ignore_status) { + return command_dispatch(this, message, ignore_status) >= 0 ? true : false; +} + +void Client::RegisterBug(BugReport_Struct* r) { + if (!r) { + return; + } + + auto b = BugReportsRepository::NewEntity(); + + b.zone = zone->GetShortName(); + b.client_version_id = static_cast(ClientVersion()); + b.client_version_name = EQ::versions::ClientVersionName(ClientVersion()); + b.account_id = AccountID(); + b.character_id = CharacterID(); + b.character_name = GetName(); + b.reporter_spoof = (strcmp(GetCleanName(), r->reporter_name) != 0 ? 1 : 0); + b.category_id = r->category_id; + b.category_name = r->category_name; + b.reporter_name = r->reporter_name; + b.ui_path = r->ui_path; + b.pos_x = r->pos_x; + b.pos_y = r->pos_y; + b.pos_z = r->pos_z; + b.heading = r->heading; + b.time_played = r->time_played; + b.target_id = r->target_id; + b.target_name = r->target_name; + b.optional_info_mask = r->optional_info_mask; + b._can_duplicate = ((r->optional_info_mask & EQ::bug::infoCanDuplicate) != 0 ? 1 : 0); + b._crash_bug = ((r->optional_info_mask & EQ::bug::infoCrashBug) != 0 ? 1 : 0); + b._target_info = ((r->optional_info_mask & EQ::bug::infoTargetInfo) != 0 ? 1 : 0); + b._character_flags = ((r->optional_info_mask & EQ::bug::infoCharacterFlags) != 0 ? 1 : 0); + b._unknown_value = ((r->optional_info_mask & EQ::bug::infoUnknownValue) != 0 ? 1 : 0); + b.bug_report = r->bug_report; + b.system_info = r->system_info; + + auto n = BugReportsRepository::InsertOne(database, b); + if (!n.id) { + Message(Chat::White, "Failed to created your bug report."); // Client sends success message + return; + } + + LogBugs("id [{}] report [{}] account [{}] name [{}] charid [{}] zone [{}]", n.id, r->bug_report, AccountID(), GetCleanName(), CharacterID(), zone->GetShortName()); + + worldserver.SendEmoteMessage( + 0, + 0, + AccountStatus::QuestTroupe, + Chat::Yellow, + fmt::format( + "{} has created a new bug report, would you like to {} it?", + GetCleanName(), + Saylink::Silent( + fmt::format( + "#bugs view {}", + n.id + ), + "view" + ) + ).c_str() + ); +} + +std::vector Client::GetApplySpellList( + ApplySpellType apply_type, + bool allow_pets, + bool is_raid_group_only, + bool allow_bots +) { + std::vector l; + + if (apply_type == ApplySpellType::Raid && IsRaidGrouped()) { + auto* r = GetRaid(); + auto group_id = r->GetGroup(this); + if (r && EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) { + for (auto i = 0; i < MAX_RAID_MEMBERS; i++) { + auto* m = r->members[i].member; + if (m && m->IsClient() && (!is_raid_group_only || r->GetGroup(m) == group_id)) { + l.push_back(m); + + if (allow_pets && m->HasPet()) { + l.push_back(m->GetPet()); + } + + if (allow_bots) { + const auto& sbl = entity_list.GetBotListByCharacterID(m->CharacterID()); + for (const auto& b : sbl) { + l.push_back(b); + } + } + } + } + } + } else if (apply_type == ApplySpellType::Group && IsGrouped()) { + auto* g = GetGroup(); + if (g) { + for (auto i = 0; i < MAX_GROUP_MEMBERS; i++) { + auto* m = g->members[i]; + if (m && m->IsClient()) { + l.push_back(m->CastToClient()); + + if (allow_pets && m->HasPet()) { + l.push_back(m->GetPet()); + } + + if (allow_bots) { + const auto& sbl = entity_list.GetBotListByCharacterID(m->CastToClient()->CharacterID()); + for (const auto& b : sbl) { + l.push_back(b); + } + } + } + } + } + } else { + l.push_back(this); + + if (allow_pets && HasPet()) { + l.push_back(GetPet()); + } + + if (allow_bots) { + const auto& sbl = entity_list.GetBotListByCharacterID(CharacterID()); + for (const auto& b : sbl) { + l.push_back(b); + } + } + } + + return l; +} + +void Client::ApplySpell( + int spell_id, + int duration, + ApplySpellType apply_type, + bool allow_pets, + bool is_raid_group_only, + bool allow_bots +) { + const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only, allow_bots); + + for (const auto& m : l) { + m->ApplySpellBuff(spell_id, duration); + } +} + +void Client::SetSpellDuration( + int spell_id, + int duration, + ApplySpellType apply_type, + bool allow_pets, + bool is_raid_group_only, + bool allow_bots +) { + const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only, allow_bots); + + for (const auto& m : l) { + m->SetBuffDuration(spell_id, duration); + } +} + +std::string Client::GetGuildPublicNote() +{ + if (!IsInAGuild()) { + return std::string(); + } + + CharGuildInfo gci; + if (!guild_mgr.GetCharInfo(character_id, gci)) { + return std::string(); + } + + return gci.public_note; +} + +void Client::MaxSkills() +{ + for (const auto &s : EQ::skills::GetSkillTypeMap()) { + auto current_skill_value = ( + EQ::skills::IsSpecializedSkill(s.first) ? + MAX_SPECIALIZED_SKILL : + content_db.GetSkillCap(GetClass(), s.first, GetLevel()) + ); + + if (GetSkill(s.first) < current_skill_value) { + SetSkill(s.first, current_skill_value); + } + } +} + +void Client::SendPath(Mob* target) +{ + if (!target) { + EQApplicationPacket outapp(OP_FindPersonReply, 0); + QueuePacket(&outapp); + return; + } + + + if ( + !RuleB(Pathing, Find) && + RuleB(Bazaar, EnableWarpToTrader) && + target->IsClient() && + ( + target->CastToClient()->Trader || + target->CastToClient()->Buyer + ) + ) { + Message( + Chat::Yellow, + fmt::format( + "Moving you to Trader {}.", + target->GetName() + ).c_str() + ); + MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + target->GetX(), + target->GetY(), + target->GetZ(), + 0.0f + ); + return; + } + + std::vector points; + + if (!RuleB(Pathing, Find) || !zone->pathing) { + points.clear(); + FindPerson_Point a; + FindPerson_Point b; + + a.x = GetX(); + a.y = GetY(); + a.z = GetZ(); + b.x = target->GetX(); + b.y = target->GetY(); + b.z = target->GetZ(); + + points.push_back(a); + points.push_back(b); + } else { + glm::vec3 path_start( + GetX(), + GetY(), + GetZ() + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION + ); + + glm::vec3 path_end( + target->GetX(), + target->GetY(), + target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION + ); + + bool partial = false; + bool stuck = false; + auto path_list = zone->pathing->FindRoute(path_start, path_end, partial, stuck); + + if (path_list.empty() || partial) { + EQApplicationPacket outapp(OP_FindPersonReply, 0); + QueuePacket(&outapp); + return; + } + + // Live appears to send the points in this order: + // Final destination. + // Current Position. + // rest of the points. + FindPerson_Point p; + + int point_number = 0; + + bool leads_to_teleporter = false; + + auto v = path_list.back(); + + p.x = v.pos.x; + p.y = v.pos.y; + p.z = v.pos.z; + points.push_back(p); + + p.x = GetX(); + p.y = GetY(); + p.z = GetZ(); + points.push_back(p); + + for (const auto& n : path_list) { + if (n.teleport) { + leads_to_teleporter = true; + break; + } + + glm::vec3 v = n.pos; + p.x = v.x; + p.y = v.y; + p.z = v.z; + + points.push_back(p); + + ++point_number; + } + + if (!leads_to_teleporter) { + p.x = target->GetX(); + p.y = target->GetY(); + p.z = target->GetZ(); + + points.push_back(p); + } + } + + SendPathPacket(points); +} diff --git a/zone/client.h b/zone/client.h index f039966eb..2bb016fe6 100644 --- a/zone/client.h +++ b/zone/client.h @@ -63,7 +63,7 @@ namespace EQ #include "questmgr.h" #include "zone.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "task_manager.h" #include "task_client_state.h" #include "cheat_manager.h" @@ -87,6 +87,7 @@ namespace EQ #define CLIENT_LD_TIMEOUT 30000 // length of time client stays in zone after LDing #define TARGETING_RANGE 200 // range for /assist and /target #define XTARGET_HARDCAP 20 +#define MAX_SPECIALIZED_SKILL 50 extern Zone* zone; extern TaskManager *task_manager; @@ -208,6 +209,7 @@ const std::string DIAWIND_RESPONSE_TWO_KEY = "diawind_npc_response_two"; const uint32 POPUPID_DIAWIND_ONE = 99999; const uint32 POPUPID_DIAWIND_TWO = 100000; const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000; +const uint32 POPUPID_REPLACE_SPELLWINDOW = 1000001; struct ClientReward { @@ -229,8 +231,6 @@ public: Client(EQStreamInterface * ieqs); ~Client(); - bool is_client_moving; - void ReconnectUCS(); void SetDisplayMobInfoWindow(bool display_mob_info_window); @@ -239,18 +239,21 @@ public: bool IsDevToolsEnabled() const; void SetDevToolsEnabled(bool in_dev_tools_enabled); + bool IsEXPEnabled() const; + void SetEXPEnabled(bool is_exp_enabled); + void SetPrimaryWeaponOrnamentation(uint32 model_id); void SetSecondaryWeaponOrnamentation(uint32 model_id); void SendChatLineBreak(uint16 color = Chat::White); bool GotoPlayer(std::string player_name); + bool GotoPlayerGroup(const std::string& player_name); + bool GotoPlayerRaid(const std::string& player_name); //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill); virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); - virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByClient(this); } @@ -259,7 +262,6 @@ public: virtual void SetAttackTimer(); int GetQuiverHaste(int delay); void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false); - int64 DoDamageCaps(int64 base_damage); void AI_Init(); void AI_Start(uint32 iMoveDelay = 0); @@ -328,13 +330,15 @@ public: void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQ::ItemData* item, bool buying); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); - void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname=nullptr); + void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname = nullptr, bool is_silent = false); void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...); void Message(uint32 type, const char* message, ...); void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...); void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber); void SendSound(); - void LearnRecipe(uint32 recipeID); + void LearnRecipe(uint32 recipe_id); + int GetRecipeMadeCount(uint32 recipe_id); + bool HasRecipeLearned(uint32 recipe_id); bool CanIncreaseTradeskill(EQ::skills::SkillType tradeskill); EQApplicationPacket* ReturnItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type); @@ -346,7 +350,7 @@ public: int GetIPExemption(); void SetIPExemption(int exemption_amount); inline bool GetHideMe() const { return gm_hide_me; } - void SetHideMe(bool hm); + void SetHideMe(bool flag); inline uint16 GetPort() const { return port; } bool IsDead() const { return(dead); } bool IsUnconscious() const { return ((current_hp <= 0) ? true : false); } @@ -410,6 +414,8 @@ public: inline void SetBaseGender(uint32 i) { m_pp.gender=i; } inline void SetDeity(uint32 i) {m_pp.deity=i;deity=i;} + void SetTrackingID(uint32 entity_id); + inline uint8 GetLevel2() const { return m_pp.level2; } inline uint16 GetBaseRace() const { return m_pp.race; } inline uint16 GetBaseClass() const { return m_pp.class_; } @@ -550,9 +556,7 @@ public: inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; } - int32 GetActSpellCost(uint16 spell_id, int32); virtual bool CheckFizzle(uint16 spell_id); - virtual bool CheckSpellLevelRestriction(uint16 spell_id); virtual int GetCurrentBuffSlots() const; virtual int GetCurrentSongSlots() const; virtual int GetCurrentDiscSlots() const { return 1; } @@ -600,10 +604,10 @@ public: inline uint32 GetEXP() const { return m_pp.exp; } - inline double GetAAEXPModifier(uint32 zone_id) const { return database.GetAAEXPModifier(CharacterID(), zone_id); }; - inline double GetEXPModifier(uint32 zone_id) const { return database.GetEXPModifier(CharacterID(), zone_id); }; - inline void SetAAEXPModifier(uint32 zone_id, double aa_modifier) { database.SetAAEXPModifier(CharacterID(), zone_id, aa_modifier); }; - inline void SetEXPModifier(uint32 zone_id, double exp_modifier) { database.SetEXPModifier(CharacterID(), zone_id, exp_modifier); }; + inline double GetAAEXPModifier(uint32 zone_id, int16 instance_version = -1) const { return database.GetAAEXPModifier(CharacterID(), zone_id, instance_version); }; + inline double GetEXPModifier(uint32 zone_id, int16 instance_version = -1) const { return database.GetEXPModifier(CharacterID(), zone_id, instance_version); }; + inline void SetAAEXPModifier(uint32 zone_id, double aa_modifier, int16 instance_version = -1) { database.SetAAEXPModifier(CharacterID(), zone_id, aa_modifier, instance_version); }; + inline void SetEXPModifier(uint32 zone_id, double exp_modifier, int16 instance_version = -1) { database.SetEXPModifier(CharacterID(), zone_id, exp_modifier, instance_version); }; bool UpdateLDoNPoints(uint32 theme_id, int points); void SetPVPPoints(uint32 Points) { m_pp.PVPCurrentPoints = Points; } @@ -616,17 +620,17 @@ public: void AddCrystals(uint32 Radiant, uint32 Ebon); void SendCrystalCounts(); - uint32 GetExperienceForKill(Mob *against); - void AddEXP(uint32 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false); - uint32 CalcEXP(uint8 conlevel = 0xFF); - void CalculateNormalizedAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp); - void CalculateStandardAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp); - void CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel); - void CalculateExp(uint32 in_add_exp, uint32 &add_exp, uint32 &add_aaxp, uint8 conlevel, bool resexp); - void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp=false); + uint64 GetExperienceForKill(Mob *against); + void AddEXP(uint64 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false); + uint64 CalcEXP(uint8 conlevel = 0xFF, bool ignore_mods = false); + void CalculateNormalizedAAExp(uint64 &add_aaxp, uint8 conlevel, bool resexp); + void CalculateStandardAAExp(uint64 &add_aaxp, uint8 conlevel, bool resexp); + void CalculateLeadershipExp(uint64 &add_exp, uint8 conlevel); + void CalculateExp(uint64 in_add_exp, uint64 &add_exp, uint64 &add_aaxp, uint8 conlevel, bool resexp); + void SetEXP(uint64 set_exp, uint64 set_aaxp, bool resexp=false); void AddLevelBasedExp(uint8 exp_percentage, uint8 max_level = 0, bool ignore_mods = false); - void SetLeadershipEXP(uint32 group_exp, uint32 raid_exp); - void AddLeadershipEXP(uint32 group_exp, uint32 raid_exp); + void SetLeadershipEXP(uint64 group_exp, uint64 raid_exp); + void AddLeadershipEXP(uint64 group_exp, uint64 raid_exp); void SendLeadershipEXPUpdate(); bool IsLeadershipEXPOn(); inline int GetLeadershipAA(int AAID) { return m_pp.leader_abilities.ranks[AAID]; } @@ -656,19 +660,19 @@ public: void MovePC(uint32 zoneID, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void MovePC(float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void MovePC(uint32 zoneID, uint32 instanceID, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); - void MoveZone(const char *zone_short_name); - void MoveZoneGroup(const char *zone_short_name); - void MoveZoneRaid(const char *zone_short_name); - void MoveZoneInstance(uint16 instance_id); - void MoveZoneInstanceGroup(uint16 instance_id); - void MoveZoneInstanceRaid(uint16 instance_id); + void MoveZone(const char *zone_short_name, const glm::vec4& location = glm::vec4(0.f)); + void MoveZoneGroup(const char *zone_short_name, const glm::vec4& location = glm::vec4(0.f)); + void MoveZoneRaid(const char *zone_short_name, const glm::vec4& location = glm::vec4(0.f)); + void MoveZoneInstance(uint16 instance_id, const glm::vec4& location = glm::vec4(0.f)); + void MoveZoneInstanceGroup(uint16 instance_id, const glm::vec4& location = glm::vec4(0.f)); + void MoveZoneInstanceRaid(uint16 instance_id, const glm::vec4& location = glm::vec4(0.f)); void SendToGuildHall(); void SendToInstance(std::string instance_type, std::string zone_short_name, uint32 instance_version, float x, float y, float z, float heading, std::string instance_identifier, uint32 duration); void AssignToInstance(uint16 instance_id); void RemoveFromInstance(uint16 instance_id); void WhoAll(); bool CheckLoreConflict(const EQ::ItemData* item); - void ChangeLastName(const char* in_lastname); + void ChangeLastName(std::string last_name); void GetGroupAAs(GroupLeadershipAA_Struct *into) const; void GetRaidAAs(RaidLeadershipAA_Struct *into) const; void ClearGroupAAs(); @@ -702,7 +706,7 @@ public: inline int GetAccountCreation() const { return account_creation; } inline int16 Admin() const { return admin; } inline uint32 CharacterID() const { return character_id; } - void UpdateAdmin(bool iFromDB = true); + void UpdateAdmin(bool from_database = true); void UpdateWho(uint8 remove = 0); bool GMHideMe(Client* client = 0); @@ -720,8 +724,8 @@ public: void SendGuildJoin(GuildJoin_Struct* gj); void RefreshGuildInfo(); - int GetClientMaxLevel() const { return client_max_level; } - void SetClientMaxLevel(int max_level) { client_max_level = max_level; } + uint8 GetClientMaxLevel() const { return client_max_level; } + void SetClientMaxLevel(uint8 max_level) { client_max_level = max_level; } void CheckManaEndUpdate(); void SendManaUpdate(); @@ -748,6 +752,8 @@ public: uint32 GetMoney(uint8 type, uint8 subtype); int GetAccountAge(); + void SendPath(Mob* target); + bool IsDiscovered(uint32 itemid); void DiscoverItem(uint32 itemid); @@ -778,6 +784,7 @@ public: uint16 MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const; inline uint16 MaxSkill(EQ::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } uint8 SkillTrainLevel(EQ::skills::SkillType skillid, uint16 class_); + void MaxSkills(); void SendTradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid); void SendTradeskillDetails(uint32 recipe_id); @@ -828,10 +835,10 @@ public: void UntrainDiscBySpellID(uint16 spell_id, bool update_client = true); bool SpellGlobalCheck(uint16 spell_id, uint32 char_id); bool SpellBucketCheck(uint16 spell_id, uint32 char_id); - uint32 GetCharMaxLevelFromQGlobal(); - uint32 GetCharMaxLevelFromBucket(); + uint8 GetCharMaxLevelFromQGlobal(); + uint8 GetCharMaxLevelFromBucket(); - void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clipping = false); + void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clip_through_walls = false, bool calculate_speed = false); inline bool IsStanding() const {return (playeraction == 0);} inline bool IsSitting() const {return (playeraction == 1);} @@ -898,11 +905,40 @@ public: void ResetOnDeathAlternateAdvancement(); void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } - void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } + void AddAAPoints(uint32 points); int GetAAPoints() { return m_pp.aapoints; } int GetSpentAA() { return m_pp.aapoints_spent; } uint32 GetRequiredAAExperience(); + bool SendGMCommand(std::string message, bool ignore_status = false); + + void RegisterBug(BugReport_Struct* r); + + std::vector GetApplySpellList( + ApplySpellType apply_type, + bool allow_pets, + bool is_raid_group_only, + bool allow_bots + ); + + void ApplySpell( + int spell_id, + int duration = 0, + ApplySpellType apply_type = ApplySpellType::Solo, + bool allow_pets = false, + bool is_raid_group_only = true, + bool allow_bots = false + ); + + void SetSpellDuration( + int spell_id, + int duration = 0, + ApplySpellType apply_type = ApplySpellType::Solo, + bool allow_pets = false, + bool is_raid_group_only = true, + bool allow_bots = false + ); + //old AA methods that we still use void ResetAA(); void RefundAA(); @@ -911,9 +947,8 @@ public: void SendClearPlayerAA(); inline uint32 GetAAXP() const { return m_pp.expAA; } inline uint32 GetAAPercent() const { return m_epp.perAA; } - int64 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); - void SetAATitle(const char *Title); - void SetTitleSuffix(const char *txt); + void SetAATitle(std::string title); + void SetTitleSuffix(std::string suffix); void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing, uint32 reduction = 0); // Item methods @@ -975,7 +1010,6 @@ public: bool CheckTradeLoreConflict(Client* other); bool CheckTradeNonDroppable(); void LinkDead(); - void Insight(uint32 t_id); bool CheckDoubleAttack(); bool CheckTripleAttack(); bool CheckDoubleRangedAttack(); @@ -995,12 +1029,14 @@ public: void DoClassAttacks(Mob *ca_target, uint16 skill = -1, bool IsRiposte=false); void ClearZoneFlag(uint32 zone_id); + inline std::set GetZoneFlags() { return zone_flags; } ; bool HasZoneFlag(uint32 zone_id) const; void LoadZoneFlags(); void SendZoneFlagInfo(Client *to) const; void SetZoneFlag(uint32 zone_id); void ClearPEQZoneFlag(uint32 zone_id); + inline std::set GetPEQZoneFlags() { return peqzone_flags; }; bool HasPEQZoneFlag(uint32 zone_id) const; void LoadPEQZoneFlags(); void SendPEQZoneFlagInfo(Client *to) const; @@ -1040,6 +1076,7 @@ public: void SendRules(); const bool GetGMSpeed() const { return (gmspeed > 0); } + const bool GetGMInvul() const { return gminvul; } bool CanUseReport; //This is used to later set the buff duration of the spell, in slot to duration. @@ -1056,6 +1093,7 @@ public: inline uint32 GetSpellByBookSlot(int book_slot) { return m_pp.spell_book[book_slot]; } inline bool HasSpellScribed(int spellid) { return FindSpellBookSlotBySpellID(spellid) != -1; } uint32 GetHighestScribedSpellinSpellGroup(uint32 spell_group); + std::unordered_map> LoadSpellGroupCache(uint8 min_level, uint8 max_level); uint16 GetMaxSkillAfterSpecializationRules(EQ::skills::SkillType skillid, uint16 maxSkill); void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0); void SendFullPopup(const char *Title, const char *Text, uint32 PopupID = 0, uint32 NegativeID = 0, uint32 Buttons = 0, uint32 Duration = 0, const char *ButtonName0 = 0, const char *ButtonName1 = 0, uint32 SoundControls = 0); @@ -1132,72 +1170,46 @@ public: ); } } - inline void UpdateTasksForItem( - TaskActivityType activity_type, - int item_id, - int count = 1 - ) + inline void UpdateTasksForItem(TaskActivityType type, int item_id, int count = 1) { if (task_state) { - task_state->UpdateTasksForItem(this, activity_type, item_id, count); + task_state->UpdateTasksForItem(this, type, item_id, count); } } - inline void UpdateTasksOnExplore(int explore_id) + inline void UpdateTasksOnLoot(Corpse* corpse, int item_id, int count = 1) { if (task_state) { - task_state->UpdateTasksOnExplore( - this, - explore_id - ); + task_state->UpdateTasksOnLoot(this, corpse, item_id, count); } } - inline bool UpdateTasksOnSpeakWith(int npc_type_id) + inline void UpdateTasksOnExplore(const glm::vec4& pos) { if (task_state) { - return task_state->UpdateTasksOnSpeakWith( - this, - npc_type_id - ); - } - else { return false; } - } - inline bool UpdateTasksOnDeliver( - std::list &items, - int cash, - int npc_type_id - ) - { - if (task_state) { - return task_state->UpdateTasksOnDeliver( - this, - items, - cash, - npc_type_id - ); - } - else { return false; } - } - inline void TaskSetSelector(Mob *mob, int task_set_id) - { - if (task_manager) { - task_manager->TaskSetSelector( - this, - task_state, - mob, - task_set_id - ); + task_state->UpdateTasksOnExplore(this, pos); } } - inline void TaskQuestSetSelector(Mob *mob, int count, int *tasks) + inline bool UpdateTasksOnSpeakWith(NPC* npc) { - if (task_manager) { - task_manager->TaskQuestSetSelector( - this, - task_state, - mob, - count, - tasks - ); + return task_state && task_state->UpdateTasksOnSpeakWith(this, npc); + } + inline bool UpdateTasksOnDeliver(std::vector& items, Trade& trade, NPC* npc) + { + return task_state && task_state->UpdateTasksOnDeliver(this, items, trade, npc); + } + void UpdateTasksOnTouchSwitch(int dz_switch_id) + { + if (task_state) { task_state->UpdateTasksOnTouch(this, dz_switch_id); } + } + inline void TaskSetSelector(Mob* mob, int task_set_id, bool ignore_cooldown) + { + if (task_manager && task_state) { + task_manager->TaskSetSelector(this, mob, task_set_id, ignore_cooldown); + } + } + inline void TaskQuestSetSelector(Mob* mob, const std::vector& tasks, bool ignore_cooldown) + { + if (task_manager && task_state) { + task_manager->TaskQuestSetSelector(this, mob, tasks, ignore_cooldown); } } inline void EnableTask(int task_count, int *task_list) @@ -1226,12 +1238,7 @@ public: inline void ProcessTaskProximities(float x, float y, float z) { if (task_state) { - task_state->ProcessTaskProximities( - this, - x, - y, - z - ); + task_state->ProcessTaskProximities(this, x, y, z); } } inline void AssignTask( @@ -1243,22 +1250,19 @@ public: task_state->AcceptNewTask(this, task_id, npc_id, std::time(nullptr), enforce_level_requirement); } } - inline int ActiveSpeakTask(int npc_type_id) + inline int ActiveSpeakTask(NPC* npc) { if (task_state) { - return task_state->ActiveSpeakTask(npc_type_id); + return task_state->ActiveSpeakTask(this, npc); } else { return 0; } } - inline int ActiveSpeakActivity(int npc_type_id, int task_id) + inline int ActiveSpeakActivity(NPC* npc, int task_id) { if (task_state) { - return task_state->ActiveSpeakActivity( - npc_type_id, - task_id - ); + return task_state->ActiveSpeakActivity(this, npc, task_id); } else { return 0; } } @@ -1301,6 +1305,8 @@ public: return (task_state ? task_state->CompletedTasksInSet(task_set_id) : 0); } void PurgeTaskTimers(); + void LockSharedTask(bool lock) { if (task_state) { task_state->LockSharedTask(this, lock); } } + void EndSharedTask(bool fail = false) { if (task_state) { task_state->EndSharedTask(this, fail); } } // shared task shims / middleware // these variables are used as a shim to intercept normal localized task functionality @@ -1343,6 +1349,8 @@ public: void ClearPendingAdventureDoorClick() { safe_delete(adventure_door_timer); } void ClearPendingAdventureData(); + bool CanEnterZone(const std::string& zone_short_name = "", int16 instance_version = -1); + int GetAggroCount(); void IncrementAggroCount(bool raid_target = false); void DecrementAggroCount(); @@ -1383,6 +1391,7 @@ public: Expedition* CreateExpedition(const std::string& zone_name, uint32 version, uint32 duration, const std::string& expedition_name, uint32 min_players, uint32 max_players, bool disable_messages = false); + Expedition* CreateExpeditionFromTemplate(uint32_t dz_template_id); Expedition* GetExpedition() const; uint32 GetExpeditionID() const { return m_expedition_id; } const ExpeditionLockoutTimer* GetExpeditionLockout( @@ -1403,8 +1412,9 @@ public: void SetDzRemovalTimer(bool enable_timer); void SendDzCompassUpdate(); void GoToDzSafeReturnOrBind(const DynamicZone* dynamic_zone); - void MovePCDynamicZone(uint32 zone_id, int zone_version = -1, bool msg_if_invalid = true); - void MovePCDynamicZone(const std::string& zone_name, int zone_version = -1, bool msg_if_invalid = true); + void MovePCDynamicZone(uint32 zone_id, int zone_version = -1, bool msg_if_invalid = false); + void MovePCDynamicZone(const std::string& zone_name, int zone_version = -1, bool msg_if_invalid = false); + bool TryMovePCDynamicZoneSwitch(int dz_switch_id); std::vector GetDynamicZones(uint32_t zone_id = 0, int zone_version = -1); std::unique_ptr CreateDzSwitchListPacket(const std::vector& dzs); std::unique_ptr CreateCompassPacket(const std::vector& entries); @@ -1429,7 +1439,8 @@ public: void SuspendMinion(int value); void Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration); void NotifyNewTitlesAvailable(); - void Signal(uint32 data); + void Signal(int signal_id); + void SendPayload(int payload_id, std::string payload_value = std::string()); Mob *GetBindSightTarget() { return bind_sight_target; } void SetBindSightTarget(Mob *n) { bind_sight_target = n; } const uint16 GetBoatID() const { return controlling_boat_id; } @@ -1552,7 +1563,8 @@ public: const char* GetRacePlural(Client* client); const char* GetClassPlural(Client* client); void SendWebLink(const char* website); - void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg); + void SendMarqueeMessage(uint32 type, std::string message, uint32 duration = 3000); + void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message); void SendSpellAnim(uint16 targetid, uint16 spell_id); void DuplicateLoreMessage(uint32 ItemID); @@ -1574,7 +1586,7 @@ public: void LoadAccountFlags(); void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); - void SetGMStatus(int newStatus); + void SetGMStatus(int16 new_status); float GetDamageMultiplier(EQ::skills::SkillType how_long_has_this_been_missing); void Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); @@ -1595,7 +1607,7 @@ public: void mod_client_death_npc(Mob* killerMob); void mod_client_death_duel(Mob* killerMob); void mod_client_death_env(); - int32 mod_client_xp(int32 in_exp, NPC *npc); + int64 mod_client_xp(int64 in_exp, NPC *npc); uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); int mod_client_haste_cap(int cap); int mod_consume(EQ::ItemData *item, EQ::item::ItemType type, int change); @@ -1629,7 +1641,9 @@ public: uint32 GetNextInvSnapshotTime() { return m_epp.next_invsnapshot_time; } void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false); - void QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction); // TODO: Fix faction processing + void QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction = false); + void CashReward(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); + void RewardFaction(int id, int amount); void ResetHPUpdateTimer() { hpupdate_timer.Start(); } @@ -1655,7 +1669,8 @@ public: Timer m_list_task_timers_rate_limit = {}; std::map GetMerchantDataBuckets(); - bool CheckMerchantDataBucket(uint8 bucket_comparison, std::string bucket_value, std::string player_value); + + std::string GetGuildPublicNote(); protected: friend class Mob; @@ -1668,7 +1683,6 @@ protected: void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true); bool client_data_loaded; - int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false); uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost); @@ -1785,6 +1799,7 @@ private: bool auto_fire; bool runmode; uint8 gmspeed; + bool gminvul; bool medding; uint16 horseId; bool revoked; @@ -1825,6 +1840,13 @@ private: int32 max_end; int32 current_endurance; + // https://github.com/EQEmu/Server/pull/2479 + bool m_lock_save_position = false; +public: + bool IsLockSavePosition() const; + void SetLockSavePosition(bool lock_save_position); +private: + PlayerProfile_Struct m_pp; ExtendedProfile_Struct m_epp; EQ::InventoryProfile m_inv; @@ -1838,7 +1860,6 @@ private: void NPCSpawn(const Seperator* sep); uint32 GetEXPForLevel(uint16 level); - bool CanBeInZone(); void SendLogoutPackets(); void SendZoneInPackets(); bool AddPacket(const EQApplicationPacket *, bool); @@ -1943,6 +1964,8 @@ public: int64 GetSharedTaskId() const; private: + bool m_exp_enabled; + //Anti Spam Stuff Timer *KarmaUpdateTimer; uint32 TotalKarma; @@ -2008,7 +2031,7 @@ private: void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQ::ItemInstance* inst, const EQ::ItemInstance* parent, bool log, bool silent, bool &error, int depth); bool InterrogateInventory_error(int16 head, int16 index, const EQ::ItemInstance* inst, const EQ::ItemInstance* parent, int depth); - int client_max_level; + uint8 client_max_level; uint32 m_expedition_id = 0; ExpeditionInvite m_pending_expedition_invite { 0 }; @@ -2017,7 +2040,6 @@ private: bool m_has_quest_compass = false; std::vector m_dynamic_zone_ids; -#ifdef BOTS public: enum BotOwnerOption : size_t { @@ -2042,12 +2064,21 @@ public: bool GetBotPrecombat() { return m_bot_precombat; } void SetBotPrecombat(bool flag = true) { m_bot_precombat = flag; } + int GetBotRequiredLevel(uint8 class_id = NO_CLASS); + uint32 GetBotCreationLimit(uint8 class_id = NO_CLASS); + int GetBotSpawnLimit(uint8 class_id = NO_CLASS); + void SetBotCreationLimit(uint32 new_creation_limit, uint8 class_id = NO_CLASS); + void SetBotRequiredLevel(int new_required_level, uint8 class_id = NO_CLASS); + void SetBotSpawnLimit(int new_spawn_limit, uint8 class_id = NO_CLASS); + + void CampAllBots(uint8 class_id = NO_CLASS); + private: bool bot_owner_options[_booCount]; bool m_bot_pulling; bool m_bot_precombat; -#endif + bool CanTradeFVNoDropItem(); }; #endif diff --git a/zone/client_bot.cpp b/zone/client_bot.cpp new file mode 100644 index 000000000..e391888fe --- /dev/null +++ b/zone/client_bot.cpp @@ -0,0 +1,161 @@ +#include "bot.h" +#include "client.h" + +bool Client::GetBotOption(BotOwnerOption boo) const { + if (boo < _booCount) { + return bot_owner_options[boo]; + } + + return false; +} + +void Client::SetBotOption(BotOwnerOption boo, bool flag) { + if (boo < _booCount) { + bot_owner_options[boo] = flag; + } +} + +uint32 Client::GetBotCreationLimit(uint8 class_id) +{ + uint32 bot_creation_limit = RuleI(Bots, CreationLimit); + + const auto bucket_name = fmt::format( + "bot_creation_limit{}", + ( + class_id && IsPlayerClass(class_id) ? + fmt::format( + "_{}", + Strings::ToLower(GetClassIDName(class_id)) + ) : + "" + ) + ); + + auto bucket_value = GetBucket(bucket_name); + if (!bucket_value.empty() && Strings::IsNumber(bucket_value)) { + bot_creation_limit = std::stoul(bucket_value); + } + + return bot_creation_limit; +} + +int Client::GetBotRequiredLevel(uint8 class_id) +{ + int bot_character_level = RuleI(Bots, BotCharacterLevel); + + const auto bucket_name = fmt::format( + "bot_required_level{}", + ( + class_id && IsPlayerClass(class_id) ? + fmt::format( + "_{}", + Strings::ToLower(GetClassIDName(class_id)) + ) : + "" + ) + ); + + auto bucket_value = GetBucket(bucket_name); + if (!bucket_value.empty() && Strings::IsNumber(bucket_value)) { + bot_character_level = std::stoi(bucket_value); + } + + return bot_character_level; +} + +int Client::GetBotSpawnLimit(uint8 class_id) +{ + int bot_spawn_limit = RuleI(Bots, SpawnLimit); + + const auto bucket_name = fmt::format( + "bot_spawn_limit{}", + ( + class_id && IsPlayerClass(class_id) ? + fmt::format( + "_{}", + Strings::ToLower(GetClassIDName(class_id)) + ) : + "" + ) + ); + + auto bucket_value = GetBucket(bucket_name); + if (!bucket_value.empty() && Strings::IsNumber(bucket_value)) { + bot_spawn_limit = std::stoi(bucket_value); + return bot_spawn_limit; + } + + if (RuleB(Bots, QuestableSpawnLimit)) { + const auto query = fmt::format( + "SELECT `value` FROM `quest_globals` WHERE `name` = '{}' AND `charid` = {} LIMIT 1", + bucket_name, + CharacterID() + ); + + auto results = database.QueryDatabase(query); // use 'database' for non-bot table calls + if (!results.Success() || !results.RowCount()) { + return bot_spawn_limit; + } + + auto row = results.begin(); + bot_spawn_limit = std::stoi(row[0]); + } + + return bot_spawn_limit; +} + +void Client::SetBotCreationLimit(uint32 new_creation_limit, uint8 class_id) +{ + const auto bucket_name = fmt::format( + "bot_creation_limit{}", + ( + class_id && IsPlayerClass(class_id) ? + fmt::format( + "_{}", + Strings::ToLower(GetClassIDName(class_id)) + ) : + "" + ) + ); + + SetBucket(bucket_name, std::to_string(new_creation_limit)); +} + +void Client::SetBotRequiredLevel(int new_required_level, uint8 class_id) +{ + const auto bucket_name = fmt::format( + "bot_required_level{}", + ( + class_id && IsPlayerClass(class_id) ? + fmt::format( + "_{}", + Strings::ToLower(GetClassIDName(class_id)) + ) : + "" + ) + ); + + SetBucket(bucket_name, std::to_string(new_required_level)); +} + +void Client::SetBotSpawnLimit(int new_spawn_limit, uint8 class_id) +{ + const auto bucket_name = fmt::format( + "bot_spawn_limit{}", + ( + class_id && IsPlayerClass(class_id) ? + fmt::format( + "_{}", + Strings::ToLower(GetClassIDName(class_id)) + ) : + "" + ) + ); + + SetBucket(bucket_name, std::to_string(new_spawn_limit)); +} + +void Client::CampAllBots(uint8 class_id) +{ + Bot::BotOrderCampAll(this, class_id); +} diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index b5186c165..c6eb3f31c 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -27,9 +27,7 @@ #include "client.h" #include "mob.h" -#ifdef BOTS - #include "bot.h" -#endif +#include "bot.h" #include @@ -292,7 +290,7 @@ int64 Client::CalcHPRegen(bool bCombat) if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) { auto max_hp = GetMaxHP(); - int fast_regen = 6 * (max_hp / zone->newzone_data.FastRegenHP); + int fast_regen = 6 * (max_hp / zone->newzone_data.fast_regen_hp); if (base < fast_regen) // weird, but what the client is doing base = fast_regen; } @@ -303,12 +301,17 @@ int64 Client::CalcHPRegen(bool bCombat) int64 Client::CalcHPRegenCap() { - int cap = RuleI(Character, ItemHealthRegenCap); - if (GetLevel() > 60) - cap = std::max(cap, GetLevel() - 30); // if the rule is set greater than normal I guess - if (GetLevel() > 65) + int64 cap = RuleI(Character, ItemHealthRegenCap); + if (GetLevel() > 60) { + cap = std::max(cap, static_cast(GetLevel() - 30)); // if the rule is set greater than normal I guess + } + + if (GetLevel() > 65) { cap += GetLevel() - 65; + } + cap += aabonuses.ItemHPRegenCap + spellbonuses.ItemHPRegenCap + itembonuses.ItemHPRegenCap; + return (cap * RuleI(Character, HPRegenMultiplier) / 100); } @@ -594,7 +597,7 @@ int64 Client::CalcMaxMana() current_mana = curMana_cap; } } - LogSpells("Client::CalcMaxMana() called for [{}] - returning [{}]", GetName(), max_mana); + LogSpells("for [{}] returning [{}]", GetName(), max_mana); return max_mana; } @@ -766,7 +769,7 @@ int64 Client::CalcManaRegen(bool bCombat) if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) { auto max_mana = GetMaxMana(); - int fast_regen = 6 * (max_mana / zone->newzone_data.FastRegenMana); + int fast_regen = 6 * (max_mana / zone->newzone_data.fast_regen_mana); if (regen < fast_regen) // weird, but what the client is doing regen = fast_regen; } @@ -1658,7 +1661,7 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) } } - LogSpells("[{}]::GetInstrumentMod() spell=[{}] mod=[{}] modcap=[{}]\n", GetName(), spell_id, effectmod, effectmodcap); + LogSpells("Name [{}] spell [{}] mod [{}] modcap [{}]\n", GetName(), spell_id, effectmod, effectmodcap); return effectmod; } @@ -1796,7 +1799,7 @@ int64 Client::CalcEnduranceRegen(bool bCombat) int64 regen = base; if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) { auto max_end = GetMaxEndurance(); - int fast_regen = 6 * (max_end / zone->newzone_data.FastRegenEndurance); + int fast_regen = 6 * (max_end / zone->newzone_data.fast_regen_endurance); if (aa_regen < fast_regen) // weird, but what the client is doing aa_regen = fast_regen; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index ee66f02b2..4b4b8f758 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -45,7 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/zone_numbers.h" #include "data_bucket.h" #include "event_codes.h" @@ -68,11 +68,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/shared_tasks.h" #include "gm_commands/door_manipulation.h" #include "client.h" +#include "../common/repositories/account_repository.h" - -#ifdef BOTS #include "bot.h" -#endif extern QueryServ* QServ; extern Zone* zone; @@ -429,6 +427,8 @@ void MapOpcodes() ConnectedOpcodes[OP_SharedTaskAcceptNew] = &Client::Handle_OP_SharedTaskAccept; ConnectedOpcodes[OP_SharedTaskQuit] = &Client::Handle_OP_SharedTaskQuit; ConnectedOpcodes[OP_SharedTaskPlayerList] = &Client::Handle_OP_SharedTaskPlayerList; + + LogInfo("Mapped [{}] client opcode handlers", _maxEmuOpcode); } void ClearMappedOpcode(EmuOpcode op) @@ -446,17 +446,13 @@ void ClearMappedOpcode(EmuOpcode op) // client methods int Client::HandlePacket(const EQApplicationPacket *app) { - if (LogSys.log_settings[Logs::LogCategory::Netcode].is_category_enabled == 1) { - char buffer[64]; - app->build_header_dump(buffer); - Log(Logs::Detail, Logs::PacketClientServer, "Dispatch opcode: %s", buffer); - } - - if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1) - Log(Logs::General, Logs::PacketClientServer, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size()); - - if (LogSys.log_settings[Logs::PacketClientServerWithDump].is_category_enabled == 1) - Log(Logs::General, Logs::PacketClientServerWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size(), DumpPacketToString(app).c_str()); + LogPacketClientServer( + "[{}] [{:#06x}] Size [{}] {}", + OpcodeManager::EmuToName(app->GetOpcode()), + eqs->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + app->Size(), + (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") + ); EmuOpcode opcode = app->GetOpcode(); if (opcode == OP_AckPacket) { @@ -471,7 +467,7 @@ int Client::HandlePacket(const EQApplicationPacket *app) case CLIENT_CONNECTING: { if (ConnectingOpcodes.count(opcode) != 1) { //Hate const cast but everything in lua needs to be non-const even if i make it non-mutable - std::vector args; + std::vector args; args.push_back(const_cast(app)); parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 1, &args); @@ -495,15 +491,10 @@ int Client::HandlePacket(const EQApplicationPacket *app) ClientPacketProc p; p = ConnectedOpcodes[opcode]; if (p == nullptr) { - std::vector args; + std::vector args; args.push_back(const_cast(app)); parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args); - if (LogSys.log_settings[Logs::PacketClientServerUnhandled].is_category_enabled == 1) { - char buffer[64]; - app->build_header_dump(buffer); - Log(Logs::General, Logs::PacketClientServerUnhandled, "%s %s", buffer, DumpPacketToString(app).c_str()); - } break; } @@ -569,7 +560,31 @@ void Client::CompleteConnect() //SendAATable(); - if (GetHideMe()) Message(Chat::Red, "[GM] You are currently hidden to all clients"); + if (GetGM() && (GetHideMe() || GetGMSpeed() || GetGMInvul() || flymode != 0 || tellsoff)) { + std::vector state; + if (GetHideMe()) { + state.emplace_back("hidden to all clients"); + } + if (GetGMSpeed()) { + state.emplace_back("running at GM speed"); + } + if (GetGMInvul()) { + state.emplace_back("invulnerable to all damage"); + } + if (flymode == GravityBehavior::Flying) { + state.emplace_back("flying"); + } + else if (flymode == GravityBehavior::Levitating) { + state.emplace_back("levitating"); + } + if (tellsoff) { + state.emplace_back("ignoring tells"); + } + + if (!state.empty()) { + Message(Chat::Red, "[GM] You are currently %s.", Strings::Join(state, ", ").c_str()); + } + } uint32 raidid = database.GetRaidID(GetName()); Raid *raid = nullptr; @@ -755,13 +770,6 @@ void Client::CompleteConnect() conn_state = ClientConnectFinished; - //enforce some rules.. - if (!CanBeInZone()) { - LogDebug("[CLIENT] Kicking char from zone, not allowed here"); - GoToSafeCoords(ZoneID("arena"), 0); - return; - } - if (zone) zone->weatherSend(this); @@ -795,7 +803,7 @@ void Client::CompleteConnect() if (zone && zone->GetInstanceTimer()) { bool is_permanent = false; uint32 remaining_time = database.GetTimeRemainingInstance(zone->GetInstanceID(), is_permanent); - auto time_string = ConvertSecondsToTime(remaining_time); + auto time_string = Strings::SecondsToTime(remaining_time); Message( Chat::Yellow, fmt::format( @@ -893,6 +901,13 @@ void Client::CompleteConnect() } heroforge_wearchange_timer.Start(250); + + // enforce some rules.. + if (!CanEnterZone()) { + LogInfo("Kicking character [{}] from zone, not allowed here (missing requirements)", GetCleanName()); + GoToBind(); + return; + } } // connecting opcode handlers @@ -1184,30 +1199,36 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.RemoveTempFactions(this); database.LoadCharacterFactionValues(cid, factionvalues); - /* Load Character Account Data: Temp until I move */ - query = StringFormat("SELECT `status`, `name`, `ls_id`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme`, `time_creation` FROM `account` WHERE `id` = %u", AccountID()); - auto results = database.QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { - admin = atoi(row[0]); - strn0cpy(account_name, row[1], sizeof(account_name)); - strn0cpy(loginserver, row[2], sizeof(loginserver)); - lsaccountid = atoi(row[3]); - gmspeed = atoi(row[4]); - revoked = atoi(row[5]); - gm_hide_me = atoi(row[6]); - account_creation = atoul(row[7]); + auto a = AccountRepository::FindOne(database, AccountID()); + if (a.id > 0) { + strn0cpy(account_name, a.name.c_str(), sizeof(account_name)); + strn0cpy(loginserver, a.ls_id.c_str(), sizeof(loginserver)); + + admin = a.status; + lsaccountid = a.lsaccount_id; + gmspeed = a.gmspeed; + revoked = a.revoked; + gm_hide_me = a.hideme; + account_creation = a.time_creation; + gminvul = a.invulnerable; + flymode = static_cast(a.flymode); + tellsoff = gm_hide_me; } /* Load Character Data */ - query = StringFormat("SELECT `lfp`, `lfg`, `xtargets`, `firstlogon`, `guild_id`, `rank` FROM `character_data` LEFT JOIN `guild_members` ON `id` = `char_id` WHERE `id` = %i", cid); - results = database.QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + query = fmt::format( + "SELECT `lfp`, `lfg`, `xtargets`, `firstlogon`, `guild_id`, `rank`, `exp_enabled` FROM `character_data` LEFT JOIN `guild_members` ON `id` = `char_id` WHERE `id` = {}", + cid + ); + auto results = database.QueryDatabase(query); + for (auto row : results) { if (row[4] && atoi(row[4]) > 0) { guild_id = atoi(row[4]); - if (row[5] != nullptr) { guildrank = atoi(row[5]); } - else { guildrank = GUILD_RANK_NONE; } + guildrank = row[5] ? atoi(row[5]) : GUILD_RANK_NONE; } + SetEXPEnabled(atobool(row[6])); + if (LFP) { LFP = atoi(row[0]); } if (LFG) { LFG = atoi(row[1]); } if (row[3]) @@ -1266,6 +1287,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* If GM, not trackable */ if (gm_hide_me) { trackable = false; } + if (gminvul) { invulnerable = true; } + if (flymode > 0) { SendAppearancePacket(AT_Levitate, flymode); } /* Set Con State for Reporting */ conn_state = PlayerProfileLoaded; @@ -1318,7 +1341,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) drakkin_details = m_pp.drakkin_details; // Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel - int client_max_level = 0; + uint8 client_max_level = 0; if (RuleB(Character, PerCharacterQglobalMaxLevel)) { client_max_level = GetCharMaxLevelFromQGlobal(); } else if (RuleB(Character, PerCharacterBucketMaxLevel)) { @@ -1510,11 +1533,11 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) LFG = false; } -#ifdef BOTS - database.botdb.LoadOwnerOptions(this); - // TODO: mod below function for loading spawned botgroups - Bot::LoadAndSpawnAllZonedBots(this); -#endif + if (RuleB(Bots, Enabled)) { + database.botdb.LoadOwnerOptions(this); + // TODO: mod below function for loading spawned botgroups + Bot::LoadAndSpawnAllZonedBots(this); + } m_inv.SetGMInventory((bool)m_pp.gm); // set to current gm state for calc CalcBonuses(); @@ -1586,28 +1609,32 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) outapp->priority = 6; FastQueuePacket(&outapp); - if (m_pp.RestTimer) + if (m_pp.RestTimer) { rest_timer.Start(m_pp.RestTimer * 1000); + } - /* Load Pet */ - database.LoadPetInfo(this); - if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { - MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); - if (GetPet() && GetPet()->IsNPC()) { - NPC *pet = GetPet()->CastToNPC(); - pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); - pet->CalcBonuses(); - pet->SetHP(m_petinfo.HP); - pet->SetMana(m_petinfo.Mana); + if (RuleB(NPC, PetZoneWithOwner)) { + /* Load Pet */ + database.LoadPetInfo(this); + if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { + MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, + m_petinfo.Name, m_petinfo.size); + if (GetPet() && GetPet()->IsNPC()) { + NPC *pet = GetPet()->CastToNPC(); + pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); + pet->CalcBonuses(); + pet->SetHP(m_petinfo.HP); + pet->SetMana(m_petinfo.Mana); - // Taunt persists when zoning on newer clients, overwrite default. - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { - if (!firstlogon) { - pet->SetTaunting(m_petinfo.taunting); + // Taunt persists when zoning on newer clients, overwrite default. + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { + if (!firstlogon) { + pet->SetTaunting(m_petinfo.taunting); + } } } + m_petinfo.SpellID = 0; } - m_petinfo.SpellID = 0; } /* Moved here so it's after where we load the pet data. */ if (!aabonuses.ZoneSuspendMinion && !spellbonuses.ZoneSuspendMinion && !itembonuses.ZoneSuspendMinion) { @@ -1705,8 +1732,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) * DevTools Load Settings */ if (Admin() >= EQ::DevTools::GM_ACCOUNT_STATUS_LEVEL) { - std::string dev_tools_window_key = StringFormat("%i-dev-tools-disabled", AccountID()); - if (DataBucket::GetData(dev_tools_window_key) == "true") { + const auto dev_tools_key = fmt::format("{}-dev-tools-disabled", AccountID()); + if (DataBucket::GetData(dev_tools_key) == "true") { dev_tools_enabled = false; } } @@ -1726,11 +1753,14 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) outapp = new EQApplicationPacket(OP_Weather, 12); Weather_Struct *ws = (Weather_Struct *)outapp->pBuffer; ws->val1 = 0x000000FF; - if (zone->zone_weather == 1) { ws->type = 0x31; } // Rain - if (zone->zone_weather == 2) { + + if (zone->zone_weather == EQ::constants::WeatherTypes::Raining) { + ws->type = 0x31; + } else if (zone->zone_weather == EQ::constants::WeatherTypes::Snowing) { outapp->pBuffer[8] = 0x01; - ws->type = 0x02; + ws->type = EQ::constants::WeatherTypes::Snowing; } + outapp->priority = 6; QueuePacket(outapp); safe_delete(outapp); @@ -1806,7 +1836,13 @@ void Client::Handle_OP_AcceptNewTask(const EQApplicationPacket *app) AcceptNewTask_Struct *ant = (AcceptNewTask_Struct*)app->pBuffer; if (ant->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && task_state) - task_state->AcceptNewTask(this, ant->task_id, ant->task_master_id, std::time(nullptr)); + { + if (task_state->CanAcceptNewTask(this, ant->task_id, ant->task_master_id)) + { + task_state->AcceptNewTask(this, ant->task_id, ant->task_master_id, std::time(nullptr)); + } + task_state->ClearLastOffers(); + } } void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app) @@ -1875,7 +1911,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) Adventure_Purchase_Struct* aps = (Adventure_Purchase_Struct*)app->pBuffer; uint32 merchantid = 0; Mob* tmp = entity_list.GetMob(aps->npcid); - if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTUREMERCHANT) && + if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTURE_MERCHANT) && (tmp->GetClass() != DISCORD_MERCHANT) && (tmp->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (tmp->GetClass() != DARK_REIGN_MERCHANT))) return; @@ -2039,6 +2075,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) { PutLootInInventory(EQ::invslot::slotCursor, *inst); } + safe_delete(inst); Save(1); } @@ -2056,7 +2093,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) uint32 merchantid = 0; Mob* tmp = entity_list.GetMob(eid->entity_id); - if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTUREMERCHANT) && + if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTURE_MERCHANT) && (tmp->GetClass() != DISCORD_MERCHANT) && (tmp->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (tmp->GetClass() != DARK_REIGN_MERCHANT))) return; @@ -2127,7 +2164,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) Adventure_Sell_Struct *ams_in = (Adventure_Sell_Struct*)app->pBuffer; Mob* vendor = entity_list.GetMob(ams_in->npcid); - if (vendor == 0 || !vendor->IsNPC() || ((vendor->GetClass() != ADVENTUREMERCHANT) && + if (vendor == 0 || !vendor->IsNPC() || ((vendor->GetClass() != ADVENTURE_MERCHANT) && (vendor->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (vendor->GetClass() != DARK_REIGN_MERCHANT))) { Message(Chat::Red, "Vendor was not found."); @@ -2181,7 +2218,14 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) } // 06/11/2016 This formula matches RoF2 client side calculation. - int32 price = (item->LDoNPrice + 1) * item->LDoNSellBackRate / 100; + uint32 price = EQ::Clamp( + price, + EQ::ClampUpper( + (item->LDoNPrice + 1) * item->LDoNSellBackRate / 100, + item->LDoNPrice + ), + item->LDoNPrice + ); if (price == 0) { @@ -2224,7 +2268,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) switch (vendor->GetClass()) { - case ADVENTUREMERCHANT: + case ADVENTURE_MERCHANT: { UpdateLDoNPoints(6, price); break; @@ -2539,6 +2583,16 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); } + const auto& export_string = fmt::format( + "{} {} {} {} {}", + alt_cur_id, + tar->GetNPCTypeID(), + tar->MerchantType, + item->ID, + cost + ); + parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_BUY, this, export_string, 0); + AddAlternateCurrencyValue(alt_cur_id, -((int32)cost)); int16 charges = 1; if (item->MaxCharges != 0) @@ -2549,6 +2603,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) { PutLootInInventory(EQ::invslot::slotCursor, *inst); } + safe_delete(inst); Save(1); } @@ -2654,7 +2709,15 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) continue; if (item->ID == inst->GetItem()->ID) { - cost = ml.alt_currency_cost; + // 06/11/2016 This formula matches RoF2 client side calculation. + cost = EQ::Clamp( + cost, + EQ::ClampUpper( + static_cast((ml.alt_currency_cost + 1) * item->LDoNSellBackRate / 100), + static_cast(ml.alt_currency_cost) + ), + static_cast(ml.alt_currency_cost) + ); found = true; break; } @@ -2693,6 +2756,16 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); } + const auto& export_string = fmt::format( + "{} {} {} {} {}", + alt_cur_id, + tar->GetNPCTypeID(), + tar->MerchantType, + item->ID, + cost + ); + parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_SELL, this, export_string, 0); + FastQueuePacket(&outapp); AddAlternateCurrencyValue(alt_cur_id, cost); Save(1); @@ -2748,7 +2821,15 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app) continue; if (item->ID == inst->GetItem()->ID) { - cost = ml.alt_currency_cost; + // 06/11/2016 This formula matches RoF2 client side calculation. + cost = EQ::Clamp( + cost, + EQ::ClampUpper( + static_cast((ml.alt_currency_cost + 1) * item->LDoNSellBackRate / 100), + static_cast(ml.alt_currency_cost) + ), + static_cast(ml.alt_currency_cost) + ); found = true; break; } @@ -2767,8 +2848,8 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app) AltCurrencySelectItemReply_Struct *reply = (AltCurrencySelectItemReply_Struct*)outapp->pBuffer; reply->unknown004 = 0xFF; reply->unknown005 = 0xFF; - reply->unknown006 = 0xFF; - reply->unknown007 = 0xFF; + reply->unknown006 = 0xFFFF; + reply->unknown008 = 0xFFFF; strcpy(reply->item_name, inst->GetItem()->Name); reply->cost = cost; FastQueuePacket(&outapp); @@ -3010,13 +3091,26 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (old_aug) { // An old augment was removed in order to be replaced with the new one (augment_action 2) CalcBonuses(); - std::vector args; + std::vector args; args.push_back(old_aug); parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); args.assign(1, tobe_auged); args.push_back(false); parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args); + + const auto export_string = fmt::format( + "{} {} {} {} {}", + tobe_auged->GetID(), + item_slot, + old_aug->GetID(), + in_augment->augment_index, + false + ); + + args.push_back(old_aug); + + parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); } tobe_auged->PutAugment(in_augment->augment_index, *new_aug); @@ -3024,12 +3118,24 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) aug = tobe_auged->GetAugment(in_augment->augment_index); if (aug) { - std::vector args; + std::vector args; args.push_back(aug); parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); args.assign(1, tobe_auged); parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args); + + args.push_back(aug); + + const auto export_string = fmt::format( + "{} {} {} {}", + tobe_auged->GetID(), + item_slot, + aug->GetID(), + in_augment->augment_index + ); + + parse->EventPlayer(EVENT_AUGMENT_INSERT_CLIENT, this, export_string, 0, &args); } else { Message( Chat::Red, @@ -3080,12 +3186,26 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) case AugmentActions::Remove: aug = tobe_auged->GetAugment(in_augment->augment_index); if (aug) { - std::vector args; + std::vector args; args.push_back(aug); parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + args.assign(1, tobe_auged); args.push_back(false); parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); + + args.push_back(aug); + + const auto export_string = fmt::format( + "{} {} {} {} {}", + tobe_auged->GetID(), + item_slot, + aug->GetID(), + in_augment->augment_index, + false + ); + + parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); } else { Message(Chat::Red, "Error: Could not find augmentation to remove at index %i. Aborting.", in_augment->augment_index); return; @@ -3130,12 +3250,26 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) // Augments can be destroyed with a right click -> Destroy at any time. aug = tobe_auged->GetAugment(in_augment->augment_index); if (aug) { - std::vector args; + std::vector args; args.push_back(aug); parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + args.assign(1, tobe_auged); args.push_back(true); parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); + + args.push_back(aug); + + const auto export_string = fmt::format( + "{} {} {} {} {}", + tobe_auged->GetID(), + item_slot, + aug->GetID(), + in_augment->augment_index, + true + ); + + parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); } else { Message( Chat::Red, @@ -3583,7 +3717,7 @@ void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app) return; } else { - LogTrading("Malformed BazaarSearch_Struct packe, Action [{}]t received, ignoring"); + LogTrading("Malformed BazaarSearch_Struct packet received, ignoring"); LogError("Malformed BazaarSearch_Struct packet received, ignoring\n"); } @@ -3672,12 +3806,18 @@ void Client::Handle_OP_Bind_Wound(const EQApplicationPacket *app) LogError("Size mismatch for Bind wound packet"); DumpPacket(app); } + + // Not allowed to forage while mounted + if (RuleB(Character, NoSkillsOnHorse) && GetHorseId()) { + MessageString(Chat::Skills, NO_SKILL_WHILE_MOUNTED); + return; + } + BindWound_Struct* bind_in = (BindWound_Struct*)app->pBuffer; Mob* bindmob = entity_list.GetMob(bind_in->to); if (!bindmob) { LogError("Bindwound on non-exsistant mob from [{}]", GetName()); - } - else { + } else { LogDebug("BindWound in: to:\'[{}]\' from=\'[{}]\'", bindmob->GetName(), GetName()); BindWound(bindmob, true); } @@ -3800,7 +3940,7 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app) } controlling_boat_id = boat->GetID(); // set the client's BoatID to show that it's on this boat - Message(0, "Board boat: %s", boatname); + Message(Chat::White, "Board boat: %s", boatname); return; } @@ -3855,13 +3995,14 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app) { m = entity_list.GetMobID(brrs->EntityID); } -#ifdef BOTS else { - Mob* bot_test = entity_list.GetMob(brrs->EntityID); - if (bot_test && bot_test->IsBot() && bot_test->GetOwner() == this) - m = bot_test; + if (RuleB(Bots, Enabled)) { + Mob *bot_test = entity_list.GetMob(brrs->EntityID); + if (bot_test && bot_test->IsBot() && bot_test->GetOwner() == this) { + m = bot_test; + } + } } -#endif if (!m) return; @@ -3879,36 +4020,25 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app) void Client::Handle_OP_Bug(const EQApplicationPacket *app) { if (!RuleB(Bugs, ReportingSystemActive)) { - Message(0, "Bug reporting is disabled on this server."); + Message(Chat::Red, "Bug reporting is disabled on this server."); return; } if (app->size != sizeof(BugReport_Struct)) { - printf("Wrong size of BugReport_Struct got %d expected %zu!\n", app->size, sizeof(BugReport_Struct)); - } - else { - BugReport_Struct* bug_report = (BugReport_Struct*)app->pBuffer; - - if (RuleB(Bugs, UseOldReportingMethod)) - database.RegisterBug(bug_report); - else - database.RegisterBug(this, bug_report); + LogError("Wrong size of BugReport_Struct got {} expected {}!", app->size, sizeof(BugReport_Struct)); + return; } - return; + auto *r = (BugReport_Struct *) app->pBuffer; + RegisterBug(r); } void Client::Handle_OP_Camp(const EQApplicationPacket *app) { -#ifdef BOTS - // This block is necessary to clean up any bot objects owned by a Client - Bot::BotOrderCampAll(this); - // Evidently, this is bad under certain conditions and causes crashes... - // Group and Raid code really needs to be overhauled to account for non-client types (mercs and bots) - //auto group = GetGroup(); - //if (group && group->GroupCount() < 2) - // group->DisbandGroup(); -#endif + if (RuleB(Bots, Enabled)) { + Bot::BotOrderCampAll(this); + } + if (IsLFP()) worldserver.StopLFP(CharacterID()); @@ -3979,7 +4109,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } if (IsAIControlled()) { MessageString(Chat::Red, NOT_IN_CONTROL); - //Message(Chat::Red, "You cant cast right now, you arent in control of yourself!"); + //Message(Chat::Red, "You cant cast right now, You aren't in control of yourself!"); return; } @@ -4051,7 +4181,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) else { database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, did not meet req level.", zone->GetShortName()); - Message(0, "Error: level not high enough.", castspell->inventoryslot); + Message(Chat::Red, "Error: level not high enough.", castspell->inventoryslot); InterruptSpell(castspell->spell_id); } } @@ -4071,25 +4201,25 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } else { - Message(0, "Error: unknown item->Click.Type (0x%02x)", item->Click.Type); + Message(Chat::Red, "Error: unknown item->Click.Type (0x%02x)", item->Click.Type); } } else { - Message(0, "Error: item not found in inventory slot #%i", castspell->inventoryslot); + Message(Chat::Red, "Error: item not found in inventory slot #%i", castspell->inventoryslot); InterruptSpell(castspell->spell_id); } } else { - Message(0, "Error: castspell->inventoryslot >= %i (0x%04x)", EQ::invslot::slotCursor, castspell->inventoryslot); + Message(Chat::Red, "Error: castspell->inventoryslot >= %i (0x%04x)", EQ::invslot::slotCursor, castspell->inventoryslot); InterruptSpell(castspell->spell_id); } } /* Discipline -- older clients use the same slot as items, but we translate to it's own */ else if (slot == CastingSlot::Discipline) { if (!UseDiscipline(castspell->spell_id, castspell->target_id)) { - LogSpells("Unknown ability being used by [{}], spell being cast is: [{}]\n", GetName(), castspell->spell_id); + LogSpells("Unknown ability being used by [{}] spell being cast is: [{}]\n", GetName(), castspell->spell_id); InterruptSpell(castspell->spell_id); return; } @@ -4209,7 +4339,7 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app) Doors* currentdoor = entity_list.FindDoor(cd->doorid); if (!currentdoor) { - Message(0, "Unable to find door, please notify a GM (DoorID: %i).", cd->doorid); + Message(Chat::Red, "Unable to find door, please notify a GM (DoorID: %i).", cd->doorid); return; } @@ -4222,18 +4352,18 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app) fmt::format( "Door ({}) [{}]", currentdoor->GetEntityID(), - EQ::SayLinkEngine::GenerateQuestSaylink("#door edit", false, "#door edit") + Saylink::Silent("#door edit") ).c_str() ); } std::string export_string = fmt::format("{}", cd->doorid); - std::vector args; + std::vector args; args.push_back(currentdoor); - parse->EventPlayer(EVENT_CLICK_DOOR, this, export_string, 0, &args); - - currentdoor->HandleClick(this, 0); - return; + if (parse->EventPlayer(EVENT_CLICK_DOOR, this, export_string, 0, &args) == 0) + { + currentdoor->HandleClick(this, 0); + } } void Client::Handle_OP_ClickObject(const EQApplicationPacket *app) @@ -4251,7 +4381,7 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app) object->HandleClick(this, click_object); - std::vector args; + std::vector args; args.push_back(object); std::string export_string = fmt::format("{}", click_object->drop_id); @@ -4497,9 +4627,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { rewind_timer.Start(30000, true); } - - is_client_moving = !(cy == m_Position.y && cx == m_Position.x); - + SetMoving(!(cy == m_Position.y && cx == m_Position.x)); /** * Client aggro scanning @@ -4510,11 +4638,11 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { LogAggroDetail( "ClientUpdate [{}] {}moving, scan timer [{}]", GetCleanName(), - is_client_moving ? "" : "NOT ", + IsMoving() ? "" : "NOT ", client_scan_npc_aggro_timer.GetRemainingTime() ); - if (is_client_moving) { + if (IsMoving()) { if (client_scan_npc_aggro_timer.GetRemainingTime() > client_scan_npc_aggro_timer_moving) { LogAggroDetail("Client [{}] Restarting with moving timer", GetCleanName()); client_scan_npc_aggro_timer.Disable(); @@ -4537,11 +4665,11 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { LogAIScanCloseDetail( "Client [{}] {}moving, scan timer [{}]", GetCleanName(), - is_client_moving ? "" : "NOT ", + IsMoving() ? "" : "NOT ", mob_close_scan_timer.GetRemainingTime() ); - if (is_client_moving) { + if (IsMoving()) { if (mob_close_scan_timer.GetRemainingTime() > client_mob_close_scan_timer_moving) { LogAIScanCloseDetail("Client [{}] Restarting with moving timer", GetCleanName()); mob_close_scan_timer.Disable(); @@ -4571,7 +4699,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update ); - if (is_client_moving && is_ready_to_update) { + if (IsMoving() && is_ready_to_update) { LogDebug("[[{}]] Client Zone Wide Position Update NPCs", GetCleanName()); auto &mob_movement_manager = MobMovementManager::Get(); @@ -4614,7 +4742,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { } /* Only feed real time updates when client is moving */ - if (is_client_moving || new_heading != m_Position.w || new_animation != animation) { + if (IsMoving() || new_heading != m_Position.w || new_animation != animation) { animation = ppu->animation; m_Position.w = new_heading; @@ -4844,7 +4972,7 @@ void Client::Handle_OP_ConsiderCorpse(const EQApplicationPacket *app) uint32 decay_time = target->GetDecayTime(); if (decay_time) { - auto time_string = ConvertSecondsToTime(decay_time, true); + auto time_string = Strings::SecondsToTime(decay_time, true); Message( Chat::NPCQuestSay, fmt::format( @@ -5925,107 +6053,11 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) if (app->size != sizeof(FindPersonRequest_Struct)) printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n", sizeof(FindPersonRequest_Struct), app->size); else { - FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer; + auto* t = (FindPersonRequest_Struct*)app->pBuffer; - std::vector points; - Mob* target = entity_list.GetMob(t->npc_id); + auto* m = entity_list.GetMob(t->npc_id); - if (target == nullptr) { - //empty length packet == not found. - EQApplicationPacket outapp(OP_FindPersonReply, 0); - QueuePacket(&outapp); - return; - } - - if (!RuleB(Pathing, Find) && RuleB(Bazaar, EnableWarpToTrader) && target->IsClient() && (target->CastToClient()->Trader || - target->CastToClient()->Buyer)) { - Message(Chat::Yellow, "Moving you to Trader %s", target->GetName()); - MovePC(zone->GetZoneID(), zone->GetInstanceID(), target->GetX(), target->GetY(), target->GetZ(), 0.0f); - } - - if (!RuleB(Pathing, Find) || !zone->pathing) - { - //fill in the path array... - // - points.clear(); - FindPerson_Point a; - FindPerson_Point b; - - a.x = GetX(); - a.y = GetY(); - a.z = GetZ(); - b.x = target->GetX(); - b.y = target->GetY(); - b.z = target->GetZ(); - - points.push_back(a); - points.push_back(b); - } - else - { - glm::vec3 Start(GetX(), GetY(), GetZ() + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION); - glm::vec3 End(target->GetX(), target->GetY(), target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION); - - bool partial = false; - bool stuck = false; - auto pathlist = zone->pathing->FindRoute(Start, End, partial, stuck); - - if (pathlist.empty() || partial) - { - EQApplicationPacket outapp(OP_FindPersonReply, 0); - QueuePacket(&outapp); - return; - } - - // Live appears to send the points in this order: - // Final destination. - // Current Position. - // rest of the points. - FindPerson_Point p; - - int PointNumber = 0; - - bool LeadsToTeleporter = false; - - auto v = pathlist.back(); - - p.x = v.pos.x; - p.y = v.pos.y; - p.z = v.pos.z; - points.push_back(p); - - p.x = GetX(); - p.y = GetY(); - p.z = GetZ(); - points.push_back(p); - - for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator) - { - if ((*Iterator).teleport) // Teleporter - { - LeadsToTeleporter = true; - break; - } - - glm::vec3 v = (*Iterator).pos; - p.x = v.x; - p.y = v.y; - p.z = v.z; - points.push_back(p); - ++PointNumber; - } - - if (!LeadsToTeleporter) - { - p.x = target->GetX(); - p.y = target->GetY(); - p.z = target->GetZ(); - - points.push_back(p); - } - } - - SendPathPacket(points); + SendPath(m); } } @@ -6055,6 +6087,13 @@ void Client::Handle_OP_Forage(const EQApplicationPacket *app) Message(Chat::Red, "Ability recovery time not yet met."); return; } + + // Not allowed to forage while mounted + if (RuleB(Character, NoSkillsOnHorse) && GetHorseId()) { + MessageString(Chat::Skills, NO_SKILL_WHILE_MOUNTED); + return; + } + p_timers.Start(pTimerForaging, ForagingReuseTime - 1); ForageItem(); @@ -6104,17 +6143,26 @@ void Client::Handle_OP_GMBecomeNPC(const EQApplicationPacket *app) BecomeNPC_Struct* bnpc = (BecomeNPC_Struct*)app->pBuffer; Mob* cli = (Mob*)entity_list.GetMob(bnpc->id); - if (cli == 0) + if (cli == nullptr) { return; + } - if (cli->IsClient()) - cli->CastToClient()->QueuePacket(app); - cli->SendAppearancePacket(AT_NPCName, 1, true); - cli->CastToClient()->SetBecomeNPC(true); - cli->CastToClient()->SetBecomeNPCLevel(bnpc->maxlevel); - cli->MessageString(Chat::White, TOGGLE_OFF); - cli->CastToClient()->tellsoff = true; - //TODO: Make this toggle a BecomeNPC flag so that it gets updated when people zone in as well; Make combat work with this. + if (cli->IsClient()) { + Client* target = cli->CastToClient(); + target->QueuePacket(app); + if(target->GetGM()) { + target->SetInvul(false); + target->SetHideMe(false); + target->SetGM(false); + } + + cli->SendAppearancePacket(AT_NPCName, 1, true); + target->SetBecomeNPC(true); + target->SetBecomeNPCLevel(bnpc->maxlevel); + cli->MessageString(Chat::White, TOGGLE_OFF); + target->tellsoff = true; + target->UpdateWho(); + } return; } @@ -6155,10 +6203,10 @@ void Client::Handle_OP_GMEmoteZone(const EQApplicationPacket *app) GMEmoteZone_Struct* gmez = (GMEmoteZone_Struct*)app->pBuffer; char* newmessage = nullptr; if (strstr(gmez->text, "^") == 0) - entity_list.Message(0, 15, gmez->text); + entity_list.Message(Chat::White, 15, gmez->text); else { for (newmessage = strtok((char*)gmez->text, "^"); newmessage != nullptr; newmessage = strtok(nullptr, "^")) - entity_list.Message(0, 15, newmessage); + entity_list.Message(Chat::White, 15, newmessage); } return; } @@ -6225,7 +6273,7 @@ void Client::Handle_OP_GMGoto(const EQApplicationPacket *app) MovePC(zone->GetZoneID(), zone->GetInstanceID(), gt->GetX(), gt->GetY(), gt->GetZ(), gt->GetHeading()); } else if (!worldserver.Connected()) - Message(0, "Error: World server disconnected."); + Message(Chat::Red, "Error: World server disconnected."); else { auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct)); memset(pack->pBuffer, 0, pack->size); @@ -6271,7 +6319,7 @@ void Client::Handle_OP_GMKick(const EQApplicationPacket *app) Client* client = entity_list.GetClientByName(gmk->name); if (client == 0) { if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack->pBuffer; @@ -6313,7 +6361,7 @@ void Client::Handle_OP_GMKill(const EQApplicationPacket *app) } else { if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { auto pack = new ServerPacket(ServerOP_KillPlayer, sizeof(ServerKillPlayer_Struct)); ServerKillPlayer_Struct* skp = (ServerKillPlayer_Struct*)pack->pBuffer; @@ -6375,7 +6423,7 @@ void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app) } Client* client = entity_list.GetClientByName(gmn->oldname); LogInfo("GM([{}]) changeing players name. Old:[{}] New:[{}]", GetName(), gmn->oldname, gmn->newname); - bool usedname = database.CheckUsedName((const char*)gmn->newname); + bool usedname = database.CheckUsedName(gmn->newname); if (client == 0) { Message(Chat::Red, "%s not found for name change. Operation failed!", gmn->oldname); return; @@ -6484,7 +6532,7 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app) void Client::Handle_OP_GMServers(const EQApplicationPacket *app) { if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { auto pack = new ServerPacket(ServerOP_ZoneStatus, strlen(GetName()) + 2); memset(pack->pBuffer, (uint8)admin, 1); @@ -6519,16 +6567,12 @@ void Client::Handle_OP_GMToggle(const EQApplicationPacket *app) GMToggle_Struct *ts = (GMToggle_Struct *)app->pBuffer; if (ts->toggle == 0) { MessageString(Chat::White, TOGGLE_OFF); - //Message(0, "Turning tells OFF"); tellsoff = true; - } - else if (ts->toggle == 1) { - //Message(0, "Turning tells ON"); + } else if (ts->toggle == 1) { MessageString(Chat::White, TOGGLE_ON); tellsoff = false; - } - else { - Message(0, "Unkown value in /toggle packet"); + } else { + Message(Chat::White, "Unkown value in /toggle packet"); } UpdateWho(); return; @@ -6568,7 +6612,7 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app) return; } - GMZoneRequest_Struct* gmzr = (GMZoneRequest_Struct*)app->pBuffer; + auto* gmzr = (GMZoneRequest_Struct*)app->pBuffer; float target_x = -1, target_y = -1, target_z = -1, target_heading; int16 min_status = AccountStatus::Player; @@ -6585,21 +6629,18 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app) strcpy(target_zone, zone_short_name); // this both loads the safe points and does a sanity check on zone name - if (!content_db.GetSafePoints( - target_zone, - 0, - &target_x, - &target_y, - &target_z, - &target_heading, - &min_status, - &min_level - )) { + auto z = GetZone(target_zone, 0); + if (z) { + target_x = z->safe_x; + target_y = z->safe_y; + target_z = z->safe_z; + target_heading = z->safe_heading; + } else { target_zone[0] = 0; } auto outapp = new EQApplicationPacket(OP_GMZoneRequest, sizeof(GMZoneRequest_Struct)); - GMZoneRequest_Struct* gmzr2 = (GMZoneRequest_Struct*)outapp->pBuffer; + auto* gmzr2 = (GMZoneRequest_Struct*)outapp->pBuffer; strcpy(gmzr2->charname, GetName()); gmzr2->zone_id = gmzr->zone_id; gmzr2->x = target_x; @@ -6749,9 +6790,8 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) if (!group) return; -#ifdef BOTS // this block is necessary to allow more control over controlling how bots are zoned or camped. - if (Bot::GroupHasBot(group)) { + if (RuleB(Bots, Enabled) && Bot::GroupHasBot(group)) { if (group->IsLeader(this)) { if ((GetTarget() == 0 || GetTarget() == this) || (group->GroupCount() < 3)) { Bot::ProcessBotGroupDisband(this, std::string()); @@ -6772,9 +6812,10 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) } group = GetGroup(); - if (!group) //We must recheck this here.. incase the final bot disbanded the party..otherwise we crash + if (!group) { return; -#endif + } + Mob* memberToDisband = GetTarget(); if (!memberToDisband) @@ -6964,11 +7005,9 @@ void Client::Handle_OP_GroupInvite2(const EQApplicationPacket *app) } } } -#ifdef BOTS else if (Invitee->IsBot()) { Bot::ProcessBotGroupInvite(this, std::string(Invitee->GetName())); } -#endif } else { @@ -7350,7 +7389,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) } else { - Message(0, "Unable to withdraw 0 quantity of %s", inst->GetItem()->Name); + Message(Chat::Red, "Unable to withdraw 0 quantity of %s", inst->GetItem()->Name); } safe_delete(inst); @@ -7487,13 +7526,13 @@ void Client::Handle_OP_GuildDelete(const EQApplicationPacket *app) LogGuilds("Received OP_GuildDelete"); if (!IsInAGuild() || !guild_mgr.IsGuildLeader(GuildID(), CharacterID())) - Message(0, "You are not a guild leader or not in a guild."); + Message(Chat::Red, "You are not a guild leader or not in a guild."); else { LogGuilds("Deleting guild [{}] ([{}])", guild_mgr.GetGuildName(GuildID()), GuildID()); if (!guild_mgr.DeleteGuild(GuildID())) - Message(0, "Guild delete failed."); + Message(Chat::Red, "Guild delete failed."); else { - Message(0, "Guild successfully deleted."); + Message(Chat::White, "Guild successfully deleted."); } } } @@ -7508,26 +7547,26 @@ void Client::Handle_OP_GuildDemote(const EQApplicationPacket *app) } if (!IsInAGuild()) - Message(0, "Error: You arent in a guild!"); + Message(Chat::Red, "Error: You aren't in a guild!"); else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_DEMOTE)) - Message(0, "You dont have permission to invite."); + Message(Chat::Red, "You don't have permission to demote."); else if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { GuildDemoteStruct* demote = (GuildDemoteStruct*)app->pBuffer; CharGuildInfo gci; if (!guild_mgr.GetCharInfo(demote->target, gci)) { - Message(0, "Unable to find '%s'", demote->target); + Message(Chat::Red, "Unable to find '%s'", demote->target); return; } if (gci.guild_id != GuildID()) { - Message(0, "You aren't in the same guild, what do you think you are doing?"); + Message(Chat::Red, "You aren't in the same guild, what do you think you are doing?"); return; } if (gci.rank < 1) { - Message(0, "%s cannot be demoted any further!", demote->target); + Message(Chat::Red, "%s cannot be demoted any further!", demote->target); return; } uint8 rank = gci.rank - 1; @@ -7543,7 +7582,7 @@ void Client::Handle_OP_GuildDemote(const EQApplicationPacket *app) Message(Chat::Red, "Error while setting rank %d on '%s'.", rank, demote->target); return; } - Message(0, "Successfully demoted %s to rank %d", demote->target, rank); + Message(Chat::White, "Successfully demoted %s to rank %d", demote->target, rank); } // SendGuildMembers(GuildID(), true); return; @@ -7561,11 +7600,11 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) GuildCommand_Struct* gc = (GuildCommand_Struct*)app->pBuffer; if (!IsInAGuild()) - Message(0, "Error: You are not in a guild!"); + Message(Chat::Red, "Error: You are not in a guild!"); else if (gc->officer > GUILD_MAX_RANK) Message(Chat::Red, "Invalid rank."); else if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { //ok, the invite is also used for changing rank as well. @@ -7585,7 +7624,7 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) if (gc->officer < client->GuildRank()) { //demotion if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_DEMOTE)) { - Message(Chat::Red, "You dont have permission to demote."); + Message(Chat::Red, "You don't have permission to demote."); return; } @@ -7607,7 +7646,7 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) else if (gc->officer > client->GuildRank()) { //promotion if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_PROMOTE)) { - Message(Chat::Red, "You dont have permission to demote."); + Message(Chat::Red, "You don't have permission to demote."); return; } @@ -7642,7 +7681,7 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) } if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_INVITE)) { - Message(Chat::Red, "You dont have permission to invite."); + Message(Chat::Red, "You don't have permission to invite."); return; } @@ -7677,13 +7716,6 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) return; } } -#ifdef BOTS - else if (invitee->IsBot()) { - // The guild system is too tightly coupled with the character_data table so we have to avoid using much of the system - Bot::ProcessGuildInvite(this, invitee->CastToBot()); - return; - } -#endif } } @@ -7737,9 +7769,9 @@ void Client::Handle_OP_GuildInviteAccept(const EQApplicationPacket *app) //uint32 tmpeq = gj->guildeqid; if (IsInAGuild() && gj->response == GuildRank()) - Message(0, "Error: You're already in a guild!"); + Message(Chat::Red, "Error: You're already in a guild!"); else if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { LogGuilds("Guild Invite Accept: guild [{}], response [{}], inviter [{}], person [{}]", gj->guildeqid, gj->response, gj->inviter, gj->newmember); @@ -7830,11 +7862,11 @@ void Client::Handle_OP_GuildLeader(const EQApplicationPacket *app) app->pBuffer[app->size - 1] = 0; GuildMakeLeader* gml = (GuildMakeLeader*)app->pBuffer; if (!IsInAGuild()) - Message(0, "Error: You arent in a guild!"); + Message(Chat::Red, "Error: You aren't in a guild!"); else if (GuildRank() != GUILD_LEADER) - Message(0, "Error: You arent the guild leader!"); + Message(Chat::Red, "Error: You aren't the guild leader!"); else if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { //NOTE: we could do cross-zone lookups here... @@ -7847,14 +7879,14 @@ void Client::Handle_OP_GuildLeader(const EQApplicationPacket *app) newleader->GetName(), newleader->CharacterID()); if (guild_mgr.SetGuildLeader(GuildID(), newleader->CharacterID())) { - Message(0, "Successfully Transfered Leadership to %s.", gml->target); + Message(Chat::White, "Successfully Transfered Leadership to %s.", gml->target); newleader->Message(Chat::Yellow, "%s has transfered the guild leadership into your hands.", GetName()); } else - Message(0, "Could not change leadership at this time."); + Message(Chat::Red, "Could not change leadership at this time."); } else - Message(0, "Failed to change leader, could not find target."); + Message(Chat::Red, "Failed to change leader, could not find target."); } // SendGuildMembers(GuildID(), true); return; @@ -7879,7 +7911,7 @@ void Client::Handle_OP_GuildManageBanker(const EQApplicationPacket *app) if (!guild_mgr.GetCharInfo(gmb->member, gci)) { - Message(0, "Unable to find '%s'", gmb->member); + Message(Chat::Red, "Unable to find '%s'", gmb->member); return; } bool IsCurrentlyABanker = guild_mgr.GetBankerFlag(gci.char_id); @@ -7908,7 +7940,7 @@ void Client::Handle_OP_GuildManageBanker(const EQApplicationPacket *app) } if (gci.guild_id != GuildID()) { - Message(0, "You aren't in the same guild, what do you think you are doing?"); + Message(Chat::Red, "You aren't in the same guild, what do you think you are doing?"); return; } @@ -7920,9 +7952,9 @@ void Client::Handle_OP_GuildManageBanker(const EQApplicationPacket *app) } if (NewBankerStatus) - Message(0, "%s has been made a guild banker.", gmb->member); + Message(Chat::White, "%s has been made a guild banker.", gmb->member); else - Message(0, "%s is no longer a guild banker.", gmb->member); + Message(Chat::White, "%s is no longer a guild banker.", gmb->member); } if (IsCurrentlyAnAlt != NewAltStatus) { @@ -7932,9 +7964,9 @@ void Client::Handle_OP_GuildManageBanker(const EQApplicationPacket *app) } if (NewAltStatus) - Message(0, "%s has been marked as an alt.", gmb->member); + Message(Chat::White, "%s has been marked as an alt.", gmb->member); else - Message(0, "%s is no longer marked as an alt.", gmb->member); + Message(Chat::White, "%s is no longer marked as an alt.", gmb->member); } } @@ -7954,21 +7986,21 @@ void Client::Handle_OP_GuildPromote(const EQApplicationPacket *app) } if (!IsInAGuild()) - Message(0, "Error: You arent in a guild!"); + Message(Chat::Red, "Error: You aren't in a guild!"); else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_PROMOTE)) - Message(0, "You dont have permission to invite."); + Message(Chat::Red, "You don't have permission to promote."); else if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { GuildPromoteStruct* promote = (GuildPromoteStruct*)app->pBuffer; CharGuildInfo gci; if (!guild_mgr.GetCharInfo(promote->target, gci)) { - Message(0, "Unable to find '%s'", promote->target); + Message(Chat::Red, "Unable to find '%s'", promote->target); return; } if (gci.guild_id != GuildID()) { - Message(0, "You aren't in the same guild, what do you think you are doing?"); + Message(Chat::Red, "You aren't in the same guild, what do you think you are doing?"); return; } @@ -7976,7 +8008,7 @@ void Client::Handle_OP_GuildPromote(const EQApplicationPacket *app) if (rank > GUILD_OFFICER) { - Message(0, "You cannot promote someone to be guild leader. You must use /guildleader."); + Message(Chat::Red, "You cannot promote someone to be guild leader. You must use /guildleader."); return; } @@ -7991,7 +8023,7 @@ void Client::Handle_OP_GuildPromote(const EQApplicationPacket *app) Message(Chat::Red, "Error while setting rank %d on '%s'.", rank, promote->target); return; } - Message(0, "Successfully promoted %s to rank %d", promote->target, rank); + Message(Chat::White, "Successfully promoted %s to rank %d", promote->target, rank); } return; } @@ -8009,11 +8041,11 @@ void Client::Handle_OP_GuildPublicNote(const EQApplicationPacket *app) CharGuildInfo gci; if (!guild_mgr.GetCharInfo(gpn->target, gci)) { - Message(0, "Unable to find '%s'", gpn->target); + Message(Chat::Red, "Unable to find '%s'", gpn->target); return; } if (gci.guild_id != GuildID()) { - Message(0, "You aren't in the same guild, what do you think you are doing?"); + Message(Chat::Red, "You aren't in the same guild, what do you think you are doing?"); return; } @@ -8026,7 +8058,7 @@ void Client::Handle_OP_GuildPublicNote(const EQApplicationPacket *app) Message(Chat::Red, "Failed to set public note on %s", gpn->target); } else { - Message(0, "Successfully changed public note on %s", gpn->target); + Message(Chat::White, "Successfully changed public note on %s", gpn->target); } // SendGuildMembers(GuildID(), true); return; @@ -8042,24 +8074,20 @@ void Client::Handle_OP_GuildRemove(const EQApplicationPacket *app) } GuildCommand_Struct* gc = (GuildCommand_Struct*)app->pBuffer; if (!IsInAGuild()) - Message(0, "Error: You arent in a guild!"); + Message(Chat::Red, "Error: You aren't in a guild!"); // we can always remove ourself, otherwise, our rank needs remove permissions else if (strcasecmp(gc->othername, GetName()) != 0 && !guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_REMOVE)) - Message(0, "You dont have permission to remove guild members."); + Message(Chat::Red, "You don't have permission to remove guild members."); else if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { -#ifdef BOTS - if (Bot::ProcessGuildRemoval(this, gc->othername)) - return; -#endif uint32 char_id; Client* client = entity_list.GetClientByName(gc->othername); if (client) { if (!client->IsInGuild(GuildID())) { - Message(0, "You aren't in the same guild, what do you think you are doing?"); + Message(Chat::Red, "You aren't in the same guild, what do you think you are doing?"); return; } char_id = client->CharacterID(); @@ -8071,11 +8099,11 @@ void Client::Handle_OP_GuildRemove(const EQApplicationPacket *app) else { CharGuildInfo gci; if (!guild_mgr.GetCharInfo(gc->othername, gci)) { - Message(0, "Unable to find '%s'", gc->othername); + Message(Chat::Red, "Unable to find '%s'", gc->othername); return; } if (gci.guild_id != GuildID()) { - Message(0, "You aren't in the same guild, what do you think you are doing?"); + Message(Chat::Red, "You aren't in the same guild, what do you think you are doing?"); return; } char_id = gci.char_id; @@ -8090,12 +8118,12 @@ void Client::Handle_OP_GuildRemove(const EQApplicationPacket *app) GuildManageRemove_Struct* gm = (GuildManageRemove_Struct*)outapp->pBuffer; gm->guildeqid = GuildID(); strcpy(gm->member, gc->othername); - Message(0, "%s successfully removed from your guild.", gc->othername); + Message(Chat::White, "%s successfully removed from your guild.", gc->othername); entity_list.QueueClientsGuild(this, outapp, false, GuildID()); safe_delete(outapp); } else - Message(0, "Unable to remove %s from your guild.", gc->othername); + Message(Chat::Red, "Unable to remove %s from your guild.", gc->othername); } // SendGuildMembers(GuildID(), true); return; @@ -8406,9 +8434,7 @@ void Client::Handle_OP_InspectRequest(const EQApplicationPacket *app) else { ProcessInspectRequest(tmp->CastToClient(), this); } } -#ifdef BOTS if (tmp != 0 && tmp->IsBot()) { Bot::ProcessBotInspectionRequest(tmp->CastToBot(), this); } -#endif return; } @@ -8470,53 +8496,18 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) response = row[0]; } - if ((response).size() > 0) { + if (!response.empty()) { if (!mod_saylink(response, silentsaylink)) { return; } - if (GetTarget() && GetTarget()->IsNPC()) { - if (silentsaylink) { - parse->EventNPC(EVENT_SAY, GetTarget()->CastToNPC(), this, response, 0); + ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true); - if (response[0] == '#' && parse->PlayerHasQuestSub(EVENT_COMMAND)) { - parse->EventPlayer(EVENT_COMMAND, this, response, 0); - } -#ifdef BOTS - else if (response[0] == '^' && parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) { - parse->EventPlayer(EVENT_BOT_COMMAND, this, response, 0); - } -#endif - else { - parse->EventPlayer(EVENT_SAY, this, response, 0); - } - } - else { - Message(Chat::LightGray, "You say, '%s'", response.c_str()); - ChannelMessageReceived(8, 0, 100, response.c_str()); - } - return; - } - else { - if (silentsaylink) { - if (response[0] == '#' && parse->PlayerHasQuestSub(EVENT_COMMAND)) { - parse->EventPlayer(EVENT_COMMAND, this, response, 0); - } -#ifdef BOTS - else if (response[0] == '^' && parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) { - parse->EventPlayer(EVENT_BOT_COMMAND, this, response, 0); - } -#endif - else { - parse->EventPlayer(EVENT_SAY, this, response, 0); - } - } - else { - Message(Chat::LightGray, "You say, '%s'", response.c_str()); - ChannelMessageReceived(8, 0, 100, response.c_str()); - } - return; + if (!silentsaylink) { + Message(Chat::LightGray, "You say, '%s'", response.c_str()); } + + return; } else { Message(Chat::Red, "Error: Say Link not found or is too long."); @@ -8531,7 +8522,6 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) SendItemPacket(0, inst, ItemPacketViewLink); safe_delete(inst); } - return; } void Client::Handle_OP_ItemLinkResponse(const EQApplicationPacket *app) @@ -8781,20 +8771,20 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } if (slot_id < 0) { - LogDebug("Unknown slot being used by [{}], slot being used is: [{}]", GetName(), request->slot); + LogDebug("Unknown slot being used by [{}] slot being used is [{}]", GetName(), request->slot); return; } const EQ::ItemInstance* inst = m_inv[slot_id]; if (!inst) { - Message(0, "Error: item not found in inventory slot #%i", slot_id); + Message(Chat::Red, "Error: item not found in inventory slot #%i", slot_id); DeleteItemInInventory(slot_id, 0, true); return; } const EQ::ItemData* item = inst->GetItem(); if (!item) { - Message(0, "Error: item not found in inventory slot #%i", slot_id); + Message(Chat::Red, "Error: item not found in inventory slot #%i", slot_id); DeleteItemInInventory(slot_id, 0, true); return; } @@ -8842,7 +8832,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (spell_id > 0 && (spells[spell_id].target_type == ST_Pet || spells[spell_id].target_type == ST_SummonedPet)) target_id = GetPetID(); - LogDebug("OP ItemVerifyRequest: spell=[{}], target=[{}], inv=[{}]", spell_id, target_id, slot_id); + LogDebug("OP ItemVerifyRequest: spell=[{}] target=[{}] inv=[{}]", spell_id, target_id, slot_id); if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQ::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check { @@ -8891,18 +8881,45 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } else if (item->ItemType == EQ::item::ItemTypeSpell) { - if (RuleB(Spells, AllowSpellMemorizeFromItem)) { + spell_id = item->Scroll.Effect; + if (RuleB(Spells, AllowSpellMemorizeFromItem)) + { + int highest_spell_id = GetHighestScribedSpellinSpellGroup(spells[spell_id].spell_group); + if (spells[spell_id].spell_group > 0 && highest_spell_id > 0) + { + if (spells[spell_id].rank > spells[highest_spell_id].rank) + { + std::string message = fmt::format("{} will replace {} in your spellbook", GetSpellName(spell_id), GetSpellName(highest_spell_id)); + SetEntityVariable("slot_id",itoa(slot_id)); + SetEntityVariable("spell_id",itoa(item->ID)); + SendPopupToClient("", message.c_str(), 1000001, 1, 10); + return; + } + else if (spells[spell_id].rank < spells[highest_spell_id].rank) + { + MessageString(Chat::Red, LESSER_SPELL_VERSION, spells[spell_id].name, spells[highest_spell_id].name); + return; + } + } DeleteItemInInventory(slot_id, 1, true); MemorizeSpellFromItem(item->ID); + return; } else { return; } } - else if ((item->Click.Type == EQ::item::ItemEffectClick) || (item->Click.Type == EQ::item::ItemEffectExpendable) || (item->Click.Type == EQ::item::ItemEffectEquipClick) || (item->Click.Type == EQ::item::ItemEffectClick2)) - { + else if ( + item->Click.Effect > 0 && + ( + (item->Click.Type == EQ::item::ItemEffectClick) || + (item->Click.Type == EQ::item::ItemEffectExpendable) || + (item->Click.Type == EQ::item::ItemEffectEquipClick) || + (item->Click.Type == EQ::item::ItemEffectClick2) + ) + ) { if (inst->GetCharges() == 0) { - //Message(0, "This item is out of charges."); + //Message(Chat::White, "This item is out of charges."); MessageString(Chat::Red, ITEM_OUT_OF_CHARGES); return; } @@ -8947,7 +8964,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { if (clickaug->GetCharges() == 0) { - //Message(0, "This item is out of charges."); + //Message(Chat::White, "This item is out of charges."); MessageString(Chat::Red, ITEM_OUT_OF_CHARGES); return; } @@ -9005,12 +9022,12 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } else { - Message(0, "Error: item not found in inventory slot #%i", slot_id); + Message(Chat::Red, "Error: item not found in inventory slot #%i", slot_id); } } else { - Message(0, "Error: Invalid inventory slot for using effects (inventory slot #%i)", slot_id); + Message(Chat::Red, "Error: Invalid inventory slot for using effects (inventory slot #%i)", slot_id); } return; @@ -9107,7 +9124,13 @@ void Client::Handle_OP_LDoNInspect(const EQApplicationPacket *app) { Mob * target = GetTarget(); if (target && target->GetClass() == LDON_TREASURE && !target->IsAura()) - Message(Chat::Yellow, "%s", target->GetCleanName()); + { + std::vector args = { target }; + if (parse->EventPlayer(EVENT_INSPECT, this, "", target->GetID(), &args) == 0) + { + Message(Chat::Yellow, "%s", target->GetCleanName()); + } + } } void Client::Handle_OP_LDoNOpen(const EQApplicationPacket *app) @@ -9229,7 +9252,7 @@ void Client::Handle_OP_LFGCommand(const EQApplicationPacket *app) strn0cpy(LFGComments, lfg->Comments, sizeof(LFGComments)); break; default: - Message(0, "Error: unknown LFG value %i", lfg->value); + Message(Chat::Red, "Error: unknown LFG value %i", lfg->value); } UpdateWho(); @@ -9256,7 +9279,7 @@ void Client::Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app) LFGGetMatchesRequest_Struct* gmrs = (LFGGetMatchesRequest_Struct*)app->pBuffer; if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { auto pack = new ServerPacket(ServerOP_LFGMatches, sizeof(ServerLFGMatchesRequest_Struct)); ServerLFGMatchesRequest_Struct* smrs = (ServerLFGMatchesRequest_Struct*)pack->pBuffer; @@ -9429,7 +9452,7 @@ void Client::Handle_OP_LFPCommand(const EQApplicationPacket *app) for (unsigned int i = 0; ipBuffer; if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { auto pack = new ServerPacket(ServerOP_LFPMatches, sizeof(ServerLFPMatchesRequest_Struct)); ServerLFPMatchesRequest_Struct* smrs = (ServerLFPMatchesRequest_Struct*)pack->pBuffer; @@ -9531,26 +9554,21 @@ void Client::Handle_OP_LootItem(const EQApplicationPacket *app) return; } - EQApplicationPacket* outapp = nullptr; - Entity* entity = entity_list.GetID(*((uint16*)app->pBuffer)); - if (entity == 0) { - Message(Chat::Red, "Error: OP_LootItem: Corpse not found (ent = 0)"); - outapp = new EQApplicationPacket(OP_LootComplete, 0); + auto* l = (LootingItem_Struct*) app->pBuffer; + auto entity = entity_list.GetID(static_cast(l->lootee)); + if (!entity) { + auto outapp = new EQApplicationPacket(OP_LootComplete, 0); QueuePacket(outapp); safe_delete(outapp); return; } - if (entity->IsCorpse()) { - entity->CastToCorpse()->LootItem(this, app); + if (!entity->IsCorpse()) { + Corpse::SendEndLootErrorPacket(this); return; } - else { - Message(Chat::Red, "Error: Corpse not found! (!ent->IsCorpse())"); - Corpse::SendEndLootErrorPacket(this); - } - return; + entity->CastToCorpse()->LootItem(this, app); } void Client::Handle_OP_LootRequest(const EQApplicationPacket *app) @@ -9773,7 +9791,7 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) if (DistanceSquared(m_Position, tar->GetPosition()) > USE_NPC_RANGE2) return; - if (tar->GetClass() != MERCERNARY_MASTER) { + if (tar->GetClass() != MERCENARY_MASTER) { return; } @@ -10850,17 +10868,17 @@ void Client::Handle_OP_Petition(const EQApplicationPacket *app) if (app->size <= 1) return; if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); /*else if(petition_list.FindPetitionByAccountName(AccountName())) { - Message(0,"You already have a petition in queue, you cannot petition again until this one has been responded to or you have deleted the petition."); + Message(Chat::White,"You already have a petition in queue, you cannot petition again until this one has been responded to or you have deleted the petition."); return; }*/ else { if (petition_list.FindPetitionByAccountName(AccountName())) { - Message(0, "You already have a petition in the queue, you must wait for it to be answered or use /deletepetition to delete it."); + Message(Chat::White, "You already have a petition in the queue, you must wait for it to be answered or use /deletepetition to delete it."); return; } auto pet = new Petition(CharacterID()); @@ -10895,7 +10913,7 @@ void Client::Handle_OP_Petition(const EQApplicationPacket *app) void Client::Handle_OP_PetitionBug(const EQApplicationPacket *app) { - Message(0, "Petition Bugs are not supported, please use /bug."); + Message(Chat::White, "Petition Bugs are not supported, please use /bug."); return; } @@ -10928,7 +10946,7 @@ void Client::Handle_OP_PetitionCheckout(const EQApplicationPacket *app) return; } if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { uint32 getpetnum = *((uint32*)app->pBuffer); Petition* getpet = petition_list.GetPetitionByID(getpetnum); @@ -10999,7 +11017,7 @@ void Client::Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app) return; } if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); + Message(Chat::Red, "Error: World server disconnected"); else { uint32 getpetnum = *((uint32*)app->pBuffer); Petition* getpet = petition_list.GetPetitionByID(getpetnum); @@ -11064,35 +11082,30 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) return; p_timers.Start(pTimerBeggingPickPocket, 8); - auto outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); - sPickPocket_Struct* pick_out = (sPickPocket_Struct*)outapp->pBuffer; - pick_out->coin = 0; - pick_out->from = victim->GetID(); - pick_out->to = GetID(); - pick_out->myskill = GetSkill(EQ::skills::SkillPickPockets); - pick_out->type = 0; - //if we do not send this packet the client will lock up and require the player to relog. if (victim == this) { - Message(0, "You catch yourself red-handed."); + Message(Chat::White, "You catch yourself red-handed."); } else if (victim->GetOwnerID()) { - Message(0, "You cannot steal from pets!"); + Message(Chat::White, "You cannot steal from pets!"); + } + else if (victim->IsClient()) { + Message(Chat::White, "Stealing from clients not yet supported."); } else if (Distance(GetPosition(), victim->GetPosition()) > 20) { Message(Chat::Red, "Attempt to pickpocket out of range detected."); database.SetMQDetectionFlag(AccountName(), GetName(), "OP_PickPocket was sent from outside combat range.", zone->GetShortName()); } else if (victim->IsNPC()) { - safe_delete(outapp); - victim->CastToNPC()->PickPocket(this); - return; + auto body = victim->GetBodyType(); + if (body == BT_Humanoid || body == BT_Monster || body == BT_Giant || + body == BT_Lycanthrope) { + victim->CastToNPC()->PickPocket(this); + return; + } } - else { - Message(0, "Stealing from clients not yet supported."); - } - QueuePacket(outapp); - safe_delete(outapp); + + SendPickPocketResponse(victim, 0, PickPocketFailed); } void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) @@ -11107,11 +11120,19 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) PopupResponse_Struct *popup_response = (PopupResponse_Struct *) app->pBuffer; + //Get Item Details if POPUPID_REPLACE_SPELLWINDOW was used + /** * Handle any EQEmu defined popup Ids first */ std::string response; switch (popup_response->popupid) { + case POPUPID_REPLACE_SPELLWINDOW: + DeleteItemInInventory(std::stoi(GetEntityVariable("slot_id")), 1, true); + MemorizeSpellFromItem(std::stoi(GetEntityVariable("spell_id"))); + return; + break; + case POPUPID_UPDATE_SHOWSTATSWINDOW: if (GetTarget() && GetTarget()->IsClient()) { GetTarget()->CastToClient()->SendStatsWindow(this, true); @@ -11123,19 +11144,19 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) break; case POPUPID_DIAWIND_ONE: - if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY.c_str())) { - response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY.c_str()); + if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY)) { + response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY); if (!response.empty()) { - ChannelMessageReceived(8, 0, 100, response.c_str()); + ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true); } } break; case POPUPID_DIAWIND_TWO: - if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY.c_str())) { - response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY.c_str()); + if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY)) { + response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY); if (!response.empty()) { - ChannelMessageReceived(8, 0, 100, response.c_str()); + ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true); } } break; @@ -11148,13 +11169,17 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) break; } - std::string export_string = fmt::format("{}", popup_response->popupid); + const auto export_string = fmt::format("{}", popup_response->popupid); parse->EventPlayer(EVENT_POPUP_RESPONSE, this, export_string, 0); - Mob *Target = GetTarget(); - if (Target && Target->IsNPC()) { - parse->EventNPC(EVENT_POPUP_RESPONSE, Target->CastToNPC(), this, export_string, 0); + auto t = GetTarget(); + if (t) { + if (t->IsNPC()) { + parse->EventNPC(EVENT_POPUP_RESPONSE, t->CastToNPC(), this, export_string, 0); + } else if (t->IsBot()) { + parse->EventBot(EVENT_POPUP_RESPONSE, t->CastToBot(), this, export_string, 0); + } } } @@ -12221,7 +12246,7 @@ void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app) p_recipes_search_struct->query[55] = '\0'; //just to be sure. LogTradeskills( - "[Handle_OP_RecipesSearch] Requested search recipes for object_type [{}] some_id [{}]", + "Requested search recipes for object_type [{}] some_id [{}]", p_recipes_search_struct->object_type, p_recipes_search_struct->some_id ); @@ -12557,7 +12582,7 @@ void Client::Handle_OP_RezzAnswer(const EQApplicationPacket *app) const Resurrect_Struct* ra = (const Resurrect_Struct*)app->pBuffer; - LogSpells("Received OP_RezzAnswer from client. Pendingrezzexp is [{}], action is [{}]", + LogSpells("[Client::Handle_OP_RezzAnswer] Received OP_RezzAnswer from client. Pendingrezzexp is [{}] action is [{}]", PendingRezzXP, ra->action ? "ACCEPT" : "DECLINE"); @@ -12735,7 +12760,7 @@ void Client::Handle_OP_SetGuildMOTD(const EQApplicationPacket *app) guild_mgr.GetGuildName(GuildID()), GuildID(), GetName(), gmotd->motd); if (!guild_mgr.SetGuildMOTD(GuildID(), gmotd->motd, GetName())) { - Message(0, "Motd update failed."); + Message(Chat::Red, "Motd update failed."); } return; @@ -12875,7 +12900,7 @@ void Client::Handle_OP_SetTitle(const EQApplicationPacket *app) return; } - SetTitle_Struct *sts = (SetTitle_Struct *)app->pBuffer; + auto sts = (SetTitle_Struct *) app->pBuffer; if (sts->title_id && !title_manager.HasTitle(this, sts->title_id)) { return; @@ -12892,9 +12917,9 @@ void Client::Handle_OP_SetTitle(const EQApplicationPacket *app) ); if (!sts->is_suffix) { - SetAATitle(title.c_str()); + SetAATitle(title); } else { - SetTitleSuffix(title.c_str()); + SetTitleSuffix(title); } } @@ -12932,22 +12957,25 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) return; } - pTimerType timer = pTimerShieldAbility; + if (!RuleB(Combat, EnableWarriorShielding)) { + Message(Chat::White, "/shield is disabled."); + return; + } + pTimerType timer = pTimerShieldAbility; if (!p_timers.Expired(&database, timer, false)) { - uint32 remaining_time = p_timers.GetRemainingTime(timer); + auto remaining_time = p_timers.GetRemainingTime(timer); Message( Chat::White, fmt::format( "You can use the ability /shield in {}.", - ConvertSecondsToTime(remaining_time) + Strings::SecondsToTime(remaining_time) ).c_str() ); return; } - Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer; - + auto shield = (Shielding_Struct*) app->pBuffer; if (ShieldAbility(shield->target_id, 15, 12000, 50, 25, true, false)) { p_timers.Start(timer, SHIELD_ABILITY_RECAST_TIME); } @@ -13095,7 +13123,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) auto hacker_str = fmt::format("Vendor Cheat: attempted to buy {} of {}: {} that cost {} cp but only has {} pp {} gp {} sp {} cp", mpo->quantity, item->ID, item->Name, mpo->price, m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); - database.SetMQDetectionFlag(AccountName(), GetName(), hacker_str, zone->GetShortName()); + database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); safe_delete(outapp); safe_delete(inst); return; @@ -13218,6 +13246,16 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) if (RuleB(EventLog, RecordBuyFromMerchant)) LogMerchant(this, tmp, mpo->quantity, mpo->price, item, true); + const auto& export_string = fmt::format( + "{} {} {} {} {}", + tmp->GetNPCTypeID(), + tmp->CastToNPC()->MerchantType, + item_id, + mpo->quantity, + mpo->price + ); + parse->EventPlayer(EVENT_MERCHANT_BUY, this, export_string, 0); + if ((RuleB(Character, EnableDiscoveredItems))) { if (!GetGM() && !IsDiscovered(item_id)) @@ -13311,32 +13349,50 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) int charges = mp->quantity; - int freeslot = 0; - if ((freeslot = zone->SaveTempItem(vendor->CastToNPC()->MerchantType, vendor->GetNPCTypeID(), itemid, charges, true)) > 0) { - EQ::ItemInstance* inst2 = inst->Clone(); + if (vendor->GetKeepsSoldItems()) { + int freeslot = 0; + if ( + (freeslot = zone->SaveTempItem( + vendor->CastToNPC()->MerchantType, + vendor->GetNPCTypeID(), + itemid, + charges, + true + ) + ) > 0) { + EQ::ItemInstance *inst2 = inst->Clone(); + + while (true) { + if (!inst2) { + break; + } + + uint32 price = ( + item->Price * + RuleR(Merchant, SellCostMod) * + item->SellRate + ); + + if (RuleB(Merchant, UsePriceMod)) { + price *= Client::CalcPriceMod(vendor, false); + } + + inst2->SetPrice(price); + inst2->SetMerchantSlot(freeslot); + + uint32 merchant_quantity = zone->GetTempMerchantQuantity(vendor->GetNPCTypeID(), freeslot); + + if (inst2->IsStackable()) { + inst2->SetCharges(merchant_quantity); + } + + inst2->SetMerchantCount(merchant_quantity); + + SendItemPacket(freeslot - 1, inst2, ItemPacketMerchant); + safe_delete(inst2); - while (true) { - if (inst2 == nullptr) break; - - if (RuleB(Merchant, UsePriceMod)) { - inst2->SetPrice(item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate*Client::CalcPriceMod(vendor, false)); } - else - inst2->SetPrice(item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate); - inst2->SetMerchantSlot(freeslot); - - uint32 MerchantQuantity = zone->GetTempMerchantQuantity(vendor->GetNPCTypeID(), freeslot); - - if (inst2->IsStackable()) { - inst2->SetCharges(MerchantQuantity); - } - inst2->SetMerchantCount(MerchantQuantity); - - SendItemPacket(freeslot - 1, inst2, ItemPacketMerchant); - safe_delete(inst2); - - break; } } @@ -13375,6 +13431,17 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } // end QS code + const auto& export_string = fmt::format( + "{} {} {} {} {}", + vendor->GetNPCTypeID(), + vendor->CastToNPC()->MerchantType, + itemid, + mp->quantity, + price + ); + parse->EventPlayer(EVENT_MERCHANT_SELL, this, export_string, 0); + + // Now remove the item from the player, this happens regardless of outcome DeleteItemInInventory( mp->itemslot, @@ -13448,7 +13515,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app) } if (GetFeigned() || IsInvisible()) { - Message(0, "You cannot use a merchant right now."); + Message(Chat::White, "You cannot use a merchant right now."); action = 0; } int primaryfaction = tmp->CastToNPC()->GetPrimaryFaction(); @@ -13893,9 +13960,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) } if (GetGM() || RuleB(Spells, AlwaysSendTargetsBuffs) || nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) || (nt->IsPet() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) || -#ifdef BOTS (nt->IsBot() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) || // TODO: bot pets -#endif (nt->IsMerc() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP())) { nt->SendBuffsToClient(this); @@ -14022,7 +14087,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) { auto hacker_str = fmt::format("{} attempting to target something untargetable, {} bodytype: {}", GetName(), GetTarget()->GetName(), (int)GetTarget()->GetBodyType()); - database.SetMQDetectionFlag(AccountName(), GetName(), hacker_str, zone->GetShortName()); + database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); SetTarget((Mob*)nullptr); return; } @@ -14059,7 +14124,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) (zone->newzone_data.maxclip * zone->newzone_data.maxclip), GetX(), GetY(), GetZ(), GetTarget()->GetName(), GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ()); - database.SetMQDetectionFlag(AccountName(), GetName(), hacker_str, zone->GetShortName()); + database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); SetTarget(nullptr); return; } @@ -14073,7 +14138,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) GetName(), (zone->newzone_data.maxclip * zone->newzone_data.maxclip), GetX(), GetY(), GetZ(), GetTarget()->GetName(), GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ()); - database.SetMQDetectionFlag(AccountName(), GetName(), hacker_str, zone->GetShortName()); + database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); SetTarget(nullptr); return; } @@ -14170,16 +14235,14 @@ void Client::Handle_OP_TrackTarget(const EQApplicationPacket *app) return; } - if (app->size != sizeof(TrackTarget_Struct)) - { - LogError("Invalid size for OP_TrackTarget: Expected: [{}], Got: [{}]", - sizeof(TrackTarget_Struct), app->size); + if (app->size != sizeof(TrackTarget_Struct)) { + LogError("Invalid size for OP_TrackTarget: Expected: [{}], Got: [{}]", sizeof(TrackTarget_Struct), app->size); return; } - TrackTarget_Struct *tts = (TrackTarget_Struct*)app->pBuffer; + auto *t = (TrackTarget_Struct*) app->pBuffer; - TrackingID = tts->EntityID; + SetTrackingID(t->EntityID); } void Client::Handle_OP_TrackUnknown(const EQApplicationPacket *app) @@ -14332,11 +14395,9 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) FinishTrade(with->CastToNPC()); } } -#ifdef BOTS // TODO: Log Bot trades else if (with->IsBot()) with->CastToBot()->FinishTrade(this, Bot::BotTradeClientNormal); -#endif trade->Reset(); } @@ -14386,7 +14447,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) { case BazaarTrader_EndTraderMode: { Trader_EndTrader(); - LogTrading("Client::Handle_OP_Trader: End Trader Session"); + LogTrading("End Trader Session"); break; } case BazaarTrader_EndTransaction: { @@ -14395,16 +14456,16 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) if (c) { c->WithCustomer(0); - LogTrading("Client::Handle_OP_Trader: End Transaction"); + LogTrading("End Transaction"); } else - LogTrading("Client::Handle_OP_Trader: Null Client Pointer"); + LogTrading("Null Client Pointer"); break; } case BazaarTrader_ShowItems: { Trader_ShowItems(); - LogTrading("Client::Handle_OP_Trader: Show Trader Items"); + LogTrading("Show Trader Items"); break; } default: { @@ -14427,7 +14488,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) { GetItems_Struct* gis = GetTraderItems(); - LogTrading("Client::Handle_OP_Trader: Start Trader Mode"); + LogTrading("Start Trader Mode"); // Verify there are no NODROP or items with a zero price bool TradeItemsValid = true; @@ -14457,6 +14518,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) if (!TradeItemsValid) { Trader_EndTrader(); + safe_delete(gis); return; } @@ -14490,7 +14552,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) } } else { - LogTrading("Client::Handle_OP_Trader: Unknown TraderStruct code of: [{}]\n", + LogTrading("Unknown TraderStruct code of: [{}]\n", ints->Code); LogError("Unknown TraderStruct code of: [{}]\n", ints->Code); @@ -14500,18 +14562,18 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) { TraderStatus_Struct* tss = (TraderStatus_Struct*)app->pBuffer; - LogTrading("Client::Handle_OP_Trader: Trader Status Code: [{}]", tss->Code); + LogTrading("Trader Status Code: [{}]", tss->Code); switch (tss->Code) { case BazaarTrader_EndTraderMode: { Trader_EndTrader(); - LogTrading("Client::Handle_OP_Trader: End Trader Session"); + LogTrading("End Trader Session"); break; } case BazaarTrader_ShowItems: { Trader_ShowItems(); - LogTrading("Client::Handle_OP_Trader: Show Trader Items"); + LogTrading("Show Trader Items"); break; } default: { @@ -14524,7 +14586,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) } else if (app->size == sizeof(TraderPriceUpdate_Struct)) { - LogTrading("Client::Handle_OP_Trader: Trader Price Update"); + LogTrading("Trader Price Update"); HandleTraderPriceUpdate(app); } else { @@ -14587,11 +14649,7 @@ void Client::Handle_OP_TradeRequest(const EQApplicationPacket *app) if (tradee && tradee->IsClient()) { tradee->CastToClient()->QueuePacket(app); } -#ifndef BOTS - else if (tradee && tradee->IsNPC()) { -#else else if (tradee && (tradee->IsNPC() || tradee->IsBot())) { -#endif if (!tradee->IsEngaged()) { trade->Start(msg->to_mob_id); EQApplicationPacket *outapp = new EQApplicationPacket(OP_TradeRequestAck, sizeof(TradeRequest_Struct)); @@ -14725,18 +14783,18 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app) if (c) { c->WithCustomer(0); - LogTrading("Client::Handle_OP_Trader: End Transaction - Code [{}]", Command); + LogTrading("End Transaction - Code [{}]", Command); } else { - LogTrading("Client::Handle_OP_Trader: Null Client Pointer for Trader - Code [{}]", Command); + LogTrading("Null Client Pointer for Trader - Code [{}]", Command); } EQApplicationPacket empty(OP_ShopEndConfirm); QueuePacket(&empty); } else { - LogTrading("Client::Handle_OP_Trader: Unhandled Code [{}]", Command); + LogTrading("Unhandled Code [{}]", Command); } } else @@ -15288,7 +15346,7 @@ void Client::Handle_OP_YellForHelp(const EQApplicationPacket *app) void Client::Handle_OP_ResetAA(const EQApplicationPacket *app) { if (Admin() >= AccountStatus::Guide) { - Message(0, "Resetting AA points."); + Message(Chat::White, "Resetting AA points."); ResetAA(); } return; @@ -15329,7 +15387,7 @@ void Client::Handle_OP_SharedTaskRemovePlayer(const EQApplicationPacket *app) auto *r = (SharedTaskRemovePlayer_Struct *) app->pBuffer; LogTasks( - "[Handle_OP_SharedTaskRemovePlayer] field1 [{}] field2 [{}] player_name [{}]", + "field1 [{}] field2 [{}] player_name [{}]", r->field1, r->field2, r->player_name @@ -15351,7 +15409,7 @@ void Client::Handle_OP_SharedTaskRemovePlayer(const EQApplicationPacket *app) strn0cpy(rp->player_name, r->player_name, sizeof(r->player_name)); LogTasks( - "[Handle_OP_SharedTaskRemovePlayer] source_character_id [{}] task_id [{}] player_name [{}]", + "source_character_id [{}] task_id [{}] player_name [{}]", rp->source_character_id, rp->task_id, rp->player_name @@ -15376,7 +15434,7 @@ void Client::Handle_OP_SharedTaskAddPlayer(const EQApplicationPacket *app) auto *r = (SharedTaskAddPlayer_Struct *) app->pBuffer; LogTasks( - "[SharedTaskAddPlayer_Struct] field1 [{}] field2 [{}] player_name [{}]", + "field1 [{}] field2 [{}] player_name [{}]", r->field1, r->field2, r->player_name @@ -15384,7 +15442,7 @@ void Client::Handle_OP_SharedTaskAddPlayer(const EQApplicationPacket *app) if (!GetTaskState()->HasActiveSharedTask()) { // this message is generated client-side in newer clients - Message(Chat::System, SharedTaskMessage::GetEQStr(SharedTaskMessage::COULD_NOT_USE_COMMAND)); + Message(Chat::System, TaskStr::Get(TaskStr::COULD_NOT_USE_COMMAND)); } else { // struct @@ -15401,7 +15459,7 @@ void Client::Handle_OP_SharedTaskAddPlayer(const EQApplicationPacket *app) strn0cpy(rp->player_name, r->player_name, sizeof(r->player_name)); LogTasks( - "[Handle_OP_SharedTaskRemovePlayer] source_character_id [{}] task_id [{}] player_name [{}]", + "source_character_id [{}] task_id [{}] player_name [{}]", rp->source_character_id, rp->task_id, rp->player_name @@ -15426,7 +15484,7 @@ void Client::Handle_OP_SharedTaskMakeLeader(const EQApplicationPacket *app) auto *r = (SharedTaskMakeLeader_Struct *) app->pBuffer; LogTasks( - "[SharedTaskMakeLeader_Struct] field1 [{}] field2 [{}] player_name [{}]", + "field1 [{}] field2 [{}] player_name [{}]", r->field1, r->field2, r->player_name @@ -15448,7 +15506,7 @@ void Client::Handle_OP_SharedTaskMakeLeader(const EQApplicationPacket *app) strn0cpy(rp->player_name, r->player_name, sizeof(r->player_name)); LogTasks( - "[Handle_OP_SharedTaskRemovePlayer] source_character_id [{}] task_id [{}] player_name [{}]", + "source_character_id [{}] task_id [{}] player_name [{}]", rp->source_character_id, rp->task_id, rp->player_name @@ -15473,7 +15531,7 @@ void Client::Handle_OP_SharedTaskInviteResponse(const EQApplicationPacket *app) auto *r = (SharedTaskInviteResponse_Struct *) app->pBuffer; LogTasks( - "[SharedTaskInviteResponse] unknown00 [{}] invite_id [{}] accepted [{}]", + "unknown00 [{}] invite_id [{}] accepted [{}]", r->unknown00, r->invite_id, r->accepted @@ -15494,7 +15552,7 @@ void Client::Handle_OP_SharedTaskInviteResponse(const EQApplicationPacket *app) strn0cpy(c->player_name, GetName(), sizeof(c->player_name)); LogTasks( - "[ServerOP_SharedTaskInviteAcceptedPlayer] source_character_id [{}] shared_task_id [{}]", + "source_character_id [{}] shared_task_id [{}]", c->source_character_id, c->shared_task_id ); @@ -15509,15 +15567,20 @@ void Client::Handle_OP_SharedTaskAccept(const EQApplicationPacket* app) auto buf = reinterpret_cast(app->pBuffer); LogTasksDetail( - "[OP_SharedTaskAccept] unknown00 [{}] unknown04 [{}] npc_entity_id [{}] task_id [{}]", + "unknown00 [{}] unknown04 [{}] npc_entity_id [{}] task_id [{}]", buf->unknown00, buf->unknown04, buf->npc_entity_id, buf->task_id ); - if (buf->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && task_state) { - task_state->AcceptNewTask(this, buf->task_id, buf->npc_entity_id, std::time(nullptr)); + if (buf->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && task_state) + { + if (task_state->CanAcceptNewTask(this, buf->task_id, buf->npc_entity_id)) + { + task_state->AcceptNewTask(this, buf->task_id, buf->npc_entity_id, std::time(nullptr)); + } + task_state->ClearLastOffers(); } } @@ -15557,3 +15620,23 @@ void Client::SetSharedTaskId(int64 shared_task_id) { Client::m_shared_task_id = shared_task_id; } + +bool Client::CanTradeFVNoDropItem() +{ + const int16 admin_status = Admin(); + const int no_drop_flag = RuleI(World, FVNoDropFlag); + const int no_drop_min_admin_status = RuleI(Character, MinStatusForNoDropExemptions); + switch (no_drop_flag) { + case FVNoDropFlagRule::Disabled: + return false; + case FVNoDropFlagRule::Enabled: + return true; + case FVNoDropFlagRule::AdminOnly: + return admin_status >= no_drop_min_admin_status; + default: + LogWarning("Invalid value {0} set for FVNoDropFlag", no_drop_flag); + return false; + } + + return false; +} diff --git a/zone/client_process.cpp b/zone/client_process.cpp index b5c56d2e6..ef2fe1b9e 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -42,7 +42,7 @@ #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "event_codes.h" #include "expedition.h" #include "guild_mgr.h" @@ -54,7 +54,7 @@ #include "worldserver.h" #include "zone.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" extern QueryServ* QServ; extern Zone* zone; @@ -124,7 +124,7 @@ bool Client::Process() { } /* I haven't naturally updated my position in 10 seconds, updating manually */ - if (!is_client_moving && position_update_timer.Check()) { + if (!IsMoving() && position_update_timer.Check()) { SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0); } @@ -291,7 +291,7 @@ bool Client::Process() { * Used in aggro checks */ if (mob_close_scan_timer.Check()) { - entity_list.ScanCloseMobs(close_mobs, this, is_client_moving); + entity_list.ScanCloseMobs(close_mobs, this, IsMoving()); } bool may_use_attacks = false; @@ -330,7 +330,7 @@ bool Client::Process() { { if (ranged->GetItem() && ranged->GetItem()->ItemType == EQ::item::ItemTypeBow) { if (ranged_timer.Check(false)) { - if (GetTarget() && (GetTarget()->IsNPC() || GetTarget()->IsClient())) { + if (GetTarget() && (GetTarget()->IsNPC() || GetTarget()->IsClient()) && IsAttackAllowed(GetTarget())) { if (GetTarget()->InFrontMob(this, GetTarget()->GetX(), GetTarget()->GetY())) { if (CheckLosFN(GetTarget())) { //client has built in los check, but auto fire does not.. done last. @@ -350,7 +350,7 @@ bool Client::Process() { } else if (ranged->GetItem() && (ranged->GetItem()->ItemType == EQ::item::ItemTypeLargeThrowing || ranged->GetItem()->ItemType == EQ::item::ItemTypeSmallThrowing)) { if (ranged_timer.Check(false)) { - if (GetTarget() && (GetTarget()->IsNPC() || GetTarget()->IsClient())) { + if (GetTarget() && (GetTarget()->IsNPC() || GetTarget()->IsClient()) && IsAttackAllowed(GetTarget())) { if (GetTarget()->InFrontMob(this, GetTarget()->GetX(), GetTarget()->GetY())) { if (CheckLosFN(GetTarget())) { //client has built in los check, but auto fire does not.. done last. @@ -411,7 +411,7 @@ bool Client::Process() { else if (!los_status || !los_status_facing) { //you can't see your target } - else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP + else if (auto_attack_target->GetHP() > -10 && IsAttackAllowed(auto_attack_target)) // -10 so we can watch people bleed in PvP { EQ::ItemInstance *wpn = GetInv().GetItem(EQ::invslot::slotPrimary); TryCombatProcs(wpn, auto_attack_target, EQ::invslot::slotPrimary); @@ -456,7 +456,7 @@ bool Client::Process() { { //you can't see your target } - else if (auto_attack_target->GetHP() > -10) { + else if (auto_attack_target->GetHP() > -10 && IsAttackAllowed(auto_attack_target)) { CheckIncreaseSkill(EQ::skills::SkillDualWield, auto_attack_target, -10); if (CheckDualWield()) { EQ::ItemInstance *wpn = GetInv().GetItem(EQ::invslot::slotSecondary); @@ -823,10 +823,10 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { const EQ::ItemData *item = nullptr; auto merchant_list = zone->merchanttable[merchant_id]; auto npc = entity_list.GetMobByNpcTypeID(npcid); - if (!merchant_list.size() == 0) { + if (merchant_list.empty()) { zone->LoadNewMerchantData(merchant_id); merchant_list = zone->merchanttable[merchant_id]; - if (!merchant_list.size()) { + if (merchant_list.empty()) { return; } } @@ -855,7 +855,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { continue; } - if (!CheckMerchantDataBucket(ml.bucket_comparison, bucket_value, player_value)) { + if (!zone->CheckDataBucket(ml.bucket_comparison, bucket_value, player_value)) { continue; } } @@ -918,7 +918,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { // Account for merchant lists with gaps. if (ml.slot >= slot_id) { if (ml.slot > slot_id) { - LogDebug("(WARNING) Merchantlist contains gap at slot [{}]. Merchant: [{}], NPC: [{}]", slot_id, merchant_id, npcid); + LogDebug("(WARNING) Merchantlist Contains gap at slot [{}]. Merchant: [{}], NPC: [{}]", slot_id, merchant_id, npcid); } slot_id = ml.slot + 1; @@ -967,7 +967,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { //this resets the slot zone->tmpmerchanttable[npcid] = temporary_merchant_list; if (npc && handy_item) { - int greet_id = zone->random.Int(MERCHANT_GREETING, MERCHANT_HANDY_ITEM4); + int greet_id = zone->random.Int(MERCHANT_GREETING, MERCHANT_HANDY_ITEM4); auto handy_id = std::to_string(greet_id); if (greet_id != MERCHANT_GREETING) { MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, npc->GetCleanName(), handy_id.c_str(), GetName(), handy_item->Name); @@ -1016,11 +1016,14 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I // Mark the corpse as rezzed in the database, just in case the corpse has buried, or the zone the // corpse is in has shutdown since the rez spell was cast. database.MarkCorpseAsRezzed(PendingRezzDBID); - LogSpells("Player [{}] got a [{}] Rezz, spellid [{}] in zone[{}], instance id [{}]", + LogSpells("Player [{}] got a [{}] Rezz spellid [{}] in zone[{}] instance id [{}]", name, (uint16)spells[SpellID].base_value[0], SpellID, ZoneID, InstanceID); - BuffFadeNonPersistDeath(); + if (RuleB(Spells, BuffsFadeOnDeath)) { + BuffFadeNonPersistDeath(); + } + int SpellEffectDescNum = GetSpellEffectDescNum(SpellID); // Rez spells with Rez effects have this DescNum (first is Titanium, second is 6.2 Client) if(RuleB(Character, UseResurrectionSickness) && SpellEffectDescNum == 82 || SpellEffectDescNum == 39067) { @@ -1080,72 +1083,86 @@ void Client::OPTGB(const EQApplicationPacket *app) void Client::OPMemorizeSpell(const EQApplicationPacket* app) { - if(app->size != sizeof(MemorizeSpell_Struct)) - { - LogError("Wrong size on OP_MemorizeSpell. Got: [{}], Expected: [{}]", app->size, sizeof(MemorizeSpell_Struct)); + if (app->size != sizeof(MemorizeSpell_Struct)) { + LogError( + "Wrong size on OP_MemorizeSpell. Got: [{}] Expected: [{}]", + app->size, + sizeof(MemorizeSpell_Struct) + ); DumpPacket(app); return; } - const MemorizeSpell_Struct* memspell = (const MemorizeSpell_Struct*) app->pBuffer; + const auto* m = (MemorizeSpell_Struct*) app->pBuffer; - if(!IsValidSpell(memspell->spell_id)) - { - Message(Chat::Red, "Unexpected error: spell id out of range"); + if (!IsValidSpell(m->spell_id)) { + Message( + Chat::Red, + fmt::format( + "Spell ID {} does not exist or is invalid.", + m->spell_id + ).c_str() + ); return; } - if - ( - GetClass() > 16 || - GetLevel() < spells[memspell->spell_id].classes[GetClass()-1] - ) - { - char val1[20]={0}; - MessageString(Chat::Red,SPELL_LEVEL_TO_LOW,ConvertArray(spells[memspell->spell_id].classes[GetClass()-1],val1),spells[memspell->spell_id].name); - //Message(Chat::Red, "Unexpected error: Class cant use this spell at your level!"); + if ( + m->scribing != memSpellForget && + ( + !EQ::ValueWithin(GetClass(), PLAYER_CLASS_WARRIOR, PLAYER_CLASS_BERSERKER) || + GetLevel() < spells[m->spell_id].classes[GetClass() - 1] + ) + ) { + MessageString( + Chat::Red, + SPELL_LEVEL_TO_LOW, + std::to_string(spells[m->spell_id].classes[GetClass() - 1]).c_str(), + spells[m->spell_id].name + ); return; } - switch(memspell->scribing) - { - case memSpellScribing: { // scribing spell to book - const EQ::ItemInstance* inst = m_inv[EQ::invslot::slotCursor]; + switch (m->scribing) { + case memSpellScribing: { + const auto* inst = m_inv[EQ::invslot::slotCursor]; - if (inst && inst->IsClassCommon()) - { - const EQ::ItemData* item = inst->GetItem(); + if (inst && inst->IsClassCommon()) { + const auto* item = inst->GetItem(); - if (RuleB(Character, RestrictSpellScribing) && !item->IsEquipable(GetRace(), GetClass())) { + if ( + RuleB(Character, RestrictSpellScribing) && + !item->IsEquipable(GetRace(), GetClass()) + ) { MessageString(Chat::Red, CANNOT_USE_ITEM); break; } - if(item && item->Scroll.Effect == (int32)(memspell->spell_id)) - { - ScribeSpell(memspell->spell_id, memspell->slot); + if (item && item->Scroll.Effect == static_cast(m->spell_id)) { + ScribeSpell(m->spell_id, m->slot); DeleteItemInInventory(EQ::invslot::slotCursor, 1, true); + } else { + Message(Chat::Red, "Scribing spell: Item Instance exists but item does not or spell ids do not match."); } - else - Message(0,"Scribing spell: inst exists but item does not or spell ids do not match."); - } - else - Message(0,"Scribing a spell without an inst on your cursor?"); - break; - } - case memSpellMemorize: { // memming spell - if(HasSpellScribed(memspell->spell_id)) - { - MemSpell(memspell->spell_id, memspell->slot); - } - else - { - database.SetMQDetectionFlag(AccountName(), GetName(), "OP_MemorizeSpell but we don't have this spell scribed...", zone->GetShortName()); + } else { + Message(Chat::Red, "Scribing a spell without an Item Instance on your cursor?"); } break; } - case memSpellForget: { // unmemming spell - UnmemSpell(memspell->slot); + case memSpellMemorize: { + if (HasSpellScribed(m->spell_id)) { + MemSpell(m->spell_id, m->slot); + } else { + database.SetMQDetectionFlag( + AccountName(), + GetName(), + "OP_MemorizeSpell but we don't have this spell scribed...", + zone->GetShortName() + ); + } + break; + } + case memSpellForget: { + UnmemSpell(m->slot); break; } } @@ -1834,7 +1851,7 @@ void Client::DoStaminaHungerUpdate() auto outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct *sta = (Stamina_Struct *)outapp->pBuffer; - LogFood("Client::DoStaminaHungerUpdate() hunger_level: [{}] thirst_level: [{}] before loss", m_pp.hunger_level, m_pp.thirst_level); + LogFood("hunger_level: [{}] thirst_level: [{}] before loss", m_pp.hunger_level, m_pp.thirst_level); if (zone->GetZoneID() != 151 && !GetGM()) { int loss = RuleI(Character, FoodLossPerUpdate); @@ -1855,7 +1872,7 @@ void Client::DoStaminaHungerUpdate() sta->water = 6000; } - LogFood("Client::DoStaminaHungerUpdate() Current hunger_level: [{}] = ([{}] minutes left) thirst_level: [{}] = ([{}] minutes left) - after loss", + LogFood("Current hunger_level: [{}] = ([{}] minutes left) thirst_level: [{}] = ([{}] minutes left) - after loss", m_pp.hunger_level, m_pp.hunger_level, m_pp.thirst_level, m_pp.thirst_level); FastQueuePacket(&outapp); @@ -1943,10 +1960,11 @@ void Client::CalcRestState() void Client::DoTracking() { - if (TrackingID == 0) + if (!TrackingID) { return; + } - Mob *m = entity_list.GetMob(TrackingID); + auto *m = entity_list.GetMob(TrackingID); if (!m || m->IsCorpse()) { MessageString(Chat::Skills, TRACK_LOST_TARGET); @@ -1954,29 +1972,43 @@ void Client::DoTracking() return; } - float RelativeHeading = GetHeading() - CalculateHeadingToTarget(m->GetX(), m->GetY()); + if (DistanceNoZ(m->GetPosition(), GetPosition()) < 10) { + Message( + Chat::Skills, + fmt::format( + "You have found {}.", + m->GetCleanName() + ).c_str() + ); + TrackingID = 0; + return; + } - if (RelativeHeading < 0) - RelativeHeading += 512; + float relative_heading = GetHeading() - CalculateHeadingToTarget(m->GetX(), m->GetY()); - if (RelativeHeading > 480) + if (relative_heading < 0) { + relative_heading += 512; + } + + if (relative_heading > 480) { MessageString(Chat::Skills, TRACK_STRAIGHT_AHEAD, m->GetCleanName()); - else if (RelativeHeading > 416) + } else if (relative_heading > 416) { MessageString(Chat::Skills, TRACK_AHEAD_AND_TO, m->GetCleanName(), "left"); - else if (RelativeHeading > 352) + } else if (relative_heading > 352) { MessageString(Chat::Skills, TRACK_TO_THE, m->GetCleanName(), "left"); - else if (RelativeHeading > 288) + } else if (relative_heading > 288) { MessageString(Chat::Skills, TRACK_BEHIND_AND_TO, m->GetCleanName(), "left"); - else if (RelativeHeading > 224) + } else if (relative_heading > 224) { MessageString(Chat::Skills, TRACK_BEHIND_YOU, m->GetCleanName()); - else if (RelativeHeading > 160) + } else if (relative_heading > 160) { MessageString(Chat::Skills, TRACK_BEHIND_AND_TO, m->GetCleanName(), "right"); - else if (RelativeHeading > 96) + } else if (relative_heading > 96) { MessageString(Chat::Skills, TRACK_TO_THE, m->GetCleanName(), "right"); - else if (RelativeHeading > 32) + } else if (relative_heading > 32) { MessageString(Chat::Skills, TRACK_AHEAD_AND_TO, m->GetCleanName(), "right"); - else if (RelativeHeading >= 0) + } else if (relative_heading >= 0) { MessageString(Chat::Skills, TRACK_STRAIGHT_AHEAD, m->GetCleanName()); + } } void Client::HandleRespawnFromHover(uint32 Option) @@ -2035,6 +2067,7 @@ void Client::HandleRespawnFromHover(uint32 Option) if (PendingRezzXP < 0 || PendingRezzSpellID == 0) { LogSpells("Unexpected Rezz from hover request"); + safe_delete(default_to_bind); return; } SetHP(GetMaxHP() / 5); diff --git a/zone/combat_record.cpp b/zone/combat_record.cpp index 28de1c8ab..8d746b52d 100644 --- a/zone/combat_record.cpp +++ b/zone/combat_record.cpp @@ -1,6 +1,6 @@ #include "combat_record.h" #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" void CombatRecord::Start(std::string in_mob_name) { @@ -22,7 +22,7 @@ void CombatRecord::Stop() mob_name, time_in_combat > 0 ? (damage_received / time_in_combat) : damage_received, time_in_combat > 0 ? (heal_received / time_in_combat) : heal_received, - time_in_combat > 0 ? ConvertSecondsToTime(time_in_combat) : "", + time_in_combat > 0 ? Strings::SecondsToTime(time_in_combat) : "", time_in_combat ); } diff --git a/zone/command.cpp b/zone/command.cpp old mode 100755 new mode 100644 index 43e755a7c..9b61bb427 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -16,10 +16,10 @@ #include "../common/features.h" #include "../common/ptimer.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/say_link.h" #include "../common/net/eqstream.h" -#include "../common/file_util.h" +#include "../common/file.h" #include "../common/repositories/dynamic_zones_repository.h" #include "data_bucket.h" @@ -44,17 +44,16 @@ extern FastMath g_Math; void CatchSignal(int sig_num); -int commandcount; // how many commands we have +int command_count; // how many commands we have // this is the pointer to the dispatch function, updated once // init has been performed to point at the real function -int (*command_dispatch)(Client *,char const *)=command_notavail; +int (*command_dispatch)(Client *, std::string, bool) = command_notavail; std::map commandlist; std::map commandaliases; - -// All allocated CommandRecords get put in here so they get deleted on shutdown -LinkedList cleanup_commandlist; +std::vector command_delete_list; +std::map commands_map; /* * command_notavail @@ -64,39 +63,12 @@ LinkedList cleanup_commandlist; * not used * */ -int command_notavail(Client *c, const char *message) +int command_notavail(Client *c, std::string message, bool ignore_status) { - c->Message(Chat::Red, "Commands not available."); + c->Message(Chat::White, "Commands not available."); return -1; } -/************************************************************************** -/* the rest below here could be in a dynamically loaded module eventually * -/*************************************************************************/ - -/* - -Access Levels: - -0 Normal -10 * Steward * -20 * Apprentice Guide * -50 * Guide * -80 * QuestTroupe * -81 * Senior Guide * -85 * GM-Tester * -90 * EQ Support * -95 * GM-Staff * -100 * GM-Admin * -150 * GM-Lead Admin * -160 * QuestMaster * -170 * GM-Areas * -180 * GM-Coder * -200 * GM-Mgmt * -250 * GM-Impossible * - -*/ - /* * command_init * initializes the command list, call at startup @@ -111,7 +83,9 @@ Access Levels: int command_init(void) { - commandaliases.clear(); + if (!commandaliases.empty()) { + command_deinit(); + } if ( command_add("acceptrules", "[acceptrules] - Accept the EQEmu Agreement", AccountStatus::Player, command_acceptrules) || @@ -120,159 +94,161 @@ int command_init(void) command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", AccountStatus::GMAdmin, command_aggrozone) || command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", AccountStatus::GMAdmin, command_ai) || command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", AccountStatus::GMLeadAdmin, command_appearance) || - command_add("appearanceeffects", "- [view] [set] [remove] appearance effects.", AccountStatus::GMAdmin, command_appearanceeffects) || + command_add("appearanceeffects", "[view] [set] [remove] appearance effects.", AccountStatus::GMAdmin, command_appearanceeffects) || command_add("apply_shared_memory", "[shared_memory_name] - Tells every zone and world to apply a specific shared memory segment by name.", AccountStatus::GMImpossible, command_apply_shared_memory) || command_add("attack", "[Entity Name] - Make your NPC target attack an entity by name", AccountStatus::GMLeadAdmin, command_attack) || - command_add("augmentitem", "Force augments an item. Must have the augment item window open.", AccountStatus::GMImpossible, command_augmentitem) || - command_add("ban", "[Character Name] [Reason]- Ban by character name", AccountStatus::GMLeadAdmin, command_ban) || - command_add("bind", "- Sets your targets bind spot to their current location", AccountStatus::GMMgmt, command_bind) || - -#ifdef BOTS - command_add("bot", "- Type \"#bot help\" or \"^help\" to the see the list of available commands for bots.", AccountStatus::Player, command_bot) || -#endif - - command_add("camerashake", "[Duration (Milliseconds)] [Intensity (1-10)] - Shakes the camera on everyone's screen globally.", AccountStatus::QuestTroupe, command_camerashake) || + command_add("augmentitem", "Force augments an item. Must have the augment item window open.", AccountStatus::GMImpossible, command_augmentitem) || + command_add("ban", "[Character Name] [Reason] - Ban by character name", AccountStatus::GMLeadAdmin, command_ban) || + command_add("bind", "Sets your targets bind spot to their current location", AccountStatus::GMMgmt, command_bind) || + command_add("bugs", "[Close|Delete|Review|Search|View] - Handles player bug reports", AccountStatus::QuestTroupe, command_bugs) || + command_add("bot", "Type \"#bot help\" or \"^help\" to the see the list of available commands for bots.", AccountStatus::Player, command_bot) || + command_add("camerashake", "[Duration (Milliseconds)] [Intensity (1-10)] - Shakes the camera on everyone's screen globally.", AccountStatus::QuestTroupe, command_camerashake) || command_add("castspell", "[Spell ID] [Instant (0 = False, 1 = True, Default is 1 if Unused)] - Cast a spell", AccountStatus::Guide, command_castspell) || - command_add("chat", "[channel num] [message] - Send a channel message to all zones", AccountStatus::GMMgmt, command_chat) || - command_add("checklos", "- Check for line of sight to your target", AccountStatus::Guide, command_checklos) || - command_add("copycharacter", "[source_char_name] [dest_char_name] [dest_account_name] Copies character to destination account", AccountStatus::GMImpossible, command_copycharacter) || - command_add("corpse", "- Manipulate corpses, use with no arguments for help", AccountStatus::Guide, command_corpse) || + command_add("chat", "[Channel ID] [Message] - Send a channel message to all zones", AccountStatus::GMMgmt, command_chat) || + command_add("checklos", "Check for line of sight to your target", AccountStatus::Guide, command_checklos) || + command_add("copycharacter", "[source_char_name] [dest_char_name] [dest_account_name] - Copies character to destination account", AccountStatus::GMImpossible, command_copycharacter) || + command_add("corpse", "Manipulate corpses, use with no arguments for help", AccountStatus::Guide, command_corpse) || command_add("corpsefix", "Attempts to bring corpses from underneath the ground within close proximity of the player", AccountStatus::Player, command_corpsefix) || command_add("countitem", "[Item ID] - Counts the specified Item ID in your or your target's inventory", AccountStatus::GMLeadAdmin, command_countitem) || - command_add("cvs", "- Summary of client versions currently online.", AccountStatus::GMMgmt, command_cvs) || + command_add("cvs", "Summary of client versions currently online.", AccountStatus::GMMgmt, command_cvs) || command_add("damage", "[Amount] - Damage yourself or your target", AccountStatus::GMAdmin, command_damage) || command_add("databuckets", "View|Delete [key] [limit]- View data buckets, limit 50 default or Delete databucket by key", AccountStatus::QuestTroupe, command_databuckets) || - command_add("date", "[yyyy] [mm] [dd] [HH] [MM] - Set EQ time", AccountStatus::EQSupport, command_date) || - command_add("dbspawn2", "[spawngroup] [respawn] [variance] - Spawn an NPC from a predefined row in the spawn2 table", AccountStatus::GMAdmin, command_dbspawn2) || - command_add("delacct", "[accountname] - Delete an account", AccountStatus::GMLeadAdmin, command_delacct) || - command_add("deletegraveyard", "[zone name] - Deletes the graveyard for the specified zone.", AccountStatus::GMMgmt, command_deletegraveyard) || + command_add("date", "[Year] [Month] [Day] [Hour] [Minute] - Set EQ time (Hour and Minute are optional)", AccountStatus::EQSupport, command_date) || + command_add("dbspawn2", "[Spawngroup ID] [Respawn] [Variance] [Condition ID] [Condition Minimum] - Spawn an NPC from a predefined row in the spawn2 table, Respawn and Variance are in Seconds (condition is optional)", AccountStatus::GMAdmin, command_dbspawn2) || + command_add("delacct", "[Account ID|Account Name] - Delete an account by ID or Name", AccountStatus::GMLeadAdmin, command_delacct) || command_add("delpetition", "[petition number] - Delete a petition", AccountStatus::ApprenticeGuide, command_delpetition) || - command_add("depop", "- Depop your NPC target", AccountStatus::Guide, command_depop) || - command_add("depopzone", "- Depop the zone", AccountStatus::GMAdmin, command_depopzone) || - command_add("devtools", "- Manages devtools", AccountStatus::GMMgmt, command_devtools) || - command_add("disablerecipe", "[Recipe ID] - Disables a Recipe", AccountStatus::QuestTroupe, command_disablerecipe) || - command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", AccountStatus::QuestTroupe, command_disarmtrap) || - command_add("distance", "- Reports the distance between you and your target.", AccountStatus::QuestTroupe, command_distance) || + command_add("depop", "[Start Spawn Timer] - Depop your NPC target and optionally start their spawn timer (false by default)", AccountStatus::Guide, command_depop) || + command_add("depopzone", "[Start Spawn Timers] - Depop the zone and optionally start spawn timers (false by default)", AccountStatus::GMAdmin, command_depopzone) || + command_add("devtools", "[Enable|Disable] - Manages Developer Tools (send no parameter for menu)", AccountStatus::GMMgmt, command_devtools) || + command_add("disablerecipe", "[Recipe ID] - Disables a Recipe", AccountStatus::QuestTroupe, command_disablerecipe) || + command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", AccountStatus::QuestTroupe, command_disarmtrap) || + command_add("distance", "Reports the distance between you and your target.", AccountStatus::QuestTroupe, command_distance) || command_add("door", "Door editing command", AccountStatus::QuestTroupe, command_door) || - command_add("doanim", "[animnum] [type] - Send an EmoteAnim for you or your target", AccountStatus::Guide, command_doanim) || + command_add("doanim", "[Animation ID|Animation Name] [Speed] - Send an animation by ID or name at the specified speed to you or your target (Speed is optional)", AccountStatus::Guide, command_doanim) || command_add("dye", "[slot|'help'] [red] [green] [blue] [use_tint] - Dyes the specified armor slot to Red, Green, and Blue provided, allows you to bypass darkness limits.", AccountStatus::ApprenticeGuide, command_dye) || command_add("dz", "Manage expeditions and dynamic zone instances", AccountStatus::QuestTroupe, command_dz) || command_add("dzkickplayers", "Removes all players from current expedition. (/kickplayers alternative for pre-RoF clients)", AccountStatus::Player, command_dzkickplayers) || command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", AccountStatus::GMAdmin, command_editmassrespawn) || - command_add("emote", "['name'/'world'/'zone'] [type] [message] - Send an emote message", AccountStatus::QuestTroupe, command_emote) || - command_add("emotesearch", "Searches NPC Emotes", AccountStatus::QuestTroupe, command_emotesearch) || + command_add("emote", "[Name|World|Zone] [type] [message] - Send an emote message by name, to the world, or to your zone (^ separator allows multiple messages to be sent at once)", AccountStatus::QuestTroupe, command_emote) || + command_add("emotesearch", "[Search Criteria] - Search for NPC Emotes", AccountStatus::QuestTroupe, command_emotesearch) || command_add("emoteview", "Lists all NPC Emotes", AccountStatus::QuestTroupe, command_emoteview) || - command_add("emptyinventory", "- Clears your or your target's entire inventory (Equipment, General, Bank, and Shared Bank)", AccountStatus::GMImpossible, command_emptyinventory) || - command_add("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) || + command_add("emptyinventory", "Clears your or your target's entire inventory (Equipment, General, Bank, and Shared Bank)", AccountStatus::GMImpossible, command_emptyinventory) || + command_add("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) || command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) || command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", AccountStatus::Guide, command_equipitem) || + command_add("exptoggle", "[Toggle] - Toggle your or your target's experience gain.", AccountStatus::QuestTroupe, command_exptoggle) || command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) || - command_add("feature", "- Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) || - command_add("findaliases", "[search criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) || - command_add("findclass", "[search criteria] - Search for a class", AccountStatus::Guide, command_findclass) || - command_add("findfaction", "[search criteria] - Search for a faction", AccountStatus::Guide, command_findfaction) || - command_add("findnpctype", "[search criteria] - Search database NPC types", AccountStatus::GMAdmin, command_findnpctype) || - command_add("findrace", "[search criteria] - Search for a race", AccountStatus::Guide, command_findrace) || - command_add("findskill", "[search criteria] - Search for a skill", AccountStatus::Guide, command_findskill) || - command_add("findspell", "[search criteria] - Search for a spell", AccountStatus::Guide, command_findspell) || - command_add("findtask", "[search criteria] - Search for a task", AccountStatus::Guide, command_findtask) || - command_add("findzone", "[search criteria] - Search database zones", AccountStatus::GMAdmin, command_findzone) || + command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) || + command_add("feature", "Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) || + command_add("size", "Change your targets size (alias of #feature size)", AccountStatus::QuestTroupe, command_feature) || + command_add("findaa", "[Search Criteria] - Search for an AA", AccountStatus::Guide, command_findaa) || + command_add("findaliases", "[Search Criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) || + command_add("findcharacter", "[Search Criteria] - Search for a character", AccountStatus::Guide, command_findcharacter) || + command_add("findclass", "[Search Criteria] - Search for a class", AccountStatus::Guide, command_findclass) || + command_add("findfaction", "[Search Criteria] - Search for a faction", AccountStatus::Guide, command_findfaction) || + command_add("findnpctype", "[Search Criteria] - Search database NPC types", AccountStatus::GMAdmin, command_findnpctype) || + command_add("findrace", "[Search Criteria] - Search for a race", AccountStatus::Guide, command_findrace) || + command_add("findrecipe", "[Search Criteria] - Search for a recipe", AccountStatus::Guide, command_findrecipe) || + command_add("findskill", "[Search Criteria] - Search for a skill", AccountStatus::Guide, command_findskill) || + command_add("findspell", "[Search Criteria] - Search for a spell", AccountStatus::Guide, command_findspell) || + command_add("findtask", "[Search Criteria] - Search for a task", AccountStatus::Guide, command_findtask) || + command_add("findzone", "[Search Criteria] - Search database zones", AccountStatus::GMAdmin, command_findzone) || command_add("fixmob", "[race|gender|texture|helm|face|hair|haircolor|beard|beardcolor|heritage|tattoo|detail] [next|prev] - Manipulate appearance of your target", AccountStatus::QuestTroupe, command_fixmob) || command_add("flag", "[Status] [Account Name] - Refresh your admin status, or set an account's Admin status if arguments provided", AccountStatus::Player, command_flag) || - command_add("flagedit", "- Edit zone flags on your target. Use #flagedit help for more info.", AccountStatus::GMAdmin, command_flagedit) || - command_add("flags", "- displays the Zone Flags of you or your target", AccountStatus::Player, command_flags) || + command_add("flagedit", "Edit zone flags on your target. Use #flagedit help for more info.", AccountStatus::GMAdmin, command_flagedit) || + command_add("flags", "displays the Zone Flags of you or your target", AccountStatus::Player, command_flags) || command_add("flymode", "[0/1/2/3/4/5] - Set your or your player target's flymode to ground/flying/levitate/water/floating/levitate_running", AccountStatus::Guide, command_flymode) || - command_add("fov", "- Check wether you're behind or in your target's field of view", AccountStatus::QuestTroupe, command_fov) || - command_add("freeze", "- Freeze your target", AccountStatus::QuestTroupe, command_freeze) || + command_add("fov", "Check wether you're behind or in your target's field of view", AccountStatus::QuestTroupe, command_fov) || + command_add("freeze", "Freeze your target", AccountStatus::QuestTroupe, command_freeze) || command_add("gassign", "[Grid ID] - Assign targetted NPC to predefined wandering grid id", AccountStatus::GMAdmin, command_gassign) || - command_add("gearup", "Developer tool to quickly equip a character", AccountStatus::GMMgmt, command_gearup) || + command_add("gearup", "Developer tool to quickly equip yourself or your target", AccountStatus::GMMgmt, command_gearup) || command_add("gender", "[0/1/2] - Change your or your target's gender to male/female/neuter", AccountStatus::Guide, command_gender) || - command_add("getplayerburiedcorpsecount", "- Get your or your target's total number of buried player corpses.", AccountStatus::GMAdmin, command_getplayerburiedcorpsecount) || + command_add("getplayerburiedcorpsecount", "Get your or your target's total number of buried player corpses.", AccountStatus::GMAdmin, command_getplayerburiedcorpsecount) || command_add("getvariable", "[Variable Name] - Get the value of a variable from the database", AccountStatus::GMMgmt, command_getvariable) || - command_add("ginfo", "- get group info on target.", AccountStatus::ApprenticeGuide, command_ginfo) || + command_add("ginfo", "get group info on target.", AccountStatus::ApprenticeGuide, command_ginfo) || command_add("giveitem", "[itemid] [charges] - Summon an item onto your target's cursor. Charges are optional.", AccountStatus::GMMgmt, command_giveitem) || command_add("givemoney", "[Platinum] [Gold] [Silver] [Copper] - Gives specified amount of money to you or your player target", AccountStatus::GMMgmt, command_givemoney) || command_add("globalview", "Lists all qglobals in cache if you were to do a quest with this target.", AccountStatus::QuestTroupe, command_globalview) || command_add("gm", "[On|Off] - Modify your or your target's GM Flag", AccountStatus::QuestTroupe, command_gm) || command_add("gmspeed", "[On|Off] - Turn GM Speed On or Off for you or your player target", AccountStatus::GMAdmin, command_gmspeed) || command_add("gmzone", "[Zone ID|Zone Short Name] [Version] [Instance Identifier] - Zones to a private GM instance (Version defaults to 0 and Instance Identifier defaults to 'gmzone' if not used)", AccountStatus::GMAdmin, command_gmzone) || + command_add("godmode", "[on/off] - Turns on/off hideme, gmspeed, invul, and flymode.", AccountStatus::GMMgmt, command_godmode) || command_add("goto", "[playername] or [x y z] [h] - Teleport to the provided coordinates or to your target", AccountStatus::Steward, command_goto) || command_add("grid", "[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid", AccountStatus::GMAreas, command_grid) || - command_add("guild", "- Guild manipulation commands. Use argument help for more info.", AccountStatus::Steward, command_guild) || + command_add("guild", "Guild manipulation commands. Use argument help for more info.", AccountStatus::Steward, command_guild) || command_add("guildapprove", "[guildapproveid] - Approve a guild with specified ID (guild creator receives the id)", AccountStatus::Player, command_guildapprove) || command_add("guildcreate", "[guildname] - Creates an approval setup for guild name specified", AccountStatus::Player, command_guildcreate) || command_add("guildlist", "[guildapproveid] - Lists character names who have approved the guild specified by the approve id", AccountStatus::Player, command_guildlist) || command_add("haste", "[percentage] - Set your haste percentage", AccountStatus::GMAdmin, command_haste) || - command_add("hatelist", "- Display hate list for NPC.", AccountStatus::QuestTroupe, command_hatelist) || - command_add("heal", "- Completely heal your target", AccountStatus::Steward, command_heal) || - command_add("help", "[search term] - List available commands and their description, specify partial command as argument to search", AccountStatus::Player, command_help) || - command_add("heromodel", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.", AccountStatus::GMMgmt, command_heromodel) || + command_add("hatelist", "Display hate list for NPC.", AccountStatus::QuestTroupe, command_hatelist) || + command_add("heal", "Completely heal your target", AccountStatus::Steward, command_heal) || + command_add("help", "[Search Criteria] - List available commands and their description, specify partial command as argument to search", AccountStatus::Player, command_help) || + command_add("heromodel", "[Hero Model] [Slot] - Set your or your target's appearance to a full set of Hero's Forge Armor, if slot is set, sends exact model just to slot.", AccountStatus::GMMgmt, command_heromodel) || command_add("hideme", "[on/off] - Hide yourself from spawn lists.", AccountStatus::QuestTroupe, command_hideme) || command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix, equiv to load_shared_memory followed by apply_shared_memory", AccountStatus::GMImpossible, command_hotfix) || - command_add("hp", "- Refresh your HP bar from the server.", AccountStatus::Player, command_hp) || - command_add("incstat", "- Increases or Decreases a client's stats permanently.", AccountStatus::GMMgmt, command_incstat) || - command_add("instance", "- Modify Instances", AccountStatus::GMMgmt, command_instance) || - command_add("interrogateinv", "- use [help] argument for available options", AccountStatus::Player, command_interrogateinv) || + command_add("hp", "Refresh your HP bar from the server.", AccountStatus::Player, command_hp) || + command_add("incstat", "Increases or Decreases a client's stats permanently.", AccountStatus::GMMgmt, command_incstat) || + command_add("instance", "Modify Instances", AccountStatus::GMMgmt, command_instance) || + command_add("interrogateinv", "use [help] argument for available options", AccountStatus::Player, command_interrogateinv) || command_add("interrupt", "[message id] [color] - Interrupt your casting. Arguments are optional.", AccountStatus::Guide, command_interrupt) || - command_add("invsnapshot", "- Manipulates inventory snapshots for your current target", AccountStatus::QuestTroupe, command_invsnapshot) || + command_add("invsnapshot", "Manipulates inventory snapshots for your current target", AccountStatus::QuestTroupe, command_invsnapshot) || command_add("invul", "[On|Off]] - Turn player target's or your invulnerable flag on or off", AccountStatus::QuestTroupe, command_invul) || command_add("ipban", "[IP] - Ban IP", AccountStatus::GMMgmt, command_ipban) || command_add("iplookup", "[charname] - Look up IP address of charname", AccountStatus::GMMgmt, command_iplookup) || - command_add("iteminfo", "- Get information about the item on your cursor", AccountStatus::Steward, command_iteminfo) || - command_add("itemsearch", "[search criteria] - Search for an item", AccountStatus::Steward, command_itemsearch) || + command_add("itemsearch", "[Search Criteria] - Search for an item", AccountStatus::Steward, command_itemsearch) || command_add("kick", "[Character Name] - Disconnect a player by name", AccountStatus::GMLeadAdmin, command_kick) || - command_add("kill", "- Kill your target", AccountStatus::GMAdmin, command_kill) || - command_add("killallnpcs", " [npc_name] Kills all npcs by search name, leave blank for all attackable NPC's", AccountStatus::GMMgmt, command_killallnpcs) || - command_add("lastname", "[Last Name] - Set you or your player target's lastname", AccountStatus::Guide, command_lastname) || - command_add("level", "[level] - Set your or your target's level", AccountStatus::Steward, command_level) || + command_add("kill", "Kill your target", AccountStatus::GMAdmin, command_kill) || + command_add("killallnpcs", "[npc_name] - Kills all npcs by search name, leave blank for all attackable NPC's", AccountStatus::GMMgmt, command_killallnpcs) || + command_add("lastname", "[Last Name] - Set your or your player target's last name (use \"-1\" to remove last name)", AccountStatus::Guide, command_lastname) || + command_add("level", "[Level] - Set your target's level", AccountStatus::Steward, command_level) || command_add("list", "[npcs|players|corpses|doors|objects] [search] - Search entities", AccountStatus::ApprenticeGuide, command_list) || - command_add("listpetition", "- List petitions", AccountStatus::Guide, command_listpetition) || + command_add("listpetition", "List petitions", AccountStatus::Guide, command_listpetition) || + command_add("lootsim", "[npc_type_id] [loottable_id] [iterations] - Runs benchmark simulations using real loot logic to report numbers and data", AccountStatus::GMImpossible, command_lootsim) || command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", AccountStatus::GMImpossible, command_load_shared_memory) || - command_add("loc", "- Print out your or your target's current location and heading", AccountStatus::Player, command_loc) || - command_add("lock", "- Lock the worldserver", AccountStatus::GMLeadAdmin, command_lock) || - command_add("logs", "Manage anything to do with logs", AccountStatus::GMImpossible, command_logs) || + command_add("loc", "Print out your or your target's current location and heading", AccountStatus::Player, command_loc) || + command_add("logs", "Manage anything to do with logs", AccountStatus::GMImpossible, command_logs) || command_add("makepet", "[Pet Name] - Make a pet", AccountStatus::Guide, command_makepet) || - command_add("mana", "- Fill your or your target's mana", AccountStatus::Guide, command_mana) || - command_add("maxskills", "Maxes skills for you.", AccountStatus::GMMgmt, command_max_all_skills) || + command_add("mana", "Fill your or your target's mana", AccountStatus::Guide, command_mana) || + command_add("maxskills", "Maxes skills for you or your player target.", AccountStatus::GMMgmt, command_max_all_skills) || command_add("memspell", "[Spell ID] [Spell Gem] - Memorize a Spell by ID to the specified Spell Gem for you or your target", AccountStatus::Guide, command_memspell) || - command_add("merchant_close_shop", "Closes a merchant shop", AccountStatus::GMAdmin, command_merchantcloseshop) || - command_add("merchant_open_shop", "Opens a merchants shop", AccountStatus::GMAdmin, command_merchantopenshop) || - command_add("modifynpcstat", "- Modifys a NPC's stats", AccountStatus::GMLeadAdmin, command_modifynpcstat) || - command_add("motd", "[new motd] - Set message of the day", AccountStatus::GMLeadAdmin, command_motd) || + command_add("merchant_close_shop", "Closes a merchant shop", AccountStatus::GMAdmin, command_merchantcloseshop) || + command_add("merchant_open_shop", "Opens a merchants shop", AccountStatus::GMAdmin, command_merchantopenshop) || + command_add("modifynpcstat", "[Stat] [Value] - Modifies an NPC's stats temporarily.", AccountStatus::GMLeadAdmin, command_modifynpcstat) || + command_add("motd", "[Message of the Day] - Set Message of the Day (leave empty to have no Message of the Day)", AccountStatus::GMLeadAdmin, command_motd) || command_add("movechar", "[Character ID|Character Name] [Zone ID|Zone Short Name] - Move an offline character to the specified zone", AccountStatus::Guide, command_movechar) || command_add("movement", "Various movement commands", AccountStatus::GMMgmt, command_movement) || - command_add("myskills", "- Show details about your current skill levels", AccountStatus::Player, command_myskills) || + command_add("myskills", "Show details about your current skill levels", AccountStatus::Player, command_myskills) || command_add("mysql", "[Help|Query] [SQL Query] - Mysql CLI, see 'Help' for options.", AccountStatus::GMImpossible, command_mysql) || - command_add("mystats", "- Show details about you or your pet", AccountStatus::Guide, command_mystats) || + command_add("mystats", "Show details about you or your pet", AccountStatus::Guide, command_mystats) || command_add("name", "[New Name] - Rename your player target", AccountStatus::GMLeadAdmin, command_name) || - command_add("netstats", "- Gets the network stats for a stream.", AccountStatus::GMMgmt, command_netstats) || - command_add("network", "- Admin commands for the udp network interface.", AccountStatus::GMImpossible, command_network) || + command_add("netstats", "Gets the network stats for a stream.", AccountStatus::GMMgmt, command_netstats) || + command_add("network", "Admin commands for the udp network interface.", AccountStatus::GMImpossible, command_network) || command_add("npccast", "[targetname/entityid] [spellid] - Causes NPC target to cast spellid on targetname/entityid", AccountStatus::QuestTroupe, command_npccast) || command_add("npcedit", "[column] [value] - Mega NPC editing command", AccountStatus::GMAdmin, command_npcedit) || command_add("npceditmass", "[name-search] [column] [value] - Mass (Zone wide) NPC data editing command", AccountStatus::GMAdmin, command_npceditmass) || command_add("npcemote", "[Message] - Make your NPC target emote a message.", AccountStatus::GMLeadAdmin, command_npcemote) || - command_add("npcloot", "- Manipulate the loot an NPC is carrying. Use #npcloot help for more information.", AccountStatus::QuestTroupe, command_npcloot) || + command_add("npcloot", "Manipulate the loot an NPC is carrying. Use #npcloot help for more information.", AccountStatus::QuestTroupe, command_npcloot) || command_add("npcsay", "[Message] - Make your NPC target say a message.", AccountStatus::GMLeadAdmin, command_npcsay) || command_add("npcshout", "[Message] - Make your NPC target shout a message.", AccountStatus::GMLeadAdmin, command_npcshout) || command_add("npcspawn", "[create/add/update/remove/delete] - Manipulate spawn DB", AccountStatus::GMAreas, command_npcspawn) || - command_add("npcstats", "- Show stats about target NPC", AccountStatus::QuestTroupe, command_npcstats) || + command_add("npcstats", "Show stats about target NPC", AccountStatus::QuestTroupe, command_npcstats) || command_add("npctypespawn", "[NPC ID] [Faction ID] - Spawn an NPC by ID from the database with an option of setting its Faction ID", AccountStatus::Steward, command_npctypespawn) || - command_add("nudge", "- Nudge your target's current position by specific values", AccountStatus::QuestTroupe, command_nudge) || + command_add("nudge", "Nudge your target's current position by specific values", AccountStatus::QuestTroupe, command_nudge) || command_add("nukebuffs", "[Beneficial|Detrimental|Help] - Strip all buffs by type on you or your target (no argument to remove all buffs)", AccountStatus::Guide, command_nukebuffs) || command_add("nukeitem", "[Item ID] - Removes the specified Item ID from you or your player target's inventory", AccountStatus::GMLeadAdmin, command_nukeitem) || command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", AccountStatus::GMAdmin, command_object) || - command_add("oocmute", "[1/0] - Mutes OOC chat", AccountStatus::GMMgmt, command_oocmute) || - command_add("opcode", "- opcode management", AccountStatus::GMImpossible, command_opcode) || - command_add("path", "- view and edit pathing", AccountStatus::GMMgmt, command_path) || + command_add("oocmute", "[0|1] - Enable or Disable Server OOC", AccountStatus::GMMgmt, command_oocmute) || + command_add("opcode", "Reloads all server patches", AccountStatus::GMImpossible, command_opcode) || + command_add("path", "view and edit pathing", AccountStatus::GMMgmt, command_path) || command_add("peekinv", "[equip/gen/cursor/poss/limbo/curlim/trib/bank/shbank/allbank/trade/world/all] - Print out contents of your player target's inventory", AccountStatus::GMAdmin, command_peekinv) || command_add("peqzone", "[Zone ID|Zone Short Name] - Teleports you to the specified zone if you meet the requirements.", AccountStatus::Player, command_peqzone) || - command_add("peqzone_flags", "- displays the PEQZone Flags of you or your target", AccountStatus::Player, command_peqzone_flags) || + command_add("peqzone_flags", "displays the PEQZone Flags of you or your target", AccountStatus::Player, command_peqzone_flags) || command_add("permaclass", "[Class ID] - Change your or your player target's class, changed client is disconnected", AccountStatus::QuestTroupe, command_permaclass) || command_add("permagender", "[Gender ID] - Change your or your player target's gender", AccountStatus::QuestTroupe, command_permagender) || command_add("permarace", "[Race ID] - Change your or your player target's race", AccountStatus::QuestTroupe, command_permarace) || - command_add("petitems", "- View your pet's items if you have one", AccountStatus::ApprenticeGuide, command_petitems) || + command_add("petitems", "View your pet's items if you have one", AccountStatus::ApprenticeGuide, command_petitems) || command_add("petitioninfo", "[petition number] - Get info about a petition", AccountStatus::ApprenticeGuide, command_petitioninfo) || - command_add("picklock", "Analog for ldon pick lock for the newer clients since we still don't have it working.", AccountStatus::Player, command_picklock) || + command_add("picklock", "Analog for ldon pick lock for the newer clients since we still don't have it working.", AccountStatus::Player, command_picklock) || command_add("profanity", "Manage censored language.", AccountStatus::GMLeadAdmin, command_profanity) || command_add("push", "[Back Push] [Up Push] - Lets you do spell push on an NPC", AccountStatus::GMLeadAdmin, command_push) || command_add("proximity", "Shows NPC proximity", AccountStatus::GMLeadAdmin, command_proximity) || @@ -281,36 +257,39 @@ int command_init(void) command_add("questerrors", "Shows quest errors.", AccountStatus::GMAdmin, command_questerrors) || command_add("race", "[racenum] - Change your or your target's race. Use racenum 0 to return to normal", AccountStatus::Guide, command_race) || command_add("raidloot", "[All|GroupLeader|RaidLeader|Selected] - Sets your Raid Loot Type if you have permission to do so.", AccountStatus::Player, command_raidloot) || - command_add("randomfeatures", "- Temporarily randomizes the Facial Features of your target", AccountStatus::QuestTroupe, command_randomfeatures) || - command_add("refreshgroup", "- Refreshes Group for you or your player target.", AccountStatus::Player, command_refreshgroup) || + command_add("randomfeatures", "Temporarily randomizes the Facial Features of your target", AccountStatus::QuestTroupe, command_randomfeatures) || + command_add("refreshgroup", "Refreshes Group for you or your player target.", AccountStatus::Player, command_refreshgroup) || command_add("reload", "Reloads different types of server data globally, use no argument for help menu.", AccountStatus::GMMgmt, command_reload) || + command_add("rq", "Reloads quests (alias of #reload quests).", AccountStatus::GMMgmt, command_reload) || + command_add("rl", "Reloads logs (alias of #reload logs).", AccountStatus::GMMgmt, command_reload) || command_add("removeitem", "[Item ID] [Amount] - Removes the specified Item ID by Amount from you or your player target's inventory (Amount defaults to 1 if not used)", AccountStatus::GMAdmin, command_removeitem) || command_add("repop", "[Force] - Repop the zone with optional force repop", AccountStatus::GMAdmin, command_repop) || - command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", AccountStatus::GMMgmt, command_resetaa) || + command_add("resetaa", "Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", AccountStatus::GMMgmt, command_resetaa) || command_add("resetaa_timer", "[All|Timer ID] - Command to reset AA cooldown timers for you or your player target.", AccountStatus::GMMgmt, command_resetaa_timer) || command_add("resetdisc_timer", "[All|Timer ID] - Command to reset discipline timers.", AccountStatus::GMMgmt, command_resetdisc_timer) || command_add("revoke", "[Character Name] [0|1] - Revokes or unrevokes a player's ability to talk in OOC by name (0 = Unrevoke, 1 = Revoke)", AccountStatus::GMMgmt, command_revoke) || command_add("roambox", "[Remove|Set] [Box Size] [Delay (Milliseconds)] - Remove or set an NPC's roambox size and delay", AccountStatus::GMMgmt, command_roambox) || command_add("rules", "(subcommand) - Manage server rules", AccountStatus::GMImpossible, command_rules) || - command_add("save", "- Force your player or player corpse target to be saved to the database", AccountStatus::Guide, command_save) || - command_add("scale", "- Handles npc scaling", AccountStatus::GMLeadAdmin, command_scale) || - command_add("scribespell", "[spellid] - Scribe specified spell in your target's spell book.", AccountStatus::GMCoder, command_scribespell) || - command_add("scribespells", "[max level] [min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_scribespells) || - command_add("sendzonespawns", "- Refresh spawn list for all clients in zone", AccountStatus::GMLeadAdmin, command_sendzonespawns) || - command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", AccountStatus::Player, command_sensetrap) || - command_add("serverinfo", "- Get CPU, Operating System, and Process Information about the server", AccountStatus::GMMgmt, command_serverinfo) || - command_add("serverrules", "- Read this server's rules", AccountStatus::Player, command_serverrules) || + command_add("save", "Force your player or player corpse target to be saved to the database", AccountStatus::Guide, command_save) || + command_add("scale", "Handles NPC scaling", AccountStatus::GMLeadAdmin, command_scale) || + command_add("scribespell", "[Spell ID] - Scribe a spell by ID to your or your target's spell book.", AccountStatus::GMCoder, command_scribespell) || + command_add("scribespells", "[Max level] [Min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_scribespells) || + command_add("sendzonespawns", "Refresh spawn list for all clients in zone", AccountStatus::GMLeadAdmin, command_sendzonespawns) || + command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", AccountStatus::Player, command_sensetrap) || + command_add("serverinfo", "Get CPU, Operating System, and Process Information about the server", AccountStatus::GMMgmt, command_serverinfo) || + command_add("serverlock", "[0|1] - Lock or Unlock the World Server (0 = Unlocked, 1 = Locked)", AccountStatus::GMLeadAdmin, command_serverlock) || + command_add("serverrules", "Read this server's rules", AccountStatus::Player, command_serverrules) || command_add("setaapts", "[AA|Group|Raid] [AA Amount] - Set your or your player target's Available AA Points by Type", AccountStatus::GMAdmin, command_setaapts) || command_add("setaaxp", "[AA|Group|Raid] [AA Experience] - Set your or your player target's AA Experience by Type", AccountStatus::GMAdmin, command_setaaxp) || command_add("setadventurepoints", "[Theme] [Points] - Set your or your player target's available Adventure Points by Theme", AccountStatus::GMLeadAdmin, command_set_adventure_points) || command_add("setaltcurrency", "[Currency ID] [Amount] - Set your or your target's available Alternate Currency by Currency ID", AccountStatus::GMAdmin, command_setaltcurrency) || command_add("setanim", "[Animation ID (IDs are 0 to 4)] - Set target's appearance to Animation ID", AccountStatus::GMMgmt, command_setanim) || + command_add("setanon", "[Anonymous Flag] - Set you or your target's Anonymous Flag (0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying)", AccountStatus::QuestTroupe, command_setanon) || command_add("setcrystals", "[value] - Set your or your player target's available radiant or ebon crystals", AccountStatus::GMAdmin, command_setcrystals) || command_add("setendurance", "[Endurance] - Set your or your target's Endurance", AccountStatus::GMAdmin, command_setendurance) || command_add("setfaction", "[Faction ID] - Sets targeted NPC's faction in the database", AccountStatus::GMAreas, command_setfaction) || - command_add("setgraveyard", "[zone name] - Creates a graveyard for the specified zone based on your target's LOC.", AccountStatus::GMMgmt, command_setgraveyard) || command_add("sethp", "[Health] - Set your or your target's Health", AccountStatus::GMAdmin, command_sethp) || - command_add("setlanguage", "[language ID] [value] - Set your target's language skillnum to value", AccountStatus::Guide, command_setlanguage) || + command_add("setlanguage", "[Language ID] [Value] - Set your or your target's Language by ID to Value", AccountStatus::Guide, command_setlanguage) || command_add("setlsinfo", "[Email] [Password] - Set loginserver email address and password (if supported by loginserver)", AccountStatus::Steward, command_setlsinfo) || command_add("setmana", "[Mana] - Set your or your target's Mana", AccountStatus::GMAdmin, command_setmana) || command_add("setpass", "[Account Name] [Password] - Set local password by account name", AccountStatus::GMLeadAdmin, command_setpass) || @@ -318,80 +297,81 @@ int command_init(void) command_add("setskill", "[skillnum] [value] - Set your target's skill skillnum to value", AccountStatus::Guide, command_setskill) || command_add("setskillall", "[Skill Level] - Set all of your or your target's skills to the specified skill level", AccountStatus::Guide, command_setskillall) || command_add("setstartzone", "[Zone ID|Zone Short Name] - Sets your or your target's starting zone (Use '0' or 'Reset' to allow the player use of /setstartcity)", AccountStatus::QuestTroupe, command_setstartzone) || - command_add("setstat", "- Sets the stats to a specific value.", AccountStatus::Max, command_setstat) || + command_add("setstat", "Sets the stats to a specific value.", AccountStatus::Max, command_setstat) || command_add("setxp", "[value] - Set your or your player target's experience", AccountStatus::GMAdmin, command_setxp) || command_add("showbonusstats", "[item|spell|all] Shows bonus stats for target from items or spells. Shows both by default.", AccountStatus::Guide, command_showbonusstats) || - command_add("showbuffs", "- List buffs active on your target or you if no target", AccountStatus::Guide, command_showbuffs) || - command_add("shownumhits", "Shows buffs numhits for yourself.", AccountStatus::Player, command_shownumhits) || + command_add("showbuffs", "List buffs active on your target or you if no target", AccountStatus::Guide, command_showbuffs) || + command_add("shownumhits", "Shows buffs numhits for yourself.", AccountStatus::Player, command_shownumhits) || command_add("shownpcgloballoot", "Show global loot entries for your target NPC", AccountStatus::Guide, command_shownpcgloballoot) || command_add("showskills", "[Start Skill ID] [All] - Show the values of your or your player target's skills in a popup 50 at a time, use 'all' as second argument to show non-usable skill's values", AccountStatus::Guide, command_showskills) || command_add("showspellslist", "Shows spell list of targeted NPC", AccountStatus::GMAdmin, command_showspellslist) || - command_add("showstats", "- Show details about you or your target", AccountStatus::Guide, command_showstats) || + command_add("showstats", "Show details about you or your target", AccountStatus::Guide, command_showstats) || command_add("showzonegloballoot", "Show global loot entries for your current zone", AccountStatus::Guide, command_showzonegloballoot) || command_add("showzonepoints", "Show zone points for current zone", AccountStatus::Guide, command_showzonepoints) || - command_add("shutdown", "- Shut this zone process down", AccountStatus::GMLeadAdmin, command_shutdown) || + command_add("shutdown", "Shut this zone process down", AccountStatus::GMLeadAdmin, command_shutdown) || command_add("spawn", "[name] [race] [level] [material] [hp] [gender] [class] [priweapon] [secweapon] [merchantid] - Spawn an NPC", AccountStatus::Steward, command_spawn) || - command_add("spawneditmass", "Mass editing spawn command", AccountStatus::GMLeadAdmin, command_spawneditmass) || - command_add("spawnfix", "- Find targeted NPC in database based on its X/Y/heading and update the database to make it spawn at your current location/heading.", AccountStatus::GMAreas, command_spawnfix) || + command_add("spawneditmass", "[Search Criteria] [Edit Option] [Edit Value] [Apply] Mass editing spawn command (Apply is optional, 0 = False, 1 = True, default is False)", AccountStatus::GMLeadAdmin, command_spawneditmass) || + command_add("spawnfix", "Find targeted NPC in database based on its X/Y/heading and update the database to make it spawn at your current location/heading.", AccountStatus::GMAreas, command_spawnfix) || command_add("spawnstatus", "[All|Disabled|Enabled|Spawn ID] - Show respawn timer status", AccountStatus::GMAdmin, command_spawnstatus) || command_add("spellinfo", "[spellid] - Get detailed info about a spell", AccountStatus::Steward, command_spellinfo) || command_add("stun", "[duration] - Stuns you or your target for duration", AccountStatus::GMAdmin, command_stun) || command_add("summon", "[Character Name] - Summons your corpse, NPC, or player target, or by character name if specified", AccountStatus::QuestTroupe, command_summon) || - command_add("summonburiedplayercorpse", "- Summons the target's oldest buried corpse, if any exist.", AccountStatus::GMAdmin, command_summonburiedplayercorpse) || + command_add("summonburiedplayercorpse", "Summons the target's oldest buried corpse, if any exist.", AccountStatus::GMAdmin, command_summonburiedplayercorpse) || command_add("summonitem", "[itemid] [charges] - Summon an item onto your cursor. Charges are optional.", AccountStatus::GMMgmt, command_summonitem) || command_add("suspend", "[name] [days] [reason] - Suspend by character name and for specificed number of days", AccountStatus::GMLeadAdmin, command_suspend) || + command_add("suspendmulti", "[Character Name One|Character Name Two|etc] [Days] [Reason] - Suspend multiple characters by name for specified number of days", AccountStatus::GMLeadAdmin, command_suspendmulti) || command_add("task", "(subcommand) - Task system commands", AccountStatus::GMLeadAdmin, command_task) || command_add("tempname", "[newname] - Temporarily renames your target. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_tempname) || command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_petname) || command_add("texture", "[Texture] [Helmet Texture] - Change your or your target's texture (Helmet Texture defaults to 0 if not used)", AccountStatus::Steward, command_texture) || command_add("time", "[Hour] [Minute] - Set world time to specified time", AccountStatus::EQSupport, command_time) || - command_add("timers", "- Display persistent timers for target", AccountStatus::GMMgmt, command_timers) || + command_add("timers", "Display persistent timers for target", AccountStatus::GMMgmt, command_timers) || command_add("timezone", "[Hour] [Minutes] - Set timezone (Minutes are optional)", AccountStatus::EQSupport, command_timezone) || - command_add("title", "[Remove|Title] [Save (0 = False, 1 = True)] - Set your or your player target's title (use remove to remove title, Save defaults to false if not used)", AccountStatus::Guide, command_title) || - command_add("titlesuffix", "[Remove|Title Suffix] [Save (0 = False, 1 = True)] - Set your or your player target's title suffix (use remove to remove title suffix, Save defaults to false if not used)", AccountStatus::Guide, command_titlesuffix) || + command_add("title", "[Title] - Set your or your player target's title (use \"-1\" to remove title)", AccountStatus::Guide, command_title) || + command_add("titlesuffix", "[Title Suffix] - Set your or your player target's title suffix (use \"-1\" to remove title suffix)", AccountStatus::Guide, command_titlesuffix) || command_add("traindisc", "[level] - Trains all the disciplines usable by the target, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_traindisc) || - command_add("trapinfo", "- Gets infomation about the traps currently spawned in the zone.", AccountStatus::QuestTroupe, command_trapinfo) || - command_add("tune", "Calculate statistical values related to combat.", AccountStatus::GMAdmin, command_tune) || - command_add("undye", "- Remove dye from all of your or your target's armor slots", AccountStatus::GMAdmin, command_undye) || - command_add("undyeme", "- Remove dye from all of your armor slots", AccountStatus::Player, command_undyeme) || - command_add("unfreeze", "- Unfreeze your target", AccountStatus::QuestTroupe, command_unfreeze) || - command_add("unlock", "- Unlock the worldserver", AccountStatus::GMLeadAdmin, command_unlock) || + command_add("trapinfo", "Gets infomation about the traps currently spawned in the zone.", AccountStatus::QuestTroupe, command_trapinfo) || + command_add("tune", "Calculate statistical values related to combat.", AccountStatus::GMAdmin, command_tune) || + command_add("undye", "Remove dye from all of your or your target's armor slots", AccountStatus::GMAdmin, command_undye) || + command_add("undyeme", "Remove dye from all of your armor slots", AccountStatus::Player, command_undyeme) || + command_add("unfreeze", "Unfreeze your target", AccountStatus::QuestTroupe, command_unfreeze) || command_add("unmemspell", "[Spell ID] - Unmemorize a Spell by ID for you or your target", AccountStatus::Guide, command_unmemspell) || - command_add("unmemspells", " - Unmemorize all spells for you or your target", AccountStatus::Guide, command_unmemspells) || + command_add("unmemspells", " Unmemorize all spells for you or your target", AccountStatus::Guide, command_unmemspells) || command_add("unscribespell", "[Spell ID] - Unscribe a spell from your or your target's spell book by Spell ID", AccountStatus::GMCoder, command_unscribespell) || - command_add("unscribespells", "- Clear out your or your player target's spell book.", AccountStatus::GMCoder, command_unscribespells) || + command_add("unscribespells", "Clear out your or your player target's spell book.", AccountStatus::GMCoder, command_unscribespells) || command_add("untraindisc", "[Spell ID] - Untrain your or your target's discipline by Spell ID", AccountStatus::GMCoder, command_untraindisc) || - command_add("untraindiscs", "- Untrains all disciplines from your target.", AccountStatus::GMCoder, command_untraindiscs) || + command_add("untraindiscs", "Untrains all disciplines from your target.", AccountStatus::GMCoder, command_untraindiscs) || command_add("updatechecksum", "update client checksum", AccountStatus::GMImpossible, command_updatechecksum) || command_add("uptime", "[zone server id] - Get uptime of worldserver, or zone server if argument provided", AccountStatus::Steward, command_uptime) || - command_add("version", "- Display current version of EQEmu server", AccountStatus::Player, command_version) || - command_add("viewcurrencies", "- View your or your target's currencies", AccountStatus::GMAdmin, command_viewcurrencies) || + command_add("version", "Display current version of EQEmu server", AccountStatus::Player, command_version) || + command_add("viewcurrencies", "View your or your target's currencies", AccountStatus::GMAdmin, command_viewcurrencies) || command_add("viewnpctype", "[NPC ID] - Show stats for an NPC by NPC ID", AccountStatus::GMAdmin, command_viewnpctype) || command_add("viewpetition", "[petition number] - View a petition", AccountStatus::ApprenticeGuide, command_viewpetition) || + command_add("viewrecipe", "[Recipe ID] - Show a recipe's entries", AccountStatus::GMAdmin, command_viewrecipe) || command_add("viewzoneloot", "[item id] - Allows you to search a zone's loot for a specific item ID. (0 shows all loot in the zone)", AccountStatus::QuestTroupe, command_viewzoneloot) || command_add("wc", "[wear slot] [material] - Sends an OP_WearChange for your target", AccountStatus::GMMgmt, command_wc) || command_add("weather", "[0/1/2/3] (Off/Rain/Snow/Manual) - Change the weather", AccountStatus::QuestTroupe, command_weather) || command_add("who", "[search]", AccountStatus::ApprenticeGuide, command_who) || - command_add("worldshutdown", "- Shut down world and all zones", AccountStatus::GMMgmt, command_worldshutdown) || + command_add("worldshutdown", "Shut down world and all zones", AccountStatus::GMMgmt, command_worldshutdown) || command_add("wp", "[add|delete] [grid_id] [pause] [waypoint_id] [-h] - Add or delete a waypoint by grid ID. (-h to use current heading)", AccountStatus::GMAreas, command_wp) || command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path. (-h to use current heading)", AccountStatus::GMAreas, command_wpadd) || - command_add("wpinfo", "- Show waypoint info about your NPC target", AccountStatus::GMAreas, command_wpinfo) || + command_add("wpinfo", "Show waypoint info about your NPC target", AccountStatus::GMAreas, command_wpinfo) || command_add("worldwide", "Performs world-wide GM functions such as cast (can be extended for other commands). Use caution", AccountStatus::GMImpossible, command_worldwide) || - command_add("xtargets", "Show your targets Extended Targets and optionally set how many xtargets they can have.", AccountStatus::GMImpossible, command_xtargets) || + command_add("xtargets", "[New Max XTargets] - Show your or your target's XTargets and optionally set max XTargets.", AccountStatus::GMImpossible, command_xtargets) || command_add("zclip", "[Minimum Clip] [Maximum Clip] [Fog Minimum Clip] [Fog Maximum Clip] [Permanent (0 = False, 1 = True)] - Change zone clipping", AccountStatus::QuestTroupe, command_zclip) || command_add("zcolor", "[Red] [Green] [Blue] [Permanent (0 = False, 1 = True)] - Change sky color", AccountStatus::QuestTroupe, command_zcolor) || command_add("zheader", "[Zone ID|Zone Short Name] [Version] - Load a zone header from the database", AccountStatus::QuestTroupe, command_zheader) || - command_add("zone", "[zonename] [x] [y] [z] - Go to specified zone (coords optional)", AccountStatus::Guide, command_zone) || + command_add("zone", "[Zone ID|Zone Short Name] [X] [Y] [Z] - Teleport to specified Zone by ID or Short Name (coordinates are optional)", AccountStatus::Guide, command_zone) || command_add("zonebootup", "[ZoneServerID] [shortname] - Make a zone server boot a specific zone", AccountStatus::GMLeadAdmin, command_zonebootup) || - command_add("zoneinstance", "[instanceid] [x] [y] [z] - Go to specified instance zone (coords optional)", AccountStatus::Guide, command_zone_instance) || + command_add("zoneinstance", "[Instance ID] [X] [Y] [Z] - Teleport to specified Instance by ID (coordinates are optional)", AccountStatus::Guide, command_zone_instance) || command_add("zonelock", "[List|Lock|Unlock] [Zone ID|Zone Short Name] - Set or get lock status of a Zone by ID or Short Name", AccountStatus::GMAdmin, command_zonelock) || command_add("zoneshutdown", "[shortname] - Shut down a zone server", AccountStatus::GMLeadAdmin, command_zoneshutdown) || - command_add("zonestatus", "- Show connected zoneservers, synonymous with /servers", AccountStatus::GMLeadAdmin, command_zonestatus) || - command_add("zopp", "Troubleshooting command - Sends a fake item packet to you. No server reference is created.", AccountStatus::GMImpossible, command_zopp) || + command_add("zonestatus", "Show connected zoneservers, synonymous with /servers", AccountStatus::GMLeadAdmin, command_zonestatus) || + command_add("zopp", "Troubleshooting command - Sends a fake item packet to you. No server reference is created.", AccountStatus::GMImpossible, command_zopp) || command_add("zsafecoords", "[X] [Y] [Z] [Heading] [Permanent (0 = False, 1 = True)] - Set the current zone's safe coordinates", AccountStatus::QuestTroupe, command_zsafecoords) || - command_add("zsave", " - Saves zheader to the database", AccountStatus::QuestTroupe, command_zsave) || + command_add("zsave", " Saves zheader to the database", AccountStatus::QuestTroupe, command_zsave) || command_add("zsky", "[Sky Type] [Permanent (0 = False, 1 = True)] - Change zone sky type", AccountStatus::QuestTroupe, command_zsky) || - command_add("zstats", "- Show info about zone header", AccountStatus::QuestTroupe, command_zstats) || + command_add("zstats", "Show info about zone header", AccountStatus::QuestTroupe, command_zstats) || command_add("zunderworld", "[Z] [Permanent (0 = False, 1 = True)] - Change zone underworld Z", AccountStatus::QuestTroupe, command_zunderworld) ) { command_deinit(); @@ -404,15 +384,13 @@ int command_init(void) std::vector> injected_command_settings; std::vector orphaned_command_settings; - for (auto cs_iter : command_settings) { - - auto cl_iter = commandlist.find(cs_iter.first); - if (cl_iter == commandlist.end()) { - - orphaned_command_settings.push_back(cs_iter.first); + for (const auto& cs : command_settings) { + auto cl = commandlist.find(cs.first); + if (cl == commandlist.end()) { + orphaned_command_settings.push_back(cs.first); LogInfo( "Command [{}] no longer exists... Deleting orphaned entry from `command_settings` table...", - cs_iter.first.c_str() + cs.first ); } } @@ -424,60 +402,58 @@ int command_init(void) } auto working_cl = commandlist; - for (auto working_cl_iter : working_cl) { - - auto cs_iter = command_settings.find(working_cl_iter.first); - if (cs_iter == command_settings.end()) { - - injected_command_settings.push_back(std::pair(working_cl_iter.first, working_cl_iter.second->access)); + for (const auto& w : working_cl) { + auto cs = command_settings.find(w.first); + if (cs == command_settings.end()) { + injected_command_settings.push_back(std::pair(w.first, w.second->admin)); LogInfo( - "New Command [{}] found... Adding to `command_settings` table with access [{}]...", - working_cl_iter.first.c_str(), - working_cl_iter.second->access + "New Command [{}] found... Adding to `command_settings` table with admin [{}]...", + w.first, + w.second->admin ); - if (working_cl_iter.second->access == 0) { + if (w.second->admin == AccountStatus::Player) { LogCommands( - "command_init(): Warning: Command [{}] defaulting to access level 0!", - working_cl_iter.first.c_str() + "command_init(): Warning: Command [{}] defaulting to admin level 0!", + w.first ); } continue; } - working_cl_iter.second->access = cs_iter->second.first; + w.second->admin = cs->second.first; LogCommands( - "command_init(): - Command [{}] set to access level [{}]", - working_cl_iter.first.c_str(), - cs_iter->second.first + "command_init(): - Command [{}] set to admin level [{}]", + w.first, + cs->second.first ); - if (cs_iter->second.second.empty()) { + if (cs->second.second.empty()) { continue; } - for (auto alias_iter : cs_iter->second.second) { - if (alias_iter.empty()) { + for (const auto& a : cs->second.second) { + if (a.empty()) { continue; } - if (commandlist.find(alias_iter) != commandlist.end()) { + if (commandlist.find(a) != commandlist.end()) { LogCommands( "command_init(): Warning: Alias [{}] already exists as a command - skipping!", - alias_iter.c_str() + a ); continue; } - commandlist[alias_iter] = working_cl_iter.second; - commandaliases[alias_iter] = working_cl_iter.first; + commandlist[a] = w.second; + commandaliases[a] = w.first; LogCommands( "command_init(): - Alias [{}] added to command [{}]", - alias_iter.c_str(), - commandaliases[alias_iter].c_str() + a, + commandaliases[a] ); } } @@ -490,7 +466,7 @@ int command_init(void) command_dispatch = command_realdispatch; - return commandcount; + return command_count; } /* @@ -503,11 +479,16 @@ int command_init(void) */ void command_deinit(void) { + for (auto &c : command_delete_list) { + delete c; + } + + command_delete_list.clear(); commandlist.clear(); commandaliases.clear(); command_dispatch = command_notavail; - commandcount = 0; + command_count = 0; } /* @@ -515,46 +496,49 @@ void command_deinit(void) * adds a command to the command list; used by command_init * * Parameters: - * command_name - the command ex: "spawn" - * desc - text description of command for #help - * access - default access level required to use command - * function - pointer to function that handles command + * command_name - the command ex: "spawn" + * description - text description of command for #help + * admin - default admin level required to use command + * function - pointer to function that handles command * */ -int command_add(std::string command_name, const char *desc, int access, CmdFuncPtr function) +int command_add(std::string command_name, std::string description, uint8 admin, CmdFuncPtr function) { if (command_name.empty()) { LogError("command_add() - Command added with empty name string - check command.cpp"); return -1; } - if (function == nullptr) { - LogError("command_add() - Command [{}] added without a valid function pointer - check command.cpp", command_name.c_str()); + + if (!function) { + LogError("command_add() - Command [{}] added without a valid function pointer - check command.cpp", command_name); return -1; } - if (commandlist.count(command_name) != 0) { - LogError("command_add() - Command [{}] is a duplicate command name - check command.cpp", command_name.c_str()); - return -1; - } - for (auto iter = commandlist.begin(); iter != commandlist.end(); ++iter) { - if (iter->second->function != function) - continue; - LogError("command_add() - Command [{}] equates to an alias of [{}] - check command.cpp", command_name.c_str(), iter->first.c_str()); + + if (commandlist.count(command_name)) { + LogError("command_add() - Command [{}] is a duplicate command name - check command.cpp", command_name); return -1; } auto c = new CommandRecord; - c->access = access; - c->desc = desc; + c->admin = admin; + c->description = description; c->function = function; + commands_map[command_name] = admin; + commandlist[command_name] = c; commandaliases[command_name] = command_name; - cleanup_commandlist.Append(c); - commandcount++; + command_delete_list.push_back(c); + command_count++; return 0; } +uint8 GetCommandStatus(Client *c, std::string command_name) { + auto command_status = commands_map[command_name]; + return command_status; +} + /* * * command_realdispatch @@ -567,386 +551,244 @@ int command_add(std::string command_name, const char *desc, int access, CmdFuncP * message - what the client typed * */ -int command_realdispatch(Client *c, const char *message) +int command_realdispatch(Client *c, std::string message, bool ignore_status) { - Seperator sep(message, ' ', 10, 100, true); // "three word argument" should be considered 1 arg + Seperator sep(message.c_str(), ' ', 10, 100, true); // "three word argument" should be considered 1 arg - command_logcommand(c, message); + command_logcommand(c, message.c_str()); - std::string cstr(sep.arg[0]+1); + std::string cstr(sep.arg[0] + 1); - if(commandlist.count(cstr) != 1) { - return(-2); + if (commandlist.count(cstr) != 1) { + return -2; } - CommandRecord *cur = commandlist[cstr]; - if(c->Admin() < cur->access){ - c->Message(Chat::Red,"Your access level is not high enough to use this command."); - return(-1); + auto cur = commandlist[cstr]; + if (!ignore_status && c->Admin() < cur->admin) { + c->Message(Chat::White, "Your status is not high enough to use this command."); + return -1; } /* QS: Player_Log_Issued_Commands */ - if (RuleB(QueryServ, PlayerLogIssuedCommandes)){ - std::string event_desc = StringFormat("Issued command :: '%s' in zoneid:%i instid:%i", message, c->GetZoneID(), c->GetInstanceID()); + if (RuleB(QueryServ, PlayerLogIssuedCommandes)) { + auto event_desc = fmt::format( + "Issued command :: '{}' in Zone ID: {} Instance ID: {}", + message, + c->GetZoneID(), + c->GetInstanceID() + ); QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc); } - if(cur->access >= COMMANDS_LOGGING_MIN_STATUS) { - LogCommands("[{}] ([{}]) used command: [{}] (target=[{}])", c->GetName(), c->AccountName(), message, c->GetTarget()?c->GetTarget()->GetName():"NONE"); + if (cur->admin >= COMMANDS_LOGGING_MIN_STATUS) { + LogCommands( + "[{}] ([{}]) used command: [{}] (target=[{}])", + c->GetName(), + c->AccountName(), + message, + c->GetTarget() ? c->GetTarget()->GetName() : "NONE" + ); } - if(cur->function == nullptr) { - LogError("Command [{}] has a null function\n", cstr.c_str()); - return(-1); - } else { - //dispatch C++ command - cur->function(c, &sep); // dispatch command + if (!cur->function) { + LogError("Command [{}] has a null function", cstr); + return -1; } + + parse->EventPlayer(EVENT_GM_COMMAND, c, message, 0); + + cur->function(c, &sep); // Dispatch C++ Command + return 0; - } void command_help(Client *c, const Seperator *sep) { - int commands_shown=0; + int found_count = 0; + std::string command_link; + std::string search_criteria = Strings::ToLower(sep->argplus[1]); - c->Message(Chat::White, "Available EQEMu commands:"); - - std::map::iterator cur,end; - cur = commandlist.begin(); - end = commandlist.end(); - - for(; cur != end; ++cur) { - if(sep->arg[1][0]) { - if(cur->first.find(sep->arg[1]) == std::string::npos) { + for (const auto& cur : commandlist) { + if (!search_criteria.empty()) { + if (!Strings::Contains(cur.first, search_criteria) && !Strings::Contains(cur.second->description, search_criteria)) { continue; } } - if(c->Admin() < cur->second->access) - continue; - commands_shown++; - c->Message(Chat::White, " %c%s %s", COMMAND_CHAR, cur->first.c_str(), cur->second->desc == nullptr?"":cur->second->desc); - } - if (parse->PlayerHasQuestSub(EVENT_COMMAND)) { - int i = parse->EventPlayer(EVENT_COMMAND, c, sep->msg, 0); - if (i >= 1) { - commands_shown += i; - } - } - c->Message(Chat::White, "%d command%s listed.", commands_shown, commands_shown!=1?"s":""); - -} - -void command_zone(Client *c, const Seperator *sep) -{ - if(c->Admin() < commandZoneToCoords && - (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4))) { - c->Message(Chat::White, "Your status is not high enough to zone to specific coordinates."); - return; - } - - uint16 zoneid = 0; - - if (sep->IsNumber(1)) - { - if(atoi(sep->arg[1])==26 && (c->Admin() < commandZoneToSpecials)){ //cshome - c->Message(Chat::White, "Only Guides and above can goto that zone."); - return; - } - zoneid = atoi(sep->arg[1]); - } - else if (sep->arg[1][0] == 0) - { - c->Message(Chat::White, "Usage: #zone [zonename]"); - c->Message(Chat::White, "Optional Usage: #zone [zonename] y x z"); - return; - } - else if (zone->GetZoneID() == 184 && c->Admin() < commandZoneToSpecials) { // Zone: 'Load' - c->Message(Chat::White, "The Gods brought you here, only they can send you away."); - return; - } else { - if((strcasecmp(sep->arg[1], "cshome")==0) && (c->Admin() < commandZoneToSpecials)){ - c->Message(Chat::White, "Only Guides and above can goto that zone."); - return; - } - - zoneid = ZoneID(sep->arg[1]); - if(zoneid == 0) { - c->Message(Chat::White, "Unable to locate zone '%s'", sep->arg[1]); - return; - } - } - -#ifdef BOTS - // This block is necessary to clean up any bot objects owned by a Client - if(zoneid != c->GetZoneID()) - Bot::ProcessClientZoneChange(c); -#endif - - if (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4)){ - //zone to specific coords - c->MovePC(zoneid, (float)atof(sep->arg[2]), atof(sep->arg[3]), atof(sep->arg[4]), 0.0f, 0); - } - else - //zone to safe coords - c->MovePC(zoneid, 0.0f, 0.0f, 0.0f, 0.0f, 0, ZoneToSafeCoords); -} - -//todo: fix this so it checks if you're in the instance set -void command_zone_instance(Client *c, const Seperator *sep) -{ - if(c->Admin() < commandZoneToCoords && - (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4))) { - c->Message(Chat::White, "Your status is not high enough to zone to specific coordinates."); - return; - } - - if (sep->arg[1][0] == 0) - { - c->Message(Chat::White, "Usage: #zoneinstance [instance id]"); - c->Message(Chat::White, "Optional Usage: #zoneinstance [instance id] y x z"); - return; - } - - uint16 zoneid = 0; - uint16 instanceid = 0; - - if(sep->IsNumber(1)) - { - instanceid = atoi(sep->arg[1]); - if(!instanceid) - { - c->Message(Chat::White, "Must enter a valid instance id."); - return; - } - - zoneid = database.ZoneIDFromInstanceID(instanceid); - if(!zoneid) - { - c->Message(Chat::White, "Instance not found or zone is set to null."); - return; - } - } - else - { - c->Message(Chat::White, "Must enter a valid instance id."); - return; - } - - if(!database.VerifyInstanceAlive(instanceid, c->CharacterID())) - { - c->Message(Chat::White, "Instance ID expiried or you are not apart of this instance."); - return; - } - - if (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4)){ - //zone to specific coords - c->MovePC(zoneid, instanceid, atof(sep->arg[2]), atof(sep->arg[3]), atof(sep->arg[4]), 0.0f, 0); - } - else{ - c->MovePC(zoneid, instanceid, 0.0f, 0.0f, 0.0f, 0.0f, 0, ZoneToSafeCoords); - } -} - -void command_level(Client *c, const Seperator *sep) -{ - uint16 level = atoi(sep->arg[1]); - - if ((level <= 0) || ((level > RuleI(Character, MaxLevel)) && (c->Admin() < commandLevelAboveCap))) { - c->Message(Chat::White, "Error: #Level: Invalid Level"); - } - else if (c->Admin() < RuleI(GM, MinStatusToLevelTarget)) { - c->SetLevel(level, true); -#ifdef BOTS - if(RuleB(Bots, BotLevelsWithOwner)) - Bot::LevelBotWithClient(c, level, true); -#endif - } - else if (!c->GetTarget()) { - c->Message(Chat::White, "Error: #Level: No target"); - } - else { - if (!c->GetTarget()->IsNPC() && ((c->Admin() < commandLevelNPCAboveCap) && (level > RuleI(Character, MaxLevel)))) { - c->Message(Chat::White, "Error: #Level: Invalid Level"); - } - else { - c->GetTarget()->SetLevel(level, true); - if(c->GetTarget()->IsClient()) { - c->GetTarget()->CastToClient()->SendLevelAppearance(); -#ifdef BOTS - if(RuleB(Bots, BotLevelsWithOwner)) - Bot::LevelBotWithClient(c->GetTarget()->CastToClient(), level, true); -#endif - } - } - } -} - -void command_spawneditmass(Client *c, const Seperator *sep) -{ - std::string query = fmt::format( - SQL( - SELECT - npc_types.id, - npc_types.name, - spawn2.respawntime, - spawn2.id - FROM - npc_types - JOIN spawnentry ON spawnentry.npcID = npc_types.id - JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID - WHERE - spawn2.zone = '{0}' and spawn2.version = {1} - GROUP BY npc_types.id - ), - zone->GetShortName(), - zone->GetInstanceVersion() - ); - - std::string status = "(Searching)"; - - if (strcasecmp(sep->arg[4], "apply") == 0) { - status = "(Applying)"; - } - - std::string search_value; - std::string edit_option; - std::string edit_value; - std::string apply_set; - - if (sep->arg[1]) { - search_value = sep->arg[1]; - } - - if (sep->arg[2]) { - edit_option = sep->arg[2]; - } - - if (sep->arg[3]) { - edit_value = sep->arg[3]; - } - - if (sep->arg[4]) { - apply_set = sep->arg[4]; - } - - if (!edit_option.empty() && edit_value.empty()) { - c->Message(Chat::Yellow, "Please specify an edit option value | #npceditmass "); - find_replace(output, "{y}", ""); - find_replace(output, "{lb}", ""); - find_replace(output, "{r}", ""); - find_replace(output, "{g}", ""); - find_replace(output, "{gold}", ""); - find_replace(output, "{orange}", ""); - find_replace(output, "{gray}", ""); - find_replace(output, "{tan}", ""); - find_replace(output, "{bullet}", "•"); - find_replace(output, "{name}", fmt::format("{}", c->GetCleanName())); - find_replace(output, "{linebreak}", "--------------------------------------------------------------------"); - find_replace(output, "{rowpad}", R"({tdpad}<"td>{tdpad}<"td><"tr>)"); - find_replace(output, "{tdpad}", "----------------------"); - find_replace(output, "{in}", "        "); + Strings::FindReplace(output, "~", ""); + Strings::FindReplace(output, "{y}", ""); + Strings::FindReplace(output, "{lb}", ""); + Strings::FindReplace(output, "{r}", ""); + Strings::FindReplace(output, "{g}", ""); + Strings::FindReplace(output, "{gold}", ""); + Strings::FindReplace(output, "{orange}", ""); + Strings::FindReplace(output, "{gray}", ""); + Strings::FindReplace(output, "{tan}", ""); + Strings::FindReplace(output, "{bullet}", "•"); + Strings::FindReplace(output, "{name}", fmt::format("{}", c->GetCleanName())); + Strings::FindReplace(output, "{linebreak}", "--------------------------------------------------------------------"); + Strings::FindReplace(output, "{rowpad}", R"({tdpad}<"td>{tdpad}<"td><"tr>)"); + Strings::FindReplace(output, "{tdpad}", "----------------------"); + Strings::FindReplace(output, "{in}", "        "); // mysterious voice bool render_mysterious_voice = false; if (markdown.find("{mysterious}") != std::string::npos) { render_mysterious_voice = true; LogDiaWind("Client [{}] Rendering mysterious voice", c->GetCleanName()); - find_replace(output, "{mysterious}", ""); + Strings::FindReplace(output, "{mysterious}", ""); } // noquotes @@ -45,7 +47,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) if (markdown.find("noquotes") != std::string::npos) { render_noquotes = true; LogDiaWind("Client [{}] Rendering noquotes", c->GetCleanName()); - find_replace(output, "noquotes", ""); + Strings::FindReplace(output, "noquotes", ""); } // nobracket @@ -53,30 +55,31 @@ void DialogueWindow::Render(Client *c, std::string markdown) if (markdown.find("nobracket") != std::string::npos) { render_nobracket = true; LogDiaWind("Client [{}] Rendering nobracket", c->GetCleanName()); - find_replace(output, "nobracket", ""); + Strings::FindReplace(output, "nobracket", ""); } bool render_hiddenresponse = false; if (markdown.find("hiddenresponse") != std::string::npos) { render_hiddenresponse = true; LogDiaWind("Client [{}] Rendering hiddenresponse", c->GetCleanName()); - find_replace(output, "hiddenresponse", ""); + Strings::FindReplace(output, "hiddenresponse", ""); } // animations - std::string animation = get_between(output, "+", "+"); + std::string animation = Strings::GetBetween(output, "+", "+"); if (!animation.empty()) { LogDiaWind("Client [{}] Animation is not empty, contents are [{}]", c->GetCleanName(), animation); - find_replace(output, fmt::format("+{}+", animation), ""); // we treat the animation field differently if it is a number - if (StringIsNumber(animation)) { + bool found_animation = false; + if (Strings::IsNumber(animation)) { LogDiaWindDetail("Client [{}] Animation is a number, firing animation [{}]", c->GetCleanName(), animation); target->DoAnim(std::stoi(animation)); + found_animation = true; } else { for (auto &a: animations) { - if (a.first.find(str_tolower(animation)) != std::string::npos) { + if (a.first.find(Strings::ToLower(animation)) != std::string::npos) { LogDiaWindDetail( "Client [{}] Animation is a string, firing animation [{}] [{}]", c->GetCleanName(), @@ -84,9 +87,14 @@ void DialogueWindow::Render(Client *c, std::string markdown) a.first ); target->DoAnim(a.second); + found_animation = true; } } } + + if (found_animation) { + Strings::FindReplace(output, fmt::format("+{}+", animation), ""); + } } if (animation.empty() && RuleB(Chat, DialogueWindowAnimatesNPCsIfNoneSet)) { @@ -105,14 +113,14 @@ void DialogueWindow::Render(Client *c, std::string markdown) } // window expire time - std::string expire_time = get_between(output, "=", "="); + std::string expire_time = Strings::GetBetween(output, "=", "="); uint32 window_expire_seconds = 0; if (!expire_time.empty()) { LogDiaWind("Client [{}] Window expire time is not empty, contents are [{}]", c->GetCleanName(), expire_time); - find_replace(output, fmt::format("={}=", expire_time), ""); + Strings::FindReplace(output, fmt::format("={}=", expire_time), ""); // we treat the animation field differently if it is a number - if (StringIsNumber(expire_time)) { + if (Strings::IsNumber(expire_time)) { LogDiaWindDetail( "Client [{}] Window expire time is a number, setting expiration to [{}]", c->GetCleanName(), @@ -133,12 +141,12 @@ void DialogueWindow::Render(Client *c, std::string markdown) if (markdown.find("wintype:") != std::string::npos) { LogDiaWind("Client [{}] Rendering wintype option", c->GetCleanName()); - auto first_split = split_string(output, "wintype:"); + auto first_split = Strings::Split(output, "wintype:"); if (!first_split.empty()) { // assumed that there is more after the wintype declaration // wintype:0 +animation+ etc. - auto second_split = split_string(first_split[1], " "); + auto second_split = Strings::Split(first_split[1], " "); if (!second_split.empty()) { wintype = second_split[0]; LogDiaWindDetail("Client [{}] Rendering wintype option wintype [{}]", c->GetCleanName(), wintype); @@ -155,7 +163,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) ); } - find_replace(output, fmt::format("wintype:{}", wintype), ""); + Strings::FindReplace(output, fmt::format("wintype:{}", wintype), ""); } } @@ -164,12 +172,12 @@ void DialogueWindow::Render(Client *c, std::string markdown) if (markdown.find("popupid:") != std::string::npos) { LogDiaWind("Client [{}] Rendering popupid option", c->GetCleanName()); - auto first_split = split_string(output, "popupid:"); + auto first_split = Strings::Split(output, "popupid:"); if (!first_split.empty()) { // assumed that there is more after the popupid declaration // popupid:0 +animation+ etc. - auto second_split = split_string(first_split[1], " "); + auto second_split = Strings::Split(first_split[1], " "); if (!second_split.empty()) { popupid = second_split[0]; LogDiaWindDetail("Client [{}] Rendering popupid option popupid [{}]", c->GetCleanName(), popupid); @@ -186,11 +194,11 @@ void DialogueWindow::Render(Client *c, std::string markdown) ); } - find_replace(output, fmt::format("popupid:{}", popupid), ""); + Strings::FindReplace(output, fmt::format("popupid:{}", popupid), ""); // set the popup id if (!popupid.empty()) { - popup_id = (StringIsNumber(popupid) ? std::atoi(popupid.c_str()) : 0); + popup_id = (Strings::IsNumber(popupid) ? std::atoi(popupid.c_str()) : 0); } } } @@ -200,9 +208,9 @@ void DialogueWindow::Render(Client *c, std::string markdown) if (markdown.find("secondresponseid:") != std::string::npos) { LogDiaWind("Client [{}] Rendering secondresponseid option", c->GetCleanName()); - auto first_split = split_string(output, "secondresponseid:"); + auto first_split = Strings::Split(output, "secondresponseid:"); if (!first_split.empty()) { - auto second_split = split_string(first_split[1], " "); + auto second_split = Strings::Split(first_split[1], " "); if (!second_split.empty()) { secondresponseid = second_split[0]; LogDiaWindDetail("Client [{}] Rendering secondresponseid option secondresponseid [{}]", @@ -219,10 +227,10 @@ void DialogueWindow::Render(Client *c, std::string markdown) ); } - find_replace(output, fmt::format("secondresponseid:{}", secondresponseid), ""); + Strings::FindReplace(output, fmt::format("secondresponseid:{}", secondresponseid), ""); if (!secondresponseid.empty()) { - negative_id = (StringIsNumber(secondresponseid) ? std::atoi(secondresponseid.c_str()) : 0); + negative_id = (Strings::IsNumber(secondresponseid) ? std::atoi(secondresponseid.c_str()) : 0); } } } @@ -237,20 +245,20 @@ void DialogueWindow::Render(Client *c, std::string markdown) LogDiaWind("Client [{}] Rendering button_one option.", c->GetCleanName()); - button_one = get_between(output, "{button_one:", "}"); + button_one = Strings::GetBetween(output, "{button_one:", "}"); LogDiaWind("Client [{}] button_one [{}]", c->GetCleanName(), button_one); if (!button_one.empty()) { - find_replace(output, fmt::format("{{button_one:{}}}", button_one), ""); - button_one_name = trim(button_one); + Strings::FindReplace(output, fmt::format("{{button_one:{}}}", button_one), ""); + button_one_name = Strings::Trim(button_one); } - button_two = get_between(output, "{button_two:", "}"); + button_two = Strings::GetBetween(output, "{button_two:", "}"); LogDiaWind("Client [{}] button_two [{}]", c->GetCleanName(), button_two); if (!button_two.empty()) { - find_replace(output, fmt::format("{{button_two:{}}}", button_two), ""); - button_two_name = trim(button_two); + Strings::FindReplace(output, fmt::format("{{button_two:{}}}", button_two), ""); + button_two_name = Strings::Trim(button_two); } LogDiaWind( @@ -270,7 +278,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) std::string strip_saylinks = output; std::map replacements = {}; while (strip_saylinks.find('[') != std::string::npos && strip_saylinks.find(']') != std::string::npos) { - std::string bracket_message = get_between(strip_saylinks, "[", "]"); + std::string bracket_message = Strings::GetBetween(strip_saylinks, "[", "]"); // strip saylinks and normalize to [regular message] size_t link_open = bracket_message.find('\x12'); @@ -284,12 +292,12 @@ void DialogueWindow::Render(Client *c, std::string markdown) ); } - find_replace(strip_saylinks, fmt::format("[{}]", bracket_message), ""); + Strings::FindReplace(strip_saylinks, fmt::format("[{}]", bracket_message), ""); } // write replacement strips for (auto &replacement: replacements) { - find_replace(output, replacement.first, replacement.second.substr(0, replacement.second.size() - 1)); + Strings::FindReplace(output, replacement.first, replacement.second.substr(0, replacement.second.size() - 1)); } // copy @@ -298,7 +306,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) // while brackets still exist int response_index = 0; while (content.find('[') != std::string::npos && content.find(']') != std::string::npos) { - std::string bracket_message = get_between(content, "[", "]"); + std::string bracket_message = Strings::GetBetween(content, "[", "]"); LogDiaWindDetail( "Client [{}] Rendering responses ({}) [{}]", @@ -311,7 +319,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) responses.emplace_back(bracket_message); // pop the response off of the message - find_replace(content, fmt::format("[{}]", bracket_message), ""); + Strings::FindReplace(content, fmt::format("[{}]", bracket_message), ""); // too many iterations / safety net if (response_index > 100) { @@ -326,49 +334,43 @@ void DialogueWindow::Render(Client *c, std::string markdown) if (responses.size() > 1) { for (auto &r: responses) { bracket_responses.emplace_back( - fmt::format("[{}]", EQ::SayLinkEngine::GenerateQuestSaylink(r, false, r)) + fmt::format("[{}]", Saylink::Create(r, false)) ); } } // Placed here to allow silent message or other message to override default for custom values. if (!button_one_name.empty() && !button_two_name.empty()) { - c->SetEntityVariable( - DIAWIND_RESPONSE_ONE_KEY.c_str(), - button_one_name.c_str() - ); - c->SetEntityVariable( - DIAWIND_RESPONSE_TWO_KEY.c_str(), - button_two_name.c_str() - ); + c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY, button_one_name); + c->SetEntityVariable(DIAWIND_RESPONSE_TWO_KEY, button_two_name); } // handle silent prompts from the [> silent syntax std::string silent_message; if (responses.empty() && markdown.find('[') != std::string::npos && markdown.find('>') != std::string::npos) { - silent_message = get_between(output, "[", ">"); + silent_message = Strings::GetBetween(output, "[", ">"); // temporary and used during the response - c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY.c_str(), silent_message.c_str()); + c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY, silent_message); // pop the silent message off - find_replace(output, fmt::format("[{}>", silent_message), ""); + Strings::FindReplace(output, fmt::format("[{}>", silent_message), ""); } else if (!responses.empty()) { // handle silent prompts from the single respond bracket syntax [] silent_message = responses[0]; // temporary and used during the response - c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY.c_str(), silent_message.c_str()); + c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY, silent_message); // pop the silent message off - find_replace(output, fmt::format("[{}]", silent_message), ""); + Strings::FindReplace(output, fmt::format("[{}]", silent_message), ""); } // strip brackets if (render_nobracket) { - find_replace(output, "[", ""); - find_replace(output, "]", ""); + Strings::FindReplace(output, "[", ""); + Strings::FindReplace(output, "]", ""); } // render title @@ -385,13 +387,13 @@ void DialogueWindow::Render(Client *c, std::string markdown) // title std::string popup_title; if (markdown.find("{title:") != std::string::npos) { - popup_title = get_between(output, "{title:", "}"); + popup_title = Strings::GetBetween(output, "{title:", "}"); LogDiaWind("Client [{}] Rendering title option title [{}]", c->GetCleanName(), popup_title); if (!popup_title.empty()) { - find_replace(output, fmt::format("{{title:{}}}", popup_title), ""); - title = trim(popup_title); + Strings::FindReplace(output, fmt::format("{{title:{}}}", popup_title), ""); + title = Strings::Trim(popup_title); } } @@ -407,7 +409,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) // click response // window type response - uint32 window_type = (StringIsNumber(wintype) ? std::atoi(wintype.c_str()) : 0); + uint32 window_type = (Strings::IsNumber(wintype) ? std::atoi(wintype.c_str()) : 0); std::string click_response_button = (window_type == 1 ? "Yes" : "OK"); std::string click_response = fmt::format( "Click [{}] to continue...", @@ -449,7 +451,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) // while brackets still exist int tag_index = 0; while (output.find('{') != std::string::npos && output.find('}') != std::string::npos) { - std::string color_tag = get_between(output, "{", "}"); + std::string color_tag = Strings::GetBetween(output, "{", "}"); LogDiaWindDetail( "Client [{}] Rendering color tags ({}) [{}]", @@ -464,7 +466,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) // build html tag html_tag = fmt::format("", color.second); // pop the response off of the message - find_replace(output, fmt::format("{{{}}}", color.first), html_tag); + Strings::FindReplace(output, fmt::format("{{{}}}", color.first), html_tag); } } @@ -479,9 +481,9 @@ void DialogueWindow::Render(Client *c, std::string markdown) // build the final output string std::string final_output; - final_output = fmt::format("{}{}{}

{}", quote_string, trim(output), quote_string, click_response); + final_output = fmt::format("{}{}{}

{}", quote_string, Strings::Trim(output), quote_string, click_response); if (render_hiddenresponse) { - final_output = fmt::format("{}{}{}", quote_string, trim(output), quote_string); + final_output = fmt::format("{}{}{}", quote_string, Strings::Trim(output), quote_string); } // send popup @@ -500,6 +502,130 @@ void DialogueWindow::Render(Client *c, std::string markdown) // if multiple brackets are presented, send message if (!bracket_responses.empty()) { c->Message(Chat::White, " --- Select Response from Options --- "); - c->Message(Chat::White, implode(" ", bracket_responses).c_str()); + c->Message(Chat::White, Strings::Implode(" ", bracket_responses).c_str()); } } + +std::string DialogueWindow::Break(uint32 break_count) +{ + if (!break_count) { + return std::string(); + } + + std::string break_message; + auto count = break_count; + + while (count) { + break_message.append("
"); + count--; + } + + return break_message; +} + +std::string DialogueWindow::CenterMessage(std::string message) +{ + if (message.empty()) { + return std::string(); + } + + auto cleaned_message = message; + + std::regex tags("<[^>]*>"); + + if (std::regex_search(cleaned_message, tags)) { + std::regex_replace(cleaned_message, tags, cleaned_message); + } + + auto message_len = cleaned_message.length(); + auto initial_index = (53 - (message_len * .80)); + auto index = 0; + std::string buffer; + while (index < initial_index) { + buffer.append(" "); + index++; + } + + return fmt::format("{} {}", buffer, message); +} + +std::string DialogueWindow::ColorMessage(std::string color, std::string message) +{ + if (message.empty()) { + return std::string(); + } + + if (!color.empty()) { + const auto &c = html_colors.find(color); + if (c != html_colors.end()) { + return fmt::format( + "{}", + c->second, + message + ); + } + } + + return message; +} + +std::string DialogueWindow::Indent(uint32 indent_count) +{ + if (!indent_count) { + return std::string(); + } + + std::string indent_message; + auto count = indent_count; + + while (count) { + indent_message.append("        "); + count--; + } + + return indent_message; +} + +std::string DialogueWindow::Link(std::string link, std::string message) +{ + if (link.empty()) { + return std::string(); + } + + if (!link.empty()) { + return fmt::format( + "{}", + link, + !message.empty() ? message : link + ); + } + + return message; +} + +std::string DialogueWindow::Table(std::string message) +{ + if (message.empty()) { + return std::string(); + } + + return fmt::format("{}
", message); +} + +std::string DialogueWindow::TableCell(std::string message) +{ + if (message.empty()) { + return ""; + } + + return fmt::format("{}", message); +} + +std::string DialogueWindow::TableRow(std::string message) +{ + if (message.empty()) { + return std::string(); + } + + return fmt::format("{}", message); +} diff --git a/zone/dialogue_window.h b/zone/dialogue_window.h index 7b0137550..5787b818f 100644 --- a/zone/dialogue_window.h +++ b/zone/dialogue_window.h @@ -381,13 +381,86 @@ const std::map animations = { {"salute", 67}, {"shiver", 68}, {"tapfoot", 69}, - {"bowto", 70}, - }; + {"bowto", 70} +}; +const std::map animation_names_map = { + { 1, "Kick" }, + { 2, "1H Piercing" }, + { 3, "2H Slashing" }, + { 4, "2H Blunt" }, + { 4, "2H Piercing" }, + { 5, "Throw" }, + { 6, "Off Hand" }, + { 7, "Bash" }, + { 8, "Main Hand" }, + { 9, "Bow" }, + { 10, "Swim" }, + { 11, "Round Kick" }, + { 12, "Get Hit" }, + { 13, "Get Hit" }, + { 14, "Falling" }, + { 15, "Drowning" }, + { 16, "Death" }, + { 17, "Stand By" }, + { 18, "Stand By" }, + { 19, "Lunge" }, + { 20, "Jump" }, + { 21, "Falling" }, + { 22, "Crouched Walk" }, + { 23, "Ladder Climb" }, + { 24, "Crouch" }, + { 25, "Swim" }, + { 26, "Idle" }, + { 27, "Cheer" }, + { 28, "Disgusted" }, + { 29, "Wave" }, + { 30, "Rude" }, + { 31, "Yawn" }, + { 33, "Move To Side" }, + { 35, "Ice Slide" }, + { 36, "Kneel" }, + { 37, "Swim" }, + { 38, "Sit" }, + { 42, "Cast" }, + { 43, "Cast" }, + { 44, "Cast" }, + { 45, "Flying Kick" }, + { 46, "Tiger Claw" }, + { 47, "Eagle Strike" }, + { 48, "Nod Yes" }, + { 49, "Shake No" }, + { 50, "Plead" }, + { 51, "Clap" }, + { 52, "Blush" }, + { 54, "Chuckle" }, + { 57, "Head Tilt" }, + { 58, "Dance" }, + { 59, "Disagree" }, + { 60, "Glare" }, + { 61, "Peer" }, + { 62, "Kneel" }, + { 63, "Laugh" }, + { 64, "Point" }, + { 65, "Shrug" }, + { 66, "Hand Raise" }, + { 67, "Salute" }, + { 68, "Shiver" }, + { 69, "Tap Foot" }, + { 70, "Bow To" } +}; class DialogueWindow { public: static void Render(Client *c, std::string markdown); + static std::string Break(uint32 break_count = 1); + static std::string CenterMessage(std::string message); + static std::string ColorMessage(std::string color, std::string message); + static std::string Indent(uint32 indent_count = 1); + static std::string Link(std::string link, std::string message = std::string()); + static std::string Table(std::string message); + static std::string TableCell(std::string message = std::string()); + static std::string TableRow(std::string message); }; diff --git a/zone/doors.cpp b/zone/doors.cpp index 9ed2c4dc6..b977ce066 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -18,7 +18,9 @@ #include "../common/global_define.h" #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" + +#include "../common/repositories/doors_repository.h" #include "client.h" #include "doors.h" @@ -28,7 +30,7 @@ #include "string_ids.h" #include "worldserver.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include @@ -39,74 +41,76 @@ #define OPEN_INVDOOR 0x03 #define CLOSE_INVDOOR 0x02 -extern EntityList entity_list; +extern EntityList entity_list; extern WorldServer worldserver; -Doors::Doors(const DoorsRepository::Doors& door) : - close_timer(5000), - m_Position(door.pos_x, door.pos_y, door.pos_z, door.heading), - m_Destination(door.dest_x, door.dest_y, door.dest_z, door.dest_heading) +Doors::Doors(const DoorsRepository::Doors &door) : + m_close_timer(5000), + m_position(door.pos_x, door.pos_y, door.pos_z, door.heading), + m_destination(door.dest_x, door.dest_y, door.dest_z, door.dest_heading) { - strn0cpy(zone_name, door.zone.c_str(), sizeof(zone_name)); - strn0cpy(door_name, door.name.c_str(), sizeof(door_name)); - strn0cpy(destination_zone_name, door.dest_zone.c_str(), sizeof(destination_zone_name)); + strn0cpy(m_zone_name, door.zone.c_str(), sizeof(m_zone_name)); + strn0cpy(m_door_name, door.name.c_str(), sizeof(m_door_name)); + strn0cpy(m_destination_zone_name, door.dest_zone.c_str(), sizeof(m_destination_zone_name)); - database_id = door.id; - door_id = door.doorid; - incline = door.incline; - open_type = door.opentype; - guild_id = door.guild; - lockpick = door.lockpick; - key_item_id = door.keyitem; - no_key_ring = door.nokeyring; - trigger_door = door.triggerdoor; - trigger_type = door.triggertype; - triggered = false; - door_param = door.door_param; - size = door.size; - invert_state = door.invert_state; - destination_instance_id = door.dest_instance; - is_ldon_door = door.is_ldon_door; - client_version_mask = door.client_version_mask; + m_database_id = door.id; + m_door_id = door.doorid; + m_incline = door.incline; + m_open_type = door.opentype; + m_guild_id = door.guild; + m_lockpick = door.lockpick; + m_key_item_id = door.keyitem; + m_no_key_ring = door.nokeyring; + m_trigger_door = door.triggerdoor; + m_trigger_type = door.triggertype; + triggered = false; + m_door_param = door.door_param; + m_size = door.size; + m_invert_state = door.invert_state; + m_destination_instance_id = door.dest_instance; + m_is_ldon_door = door.is_ldon_door; + m_dz_switch_id = door.dz_switch_id; + m_client_version_mask = door.client_version_mask; SetOpenState(false); - close_timer.Disable(); + m_close_timer.Disable(); - disable_timer = (door.disable_timer == 1 ? true : false); + m_disable_timer = (door.disable_timer == 1 ? true : false); } Doors::Doors(const char *model, const glm::vec4 &position, uint8 open_type, uint16 size) : - close_timer(5000), - m_Position(position), - m_Destination(glm::vec4()){ + m_close_timer(5000), + m_position(position), + m_destination(glm::vec4()) +{ - strn0cpy(zone_name, zone->GetShortName(), 32); - strn0cpy(door_name, model, 32); - strn0cpy(destination_zone_name, "NONE", 32); + strn0cpy(m_zone_name, zone->GetShortName(), 32); + strn0cpy(m_door_name, model, 32); + strn0cpy(m_destination_zone_name, "NONE", 32); - database_id = (uint32) content_db.GetDoorsCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()); - door_id = (uint8) content_db.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()); + m_database_id = content_db.GetDoorsCountPlusOne(); + m_door_id = content_db.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()); - open_type = open_type; - size = size; - incline = 0; - guild_id = 0; - lockpick = 0; - key_item_id = 0; - no_key_ring = 0; - trigger_door = 0; - trigger_type = 0; - triggered = false; - door_param = 0; - invert_state = 0; - is_ldon_door = 0; - client_version_mask = 4294967295u; - disable_timer = 0; - destination_instance_id = 0; + m_open_type = open_type; + m_size = size; + m_incline = 0; + m_guild_id = 0; + m_lockpick = 0; + m_key_item_id = 0; + m_no_key_ring = 0; + m_trigger_door = 0; + m_trigger_type = 0; + triggered = false; + m_door_param = 0; + m_invert_state = 0; + m_is_ldon_door = 0; + m_client_version_mask = 4294967295u; + m_disable_timer = 0; + m_destination_instance_id = 0; SetOpenState(false); - close_timer.Disable(); + m_close_timer.Disable(); } @@ -116,57 +120,58 @@ Doors::~Doors() bool Doors::Process() { - if (close_timer.Enabled() && close_timer.Check() && IsDoorOpen()) { - if (open_type == 40 || GetTriggerType() == 1) { - auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); - MoveDoor_Struct *md = (MoveDoor_Struct *) outapp->pBuffer; - md->doorid = door_id; - md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; + if (m_close_timer.Enabled() && m_close_timer.Check() && IsDoorOpen()) { + if (m_open_type == 40 || GetTriggerType() == 1) { + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + MoveDoor_Struct *md = (MoveDoor_Struct *) outapp->pBuffer; + md->doorid = m_door_id; + md->action = m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; entity_list.QueueClients(0, outapp); safe_delete(outapp); } triggered = false; - close_timer.Disable(); + m_close_timer.Disable(); SetOpenState(false); } return true; } -void Doors::HandleClick(Client* sender, uint8 trigger) { +void Doors::HandleClick(Client *sender, uint8 trigger) +{ Log(Logs::Detail, Logs::Doors, - "%s clicked door %s (dbid %d, eqid %d) at %s", - sender->GetName(), - door_name, - database_id, - door_id, - to_string(m_Position).c_str() + "%s clicked door %s (dbid %d, eqid %d) at %s", + sender->GetName(), + m_door_name, + m_database_id, + m_door_id, + to_string(m_position).c_str() ); Log(Logs::Detail, Logs::Doors, - "incline %d, open_type %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", - incline, - open_type, - lockpick, - key_item_id, - no_key_ring, - trigger_door, - trigger_type, - door_param + "incline %d, open_type %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", + m_incline, + m_open_type, + m_lockpick, + m_key_item_id, + m_no_key_ring, + m_trigger_door, + m_trigger_type, + m_door_param ); Log(Logs::Detail, Logs::Doors, - "disable_timer '%s',size %d, invert %d, dest: %s %s", - (disable_timer ? "true" : "false"), - size, - invert_state, - destination_zone_name, - to_string(m_Destination).c_str() + "disable_timer '%s',size %d, invert %d, dest: %s %s", + (m_disable_timer ? "true" : "false"), + m_size, + m_invert_state, + m_destination_zone_name, + to_string(m_destination).c_str() ); - auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); auto *move_door_packet = (MoveDoor_Struct *) outapp->pBuffer; - move_door_packet->doorid = door_id; + move_door_packet->doorid = m_door_id; if (IsLDoNDoor()) { if (sender) { @@ -176,7 +181,8 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { sender->MessageString(Chat::Red, DUNGEON_SEALED); safe_delete(outapp); return; - } else { + } + else { sender->KeyRingAdd(RuleI(Adventure, ItemIDToEnablePorts)); } } @@ -185,8 +191,8 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { if (!sender->GetPendingAdventureDoorClick()) { sender->PendingAdventureDoorClick(); auto pack = new ServerPacket( - ServerOP_AdventureClickDoor, - sizeof(ServerPlayerClickedAdventureDoor_Struct) + ServerOP_AdventureClickDoor, + sizeof(ServerPlayerClickedAdventureDoor_Struct) ); /** @@ -207,11 +213,17 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { } } - // todo: if IsDzDoor() call Client::MovePCDynamicZone(target_zone_id) (for systems that use dzs) + if (m_dz_switch_id != 0) { + sender->UpdateTasksOnTouchSwitch(m_dz_switch_id); + if (sender->TryMovePCDynamicZoneSwitch(m_dz_switch_id)) { + safe_delete(outapp); + return; + } + } uint32 required_key_item = GetKeyItem(); uint8 disable_add_to_key_ring = GetNoKeyring(); - bool player_has_key = false; + bool player_has_key = false; uint32 player_key = 0; const EQ::ItemInstance *lock_pick_item = sender->GetInv().GetItem(EQ::invslot::slotCursor); @@ -240,33 +252,50 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { * Door is only triggered by an object */ if (trigger == 1) { - if (!IsDoorOpen() || (open_type == 58)) { - move_door_packet->action = static_cast(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); - } else { - move_door_packet->action = static_cast(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + if (!IsDoorOpen() || (m_open_type == 58)) { + move_door_packet->action = static_cast(m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); } - } else { + else { + move_door_packet->action = static_cast(m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + } + } + else { safe_delete(outapp); return; } } + // enforce flags before they hit zoning process + auto z = GetZone(m_destination_zone_name, 0); + if (z && !z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && std::stoi(z->flag_needed) == 1) { + if (sender->Admin() < minStatusToIgnoreZoneFlags && !sender->HasZoneFlag(z->zoneidnumber)) { + LogInfo( + "Character [{}] does not have the flag to be in this zone [{}]!", + sender->GetCleanName(), + z->flag_needed + ); + sender->MessageString(Chat::LightBlue, DOORS_LOCKED); + } + } + /** * Guild Doors * * Door is not locked */ - bool is_guild_door = (GetGuildID() > 0) && (GetGuildID() == sender->GuildID()); - bool is_door_not_locked = ((required_key_item == 0) && (GetLockpick() == 0) && (GetGuildID() == 0)); - bool is_door_open_and_open_able = (IsDoorOpen() && (open_type == 58)); + bool is_guild_door = (GetGuildID() > 0) && (GetGuildID() == sender->GuildID()); + bool is_door_not_locked = ((required_key_item == 0) && (GetLockpick() == 0) && (GetGuildID() == 0)); + bool is_door_open_and_open_able = (IsDoorOpen() && (m_open_type == 58)); if (is_door_not_locked || is_door_open_and_open_able || is_guild_door) { if (!IsDoorOpen() || (GetOpenType() == 58)) { - move_door_packet->action = static_cast(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); - } else { - move_door_packet->action = static_cast(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + move_door_packet->action = static_cast(m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); } - } else { + else { + move_door_packet->action = static_cast(m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + } + } + else { /** * Guild Doors @@ -275,9 +304,10 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { std::string guild_name; char door_message[240]; - if (guild_mgr.GetGuildNameByID(guild_id, guild_name)) { + if (guild_mgr.GetGuildNameByID(m_guild_id, guild_name)) { sprintf(door_message, "Only members of the <%s> guild may enter here", guild_name.c_str()); - } else { + } + else { strcpy(door_message, "Door is locked by an unknown guild"); } @@ -300,24 +330,25 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { if (sender->GetGM()) { sender->MessageString(Chat::LightBlue, DOORS_GM); - if (!IsDoorOpen() || (open_type == 58)) { - move_door_packet->action = static_cast(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); - } else { - move_door_packet->action = static_cast(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + if (!IsDoorOpen() || (m_open_type == 58)) { + move_door_packet->action = static_cast(m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); + } + else { + move_door_packet->action = static_cast(m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); } } - /** - * Player has something they are trying to open it with - */ + /** + * Player has something they are trying to open it with + */ else if (player_key) { /** * Key required and client is using the right key */ if (required_key_item && - (required_key_item == player_key)) { + (required_key_item == player_key)) { if (!disable_add_to_key_ring) { sender->KeyRingAdd(player_key); @@ -325,20 +356,21 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { sender->Message(Chat::LightBlue, "You got it open!"); - if (!IsDoorOpen() || (open_type == 58)) { - move_door_packet->action = static_cast(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); - } else { - move_door_packet->action = static_cast(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + if (!IsDoorOpen() || (m_open_type == 58)) { + move_door_packet->action = static_cast(m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); + } + else { + move_door_packet->action = static_cast(m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); } } } - /** - * Try Lock pick - */ + /** + * Try Lock pick + */ else if (lock_pick_item != nullptr) { if (sender->GetSkill(EQ::skills::SkillPickLock)) { - Timer* pick_lock_timer = sender->GetPickLockTimer(); + Timer *pick_lock_timer = sender->GetPickLockTimer(); if (lock_pick_item->GetItem()->ItemType == EQ::item::ItemTypeLockPick) { if (!pick_lock_timer->Check()) { // Stop full scale mad spamming @@ -357,31 +389,37 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { if (!IsDoorOpen()) { sender->CheckIncreaseSkill(EQ::skills::SkillPickLock, nullptr, 1); - move_door_packet->action = static_cast(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); + move_door_packet->action = static_cast(m_invert_state == 0 ? OPEN_DOOR + : OPEN_INVDOOR); sender->MessageString(Chat::LightBlue, DOORS_SUCCESSFUL_PICK); - } else { - move_door_packet->action = static_cast(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); } - } else { + else { + move_door_packet->action = static_cast(m_invert_state == 0 ? CLOSE_DOOR + : CLOSE_INVDOOR); + } + } + else { sender->MessageString(Chat::LightBlue, DOORS_INSUFFICIENT_SKILL); safe_delete(outapp); return; } - } else { + } + else { sender->MessageString(Chat::LightBlue, DOORS_NO_PICK); safe_delete(outapp); return; } - } else { + } + else { sender->MessageString(Chat::LightBlue, DOORS_CANT_PICK); safe_delete(outapp); return; } } - /** - * Locked door and nothing to open it with - */ + /** + * Locked door and nothing to open it with + */ else { /** @@ -390,12 +428,14 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { if (sender->KeyRingCheck(required_key_item)) { player_key = required_key_item; sender->Message(Chat::LightBlue, "You got it open!"); // more debug spam - if (!IsDoorOpen() || (open_type == 58)) { - move_door_packet->action = static_cast(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); - } else { - move_door_packet->action = static_cast(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + if (!IsDoorOpen() || (m_open_type == 58)) { + move_door_packet->action = static_cast(m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); } - } else { + else { + move_door_packet->action = static_cast(m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + } + } + else { sender->MessageString(Chat::LightBlue, DOORS_LOCKED); safe_delete(outapp); return; @@ -404,16 +444,20 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { } entity_list.QueueClients(sender, outapp, false); - if (!IsDoorOpen() || (open_type == 58)) { - if (!disable_timer) - close_timer.Start(); + if (!IsDoorOpen() || (m_open_type == 58)) { + if (!m_disable_timer) { + m_close_timer.Start(); + } - if(strncmp(destination_zone_name, "NONE", strlen("NONE")) == 0) + if (strncmp(m_destination_zone_name, "NONE", strlen("NONE")) == 0) { SetOpenState(true); - } else { - close_timer.Disable(); - if (!disable_timer) + } + } + else { + m_close_timer.Disable(); + if (!m_disable_timer) { SetOpenState(false); + } } /* @@ -423,7 +467,8 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { * we return because we don't want people using teleports on an unlocked door (exploit!) */ - if ((move_door_packet->action == CLOSE_DOOR && invert_state == 0) || (move_door_packet->action == CLOSE_INVDOOR && invert_state == 1)) { + if ((move_door_packet->action == CLOSE_DOOR && m_invert_state == 0) || + (move_door_packet->action == CLOSE_INVDOOR && m_invert_state == 1)) { safe_delete(outapp); return; } @@ -435,15 +480,18 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { if (trigger_door_entity && !trigger_door_entity->triggered) { triggered = true; trigger_door_entity->HandleClick(sender, 1); - } else { + } + else { triggered = false; } - } else if ((GetTriggerDoorID() != 0) && (GetTriggerType() != 1)) { + } + else if ((GetTriggerDoorID() != 0) && (GetTriggerType() != 1)) { Doors *trigger_door_entity = entity_list.FindDoor(GetTriggerDoorID()); if (trigger_door_entity && !trigger_door_entity->triggered) { triggered = true; trigger_door_entity->HandleClick(sender, 0); - } else { + } + else { triggered = false; } } @@ -451,272 +499,244 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { /** * Teleport door */ - if (((open_type == 57) || (open_type == 58)) && - (strncmp(destination_zone_name, "NONE", strlen("NONE")) != 0)) { + if (((m_open_type == 57) || (m_open_type == 58)) && + (strncmp(m_destination_zone_name, "NONE", strlen("NONE")) != 0)) { /** * If click destination is same zone and doesn't require a key */ - if ((strncmp(destination_zone_name, zone_name, strlen(zone_name)) == 0) && (!required_key_item)) { + if ((strncmp(m_destination_zone_name, m_zone_name, strlen(m_zone_name)) == 0) && (!required_key_item)) { if (!disable_add_to_key_ring) { sender->KeyRingAdd(player_key); } sender->MovePC( - zone->GetZoneID(), - zone->GetInstanceID(), - m_Destination.x, - m_Destination.y, - m_Destination.z, - m_Destination.w + zone->GetZoneID(), + zone->GetInstanceID(), + m_destination.x, + m_destination.y, + m_destination.z, + m_destination.w ); } - /** - * If requires a key - */ + /** + * If requires a key + */ else if ( - (!IsDoorOpen() || open_type == 58) && - (required_key_item && ((required_key_item == player_key) || sender->GetGM())) - ) { + (!IsDoorOpen() || m_open_type == 58) && + (required_key_item && ((required_key_item == player_key) || sender->GetGM())) + ) { if (!disable_add_to_key_ring) { sender->KeyRingAdd(player_key); } - if (ZoneID(destination_zone_name) == zone->GetZoneID()) { + if (ZoneID(m_destination_zone_name) == zone->GetZoneID()) { sender->MovePC( - zone->GetZoneID(), - zone->GetInstanceID(), - m_Destination.x, - m_Destination.y, - m_Destination.z, - m_Destination.w + zone->GetZoneID(), + zone->GetInstanceID(), + m_destination.x, + m_destination.y, + m_destination.z, + m_destination.w ); - } else { + } + else { sender->MovePC( - ZoneID(destination_zone_name), - static_cast(destination_instance_id), - m_Destination.x, - m_Destination.y, - m_Destination.z, - m_Destination.w + ZoneID(m_destination_zone_name), + static_cast(m_destination_instance_id), + m_destination.x, + m_destination.y, + m_destination.z, + m_destination.w ); } } - if ((!IsDoorOpen() || open_type == 58) && (!required_key_item)) { - if (ZoneID(destination_zone_name) == zone->GetZoneID()) { + if ((!IsDoorOpen() || m_open_type == 58) && (!required_key_item)) { + if (ZoneID(m_destination_zone_name) == zone->GetZoneID()) { sender->MovePC( - zone->GetZoneID(), - zone->GetInstanceID(), - m_Destination.x, - m_Destination.y, - m_Destination.z, - m_Destination.w + zone->GetZoneID(), + zone->GetInstanceID(), + m_destination.x, + m_destination.y, + m_destination.z, + m_destination.w ); - } else { + } + else { sender->MovePC( - ZoneID(destination_zone_name), - static_cast(destination_instance_id), - m_Destination.x, - m_Destination.y, - m_Destination.z, - m_Destination.w + ZoneID(m_destination_zone_name), + static_cast(m_destination_instance_id), + m_destination.x, + m_destination.y, + m_destination.z, + m_destination.w ); } } } } -void Doors::Open(Mob* sender, bool alt_mode) +void Doors::Open(Mob *sender, bool alt_mode) { if (sender) { - if (GetTriggerType() == 255 || GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || open_type == 59 || open_type == 58 || !sender->IsNPC()) { // this object isnt triggered or door is locked - NPCs should not open locked doors! + if (GetTriggerType() == 255 || GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || + m_open_type == 59 || m_open_type == 58 || + !sender->IsNPC()) { // this object isnt triggered or door is locked - NPCs should not open locked doors! return; } - auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); - MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer; - md->doorid = door_id; - md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR; + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + MoveDoor_Struct *md = (MoveDoor_Struct *) outapp->pBuffer; + md->doorid = m_door_id; + md->action = m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR; entity_list.QueueCloseClients(sender, outapp, false, 200); safe_delete(outapp); if (!alt_mode) { // original function - if (!is_open) { - if (!disable_timer) - close_timer.Start(); - is_open = true; + if (!m_is_open) { + if (!m_disable_timer) { + m_close_timer.Start(); + } + m_is_open = true; } else { - close_timer.Disable(); - if (!disable_timer) - is_open = false; + m_close_timer.Disable(); + if (!m_disable_timer) { + m_is_open = false; + } } } else { // alternative function - if (!disable_timer) - close_timer.Start(); - is_open = true; + if (!m_disable_timer) { + m_close_timer.Start(); + } + m_is_open = true; } } } void Doors::ForceOpen(Mob *sender, bool alt_mode) { - auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); - MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer; - md->doorid = door_id; - md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR; + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + MoveDoor_Struct *md = (MoveDoor_Struct *) outapp->pBuffer; + md->doorid = m_door_id; + md->action = m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR; entity_list.QueueClients(sender, outapp, false); safe_delete(outapp); if (!alt_mode) { // original function - if (!is_open) { - if (!disable_timer) - close_timer.Start(); - is_open = true; + if (!m_is_open) { + if (!m_disable_timer) { + m_close_timer.Start(); + } + m_is_open = true; } else { - close_timer.Disable(); - if (!disable_timer) - is_open = false; + m_close_timer.Disable(); + if (!m_disable_timer) { + m_is_open = false; + } } } else { // alternative function - if (!disable_timer) - close_timer.Start(); - is_open = true; + if (!m_disable_timer) { + m_close_timer.Start(); + } + m_is_open = true; } } -void Doors::ForceClose(Mob *sender, bool alt_mode) { - auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); +void Doors::ForceClose(Mob *sender, bool alt_mode) +{ + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct *move_door_packet; move_door_packet = (MoveDoor_Struct *) outapp->pBuffer; - move_door_packet->doorid = door_id; - move_door_packet->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; // change from original (open to close) + move_door_packet->doorid = m_door_id; + move_door_packet->action = m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; // change from original (open to close) entity_list.QueueClients(sender, outapp, false); safe_delete(outapp); if (!alt_mode) { // original function - if (!is_open) { - if (!disable_timer) - close_timer.Start(); - is_open = true; - } else { - close_timer.Disable(); - is_open = false; + if (!m_is_open) { + if (!m_disable_timer) { + m_close_timer.Start(); + } + m_is_open = true; + } + else { + m_close_timer.Disable(); + m_is_open = false; + } + } + else { // alternative function + if (m_is_open) { + m_close_timer.Trigger(); } - } else { // alternative function - if (is_open) - close_timer.Trigger(); } } void Doors::ToggleState(Mob *sender) { - if(GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || open_type == 58 || open_type == 40) { // borrowed some NPCOpen criteria + if (GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || m_open_type == 58 || + m_open_type == 40) { // borrowed some NPCOpen criteria return; } - auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); - MoveDoor_Struct* move_door_packet; - move_door_packet = (MoveDoor_Struct*)outapp->pBuffer; - move_door_packet->doorid = door_id; + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + MoveDoor_Struct *move_door_packet; + move_door_packet = (MoveDoor_Struct *) outapp->pBuffer; + move_door_packet->doorid = m_door_id; - if(!is_open) { - move_door_packet->action = static_cast(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); - is_open=true; + if (!m_is_open) { + move_door_packet->action = static_cast(m_invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); + m_is_open = true; } else { - move_door_packet->action = static_cast(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); - is_open=false; + move_door_packet->action = static_cast(m_invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); + m_is_open = false; } - entity_list.QueueClients(sender,outapp,false); + entity_list.QueueClients(sender, outapp, false); safe_delete(outapp); } -int32 ZoneDatabase::GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version) { - - std::string query = StringFormat("SELECT MAX(id), count(*) FROM doors " - "WHERE zone = '%s' AND (version = %u OR version = -1)", - zone_name, version); - auto results = QueryDatabase(query); - if (!results.Success()) { - return -1; - } - - if (results.RowCount() != 1) - return -1; - - auto row = results.begin(); - - if (!oMaxID) - return atoi(row[1]); - - if (row[0]) - *oMaxID = atoi(row[0]); - else - *oMaxID = 0; - - return atoi(row[1]); +uint32 ZoneDatabase::GetDoorsCountPlusOne() +{ + const uint32 max_door_id = static_cast(DoorsRepository::GetMaxId(*this)); + return (max_door_id + 1); } -int32 ZoneDatabase::GetDoorsCountPlusOne(const char *zone_name, int16 version) { - std::string query = StringFormat( - "SELECT MAX(id) FROM doors WHERE zone = '%s' AND version = %u", - zone_name, - version - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - return -1; - } - - if (results.RowCount() != 1) - return -1; - - auto row = results.begin(); - - if (!row[0]) - return 0; - - return atoi(row[0]) + 1; -} - -int32 ZoneDatabase::GetDoorsDBCountPlusOne(const char *zone_name, int16 version) { - - uint32 oMaxID = 0; - - std::string query = StringFormat("SELECT MAX(doorid) FROM doors " - "WHERE zone = '%s' AND (version = %u OR version = -1)", - zone_name, version); +int ZoneDatabase::GetDoorsDBCountPlusOne(std::string zone_short_name, int16 version) +{ + const auto query = fmt::format( + "SELECT COALESCE(MAX(doorid), 1) FROM doors " + "WHERE zone = '{}' AND (version = {} OR version = -1)", + zone_short_name, + version + ); auto results = QueryDatabase(query); - if (!results.Success()) { + if (!results.Success() || !results.RowCount()) { return -1; } - if (results.RowCount() != 1) - return -1; + auto row = results.begin(); - auto row = results.begin(); + if (!row[0]) { + return 0; + } - if (!row[0]) - return 0; - - return atoi(row[0]) + 1; + return std::stoi(row[0]) + 1; } -std::vector ZoneDatabase::LoadDoors(const std::string& zone_name, int16 version) +std::vector ZoneDatabase::LoadDoors(const std::string &zone_name, int16 version) { - LogInfo("Loading Doors from database"); + auto door_entries = DoorsRepository::GetWhere( + *this, fmt::format( + "zone = '{}' AND (version = {} OR version = -1) {} ORDER BY doorid ASC", + zone_name, version, ContentFilterCriteria::apply())); - auto door_entries = DoorsRepository::GetWhere(*this, fmt::format( - "zone = '{}' AND (version = {} OR version = -1) {} ORDER BY doorid ASC", - zone_name, version, ContentFilterCriteria::apply())); - - LogDoors("Loaded [{}] doors for [{}] version [{}]", door_entries.size(), zone_name, version); + LogDoors("Loaded [{}] doors for [{}] version [{}]", Strings::Commify(door_entries.size()), zone_name, version); return door_entries; } @@ -724,49 +744,56 @@ std::vector ZoneDatabase::LoadDoors(const std::string& z void Doors::SetLocation(float x, float y, float z) { entity_list.DespawnAllDoors(); - m_Position = glm::vec4(x, y, z, m_Position.w); + m_position = glm::vec4(x, y, z, m_position.w); entity_list.RespawnAllDoors(); } -void Doors::SetPosition(const glm::vec4& position) { +void Doors::SetPosition(const glm::vec4 &position) +{ entity_list.DespawnAllDoors(); - m_Position = position; + m_position = position; entity_list.RespawnAllDoors(); } -void Doors::SetIncline(int in) { +void Doors::SetIncline(int in) +{ entity_list.DespawnAllDoors(); - incline = in; + m_incline = in; entity_list.RespawnAllDoors(); } -void Doors::SetInvertState(int in) { +void Doors::SetInvertState(int in) +{ entity_list.DespawnAllDoors(); - invert_state = in; + m_invert_state = in; entity_list.RespawnAllDoors(); } -void Doors::SetOpenType(uint8 in) { +void Doors::SetOpenType(uint8 in) +{ entity_list.DespawnAllDoors(); - open_type = in; + m_open_type = in; entity_list.RespawnAllDoors(); } -void Doors::SetDoorName(const char* name) { +void Doors::SetDoorName(const char *name) +{ entity_list.DespawnAllDoors(); - memset(door_name, 0, sizeof(door_name)); - strncpy(door_name, name, sizeof(door_name)); + memset(m_door_name, 0, sizeof(m_door_name)); + strncpy(m_door_name, name, sizeof(m_door_name)); entity_list.RespawnAllDoors(); } -void Doors::SetSize(uint16 in) { +void Doors::SetSize(uint16 in) +{ entity_list.DespawnAllDoors(); - size = in; + m_size = in; entity_list.RespawnAllDoors(); } -void Doors::SetDisableTimer(bool flag) { - disable_timer = flag; +void Doors::SetDisableTimer(bool flag) +{ + m_disable_timer = flag; } void Doors::CreateDatabaseEntry() @@ -775,14 +802,11 @@ void Doors::CreateDatabaseEntry() return; } - /** - * Persist - */ content_db.InsertDoor( GetDoorDBID(), GetDoorID(), GetDoorName(), - m_Position, + m_position, GetOpenType(), static_cast(GetGuildID()), GetLockpick(), @@ -796,15 +820,15 @@ void Doors::CreateDatabaseEntry() float Doors::GetX() { - return m_Position.x; + return m_position.x; } float Doors::GetY() { - return m_Position.y; + return m_position.y; } float Doors::GetZ() { - return m_Position.z; + return m_position.z; } diff --git a/zone/doors.h b/zone/doors.h index a0d9c6364..6ee15f46b 100644 --- a/zone/doors.h +++ b/zone/doors.h @@ -17,30 +17,31 @@ public: Doors(const char *model, const glm::vec4& position, uint8 open_type = 58, uint16 size = 100); Doors(const DoorsRepository::Doors& door); - bool GetDisableTimer() { return disable_timer; } + bool GetDisableTimer() { return m_disable_timer; } bool IsDoor() const { return true; } - bool IsDoorOpen() { return is_open; } + bool IsDoorOpen() { return m_is_open; } bool Process(); bool triggered; - char *GetDoorName() { return door_name; } - const glm::vec4 GetDestination() const { return m_Destination; } - const glm::vec4 &GetPosition() const { return m_Position; } - int GetIncline() { return incline; } - int GetInvertState() { return invert_state; } - uint8 GetDoorID() { return door_id; } - uint8 GetNoKeyring() { return no_key_ring; } - uint8 GetOpenType() { return open_type; } - uint8 GetTriggerDoorID() { return trigger_door; } - uint8 GetTriggerType() { return trigger_type; } - uint8 IsLDoNDoor() { return is_ldon_door; } - uint16 GetLockpick() { return lockpick; } - uint16 GetSize() { return size; } - uint32 GetClientVersionMask() { return client_version_mask; } - uint32 GetDoorDBID() { return database_id; } - uint32 GetDoorParam() { return door_param; } - uint32 GetEntityID() { return entity_id; } - uint32 GetGuildID() { return guild_id; } - uint32 GetKeyItem() { return key_item_id; } + char *GetDoorName() { return m_door_name; } + const glm::vec4 GetDestination() const { return m_destination; } + const glm::vec4 &GetPosition() const { return m_position; } + int GetDzSwitchID() const { return m_dz_switch_id; } + int GetIncline() { return m_incline; } + int GetInvertState() { return m_invert_state; } + uint8 GetDoorID() { return m_door_id; } + uint8 GetNoKeyring() { return m_no_key_ring; } + uint8 GetOpenType() { return m_open_type; } + uint8 GetTriggerDoorID() { return m_trigger_door; } + uint8 GetTriggerType() { return m_trigger_type; } + uint8 IsLDoNDoor() { return m_is_ldon_door; } + uint16 GetLockpick() { return m_lockpick; } + uint16 GetSize() { return m_size; } + uint32 GetClientVersionMask() { return m_client_version_mask; } + uint32 GetDoorDBID() { return m_database_id; } + uint32 GetDoorParam() { return m_door_param; } + uint32 GetEntityID() { return m_entity_id; } + uint32 GetGuildID() { return m_guild_id; } + uint32 GetKeyItem() { return m_key_item_id; } void CreateDatabaseEntry(); void ForceClose(Mob *sender, bool alt_mode = false); void ForceOpen(Mob *sender, bool alt_mode = false); @@ -48,14 +49,14 @@ public: void Open(Mob *sender, bool alt_mode = false); void SetDisableTimer(bool flag); void SetDoorName(const char *name); - void SetEntityID(uint32 entity) { entity_id = entity; } + void SetEntityID(uint32 entity) { m_entity_id = entity; } void SetIncline(int in); void SetInvertState(int in); - void SetKeyItem(uint32 in) { key_item_id = in; } + void SetKeyItem(uint32 in) { m_key_item_id = in; } void SetLocation(float x, float y, float z); - void SetLockpick(uint16 in) { lockpick = in; } - void SetNoKeyring(uint8 in) { no_key_ring = in; } - void SetOpenState(bool st) { is_open = st; } + void SetLockpick(uint16 in) { m_lockpick = in; } + void SetNoKeyring(uint8 in) { m_no_key_ring = in; } + void SetOpenState(bool st) { m_is_open = st; } void SetOpenType(uint8 in); void SetPosition(const glm::vec4 &position); void SetSize(uint16 size); @@ -67,30 +68,31 @@ public: private: - uint32 database_id; - uint8 door_id; - char zone_name[32]; - char door_name[32]; - glm::vec4 m_Position; - int incline; - uint8 open_type; - uint32 guild_id; - uint16 lockpick; - uint32 key_item_id; - uint8 no_key_ring; - uint8 trigger_door; - uint8 trigger_type; - uint32 door_param; - uint16 size; - int invert_state; - uint32 entity_id; - bool disable_timer; - bool is_open; - Timer close_timer; - char destination_zone_name[16]; - int destination_instance_id; - glm::vec4 m_Destination; - uint8 is_ldon_door; - uint32 client_version_mask; + uint32 m_database_id; + uint8 m_door_id; + char m_zone_name[32]; + char m_door_name[32]; + glm::vec4 m_position; + int m_incline; + uint8 m_open_type; + uint32 m_guild_id; + uint16 m_lockpick; + uint32 m_key_item_id; + uint8 m_no_key_ring; + uint8 m_trigger_door; + uint8 m_trigger_type; + uint32 m_door_param; + uint16 m_size; + int m_invert_state; + uint32 m_entity_id; + bool m_disable_timer; + bool m_is_open; + Timer m_close_timer; + char m_destination_zone_name[16]; + int m_destination_instance_id; + glm::vec4 m_destination; + uint8 m_is_ldon_door; + int m_dz_switch_id = 0; + uint32 m_client_version_mask; }; #endif diff --git a/zone/dynamic_zone.cpp b/zone/dynamic_zone.cpp index a7f2bb822..4f01c737e 100644 --- a/zone/dynamic_zone.cpp +++ b/zone/dynamic_zone.cpp @@ -27,9 +27,6 @@ extern WorldServer worldserver; -// message string 8312 added in September 08 2020 Test patch (used by both dz and shared tasks) -const char* const CREATE_NOT_ALL_ADDED = "Not all players in your {} were added to the {}. The {} can take a maximum of {} players, and your {} has {}."; - DynamicZone::DynamicZone( uint32_t zone_id, uint32_t version, uint32_t duration, DynamicZoneType type) { @@ -148,6 +145,7 @@ void DynamicZone::CacheAllFromDatabase() zone->dynamic_zone_cache.emplace(dz_id, std::move(dz)); } + LogInfo("Loaded [{}] dynamic zone(s)", Strings::Commify(zone->dynamic_zone_cache.size())); LogDynamicZones("Caching [{}] dynamic zone(s) took [{}s]", zone->dynamic_zone_cache.size(), bench.elapsed()); } @@ -243,7 +241,7 @@ void DynamicZone::HandleWorldMessage(ServerPacket* pack) auto expedition = Expedition::FindCachedExpeditionByDynamicZoneID(dz->GetID()); if (expedition) { - LogExpeditionsModerate("Deleting expedition [{}] from zone cache", expedition->GetID()); + LogExpeditionsDetail("Deleting expedition [{}] from zone cache", expedition->GetID()); zone->expedition_cache.erase(expedition->GetID()); } } @@ -363,6 +361,16 @@ void DynamicZone::HandleWorldMessage(ServerPacket* pack) } break; } + case ServerOP_DzSetSwitchID: + { + auto buf = reinterpret_cast(pack->pBuffer); + auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id); + if (dz) + { + dz->ProcessSetSwitchID(buf->dz_switch_id); + } + break; + } case ServerOP_DzGetMemberStatuses: { // reply from world for online member statuses request for async zone member updates @@ -414,6 +422,20 @@ void DynamicZone::HandleWorldMessage(ServerPacket* pack) } break; } + case ServerOP_DzMovePC: + { + auto buf = reinterpret_cast(pack->pBuffer); + auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id); + if (dz) + { + Client* client = entity_list.GetClientByCharID(buf->character_id); + if (client) + { + dz->MovePCInto(client, false); + } + } + break; + } } } @@ -517,6 +539,12 @@ void DynamicZone::SendCompassUpdateToZoneMembers() } } +void DynamicZone::ProcessSetSwitchID(int dz_switch_id) +{ + DynamicZoneBase::ProcessSetSwitchID(dz_switch_id); + SendCompassUpdateToZoneMembers(); +} + void DynamicZone::SendLeaderNameToZoneMembers() { auto outapp_leader = CreateLeaderNamePacket(); @@ -777,3 +805,23 @@ bool DynamicZone::CanClientLootCorpse(Client* client, uint32_t npc_type_id, uint return true; } + +void DynamicZone::MovePCInto(Client* client, bool world_verify) const +{ + if (!world_verify) + { + DynamicZoneLocation zonein = GetZoneInLocation(); + ZoneMode zone_mode = HasZoneInLocation() ? ZoneMode::ZoneSolicited : ZoneMode::ZoneToSafeCoords; + client->MovePC(GetZoneID(), GetInstanceID(), zonein.x, zonein.y, zonein.z, zonein.heading, 0, zone_mode); + } + else + { + ServerPacket pack(ServerOP_DzMovePC, sizeof(ServerDzMovePC_Struct)); + auto buf = reinterpret_cast(pack.pBuffer); + buf->dz_id = GetID(); + buf->sender_zone_id = static_cast(zone->GetZoneID()); + buf->sender_instance_id = static_cast(zone->GetInstanceID()); + buf->character_id = client->CharacterID(); + worldserver.SendPacket(&pack); + } +} diff --git a/zone/dynamic_zone.h b/zone/dynamic_zone.h index de23ce238..45d4e93ea 100644 --- a/zone/dynamic_zone.h +++ b/zone/dynamic_zone.h @@ -32,8 +32,6 @@ class Database; class EQApplicationPacket; class ServerPacket; -extern const char* const CREATE_NOT_ALL_ADDED; - class DynamicZone : public DynamicZoneBase { public: @@ -53,6 +51,7 @@ public: void DoAsyncZoneMemberUpdates(); bool CanClientLootCorpse(Client* client, uint32_t npc_type_id, uint32_t entity_id); bool IsCurrentZoneDzInstance() const; + void MovePCInto(Client* client, bool world_verify = false) const; void RegisterOnClientAddRemove(std::function on_client_addremove); void SendClientWindowUpdate(Client* client); void SendLeaderNameToZoneMembers(); @@ -76,6 +75,7 @@ protected: void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed) override; bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status) override; void ProcessRemoveAllMembers(bool silent = false) override; + void ProcessSetSwitchID(int dz_switch_id) override; bool SendServerPacket(ServerPacket* packet) override; private: diff --git a/zone/effects.cpp b/zone/effects.cpp index dd58ec656..86a5c847f 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -28,10 +28,10 @@ #include "string_ids.h" #include "worldserver.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "position.h" -float Mob::GetActSpellRange(uint16 spell_id, float range, bool IsBard) +float Mob::GetActSpellRange(uint16 spell_id, float range) { float extrange = 100; @@ -57,7 +57,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { value -= (GetLevel() - 40) * 20; //This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch. - if (spell_id == SPELL_IMP_HARM_TOUCH && IsClient()) //Improved Harm Touch + if (spell_id == SPELL_IMP_HARM_TOUCH && (IsClient() || IsBot())) //Improved Harm Touch value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level) @@ -65,12 +65,12 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation; //Crtical Hit Calculation pathway - if (chance > 0 || (IsClient() && GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) { + if (chance > 0 || ((IsClient() || IsBot()) && GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) { int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals. //Improved Harm Touch is a guaranteed crit if you have at least one level of SCF. - if (spell_id == SPELL_IMP_HARM_TOUCH && IsClient() && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) + if (spell_id == SPELL_IMP_HARM_TOUCH && (IsClient() || IsBot()) && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) chance = 100; if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance) @@ -82,7 +82,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack; } - else if ((IsClient() && GetClass() == WIZARD) || (IsMerc() && GetClass() == CASTERDPS)) { + else if (((IsClient() || IsBot()) && GetClass() == WIZARD) || (IsMerc() && GetClass() == CASTERDPS)) { if ((GetLevel() >= RuleI(Spells, WizCritLevel)) && zone->random.Roll(RuleI(Spells, WizCritChance))){ //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed) ratio += zone->random.Int(20,70); @@ -90,7 +90,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { } } - if (IsClient() && GetClass() == WIZARD) + if ((IsClient() || IsBot()) && GetClass() == WIZARD) ratio += RuleI(Spells, WizCritRatio); //Default is zero if (Critical){ @@ -123,9 +123,9 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { else if (IsNPC() && CastToNPC()->GetSpellScale()) value = int64(static_cast(value) * CastToNPC()->GetSpellScale() / 100.0f); - entity_list.MessageCloseString( - this, true, 100, Chat::SpellCrit, - OTHER_CRIT_BLAST, GetName(), itoa(-value)); + entity_list.FilteredMessageCloseString( + this, true, 100, Chat::SpellCrit, FilterSpellCrits, + OTHER_CRIT_BLAST, 0, GetName(), itoa(-value)); if (IsClient()) MessageString(Chat::SpellCrit, YOU_CRIT_BLAST, itoa(-value)); @@ -285,39 +285,45 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ int64 Mob::GetExtraSpellAmt(uint16 spell_id, int64 extra_spell_amt, int64 base_spell_dmg) { if (RuleB(Spells, FlatItemExtraSpellAmt)) { - if (RuleB(Spells, ItemExtraSpellAmtCalcAsPercent)) - return abs(base_spell_dmg)*extra_spell_amt/100; - else + if (RuleB(Spells, ItemExtraSpellAmtCalcAsPercent)) { + return std::abs(base_spell_dmg) * extra_spell_amt / 100; + } else { return extra_spell_amt; + } } int total_cast_time = 0; - if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) - total_cast_time = spells[spell_id].recast_time + spells[spell_id].cast_time; - else + if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) { + total_cast_time = spells[spell_id].recast_time + spells[spell_id].cast_time; + } else { total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time; - - if (total_cast_time > 0 && total_cast_time <= 2500) - extra_spell_amt = extra_spell_amt*25/100; - else if (total_cast_time > 2500 && total_cast_time < 7000) - extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000; - else - extra_spell_amt = extra_spell_amt * total_cast_time / 7000; - - //Confirmed with parsing 10/9/21 ~Kayen - if (extra_spell_amt * 2 > abs(base_spell_dmg)) { - extra_spell_amt = abs(base_spell_dmg) / 2; } - if (RuleB(Spells, ItemExtraSpellAmtCalcAsPercent)) - return abs(base_spell_dmg)*extra_spell_amt/100; + if (total_cast_time > 0 && total_cast_time <= 2500) { + extra_spell_amt = extra_spell_amt * 25 / 100; + } else if (total_cast_time > 2500 && total_cast_time < 7000) { + extra_spell_amt = extra_spell_amt * (167 * ((total_cast_time - 1000) / 1000)) / 1000; + } else { + extra_spell_amt = extra_spell_amt * total_cast_time / 7000; + } + + //Confirmed with parsing 10/9/21 ~Kayen + if (extra_spell_amt * 2 > std::abs(base_spell_dmg)) { + extra_spell_amt = std::abs(base_spell_dmg) / 2; + } + + if (RuleB(Spells, ItemExtraSpellAmtCalcAsPercent)) { + return std::abs(base_spell_dmg) * extra_spell_amt / 100; + } return extra_spell_amt; } int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool from_buff_tic) { - + if (target == nullptr && IsBot()) { + target = this; + } if (IsNPC()) { value += value * CastToNPC()->GetSpellFocusHeal() / 100; @@ -443,7 +449,7 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr } -int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) +int32 Mob::GetActSpellCost(uint16 spell_id, int32 cost) { //FrenziedDevastation doubles mana cost of all DD spells int16 FrenziedDevastation = itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation; @@ -454,7 +460,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { - int16 mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; + int mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell if(mana_back > cost) mana_back = cost; @@ -514,109 +520,100 @@ bool Client::TrainDiscipline(uint32 itemid) { //get the item info const EQ::ItemData *item = database.GetItem(itemid); - if(item == nullptr) { + if (!item) { Message(Chat::Red, "Unable to find the tome you turned in!"); - LogError("Unable to find turned in tome id [{}]\n", (unsigned long)itemid); - return(false); + LogError("Unable to find turned in tome id [{}]", itemid); + return false; } if (!item->IsClassCommon() || item->ItemType != EQ::item::ItemTypeSpell) { Message(Chat::Red, "Invalid item type, you cannot learn from this item."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } //Need a way to determine the difference between a spell and a tome //so they cant turn in a spell and get it as a discipline //this is kinda a hack: - if(!( - item->Name[0] == 'T' && - item->Name[1] == 'o' && - item->Name[2] == 'm' && - item->Name[3] == 'e' && - item->Name[4] == ' ' - ) && !( - item->Name[0] == 'S' && - item->Name[1] == 'k' && - item->Name[2] == 'i' && - item->Name[3] == 'l' && - item->Name[4] == 'l' && - item->Name[5] == ':' && - item->Name[6] == ' ' - )) { + const std::string item_name = item->Name; + + if ( + item_name.substr(0, 5) != std::string("Tome ") && + item_name.substr(0, 7) != std::string("Skill: ") + ) { Message(Chat::Red, "This item is not a tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } - int myclass = GetClass(); - if(myclass == WIZARD || myclass == ENCHANTER || myclass == MAGICIAN || myclass == NECROMANCER) { + const auto player_class = GetClass(); + if (player_class == WIZARD || player_class == ENCHANTER || player_class == MAGICIAN || player_class == NECROMANCER) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } //make sure we can train this... //can we use the item? - uint32 cbit = 1 << (myclass-1); - if(!(item->Classes & cbit)) { + const auto class_bit = static_cast(1 << (player_class - 1)); + if (!(item->Classes & class_bit)) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } - uint32 spell_id = item->Scroll.Effect; - if(!IsValidSpell(spell_id)) { - Message(Chat::Red, "This tome contains invalid knowledge."); - return(false); + const auto spell_id = static_cast(item->Scroll.Effect); + if (!IsValidSpell(spell_id)) { + Message(Chat::Red, "This tome Contains invalid knowledge."); + return false; } //can we use the spell? - const SPDat_Spell_Struct &spell = spells[spell_id]; - uint8 level_to_use = spell.classes[myclass - 1]; - if(level_to_use == 255) { + const auto& spell = spells[spell_id]; + const auto level_to_use = spell.classes[player_class - 1]; + if (level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } - if(level_to_use > GetLevel()) { - Message(Chat::Red, "You must be at least level %d to learn this discipline.", level_to_use); + if (level_to_use > GetLevel()) { + Message(Chat::Red, fmt::format("You must be at least level {} to learn this discipline.", level_to_use).c_str()); //summon them the item back... SummonItem(itemid); - return(false); + return false; } //add it to PP. - int r; - for(r = 0; r < MAX_PP_DISCIPLINES; r++) { - if(m_pp.disciplines.values[r] == spell_id) { + for (int r = 0; r < MAX_PP_DISCIPLINES; r++) { + if (m_pp.disciplines.values[r] == spell_id) { Message(Chat::Red, "You already know this discipline."); //summon them the item back... SummonItem(itemid); - return(false); - } else if(m_pp.disciplines.values[r] == 0) { + return false; + } else if (m_pp.disciplines.values[r] == 0) { m_pp.disciplines.values[r] = spell_id; database.SaveCharacterDisc(CharacterID(), r, spell_id); SendDisciplineUpdate(); - Message(0, "You have learned a new discipline!"); - return(true); + Message(Chat::White, "You have learned a new discipline!"); + return true; } } + Message(Chat::Red, "You have learned too many disciplines and can learn no more."); - return(false); + return false; } bool Client::MemorizeSpellFromItem(uint32 item_id) { - const EQ::ItemData *item = database.GetItem(item_id); - if(item == nullptr) { + const auto& item = database.GetItem(item_id); + if (!item) { Message(Chat::Red, "Unable to find the scroll!"); - LogError("Unable to find scroll id [{}]\n", (unsigned long)item_id); + LogError("Unable to find scroll id [{}]", item_id); return false; } @@ -626,43 +623,41 @@ bool Client::MemorizeSpellFromItem(uint32 item_id) { return false; } - if(!( - item->Name[0] == 'S' && - item->Name[1] == 'p' && - item->Name[2] == 'e' && - item->Name[3] == 'l' && - item->Name[4] == 'l' && - item->Name[5] == ':' && - item->Name[6] == ' ' - )) { + const std::string item_name = item->Name; + + if ( + item_name.substr(0, 7) != std::string("Spell: ") && + item_name.substr(0, 6) != std::string("Song: ") + ) { Message(Chat::Red, "This item is not a scroll."); SummonItem(item_id); return false; } - int player_class = GetClass(); - uint32 cbit = 1 << (player_class - 1); - if(!(item->Classes & cbit)) { + + const auto class_bit = static_cast(1 << (GetClass() - 1)); + + if (!(item->Classes & class_bit)) { Message(Chat::Red, "Your class cannot learn from this scroll."); SummonItem(item_id); return false; } - uint32 spell_id = item->Scroll.Effect; - if(!IsValidSpell(spell_id)) { - Message(Chat::Red, "This scroll contains invalid knowledge."); + const auto spell_id = static_cast(item->Scroll.Effect); + if (!IsValidSpell(spell_id)) { + Message(Chat::Red, "This scroll Contains invalid knowledge."); return false; } - const SPDat_Spell_Struct &spell = spells[spell_id]; - uint8 level_to_use = spell.classes[player_class - 1]; - if(level_to_use == 255) { + const auto& spell = spells[spell_id]; + const auto level_to_use = spell.classes[GetClass() - 1]; + if (level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this scroll."); SummonItem(item_id); return false; } - if(level_to_use > GetLevel()) { - Message(Chat::Red, "You must be at least level %d to learn this spell.", level_to_use); + if (level_to_use > GetLevel()) { + Message(Chat::Red, fmt::format("You must be at least level {} to learn this spell.", level_to_use).c_str()); SummonItem(item_id); return false; } @@ -673,19 +668,19 @@ bool Client::MemorizeSpellFromItem(uint32 item_id) { if (next_slot != -1) { ScribeSpell(spell_id, next_slot); return true; - } - else { + } else { Message( Chat::Red, - "Unable to scribe spell %s (%i) to spellbook: no more spell book slots available.", - ((spell_id >= 0 && spell_id < SPDAT_RECORDS) ? spells[spell_id].name : "Out-of-range"), - spell_id + fmt::format( + "Unable to scribe {} ({}) to spellbook, no more spell book slots available.", + ((spell_id >= 0 && spell_id < SPDAT_RECORDS) ? spells[spell_id].name : "Out-of-range"), + spell_id + ).c_str() ); SummonItem(item_id); return false; } - } - else { + } else { Message(Chat::Red, "You already know this spell."); SummonItem(item_id); return false; @@ -741,7 +736,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { if (IsAmnesiad()) { MessageString(Chat::Red, MELEE_SILENCE); } - return(false); + return false; } //make sure we have the spell... @@ -751,12 +746,12 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { break; } if(r == MAX_PP_DISCIPLINES) - return(false); //not found. + return false; //not found. //make sure we can use it.. if(!IsValidSpell(spell_id)) { - Message(Chat::Red, "This tome contains invalid knowledge."); - return(false); + Message(Chat::Red, "This tome Contains invalid knowledge."); + return false; } if (DivineAura() && !IgnoreCastingRestriction(spell_id)) { @@ -769,18 +764,18 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { if(level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this tome."); //should summon them a new one... - return(false); + return false; } if(level_to_use > GetLevel()) { MessageString(Chat::Red, DISC_LEVEL_USE_ERROR); //should summon them a new one... - return(false); + return false; } if(GetEndurance() < spell.endurance_cost) { Message(11, "You are too fatigued to use this skill right now."); - return(false); + return false; } // sneak attack discs require you to be hidden for 4 seconds before use @@ -801,7 +796,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { Chat::White, fmt::format( "You can use this discipline in {}.", - ConvertSecondsToTime(remaining_time) + Strings::SecondsToTime(remaining_time) ).c_str() ); return false; @@ -852,7 +847,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline); } } - return(true); + return true; } uint32 Client::GetDisciplineTimer(uint32 timer_id) { @@ -925,6 +920,9 @@ void EntityList::AETaunt(Client *taunter, float range, int32 bonus_hate) for (auto &it : entity_list.GetCloseMobList(taunter, range)) { Mob *them = it.second; + if (!them) { + continue; + } if (!them->IsNPC()) { continue; @@ -1010,7 +1008,6 @@ void EntityList::AESpell( for (auto &it : entity_list.GetCloseMobList(caster_mob, distance)) { current_mob = it.second; - if (!current_mob) { continue; } @@ -1161,6 +1158,9 @@ void EntityList::MassGroupBuff( for (auto &it : entity_list.GetCloseMobList(caster, distance)) { current_mob = it.second; + if (!current_mob) { + continue; + } /** * Skip center @@ -1227,6 +1227,9 @@ void EntityList::AEAttack( for (auto &it : entity_list.GetCloseMobList(attacker, distance)) { current_mob = it.second; + if (!current_mob) { + continue; + } if (current_mob->IsNPC() && current_mob != attacker //this is not needed unless NPCs can use this @@ -1236,11 +1239,9 @@ void EntityList::AEAttack( ) { for (int i = 0; i < attack_rounds; i++) { - if (!attacker->IsClient() || attacker->GetClass() == MONK || attacker->GetClass() == RANGER) { attacker->Attack(current_mob, Hand, false, false, is_from_spell); - } - else { + } else { attacker->CastToClient()->DoAttackRounds(current_mob, Hand, is_from_spell); } } diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 85665f1c4..3b895a63c 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -21,7 +21,7 @@ #include "../common/global_define.h" #include "../common/seperator.h" #include "../common/misc_functions.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/features.h" #include "masterentity.h" #include "embparser.h" @@ -33,6 +33,29 @@ extern Zone *zone; +#ifdef EMBPERL_XS +void perl_register_quest(); +#ifdef EMBPERL_XS_CLASSES +void perl_register_mob(); +void perl_register_npc(); +void perl_register_client(); +void perl_register_corpse(); +void perl_register_entitylist(); +void perl_register_perlpacket(); +void perl_register_group(); +void perl_register_raid(); +void perl_register_inventory(); +void perl_register_questitem(); +void perl_register_spell(); +void perl_register_hateentry(); +void perl_register_object(); +void perl_register_doors(); +void perl_register_expedition(); +void perl_register_expedition_lock_messages(); +void perl_register_bot(); +#endif // EMBPERL_XS_CLASSES +#endif // EMBPERL_XS + const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_SAY", "EVENT_ITEM", @@ -129,7 +152,26 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_EQUIP_ITEM_CLIENT", "EVENT_UNEQUIP_ITEM_CLIENT", "EVENT_SKILL_UP", - "EVENT_LANGUAGE_SKILL_UP" + "EVENT_LANGUAGE_SKILL_UP", + "EVENT_ALT_CURRENCY_MERCHANT_BUY", + "EVENT_ALT_CURRENCY_MERCHANT_SELL", + "EVENT_MERCHANT_BUY", + "EVENT_MERCHANT_SELL", + "EVENT_INSPECT", + "EVENT_TASK_BEFORE_UPDATE", + "EVENT_AA_BUY", + "EVENT_AA_GAIN", + "EVENT_PAYLOAD", + "EVENT_LEVEL_DOWN", + "EVENT_GM_COMMAND", + "EVENT_DESPAWN", + "EVENT_DESPAWN_ZONE", + "EVENT_BOT_CREATE", + "EVENT_AUGMENT_INSERT_CLIENT", + "EVENT_AUGMENT_REMOVE_CLIENT", + // Add new events before these or Lua crashes + "EVENT_SPELL_EFFECT_BOT", + "EVENT_SPELL_EFFECT_BUFF_TIC_BOT" }; PerlembParser::PerlembParser() : perl(nullptr) @@ -137,6 +179,8 @@ PerlembParser::PerlembParser() : perl(nullptr) global_npc_quest_status_ = questUnloaded; player_quest_status_ = questUnloaded; global_player_quest_status_ = questUnloaded; + bot_quest_status_ = questUnloaded; + global_bot_quest_status_ = questUnloaded; } PerlembParser::~PerlembParser() @@ -170,15 +214,25 @@ void PerlembParser::ReloadQuests() global_npc_quest_status_ = questUnloaded; player_quest_status_ = questUnloaded; global_player_quest_status_ = questUnloaded; + bot_quest_status_ = questUnloaded; + global_bot_quest_status_ = questUnloaded; + item_quest_status_.clear(); spell_quest_status_.clear(); } int PerlembParser::EventCommon( - QuestEventID event, uint32 objid, const char *data, NPC *npcmob, EQ::ItemInstance *item_inst, const SPDat_Spell_Struct* spell, Mob *mob, - uint32 extradata, bool global, std::vector *extra_pointers -) -{ + QuestEventID event, + uint32 objid, + const char *data, + Mob *npcmob, + EQ::ItemInstance *item_inst, + const SPDat_Spell_Struct* spell, + Mob *mob, + uint32 extradata, + bool global, + std::vector *extra_pointers +) { if (!perl) { return 0; } @@ -187,20 +241,46 @@ int PerlembParser::EventCommon( return 0; } - bool isPlayerQuest = false; - bool isGlobalPlayerQuest = false; - bool isGlobalNPC = false; - bool isItemQuest = false; - bool isSpellQuest = false; + bool isPlayerQuest = false; + bool isGlobalPlayerQuest = false; + bool isGlobalNPC = false; + bool isBotQuest = false; + bool isGlobalBotQuest = false; + bool isItemQuest = false; + bool isSpellQuest = false; + std::string package_name; GetQuestTypes( - isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, - event, npcmob, item_inst, mob, global + isPlayerQuest, + isGlobalPlayerQuest, + isBotQuest, + isGlobalBotQuest, + isGlobalNPC, + isItemQuest, + isSpellQuest, + event, + npcmob, + item_inst, + mob, + global ); + GetQuestPackageName( - isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, - package_name, event, objid, data, npcmob, item_inst, global + isPlayerQuest, + isGlobalPlayerQuest, + isBotQuest, + isGlobalBotQuest, + isGlobalNPC, + isItemQuest, + isSpellQuest, + package_name, + event, + objid, + data, + npcmob, + item_inst, + global ); const char *sub_name = QuestEventSubroutines[event]; @@ -216,6 +296,8 @@ int PerlembParser::EventCommon( ExportQGlobals( isPlayerQuest, isGlobalPlayerQuest, + isBotQuest, + isGlobalBotQuest, isGlobalNPC, isItemQuest, isSpellQuest, @@ -231,6 +313,8 @@ int PerlembParser::EventCommon( ExportMobVariables( isPlayerQuest, isGlobalPlayerQuest, + isBotQuest, + isGlobalBotQuest, isGlobalNPC, isItemQuest, isSpellQuest, @@ -257,6 +341,8 @@ int PerlembParser::EventCommon( if (isPlayerQuest || isGlobalPlayerQuest) { return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr, nullptr); + } else if (isBotQuest || isGlobalBotQuest) { + return SendCommands(package_name.c_str(), sub_name, 0, npcmob, mob, nullptr, nullptr); } else if (isItemQuest) { return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, item_inst, nullptr); } else if (isSpellQuest) { @@ -271,24 +357,24 @@ int PerlembParser::EventCommon( } int PerlembParser::EventNPC( - QuestEventID evt, NPC *npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers + QuestEventID evt, NPC *npc, Mob *mob, std::string data, uint32 extra_data, + std::vector *extra_pointers ) { - return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, nullptr, init, extra_data, false, extra_pointers); + return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, nullptr, mob, extra_data, false, extra_pointers); } int PerlembParser::EventGlobalNPC( - QuestEventID evt, NPC *npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers + QuestEventID evt, NPC *npc, Mob *mob, std::string data, uint32 extra_data, + std::vector *extra_pointers ) { - return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, nullptr, init, extra_data, true, extra_pointers); + return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, nullptr, mob, extra_data, true, extra_pointers); } int PerlembParser::EventPlayer( QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers + std::vector *extra_pointers ) { return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, nullptr, client, extra_data, false, extra_pointers); @@ -296,7 +382,7 @@ int PerlembParser::EventPlayer( int PerlembParser::EventGlobalPlayer( QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers + std::vector *extra_pointers ) { return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, nullptr, client, extra_data, true, extra_pointers); @@ -304,7 +390,7 @@ int PerlembParser::EventGlobalPlayer( int PerlembParser::EventItem( QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers + std::vector *extra_pointers ) { // needs pointer validation on 'item' argument @@ -312,11 +398,11 @@ int PerlembParser::EventItem( } int PerlembParser::EventSpell( - QuestEventID evt, NPC *npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers + QuestEventID evt, Mob *mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers ) { - return EventCommon(evt, spell_id, data.c_str(), npc, nullptr, &spells[spell_id], client, extra_data, false, extra_pointers); + return EventCommon(evt, spell_id, data.c_str(), mob, nullptr, &spells[spell_id], client, extra_data, false, extra_pointers); } bool PerlembParser::HasQuestSub(uint32 npcid, QuestEventID evt) @@ -776,6 +862,22 @@ void PerlembParser::ExportVar(const char *pkgprefix, const char *varname, const } } + +void PerlembParser::ExportVar(const char* pkgprefix, const char* varname, const char* classname, void* value) +{ + if (!perl) { + return; + } + + // todo: try/catch shouldn't be necessary here (called perl apis don't throw) + try { + perl->setptr(std::string(pkgprefix).append("::").append(varname).c_str(), classname, value); + } + catch (std::string e) { + AddError(fmt::format("Error exporting Perl variable [{}]", e)); + } +} + int PerlembParser::SendCommands( const char *pkgprefix, const char *event, @@ -804,84 +906,93 @@ int PerlembParser::SendCommands( perl->eval(cmd.c_str()); #ifdef EMBPERL_XS_CLASSES - + dTHX; { std::string cl = (std::string) "$" + (std::string) pkgprefix + (std::string) "::client"; std::string np = (std::string) "$" + (std::string) pkgprefix + (std::string) "::npc"; std::string qi = (std::string) "$" + (std::string) pkgprefix + (std::string) "::questitem"; std::string sp = (std::string) "$" + (std::string) pkgprefix + (std::string) "::spell"; std::string enl = (std::string) "$" + (std::string) pkgprefix + (std::string) "::entity_list"; + std::string bot = (std::string) "$" + (std::string) pkgprefix + (std::string) "::bot"; + if (clear_vars_.find(cl) != clear_vars_.end()) { - std::string eval_str = cl; - eval_str += " = undef;"; - perl->eval(eval_str.c_str()); + auto e = fmt::format("{} = undef;", cl); + perl->eval(e.c_str()); } if (clear_vars_.find(np) != clear_vars_.end()) { - std::string eval_str = np; - eval_str += " = undef;"; - perl->eval(eval_str.c_str()); + auto e = fmt::format("{} = undef;", np); + perl->eval(e.c_str()); } if (clear_vars_.find(qi) != clear_vars_.end()) { - std::string eval_str = qi; - eval_str += " = undef;"; - perl->eval(eval_str.c_str()); + auto e = fmt::format("{} = undef;", qi); + perl->eval(e.c_str()); } if (clear_vars_.find(sp) != clear_vars_.end()) { - std::string eval_str = sp; - eval_str += " = undef;"; - perl->eval(eval_str.c_str()); + auto e = fmt::format("{} = undef;", sp); + perl->eval(e.c_str()); } if (clear_vars_.find(enl) != clear_vars_.end()) { - std::string eval_str = enl; - eval_str += " = undef;"; - perl->eval(eval_str.c_str()); + auto e = fmt::format("{} = undef;", enl); + perl->eval(e.c_str()); + } + + if (clear_vars_.find(bot) != clear_vars_.end()) { + auto e = fmt::format("{} = undef;", bot); + perl->eval(e.c_str()); } } - char namebuf[64]; + std::string buf; //init a couple special vars: client, npc, entity_list Client *curc = quest_manager.GetInitiator(); - snprintf(namebuf, 64, "%s::client", pkgprefix); - SV *client = get_sv(namebuf, true); - if (curc != nullptr) { + buf = fmt::format("{}::client", pkgprefix); + SV *client = get_sv(buf.c_str(), true); + if (curc) { sv_setref_pv(client, "Client", curc); - } - else { + } else { //clear out the value, mainly to get rid of blessedness sv_setsv(client, _empty_sv); } //only export NPC if it's a npc quest - if (!other->IsClient()) { + if (!other->IsClient() && other->IsNPC()) { NPC *curn = quest_manager.GetNPC(); - snprintf(namebuf, 64, "%s::npc", pkgprefix); - SV *npc = get_sv(namebuf, true); + buf = fmt::format("{}::npc", pkgprefix); + SV *npc = get_sv(buf.c_str(), true); sv_setref_pv(npc, "NPC", curn); } + if (!other->IsClient() && other->IsBot()) { + Bot *curb = quest_manager.GetBot(); + buf = fmt::format("{}::bot", pkgprefix); + SV *bot = get_sv(buf.c_str(), true); + sv_setref_pv(bot, "Bot", curb); + } + //only export QuestItem if it's an item quest if (item_inst) { EQ::ItemInstance *curi = quest_manager.GetQuestItem(); - snprintf(namebuf, 64, "%s::questitem", pkgprefix); - SV *questitem = get_sv(namebuf, true); + buf = fmt::format("{}::questitem", pkgprefix); + SV *questitem = get_sv(buf.c_str(), true); sv_setref_pv(questitem, "QuestItem", curi); } if (spell) { const SPDat_Spell_Struct* current_spell = quest_manager.GetQuestSpell(); SPDat_Spell_Struct* real_spell = const_cast(current_spell); - snprintf(namebuf, 64, "%s::spell", pkgprefix); - SV *spell = get_sv(namebuf, true); + buf = fmt::format("{}::spell", pkgprefix); + SV *spell = get_sv(buf.c_str(), true); sv_setref_pv(spell, "Spell", (void *) real_spell); } - snprintf(namebuf, 64, "%s::entity_list", pkgprefix); - SV *el = get_sv(namebuf, true); + + buf = fmt::format("{}::entity_list", pkgprefix); + SV *el = get_sv(buf.c_str(), true); sv_setref_pv(el, "EntityList", &entity_list); #endif @@ -895,11 +1006,14 @@ int PerlembParser::SendCommands( std::string qi = (std::string) "$" + (std::string) pkgprefix + (std::string) "::questitem"; std::string sp = (std::string) "$" + (std::string) pkgprefix + (std::string) "::spell"; std::string enl = (std::string) "$" + (std::string) pkgprefix + (std::string) "::entity_list"; + std::string bot = (std::string) "$" + (std::string) pkgprefix + (std::string) "::bot"; + clear_vars_[cl] = 1; clear_vars_[np] = 1; clear_vars_[qi] = 1; clear_vars_[sp] = 1; clear_vars_[enl] = 1; + clear_vars_[bot] = 1; } #endif @@ -909,7 +1023,7 @@ int PerlembParser::SendCommands( "Script Error | Package [{}] Event [{}] Error [{}]", pkgprefix, event, - trim(e) + Strings::Trim(e) ) ); } @@ -918,19 +1032,16 @@ int PerlembParser::SendCommands( #ifdef EMBPERL_XS_CLASSES if (!quest_manager.QuestsRunning()) { - auto iter = clear_vars_.begin(); std::string eval_str; - while (iter != clear_vars_.end()) { - eval_str += iter->first; - eval_str += " = undef;"; - ++iter; + for (const auto &v : clear_vars_) { + eval_str += fmt::format("{} = undef;", v.first); } + clear_vars_.clear(); try { perl->eval(eval_str.c_str()); - } - catch (std::string e) { + } catch (std::string e) { AddError( fmt::format( "Script Clear Error | Error [{}]", @@ -946,102 +1057,83 @@ int PerlembParser::SendCommands( void PerlembParser::MapFunctions() { + dTHX; _empty_sv = newSV(0); - perl->eval( - "{" - "package quest;" - "&boot_quest;" //load our quest XS - #ifdef EMBPERL_XS_CLASSES - "package Mob;" - "&boot_Mob;" //load our Mob XS - - "package Client;" - "our @ISA = qw(Mob);" //client inherits mob. - "&boot_Mob;" //load our Mob XS - "&boot_Client;" //load our Client XS - - "package NPC;" - "our @ISA = qw(Mob);" //NPC inherits mob. - "&boot_Mob;" //load our Mob XS - "&boot_NPC;" //load our NPC XS - - "package Corpse;" - "our @ISA = qw(Mob);" //Corpse inherits mob. - "&boot_Mob;" //load our Mob XS - "&boot_Corpse;" //load our Mob XS - - "package EntityList;" - "&boot_EntityList;" //load our EntityList XS - - "package PerlPacket;" - "&boot_PerlPacket;" //load our PerlPacket XS - - "package Group;" - "&boot_Group;" //load our Group XS - - "package Raid;" - "&boot_Raid;" //load our Raid XS - - "package Inventory;" - "&boot_Inventory;" // load inventory XS - - "package QuestItem;" - "&boot_QuestItem;" // load quest Item XS - - "package Spell;" - "&boot_Spell;" // load quest Spell XS - - "package HateEntry;" - "&boot_HateEntry;" // load quest Hate XS - - "package Object;" - "&boot_Object;" // load quest Object XS - - "package Doors;" - "&boot_Doors;" // load quest Doors XS - - "package Expedition;" - "&boot_Expedition;" - -#ifdef BOTS - "package Bot;" - "our @ISA = qw(NPC);" // Bot inherits NPC - "&boot_Mob;" // load our Mob XS - "&boot_NPC;" // load our NPC XS - "&boot_Bot;" // load our Bot XS -#endif - - #endif - "package main;" - "}" - ); + perl_register_quest(); +#ifdef EMBPERL_XS_CLASSES + perl_register_mob(); + perl_register_npc(); + perl_register_client(); + perl_register_corpse(); + perl_register_entitylist(); + perl_register_perlpacket(); + perl_register_group(); + perl_register_raid(); + perl_register_inventory(); + perl_register_questitem(); + perl_register_spell(); + perl_register_hateentry(); + perl_register_object(); + perl_register_doors(); + perl_register_expedition(); + perl_register_expedition_lock_messages(); + perl_register_bot(); +#endif // EMBPERL_XS_CLASSES } void PerlembParser::GetQuestTypes( - bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, - bool &isSpellQuest, QuestEventID event, NPC *npcmob, EQ::ItemInstance *item_inst, Mob *mob, bool global -) -{ - if (event == EVENT_SPELL_EFFECT_CLIENT || + bool &isPlayerQuest, + bool &isGlobalPlayerQuest, + bool &isBotQuest, + bool &isGlobalBotQuest, + bool &isGlobalNPC, + bool &isItemQuest, + bool &isSpellQuest, + QuestEventID event, + Mob *npcmob, + EQ::ItemInstance *item_inst, + Mob *mob, + bool global +) { + if ( + event == EVENT_SPELL_EFFECT_CLIENT || event == EVENT_SPELL_EFFECT_NPC || + event == EVENT_SPELL_EFFECT_BOT || event == EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT || event == EVENT_SPELL_EFFECT_BUFF_TIC_NPC || + event == EVENT_SPELL_EFFECT_BUFF_TIC_BOT || event == EVENT_SPELL_FADE || - event == EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE) { + event == EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE + ) { isSpellQuest = true; - } - else { - if (!npcmob && mob) { + } else { + if (npcmob) { if (!item_inst) { if (global) { - isGlobalPlayerQuest = true; - } - else { - isPlayerQuest = true; + if (npcmob->IsBot()) { + isGlobalBotQuest = true; + } + } else { + if (npcmob->IsBot()) { + isBotQuest = true; + } } + } else { + isItemQuest = true; } - else { + } else if (!npcmob && mob) { + if (!item_inst) { + if (global) { + if (mob->IsClient()) { + isGlobalPlayerQuest = true; + } + } else { + if (mob->IsClient()) { + isPlayerQuest = true; + } + } + } else { isItemQuest = true; } } @@ -1051,6 +1143,8 @@ void PerlembParser::GetQuestTypes( void PerlembParser::GetQuestPackageName( bool &isPlayerQuest, bool &isGlobalPlayerQuest, + bool &isBotQuest, + bool &isGlobalBotQuest, bool &isGlobalNPC, bool &isItemQuest, bool &isSpellQuest, @@ -1058,7 +1152,7 @@ void PerlembParser::GetQuestPackageName( QuestEventID event, uint32 objid, const char *data, - NPC *npcmob, + Mob *npcmob, EQ::ItemInstance *item_inst, bool global ) @@ -1066,6 +1160,8 @@ void PerlembParser::GetQuestPackageName( if ( !isPlayerQuest && !isGlobalPlayerQuest && + !isBotQuest && + !isGlobalBotQuest && !isItemQuest && !isSpellQuest ) { @@ -1073,30 +1169,30 @@ void PerlembParser::GetQuestPackageName( isGlobalNPC = true; package_name = "qst_global_npc"; } else { - package_name = "qst_npc_"; - package_name += std::to_string(npcmob->GetNPCTypeID()); + package_name = fmt::format("qst_npc_{}", npcmob->GetNPCTypeID()); } } else if (isItemQuest) { // need a valid EQ::ItemInstance pointer check here..unsure how to cancel this process const EQ::ItemData *item = item_inst->GetItem(); - package_name = "qst_item_"; - package_name += std::to_string(item->ID); + package_name = fmt::format("qst_item_{}", item->ID); } else if (isPlayerQuest) { package_name = "qst_player"; } else if (isGlobalPlayerQuest) { package_name = "qst_global_player"; + } else if (isBotQuest) { + package_name = "qst_bot"; + } else if (isGlobalBotQuest) { + package_name = "qst_global_bot"; } else { - package_name = "qst_spell_"; - package_name += std::to_string(objid); + package_name = fmt::format("qst_spell_{}", objid); } } -void PerlembParser::ExportCharID(const std::string &package_name, int &char_id, NPC *npcmob, Mob *mob) +void PerlembParser::ExportCharID(const std::string &package_name, int &char_id, Mob *npcmob, Mob *mob) { if (mob && mob->IsClient()) { // some events like waypoint and spawn don't have a player involved char_id = mob->CastToClient()->CharacterID(); - } - else { + } else { if (npcmob) { char_id = -static_cast(npcmob->GetNPCTypeID()); // make char id negative npc id as a fudge } @@ -1108,29 +1204,54 @@ void PerlembParser::ExportCharID(const std::string &package_name, int &char_id, } void PerlembParser::ExportQGlobals( - bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, - bool isSpellQuest, std::string &package_name, NPC *npcmob, Mob *mob, int char_id -) -{ + bool isPlayerQuest, + bool isGlobalPlayerQuest, + bool isBotQuest, + bool isGlobalBotQuest, + bool isGlobalNPC, + bool isItemQuest, + bool isSpellQuest, + std::string &package_name, + Mob *npcmob, + Mob *mob, + int char_id +) { //NPC quest - if (!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest && !isSpellQuest) { + if ( + !isPlayerQuest && + !isGlobalPlayerQuest && + !isBotQuest && + !isGlobalBotQuest && + !isItemQuest && + !isSpellQuest + ) { //only export for npcs that are global enabled. if (npcmob && npcmob->GetQglobal()) { std::map globhash; - QGlobalCache *npc_c = nullptr; - QGlobalCache *char_c = nullptr; - QGlobalCache *zone_c = nullptr; + QGlobalCache *npc_c = nullptr; + QGlobalCache *char_c = nullptr; + QGlobalCache *zone_c = nullptr; //retrieve our globals - npc_c = npcmob->GetQGlobals(); + if (npcmob) { + if (npcmob->IsNPC()) { + npc_c = npcmob->CastToNPC()->GetQGlobals(); + } else if (npcmob->IsClient()) { + char_c = npcmob->CastToClient()->GetQGlobals(); + } + } + if (mob && mob->IsClient()) { char_c = mob->CastToClient()->GetQGlobals(); } + zone_c = zone->GetQGlobals(); if (!npc_c) { - npc_c = npcmob->CreateQGlobals(); - npc_c->LoadByNPCID(npcmob->GetNPCTypeID()); + if (npcmob && npcmob->IsNPC()) { + npc_c = npcmob->CastToNPC()->CreateQGlobals(); + npc_c->LoadByNPCID(npcmob->GetNPCTypeID()); + } } if (!char_c) { @@ -1153,7 +1274,8 @@ void PerlembParser::ExportQGlobals( npc_c->GetBucket(), npcmob->GetNPCTypeID(), char_id, - zone->GetZoneID()); + zone->GetZoneID()) + ; } if (char_c) { @@ -1162,7 +1284,8 @@ void PerlembParser::ExportQGlobals( char_c->GetBucket(), npcmob->GetNPCTypeID(), char_id, - zone->GetZoneID()); + zone->GetZoneID() + ); } if (zone_c) { @@ -1171,7 +1294,8 @@ void PerlembParser::ExportQGlobals( zone_c->GetBucket(), npcmob->GetNPCTypeID(), char_id, - zone->GetZoneID()); + zone->GetZoneID() + ); } auto iter = globalMap.begin(); @@ -1180,19 +1304,20 @@ void PerlembParser::ExportQGlobals( ExportVar(package_name.c_str(), (*iter).name.c_str(), (*iter).value.c_str()); ++iter; } + ExportHash(package_name.c_str(), "qglobals", globhash); } - } - else { + } else { std::map globhash; - QGlobalCache *char_c = nullptr; - QGlobalCache *zone_c = nullptr; + QGlobalCache *char_c = nullptr; + QGlobalCache *zone_c = nullptr; //retrieve our globals if (mob && mob->IsClient()) { char_c = mob->CastToClient()->GetQGlobals(); } - zone_c = zone->GetQGlobals(); + + zone_c = zone->GetQGlobals(); if (!char_c) { if (mob && mob->IsClient()) { @@ -1222,15 +1347,23 @@ void PerlembParser::ExportQGlobals( ExportVar(package_name.c_str(), (*iter).name.c_str(), (*iter).value.c_str()); ++iter; } + ExportHash(package_name.c_str(), "qglobals", globhash); } } void PerlembParser::ExportMobVariables( - bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, - bool isSpellQuest, std::string &package_name, Mob *mob, NPC *npcmob -) -{ + bool isPlayerQuest, + bool isGlobalPlayerQuest, + bool isBotQuest, + bool isGlobalBotQuest, + bool isGlobalNPC, + bool isItemQuest, + bool isSpellQuest, + std::string &package_name, + Mob *mob, + Mob *npcmob +) { uint8 fac = 0; if (mob && mob->IsClient()) { ExportVar(package_name.c_str(), "uguild_id", mob->CastToClient()->GuildID()); @@ -1238,8 +1371,19 @@ void PerlembParser::ExportMobVariables( ExportVar(package_name.c_str(), "status", mob->CastToClient()->Admin()); } - if (!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest) { - if (mob && npcmob && mob->IsClient()) { + if (mob && mob->IsBot()) { + ExportVar(package_name.c_str(), "bot_id", mob->CastToBot()->GetBotID()); + ExportVar(package_name.c_str(), "bot_owner_char_id", mob->CastToBot()->GetBotOwnerCharacterID()); + } + + if ( + !isPlayerQuest && + !isGlobalPlayerQuest && + !isBotQuest && + !isGlobalBotQuest && + !isItemQuest + ) { + if (mob && mob->IsClient() && npcmob && npcmob->IsNPC()) { Client *client = mob->CastToClient(); fac = client->GetFactionLevel( @@ -1257,8 +1401,15 @@ void PerlembParser::ExportMobVariables( ExportVar(package_name.c_str(), "userid", mob->GetID()); } - if (!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest && !isSpellQuest) { - if (npcmob) { + if ( + !isPlayerQuest && + !isGlobalPlayerQuest && + !isBotQuest && + !isGlobalBotQuest && + !isItemQuest && + !isSpellQuest + ) { + if (npcmob->IsNPC()) { ExportVar(package_name.c_str(), "mname", npcmob->GetName()); ExportVar(package_name.c_str(), "mobid", npcmob->GetID()); ExportVar(package_name.c_str(), "mlevel", npcmob->GetLevel()); @@ -1327,14 +1478,20 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) } void PerlembParser::ExportEventVariables( - std::string &package_name, QuestEventID event, uint32 objid, const char *data, - NPC *npcmob, EQ::ItemInstance *item_inst, Mob *mob, uint32 extradata, std::vector *extra_pointers -) -{ + std::string &package_name, + QuestEventID event, + uint32 objid, + const char *data, + Mob *npcmob, + EQ::ItemInstance *item_inst, + Mob *mob, + uint32 extradata, + std::vector *extra_pointers +) { switch (event) { case EVENT_SAY: { - if (npcmob && mob) { - npcmob->DoQuestPause(mob); + if (npcmob && npcmob->IsNPC() && mob) { + npcmob->CastToNPC()->DoQuestPause(mob); } ExportVar(package_name.c_str(), "data", objid); @@ -1345,48 +1502,55 @@ void PerlembParser::ExportEventVariables( case EVENT_TRADE: { if (extra_pointers) { - size_t sz = extra_pointers->size(); + size_t sz = extra_pointers->size(); for (size_t i = 0; i < sz; ++i) { - EQ::ItemInstance *inst = EQ::any_cast(extra_pointers->at(i)); + auto* inst = std::any_cast(extra_pointers->at(i)); + const uint32 item_id = inst ? inst->GetItem()->ID : 0; + const int16 item_charges = inst ? inst->GetCharges() : 0; + const auto is_attuned = inst ? inst->IsAttuned() : false; - std::string var_name = "item"; - var_name += std::to_string(i + 1); + auto var_name = fmt::format("item{}", i + 1); + ExportVar(package_name.c_str(), var_name.c_str(), item_id); + auto temp_var_name = fmt::format("{}_charges", var_name); + ExportVar(package_name.c_str(), temp_var_name.c_str(), item_charges); + + temp_var_name = fmt::format("{}_attuned", var_name); + ExportVar(package_name.c_str(), temp_var_name.c_str(), is_attuned); + + temp_var_name = fmt::format("{}_inst", var_name); if (inst) { - ExportVar(package_name.c_str(), var_name.c_str(), inst->GetItem()->ID); - - std::string temp_var_name = var_name; - temp_var_name += "_charges"; - ExportVar(package_name.c_str(), temp_var_name.c_str(), inst->GetCharges()); - - temp_var_name = var_name; - temp_var_name += "_attuned"; - ExportVar(package_name.c_str(), temp_var_name.c_str(), inst->IsAttuned()); - } - else { - ExportVar(package_name.c_str(), var_name.c_str(), 0); - - std::string temp_var_name = var_name; - temp_var_name += "_charges"; - ExportVar(package_name.c_str(), temp_var_name.c_str(), 0); - - temp_var_name = var_name; - temp_var_name += "_attuned"; + ExportVar(package_name.c_str(), temp_var_name.c_str(), "QuestItem", inst); + } else { ExportVar(package_name.c_str(), temp_var_name.c_str(), 0); } } } - ExportVar(package_name.c_str(), "copper", GetVar("copper." + std::string(itoa(objid))).c_str()); - ExportVar(package_name.c_str(), "silver", GetVar("silver." + std::string(itoa(objid))).c_str()); - ExportVar(package_name.c_str(), "gold", GetVar("gold." + std::string(itoa(objid))).c_str()); - ExportVar(package_name.c_str(), "platinum", GetVar("platinum." + std::string(itoa(objid))).c_str()); - std::string hashname = package_name + std::string("::itemcount"); - perl->eval(std::string("%").append(hashname).append(" = ();").c_str()); - perl->eval(std::string("++$").append(hashname).append("{$").append(package_name).append("::item1};").c_str()); - perl->eval(std::string("++$").append(hashname).append("{$").append(package_name).append("::item2};").c_str()); - perl->eval(std::string("++$").append(hashname).append("{$").append(package_name).append("::item3};").c_str()); - perl->eval(std::string("++$").append(hashname).append("{$").append(package_name).append("::item4};").c_str()); + auto unique_id = npcmob->GetNPCTypeID(); + if (npcmob->IsBot()) { + unique_id = npcmob->CastToBot()->GetBotID(); + } + + ExportVar(package_name.c_str(), "copper", GetVar(fmt::format("copper.{}", unique_id)).c_str()); + ExportVar(package_name.c_str(), "silver", GetVar(fmt::format("silver.{}", unique_id)).c_str()); + ExportVar(package_name.c_str(), "gold", GetVar(fmt::format("gold.{}", unique_id)).c_str()); + ExportVar(package_name.c_str(), "platinum", GetVar(fmt::format("platinum.{}", unique_id)).c_str()); + + auto hash_name = fmt::format("{}::itemcount", package_name); + perl->eval(fmt::format("%{} = ();", hash_name).c_str()); + perl->eval(fmt::format("++${}{{${}::item1}};", hash_name, package_name).c_str()); + perl->eval(fmt::format("++${}{{${}::item2}};", hash_name, package_name).c_str()); + perl->eval(fmt::format("++${}{{${}::item3}};", hash_name, package_name).c_str()); + perl->eval(fmt::format("++${}{{${}::item4}};", hash_name, package_name).c_str()); + + if (npcmob->IsBot()) { + perl->eval(fmt::format("++${}{{${}::item5}};", hash_name, package_name).c_str()); + perl->eval(fmt::format("++${}{{${}::item6}};", hash_name, package_name).c_str()); + perl->eval(fmt::format("++${}{{${}::item7}};", hash_name, package_name).c_str()); + perl->eval(fmt::format("++${}{{${}::item8}};", hash_name, package_name).c_str()); + } + break; } @@ -1397,14 +1561,8 @@ void PerlembParser::ExportEventVariables( } case EVENT_HP: { - if (extradata == 1) { - ExportVar(package_name.c_str(), "hpevent", "-1"); - ExportVar(package_name.c_str(), "inchpevent", data); - } - else { - ExportVar(package_name.c_str(), "hpevent", data); - ExportVar(package_name.c_str(), "inchpevent", "-1"); - } + ExportVar(package_name.c_str(), "hpevent", extradata ? "-1" : data); + ExportVar(package_name.c_str(), "inchpevent", extradata ? data : "-1"); break; } @@ -1418,6 +1576,13 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_PAYLOAD: { + Seperator sep(data); + ExportVar(package_name.c_str(), "payload_id", sep.arg[0]); + ExportVar(package_name.c_str(), "payload_value", sep.arg[1]); + break; + } + case EVENT_NPC_SLAY: { ExportVar(package_name.c_str(), "killed", mob->GetNPCTypeID()); break; @@ -1433,7 +1598,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "version", zone->GetInstanceVersion()); break; } - + case EVENT_LOOT_ZONE: case EVENT_LOOT: { Seperator sep(data); @@ -1447,7 +1612,11 @@ void PerlembParser::ExportEventVariables( case EVENT_ZONE: { Seperator sep(data); ExportVar(package_name.c_str(), "from_zone_id", sep.arg[0]); - ExportVar(package_name.c_str(), "target_zone_id", sep.arg[1]); + ExportVar(package_name.c_str(), "from_instance_id", sep.arg[1]); + ExportVar(package_name.c_str(), "from_instance_version", sep.arg[2]); + ExportVar(package_name.c_str(), "target_zone_id", sep.arg[3]); + ExportVar(package_name.c_str(), "target_instance_id", sep.arg[4]); + ExportVar(package_name.c_str(), "target_instance_version", sep.arg[5]); break; } @@ -1480,6 +1649,7 @@ void PerlembParser::ExportEventVariables( } case EVENT_TASK_COMPLETE: + case EVENT_TASK_BEFORE_UPDATE: case EVENT_TASK_UPDATE: { Seperator sep(data); ExportVar(package_name.c_str(), "donecount", sep.arg[0]); @@ -1505,6 +1675,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "popupid", data); break; } + case EVENT_ENVIRONMENTAL_DAMAGE: { Seperator sep(data); ExportVar(package_name.c_str(), "env_damage", sep.arg[0]); @@ -1551,8 +1722,11 @@ void PerlembParser::ExportEventVariables( break; } + + case EVENT_SPELL_EFFECT_BUFF_TIC_BOT: case EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT: case EVENT_SPELL_EFFECT_BUFF_TIC_NPC: + case EVENT_SPELL_EFFECT_BOT: case EVENT_SPELL_EFFECT_CLIENT: case EVENT_SPELL_EFFECT_NPC: case EVENT_SPELL_FADE: { @@ -1610,6 +1784,7 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_DEATH_ZONE: case EVENT_DEATH: case EVENT_DEATH_COMPLETE: { Seperator sep(data); @@ -1617,8 +1792,31 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]); ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]); ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); + if (extra_pointers && extra_pointers->size() >= 1) + { + Corpse* corpse = std::any_cast(extra_pointers->at(0)); + if (corpse) + { + ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID()); + } + } + if (extra_pointers && extra_pointers->size() >= 2) + { + NPC* killed = std::any_cast(extra_pointers->at(1)); + if (killed) + { + ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID()); + ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0); + ExportVar(package_name.c_str(), "killed_x", killed->GetX()); + ExportVar(package_name.c_str(), "killed_y", killed->GetY()); + ExportVar(package_name.c_str(), "killed_z", killed->GetZ()); + ExportVar(package_name.c_str(), "killed_h", killed->GetHeading()); + } + } break; } + case EVENT_DROP_ITEM: { ExportVar(package_name.c_str(), "quantity", item_inst->IsStackable() ? item_inst->GetCharges() : 1); ExportVar(package_name.c_str(), "itemname", item_inst->GetItem()->Name); @@ -1627,31 +1825,21 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "slotid", extradata); break; } + case EVENT_SPAWN_ZONE: { - Seperator sep(data); - ExportVar(package_name.c_str(), "spawned_entity_id", sep.arg[0]); - ExportVar(package_name.c_str(), "spawned_npc_id", sep.arg[1]); - break; - } - case EVENT_DEATH_ZONE: { - Seperator sep(data); - ExportVar(package_name.c_str(), "killer_id", sep.arg[0]); - ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]); - ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]); - ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); - ExportVar(package_name.c_str(), "killed_npc_id", sep.arg[4]); - ExportVar(package_name.c_str(), "killed_x", sep.arg[5]); - ExportVar(package_name.c_str(), "killed_y", sep.arg[6]); - ExportVar(package_name.c_str(), "killed_z", sep.arg[7]); - ExportVar(package_name.c_str(), "killed_h", sep.arg[8]); + ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID()); + ExportVar(package_name.c_str(), "spawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "spawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); break; } + case EVENT_USE_SKILL: { Seperator sep(data); ExportVar(package_name.c_str(), "skill_id", sep.arg[0]); ExportVar(package_name.c_str(), "skill_level", sep.arg[1]); break; } + case EVENT_COMBINE_VALIDATE: { Seperator sep(data); ExportVar(package_name.c_str(), "recipe_id", extradata); @@ -1670,6 +1858,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "tradeskill_id", tradeskill_id.c_str()); break; } + case EVENT_BOT_COMMAND: { Seperator sep(data); ExportVar(package_name.c_str(), "bot_command", (sep.arg[0] + 1)); @@ -1679,6 +1868,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "langid", extradata); break; } + case EVENT_WARP: { Seperator sep(data); ExportVar(package_name.c_str(), "from_x", sep.arg[0]); @@ -1686,12 +1876,12 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "from_z", sep.arg[2]); break; } - + case EVENT_CONSIDER: { ExportVar(package_name.c_str(), "entity_id", std::stoi(data)); break; } - + case EVENT_CONSIDER_CORPSE: { ExportVar(package_name.c_str(), "corpse_entity_id", std::stoi(data)); break; @@ -1711,6 +1901,19 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_AUGMENT_INSERT_CLIENT: + case EVENT_AUGMENT_REMOVE_CLIENT: { + Seperator sep(data); + ExportVar(package_name.c_str(), "item_id", sep.arg[0]); + ExportVar(package_name.c_str(), "item_slot", sep.arg[1]); + ExportVar(package_name.c_str(), "augment_id", sep.arg[2]); + ExportVar(package_name.c_str(), "augment_slot", sep.arg[3]); + if (sep.argnum >= 4) { + ExportVar(package_name.c_str(), "destroyed", sep.arg[4]); + } + break; + } + case EVENT_SKILL_UP: { Seperator sep(data); ExportVar(package_name.c_str(), "skill_id", sep.arg[0]); @@ -1728,10 +1931,215 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_ALT_CURRENCY_MERCHANT_BUY: + case EVENT_ALT_CURRENCY_MERCHANT_SELL: { + Seperator sep(data); + ExportVar(package_name.c_str(), "currency_id", sep.arg[0]); + ExportVar(package_name.c_str(), "npc_id", sep.arg[1]); + ExportVar(package_name.c_str(), "merchant_id", sep.arg[2]); + ExportVar(package_name.c_str(), "item_id", sep.arg[3]); + ExportVar(package_name.c_str(), "item_cost", sep.arg[4]); + break; + } + + case EVENT_MERCHANT_BUY: + case EVENT_MERCHANT_SELL: { + Seperator sep(data); + ExportVar(package_name.c_str(), "npc_id", sep.arg[0]); + ExportVar(package_name.c_str(), "merchant_id", sep.arg[1]); + ExportVar(package_name.c_str(), "item_id", sep.arg[2]); + ExportVar(package_name.c_str(), "item_quantity", sep.arg[3]); + ExportVar(package_name.c_str(), "item_cost", sep.arg[4]); + break; + } + + case EVENT_AA_BUY: { + Seperator sep(data); + ExportVar(package_name.c_str(), "aa_cost", sep.arg[0]); + ExportVar(package_name.c_str(), "aa_id", sep.arg[1]); + ExportVar(package_name.c_str(), "aa_previous_id", sep.arg[2]); + ExportVar(package_name.c_str(), "aa_next_id", sep.arg[3]); + break; + } + + case EVENT_AA_GAIN: { + ExportVar(package_name.c_str(), "aa_gained", data); + break; + } + + case EVENT_INSPECT: { + ExportVar(package_name.c_str(), "target_id", extradata); + break; + } + + case EVENT_LEVEL_UP: { + ExportVar(package_name.c_str(), "levels_gained", data); + break; + } + + case EVENT_LEVEL_DOWN: { + ExportVar(package_name.c_str(), "levels_lost", data); + break; + } + + case EVENT_GM_COMMAND: { + ExportVar(package_name.c_str(), "message", data); + break; + } + + case EVENT_ENTER_AREA: + case EVENT_LEAVE_AREA: { + if (extra_pointers && extra_pointers->size() >= 2) { + ExportVar(package_name.c_str(), "area_id", *std::any_cast(extra_pointers->at(0))); + ExportVar(package_name.c_str(), "area_type", *std::any_cast(extra_pointers->at(1))); + } + break; + } + + case EVENT_DESPAWN: { + ExportVar(package_name.c_str(), "despawned_entity_id", npcmob->GetID()); + ExportVar(package_name.c_str(), "despawned_bot_id", npcmob->IsBot() ? npcmob->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "despawned_npc_id", npcmob->IsNPC() ? npcmob->GetNPCTypeID() : 0); + break; + } + + case EVENT_DESPAWN_ZONE: { + ExportVar(package_name.c_str(), "despawned_entity_id", mob->GetID()); + ExportVar(package_name.c_str(), "despawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "despawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); + break; + } + + case EVENT_BOT_CREATE: { + Seperator sep(data); + ExportVar(package_name.c_str(), "bot_name", sep.arg[0]); + ExportVar(package_name.c_str(), "bot_id", sep.arg[1]); + ExportVar(package_name.c_str(), "bot_race", sep.arg[2]); + ExportVar(package_name.c_str(), "bot_class", sep.arg[3]); + ExportVar(package_name.c_str(), "bot_gender", sep.arg[4]); + break; + } + default: { break; } } } +void PerlembParser::LoadBotScript(std::string filename) +{ + if (!perl) { + return; + } + + if (bot_quest_status_ != questUnloaded) { + return; + } + + try { + perl->eval_file("qst_bot", filename.c_str()); + } catch (std::string e) { + AddError( + fmt::format( + "Error Compiling Bot Quest File [{}] Error [{}]", + filename, + e + ) + ); + + bot_quest_status_ = questFailedToLoad; + return; + } + + bot_quest_status_ = questLoaded; +} + +void PerlembParser::LoadGlobalBotScript(std::string filename) +{ + if (!perl) { + return; + } + + if (global_bot_quest_status_ != questUnloaded) { + return; + } + + try { + perl->eval_file("qst_global_bot", filename.c_str()); + } catch (std::string e) { + AddError( + fmt::format( + "Error Compiling Global Bot Quest File [{}] Error [{}]", + filename, + e + ) + ); + + global_bot_quest_status_ = questFailedToLoad; + return; + } + + global_bot_quest_status_ = questLoaded; +} + +bool PerlembParser::BotHasQuestSub(QuestEventID evt) +{ + if (!perl) { + return false; + } + + if (bot_quest_status_ != questLoaded) { + return false; + } + + if (evt >= _LargestEventID) { + return false; + } + + const char *subname = QuestEventSubroutines[evt]; + + return (perl->SubExists("qst_bot", subname)); +} + +bool PerlembParser::GlobalBotHasQuestSub(QuestEventID evt) +{ + if (!perl) { + return false; + } + + if (global_bot_quest_status_ != questLoaded) { + return false; + } + + if (evt >= _LargestEventID) { + return false; + } + + const char *subname = QuestEventSubroutines[evt]; + + return (perl->SubExists("qst_global_bot", subname)); +} + +int PerlembParser::EventBot( + QuestEventID evt, + Bot *bot, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + return EventCommon(evt, 0, data.c_str(), bot, nullptr, nullptr, mob, extra_data, false, extra_pointers); +} + +int PerlembParser::EventGlobalBot( + QuestEventID evt, + Bot *bot, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + return EventCommon(evt, 0, data.c_str(), bot, nullptr, nullptr, mob, extra_data, true, extra_pointers); +} + #endif diff --git a/zone/embparser.h b/zone/embparser.h index 52bba1589..c22417a1b 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -36,7 +36,7 @@ namespace EQ class ItemInstance; } -typedef enum +typedef enum { questUnloaded, questLoaded, @@ -47,19 +47,71 @@ class PerlembParser : public QuestInterface { public: PerlembParser(); ~PerlembParser(); - - virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers); + + virtual int EventNPC( + QuestEventID evt, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventGlobalNPC( + QuestEventID evt, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventPlayer( + QuestEventID evt, + Client *client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventGlobalPlayer( + QuestEventID evt, + Client *client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventItem( + QuestEventID evt, + Client *client, + EQ::ItemInstance *item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventSpell( + QuestEventID evt, + Mob* mob, + Client *client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventGlobalBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); virtual bool HasQuestSub(uint32 npcid, QuestEventID evt); virtual bool HasGlobalQuestSub(QuestEventID evt); @@ -67,6 +119,8 @@ public: virtual bool GlobalPlayerHasQuestSub(QuestEventID evt); virtual bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt); virtual bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt); + virtual bool BotHasQuestSub(QuestEventID evt); + virtual bool GlobalBotHasQuestSub(QuestEventID evt); virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadGlobalNPCScript(std::string filename); @@ -74,6 +128,8 @@ public: virtual void LoadGlobalPlayerScript(std::string filename); virtual void LoadItemScript(std::string filename, EQ::ItemInstance *item); virtual void LoadSpellScript(std::string filename, uint32 spell_id); + virtual void LoadBotScript(std::string filename); + virtual void LoadGlobalBotScript(std::string filename); virtual void AddVar(std::string name, std::string val); virtual std::string GetVar(std::string name); @@ -82,40 +138,116 @@ public: private: Embperl *perl; - + void ExportHash(const char *pkgprefix, const char *hashname, std::map &vals); void ExportVar(const char *pkgprefix, const char *varname, const char *value); void ExportVar(const char *pkgprefix, const char *varname, int32 value); void ExportVar(const char *pkgprefix, const char *varname, uint32 value); void ExportVar(const char *pkgprefix, const char *varname, float value); + void ExportVar(const char* pkgprefix, const char* varname, const char* classname, void* value); void ExportVarComplex(const char *pkgprefix, const char *varname, const char *value); - int EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, EQ::ItemInstance* item_inst, const SPDat_Spell_Struct* spell, Mob* mob, - uint32 extradata, bool global, std::vector *extra_pointers); - int SendCommands(const char *pkgprefix, const char *event, uint32 spell_id, Mob* other, Mob* mob, EQ::ItemInstance *item_inst, const SPDat_Spell_Struct *spell); + int EventCommon( + QuestEventID event, + uint32 objid, + const char* data, + Mob* npcmob, + EQ::ItemInstance* item_inst, + const SPDat_Spell_Struct* spell, + Mob* mob, + uint32 extradata, + bool global, + std::vector *extra_pointers + ); + int SendCommands( + const char *pkgprefix, + const char *event, + uint32 spell_id, + Mob* other, + Mob* mob, + EQ::ItemInstance *item_inst, + const SPDat_Spell_Struct *spell + ); void MapFunctions(); - void GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, - bool &isSpellQuest, QuestEventID event, NPC* npcmob, EQ::ItemInstance* item_inst, Mob* mob, bool global); - void GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, - bool &isSpellQuest, std::string &package_name, QuestEventID event, uint32 objid, const char * data, - NPC* npcmob, EQ::ItemInstance* item_inst, bool global); - void ExportCharID(const std::string &package_name, int &char_id, NPC *npcmob, Mob *mob); - void ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, - bool isSpellQuest, std::string &package_name, NPC *npcmob, Mob *mob, int char_id); - void ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, - bool isSpellQuest, std::string &package_name, Mob *mob, NPC *npcmob); + void GetQuestTypes( + bool &isPlayerQuest, + bool &isGlobalPlayerQuest, + bool &isBotQuest, + bool &isGlobalBotQuest, + bool &isGlobalNPC, + bool &isItemQuest, + bool &isSpellQuest, + QuestEventID event, + Mob* npcmob, + EQ::ItemInstance* item_inst, + Mob* mob, + bool global + ); + void GetQuestPackageName( + bool &isPlayerQuest, + bool &isGlobalPlayerQuest, + bool &isBotQuest, + bool &isGlobalBotQuest, + bool &isGlobalNPC, + bool &isItemQuest, + bool &isSpellQuest, + std::string &package_name, + QuestEventID event, + uint32 objid, + const char * data, + Mob* npcmob, + EQ::ItemInstance* item_inst, + bool global + ); + void ExportCharID(const std::string &package_name, int &char_id, Mob *npcmob, Mob *mob); + void ExportQGlobals( + bool isPlayerQuest, + bool isGlobalPlayerQuest, + bool isBotQuest, + bool isGlobalBotQuest, + bool isGlobalNPC, + bool isItemQuest, + bool isSpellQuest, + std::string &package_name, + Mob *npcmob, + Mob *mob, + int char_id + ); + void ExportMobVariables( + bool isPlayerQuest, + bool isGlobalPlayerQuest, + bool isBotQuest, + bool isGlobalBotQuest, + bool isGlobalNPC, + bool isItemQuest, + bool isSpellQuest, + std::string &package_name, + Mob *mob, + Mob *npcmob + ); void ExportZoneVariables(std::string &package_name); void ExportItemVariables(std::string &package_name, Mob *mob); - void ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data, - NPC* npcmob, EQ::ItemInstance* item_inst, Mob* mob, uint32 extradata, std::vector *extra_pointers); - + void ExportEventVariables( + std::string &package_name, + QuestEventID event, + uint32 objid, + const char* data, + Mob* npcmob, + EQ::ItemInstance* item_inst, + Mob* mob, + uint32 extradata, + std::vector *extra_pointers + ); + std::map npc_quest_status_; PerlQuestStatus global_npc_quest_status_; PerlQuestStatus player_quest_status_; PerlQuestStatus global_player_quest_status_; std::map item_quest_status_; std::map spell_quest_status_; + PerlQuestStatus bot_quest_status_; + PerlQuestStatus global_bot_quest_status_; std::map vars_; SV *_empty_sv; diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 3f3af3261..77036ecbe 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -26,7 +26,8 @@ #include "../common/misc_functions.h" #include "../common/eqemu_logsys.h" -#include "embparser.h" +#include "dialogue_window.h" +#include "embperl.h" #include "embxs.h" #include "entity.h" #include "expedition.h" @@ -40,3233 +41,1485 @@ extern Zone *zone; extern QueryServ *QServ; -/* - -Some useful perl API info: - -SvUV == string to unsigned value (char->ulong) -SvIV == string to signed value (char->long) -SvNV == string to real value (float,double) -SvPV_nolen == string with no length restriction - -*/ - #ifdef EMBPERL_XS_CLASSES //Any creation of new Client objects gets the current quest Client -XS(XS_Client_new); -XS(XS_Client_new) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::Client::new()"); - { - Client *RETVAL; - - RETVAL = quest_manager.GetInitiator(); - ST(0) = sv_newmortal(); - if (RETVAL) - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +Client* Perl__Client_new() +{ + return quest_manager.GetInitiator(); } //Any creation of new NPC objects gets the current quest NPC -XS(XS_NPC_new); -XS(XS_NPC_new) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::NPC::new()"); - { - NPC *RETVAL; - - RETVAL = quest_manager.GetNPC(); - ST(0) = sv_newmortal(); - if (RETVAL) - sv_setref_pv(ST(0), "NPC", (void *) RETVAL); - } - XSRETURN(1); +NPC* Perl__NPC_new() +{ + return quest_manager.GetNPC(); } //Any creation of new NPC objects gets the current quest NPC -XS(XS_EntityList_new); -XS(XS_EntityList_new) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::EntityList::new()"); - { - EntityList *RETVAL; - - RETVAL = &entity_list; - ST(0) = sv_newmortal(); - if (RETVAL) - sv_setref_pv(ST(0), "EntityList", (void *) RETVAL); - } - XSRETURN(1); +EntityList* Perl__EntityList_new() +{ + return &entity_list; } //Any creation of new inventory gets the curreny inventory -XS(XS_Inventory_new); -XS(XS_Inventory_new) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::Inventory::new()"); - - EQ::InventoryProfile* RETVAL; - - RETVAL = quest_manager.GetInventory(); - ST(0) = sv_newmortal(); - if (RETVAL) - sv_setref_pv(ST(0), "Inventory", (void *) RETVAL); - - XSRETURN(1); +EQ::InventoryProfile* Perl__Inventory_new() +{ + return quest_manager.GetInventory(); } //Any creation of new quest items gets the current quest item -XS(XS_QuestItem_new); -XS(XS_QuestItem_new) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::QuestItem::new()"); - - EQ::ItemInstance *RETVAL; - - RETVAL = quest_manager.GetQuestItem(); - ST(0) = sv_newmortal(); - if (RETVAL) - sv_setref_pv(ST(0), "QuestItem", (void *) RETVAL); - - XSRETURN(1); +EQ::ItemInstance* Perl__QuestItem_new() +{ + return quest_manager.GetQuestItem(); } //Any creation of new Spells gets the current Spell -XS(XS_Spell_new); -XS(XS_Spell_new) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::Spell::new()"); - - const SPDat_Spell_Struct* spell = quest_manager.GetQuestSpell(); - ST(0) = sv_newmortal(); - if (spell) - sv_setref_pv(ST(0), "Spell", (void *) spell); - - XSRETURN(1); -} - -//Any creation of new quest items gets the current quest item -XS(XS_MobList_new); -XS(XS_MobList_new) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::MobList::new()"); - - ListElement *RETVAL; - - RETVAL = nullptr; - ST(0) = sv_newmortal(); - if (RETVAL) - sv_setref_pv(ST(0), "MobList", (void *) RETVAL); - - XSRETURN(1); +SPDat_Spell_Struct* Perl__Spell_new() +{ + // should be safe, it's read only in perl (could also use proxy lika lua) + return const_cast(quest_manager.GetQuestSpell()); } #endif //EMBPERL_XS_CLASSES -XS(XS__echo); // prototype to pass -Wmissing-prototypes -XS(XS__echo) { - dXSARGS; - - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::echo(int emote_color_id, string message)"); - - quest_manager.echo(SvUV(ST(0)), SvPV_nolen(ST(1))); - - XSRETURN_EMPTY; +void Perl__echo(int emote_color_id, const char* message) +{ + quest_manager.echo(emote_color_id, message); } -XS(XS__say); // prototype to pass -Wmissing-prototypes -XS(XS__say) { - dXSARGS; - +void Perl__say(const char* message) +{ Journal::Options opts; // we currently default to these - opts.speak_mode = Journal::SpeakMode::Say; + opts.speak_mode = Journal::SpeakMode::Say; opts.journal_mode = Journal::Mode::Log2; - opts.language = 0; + opts.language = 0; opts.message_type = Chat::NPCQuestSay; - if (items == 0 || items > 5) { - Perl_croak(aTHX_ "Usage: quest::say(string message, [int language_id], [int message_type], [int speak_mode], [int journal_mode])"); - } else if (items == 2) { - opts.language = (int)SvIV(ST(1)); - } else if (items == 3) { - opts.language = (int)SvIV(ST(1)); - opts.message_type = (int)SvIV(ST(2)); - } else if (items == 4) { - opts.language = (int)SvIV(ST(1)); - opts.message_type = (int)SvIV(ST(2)); - opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3)); - } else if (items == 5) { - opts.language = (int)SvIV(ST(1)); - opts.message_type = (int)SvIV(ST(2)); - opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3)); - opts.journal_mode = (Journal::Mode)SvIV(ST(4)); - } - quest_manager.say(SvPV_nolen(ST(0)), opts); - - XSRETURN_EMPTY; + quest_manager.say(message, opts); } -XS(XS__me); // prototype to pass -Wmissing-prototypes -XS(XS__me) { - dXSARGS; +void Perl__say(const char* message, int language_id) +{ + Journal::Options opts; + opts.speak_mode = Journal::SpeakMode::Say; + opts.journal_mode = Journal::Mode::Log2; + opts.language = language_id; + opts.message_type = Chat::NPCQuestSay; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::me(string message)"); - - quest_manager.me(SvPV_nolen(ST(0))); - - XSRETURN_EMPTY; + quest_manager.say(message, opts); } -XS(XS__summonitem); // prototype to pass -Wmissing-prototypes -XS(XS__summonitem) { - dXSARGS; - if (items == 1) - quest_manager.summonitem(SvUV(ST(0))); - else if (items == 2) - quest_manager.summonitem(SvUV(ST(0)), SvUV(ST(1))); - else - Perl_croak(aTHX_ "Usage: quest::summonitem(int item_id, [int charges])"); - XSRETURN_EMPTY; +void Perl__say(const char* message, int language_id, int message_type) +{ + Journal::Options opts; + opts.speak_mode = Journal::SpeakMode::Say; + opts.journal_mode = Journal::Mode::Log2; + opts.language = language_id; + opts.message_type = message_type; + + quest_manager.say(message, opts); } -XS(XS__write); -XS(XS__write) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::write(string file_name, string message)"); +void Perl__say(const char* message, int language_id, int message_type, int speak_mode) +{ + Journal::Options opts; + opts.speak_mode = static_cast(speak_mode); + opts.journal_mode = Journal::Mode::Log2; + opts.language = language_id; + opts.message_type = message_type; - char *file = (char *) SvPV_nolen(ST(0)); - char *message = (char *) SvPV_nolen(ST(1)); + quest_manager.say(message, opts); +} +void Perl__say(const char* message, int language_id, int message_type, int speak_mode, int journal_mode) +{ + Journal::Options opts; + opts.speak_mode = static_cast(speak_mode); + opts.journal_mode = static_cast(journal_mode); + opts.language = language_id; + opts.message_type = message_type; + + quest_manager.say(message, opts); +} + +void Perl__me(const char* message) +{ + quest_manager.me(message); +} + +void Perl__summonitem(int item_id) +{ + quest_manager.summonitem(item_id); +} + +void Perl__summonitem(int item_id, int charges) +{ + quest_manager.summonitem(item_id, charges); +} + +void Perl__write(const char* file, const char* message) +{ quest_manager.write(file, message); - - XSRETURN_EMPTY; } -XS(XS__spawn); -XS(XS__spawn) { - dXSARGS; - if (items != 6) - Perl_croak(aTHX_ "Usage: quest::spawn(int npc_type_id, int grid_id, int int_unused, float x, float y, float z)"); - - uint16 RETVAL; - dXSTARG; - - int npc_type_id = (int) SvIV(ST(0)); - int grid_id = (int) SvIV(ST(1)); - int int_unused = (int) SvIV(ST(2)); - auto position = glm::vec4((float) SvNV(ST(3)), (float) SvNV(ST(4)), (float) SvNV(ST(5)), 0.0f); - - Mob *r = quest_manager.spawn2(npc_type_id, grid_id, int_unused, position); - RETVAL = (r != nullptr) ? r->GetID() : 0; - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +int Perl__spawn(int npc_type_id, int grid_id, int unused, float x, float y, float z) +{ + auto position = glm::vec4(x, y, z, 0.0f); + Mob* mob = quest_manager.spawn2(npc_type_id, grid_id, unused, position); + return mob ? mob->GetID() : 0; } -XS(XS__spawn2); -XS(XS__spawn2) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: quest::spawn2(int npc_type_id, int grid_id, int int_unused, float x, float y, float z, float heading)"); - - uint16 RETVAL; - dXSTARG; - - int npc_type_id = (int) SvIV(ST(0)); - int grid_id = (int) SvIV(ST(1)); - int int_unused = (int) SvIV(ST(2)); - auto position = glm::vec4((float) SvNV(ST(3)), (float) SvNV(ST(4)), (float) SvNV(ST(5)), (float) SvNV(ST(6))); - - Mob *r = quest_manager.spawn2(npc_type_id, grid_id, int_unused, position); - RETVAL = (r != nullptr) ? r->GetID() : 0; - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +int Perl__spawn2(int npc_type_id, int grid_id, int unused, float x, float y, float z, float heading) +{ + auto position = glm::vec4(x, y, z, heading); + Mob* mob = quest_manager.spawn2(npc_type_id, grid_id, unused, position); + return mob ? mob->GetID() : 0; } -XS(XS__unique_spawn); -XS(XS__unique_spawn) { - dXSARGS; - if (items != 6 && items != 7) - Perl_croak(aTHX_ "Usage: quest::unique_spawn(int npc_type_id, int grid_id, int int_unused, float x, float y, float z, [float heading])"); - - uint16 RETVAL; - dXSTARG; - - int npc_type_id = (int) SvIV(ST(0)); - int grid_id = (int) SvIV(ST(1)); - int int_unused = (int) SvIV(ST(2)); - float x = (float) SvNV(ST(3)); - float y = (float) SvNV(ST(4)); - float z = (float) SvNV(ST(5)); - float heading = 0; - if (items == 7) - heading = (float) SvNV(ST(6)); - - Mob *r = quest_manager.unique_spawn(npc_type_id, grid_id, int_unused, glm::vec4(x, y, z, heading)); - RETVAL = (r != nullptr) ? r->GetID() : 0; - - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +int Perl__unique_spawn(int npc_type_id, int grid_id, int unused, float x, float y, float z) +{ + auto position = glm::vec4(x, y, z, 0.0f); + Mob* mob = quest_manager.unique_spawn(npc_type_id, grid_id, unused, position); + return mob ? mob->GetID() : 0; } -XS(XS__spawn_from_spawn2); -XS(XS__spawn_from_spawn2) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::spawn_from_spawn2(int spawn2_id)"); - - uint16 RETVAL; - dXSTARG; - - int spawn2_id = (int) SvIV(ST(0)); - - Mob *r = quest_manager.spawn_from_spawn2(spawn2_id); - RETVAL = (r != nullptr) ? r->GetID() : 0; - - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +int Perl__unique_spawn(int npc_type_id, int grid_id, int unused, float x, float y, float z, float heading) +{ + auto position = glm::vec4(x, y, z, heading); + Mob* mob = quest_manager.unique_spawn(npc_type_id, grid_id, unused, position); + return mob ? mob->GetID() : 0; } -XS(XS__enable_spawn2); -XS(XS__enable_spawn2) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::enable_spawn2(int spawn2_id)"); - - int spawn2_id = (int) SvIV(ST(0)); +int Perl__spawn_from_spawn2(uint32_t spawn2_id) +{ + Mob* mob = quest_manager.spawn_from_spawn2(spawn2_id); + return mob ? mob->GetID() : 0; +} +void Perl__enable_spawn2(uint32_t spawn2_id) +{ quest_manager.enable_spawn2(spawn2_id); - XSRETURN_EMPTY; } -XS(XS__disable_spawn2); -XS(XS__disable_spawn2) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::disable_spawn2(int spawn2_id)"); - - int spawn2_id = (int) SvIV(ST(0)); - +void Perl__disable_spawn2(uint32_t spawn2_id) +{ quest_manager.disable_spawn2(spawn2_id); - XSRETURN_EMPTY; } -XS(XS__setstat); -XS(XS__setstat) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::setstat(stat_id, int_value)"); - - int stat_id = (int) SvIV(ST(0)); - int int_value = (int) SvIV(ST(1)); - +void Perl__setstat(int stat_id, int int_value) +{ quest_manager.setstat(stat_id, int_value); - - XSRETURN_EMPTY; } -XS(XS__incstat); //old setstat command aza -XS(XS__incstat) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::incstat(int stat_id, int value)"); - - int stat_id = (int) SvIV(ST(0)); - int int_value = (int) SvIV(ST(1)); - +void Perl__incstat(int stat_id, int int_value) +{ quest_manager.incstat(stat_id, int_value); - - XSRETURN_EMPTY; } -XS(XS__getinventoryslotid); -XS(XS__getinventoryslotid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getinventoryslotid(string identifier)"); +int Perl__getinventoryslotid(std::string identifier) +{ + int result = EQ::invslot::SLOT_INVALID; - int16 RETVAL = EQ::invslot::SLOT_INVALID; - dXSTARG; - - std::string identifier = (Const_char *)SvPV_nolen(ST(0)); - for (std::string::size_type i = 0; i < identifier.length(); ++i) + for (std::string::size_type i = 0; i < identifier.size(); ++i) identifier[i] = std::tolower(identifier[i]); if (identifier.find('.') == std::string::npos) { - if (identifier == "invalid") RETVAL = EQ::invslot::SLOT_INVALID; - else if (identifier == "charm") RETVAL = EQ::invslot::slotCharm; - else if (identifier == "ear1") RETVAL = EQ::invslot::slotEar1; - else if (identifier == "head") RETVAL = EQ::invslot::slotHead; - else if (identifier == "face") RETVAL = EQ::invslot::slotFace; - else if (identifier == "ear2") RETVAL = EQ::invslot::slotEar2; - else if (identifier == "neck") RETVAL = EQ::invslot::slotNeck; - else if (identifier == "shoulders") RETVAL = EQ::invslot::slotShoulders; - else if (identifier == "arms") RETVAL = EQ::invslot::slotArms; - else if (identifier == "back") RETVAL = EQ::invslot::slotBack; - else if (identifier == "wrist1") RETVAL = EQ::invslot::slotWrist1; - else if (identifier == "wrist2") RETVAL = EQ::invslot::slotWrist2; - else if (identifier == "range") RETVAL = EQ::invslot::slotRange; - else if (identifier == "hands") RETVAL = EQ::invslot::slotHands; - else if (identifier == "primary") RETVAL = EQ::invslot::slotPrimary; - else if (identifier == "secondary") RETVAL = EQ::invslot::slotSecondary; - else if (identifier == "finger1") RETVAL = EQ::invslot::slotFinger1; - else if (identifier == "finger2") RETVAL = EQ::invslot::slotFinger2; - else if (identifier == "chest") RETVAL = EQ::invslot::slotChest; - else if (identifier == "legs") RETVAL = EQ::invslot::slotLegs; - else if (identifier == "feet") RETVAL = EQ::invslot::slotFeet; - else if (identifier == "waist") RETVAL = EQ::invslot::slotWaist; - else if (identifier == "powersource") RETVAL = EQ::invslot::slotPowerSource; - else if (identifier == "ammo") RETVAL = EQ::invslot::slotAmmo; - else if (identifier == "general1") RETVAL = EQ::invslot::slotGeneral1; - else if (identifier == "general2") RETVAL = EQ::invslot::slotGeneral2; - else if (identifier == "general3") RETVAL = EQ::invslot::slotGeneral3; - else if (identifier == "general4") RETVAL = EQ::invslot::slotGeneral4; - else if (identifier == "general5") RETVAL = EQ::invslot::slotGeneral5; - else if (identifier == "general6") RETVAL = EQ::invslot::slotGeneral6; - else if (identifier == "general7") RETVAL = EQ::invslot::slotGeneral7; - else if (identifier == "general8") RETVAL = EQ::invslot::slotGeneral8; - else if (identifier == "general9") RETVAL = EQ::invslot::slotGeneral9; - else if (identifier == "general10") RETVAL = EQ::invslot::slotGeneral10; - else if (identifier == "cursor") RETVAL = EQ::invslot::slotCursor; - else if (identifier == "tradeskill") RETVAL = EQ::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE; - else if (identifier == "augment") RETVAL = EQ::invslot::SLOT_AUGMENT_GENERIC_RETURN; + if (identifier == "invalid") result = EQ::invslot::SLOT_INVALID; + else if (identifier == "charm") result = EQ::invslot::slotCharm; + else if (identifier == "ear1") result = EQ::invslot::slotEar1; + else if (identifier == "head") result = EQ::invslot::slotHead; + else if (identifier == "face") result = EQ::invslot::slotFace; + else if (identifier == "ear2") result = EQ::invslot::slotEar2; + else if (identifier == "neck") result = EQ::invslot::slotNeck; + else if (identifier == "shoulders") result = EQ::invslot::slotShoulders; + else if (identifier == "arms") result = EQ::invslot::slotArms; + else if (identifier == "back") result = EQ::invslot::slotBack; + else if (identifier == "wrist1") result = EQ::invslot::slotWrist1; + else if (identifier == "wrist2") result = EQ::invslot::slotWrist2; + else if (identifier == "range") result = EQ::invslot::slotRange; + else if (identifier == "hands") result = EQ::invslot::slotHands; + else if (identifier == "primary") result = EQ::invslot::slotPrimary; + else if (identifier == "secondary") result = EQ::invslot::slotSecondary; + else if (identifier == "finger1") result = EQ::invslot::slotFinger1; + else if (identifier == "finger2") result = EQ::invslot::slotFinger2; + else if (identifier == "chest") result = EQ::invslot::slotChest; + else if (identifier == "legs") result = EQ::invslot::slotLegs; + else if (identifier == "feet") result = EQ::invslot::slotFeet; + else if (identifier == "waist") result = EQ::invslot::slotWaist; + else if (identifier == "powersource") result = EQ::invslot::slotPowerSource; + else if (identifier == "ammo") result = EQ::invslot::slotAmmo; + else if (identifier == "general1") result = EQ::invslot::slotGeneral1; + else if (identifier == "general2") result = EQ::invslot::slotGeneral2; + else if (identifier == "general3") result = EQ::invslot::slotGeneral3; + else if (identifier == "general4") result = EQ::invslot::slotGeneral4; + else if (identifier == "general5") result = EQ::invslot::slotGeneral5; + else if (identifier == "general6") result = EQ::invslot::slotGeneral6; + else if (identifier == "general7") result = EQ::invslot::slotGeneral7; + else if (identifier == "general8") result = EQ::invslot::slotGeneral8; + else if (identifier == "general9") result = EQ::invslot::slotGeneral9; + else if (identifier == "general10") result = EQ::invslot::slotGeneral10; + else if (identifier == "cursor") result = EQ::invslot::slotCursor; + else if (identifier == "tradeskill") result = EQ::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE; + else if (identifier == "augment") result = EQ::invslot::SLOT_AUGMENT_GENERIC_RETURN; } else { - if (identifier == "possessions.begin") RETVAL = EQ::invslot::POSSESSIONS_BEGIN; - else if (identifier == "possessions.end") RETVAL = EQ::invslot::POSSESSIONS_END; - else if (identifier == "equipment.begin") RETVAL = EQ::invslot::EQUIPMENT_BEGIN; - else if (identifier == "equipment.end") RETVAL = EQ::invslot::EQUIPMENT_END; - else if (identifier == "general.begin") RETVAL = EQ::invslot::GENERAL_BEGIN; - else if (identifier == "general.end") RETVAL = EQ::invslot::GENERAL_END; - else if (identifier == "possessionsbags.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN; - else if (identifier == "possessionsbags.end") RETVAL = EQ::invbag::CURSOR_BAG_END; - else if (identifier == "generalbags.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN; - else if (identifier == "generalbags.end") RETVAL = EQ::invbag::GENERAL_BAGS_END; - else if (identifier == "general1bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN; - else if (identifier == "general1bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 9; - else if (identifier == "general2bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 10; - else if (identifier == "general2bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 19; - else if (identifier == "general3bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 20; - else if (identifier == "general3bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 29; - else if (identifier == "general4bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 30; - else if (identifier == "general4bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 39; - else if (identifier == "general5bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 40; - else if (identifier == "general5bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 49; - else if (identifier == "general6bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 50; - else if (identifier == "general6bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 59; - else if (identifier == "general7bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 60; - else if (identifier == "general7bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 69; - else if (identifier == "general8bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 70; - else if (identifier == "general8bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 79; - else if (identifier == "general9bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 80; - else if (identifier == "general9bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 89; - else if (identifier == "general10bag.begin") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 90; - else if (identifier == "general10bag.end") RETVAL = EQ::invbag::GENERAL_BAGS_BEGIN + 99; - else if (identifier == "cursorbag.begin") RETVAL = EQ::invbag::CURSOR_BAG_BEGIN; - else if (identifier == "cursorbag.end") RETVAL = EQ::invbag::CURSOR_BAG_END; - else if (identifier == "bank.begin") RETVAL = EQ::invslot::BANK_BEGIN; - else if (identifier == "bank.end") RETVAL = EQ::invslot::BANK_END; - else if (identifier == "bankbags.begin") RETVAL = EQ::invbag::BANK_BAGS_BEGIN; - else if (identifier == "bankbags.end") RETVAL = EQ::invbag::BANK_BAGS_END; - else if (identifier == "sharedbank.begin") RETVAL = EQ::invslot::SHARED_BANK_BEGIN; - else if (identifier == "sharedbank.end") RETVAL = EQ::invslot::SHARED_BANK_END; - else if (identifier == "sharedbankbags.begin") RETVAL = EQ::invbag::SHARED_BANK_BAGS_BEGIN; - else if (identifier == "sharedbankbags.end") RETVAL = EQ::invbag::SHARED_BANK_BAGS_END; - else if (identifier == "bagslot.begin") RETVAL = EQ::invbag::SLOT_BEGIN; - else if (identifier == "bagslot.end") RETVAL = EQ::invbag::SLOT_END; - else if (identifier == "augsocket.begin") RETVAL = EQ::invaug::SOCKET_BEGIN; - else if (identifier == "augsocket.end") RETVAL = EQ::invaug::SOCKET_END; + if (identifier == "possessions.begin") result = EQ::invslot::POSSESSIONS_BEGIN; + else if (identifier == "possessions.end") result = EQ::invslot::POSSESSIONS_END; + else if (identifier == "equipment.begin") result = EQ::invslot::EQUIPMENT_BEGIN; + else if (identifier == "equipment.end") result = EQ::invslot::EQUIPMENT_END; + else if (identifier == "general.begin") result = EQ::invslot::GENERAL_BEGIN; + else if (identifier == "general.end") result = EQ::invslot::GENERAL_END; + else if (identifier == "possessionsbags.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN; + else if (identifier == "possessionsbags.end") result = EQ::invbag::CURSOR_BAG_END; + else if (identifier == "generalbags.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN; + else if (identifier == "generalbags.end") result = EQ::invbag::GENERAL_BAGS_END; + else if (identifier == "general1bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN; + else if (identifier == "general1bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 9; + else if (identifier == "general2bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 10; + else if (identifier == "general2bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 19; + else if (identifier == "general3bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 20; + else if (identifier == "general3bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 29; + else if (identifier == "general4bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 30; + else if (identifier == "general4bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 39; + else if (identifier == "general5bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 40; + else if (identifier == "general5bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 49; + else if (identifier == "general6bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 50; + else if (identifier == "general6bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 59; + else if (identifier == "general7bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 60; + else if (identifier == "general7bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 69; + else if (identifier == "general8bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 70; + else if (identifier == "general8bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 79; + else if (identifier == "general9bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 80; + else if (identifier == "general9bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 89; + else if (identifier == "general10bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 90; + else if (identifier == "general10bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 99; + else if (identifier == "cursorbag.begin") result = EQ::invbag::CURSOR_BAG_BEGIN; + else if (identifier == "cursorbag.end") result = EQ::invbag::CURSOR_BAG_END; + else if (identifier == "bank.begin") result = EQ::invslot::BANK_BEGIN; + else if (identifier == "bank.end") result = EQ::invslot::BANK_END; + else if (identifier == "bankbags.begin") result = EQ::invbag::BANK_BAGS_BEGIN; + else if (identifier == "bankbags.end") result = EQ::invbag::BANK_BAGS_END; + else if (identifier == "sharedbank.begin") result = EQ::invslot::SHARED_BANK_BEGIN; + else if (identifier == "sharedbank.end") result = EQ::invslot::SHARED_BANK_END; + else if (identifier == "sharedbankbags.begin") result = EQ::invbag::SHARED_BANK_BAGS_BEGIN; + else if (identifier == "sharedbankbags.end") result = EQ::invbag::SHARED_BANK_BAGS_END; + else if (identifier == "bagslot.begin") result = EQ::invbag::SLOT_BEGIN; + else if (identifier == "bagslot.end") result = EQ::invbag::SLOT_END; + else if (identifier == "augsocket.begin") result = EQ::invaug::SOCKET_BEGIN; + else if (identifier == "augsocket.end") result = EQ::invaug::SOCKET_END; } - XSprePUSH; - PUSHi((IV) RETVAL); - XSRETURN(1); + return result; } -XS(XS__castspell); -XS(XS__castspell) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::castspell(int spell_id, int target_id)"); - - int spell_id = (int) SvIV(ST(0)); - int target_id = (int) SvIV(ST(1)); - +void Perl__castspell(int spell_id, int target_id) +{ quest_manager.castspell(spell_id, target_id); - - XSRETURN_EMPTY; } -XS(XS__selfcast); -XS(XS__selfcast) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::selfcast(int spell_id)"); - - int spell_id = (int) SvIV(ST(0)); - +void Perl__selfcast(int spell_id) +{ quest_manager.selfcast(spell_id); - - XSRETURN_EMPTY; } -XS(XS__addloot); -XS(XS__addloot) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::addloot(uint32 item_id, uint16 charges = 0, [bool equip_item = true])"); - - uint32 item_id = (uint32) SvUV(ST(0)); - uint16 charges = 0; - bool equipitem = true; - - if (items > 1) - charges = (uint16) SvUV(ST(1)); - if (items > 2) - equipitem = (bool) SvTRUE(ST(2)); - - quest_manager.addloot(item_id, charges, equipitem); - - XSRETURN_EMPTY; +void Perl__addloot(int item_id) +{ + quest_manager.addloot(item_id); } -XS(XS__zone); -XS(XS__zone) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::zone(string zone_name)"); +void Perl__addloot(int item_id, int charges) +{ + quest_manager.addloot(item_id, charges); +} - char *zone_name = (char *) SvPV_nolen(ST(0)); +void Perl__addloot(int item_id, int charges, bool equip_item) +{ + quest_manager.addloot(item_id, charges, equip_item); +} +void Perl__zone(const char* zone_name) +{ quest_manager.Zone(zone_name); - - XSRETURN_EMPTY; } -XS(XS__zonegroup); -XS(XS__zonegroup) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::zonegroup(string zone_name)"); - - char *zone_name = (char *) SvPV_nolen(ST(0)); - +void Perl__zonegroup(const char* zone_name) +{ quest_manager.ZoneGroup(zone_name); - - XSRETURN_EMPTY; } -XS(XS__zoneraid); -XS(XS__zoneraid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::zoneraid(string zone_name)"); - - char *zone_name = (char *) SvPV_nolen(ST(0)); - +void Perl__zoneraid(const char* zone_name) +{ quest_manager.ZoneRaid(zone_name); - - XSRETURN_EMPTY; } -XS(XS__hastimer); -XS(XS__hastimer) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::hastimer(string timer_name)"); - - bool RETVAL; - char *timer_name = (char *)SvPV_nolen(ST(0)); - - RETVAL = quest_manager.hastimer(timer_name); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__hastimer(const char* timer_name) +{ + return quest_manager.hastimer(timer_name); } -XS(XS__getremainingtimeMS); -XS(XS__getremainingtimeMS) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getremainingtimeMS(string timer_name)"); - - uint32 RETVAL; - dXSTARG; - char *timer_name = (char *)SvPV_nolen(ST(0)); - - RETVAL = quest_manager.getremainingtimeMS(timer_name); - - XSprePUSH; - PUSHu((UV) RETVAL); - XSRETURN(1); +uint32_t Perl__getremainingtimeMS(const char* timer_name) +{ + return quest_manager.getremainingtimeMS(timer_name); } -XS(XS__gettimerdurationMS); -XS(XS__gettimerdurationMS) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::gettimerdurationMS(string timer_name)"); - - uint32 RETVAL; - dXSTARG; - char *timer_name = (char *)SvPV_nolen(ST(0)); - - RETVAL = quest_manager.gettimerdurationMS(timer_name); - - XSprePUSH; - PUSHu((UV) RETVAL); - XSRETURN(1); +uint32_t Perl__gettimerdurationMS(const char* timer_name) +{ + return quest_manager.gettimerdurationMS(timer_name); } -XS(XS__settimer); -XS(XS__settimer) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::settimer(string timer_name, int seconds)"); - - char *timer_name = (char *) SvPV_nolen(ST(0)); - int seconds = (int) SvIV(ST(1)); - +void Perl__settimer(const char* timer_name, int seconds) +{ quest_manager.settimer(timer_name, seconds); - - XSRETURN_EMPTY; } -XS(XS__settimerMS); -XS(XS__settimerMS) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::settimerMS(string timer_name, int milliseconds)"); - - char *timer_name = (char *) SvPV_nolen(ST(0)); - int milliseconds = (int) SvIV(ST(1)); - +void Perl__settimerMS(const char* timer_name, int milliseconds) +{ quest_manager.settimerMS(timer_name, milliseconds); - - XSRETURN_EMPTY; } -XS(XS__stoptimer); -XS(XS__stoptimer) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::stoptimer(string timer_name)"); - - char *timer_name = (char *) SvPV_nolen(ST(0)); - +void Perl__stoptimer(const char* timer_name) +{ quest_manager.stoptimer(timer_name); - - XSRETURN_EMPTY; } -XS(XS__stopalltimers); -XS(XS__stopalltimers) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::stopalltimers()"); - +void Perl__stopalltimers() +{ quest_manager.stopalltimers(); - - XSRETURN_EMPTY; } -XS(XS__emote); -XS(XS__emote) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::emote(string message)"); - - char *message = (char *) SvPV_nolen(ST(0)); - +void Perl__emote(const char* message) +{ quest_manager.emote(message); - - XSRETURN_EMPTY; } -XS(XS__shout); -XS(XS__shout) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::shout(string message)"); - - char *message = (char *) SvPV_nolen(ST(0)); - +void Perl__shout(const char* message) +{ quest_manager.shout(message); - - XSRETURN_EMPTY; } -XS(XS__shout2); -XS(XS__shout2) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::shout2(string message)"); - - char *message = (char *) SvPV_nolen(ST(0)); - +void Perl__shout2(const char* message) +{ quest_manager.shout2(message); - - XSRETURN_EMPTY; } -XS(XS__gmsay); -XS(XS__gmsay) { - dXSARGS; - if ((items < 1) || (items > 5)) - Perl_croak(aTHX_ "Usage: quest::gmsay(string message, [int color_id], [bool send_to_world = 0])"); +void Perl__gmsay(const char* message) +{ + quest_manager.gmsay(message, Chat::LightGray, false, 0, AccountStatus::QuestTroupe); +} - char *message = (char *) SvPV_nolen(ST(0)); - int color_id = 7; - bool send_to_world = 0; - uint32 to_guilddbid = 0; - uint16 to_minstatus = 80; +void Perl__gmsay(const char* message, int color_id) +{ + quest_manager.gmsay(message, color_id, false, 0, AccountStatus::QuestTroupe); +} - if (items > 1) { - color_id = (int) SvIV(ST(1)); - } +void Perl__gmsay(const char* message, int color_id, bool send_to_world) +{ + quest_manager.gmsay(message, color_id, send_to_world, 0, AccountStatus::QuestTroupe); +} - if (items > 2) { - send_to_world = ((int) SvIV(ST(2))) == 0 ? false : true; - } - - if (items > 3) - to_guilddbid = (int) SvUV(ST(3)); - - if (items > 4) - to_minstatus = (int) SvUV(ST(4)); +void Perl__gmsay(const char* message, int color_id, bool send_to_world, int to_guilddbid) +{ + quest_manager.gmsay(message, color_id, send_to_world, to_guilddbid, AccountStatus::QuestTroupe); +} +void Perl__gmsay(const char* message, int color_id, bool send_to_world, int to_guilddbid, int to_minstatus) +{ quest_manager.gmsay(message, color_id, send_to_world, to_guilddbid, to_minstatus); - - XSRETURN_EMPTY; } -XS(XS__depop); -XS(XS__depop) { - dXSARGS; - if (items < 0 || items > 1) - Perl_croak(aTHX_ "Usage: quest::depop(int npc_type_id = 0)"); - - int npc_type_id; - - if (items < 1) - npc_type_id = 0; - else - npc_type_id = (int) SvIV(ST(0)); - +void Perl__depop() +{ + quest_manager.depop(); +} +void Perl__depop(int npc_type_id) +{ quest_manager.depop(npc_type_id); - - XSRETURN_EMPTY; } -XS(XS__depop_withtimer); -XS(XS__depop_withtimer) { - dXSARGS; - if (items < 0 || items > 1) - Perl_croak(aTHX_ "Usage: quest::depop_withtimer(int npc_type_id = 0)"); - - int npc_type_id; - - if (items < 1) - npc_type_id = 0; - else - npc_type_id = (int) SvIV(ST(0)); - +void Perl__depop_withtimer() +{ + quest_manager.depop_withtimer(); +} +void Perl__depop_withtimer(int npc_type_id) +{ quest_manager.depop_withtimer(npc_type_id); - - XSRETURN_EMPTY; } -XS(XS__depopall); -XS(XS__depopall) { - dXSARGS; - if (items < 0 || items > 1) - Perl_croak(aTHX_ "Usage: quest::depopall(int npc_type_id = 0)"); - - int npc_type_id; - - if (items < 1) - npc_type_id = 0; - else - npc_type_id = (int) SvIV(ST(0)); - +void Perl__depopall() +{ + quest_manager.depopall(); +} +void Perl__depopall(int npc_type_id) +{ quest_manager.depopall(npc_type_id); - - XSRETURN_EMPTY; } -XS(XS__settarget); -XS(XS__settarget) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::settarget(string target_enum ['npc_type', 'entity'], int target_id)"); - - char *target_enum = (char *) SvPV_nolen(ST(0)); - int target_id = (int) SvIV(ST(1)); - +void Perl__settarget(const char* target_enum, int target_id) +{ quest_manager.settarget(target_enum, target_id); - - XSRETURN_EMPTY; } -XS(XS__follow); -XS(XS__follow) { - dXSARGS; - if (items != 1 && items != 2) - Perl_croak(aTHX_ "Usage: quest::follow(int entity_id, [int distance = 10])"); - - int entity_id = (int) SvIV(ST(0)); - int distance; - - if (items == 2) - distance = (int) SvIV(ST(1)); - else - distance = 10; +void Perl__follow(int entity_id) +{ + quest_manager.follow(entity_id, 10); +} +void Perl__follow(int entity_id, int distance) +{ quest_manager.follow(entity_id, distance); - - XSRETURN_EMPTY; } -XS(XS__sfollow); -XS(XS__sfollow) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::sfollow()"); - - +void Perl__sfollow() +{ quest_manager.sfollow(); - - XSRETURN_EMPTY; } -XS(XS__changedeity); -XS(XS__changedeity) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::changedeity(int deity_id)"); - - int deity_id = (int) SvIV(ST(0)); - +void Perl__changedeity(int deity_id) +{ quest_manager.changedeity(deity_id); - - XSRETURN_EMPTY; } -XS(XS__exp); -XS(XS__exp) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::exp(int amount)"); - - int amt = (int) SvIV(ST(0)); - - quest_manager.exp(amt); - - XSRETURN_EMPTY; +void Perl__exp(int amount) +{ + quest_manager.exp(amount); } -XS(XS__level); -XS(XS__level) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::level(int new_level)"); - - int newlevel = (int) SvIV(ST(0)); - - quest_manager.level(newlevel); - - XSRETURN_EMPTY; +void Perl__level(int new_level) +{ + quest_manager.level(new_level); } -XS(XS__traindisc); -XS(XS__traindisc) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::traindisc(int tome_item_id)"); - - int discipline_tome_item_id = (int) SvIV(ST(0)); - - quest_manager.traindisc(discipline_tome_item_id); - - XSRETURN_EMPTY; +void Perl__traindisc(int tome_item_id) +{ + quest_manager.traindisc(tome_item_id); } -XS(XS__isdisctome); -XS(XS__isdisctome) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::isdisctome(int item_id)"); - - bool RETVAL; - int item_id = (int) SvIV(ST(0)); - - RETVAL = quest_manager.isdisctome(item_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__isdisctome(int item_id) +{ + return quest_manager.isdisctome(item_id); } -XS(XS__getracename); -XS(XS__getracename) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getracename(uint16 race_id)"); - - dXSTARG; - uint16 race_id = (int) SvIV(ST(0)); - std::string race_name = quest_manager.getracename(race_id); - - sv_setpv(TARG, race_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +std::string Perl__getracename(uint16 race_id) +{ + return quest_manager.getracename(race_id); } -XS(XS__getspellname); -XS(XS__getspellname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getspellname(uint32 spell_id)"); - - dXSTARG; - uint32 spell_id = (int) SvIV(ST(0)); - std::string spell_name = quest_manager.getspellname(spell_id); - - sv_setpv(TARG, spell_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +std::string Perl__getspellname(uint32 spell_id) +{ + return quest_manager.getspellname(spell_id); } -XS(XS__get_spell_level); -XS(XS__get_spell_level) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::get_spell_level(uint16 spell_id, uint8 class_id)"); - - dXSTARG; - uint16 spell_id = (int)SvIV(ST(0)); - uint8 class_id = (int)SvIV(ST(1)); - uint8 spell_level = IsValidSpell(spell_id) ? GetSpellLevel(spell_id, class_id) : 0; - uint8 server_max_level = RuleI(Character, MaxLevel); - - if (spell_level && spell_level > server_max_level) - spell_level = 0; - - XSprePUSH; - PUSHu((UV)spell_level); - - XSRETURN(1); +int Perl__get_spell_level(uint32_t spell_id, int class_id) +{ + int spell_level = IsValidSpell(spell_id) ? GetSpellLevel(spell_id, class_id) : 0; + return (spell_level > RuleI(Character, MaxLevel)) ? 0 : spell_level; } -XS(XS__getskillname); -XS(XS__getskillname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getskillname(int skill_id)"); - - dXSTARG; - int skill_id = (int) SvIV(ST(0)); - std::string skill_name = quest_manager.getskillname(skill_id); - - sv_setpv(TARG, skill_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +std::string Perl__getskillname(int skill_id) +{ + return quest_manager.getskillname(skill_id); } -XS(XS__safemove); -XS(XS__safemove) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::safemove()"); - - +void Perl__safemove() +{ quest_manager.safemove(); - - XSRETURN_EMPTY; } -XS(XS__rain); -XS(XS__rain) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::rain(int weather)"); - - int weather = (int) SvIV(ST(0)); - +void Perl__rain(int weather) +{ quest_manager.rain(weather); - - XSRETURN_EMPTY; } -XS(XS__snow); -XS(XS__snow) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::snow(int weather)"); - - int weather = (int) SvIV(ST(0)); - +void Perl__snow(int weather) +{ quest_manager.snow(weather); - - XSRETURN_EMPTY; } -XS(XS__surname); -XS(XS__surname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::surname(string name)"); - - char *name = (char *) SvPV_nolen(ST(0)); - - quest_manager.surname(name); - - XSRETURN_EMPTY; +void Perl__surname(std::string last_name) +{ + quest_manager.surname(last_name); } -XS(XS__permaclass); -XS(XS__permaclass) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::permaclass(int class_id)"); - - int class_id = (int) SvIV(ST(0)); - +void Perl__permaclass(int class_id) +{ quest_manager.permaclass(class_id); - - XSRETURN_EMPTY; } -XS(XS__permarace); -XS(XS__permarace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::permarace(int race_id)"); - - int race_id = (int) SvIV(ST(0)); - +void Perl__permarace(int race_id) +{ quest_manager.permarace(race_id); - - XSRETURN_EMPTY; } -XS(XS__permagender); -XS(XS__permagender) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::permagender(int gender_id)"); - - int gender_id = (int) SvIV(ST(0)); - +void Perl__permagender(int gender_id) +{ quest_manager.permagender(gender_id); - - XSRETURN_EMPTY; } -XS(XS__scribespells); -XS(XS__scribespells) { - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: quest::scribespells(int max_level, [int min_level = 1])"); - - uint16 RETVAL; - dXSTARG; - - uint8 max_level = (uint8) SvIV(ST(0)); - uint8 min_level = (uint8) SvIV(ST(1)); - - if (min_level) - RETVAL = quest_manager.scribespells(max_level, min_level); - else - RETVAL = quest_manager.scribespells(max_level); - - XSprePUSH; - PUSHu((UV) RETVAL); - XSRETURN(1); +int Perl__scribespells(int max_level) +{ + return quest_manager.scribespells(max_level); } -XS(XS__traindiscs); -XS(XS__traindiscs) { - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: quest::traindiscs(int max_level, [int min_level = 1])"); - - uint16 RETVAL; - dXSTARG; - - uint8 max_level = (uint8) SvIV(ST(0)); - uint8 min_level = (uint8) SvIV(ST(1)); - - if (min_level) - RETVAL = quest_manager.traindiscs(max_level, min_level); - else - RETVAL = quest_manager.traindiscs(max_level); - - XSprePUSH; - PUSHu((UV) RETVAL); - XSRETURN(1); +int Perl__scribespells(int max_level, int min_level) +{ + return quest_manager.scribespells(max_level, min_level); } -XS(XS__unscribespells); -XS(XS__unscribespells) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::unscribespells()"); +int Perl__traindiscs(int max_level) +{ + return quest_manager.traindiscs(max_level); +} +int Perl__traindiscs(int max_level, int min_level) +{ + return quest_manager.traindiscs(max_level, min_level); +} +void Perl__unscribespells() +{ quest_manager.unscribespells(); - - XSRETURN_EMPTY; } -XS(XS__untraindiscs); -XS(XS__untraindiscs) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::untraindiscs()"); - - +void Perl__untraindiscs() +{ quest_manager.untraindiscs(); - - XSRETURN_EMPTY; } -XS(XS__givecash); -XS(XS__givecash) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: quest::givecash(int copper, int silver, int gold, int platinum)"); +void Perl__givecash(uint32 copper) +{ + quest_manager.givecash(copper); +} - int copper = (int) SvIV(ST(0)); - int silver = (int) SvIV(ST(1)); - int gold = (int) SvIV(ST(2)); - int platinum = (int) SvIV(ST(3)); +void Perl__givecash(uint32 copper, uint32 silver) +{ + quest_manager.givecash(copper, silver); +} +void Perl__givecash(uint32 copper, uint32 silver, uint32 gold) +{ + quest_manager.givecash(copper, silver, gold); +} + +void Perl__givecash(uint32 copper, uint32 silver, uint32 gold, uint32 platinum) +{ quest_manager.givecash(copper, silver, gold, platinum); - - XSRETURN_EMPTY; } -XS(XS__pvp); -XS(XS__pvp) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::pvp(string mode [on|off])"); - - char *mode = (char *) SvPV_nolen(ST(0)); - +void Perl__pvp(const char* mode) +{ quest_manager.pvp(mode); - - XSRETURN_EMPTY; } -XS(XS__movepc); -XS(XS__movepc) { - dXSARGS; - if (items != 4 && items != 5) - Perl_croak(aTHX_ "Usage: quest::movepc(int zone_id, float x, float y, float z [float heading])"); - - int zone_id = (int) SvIV(ST(0)); - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - - if (items == 4) - - quest_manager.movepc(zone_id, x, y, z, 0.0f); - - else { - float heading = (float) SvNV(ST(4)); - quest_manager.movepc(zone_id, x, y, z, heading); - } - - XSRETURN_EMPTY; +void Perl__movepc(int zone_id, float x, float y, float z) +{ + quest_manager.movepc(zone_id, x, y, z, 0.0f); } -XS(XS__gmmove); -XS(XS__gmmove) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::gmmove(float x, float y, float z)"); - - float x = (float) SvNV(ST(0)); - float y = (float) SvNV(ST(1)); - float z = (float) SvNV(ST(2)); +void Perl__movepc(int zone_id, float x, float y, float z, float heading) +{ + quest_manager.movepc(zone_id, x, y, z, heading); +} +void Perl__gmmove(float x, float y, float z) +{ quest_manager.gmmove(x, y, z); - - XSRETURN_EMPTY; } -XS(XS__movegrp); -XS(XS__movegrp) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: quest::movegrp(int zone_id, float x, float y, float z)"); - - int zone_id = (int) SvIV(ST(0)); - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - +void Perl__movegrp(int zone_id, float x, float y, float z) +{ quest_manager.movegrp(zone_id, x, y, z); - - XSRETURN_EMPTY; } -XS(XS__doanim); -XS(XS__doanim) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::doanim(int animation_id)"); - - int anim_id = (int) SvIV(ST(0)); - - quest_manager.doanim(anim_id); - - XSRETURN_EMPTY; +void Perl__doanim(int animation_id) +{ + quest_manager.doanim(animation_id); } -XS(XS__addskill); -XS(XS__addskill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::addskill(int skill_id, int value)"); - - int skill_id = (int) SvIV(ST(0)); - int int_value = (int) SvIV(ST(1)); - - quest_manager.addskill(skill_id, int_value); - - XSRETURN_EMPTY; +void Perl__doanim(int animation_id, int animation_speed) +{ + quest_manager.doanim(animation_id, animation_speed); } -XS(XS__setlanguage); -XS(XS__setlanguage) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::setlanguage(int skill_id, int value)"); - - int skill_id = (int) SvIV(ST(0)); - int int_value = (int) SvIV(ST(1)); - - quest_manager.setlanguage(skill_id, int_value); - - XSRETURN_EMPTY; +void Perl__doanim(int animation_id, int animation_speed, bool ackreq) +{ + quest_manager.doanim(animation_id, animation_speed, ackreq); } -XS(XS__setskill); -XS(XS__setskill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::setskill(int skill_id, int value)"); - - int skill_id = (int) SvIV(ST(0)); - int int_value = (int) SvIV(ST(1)); - - quest_manager.setskill(skill_id, int_value); - - XSRETURN_EMPTY; +void Perl__doanim(int animation_id, int animation_speed, bool ackreq, int filter) +{ + quest_manager.doanim(animation_id, animation_speed, ackreq, static_cast(filter)); } -XS(XS__setallskill); -XS(XS__setallskill) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::setallskill(int value)"); - - int int_value = (int) SvIV(ST(0)); - - quest_manager.setallskill(int_value); - - XSRETURN_EMPTY; +void Perl__addskill(int skill_id, int value) +{ + quest_manager.addskill(skill_id, value); } -XS(XS__attack); -XS(XS__attack) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::attack(string client_name)"); +void Perl__setlanguage(int skill_id, int value) +{ + quest_manager.setlanguage(skill_id, value); +} - char *client_name = (char *) SvPV_nolen(ST(0)); +void Perl__setskill(int skill_id, int value) +{ + quest_manager.setskill(skill_id, value); +} +void Perl__setallskill(int value) +{ + quest_manager.setallskill(value); +} + +void Perl__attack(const char* client_name) +{ quest_manager.attack(client_name); - - XSRETURN_EMPTY; } -XS(XS__attacknpc); -XS(XS__attacknpc) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::attacknpc(int npc_entity_id)"); - - int npc_entity_id = (int) SvIV(ST(0)); - +void Perl__attacknpc(int npc_entity_id) +{ quest_manager.attacknpc(npc_entity_id); - - XSRETURN_EMPTY; } -XS(XS__attacknpctype); -XS(XS__attacknpctype) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::attacknpctype(int npc_type_id)"); - - int npc_type_id = (int) SvIV(ST(0)); - +void Perl__attacknpctype(int npc_type_id) +{ quest_manager.attacknpctype(npc_type_id); - - XSRETURN_EMPTY; } -XS(XS__save); -XS(XS__save) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::save()"); - - +void Perl__save() +{ quest_manager.save(); - - XSRETURN_EMPTY; } -XS(XS__faction); -XS(XS__faction) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::faction(int faction_id, int value, [int temp = 0])"); - - int faction_id = (int) SvIV(ST(0)); - int int_value = (int) SvIV(ST(1)); - int temp; - - if (items == 2) - temp = 0; - else - temp = (int) SvIV(ST(2)); - - quest_manager.faction(faction_id, int_value, temp); - - XSRETURN_EMPTY; +void Perl__faction(int faction_id, int value) +{ + quest_manager.faction(faction_id, value, 0); } -XS(XS__setsky); -XS(XS__setsky) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::setsky(uint8 sky)"); +void Perl__faction(int faction_id, int value, int temp) +{ + quest_manager.faction(faction_id, value, temp); +} - unsigned char new_sky = (unsigned char) SvUV(ST(0)); +void Perl__rewardfaction(int faction_id, int value) +{ + quest_manager.rewardfaction(faction_id, value); +} +void Perl__setsky(uint8 new_sky) +{ quest_manager.setsky(new_sky); - - XSRETURN_EMPTY; } -XS(XS__setguild); -XS(XS__setguild) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::setguild(int guild_id, int guild_rank_id)"); - - unsigned long new_guild_id = (unsigned long) SvUV(ST(0)); - int guild_rank_id = (int) SvIV(ST(1)); - - quest_manager.setguild(new_guild_id, guild_rank_id); - - XSRETURN_EMPTY; +void Perl__setguild(uint32_t guild_id, uint8_t guild_rank_id) +{ + quest_manager.setguild(guild_id, guild_rank_id); } -XS(XS__createguild); -XS(XS__createguild) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::createguild(string guild_name, string leader_name)"); - - char *guild_name = (char *) SvPV_nolen(ST(0)); - char *leader_name = (char *) SvPV_nolen(ST(1)); - +void Perl__createguild(const char* guild_name, const char* leader_name) +{ quest_manager.CreateGuild(guild_name, leader_name); - - XSRETURN_EMPTY; } -XS(XS__settime); -XS(XS__settime) { - dXSARGS; - if (items < 2) - Perl_croak(aTHX_ "Usage: quest::settime(int new_hour, int new_min, [bool update_world = true])"); - - if (items == 2) { - int new_hour = (int) SvIV(ST(0)); - int new_min = (int) SvIV(ST(1)); - quest_manager.settime(new_hour, new_min, true); - } else if (items == 3) { - int new_hour = (int) SvIV(ST(0)); - int new_min = (int) SvIV(ST(1)); - - int update_world = (int) SvIV(ST(2)); - if (update_world == 1) { - quest_manager.settime(new_hour, new_min, true); - } else { - quest_manager.settime(new_hour, new_min, false); - } - } - - XSRETURN_EMPTY; +void Perl__settime(int new_hour, int new_min) +{ + quest_manager.settime(new_hour, new_min); } -XS(XS__itemlink); -XS(XS__itemlink) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::itemlink(int item_id)"); - - int item_id = (int) SvIV(ST(0)); +void Perl__settime(int new_hour, int new_min, bool update_world) +{ + quest_manager.settime(new_hour, new_min, update_world); +} +void Perl__itemlink(int item_id) +{ quest_manager.itemlink(item_id); - - XSRETURN_EMPTY; } -XS(XS__signalwith); -XS(XS__signalwith) { - dXSARGS; - - if (items == 2) { - int npc_id = (int) SvIV(ST(0)); - int signal_id = (int) SvIV(ST(1)); - quest_manager.signalwith(npc_id, signal_id); - } else if (items == 3) { - int npc_id = (int) SvIV(ST(0)); - int signal_id = (int) SvIV(ST(1)); - int wait = (int) SvIV(ST(2)); - quest_manager.signalwith(npc_id, signal_id, wait); - } else { - Perl_croak(aTHX_ "Usage: quest::signalwith(int npc_id, int signal_id, [int wait_ms])"); - } - - XSRETURN_EMPTY; +void Perl__signalwith(int npc_id, int signal_id) +{ + quest_manager.signalwith(npc_id, signal_id); } -XS(XS__signal); -XS(XS__signal) { - dXSARGS; - - if (items == 1) { - int npc_id = (int) SvIV(ST(0)); - quest_manager.signal(npc_id); - } else if (items == 2) { - int npc_id = (int) SvIV(ST(0)); - int wait = (int) SvIV(ST(1)); - quest_manager.signal(npc_id, wait); - } else { - Perl_croak(aTHX_ "Usage: quest::signal(int npc_id, [int wait_ms])"); - } - - XSRETURN_EMPTY; +void Perl__signalwith(int npc_id, int signal_id, int wait_ms) +{ + quest_manager.signalwith(npc_id, signal_id, wait_ms); } -XS(XS__setglobal); -XS(XS__setglobal) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: quest::setglobal(stirng key, string value, int options, string duration)"); - - char *key = (char *) SvPV_nolen(ST(0)); - char *str_value = (char *) SvPV_nolen(ST(1)); - int options = (int) SvIV(ST(2)); - char *duration = (char *) SvPV_nolen(ST(3)); - - quest_manager.setglobal(key, str_value, options, duration); - - XSRETURN_EMPTY; +void Perl__signal(int npc_id) +{ + quest_manager.signal(npc_id); } -XS(XS__targlobal); -XS(XS__targlobal) { - dXSARGS; - if (items != 6) - Perl_croak(aTHX_ "Usage: quest::targlobal(stirng key, string value, string duration, int npc_id, int chararacter_id, int zone_id)"); - - char *key = (char *) SvPV_nolen(ST(0)); - char *str_value = (char *) SvPV_nolen(ST(1)); - char *duration = (char *) SvPV_nolen(ST(2)); - int npc_id = (int) SvIV(ST(3)); - int char_id = (int) SvIV(ST(4)); - int zone_id = (int) SvIV(ST(5)); - - quest_manager.targlobal(key, str_value, duration, npc_id, char_id, zone_id); - - XSRETURN_EMPTY; +void Perl__signal(int npc_id, int wait_ms) +{ + quest_manager.signal(npc_id, wait_ms); } -XS(XS__delglobal); -XS(XS__delglobal) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::delglobal(string key)"); +void Perl__setglobal(const char* key, const char* value, int options, const char* duration) +{ + quest_manager.setglobal(key, value, options, duration); +} - char *key = (char *) SvPV_nolen(ST(0)); +void Perl__targlobal(const char* key, const char* value, const char* duration, int npc_id, int char_id, int zone_id) +{ + quest_manager.targlobal(key, value, duration, npc_id, char_id, zone_id); +} +void Perl__delglobal(const char* key) +{ quest_manager.delglobal(key); - - XSRETURN_EMPTY; } -XS(XS__ding); -XS(XS__ding) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::ding()"); - - +void Perl__ding() +{ quest_manager.ding(); - - XSRETURN_EMPTY; } -XS(XS__rebind); -XS(XS__rebind) { - dXSARGS; - if (items < 4 || items > 5) - Perl_croak(aTHX_ "Usage: quest::rebind(int zone_id, float x, float y, float z, [float heading])"); - - int zone_id = (int) SvIV(ST(0)); - float target_x = (float) SvNV(ST(1)); - float target_y = (float) SvNV(ST(2)); - float target_z = (float) SvNV(ST(3)); - if (items > 4) { - float target_heading = (float) SvNV(ST(4)); - quest_manager.rebind(zone_id, glm::vec4(target_x, target_y, target_z, target_heading)); - } else { - quest_manager.rebind(zone_id, glm::vec3(target_x, target_y, target_z)); - } - XSRETURN_EMPTY; +void Perl__rebind(int zone_id, float x, float y, float z) +{ + quest_manager.rebind(zone_id, glm::vec3(x, y, z)); } -XS(XS__start); -XS(XS__start) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::start(int waypoint)"); - - int wp = (int) SvIV(ST(0)); - - quest_manager.start(wp); - - XSRETURN_EMPTY; +void Perl__rebind(int zone_id, float x, float y, float z, float heading) +{ + quest_manager.rebind(zone_id, glm::vec4(x, y, z, heading)); } -XS(XS__stop); -XS(XS__stop) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::stop()"); - +void Perl__start(int waypoint) +{ + quest_manager.start(waypoint); +} +void Perl__stop() +{ quest_manager.stop(); - - XSRETURN_EMPTY; } -XS(XS__pause); -XS(XS__pause) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::pause(int duration-ms)"); - - int duration = (int) SvIV(ST(0)); - - quest_manager.pause(duration); - - XSRETURN_EMPTY; +void Perl__pause(int duration_ms) +{ + quest_manager.pause(duration_ms); } -XS(XS__moveto); -XS(XS__moveto) { - dXSARGS; - if (items != 3 && items != 4 && items != 5) - Perl_croak(aTHX_ "Usage: quest::moveto(float x, float y, float z, [float heading], [bool save_guard_location])"); - - float x = (float) SvNV(ST(0)); - float y = (float) SvNV(ST(1)); - float z = (float) SvNV(ST(2)); - float h; - bool saveguard; - - if (items > 3) - h = (float) SvNV(ST(3)); - else - h = 0; - - if (items > 4) - saveguard = (bool) SvTRUE(ST(4)); - else - saveguard = false; - - quest_manager.moveto(glm::vec4(x, y, z, h), saveguard); - - XSRETURN_EMPTY; +void Perl__moveto(float x, float y, float z) +{ + quest_manager.moveto(glm::vec4(x, y, z, 0.0f), false); } -XS(XS__resume); -XS(XS__resume) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::resume()"); +void Perl__moveto(float x, float y, float z, float h) +{ + quest_manager.moveto(glm::vec4(x, y, z, h), false); +} +void Perl__moveto(float x, float y, float z, float h, bool save_guard_location) +{ + quest_manager.moveto(glm::vec4(x, y, z, h), save_guard_location); +} +void Perl__resume() +{ quest_manager.resume(); - - XSRETURN_EMPTY; } -XS(XS__addldonpoints); -XS(XS__addldonpoints) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::addldonpoints(uint32 theme_id, int points)"); - - uint32 theme_id = (uint32) SvUV(ST(0)); - int points = (int) SvIV(ST(1)); +void Perl__addldonpoints(uint32 theme_id, int points) +{ quest_manager.addldonpoints(theme_id, points); - XSRETURN_EMPTY; } -XS(XS__addldonwin); -XS(XS__addldonwin) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::addldonwin(uint32 theme_id)"); - - uint32 theme_id = (uint32) SvUV(ST(0)); +void Perl__addldonwin(uint32 theme_id) +{ quest_manager.addldonwin(theme_id); - XSRETURN_EMPTY; } -XS(XS__addldonloss); -XS(XS__addldonloss) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::addldonloss(uint32 theme_id)"); - - uint32 theme_id = (uint32) SvUV(ST(0)); +void Perl__addldonloss(uint32 theme_id) +{ quest_manager.addldonloss(theme_id); - XSRETURN_EMPTY; } -XS(XS__setnexthpevent); -XS(XS__setnexthpevent) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::setnexthpevent(int at_mob_percentage)"); - - int at = (int)SvIV(ST(0)); - - quest_manager.setnexthpevent(at); - - XSRETURN_EMPTY; +void Perl__setnexthpevent(int at_mob_percentage) +{ + quest_manager.setnexthpevent(at_mob_percentage); } -XS(XS__setnextinchpevent); -XS(XS__setnextinchpevent) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::setnextinchpevent(int at_mob_percentage)"); - - int at = (int)SvIV(ST(0)); - - quest_manager.setnextinchpevent(at); - - XSRETURN_EMPTY; +void Perl__setnextinchpevent(int at_mob_percentage) +{ + quest_manager.setnextinchpevent(at_mob_percentage); } -XS(XS__sethp); -XS(XS__sethp) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::sethp(int mob_health_percentage [0-100])"); - - int hpperc = (int)SvIV(ST(0)); - - quest_manager.sethp(hpperc); - - XSRETURN_EMPTY; +void Perl__sethp(int mob_health_percentage) +{ + quest_manager.sethp(mob_health_percentage); } -XS(XS__respawn); -XS(XS__respawn) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::respawn(int npc_type_id, int grid_id)"); - - int npc_type_id = (int)SvIV(ST(0)); - int grid_id = (int)SvIV(ST(1)); - +void Perl__respawn(int npc_type_id, int grid_id) +{ quest_manager.respawn(npc_type_id, grid_id); - - XSRETURN_EMPTY; } -//64 bit windows seems to optimize something poorly here causing access violations. -//If you don't do anything with index before passing it to perl it gets optimized out -//Disabling optimization right now for msvc on this function is the best solution. -#ifdef _MSC_VER -#pragma optimize( "", off ) -#endif - -XS(XS__ChooseRandom); -XS(XS__ChooseRandom) { - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: quest::ChooseRandom(option1, option2, option3, option4, option5...[no limit])"); - - dXSTARG; - int index = zone->random.Int(0, items - 1); - SV* RETVAL = ST(index); - - XSprePUSH; - PUSHs(RETVAL); - - XSRETURN(1); //return 1 element from the stack (ST(0)) +perl::scalar Perl__ChooseRandom(perl::array options) +{ + int index = zone->random.Int(0, static_cast(options.size()) - 1); + return options[index]; } -#ifdef _MSC_VER -#pragma optimize( "", on ) -#endif - -XS(XS__set_proximity); -XS(XS__set_proximity) { - dXSARGS; - if (items != 4 && items != 6 && items != 7) - Perl_croak(aTHX_ "Usage: quest::set_proximity(float min_x, float max_x, float min_y, float max_y, [float min_z], [float max_z], [say])"); - - float min_x = (float) SvNV(ST(0)); - float max_x = (float) SvNV(ST(1)); - float min_y = (float) SvNV(ST(2)); - float max_y = (float) SvNV(ST(3)); - - if (items == 4) - quest_manager.set_proximity(min_x, max_x, min_y, max_y); - else { - float min_z = (float) SvNV(ST(4)); - float max_z = (float) SvNV(ST(5)); - bool bSay = false; - if (items == 7) - bSay = (bool) SvTRUE(ST(6)); - quest_manager.set_proximity(min_x, max_x, min_y, max_y, min_z, max_z, bSay); - } - - XSRETURN_EMPTY; +void Perl__set_proximity(float min_x, float max_x, float min_y, float max_y) +{ + quest_manager.set_proximity(min_x, max_x, min_y, max_y); } -XS(XS__clear_proximity); -XS(XS__clear_proximity) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::clear_proximity()"); +void Perl__set_proximity(float min_x, float max_x, float min_y, float max_y, float min_z, float max_z) +{ + quest_manager.set_proximity(min_x, max_x, min_y, max_y, min_z, max_z); +} +void Perl__set_proximity(float min_x, float max_x, float min_y, float max_y, float min_z, float max_z, bool enable_say) +{ + quest_manager.set_proximity(min_x, max_x, min_y, max_y, min_z, max_z, enable_say); +} + +void Perl__clear_proximity() +{ quest_manager.clear_proximity(); - - XSRETURN_EMPTY; } -XS(XS__enable_proximity_say); -XS(XS__enable_proximity_say) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::enable_proximity_say()"); - +void Perl__enable_proximity_say() +{ quest_manager.enable_proximity_say(); - - XSRETURN_EMPTY; } -XS(XS__disable_proximity_say); -XS(XS__disable_proximity_say) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::disable_proximity_say()"); - +void Perl__disable_proximity_say() +{ quest_manager.disable_proximity_say(); - - XSRETURN_EMPTY; } -XS(XS__setanim); -XS(XS__setanim) //Cisyouc: mob->setappearance() addition +void Perl__setanim(int npc_type_id, int appearance_number) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::setanim(int npc_type_id, int appearance_number[0-4]);"); - - quest_manager.setanim(SvUV(ST(0)), SvUV(ST(1))); - - XSRETURN_EMPTY; + quest_manager.setanim(npc_type_id, appearance_number); } -XS(XS__showgrid); -XS(XS__showgrid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::showgrid(int grid_id);"); - - quest_manager.showgrid(SvUV(ST(0))); - - XSRETURN_EMPTY; +void Perl__showgrid(int grid_id) +{ + quest_manager.showgrid(grid_id); } -XS(XS__spawn_condition); -XS(XS__spawn_condition) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: quest::spawn_condition(string zone_short, [int instance_id], uint16 condition_id, int16 value)"); - - if (items == 3) { - char *zone_short = (char *) SvPV_nolen(ST(0)); - uint16 condition_id = (int) SvUV(ST(1)); - int16 int_value = (int) SvIV(ST(2)); - - quest_manager.spawn_condition(zone_short, zone->GetInstanceID(), condition_id, int_value); - } else { - char *zone_short = (char *) SvPV_nolen(ST(0)); - uint32 instance_id = (int) SvUV(ST(1)); - uint16 condition_id = (int) SvUV(ST(2)); - int16 int_value = (int) SvIV(ST(3)); - - quest_manager.spawn_condition(zone_short, instance_id, condition_id, int_value); - } - XSRETURN_EMPTY; +void Perl__spawn_condition(const char* zone_short, uint16 condition_id, int16 value) +{ + quest_manager.spawn_condition(zone_short, zone->GetInstanceID(), condition_id, value); } -XS(XS__get_spawn_condition); -XS(XS__get_spawn_condition) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::get_spawn_condition(string zone_short, [int instance_id], int condition_id)"); - - if (items == 2) { - int16 RETVAL; - dXSTARG; - - char *zone_short = (char *) SvPV_nolen(ST(0)); - uint16 cond_id = (int) SvIV(ST(1)); - - RETVAL = quest_manager.get_spawn_condition(zone_short, zone->GetInstanceID(), cond_id); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); - } else { - int16 RETVAL; - dXSTARG; - - char *zone_short = (char *) SvPV_nolen(ST(0)); - uint16 instance_id = (int) SvIV(ST(1)); - uint16 cond_id = (int) SvIV(ST(2)); - - RETVAL = quest_manager.get_spawn_condition(zone_short, instance_id, cond_id); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); - } +void Perl__spawn_condition(const char* zone_short, uint32_t instance_id, uint16 condition_id, int16 value) +{ + quest_manager.spawn_condition(zone_short, instance_id, condition_id, value); } -XS(XS__toggle_spawn_event); -XS(XS__toggle_spawn_event) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: quest::toggle_spawn_event(uint32 event_id, [bool is_enabled = false], [bool is_strict = false], [bool reset_base = false])"); +int Perl__get_spawn_condition(const char* zone_short, uint16 condition_id) +{ + return quest_manager.get_spawn_condition(zone_short, zone->GetInstanceID(), condition_id); +} - uint32 event_id = (int) SvIV(ST(0)); - bool is_enabled = ((int) SvIV(ST(1))) == 0 ? false : true; - bool is_strict = ((int) SvIV(ST(2))) == 0 ? false : true; - bool reset_base = ((int) SvIV(ST(3))) == 0 ? false : true; +int Perl__get_spawn_condition(const char* zone_short, uint32 instance_id, uint16 condition_id) +{ + return quest_manager.get_spawn_condition(zone_short, instance_id, condition_id); +} +void Perl__toggle_spawn_event(int event_id, bool is_enabled, bool is_strict, bool reset_base) +{ quest_manager.toggle_spawn_event(event_id, is_enabled, is_strict, reset_base); - - XSRETURN_EMPTY; } -XS(XS__has_zone_flag); -XS(XS__has_zone_flag) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::has_zone_flag(uint32 zone_id)"); - - int16 RETVAL; - dXSTARG; - - uint32 zone_id = (int) SvIV(ST(0)); - - RETVAL = quest_manager.has_zone_flag(zone_id); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); - +bool Perl__has_zone_flag(int zone_id) +{ + return quest_manager.has_zone_flag(zone_id); } -XS(XS__set_zone_flag); -XS(XS__set_zone_flag) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::set_zone_flag(uint32 zone_id)"); - - uint32 zone_id = (int) SvIV(ST(0)); - +void Perl__set_zone_flag(int zone_id) +{ quest_manager.set_zone_flag(zone_id); - - XSRETURN_EMPTY; } -XS(XS__clear_zone_flag); -XS(XS__clear_zone_flag) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::clear_zone_flag(uint32 zone_id)"); - - uint32 zone_id = (int) SvIV(ST(0)); - +void Perl__clear_zone_flag(int zone_id) +{ quest_manager.clear_zone_flag(zone_id); - - XSRETURN_EMPTY; } -XS(XS__summonburiedplayercorpse); -XS(XS__summonburiedplayercorpse) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: quest::summonburiedplayercorpse(uint32 char_id, float dest_x, float dest_y, float dest_z, float dest_heading)"); - - bool RETVAL; - uint32 char_id = (int) SvIV(ST(0)); - auto position = glm::vec4((float) SvIV(ST(1)), (float) SvIV(ST(2)), (float) SvIV(ST(3)), (float) SvIV(ST(4))); - - RETVAL = quest_manager.summonburiedplayercorpse(char_id, position); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__summonburiedplayercorpse(uint32 char_id, float dest_x, float dest_y, float dest_z, float dest_heading) +{ + auto position = glm::vec4(dest_x, dest_y, dest_z, dest_heading); + return quest_manager.summonburiedplayercorpse(char_id, position); } -XS(XS__summonallplayercorpses); -XS(XS__summonallplayercorpses) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: quest::summonallplayercorpses(int char_id, float dest_x, float dest_y, float dest_z, float dest_heading)"); - - bool RETVAL; - uint32 char_id = (int) SvIV(ST(0)); - auto position = glm::vec4((float) SvIV(ST(1)), (float) SvIV(ST(2)), (float) SvIV(ST(3)), (float) SvIV(ST(4))); - - RETVAL = quest_manager.summonallplayercorpses(char_id, position); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__summonallplayercorpses(uint32 char_id, float dest_x, float dest_y, float dest_z, float dest_heading) +{ + auto position = glm::vec4(dest_x, dest_y, dest_z, dest_heading); + return quest_manager.summonallplayercorpses(char_id, position); } -XS(XS__getplayercorpsecount); -XS(XS__getplayercorpsecount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getplayercorpsecount(uint32 char_id)"); - - uint32 RETVAL; - dXSTARG; - - uint32 char_id = (int) SvIV(ST(0)); - - RETVAL = quest_manager.getplayercorpsecount(char_id); - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +int Perl__getplayercorpsecount(uint32 char_id) +{ + return quest_manager.getplayercorpsecount(char_id); } -XS(XS__getplayercorpsecountbyzoneid); -XS(XS__getplayercorpsecountbyzoneid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::getplayercorpsecountbyzoneid(uint32 char_id, uint32 zone_id)"); - - uint32 RETVAL; - dXSTARG; - - uint32 char_id = (int) SvIV(ST(0)); - uint32 zone_id = (int)SvIV(ST(1)); - - RETVAL = quest_manager.getplayercorpsecountbyzoneid(char_id, zone_id); - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +int Perl__getplayercorpsecountbyzoneid(uint32 char_id, uint32 zone_id) +{ + return quest_manager.getplayercorpsecountbyzoneid(char_id, zone_id); } -XS(XS__getplayerburiedcorpsecount); -XS(XS__getplayerburiedcorpsecount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getplayerburiedcorpsecount(int character_id)"); - - uint32 RETVAL; - dXSTARG; - - uint32 char_id = (int) SvIV(ST(0)); - - RETVAL = quest_manager.getplayerburiedcorpsecount(char_id); - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +int Perl__getplayerburiedcorpsecount(uint32 char_id) +{ + return quest_manager.getplayerburiedcorpsecount(char_id); } -XS(XS__buryplayercorpse); -XS(XS__buryplayercorpse) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::buryplayercorpse(int character_id)"); - - uint32 RETVAL; - dXSTARG; - - uint32 char_id = (int) SvIV(ST(0)); - - RETVAL = quest_manager.buryplayercorpse(char_id); - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); +bool Perl__buryplayercorpse(uint32 char_id) +{ + return quest_manager.buryplayercorpse(char_id); } -XS(XS__forcedooropen); -XS(XS__forcedooropen) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: quest::forcedooropen(int door_id, [int alt_mode=0])"); - - if (items == 1) { - uint32 door_id = (int) SvIV(ST(0)); - - quest_manager.forcedooropen(door_id, false); - - XSRETURN_EMPTY; - } else { - uint32 door_id = (int) SvIV(ST(0)); - bool alt_mode = (int) SvIV(ST(1)) == 0 ? false : true; - - quest_manager.forcedooropen(door_id, alt_mode); - - XSRETURN_EMPTY; - } +void Perl__forcedooropen(uint32 door_id) +{ + quest_manager.forcedooropen(door_id, false); } -XS(XS__forcedoorclose); -XS(XS__forcedoorclose) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: quest::forcedoorclose(int door_id, [bool alt_mode = 0])"); - - if (items == 1) { - uint32 door_id = (int) SvIV(ST(0)); - - quest_manager.forcedoorclose(door_id, false); - - XSRETURN_EMPTY; - } else { - uint32 door_id = (int) SvIV(ST(0)); - bool alt_mode = (int) SvIV(ST(1)) == 0 ? false : true; - - quest_manager.forcedoorclose(door_id, alt_mode); - - XSRETURN_EMPTY; - } +void Perl__forcedooropen(uint32 door_id, bool alt_mode) +{ + quest_manager.forcedooropen(door_id, alt_mode); } -XS(XS__toggledoorstate); -XS(XS__toggledoorstate) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::toggledoorstate(int door_id)"); +void Perl__forcedoorclose(uint32 door_id) +{ + quest_manager.forcedoorclose(door_id, false); +} - uint32 door_id = (int) SvIV(ST(0)); +void Perl__forcedoorclose(uint32 door_id, bool alt_mode) +{ + quest_manager.forcedoorclose(door_id, alt_mode); +} +void Perl__toggledoorstate(uint32 door_id) +{ quest_manager.toggledoorstate(door_id); - - XSRETURN_EMPTY; } -XS(XS__isdooropen); -XS(XS__isdooropen) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::isdooropen(int door_id)"); - - bool RETVAL; - dXSTARG; - - uint32 door_id = (int) SvIV(ST(0)); - - RETVAL = quest_manager.isdooropen(door_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__isdooropen(uint32 door_id) +{ + return quest_manager.isdooropen(door_id); } -XS(XS__depopzone); -XS(XS__depopzone) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::depopzone([bool start_spawn_status = false])"); - - bool StartSpawnStatus = ((int) SvIV(ST(0))) == 0 ? false : true; - - quest_manager.depopzone(StartSpawnStatus); - - XSRETURN_EMPTY; +void Perl__depopzone(bool start_spawn_status) +{ + quest_manager.depopzone(start_spawn_status); } -XS(XS__repopzone); -XS(XS__repopzone) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::repopzone()"); - +void Perl__repopzone() +{ quest_manager.repopzone(); - - XSRETURN_EMPTY; } -XS(XS__processmobswhilezoneempty); -XS(XS__processmobswhilezoneempty) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::processmobswhilezoneempty(bool on)"); - - bool ProcessingOn = ((int) SvIV(ST(0))) == 0 ? false : true; - - quest_manager.processmobswhilezoneempty(ProcessingOn); - - XSRETURN_EMPTY; +void Perl__processmobswhilezoneempty(bool on) +{ + quest_manager.processmobswhilezoneempty(on); } -XS(XS__npcrace); -XS(XS__npcrace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::npcrace(int race_id)"); - - int race_id = (int) SvIV(ST(0)); - +void Perl__npcrace(int race_id) +{ quest_manager.npcrace(race_id); - - XSRETURN_EMPTY; } -XS(XS__npcgender); -XS(XS__npcgender) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::npcgender(int gender_id)"); - - int gender_id = (int) SvIV(ST(0)); - +void Perl__npcgender(int gender_id) +{ quest_manager.npcgender(gender_id); - - XSRETURN_EMPTY; } -XS(XS__npcsize); -XS(XS__npcsize) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::npcsize(int size)"); - - int size = (int) SvIV(ST(0)); - +void Perl__npcsize(int size) +{ quest_manager.npcsize(size); - - XSRETURN_EMPTY; } -XS(XS__npctexture); -XS(XS__npctexture) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::npctexture(int texture_id)"); - - int texture_id = (int) SvIV(ST(0)); - +void Perl__npctexture(int texture_id) +{ quest_manager.npctexture(texture_id); - - XSRETURN_EMPTY; } -XS(XS__playerrace); -XS(XS__playerrace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::playerrace(int race_id)"); - - int race_id = (int) SvIV(ST(0)); - +void Perl__playerrace(int race_id) +{ quest_manager.playerrace(race_id); - - XSRETURN_EMPTY; } -XS(XS__playergender); -XS(XS__playergender) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::playergender(int gender_id)"); - - int gender_id = (int) SvIV(ST(0)); - +void Perl__playergender(int gender_id) +{ quest_manager.playergender(gender_id); - - XSRETURN_EMPTY; } -XS(XS__playersize); -XS(XS__playersize) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::playersize(int newsize)"); - - int newsize = (int) SvIV(ST(0)); - +void Perl__playersize(int newsize) +{ quest_manager.playersize(newsize); - - XSRETURN_EMPTY; } -XS(XS__playertexture); -XS(XS__playertexture) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::playertexture(int texture_id)"); - - int texture_id = (int) SvIV(ST(0)); - +void Perl__playertexture(int texture_id) +{ quest_manager.playertexture(texture_id); - - XSRETURN_EMPTY; } -XS(XS__playerfeature); -XS(XS__playerfeature) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::playerfeature(string feature [race|gender|texture|helm|haircolor|beardcolor|eyecolor1|eyecolor2|hair|face|beard|heritage|tatoo|details|size], int setting)"); - - char *str_value = (char *) SvPV_nolen(ST(0)); - int int_value = (int) SvIV(ST(1)); - - quest_manager.playerfeature(str_value, int_value); - - XSRETURN_EMPTY; -} - -XS(XS__npcfeature); -XS(XS__npcfeature) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::npcfeature(string feature [race|gender|texture|helm|haircolor|beardcolor|eyecolor1|eyecolor2|hair|face|beard|heritage|tatoo|details|size], int value)"); - - char *str_value = (char *) SvPV_nolen(ST(0)); - int int_value = (int) SvIV(ST(1)); - - quest_manager.npcfeature(str_value, int_value); - - XSRETURN_EMPTY; -} - -#ifdef BOTS - -XS(XS__createbotcount); -XS(XS__createbotcount) +void Perl__playerfeature(char* feature, int value) { - dXSARGS; - int RETVAL; - dXSTARG; - - RETVAL = quest_manager.createbotcount(); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); + quest_manager.playerfeature(feature, value); } -XS(XS__spawnbotcount); -XS(XS__spawnbotcount) +void Perl__npcfeature(char* feature, int value) { - dXSARGS; - int RETVAL; - dXSTARG; - - RETVAL = quest_manager.spawnbotcount(); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); + quest_manager.npcfeature(feature, value); } -XS(XS__botquest); -XS(XS__botquest) +int Perl__createbotcount() { - dXSARGS; - bool RETVAL; - dXSTARG; - - RETVAL = quest_manager.botquest(); - XSprePUSH; - PUSHi((IV) RETVAL); - XSRETURN(1); + return quest_manager.createbotcount(); } -XS(XS__createBot); -XS(XS__createBot) +int Perl__createbotcount(uint8 class_id) { - dXSARGS; - bool RETVAL; - dXSTARG; + return quest_manager.createbotcount(class_id); +} - if(items != 6) +int Perl__spawnbotcount() +{ + return quest_manager.spawnbotcount(); +} + +int Perl__spawnbotcount(uint8 class_id) +{ + return quest_manager.spawnbotcount(class_id); +} + +bool Perl__botquest() +{ + return quest_manager.botquest(); +} + +bool Perl__createBot(const char* firstname, const char* lastname, int level, int race_id, int class_id, int gender_id) +{ + return quest_manager.createBot(firstname, lastname, level, race_id, class_id, gender_id); +} + +void Perl__taskselector(perl::array task_ids) +{ + if (task_ids.size() > MAXCHOOSERENTRIES) { - Perl_croak(aTHX_ "Usage: quest::createBot(string first_name, string last_name, int level, int race_id, int class_id, int gender_id)"); + throw std::runtime_error(fmt::format("Exceeded max number of task offers [{}]", MAXCHOOSERENTRIES)); } - char *firstname = (char *)SvPV_nolen(ST(0)); - char *lastname = (char *)SvPV_nolen(ST(1)); - int level = (int) SvIV(ST(2)); - int race_id = (int) SvIV(ST(3)); - int class_id = (int) SvIV(ST(4)); - int gender_id = (int) SvIV(ST(5)); - - RETVAL = quest_manager.createBot(firstname, lastname, level, race_id, class_id, gender_id); - XSprePUSH; - PUSHi((IV) RETVAL); - XSRETURN(1); + std::vector tasks; + for (int i = 0; i < task_ids.size(); ++i) + { + tasks.push_back(task_ids[i]); + } + quest_manager.taskselector(tasks); } -#endif //BOTS +void Perl__taskselector_nocooldown(perl::array task_ids) +{ + std::vector tasks; + for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i) + { + tasks.push_back(task_ids[i]); + } + quest_manager.taskselector(tasks, true); +} -XS(XS__taskselector); -XS(XS__taskselector) { - dXSARGS; - if ((items >= 1) && (items <= MAXCHOOSERENTRIES)) { - int tasks[MAXCHOOSERENTRIES]; - for (int i = 0; i < items; i++) { - tasks[i] = (int) SvIV(ST(i)); - } - quest_manager.taskselector(items, tasks); - } else { - Perl_croak(aTHX_ "Usage: quest::taskselector(int task_id, 2, 3, 4, 5 [up to 40])"); +void Perl__task_setselector(int task_set_id) +{ + quest_manager.tasksetselector(task_set_id); +} + +void Perl__task_setselector(int task_set_id, bool ignore_cooldown) +{ + quest_manager.tasksetselector(task_set_id, ignore_cooldown); +} + +void Perl__enabletask(perl::array task_ids) +{ + int count = 0; + int tasks[MAXCHOOSERENTRIES]; + for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i) + { + tasks[i] = task_ids[i]; + ++count; } - XSRETURN_EMPTY; + quest_manager.enabletask(count, tasks); } -XS(XS__task_setselector); -XS(XS__task_setselector) { - dXSARGS; - if (items == 1) { - int task_setid = (int) SvIV(ST(0)); - quest_manager.tasksetselector(task_setid); - } else { - Perl_croak(aTHX_ "Usage: quest::task_setselector(int task_set_id)"); + +void Perl__disabletask(perl::array task_ids) +{ + int count = 0; + int tasks[MAXCHOOSERENTRIES]; + for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i) + { + tasks[i] = task_ids[i]; + ++count; } - XSRETURN_EMPTY; -} -XS(XS__enabletask); -XS(XS__enabletask) { - dXSARGS; - if ((items >= 1) && (items <= 10)) { - int tasks[10]; - for (int i = 0; i < items; i++) { - tasks[i] = (int) SvIV(ST(i)); - } - quest_manager.enabletask(items, tasks); - } else { - Perl_croak(aTHX_ "Usage: quest::enabletask(int task_id, 2, 3, [up to 10])"); - } - - XSRETURN_EMPTY; -} -XS(XS__disabletask); -XS(XS__disabletask) { - dXSARGS; - if ((items >= 1) && (items <= 10)) { - int tasks[10]; - for (int i = 0; i < items; i++) { - tasks[i] = (int) SvIV(ST(i)); - } - quest_manager.disabletask(items, tasks); - } else { - Perl_croak(aTHX_ "Usage: quest::disabletask(int task_id, 2, 3, [up to 10])"); - } - - XSRETURN_EMPTY; + quest_manager.disabletask(count, tasks); } -XS(XS__istaskenabled); -XS(XS__istaskenabled) { - dXSARGS; - bool RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_id = (int) SvIV(ST(0)); - RETVAL = quest_manager.istaskenabled(task_id); - } else { - Perl_croak(aTHX_ "Usage: quest::istaskenabled(int task_id)"); - } - - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__istaskenabled(int task_id) +{ + return quest_manager.istaskenabled(task_id); } -XS(XS__istaskactive); -XS(XS__istaskactive) { - dXSARGS; - bool RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_id = (int) SvIV(ST(0)); - RETVAL = quest_manager.istaskactive(task_id); - } else { - Perl_croak(aTHX_ "Usage: quest::istaskactive(int task_id)"); - } - - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__istaskactive(int task_id) +{ + return quest_manager.istaskactive(task_id); } -XS(XS__istaskactivityactive); -XS(XS__istaskactivityactive) { - dXSARGS; - bool RETVAL; - dXSTARG; - - if (items == 2) { - unsigned int task_id = (int) SvIV(ST(0)); - unsigned int activity_id = (int) SvIV(ST(1)); - RETVAL = quest_manager.istaskactivityactive(task_id, activity_id); - } else { - Perl_croak(aTHX_ "Usage: quest::istaskactivityactive(int task_id, int activity_id)"); - } - - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__istaskactivityactive(int task_id, int activity_id) +{ + return quest_manager.istaskactivityactive(task_id, activity_id); } -XS(XS__gettaskactivitydonecount); -XS(XS__gettaskactivitydonecount) { - dXSARGS; - uint32 RETVAL; - dXSTARG; - - if (items == 2) { - unsigned int task_id = (int) SvIV(ST(0)); - unsigned int activity_id = (int) SvIV(ST(1)); - RETVAL = quest_manager.gettaskactivitydonecount(task_id, activity_id); - XSprePUSH; - PUSHu((UV) RETVAL); - } else { - Perl_croak(aTHX_ "Usage: quest::gettaskactivitydonecount(int task_id, int activity_id)"); - } - - XSRETURN(1); +int Perl__gettaskactivitydonecount(int task_id, int activity_id) +{ + return quest_manager.gettaskactivitydonecount(task_id, activity_id); } -XS(XS__updatetaskactivity); -XS(XS__updatetaskactivity) { - dXSARGS; - unsigned int task_id, activity_id; - int count = 1; - bool ignore_quest_update = false; - if (items == 2) { - task_id = (int) SvIV(ST(0)); - activity_id = (int) SvIV(ST(1)); - quest_manager.updatetaskactivity(task_id, activity_id, count, false); - } else if (items == 3 || items == 4) { - task_id = (int) SvIV(ST(0)); - activity_id = (int) SvIV(ST(1)); - count = (int) SvIV(ST(2)); - if (items == 4) { - bool ignore_quest_update = (bool) SvTRUE(ST(3)); - } - quest_manager.updatetaskactivity(task_id, activity_id, count, ignore_quest_update); - } else { - Perl_croak(aTHX_ "Usage: quest::updatetaskactivity(int task_id, int activity_id, [int count], [bool ignore_quest_update = false])"); - } - - XSRETURN_EMPTY; +void Perl__updatetaskactivity(int task_id, int activity_id) +{ + quest_manager.updatetaskactivity(task_id, activity_id, 1); } -XS(XS__resettaskactivity); -XS(XS__resettaskactivity) { - dXSARGS; - if (items == 2) { - int task_id = (int) SvIV(ST(0)); - int activity_id = (int) SvIV(ST(1)); - - quest_manager.resettaskactivity(task_id, activity_id); - - } else { - Perl_croak(aTHX_ "Usage: quest::resettaskactivity(int task_id, int activity_id)"); - } - - XSRETURN_EMPTY; +void Perl__updatetaskactivity(int task_id, int activity_id, int count) +{ + quest_manager.updatetaskactivity(task_id, activity_id, count); } -XS(XS__taskexploredarea); -XS(XS__taskexploredarea) { - dXSARGS; - unsigned int explore_id; - if (items == 1) { - explore_id = (int) SvIV(ST(0)); - quest_manager.taskexploredarea(explore_id); - } else { - Perl_croak(aTHX_ "Usage: quest::taskexplorearea(int explore_id)"); - } - - XSRETURN_EMPTY; +void Perl__updatetaskactivity(int task_id, int activity_id, int count, bool ignore_quest_update) +{ + quest_manager.updatetaskactivity(task_id, activity_id, count, ignore_quest_update); } -XS(XS__assigntask); -XS(XS__assigntask) { - dXSARGS; - unsigned int task_id; - bool enforce_level_requirement = false; - if (items == 1 || items == 2) { - task_id = (int) SvIV(ST(0)); - if (items == 2) { - if ((int) SvIV(ST(1)) == 1) { - enforce_level_requirement = true; - } - } - quest_manager.assigntask(task_id, enforce_level_requirement); - } else { - Perl_croak(aTHX_ "Usage: quest::assigntask(int task_id, [bool enforce_level_requirement = false])"); - } - - XSRETURN_EMPTY; +void Perl__resettaskactivity(int task_id, int activity_id) +{ + quest_manager.resettaskactivity(task_id, activity_id); } -XS(XS__failtask); -XS(XS__failtask) { - dXSARGS; - unsigned int task_id; - if (items == 1) { - task_id = (int) SvIV(ST(0)); - quest_manager.failtask(task_id); - } else { - Perl_croak(aTHX_ "Usage: quest::failtask(int task_id)"); - } - - XSRETURN_EMPTY; +void Perl__assigntask(int task_id) +{ + quest_manager.assigntask(task_id); } -XS(XS__tasktimeleft); -XS(XS__tasktimeleft) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_id = (int) SvIV(ST(0)); - RETVAL = quest_manager.tasktimeleft(task_id); - } else { - Perl_croak(aTHX_ "Usage: quest::tasktimeleft(int task_id)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +void Perl__assigntask(int task_id, bool enforce_level_requirement) +{ + quest_manager.assigntask(task_id, enforce_level_requirement); } -XS(XS__istaskcompleted); -XS(XS__istaskcompleted) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_id = (int) SvIV(ST(0)); - RETVAL = quest_manager.istaskcompleted(task_id); - } else { - Perl_croak(aTHX_ "Usage: quest::istaskcompleted(int task_id)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +void Perl__failtask(int task_id) +{ + quest_manager.failtask(task_id); } -XS(XS__enabledtaskcount); -XS(XS__enabledtaskcount) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_set = (int) SvIV(ST(0)); - RETVAL = quest_manager.enabledtaskcount(task_set); - } else { - Perl_croak(aTHX_ "Usage: quest::enabledtaskcount(int task_set)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__tasktimeleft(int task_id) +{ + return quest_manager.tasktimeleft(task_id); } -XS(XS__firsttaskinset); -XS(XS__firsttaskinset) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_set = (int) SvIV(ST(0)); - RETVAL = quest_manager.firsttaskinset(task_set); - } else { - Perl_croak(aTHX_ "Usage: quest::firsttaskinset(int task_set)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__istaskcompleted(int task_id) +{ + return quest_manager.istaskcompleted(task_id); } -XS(XS__lasttaskinset); -XS(XS__lasttaskinset) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_set = (int) SvIV(ST(0)); - RETVAL = quest_manager.lasttaskinset(task_set); - } else { - Perl_croak(aTHX_ "Usage: quest::lasttaskinset(int task_set)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__enabledtaskcount(int task_set) +{ + return quest_manager.enabledtaskcount(task_set); } -XS(XS__nexttaskinset); -XS(XS__nexttaskinset) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 2) { - unsigned int task_set = (int) SvIV(ST(0)); - unsigned int task_id = (int) SvIV(ST(1)); - RETVAL = quest_manager.nexttaskinset(task_set, task_id); - } else { - Perl_croak(aTHX_ "Usage: quest::nexttaskinset(int task_set, int task_id)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); -} -XS(XS__activespeaktask); -XS(XS__activespeaktask) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 0) { - RETVAL = quest_manager.activespeaktask(); - } else { - Perl_croak(aTHX_ "Usage: quest::activespeaktask()"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__firsttaskinset(int task_set) +{ + return quest_manager.firsttaskinset(task_set); } -XS(XS__activespeakactivity); -XS(XS__activespeakactivity) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_id = (int) SvIV(ST(0)); - RETVAL = quest_manager.activespeakactivity(task_id); - } else { - Perl_croak(aTHX_ "Usage: quest::activespeakactivity(int task_id)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__lasttaskinset(int task_set) +{ + return quest_manager.lasttaskinset(task_set); } -XS(XS__activetasksinset); -XS(XS__activetasksinset) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_set = (int) SvIV(ST(0)); - RETVAL = quest_manager.activetasksinset(task_set); - } else { - Perl_croak(aTHX_ "Usage: quest::activetasksinset(int task_set)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__nexttaskinset(int task_set, int task_id) +{ + return quest_manager.nexttaskinset(task_set, task_id); } -XS(XS__completedtasksinset); -XS(XS__completedtasksinset) { - dXSARGS; - int RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task_set = (int) SvIV(ST(0)); - RETVAL = quest_manager.completedtasksinset(task_set); - } else { - Perl_croak(aTHX_ "Usage: quest::completedtasksinset(int task_set)"); - } - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__activespeaktask() +{ + return quest_manager.activespeaktask(); } - -XS(XS__istaskappropriate); -XS(XS__istaskappropriate) { - dXSARGS; - bool RETVAL; - dXSTARG; - - if (items == 1) { - unsigned int task = (int) SvIV(ST(0)); - RETVAL = quest_manager.istaskappropriate(task); - } else { - Perl_croak(aTHX_ "Usage: quest::istaskaappropriate(int task_id)"); - } - - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); +int Perl__activespeakactivity(int task_id) +{ + return quest_manager.activespeakactivity(task_id); } -XS(XS__gettaskname); -XS(XS__gettaskname) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::gettaskname(uint32 task_id)"); - } - - dXSTARG; - uint32 task_id = (int) SvIV(ST(0)); - std::string task_name = quest_manager.gettaskname(task_id); - - sv_setpv(TARG, task_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +int Perl__activetasksinset(int task_set) +{ + return quest_manager.activetasksinset(task_set); } -XS(XS__popup); // prototype to pass -Wmissing-prototypes -XS(XS__popup) { - dXSARGS; - int popup_id = 0; - int buttons = 0; - int duration = 0; - - if ((items < 2) || (items > 5)) - Perl_croak(aTHX_ "Usage: quest::popup(string window_title, string message, int popup_id, int buttons, int duration)"); - - if (items >= 3) - popup_id = (int) SvIV(ST(2)); - - if (items >= 4) - buttons = (int) SvIV(ST(3)); - - if (items == 5) - duration = (int) SvIV(ST(4)); - - quest_manager.popup(SvPV_nolen(ST(0)), SvPV_nolen(ST(1)), popup_id, buttons, duration); - - XSRETURN_EMPTY; +int Perl__completedtasksinset(int task_set) +{ + return quest_manager.completedtasksinset(task_set); } -XS(XS__clearspawntimers); -XS(XS__clearspawntimers) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::clearspawntimers()"); +bool Perl__istaskappropriate(int task_id) +{ + return quest_manager.istaskappropriate(task_id); +} +std::string Perl__gettaskname(uint32 task_id) +{ + return quest_manager.gettaskname(task_id); +} + +int Perl__get_dz_task_id() +{ + return quest_manager.GetCurrentDzTaskID(); +} + +void Perl__end_dz_task() +{ + quest_manager.EndCurrentDzTask(); +} + +void Perl__end_dz_task(bool send_fail) +{ + quest_manager.EndCurrentDzTask(send_fail); +} + +void Perl__popup(const char* window_title, const char* message) +{ + quest_manager.popup(window_title, message, 0, 0, 0); +} + +void Perl__popup(const char* window_title, const char* message, int popup_id) +{ + quest_manager.popup(window_title, message, popup_id, 0, 0); +} + +void Perl__popup(const char* window_title, const char* message, int popup_id, int buttons) +{ + quest_manager.popup(window_title, message, popup_id, buttons, 0); +} + +void Perl__popup(const char* window_title, const char* message, int popup_id, int buttons, int duration) +{ + quest_manager.popup(window_title, message, popup_id, buttons, duration); +} + +void Perl__clearspawntimers() +{ quest_manager.clearspawntimers(); - - XSRETURN_EMPTY; } -XS(XS__ze); -XS(XS__ze) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::ze(int emote_color_id, string message)"); - - int channel_id = (int) SvIV(ST(0)); - char *message = (char *) SvPV_nolen(ST(1)); - - quest_manager.ze(channel_id, message); - - XSRETURN_EMPTY; +void Perl__ze(int emote_color_id, const char* message) +{ + return quest_manager.ze(emote_color_id, message); } -XS(XS__we); -XS(XS__we) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::we(int emote_color_id, string message)"); - - int channel_id = (int) SvIV(ST(0)); - char *message = (char *) SvPV_nolen(ST(1)); - - quest_manager.we(channel_id, message); - - XSRETURN_EMPTY; +void Perl__we(int emote_color_id, const char* message) +{ + quest_manager.we(emote_color_id, message); } -XS(XS__message); -XS(XS__message) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::message(int color, string message)"); - - int color = (int) SvIV(ST(0)); - char *message = (char *) SvPV_nolen(ST(1)); +void Perl__message(int color, const char* message) +{ quest_manager.message(color, message); - XSRETURN_EMPTY; } -XS(XS__whisper); -XS(XS__whisper) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::whisper(string message)"); - - char *message = (char *) SvPV_nolen(ST(0)); +void Perl__whisper(const char* message) +{ quest_manager.whisper(message); - XSRETURN_EMPTY; } -XS(XS__getlevel); -XS(XS__getlevel) { - dXSARGS; - if (items > 1) - Perl_croak(aTHX_ "Usage: quest::getlevel(int type)"); - - int RETVAL; - dXSTARG; - - int type; - if (items == 1) - type = (int) SvIV(ST(0)); - else - type = 0; - - RETVAL = quest_manager.getlevel(type); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); +int Perl__getlevel(uint8 type) +{ + return quest_manager.getlevel(type); } -XS(XS__CreateGroundObject); -XS(XS__CreateGroundObject) { - dXSARGS; - if (items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: quest::creategroundobject(int item_id, float x, float y, float z, float heading, [uint32 decay_time-ms = 300000])"); +uint16 Perl__CreateGroundObject(uint32_t item_id, float x, float y, float z, float heading) +{ + return quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, heading)); +} - int item_id = (int) SvIV(ST(0)); - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float heading = (float) SvNV(ST(4)); - uint16 id = 0; +uint16 Perl__CreateGroundObject(uint32_t item_id, float x, float y, float z, float heading, uint32_t decay_time_ms) +{ + return quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, heading), decay_time_ms); +} - if (items == 5) - id = quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, heading)); - else { - uint32 decay_time = (uint32) SvIV(ST(5)); - id = quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, heading), decay_time); +uint16 Perl__CreateGroundObjectFromModel(const char* modelname, float x, float y, float z, float heading) +{ + return quest_manager.CreateGroundObjectFromModel(modelname, glm::vec4(x, y, z, heading)); +} + +uint16 Perl__CreateGroundObjectFromModel(const char* modelname, float x, float y, float z, float heading, uint8_t object_type) +{ + return quest_manager.CreateGroundObjectFromModel(modelname, glm::vec4(x, y, z, heading), object_type); +} + +uint16 Perl__CreateGroundObjectFromModel(const char* modelname, float x, float y, float z, float heading, uint8_t object_type, uint32_t decay_time_ms) +{ + return quest_manager.CreateGroundObjectFromModel(modelname, glm::vec4(x, y, z, heading), object_type, decay_time_ms); +} + +uint16 Perl__CreateDoor(const char* modelname, float x, float y, float z, float heading) +{ + return quest_manager.CreateDoor(modelname, x, y, z, heading, 58, 100); +} + +uint16 Perl__CreateDoor(const char* modelname, float x, float y, float z, float heading, uint8_t object_type) +{ + return quest_manager.CreateDoor(modelname, x, y, z, heading, object_type, 100); +} + +uint16 Perl__CreateDoor(const char* modelname, float x, float y, float z, float heading, uint8_t object_type, uint16_t size) +{ + return quest_manager.CreateDoor(modelname, x, y, z, heading, object_type, size); +} + +void Perl__ModifyNPCStat(const char* key, const char* value) +{ + quest_manager.ModifyNPCStat(key, value); +} + +int Perl__collectitems(uint32_t item_id, bool remove_item) +{ + return quest_manager.collectitems(item_id, remove_item); +} + +int Perl__countitem(uint32_t item_id) +{ + return quest_manager.countitem(item_id); +} + +void Perl__removeitem(uint32_t item_id) +{ + quest_manager.removeitem(item_id); +} + +void Perl__removeitem(uint32_t item_id, int quantity) +{ + quest_manager.removeitem(item_id, quantity); +} + +std::string Perl__getitemname(uint32 item_id) +{ + return quest_manager.getitemname(item_id); +} + +std::string Perl__getnpcnamebyid(uint32 npc_id) +{ + return quest_manager.getnpcnamebyid(npc_id); +} + +void Perl__UpdateSpawnTimer(uint32 id, uint32 new_time) +{ + quest_manager.UpdateSpawnTimer(id, new_time); +} + +void Perl__MerchantSetItem(uint32 npc_id, uint32 item_id) +{ + quest_manager.MerchantSetItem(npc_id, item_id); +} + +void Perl__MerchantSetItem(uint32 npc_id, uint32 item_id, uint32 quantity) +{ + quest_manager.MerchantSetItem(npc_id, item_id, quantity); +} + +uint32_t Perl__MerchantCountItem(uint32 npc_id, uint32 item_id) +{ + return quest_manager.MerchantCountItem(npc_id, item_id); +} + +int Perl__CreateInstance(const char* zone_name, int16 version, int32 duration) +{ + return quest_manager.CreateInstance(zone_name, version, duration); +} + +void Perl__DestroyInstance(uint16 id) +{ + quest_manager.DestroyInstance(id); +} + +void Perl__UpdateInstanceTimer(int16 instance_id, uint32 duration) +{ + quest_manager.UpdateInstanceTimer(instance_id, duration); +} + +uint32_t Perl__GetInstanceTimer() +{ + return quest_manager.GetInstanceTimer(); +} + +uint32_t Perl__GetInstanceTimerByID(uint16 instance_id) +{ + return quest_manager.GetInstanceTimerByID(instance_id); +} + +int Perl__GetInstanceID(const char* zone_name, uint16 version) +{ + return quest_manager.GetInstanceID(zone_name, version); +} + +uint8 Perl__GetInstanceVersionByID(uint16 instance_id) +{ + return database.GetInstanceVersion(instance_id); +} + +uint32 Perl__GetInstanceZoneIDByID(uint16 instance_id) +{ + return database.GetInstanceZoneID(instance_id); +} + +perl::array Perl__GetInstanceIDs(std::string zone_name) +{ + perl::array result; + + const auto instance_ids = quest_manager.GetInstanceIDs(zone_name); + for (int i = 0; i < instance_ids.size(); i++) { + result.push_back(instance_ids[i]); } - XSRETURN_IV(id); + return result; } -XS(XS__CreateGroundObjectFromModel); -XS(XS__CreateGroundObjectFromModel) { - dXSARGS; - if (items < 5 || items > 7) - Perl_croak(aTHX_ "Usage: quest::creategroundobjectfrommodel(string model_name, float x, float y, float z, float heading, [int object_type], [uint32 decay_time-ms = 300000])"); - - char *modelname = (char *) SvPV_nolen(ST(0)); - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float heading = (float) SvNV(ST(4)); - uint32 object_type = 0; - uint32 decay_time = 0; - uint16 id = 0; - - if (items > 5) - object_type = (uint32) SvIV(ST(5)); - - if (items > 6) - decay_time = (uint32) SvIV(ST(6)); - - id = quest_manager.CreateGroundObjectFromModel(modelname, glm::vec4(x, y, z, heading), object_type, decay_time); - XSRETURN_IV(id); +int Perl__GetInstanceIDByCharID(const char* zone_name, int16 version, uint32 character_id) +{ + return quest_manager.GetInstanceIDByCharID(zone_name, version, character_id); } -XS(XS__CreateDoor); -XS(XS__CreateDoor) { - dXSARGS; - if (items < 5 || items > 7) - Perl_croak(aTHX_ "Usage: quest::createdoor(string model_name, float x, float y, float z, float heading, [int object_type = 58], [int size = 100])"); +perl::array Perl__GetInstanceIDsByCharID(std::string zone_name, uint32 character_id) +{ + perl::array result; - char *modelname = (char *) SvPV_nolen(ST(0)); - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float heading = (float) SvNV(ST(4)); - uint32 object_type = 58; - uint32 size = 100; - uint16 id = 0; + const auto instance_ids = quest_manager.GetInstanceIDs(zone_name, character_id); + for (int i = 0; i < instance_ids.size(); i++) { + result.push_back(instance_ids[i]); + } - if (items > 5) - object_type = (uint32) SvIV(ST(5)); - - if (items > 6) - size = (uint32) SvIV(ST(6)); - - id = quest_manager.CreateDoor(modelname, x, y, z, heading, object_type, size); - XSRETURN_IV(id); + return result; } -XS(XS__ModifyNPCStat); -XS(XS__ModifyNPCStat) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::modifynpcstat(string key, string value)"); +std::string Perl__GetCharactersInInstance(uint16 instance_id) +{ + std::list character_ids; + std::string char_id_string = "No players in that instance."; - quest_manager.ModifyNPCStat(SvPV_nolen(ST(0)), SvPV_nolen(ST(1))); + database.GetCharactersInInstance(instance_id, character_ids); - XSRETURN_EMPTY; -} - -XS(XS__collectitems); -XS(XS__collectitems) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::collectitems(int item_id, [bool remove_item = true])"); - - uint32 item_id = (int) SvIV(ST(0)); - bool remove_item = ((int) SvIV(ST(1))) == 0 ? false : true; - - int quantity = - quest_manager.collectitems(item_id, remove_item); - - XSRETURN_IV(quantity); -} - -XS(XS__countitem); -XS(XS__countitem) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::countitem(int item_id)"); - - uint32 item_id = (int) SvIV(ST(0)); - - int quantity = quest_manager.countitem(item_id); - - XSRETURN_IV(quantity); -} - -XS(XS__removeitem); -XS(XS__removeitem) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: quest::removeitem(int item_id, [int quantity = 1])"); - - uint32 item_id = (int) SvIV(ST(0)); - uint32 quantity = 1; - if (items > 1) - quantity = (int) SvIV(ST(1)); - - quest_manager.removeitem(item_id, quantity); - - XSRETURN_EMPTY; -} - -XS(XS__getitemname); -XS(XS__getitemname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getitemname(uint32 item_id)"); - - dXSTARG; - uint32 item_id = (int) SvIV(ST(0)); - std::string item_name = quest_manager.getitemname(item_id); - - sv_setpv(TARG, item_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__getnpcnamebyid); -XS(XS__getnpcnamebyid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getnpcnamebyid(uint32 npc_id)"); - - dXSTARG; - uint32 npc_id = (int) SvIV(ST(0)); - auto npc_name = quest_manager.getnpcnamebyid(npc_id); - sv_setpv(TARG, npc_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__UpdateSpawnTimer); -XS(XS__UpdateSpawnTimer) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::updatespawntimer(uint32 spawn2_id, uint32 updated_time_till_repop)"); - - uint32 spawn2_id = (int) SvIV(ST(0)); - uint32 updated_time_till_repop = (int) SvIV(ST(1)); - - quest_manager.UpdateSpawnTimer(spawn2_id, updated_time_till_repop); - - XSRETURN_EMPTY; -} - -XS(XS__MerchantSetItem); -XS(XS__MerchantSetItem) { - dXSARGS; - if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: quest::MerchantSetItem(uint32 npc_id, uint32 item_id, [uint32 quantity])"); - - uint32 npc_id = (int) SvUV(ST(0)); - uint32 item_id = (int) SvUV(ST(1)); - uint32 quantity = 0; - if (items == 3) - quantity = (int) SvUV(ST(2)); - - quest_manager.MerchantSetItem(npc_id, item_id, quantity); - - XSRETURN_EMPTY; -} - -XS(XS__MerchantCountItem); -XS(XS__MerchantCountItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::MerchantCountItem(uint32 npc_id, uint32 item_id)"); - - uint32 npc_id = (int) SvUV(ST(0)); - uint32 item_id = (int) SvUV(ST(1)); - uint32 quantity = quest_manager.MerchantCountItem(npc_id, item_id); - - XSRETURN_UV(quantity); -} - -XS(XS__varlink); -XS(XS__varlink) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::varlink(uint32 item_id)"); - dXSTARG; - - Const_char *RETVAL; - char text[250]; - uint32 item_id; - item_id = (int) SvUV(ST(0)); - - RETVAL = quest_manager.varlink(text, item_id); - - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__CreateInstance); -XS(XS__CreateInstance) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::CreateInstance(string zone_name, uint16 version, uint32 duration)"); - - char *zone = (char *) SvPV_nolen(ST(0)); - uint16 version = (int) SvUV(ST(1)); - uint32 duration = (int) SvUV(ST(2)); - uint32 id = quest_manager.CreateInstance(zone, version, duration); - - XSRETURN_UV(id); -} - -XS(XS__DestroyInstance); -XS(XS__DestroyInstance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::DestroyInstance(int id)"); - - uint16 id = (int) SvUV(ST(0)); - quest_manager.DestroyInstance(id); - - XSRETURN_EMPTY; -} - -XS(XS__UpdateInstanceTimer); -XS(XS__UpdateInstanceTimer) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::UpdateInstanceTimer(int16 instance_id, uint32 duration)"); - - uint16 instance_id = (uint16) SvUV(ST(0)); - uint32 duration = (uint32) SvUV(ST(1)); - quest_manager.UpdateInstanceTimer(instance_id, duration); - - XSRETURN_EMPTY; -} - -XS(XS__GetInstanceTimer); -XS(XS__GetInstanceTimer) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::GetInstanceTimer()"); - - uint32 timer = quest_manager.GetInstanceTimer(); - - XSRETURN_UV(timer); -} - -XS(XS__GetInstanceTimerByID); -XS(XS__GetInstanceTimerByID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetInstanceTimerByID(uint16 instance_id)"); - - uint16 instance_id = (uint16) SvUV(ST(0)); - uint32 timer = quest_manager.GetInstanceTimerByID(instance_id); - - XSRETURN_UV(timer); -} - -XS(XS__GetInstanceID); -XS(XS__GetInstanceID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::GetInstanceID(string zone_name, uint16 version)"); - - char *zone = (char *) SvPV_nolen(ST(0)); - uint16 version = (int) SvUV(ST(1)); - uint16 id = quest_manager.GetInstanceID(zone, version); - - XSRETURN_UV(id); -} - -XS(XS__GetInstanceIDByCharID); -XS(XS__GetInstanceIDByCharID) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::GetInstanceIDByCharID(string zone_name, uint16 version, uint32 char_id)"); - - char *zone = (char *) SvPV_nolen(ST(0)); - uint16 version = (int) SvUV(ST(1)); - uint32 char_id = (int) SvUV(ST(2)); - uint16 id = quest_manager.GetInstanceIDByCharID(zone, version, char_id); - - XSRETURN_UV(id); -} - -XS(XS__GetCharactersInInstance); -XS(XS__GetCharactersInInstance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetCharactersInInstance(uint16 instance_id)"); - dXSTARG; - - Const_char *RETVAL; - uint16 instance_id = (int) SvUV(ST(0)); - std::list char_id_list; - std::string char_id_string; - - database.GetCharactersInInstance(instance_id, char_id_list); - - if (char_id_list.size() > 0) { - char_id_string = itoa(char_id_list.size()); - char_id_string += " player(s) in instance: "; - auto iter = char_id_list.begin(); - while (iter != char_id_list.end()) { + if (character_ids.size() > 0) + { + char_id_string = fmt::format("{} player(s) in instance: ", character_ids.size()); + auto iter = character_ids.begin(); + while (iter != character_ids.end()) { char char_name[64]; database.GetCharName(*iter, char_name); char_id_string += char_name; @@ -3274,5600 +1527,3152 @@ XS(XS__GetCharactersInInstance) { char_id_string += itoa(*iter); char_id_string += ")"; ++iter; - if (iter != char_id_list.end()) + if (iter != character_ids.end()) char_id_string += ", "; } - RETVAL = char_id_string.c_str(); - } else - RETVAL = "No players in that instance."; - - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__AssignToInstance); -XS(XS__AssignToInstance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::AssignToInstance(uint16 instance_id)"); - - uint16 instance_id = (int) SvUV(ST(0)); - quest_manager.AssignToInstance(instance_id); - - XSRETURN_EMPTY; -} - -XS(XS__AssignToInstanceByCharID); -XS(XS__AssignToInstanceByCharID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::AssignToInstanceByCharID(uint16 instance_id, uint32 char_id)"); - - uint16 instance_id = (int) SvUV(ST(0)); - uint32 char_id = (int) SvUV(ST(1)); - quest_manager.AssignToInstanceByCharID(instance_id, char_id); - - XSRETURN_EMPTY; -} - -XS(XS__AssignGroupToInstance); -XS(XS__AssignGroupToInstance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::AssignGroupToInstance(uint16 instance_id)"); - - uint16 instance_id = (int) SvUV(ST(0)); - quest_manager.AssignGroupToInstance(instance_id); - - XSRETURN_EMPTY; -} - -XS(XS__AssignRaidToInstance); -XS(XS__AssignRaidToInstance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::AssignRaidToInstance(uint16 instance_id)"); - - uint16 instance_id = (int) SvUV(ST(0)); - quest_manager.AssignRaidToInstance(instance_id); - - XSRETURN_EMPTY; -} - -XS(XS__RemoveFromInstance); -XS(XS__RemoveFromInstance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::RemoveFromInstance(uint16 instance_id)"); - - uint16 instance_id = (int) SvUV(ST(0)); - quest_manager.RemoveFromInstance(instance_id); - - XSRETURN_EMPTY; -} - -XS(XS__RemoveFromInstanceByCharID); -XS(XS__RemoveFromInstanceByCharID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id)"); - - uint16 instance_id = (int) SvUV(ST(0)); - uint32 char_id = (int) SvUV(ST(1)); - quest_manager.RemoveFromInstanceByCharID(instance_id, char_id); - - XSRETURN_EMPTY; -} - -XS(XS__CheckInstanceByCharID); -XS(XS__CheckInstanceByCharID) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: quest::CheckInstanceByCharID(uint16 instance_id, uint32 char_id)"); - } - - bool RETVAL; - dXSTARG; - - uint16 instance_id = (int) SvUV(ST(0)); - uint32 char_id = (int) SvUV(ST(1)); - RETVAL = quest_manager.CheckInstanceByCharID(instance_id, char_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__RemoveAllFromInstance); -XS(XS__RemoveAllFromInstance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::RemoveAllFromInstance(uint16 instance_id)"); - - uint16 instance_id = (int) SvUV(ST(0)); - quest_manager.RemoveAllFromInstance(instance_id); - - XSRETURN_EMPTY; -} - -XS(XS__MovePCInstance); -XS(XS__MovePCInstance) { - dXSARGS; - if (items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: quest::MovePCInstance(int zone_id, int instance_id, float x, float y, float z, [float heading])"); - - int zone_id = (int) SvIV(ST(0)); - int instance_id = (int) SvIV(ST(1)); - float x = (float) SvNV(ST(2)); - float y = (float) SvNV(ST(3)); - float z = (float) SvNV(ST(4)); - float heading = 0.0f; - - if (items == 6) { - heading = (float) SvNV(ST(5)); - } - - quest_manager.MovePCInstance(zone_id, instance_id, glm::vec4(x, y, z, heading)); - - XSRETURN_EMPTY; -} - -XS(XS__FlagInstanceByGroupLeader); -XS(XS__FlagInstanceByGroupLeader) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::FlagInstanceByGroupLeader(uint32 zone, uint16 version)"); - - uint32 zone = (int) SvUV(ST(0)); - uint16 version = (int) SvUV(ST(1)); - quest_manager.FlagInstanceByGroupLeader(zone, version); - - XSRETURN_EMPTY; -} - -XS(XS__FlagInstanceByRaidLeader); -XS(XS__FlagInstanceByRaidLeader) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::FlagInstanceByRaidLeader(uint32 zone, uint16 version)"); - - uint32 zone = (int) SvUV(ST(0)); - uint16 version = (int) SvUV(ST(1)); - quest_manager.FlagInstanceByRaidLeader(zone, version); - - XSRETURN_EMPTY; -} - -XS(XS__saylink); -XS(XS__saylink) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::saylink(string message, [bool silent = false], [link_name = message])"); - dXSTARG; - - std::string RETVAL; - char message[250]; - char link_name[250]; - bool silent = false; - strcpy(message, (char *) SvPV_nolen(ST(0))); - if (items >= 2) { - silent = ((int) SvIV(ST(1))) == 0 ? false : true; - } - if (items == 3) - strcpy(link_name, (char *) SvPV_nolen(ST(2))); - else - strcpy(link_name, message); - - RETVAL = quest_manager.saylink(message, silent, link_name); - - sv_setpv(TARG, RETVAL.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__getcharnamebyid); -XS(XS__getcharnamebyid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getcharnamebyid(uint32 char_id)"); - dXSTARG; - - Const_char *RETVAL; - uint32 char_id = (int) SvUV(ST(0)); - auto name = quest_manager.getcharnamebyid(char_id); - - RETVAL = name.c_str(); - - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; -} - -XS(XS__getcharidbyname); -XS(XS__getcharidbyname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getcharidbyname(string name)"); - dXSTARG; - - uint32 RETVAL; - const char *name = (const char *) SvPV_nolen(ST(0)); - - RETVAL = quest_manager.getcharidbyname(name); - XSprePUSH; - PUSHu((UV) RETVAL); - - XSRETURN(1); -} - -XS(XS__getclassname); -XS(XS__getclassname) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: quest::getclassname(uint8 class_id, [uint8 level = 0])"); - dXSTARG; - - std::string RETVAL; - uint8 class_id = (int) SvUV(ST(0)); - uint8 level = 0; - if (items > 1) - level = (int) SvUV(ST(1)); - - RETVAL = quest_manager.getclassname(class_id, level); - sv_setpv(TARG, RETVAL.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__getcurrencyitemid); -XS(XS__getcurrencyitemid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getcurrencyitemid(int currency_id)"); - dXSTARG; - - int RETVAL; - uint32 currency_id = (uint32) SvUV(ST(0)); - - RETVAL = quest_manager.getcurrencyitemid(currency_id); - - XSprePUSH; - PUSHi((IV) RETVAL); - XSRETURN(1); -} - -XS(XS__getcurrencyid); -XS(XS__getcurrencyid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getcurrencyid(uint32 item_id)"); - dXSTARG; - - uint32 RETVAL; - uint32 item_id = (uint32) SvUV(ST(0)); - - RETVAL = quest_manager.getcurrencyid(item_id); - XSprePUSH; - PUSHi((IV) RETVAL); - XSRETURN(1); -} - -XS(XS__getguildnamebyid); -XS(XS__getguildnamebyid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getguildnamebyid(uint32 guild_id)"); - dXSTARG; - - Const_char *RETVAL; - uint32 guild_id = (int) SvUV(ST(0)); - - RETVAL = quest_manager.getguildnamebyid(guild_id); - - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__getguildidbycharid); -XS(XS__getguildidbycharid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getguildidbycharid(uint32 char_id)"); - dXSTARG; - - int RETVAL; - uint32 char_id = (int) SvUV(ST(0)); - - RETVAL = quest_manager.getguildidbycharid(char_id); - - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); -} - -XS(XS__getgroupidbycharid); -XS(XS__getgroupidbycharid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getgroupidbycharid(uint32 char_id)"); - dXSTARG; - - int RETVAL; - uint32 char_id = (int) SvUV(ST(0)); - - RETVAL = quest_manager.getgroupidbycharid(char_id); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); -} - -XS(XS__getraididbycharid); -XS(XS__getraididbycharid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getraididbycharid(uint32 char_id)"); - dXSTARG; - - int RETVAL; - uint32 char_id = (int) SvUV(ST(0)); - - RETVAL = quest_manager.getraididbycharid(char_id); - XSprePUSH; - PUSHi((IV) RETVAL); - - XSRETURN(1); -} - -XS(XS__SetRunning); -XS(XS__SetRunning) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::SetRunning(bool is_running)"); - - bool val = ((int) SvIV(ST(0))) == 0 ? false : true; - - quest_manager.SetRunning(val); - - XSRETURN_EMPTY; -} - -XS(XS__IsRunning); -XS(XS__IsRunning) { - dXSARGS; - if (items >= 1) - Perl_croak(aTHX_ "Usage: quest::IsRunning()"); - - bool RETVAL; - dXSTARG; - - RETVAL = quest_manager.IsRunning(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsEffectInSpell); -XS(XS__IsEffectInSpell) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::IsEffectInSpell(uint32 spell_id, uint32 effect_id)"); - - uint32 spell_id = (uint32) SvUV(ST(0)); - uint32 effect_id = (uint32) SvUV(ST(1)); - bool RETVAL; - dXSTARG; - - RETVAL = IsEffectInSpell(spell_id, effect_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsBeneficialSpell); -XS(XS__IsBeneficialSpell) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::IsBeneficialSpell(uint32 spell_id)"); - - uint32 spell_id = (uint32) SvUV(ST(0)); - bool RETVAL; - dXSTARG; - - RETVAL = BeneficialSpell(spell_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__GetSpellResistType); -XS(XS__GetSpellResistType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetSpellResistType(uint32 spell_id)"); - - uint32 spell_id = (uint32) SvUV(ST(0)); - int32 spell_val = 0; - dXSTARG; - - spell_val = GetSpellResistType(spell_id); - XSRETURN_UV(spell_val); -} - -XS(XS__GetSpellTargetType); -XS(XS__GetSpellTargetType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetSpellTargetType(uint32 spell_id)"); - - uint32 spell_id = (uint32) SvUV(ST(0)); - int32 spell_val = 0; - dXSTARG; - - spell_val = GetSpellTargetType(spell_id); - XSRETURN_UV(spell_val); -} - -XS(XS__FlyMode); -XS(XS__FlyMode) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::FlyMode(uint8 mode [0-5])"); - - GravityBehavior flymode = (GravityBehavior) SvUV(ST(0)); - quest_manager.FlyMode(flymode); - - XSRETURN_EMPTY; -} - -XS(XS_FactionValue); -XS(XS_FactionValue) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::factionvalue()"); - - uint8 fac = quest_manager.FactionValue(); - XSRETURN_UV(fac); -} - -XS(XS__enabletitle); -XS(XS__enabletitle) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::enabletitle(int title_set_id)"); - - int titleset = (int) SvIV(ST(0)); - - quest_manager.enabletitle(titleset); - - XSRETURN_EMPTY; -} - -XS(XS__checktitle); -XS(XS__checktitle) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::checktitle(int title_set_id)"); - - bool RETVAL; - int titleset = (int) SvIV(ST(0)); - - RETVAL = quest_manager.checktitle(titleset); - - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__removetitle); -XS(XS__removetitle) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::removetitle(int title_set_id)"); - - int titleset = (int) SvIV(ST(0)); - - quest_manager.removetitle(titleset); - - XSRETURN_EMPTY; -} - -XS(XS__wearchange); -XS(XS__wearchange) { - dXSARGS; - if (items < 2) - Perl_croak(aTHX_ "Usage: quest::wearchange(uint8 slot, uint16 texture_id, [uint32 hero_forge_model_id = 0], [uint32 elite_material_id = 0])"); - - uint8 slot = (int) SvUV(ST(0)); - uint16 texture_id = (int) SvUV(ST(1)); - - uint32 hero_forge_model_id = 0; - uint32 elite_material_id = 0; - - if (items > 2) - hero_forge_model_id = (int) SvUV(ST(2)); - - if (items > 3) - elite_material_id = (int) SvUV(ST(3)); - - quest_manager.wearchange(slot, texture_id, hero_forge_model_id, elite_material_id); - - XSRETURN_EMPTY; -} - -XS(XS__voicetell); -XS(XS__voicetell) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: quest::voicetell(string client_name, int macro_id, int ace_id, int gender_id)"); - - char *client_name = (char *) SvPV_nolen(ST(0)); - int macro_id = (int) SvIV(ST(1)); - int race_id = (int) SvIV(ST(2)); - int gender_id = (int) SvIV(ST(3)); - - quest_manager.voicetell(client_name, macro_id, race_id, gender_id); - - XSRETURN_EMPTY; -} - -XS(XS__LearnRecipe); -XS(XS__LearnRecipe) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::LearnRecipe(int recipe_id)"); - - uint32 recipe_id = (uint32) SvIV(ST(0)); - - quest_manager.LearnRecipe(recipe_id); - - XSRETURN_EMPTY; -} - -XS(XS__SendMail); -XS(XS__SendMail) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: quest::SendMail(stirng to, string from, string subject, string message)"); - - char *to = (char *) SvPV_nolen(ST(0)); - char *from = (char *) SvPV_nolen(ST(1)); - char *subject = (char *) SvPV_nolen(ST(2)); - char *message = (char *) SvPV_nolen(ST(3)); - - quest_manager.SendMail(to, from, subject, message); - - XSRETURN_EMPTY; -} - -XS(XS__GetZoneID); -XS(XS__GetZoneID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetZoneID(string zone)"); - - char *zone = (char *) SvPV_nolen(ST(0)); - int32 id = quest_manager.GetZoneID(zone); - - XSRETURN_IV(id); -} - -XS(XS__GetZoneLongName); -XS(XS__GetZoneLongName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetZoneLongName(string zone)"); - dXSTARG; - - std::string zone = (std::string) SvPV_nolen(ST(0)); - std::string RETVAL = quest_manager.GetZoneLongName(zone); - - sv_setpv(TARG, RETVAL.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__GetZoneLongNameByID); -XS(XS__GetZoneLongNameByID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetZoneLongNameByID(uint32 zone_id)"); - - dXSTARG; - uint32 zone_id = (uint32) SvUV(ST(0)); - std::string zone_long_name = quest_manager.GetZoneLongNameByID(zone_id); - sv_setpv(TARG, zone_long_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__GetZoneShortName); -XS(XS__GetZoneShortName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::GetZoneShortName(uint32 zone_id)"); - - dXSTARG; - uint32 zone_id = (uint32) SvUV(ST(0)); - std::string zone_short_name = quest_manager.GetZoneShortName(zone_id); - sv_setpv(TARG, zone_short_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__GetTimeSeconds); -XS(XS__GetTimeSeconds) { - dXSARGS; - if (items != 0) - Perl_croak(aTHX_ "Usage: quest::GetTimeSeconds()"); - - uint32 seconds = 0; - dXSTARG; - - seconds = Timer::GetTimeSeconds(); - XSRETURN_UV(seconds); -} - -XS(XS__enablerecipe); -XS(XS__enablerecipe) { - dXSARGS; - bool success = false; - - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::enablerecipe(int recipe_id)"); - } else { - uint32 recipe_id = (uint32) SvIV(ST(0)); - success = quest_manager.EnableRecipe(recipe_id); - } - if (!success) { - XSRETURN_NO; - } - - XSRETURN_YES; -} - -XS(XS__disablerecipe); -XS(XS__disablerecipe) { - dXSARGS; - bool success = false; - - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::disablerecipe(int recipe_id)"); - } else { - uint32 recipe_id = (uint32) SvIV(ST(0)); - success = quest_manager.DisableRecipe(recipe_id); - } - if (!success) { - XSRETURN_NO; - } - - XSRETURN_YES; -} - -XS(XS__clear_npctype_cache); -XS(XS__clear_npctype_cache) { - dXSARGS; - - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::clear_npctype_cache(int npc_type_id)"); - } else { - int32 npc_type_id = (int32) SvIV(ST(0)); - quest_manager.ClearNPCTypeCache(npc_type_id); - } - - XSRETURN_EMPTY; -} - -XS(XS__reloadzonestaticdata); -XS(XS__reloadzonestaticdata) { - dXSARGS; - - quest_manager.ReloadZoneStaticData(); - - XSRETURN_EMPTY; -} - -XS(XS__qs_send_query); -XS(XS__qs_send_query) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::qs_send_query(string query)"); - } else { - // char *Query = (char *)SvPV_nolen(ST(0)); - std::string Query = (std::string) SvPV_nolen(ST(0)); - QServ->SendQuery(Query); - } - XSRETURN_EMPTY; -} - -XS(XS__qs_player_event); -XS(XS__qs_player_event) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: quest::qs_player_event(int character_id, string message)"); - } else { - int char_id = (int) SvIV(ST(0)); - std::string message = (std::string) SvPV_nolen(ST(1)); - QServ->PlayerLogEvent(Player_Log_Quest, char_id, message); - } - XSRETURN_EMPTY; -} - - - -XS(XS__log); -XS(XS__log) { - dXSARGS; - if (items != 1 && items != 2) { - Perl_croak(aTHX_ "Usage: quest::log(uint8 log_category, string message)"); - } - else { - uint8 log_category = (uint8)SvIV(ST(0)); - std::string log_message = (std::string) SvPV_nolen(ST(1)); - - if (log_category >= Logs::MaxCategoryID) { - return; - } - - Log(Logs::General, log_category, log_message.c_str()); - } - XSRETURN_EMPTY; -} - -XS(XS__debug); -XS(XS__debug) { - dXSARGS; - if (items != 1 && items != 2) { - Perl_croak(aTHX_ "Usage: quest::debug(string message, [uint8 debug_level = 1 [1-3]])"); - } else { - std::string log_message = (std::string) SvPV_nolen(ST(0)); - uint8 debug_level = 1; - - if (items == 2) - debug_level = (uint8) SvIV(ST(1)); - - if (debug_level > Logs::Detail) - return; - - if (debug_level == Logs::General) { - Log(Logs::General, Logs::QuestDebug, log_message.c_str()); - } else if (debug_level == Logs::Moderate) { - Log(Logs::Moderate, Logs::QuestDebug, log_message.c_str()); - } else if (debug_level == Logs::Detail) { - Log(Logs::Detail, Logs::QuestDebug, log_message.c_str()); - } - } - XSRETURN_EMPTY; -} - -XS(XS__log_combat); -XS(XS__log_combat) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::log_combat(string message)"); - } - else { - - std::string log_message = (std::string) SvPV_nolen(ST(0)); - Log(Logs::General, Logs::Combat, log_message.c_str()); - } - XSRETURN_EMPTY; -} - - -XS(XS__UpdateZoneHeader); -XS(XS__UpdateZoneHeader) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::UpdateZoneHeader(string key, string value)"); - - std::string key = (std::string) SvPV_nolen(ST(0)); - std::string str_value = (std::string) SvPV_nolen(ST(1)); - quest_manager.UpdateZoneHeader(key, str_value); - - XSRETURN_EMPTY; -} - -XS(XS__set_rule); -XS(XS__set_rule) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::set_rule(string rule_name, string rule_value)"); - - std::string rule_name = (std::string) SvPV_nolen(ST(0)); - std::string rule_value = (std::string) SvPV_nolen(ST(1)); - RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str()); - - XSRETURN_EMPTY; -} - -XS(XS__get_rule); -XS(XS__get_rule) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::get_rule(string rule_name)"); - - dXSTARG; - std::string rule_name = (std::string) SvPV_nolen(ST(0)); - std::string rule_value; - RuleManager::Instance()->GetRule(rule_name.c_str(), rule_value); - - sv_setpv(TARG, rule_value.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__get_data); -XS(XS__get_data) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::get_data(string bucket_key)"); - - dXSTARG; - std::string key = (std::string) SvPV_nolen(ST(0)); - - sv_setpv(TARG, DataBucket::GetData(key).c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__get_data_expires); -XS(XS__get_data_expires) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::get_data_expires(string bucket_key)"); - - dXSTARG; - std::string key = (std::string) SvPV_nolen(ST(0)); - - sv_setpv(TARG, DataBucket::GetDataExpires(key).c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__set_data); -XS(XS__set_data) { - dXSARGS; - if (items != 2 && items != 3) { - Perl_croak(aTHX_ "Usage: quest::set_data(string key, string value, [string expires_at = 0])"); - } else { - std::string key = (std::string) SvPV_nolen(ST(0)); - std::string value = (std::string) SvPV_nolen(ST(1)); - - std::string expires_at; - if (items == 3) - expires_at = (std::string) SvPV_nolen(ST(2)); - - DataBucket::SetData(key, value, expires_at); - } - XSRETURN_EMPTY; -} - -XS(XS__delete_data); -XS(XS__delete_data) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::delete_data(string bucket_key)"); - - dXSTARG; - std::string key = (std::string) SvPV_nolen(ST(0)); - - XSprePUSH; - PUSHi((IV) DataBucket::DeleteData(key)); - - XSRETURN(1); -} - - -XS(XS__IsClassicEnabled); -XS(XS__IsClassicEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_classic_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsClassicEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheRuinsOfKunarkEnabled); -XS(XS__IsTheRuinsOfKunarkEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_ruins_of_kunark_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheRuinsOfKunarkEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheScarsOfVeliousEnabled); -XS(XS__IsTheScarsOfVeliousEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_scars_of_velious_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheScarsOfVeliousEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheShadowsOfLuclinEnabled); -XS(XS__IsTheShadowsOfLuclinEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_shadows_of_luclin_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheShadowsOfLuclinEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsThePlanesOfPowerEnabled); -XS(XS__IsThePlanesOfPowerEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_planes_of_power_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsThePlanesOfPowerEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheLegacyOfYkeshaEnabled); -XS(XS__IsTheLegacyOfYkeshaEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_legacy_of_ykesha_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheLegacyOfYkeshaEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsLostDungeonsOfNorrathEnabled); -XS(XS__IsLostDungeonsOfNorrathEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_lost_dungeons_of_norrath_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsLostDungeonsOfNorrathEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsGatesOfDiscordEnabled); -XS(XS__IsGatesOfDiscordEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_gates_of_discord_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsGatesOfDiscordEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsOmensOfWarEnabled); -XS(XS__IsOmensOfWarEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_omens_of_war_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsOmensOfWarEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsDragonsOfNorrathEnabled); -XS(XS__IsDragonsOfNorrathEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_dragons_of_norrath_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsDragonsOfNorrathEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsDepthsOfDarkhollowEnabled); -XS(XS__IsDepthsOfDarkhollowEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_depths_of_darkhollow_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsDepthsOfDarkhollowEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsProphecyOfRoEnabled); -XS(XS__IsProphecyOfRoEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_prophecy_of_ro_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsProphecyOfRoEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheSerpentsSpineEnabled); -XS(XS__IsTheSerpentsSpineEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_serpents_spine_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheSerpentsSpineEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheBuriedSeaEnabled); -XS(XS__IsTheBuriedSeaEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_buried_sea_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheBuriedSeaEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsSecretsOfFaydwerEnabled); -XS(XS__IsSecretsOfFaydwerEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_secrets_of_faydwer_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsSecretsOfFaydwerEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsSeedsOfDestructionEnabled); -XS(XS__IsSeedsOfDestructionEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_seeds_of_destruction_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsSeedsOfDestructionEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsUnderfootEnabled); -XS(XS__IsUnderfootEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_underfoot_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsUnderfootEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsHouseOfThuleEnabled); -XS(XS__IsHouseOfThuleEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_house_of_thule_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsHouseOfThuleEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsVeilOfAlarisEnabled); -XS(XS__IsVeilOfAlarisEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_veil_of_alaris_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsVeilOfAlarisEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsRainOfFearEnabled); -XS(XS__IsRainOfFearEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_rain_of_fear_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsRainOfFearEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCallOfTheForsakenEnabled); -XS(XS__IsCallOfTheForsakenEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_call_of_the_forsaken_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCallOfTheForsakenEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheDarkenedSeaEnabled); -XS(XS__IsTheDarkenedSeaEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_darkened_sea_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheDarkenedSeaEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheBrokenMirrorEnabled); -XS(XS__IsTheBrokenMirrorEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_broken_mirror_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheBrokenMirrorEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsEmpiresOfKunarkEnabled); -XS(XS__IsEmpiresOfKunarkEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_empires_of_kunark_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsEmpiresOfKunarkEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsRingOfScaleEnabled); -XS(XS__IsRingOfScaleEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_ring_of_scale_enabled()"); } - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsRingOfScaleEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTheBurningLandsEnabled); -XS(XS__IsTheBurningLandsEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_the_burning_lands_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTheBurningLandsEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsTormentOfVeliousEnabled); -XS(XS__IsTormentOfVeliousEnabled) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_torment_of_velious_enabled()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsTormentOfVeliousEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionClassic); -XS(XS__IsCurrentExpansionClassic) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_classic()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionClassic(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheRuinsOfKunark); -XS(XS__IsCurrentExpansionTheRuinsOfKunark) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_ruins_of_kunark()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheRuinsOfKunark(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheScarsOfVelious); -XS(XS__IsCurrentExpansionTheScarsOfVelious) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_scars_of_velious()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheScarsOfVelious(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheShadowsOfLuclin); -XS(XS__IsCurrentExpansionTheShadowsOfLuclin) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_shadows_of_luclin()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheShadowsOfLuclin(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionThePlanesOfPower); -XS(XS__IsCurrentExpansionThePlanesOfPower) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_planes_of_power()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionThePlanesOfPower(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheLegacyOfYkesha); -XS(XS__IsCurrentExpansionTheLegacyOfYkesha) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_legacy_of_ykesha()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheLegacyOfYkesha(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionLostDungeonsOfNorrath); -XS(XS__IsCurrentExpansionLostDungeonsOfNorrath) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_lost_dungeons_of_norrath()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionLostDungeonsOfNorrath(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionGatesOfDiscord); -XS(XS__IsCurrentExpansionGatesOfDiscord) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_gates_of_discord()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionGatesOfDiscord(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionOmensOfWar); -XS(XS__IsCurrentExpansionOmensOfWar) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_omens_of_war()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionOmensOfWar(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionDragonsOfNorrath); -XS(XS__IsCurrentExpansionDragonsOfNorrath) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_dragons_of_norrath()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionDragonsOfNorrath(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionDepthsOfDarkhollow); -XS(XS__IsCurrentExpansionDepthsOfDarkhollow) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_depths_of_darkhollow()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionDepthsOfDarkhollow(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionProphecyOfRo); -XS(XS__IsCurrentExpansionProphecyOfRo) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_prophecy_of_ro()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionProphecyOfRo(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheSerpentsSpine); -XS(XS__IsCurrentExpansionTheSerpentsSpine) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_serpents_spine()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheSerpentsSpine(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheBuriedSea); -XS(XS__IsCurrentExpansionTheBuriedSea) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_buried_sea()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheBuriedSea(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionSecretsOfFaydwer); -XS(XS__IsCurrentExpansionSecretsOfFaydwer) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_secrets_of_faydwer()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionSecretsOfFaydwer(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionSeedsOfDestruction); -XS(XS__IsCurrentExpansionSeedsOfDestruction) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_seeds_of_destruction()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionSeedsOfDestruction(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionUnderfoot); -XS(XS__IsCurrentExpansionUnderfoot) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_underfoot()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionUnderfoot(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionHouseOfThule); -XS(XS__IsCurrentExpansionHouseOfThule) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_house_of_thule()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionHouseOfThule(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionVeilOfAlaris); -XS(XS__IsCurrentExpansionVeilOfAlaris) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_veil_of_alaris()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionVeilOfAlaris(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionRainOfFear); -XS(XS__IsCurrentExpansionRainOfFear) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_rain_of_fear()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionRainOfFear(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionCallOfTheForsaken); -XS(XS__IsCurrentExpansionCallOfTheForsaken) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_call_of_the_forsaken()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionCallOfTheForsaken(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheDarkenedSea); -XS(XS__IsCurrentExpansionTheDarkenedSea) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_darkened_sea()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheDarkenedSea(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheBrokenMirror); -XS(XS__IsCurrentExpansionTheBrokenMirror) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_broken_mirror()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheBrokenMirror(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionEmpiresOfKunark); -XS(XS__IsCurrentExpansionEmpiresOfKunark) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_empires_of_kunark()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionEmpiresOfKunark(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionRingOfScale); -XS(XS__IsCurrentExpansionRingOfScale) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_ring_of_scale()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionRingOfScale(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTheBurningLands); -XS(XS__IsCurrentExpansionTheBurningLands) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_burning_lands()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTheBurningLands(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsCurrentExpansionTormentOfVelious); -XS(XS__IsCurrentExpansionTormentOfVelious) { - dXSARGS; - if (items >= 1) { - Perl_croak(aTHX_ "Usage: quest::is_current_expansion_torment_of_velious()"); - } - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsCurrentExpansionTormentOfVelious(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); -} - -XS(XS__IsContentFlagEnabled); -XS(XS__IsContentFlagEnabled) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::is_content_flag_enabled(string flag_name)"); - } - - std::string flag_name = (std::string) SvPV_nolen(ST(0)); - - bool RETVAL; - dXSTARG; - RETVAL = content_service.IsContentFlagEnabled(flag_name); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - XSRETURN(1); + return char_id_string; } -XS(XS__SetContentFlag); -XS(XS__SetContentFlag) +void Perl__AssignToInstance(uint16 instance_id) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: quest::set_content_flag(string flag_name, enabled)"); - } - - std::string flag_name = (std::string) SvPV_nolen(ST(0)); - bool enabled = (int) SvIV(ST(1)) != 0; - - content_service.SetContentFlag(flag_name, enabled); - XSRETURN_EMPTY; + quest_manager.AssignToInstance(instance_id); } -XS(XS__get_expedition); -XS(XS__get_expedition) { - dXSARGS; - if (items != 0) { - Perl_croak(aTHX_ "Usage: quest::get_expedition()"); - } +void Perl__AssignToInstanceByCharID(uint16 instance_id, uint32 character_id) +{ + quest_manager.AssignToInstanceByCharID(instance_id, character_id); +} - Expedition* RETVAL = nullptr; +void Perl__AssignGroupToInstance(uint16 instance_id) +{ + quest_manager.AssignGroupToInstance(instance_id); +} + +void Perl__AssignRaidToInstance(uint16 instance_id) +{ + quest_manager.AssignRaidToInstance(instance_id); +} + +void Perl__RemoveFromInstance(uint16 instance_id) +{ + quest_manager.RemoveFromInstance(instance_id); +} + +void Perl__RemoveFromInstanceByCharID(uint16 instance_id, uint32 character_id) +{ + quest_manager.RemoveFromInstanceByCharID(instance_id, character_id); +} + +bool Perl__CheckInstanceByCharID(uint16 instance_id, uint32 character_id) +{ + return quest_manager.CheckInstanceByCharID(instance_id, character_id); +} + +void Perl__RemoveAllFromInstance(uint16 instance_id) +{ + quest_manager.RemoveAllFromInstance(instance_id); +} + +void Perl__MovePCInstance(int zone_id, int instance_id, float x, float y, float z) +{ + quest_manager.MovePCInstance(zone_id, instance_id, glm::vec4(x, y, z, 0.0f)); +} + +void Perl__MovePCInstance(int zone_id, int instance_id, float x, float y, float z, float heading) +{ + quest_manager.MovePCInstance(zone_id, instance_id, glm::vec4(x, y, z, heading)); +} + +void Perl__FlagInstanceByGroupLeader(uint32 zone, uint16 version) +{ + quest_manager.FlagInstanceByGroupLeader(zone, version); +} + +void Perl__FlagInstanceByRaidLeader(uint32 zone, uint16 version) +{ + quest_manager.FlagInstanceByRaidLeader(zone, version); +} + +std::string Perl__saylink(const char* text) +{ + // const cast is safe since, target api doesn't modify it + return quest_manager.saylink(const_cast(text), false, text); +} + +std::string Perl__saylink(const char* text, bool silent) +{ + return quest_manager.saylink(const_cast(text), silent, text); +} + +std::string Perl__saylink(const char* text, bool silent, const char* link_name) +{ + return quest_manager.saylink(const_cast(text), silent, link_name); +} + +std::string Perl__getcharnamebyid(uint32 char_id) +{ + return quest_manager.getcharnamebyid(char_id); +} + +uint32_t Perl__getcharidbyname(const char* name) +{ + return quest_manager.getcharidbyname(name); +} + +std::string Perl__getclassname(uint8 class_id) +{ + return quest_manager.getclassname(class_id); +} + +std::string Perl__getclassname(uint8 class_id, uint8 level) +{ + return quest_manager.getclassname(class_id, level); +} + +uint32 Perl__getcurrencyitemid(uint32 currency_id) +{ + return quest_manager.getcurrencyitemid(currency_id); +} + +uint32 Perl__getcurrencyid(uint32 item_id) +{ + return quest_manager.getcurrencyid(item_id); +} + +std::string Perl__getguildnamebyid(int guild_id) +{ + return quest_manager.getguildnamebyid(guild_id); +} + +int Perl__getguildidbycharid(uint32 char_id) +{ + return quest_manager.getguildidbycharid(char_id); +} + +int Perl__getgroupidbycharid(uint32 char_id) +{ + return quest_manager.getgroupidbycharid(char_id); +} + +int Perl__getraididbycharid(uint32 char_id) +{ + return quest_manager.getraididbycharid(char_id); +} + +void Perl__SetRunning(bool is_running) +{ + quest_manager.SetRunning(is_running); +} + +bool Perl__IsRunning() +{ + return quest_manager.IsRunning(); +} + +bool Perl__IsEffectInSpell(uint32 spell_id, uint32 effect_id) +{ + return IsEffectInSpell(spell_id, effect_id); +} + +bool Perl__IsBeneficialSpell(uint16 spell_id) +{ + return BeneficialSpell(spell_id); +} + +int Perl__GetSpellResistType(uint16 spell_id) +{ + return GetSpellResistType(spell_id); +} + +int Perl__GetSpellTargetType(uint16 spell_id) +{ + return GetSpellTargetType(spell_id); +} + +void Perl__FlyMode(GravityBehavior flymode) +{ + quest_manager.FlyMode(flymode); +} + +int Perl__FactionValue() +{ + return quest_manager.FactionValue(); +} + +void Perl__enabletitle(int title_set) +{ + quest_manager.enabletitle(title_set); +} + +bool Perl__checktitle(int title_set) +{ + return quest_manager.checktitle(title_set); +} + +void Perl__removetitle(int title_set) +{ + quest_manager.removetitle(title_set); +} + +void Perl__wearchange(uint8 slot, uint16 texture_id) +{ + quest_manager.wearchange(slot, texture_id); +} + +void Perl__wearchange(uint8 slot, uint16 texture_id, uint32 hero_forge_model_id) +{ + quest_manager.wearchange(slot, texture_id, hero_forge_model_id); +} + +void Perl__wearchange(uint8 slot, uint16 texture_id, uint32 hero_forge_model_id, uint32 elite_material_id) +{ + quest_manager.wearchange(slot, texture_id, hero_forge_model_id, elite_material_id); +} + +void Perl__voicetell(const char* client_name, int macro_id, int race_id, int gender_id) +{ + quest_manager.voicetell(client_name, macro_id, race_id, gender_id); +} + +void Perl__LearnRecipe(int recipe_id) +{ + quest_manager.LearnRecipe(recipe_id); +} + +void Perl__SendMail(const char* to, const char* from, const char* subject, const char* message) +{ + quest_manager.SendMail(to, from, subject, message); +} + +int Perl__GetZoneID(const char* zone) +{ + return quest_manager.GetZoneID(zone); +} + +std::string Perl__GetZoneLongName(std::string zone) +{ + return quest_manager.GetZoneLongName(zone); +} + +std::string Perl__GetZoneLongNameByID(uint32 zone_id) +{ + return quest_manager.GetZoneLongNameByID(zone_id); +} + +std::string Perl__GetZoneShortName(uint32 zone_id) +{ + return quest_manager.GetZoneShortName(zone_id); +} + +uint32 Perl__GetTimeSeconds() +{ + return Timer::GetTimeSeconds(); +} + +bool Perl__enablerecipe(uint32 recipe_id) +{ + return quest_manager.EnableRecipe(recipe_id); +} + +bool Perl__disablerecipe(uint32 recipe_id) +{ + return quest_manager.DisableRecipe(recipe_id); +} + +void Perl__clear_npctype_cache(int npc_type_id) +{ + quest_manager.ClearNPCTypeCache(npc_type_id); +} + +void Perl__reloadzonestaticdata() +{ + quest_manager.ReloadZoneStaticData(); +} + +void Perl__qs_send_query(std::string query) +{ + QServ->SendQuery(std::move(query)); +} + +void Perl__qs_player_event(int char_id, std::string message) +{ + QServ->PlayerLogEvent(Player_Log_Quest, char_id, message); +} + +void Perl__log(int category, const char* message) +{ + if (category < Logs::None || category >= Logs::MaxCategoryID) + return; + + Log(Logs::General, static_cast(category), message); +} + +void Perl__debug(const char* message) +{ + Log(Logs::General, Logs::QuestDebug, message); +} + +void Perl__debug(const char* message, int level) +{ + if (level < Logs::General || level > Logs::Detail) + return; + + Log(static_cast(level), Logs::QuestDebug, message); +} + +void Perl__log_combat(const char* message) +{ + Log(Logs::General, Logs::Combat, message); +} + +void Perl__UpdateZoneHeader(std::string key, std::string value) +{ + quest_manager.UpdateZoneHeader(key, value); +} + +void Perl__set_rule(const char* rule_name, const char* rule_value) +{ + RuleManager::Instance()->SetRule(rule_name, rule_value); +} + +std::string Perl__get_rule(const char* rule_name) +{ + std::string rule_value; + RuleManager::Instance()->GetRule(rule_name, rule_value); + return rule_value; +} + +std::string Perl__get_data(std::string bucket_key) +{ + return DataBucket::GetData(bucket_key); +} + +std::string Perl__get_data_expires(std::string bucket_key) +{ + return DataBucket::GetDataExpires(bucket_key); +} + +void Perl__set_data(std::string key, std::string value) +{ + DataBucket::SetData(key, value); +} + +void Perl__set_data(std::string key, std::string value, std::string expires_at) +{ + DataBucket::SetData(key, value, expires_at); +} + +bool Perl__delete_data(std::string bucket_key) +{ + return DataBucket::DeleteData(bucket_key); +} + +bool Perl__IsClassicEnabled() +{ + return content_service.IsClassicEnabled(); +} + +bool Perl__IsTheRuinsOfKunarkEnabled() +{ + return content_service.IsTheRuinsOfKunarkEnabled(); +} + +bool Perl__IsTheScarsOfVeliousEnabled() +{ + return content_service.IsTheScarsOfVeliousEnabled(); +} + +bool Perl__IsTheShadowsOfLuclinEnabled() +{ + return content_service.IsTheShadowsOfLuclinEnabled(); +} + +bool Perl__IsThePlanesOfPowerEnabled() +{ + return content_service.IsThePlanesOfPowerEnabled(); +} + +bool Perl__IsTheLegacyOfYkeshaEnabled() +{ + return content_service.IsTheLegacyOfYkeshaEnabled(); +} + +bool Perl__IsLostDungeonsOfNorrathEnabled() +{ + return content_service.IsLostDungeonsOfNorrathEnabled(); +} + +bool Perl__IsGatesOfDiscordEnabled() +{ + return content_service.IsGatesOfDiscordEnabled(); +} + +bool Perl__IsOmensOfWarEnabled() +{ + return content_service.IsOmensOfWarEnabled(); +} + +bool Perl__IsDragonsOfNorrathEnabled() +{ + return content_service.IsDragonsOfNorrathEnabled(); +} + +bool Perl__IsDepthsOfDarkhollowEnabled() +{ + return content_service.IsDepthsOfDarkhollowEnabled(); +} + +bool Perl__IsProphecyOfRoEnabled() +{ + return content_service.IsProphecyOfRoEnabled(); +} + +bool Perl__IsTheSerpentsSpineEnabled() +{ + return content_service.IsTheSerpentsSpineEnabled(); +} + +bool Perl__IsTheBuriedSeaEnabled() +{ + return content_service.IsTheBuriedSeaEnabled(); +} + +bool Perl__IsSecretsOfFaydwerEnabled() +{ + return content_service.IsSecretsOfFaydwerEnabled(); +} + +bool Perl__IsSeedsOfDestructionEnabled() +{ + return content_service.IsSeedsOfDestructionEnabled(); +} + +bool Perl__IsUnderfootEnabled() +{ + return content_service.IsUnderfootEnabled(); +} + +bool Perl__IsHouseOfThuleEnabled() +{ + return content_service.IsHouseOfThuleEnabled(); +} + +bool Perl__IsVeilOfAlarisEnabled() +{ + return content_service.IsVeilOfAlarisEnabled(); +} + +bool Perl__IsRainOfFearEnabled() +{ + return content_service.IsRainOfFearEnabled(); +} + +bool Perl__IsCallOfTheForsakenEnabled() +{ + return content_service.IsCallOfTheForsakenEnabled(); +} + +bool Perl__IsTheDarkenedSeaEnabled() +{ + return content_service.IsTheDarkenedSeaEnabled(); +} + +bool Perl__IsTheBrokenMirrorEnabled() +{ + return content_service.IsTheBrokenMirrorEnabled(); +} + +bool Perl__IsEmpiresOfKunarkEnabled() +{ + return content_service.IsEmpiresOfKunarkEnabled(); +} + +bool Perl__IsRingOfScaleEnabled() +{ + return content_service.IsRingOfScaleEnabled(); +} + +bool Perl__IsTheBurningLandsEnabled() +{ + return content_service.IsTheBurningLandsEnabled(); +} + +bool Perl__IsTormentOfVeliousEnabled() +{ + return content_service.IsTormentOfVeliousEnabled(); +} + +bool Perl__IsCurrentExpansionClassic() +{ + return content_service.IsCurrentExpansionClassic(); +} + +bool Perl__IsCurrentExpansionTheRuinsOfKunark() +{ + return content_service.IsCurrentExpansionTheRuinsOfKunark(); +} + +bool Perl__IsCurrentExpansionTheScarsOfVelious() +{ + return content_service.IsCurrentExpansionTheScarsOfVelious(); +} + +bool Perl__IsCurrentExpansionTheShadowsOfLuclin() +{ + return content_service.IsCurrentExpansionTheShadowsOfLuclin(); +} + +bool Perl__IsCurrentExpansionThePlanesOfPower() +{ + return content_service.IsCurrentExpansionThePlanesOfPower(); +} + +bool Perl__IsCurrentExpansionTheLegacyOfYkesha() +{ + return content_service.IsCurrentExpansionTheLegacyOfYkesha(); +} + +bool Perl__IsCurrentExpansionLostDungeonsOfNorrath() +{ + return content_service.IsCurrentExpansionLostDungeonsOfNorrath(); +} + +bool Perl__IsCurrentExpansionGatesOfDiscord() +{ + return content_service.IsCurrentExpansionGatesOfDiscord(); +} + +bool Perl__IsCurrentExpansionOmensOfWar() +{ + return content_service.IsCurrentExpansionOmensOfWar(); +} + +bool Perl__IsCurrentExpansionDragonsOfNorrath() +{ + return content_service.IsCurrentExpansionDragonsOfNorrath(); +} + +bool Perl__IsCurrentExpansionDepthsOfDarkhollow() +{ + return content_service.IsCurrentExpansionDepthsOfDarkhollow(); +} + +bool Perl__IsCurrentExpansionProphecyOfRo() +{ + return content_service.IsCurrentExpansionProphecyOfRo(); +} + +bool Perl__IsCurrentExpansionTheSerpentsSpine() +{ + return content_service.IsCurrentExpansionTheSerpentsSpine(); +} + +bool Perl__IsCurrentExpansionTheBuriedSea() +{ + return content_service.IsCurrentExpansionTheBuriedSea(); +} + +bool Perl__IsCurrentExpansionSecretsOfFaydwer() +{ + return content_service.IsCurrentExpansionSecretsOfFaydwer(); +} + +bool Perl__IsCurrentExpansionSeedsOfDestruction() +{ + return content_service.IsCurrentExpansionSeedsOfDestruction(); +} + +bool Perl__IsCurrentExpansionUnderfoot() +{ + return content_service.IsCurrentExpansionUnderfoot(); +} + +bool Perl__IsCurrentExpansionHouseOfThule() +{ + return content_service.IsCurrentExpansionHouseOfThule(); +} + +bool Perl__IsCurrentExpansionVeilOfAlaris() +{ + return content_service.IsCurrentExpansionVeilOfAlaris(); +} + +bool Perl__IsCurrentExpansionRainOfFear() +{ + return content_service.IsCurrentExpansionRainOfFear(); +} + +bool Perl__IsCurrentExpansionCallOfTheForsaken() +{ + return content_service.IsCurrentExpansionCallOfTheForsaken(); +} + +bool Perl__IsCurrentExpansionTheDarkenedSea() +{ + return content_service.IsCurrentExpansionTheDarkenedSea(); +} + +bool Perl__IsCurrentExpansionTheBrokenMirror() +{ + return content_service.IsCurrentExpansionTheBrokenMirror(); +} + +bool Perl__IsCurrentExpansionEmpiresOfKunark() +{ + return content_service.IsCurrentExpansionEmpiresOfKunark(); +} + +bool Perl__IsCurrentExpansionRingOfScale() +{ + return content_service.IsCurrentExpansionRingOfScale(); +} + +bool Perl__IsCurrentExpansionTheBurningLands() +{ + return content_service.IsCurrentExpansionTheBurningLands(); +} + +bool Perl__IsCurrentExpansionTormentOfVelious() +{ + return content_service.IsCurrentExpansionTormentOfVelious(); +} + +bool Perl__IsContentFlagEnabled(std::string flag_name) +{ + return content_service.IsContentFlagEnabled(flag_name); +} + +void Perl__SetContentFlag(std::string flag_name, bool enabled) +{ + content_service.SetContentFlag(flag_name, enabled); +} + +Expedition* Perl__get_expedition() +{ if (zone && zone->GetInstanceID() != 0) { - RETVAL = Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID()); + return Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID()); } - EXTEND(sp, 1); // grow stack, function had 0 arguments - ST(0) = sv_newmortal(); // PUSHs(sv_newmortal()); - if (RETVAL) { - sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); - } - - XSRETURN(1); + return nullptr; } -XS(XS__get_expedition_by_char_id); -XS(XS__get_expedition_by_char_id) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::get_expedition_by_char_id(uint32 character_id)"); - } - - uint32 character_id = (int)SvUV(ST(0)); - - Expedition* RETVAL = Expedition::FindCachedExpeditionByCharacterID(character_id); - - ST(0) = sv_newmortal(); - if (RETVAL) { - sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); - } - - XSRETURN(1); +Expedition* Perl__get_expedition_by_char_id(uint32 char_id) +{ + return Expedition::FindCachedExpeditionByCharacterID(char_id); } -XS(XS__get_expedition_by_dz_id); -XS(XS__get_expedition_by_dz_id) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::get_expedition_by_dz_id(uint32 dynamic_zone_id)"); - } - - uint32 dz_id = (int)SvUV(ST(0)); - - Expedition* RETVAL = Expedition::FindCachedExpeditionByDynamicZoneID(dz_id); - - ST(0) = sv_newmortal(); - if (RETVAL) { - sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); - } - - XSRETURN(1); +Expedition* Perl__get_expedition_by_dz_id(uint32 dz_id) +{ + return Expedition::FindCachedExpeditionByDynamicZoneID(dz_id); } -XS(XS__get_expedition_by_zone_instance); -XS(XS__get_expedition_by_zone_instance) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: quest::GetExpeditionByZoneInstance(uint16 zone_id, uint16 instance_id)"); - } - - uint16 zone_id = (uint16)SvUV(ST(0)); - uint16 instance_id = (uint16)SvUV(ST(1)); - - Expedition* RETVAL = Expedition::FindCachedExpeditionByZoneInstance(zone_id, instance_id); - - ST(0) = sv_newmortal(); - if (RETVAL) { - sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); - } - - XSRETURN(1); +Expedition* Perl__get_expedition_by_zone_instance(uint32 zone_id, uint32 instance_id) +{ + return Expedition::FindCachedExpeditionByZoneInstance(zone_id, instance_id); } -XS(XS__get_expedition_lockout_by_char_id); -XS(XS__get_expedition_lockout_by_char_id) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: quest::get_expedition_lockout_by_char_id(uint32 character_id, string expedition_name, string event_name)"); - } +perl::reference Perl__get_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name) +{ + perl::hash table; - uint32_t character_id = static_cast(SvUV(ST(0))); - std::string expedition_name = SvPV_nolen(ST(1)); - std::string event_name = SvPV_nolen(ST(2)); + auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id); - auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(character_id); auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const ExpeditionLockoutTimer& lockout) { return lockout.IsSameLockout(expedition_name, event_name); }); - // mortalize so its refcnt is auto decremented on function exit to avoid leak - HV* hash = (HV*)sv_2mortal((SV*)newHV()); // hash refcnt +1 (mortal -1) - if (it != lockouts.end()) { - hv_store(hash, "remaining", strlen("remaining"), newSVuv(it->GetSecondsRemaining()), 0); - hv_store(hash, "uuid", strlen("uuid"), newSVpv(it->GetExpeditionUUID().c_str(), 0), 0); + table["remaining"] = it->GetSecondsRemaining(); + table["uuid"] = it->GetExpeditionUUID(); } - ST(0) = sv_2mortal(newRV((SV*)hash)); // hash refcnt: 2 (-1 mortal), reference: 1 (-1 mortal) - XSRETURN(1); + return perl::reference(table); } -XS(XS__get_expedition_lockouts_by_char_id); -XS(XS__get_expedition_lockouts_by_char_id) { - dXSARGS; - if (items != 1 && items != 2) { - Perl_croak(aTHX_ "Usage: quest::get_expedition_lockouts_by_char_id(uint32 character_id, [string expedition_name])"); - } - - HV* hash = newHV(); // hash refcnt +1 (non-mortal, newRV_noinc to not inc) - SV* hash_ref = nullptr; // for expedition event hash if filtering on expedition - - uint32_t character_id = static_cast(SvUV(ST(0))); - std::string expedition_name; - if (items == 2) - { - expedition_name = SvPV_nolen(ST(1)); - } - - auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(character_id); +perl::reference Perl__get_expedition_lockouts_by_char_id(uint32 char_id) +{ + perl::hash table; + auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id); for (const auto& lockout : lockouts) { - uint32_t name_len = static_cast(lockout.GetExpeditionName().size()); - uint32_t event_len = static_cast(lockout.GetEventName().size()); - - // hashes are stored through references inside other hashes/arrays. we need - // to wrap newHV in newRV references when inserting nested hash values. - // we use newRV_noinc to not increment the hash's ref count; rv will own it - - SV** entry = hv_fetch(hash, lockout.GetExpeditionName().c_str(), name_len, false); - if (!entry) + if (!table.exists(lockout.GetExpeditionName())) { - // create expedition entry in hash with its value as ref to event hash - SV* event_hash_ref = newRV_noinc((SV*)newHV()); // ref takes ownership - if (!expedition_name.empty() && lockout.GetExpeditionName() == expedition_name) - { - hash_ref = event_hash_ref; // save ref for filtered expedition return - } - entry = hv_store(hash, lockout.GetExpeditionName().c_str(), name_len, event_hash_ref, 0); + table[lockout.GetExpeditionName()] = perl::reference(perl::hash()); } - // *entry is a reference to expedition's event hash (which it owns). the - // event entry in the hash will contain ref to a lockout detail hash - if (entry && SvROK(*entry) && SvTYPE(SvRV(*entry)) == SVt_PVHV) // is ref to hash type + perl::hash expedition_table = table[lockout.GetExpeditionName()]; + if (!expedition_table.exists(lockout.GetEventName())) { - HV* details_hash = newHV(); // refcnt +1, reference will take ownership - hv_store(details_hash, "remaining", strlen("remaining"), newSVuv(lockout.GetSecondsRemaining()), 0); - hv_store(details_hash, "uuid", strlen("uuid"), newSVpv(lockout.GetExpeditionUUID().c_str(), 0), 0); - - HV* event_hash = (HV*)SvRV(*entry); - hv_store(event_hash, lockout.GetEventName().c_str(), event_len, - (SV*)newRV_noinc((SV*)details_hash), 0); + expedition_table[lockout.GetEventName()] = perl::reference(perl::hash()); } + + perl::hash event_table = expedition_table[lockout.GetEventName()]; + event_table["remaining"] = lockout.GetSecondsRemaining(); + event_table["uuid"] = lockout.GetExpeditionUUID(); } - SV* rv = &PL_sv_undef; - - if (!expedition_name.empty()) - { - rv = hash_ref ? sv_2mortal(hash_ref) : &PL_sv_undef; // ref that owns event hash for expedition - } - else - { - rv = sv_2mortal(newRV_noinc((SV*)hash)); // takes ownership of expedition hash - } - - ST(0) = rv; - XSRETURN(1); + return perl::reference(table); } -XS(XS__add_expedition_lockout_all_clients); -XS(XS__add_expedition_lockout_all_clients) { - dXSARGS; - if (items != 3 && items != 4) { - Perl_croak(aTHX_ "Usage: quest::add_expedition_lockout_all_clients(string expedition_name, string event_name, uint32 seconds, [string uuid])"); - } +perl::reference Perl__get_expedition_lockouts_by_char_id(uint32 char_id, std::string expedition_name) +{ + perl::hash table; - std::string expedition_name = SvPV_nolen(ST(0)); - std::string event_name = SvPV_nolen(ST(1)); - uint32_t seconds = static_cast(SvUV(ST(2))); - std::string uuid; - - if (items == 4) + auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id); + for (const auto& lockout : lockouts) { - uuid = SvPV_nolen(ST(3)); + if (lockout.GetExpeditionName() == expedition_name) + { + if (!table.exists(lockout.GetEventName())) + { + table[lockout.GetEventName()] = perl::reference(perl::hash()); + } + perl::hash event_table = table[lockout.GetEventName()]; + event_table["remaining"] = lockout.GetSecondsRemaining(); + event_table["uuid"] = lockout.GetExpeditionUUID(); + } } + return perl::reference(table); +} + +void Perl__add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds) +{ + auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds); + Expedition::AddLockoutClients(lockout); +} + +void Perl__add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) +{ auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid); Expedition::AddLockoutClients(lockout); - - XSRETURN_EMPTY; } -XS(XS__add_expedition_lockout_by_char_id); -XS(XS__add_expedition_lockout_by_char_id) { - dXSARGS; - if (items != 4 && items != 5) { - Perl_croak(aTHX_ "Usage: quest::add_expedition_lockout_by_char_id(uint32 character_id, string expedition_name, string event_name, uint32 seconds, [string uuid])"); - } - - std::string uuid; - if (items == 5) - { - uuid = SvPV_nolen(ST(4)); - } - - uint32_t character_id = static_cast(SvUV(ST(0))); - std::string expedition_name = SvPV_nolen(ST(1)); - std::string event_name = SvPV_nolen(ST(2)); - uint32_t seconds = static_cast(SvUV(ST(3))); - - Expedition::AddLockoutByCharacterID(character_id, expedition_name, event_name, seconds, uuid); - - XSRETURN_EMPTY; +void Perl__add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds) +{ + Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds); } -XS(XS__remove_expedition_lockout_by_char_id); -XS(XS__remove_expedition_lockout_by_char_id) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: quest::remove_expedition_lockout_by_char_id(uint32 character_id, string expedition_name, string event_name)"); - } - - uint32_t character_id = static_cast(SvUV(ST(0))); - std::string expedition_name = SvPV_nolen(ST(1)); - std::string event_name = SvPV_nolen(ST(2)); - - Expedition::RemoveLockoutsByCharacterID(character_id, expedition_name, event_name); - - XSRETURN_EMPTY; +void Perl__add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) +{ + Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds, uuid); } -XS(XS__remove_all_expedition_lockouts_by_char_id); -XS(XS__remove_all_expedition_lockouts_by_char_id) { - dXSARGS; - if (items != 1 && items != 2) { - Perl_croak(aTHX_ "Usage: quest::remove_expedition_lockout_by_char_id(uint32 character_id, [string expedition_name])"); - } - - std::string expedition_name; - if (items == 2) - { - expedition_name = SvPV_nolen(ST(1)); - } - - uint32_t character_id = static_cast(SvUV(ST(0))); - Expedition::RemoveLockoutsByCharacterID(character_id, expedition_name); - - XSRETURN_EMPTY; +void Perl__remove_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name) +{ + Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name, event_name); } -XS(XS__createitem); -XS(XS__createitem) { - dXSARGS; - if (items < 1 || items > 9) { - Perl_croak(aTHX_ "Usage: quest::createitem(uint32 item_id, [int16 charges = 0, uint32 augment_one = 0, uint32 augment_two = 0, uint32 augment_three = 0, uint32 augment_four = 0, uint32 augment_five = 0, uint32 augment_six = 0, bool attuned = false])"); - } - - EQ::ItemInstance* RETVAL = nullptr; - uint32 item_id = (uint32)SvUV(ST(0)); - int16 charges = 0; - uint32 augment_one = 0; - uint32 augment_two = 0; - uint32 augment_three = 0; - uint32 augment_four = 0; - uint32 augment_five = 0; - uint32 augment_six = 0; - bool attuned = false; - if (items > 1) - charges = (int16)SvIV(ST(1)); - if (items > 2) - augment_one = (uint32)SvUV(ST(2)); - if (items > 3) - augment_two = (uint32)SvUV(ST(3)); - if (items > 4) - augment_three = (uint32)SvUV(ST(4)); - if (items > 5) - augment_four = (uint32)SvUV(ST(5)); - if (items > 6) - augment_five = (uint32)SvUV(ST(6)); - if (items > 7) - augment_six = (uint32)SvUV(ST(7)); - if (items > 8) - attuned = (bool)SvNV(ST(8)); - - if (database.GetItem(item_id)) { - RETVAL = database.CreateItem(item_id, charges, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six, attuned); - } - - ST(0) = sv_newmortal(); - if (RETVAL) { - sv_setref_pv(ST(0), "QuestItem", (void*)RETVAL); - } - XSRETURN(1); +void Perl__remove_all_expedition_lockouts_by_char_id(uint32 char_id) +{ + Expedition::RemoveLockoutsByCharacterID(char_id); } -XS(XS__secondstotime); -XS(XS__secondstotime) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::secondstotime(int duration)"); - } - - dXSTARG; - std::string time_string; - int duration = (int) SvIV(ST(0)); - time_string = quest_manager.secondstotime(duration); - sv_setpv(TARG, time_string.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +void Perl__remove_all_expedition_lockouts_by_char_id(uint32 char_id, std::string expedition_name) +{ + Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name); } -XS(XS__gethexcolorcode); -XS(XS__gethexcolorcode) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::gethexcolorcode(string color_name)"); - } - - dXSTARG; - std::string hex_color_code; - std::string color_name = SvPV_nolen(ST(0)); - hex_color_code = quest_manager.gethexcolorcode(color_name); - sv_setpv(TARG, hex_color_code.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +EQ::ItemInstance* Perl__createitem(uint32 item_id) +{ + return database.CreateItem(item_id); } -XS(XS__getaaexpmodifierbycharid); -XS(XS__getaaexpmodifierbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::getaaexpmodifierbycharid(uint32 character_id, uint32 zone_id)"); - - dXSTARG; - double aa_modifier; - uint32 character_id = (uint32) SvUV(ST(0)); - uint32 zone_id = (uint32) SvUV(ST(1)); - aa_modifier = quest_manager.GetAAEXPModifierByCharID(character_id, zone_id); - XSprePUSH; - PUSHn((double) aa_modifier); - XSRETURN(1); +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges) +{ + return database.CreateItem(item_id, charges); } -XS(XS__getexpmodifierbycharid); -XS(XS__getexpmodifierbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::getexpmodifierbycharid(uint32 character_id, uint32 zone_id)"); - - dXSTARG; - double exp_modifier; - uint32 character_id = (uint32) SvUV(ST(0)); - uint32 zone_id = (uint32) SvUV(ST(1)); - exp_modifier = quest_manager.GetEXPModifierByCharID(character_id, zone_id); - XSprePUSH; - PUSHn((double) exp_modifier); - XSRETURN(1); +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges, uint32 augment_one) +{ + return database.CreateItem(item_id, charges, augment_one); } -XS(XS__setaaexpmodifierbycharid); -XS(XS__setaaexpmodifierbycharid) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: quest::setaaexpmodifierbycharid(uint32 character_id, uint32 zone_id, float aa_modifier)"); - } - uint32 character_id = (uint32) SvUV(ST(0)); - uint32 zone_id = (uint32) SvUV(ST(1)); - double aa_modifier = (double) SvNV(ST(2)); +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges, uint32 augment_one, uint32 augment_two) +{ + return database.CreateItem(item_id, charges, augment_one, augment_two); +} + +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges, uint32 augment_one, uint32 augment_two, uint32 augment_three) +{ + return database.CreateItem(item_id, charges, augment_one, augment_two, augment_three); +} + +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four) +{ + return database.CreateItem(item_id, charges, augment_one, augment_two, augment_three, augment_four); +} + +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five) +{ + return database.CreateItem(item_id, charges, augment_one, augment_two, augment_three, augment_four, augment_five); +} + +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six) +{ + return database.CreateItem(item_id, charges, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six); +} + +EQ::ItemInstance* Perl__createitem(uint32 item_id, int16 charges, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six, bool attuned) +{ + return database.CreateItem(item_id, charges, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six, attuned); +} + +std::string Perl__secondstotime(int duration) +{ + return Strings::SecondsToTime(duration); +} + +uint32 Perl__timetoseconds(std::string time_string) +{ + return Strings::TimeToSeconds(time_string); +} + +std::string Perl__gethexcolorcode(std::string color_name) +{ + return quest_manager.gethexcolorcode(color_name); +} + +double Perl__getaaexpmodifierbycharid(uint32 character_id, uint32 zone_id) +{ + return quest_manager.GetAAEXPModifierByCharID(character_id, zone_id); +} + +double Perl__getaaexpmodifierbycharid(uint32 character_id, uint32 zone_id, int16 instance_version) +{ + return quest_manager.GetAAEXPModifierByCharID(character_id, zone_id, instance_version); +} + +double Perl__getexpmodifierbycharid(uint32 character_id, uint32 zone_id) +{ + return quest_manager.GetEXPModifierByCharID(character_id, zone_id); +} + +double Perl__getexpmodifierbycharid(uint32 character_id, uint32 zone_id, int16 instance_version) +{ + return quest_manager.GetEXPModifierByCharID(character_id, zone_id, instance_version); +} + +void Perl__setaaexpmodifierbycharid(uint32 character_id, uint32 zone_id, double aa_modifier) +{ quest_manager.SetAAEXPModifierByCharID(character_id, zone_id, aa_modifier); - XSRETURN_EMPTY; } -XS(XS__setexpmodifierbycharid); -XS(XS__setexpmodifierbycharid) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: quest::setexpmodifierbycharid(uint32 character_id, uint32 zone_id, float exp_modifier)"); - } - uint32 character_id = (uint32) SvUV(ST(0)); - uint32 zone_id = (uint32) SvUV(ST(1)); - double exp_modifier = (double) SvNV(ST(2)); +void Perl__setaaexpmodifierbycharid(uint32 character_id, uint32 zone_id, double aa_modifier, int16 instance_version) +{ + quest_manager.SetAAEXPModifierByCharID(character_id, zone_id, aa_modifier, instance_version); +} + +void Perl__setexpmodifierbycharid(uint32 character_id, uint32 zone_id, double exp_modifier) +{ quest_manager.SetEXPModifierByCharID(character_id, zone_id, exp_modifier); - XSRETURN_EMPTY; } -XS(XS__getcleannpcnamebyid); -XS(XS__getcleannpcnamebyid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getcleannpcnamebyid(uint32 npc_id)"); - - dXSTARG; - uint32 npc_id = (uint32) SvUV(ST(0)); - auto npc_name = quest_manager.getcleannpcnamebyid(npc_id); - sv_setpv(TARG, npc_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +void Perl__setexpmodifierbycharid(uint32 character_id, uint32 zone_id, double exp_modifier, int16 instance_version) +{ + quest_manager.SetEXPModifierByCharID(character_id, zone_id, exp_modifier, instance_version); } -XS(XS__getgendername); -XS(XS__getgendername) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getgendername(uint32 gender_id)"); - - dXSTARG; - uint32 gender_id = (uint32) SvUV(ST(0)); - auto gender_name = quest_manager.getgendername(gender_id); - sv_setpv(TARG, gender_name.c_str()); +std::string Perl__getcleannpcnamebyid(uint32 npc_id) +{ + return quest_manager.getcleannpcnamebyid(npc_id); } -XS(XS__getdeityname); -XS(XS__getdeityname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getdeityname(uint32 deity_id)"); - - dXSTARG; - uint32 deity_id = (uint32) SvUV(ST(0)); - auto deity_name = quest_manager.getdeityname(deity_id); - sv_setpv(TARG, deity_name.c_str()); +std::string Perl__getgendername(uint32 gender_id) +{ + return quest_manager.getgendername(gender_id); } -XS(XS__getinventoryslotname); -XS(XS__getinventoryslotname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getinventoryslotname(int16 slot_id)"); - - dXSTARG; - int16 slot_id = (int16) SvIV(ST(0)); - auto slot_name = quest_manager.getinventoryslotname(slot_id); - sv_setpv(TARG, slot_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +std::string Perl__getdeityname(uint32 deity_id) +{ + return quest_manager.getdeityname(deity_id); } -XS(XS__rename); -XS(XS__rename) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::rename(string name)"); +std::string Perl__getinventoryslotname(int16 slot_id) +{ + return quest_manager.getinventoryslotname(slot_id); +} - std::string name = (std::string) SvPV_nolen(ST(0)); +void Perl__rename(std::string name) +{ quest_manager.rename(name); - XSRETURN_EMPTY; } -XS(XS__get_data_remaining); -XS(XS__get_data_remaining) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::get_data_remaining(string bucket_name)"); +std::string Perl__get_data_remaining(std::string bucket_name) +{ + return DataBucket::GetDataRemaining(bucket_name); +} - dXSTARG; - std::string bucket_name = (std::string) SvPV_nolen(ST(0)); +const int Perl__getitemstat(uint32 item_id, std::string identifier) +{ + return quest_manager.getitemstat(item_id, identifier); +} - sv_setpv(TARG, DataBucket::GetDataRemaining(bucket_name).c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +int Perl__getspellstat(uint32 spell_id, std::string stat_identifier) +{ + return quest_manager.getspellstat(spell_id, stat_identifier); } -XS(XS__getitemstat); -XS(XS__getitemstat) { - dXSARGS; - int stat_value; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::getitemstat(uint32 item_id, string stat_identifier)"); +int Perl__getspellstat(uint32 spell_id, std::string stat_identifier, uint8 slot) +{ + return quest_manager.getspellstat(spell_id, stat_identifier, slot); +} - dXSTARG; - uint32 item_id = (uint32) SvUV(ST(0)); - std::string stat_identifier = (std::string) SvPV_nolen(ST(1)); - stat_value = quest_manager.getitemstat(item_id, stat_identifier); +void Perl__crosszoneaddldonlossbycharid(int character_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Character, CZLDoNUpdateSubtype_AddLoss, character_id, theme_id); +} - XSprePUSH; - PUSHi((IV) stat_value); +void Perl__crosszoneaddldonlossbygroupid(int group_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Group, CZLDoNUpdateSubtype_AddLoss, group_id, theme_id); +} - XSRETURN(1); +void Perl__crosszoneaddldonlossbyraidid(int raid_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Raid, CZLDoNUpdateSubtype_AddLoss, raid_id, theme_id); } -XS(XS__getspellstat); -XS(XS__getspellstat) { - dXSARGS; - int stat_value; - if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: quest::getspellstat(uint32 spell_id, string stat_identifier, uint8 slot)"); +void Perl__crosszoneaddldonlossbyguildid(int guild_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Guild, CZLDoNUpdateSubtype_AddLoss, guild_id, theme_id); +} - dXSTARG; - uint32 spell_id = (uint32) SvUV(ST(0)); - std::string stat_identifier = (std::string) SvPV_nolen(ST(1)); - uint8 slot = 0; - if (items == 3) - slot = (uint8) SvUV(ST(2)); +void Perl__crosszoneaddldonlossbyexpeditionid(uint32 expedition_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Expedition, CZLDoNUpdateSubtype_AddLoss, expedition_id, theme_id); +} - stat_value = quest_manager.getspellstat(spell_id, stat_identifier, slot); +void Perl__crosszoneaddldonlossbyclientname(const char* client_name, uint32 theme_id) +{ + int update_identifier = 0; + int points = 1; + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_ClientName, CZLDoNUpdateSubtype_AddLoss, update_identifier, theme_id, points, client_name); +} - XSprePUSH; - PUSHi((IV) stat_value); +void Perl__crosszoneaddldonpointsbycharid(int character_id, uint32 theme_id, int points) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Character, CZLDoNUpdateSubtype_AddPoints, character_id, theme_id, points); +} - XSRETURN(1); +void Perl__crosszoneaddldonpointsbygroupid(int group_id, uint32 theme_id, int points) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Group, CZLDoNUpdateSubtype_AddPoints, group_id, theme_id, points); } -XS(XS__crosszoneaddldonlossbycharid); -XS(XS__crosszoneaddldonlossbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbycharid(int character_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; - int character_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonpointsbyraidid(int raid_id, uint32 theme_id, int points) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Raid, CZLDoNUpdateSubtype_AddPoints, raid_id, theme_id, points); } -XS(XS__crosszoneaddldonlossbygroupid); -XS(XS__crosszoneaddldonlossbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbygroupid(int group_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; - int group_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonpointsbyguildid(int guild_id, uint32 theme_id, int points) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Guild, CZLDoNUpdateSubtype_AddPoints, guild_id, theme_id, points); } -XS(XS__crosszoneaddldonlossbyraidid); -XS(XS__crosszoneaddldonlossbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyraidid(int raid_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; - int raid_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonpointsbyexpeditionid(uint32 expedition_id, uint32 theme_id, int points) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Expedition, CZLDoNUpdateSubtype_AddPoints, expedition_id, theme_id, points); } -XS(XS__crosszoneaddldonlossbyguildid); -XS(XS__crosszoneaddldonlossbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyguildid(int guild_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; - int guild_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonpointsbyclientname(const char* client_name, uint32 theme_id, int points) +{ + int update_identifier = 0; + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_ClientName, CZLDoNUpdateSubtype_AddPoints, update_identifier, theme_id, points, client_name); } -XS(XS__crosszoneaddldonlossbyexpeditionid); -XS(XS__crosszoneaddldonlossbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonwinbycharid(int character_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Character, CZLDoNUpdateSubtype_AddWin, character_id, theme_id); } -XS(XS__crosszoneaddldonlossbyclientname); -XS(XS__crosszoneaddldonlossbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyclientname(const char* client_name, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; - int update_identifier = 0; - int points = 1; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonwinbygroupid(int group_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Group, CZLDoNUpdateSubtype_AddWin, group_id, theme_id); } -XS(XS__crosszoneaddldonpointsbycharid); -XS(XS__crosszoneaddldonpointsbycharid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbycharid(int character_id, uint32 theme_id, int points)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; - int character_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - int points = (int) SvIV(ST(2)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id, points); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonwinbyraidid(int raid_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Raid, CZLDoNUpdateSubtype_AddWin, raid_id, theme_id); } -XS(XS__crosszoneaddldonpointsbygroupid); -XS(XS__crosszoneaddldonpointsbygroupid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbygroupid(int group_id, uint32 theme_id, int points)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; - int group_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - int points = (int) SvIV(ST(2)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id, points); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonwinbyguildid(int guild_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Guild, CZLDoNUpdateSubtype_AddWin, guild_id, theme_id); } -XS(XS__crosszoneaddldonpointsbyraidid); -XS(XS__crosszoneaddldonpointsbyraidid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyraidid(int raid_id, uint32 theme_id, int points)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; - int raid_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - int points = (int) SvIV(ST(2)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id, points); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonwinbyexpeditionid(uint32 expedition_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Expedition, CZLDoNUpdateSubtype_AddWin, expedition_id, theme_id); } -XS(XS__crosszoneaddldonpointsbyguildid); -XS(XS__crosszoneaddldonpointsbyguildid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyguildid(int guild_id, uint32 theme_id, int points)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; - int guild_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - int points = (int) SvIV(ST(2)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id, points); - } - XSRETURN_EMPTY; +void Perl__crosszoneaddldonwinbyclientname(const char* client_name, uint32 theme_id) +{ + int update_identifier = 0; + int points = 1; + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_ClientName, CZLDoNUpdateSubtype_AddWin, update_identifier, theme_id, points, client_name); } -XS(XS__crosszoneaddldonpointsbyexpeditionid); -XS(XS__crosszoneaddldonpointsbyexpeditionid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyexpeditionid(uint32 expedition_id, uint32 theme_id, int points)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - int points = (int) SvIV(ST(2)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id, points); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbycharid(int character_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_AssignTask, character_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneaddldonpointsbyclientname); -XS(XS__crosszoneaddldonpointsbyclientname) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyclientname(const char* client_name, uint32 theme_id, int points)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - int points = (int) SvIV(ST(2)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbycharid(int character_id, uint32 task_id, bool enforce_level_requirement) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_AssignTask, character_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneaddldonwinbycharid); -XS(XS__crosszoneaddldonwinbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbycharid(int character_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; - int character_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbygroupid(int group_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_AssignTask, group_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneaddldonwinbygroupid); -XS(XS__crosszoneaddldonwinbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbygroupid(int group_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; - int group_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbygroupid(int group_id, uint32 task_id, bool enforce_level_requirement) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_AssignTask, group_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneaddldonwinbyraidid); -XS(XS__crosszoneaddldonwinbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyraidid(int raid_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; - int raid_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyraidid(int raid_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_AssignTask, raid_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneaddldonwinbyguildid); -XS(XS__crosszoneaddldonwinbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyguildid(int guild_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; - int guild_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyraidid(int raid_id, uint32 task_id, bool enforce_level_requirement) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_AssignTask, raid_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneaddldonwinbyexpeditionid); -XS(XS__crosszoneaddldonwinbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyguildid(int guild_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_AssignTask, guild_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneaddldonwinbyclientname); -XS(XS__crosszoneaddldonwinbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyclientname(const char* client_name, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; - int update_identifier = 0; - int points = 1; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyguildid(int guild_id, uint32 task_id, bool enforce_level_requirement) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_AssignTask, guild_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneassigntaskbycharid); -XS(XS__crosszoneassigntaskbycharid) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneassigntaskbycharid(int character_id, uint32 task_identifier, [bool enforce_level_requirement = false])"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZTaskUpdateSubtype_AssignTask; - int character_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvIV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - enforce_level_requirement = (bool) SvTRUE(ST(2)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, character_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyexpeditionid(uint32 expedition_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_AssignTask, expedition_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneassigntaskbygroupid); -XS(XS__crosszoneassigntaskbygroupid) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneassigntaskbygroupid(int group_id, uint32 task_identifier, [bool enforce_level_requirement = false])"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZTaskUpdateSubtype_AssignTask; - int group_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvIV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - enforce_level_requirement = (bool) SvTRUE(ST(2)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, group_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyexpeditionid(uint32 expedition_id, uint32 task_id, bool enforce_level_requirement) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_AssignTask, expedition_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneassigntaskbyraidid); -XS(XS__crosszoneassigntaskbyraidid) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneassigntaskbyraidid(int raid_id, uint32 task_identifier, [bool enforce_level_requirement = false])"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZTaskUpdateSubtype_AssignTask; - int raid_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvIV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - enforce_level_requirement = (bool) SvTRUE(ST(2)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, raid_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyclientname(const char* client_name, uint32 task_id) +{ + int update_identifier = 0; + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_AssignTask, update_identifier, task_id, task_subidentifier, update_count, enforce_level_requirement, client_name); } -XS(XS__crosszoneassigntaskbyguildid); -XS(XS__crosszoneassigntaskbyguildid) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneassigntaskbyguildid(int guild_id, uint32 task_identifier, [bool enforce_level_requirement = false])"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZTaskUpdateSubtype_AssignTask; - int guild_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvIV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - enforce_level_requirement = (bool) SvTRUE(ST(2)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, guild_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneassigntaskbyclientname(const char* client_name, uint32 task_id, bool enforce_level_requirement) +{ + int update_identifier = 0; + int task_subidentifier = -1; + int update_count = 1; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_AssignTask, update_identifier, task_id, task_subidentifier, update_count, enforce_level_requirement, client_name); } -XS(XS__crosszoneassigntaskbyexpeditionid); -XS(XS__crosszoneassigntaskbyexpeditionid) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneassigntaskbyexpeditionid(uint32 expedition_id, uint32 task_identifier, [bool enforce_level_requirement = false])"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZTaskUpdateSubtype_AssignTask; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 task_identifier = (uint32) SvIV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - enforce_level_requirement = (bool) SvTRUE(ST(2)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, expedition_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonecastspellbycharid(int character_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Character, CZSpellUpdateSubtype_Cast, character_id, spell_id); } -XS(XS__crosszoneassigntaskbyclientname); -XS(XS__crosszoneassigntaskbyclientname) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneassigntaskbyclientname(const char* client_name, uint32 task_identifier, [bool enforce_level_requirement = false])"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZTaskUpdateSubtype_AssignTask; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 task_identifier = (uint32) SvIV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - enforce_level_requirement = (bool) SvTRUE(ST(2)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, update_identifier, task_identifier, task_subidentifier, update_count, enforce_level_requirement, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonecastspellbygroupid(int group_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Group, CZSpellUpdateSubtype_Cast, group_id, spell_id); } -XS(XS__crosszonecastspellbycharid); -XS(XS__crosszonecastspellbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonecastspellbycharid(int character_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZSpellUpdateSubtype_Cast; - int character_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvIV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, character_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszonecastspellbyraidid(int raid_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Raid, CZSpellUpdateSubtype_Cast, raid_id, spell_id); } -XS(XS__crosszonecastspellbygroupid); -XS(XS__crosszonecastspellbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonecastspellbygroupid(int group_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZSpellUpdateSubtype_Cast; - int group_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvIV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, group_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszonecastspellbyguildid(int guild_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Guild, CZSpellUpdateSubtype_Cast, guild_id, spell_id); } -XS(XS__crosszonecastspellbyraidid); -XS(XS__crosszonecastspellbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonecastspellbyraidid(int raid_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZSpellUpdateSubtype_Cast; - int raid_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvIV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, raid_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszonecastspellbyexpeditionid(uint32 expedition_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Expedition, CZSpellUpdateSubtype_Cast, expedition_id, spell_id); } -XS(XS__crosszonecastspellbyguildid); -XS(XS__crosszonecastspellbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonecastspellbyguildid(int guild_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZSpellUpdateSubtype_Cast; - int guild_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, guild_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszonecastspellbyclientname(const char* client_name, uint32 spell_id) +{ + int update_identifier = 0; + quest_manager.CrossZoneSpell(CZUpdateType_ClientName, CZSpellUpdateSubtype_Cast, update_identifier, spell_id, client_name); } -XS(XS__crosszonecastspellbyexpeditionid); -XS(XS__crosszonecastspellbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonecastspellbyexpeditionid(uint32 expedition_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZSpellUpdateSubtype_Cast; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, expedition_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszonedialoguewindowbycharid(int character_id, const char* message) +{ + quest_manager.CrossZoneDialogueWindow(CZUpdateType_Character, character_id, message); } -XS(XS__crosszonecastspellbyclientname); -XS(XS__crosszonecastspellbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonecastspellbyclientname(const char* client_name, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZSpellUpdateSubtype_Cast; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, update_identifier, spell_id, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonedialoguewindowbygroupid(int group_id, const char* message) +{ + quest_manager.CrossZoneDialogueWindow(CZUpdateType_Group, group_id, message); } -XS(XS__crosszonedialoguewindowbycharid); -XS(XS__crosszonedialoguewindowbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedialoguewindowbycharid(int character_id, string message)"); - { - uint8 update_type = CZUpdateType_Character; - int character_id = (int) SvIV(ST(0)); - const char* message = (const char*) SvPV_nolen(ST(1)); - quest_manager.CrossZoneDialogueWindow(update_type, character_id, message); - } - XSRETURN_EMPTY; +void Perl__crosszonedialoguewindowbyraidid(int raid_id, const char* message) +{ + quest_manager.CrossZoneDialogueWindow(CZUpdateType_Raid, raid_id, message); } -XS(XS__crosszonedialoguewindowbygroupid); -XS(XS__crosszonedialoguewindowbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedialoguewindowbygroupid(int group_id, string message)"); - { - uint8 update_type = CZUpdateType_Group; - int group_id = (int) SvIV(ST(0)); - const char* message = (const char*) SvPV_nolen(ST(1)); - quest_manager.CrossZoneDialogueWindow(update_type, group_id, message); - } - XSRETURN_EMPTY; +void Perl__crosszonedialoguewindowbyguildid(int guild_id, const char* message) +{ + quest_manager.CrossZoneDialogueWindow(CZUpdateType_Guild, guild_id, message); } -XS(XS__crosszonedialoguewindowbyraidid); -XS(XS__crosszonedialoguewindowbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedialoguewindowbyraidid(int raid_id, string message)"); - { - uint8 update_type = CZUpdateType_Raid; - int raid_id = (int) SvIV(ST(0)); - const char* message = (const char*) SvPV_nolen(ST(1)); - quest_manager.CrossZoneDialogueWindow(update_type, raid_id, message); - } - XSRETURN_EMPTY; +void Perl__crosszonedialoguewindowbyexpeditionid(uint32 expedition_id, const char* message) +{ + quest_manager.CrossZoneDialogueWindow(CZUpdateType_Expedition, expedition_id, message); } -XS(XS__crosszonedialoguewindowbyguildid); -XS(XS__crosszonedialoguewindowbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedialoguewindowbyguildid(int guild_id, string message)"); - { - uint8 update_type = CZUpdateType_Guild; - int guild_id = (int) SvIV(ST(0)); - const char* message = (const char*) SvPV_nolen(ST(1)); - quest_manager.CrossZoneDialogueWindow(update_type, guild_id, message); - } - XSRETURN_EMPTY; +void Perl__crosszonedialoguewindowbyclientname(const char* client_name, const char* message) +{ + int update_identifier = 0; + quest_manager.CrossZoneDialogueWindow(CZUpdateType_ClientName, update_identifier, message, client_name); } -XS(XS__crosszonedialoguewindowbyexpeditionid); -XS(XS__crosszonedialoguewindowbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedialoguewindowbyexpeditionid(uint32 expedition_id, string message)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint32 expedition_id = (uint32) SvUV(ST(0)); - const char* message = (const char*) SvPV_nolen(ST(1)); - quest_manager.CrossZoneDialogueWindow(update_type, expedition_id, message); - } - XSRETURN_EMPTY; +void Perl__crosszonedisabletaskbycharid(int character_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_DisableTask, character_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonedialoguewindowbyclientname); -XS(XS__crosszonedialoguewindowbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedialoguewindowbyclientname(const char* client_name, string message)"); - { - uint8 update_type = CZUpdateType_ClientName; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - const char* message = (const char*) SvPV_nolen(ST(1)); - quest_manager.CrossZoneDialogueWindow(update_type, update_identifier, message, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonedisabletaskbygroupid(int group_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_DisableTask, group_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonedisabletaskbycharid); -XS(XS__crosszonedisabletaskbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedisabletaskbycharid(int character_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZTaskUpdateSubtype_DisableTask; - int character_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, character_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonedisabletaskbyraidid(int raid_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_DisableTask, raid_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonedisabletaskbygroupid); -XS(XS__crosszonedisabletaskbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedisabletaskbygroupid(int group_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZTaskUpdateSubtype_DisableTask; - int group_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, group_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonedisabletaskbyguildid(int guild_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_DisableTask, guild_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonedisabletaskbyraidid); -XS(XS__crosszonedisabletaskbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedisabletaskbyraidid(int raid_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZTaskUpdateSubtype_DisableTask; - int raid_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, raid_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonedisabletaskbyexpeditionid(uint32 expedition_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_DisableTask, expedition_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonedisabletaskbyguildid); -XS(XS__crosszonedisabletaskbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedisabletaskbyguildid(int guild_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZTaskUpdateSubtype_DisableTask; - int guild_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, guild_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonedisabletaskbyclientname(const char* client_name, uint32 task_id) +{ + int update_identifier = 0; + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_DisableTask, update_identifier, task_id, task_subidentifier, update_count, enforce_level_requirement, client_name); } -XS(XS__crosszonedisabletaskbyexpeditionid); -XS(XS__crosszonedisabletaskbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedisabletaskbyexpeditionid(uint32 expedition_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZTaskUpdateSubtype_DisableTask; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, expedition_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneenabletaskbycharid(int character_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_EnableTask, character_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonedisabletaskbyclientname); -XS(XS__crosszonedisabletaskbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonedisabletaskbyclientname(const char* client_name, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZTaskUpdateSubtype_DisableTask; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, update_identifier, task_identifier, task_subidentifier, update_count, enforce_level_requirement, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneenabletaskbygroupid(int group_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_EnableTask, group_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneenabletaskbycharid); -XS(XS__crosszoneenabletaskbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneenabletaskbycharid(int character_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZTaskUpdateSubtype_EnableTask; - int character_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, character_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneenabletaskbyraidid(int raid_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_EnableTask, raid_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneenabletaskbygroupid); -XS(XS__crosszoneenabletaskbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneenabletaskbygroupid(int group_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZTaskUpdateSubtype_EnableTask; - int group_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, group_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneenabletaskbyguildid(int guild_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_EnableTask, guild_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneenabletaskbyraidid); -XS(XS__crosszoneenabletaskbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneenabletaskbyraidid(int raid_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZTaskUpdateSubtype_EnableTask; - int raid_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, raid_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneenabletaskbyexpeditionid(uint32 expedition_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_EnableTask, expedition_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneenabletaskbyguildid); -XS(XS__crosszoneenabletaskbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneenabletaskbyguildid(int guild_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZTaskUpdateSubtype_EnableTask; - int guild_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, guild_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneenabletaskbyclientname(const char* client_name, uint32 task_id) +{ + int update_identifier = 0; + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_EnableTask, update_identifier, task_id, task_subidentifier, update_count, enforce_level_requirement, client_name); } -XS(XS__crosszoneenabletaskbyexpeditionid); -XS(XS__crosszoneenabletaskbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneenabletaskbyexpeditionid(uint32 expedition_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZTaskUpdateSubtype_EnableTask; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, expedition_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonefailtaskbycharid(int character_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_FailTask, character_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneenabletaskbyclientname); -XS(XS__crosszoneenabletaskbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneenabletaskbyclientname(const char* client_name, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZTaskUpdateSubtype_EnableTask; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, update_identifier, task_identifier, task_subidentifier, update_count, enforce_level_requirement, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonefailtaskbygroupid(int group_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_FailTask, group_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonefailtaskbycharid); -XS(XS__crosszonefailtaskbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonefailtaskbycharid(int character_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZTaskUpdateSubtype_FailTask; - int character_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, character_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonefailtaskbyraidid(int raid_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_FailTask, raid_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonefailtaskbygroupid); -XS(XS__crosszonefailtaskbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonefailtaskbygroupid(int group_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZTaskUpdateSubtype_FailTask; - int group_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, group_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonefailtaskbyguildid(int guild_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_FailTask, guild_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonefailtaskbyraidid); -XS(XS__crosszonefailtaskbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonefailtaskbyraidid(int raid_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZTaskUpdateSubtype_FailTask; - int raid_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, raid_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonefailtaskbyexpeditionid(uint32 expedition_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_FailTask, expedition_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszonefailtaskbyguildid); -XS(XS__crosszonefailtaskbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonefailtaskbyguildid(int guild_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZTaskUpdateSubtype_FailTask; - int guild_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, guild_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonefailtaskbyclientname(const char* client_name, uint32 task_id) +{ + int update_identifier = 0; + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_FailTask, update_identifier, task_id, task_subidentifier, update_count, enforce_level_requirement, client_name); } -XS(XS__crosszonefailtaskbyexpeditionid); -XS(XS__crosszonefailtaskbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonefailtaskbyexpeditionid(uint32 expedition_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZTaskUpdateSubtype_FailTask; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, expedition_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonemarqueebycharid(int character_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message) +{ + quest_manager.CrossZoneMarquee(CZUpdateType_Character, character_id, type, priority, fade_in, fade_out, duration, message); } -XS(XS__crosszonefailtaskbyclientname); -XS(XS__crosszonefailtaskbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonefailtaskbyclientname(const char* client_name, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZTaskUpdateSubtype_FailTask; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, update_identifier, task_identifier, task_subidentifier, update_count, enforce_level_requirement, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonemarqueebygroupid(int group_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message) +{ + quest_manager.CrossZoneMarquee(CZUpdateType_Group, group_id, type, priority, fade_in, fade_out, duration, message); } -XS(XS__crosszonemarqueebycharid); -XS(XS__crosszonemarqueebycharid) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: quest::crosszonemarqueebycharid(int character_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message)"); - { - uint8 update_type = CZUpdateType_Character; - int character_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - int priority = (int) SvIV(ST(2)); - int fade_in = (int) SvIV(ST(3)); - int fade_out = (int) SvIV(ST(4)); - int duration = (int) SvIV(ST(5)); - char *message = (char *) SvPV_nolen(ST(6)); - quest_manager.CrossZoneMarquee(update_type, character_id, type, priority, fade_in, fade_out, duration, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemarqueebyraidid(int raid_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message) +{ + quest_manager.CrossZoneMarquee(CZUpdateType_Raid, raid_id, type, priority, fade_in, fade_out, duration, message); } -XS(XS__crosszonemarqueebygroupid); -XS(XS__crosszonemarqueebygroupid) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: quest::crosszonemarqueebygroupid(int group_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message)"); - { - uint8 update_type = CZUpdateType_Group; - int group_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - int priority = (int) SvIV(ST(2)); - int fade_in = (int) SvIV(ST(3)); - int fade_out = (int) SvIV(ST(4)); - int duration = (int) SvIV(ST(5)); - char *message = (char *) SvPV_nolen(ST(6)); - quest_manager.CrossZoneMarquee(update_type, group_id, type, priority, fade_in, fade_out, duration, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemarqueebyguildid(int guild_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message) +{ + quest_manager.CrossZoneMarquee(CZUpdateType_Guild, guild_id, type, priority, fade_in, fade_out, duration, message); } -XS(XS__crosszonemarqueebyraidid); -XS(XS__crosszonemarqueebyraidid) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: quest::crosszonemarqueebyraidid(int raid_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message)"); - { - uint8 update_type = CZUpdateType_Raid; - int raid_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - int priority = (int) SvIV(ST(2)); - int fade_in = (int) SvIV(ST(3)); - int fade_out = (int) SvIV(ST(4)); - int duration = (int) SvIV(ST(5)); - char *message = (char *) SvPV_nolen(ST(6)); - quest_manager.CrossZoneMarquee(update_type, raid_id, type, priority, fade_in, fade_out, duration, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemarqueebyexpeditionid(uint32 expedition_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message) +{ + quest_manager.CrossZoneMarquee(CZUpdateType_Expedition, expedition_id, type, priority, fade_in, fade_out, duration, message); } -XS(XS__crosszonemarqueebyguildid); -XS(XS__crosszonemarqueebyguildid) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: quest::crosszonemarqueebyguildid(int guild_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message)"); - { - uint8 update_type = CZUpdateType_Guild; - int guild_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - int priority = (int) SvIV(ST(2)); - int fade_in = (int) SvIV(ST(3)); - int fade_out = (int) SvIV(ST(4)); - int duration = (int) SvIV(ST(5)); - char *message = (char *) SvPV_nolen(ST(6)); - quest_manager.CrossZoneMarquee(update_type, guild_id, type, priority, fade_in, fade_out, duration, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemarqueebyclientname(const char* client_name, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message) +{ + int update_identifier = 0; + quest_manager.CrossZoneMarquee(CZUpdateType_ClientName, update_identifier, type, priority, fade_in, fade_out, duration, message, client_name); } -XS(XS__crosszonemarqueebyexpeditionid); -XS(XS__crosszonemarqueebyexpeditionid) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: quest::crosszonemarqueebyexpeditionid(uint32 expedition_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - int priority = (int) SvIV(ST(2)); - int fade_in = (int) SvIV(ST(3)); - int fade_out = (int) SvIV(ST(4)); - int duration = (int) SvIV(ST(5)); - char *message = (char *) SvPV_nolen(ST(6)); - quest_manager.CrossZoneMarquee(update_type, expedition_id, type, priority, fade_in, fade_out, duration, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemessageplayerbycharid(int character_id, uint32 type, const char* message) +{ + quest_manager.CrossZoneMessage(CZUpdateType_Character, character_id, type, message); } -XS(XS__crosszonemarqueebyclientname); -XS(XS__crosszonemarqueebyclientname) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: quest::crosszonemarqueebyclientname(const char* client_name, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message)"); - { - uint8 update_type = CZUpdateType_ClientName; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - int priority = (int) SvIV(ST(2)); - int fade_in = (int) SvIV(ST(3)); - int fade_out = (int) SvIV(ST(4)); - int duration = (int) SvIV(ST(5)); - char *message = (char *) SvPV_nolen(ST(6)); - quest_manager.CrossZoneMarquee(update_type, update_identifier, type, priority, fade_in, fade_out, duration, message, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonemessageplayerbygroupid(int group_id, uint32 type, const char* message) +{ + quest_manager.CrossZoneMessage(CZUpdateType_Group, group_id, type, message); } -XS(XS__crosszonemessageplayerbycharid); -XS(XS__crosszonemessageplayerbycharid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbycharid(int character_id, uint32 type, const char* message)"); - { - uint8 update_type = CZUpdateType_Character; - int character_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - const char* message = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneMessage(update_type, character_id, type, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemessageplayerbyraidid(int raid_id, uint32 type, const char* message) +{ + quest_manager.CrossZoneMessage(CZUpdateType_Raid, raid_id, type, message); } -XS(XS__crosszonemessageplayerbygroupid); -XS(XS__crosszonemessageplayerbygroupid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbygroupid(int group_id, uint32 type, const char* message)"); - { - uint8 update_type = CZUpdateType_Group; - int group_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - const char* message = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneMessage(update_type, group_id, type, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemessageplayerbyguildid(int guild_id, uint32 type, const char* message) +{ + quest_manager.CrossZoneMessage(CZUpdateType_Guild, guild_id, type, message); } -XS(XS__crosszonemessageplayerbyraidid); -XS(XS__crosszonemessageplayerbyraidid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbyraidid(int raid_id, uint32 type, const char* message)"); - { - uint8 update_type = CZUpdateType_Raid; - int raid_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - const char* message = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneMessage(update_type, raid_id, type, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemessageplayerbyexpeditionid(uint32 expedition_id, uint32 type, const char* message) +{ + quest_manager.CrossZoneMessage(CZUpdateType_Expedition, expedition_id, type, message); } -XS(XS__crosszonemessageplayerbyguildid); -XS(XS__crosszonemessageplayerbyguildid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbyguildid(int guild_id, uint32 type, const char* message)"); - { - uint8 update_type = CZUpdateType_Guild; - int guild_id = (int) SvIV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - const char* message = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneMessage(update_type, guild_id, type, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemessageplayerbyname(const char* client_name, uint32 type, const char* message) +{ + int update_identifier = 0; + quest_manager.CrossZoneMessage(CZUpdateType_ClientName, update_identifier, type, message, client_name); } -XS(XS__crosszonemessageplayerbyexpeditionid); -XS(XS__crosszonemessageplayerbyexpeditionid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbyexpeditionid(uint32 expedition_id, uint32 type, const char* message)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - const char* message = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneMessage(update_type, expedition_id, type, message); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveplayerbycharid(int character_id, const char* zone_short_name) +{ + uint16 instance_id = 0; + quest_manager.CrossZoneMove(CZUpdateType_Character, CZMoveUpdateSubtype_MoveZone, character_id, zone_short_name, instance_id); } -XS(XS__crosszonemessageplayerbyname); -XS(XS__crosszonemessageplayerbyname) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbyname(const char* client_name, uint32 type, const char* message)"); - { - uint8 update_type = CZUpdateType_ClientName; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 type = (uint32) SvUV(ST(1)); - const char* message = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneMessage(update_type, update_identifier, type, message, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveplayerbygroupid(int group_id, const char* zone_short_name) +{ + uint16 instance_id = 0; + quest_manager.CrossZoneMove(CZUpdateType_Group, CZMoveUpdateSubtype_MoveZone, group_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveplayerbycharid); -XS(XS__crosszonemoveplayerbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveplayerbycharid(int character_id, string zone_short_name)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZone; - int character_id = (int) SvIV(ST(0)); - const char* zone_short_name = (const char*) SvPV_nolen(ST(1)); - uint16 instance_id = 0; - quest_manager.CrossZoneMove(update_type, update_subtype, character_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveplayerbyraidid(int raid_id, const char* zone_short_name) +{ + uint16 instance_id = 0; + quest_manager.CrossZoneMove(CZUpdateType_Raid, CZMoveUpdateSubtype_MoveZone, raid_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveplayerbygroupid); -XS(XS__crosszonemoveplayerbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveplayerbygroupid(int group_id, string zone_short_name)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZone; - int group_id = (int) SvIV(ST(0)); - const char* zone_short_name = (const char*) SvPV_nolen(ST(1)); - uint16 instance_id = 0; - quest_manager.CrossZoneMove(update_type, update_subtype, group_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveplayerbyguildid(int guild_id, const char* zone_short_name) +{ + uint16 instance_id = 0; + quest_manager.CrossZoneMove(CZUpdateType_Guild, CZMoveUpdateSubtype_MoveZone, guild_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveplayerbyraidid); -XS(XS__crosszonemoveplayerbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveplayerbyraidid(int raid_id, string zone_short_name)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZone; - int raid_id = (int) SvIV(ST(0)); - const char* zone_short_name = (const char*) SvPV_nolen(ST(1)); - uint16 instance_id = 0; - quest_manager.CrossZoneMove(update_type, update_subtype, raid_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveplayerbyexpeditionid(uint32 expedition_id, const char* zone_short_name) +{ + uint16 instance_id = 0; + quest_manager.CrossZoneMove(CZUpdateType_Expedition, CZMoveUpdateSubtype_MoveZone, expedition_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveplayerbyguildid); -XS(XS__crosszonemoveplayerbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveplayerbyguildid(int guild_id, string zone_short_name)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZone; - int guild_id = (int) SvIV(ST(0)); - const char* zone_short_name = (const char*) SvPV_nolen(ST(1)); - uint16 instance_id = 0; - quest_manager.CrossZoneMove(update_type, update_subtype, guild_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveplayerbyname(const char* client_name, const char* zone_short_name) +{ + int update_identifier = 0; + uint16 instance_id = 0; + quest_manager.CrossZoneMove(CZUpdateType_ClientName, CZMoveUpdateSubtype_MoveZone, update_identifier, zone_short_name, instance_id, client_name); } -XS(XS__crosszonemoveplayerbyexpeditionid); -XS(XS__crosszonemoveplayerbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveplayerbyexpeditionid(uint32 expedition_id, string zone_short_name)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZone; - uint32 expedition_id = (uint32) SvUV(ST(0)); - const char* zone_short_name = (const char*) SvPV_nolen(ST(1)); - uint16 instance_id = 0; - quest_manager.CrossZoneMove(update_type, update_subtype, expedition_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveinstancebycharid(int character_id, uint16 instance_id) +{ + const char* zone_short_name = ""; + quest_manager.CrossZoneMove(CZUpdateType_Character, CZMoveUpdateSubtype_MoveZoneInstance, character_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveplayerbyname); -XS(XS__crosszonemoveplayerbyname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveplayerbyname(const char* client_name, string zone_short_name)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZone; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - const char* zone_short_name = (const char*) SvPV_nolen(ST(1)); - uint16 instance_id = 0; - quest_manager.CrossZoneMove(update_type, update_subtype, update_identifier, zone_short_name, instance_id, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveinstancebygroupid(int group_id, uint16 instance_id) +{ + const char* zone_short_name = ""; + quest_manager.CrossZoneMove(CZUpdateType_Group, CZMoveUpdateSubtype_MoveZoneInstance, group_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveinstancebycharid); -XS(XS__crosszonemoveinstancebycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveinstancebycharid(int character_id, uint16 instance_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZoneInstance; - const char* zone_short_name = ""; - int character_id = (int) SvIV(ST(0)); - uint16 instance_id = (uint16) SvUV(ST(1)); - quest_manager.CrossZoneMove(update_type, update_subtype, character_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveinstancebyraidid(int raid_id, uint16 instance_id) +{ + const char* zone_short_name = ""; + quest_manager.CrossZoneMove(CZUpdateType_Raid, CZMoveUpdateSubtype_MoveZoneInstance, raid_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveinstancebygroupid); -XS(XS__crosszonemoveinstancebygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveinstancebygroupid(int group_id, uint16 instance_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZoneInstance; - const char* zone_short_name = ""; - int group_id = (int) SvIV(ST(0)); - uint16 instance_id = (uint16) SvUV(ST(1)); - quest_manager.CrossZoneMove(update_type, update_subtype, group_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveinstancebyguildid(int guild_id, uint16 instance_id) +{ + const char* zone_short_name = ""; + quest_manager.CrossZoneMove(CZUpdateType_Guild, CZMoveUpdateSubtype_MoveZoneInstance, guild_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveinstancebyraidid); -XS(XS__crosszonemoveinstancebyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveinstancebyraidid(int raid_id, uint16 instance_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZoneInstance; - const char* zone_short_name = ""; - int raid_id = (int) SvIV(ST(0)); - uint16 instance_id = (uint16) SvUV(ST(1)); - quest_manager.CrossZoneMove(update_type, update_subtype, raid_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveinstancebyexpeditionid(uint32 expedition_id, uint16 instance_id) +{ + const char* zone_short_name = ""; + quest_manager.CrossZoneMove(CZUpdateType_Expedition, CZMoveUpdateSubtype_MoveZoneInstance, expedition_id, zone_short_name, instance_id); } -XS(XS__crosszonemoveinstancebyguildid); -XS(XS__crosszonemoveinstancebyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveinstancebyguildid(int guild_id, uint16 instance_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZoneInstance; - const char* zone_short_name = ""; - int guild_id = (int) SvIV(ST(0)); - uint16 instance_id = (uint16) SvUV(ST(1)); - quest_manager.CrossZoneMove(update_type, update_subtype, guild_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszonemoveinstancebyclientname(const char* client_name, uint16 instance_id) +{ + int update_identifier = 0; + const char* zone_short_name = ""; + quest_manager.CrossZoneMove(CZUpdateType_ClientName, CZMoveUpdateSubtype_MoveZoneInstance, update_identifier, zone_short_name, instance_id, client_name); } -XS(XS__crosszonemoveinstancebyexpeditionid); -XS(XS__crosszonemoveinstancebyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveinstancebyexpeditionid(uint32 expedition_id, uint16 instance_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZoneInstance; - const char* zone_short_name = ""; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint16 instance_id = (uint16) SvUV(ST(1)); - quest_manager.CrossZoneMove(update_type, update_subtype, expedition_id, zone_short_name, instance_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonlossbycharid(int character_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Character, CZLDoNUpdateSubtype_RemoveLoss, character_id, theme_id); } -XS(XS__crosszonemoveinstancebyclientname); -XS(XS__crosszonemoveinstancebyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonemoveinstancebyclientname(const char* client_name, uint16 instance_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZMoveUpdateSubtype_MoveZoneInstance; - const char* zone_short_name = ""; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint16 instance_id = (uint16) SvUV(ST(1)); - quest_manager.CrossZoneMove(update_type, update_subtype, update_identifier, zone_short_name, instance_id, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonlossbygroupid(int group_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Group, CZLDoNUpdateSubtype_RemoveLoss, group_id, theme_id); } -XS(XS__crosszoneremoveldonlossbycharid); -XS(XS__crosszoneremoveldonlossbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbycharid(int character_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; - int character_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonlossbyraidid(int raid_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Raid, CZLDoNUpdateSubtype_RemoveLoss, raid_id, theme_id); } -XS(XS__crosszoneremoveldonlossbygroupid); -XS(XS__crosszoneremoveldonlossbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbygroupid(int group_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; - int group_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonlossbyguildid(int guild_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Guild, CZLDoNUpdateSubtype_RemoveLoss, guild_id, theme_id); } -XS(XS__crosszoneremoveldonlossbyraidid); -XS(XS__crosszoneremoveldonlossbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyraidid(int raid_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; - int raid_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonlossbyexpeditionid(uint32 expedition_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Expedition, CZLDoNUpdateSubtype_RemoveLoss, expedition_id, theme_id); } -XS(XS__crosszoneremoveldonlossbyguildid); -XS(XS__crosszoneremoveldonlossbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyguildid(int guild_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; - int guild_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonlossbyclientname(const char* client_name, uint32 theme_id) +{ + int update_identifier = 0; + int points = 1; + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_ClientName, CZLDoNUpdateSubtype_RemoveLoss, update_identifier, theme_id, points, client_name); } -XS(XS__crosszoneremoveldonlossbyexpeditionid); -XS(XS__crosszoneremoveldonlossbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonwinbycharid(int character_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Character, CZLDoNUpdateSubtype_RemoveWin, character_id, theme_id); } -XS(XS__crosszoneremoveldonlossbyclientname); -XS(XS__crosszoneremoveldonlossbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyclientname(const char* client_name, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; - int update_identifier = 0; - int points = 1; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonwinbygroupid(int group_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Group, CZLDoNUpdateSubtype_RemoveWin, group_id, theme_id); } -XS(XS__crosszoneremoveldonwinbycharid); -XS(XS__crosszoneremoveldonwinbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbycharid(int character_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; - int character_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonwinbyraidid(int raid_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Raid, CZLDoNUpdateSubtype_RemoveWin, raid_id, theme_id); } -XS(XS__crosszoneremoveldonwinbygroupid); -XS(XS__crosszoneremoveldonwinbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbygroupid(int group_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; - int group_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonwinbyguildid(int guild_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Guild, CZLDoNUpdateSubtype_RemoveWin, guild_id, theme_id); } -XS(XS__crosszoneremoveldonwinbyraidid); -XS(XS__crosszoneremoveldonwinbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyraidid(int raid_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; - int raid_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonwinbyexpeditionid(uint32 expedition_id, uint32 theme_id) +{ + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_Expedition, CZLDoNUpdateSubtype_RemoveWin, expedition_id, theme_id); } -XS(XS__crosszoneremoveldonwinbyguildid); -XS(XS__crosszoneremoveldonwinbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyguildid(int guild_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; - int guild_id = (int) SvIV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremoveldonwinbyclientname(const char* client_name, uint32 theme_id) +{ + int update_identifier = 0; + int points = 1; + quest_manager.CrossZoneLDoNUpdate(CZUpdateType_ClientName, CZLDoNUpdateSubtype_RemoveWin, update_identifier, theme_id, points, client_name); } -XS(XS__crosszoneremoveldonwinbyexpeditionid); -XS(XS__crosszoneremoveldonwinbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovespellbycharid(int character_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Character, CZSpellUpdateSubtype_Remove, character_id, spell_id); } -XS(XS__crosszoneremoveldonwinbyclientname); -XS(XS__crosszoneremoveldonwinbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyclientname(const char* client_name, uint32 theme_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; - int update_identifier = 0; - int points = 1; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 theme_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovespellbygroupid(int group_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Group, CZSpellUpdateSubtype_Remove, group_id, spell_id); } -XS(XS__crosszoneremovespellbycharid); -XS(XS__crosszoneremovespellbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovespellbycharid(int character_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZSpellUpdateSubtype_Remove; - int character_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, character_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovespellbyraidid(int raid_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Raid, CZSpellUpdateSubtype_Remove, raid_id, spell_id); } -XS(XS__crosszoneremovespellbygroupid); -XS(XS__crosszoneremovespellbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovespellbygroupid(int group_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZSpellUpdateSubtype_Remove; - int group_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, group_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovespellbyguildid(int guild_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Guild, CZSpellUpdateSubtype_Remove, guild_id, spell_id); } -XS(XS__crosszoneremovespellbyraidid); -XS(XS__crosszoneremovespellbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovespellbyraidid(int raid_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZSpellUpdateSubtype_Remove; - int raid_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, raid_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovespellbyexpeditionid(uint32 expedition_id, uint32 spell_id) +{ + quest_manager.CrossZoneSpell(CZUpdateType_Expedition, CZSpellUpdateSubtype_Remove, expedition_id, spell_id); } -XS(XS__crosszoneremovespellbyguildid); -XS(XS__crosszoneremovespellbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovespellbyguildid(int guild_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZSpellUpdateSubtype_Remove; - int guild_id = (int) SvIV(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, guild_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovespellbyclientname(const char* client_name, uint32 spell_id) +{ + int update_identifier = 0; + quest_manager.CrossZoneSpell(CZUpdateType_ClientName, CZSpellUpdateSubtype_Remove, update_identifier, spell_id, client_name); } -XS(XS__crosszoneremovespellbyexpeditionid); -XS(XS__crosszoneremovespellbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovespellbyexpeditionid(uint32 expedition_id, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZSpellUpdateSubtype_Remove; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, expedition_id, spell_id); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovetaskbycharid(int character_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_RemoveTask, character_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneremovespellbyclientname); -XS(XS__crosszoneremovespellbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovespellbyclientname(const char* client_name, uint32 spell_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZSpellUpdateSubtype_Remove; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 spell_id = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSpell(update_type, update_subtype, update_identifier, spell_id, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovetaskbygroupid(int group_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_RemoveTask, group_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneremovetaskbycharid); -XS(XS__crosszoneremovetaskbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovetaskbycharid(int character_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZTaskUpdateSubtype_RemoveTask; - int character_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, character_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovetaskbyraidid(int raid_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_RemoveTask, raid_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneremovetaskbygroupid); -XS(XS__crosszoneremovetaskbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovetaskbygroupid(int group_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZTaskUpdateSubtype_RemoveTask; - int group_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, group_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovetaskbyguildid(int guild_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_RemoveTask, guild_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneremovetaskbyraidid); -XS(XS__crosszoneremovetaskbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovetaskbyraidid(int raid_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZTaskUpdateSubtype_RemoveTask; - int raid_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, raid_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovetaskbyexpeditionid(uint32 expedition_id, uint32 task_id) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_RemoveTask, expedition_id, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__crosszoneremovetaskbyguildid); -XS(XS__crosszoneremovetaskbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovetaskbyguildid(int guild_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZTaskUpdateSubtype_RemoveTask; - int guild_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, guild_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneremovetaskbyclientname(const char* client_name, uint32 task_id) +{ + int update_identifier = 0; + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_RemoveTask, update_identifier, task_id, task_subidentifier, update_count, enforce_level_requirement, client_name); } -XS(XS__crosszoneremovetaskbyexpeditionid); -XS(XS__crosszoneremovetaskbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovetaskbyexpeditionid(uint32 expedition_id, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZTaskUpdateSubtype_RemoveTask; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, expedition_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneresetactivitybycharid(int character_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_ActivityReset, character_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneremovetaskbyclientname); -XS(XS__crosszoneremovetaskbyclientname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszoneremovetaskbyclientname(const char* client_name, uint32 task_identifier)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZTaskUpdateSubtype_RemoveTask; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, update_identifier, task_identifier, task_subidentifier, update_count, enforce_level_requirement, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneresetactivitybygroupid(int group_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_ActivityReset, group_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneresetactivitybycharid); -XS(XS__crosszoneresetactivitybycharid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneresetactivitybycharid(int character_id, uint32 task_identifier, int activity_id)"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityReset; - int character_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int activity_id = (int) SvIV(ST(2)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, character_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneresetactivitybyraidid(int raid_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_ActivityReset, raid_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneresetactivitybygroupid); -XS(XS__crosszoneresetactivitybygroupid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneresetactivitybygroupid(int group_id, uint32 task_identifier, int activity_id)"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityReset; - int group_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int activity_id = (int) SvIV(ST(2)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, group_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneresetactivitybyguildid(int guild_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_ActivityReset, guild_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneresetactivitybyraidid); -XS(XS__crosszoneresetactivitybyraidid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneresetactivitybyraidid(int raid_id, uint32 task_identifier, int activity_id)"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityReset; - int raid_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int activity_id = (int) SvIV(ST(2)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, raid_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneresetactivitybyexpeditionid(uint32 expedition_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_ActivityReset, expedition_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneresetactivitybyguildid); -XS(XS__crosszoneresetactivitybyguildid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneresetactivitybyguildid(int guild_id, uint32 task_identifier, int activity_id)"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityReset; - int guild_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int activity_id = (int) SvIV(ST(2)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, guild_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneresetactivitybyclientname(const char* client_name, uint32 task_id, int activity_id) +{ + int update_identifier = 0; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_ActivityReset, update_identifier, task_id, activity_id, update_count, enforce_level_requirement, client_name); } -XS(XS__crosszoneresetactivitybyexpeditionid); -XS(XS__crosszoneresetactivitybyexpeditionid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneresetactivitybyexpeditionid(uint32 expedition_id, uint32 task_identifier, int activity_id)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityReset; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int activity_id = (int) SvIV(ST(2)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, expedition_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszonesetentityvariablebycharid(int character_id, const char* variable_name, const char* variable_value) +{ + quest_manager.CrossZoneSetEntityVariable(CZUpdateType_Character, character_id, variable_name, variable_value); } -XS(XS__crosszoneresetactivitybyclientname); -XS(XS__crosszoneresetactivitybyclientname) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszoneresetactivitybyclientname(const char* client_name, uint32 task_identifier, int activity_id)"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityReset; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int activity_id = (int) SvIV(ST(2)); - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, update_identifier, task_identifier, task_subidentifier, update_count, enforce_level_requirement, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonesetentityvariablebygroupid(int group_id, const char* variable_name, const char* variable_value) +{ + quest_manager.CrossZoneSetEntityVariable(CZUpdateType_Group, group_id, variable_name, variable_value); } -XS(XS__crosszonesetentityvariablebycharid); -XS(XS__crosszonesetentityvariablebycharid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonesetentityvariablebycharid(int character_id, const char* variable_name, const char* variable_value)"); - { - uint8 update_type = CZUpdateType_Character; - int character_id = (int) SvIV(ST(0)); - const char* variable_name = (const char*) SvPV_nolen(ST(1)); - const char* variable_value = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariable(update_type, character_id, variable_name, variable_value); - } - XSRETURN_EMPTY; +void Perl__crosszonesetentityvariablebyraidid(int raid_id, const char* variable_name, const char* variable_value) +{ + quest_manager.CrossZoneSetEntityVariable(CZUpdateType_Raid, raid_id, variable_name, variable_value); } -XS(XS__crosszonesetentityvariablebygroupid); -XS(XS__crosszonesetentityvariablebygroupid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonesetentityvariablebygroupid(int group_id, const char* variable_name, const char* variable_value)"); - { - uint8 update_type = CZUpdateType_Group; - int group_id = (int) SvIV(ST(0)); - const char* variable_name = (const char*) SvPV_nolen(ST(1)); - const char* variable_value = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariable(update_type, group_id, variable_name, variable_value); - } - XSRETURN_EMPTY; +void Perl__crosszonesetentityvariablebyguildid(int guild_id, const char* variable_name, const char* variable_value) +{ + quest_manager.CrossZoneSetEntityVariable(CZUpdateType_Guild, guild_id, variable_name, variable_value); } -XS(XS__crosszonesetentityvariablebyraidid); -XS(XS__crosszonesetentityvariablebyraidid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonesetentityvariablebyraidid(int raid_id, const char* variable_name, const char* variable_value)"); - { - uint8 update_type = CZUpdateType_Raid; - int raid_id = (int) SvIV(ST(0)); - const char* variable_name = (const char*) SvPV_nolen(ST(1)); - const char* variable_value = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariable(update_type, raid_id, variable_name, variable_value); - } - XSRETURN_EMPTY; +void Perl__crosszonesetentityvariablebyexpeditionid(uint32 expedition_id, const char* variable_name, const char* variable_value) +{ + quest_manager.CrossZoneSetEntityVariable(CZUpdateType_Expedition, expedition_id, variable_name, variable_value); } -XS(XS__crosszonesetentityvariablebyguildid); -XS(XS__crosszonesetentityvariablebyguildid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonesetentityvariablebyguildid(int guild_id, const char* variable_name, const char* variable_value)"); - { - uint8 update_type = CZUpdateType_Guild; - int guild_id = (int) SvIV(ST(0)); - const char* variable_name = (const char*) SvPV_nolen(ST(1)); - const char* variable_value = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariable(update_type, guild_id, variable_name, variable_value); - } - XSRETURN_EMPTY; +void Perl__crosszonesetentityvariablebyclientname(const char* client_name, const char* variable_name, const char* variable_value) +{ + int update_identifier = 0; + quest_manager.CrossZoneSetEntityVariable(CZUpdateType_ClientName, update_identifier, variable_name, variable_value, client_name); } -XS(XS__crosszonesetentityvariablebyexpeditionid); -XS(XS__crosszonesetentityvariablebyexpeditionid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonesetentityvariablebyexpeditionid(uint32 expedition_id, const char* variable_name, const char* variable_value)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint32 expedition_id = (uint32) SvUV(ST(0)); - const char* variable_name = (const char*) SvPV_nolen(ST(1)); - const char* variable_value = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariable(update_type, expedition_id, variable_name, variable_value); - } - XSRETURN_EMPTY; +void Perl__crosszonesetentityvariablebynpctypeid(int npc_id, const char* variable_name, const char* variable_value) +{ + quest_manager.CrossZoneSetEntityVariable(CZUpdateType_NPC, npc_id, variable_name, variable_value); } -XS(XS__crosszonesetentityvariablebyclientname); -XS(XS__crosszonesetentityvariablebyclientname) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonesetentityvariablebyclientname(const char* client_name, const char* variable_name, const char* variable_value)"); - { - uint8 update_type = CZUpdateType_ClientName; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - const char* variable_name = (const char*) SvPV_nolen(ST(1)); - const char* variable_value = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariable(update_type, update_identifier, variable_name, variable_value, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszonesignalclientbycharid(int character_id, int signal_id) +{ + quest_manager.CrossZoneSignal(CZUpdateType_Character, character_id, signal_id); } -XS(XS__crosszonesetentityvariablebynpctypeid); -XS(XS__crosszonesetentityvariablebynpctypeid) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: quest::crosszonesetentityvariablebynpctypeid(int npc_id, const char* variable_name, const char* variable_value)"); - { - uint8 update_type = CZUpdateType_NPC; - int npc_id = (int) SvIV(ST(0)); - const char* variable_name = (const char*) SvPV_nolen(ST(1)); - const char* variable_value = (const char*) SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariable(update_type, npc_id, variable_name, variable_value); - } - XSRETURN_EMPTY; +void Perl__crosszonesignalclientbygroupid(int group_id, int signal_id) +{ + quest_manager.CrossZoneSignal(CZUpdateType_Group, group_id, signal_id); } -XS(XS__crosszonesignalclientbycharid); -XS(XS__crosszonesignalclientbycharid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonesignalclientbycharid(int character_id, uint32 signal)"); - { - uint8 update_type = CZUpdateType_Character; - int character_id = (int) SvIV(ST(0)); - uint32 signal = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSignal(update_type, character_id, signal); - } - XSRETURN_EMPTY; +void Perl__crosszonesignalclientbyraidid(int raid_id, int signal_id) +{ + quest_manager.CrossZoneSignal(CZUpdateType_Raid, raid_id, signal_id); } -XS(XS__crosszonesignalclientbygroupid); -XS(XS__crosszonesignalclientbygroupid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonesignalclientbygroupid(int group_id, uint32 signal)"); - { - uint8 update_type = CZUpdateType_Group; - int group_id = (int) SvIV(ST(0)); - uint32 signal = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSignal(update_type, group_id, signal); - } - XSRETURN_EMPTY; +void Perl__crosszonesignalclientbyguildid(int guild_id, int signal_id) +{ + quest_manager.CrossZoneSignal(CZUpdateType_Guild, guild_id, signal_id); } -XS(XS__crosszonesignalclientbyraidid); -XS(XS__crosszonesignalclientbyraidid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonesignalclientbyraidid(int raid_id, uint32 signal)"); - { - uint8 update_type = CZUpdateType_Raid; - int raid_id = (int) SvIV(ST(0)); - uint32 signal = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSignal(update_type, raid_id, signal); - } - XSRETURN_EMPTY; +void Perl__crosszonesignalclientbyexpeditionid(uint32 expedition_id, int signal_id) +{ + quest_manager.CrossZoneSignal(CZUpdateType_Expedition, expedition_id, signal_id); } -XS(XS__crosszonesignalclientbyguildid); -XS(XS__crosszonesignalclientbyguildid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonesignalclientbyguildid(int guild_id, uint32 signal)"); - { - uint8 update_type = CZUpdateType_Guild; - int guild_id = (int) SvIV(ST(0)); - uint32 signal = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSignal(update_type, guild_id, signal); - } - XSRETURN_EMPTY; +void Perl__crosszonesignalclientbyname(const char* client_name, int signal_id) +{ + int update_identifier = 0; + quest_manager.CrossZoneSignal(CZUpdateType_Expedition, update_identifier, signal_id, client_name); } -XS(XS__crosszonesignalclientbyexpeditionid); -XS(XS__crosszonesignalclientbyexpeditionid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonesignalclientbyexpeditionid(uint32 expedition_id, uint32 signal)"); - { - uint8 update_type = CZUpdateType_Expedition; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 signal = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSignal(update_type, expedition_id, signal); - } - XSRETURN_EMPTY; +void Perl__crosszonesignalnpcbynpctypeid(uint32 npc_id, int signal_id) +{ + quest_manager.CrossZoneSignal(CZUpdateType_NPC, npc_id, signal_id); } -XS(XS__crosszonesignalclientbyname); -XS(XS__crosszonesignalclientbyname) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonesignalclientbyname(const char* client_name, uint32 signal)"); - { - uint8 update_type = CZUpdateType_Expedition; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 signal = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSignal(update_type, update_identifier, signal, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybycharid(int character_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_ActivityUpdate, character_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszonesignalnpcbynpctypeid); -XS(XS__crosszonesignalnpcbynpctypeid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::crosszonesignalnpcbynpctypeid(uint32 npc_id, uint32 signal)"); - { - uint8 update_type = CZUpdateType_NPC; - uint32 npc_id = (uint32) SvUV(ST(0)); - uint32 signal = (uint32) SvUV(ST(1)); - quest_manager.CrossZoneSignal(update_type, npc_id, signal); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybycharid(int character_id, uint32 task_id, int activity_id, int update_count) +{ + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Character, CZTaskUpdateSubtype_ActivityUpdate, character_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneupdateactivitybycharid); -XS(XS__crosszoneupdateactivitybycharid) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: quest::crosszoneupdateactivitybycharid(int character_id, uint32 task_identifier, int activity_id, [int update_count = 1])"); - { - uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityUpdate; - int character_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = (int) SvIV(ST(2)); - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 4) - update_count = (int) SvIV(ST(3)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, character_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybygroupid(int group_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_ActivityUpdate, group_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneupdateactivitybygroupid); -XS(XS__crosszoneupdateactivitybygroupid) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: quest::crosszoneupdateactivitybygroupid(int group_id, uint32 task_identifier, int activity_id, [int update_count = 1])"); - { - uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityUpdate; - int group_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = (int) SvIV(ST(2)); - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 4) - update_count = (int) SvIV(ST(3)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, group_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybygroupid(int group_id, uint32 task_id, int activity_id, int update_count) +{ + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Group, CZTaskUpdateSubtype_ActivityUpdate, group_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneupdateactivitybyraidid); -XS(XS__crosszoneupdateactivitybyraidid) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: quest::crosszoneupdateactivitybyraidid(int raid_id, uint32 task_identifier, int activity_id, [int update_count = 1])"); - { - uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityUpdate; - int raid_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = (int) SvIV(ST(2)); - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 4) - update_count = (int) SvIV(ST(3)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, raid_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybyraidid(int raid_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_ActivityUpdate, raid_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneupdateactivitybyguildid); -XS(XS__crosszoneupdateactivitybyguildid) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: quest::crosszoneupdateactivitybyguildid(int guild_id, uint32 task_identifier, int activity_id, [int update_count = 1])"); - { - uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityUpdate; - int guild_id = (int) SvIV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = (int) SvIV(ST(2)); - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 4) - update_count = (int) SvIV(ST(3)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, guild_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybyraidid(int raid_id, uint32 task_id, int activity_id, int update_count) +{ + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Raid, CZTaskUpdateSubtype_ActivityUpdate, raid_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneupdateactivitybyexpeditionid); -XS(XS__crosszoneupdateactivitybyexpeditionid) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: quest::crosszoneupdateactivitybyexpeditionid(uint32 expedition_id, uint32 task_identifier, int activity_id, [int update_count = 1])"); - { - uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityUpdate; - uint32 expedition_id = (uint32) SvUV(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = (int) SvIV(ST(2)); - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 4) - update_count = (int) SvIV(ST(3)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, expedition_id, task_identifier, task_subidentifier, update_count, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybyguildid(int guild_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_ActivityUpdate, guild_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__crosszoneupdateactivitybyclientname); -XS(XS__crosszoneupdateactivitybyclientname) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: quest::crosszoneupdateactivitybyclientname(const char* client_name, uint32 task_identifier, int activity_id, [int update_count = 1])"); - { - uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZTaskUpdateSubtype_ActivityUpdate; - int update_identifier = 0; - const char* client_name = (const char*) SvPV_nolen(ST(0)); - uint32 task_identifier = (uint32) SvUV(ST(1)); - int task_subidentifier = (int) SvIV(ST(2)); - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 4) - update_count = (int) SvIV(ST(3)); - - quest_manager.CrossZoneTaskUpdate(update_type, update_subtype, update_identifier, task_identifier, task_subidentifier, update_count, enforce_level_requirement, client_name); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybyguildid(int guild_id, uint32 task_id, int activity_id, int update_count) +{ + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Guild, CZTaskUpdateSubtype_ActivityUpdate, guild_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__worldwideaddldonloss); -XS(XS__worldwideaddldonloss) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideaddldonloss(uint32 theme_id, [min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_AddLoss; - uint32 theme_id = (uint32)SvUV(ST(0)); - int points = 1; - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8)SvUV(ST(1)); - - if (items == 3) - max_status = (uint8)SvUV(ST(2)); - - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__crosszoneupdateactivitybyexpeditionid(uint32 expedition_id, uint32 task_id, int activity_id) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_ActivityUpdate, expedition_id, task_id, activity_id, update_count, enforce_level_requirement); } -XS(XS__worldwideaddldonpoints); -XS(XS__worldwideaddldonpoints) { - dXSARGS; - if (items < 1 || items > 4) - Perl_croak(aTHX_ "Usage: quest::worldwideaddldonpoints(uint32 theme_id. [int points = 1, min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_AddPoints; - uint32 theme_id = (uint32)SvUV(ST(0)); - int points = 1; - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - points = (int)SvIV(ST(1)); +void Perl__crosszoneupdateactivitybyexpeditionid(uint32 expedition_id, uint32 task_id, int activity_id, int update_count) +{ + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_Expedition, CZTaskUpdateSubtype_ActivityUpdate, expedition_id, task_id, activity_id, update_count, enforce_level_requirement); +} - if (items == 3) - min_status = (uint8)SvUV(ST(2)); +void Perl__crosszoneupdateactivitybyclientname(const char* client_name, uint32 task_id, int activity_id) +{ + int update_identifier = 0; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_ActivityUpdate, update_identifier, task_id, activity_id, update_count, enforce_level_requirement, client_name); +} - if (items == 4) - max_status = (uint8)SvUV(ST(3)); +void Perl__crosszoneupdateactivitybyclientname(const char* client_name, uint32 task_id, int activity_id, int update_count) +{ + int update_identifier = 0; + bool enforce_level_requirement = false; + quest_manager.CrossZoneTaskUpdate(CZUpdateType_ClientName, CZTaskUpdateSubtype_ActivityUpdate, update_identifier, task_id, activity_id, update_count, enforce_level_requirement, client_name); +} - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideaddldonloss(uint32 theme_id) +{ + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddLoss, theme_id); } -XS(XS__worldwideaddldonwin); -XS(XS__worldwideaddldonwin) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideaddldonwin(uint32 theme_id, [min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_AddWin; - uint32 theme_id = (uint32)SvUV(ST(0)); - int points = 1; - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8)SvUV(ST(1)); - - if (items == 3) - max_status = (uint8)SvUV(ST(2)); - - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideaddldonloss(uint32 theme_id, uint8 min_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddLoss, theme_id, points, min_status); } -XS(XS__worldwideassigntask); -XS(XS__worldwideassigntask) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideassigntask(uint32 task_identifier, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint8 update_type = WWTaskUpdateType_AssignTask; - uint32 task_identifier = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideTaskUpdate(update_type, task_identifier, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideaddldonloss(uint32 theme_id, uint8 min_status, uint8 max_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddLoss, theme_id, points, min_status, max_status); } -XS(XS__worldwidecastspell); -XS(XS__worldwidecastspell) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwidecastspell(uint32 spell_id, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint8 update_type = WWSpellUpdateType_Cast; - uint32 spell_id = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); +void Perl__worldwideaddldonpoints(uint32 theme_id) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddPoints, theme_id, points); +} - if (items == 3) - max_status = (uint8) SvUV(ST(2)); +void Perl__worldwideaddldonpoints(uint32 theme_id, int points) +{ + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddPoints, theme_id, points); +} - quest_manager.WorldWideSpell(update_type, spell_id, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideaddldonpoints(uint32 theme_id, int points, uint8 min_status) +{ + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddPoints, theme_id, points, min_status); } -XS(XS__worldwidedialoguewindow); -XS(XS__worldwidedialoguewindow) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwidedialoguewindow(string message, [uint8 min_status = 0, uint8 max_status = 0])"); - { - const char* message = (const char*) SvPV_nolen(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8)SvUV(ST(1)); +void Perl__worldwideaddldonpoints(uint32 theme_id, int points, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddPoints, theme_id, points, min_status, max_status); +} - if (items == 3) - max_status = (uint8)SvUV(ST(2)); +void Perl__worldwideaddldonwin(uint32 theme_id) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddWin, theme_id, points); +} - quest_manager.WorldWideDialogueWindow(message, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideaddldonwin(uint32 theme_id, uint8 min_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddWin, theme_id, points, min_status); } -XS(XS__worldwidedisabletask); -XS(XS__worldwidedisabletask) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwidedisabletask(uint32 task_id, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint8 update_type = WWTaskUpdateType_DisableTask; - uint32 task_identifier = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideTaskUpdate(update_type, task_identifier, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideaddldonwin(uint32 theme_id, uint8 min_status, uint8 max_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_AddWin, theme_id, points, min_status, max_status); } -XS(XS__worldwideenabletask); -XS(XS__worldwideenabletask) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideenabletask(uint32 task_id, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint8 update_type = WWTaskUpdateType_EnableTask; - uint32 task_identifier = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideTaskUpdate(update_type, task_identifier, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideassigntask(uint32 task_id) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_AssignTask, task_id); } -XS(XS__worldwidefailtask); -XS(XS__worldwidefailtask) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwidefailtask(uint32 task_id, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint8 update_type = WWTaskUpdateType_FailTask; - uint32 task_identifier = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideTaskUpdate(update_type, task_identifier, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideassigntask(uint32 task_id, bool enforce_level_requirement) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_AssignTask, task_id, task_subidentifier, update_count, enforce_level_requirement); } -XS(XS__worldwidemarquee); -XS(XS__worldwidemarquee) { - dXSARGS; - if (items < 6 || items > 8) - Perl_croak(aTHX_ "Usage: quest::worldwidemarquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint32 type = (uint32) SvUV(ST(0)); - uint32 priority = (uint32) SvUV(ST(1)); - uint32 fade_in = (uint32) SvUV(ST(2)); - uint32 fade_out = (uint32) SvUV(ST(3)); - uint32 duration = (uint32) SvUV(ST(4)); - const char* message = (const char*) SvPV_nolen(ST(5)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 7) - min_status = (uint8) SvUV(ST(6)); - - if (items == 8) - max_status = (uint8) SvUV(ST(7)); - - quest_manager.WorldWideMarquee(type, priority, fade_in, fade_out, duration, message, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideassigntask(uint32 task_id, bool enforce_level_requirement, uint8 min_status) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_AssignTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status); } -XS(XS__worldwidemessage); -XS(XS__worldwidemessage) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: quest::worldwidemessage(uint32 type, const char* message, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint32 type = (uint32) SvUV(ST(0)); - const char* message = (const char*) SvPV_nolen(ST(1)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 3) - min_status = (uint8) SvUV(ST(2)); +void Perl__worldwideassigntask(uint32 task_id, bool enforce_level_requirement, uint8 min_status, uint8 max_status) +{ + int task_subidentifier = -1; + int update_count = 1; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_AssignTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); +} - if (items == 4) - max_status = (uint8) SvUV(ST(3)); +void Perl__worldwidecastspell(uint32 spell_id) +{ + quest_manager.WorldWideSpell(WWSpellUpdateType_Cast, spell_id); +} - quest_manager.WorldWideMessage(type, message, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwidecastspell(uint32 spell_id, uint8 min_status) +{ + quest_manager.WorldWideSpell(WWSpellUpdateType_Cast, spell_id, min_status); } -XS(XS__worldwidemove); -XS(XS__worldwidemove) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwidemove(const char* zone_short_name, [uint8 min_status = 0, uint8 max_status = 0])"); - { - uint8 update_type = WWMoveUpdateType_MoveZone; - const char* zone_short_name = (const char*) SvPV_nolen(ST(0)); - uint16 instance_id = 0; - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideMove(update_type, zone_short_name, instance_id, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwidecastspell(uint32 spell_id, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideSpell(WWSpellUpdateType_Cast, spell_id, min_status, max_status); } -XS(XS__worldwidemoveinstance); -XS(XS__worldwidemoveinstance) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwidemoveinstance(uint16 instance_id, [uint8 min_status = 0, uint max_status = 0])"); - { - uint8 update_type = WWMoveUpdateType_MoveZoneInstance; - const char* zone_short_name = ""; - uint16 instance_id = (uint16) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideMove(update_type, zone_short_name, instance_id, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwidedialoguewindow(const char* message) +{ + quest_manager.WorldWideDialogueWindow(message); } -XS(XS__worldwideremoveldonloss); -XS(XS__worldwideremoveldonloss) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideremoveldonloss(uint32 theme_id, [min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_RemoveLoss; - uint32 theme_id = (uint32)SvUV(ST(0)); - int points = 1; - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8)SvUV(ST(1)); - - if (items == 3) - max_status = (uint8)SvUV(ST(2)); - - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwidedialoguewindow(const char* message, uint8 min_status) +{ + quest_manager.WorldWideDialogueWindow(message, min_status); } -XS(XS__worldwideremoveldonwin); -XS(XS__worldwideremoveldonwin) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideremoveldonwin(uint32 theme_id, [min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_RemoveWin; - uint32 theme_id = (uint32)SvUV(ST(0)); - int points = 1; - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8)SvUV(ST(1)); - - if (items == 3) - max_status = (uint8)SvUV(ST(2)); - - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwidedialoguewindow(const char* message, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideDialogueWindow(message, min_status, max_status); } -XS(XS__worldwideremovespell); -XS(XS__worldwideremovespell) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideremovespell(uint32 spell_id, [uint8 min_status = 0, uint max_status = 0])"); - { - uint8 update_type = WWSpellUpdateType_Remove; - uint32 spell_id = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); +void Perl__worldwidedisabletask(uint32 task_id) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_DisableTask, task_id); +} - if (items == 3) - max_status = (uint8) SvUV(ST(2)); +void Perl__worldwidedisabletask(uint32 task_id, uint8 min_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_DisableTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status); +} - quest_manager.WorldWideSpell(update_type, spell_id, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwidedisabletask(uint32 task_id, uint8 min_status, uint8 max_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_DisableTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); } -XS(XS__worldwideremovetask); -XS(XS__worldwideremovetask) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideremovetask(uint32 task_identifier, [uint8 min_status = 0, uint max_status = 0])"); - { - uint8 update_type = WWTaskUpdateType_RemoveTask; - uint32 task_identifier = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - int task_subidentifier = -1; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideTaskUpdate(update_type, task_identifier, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); - } +void Perl__worldwideenabletask(uint32 task_id) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_EnableTask, task_id); +} - XSRETURN_EMPTY; +void Perl__worldwideenabletask(uint32 task_id, uint8 min_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_EnableTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status); } -XS(XS__worldwideresetactivity); -XS(XS__worldwideresetactivity) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: quest::worldwideresetactivity(uint32 task_identifier, int activity_id, [uint8 min_status = 0, uint max_status = 0])"); - { - uint8 update_type = WWTaskUpdateType_ActivityReset; - uint32 task_identifier = (uint32) SvUV(ST(0)); - int task_subidentifier = (int) SvIV(ST(1)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - min_status = (uint8) SvUV(ST(2)); - - if (items == 4) - max_status = (uint8) SvUV(ST(3)); - - quest_manager.WorldWideTaskUpdate(update_type, task_identifier, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwideenabletask(uint32 task_id, uint8 min_status, uint8 max_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_EnableTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); } -XS(XS__worldwidesetentityvariableclient); -XS(XS__worldwidesetentityvariableclient) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: quest::worldwidesetentityvariableclient(const char* variable_name, const char* variable_value, [uint8 min_status = 0, uint max_status = 0])"); - { - uint8 update_type = WWSetEntityVariableUpdateType_Character; - const char* variable_name = (const char*) SvPV_nolen(ST(0)); - const char* variable_value = (const char*) SvPV_nolen(ST(1)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 3) - min_status = (uint8) SvUV(ST(2)); - - if (items == 4) - max_status = (uint8) SvUV(ST(3)); - - quest_manager.WorldWideSetEntityVariable(update_type, variable_name, variable_value, min_status, max_status); - } - XSRETURN_EMPTY; +void Perl__worldwidefailtask(uint32 task_id) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_FailTask, task_id); +} + +void Perl__worldwidefailtask(uint32 task_id, uint8 min_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_FailTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status); +} + +void Perl__worldwidefailtask(uint32 task_id, uint8 min_status, uint8 max_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_FailTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); +} + +void Perl__worldwidemarquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message) +{ + quest_manager.WorldWideMarquee(type, priority, fade_in, fade_out, duration, message); +} + +void Perl__worldwidemarquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message, uint8 min_status) +{ + quest_manager.WorldWideMarquee(type, priority, fade_in, fade_out, duration, message, min_status); +} + +void Perl__worldwidemarquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideMarquee(type, priority, fade_in, fade_out, duration, message, min_status, max_status); +} + +void Perl__worldwidemessage(uint32 type, const char* message) +{ + quest_manager.WorldWideMessage(type, message); +} + +void Perl__worldwidemessage(uint32 type, const char* message, uint8 min_status) +{ + quest_manager.WorldWideMessage(type, message, min_status); +} + +void Perl__worldwidemessage(uint32 type, const char* message, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideMessage(type, message, min_status, max_status); +} + +void Perl__worldwidemove(const char* zone_short_name) +{ + quest_manager.WorldWideMove(WWMoveUpdateType_MoveZone, zone_short_name); +} + +void Perl__worldwidemove(const char* zone_short_name, uint8 min_status) +{ + uint16 instance_id = 0; + quest_manager.WorldWideMove(WWMoveUpdateType_MoveZone, zone_short_name, instance_id, min_status); +} + +void Perl__worldwidemove(const char* zone_short_name, uint8 min_status, uint8 max_status) +{ + uint16 instance_id = 0; + quest_manager.WorldWideMove(WWMoveUpdateType_MoveZone, zone_short_name, instance_id, min_status, max_status); +} + +void Perl__worldwidemoveinstance(uint16 instance_id) +{ + const char* zone_short_name = ""; + quest_manager.WorldWideMove(WWMoveUpdateType_MoveZoneInstance, zone_short_name, instance_id); +} + +void Perl__worldwidemoveinstance(uint16 instance_id, uint8 min_status) +{ + const char* zone_short_name = ""; + quest_manager.WorldWideMove(WWMoveUpdateType_MoveZoneInstance, zone_short_name, instance_id, min_status); +} + +void Perl__worldwidemoveinstance(uint16 instance_id, uint8 min_status, uint8 max_status) +{ + const char* zone_short_name = ""; + quest_manager.WorldWideMove(WWMoveUpdateType_MoveZoneInstance, zone_short_name, instance_id, min_status, max_status); +} + +void Perl__worldwideremoveldonloss(uint32 theme_id) +{ + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_RemoveLoss, theme_id); +} + +void Perl__worldwideremoveldonloss(uint32 theme_id, uint8 min_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_RemoveLoss, theme_id, points, min_status); +} + +void Perl__worldwideremoveldonloss(uint32 theme_id, uint8 min_status, uint8 max_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_RemoveLoss, theme_id, points, min_status, max_status); +} + +void Perl__worldwideremoveldonwin(uint32 theme_id) +{ + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_RemoveWin, theme_id); +} + +void Perl__worldwideremoveldonwin(uint32 theme_id, uint8 min_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_RemoveWin, theme_id, points, min_status); +} + +void Perl__worldwideremoveldonwin(uint32 theme_id, uint8 min_status, uint8 max_status) +{ + int points = 1; + quest_manager.WorldWideLDoNUpdate(CZLDoNUpdateSubtype_RemoveWin, theme_id, points, min_status, max_status); +} + +void Perl__worldwideremovespell(uint32 spell_id) +{ + quest_manager.WorldWideSpell(WWSpellUpdateType_Remove, spell_id); +} + +void Perl__worldwideremovespell(uint32 spell_id, uint8 min_status) +{ + quest_manager.WorldWideSpell(WWSpellUpdateType_Remove, spell_id, min_status); +} + +void Perl__worldwideremovespell(uint32 spell_id, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideSpell(WWSpellUpdateType_Remove, spell_id, min_status, max_status); +} + +void Perl__worldwideremovetask(uint32 task_id) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_RemoveTask, task_id); +} + +void Perl__worldwideremovetask(uint32 task_id, uint8 min_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_RemoveTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status); +} + +void Perl__worldwideremovetask(uint32 task_id, uint8 min_status, uint8 max_status) +{ + int task_subidentifier = -1; + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_RemoveTask, task_id, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); +} + +void Perl__worldwideresetactivity(uint32 task_id, int activity_id) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_ActivityReset, task_id); +} + +void Perl__worldwideresetactivity(uint32 task_id, int activity_id, uint8 min_status) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_ActivityReset, task_id, activity_id, update_count, enforce_level_requirement, min_status); +} + +void Perl__worldwideresetactivity(uint32 task_id, int activity_id, uint8 min_status, uint8 max_status) +{ + int update_count = 1; + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_ActivityReset, task_id, activity_id, update_count, enforce_level_requirement, min_status, max_status); +} + +void Perl__worldwidesetentityvariableclient(const char* variable_name, const char* variable_value) +{ + quest_manager.WorldWideSetEntityVariable(WWSetEntityVariableUpdateType_Character, variable_name, variable_value); +} + +void Perl__worldwidesetentityvariableclient(const char* variable_name, const char* variable_value, uint8 min_status) +{ + quest_manager.WorldWideSetEntityVariable(WWSetEntityVariableUpdateType_Character, variable_name, variable_value, min_status); +} + +void Perl__worldwidesetentityvariableclient(const char* variable_name, const char* variable_value, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideSetEntityVariable(WWSetEntityVariableUpdateType_Character, variable_name, variable_value, min_status, max_status); +} + +void Perl__worldwidesetentityvariablenpc(const char* variable_name, const char* variable_value) +{ + quest_manager.WorldWideSetEntityVariable(WWSetEntityVariableUpdateType_NPC, variable_name, variable_value); +} + +void Perl__worldwidesignalnpc(int signal_id) +{ + quest_manager.WorldWideSignal(WWSignalUpdateType_NPC, signal_id); +} + +void Perl__worldwidesignalclient(int signal_id) +{ + quest_manager.WorldWideSignal(WWSignalUpdateType_Character, signal_id); } -XS(XS__worldwidesetentityvariablenpc); -XS(XS__worldwidesetentityvariablenpc) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: quest::worldwidesetentityvariablenpc(const char* variable_name, const char* variable_value)"); +void Perl__worldwidesignalclient(int signal_id, uint8 min_status) +{ + quest_manager.WorldWideSignal(WWSignalUpdateType_Character, signal_id, min_status); +} + +void Perl__worldwidesignalclient(int signal_id, uint8 min_status, uint8 max_status) +{ + quest_manager.WorldWideSignal(WWSignalUpdateType_Character, signal_id, min_status, max_status); +} + +void Perl__worldwideupdateactivity(uint32 task_id, int activity_id) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_ActivityUpdate, task_id, activity_id); +} + +void Perl__worldwideupdateactivity(uint32 task_id, int activity_id, int update_count) +{ + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_ActivityUpdate, task_id, activity_id, update_count); +} + +void Perl__worldwideupdateactivity(uint32 task_id, int activity_id, int update_count, uint8 min_status) +{ + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_ActivityUpdate, task_id, activity_id, update_count, enforce_level_requirement, min_status); +} + +void Perl__worldwideupdateactivity(uint32 task_id, int activity_id, int update_count, uint8 min_status, uint8 max_status) +{ + bool enforce_level_requirement = false; + quest_manager.WorldWideTaskUpdate(WWTaskUpdateType_ActivityUpdate, task_id, activity_id, update_count, enforce_level_requirement, min_status, max_status); +} + +bool Perl__isnpcspawned(perl::array npc_id_array) +{ + std::vector npc_ids; + for (int i = 0; i < npc_id_array.size(); ++i) { - uint8 update_type = WWSetEntityVariableUpdateType_NPC; - const char* variable_name = (const char*) SvPV_nolen(ST(0)); - const char* variable_value = (const char*) SvPV_nolen(ST(1)); - quest_manager.WorldWideSetEntityVariable(update_type, variable_name, variable_value); + npc_ids.push_back(static_cast(npc_id_array[i])); } - XSRETURN_EMPTY; + return entity_list.IsNPCSpawned(npc_ids); } -XS(XS__worldwidesignalnpc); -XS(XS__worldwidesignalnpc) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::worldwidesignalnpc(uint32 signal)"); +uint32_t Perl__countspawnednpcs(perl::array npc_id_array) +{ + std::vector npc_ids; + for (int i = 0; i < npc_id_array.size(); ++i) { - uint8 update_type = WWSignalUpdateType_NPC; - uint32 signal = (uint32) SvUV(ST(0)); - quest_manager.WorldWideSignal(update_type, signal); + npc_ids.push_back(static_cast(npc_id_array[i])); } - XSRETURN_EMPTY; + return entity_list.CountSpawnedNPCs(npc_ids); } -XS(XS__worldwidesignalclient); -XS(XS__worldwidesignalclient) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwidesignalclient(uint32 signal, [uint8 min_status = 0, uint max_status = 0])"); - { - uint8 update_type = WWSignalUpdateType_Character; - uint32 signal = (uint32) SvUV(ST(0)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); +SPDat_Spell_Struct* Perl__getspell(uint32 spell_id) +{ + // should be safe, it's read only in perl (could also use proxy lika lua) + return const_cast(quest_manager.getspell(spell_id)); +} - if (items == 3) - max_status = (uint8) SvUV(ST(2)); +std::string Perl__getldonthemename(uint32 theme_id) +{ + return quest_manager.getldonthemename(theme_id); +} - quest_manager.WorldWideSignal(update_type, signal, min_status, max_status); - } - XSRETURN_EMPTY; +std::string Perl__getfactionname(int faction_id) +{ + return quest_manager.getfactionname(faction_id); } -XS(XS__worldwideupdateactivity); -XS(XS__worldwideupdateactivity) { - dXSARGS; - if (items < 2 || items > 5) - Perl_croak(aTHX_ "Usage: quest::worldwideupdateactivity(uint32 task_identifier, int activity_id, [int update_count = 1, uint8 min_status = 0, uint max_status = 0])"); - { - uint8 update_type = WWTaskUpdateType_ActivityUpdate; - uint32 task_identifier = (uint32) SvUV(ST(0)); - int task_subidentifier = (int) SvIV(ST(1)); - uint8 min_status = AccountStatus::Player; - uint8 max_status = AccountStatus::Player; - int update_count = 1; - bool enforce_level_requirement = false; - if (items == 3) - update_count = (int) SvIV(ST(2)); - - if (items == 4) - min_status = (uint8) SvUV(ST(3)); - - if (items == 5) - max_status = (uint8) SvUV(ST(4)); - - quest_manager.WorldWideTaskUpdate(update_type, task_identifier, task_subidentifier, update_count, enforce_level_requirement, min_status, max_status); +std::string Perl__getlanguagename(int language_id) +{ + return quest_manager.getlanguagename(language_id); +} + +std::string Perl__getbodytypename(uint32 bodytype_id) +{ + return quest_manager.getbodytypename(bodytype_id); +} + +std::string Perl__getconsiderlevelname(uint8 consider_level) +{ + return quest_manager.getconsiderlevelname(consider_level); +} + +std::string Perl__getenvironmentaldamagename(uint8 damage_type) +{ + return quest_manager.getenvironmentaldamagename(damage_type); +} + +std::string Perl__commify(perl::scalar number) +{ + return Strings::Commify(number.c_str()); +} + +bool Perl__checknamefilter(std::string name) +{ + return database.CheckNameFilter(name); +} + +void Perl__discordsend(std::string webhook_name, std::string message) +{ + zone->SendDiscordMessage(webhook_name, message); +} + +void Perl__tracknpc(uint32 entity_id) +{ + quest_manager.TrackNPC(entity_id); +} + +int Perl__getrecipemadecount(uint32 recipe_id) +{ + return quest_manager.GetRecipeMadeCount(recipe_id); +} + +std::string Perl__getrecipename(uint32 recipe_id) +{ + return quest_manager.GetRecipeName(recipe_id); +} + +bool Perl__hasrecipelearned(uint32 recipe_id) +{ + return quest_manager.HasRecipeLearned(recipe_id); +} + +bool Perl__IsRaining() +{ + if (!zone) { + return false; } - XSRETURN_EMPTY; + + return zone->IsRaining(); } -XS(XS__isnpcspawned); -XS(XS__isnpcspawned) { - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: quest::isnpcspawned(npc_id_one, npc_id_two, npc_idthree, npc_id_four, npc_id_five...[no limit])"); - { - std::vector npc_ids; - bool is_spawned = false; - for (int index = 0; index < items; index++) { - npc_ids.push_back((uint32)SvUV(ST(index))); - } - is_spawned = entity_list.IsNPCSpawned(npc_ids); - ST(0) = boolSV(is_spawned); - sv_2mortal(ST(0)); - XSRETURN(1); +bool Perl__IsSnowing() +{ + if (!zone) { + return false; } + + return zone->IsSnowing(); } -XS(XS__countspawnednpcs); -XS(XS__countspawnednpcs) { - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: quest::countspawnednpcs(npc_id_one, npc_id_two, npc_idthree, npc_id_four, npc_id_five...[no limit])"); - { - dXSTARG; - std::vector npc_ids; - uint32 npc_count = 0; - for (int index = 0; index < items; index++) { - npc_ids.push_back((uint32)SvUV(ST(index))); - } - npc_count = entity_list.CountSpawnedNPCs(npc_ids); - XSprePUSH; - PUSHu((UV) npc_count); - XSRETURN(1); +std::string Perl__getaaname(int aa_id) +{ + if (!zone) { + return std::string(); } + + return zone->GetAAName(aa_id); } -XS(XS__getspell); -XS(XS__getspell) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getspell(uint32 spell_id)"); - { - dXSTARG; - uint32 spell_id = (uint32) SvUV(ST(0)); - const SPDat_Spell_Struct* spell = quest_manager.getspell(spell_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Spell", (void *) spell); - XSRETURN(1); - } -} - -XS(XS__getldonthemename); -XS(XS__getldonthemename) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getldonthemename(uint32 theme_id)"); - { - dXSTARG; - uint32 theme_id = (uint32) SvUV(ST(0)); - std::string theme_name = quest_manager.getldonthemename(theme_id); - - sv_setpv(TARG, theme_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +std::string Perl__popupbreak() { + return DialogueWindow::Break(); +} + +std::string Perl__popupbreak(uint32 break_count) { + return DialogueWindow::Break(break_count); +} + +std::string Perl__popupcentermessage(std::string message) { + return DialogueWindow::CenterMessage(message); +} + +std::string Perl__popupcolormessage(std::string color, std::string message) { + return DialogueWindow::ColorMessage(color, message); +} + +std::string Perl__popupindent() { + return DialogueWindow::Indent(); +} + +std::string Perl__popupindent(uint32 indent_count) { + return DialogueWindow::Indent(indent_count); +} + +std::string Perl__popuplink(std::string link) { + return DialogueWindow::Link(link); +} + +std::string Perl__popuplink(std::string link, std::string message) { + return DialogueWindow::Link(link, message); +} + +std::string Perl__popuptable(std::string message) { + return DialogueWindow::Table(message); +} + +std::string Perl__popuptablecell() { + return DialogueWindow::TableCell(); +} + +std::string Perl__popuptablecell(std::string message) { + return DialogueWindow::TableCell(message); +} + +std::string Perl__popuptablerow(std::string message) { + return DialogueWindow::TableRow(message); +} + +void Perl__marquee(uint32 type, std::string message) +{ + quest_manager.marquee(type, message); +} + +void Perl__marquee(uint32 type, std::string message, uint32 duration) +{ + quest_manager.marquee(type, message, duration); +} + +void Perl__marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) +{ + quest_manager.marquee(type, priority, fade_in, fade_out, duration, message); +} + +void Perl__zonemarquee(uint32 type, std::string message) +{ + if (!zone) { + return; } + + entity_list.Marquee(type, message); } -XS(XS__getfactionname); -XS(XS__getfactionname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getfactionname(int faction_id)"); - { - dXSTARG; - int faction_id = (int) SvIV(ST(0)); - std::string faction_name = quest_manager.getfactionname(faction_id); - - sv_setpv(TARG, faction_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +void Perl__zonemarquee(uint32 type, std::string message, uint32 duration) +{ + if (!zone) { + return; } + + entity_list.Marquee(type, message, duration); } -XS(XS__getlanguagename); -XS(XS__getlanguagename) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getlanguagename(int language_id)"); - { - dXSTARG; - int language_id = (int) SvIV(ST(0)); - std::string language_name = quest_manager.getlanguagename(language_id); - - sv_setpv(TARG, language_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +void Perl__zonemarquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) +{ + if (!zone) { + return; } + + entity_list.Marquee(type, priority, fade_in, fade_out, duration, message); } -XS(XS__getbodytypename); -XS(XS__getbodytypename) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getbodytypename(uint32 bodytype_id)"); - { - dXSTARG; - uint32 bodytype_id = (uint32) SvUV(ST(0)); - std::string bodytype_name = quest_manager.getbodytypename(bodytype_id); - - sv_setpv(TARG, bodytype_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +bool Perl__ishotzone() +{ + if (!zone) { + return false; } + + return zone->IsHotzone(); } -XS(XS__getconsiderlevelname); -XS(XS__getconsiderlevelname) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getconsiderlevelname(uint8 consider_level)"); - { - dXSTARG; - uint8 consider_level = (uint8) SvUV(ST(0)); - std::string consider_level_name = quest_manager.getconsiderlevelname(consider_level); - - sv_setpv(TARG, consider_level_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); +void Perl__sethotzone(bool is_hotzone) +{ + if (!zone) { + return; } + + zone->SetIsHotzone(is_hotzone); +} + +void Perl__set_proximity_range(float x_range, float y_range) +{ + quest_manager.set_proximity_range(x_range, y_range); +} + +void Perl__set_proximity_range(float x_range, float y_range, float z_range) +{ + quest_manager.set_proximity_range(x_range, y_range, z_range); +} + +void Perl__set_proximity_range(float x_range, float y_range, float z_range, bool enable_say) +{ + quest_manager.set_proximity_range(x_range, y_range, z_range, enable_say); +} + +std::string Perl__varlink(uint32 item_id) +{ + return quest_manager.varlink(item_id); +} + +std::string Perl__varlink(uint32 item_id, int16 charges) +{ + return quest_manager.varlink(item_id, charges); +} + +std::string Perl__varlink(uint32 item_id, int16 charges, uint32 aug1) +{ + return quest_manager.varlink(item_id, charges, aug1); +} + +std::string Perl__varlink(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2) +{ + return quest_manager.varlink(item_id, charges, aug1, aug2); +} + +std::string Perl__varlink(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3) +{ + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3); +} + +std::string Perl__varlink(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4) +{ + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4); +} + +std::string Perl__varlink(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) +{ + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5); +} + +std::string Perl__varlink(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6) +{ + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6); +} + +std::string Perl__varlink(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, bool attuned) +{ + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6, attuned); } -XS(XS__getenvironmentaldamagename); -XS(XS__getenvironmentaldamagename) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getenvironmentaldamagename(uint8 damage_type)"); - - dXSTARG; - uint8 damage_type = (uint8) SvIV(ST(0)); - std::string environmental_damage_name = quest_manager.getenvironmentaldamagename(damage_type); - - sv_setpv(TARG, environmental_damage_name.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -XS(XS__commify); -XS(XS__commify) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::commify(string number)"); - - dXSTARG; - std::string number = (std::string) SvPV_nolen(ST(0)); - std::string commified_number = commify(number); - - sv_setpv(TARG, commified_number.c_str()); - XSprePUSH; - PUSHTARG; - XSRETURN(1); -} - -/* -This is the callback perl will look for to setup the -quest package's XSUBs -*/ -EXTERN_C XS(boot_quest); // prototype to pass -Wmissing-prototypes -EXTERN_C XS(boot_quest) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = '\0'; - - if (items != 1) - LogError("boot_quest does not take any arguments"); - - char buf[128]; //shouldent have any function names longer than this. - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK; - -#ifdef BOTS - newXS(strcpy(buf, "botquest"), XS__botquest, file); - newXS(strcpy(buf, "spawnbotcount"), XS__spawnbotcount, file); - newXS(strcpy(buf, "createbotcount"), XS__createbotcount, file); - newXS(strcpy(buf, "createBot"), XS__createBot, file); -#endif //BOTS - - newXS(strcpy(buf, "AssignGroupToInstance"), XS__AssignGroupToInstance, file); - newXS(strcpy(buf, "AssignRaidToInstance"), XS__AssignRaidToInstance, file); - newXS(strcpy(buf, "AssignToInstance"), XS__AssignToInstance, file); - newXS(strcpy(buf, "AssignToInstanceByCharID"), XS__AssignToInstanceByCharID, file); - newXS(strcpy(buf, "ChooseRandom"), XS__ChooseRandom, file); - newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file); - newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file); - newXS(strcpy(buf, "UpdateInstanceTimer"), XS__UpdateInstanceTimer, file); - newXS(strcpy(buf, "GetInstanceTimer"), XS__GetInstanceTimer, file); - newXS(strcpy(buf, "GetInstanceTimerByID"), XS__GetInstanceTimerByID, file); - newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file); - newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file); - newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file); - newXS(strcpy(buf, "GetCharactersInInstance"), XS__GetCharactersInInstance, file); - newXS(strcpy(buf, "GetInstanceID"), XS__GetInstanceID, file); - newXS(strcpy(buf, "GetInstanceIDByCharID"), XS__GetInstanceIDByCharID, file); - newXS(strcpy(buf, "GetSpellResistType"), XS__GetSpellResistType, file); - newXS(strcpy(buf, "GetSpellTargetType"), XS__GetSpellTargetType, file); - newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file); - newXS(strcpy(buf, "GetZoneID"), XS__GetZoneID, file); - newXS(strcpy(buf, "GetZoneLongName"), XS__GetZoneLongName, file); - newXS(strcpy(buf, "GetZoneLongNameByID"), XS__GetZoneLongNameByID, file); - newXS(strcpy(buf, "GetZoneShortName"), XS__GetZoneShortName, file); - newXS(strcpy(buf, "set_rule"), XS__set_rule, file); - newXS(strcpy(buf, "get_rule"), XS__get_rule, file); - newXS(strcpy(buf, "get_data"), XS__get_data, file); - newXS(strcpy(buf, "get_data_expires"), XS__get_data_expires, file); - newXS(strcpy(buf, "get_data_remaining"), XS__get_data_remaining, file); - newXS(strcpy(buf, "set_data"), XS__set_data, file); - newXS(strcpy(buf, "delete_data"), XS__delete_data, file); - newXS(strcpy(buf, "IsBeneficialSpell"), XS__IsBeneficialSpell, file); - newXS(strcpy(buf, "IsEffectInSpell"), XS__IsEffectInSpell, file); - newXS(strcpy(buf, "IsRunning"), XS__IsRunning, file); - newXS(strcpy(buf, "LearnRecipe"), XS__LearnRecipe, file); - newXS(strcpy(buf, "MerchantCountItem"), XS__MerchantCountItem, file); - newXS(strcpy(buf, "MerchantSetItem"), XS__MerchantSetItem, file); - newXS(strcpy(buf, "MovePCInstance"), XS__MovePCInstance, file); - newXS(strcpy(buf, "RemoveAllFromInstance"), XS__RemoveAllFromInstance, file); - newXS(strcpy(buf, "RemoveFromInstance"), XS__RemoveFromInstance, file); - newXS(strcpy(buf, "RemoveFromInstanceByCharID"), XS__RemoveFromInstanceByCharID, file); - newXS(strcpy(buf, "CheckInstanceByCharID"), XS__CheckInstanceByCharID, file); - newXS(strcpy(buf, "SendMail"), XS__SendMail, file); - newXS(strcpy(buf, "SetRunning"), XS__SetRunning, file); - newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file); - newXS(strcpy(buf, "activespeaktask"), XS__activespeaktask, file); - newXS(strcpy(buf, "activetasksinset"), XS__activetasksinset, file); - newXS(strcpy(buf, "add_expedition_lockout_all_clients"), XS__add_expedition_lockout_all_clients, file); - newXS(strcpy(buf, "add_expedition_lockout_by_char_id"), XS__add_expedition_lockout_by_char_id, file); - newXS(strcpy(buf, "addldonloss"), XS__addldonloss, file); - newXS(strcpy(buf, "addldonpoints"), XS__addldonpoints, file); - newXS(strcpy(buf, "addldonwin"), XS__addldonwin, file); - newXS(strcpy(buf, "addloot"), XS__addloot, file); - newXS(strcpy(buf, "addskill"), XS__addskill, file); - newXS(strcpy(buf, "assigntask"), XS__assigntask, file); - newXS(strcpy(buf, "attack"), XS__attack, file); - newXS(strcpy(buf, "attacknpc"), XS__attacknpc, file); - newXS(strcpy(buf, "attacknpctype"), XS__attacknpctype, file); - newXS(strcpy(buf, "buryplayercorpse"), XS__buryplayercorpse, file); - newXS(strcpy(buf, "castspell"), XS__castspell, file); - newXS(strcpy(buf, "changedeity"), XS__changedeity, file); - newXS(strcpy(buf, "checktitle"), XS__checktitle, file); - newXS(strcpy(buf, "clear_npctype_cache"), XS__clear_npctype_cache, file); - newXS(strcpy(buf, "clear_proximity"), XS__clear_proximity, file); - newXS(strcpy(buf, "clear_zone_flag"), XS__clear_zone_flag, file); - newXS(strcpy(buf, "clearspawntimers"), XS__clearspawntimers, file); - newXS(strcpy(buf, "collectitems"), XS__collectitems, file); - newXS(strcpy(buf, "commify"), XS__commify, file); - newXS(strcpy(buf, "completedtasksinset"), XS__completedtasksinset, file); - newXS(strcpy(buf, "countitem"), XS__countitem, file); - newXS(strcpy(buf, "countspawnednpcs"), XS__countspawnednpcs, file); - newXS(strcpy(buf, "createdoor"), XS__CreateDoor, file); - newXS(strcpy(buf, "creategroundobject"), XS__CreateGroundObject, file); - newXS(strcpy(buf, "creategroundobjectfrommodel"), XS__CreateGroundObjectFromModel, file); - newXS(strcpy(buf, "createguild"), XS__createguild, file); - newXS(strcpy(buf, "createitem"), XS__createitem, file); - newXS(strcpy(buf, "crosszoneaddldonlossbycharid"), XS__crosszoneaddldonlossbycharid, file); - newXS(strcpy(buf, "crosszoneaddldonlossbygroupid"), XS__crosszoneaddldonlossbygroupid, file); - newXS(strcpy(buf, "crosszoneaddldonlossbyraidid"), XS__crosszoneaddldonlossbyraidid, file); - newXS(strcpy(buf, "crosszoneaddldonlossbyguildid"), XS__crosszoneaddldonlossbyguildid, file); - newXS(strcpy(buf, "crosszoneaddldonlossbyexpeditionid"), XS__crosszoneaddldonlossbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneaddldonlossbyclientname"), XS__crosszoneaddldonlossbyclientname, file); - newXS(strcpy(buf, "crosszoneaddldonpointsbycharid"), XS__crosszoneaddldonpointsbycharid, file); - newXS(strcpy(buf, "crosszoneaddldonpointsbygroupid"), XS__crosszoneaddldonpointsbygroupid, file); - newXS(strcpy(buf, "crosszoneaddldonpointsbyraidid"), XS__crosszoneaddldonpointsbyraidid, file); - newXS(strcpy(buf, "crosszoneaddldonpointsbyguildid"), XS__crosszoneaddldonpointsbyguildid, file); - newXS(strcpy(buf, "crosszoneaddldonpointsbyexpeditionid"), XS__crosszoneaddldonpointsbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneaddldonpointsbyclientname"), XS__crosszoneaddldonpointsbyclientname, file); - newXS(strcpy(buf, "crosszoneaddldonwinbycharid"), XS__crosszoneaddldonwinbycharid, file); - newXS(strcpy(buf, "crosszoneaddldonwinbygroupid"), XS__crosszoneaddldonwinbygroupid, file); - newXS(strcpy(buf, "crosszoneaddldonwinbyraidid"), XS__crosszoneaddldonwinbyraidid, file); - newXS(strcpy(buf, "crosszoneaddldonwinbyguildid"), XS__crosszoneaddldonwinbyguildid, file); - newXS(strcpy(buf, "crosszoneaddldonwinbyexpeditionid"), XS__crosszoneaddldonwinbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneaddldonwinbyclientname"), XS__crosszoneaddldonwinbyclientname, file); - newXS(strcpy(buf, "crosszoneassigntaskbycharid"), XS__crosszoneassigntaskbycharid, file); - newXS(strcpy(buf, "crosszoneassigntaskbygroupid"), XS__crosszoneassigntaskbygroupid, file); - newXS(strcpy(buf, "crosszoneassigntaskbyraidid"), XS__crosszoneassigntaskbyraidid, file); - newXS(strcpy(buf, "crosszoneassigntaskbyguildid"), XS__crosszoneassigntaskbyguildid, file); - newXS(strcpy(buf, "crosszoneassigntaskbyexpeditionid"), XS__crosszoneassigntaskbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneassigntaskbyclientname"), XS__crosszoneassigntaskbyclientname, file); - newXS(strcpy(buf, "crosszonecastspellbycharid"), XS__crosszonecastspellbycharid, file); - newXS(strcpy(buf, "crosszonecastspellbygroupid"), XS__crosszonecastspellbygroupid, file); - newXS(strcpy(buf, "crosszonecastspellbyraidid"), XS__crosszonecastspellbyraidid, file); - newXS(strcpy(buf, "crosszonecastspellbyguildid"), XS__crosszonecastspellbyguildid, file); - newXS(strcpy(buf, "crosszonecastspellbyexpeditionid"), XS__crosszonecastspellbyexpeditionid, file); - newXS(strcpy(buf, "crosszonecastspellbyclientname"), XS__crosszonecastspellbyclientname, file); - newXS(strcpy(buf, "crosszonedialoguewindowbycharid"), XS__crosszonedialoguewindowbycharid, file); - newXS(strcpy(buf, "crosszonedialoguewindowbygroupid"), XS__crosszonedialoguewindowbygroupid, file); - newXS(strcpy(buf, "crosszonedialoguewindowbyraidid"), XS__crosszonedialoguewindowbyraidid, file); - newXS(strcpy(buf, "crosszonedialoguewindowbyguildid"), XS__crosszonedialoguewindowbyguildid, file); - newXS(strcpy(buf, "crosszonedialoguewindowbyexpeditionid"), XS__crosszonedialoguewindowbyexpeditionid, file); - newXS(strcpy(buf, "crosszonedialoguewindowbyclientname"), XS__crosszonedialoguewindowbyclientname, file); - newXS(strcpy(buf, "crosszonedisabletaskbycharid"), XS__crosszonedisabletaskbycharid, file); - newXS(strcpy(buf, "crosszonedisabletaskbygroupid"), XS__crosszonedisabletaskbygroupid, file); - newXS(strcpy(buf, "crosszonedisabletaskbyraidid"), XS__crosszonedisabletaskbyraidid, file); - newXS(strcpy(buf, "crosszonedisabletaskbyguildid"), XS__crosszonedisabletaskbyguildid, file); - newXS(strcpy(buf, "crosszonedisabletaskbyexpeditionid"), XS__crosszonedisabletaskbyexpeditionid, file); - newXS(strcpy(buf, "crosszonedisabletaskbyclientname"), XS__crosszonedisabletaskbyclientname, file); - newXS(strcpy(buf, "crosszoneenabletaskbycharid"), XS__crosszoneenabletaskbycharid, file); - newXS(strcpy(buf, "crosszoneenabletaskbygroupid"), XS__crosszoneenabletaskbygroupid, file); - newXS(strcpy(buf, "crosszoneenabletaskbyraidid"), XS__crosszoneenabletaskbyraidid, file); - newXS(strcpy(buf, "crosszoneenabletaskbyguildid"), XS__crosszoneenabletaskbyguildid, file); - newXS(strcpy(buf, "crosszoneenabletaskbyexpeditionid"), XS__crosszoneenabletaskbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneenabletaskbyclientname"), XS__crosszoneenabletaskbyclientname, file); - newXS(strcpy(buf, "crosszonefailtaskbycharid"), XS__crosszonefailtaskbycharid, file); - newXS(strcpy(buf, "crosszonefailtaskbygroupid"), XS__crosszonefailtaskbygroupid, file); - newXS(strcpy(buf, "crosszonefailtaskbyraidid"), XS__crosszonefailtaskbyraidid, file); - newXS(strcpy(buf, "crosszonefailtaskbyguildid"), XS__crosszonefailtaskbyguildid, file); - newXS(strcpy(buf, "crosszonefailtaskbyexpeditionid"), XS__crosszonefailtaskbyexpeditionid, file); - newXS(strcpy(buf, "crosszonefailtaskbyclientname"), XS__crosszonefailtaskbyclientname, file); - newXS(strcpy(buf, "crosszonemarqueebycharid"), XS__crosszonemarqueebycharid, file); - newXS(strcpy(buf, "crosszonemarqueebygroupid"), XS__crosszonemarqueebygroupid, file); - newXS(strcpy(buf, "crosszonemarqueebyraidid"), XS__crosszonemarqueebyraidid, file); - newXS(strcpy(buf, "crosszonemarqueebyguildid"), XS__crosszonemarqueebyguildid, file); - newXS(strcpy(buf, "crosszonemarqueebyexpeditionid"), XS__crosszonemarqueebyexpeditionid, file); - newXS(strcpy(buf, "crosszonemarqueebyclientname"), XS__crosszonemarqueebyclientname, file); - newXS(strcpy(buf, "crosszonemessageplayerbycharid"), XS__crosszonemessageplayerbycharid, file); - newXS(strcpy(buf, "crosszonemessageplayerbygroupid"), XS__crosszonemessageplayerbygroupid, file); - newXS(strcpy(buf, "crosszonemessageplayerbyraidid"), XS__crosszonemessageplayerbyraidid, file); - newXS(strcpy(buf, "crosszonemessageplayerbyguildid"), XS__crosszonemessageplayerbyguildid, file); - newXS(strcpy(buf, "crosszonemessageplayerbyexpeditionid"), XS__crosszonemessageplayerbyexpeditionid, file); - newXS(strcpy(buf, "crosszonemessageplayerbyname"), XS__crosszonemessageplayerbyname, file); - newXS(strcpy(buf, "crosszonemoveplayerbycharid"), XS__crosszonemoveplayerbycharid, file); - newXS(strcpy(buf, "crosszonemoveplayerbygroupid"), XS__crosszonemoveplayerbygroupid, file); - newXS(strcpy(buf, "crosszonemoveplayerbyraidid"), XS__crosszonemoveplayerbyraidid, file); - newXS(strcpy(buf, "crosszonemoveplayerbyguildid"), XS__crosszonemoveplayerbyguildid, file); - newXS(strcpy(buf, "crosszonemoveplayerbyexpeditionid"), XS__crosszonemoveplayerbyexpeditionid, file); - newXS(strcpy(buf, "crosszonemoveplayerbyname"), XS__crosszonemoveplayerbyname, file); - newXS(strcpy(buf, "crosszonemoveinstancebycharid"), XS__crosszonemoveinstancebycharid, file); - newXS(strcpy(buf, "crosszonemoveinstancebygroupid"), XS__crosszonemoveinstancebygroupid, file); - newXS(strcpy(buf, "crosszonemoveinstancebyraidid"), XS__crosszonemoveinstancebyraidid, file); - newXS(strcpy(buf, "crosszonemoveinstancebyguildid"), XS__crosszonemoveinstancebyguildid, file); - newXS(strcpy(buf, "crosszonemoveinstancebyexpeditionid"), XS__crosszonemoveinstancebyexpeditionid, file); - newXS(strcpy(buf, "crosszonemoveinstancebyclientname"), XS__crosszonemoveinstancebyclientname, file); - newXS(strcpy(buf, "crosszoneremoveldonlossbycharid"), XS__crosszoneremoveldonlossbycharid, file); - newXS(strcpy(buf, "crosszoneremoveldonlossbygroupid"), XS__crosszoneremoveldonlossbygroupid, file); - newXS(strcpy(buf, "crosszoneremoveldonlossbyraidid"), XS__crosszoneremoveldonlossbyraidid, file); - newXS(strcpy(buf, "crosszoneremoveldonlossbyguildid"), XS__crosszoneremoveldonlossbyguildid, file); - newXS(strcpy(buf, "crosszoneremoveldonlossbyexpeditionid"), XS__crosszoneremoveldonlossbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneremoveldonlossbyclientname"), XS__crosszoneremoveldonlossbyclientname, file); - newXS(strcpy(buf, "crosszoneremoveldonwinbycharid"), XS__crosszoneremoveldonwinbycharid, file); - newXS(strcpy(buf, "crosszoneremoveldonwinbygroupid"), XS__crosszoneremoveldonwinbygroupid, file); - newXS(strcpy(buf, "crosszoneremoveldonwinbyraidid"), XS__crosszoneremoveldonwinbyraidid, file); - newXS(strcpy(buf, "crosszoneremoveldonwinbyguildid"), XS__crosszoneremoveldonwinbyguildid, file); - newXS(strcpy(buf, "crosszoneremoveldonwinbyexpeditionid"), XS__crosszoneremoveldonwinbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneremoveldonwinbyclientname"), XS__crosszoneremoveldonwinbyclientname, file); - newXS(strcpy(buf, "crosszoneremovespellbycharid"), XS__crosszoneremovespellbycharid, file); - newXS(strcpy(buf, "crosszoneremovespellbygroupid"), XS__crosszoneremovespellbygroupid, file); - newXS(strcpy(buf, "crosszoneremovespellbyraidid"), XS__crosszoneremovespellbyraidid, file); - newXS(strcpy(buf, "crosszoneremovespellbyguildid"), XS__crosszoneremovespellbyguildid, file); - newXS(strcpy(buf, "crosszoneremovespellbyexpeditionid"), XS__crosszoneremovespellbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneremovespellbyclientname"), XS__crosszoneremovespellbyclientname, file); - newXS(strcpy(buf, "crosszoneremovetaskbycharid"), XS__crosszoneremovetaskbycharid, file); - newXS(strcpy(buf, "crosszoneremovetaskbygroupid"), XS__crosszoneremovetaskbygroupid, file); - newXS(strcpy(buf, "crosszoneremovetaskbyraidid"), XS__crosszoneremovetaskbyraidid, file); - newXS(strcpy(buf, "crosszoneremovetaskbyguildid"), XS__crosszoneremovetaskbyguildid, file); - newXS(strcpy(buf, "crosszoneremovetaskbyexpeditionid"), XS__crosszoneremovetaskbyexpeditionid, file); - newXS(strcpy(buf, "crosszoneremovetaskbyclientname"), XS__crosszoneremovetaskbyclientname, file); - newXS(strcpy(buf, "crosszoneresetactivitybycharid"), XS__crosszoneresetactivitybycharid, file); - newXS(strcpy(buf, "crosszoneresetactivitybygroupid"), XS__crosszoneresetactivitybygroupid, file); - newXS(strcpy(buf, "crosszoneresetactivitybyraidid"), XS__crosszoneresetactivitybyraidid, file); - newXS(strcpy(buf, "crosszoneresetactivitybyguildid"), XS__crosszoneresetactivitybyguildid, file); - newXS(strcpy(buf, "crosszoneresetactivitybyexpeditionid"), XS__crosszoneresetactivitybyexpeditionid, file); - newXS(strcpy(buf, "crosszoneresetactivitybyclientname"), XS__crosszoneresetactivitybyclientname, file); - newXS(strcpy(buf, "crosszonesetentityvariablebycharid"), XS__crosszonesetentityvariablebycharid, file); - newXS(strcpy(buf, "crosszonesetentityvariablebygroupid"), XS__crosszonesetentityvariablebygroupid, file); - newXS(strcpy(buf, "crosszonesetentityvariablebyraidid"), XS__crosszonesetentityvariablebyraidid, file); - newXS(strcpy(buf, "crosszonesetentityvariablebyguildid"), XS__crosszonesetentityvariablebyguildid, file); - newXS(strcpy(buf, "crosszonesetentityvariablebyexpeditionid"), XS__crosszonesetentityvariablebyexpeditionid, file); - newXS(strcpy(buf, "crosszonesetentityvariablebyclientname"), XS__crosszonesetentityvariablebyclientname, file); - newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, file); - newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file); - newXS(strcpy(buf, "crosszonesignalclientbygroupid"), XS__crosszonesignalclientbygroupid, file); - newXS(strcpy(buf, "crosszonesignalclientbyraidid"), XS__crosszonesignalclientbyraidid, file); - newXS(strcpy(buf, "crosszonesignalclientbyguildid"), XS__crosszonesignalclientbyguildid, file); - newXS(strcpy(buf, "crosszonesignalclientbyexpeditionid"), XS__crosszonesignalclientbyexpeditionid, file); - newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file); - newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file); - newXS(strcpy(buf, "crosszoneupdateactivitybycharid"), XS__crosszoneupdateactivitybycharid, file); - newXS(strcpy(buf, "crosszoneupdateactivitybygroupid"), XS__crosszoneupdateactivitybygroupid, file); - newXS(strcpy(buf, "crosszoneupdateactivitybyraidid"), XS__crosszoneupdateactivitybyraidid, file); - newXS(strcpy(buf, "crosszoneupdateactivitybyguildid"), XS__crosszoneupdateactivitybyguildid, file); - newXS(strcpy(buf, "crosszoneupdateactivitybyexpeditionid"), XS__crosszoneupdateactivitybyexpeditionid, file); - newXS(strcpy(buf, "crosszoneupdateactivitybyclientname"), XS__crosszoneupdateactivitybyclientname, file); - newXS(strcpy(buf, "worldwideaddldonloss"), XS__worldwideaddldonloss, file); - newXS(strcpy(buf, "worldwideaddldonpoints"), XS__worldwideaddldonpoints, file); - newXS(strcpy(buf, "worldwideaddldonwin"), XS__worldwideaddldonwin, file); - newXS(strcpy(buf, "worldwidecastspell"), XS__worldwidecastspell, file); - newXS(strcpy(buf, "worldwidedialoguewindow"), XS__worldwidedialoguewindow, file); - newXS(strcpy(buf, "worldwidedisabletask"), XS__worldwidedisabletask, file); - newXS(strcpy(buf, "worldwideenabletask"), XS__worldwideenabletask, file); - newXS(strcpy(buf, "worldwidefailtask"), XS__worldwidefailtask, file); - newXS(strcpy(buf, "worldwidemarquee"), XS__worldwidemarquee, file); - newXS(strcpy(buf, "worldwidemessage"), XS__worldwidemessage, file); - newXS(strcpy(buf, "worldwidemove"), XS__worldwidemove, file); - newXS(strcpy(buf, "worldwidemoveinstance"), XS__worldwidemoveinstance, file); - newXS(strcpy(buf, "worldwideremoveldonloss"), XS__worldwideremoveldonloss, file); - newXS(strcpy(buf, "worldwideremoveldonwin"), XS__worldwideremoveldonwin, file); - newXS(strcpy(buf, "worldwideremovespell"), XS__worldwideremovespell, file); - newXS(strcpy(buf, "worldwideremovetask"), XS__worldwideremovetask, file); - newXS(strcpy(buf, "worldwideresetactivity"), XS__worldwideresetactivity, file); - newXS(strcpy(buf, "worldwidesetentityvariableclient"), XS__worldwidesetentityvariableclient, file); - newXS(strcpy(buf, "worldwidesetentityvariablenpc"), XS__worldwidesetentityvariablenpc, file); - newXS(strcpy(buf, "worldwidesignalclient"), XS__worldwidesignalclient, file); - newXS(strcpy(buf, "worldwidesignalnpc"), XS__worldwidesignalnpc, file); - newXS(strcpy(buf, "worldwideupdateactivity"), XS__worldwideupdateactivity, file); - newXS(strcpy(buf, "debug"), XS__debug, file); - newXS(strcpy(buf, "delglobal"), XS__delglobal, file); - newXS(strcpy(buf, "depop"), XS__depop, file); - newXS(strcpy(buf, "depop_withtimer"), XS__depop_withtimer, file); - newXS(strcpy(buf, "depopall"), XS__depopall, file); - newXS(strcpy(buf, "depopzone"), XS__depopzone, file); - newXS(strcpy(buf, "ding"), XS__ding, file); - newXS(strcpy(buf, "disable_proximity_say"), XS__disable_proximity_say, file); - newXS(strcpy(buf, "disable_spawn2"), XS__disable_spawn2, file); - newXS(strcpy(buf, "disablerecipe"), XS__disablerecipe, file); - newXS(strcpy(buf, "disabletask"), XS__disabletask, file); - newXS(strcpy(buf, "doanim"), XS__doanim, file); - newXS(strcpy(buf, "echo"), XS__echo, file); - newXS(strcpy(buf, "emote"), XS__emote, file); - newXS(strcpy(buf, "enable_proximity_say"), XS__enable_proximity_say, file); - newXS(strcpy(buf, "enable_spawn2"), XS__enable_spawn2, file); - newXS(strcpy(buf, "enabledtaskcount"), XS__enabledtaskcount, file); - newXS(strcpy(buf, "enablerecipe"), XS__enablerecipe, file); - newXS(strcpy(buf, "enabletask"), XS__enabletask, file); - newXS(strcpy(buf, "enabletitle"), XS__enabletitle, file); - newXS(strcpy(buf, "exp"), XS__exp, file); - newXS(strcpy(buf, "faction"), XS__faction, file); - newXS(strcpy(buf, "factionvalue"), XS_FactionValue, file); - newXS(strcpy(buf, "failtask"), XS__failtask, file); - newXS(strcpy(buf, "firsttaskinset"), XS__firsttaskinset, file); - newXS(strcpy(buf, "follow"), XS__follow, file); - newXS(strcpy(buf, "forcedoorclose"), XS__forcedoorclose, file); - newXS(strcpy(buf, "forcedooropen"), XS__forcedooropen, file); - newXS(strcpy(buf, "getaaexpmodifierbycharid"), XS__getaaexpmodifierbycharid, file); - newXS(strcpy(buf, "getbodytypename"), XS__getbodytypename, file); - newXS(strcpy(buf, "getcharidbyname"), XS__getcharidbyname, file); - newXS(strcpy(buf, "getclassname"), XS__getclassname, file); - newXS(strcpy(buf, "getcleannpcnamebyid"), XS__getcleannpcnamebyid, file); - newXS(strcpy(buf, "getconsiderlevelname"), XS__getconsiderlevelname, file); - newXS(strcpy(buf, "gethexcolorcode"), XS__gethexcolorcode, file); - newXS(strcpy(buf, "getcurrencyid"), XS__getcurrencyid, file); - newXS(strcpy(buf, "getexpmodifierbycharid"), XS__getexpmodifierbycharid, file); - newXS(strcpy(buf, "get_expedition"), XS__get_expedition, file); - newXS(strcpy(buf, "get_expedition_by_char_id"), XS__get_expedition_by_char_id, file); - newXS(strcpy(buf, "get_expedition_by_dz_id"), XS__get_expedition_by_dz_id, file); - newXS(strcpy(buf, "get_expedition_by_zone_instance"), XS__get_expedition_by_zone_instance, file); - newXS(strcpy(buf, "get_expedition_lockout_by_char_id"), XS__get_expedition_lockout_by_char_id, file); - newXS(strcpy(buf, "get_expedition_lockouts_by_char_id"), XS__get_expedition_lockouts_by_char_id, file); - newXS(strcpy(buf, "getfactionname"), XS__getfactionname, file); - newXS(strcpy(buf, "getinventoryslotid"), XS__getinventoryslotid, file); - newXS(strcpy(buf, "getitemname"), XS__getitemname, file); - newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file); - newXS(strcpy(buf, "getitemstat"), XS__getitemstat, file); - newXS(strcpy(buf, "getlanguagename"), XS__getlanguagename, file); - newXS(strcpy(buf, "getldonthemename"), XS__getldonthemename, file); - newXS(strcpy(buf, "getnpcnamebyid"), XS__getnpcnamebyid, file); - newXS(strcpy(buf, "get_spawn_condition"), XS__get_spawn_condition, file); - newXS(strcpy(buf, "getcharnamebyid"), XS__getcharnamebyid, file); - newXS(strcpy(buf, "getcurrencyitemid"), XS__getcurrencyitemid, file); - newXS(strcpy(buf, "getgendername"), XS__getgendername, file); - newXS(strcpy(buf, "getdeityname"), XS__getdeityname, file); - newXS(strcpy(buf, "getenvironmentaldamagename"), XS__getenvironmentaldamagename, file); - newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file); - newXS(strcpy(buf, "getguildidbycharid"), XS__getguildidbycharid, file); - newXS(strcpy(buf, "getgroupidbycharid"), XS__getgroupidbycharid, file); - newXS(strcpy(buf, "getinventoryslotname"), XS__getinventoryslotname, file); - newXS(strcpy(buf, "getraididbycharid"), XS__getraididbycharid, file); - newXS(strcpy(buf, "getracename"), XS__getracename, file); - newXS(strcpy(buf, "getremainingtimeMS"), XS__getremainingtimeMS, file); - newXS(strcpy(buf, "getspell"), XS__getspell, file); - newXS(strcpy(buf, "getspellname"), XS__getspellname, file); - newXS(strcpy(buf, "get_spell_level"), XS__get_spell_level, file); - newXS(strcpy(buf, "getspellstat"), XS__getspellstat, file); - newXS(strcpy(buf, "getskillname"), XS__getskillname, file); - newXS(strcpy(buf, "getlevel"), XS__getlevel, file); - newXS(strcpy(buf, "getplayerburiedcorpsecount"), XS__getplayerburiedcorpsecount, file); - newXS(strcpy(buf, "getplayercorpsecount"), XS__getplayercorpsecount, file); - newXS(strcpy(buf, "getplayercorpsecountbyzoneid"), XS__getplayercorpsecountbyzoneid, file); - newXS(strcpy(buf, "gettaskactivitydonecount"), XS__gettaskactivitydonecount, file); - newXS(strcpy(buf, "gettaskname"), XS__gettaskname, file); - newXS(strcpy(buf, "gettimerdurationMS"), XS__gettimerdurationMS, file); - newXS(strcpy(buf, "givecash"), XS__givecash, file); - newXS(strcpy(buf, "gmmove"), XS__gmmove, file); - newXS(strcpy(buf, "gmsay"), XS__gmsay, file); - newXS(strcpy(buf, "has_zone_flag"), XS__has_zone_flag, file); - newXS(strcpy(buf, "hastimer"), XS__hastimer, file); - newXS(strcpy(buf, "incstat"), XS__incstat, file); - newXS(strcpy(buf, "isdisctome"), XS__isdisctome, file); - newXS(strcpy(buf, "isdooropen"), XS__isdooropen, file); - newXS(strcpy(buf, "isnpcspawned"), XS__isnpcspawned, file); - newXS(strcpy(buf, "istaskactive"), XS__istaskactive, file); - newXS(strcpy(buf, "istaskactivityactive"), XS__istaskactivityactive, file); - newXS(strcpy(buf, "istaskappropriate"), XS__istaskappropriate, file); - newXS(strcpy(buf, "istaskcompleted"), XS__istaskcompleted, file); - newXS(strcpy(buf, "istaskenabled"), XS__istaskenabled, file); - newXS(strcpy(buf, "itemlink"), XS__itemlink, file); - newXS(strcpy(buf, "lasttaskinset"), XS__lasttaskinset, file); - newXS(strcpy(buf, "level"), XS__level, file); - newXS(strcpy(buf, "log"), XS__log, file); - newXS(strcpy(buf, "log_combat"), XS__log_combat, file); - newXS(strcpy(buf, "me"), XS__me, file); - newXS(strcpy(buf, "message"), XS__message, file); - newXS(strcpy(buf, "modifynpcstat"), XS__ModifyNPCStat, file); - newXS(strcpy(buf, "movegrp"), XS__movegrp, file); - newXS(strcpy(buf, "movepc"), XS__movepc, file); - newXS(strcpy(buf, "moveto"), XS__moveto, file); - newXS(strcpy(buf, "nexttaskinset"), XS__nexttaskinset, file); - newXS(strcpy(buf, "npcfeature"), XS__npcfeature, file); - newXS(strcpy(buf, "npcgender"), XS__npcgender, file); - newXS(strcpy(buf, "npcrace"), XS__npcrace, file); - newXS(strcpy(buf, "npcsize"), XS__npcsize, file); - newXS(strcpy(buf, "npctexture"), XS__npctexture, file); - newXS(strcpy(buf, "pause"), XS__pause, file); - newXS(strcpy(buf, "permaclass"), XS__permaclass, file); - newXS(strcpy(buf, "permagender"), XS__permagender, file); - newXS(strcpy(buf, "permarace"), XS__permarace, file); - newXS(strcpy(buf, "playerfeature"), XS__playerfeature, file); - newXS(strcpy(buf, "playergender"), XS__playergender, file); - newXS(strcpy(buf, "playerrace"), XS__playerrace, file); - newXS(strcpy(buf, "playersize"), XS__playersize, file); - newXS(strcpy(buf, "playertexture"), XS__playertexture, file); - newXS(strcpy(buf, "popup"), XS__popup, file); - newXS(strcpy(buf, "processmobswhilezoneempty"), XS__processmobswhilezoneempty, file); - newXS(strcpy(buf, "pvp"), XS__pvp, file); - newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file); - newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file); - newXS(strcpy(buf, "rain"), XS__rain, file); - newXS(strcpy(buf, "rebind"), XS__rebind, file); - newXS(strcpy(buf, "reloadzonestaticdata"), XS__reloadzonestaticdata, file); - newXS(strcpy(buf, "remove_all_expedition_lockouts_by_char_id"), XS__remove_all_expedition_lockouts_by_char_id, file); - newXS(strcpy(buf, "remove_expedition_lockout_by_char_id"), XS__remove_expedition_lockout_by_char_id, file); - newXS(strcpy(buf, "removeitem"), XS__removeitem, file); - newXS(strcpy(buf, "removetitle"), XS__removetitle, file); - newXS(strcpy(buf, "rename"), XS__rename, file); - newXS(strcpy(buf, "repopzone"), XS__repopzone, file); - newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file); - newXS(strcpy(buf, "respawn"), XS__respawn, file); - newXS(strcpy(buf, "resume"), XS__resume, file); - newXS(strcpy(buf, "safemove"), XS__safemove, file); - newXS(strcpy(buf, "save"), XS__save, file); - newXS(strcpy(buf, "say"), XS__say, file); - newXS(strcpy(buf, "saylink"), XS__saylink, file); - newXS(strcpy(buf, "scribespells"), XS__scribespells, file); - newXS(strcpy(buf, "secondstotime"), XS__secondstotime, file); - newXS(strcpy(buf, "selfcast"), XS__selfcast, file); - newXS(strcpy(buf, "setaaexpmodifierbycharid"), XS__setaaexpmodifierbycharid, file); - newXS(strcpy(buf, "set_proximity"), XS__set_proximity, file); - newXS(strcpy(buf, "set_zone_flag"), XS__set_zone_flag, file); - newXS(strcpy(buf, "setallskill"), XS__setallskill, file); - newXS(strcpy(buf, "setanim"), XS__setanim, file); - newXS(strcpy(buf, "setexpmodifierbycharid"), XS__setexpmodifierbycharid, file); - newXS(strcpy(buf, "setglobal"), XS__setglobal, file); - newXS(strcpy(buf, "setguild"), XS__setguild, file); - newXS(strcpy(buf, "sethp"), XS__sethp, file); - newXS(strcpy(buf, "setlanguage"), XS__setlanguage, file); - newXS(strcpy(buf, "setnexthpevent"), XS__setnexthpevent, file); - newXS(strcpy(buf, "setnextinchpevent"), XS__setnextinchpevent, file); - newXS(strcpy(buf, "setskill"), XS__setskill, file); - newXS(strcpy(buf, "setsky"), XS__setsky, file); - newXS(strcpy(buf, "setstat"), XS__setstat, file); - newXS(strcpy(buf, "settarget"), XS__settarget, file); - newXS(strcpy(buf, "settime"), XS__settime, file); - newXS(strcpy(buf, "settimer"), XS__settimer, file); - newXS(strcpy(buf, "settimerMS"), XS__settimerMS, file); - newXS(strcpy(buf, "sfollow"), XS__sfollow, file); - newXS(strcpy(buf, "shout"), XS__shout, file); - newXS(strcpy(buf, "shout2"), XS__shout2, file); - newXS(strcpy(buf, "showgrid"), XS__showgrid, file); - newXS(strcpy(buf, "signal"), XS__signal, file); - newXS(strcpy(buf, "signalwith"), XS__signalwith, file); - newXS(strcpy(buf, "snow"), XS__snow, file); - newXS(strcpy(buf, "spawn"), XS__spawn, file); - newXS(strcpy(buf, "spawn2"), XS__spawn2, file); - newXS(strcpy(buf, "spawn_condition"), XS__spawn_condition, file); - newXS(strcpy(buf, "spawn_from_spawn2"), XS__spawn_from_spawn2, file); - newXS(strcpy(buf, "start"), XS__start, file); - newXS(strcpy(buf, "stop"), XS__stop, file); - newXS(strcpy(buf, "stopalltimers"), XS__stopalltimers, file); - newXS(strcpy(buf, "stoptimer"), XS__stoptimer, file); - newXS(strcpy(buf, "summonallplayercorpses"), XS__summonallplayercorpses, file); - newXS(strcpy(buf, "summonburiedplayercorpse"), XS__summonburiedplayercorpse, file); - newXS(strcpy(buf, "summonitem"), XS__summonitem, file); - newXS(strcpy(buf, "surname"), XS__surname, file); - newXS(strcpy(buf, "targlobal"), XS__targlobal, file); - newXS(strcpy(buf, "taskexploredarea"), XS__taskexploredarea, file); - newXS(strcpy(buf, "taskselector"), XS__taskselector, file); - newXS(strcpy(buf, "task_setselector"), XS__task_setselector, file); - newXS(strcpy(buf, "tasktimeleft"), XS__tasktimeleft, file); - newXS(strcpy(buf, "toggle_spawn_event"), XS__toggle_spawn_event, file); - newXS(strcpy(buf, "toggledoorstate"), XS__toggledoorstate, file); - newXS(strcpy(buf, "traindisc"), XS__traindisc, file); - newXS(strcpy(buf, "traindiscs"), XS__traindiscs, file); - newXS(strcpy(buf, "unique_spawn"), XS__unique_spawn, file); - newXS(strcpy(buf, "unscribespells"), XS__unscribespells, file); - newXS(strcpy(buf, "untraindiscs"), XS__untraindiscs, file); - newXS(strcpy(buf, "updatespawntimer"), XS__UpdateSpawnTimer, file); - newXS(strcpy(buf, "updatetaskactivity"), XS__updatetaskactivity, file); - newXS(strcpy(buf, "UpdateZoneHeader"), XS__UpdateZoneHeader, file); - newXS(strcpy(buf, "varlink"), XS__varlink, file); - newXS(strcpy(buf, "voicetell"), XS__voicetell, file); - newXS(strcpy(buf, "we"), XS__we, file); - newXS(strcpy(buf, "wearchange"), XS__wearchange, file); - newXS(strcpy(buf, "whisper"), XS__whisper, file); - newXS(strcpy(buf, "write"), XS__write, file); - newXS(strcpy(buf, "ze"), XS__ze, file); - newXS(strcpy(buf, "zone"), XS__zone, file); - newXS(strcpy(buf, "zonegroup"), XS__zonegroup, file); - newXS(strcpy(buf, "zoneraid"), XS__zoneraid, file); +bool Perl__do_augment_slots_match(uint32 item_one, uint32 item_two) +{ + return quest_manager.DoAugmentSlotsMatch(item_one, item_two); +} + +int8 Perl__does_augment_fit(EQ::ItemInstance* inst, uint32 augment_id) +{ + return quest_manager.DoesAugmentFit(inst, augment_id); +} + +void perl_register_quest() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_package("quest"); + + package.add("botquest", &Perl__botquest); + package.add("spawnbotcount", (int(*)())&Perl__spawnbotcount); + package.add("spawnbotcount", (int(*)(uint8))&Perl__spawnbotcount); + package.add("createbotcount", (int(*)())&Perl__createbotcount); + package.add("createbotcount", (int(*)(uint8))&Perl__createbotcount); + package.add("createBot", &Perl__createBot); + + package.add("AssignGroupToInstance", &Perl__AssignGroupToInstance); + package.add("AssignRaidToInstance", &Perl__AssignRaidToInstance); + package.add("AssignToInstance", &Perl__AssignToInstance); + package.add("AssignToInstanceByCharID", &Perl__AssignToInstanceByCharID); + package.add("ChooseRandom", &Perl__ChooseRandom); + package.add("CreateInstance", &Perl__CreateInstance); + package.add("DestroyInstance", &Perl__DestroyInstance); + package.add("UpdateInstanceTimer", &Perl__UpdateInstanceTimer); + package.add("GetInstanceTimer", &Perl__GetInstanceTimer); + package.add("GetInstanceTimerByID", &Perl__GetInstanceTimerByID); + package.add("FlagInstanceByGroupLeader", &Perl__FlagInstanceByGroupLeader); + package.add("FlagInstanceByRaidLeader", &Perl__FlagInstanceByRaidLeader); + package.add("FlyMode", &Perl__FlyMode); + package.add("GetCharactersInInstance", &Perl__GetCharactersInInstance); + package.add("GetInstanceID", &Perl__GetInstanceID); + package.add("GetInstanceIDByCharID", &Perl__GetInstanceIDByCharID); + package.add("GetInstanceIDs", &Perl__GetInstanceIDs); + package.add("GetInstanceIDsByCharID", &Perl__GetInstanceIDsByCharID); + package.add("GetInstanceVersionByID", &Perl__GetInstanceVersionByID); + package.add("GetInstanceZoneIDByID", &Perl__GetInstanceZoneIDByID); + package.add("GetSpellResistType", &Perl__GetSpellResistType); + package.add("GetSpellTargetType", &Perl__GetSpellTargetType); + package.add("GetTimeSeconds", &Perl__GetTimeSeconds); + package.add("GetZoneID", &Perl__GetZoneID); + package.add("GetZoneLongName", &Perl__GetZoneLongName); + package.add("GetZoneLongNameByID", &Perl__GetZoneLongNameByID); + package.add("GetZoneShortName", &Perl__GetZoneShortName); + package.add("set_rule", &Perl__set_rule); + package.add("get_rule", &Perl__get_rule); + package.add("get_data", &Perl__get_data); + package.add("get_data_expires", &Perl__get_data_expires); + package.add("get_data_remaining", &Perl__get_data_remaining); + package.add("set_data", (void(*)(std::string, std::string))&Perl__set_data); + package.add("set_data", (void(*)(std::string, std::string, std::string))&Perl__set_data); + package.add("delete_data", &Perl__delete_data); + package.add("IsBeneficialSpell", &Perl__IsBeneficialSpell); + package.add("IsEffectInSpell", &Perl__IsEffectInSpell); + package.add("IsRaining", &Perl__IsRaining); + package.add("IsSnowing", &Perl__IsSnowing); + package.add("IsRunning", &Perl__IsRunning); + package.add("LearnRecipe", &Perl__LearnRecipe); + package.add("MerchantCountItem", &Perl__MerchantCountItem); + package.add("MerchantSetItem", (void(*)(uint32, uint32))&Perl__MerchantSetItem); + package.add("MerchantSetItem", (void(*)(uint32, uint32, uint32))&Perl__MerchantSetItem); + package.add("MovePCInstance", (void(*)(int, int, float, float, float))&Perl__MovePCInstance); + package.add("MovePCInstance", (void(*)(int, int, float, float, float, float))&Perl__MovePCInstance); + package.add("RemoveAllFromInstance", &Perl__RemoveAllFromInstance); + package.add("RemoveFromInstance", &Perl__RemoveFromInstance); + package.add("RemoveFromInstanceByCharID", &Perl__RemoveFromInstanceByCharID); + package.add("CheckInstanceByCharID", &Perl__CheckInstanceByCharID); + package.add("SendMail", &Perl__SendMail); + package.add("SetRunning", &Perl__SetRunning); + package.add("activespeakactivity", &Perl__activespeakactivity); + package.add("activespeaktask", &Perl__activespeaktask); + package.add("activetasksinset", &Perl__activetasksinset); + package.add("add_expedition_lockout_all_clients", (void(*)(std::string, std::string, uint32))&Perl__add_expedition_lockout_all_clients); + package.add("add_expedition_lockout_all_clients", (void(*)(std::string, std::string, uint32, std::string))&Perl__add_expedition_lockout_all_clients); + package.add("add_expedition_lockout_by_char_id", (void(*)(uint32, std::string, std::string, uint32))&Perl__add_expedition_lockout_by_char_id); + package.add("add_expedition_lockout_by_char_id", (void(*)(uint32, std::string, std::string, uint32, std::string))&Perl__add_expedition_lockout_by_char_id); + package.add("addldonloss", &Perl__addldonloss); + package.add("addldonpoints", &Perl__addldonpoints); + package.add("addldonwin", &Perl__addldonwin); + package.add("addloot", (void(*)(int))&Perl__addloot); + package.add("addloot", (void(*)(int, int))&Perl__addloot); + package.add("addloot", (void(*)(int, int, bool))&Perl__addloot); + package.add("addskill", &Perl__addskill); + package.add("assigntask", (void(*)(int))&Perl__assigntask); + package.add("assigntask", (void(*)(int, bool))&Perl__assigntask); + package.add("attack", &Perl__attack); + package.add("attacknpc", &Perl__attacknpc); + package.add("attacknpctype", &Perl__attacknpctype); + package.add("buryplayercorpse", &Perl__buryplayercorpse); + package.add("castspell", &Perl__castspell); + package.add("changedeity", &Perl__changedeity); + package.add("checknamefilter", &Perl__checknamefilter), + package.add("checktitle", &Perl__checktitle); + package.add("clear_npctype_cache", &Perl__clear_npctype_cache); + package.add("clear_proximity", &Perl__clear_proximity); + package.add("clear_zone_flag", &Perl__clear_zone_flag); + package.add("clearspawntimers", &Perl__clearspawntimers); + package.add("collectitems", &Perl__collectitems); + package.add("commify", &Perl__commify); + package.add("completedtasksinset", &Perl__completedtasksinset); + package.add("countitem", &Perl__countitem); + package.add("countspawnednpcs", &Perl__countspawnednpcs); + package.add("createdoor", (uint16(*)(const char*, float, float, float, float))&Perl__CreateDoor); + package.add("createdoor", (uint16(*)(const char*, float, float, float, float, uint8_t))&Perl__CreateDoor); + package.add("createdoor", (uint16(*)(const char*, float, float, float, float, uint8_t, uint16_t))&Perl__CreateDoor); + package.add("creategroundobject", (uint16(*)(uint32_t, float, float, float, float))&Perl__CreateGroundObject); + package.add("creategroundobject", (uint16(*)(uint32_t, float, float, float, float, uint32_t))&Perl__CreateGroundObject); + package.add("creategroundobjectfrommodel", (uint16(*)(const char*, float, float, float, float))&Perl__CreateGroundObjectFromModel); + package.add("creategroundobjectfrommodel", (uint16(*)(const char*, float, float, float, float, uint8_t))&Perl__CreateGroundObjectFromModel); + package.add("creategroundobjectfrommodel", (uint16(*)(const char*, float, float, float, float, uint8_t, uint32_t))&Perl__CreateGroundObjectFromModel); + package.add("createguild", &Perl__createguild); + package.add("createitem", (EQ::ItemInstance*(*)(uint32))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16, uint32))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16, uint32, uint32))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16, uint32, uint32, uint32))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16, uint32, uint32, uint32, uint32))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16, uint32, uint32, uint32, uint32, uint32))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16, uint32, uint32, uint32, uint32, uint32, uint32))&Perl__createitem); + package.add("createitem", (EQ::ItemInstance*(*)(uint32, int16, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Perl__createitem); + package.add("crosszoneaddldonlossbycharid", &Perl__crosszoneaddldonlossbycharid); + package.add("crosszoneaddldonlossbygroupid", &Perl__crosszoneaddldonlossbygroupid); + package.add("crosszoneaddldonlossbyraidid", &Perl__crosszoneaddldonlossbyraidid); + package.add("crosszoneaddldonlossbyguildid", &Perl__crosszoneaddldonlossbyguildid); + package.add("crosszoneaddldonlossbyexpeditionid", &Perl__crosszoneaddldonlossbyexpeditionid); + package.add("crosszoneaddldonlossbyclientname", &Perl__crosszoneaddldonlossbyclientname); + package.add("crosszoneaddldonpointsbycharid", &Perl__crosszoneaddldonpointsbycharid); + package.add("crosszoneaddldonpointsbygroupid", &Perl__crosszoneaddldonpointsbygroupid); + package.add("crosszoneaddldonpointsbyraidid", &Perl__crosszoneaddldonpointsbyraidid); + package.add("crosszoneaddldonpointsbyguildid", &Perl__crosszoneaddldonpointsbyguildid); + package.add("crosszoneaddldonpointsbyexpeditionid", &Perl__crosszoneaddldonpointsbyexpeditionid); + package.add("crosszoneaddldonpointsbyclientname", &Perl__crosszoneaddldonpointsbyclientname); + package.add("crosszoneaddldonwinbycharid", &Perl__crosszoneaddldonwinbycharid); + package.add("crosszoneaddldonwinbygroupid", &Perl__crosszoneaddldonwinbygroupid); + package.add("crosszoneaddldonwinbyraidid", &Perl__crosszoneaddldonwinbyraidid); + package.add("crosszoneaddldonwinbyguildid", &Perl__crosszoneaddldonwinbyguildid); + package.add("crosszoneaddldonwinbyexpeditionid", &Perl__crosszoneaddldonwinbyexpeditionid); + package.add("crosszoneaddldonwinbyclientname", &Perl__crosszoneaddldonwinbyclientname); + package.add("crosszoneassigntaskbycharid", (void(*)(int, uint32))&Perl__crosszoneassigntaskbycharid); + package.add("crosszoneassigntaskbycharid", (void(*)(int, uint32, bool))&Perl__crosszoneassigntaskbycharid); + package.add("crosszoneassigntaskbygroupid", (void(*)(int, uint32))&Perl__crosszoneassigntaskbygroupid); + package.add("crosszoneassigntaskbygroupid", (void(*)(int, uint32, bool))&Perl__crosszoneassigntaskbygroupid); + package.add("crosszoneassigntaskbyraidid", (void(*)(int, uint32))&Perl__crosszoneassigntaskbyraidid); + package.add("crosszoneassigntaskbyraidid", (void(*)(int, uint32, bool))&Perl__crosszoneassigntaskbyraidid); + package.add("crosszoneassigntaskbyguildid", (void(*)(int, uint32))&Perl__crosszoneassigntaskbyguildid); + package.add("crosszoneassigntaskbyguildid", (void(*)(int, uint32, bool))&Perl__crosszoneassigntaskbyguildid); + package.add("crosszoneassigntaskbyexpeditionid", (void(*)(uint32, uint32))&Perl__crosszoneassigntaskbyexpeditionid); + package.add("crosszoneassigntaskbyexpeditionid", (void(*)(uint32, uint32, bool))&Perl__crosszoneassigntaskbyexpeditionid); + package.add("crosszoneassigntaskbyclientname", (void(*)(const char*, uint32))&Perl__crosszoneassigntaskbyclientname); + package.add("crosszoneassigntaskbyclientname", (void(*)(const char*, uint32, bool))&Perl__crosszoneassigntaskbyclientname); + package.add("crosszonecastspellbycharid", &Perl__crosszonecastspellbycharid); + package.add("crosszonecastspellbygroupid", &Perl__crosszonecastspellbygroupid); + package.add("crosszonecastspellbyraidid", &Perl__crosszonecastspellbyraidid); + package.add("crosszonecastspellbyguildid", &Perl__crosszonecastspellbyguildid); + package.add("crosszonecastspellbyexpeditionid", &Perl__crosszonecastspellbyexpeditionid); + package.add("crosszonecastspellbyclientname", &Perl__crosszonecastspellbyclientname); + package.add("crosszonedialoguewindowbycharid", &Perl__crosszonedialoguewindowbycharid); + package.add("crosszonedialoguewindowbygroupid", &Perl__crosszonedialoguewindowbygroupid); + package.add("crosszonedialoguewindowbyraidid", &Perl__crosszonedialoguewindowbyraidid); + package.add("crosszonedialoguewindowbyguildid", &Perl__crosszonedialoguewindowbyguildid); + package.add("crosszonedialoguewindowbyexpeditionid", &Perl__crosszonedialoguewindowbyexpeditionid); + package.add("crosszonedialoguewindowbyclientname", &Perl__crosszonedialoguewindowbyclientname); + package.add("crosszonedisabletaskbycharid", &Perl__crosszonedisabletaskbycharid); + package.add("crosszonedisabletaskbygroupid", &Perl__crosszonedisabletaskbygroupid); + package.add("crosszonedisabletaskbyraidid", &Perl__crosszonedisabletaskbyraidid); + package.add("crosszonedisabletaskbyguildid", &Perl__crosszonedisabletaskbyguildid); + package.add("crosszonedisabletaskbyexpeditionid", &Perl__crosszonedisabletaskbyexpeditionid); + package.add("crosszonedisabletaskbyclientname", &Perl__crosszonedisabletaskbyclientname); + package.add("crosszoneenabletaskbycharid", &Perl__crosszoneenabletaskbycharid); + package.add("crosszoneenabletaskbygroupid", &Perl__crosszoneenabletaskbygroupid); + package.add("crosszoneenabletaskbyraidid", &Perl__crosszoneenabletaskbyraidid); + package.add("crosszoneenabletaskbyguildid", &Perl__crosszoneenabletaskbyguildid); + package.add("crosszoneenabletaskbyexpeditionid", &Perl__crosszoneenabletaskbyexpeditionid); + package.add("crosszoneenabletaskbyclientname", &Perl__crosszoneenabletaskbyclientname); + package.add("crosszonefailtaskbycharid", &Perl__crosszonefailtaskbycharid); + package.add("crosszonefailtaskbygroupid", &Perl__crosszonefailtaskbygroupid); + package.add("crosszonefailtaskbyraidid", &Perl__crosszonefailtaskbyraidid); + package.add("crosszonefailtaskbyguildid", &Perl__crosszonefailtaskbyguildid); + package.add("crosszonefailtaskbyexpeditionid", &Perl__crosszonefailtaskbyexpeditionid); + package.add("crosszonefailtaskbyclientname", &Perl__crosszonefailtaskbyclientname); + package.add("crosszonemarqueebycharid", &Perl__crosszonemarqueebycharid); + package.add("crosszonemarqueebygroupid", &Perl__crosszonemarqueebygroupid); + package.add("crosszonemarqueebyraidid", &Perl__crosszonemarqueebyraidid); + package.add("crosszonemarqueebyguildid", &Perl__crosszonemarqueebyguildid); + package.add("crosszonemarqueebyexpeditionid", &Perl__crosszonemarqueebyexpeditionid); + package.add("crosszonemarqueebyclientname", &Perl__crosszonemarqueebyclientname); + package.add("crosszonemessageplayerbycharid", &Perl__crosszonemessageplayerbycharid); + package.add("crosszonemessageplayerbygroupid", &Perl__crosszonemessageplayerbygroupid); + package.add("crosszonemessageplayerbyraidid", &Perl__crosszonemessageplayerbyraidid); + package.add("crosszonemessageplayerbyguildid", &Perl__crosszonemessageplayerbyguildid); + package.add("crosszonemessageplayerbyexpeditionid", &Perl__crosszonemessageplayerbyexpeditionid); + package.add("crosszonemessageplayerbyname", &Perl__crosszonemessageplayerbyname); + package.add("crosszonemoveplayerbycharid", &Perl__crosszonemoveplayerbycharid); + package.add("crosszonemoveplayerbygroupid", &Perl__crosszonemoveplayerbygroupid); + package.add("crosszonemoveplayerbyraidid", &Perl__crosszonemoveplayerbyraidid); + package.add("crosszonemoveplayerbyguildid", &Perl__crosszonemoveplayerbyguildid); + package.add("crosszonemoveplayerbyexpeditionid", &Perl__crosszonemoveplayerbyexpeditionid); + package.add("crosszonemoveplayerbyname", &Perl__crosszonemoveplayerbyname); + package.add("crosszonemoveinstancebycharid", &Perl__crosszonemoveinstancebycharid); + package.add("crosszonemoveinstancebygroupid", &Perl__crosszonemoveinstancebygroupid); + package.add("crosszonemoveinstancebyraidid", &Perl__crosszonemoveinstancebyraidid); + package.add("crosszonemoveinstancebyguildid", &Perl__crosszonemoveinstancebyguildid); + package.add("crosszonemoveinstancebyexpeditionid", &Perl__crosszonemoveinstancebyexpeditionid); + package.add("crosszonemoveinstancebyclientname", &Perl__crosszonemoveinstancebyclientname); + package.add("crosszoneremoveldonlossbycharid", &Perl__crosszoneremoveldonlossbycharid); + package.add("crosszoneremoveldonlossbygroupid", &Perl__crosszoneremoveldonlossbygroupid); + package.add("crosszoneremoveldonlossbyraidid", &Perl__crosszoneremoveldonlossbyraidid); + package.add("crosszoneremoveldonlossbyguildid", &Perl__crosszoneremoveldonlossbyguildid); + package.add("crosszoneremoveldonlossbyexpeditionid", &Perl__crosszoneremoveldonlossbyexpeditionid); + package.add("crosszoneremoveldonlossbyclientname", &Perl__crosszoneremoveldonlossbyclientname); + package.add("crosszoneremoveldonwinbycharid", &Perl__crosszoneremoveldonwinbycharid); + package.add("crosszoneremoveldonwinbygroupid", &Perl__crosszoneremoveldonwinbygroupid); + package.add("crosszoneremoveldonwinbyraidid", &Perl__crosszoneremoveldonwinbyraidid); + package.add("crosszoneremoveldonwinbyguildid", &Perl__crosszoneremoveldonwinbyguildid); + package.add("crosszoneremoveldonwinbyexpeditionid", &Perl__crosszoneremoveldonwinbyexpeditionid); + package.add("crosszoneremoveldonwinbyclientname", &Perl__crosszoneremoveldonwinbyclientname); + package.add("crosszoneremovespellbycharid", &Perl__crosszoneremovespellbycharid); + package.add("crosszoneremovespellbygroupid", &Perl__crosszoneremovespellbygroupid); + package.add("crosszoneremovespellbyraidid", &Perl__crosszoneremovespellbyraidid); + package.add("crosszoneremovespellbyguildid", &Perl__crosszoneremovespellbyguildid); + package.add("crosszoneremovespellbyexpeditionid", &Perl__crosszoneremovespellbyexpeditionid); + package.add("crosszoneremovespellbyclientname", &Perl__crosszoneremovespellbyclientname); + package.add("crosszoneremovetaskbycharid", &Perl__crosszoneremovetaskbycharid); + package.add("crosszoneremovetaskbygroupid", &Perl__crosszoneremovetaskbygroupid); + package.add("crosszoneremovetaskbyraidid", &Perl__crosszoneremovetaskbyraidid); + package.add("crosszoneremovetaskbyguildid", &Perl__crosszoneremovetaskbyguildid); + package.add("crosszoneremovetaskbyexpeditionid", &Perl__crosszoneremovetaskbyexpeditionid); + package.add("crosszoneremovetaskbyclientname", &Perl__crosszoneremovetaskbyclientname); + package.add("crosszoneresetactivitybycharid", &Perl__crosszoneresetactivitybycharid); + package.add("crosszoneresetactivitybygroupid", &Perl__crosszoneresetactivitybygroupid); + package.add("crosszoneresetactivitybyraidid", &Perl__crosszoneresetactivitybyraidid); + package.add("crosszoneresetactivitybyguildid", &Perl__crosszoneresetactivitybyguildid); + package.add("crosszoneresetactivitybyexpeditionid", &Perl__crosszoneresetactivitybyexpeditionid); + package.add("crosszoneresetactivitybyclientname", &Perl__crosszoneresetactivitybyclientname); + package.add("crosszonesetentityvariablebycharid", &Perl__crosszonesetentityvariablebycharid); + package.add("crosszonesetentityvariablebygroupid", &Perl__crosszonesetentityvariablebygroupid); + package.add("crosszonesetentityvariablebyraidid", &Perl__crosszonesetentityvariablebyraidid); + package.add("crosszonesetentityvariablebyguildid", &Perl__crosszonesetentityvariablebyguildid); + package.add("crosszonesetentityvariablebyexpeditionid", &Perl__crosszonesetentityvariablebyexpeditionid); + package.add("crosszonesetentityvariablebyclientname", &Perl__crosszonesetentityvariablebyclientname); + package.add("crosszonesetentityvariablebynpctypeid", &Perl__crosszonesetentityvariablebynpctypeid); + package.add("crosszonesignalclientbycharid", &Perl__crosszonesignalclientbycharid); + package.add("crosszonesignalclientbygroupid", &Perl__crosszonesignalclientbygroupid); + package.add("crosszonesignalclientbyraidid", &Perl__crosszonesignalclientbyraidid); + package.add("crosszonesignalclientbyguildid", &Perl__crosszonesignalclientbyguildid); + package.add("crosszonesignalclientbyexpeditionid", &Perl__crosszonesignalclientbyexpeditionid); + package.add("crosszonesignalclientbyname", &Perl__crosszonesignalclientbyname); + package.add("crosszonesignalnpcbynpctypeid", &Perl__crosszonesignalnpcbynpctypeid); + package.add("crosszoneupdateactivitybycharid", (void(*)(int, uint32, int))&Perl__crosszoneupdateactivitybycharid); + package.add("crosszoneupdateactivitybycharid", (void(*)(int, uint32, int, int))&Perl__crosszoneupdateactivitybycharid); + package.add("crosszoneupdateactivitybygroupid", (void(*)(int, uint32, int))&Perl__crosszoneupdateactivitybygroupid); + package.add("crosszoneupdateactivitybygroupid", (void(*)(int, uint32, int, int))&Perl__crosszoneupdateactivitybygroupid); + package.add("crosszoneupdateactivitybyraidid", (void(*)(int, uint32, int))&Perl__crosszoneupdateactivitybyraidid); + package.add("crosszoneupdateactivitybyraidid", (void(*)(int, uint32, int, int))&Perl__crosszoneupdateactivitybyraidid); + package.add("crosszoneupdateactivitybyguildid", (void(*)(int, uint32, int))&Perl__crosszoneupdateactivitybyguildid); + package.add("crosszoneupdateactivitybyguildid", (void(*)(int, uint32, int, int))&Perl__crosszoneupdateactivitybyguildid); + package.add("crosszoneupdateactivitybyexpeditionid", (void(*)(uint32, uint32, int))&Perl__crosszoneupdateactivitybyexpeditionid); + package.add("crosszoneupdateactivitybyexpeditionid", (void(*)(uint32, uint32, int, int))&Perl__crosszoneupdateactivitybyexpeditionid); + package.add("crosszoneupdateactivitybyclientname", (void(*)(const char*, uint32, int))&Perl__crosszoneupdateactivitybyclientname); + package.add("crosszoneupdateactivitybyclientname", (void(*)(const char*, uint32, int, int))&Perl__crosszoneupdateactivitybyclientname); + package.add("worldwideaddldonloss", (void(*)(uint32))&Perl__worldwideaddldonloss); + package.add("worldwideaddldonloss", (void(*)(uint32, uint8))&Perl__worldwideaddldonloss); + package.add("worldwideaddldonloss", (void(*)(uint32, uint8, uint8))&Perl__worldwideaddldonloss); + package.add("worldwideaddldonpoints", (void(*)(uint32))&Perl__worldwideaddldonpoints); + package.add("worldwideaddldonpoints", (void(*)(uint32, int))&Perl__worldwideaddldonpoints); + package.add("worldwideaddldonpoints", (void(*)(uint32, int, uint8))&Perl__worldwideaddldonpoints); + package.add("worldwideaddldonpoints", (void(*)(uint32, int, uint8, uint8))&Perl__worldwideaddldonpoints); + package.add("worldwideaddldonwin", (void(*)(uint32))&Perl__worldwideaddldonwin); + package.add("worldwideaddldonwin", (void(*)(uint32, uint8))&Perl__worldwideaddldonwin); + package.add("worldwideaddldonwin", (void(*)(uint32, uint8, uint8))&Perl__worldwideaddldonwin); + package.add("worldwideassigntask", (void(*)(uint32))&Perl__worldwideassigntask); + package.add("worldwideassigntask", (void(*)(uint32, bool))&Perl__worldwideassigntask); + package.add("worldwideassigntask", (void(*)(uint32, bool, uint8))&Perl__worldwideassigntask); + package.add("worldwideassigntask", (void(*)(uint32, bool, uint8, uint8))&Perl__worldwideassigntask); + package.add("worldwidecastspell", (void(*)(uint32))&Perl__worldwidecastspell); + package.add("worldwidecastspell", (void(*)(uint32, uint8))&Perl__worldwidecastspell); + package.add("worldwidecastspell", (void(*)(uint32, uint8, uint8 max_status))&Perl__worldwidecastspell); + package.add("worldwidedialoguewindow", (void(*)(const char*))&Perl__worldwidedialoguewindow); + package.add("worldwidedialoguewindow", (void(*)(const char*, uint8))&Perl__worldwidedialoguewindow); + package.add("worldwidedialoguewindow", (void(*)(const char*, uint8, uint8))&Perl__worldwidedialoguewindow); + package.add("worldwidedisabletask", (void(*)(uint32))&Perl__worldwidedisabletask); + package.add("worldwidedisabletask", (void(*)(uint32, uint8))&Perl__worldwidedisabletask); + package.add("worldwidedisabletask", (void(*)(uint32, uint8, uint8))&Perl__worldwidedisabletask); + package.add("worldwideenabletask", (void(*)(uint32))&Perl__worldwideenabletask); + package.add("worldwideenabletask", (void(*)(uint32, uint8))&Perl__worldwideenabletask); + package.add("worldwideenabletask", (void(*)(uint32, uint8, uint8))&Perl__worldwideenabletask); + package.add("worldwidefailtask", (void(*)(uint32))&Perl__worldwidefailtask); + package.add("worldwidefailtask", (void(*)(uint32, uint8))&Perl__worldwidefailtask); + package.add("worldwidefailtask", (void(*)(uint32, uint8, uint8))&Perl__worldwidefailtask); + package.add("worldwidemarquee", (void(*)(uint32, uint32, uint32, uint32, uint32, const char*))&Perl__worldwidemarquee); + package.add("worldwidemarquee", (void(*)(uint32, uint32, uint32, uint32, uint32, const char*, uint8))&Perl__worldwidemarquee); + package.add("worldwidemarquee", (void(*)(uint32, uint32, uint32, uint32, uint32, const char*, uint8, uint8))&Perl__worldwidemarquee); + package.add("worldwidemessage", (void(*)(uint32, const char*))&Perl__worldwidemessage); + package.add("worldwidemessage", (void(*)(uint32, const char*, uint8))&Perl__worldwidemessage); + package.add("worldwidemessage", (void(*)(uint32, const char*, uint8, uint8))&Perl__worldwidemessage); + package.add("worldwidemove", (void(*)(const char*))&Perl__worldwidemove); + package.add("worldwidemove", (void(*)(const char*, uint8))&Perl__worldwidemove); + package.add("worldwidemove", (void(*)(const char*, uint8, uint8))&Perl__worldwidemove); + package.add("worldwidemoveinstance", (void(*)(uint16))&Perl__worldwidemoveinstance); + package.add("worldwidemoveinstance", (void(*)(uint16, uint8))&Perl__worldwidemoveinstance); + package.add("worldwidemoveinstance", (void(*)(uint16, uint8, uint8))&Perl__worldwidemoveinstance); + package.add("worldwideremoveldonloss", (void(*)(uint32))&Perl__worldwideremoveldonloss); + package.add("worldwideremoveldonloss", (void(*)(uint32, uint8))&Perl__worldwideremoveldonloss); + package.add("worldwideremoveldonloss", (void(*)(uint32, uint8, uint8))&Perl__worldwideremoveldonloss); + package.add("worldwideremoveldonwin", (void(*)(uint32))&Perl__worldwideremoveldonwin); + package.add("worldwideremoveldonwin", (void(*)(uint32, uint8))&Perl__worldwideremoveldonwin); + package.add("worldwideremoveldonwin", (void(*)(uint32, uint8, uint8))&Perl__worldwideremoveldonwin); + package.add("worldwideremovespell", (void(*)(uint32))&Perl__worldwideremovespell); + package.add("worldwideremovespell", (void(*)(uint32, uint8))&Perl__worldwideremovespell); + package.add("worldwideremovespell", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovespell); + package.add("worldwideremovetask", (void(*)(uint32))&Perl__worldwideremovetask); + package.add("worldwideremovetask", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovetask); + package.add("worldwideremovetask", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovetask); + package.add("worldwideresetactivity", (void(*)(uint32, int))&Perl__worldwideresetactivity); + package.add("worldwideresetactivity", (void(*)(uint32, int, uint8))&Perl__worldwideresetactivity); + package.add("worldwideresetactivity", (void(*)(uint32, int, uint8, uint8))&Perl__worldwideresetactivity); + package.add("worldwidesetentityvariableclient", (void(*)(const char*, const char*))&Perl__worldwidesetentityvariableclient); + package.add("worldwidesetentityvariableclient", (void(*)(const char*, const char*, uint8))&Perl__worldwidesetentityvariableclient); + package.add("worldwidesetentityvariableclient", (void(*)(const char*, const char*, uint8, uint8))&Perl__worldwidesetentityvariableclient); + package.add("worldwidesetentityvariablenpc", &Perl__worldwidesetentityvariablenpc); + package.add("worldwidesignalclient", (void(*)(int))&Perl__worldwidesignalclient); + package.add("worldwidesignalclient", (void(*)(int, uint8))&Perl__worldwidesignalclient); + package.add("worldwidesignalclient", (void(*)(int, uint8, uint8))&Perl__worldwidesignalclient); + package.add("worldwidesignalnpc", &Perl__worldwidesignalnpc); + package.add("worldwideupdateactivity", (void(*)(uint32, int))&Perl__worldwideupdateactivity); + package.add("worldwideupdateactivity", (void(*)(uint32, int, int))&Perl__worldwideupdateactivity); + package.add("worldwideupdateactivity", (void(*)(uint32, int, int, uint8))&Perl__worldwideupdateactivity); + package.add("worldwideupdateactivity", (void(*)(uint32, int, int, uint8, uint8))&Perl__worldwideupdateactivity); + package.add("debug", (void(*)(const char*))&Perl__debug); + package.add("debug", (void(*)(const char*, int))&Perl__debug); + package.add("delglobal", &Perl__delglobal); + package.add("depop", (void(*)())&Perl__depop); + package.add("depop", (void(*)(int))&Perl__depop); + package.add("depop_withtimer", (void(*)())&Perl__depop_withtimer); + package.add("depop_withtimer", (void(*)(int))&Perl__depop_withtimer); + package.add("depopall", (void(*)())&Perl__depopall); + package.add("depopall", (void(*)(int))&Perl__depopall); + package.add("depopzone", &Perl__depopzone); + package.add("ding", &Perl__ding); + package.add("disable_proximity_say", &Perl__disable_proximity_say); + package.add("disable_spawn2", &Perl__disable_spawn2); + package.add("disablerecipe", &Perl__disablerecipe); + package.add("disabletask", &Perl__disabletask); + package.add("discordsend", &Perl__discordsend); + package.add("doanim", (void(*)(int))&Perl__doanim); + package.add("doanim", (void(*)(int, int))&Perl__doanim); + package.add("doanim", (void(*)(int, int, bool))&Perl__doanim); + package.add("doanim", (void(*)(int, int, bool, int))&Perl__doanim); + package.add("do_augment_slots_match", &Perl__do_augment_slots_match); + package.add("does_augment_fit", &Perl__does_augment_fit); + package.add("echo", &Perl__echo); + package.add("emote", &Perl__emote); + package.add("enable_proximity_say", &Perl__enable_proximity_say); + package.add("enable_spawn2", &Perl__enable_spawn2); + package.add("enabledtaskcount", &Perl__enabledtaskcount); + package.add("enablerecipe", &Perl__enablerecipe); + package.add("enabletask", &Perl__enabletask); + package.add("enabletitle", &Perl__enabletitle); + package.add("end_dz_task", (void(*)())&Perl__end_dz_task); + package.add("end_dz_task", (void(*)(bool))&Perl__end_dz_task); + package.add("exp", &Perl__exp); + package.add("faction", (void(*)(int, int))&Perl__faction); + package.add("faction", (void(*)(int, int, int))&Perl__faction); + package.add("factionvalue", &Perl__FactionValue); + package.add("failtask", &Perl__failtask); + package.add("firsttaskinset", &Perl__firsttaskinset); + package.add("follow", (void(*)(int))&Perl__follow); + package.add("follow", (void(*)(int, int))&Perl__follow); + package.add("forcedoorclose", (void(*)(uint32))&Perl__forcedoorclose); + package.add("forcedoorclose", (void(*)(uint32, bool))&Perl__forcedoorclose); + package.add("forcedooropen", (void(*)(uint32))&Perl__forcedooropen); + package.add("forcedooropen", (void(*)(uint32, bool))&Perl__forcedooropen); + package.add("getaaexpmodifierbycharid", (double(*)(uint32, uint32))&Perl__getaaexpmodifierbycharid); + package.add("getaaexpmodifierbycharid", (double(*)(uint32, uint32, int16))&Perl__getaaexpmodifierbycharid); + package.add("getaaname", (std::string(*)(int))&Perl__getaaname); + package.add("getbodytypename", &Perl__getbodytypename); + package.add("getcharidbyname", &Perl__getcharidbyname); + package.add("getclassname", (std::string(*)(uint8))&Perl__getclassname); + package.add("getclassname", (std::string(*)(uint8, uint8))&Perl__getclassname); + package.add("getcleannpcnamebyid", &Perl__getcleannpcnamebyid); + package.add("getconsiderlevelname", &Perl__getconsiderlevelname); + package.add("gethexcolorcode", &Perl__gethexcolorcode); + package.add("getcurrencyid", &Perl__getcurrencyid); + package.add("get_dz_task_id", &Perl__get_dz_task_id); + package.add("getexpmodifierbycharid", (double(*)(uint32, uint32))&Perl__getexpmodifierbycharid); + package.add("getexpmodifierbycharid", (double(*)(uint32, uint32, int16))&Perl__getexpmodifierbycharid); + package.add("get_expedition", &Perl__get_expedition); + package.add("get_expedition_by_char_id", &Perl__get_expedition_by_char_id); + package.add("get_expedition_by_dz_id", &Perl__get_expedition_by_dz_id); + package.add("get_expedition_by_zone_instance", &Perl__get_expedition_by_zone_instance); + package.add("get_expedition_lockout_by_char_id", &Perl__get_expedition_lockout_by_char_id); + package.add("get_expedition_lockouts_by_char_id", (perl::reference(*)(uint32))&Perl__get_expedition_lockouts_by_char_id); + package.add("get_expedition_lockouts_by_char_id", (perl::reference(*)(uint32, std::string))&Perl__get_expedition_lockouts_by_char_id); + package.add("getfactionname", &Perl__getfactionname); + package.add("getinventoryslotid", &Perl__getinventoryslotid); + package.add("getitemname", &Perl__getitemname); + package.add("getItemName", &Perl__qc_getItemName); + package.add("getitemstat", &Perl__getitemstat); + package.add("getlanguagename", &Perl__getlanguagename); + package.add("getldonthemename", &Perl__getldonthemename); + package.add("getnpcnamebyid", &Perl__getnpcnamebyid); + package.add("get_spawn_condition", (int(*)(const char*, uint16))&Perl__get_spawn_condition); + package.add("get_spawn_condition", (int(*)(const char*, uint32, uint16))&Perl__get_spawn_condition); + package.add("getcharnamebyid", &Perl__getcharnamebyid); + package.add("getcurrencyitemid", &Perl__getcurrencyitemid); + package.add("getgendername", &Perl__getgendername); + package.add("getdeityname", &Perl__getdeityname); + package.add("getenvironmentaldamagename", &Perl__getenvironmentaldamagename); + package.add("getguildnamebyid", &Perl__getguildnamebyid); + package.add("getguildidbycharid", &Perl__getguildidbycharid); + package.add("getgroupidbycharid", &Perl__getgroupidbycharid); + package.add("getinventoryslotname", &Perl__getinventoryslotname); + package.add("getraididbycharid", &Perl__getraididbycharid); + package.add("getracename", &Perl__getracename); + package.add("getremainingtimeMS", &Perl__getremainingtimeMS); + package.add("getspell", &Perl__getspell); + package.add("getspellname", &Perl__getspellname); + package.add("get_spell_level", &Perl__get_spell_level); + package.add("getspellstat", (int(*)(uint32, std::string))&Perl__getspellstat); + package.add("getspellstat", (int(*)(uint32, std::string, uint8))&Perl__getspellstat); + package.add("getskillname", &Perl__getskillname); + package.add("getlevel", &Perl__getlevel); + package.add("getplayerburiedcorpsecount", &Perl__getplayerburiedcorpsecount); + package.add("getplayercorpsecount", &Perl__getplayercorpsecount); + package.add("getplayercorpsecountbyzoneid", &Perl__getplayercorpsecountbyzoneid); + package.add("getrecipemadecount", &Perl__getrecipemadecount); + package.add("getrecipename", &Perl__getrecipename); + package.add("gettaskactivitydonecount", &Perl__gettaskactivitydonecount); + package.add("gettaskname", &Perl__gettaskname); + package.add("gettimerdurationMS", &Perl__gettimerdurationMS); + package.add("givecash", (void(*)(uint32))&Perl__givecash); + package.add("givecash", (void(*)(uint32, uint32))&Perl__givecash); + package.add("givecash", (void(*)(uint32, uint32, uint32))&Perl__givecash); + package.add("givecash", (void(*)(uint32, uint32, uint32, uint32))&Perl__givecash); + package.add("gmmove", &Perl__gmmove); + package.add("gmsay", (void(*)(const char*))&Perl__gmsay); + package.add("gmsay", (void(*)(const char*, int))&Perl__gmsay); + package.add("gmsay", (void(*)(const char*, int, bool))&Perl__gmsay); + package.add("gmsay", (void(*)(const char*, int, bool, int))&Perl__gmsay); + package.add("gmsay", (void(*)(const char*, int, bool, int, int))&Perl__gmsay); + package.add("has_zone_flag", &Perl__has_zone_flag); + package.add("hasrecipelearned", &Perl__hasrecipelearned); + package.add("hastimer", &Perl__hastimer); + package.add("incstat", &Perl__incstat); + package.add("isdisctome", &Perl__isdisctome); + package.add("isdooropen", &Perl__isdooropen); + package.add("ishotzone", &Perl__ishotzone); + package.add("isnpcspawned", &Perl__isnpcspawned); + package.add("istaskactive", &Perl__istaskactive); + package.add("istaskactivityactive", &Perl__istaskactivityactive); + package.add("istaskappropriate", &Perl__istaskappropriate); + package.add("istaskcompleted", &Perl__istaskcompleted); + package.add("istaskenabled", &Perl__istaskenabled); + package.add("itemlink", &Perl__itemlink); + package.add("lasttaskinset", &Perl__lasttaskinset); + package.add("level", &Perl__level); + package.add("log", &Perl__log); + package.add("log_combat", &Perl__log_combat); + package.add("marquee", (void(*)(uint32, std::string))&Perl__marquee); + package.add("marquee", (void(*)(uint32, std::string, uint32))&Perl__marquee); + package.add("marquee", (void(*)(uint32, uint32, uint32, uint32, uint32, std::string))&Perl__marquee); + package.add("me", &Perl__me); + package.add("message", &Perl__message); + package.add("modifynpcstat", &Perl__ModifyNPCStat); + package.add("movegrp", &Perl__movegrp); + package.add("movepc",(void(*)(int, float, float, float))&Perl__movepc); + package.add("movepc",(void(*)(int, float, float, float, float))&Perl__movepc); + package.add("moveto", (void(*)(float, float, float))&Perl__moveto); + package.add("moveto", (void(*)(float, float, float, float))&Perl__moveto); + package.add("moveto", (void(*)(float, float, float, float, bool))&Perl__moveto); + package.add("nexttaskinset", &Perl__nexttaskinset); + package.add("npcfeature", &Perl__npcfeature); + package.add("npcgender", &Perl__npcgender); + package.add("npcrace", &Perl__npcrace); + package.add("npcsize", &Perl__npcsize); + package.add("npctexture", &Perl__npctexture); + package.add("pause", &Perl__pause); + package.add("permaclass", &Perl__permaclass); + package.add("permagender", &Perl__permagender); + package.add("permarace", &Perl__permarace); + package.add("playerfeature", &Perl__playerfeature); + package.add("playergender", &Perl__playergender); + package.add("playerrace", &Perl__playerrace); + package.add("playersize", &Perl__playersize); + package.add("playertexture", &Perl__playertexture); + package.add("popup", (void(*)(const char*, const char*))&Perl__popup); + package.add("popup", (void(*)(const char*, const char*, int))&Perl__popup); + package.add("popup", (void(*)(const char*, const char*, int, int))&Perl__popup); + package.add("popup", (void(*)(const char*, const char*, int, int, int))&Perl__popup); + package.add("popupbreak", (std::string(*)())&Perl__popupbreak); + package.add("popupbreak", (std::string(*)(uint32))&Perl__popupbreak); + package.add("popupcentermessage", &Perl__popupcentermessage); + package.add("popupcolormessage", &Perl__popupcolormessage); + package.add("popupindent", (std::string(*)())&Perl__popupindent); + package.add("popupindent", (std::string(*)(uint32))&Perl__popupindent); + package.add("popuplink", (std::string(*)(std::string))&Perl__popuplink); + package.add("popuplink", (std::string(*)(std::string, std::string))&Perl__popuplink); + package.add("popuptable", &Perl__popuptable); + package.add("popuptablecell", (std::string(*)())&Perl__popuptablecell); + package.add("popuptablecell", (std::string(*)(std::string))&Perl__popuptablecell); + package.add("popuptablerow", &Perl__popuptablerow); + package.add("processmobswhilezoneempty", &Perl__processmobswhilezoneempty); + package.add("pvp", &Perl__pvp); + package.add("qs_player_event", &Perl__qs_player_event); + package.add("qs_send_query", &Perl__qs_send_query); + package.add("rain", &Perl__rain); + package.add("rebind", (void(*)(int, float, float, float))&Perl__rebind); + package.add("rebind", (void(*)(int, float, float, float, float))&Perl__rebind); + package.add("reloadzonestaticdata", &Perl__reloadzonestaticdata); + package.add("remove_all_expedition_lockouts_by_char_id", (void(*)(uint32))&Perl__remove_all_expedition_lockouts_by_char_id); + package.add("remove_all_expedition_lockouts_by_char_id", (void(*)(uint32, std::string))&Perl__remove_all_expedition_lockouts_by_char_id); + package.add("remove_expedition_lockout_by_char_id", &Perl__remove_expedition_lockout_by_char_id); + package.add("removeitem", (void(*)(uint32_t))&Perl__removeitem); + package.add("removeitem", (void(*)(uint32_t, int))&Perl__removeitem); + package.add("removetitle", &Perl__removetitle); + package.add("rename", &Perl__rename); + package.add("repopzone", &Perl__repopzone); + package.add("resettaskactivity", &Perl__resettaskactivity); + package.add("respawn", &Perl__respawn); + package.add("resume", &Perl__resume); + package.add("rewardfaction", &Perl__rewardfaction); + package.add("safemove", &Perl__safemove); + package.add("save", &Perl__save); + package.add("say", (void(*)(const char*))&Perl__say); + package.add("say", (void(*)(const char*, int))&Perl__say); + package.add("say", (void(*)(const char*, int, int))&Perl__say); + package.add("say", (void(*)(const char*, int, int, int))&Perl__say); + package.add("say", (void(*)(const char*, int, int, int, int))&Perl__say); + package.add("saylink", (std::string(*)(const char*))&Perl__saylink); + package.add("saylink", (std::string(*)(const char*, bool))&Perl__saylink); + package.add("saylink", (std::string(*)(const char*, bool, const char*))&Perl__saylink); + package.add("scribespells", (int(*)(int))&Perl__scribespells); + package.add("scribespells", (int(*)(int, int))&Perl__scribespells); + package.add("secondstotime", &Perl__secondstotime); + package.add("selfcast", &Perl__selfcast); + package.add("setaaexpmodifierbycharid", (void(*)(uint32, uint32, double))&Perl__setaaexpmodifierbycharid); + package.add("setaaexpmodifierbycharid", (void(*)(uint32, uint32, double, int16))&Perl__setaaexpmodifierbycharid); + package.add("set_proximity", (void(*)(float, float, float, float))&Perl__set_proximity); + package.add("set_proximity", (void(*)(float, float, float, float, float, float))&Perl__set_proximity); + package.add("set_proximity", (void(*)(float, float, float, float, float, float, bool))&Perl__set_proximity); + package.add("set_proximity_range", (void(*)(float, float))&Perl__set_proximity_range); + package.add("set_proximity_range", (void(*)(float, float, float))&Perl__set_proximity_range); + package.add("set_proximity_range", (void(*)(float, float, float, bool))&Perl__set_proximity_range); + package.add("set_zone_flag", &Perl__set_zone_flag); + package.add("setallskill", &Perl__setallskill); + package.add("setanim", &Perl__setanim); + package.add("setexpmodifierbycharid", (void(*)(uint32, uint32, double))&Perl__setexpmodifierbycharid); + package.add("setexpmodifierbycharid", (void(*)(uint32, uint32, double, int16))&Perl__setexpmodifierbycharid); + package.add("setglobal", &Perl__setglobal); + package.add("setguild", &Perl__setguild); + package.add("sethp", &Perl__sethp); + package.add("sethotzone", &Perl__sethotzone); + package.add("setlanguage", &Perl__setlanguage); + package.add("setnexthpevent", &Perl__setnexthpevent); + package.add("setnextinchpevent", &Perl__setnextinchpevent); + package.add("setskill", &Perl__setskill); + package.add("setsky", &Perl__setsky); + package.add("setstat", &Perl__setstat); + package.add("settarget", &Perl__settarget); + package.add("settime", (void(*)(int, int))&Perl__settime); + package.add("settime", (void(*)(int, int, bool))&Perl__settime); + package.add("settimer", &Perl__settimer); + package.add("settimerMS", &Perl__settimerMS); + package.add("sfollow", &Perl__sfollow); + package.add("shout", &Perl__shout); + package.add("shout2", &Perl__shout2); + package.add("showgrid", &Perl__showgrid); + package.add("signal", (void(*)(int))&Perl__signal); + package.add("signal", (void(*)(int, int))&Perl__signal); + package.add("signalwith", (void(*)(int, int))&Perl__signalwith); + package.add("signalwith", (void(*)(int, int, int))&Perl__signalwith); + package.add("snow", &Perl__snow); + package.add("spawn", &Perl__spawn); + package.add("spawn2", &Perl__spawn2); + package.add("spawn_condition", (void(*)(const char*, uint16, int16))&Perl__spawn_condition); + package.add("spawn_condition", (void(*)(const char*, uint32_t, uint16, int16))&Perl__spawn_condition); + package.add("spawn_from_spawn2", &Perl__spawn_from_spawn2); + package.add("start", &Perl__start); + package.add("stop", &Perl__stop); + package.add("stopalltimers", &Perl__stopalltimers); + package.add("stoptimer", &Perl__stoptimer); + package.add("summonallplayercorpses", &Perl__summonallplayercorpses); + package.add("summonburiedplayercorpse", &Perl__summonburiedplayercorpse); + package.add("summonitem", (void(*)(int))&Perl__summonitem); + package.add("summonitem", (void(*)(int, int))&Perl__summonitem); + package.add("surname", &Perl__surname); + package.add("targlobal", &Perl__targlobal); + package.add("taskselector", &Perl__taskselector); + package.add("taskselector_nocooldown", &Perl__taskselector_nocooldown); + package.add("task_setselector", (void(*)(int))&Perl__task_setselector); + package.add("task_setselector", (void(*)(int, bool))&Perl__task_setselector); + package.add("tasktimeleft", &Perl__tasktimeleft); + package.add("timetoseconds", &Perl__timetoseconds); + package.add("toggle_spawn_event", &Perl__toggle_spawn_event); + package.add("toggledoorstate", &Perl__toggledoorstate); + package.add("tracknpc", &Perl__tracknpc); + package.add("traindisc", &Perl__traindisc); + package.add("traindiscs", (int(*)(int))&Perl__traindiscs); + package.add("traindiscs", (int(*)(int, int))&Perl__traindiscs); + package.add("unique_spawn", (int(*)(int, int, int, float, float, float))&Perl__unique_spawn); + package.add("unique_spawn", (int(*)(int, int, int, float, float, float, float))&Perl__unique_spawn); + package.add("unscribespells", &Perl__unscribespells); + package.add("untraindiscs", &Perl__untraindiscs); + package.add("updatespawntimer", &Perl__UpdateSpawnTimer); + package.add("updatetaskactivity", (void(*)(int, int))&Perl__updatetaskactivity); + package.add("updatetaskactivity", (void(*)(int, int, int))&Perl__updatetaskactivity); + package.add("updatetaskactivity", (void(*)(int, int, int, bool))&Perl__updatetaskactivity); + package.add("UpdateZoneHeader", &Perl__UpdateZoneHeader); + package.add("varlink", (std::string(*)(uint32))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16, uint32))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16, uint32, uint32))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16, uint32, uint32, uint32))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16, uint32, uint32, uint32, uint32))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16, uint32, uint32, uint32, uint32, uint32))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16, uint32, uint32, uint32, uint32, uint32, uint32))&Perl__varlink); + package.add("varlink", (std::string(*)(uint32, int16, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Perl__varlink); + package.add("voicetell", &Perl__voicetell); + package.add("we", &Perl__we); + package.add("wearchange", (void(*)(uint8, uint16))&Perl__wearchange); + package.add("wearchange", (void(*)(uint8, uint16, uint32))&Perl__wearchange); + package.add("wearchange", (void(*)(uint8, uint16, uint32, uint32))&Perl__wearchange); + package.add("whisper", &Perl__whisper); + package.add("write", &Perl__write); + package.add("ze", &Perl__ze); + package.add("zone", &Perl__zone); + package.add("zonemarquee", (void(*)(uint32, std::string))&Perl__zonemarquee); + package.add("zonemarquee", (void(*)(uint32, std::string, uint32))&Perl__zonemarquee); + package.add("zonemarquee", (void(*)(uint32, uint32, uint32, uint32, uint32, std::string))&Perl__zonemarquee); + package.add("zonegroup", &Perl__zonegroup); + package.add("zoneraid", &Perl__zoneraid); /** * Expansions */ - newXS(strcpy(buf, "is_classic_enabled"), XS__IsClassicEnabled, file); - newXS(strcpy(buf, "is_the_ruins_of_kunark_enabled"), XS__IsTheRuinsOfKunarkEnabled, file); - newXS(strcpy(buf, "is_the_scars_of_velious_enabled"), XS__IsTheScarsOfVeliousEnabled, file); - newXS(strcpy(buf, "is_the_shadows_of_luclin_enabled"), XS__IsTheShadowsOfLuclinEnabled, file); - newXS(strcpy(buf, "is_the_planes_of_power_enabled"), XS__IsThePlanesOfPowerEnabled, file); - newXS(strcpy(buf, "is_the_legacy_of_ykesha_enabled"), XS__IsTheLegacyOfYkeshaEnabled, file); - newXS(strcpy(buf, "is_lost_dungeons_of_norrath_enabled"), XS__IsLostDungeonsOfNorrathEnabled, file); - newXS(strcpy(buf, "is_gates_of_discord_enabled"), XS__IsGatesOfDiscordEnabled, file); - newXS(strcpy(buf, "is_omens_of_war_enabled"), XS__IsOmensOfWarEnabled, file); - newXS(strcpy(buf, "is_dragons_of_norrath_enabled"), XS__IsDragonsOfNorrathEnabled, file); - newXS(strcpy(buf, "is_depths_of_darkhollow_enabled"), XS__IsDepthsOfDarkhollowEnabled, file); - newXS(strcpy(buf, "is_prophecy_of_ro_enabled"), XS__IsProphecyOfRoEnabled, file); - newXS(strcpy(buf, "is_the_serpents_spine_enabled"), XS__IsTheSerpentsSpineEnabled, file); - newXS(strcpy(buf, "is_the_buried_sea_enabled"), XS__IsTheBuriedSeaEnabled, file); - newXS(strcpy(buf, "is_secrets_of_faydwer_enabled"), XS__IsSecretsOfFaydwerEnabled, file); - newXS(strcpy(buf, "is_seeds_of_destruction_enabled"), XS__IsSeedsOfDestructionEnabled, file); - newXS(strcpy(buf, "is_underfoot_enabled"), XS__IsUnderfootEnabled, file); - newXS(strcpy(buf, "is_house_of_thule_enabled"), XS__IsHouseOfThuleEnabled, file); - newXS(strcpy(buf, "is_veil_of_alaris_enabled"), XS__IsVeilOfAlarisEnabled, file); - newXS(strcpy(buf, "is_rain_of_fear_enabled"), XS__IsRainOfFearEnabled, file); - newXS(strcpy(buf, "is_call_of_the_forsaken_enabled"), XS__IsCallOfTheForsakenEnabled, file); - newXS(strcpy(buf, "is_the_darkened_sea_enabled"), XS__IsTheDarkenedSeaEnabled, file); - newXS(strcpy(buf, "is_the_broken_mirror_enabled"), XS__IsTheBrokenMirrorEnabled, file); - newXS(strcpy(buf, "is_empires_of_kunark_enabled"), XS__IsEmpiresOfKunarkEnabled, file); - newXS(strcpy(buf, "is_ring_of_scale_enabled"), XS__IsRingOfScaleEnabled, file); - newXS(strcpy(buf, "is_the_burning_lands_enabled"), XS__IsTheBurningLandsEnabled, file); - newXS(strcpy(buf, "is_torment_of_velious_enabled"), XS__IsTormentOfVeliousEnabled, file); - newXS(strcpy(buf, "is_current_expansion_classic"), XS__IsCurrentExpansionClassic, file); - newXS(strcpy(buf, "is_current_expansion_the_ruins_of_kunark"), XS__IsCurrentExpansionTheRuinsOfKunark, file); - newXS(strcpy(buf, "is_current_expansion_the_scars_of_velious"), XS__IsCurrentExpansionTheScarsOfVelious, file); - newXS(strcpy(buf, "is_current_expansion_the_shadows_of_luclin"), XS__IsCurrentExpansionTheShadowsOfLuclin, file); - newXS(strcpy(buf, "is_current_expansion_the_planes_of_power"), XS__IsCurrentExpansionThePlanesOfPower, file); - newXS(strcpy(buf, "is_current_expansion_the_legacy_of_ykesha"), XS__IsCurrentExpansionTheLegacyOfYkesha, file); - newXS(strcpy(buf, "is_current_expansion_lost_dungeons_of_norrath"), XS__IsCurrentExpansionLostDungeonsOfNorrath, file); - newXS(strcpy(buf, "is_current_expansion_gates_of_discord"), XS__IsCurrentExpansionGatesOfDiscord, file); - newXS(strcpy(buf, "is_current_expansion_omens_of_war"), XS__IsCurrentExpansionOmensOfWar, file); - newXS(strcpy(buf, "is_current_expansion_dragons_of_norrath"), XS__IsCurrentExpansionDragonsOfNorrath, file); - newXS(strcpy(buf, "is_current_expansion_depths_of_darkhollow"), XS__IsCurrentExpansionDepthsOfDarkhollow, file); - newXS(strcpy(buf, "is_current_expansion_prophecy_of_ro"), XS__IsCurrentExpansionProphecyOfRo, file); - newXS(strcpy(buf, "is_current_expansion_the_serpents_spine"), XS__IsCurrentExpansionTheSerpentsSpine, file); - newXS(strcpy(buf, "is_current_expansion_the_buried_sea"), XS__IsCurrentExpansionTheBuriedSea, file); - newXS(strcpy(buf, "is_current_expansion_secrets_of_faydwer"), XS__IsCurrentExpansionSecretsOfFaydwer, file); - newXS(strcpy(buf, "is_current_expansion_seeds_of_destruction"), XS__IsCurrentExpansionSeedsOfDestruction, file); - newXS(strcpy(buf, "is_current_expansion_underfoot"), XS__IsCurrentExpansionUnderfoot, file); - newXS(strcpy(buf, "is_current_expansion_house_of_thule"), XS__IsCurrentExpansionHouseOfThule, file); - newXS(strcpy(buf, "is_current_expansion_veil_of_alaris"), XS__IsCurrentExpansionVeilOfAlaris, file); - newXS(strcpy(buf, "is_current_expansion_rain_of_fear"), XS__IsCurrentExpansionRainOfFear, file); - newXS(strcpy(buf, "is_current_expansion_call_of_the_forsaken"), XS__IsCurrentExpansionCallOfTheForsaken, file); - newXS(strcpy(buf, "is_current_expansion_the_darkened_sea"), XS__IsCurrentExpansionTheDarkenedSea, file); - newXS(strcpy(buf, "is_current_expansion_the_broken_mirror"), XS__IsCurrentExpansionTheBrokenMirror, file); - newXS(strcpy(buf, "is_current_expansion_empires_of_kunark"), XS__IsCurrentExpansionEmpiresOfKunark, file); - newXS(strcpy(buf, "is_current_expansion_ring_of_scale"), XS__IsCurrentExpansionRingOfScale, file); - newXS(strcpy(buf, "is_current_expansion_the_burning_lands"), XS__IsCurrentExpansionTheBurningLands, file); - newXS(strcpy(buf, "is_current_expansion_torment_of_velious"), XS__IsCurrentExpansionTormentOfVelious, file); + package.add("is_classic_enabled", &Perl__IsClassicEnabled); + package.add("is_the_ruins_of_kunark_enabled", &Perl__IsTheRuinsOfKunarkEnabled); + package.add("is_the_scars_of_velious_enabled", &Perl__IsTheScarsOfVeliousEnabled); + package.add("is_the_shadows_of_luclin_enabled", &Perl__IsTheShadowsOfLuclinEnabled); + package.add("is_the_planes_of_power_enabled", &Perl__IsThePlanesOfPowerEnabled); + package.add("is_the_legacy_of_ykesha_enabled", &Perl__IsTheLegacyOfYkeshaEnabled); + package.add("is_lost_dungeons_of_norrath_enabled", &Perl__IsLostDungeonsOfNorrathEnabled); + package.add("is_gates_of_discord_enabled", &Perl__IsGatesOfDiscordEnabled); + package.add("is_omens_of_war_enabled", &Perl__IsOmensOfWarEnabled); + package.add("is_dragons_of_norrath_enabled", &Perl__IsDragonsOfNorrathEnabled); + package.add("is_depths_of_darkhollow_enabled", &Perl__IsDepthsOfDarkhollowEnabled); + package.add("is_prophecy_of_ro_enabled", &Perl__IsProphecyOfRoEnabled); + package.add("is_the_serpents_spine_enabled", &Perl__IsTheSerpentsSpineEnabled); + package.add("is_the_buried_sea_enabled", &Perl__IsTheBuriedSeaEnabled); + package.add("is_secrets_of_faydwer_enabled", &Perl__IsSecretsOfFaydwerEnabled); + package.add("is_seeds_of_destruction_enabled", &Perl__IsSeedsOfDestructionEnabled); + package.add("is_underfoot_enabled", &Perl__IsUnderfootEnabled); + package.add("is_house_of_thule_enabled", &Perl__IsHouseOfThuleEnabled); + package.add("is_veil_of_alaris_enabled", &Perl__IsVeilOfAlarisEnabled); + package.add("is_rain_of_fear_enabled", &Perl__IsRainOfFearEnabled); + package.add("is_call_of_the_forsaken_enabled", &Perl__IsCallOfTheForsakenEnabled); + package.add("is_the_darkend_sea_enabled", &Perl__IsTheDarkenedSeaEnabled); + package.add("is_the_broken_mirror_enabled", &Perl__IsTheBrokenMirrorEnabled); + package.add("is_empires_of_kunark_enabled", &Perl__IsEmpiresOfKunarkEnabled); + package.add("is_ring_of_scale_enabled", &Perl__IsRingOfScaleEnabled); + package.add("is_the_burning_lands_enabled", &Perl__IsTheBurningLandsEnabled); + package.add("is_torment_of_velious_enabled", &Perl__IsTormentOfVeliousEnabled); + package.add("is_current_expansion_classic", &Perl__IsCurrentExpansionClassic); + package.add("is_current_expansion_the_ruins_of_kunark", &Perl__IsCurrentExpansionTheRuinsOfKunark); + package.add("is_current_expansion_the_scars_of_velious", &Perl__IsCurrentExpansionTheScarsOfVelious); + package.add("is_current_expansion_the_shadows_of_luclin", &Perl__IsCurrentExpansionTheShadowsOfLuclin); + package.add("is_current_expansion_the_planes_of_power", &Perl__IsCurrentExpansionThePlanesOfPower); + package.add("is_current_expansion_the_legacy_of_ykesha", &Perl__IsCurrentExpansionTheLegacyOfYkesha); + package.add("is_current_expansion_lost_dungeons_of_norrath", &Perl__IsCurrentExpansionLostDungeonsOfNorrath); + package.add("is_current_expansion_gates_of_discord", &Perl__IsCurrentExpansionGatesOfDiscord); + package.add("is_current_expansion_omens_of_war", &Perl__IsCurrentExpansionOmensOfWar); + package.add("is_current_expansion_dragons_of_norrath", &Perl__IsCurrentExpansionDragonsOfNorrath); + package.add("is_current_expansion_depths_of_darkhollow", &Perl__IsCurrentExpansionDepthsOfDarkhollow); + package.add("is_current_expansion_prophecy_of_ro", &Perl__IsCurrentExpansionProphecyOfRo); + package.add("is_current_expansion_the_serpents_spine", &Perl__IsCurrentExpansionTheSerpentsSpine); + package.add("is_current_expansion_the_buried_sea", &Perl__IsCurrentExpansionTheBuriedSea); + package.add("is_current_expansion_secrets_of_faydwer", &Perl__IsCurrentExpansionSecretsOfFaydwer); + package.add("is_current_expansion_seeds_of_destruction", &Perl__IsCurrentExpansionSeedsOfDestruction); + package.add("is_current_expansion_underfoot", &Perl__IsCurrentExpansionUnderfoot); + package.add("is_current_expansion_house_of_thule", &Perl__IsCurrentExpansionHouseOfThule); + package.add("is_current_expansion_veil_of_alaris", &Perl__IsCurrentExpansionVeilOfAlaris); + package.add("is_current_expansion_rain_of_fear", &Perl__IsCurrentExpansionRainOfFear); + package.add("is_current_expansion_call_of_the_forsaken", &Perl__IsCurrentExpansionCallOfTheForsaken); + package.add("is_current_expansion_the_darkend_sea", &Perl__IsCurrentExpansionTheDarkenedSea); + package.add("is_current_expansion_the_broken_mirror", &Perl__IsCurrentExpansionTheBrokenMirror); + package.add("is_current_expansion_empires_of_kunark", &Perl__IsCurrentExpansionEmpiresOfKunark); + package.add("is_current_expansion_ring_of_scale", &Perl__IsCurrentExpansionRingOfScale); + package.add("is_current_expansion_the_burning_lands", &Perl__IsCurrentExpansionTheBurningLands); + package.add("is_current_expansion_torment_of_velious", &Perl__IsCurrentExpansionTormentOfVelious); /** * Content flags */ - newXS(strcpy(buf, "is_content_flag_enabled"), XS__IsContentFlagEnabled, file); - newXS(strcpy(buf, "set_content_flag"), XS__SetContentFlag, file); + package.add("is_content_flag_enabled", &Perl__IsContentFlagEnabled); + package.add("set_content_flag", &Perl__SetContentFlag); - XSRETURN_YES; } #endif diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 9be785566..bdbe5d70e 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -18,34 +18,15 @@ Eglin #include "embperl.h" #include "embxs.h" #include "../common/features.h" +#include "../common/path_manager.h" +#include "../common/process/process.h" +#include "../common/file.h" +#include "../common/timer.h" + #ifndef GvCV_set #define GvCV_set(gv,cv) (GvCV(gv) = (cv)) #endif -#ifdef EMBPERL_XS -EXTERN_C XS(boot_quest); -#ifdef EMBPERL_XS_CLASSES -EXTERN_C XS(boot_Mob); -EXTERN_C XS(boot_NPC); -EXTERN_C XS(boot_Client); -EXTERN_C XS(boot_Corpse); -EXTERN_C XS(boot_EntityList); -EXTERN_C XS(boot_Group); -EXTERN_C XS(boot_Raid); -EXTERN_C XS(boot_Inventory); -EXTERN_C XS(boot_QuestItem); -EXTERN_C XS(boot_Spell); -EXTERN_C XS(boot_HateEntry); -EXTERN_C XS(boot_Object); -EXTERN_C XS(boot_Doors); -EXTERN_C XS(boot_PerlPacket); -EXTERN_C XS(boot_Expedition); -#ifdef BOTS -EXTERN_C XS(boot_Bot); -#endif -#endif -#endif - #ifdef EMBPERL_IO_CAPTURE XS(XS_EQEmuIO_PRINT); #endif //EMBPERL_IO_CAPTURE @@ -74,36 +55,6 @@ EXTERN_C void xs_init(pTHX) //add the strcpy stuff to get rid of const warnings.... newXS(strcpy(buf, "DynaLoader::boot_DynaLoader"), boot_DynaLoader, file); - newXS(strcpy(buf, "quest::boot_qc"), boot_qc, file); -#ifdef EMBPERL_XS - newXS(strcpy(buf, "quest::boot_quest"), boot_quest, file); -#ifdef EMBPERL_XS_CLASSES - newXS(strcpy(buf, "Mob::boot_Mob"), boot_Mob, file); - newXS(strcpy(buf, "NPC::boot_Mob"), boot_Mob, file); - newXS(strcpy(buf, "NPC::boot_NPC"), boot_NPC, file); - newXS(strcpy(buf, "Corpse::boot_Mob"), boot_Mob, file); - newXS(strcpy(buf, "Corpse::boot_Corpse"), boot_Corpse, file); - newXS(strcpy(buf, "Client::boot_Mob"), boot_Mob, file); - newXS(strcpy(buf, "Client::boot_Client"), boot_Client, file); - newXS(strcpy(buf, "EntityList::boot_EntityList"), boot_EntityList, file); - newXS(strcpy(buf, "PerlPacket::boot_PerlPacket"), boot_PerlPacket, file); - newXS(strcpy(buf, "Group::boot_Group"), boot_Group, file); - newXS(strcpy(buf, "Raid::boot_Raid"), boot_Raid, file); - newXS(strcpy(buf, "Inventory::boot_Inventory"), boot_Inventory, file); - newXS(strcpy(buf, "QuestItem::boot_QuestItem"), boot_QuestItem, file); - newXS(strcpy(buf, "Spell::boot_Spell"), boot_Spell, file); - newXS(strcpy(buf, "HateEntry::boot_HateEntry"), boot_HateEntry, file); - newXS(strcpy(buf, "Object::boot_Object"), boot_Object, file); - newXS(strcpy(buf, "Doors::boot_Doors"), boot_Doors, file); - newXS(strcpy(buf, "Expedition::boot_Expedition"), boot_Expedition, file); -#ifdef BOTS - newXS(strcpy(buf, "Bot::boot_Mob"), boot_Mob, file); - newXS(strcpy(buf, "Bot::boot_NPC"), boot_NPC, file); - newXS(strcpy(buf, "Bot::boot_Bot"), boot_Bot, file); -#endif -; -#endif -#endif #ifdef EMBPERL_IO_CAPTURE newXS(strcpy(buf, "EQEmuIO::PRINT"), XS_EQEmuIO_PRINT, file); #endif @@ -133,7 +84,7 @@ void Embperl::DoInit() { perl_run(my_perl); //a little routine we use a lot. - eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error + eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error //ruin the perl exit and command: eval_pv("sub my_exit {}",TRUE); @@ -200,11 +151,11 @@ void Embperl::DoInit() { //should probably read the directory in c, instead, so that //I can echo filenames as I do it, but c'mon... I'm lazy and this 1 line reads in all the plugins std::string perl_command = - "if(opendir(D,'" + Config->PluginDir +"')) { " + "if(opendir(D,'" + path.GetPluginsPath() +"')) { " " my @d = readdir(D);" " closedir(D);" " foreach(@d){ " - " main::eval_file('plugin','" + Config->PluginDir + "/'.$_)if/\\.pl$/;" + " main::eval_file('plugin','" + path.GetPluginsPath() + "/'.$_)if/\\.pl$/;" " }" "}"; eval_pv(perl_command.c_str(),FALSE); @@ -281,21 +232,21 @@ int Embperl::eval_file(const char * packagename, const char * filename) std::vector args; args.push_back(packagename); args.push_back(filename); + return dosub("main::eval_file", &args); } int Embperl::dosub(const char * subname, const std::vector * args, int mode) { dSP; - int ret_value = 0; - int count; + int ret_value = 0; + int count; std::string error; ENTER; SAVETMPS; PUSHMARK(SP); - if(args && !args->empty()) - { + if (args && !args->empty()) { for (auto i = args->begin(); i != args->end(); ++i) { XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length()))); } @@ -305,16 +256,14 @@ int Embperl::dosub(const char * subname, const std::vector * args, count = call_pv(subname, mode); SPAGAIN; - if(SvTRUE(ERRSV)) - { + if (SvTRUE(ERRSV)) { error = SvPV_nolen(ERRSV); POPs; } - else - { - if(count == 1) { + else { + if (count == 1) { SV *ret = POPs; - if(SvTYPE(ret) == SVt_IV) { + if (SvTYPE(ret) == SVt_IV) { IV v = SvIV(ret); ret_value = v; } @@ -325,8 +274,26 @@ int Embperl::dosub(const char * subname, const std::vector * args, FREETMPS; LEAVE; - if(error.length() > 0) - { + // not sure why we pass this as blind args, strange + // check for syntax errors + if (args && !args->empty()) { + const std::string &filename = args->back(); + std::string sub = subname; + if (sub == "main::eval_file" && !filename.empty() && File::Exists(filename)) { + BenchTimer benchmark; + std::string syntax_error = Process::execute( + fmt::format("perl -c {} 2>&1", filename) + ); + LogQuests("Perl eval [{}] took [{}]", filename, benchmark.elapsed()); + syntax_error = Strings::Trim(syntax_error); + if (!Strings::Contains(syntax_error, "syntax OK")) { + syntax_error += SvPVX(ERRSV); + throw syntax_error; + } + } + } + + if (error.length() > 0) { std::string errmsg = "Perl runtime error: "; errmsg += SvPVX(ERRSV); throw errmsg; diff --git a/zone/embperl.h b/zone/embperl.h index 816e9b84a..d639a4311 100644 --- a/zone/embperl.h +++ b/zone/embperl.h @@ -18,22 +18,13 @@ Eglin #include #include -//headers from the Perl distribution -#include -#define WIN32IO_IS_STDIO +// this option disables distinct int/float/string function argument types for +// backwards compatibility with current perl api usage +// e.g. quest::settimer(0, 1) using number for timer name instead of string +#define PERLBIND_NO_STRICT_SCALAR_TYPES +#include +namespace perl = perlbind; -#ifndef WIN32 -extern "C" { //the perl headers dont do this for us... -#endif -#if _MSC_VER -#define __inline__ __inline -#define __builtin_expect -#endif -#include -#include -#ifndef WIN32 -}; -#endif #ifdef WIN32 #define snprintf _snprintf #endif @@ -138,6 +129,11 @@ public: SV *t = get_sv(varname, true); sv_setpv(t, val); } + // put a pointer into a blessed perl variable + void setptr(const char* varname, const char* classname, void* val) const { + SV* t = get_sv(varname, GV_ADD); + sv_setref_pv(t, classname, val); + } // put key-value pairs in hash void sethash(const char *varname, std::map &vals) diff --git a/zone/embxs.cpp b/zone/embxs.cpp index d22f3ecac..2481b330c 100644 --- a/zone/embxs.cpp +++ b/zone/embxs.cpp @@ -16,80 +16,41 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef EMBPERL +#ifdef EMBPERL #include "../common/global_define.h" #include "../common/eqemu_logsys.h" +#include "embxs.h" +#include "embperl.h" #include "masterentity.h" #include "command.h" -#ifdef BOTS #include "bot_command.h" -#endif -#include "embperl.h" -#include "embxs.h" - - - -const char *getItemName(unsigned itemid) -{ +const char *getItemName(unsigned itemid) +{ const EQ::ItemData* item = nullptr; - item = database.GetItem(itemid); + item = database.GetItem(itemid); - if (item) - return item->Name; - else - return nullptr; -} - -XS(XS_qc_getItemName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_qc_getItemName) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: quest::getItemName(itemid)"); - { - unsigned itemid = (unsigned)SvUV(ST(0)); - const char * RETVAL; - dXSTARG; - RETVAL = getItemName(itemid); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); + if (item) + return item->Name; + else + return nullptr; } - -EXTERN_C XS(boot_qc); /* prototype to pass -Wmissing-prototypes */ -EXTERN_C XS(boot_qc) -{ - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = '\0'; - - if(items != 1) - LogError("boot_qc does not take any arguments"); - - char buf[128]; //shouldent have any function names longer than this. - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK ; - - newXS(strcpy(buf, "quest::getItemName"), XS_qc_getItemName, file); - - XSRETURN_YES; +const char* Perl__qc_getItemName(unsigned itemid) +{ + return getItemName(itemid); // possible nullptr return } #ifdef EMBPERL_IO_CAPTURE -XS(XS_EQEmuIO_PRINT); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQEmuIO_PRINT) -{ - dXSARGS; +XS(XS_EQEmuIO_PRINT); /* prototype to pass -Wmissing-prototypes */ +XS(XS_EQEmuIO_PRINT) +{ + dXSARGS; if (items < 2) return; -// Perl_croak(aTHX_ "Usage: EQEmuIO::PRINT(@strings)"); +// Perl_croak(aTHX_ "Usage: EQEmuIO::PRINT(@strings)"); int r; for (r = 1; r < items; r++) { diff --git a/zone/embxs.h b/zone/embxs.h index 97e3bb573..22f294ca6 100644 --- a/zone/embxs.h +++ b/zone/embxs.h @@ -1,24 +1,7 @@ #ifndef EMBXS_H #define EMBXS_H -//headers from the Perl distribution -#include -#define WIN32IO_IS_STDIO - -#ifndef WIN32 -extern "C" { //the perl headers dont do this for us... -#endif -#if _MSC_VER -#define __inline__ __inline -#define __builtin_expect -#endif -#include -#include -#ifndef WIN32 -}; -#endif - const char *getItemName(unsigned itemid); -XS(XS_qc_getItemName); /* prototype to pass -Wmissing-prototypes */ -EXTERN_C XS(boot_qc); /* prototype to pass -Wmissing-prototypes */ +const char* Perl__qc_getItemName(unsigned itemid); + #endif // EMBXS_H diff --git a/zone/encounter.cpp b/zone/encounter.cpp index 5eba3b028..f03909e2f 100644 --- a/zone/encounter.cpp +++ b/zone/encounter.cpp @@ -32,13 +32,64 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA class Zone; -Encounter::Encounter(const char* enc_name) - :Mob - ( - nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, glm::vec4(0,0,0,0), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQ::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false - ) -{ +Encounter::Encounter(const char *enc_name) : Mob( + nullptr, // in_name + nullptr, // in_lastname + 0, // in_cur_hp + 0, // in_max_hp + MALE, // in_gender + INVISIBLE_MAN, // in_race + 0, // in_class + BT_NoTarget, // in_bodytype + 0, // in_deity + 0, // in_level + 0, // in_npcype_id + 0, // in_size + 0, // in_runspeed + glm::vec4(0, 0, 0, 0), // position + 0, // in_light + 0, // in_texture + 0, // in_helmtexture + 0, // in_ac + 0, // in_atk + 0, // in_str + 0, // in_sta + 0, // in_dex + 0, // in_agi + 0, // in_int + 0, // in_wis + 0, // in_cha + 0, // in_haircolor + 0, // in_beardcolor + 0, // in_eyecolor1 + 0, // in_eyecolor2 + 0, // in_hairstyle + 0, // in_luclinface + 0, // in_beard + 0, // in_drakkin_heritage + 0, // in_drakkin_tattoo + 0, // in_drakkin_details + EQ::TintProfile(), // in_armor_tint + 0, // in_aa_title + 0, // in_see_invis + 0, // in_see_invis_undead + 0, // in_see_hide + 0, // in_see_improved_hide + 0, // in_hp_regen + 0, // in_mana_regen + 0, // in_qglobal + 0, // in_maxlevel + 0, // in_scalerate + 0, // in_armtexture + 0, // in_bracertexture + 0, // in_handtexture + 0, // in_legtexture + 0, // in_feettexture + 0, // in_usemodel + false, // in_always_aggros_foes + 0, // in_heroic_strikethrough + false // in_keeps_sold_items +) { encounter_name[0] = 0; strn0cpy(encounter_name, enc_name, 64); remove_me = false; diff --git a/zone/encounter.h b/zone/encounter.h index fd9f5e99d..8e79f356d 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -36,8 +36,8 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) { return true; } virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; } - virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr) { + bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override { return false; } virtual bool HasRaid() { return false; } diff --git a/zone/entity.cpp b/zone/entity.cpp index 1f786cb4c..af1d4e880 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -15,6 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "../common/data_verification.h" #include "../common/global_define.h" #include #include @@ -51,9 +52,7 @@ #define strcasecmp _stricmp #endif -#ifdef BOTS #include "bot.h" -#endif extern Zone *zone; extern volatile bool is_zone_loaded; @@ -277,29 +276,15 @@ const Encounter* Entity::CastToEncounter() const return static_cast(this); } -#ifdef BOTS Bot *Entity::CastToBot() { -#ifdef _EQDEBUG - if (!IsBot()) { - std::cout << "CastToBot error" << std::endl; - return 0; - } -#endif return static_cast(this); } const Bot *Entity::CastToBot() const { -#ifdef _EQDEBUG - if (!IsBot()) { - std::cout << "CastToBot error" << std::endl; - return 0; - } -#endif return static_cast(this); } -#endif EntityList::EntityList() : @@ -553,11 +538,9 @@ void EntityList::MobProcess() if(mob->IsMerc()) { entity_list.RemoveMerc(id); } -#ifdef BOTS else if(mob->IsBot()) { entity_list.RemoveBot(id); } -#endif else if(mob->IsNPC()) { entity_list.RemoveNPC(id); } @@ -567,7 +550,6 @@ void EntityList::MobProcess() in.s_addr = mob->CastToClient()->GetIP(); LogInfo("Dropping client: Process=false, ip=[{}] port=[{}]", inet_ntoa(in), mob->CastToClient()->GetPort()); #endif - zone->StartShutdownTimer(); Group *g = GetGroupByMob(mob); if(g) { LogError("About to delete a client still in a group"); @@ -685,66 +667,61 @@ void EntityList::AddCorpse(Corpse *corpse, uint32 in_id) corpse_timer.Start(); } -void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) +void EntityList::AddNPC(NPC *npc, bool send_spawn_packet, bool dont_queue) { npc->SetID(GetFreeID()); //If this is not set here we will despawn pets from new AC changes auto owner_id = npc->GetOwnerID(); - if(owner_id) { + if (owner_id) { auto owner = entity_list.GetMob(owner_id); if (owner) { owner->SetPetID(npc->GetID()); } } - parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); - - uint16 emoteid = npc->GetEmoteID(); - if (emoteid != 0) - npc->DoNPCEmote(ONSPAWN, emoteid); - npc->SetSpawned(); - if (SendSpawnPacket) { - if (dontqueue) { // aka, SEND IT NOW BITCH! - auto app = new EQApplicationPacket; - npc->CreateSpawnPacket(app, npc); - QueueClients(npc, app); - npc->SendArmorAppearance(); - npc->SetAppearance(npc->GetGuardPointAnim(),false); - if (!npc->IsTargetable()) - npc->SendTargetable(false); - safe_delete(app); - } else { - auto ns = new NewSpawn_Struct; - memset(ns, 0, sizeof(NewSpawn_Struct)); - npc->FillSpawnStruct(ns, nullptr); // Not working on player newspawns, so it's safe to use a ForWho of 0 - AddToSpawnQueue(npc->GetID(), &ns); - safe_delete(ns); - } - if (npc->IsFindable()) - UpdateFindableNPCState(npc, false); - } npc_list.insert(std::pair(npc->GetID(), npc)); mob_list.insert(std::pair(npc->GetID(), npc)); - entity_list.ScanCloseMobs(npc->close_mobs, npc, true); + parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); - /* Zone controller process EVENT_SPAWN_ZONE */ - if (RuleB(Zone, UseZoneController)) { - auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID); - if (controller && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ - std::string export_string = fmt::format( - "{} {}", - npc->GetID(), - npc->GetNPCTypeID() - ); - parse->EventNPC(EVENT_SPAWN_ZONE, controller, nullptr, export_string, 0); + const auto emote_id = npc->GetEmoteID(); + if (emote_id != 0) { + npc->DoNPCEmote(EQ::constants::EmoteEventTypes::OnSpawn, emote_id); + } + + npc->SetSpawned(); + + if (send_spawn_packet) { + if (dont_queue) { + auto app = new EQApplicationPacket; + npc->CreateSpawnPacket(app, npc); + QueueClients(npc, app); + npc->SendArmorAppearance(); + npc->SetAppearance(npc->GetGuardPointAnim(), false); + + if (!npc->IsTargetable()) { + npc->SendTargetable(false); + } + + safe_delete(app); + } else { + auto ns = new NewSpawn_Struct; + memset(ns, 0, sizeof(NewSpawn_Struct)); + npc->FillSpawnStruct(ns, nullptr); + AddToSpawnQueue(npc->GetID(), &ns); + safe_delete(ns); + } + + if (npc->IsFindable()) { + UpdateFindableNPCState(npc, false); } } - /** - * Set whether NPC was spawned in or out of water - */ + entity_list.ScanCloseMobs(npc->close_mobs, npc, true); + + npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr); + if (zone->HasMap() && zone->HasWaterMap()) { npc->SetSpawnedInWater(false); if (zone->watermap->InLiquid(npc->GetPosition())) { @@ -1725,6 +1702,9 @@ void EntityList::QueueCloseClients( for (auto &e : GetCloseMobList(sender, distance)) { Mob *mob = e.second; + if (!mob) { + continue; + } if (!mob->IsClient()) { continue; @@ -1803,7 +1783,7 @@ void EntityList::QueueClientsStatus(Mob *sender, const EQApplicationPacket *app, void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee) { if (winner->GetLevelCon(winner->GetLevel(), loser->GetLevel()) > 2) { - std::vector args; + std::vector args; args.push_back(winner); args.push_back(loser); @@ -1871,14 +1851,55 @@ Client *EntityList::GetClientByLSID(uint32 iLSID) return nullptr; } +Bot* EntityList::GetRandomBot(const glm::vec3& location, float distance, Bot* exclude_bot) +{ + auto is_whole_zone = false; + if (location.x == 0.0f && location.y == 0.0f) { + is_whole_zone = true; + } + + auto distance_squared = (distance * distance); + + std::vector bots_in_range; + + for (const auto& b : bot_list) { + if ( + b != exclude_bot && + ( + is_whole_zone || + DistanceSquared(static_cast(b->GetPosition()), location) <= distance_squared + ) + ) { + bots_in_range.push_back(b); + } + } + + if (bots_in_range.empty()) { + return nullptr; + } + + return bots_in_range[zone->random.Int(0, bots_in_range.size() - 1)]; + +} + Client *EntityList::GetRandomClient(const glm::vec3& location, float distance, Client *exclude_client) { + auto is_whole_zone = false; + if (location.x == 0.0f && location.y == 0.0f) { + is_whole_zone = true; + } + + auto distance_squared = (distance * distance); + std::vector clients_in_range; for (const auto& client : client_list) { if ( client.second != exclude_client && - DistanceSquared(static_cast(client.second->GetPosition()), location) <= distance + ( + is_whole_zone || + DistanceSquared(static_cast(client.second->GetPosition()), location) <= distance_squared + ) ) { clients_in_range.push_back(client.second); } @@ -1893,12 +1914,22 @@ Client *EntityList::GetRandomClient(const glm::vec3& location, float distance, C NPC* EntityList::GetRandomNPC(const glm::vec3& location, float distance, NPC* exclude_npc) { + auto is_whole_zone = false; + if (location.x == 0.0f && location.y == 0.0f) { + is_whole_zone = true; + } + + auto distance_squared = (distance * distance); + std::vector npcs_in_range; for (const auto& npc : npc_list) { if ( npc.second != exclude_npc && - DistanceSquared(static_cast(npc.second->GetPosition()), location) <= distance + ( + is_whole_zone || + DistanceSquared(static_cast(npc.second->GetPosition()), location) <= distance_squared + ) ) { npcs_in_range.push_back(npc.second); } @@ -1913,12 +1944,22 @@ NPC* EntityList::GetRandomNPC(const glm::vec3& location, float distance, NPC* ex Mob* EntityList::GetRandomMob(const glm::vec3& location, float distance, Mob* exclude_mob) { + auto is_whole_zone = false; + if (location.x == 0.0f && location.y == 0.0f) { + is_whole_zone = true; + } + + auto distance_squared = (distance * distance); + std::vector mobs_in_range; for (const auto& mob : mob_list) { if ( mob.second != exclude_mob && - DistanceSquared(static_cast(mob.second->GetPosition()), location) <= distance + ( + is_whole_zone || + DistanceSquared(static_cast(mob.second->GetPosition()), location) <= distance_squared + ) ) { mobs_in_range.push_back(mob.second); } @@ -2091,6 +2132,14 @@ Group *EntityList::GetGroupByID(uint32 group_id) return nullptr; } +bool EntityList::IsInSameGroupOrRaidGroup(Client *client1, Client *client2) { + Group* group = entity_list.GetGroupByClient(client1); + Raid* raid = entity_list.GetRaidByClient(client1); + + return (group && group->IsGroupMember(client2)) + || (raid && raid->IsRaidMember(client2->GetName()) && raid->GetGroup(client1) == raid->GetGroup(client2)); +} + Group *EntityList::GetGroupByClient(Client *client) { std::list ::iterator iterator; @@ -2366,6 +2415,7 @@ void EntityList::FilteredMessageCloseString( uint32 type, eqFilterType filter, uint32 string_id, + Mob *skip, const char *message1, const char *message2, const char *message3, @@ -2382,7 +2432,7 @@ void EntityList::FilteredMessageCloseString( for (auto & it : client_list) { c = it.second; - if (c && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender)) { + if (c && c != skip && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender)) { c->FilteredMessageString( sender, type, filter, string_id, message1, message2, message3, message4, message5, @@ -2857,7 +2907,7 @@ void EntityList::ScanCloseMobs( for (auto &e : mob_list) { auto mob = e.second; - if (!mob->IsNPC() && !mob->IsClient()) { + if (!mob->IsNPC() && !mob->IsClient() && !mob->IsBot() && !mob->IsMerc()) { continue; } @@ -2886,7 +2936,7 @@ void EntityList::ScanCloseMobs( } } - LogAIScanClose( + LogAIScanCloseDetail( "[{}] Scanning Close List | list_size [{}] moving [{}]", scanning_mob->GetCleanName(), close_mobs.size(), @@ -3075,13 +3125,8 @@ void EntityList::RemoveEntity(uint16 id) return; else if (entity_list.RemoveMerc(id)) return; - -#ifdef BOTS - // This block of code is necessary to clean up bot objects else if (entity_list.RemoveBot(id)) return; -#endif //BOTS - else entity_list.RemoveObject(id); } @@ -3308,18 +3353,44 @@ uint32 EntityList::DeleteNPCCorpses() void EntityList::CorpseFix(Client* c) { + uint32 fixed_count = 0; + for (const auto& e : corpse_list) { + auto cur = e.second; + if (cur->IsNPCCorpse()) { + if (DistanceNoZ(c->GetPosition(), cur->GetPosition()) < 100) { + c->Message( + Chat::White, + fmt::format( + "Attempting to fix {}.", + cur->GetCleanName() + ).c_str() + ); - auto it = corpse_list.begin(); - while (it != corpse_list.end()) { - Corpse* corpse = it->second; - if (corpse->IsNPCCorpse()) { - if (DistanceNoZ(c->GetPosition(), corpse->GetPosition()) < 100) { - c->Message(Chat::Yellow, "Attempting to fix %s", it->second->GetCleanName()); - corpse->GMMove(corpse->GetX(), corpse->GetY(), c->GetZ() + 2, 0); + cur->GMMove( + cur->GetX(), + cur->GetY(), + cur->GetFixedZ(c->GetPosition()), + c->GetHeading() + ); + + fixed_count++; } } - ++it; } + + if (!fixed_count) { + c->Message(Chat::White, "There were no nearby NPC corpses to fix."); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Fixed {} nearby NPC corpse{}.", + fixed_count, + fixed_count != 1 ? "s" : "" + ).c_str() + ); } // returns the number of corpses deleted. A negative number indicates an error code. @@ -3570,7 +3641,7 @@ void EntityList::ClearFeignAggro(Mob *targ) } if (targ->IsClient()) { - std::vector args; + std::vector args; args.push_back(it->second); int i = parse->EventPlayer(EVENT_FEIGN_DEATH, targ->CastToClient(), "", 0, &args); if (i != 0) { @@ -3642,46 +3713,53 @@ void EntityList::SignalMobsByNPCID(uint32 snpc, int signal_id) bool EntityList::MakeTrackPacket(Client *client) { std::list > tracking_list; - uint32 distance = 0; - float MobDistance; + auto distance = static_cast(client->GetSkill(EQ::skills::SkillTracking) * client->GetClassTrackingDistanceMultiplier(client->GetClass())); - distance = (client->GetSkill(EQ::skills::SkillTracking) * client->GetClassTrackingDistanceMultiplier(client->GetClass())); - - if (distance <= 0) + if (distance <= 0.0f) { return false; - if (distance < 300) - distance = 300; + } + + if (distance < 300.0f) { + distance = 300.0f; + } for (auto it = mob_list.cbegin(); it != mob_list.cend(); ++it) { - if (!it->second || it->second == client || !it->second->IsTrackable() || - it->second->IsInvisible(client)) + if ( + !it->second || + it->second == client || + !it->second->IsTrackable() || + it->second->IsInvisible(client) + ) { continue; + } - MobDistance = DistanceNoZ(it->second->GetPosition(), client->GetPosition()); - if (MobDistance > distance) + const auto mob_distance = DistanceNoZ(it->second->GetPosition(), client->GetPosition()); + if (mob_distance > distance) { continue; + } - tracking_list.push_back(std::make_pair(it->second, MobDistance)); + tracking_list.push_back(std::make_pair(it->second, mob_distance)); } tracking_list.sort( [](const std::pair &a, const std::pair &b) { return a.first->GetSpawnTimeStamp() > b.first->GetSpawnTimeStamp(); - }); + } + ); + auto outapp = new EQApplicationPacket(OP_Track, sizeof(Track_Struct) * tracking_list.size()); - Tracking_Struct *outtrack = (Tracking_Struct *)outapp->pBuffer; + auto pack = (Tracking_Struct *) outapp->pBuffer; outapp->priority = 6; int index = 0; for (auto it = tracking_list.cbegin(); it != tracking_list.cend(); ++it, ++index) { - Mob *cur_entity = it->first; - outtrack->Entrys[index].entityid = (uint32)cur_entity->GetID(); - outtrack->Entrys[index].distance = it->second; - outtrack->Entrys[index].level = cur_entity->GetLevel(); - outtrack->Entrys[index].is_npc = !cur_entity->IsClient(); - strn0cpy(outtrack->Entrys[index].name, cur_entity->GetName(), sizeof(outtrack->Entrys[index].name)); - outtrack->Entrys[index].is_pet = cur_entity->IsPet(); - outtrack->Entrys[index].is_merc = cur_entity->IsMerc(); + pack->Entrys[index].entityid = static_cast(it->first->GetID()); + pack->Entrys[index].distance = it->second; + pack->Entrys[index].level = it->first->GetLevel(); + pack->Entrys[index].is_npc = !it->first->IsClient(); + strn0cpy(pack->Entrys[index].name, it->first->GetName(), sizeof(pack->Entrys[index].name)); + pack->Entrys[index].is_pet = it->first->IsPet(); + pack->Entrys[index].is_merc = it->first->IsMerc(); } client->QueuePacket(outapp); @@ -3909,14 +3987,31 @@ void EntityList::ProcessMove(Client *c, const glm::vec3& location) for (auto iter = events.begin(); iter != events.end(); ++iter) { quest_proximity_event& evt = (*iter); + + std::vector args; + args.push_back(&evt.area_id); + args.push_back(&evt.area_type); + if (evt.npc) { - std::vector args; - parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0, &args); + if (evt.event_id == EVENT_ENTER) { + parse->EventNPC(EVENT_ENTER, evt.npc, evt.client, "", 0); + } else if (evt.event_id == EVENT_EXIT) { + parse->EventNPC(EVENT_EXIT, evt.npc, evt.client, "", 0); + } else if (evt.event_id == EVENT_ENTER_AREA) { + parse->EventNPC(EVENT_ENTER_AREA, evt.npc, evt.client, "", 0, &args); + } else if (evt.event_id == EVENT_LEAVE_AREA) { + parse->EventNPC(EVENT_LEAVE_AREA, evt.npc, evt.client, "", 0, &args); + } } else { - std::vector args; - args.push_back(&evt.area_id); - args.push_back(&evt.area_type); - parse->EventPlayer(evt.event_id, evt.client, "", 0, &args); + if (evt.event_id == EVENT_ENTER) { + parse->EventPlayer(EVENT_ENTER, evt.client, "", 0); + } else if (evt.event_id == EVENT_EXIT) { + parse->EventPlayer(EVENT_EXIT, evt.client, "", 0); + } else if (evt.event_id == EVENT_ENTER_AREA) { + parse->EventPlayer(EVENT_ENTER_AREA, evt.client, "", 0, &args); + } else if (evt.event_id == EVENT_LEAVE_AREA) { + parse->EventPlayer(EVENT_LEAVE_AREA, evt.client, "", 0, &args); + } } } } @@ -3969,10 +4064,20 @@ void EntityList::ProcessMove(NPC *n, float x, float y, float z) { for (auto iter = events.begin(); iter != events.end(); ++iter) { quest_proximity_event &evt = (*iter); - std::vector args; + + std::vector args; args.push_back(&evt.area_id); args.push_back(&evt.area_type); - parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0, &args); + + if (evt.event_id == EVENT_ENTER) { + parse->EventNPC(EVENT_ENTER, evt.npc, evt.client, "", 0); + } else if (evt.event_id == EVENT_EXIT) { + parse->EventNPC(EVENT_EXIT, evt.npc, evt.client, "", 0); + } else if (evt.event_id == EVENT_ENTER_AREA) { + parse->EventNPC(EVENT_ENTER_AREA, evt.npc, evt.client, "", 0, &args); + } else if (evt.event_id == EVENT_LEAVE_AREA) { + parse->EventNPC(EVENT_LEAVE_AREA, evt.npc, evt.client, "", 0, &args); + } } } @@ -4216,10 +4321,12 @@ bool EntityList::LimitCheckName(const char *npc_name) { auto it = npc_list.begin(); while (it != npc_list.end()) { - NPC* npc = it->second; - if (npc) - if (strcasecmp(npc_name, npc->GetRawNPCTypeName()) == 0) + NPC *npc = it->second; + if (npc) { + if (strcasecmp(npc_name, npc->GetRawNPCTypeName()) == 0) { return false; + } + } ++it; } return true; @@ -4373,6 +4480,9 @@ void EntityList::QuestJournalledSayClose( if (RuleB(Chat, QuestDialogueUsesDialogueWindow)) { for (auto &e : GetCloseMobList(sender, (dist * dist))) { Mob *mob = e.second; + if (!mob) { + continue; + } if (!mob->IsClient()) { continue; @@ -4892,9 +5002,9 @@ void EntityList::ZoneWho(Client *c, Who_All_Struct *Who) FormatMSGID = 5024; // 5024 %T1[ANONYMOUS] %2 %3 else if (ClientEntry->GetAnon() == 2) FormatMSGID = 5023; // 5023 %T1[ANONYMOUS] %2 %3 %4 - uint32 PlayerClass = 0; + uint32 PlayerClass = NO_CLASS; uint32 PlayerLevel = 0; - uint32 PlayerRace = 0; + uint32 PlayerRace = RACE_DOUG_0; uint32 ZoneMSGID = 0xFFFFFFFF; if (ClientEntry->GetAnon()==0) { @@ -4998,14 +5108,12 @@ void EntityList::GateAllClients() } } -void EntityList::SignalAllClients(uint32 data) +void EntityList::SignalAllClients(int signal_id) { - auto it = client_list.begin(); - while (it != client_list.end()) { - Client *ent = it->second; - if (ent) - ent->Signal(data); - ++it; + for (const auto& c : client_list) { + if (c.second) { + c.second->Signal(signal_id); + } } } @@ -5053,16 +5161,16 @@ void EntityList::GetClientList(std::list &c_list) } } -#ifdef BOTS void EntityList::GetBotList(std::list &b_list) { b_list.clear(); - for (auto bot : bot_list) { - b_list.push_back(bot); + + for (const auto& b : bot_list) { + b_list.push_back(b); } } -std::vector EntityList::GetBotListByCharacterID(uint32 character_id) +std::vector EntityList::GetBotListByCharacterID(uint32 character_id, uint8 class_id) { std::vector client_bot_list; @@ -5070,16 +5178,20 @@ std::vector EntityList::GetBotListByCharacterID(uint32 character_id) return client_bot_list; } - for (auto bot : bot_list) { - if (bot->GetOwner() && bot->GetBotOwnerCharacterID() == character_id) { - client_bot_list.push_back(bot); + for (const auto& b : bot_list) { + if ( + b->GetOwner() && + b->GetBotOwnerCharacterID() == character_id && + (!class_id || b->GetClass() == class_id) + ) { + client_bot_list.push_back(b); } } return client_bot_list; } -std::vector EntityList::GetBotListByClientName(std::string client_name) +std::vector EntityList::GetBotListByClientName(std::string client_name, uint8 class_id) { std::vector client_bot_list; @@ -5087,15 +5199,58 @@ std::vector EntityList::GetBotListByClientName(std::string client_name) return client_bot_list; } - for (auto bot : bot_list) { - if (bot->GetOwner() && str_tolower(bot->GetOwner()->GetCleanName()) == str_tolower(client_name)) { - client_bot_list.push_back(bot); + for (const auto& b : bot_list) { + if ( + b->GetOwner() && + Strings::ToLower(b->GetOwner()->GetCleanName()) == Strings::ToLower(client_name) && + (!class_id || b->GetClass() == class_id) + ) { + client_bot_list.push_back(b); } } return client_bot_list; } -#endif + +void EntityList::SignalAllBotsByOwnerCharacterID(uint32 character_id, int signal_id) +{ + auto client_bot_list = GetBotListByCharacterID(character_id); + if (client_bot_list.empty()) { + return; + } + + for (const auto& b : client_bot_list) { + b->Signal(signal_id); + } +} + +void EntityList::SignalAllBotsByOwnerName(std::string owner_name, int signal_id) +{ + auto client_bot_list = GetBotListByClientName(owner_name); + if (client_bot_list.empty()) { + return; + } + + for (const auto& b : client_bot_list) { + b->Signal(signal_id); + } +} + +void EntityList::SignalBotByBotID(uint32 bot_id, int signal_id) +{ + auto b = GetBotByBotID(bot_id); + if (b) { + b->Signal(signal_id); + } +} + +void EntityList::SignalBotByBotName(std::string bot_name, int signal_id) +{ + auto b = GetBotByBotName(bot_name); + if (b) { + b->Signal(signal_id); + } +} void EntityList::GetCorpseList(std::list &c_list) { @@ -5359,12 +5514,12 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count) safe_delete_array(marked); } -void EntityList::CameraEffect(uint32 duration, uint32 intensity) +void EntityList::CameraEffect(uint32 duration, float intensity) { auto outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer; cs->duration = duration; // Duration in milliseconds - cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10. + cs->intensity = intensity; entity_list.QueueClients(0, outapp); safe_delete(outapp); } @@ -5508,7 +5663,6 @@ std::vector EntityList::GetTargetsForVirusEffect(Mob *spreader, Mob *origi bool is_detrimental_spell = IsDetrimentalSpell(spell_id); for (auto &it : entity_list.GetCloseMobList(spreader, range)) { Mob *mob = it.second; - if (!mob) { continue; } @@ -5692,10 +5846,107 @@ int EntityList::MovePlayerCorpsesToGraveyard(bool force_move_from_instance) } void EntityList::DespawnGridNodes(int32 grid_id) { - for (auto mob_iterator : mob_list) { - Mob *mob = mob_iterator.second; - if (mob->IsNPC() && mob->GetRace() == 2254 && mob->EntityVariableExists("grid_id") && atoi(mob->GetEntityVariable("grid_id")) == grid_id) { + for (auto m : mob_list) { + Mob *mob = m.second; + if ( + mob->IsNPC() && + mob->GetRace() == RACE_NODE_2254 && + mob->EntityVariableExists("grid_id") && + std::stoi(mob->GetEntityVariable("grid_id")) == grid_id) + { mob->Depop(); } } } + +void EntityList::Marquee(uint32 type, std::string message, uint32 duration) { + for (const auto& c : client_list) { + if (c.second) { + c.second->SendMarqueeMessage(type, message, duration); + } + } +} + +void EntityList::Marquee( + uint32 type, + uint32 priority, + uint32 fade_in, + uint32 fade_out, + uint32 duration, + std::string message +) { + for (const auto& c : client_list) { + if (c.second) { + c.second->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, message); + } + } +} + +std::vector EntityList::GetFilteredEntityList(Mob* sender, uint32 distance, EntityFilterType filter_type) +{ + std::vector l; + if (!sender) { + return l; + } + + const auto squared_distance = (distance * distance); + const auto position = sender->GetPosition(); + for (auto &m: mob_list) { + if (!m.second) { + continue; + } + + if (m.second == sender) { + continue; + } + + if ( + distance && + DistanceSquaredNoZ( + position, + m.second->GetPosition() + ) > squared_distance + ) { + continue; + } + + if ( + (filter_type == EntityFilterType::Bots && !m.second->IsBot()) || + (filter_type == EntityFilterType::Clients && !m.second->IsClient()) || + (filter_type == EntityFilterType::NPCs && !m.second->IsNPC()) + ) { + continue; + } + + l.push_back(m.second); + } + + return l; +} + +void EntityList::DamageArea( + Mob* sender, + int64 damage, + uint32 distance, + EntityFilterType filter_type, + bool is_percentage +) { + if (!sender) { + return; + } + + if (damage <= 0) { + return; + } + + const auto& l = GetFilteredEntityList(sender, distance, filter_type); + for (const auto& e : l) { + if (is_percentage) { + const auto damage_percentage = EQ::Clamp(damage, static_cast(1), static_cast(100)); + const auto total_damage = (e->GetMaxHP() / 100) * damage_percentage; + e->Damage(sender, total_damage, SPELL_UNKNOWN, EQ::skills::SkillEagleStrike); + } else { + e->Damage(sender, damage, SPELL_UNKNOWN, EQ::skills::SkillEagleStrike); + } + } +} diff --git a/zone/entity.h b/zone/entity.h index f06e26119..d79bd9e83 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -26,6 +26,7 @@ #include "../common/servertalk.h" #include "../common/bodytypes.h" #include "../common/eq_constants.h" +#include "../common/emu_constants.h" #include "position.h" #include "zonedump.h" @@ -56,10 +57,7 @@ struct QGlobal; struct UseAA_Struct; struct Who_All_Struct; -#ifdef BOTS class Bot; -class BotRaids; -#endif extern EntityList entity_list; @@ -117,10 +115,8 @@ public: virtual const char* GetName() { return ""; } bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1); -#ifdef BOTS Bot* CastToBot(); const Bot* CastToBot() const; -#endif protected: friend class EntityList; @@ -189,10 +185,13 @@ public: Client *GetClientByWID(uint32 iWID); Client *GetClientByLSID(uint32 iLSID); Client *GetClient(uint32 ip, uint16 port); - Client* GetRandomClient(const glm::vec3& location, float distance, Client* exclude_client = nullptr); - NPC* GetRandomNPC(const glm::vec3& location, float distance, NPC* exclude_npc = nullptr); - Mob* GetRandomMob(const glm::vec3& location, float distance, Mob* exclude_mob = nullptr); + + Bot* GetRandomBot(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Bot* exclude_bot = nullptr); + Client* GetRandomClient(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Client* exclude_client = nullptr); + NPC* GetRandomNPC(const glm::vec3& location = glm::vec3(0.f), float distance = 0, NPC* exclude_npc = nullptr); + Mob* GetRandomMob(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Mob* exclude_mob = nullptr); Group *GetGroupByMob(Mob* mob); + bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2); Group *GetGroupByClient(Client* client); Group *GetGroupByID(uint32 id); Group *GetGroupByLeaderName(const char* leader); @@ -271,7 +270,7 @@ public: bool MakeTrackPacket(Client* client); void SendTraders(Client* client); void AddClient(Client*); - void AddNPC(NPC*, bool SendSpawnPacket = true, bool dontqueue = false); + void AddNPC(NPC*, bool send_spawn_packet = true, bool dont_queue = false); void AddMerc(Merc*, bool SendSpawnPacket = true, bool dontqueue = false); void AddCorpse(Corpse* pc, uint32 in_id = 0xFFFFFFFF); void AddObject(Object*, bool SendSpawnPacket = true); @@ -333,6 +332,22 @@ public: void DescribeAggro(Client *to_who, NPC *from_who, float dist, bool verbose); + std::vector GetFilteredEntityList( + Mob* sender, + uint32 distance = 0, + EntityFilterType filter_type = EntityFilterType::All + ); + + void DamageArea( + Mob* sender, + int64 damage, + uint32 distance = 0, + EntityFilterType filter_type = EntityFilterType::All, + bool is_percentage = false + ); + + void Marquee(uint32 type, std::string message, uint32 duration = 3000); + void Marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message); void Message(uint32 to_guilddbid, uint32 type, const char* message, ...); void MessageStatus(uint32 to_guilddbid, int to_minstatus, uint32 type, const char* message, ...); void MessageClose(Mob* sender, bool skipsender, float dist, uint32 type, const char* message, ...); @@ -361,6 +376,7 @@ public: uint32 type, eqFilterType filter, uint32 string_id, + Mob *skip = 0, const char *message1 = 0, const char *message2 = 0, const char *message3 = 0, @@ -484,7 +500,7 @@ public: Corpse* GetClosestCorpse(Mob* sender, const char *Name); void TryWakeTheDead(Mob* sender, Mob* target, int32 spell_id, uint32 max_distance, uint32 duration, uint32 amount_pets); NPC* GetClosestBanker(Mob* sender, uint32 &distance); - void CameraEffect(uint32 duration, uint32 intensity); + void CameraEffect(uint32 duration, float intensity); Mob* GetClosestMobByBodyType(Mob* sender, bodyType BodyType, bool skip_client_pets=false); void ForceGroupUpdate(uint32 gid); void SendGroupLeave(uint32 gid, const char *name); @@ -499,7 +515,7 @@ public: void UnMarkNPC(uint16 ID); void GateAllClients(); - void SignalAllClients(uint32 data); + void SignalAllClients(int signal_id); void UpdateQGlobal(uint32 qid, QGlobal newGlobal); void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID); void SendFindableNPCList(Client *c); @@ -524,11 +540,13 @@ public: inline const std::unordered_map &GetNPCList() { return npc_list; } inline const std::unordered_map &GetMercList() { return merc_list; } inline const std::unordered_map &GetClientList() { return client_list; } -#ifdef BOTS inline const std::list &GetBotList() { return bot_list; } - std::vector GetBotListByCharacterID(uint32 character_id); - std::vector GetBotListByClientName(std::string client_name); -#endif + std::vector GetBotListByCharacterID(uint32 character_id, uint8 class_id = NO_CLASS); + std::vector GetBotListByClientName(std::string client_name, uint8 class_id = NO_CLASS); + void SignalAllBotsByOwnerCharacterID(uint32 character_id, int signal_id); + void SignalAllBotsByOwnerName(std::string owner_name, int signal_id); + void SignalBotByBotID(uint32 bot_id, int signal_id); + void SignalBotByBotName(std::string bot_name, int signal_id); inline const std::unordered_map &GetCorpseList() { return corpse_list; } inline const std::unordered_map &GetObjectList() { return object_list; } inline const std::unordered_map &GetDoorsList() { return door_list; } @@ -593,15 +611,15 @@ private: Timer raid_timer; Timer trap_timer; - // Please Do Not Declare Any EntityList Class Members After This Comment -#ifdef BOTS + public: - void AddBot(Bot* newBot, bool SendSpawnPacket = true, bool dontqueue = false); + void AddBot(Bot* new_bot, bool send_spawn_packet = true, bool dont_queue = false); bool RemoveBot(uint16 entityID); Mob* GetMobByBotID(uint32 botID); Bot* GetBotByBotID(uint32 botID); Bot* GetBotByBotName(std::string botName); - Client* GetBotOwnerByBotEntityID(uint16 entityID); + Client* GetBotOwnerByBotEntityID(uint32 entity_id); + Client* GetBotOwnerByBotID(const uint32 bot_id); std::list GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID); bool Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes); // TODO: Evaluate this closesly in hopes to eliminate @@ -612,7 +630,6 @@ private: void GetBotList(std::list &b_list); private: std::list bot_list; -#endif }; class BulkZoneSpawnPacket { diff --git a/zone/event_codes.h b/zone/event_codes.h index 9044a9bf4..2c56f42c6 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -98,6 +98,25 @@ typedef enum { EVENT_UNEQUIP_ITEM_CLIENT, EVENT_SKILL_UP, EVENT_LANGUAGE_SKILL_UP, + EVENT_ALT_CURRENCY_MERCHANT_BUY, + EVENT_ALT_CURRENCY_MERCHANT_SELL, + EVENT_MERCHANT_BUY, + EVENT_MERCHANT_SELL, + EVENT_INSPECT, + EVENT_TASK_BEFORE_UPDATE, + EVENT_AA_BUY, + EVENT_AA_GAIN, + EVENT_PAYLOAD, + EVENT_LEVEL_DOWN, + EVENT_GM_COMMAND, + EVENT_DESPAWN, + EVENT_DESPAWN_ZONE, + EVENT_BOT_CREATE, + EVENT_AUGMENT_INSERT_CLIENT, + EVENT_AUGMENT_REMOVE_CLIENT, + // Add new events before these or Lua crashes + EVENT_SPELL_EFFECT_BOT, + EVENT_SPELL_EFFECT_BUFF_TIC_BOT, _LargestEventID } QuestEventID; diff --git a/zone/exp.cpp b/zone/exp.cpp index aad0f141b..27d7987dd 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -19,9 +19,10 @@ #include "../common/global_define.h" #include "../common/features.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" +#include "data_bucket.h" #include "groups.h" #include "mob.h" #include "raids.h" @@ -30,14 +31,13 @@ #include "quest_parser_collection.h" #include "lua_parser.h" #include "string_ids.h" +#include "../common/data_verification.h" -#ifdef BOTS #include "bot.h" -#endif extern QueryServ* QServ; -static uint32 ScaleAAXPBasedOnCurrentAATotal(int earnedAA, uint32 add_aaxp) +static uint64 ScaleAAXPBasedOnCurrentAATotal(int earnedAA, uint64 add_aaxp) { float baseModifier = RuleR(AA, ModernAAScalingStartPercent); int aaMinimum = RuleI(AA, ModernAAScalingAAMinimum); @@ -63,7 +63,7 @@ static uint32 ScaleAAXPBasedOnCurrentAATotal(int earnedAA, uint32 add_aaxp) float normalizedScale = (float)remainingAA / scaleRange; // Scale. - uint32 totalWithExpMod = add_aaxp * (baseModifier / 100) * normalizedScale; + uint64 totalWithExpMod = add_aaxp * (baseModifier / 100) * normalizedScale; // Are we so close to the scale limit that we're earning more XP without scaling? This // will happen when we get very close to the limit. In this case, just grant the unscaled @@ -103,108 +103,93 @@ static uint32 MaxBankedRaidLeadershipPoints(int Level) return 10; } -uint32 Client::CalcEXP(uint8 conlevel) { +uint64 Client::CalcEXP(uint8 consider_level, bool ignore_modifiers) { + uint64 in_add_exp = EXP_FORMULA; - uint32 in_add_exp = EXP_FORMULA; - - - if((XPRate != 0)) - in_add_exp = static_cast(in_add_exp * (static_cast(XPRate) / 100.0f)); - - float totalmod = 1.0; - float zemmod = 1.0; - //get modifiers - if(RuleR(Character, ExpMultiplier) >= 0){ - totalmod *= RuleR(Character, ExpMultiplier); + if (XPRate != 0) { + in_add_exp = static_cast(in_add_exp * (static_cast(XPRate) / 100.0f)); } - if(zone->newzone_data.zone_exp_multiplier >= 0){ - zemmod *= zone->newzone_data.zone_exp_multiplier; - } + if (!ignore_modifiers) { + auto total_modifier = 1.0f; + auto zone_modifier = 1.0f; - if(RuleB(Character,UseRaceClassExpBonuses)) - { - if(GetBaseRace() == HALFLING){ - totalmod *= 1.05; + if (RuleR(Character, ExpMultiplier) >= 0) { + total_modifier *= RuleR(Character, ExpMultiplier); } - if(GetClass() == ROGUE || GetClass() == WARRIOR){ - totalmod *= 1.05; + if (zone->newzone_data.zone_exp_multiplier >= 0) { + zone_modifier *= zone->newzone_data.zone_exp_multiplier; } + + if (RuleB(Character, UseRaceClassExpBonuses)) { + if ( + GetClass() == WARRIOR || + GetClass() == ROGUE || + GetBaseRace() == HALFLING + ) { + total_modifier *= 1.05; + } + } + + if (zone->IsHotzone()) { + total_modifier += RuleR(Zone, HotZoneBonus); + } + + in_add_exp = uint64(float(in_add_exp) * total_modifier * zone_modifier); } - if(zone->IsHotzone()) - { - totalmod += RuleR(Zone, HotZoneBonus); - } - - in_add_exp = uint32(float(in_add_exp) * totalmod * zemmod); - - if(RuleB(Character,UseXPConScaling)) - { - if (conlevel != 0xFF) { - switch (conlevel) - { - case CON_GRAY: - in_add_exp = 0; - return 0; - case CON_GREEN: - in_add_exp = in_add_exp * RuleI(Character, GreenModifier) / 100; - break; - case CON_LIGHTBLUE: - in_add_exp = in_add_exp * RuleI(Character, LightBlueModifier)/100; - break; - case CON_BLUE: - in_add_exp = in_add_exp * RuleI(Character, BlueModifier)/100; - break; - case CON_WHITE: - in_add_exp = in_add_exp * RuleI(Character, WhiteModifier)/100; - break; - case CON_YELLOW: - in_add_exp = in_add_exp * RuleI(Character, YellowModifier)/100; - break; - case CON_RED: - in_add_exp = in_add_exp * RuleI(Character, RedModifier)/100; - break; + if (RuleB(Character,UseXPConScaling)) { + if (consider_level != 0xFF) { + switch (consider_level) { + case CON_GRAY: + in_add_exp = 0; + return 0; + case CON_GREEN: + in_add_exp = in_add_exp * RuleI(Character, GreenModifier) / 100; + break; + case CON_LIGHTBLUE: + in_add_exp = in_add_exp * RuleI(Character, LightBlueModifier) / 100; + break; + case CON_BLUE: + in_add_exp = in_add_exp * RuleI(Character, BlueModifier) / 100; + break; + case CON_WHITE: + in_add_exp = in_add_exp * RuleI(Character, WhiteModifier) / 100; + break; + case CON_YELLOW: + in_add_exp = in_add_exp * RuleI(Character, YellowModifier) / 100; + break; + case CON_RED: + in_add_exp = in_add_exp * RuleI(Character, RedModifier) / 100; + break; } } } - float aatotalmod = 1.0; - if(zone->newzone_data.zone_exp_multiplier >= 0){ - aatotalmod *= zone->newzone_data.zone_exp_multiplier; - } - - - - if(RuleB(Character,UseRaceClassExpBonuses)) - { - if(GetBaseRace() == HALFLING){ - aatotalmod *= 1.05; + if (!ignore_modifiers) { + if (RuleB(Zone, LevelBasedEXPMods)) { + if (zone->level_exp_mod[GetLevel()].ExpMod) { + in_add_exp *= zone->level_exp_mod[GetLevel()].ExpMod; + } } - if(GetClass() == ROGUE || GetClass() == WARRIOR){ - aatotalmod *= 1.05; + if (RuleR(Character, FinalExpMultiplier) >= 0) { + in_add_exp *= RuleR(Character, FinalExpMultiplier); } - } - if(RuleB(Zone, LevelBasedEXPMods)){ - if(zone->level_exp_mod[GetLevel()].ExpMod){ - in_add_exp *= zone->level_exp_mod[GetLevel()].ExpMod; + if (RuleB(Character, EnableCharacterEXPMods)) { + in_add_exp *= GetEXPModifier(zone->GetZoneID(), zone->GetInstanceVersion()); } } - if (RuleR(Character, FinalExpMultiplier) >= 0) { - in_add_exp *= RuleR(Character, FinalExpMultiplier); - } - return in_add_exp; } -uint32 Client::GetExperienceForKill(Mob *against) +uint64 Client::GetExperienceForKill(Mob *against) { #ifdef LUA_EQEMU - uint32 lua_ret = 0; + uint64 lua_ret = 0; bool ignoreDefault = false; lua_ret = LuaParser::Instance()->GetExperienceForKill(this, against, ignoreDefault); @@ -215,7 +200,7 @@ uint32 Client::GetExperienceForKill(Mob *against) if (against && against->IsNPC()) { uint32 level = (uint32)against->GetLevel(); - uint32 ret = EXP_FORMULA; + uint64 ret = EXP_FORMULA; auto mod = against->GetKillExpMod(); if(mod >= 0) { @@ -256,7 +241,7 @@ float static GetConLevelModifierPercent(uint8 conlevel) } } -void Client::CalculateNormalizedAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp) +void Client::CalculateNormalizedAAExp(uint64 &add_aaxp, uint8 conlevel, bool resexp) { // Functionally this is the same as having the case in the switch, but this is // cleaner to read. @@ -280,7 +265,7 @@ void Client::CalculateNormalizedAAExp(uint32 &add_aaxp, uint8 conlevel, bool res add_aaxp = percentToAAXp * (xpPerAA / (whiteConKillsPerAA / colorModifier)); } -void Client::CalculateStandardAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp) +void Client::CalculateStandardAAExp(uint64 &add_aaxp, uint8 conlevel, bool resexp) { if (!resexp) { @@ -328,29 +313,29 @@ void Client::CalculateStandardAAExp(uint32 &add_aaxp, uint8 conlevel, bool resex } if (RuleB(Character, EnableCharacterEXPMods)) { - add_aaxp *= GetAAEXPModifier(GetZoneID()); + add_aaxp *= GetAAEXPModifier(zone->GetZoneID(), zone->GetInstanceVersion()); } - add_aaxp = (uint32)(RuleR(Character, AAExpMultiplier) * add_aaxp * aatotalmod); + add_aaxp = (uint64)(RuleR(Character, AAExpMultiplier) * add_aaxp * aatotalmod); } -void Client::CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel) +void Client::CalculateLeadershipExp(uint64 &add_exp, uint8 conlevel) { if (IsLeadershipEXPOn() && (conlevel == CON_BLUE || conlevel == CON_WHITE || conlevel == CON_YELLOW || conlevel == CON_RED)) { - add_exp = static_cast(static_cast(add_exp) * 0.8f); + add_exp = static_cast(static_cast(add_exp) * 0.8f); if (GetGroup()) { if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()) && RuleI(Character, KillsPerGroupLeadershipAA) > 0) { - uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); + uint64 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); Client *mentoree = GetGroup()->GetMentoree(); if (GetGroup()->GetMentorPercent() && mentoree && mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) { - uint32 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f); + uint64 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f); exp -= mentor_exp; mentoree->AddLeadershipEXP(mentor_exp, 0); // ends up rounded down mentoree->MessageString(Chat::LeaderShip, GAIN_GROUP_LEADERSHIP_EXP); @@ -390,12 +375,12 @@ void Client::CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel) && RuleI(Character, KillsPerGroupLeadershipAA) > 0) { uint32 group_id = raid->GetGroup(this); - uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); + uint64 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); Client *mentoree = raid->GetMentoree(group_id); if (raid->GetMentorPercent(group_id) && mentoree && mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) { - uint32 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f); + uint64 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f); exp -= mentor_exp; mentoree->AddLeadershipEXP(mentor_exp, 0); mentoree->MessageString(Chat::LeaderShip, GAIN_GROUP_LEADERSHIP_EXP); @@ -415,13 +400,13 @@ void Client::CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel) } } -void Client::CalculateExp(uint32 in_add_exp, uint32 &add_exp, uint32 &add_aaxp, uint8 conlevel, bool resexp) +void Client::CalculateExp(uint64 in_add_exp, uint64 &add_exp, uint64 &add_aaxp, uint8 conlevel, bool resexp) { add_exp = in_add_exp; if (!resexp && (XPRate != 0)) { - add_exp = static_cast(in_add_exp * (static_cast(XPRate) / 100.0f)); + add_exp = static_cast(in_add_exp * (static_cast(XPRate) / 100.0f)); } // Make sure it was initialized. @@ -465,7 +450,7 @@ void Client::CalculateExp(uint32 in_add_exp, uint32 &add_exp, uint32 &add_aaxp, totalmod += RuleR(Zone, HotZoneBonus); } - add_exp = uint32(float(add_exp) * totalmod * zemmod); + add_exp = uint64(float(add_exp) * totalmod * zemmod); //if XP scaling is based on the con of a monster, do that now. if (RuleB(Character, UseXPConScaling)) @@ -491,25 +476,40 @@ void Client::CalculateExp(uint32 in_add_exp, uint32 &add_exp, uint32 &add_aaxp, } if (RuleB(Character, EnableCharacterEXPMods)) { - add_exp *= GetEXPModifier(GetZoneID()); + add_exp *= GetEXPModifier(zone->GetZoneID(), zone->GetInstanceVersion()); + } + + //Enforce Percent XP Cap per kill, if rule is enabled + int kill_percent_xp_cap = RuleI(Character, ExperiencePercentCapPerKill); + if (kill_percent_xp_cap >= 0) { + auto experience_for_level = (GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())); + float exp_percent = (float)((float)add_exp / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel()))) * (float)100; //EXP needed for level + if (exp_percent > kill_percent_xp_cap) { + add_exp = GetEXP() + static_cast(std::floor(experience_for_level * (kill_percent_xp_cap / 100.0f))); + return; + } } add_exp = GetEXP() + add_exp; } -void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { +void Client::AddEXP(uint64 in_add_exp, uint8 conlevel, bool resexp) { + if (!IsEXPEnabled()) { + return; + } + EVENT_ITEM_ScriptStopReturn(); - uint32 exp = 0; - uint32 aaexp = 0; + uint64 exp = 0; + uint64 aaexp = 0; - if (m_epp.perAA<0 || m_epp.perAA>100) - m_epp.perAA=0; // stop exploit with sanity check + if (m_epp.perAA < 0 || m_epp.perAA > 100) { + m_epp.perAA = 0; // stop exploit with sanity check + } // Calculate regular XP CalculateExp(in_add_exp, exp, aaexp, conlevel, resexp); - // Calculate regular AA XP if (!RuleB(AA, NormalizedAAEnabled)) { @@ -540,6 +540,23 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { aaexp = had_aaexp; //watch for wrap } + // Check for Unused AA Cap. If at or above cap, set AAs to cap, set aaexp to 0 and set aa percentage to 0. + // Doing this here means potentially one kill wasted worth of experience, but easiest to put it here than to rewrite this function. + int aa_cap = RuleI(AA, UnusedAAPointCap); + + if (aa_cap >= 0 && aaexp > 0) { + if (m_pp.aapoints == aa_cap) { + MessageString(Chat::Red, AA_CAP); + aaexp = 0; + m_epp.perAA = 0; + } else if (m_pp.aapoints > aa_cap) { + MessageString(Chat::Red, OVER_AA_CAP, fmt::format_int(aa_cap).c_str(), fmt::format_int(aa_cap).c_str()); + m_pp.aapoints = aa_cap; + aaexp = 0; + m_epp.perAA = 0; + } + } + // AA Sanity Checking for players who set aa exp and deleveled below allowed aa level. if (GetLevel() <= 50 && m_epp.perAA > 0) { Message(Chat::Yellow, "You are below the level allowed to gain AA Experience. AA Experience set to 0%"); @@ -551,7 +568,7 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { SetEXP(exp, aaexp, resexp); } -void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { +void Client::SetEXP(uint64 set_exp, uint64 set_aaxp, bool isrezzexp) { LogDebug("Attempting to Set Exp for [{}] (XP: [{}], AAXP: [{}], Rez: [{}])", GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false"); auto max_AAXP = GetRequiredAAExperience(); @@ -570,26 +587,34 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { } } - if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) { - - uint32 exp_gained = set_exp - m_pp.exp; - uint32 aaxp_gained = set_aaxp - m_pp.expAA; + uint64 current_exp = GetEXP(); + uint64 current_aa_exp = GetAAXP(); + uint64 total_current_exp = current_exp + current_aa_exp; + uint64 total_add_exp = set_exp + set_aaxp; + if (total_add_exp > total_current_exp) { + uint64 exp_gained = set_exp - current_exp; + uint64 aa_exp_gained = set_aaxp - current_aa_exp; float exp_percent = (float)((float)exp_gained / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100; //EXP needed for level - float aaxp_percent = (float)((float)aaxp_gained / (float)(RuleI(AA, ExpPerPoint)))*(float)100; //AAEXP needed for level + float aa_exp_percent = (float)((float)aa_exp_gained / (float)(RuleI(AA, ExpPerPoint)))*(float)100; //AAEXP needed for level std::string exp_amount_message = ""; if (RuleI(Character, ShowExpValues) >= 1) { - if (exp_gained > 0 && aaxp_gained > 0) exp_amount_message = StringFormat("%u, %u AA", exp_gained, aaxp_gained); - else if (exp_gained > 0) exp_amount_message = StringFormat("%u", exp_gained); - else exp_amount_message = StringFormat("%u AA", aaxp_gained); + if (exp_gained > 0 && aa_exp_gained > 0) { + exp_amount_message = fmt::format("({}) ({})", exp_gained, aa_exp_gained); + } + else if (exp_gained > 0) { + exp_amount_message = fmt::format("({})", exp_gained); + } + else { + exp_amount_message = fmt::format("({}) AA", aa_exp_gained); + } } std::string exp_percent_message = ""; if (RuleI(Character, ShowExpValues) >= 2) { - if (exp_gained > 0 && aaxp_gained > 0) exp_percent_message = StringFormat("(%.3f%%, %.3f%%AA)", exp_percent, aaxp_percent); + if (exp_gained > 0 && aa_exp_gained > 0) exp_percent_message = StringFormat("(%.3f%%, %.3f%%AA)", exp_percent, aa_exp_percent); else if (exp_gained > 0) exp_percent_message = StringFormat("(%.3f%%)", exp_percent); - else exp_percent_message = StringFormat("(%.3f%%AA)", aaxp_percent); + else exp_percent_message = StringFormat("(%.3f%%AA)", aa_exp_percent); } - if (isrezzexp) { if (RuleI(Character, ShowExpValues) > 0) Message(Chat::Experience, "You regain %s experience from resurrection. %s", exp_amount_message.c_str(), exp_percent_message.c_str()); @@ -612,8 +637,8 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { } } } - else if((set_exp + set_aaxp) < (m_pp.exp+m_pp.expAA)){ //only loss message if you lose exp, no message if you gained/lost nothing. - uint32 exp_lost = m_pp.exp - set_exp; + else if(total_add_exp < total_current_exp){ //only loss message if you lose exp, no message if you gained/lost nothing. + uint64 exp_lost = current_exp - set_exp; float exp_percent = (float)((float)exp_lost / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100; if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) Message(Chat::Yellow, "You have lost %i experience.", exp_lost); @@ -696,6 +721,13 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { SendSound(); } + const auto export_string = fmt::format( + "{}", + gained + ); + + parse->EventPlayer(EVENT_AA_GAIN, this, export_string, 0); + /* QS: PlayerLogAARate */ if (RuleB(QueryServ, PlayerLogAARate)){ int add_points = (m_pp.aapoints - last_unspentAA); @@ -722,12 +754,12 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { } } - if (GetClientMaxLevel() > 0) { - int client_max_level = GetClientMaxLevel(); + auto client_max_level = GetClientMaxLevel(); + if (client_max_level) { if (GetLevel() >= client_max_level) { - uint32 expneeded = GetEXPForLevel(client_max_level); - if(set_exp > expneeded) { - set_exp = expneeded; + auto exp_needed = GetEXPForLevel(client_max_level); + if (set_exp > exp_needed) { + set_exp = exp_needed; } } } @@ -751,17 +783,14 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { else MessageString(Chat::Experience, LOSE_LEVEL, ConvertArray(check_level, val1)); -#ifdef BOTS uint8 myoldlevel = GetLevel(); -#endif SetLevel(check_level); -#ifdef BOTS - if(RuleB(Bots, BotLevelsWithOwner)) + if (RuleB(Bots, Enabled) && RuleB(Bots, BotLevelsWithOwner)) { // hack way of doing this..but, least invasive... (same criteria as gain level for sendlvlapp) - Bot::LevelBotWithClient(this, GetLevel(), (myoldlevel==check_level-1)); -#endif + Bot::LevelBotWithClient(this, GetLevel(), (myoldlevel == check_level - 1)); + } } //If were at max level then stop gaining experience if we make it to the cap @@ -804,60 +833,83 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { void Client::SetLevel(uint8 set_level, bool command) { if (GetEXPForLevel(set_level) == 0xFFFFFFFF) { - LogError("Client::SetLevel() GetEXPForLevel([{}]) = 0xFFFFFFFF", set_level); + LogError("GetEXPForLevel([{}]) = 0xFFFFFFFF", set_level); return; } auto outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct)); - LevelUpdate_Struct* lu = (LevelUpdate_Struct*)outapp->pBuffer; + auto* lu = (LevelUpdate_Struct *) outapp->pBuffer; lu->level = set_level; - if(m_pp.level2 != 0) + + if (m_pp.level2 != 0) { lu->level_old = m_pp.level2; - else + } else { lu->level_old = level; + } level = set_level; - if(IsRaidGrouped()) { + if (IsRaidGrouped()) { Raid *r = GetRaid(); - if(r){ + if (r) { r->UpdateLevel(GetName(), set_level); } } - if(set_level > m_pp.level2) { - if(m_pp.level2 == 0) + + if (set_level > m_pp.level2) { + if (m_pp.level2 == 0) { m_pp.points += 5; - else + } else { m_pp.points += (5 * (set_level - m_pp.level2)); + } m_pp.level2 = set_level; } - if(set_level > m_pp.level) { - parse->EventPlayer(EVENT_LEVEL_UP, this, "", 0); - /* QS: PlayerLogLevels */ - if (RuleB(QueryServ, PlayerLogLevels)){ - std::string event_desc = StringFormat("Leveled UP :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, GetZoneID(), GetInstanceID()); + + if (set_level > m_pp.level) { + const auto export_string = fmt::format("{}", (set_level - m_pp.level)); + parse->EventPlayer(EVENT_LEVEL_UP, this, export_string, 0); + + if (RuleB(QueryServ, PlayerLogLevels)) { + const auto event_desc = fmt::format( + "Leveled UP :: to Level:{} from Level:{} in zoneid:{} instid:{}", + set_level, + m_pp.level, + GetZoneID(), + GetInstanceID() + ); QServ->PlayerLogEvent(Player_Log_Levels, CharacterID(), event_desc); } - } - else if (set_level < m_pp.level){ - /* QS: PlayerLogLevels */ - if (RuleB(QueryServ, PlayerLogLevels)){ - std::string event_desc = StringFormat("Leveled DOWN :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, GetZoneID(), GetInstanceID()); + } else if (set_level < m_pp.level) { + const auto export_string = fmt::format("{}", (m_pp.level - set_level)); + parse->EventPlayer(EVENT_LEVEL_DOWN, this, export_string, 0); + + if (RuleB(QueryServ, PlayerLogLevels)) { + const auto event_desc = fmt::format( + "Leveled DOWN :: to Level:{} from Level:{} in zoneid:{} instid:{}", + set_level, + m_pp.level, + GetZoneID(), + GetInstanceID() + ); QServ->PlayerLogEvent(Player_Log_Levels, CharacterID(), event_desc); } } m_pp.level = set_level; - if (command){ + + if (command) { m_pp.exp = GetEXPForLevel(set_level); - Message(Chat::Yellow, "Welcome to level %i!", set_level); + Message(Chat::Yellow, fmt::format("Welcome to level {}!", set_level).c_str()); lu->exp = 0; + } else { + const auto temporary_xp = ( + static_cast(m_pp.exp - GetEXPForLevel(GetLevel())) / + static_cast(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())) + ); + lu->exp = static_cast(330.0f * temporary_xp); } - else { - float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) / ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel())); - lu->exp = (uint32)(330.0f * tmpxp); - } + QueuePacket(outapp); safe_delete(outapp); SendAppearancePacket(AT_WhoLevel, set_level); // who level change @@ -866,16 +918,18 @@ void Client::SetLevel(uint8 set_level, bool command) CalcBonuses(); - if(!RuleB(Character, HealOnLevel)) { - int mhp = CalcMaxHP(); - if(GetHP() > mhp) - SetHP(mhp); - } - else { + if (!RuleB(Character, HealOnLevel)) { + const auto max_hp = CalcMaxHP(); + if (GetHP() > max_hp) { + SetHP(max_hp); + } + } else { SetHP(CalcMaxHP()); // Why not, lets give them a free heal } - if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true); + if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) { + SetPVP(true); + } DoTributeUpdate(); SendHPUpdate(); @@ -953,7 +1007,7 @@ uint32 Client::GetEXPForLevel(uint16 check_level) racemod = 0.95; } - finalxp = uint32(finalxp * racemod); + finalxp = uint64(finalxp * racemod); } if(RuleB(Character,UseOldClassExpPenalties)) @@ -971,7 +1025,7 @@ uint32 Client::GetEXPForLevel(uint16 check_level) classmod = 0.9; } - finalxp = uint32(finalxp * classmod); + finalxp = uint64(finalxp * classmod); } finalxp = mod_client_xp_for_level(finalxp, check_level); @@ -981,8 +1035,8 @@ uint32 Client::GetEXPForLevel(uint16 check_level) void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level, bool ignore_mods) { - uint32 award; - uint32 xp_for_level; + uint64 award; + uint64 xp_for_level; if (exp_percentage > 100) { @@ -1007,114 +1061,113 @@ void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level, bool ignore award *= RuleR(Character, FinalExpMultiplier); } - uint32 newexp = GetEXP() + award; + uint64 newexp = GetEXP() + award; SetEXP(newexp, GetAAXP()); } -void Group::SplitExp(uint32 exp, Mob* other) { - if( other->CastToNPC()->MerchantType != 0 ) // Ensure NPC isn't a merchant +void Group::SplitExp(const uint64 exp, Mob* other) { + if (other->CastToNPC()->MerchantType != 0) { return; + } - if(other->GetOwner() && other->GetOwner()->IsClient()) // Ensure owner isn't pc + if (other->GetOwner() && other->GetOwner()->IsClient()) { return; + } - unsigned int i; - uint32 groupexp = exp; - uint8 membercount = 0; - uint8 maxlevel = 1; + const auto member_count = GroupCount(); + if (!member_count) { + return; + } - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr) { - if(members[i]->GetLevel() > maxlevel) - maxlevel = members[i]->GetLevel(); + auto group_experience = exp; + const auto highest_level = GetHighestLevel(); - membercount++; + auto group_modifier = 1.0f; + if (RuleB(Character, EnableGroupEXPModifier)) { + if (EQ::ValueWithin(member_count, 2, 5)) { + group_modifier = 1 + RuleR(Character, GroupMemberEXPModifier) * (member_count - 1); // 2 = 1.2x, 3 = 1.4x, 4 = 1.6x, 5 = 1.8x + } else if (member_count == 6) { + group_modifier = RuleR(Character, FullGroupEXPModifier); } } - float groupmod; - if (membercount > 1 && membercount < 6) - groupmod = 1 + .2*(membercount - 1); //2members=1.2exp, 3=1.4, 4=1.6, 5=1.8 - else if (membercount == 6) - groupmod = 2.16; - else - groupmod = 1.0; - if(membercount > 1 && membercount <= 6) - groupexp += (uint32)((float)exp * groupmod * (RuleR(Character, GroupExpMultiplier))); + if (EQ::ValueWithin(member_count, 2, 6)) { + group_experience += static_cast( + static_cast(exp) * + group_modifier * + RuleR(Character, GroupExpMultiplier) + ); + } - int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel()); - if(conlevel == CON_GRAY) - return; //no exp for greenies... - - if (membercount == 0) + const uint8 consider_level = Mob::GetLevelCon(highest_level, other->GetLevel()); + if (consider_level == CON_GRAY) { return; + } - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i]->IsClient()) // If Group Member is Client - { - Client *cmember = members[i]->CastToClient(); - // add exp + exp cap - int16 diff = cmember->GetLevel() - maxlevel; - int16 maxdiff = -(cmember->GetLevel()*15/10 - cmember->GetLevel()); - if(maxdiff > -5) - maxdiff = -5; - if (diff >= (maxdiff)) { /*Instead of person who killed the mob, the person who has the highest level in the group*/ - uint32 tmp = (cmember->GetLevel()+3) * (cmember->GetLevel()+3) * 75 * 35 / 10; - uint32 tmp2 = groupexp / membercount; - cmember->AddEXP( tmp < tmp2 ? tmp : tmp2, conlevel ); + for (const auto& m : members) { + if (m && m->IsClient()) { + const int32 diff = m->GetLevel() - highest_level; + int32 max_diff = -(m->GetLevel() * 15 / 10 - m->GetLevel()); + + if (max_diff > -5) { + max_diff = -5; + } + + if (diff >= max_diff) { + const uint64 tmp = (m->GetLevel() + 3) * (m->GetLevel() + 3) * 75 * 35 / 10; + const uint64 tmp2 = group_experience / member_count; + m->CastToClient()->AddEXP(tmp < tmp2 ? tmp : tmp2, consider_level); } } } } -void Raid::SplitExp(uint32 exp, Mob* other) { - if( other->CastToNPC()->MerchantType != 0 ) // Ensure NPC isn't a merchant +void Raid::SplitExp(const uint64 exp, Mob* other) { + if (other->CastToNPC()->MerchantType != 0) { return; - - if(other->GetOwner() && other->GetOwner()->IsClient()) // Ensure owner isn't pc - return; - - uint32 groupexp = exp; - uint8 membercount = 0; - uint8 maxlevel = 1; - - for (int i = 0; i < MAX_RAID_MEMBERS; i++) { - if (members[i].member != nullptr) { - if(members[i].member->GetLevel() > maxlevel) - maxlevel = members[i].member->GetLevel(); - - membercount++; - } } - groupexp = (uint32)((float)groupexp * (1.0f-(RuleR(Character, RaidExpMultiplier)))); - - int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel()); - if(conlevel == CON_GRAY) - return; //no exp for greenies... - - if (membercount == 0) + if (other->GetOwner() && other->GetOwner()->IsClient()) { return; + } - for (unsigned int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (members[x].member != nullptr) // If Group Member is Client - { - Client *cmember = members[x].member; - // add exp + exp cap - int16 diff = cmember->GetLevel() - maxlevel; - int16 maxdiff = -(cmember->GetLevel()*15/10 - cmember->GetLevel()); - if(maxdiff > -5) - maxdiff = -5; - if (diff >= (maxdiff)) { /*Instead of person who killed the mob, the person who has the highest level in the group*/ - uint32 tmp = (cmember->GetLevel()+3) * (cmember->GetLevel()+3) * 75 * 35 / 10; - uint32 tmp2 = (groupexp / membercount) + 1; - cmember->AddEXP( tmp < tmp2 ? tmp : tmp2, conlevel ); + const auto member_count = RaidCount(); + if (!member_count) { + return; + } + + auto raid_experience = exp; + const auto highest_level = GetHighestLevel(); + + raid_experience = static_cast( + static_cast(raid_experience) * + (1.0f - RuleR(Character, RaidExpMultiplier)) + ); + + const auto consider_level = Mob::GetLevelCon(highest_level, other->GetLevel()); + if (consider_level == CON_GRAY) { + return; + } + + for (const auto& m : members) { + if (m.member) { + const int32 diff = m.member->GetLevel() - highest_level; + int32 max_diff = -(m.member->GetLevel() * 15 / 10 - m.member->GetLevel()); + + if (max_diff > -5) { + max_diff = -5; + } + + if (diff >= max_diff) { + const uint64 tmp = (m.member->GetLevel() + 3) * (m.member->GetLevel() + 3) * 75 * 35 / 10; + const uint64 tmp2 = (raid_experience / member_count) + 1; + m.member->AddEXP(tmp < tmp2 ? tmp : tmp2, consider_level); } } } } -void Client::SetLeadershipEXP(uint32 group_exp, uint32 raid_exp) { +void Client::SetLeadershipEXP(uint64 group_exp, uint64 raid_exp) { while(group_exp >= GROUP_EXP_PER_POINT) { group_exp -= GROUP_EXP_PER_POINT; m_pp.group_leadership_points++; @@ -1132,7 +1185,7 @@ void Client::SetLeadershipEXP(uint32 group_exp, uint32 raid_exp) { SendLeadershipEXPUpdate(); } -void Client::AddLeadershipEXP(uint32 group_exp, uint32 raid_exp) { +void Client::AddLeadershipEXP(uint64 group_exp, uint64 raid_exp) { SetLeadershipEXP(GetGroupEXP() + group_exp, GetRaidEXP() + raid_exp); } @@ -1148,44 +1201,52 @@ void Client::SendLeadershipEXPUpdate() { FastQueuePacket(&outapp); } -uint32 Client::GetCharMaxLevelFromQGlobal() { - QGlobalCache *char_c = nullptr; - char_c = GetQGlobals(); +uint8 Client::GetCharMaxLevelFromQGlobal() { + auto char_cache = GetQGlobals(); - std::list globalMap; - uint32 ntype = 0; + std::list global_map; - if(char_c) { - QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, CharacterID(), zone->GetZoneID()); + if (char_cache) { + QGlobalCache::Combine(global_map, char_cache->GetBucket(), 0, CharacterID(), zone->GetZoneID()); } - auto iter = globalMap.begin(); - uint32 gcount = 0; - while(iter != globalMap.end()) { - if((*iter).name.compare("CharMaxLevel") == 0){ - return atoi((*iter).value.c_str()); + for (const auto& global : global_map) { + if (global.name == "CharMaxLevel") { + if (Strings::IsNumber(global.value)) { + return static_cast(std::stoul(global.value)); + } } - ++iter; - ++gcount; } return 0; } -uint32 Client::GetCharMaxLevelFromBucket() +uint8 Client::GetCharMaxLevelFromBucket() { - uint32 char_id = CharacterID(); - std::string query = StringFormat("SELECT value FROM data_buckets WHERE `key` = '%i-CharMaxLevel'", char_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("Data bucket for CharMaxLevel for char ID [{}] failed", char_id); - return 0; + auto new_bucket_name = fmt::format( + "{}-CharMaxLevel", + GetBucketKey() + ); + + auto bucket_value = DataBucket::GetData(new_bucket_name); + if (!bucket_value.empty()) { + if (Strings::IsNumber(bucket_value)) { + return static_cast(std::stoul(bucket_value)); + } } - if (results.RowCount() > 0) { - auto row = results.begin(); - return atoi(row[0]); + auto old_bucket_name = fmt::format( + "{}-CharMaxLevel", + CharacterID() + ); + + bucket_value = DataBucket::GetData(old_bucket_name); + if (!bucket_value.empty()) { + if (Strings::IsNumber(bucket_value)) { + return static_cast(std::stoul(bucket_value)); + } } + return 0; } diff --git a/zone/expedition.cpp b/zone/expedition.cpp index 8c1b50dfd..4233882f9 100644 --- a/zone/expedition.cpp +++ b/zone/expedition.cpp @@ -35,8 +35,6 @@ extern Zone* zone; // message string 8271 (not in emu clients) const char* const DZ_YOU_NOT_ASSIGNED = "You could not use this command because you are not currently assigned to a dynamic zone."; -// message string 9265 (not in emu clients) -const char* const EXPEDITION_OTHER_BELONGS = "{} attempted to create an expedition but {} already belongs to one."; // lockout warnings were added to live in March 11 2020 patch const char* const DZADD_INVITE_WARNING = "Warning! You will be given replay timers for the following events if you enter %s:"; const char* const DZADD_INVITE_WARNING_TIMER = "%s - %sD:%sH:%sM"; @@ -47,6 +45,12 @@ constexpr char LOCK_BEGIN[] = "The trial has begun. You cannot const int32_t Expedition::REPLAY_TIMER_ID = -1; const int32_t Expedition::EVENT_TIMER_ID = 1; +Expedition::Expedition(DynamicZone* dz) : + m_dynamic_zone(dz) +{ + assert(m_dynamic_zone != nullptr); +} + Expedition::Expedition(DynamicZone* dz, uint32_t id, uint32_t dz_id) : m_dynamic_zone(dz), m_id(id), @@ -88,7 +92,7 @@ Expedition* Expedition::TryCreate(Client* requester, DynamicZone& dz_request, bo // request parses leader, members list, and lockouts while validating if (!request.Validate(requester)) { - LogExpeditionsModerate("[{}] request by [{}] denied", request.GetExpeditionName(), requester->GetName()); + LogExpeditionsDetail("[{}] request by [{}] denied", request.GetExpeditionName(), requester->GetName()); return nullptr; } @@ -227,6 +231,8 @@ bool Expedition::CacheAllFromDatabase() CacheExpeditions(std::move(expeditions)); + LogInfo("Loaded [{}] expedition(s)", Strings::Commify(zone->expedition_cache.size())); + LogExpeditions("Caching [{}] expedition(s) took [{}s]", zone->expedition_cache.size(), benchmark.elapsed()); return true; @@ -426,7 +432,7 @@ void Expedition::SendClientExpeditionInvite( return; } - LogExpeditionsModerate( + LogExpeditionsDetail( "Sending expedition [{}] invite to player [{}] inviter [{}] swap name [{}]", m_id, client->GetName(), inviter_name, swap_remove_name ); @@ -571,7 +577,7 @@ void Expedition::DzInviteResponse(Client* add_client, bool accepted, const std:: return; } - LogExpeditionsModerate("Invite response by [{}] accepted [{}] swap_name [{}]", + LogExpeditionsDetail("Invite response by [{}] accepted [{}] swap_name [{}]", add_client->GetName(), accepted, swap_remove_name); // a null leader_client is handled by SendLeaderMessage fallbacks @@ -677,7 +683,7 @@ void Expedition::TryAddClient( return; } - LogExpeditionsModerate( + LogExpeditionsDetail( "Add player request for expedition [{}] by inviter [{}] add name [{}] swap name [{}]", m_id, inviter_name, add_client->GetName(), swap_remove_name ); diff --git a/zone/expedition.h b/zone/expedition.h index 73b63ade1..d9d47a34e 100644 --- a/zone/expedition.h +++ b/zone/expedition.h @@ -37,7 +37,6 @@ class ExpeditionRequest; class ServerPacket; extern const char* const DZ_YOU_NOT_ASSIGNED; -extern const char* const EXPEDITION_OTHER_BELONGS; enum class ExpeditionLockMessage : uint8_t { @@ -50,7 +49,7 @@ class Expedition { public: Expedition() = delete; - Expedition(DynamicZone* dz) : m_dynamic_zone(dz) { assert(m_dynamic_zone != nullptr); } + Expedition(DynamicZone* dz); Expedition(DynamicZone* dz, uint32_t id, uint32_t dz_id); static Expedition* TryCreate(Client* requester, DynamicZone& dynamiczone, bool disable_messages); diff --git a/zone/expedition_database.cpp b/zone/expedition_database.cpp index 9a3bfb837..1f49c917e 100644 --- a/zone/expedition_database.cpp +++ b/zone/expedition_database.cpp @@ -23,7 +23,7 @@ #include "zonedb.h" #include "../common/database.h" #include "../common/expedition_lockout_timer.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include uint32_t ExpeditionDatabase::InsertExpedition(uint32_t dz_id) @@ -100,7 +100,7 @@ std::vector ExpeditionDatabase::LoadCharacterLockouts( character_id = {} AND expire_time > NOW() AND expedition_name = '{}'; - ), character_id, EscapeString(expedition_name)); + ), character_id, Strings::Escape(expedition_name)); auto results = database.QueryDatabase(query); if (results.Success()) @@ -145,7 +145,7 @@ void ExpeditionDatabase::DeleteAllCharacterLockouts( std::string query = fmt::format(SQL( DELETE FROM character_expedition_lockouts WHERE character_id = {} AND expedition_name = '{}'; - ), character_id, EscapeString(expedition_name)); + ), character_id, Strings::Escape(expedition_name)); database.QueryDatabase(query); } @@ -164,7 +164,7 @@ void ExpeditionDatabase::DeleteCharacterLockout( character_id = {} AND expedition_name = '{}' AND event_name = '{}'; - ), character_id, EscapeString(expedition_name), EscapeString(event_name)); + ), character_id, Strings::Escape(expedition_name), Strings::Escape(event_name)); database.QueryDatabase(query); } @@ -191,7 +191,7 @@ void ExpeditionDatabase::DeleteMembersLockout( IN ({}) AND expedition_name = '{}' AND event_name = '{}'; - ), query_character_ids, EscapeString(expedition_name), EscapeString(event_name)); + ), query_character_ids, Strings::Escape(expedition_name), Strings::Escape(event_name)); database.QueryDatabase(query); } @@ -204,7 +204,7 @@ void ExpeditionDatabase::DeleteLockout(uint32_t expedition_id, const std::string auto query = fmt::format(SQL( DELETE FROM expedition_lockouts WHERE expedition_id = {} AND event_name = '{}'; - ), expedition_id, EscapeString(event_name)); + ), expedition_id, Strings::Escape(event_name)); database.QueryDatabase(query); } @@ -223,8 +223,8 @@ void ExpeditionDatabase::InsertCharacterLockouts(uint32_t character_id, lockout.GetExpireTime(), lockout.GetDuration(), lockout.GetExpeditionUUID(), - EscapeString(lockout.GetExpeditionName()), - EscapeString(lockout.GetEventName()) + Strings::Escape(lockout.GetExpeditionName()), + Strings::Escape(lockout.GetEventName()) ); } @@ -263,8 +263,8 @@ void ExpeditionDatabase::InsertMembersLockout( lockout.GetExpireTime(), lockout.GetDuration(), lockout.GetExpeditionUUID(), - EscapeString(lockout.GetExpeditionName()), - EscapeString(lockout.GetEventName()) + Strings::Escape(lockout.GetExpeditionName()), + Strings::Escape(lockout.GetEventName()) ); } @@ -306,7 +306,7 @@ void ExpeditionDatabase::InsertLockout( ), expedition_id, lockout.GetExpeditionUUID(), - EscapeString(lockout.GetEventName()), + Strings::Escape(lockout.GetEventName()), lockout.GetExpireTime(), lockout.GetDuration() ); @@ -326,7 +326,7 @@ void ExpeditionDatabase::InsertLockouts( "({}, '{}', '{}', FROM_UNIXTIME({}), {}),", expedition_id, lockout.second.GetExpeditionUUID(), - EscapeString(lockout.second.GetEventName()), + Strings::Escape(lockout.second.GetEventName()), lockout.second.GetExpireTime(), lockout.second.GetDuration() ); @@ -388,8 +388,8 @@ void ExpeditionDatabase::AddLockoutDuration(const std::vector lockout.GetExpireTime(), lockout.GetDuration(), lockout.GetExpeditionUUID(), - EscapeString(lockout.GetExpeditionName()), - EscapeString(lockout.GetEventName()) + Strings::Escape(lockout.GetExpeditionName()), + Strings::Escape(lockout.GetEventName()) ); } diff --git a/zone/expedition_request.cpp b/zone/expedition_request.cpp index 98cad6050..dfca1d581 100644 --- a/zone/expedition_request.cpp +++ b/zone/expedition_request.cpp @@ -30,6 +30,11 @@ constexpr char SystemName[] = "expedition"; +// message string 8312 added in September 08 2020 Test patch (used by both dz and shared tasks) +constexpr const char* CREATE_NOT_ALL_ADDED = "Not all players in your {} were added to the {}. The {} can take a maximum of {} players, and your {} has {}."; +// message string 9265 (not in emu clients) +constexpr const char* EXPEDITION_OTHER_BELONGS = "{} attempted to create an expedition but {} already belongs to one."; + ExpeditionRequest::ExpeditionRequest(const DynamicZone& dz, bool disable_messages) : m_expedition_name(dz.GetName()), m_min_players(dz.GetMinPlayers()), diff --git a/zone/forage.cpp b/zone/forage.cpp index 375788420..21074b4a4 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -20,7 +20,7 @@ #include "../common/eqemu_logsys.h" #include "../common/misc_functions.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "entity.h" #include "forage.h" @@ -30,7 +30,7 @@ #include "titles.h" #include "water_map.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include @@ -374,7 +374,7 @@ void Client::GoFish() } if (inst) { - std::vector args; + std::vector args; args.push_back(inst); parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args); } @@ -419,7 +419,6 @@ void Client::GoFish() } void Client::ForageItem(bool guarantee) { - int skill_level = GetSkill(EQ::skills::SkillForage); //be wary of the string ids in switch below when changing this. @@ -439,12 +438,12 @@ void Client::ForageItem(bool guarantee) { uint32 foragedfood = 0; uint32 stringid = FORAGE_NOEAT; - if (zone->random.Roll(25)) { + if (zone->random.Roll(RuleI(Zone, ForageChance))) { foragedfood = content_db.GetZoneForage(m_pp.zone_id, skill_level); } //not an else in case theres no DB food - if(foragedfood == 0) { + if (foragedfood == 0) { uint8 index = 0; index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1); foragedfood = common_food_ids[index]; @@ -452,66 +451,64 @@ void Client::ForageItem(bool guarantee) { const EQ::ItemData* food_item = database.GetItem(foragedfood); - if(!food_item) { + if (!food_item) { LogError("nullptr returned from database.GetItem in ClientForageItem"); return; } - if(foragedfood == 13106) + if (foragedfood == 13106) { stringid = FORAGE_GRUBS; - else + } else { switch(food_item->ItemType) { case EQ::item::ItemTypeFood: stringid = FORAGE_FOOD; break; case EQ::item::ItemTypeDrink: - if(strstr(food_item->Name, "ater")) + if (strstr(food_item->Name, "ater")) { stringid = FORAGE_WATER; - else + } else { stringid = FORAGE_DRINK; + } break; default: break; } + } MessageString(Chat::Skills, stringid); EQ::ItemInstance* inst = database.CreateItem(food_item, 1); - if(inst != nullptr) { + if (inst != nullptr) { // check to make sure it isn't a foraged lore item - if(CheckLoreConflict(inst->GetItem())) - { + if (CheckLoreConflict(inst->GetItem())) { MessageString(Chat::White, DUP_LORE); safe_delete(inst); - } - else { + } else { PushItemOnCursor(*inst); SendItemPacket(EQ::invslot::slotCursor, inst, ItemPacketLimbo); - if(RuleB(TaskSystem, EnableTaskSystem)) + if(RuleB(TaskSystem, EnableTaskSystem)) { UpdateTasksForItem(TaskActivityType::Forage, foragedfood); + } safe_delete(inst); inst = m_inv.GetItem(EQ::invslot::slotCursor); } - if(inst) { - std::vector args; + if (inst) { + std::vector args; args.push_back(inst); parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst->GetID(), &args); } } int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems; - if(!guarantee && zone->random.Roll(ChanceSecondForage)) { + if (!guarantee && zone->random.Roll(ChanceSecondForage)) { MessageString(Chat::Skills, FORAGE_MASTERY); ForageItem(true); } - } else { MessageString(Chat::Skills, FORAGE_FAILED); parse->EventPlayer(EVENT_FORAGE_FAILURE, this, "", 0); } CheckIncreaseSkill(EQ::skills::SkillForage, nullptr, 5); - } - diff --git a/zone/gm_commands/advnpcspawn.cpp b/zone/gm_commands/advnpcspawn.cpp index 7daa174d4..0ec3cbd63 100755 --- a/zone/gm_commands/advnpcspawn.cpp +++ b/zone/gm_commands/advnpcspawn.cpp @@ -33,7 +33,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) return; } - std::string spawn_command = str_tolower(sep->arg[1]); + std::string spawn_command = Strings::ToLower(sep->arg[1]); bool is_add_entry = spawn_command.find("addentry") != std::string::npos; bool is_add_spawn = spawn_command.find("addspawn") != std::string::npos; bool is_clear_box = spawn_command.find("clearbox") != std::string::npos; @@ -91,20 +91,20 @@ void command_advnpcspawn(Client *c, const Seperator *sep) return; } - auto spawngroup_id = std::stoi(sep->arg[2]); - auto npc_id = std::stoi(sep->arg[2]); - auto spawn_chance = std::stoi(sep->arg[2]); + auto spawngroup_id = std::stoul(sep->arg[2]); + auto npc_id = std::stoul(sep->arg[3]); + auto spawn_chance = std::stoul(sep->arg[4]); - std::string query = fmt::format( + auto query = fmt::format( SQL( - INSERT INTO spawnentry(spawngroupID, npcID, chance) - VALUES({}, {}, {}) + INSERT INTO spawnentry (spawngroupID, npcID, chance) + VALUES ({}, {}, {}) ), spawngroup_id, npc_id, spawn_chance ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to add entry to Spawngroup."); return; @@ -121,36 +121,37 @@ void command_advnpcspawn(Client *c, const Seperator *sep) ).c_str() ); return; - } - else if (is_add_spawn) { - content_db.NPCSpawnDB( - NPCSpawnTypes::AddSpawnFromSpawngroup, - zone->GetShortName(), - zone->GetInstanceVersion(), - c, - 0, - std::stoi(sep->arg[2]) - ); - c->Message( - Chat::White, - fmt::format( - "Spawn Added | Added spawn from Spawngroup ID {}.", - std::stoi(sep->arg[2]) - ).c_str() - ); + } else if (is_add_spawn) { + if ( + content_db.NPCSpawnDB( + NPCSpawnTypes::AddSpawnFromSpawngroup, + zone->GetShortName(), + zone->GetInstanceVersion(), + c, + 0, + std::stoul(sep->arg[2]) + ) + ) { + c->Message( + Chat::White, + fmt::format( + "Spawn Added | Added spawn from Spawngroup ID {}.", + std::stoul(sep->arg[2]) + ).c_str() + ); + } return; - } - else if (is_clear_box) { + } else if (is_clear_box) { if (arguments != 2 || !sep->IsNumber(2)) { c->Message(Chat::White, "Usage: #advnpcspawn clearbox [Spawngroup ID]"); return; } - std::string query = fmt::format( + auto query = fmt::format( "UPDATE spawngroup SET dist = 0, min_x = 0, max_x = 0, min_y = 0, max_y = 0, delay = 0 WHERE id = {}", - std::stoi(sep->arg[2]) + std::stoul(sep->arg[2]) ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to clear Spawngroup box."); return; @@ -160,44 +161,45 @@ void command_advnpcspawn(Client *c, const Seperator *sep) Chat::White, fmt::format( "Spawngroup {} Roambox Cleared | Delay: 0 Distance: 0.00", - std::stoi(sep->arg[2]) + std::stoul(sep->arg[2]) ).c_str() ); + c->Message( Chat::White, fmt::format( "Spawngroup {} Roambox Cleared | Minimum X: 0.00 Maximum X: 0.00", - std::stoi(sep->arg[2]) + std::stoul(sep->arg[2]) ).c_str() ); + c->Message( Chat::White, fmt::format( "Spawngroup {} Roambox Cleared | Minimum Y: 0.00 Maximum Y: 0.00", - std::stoi(sep->arg[2]) + std::stoul(sep->arg[2]) ).c_str() ); return; - } - else if (is_delete_spawn) { + } else if (is_delete_spawn) { if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { c->Message(Chat::White, "You must target an NPC to use this command."); return; } - NPC *target = c->GetTarget()->CastToNPC(); - Spawn2 *spawn2 = target->respawn2; + auto target = c->GetTarget()->CastToNPC(); + auto spawn2 = target->respawn2; if (!spawn2) { c->Message(Chat::White, "Failed to delete spawn because NPC has no Spawn2."); return; } - auto spawn2_id = spawn2->GetID(); - std::string query = fmt::format( + auto spawn2_id = spawn2->GetID(); + auto query = fmt::format( "DELETE FROM spawn2 WHERE id = {}", spawn2_id ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to delete spawn."); return; @@ -207,13 +209,13 @@ void command_advnpcspawn(Client *c, const Seperator *sep) Chat::White, fmt::format( "Spawn2 {} Deleted | Name: {}", - spawn2_id,c->GetTargetDescription(target) + spawn2_id, + c->GetTargetDescription(target) ).c_str() ); target->Depop(false); return; - } - else if (is_edit_box) { + } else if (is_edit_box) { if ( arguments != 8 || !sep->IsNumber(3) || @@ -222,22 +224,22 @@ void command_advnpcspawn(Client *c, const Seperator *sep) !sep->IsNumber(6) || !sep->IsNumber(7) || !sep->IsNumber(8) - ) { + ) { c->Message( Chat::White, "Usage: #advnpcspawn editbox [Spawngroup ID] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay]" ); return; } - auto spawngroup_id = std::stoi(sep->arg[2]); - auto distance = std::stof(sep->arg[3]); - auto minimum_x = std::stof(sep->arg[4]); - auto maximum_x = std::stof(sep->arg[5]); - auto minimum_y = std::stof(sep->arg[6]); - auto maximum_y = std::stof(sep->arg[7]); - auto delay = std::stoi(sep->arg[8]); + auto spawngroup_id = std::stoul(sep->arg[2]); + auto distance = std::stof(sep->arg[3]); + auto minimum_x = std::stof(sep->arg[4]); + auto maximum_x = std::stof(sep->arg[5]); + auto minimum_y = std::stof(sep->arg[6]); + auto maximum_y = std::stof(sep->arg[7]); + auto delay = std::stoi(sep->arg[8]); - std::string query = fmt::format( + auto query = fmt::format( "UPDATE spawngroup SET dist = {:.2f}, min_x = {:.2f}, max_x = {:.2f}, max_y = {:.2f}, min_y = {:.2f}, delay = {} WHERE id = {}", distance, minimum_x, @@ -247,7 +249,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) delay, spawngroup_id ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to edit Spawngroup box."); return; @@ -262,6 +264,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) distance ).c_str() ); + c->Message( Chat::White, fmt::format( @@ -271,6 +274,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) maximum_x ).c_str() ); + c->Message( Chat::White, fmt::format( @@ -281,8 +285,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) ).c_str() ); return; - } - else if (is_edit_respawn) { + } else if (is_edit_respawn) { if (arguments < 2 || !sep->IsNumber(2)) { c->Message(Chat::White, "Usage: #advnpcspawn editrespawn [Respawn Timer] [Variance]"); return; @@ -293,27 +296,24 @@ void command_advnpcspawn(Client *c, const Seperator *sep) return; } - NPC *target = c->GetTarget()->CastToNPC(); - Spawn2 *spawn2 = target->respawn2; + auto target = c->GetTarget()->CastToNPC(); + auto spawn2 = target->respawn2; if (!spawn2) { c->Message(Chat::White, "Failed to edit respawn because NPC has no Spawn2."); return; } - auto spawn2_id = spawn2->GetID(); - uint32 respawn_timer = std::stoi(sep->arg[2]); - uint32 variance = ( - sep->IsNumber(3) ? - std::stoi(sep->arg[3]) : - spawn2->GetVariance() - ); - std::string query = fmt::format( + auto spawn2_id = spawn2->GetID(); + auto respawn_timer = std::stoul(sep->arg[2]); + auto variance = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : spawn2->GetVariance(); + + auto query = fmt::format( "UPDATE spawn2 SET respawntime = {}, variance = {} WHERE id = {}", respawn_timer, variance, spawn2_id ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to edit respawn."); return; @@ -329,37 +329,29 @@ void command_advnpcspawn(Client *c, const Seperator *sep) variance ).c_str() ); + spawn2->SetRespawnTimer(respawn_timer); spawn2->SetVariance(variance); return; - } - else if (is_make_group) { - if ( - arguments != 9 || - !sep->IsNumber(3) || - !sep->IsNumber(4) || - !sep->IsNumber(5) || - !sep->IsNumber(6) || - !sep->IsNumber(7) || - !sep->IsNumber(8) || - !sep->IsNumber(9) - ) { + } else if (is_make_group) { + if (arguments < 2) { c->Message( Chat::White, "Usage: #advncspawn makegroup [Spawn Group Name] [Spawn Limit] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay]" ); return; } - std::string spawngroup_name = sep->arg[2]; - auto spawn_limit = std::stoi(sep->arg[3]); - auto distance = std::stof(sep->arg[4]); - auto minimum_x = std::stof(sep->arg[5]); - auto maximum_x = std::stof(sep->arg[6]); - auto minimum_y = std::stof(sep->arg[7]); - auto maximum_y = std::stof(sep->arg[8]); - auto delay = std::stoi(sep->arg[9]); - std::string query = fmt::format( + std::string spawngroup_name = sep->arg[2]; + auto spawn_limit = sep->IsNumber(3) ? std::stoi(sep->arg[3]) : 0; + auto distance = sep->IsNumber(4) ? std::stof(sep->arg[4]) : 0.0f; + auto minimum_x = sep->IsNumber(5) ? std::stof(sep->arg[5]) : 0.0f; + auto maximum_x = sep->IsNumber(6) ? std::stof(sep->arg[6]) : 0.0f; + auto minimum_y = sep->IsNumber(7) ? std::stof(sep->arg[7]) : 0.0f; + auto maximum_y = sep->IsNumber(8) ? std::stof(sep->arg[8]) : 0.0f; + auto delay = sep->IsNumber(9) ? std::stoi(sep->arg[9]) : 0; + + auto query = fmt::format( "INSERT INTO spawngroup" "(name, spawn_limit, dist, min_x, max_x, min_y, max_y, delay)" "VALUES ('{}', {}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {})", @@ -372,7 +364,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) maximum_y, delay ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to make Spawngroup."); return; @@ -416,39 +408,42 @@ void command_advnpcspawn(Client *c, const Seperator *sep) ).c_str() ); return; - } - else if (is_make_npc) { + } else if (is_make_npc) { if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { c->Message(Chat::White, "You must target an NPC to use this command."); return; } - NPC *target = c->GetTarget()->CastToNPC(); - content_db.NPCSpawnDB( - NPCSpawnTypes::CreateNewNPC, - zone->GetShortName(), - zone->GetInstanceVersion(), - c, - target - ); + if ( + content_db.NPCSpawnDB( + NPCSpawnTypes::CreateNewNPC, + zone->GetShortName(), + zone->GetInstanceVersion(), + c, + c->GetTarget()->CastToNPC() + ) + ) { + c->Message(Chat::White, "Created a new NPC."); + } + return; - } - else if (is_move_spawn) { + } else if (is_move_spawn) { if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { c->Message(Chat::White, "You must target an NPC to use this command."); return; } - NPC *target = c->GetTarget()->CastToNPC(); - Spawn2 *spawn2 = target->respawn2; + auto target = c->GetTarget()->CastToNPC(); + auto spawn2 = target->respawn2; if (!spawn2) { c->Message(Chat::White, "Failed to move spawn because NPC has no Spawn2."); return; } - auto client_position = c->GetPosition(); - auto spawn2_id = spawn2->GetID(); - std::string query = fmt::format( + auto client_position = c->GetPosition(); + auto spawn2_id = spawn2->GetID(); + + auto query = fmt::format( "UPDATE spawn2 SET x = {:.2f}, y = {:.2f}, z = {:.2f}, heading = {:.2f} WHERE id = {}", client_position.x, client_position.y, @@ -456,7 +451,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) client_position.w, spawn2_id ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to move spawn."); return; @@ -470,6 +465,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) c->GetTargetDescription(target) ).c_str() ); + c->Message( Chat::White, fmt::format( @@ -481,6 +477,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) client_position.w ).c_str() ); + target->GMMove( client_position.x, client_position.y, @@ -488,8 +485,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) client_position.w ); return; - } - else if (is_set_version) { + } else if (is_set_version) { if (arguments != 2 || !sep->IsNumber(2)) { c->Message(Chat::White, "Usage: #advnpcspawn setversion [Version]"); return; @@ -500,14 +496,15 @@ void command_advnpcspawn(Client *c, const Seperator *sep) return; } - NPC *target = c->GetTarget()->CastToNPC(); - auto version = std::stoi(sep->arg[2]); - std::string query = fmt::format( + auto target = c->GetTarget()->CastToNPC(); + auto version = std::stoul(sep->arg[2]); + + auto query = fmt::format( "UPDATE spawn2 SET version = {} WHERE spawngroupID = {}", version, target->GetSpawnGroupId() ); - auto results = content_db.QueryDatabase(query); + auto results = content_db.QueryDatabase(query); if (!results.Success()) { c->Message(Chat::White, "Failed to set version."); return; diff --git a/zone/gm_commands/ai.cpp b/zone/gm_commands/ai.cpp index 88c3e2a02..9ae6351e1 100755 --- a/zone/gm_commands/ai.cpp +++ b/zone/gm_commands/ai.cpp @@ -17,7 +17,7 @@ void command_ai(Client *c, const Seperator *sep) c->Message(Chat::White, "You must target an NPC to use this command."); return; } - + auto target = c->GetTarget()->CastToNPC(); bool is_consider = !strcasecmp(sep->arg[1], "consider"); @@ -42,7 +42,7 @@ void command_ai(Client *c, const Seperator *sep) return; } - if (is_consider) { + if (is_consider) { if (arguments == 2) { auto mob_name = sep->arg[2]; auto mob_to_consider = entity_list.GetMob(mob_name); @@ -153,7 +153,7 @@ void command_ai(Client *c, const Seperator *sep) delay ? fmt::format( "a delay of {} ({})", - ConvertMillisecondsToTime(delay), + Strings::MillisecondsToTime(delay), delay ): "no delay" @@ -162,7 +162,7 @@ void command_ai(Client *c, const Seperator *sep) minimum_delay ? fmt::format( "a minimum delay of {} ({})", - ConvertMillisecondsToTime(minimum_delay), + Strings::MillisecondsToTime(minimum_delay), minimum_delay ): "no minimum delay" @@ -209,7 +209,7 @@ void command_ai(Client *c, const Seperator *sep) fmt::format( "a delay of {} ({})", delay, - ConvertMillisecondsToTime(delay) + Strings::MillisecondsToTime(delay) ): "no delay" ), @@ -218,7 +218,7 @@ void command_ai(Client *c, const Seperator *sep) fmt::format( "a minimum delay of {} ({})", minimum_delay, - ConvertMillisecondsToTime(delay) + Strings::MillisecondsToTime(delay) ): "no minimum delay" ) diff --git a/zone/gm_commands/ban.cpp b/zone/gm_commands/ban.cpp index ab5131a32..3d2530ab9 100755 --- a/zone/gm_commands/ban.cpp +++ b/zone/gm_commands/ban.cpp @@ -28,16 +28,16 @@ void command_ban(Client *c, const Seperator *sep) c->Message( Chat::White, fmt::format( - "Character {} does not exist." - ).c_str(), - character_name + "Character {} does not exist.", + character_name + ).c_str() ); return; } auto query = fmt::format( "UPDATE account SET status = -2, ban_reason = '{}' WHERE id = {}", - EscapeString(reason), + Strings::Escape(reason), account_id ); auto results = database.QueryDatabase(query); @@ -53,20 +53,19 @@ void command_ban(Client *c, const Seperator *sep) ); ServerPacket flagUpdatePack(ServerOP_FlagUpdate, sizeof(ServerFlagUpdate_Struct)); - ServerFlagUpdate_Struct *sfus = (ServerFlagUpdate_Struct *) flagUpdatePack.pBuffer; + auto sfus = (ServerFlagUpdate_Struct *) flagUpdatePack.pBuffer; sfus->account_id = account_id; sfus->admin = -2; worldserver.SendPacket(&flagUpdatePack); - Client *client = nullptr; - client = entity_list.GetClientByName(character_name.c_str()); + auto client = entity_list.GetClientByName(character_name.c_str()); if (client) { client->WorldKick(); return; } ServerPacket kickPlayerPack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); - ServerKickPlayer_Struct *skp = (ServerKickPlayer_Struct *) kickPlayerPack.pBuffer; + auto skp = (ServerKickPlayer_Struct *) kickPlayerPack.pBuffer; strcpy(skp->adminname, c->GetName()); strcpy(skp->name, character_name.c_str()); skp->adminrank = c->Admin(); diff --git a/zone/gm_commands/bind.cpp b/zone/gm_commands/bind.cpp index 4c1b56644..f90e131af 100755 --- a/zone/gm_commands/bind.cpp +++ b/zone/gm_commands/bind.cpp @@ -16,7 +16,7 @@ void command_bind(Client *c, const Seperator *sep) ); if (!bind_allowed) { - c->Message(Chat::White, "Yu cannot bind here."); + c->Message(Chat::White, "You cannot bind here."); return; } diff --git a/zone/gm_commands/bugs.cpp b/zone/gm_commands/bugs.cpp new file mode 100755 index 000000000..44e49686e --- /dev/null +++ b/zone/gm_commands/bugs.cpp @@ -0,0 +1,343 @@ +#include "../client.h" +#include "../../common/repositories/bug_reports_repository.h" + +void command_bugs(Client *c, const Seperator *sep) +{ + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #bugs close [Bug ID] - Close a Bug Report by ID"); + c->Message(Chat::White, "Usage: #bugs delete [Bug ID] - Delete a Bug Report by ID"); + c->Message(Chat::White, "Usage: #bugs review [Bug ID] [Review] - Review a Bug Report by ID"); + c->Message(Chat::White, "Usage: #bugs search [Search Criteria] - Search for Bug Reports"); + c->Message(Chat::White, "Usage: #bugs view [Bug ID] - View a Bug Report by ID"); + return; + } + + bool is_close = !strcasecmp(sep->arg[1], "close"); + bool is_delete = !strcasecmp(sep->arg[1], "delete"); + bool is_review = !strcasecmp(sep->arg[1], "review"); + bool is_search = !strcasecmp(sep->arg[1], "search"); + bool is_view = !strcasecmp(sep->arg[1], "view"); + if ( + !is_close && + !is_delete && + !is_review && + !is_search && + !is_view + ) { + c->Message(Chat::White, "Usage: #bugs close [Bug ID] - Close a Bug Report by ID"); + c->Message(Chat::White, "Usage: #bugs delete [Bug ID] - Delete a Bug Report by ID"); + c->Message(Chat::White, "Usage: #bugs review [Bug ID] [Review] - Review a Bug Report by ID"); + c->Message(Chat::White, "Usage: #bugs search [Search Criteria] - Search for Bug Reports"); + c->Message(Chat::White, "Usage: #bugs view [Bug ID] - View a Bug Report by ID"); + return; + } + + if (is_close) { + if (!sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #bugs close [Bug ID] - Close a Bug Report by ID"); + return; + } + + auto bug_id = std::stoul(sep->arg[2]); + + auto r = BugReportsRepository::FindOne(content_db, bug_id); + if (!r.id) { + c->Message( + Chat::White, + fmt::format( + "Bug ID {} does not exist or is invalid.", + bug_id + ).c_str() + ); + return; + } + + r.bug_status = 1; + + if (!BugReportsRepository::UpdateOne(content_db, r)) { + c->Message( + Chat::White, + fmt::format( + "Failed to close Bug ID {}.", + bug_id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Successfully closed Bug ID {}.", + bug_id + ).c_str() + ); + + } else if (is_delete) { + if (!sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #bugs delete [Bug ID] - Delete a Bug Report by ID"); + return; + } + + auto bug_id = std::stoul(sep->arg[2]); + auto deleted_count = BugReportsRepository::DeleteOne(content_db, bug_id); + if (!deleted_count) { + c->Message( + Chat::White, + fmt::format( + "Bug ID {} does not exist or is invalid.", + bug_id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} successfully deleted.", + bug_id + ).c_str() + ); + } else if (is_review) { + if ( + arguments < 3 || + !sep->IsNumber(2) + ) { + c->Message(Chat::White, "Usage: #bugs review [Bug ID] [Review] - Review a Bug Report by ID"); + return; + } + + auto bug_id = std::stoul(sep->arg[2]); + auto bug_review = sep->argplus[3]; + + auto r = BugReportsRepository::FindOne(content_db, bug_id); + if (!r.id) { + c->Message( + Chat::White, + fmt::format( + "Bug ID {} does not exist or is invalid.", + bug_id + ).c_str() + ); + return; + } + + r.last_review = std::time(nullptr); + r.last_reviewer = c->GetCleanName(); + r.reviewer_notes = bug_review; + + if (!BugReportsRepository::UpdateOne(content_db, r)) { + c->Message( + Chat::White, + fmt::format( + "Failed to add a review on Bug ID {}.", + bug_id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Successfully added a review on Bug ID {}.", + bug_id + ).c_str() + ); + } else if (is_search) { + if (arguments < 2) { + c->Message(Chat::White, "Usage: #bugs search [Search Criteria] - Search for Bug Reports"); + return; + } + + auto search_criteria = sep->argplus[2]; + auto l = BugReportsRepository::GetWhere( + content_db, + fmt::format( + "bug_status = 0 AND (character_name LIKE '%%{}%%' OR bug_report LIKE '%%{}%%')", + Strings::Escape(search_criteria), + Strings::Escape(search_criteria) + ) + ); + if (l.empty()) { + c->Message( + Chat::White, + fmt::format( + "No Bug Reports were found matching '{}'.", + search_criteria + ).c_str() + ); + return; + } + + for (const auto& r : l) { + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Character: {} Report: {} | {} | {}", + r.id, + r.character_name, + r.bug_report, + Saylink::Silent( + fmt::format( + "#bugs view {}", + r.id + ), + "View" + ), + Saylink::Silent( + fmt::format( + "#bugs close {}", + r.id + ), + "Close" + ) + ).c_str() + ); + } + } else if (is_view) { + if (!sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #bugs view [Bug ID] - View a Bug Report by ID"); + return; + } + + auto bug_id = std::stoul(sep->arg[2]); + + auto r = BugReportsRepository::FindOne(content_db, bug_id); + if (!r.id) { + c->Message( + Chat::White, + fmt::format( + "Bug ID {} does not exist or is invalid.", + bug_id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Character: {} ({}) Category: {} ({})", + r.id, + r.character_name, + r.character_id, + r.category_name, + r.category_id + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Zone: {} ({})", + r.id, + ZoneLongName(ZoneID(r.zone)), + r.zone + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Position: {:.2f}, {:.2f}, {:.2f}, {}", + r.id, + r.pos_x, + r.pos_y, + r.pos_z, + r.heading + ).c_str() + ); + + if (r._target_info) { + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Target: {} ({})", + r.id, + r.target_name, + r.target_id + ).c_str() + ); + } + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Can Duplicate: {} Crash Bug: {}", + r.id, + r._can_duplicate ? "Yes" : "No", + r._crash_bug ? "Yes" : "No" + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Character Flags: {} Unknown Value: {}", + r.id, + r._character_flags ? "Yes" : "No", + r._unknown_value ? "Yes" : "No" + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Report: {} Reported: {}", + r.id, + r.bug_report, + r.report_datetime + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Client: {} ({}) UI Path: {}", + r.id, + r.client_version_name, + r.client_version_id, + r.ui_path + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | System Info: {}", + r.id, + r.system_info + ).c_str() + ); + + if (r.last_reviewer != "None") { + c->Message( + Chat::White, + fmt::format( + "Bug ID {} | Last Reviewer: {} Last Reviewed: {} Reviewer Notes: {}", + r.id, + r.last_reviewer, + r.last_review, + r.reviewer_notes + ).c_str() + ); + } + + c->Message( + Chat::White, + fmt::format( + "Would you like to {} this bug?", + Saylink::Silent( + fmt::format( + "#bugs close {}", + r.id + ), + "close" + ) + ).c_str() + ); + } +} diff --git a/zone/gm_commands/camerashake.cpp b/zone/gm_commands/camerashake.cpp index cb781a99a..9c2e8a5f0 100755 --- a/zone/gm_commands/camerashake.cpp +++ b/zone/gm_commands/camerashake.cpp @@ -23,7 +23,7 @@ void command_camerashake(Client *c, const Seperator *sep) Chat::White, fmt::format( "Sending camera shake to world with a duration of {} ({}) and an intensity of {}.", - ConvertMillisecondsToTime(duration), + Strings::MillisecondsToTime(duration), duration, intensity ).c_str() diff --git a/zone/gm_commands/chat.cpp b/zone/gm_commands/chat.cpp index 4b511ec84..30bbe11d7 100755 --- a/zone/gm_commands/chat.cpp +++ b/zone/gm_commands/chat.cpp @@ -5,11 +5,16 @@ extern WorldServer worldserver; void command_chat(Client *c, const Seperator *sep) { - if (sep->arg[2][0] == 0) { - c->Message(Chat::White, "Usage: #chat [channum] [message]"); + auto arguments = sep->argnum; + if (arguments < 2 || !sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #chat [Channel ID] [Message]"); + return; } - else if (!worldserver.SendChannelMessage(0, 0, (uint8) atoi(sep->arg[1]), 0, 0, 100, sep->argplus[2])) { - c->Message(Chat::White, "Error: World server disconnected"); + + auto channel_id = static_cast(std::stoul(sep->arg[1])); + std::string message = sep->argplus[2]; + if (!worldserver.SendChannelMessage(0, 0, channel_id, 0, 0, 100, message.c_str())) { + c->Message(Chat::White, "World server is disconnected."); } } diff --git a/zone/gm_commands/damage.cpp b/zone/gm_commands/damage.cpp index 490253cad..fbe1242d5 100755 --- a/zone/gm_commands/damage.cpp +++ b/zone/gm_commands/damage.cpp @@ -8,9 +8,10 @@ void command_damage(Client *c, const Seperator *sep) return; } - Mob* target = c; - if (c->GetTarget()) { - target = c->GetTarget(); + Mob* target = c->GetTarget(); + if (!target) { + c->Message(Chat::White, "You must have a target to use #damage."); + return; } int64 damage = std::stoll(sep->arg[1], nullptr, 10); diff --git a/zone/gm_commands/databuckets.cpp b/zone/gm_commands/databuckets.cpp index 82df39342..48ad596f2 100755 --- a/zone/gm_commands/databuckets.cpp +++ b/zone/gm_commands/databuckets.cpp @@ -21,7 +21,7 @@ void command_databuckets(Client *c, const Seperator *sep) } } if (sep->arg[2]) { - key_filter = str_tolower(sep->arg[2]); + key_filter = Strings::ToLower(sep->arg[2]); } std::string query = "SELECT `id`, `key`, `value`, `expires` FROM data_buckets"; if (!key_filter.empty()) { query += StringFormat(" WHERE `key` LIKE '%%%s%%'", key_filter.c_str()); } @@ -68,7 +68,7 @@ void command_databuckets(Client *c, const Seperator *sep) c->Message( Chat::White, "%s : %s", - EQ::SayLinkEngine::GenerateQuestSaylink(del_saylink, false, "Delete").c_str(), + Saylink::Silent(del_saylink, "Delete").c_str(), key.c_str(), " Value: ", value.c_str()); diff --git a/zone/gm_commands/date.cpp b/zone/gm_commands/date.cpp index 3e8aa2455..0154f233f 100755 --- a/zone/gm_commands/date.cpp +++ b/zone/gm_commands/date.cpp @@ -2,28 +2,66 @@ void command_date(Client *c, const Seperator *sep) { - //yyyy mm dd hh mm local - if (sep->arg[3][0] == 0 || !sep->IsNumber(1) || !sep->IsNumber(2) || !sep->IsNumber(3)) { - c->Message(Chat::Red, "Usage: #date yyyy mm dd [HH MM]"); - } - else { - int h = 0, m = 0; - TimeOfDay_Struct eqTime; - zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime); - if (!sep->IsNumber(4)) { - h = eqTime.hour; - } - else { - h = atoi(sep->arg[4]); - } - if (!sep->IsNumber(5)) { - m = eqTime.minute; - } - else { - m = atoi(sep->arg[5]); - } - c->Message(Chat::Red, "Setting world time to %s-%s-%s %i:%i...", sep->arg[1], sep->arg[2], sep->arg[3], h, m); - zone->SetDate(atoi(sep->arg[1]), atoi(sep->arg[2]), atoi(sep->arg[3]), h, m); + int arguments = sep->argnum; + if ( + !arguments || + !sep->IsNumber(1) || + !sep->IsNumber(2) || + !sep->IsNumber(3) + ) { + c->Message(Chat::White, "Usage: #date [Year] [Month] [Day] [Hour] [Minute]"); + return; } + + TimeOfDay_Struct eq_time; + zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time); + + auto year = static_cast(std::stoul(sep->arg[1])); + auto month = static_cast(std::stoul(sep->arg[2])); + auto day = static_cast(std::stoul(sep->arg[3])); + + auto hour = !sep->IsNumber(4) ? eq_time.hour : static_cast(std::stoul(sep->arg[4]) + 1); + auto minute = !sep->IsNumber(5) ? eq_time.minute : static_cast(std::stoul(sep->arg[5])); + + c->Message( + Chat::White, + fmt::format("Setting world time to {}/{}/{} {:02}:{:02} {}.", + year, + month, + day, + ( + (hour % 12) == 0 ? + 12 : + (hour % 12) + ), + minute, + ( + hour >= 13 ? + "PM" : + "AM" + ) + ).c_str() + ); + + zone->SetDate(year, month, day, hour, minute); + + LogInfo( + "{} :: Setting world time to {}/{}/{} {:02}:{:02} {}.", + c->GetCleanName(), + year, + month, + day, + ( + (hour % 12) == 0 ? + 12 : + (hour % 12) + ), + minute, + ( + hour >= 13 ? + "PM" : + "AM" + ) + ); } diff --git a/zone/gm_commands/dbspawn2.cpp b/zone/gm_commands/dbspawn2.cpp index 2f31e2f19..aa5740b32 100755 --- a/zone/gm_commands/dbspawn2.cpp +++ b/zone/gm_commands/dbspawn2.cpp @@ -2,30 +2,103 @@ void command_dbspawn2(Client *c, const Seperator *sep) { + auto arguments = sep->argnum; + if ( + !arguments || + !sep->IsNumber(1) || + !sep->IsNumber(2) || + !sep->IsNumber(3) + ) { + c->Message(Chat::White, "Usage: #dbspawn2 [Spawngroup ID] [Respawn] [Variance] [Condition ID] [Condition Minimum]"); + c->Message(Chat::White, "Note: Respawn and Variance are in Seconds."); + return; + } - if (sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)) { - LogInfo("Spawning database spawn"); - uint16 cond = 0; - int16 cond_min = 0; - if (sep->IsNumber(4)) { - cond = atoi(sep->arg[4]); - if (sep->IsNumber(5)) { - cond_min = atoi(sep->arg[5]); - } - } - database.CreateSpawn2( - c, - atoi(sep->arg[1]), - zone->GetShortName(), - c->GetPosition(), - atoi(sep->arg[2]), - atoi(sep->arg[3]), - cond, - cond_min + auto position = c->GetPosition(); + + auto spawngroup_id = std::stoul(sep->arg[1]); + auto respawn = std::stoul(sep->arg[2]); + auto variance = std::stoul(sep->arg[3]); + + auto condition_id = sep->IsNumber(4) ? static_cast(std::stoul(sep->arg[4])) : static_cast(0); + auto condition_minimum = sep->IsNumber(5) ? static_cast(std::stoul(sep->arg[5])) : static_cast(0); + + if (!database.CreateSpawn2( + c, + spawngroup_id, + zone->GetShortName(), + position, + respawn, + variance, + condition_id, + condition_minimum + )) { + c->Message( + Chat::White, + fmt::format( + "Failed to add Spawngroup ID {} to {} at {:.2f}, {:.2f}, {:.2f}, {:.2f}.", + spawngroup_id, + zone->GetZoneDescription(), + position.x, + position.y, + position.z, + position.w + ).c_str() ); + return; } - else { - c->Message(Chat::White, "Usage: #dbspawn2 spawngroup respawn variance [condition_id] [condition_min]"); - } -} + c->Message( + Chat::White, + fmt::format( + "Spawngroup Added | ID: {}", + spawngroup_id + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spawngroup Added | Zone: {}", + zone->GetZoneDescription() + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spawngroup Added | Position: {:.2f}, {:.2f}, {:.2f}, {:.2f}", + position.x, + position.y, + position.z, + position.w + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spawngroup Added | Respawn: {} ({})", + Strings::SecondsToTime(respawn), + respawn + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spawngroup Added | Variance: {} ({})", + Strings::SecondsToTime(variance), + variance + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Spawngroup Added | Condition ID: {} Condition Minimum: {}", + condition_id, + condition_minimum + ).c_str() + ); +} diff --git a/zone/gm_commands/delacct.cpp b/zone/gm_commands/delacct.cpp index 959fe7404..ff3a10edd 100755 --- a/zone/gm_commands/delacct.cpp +++ b/zone/gm_commands/delacct.cpp @@ -1,21 +1,75 @@ #include "../client.h" +#include "../../common/repositories/account_repository.h" void command_delacct(Client *c, const Seperator *sep) { - if (sep->arg[1][0] == 0) { - c->Message(Chat::White, "Format: #delacct accountname"); + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Format: #delacct [Account ID|Account Name]"); + return; } - else { - std::string user; - std::string loginserver; - ParseAccountString(sep->arg[1], user, loginserver); - if (database.DeleteAccount(user.c_str(), loginserver.c_str())) { - c->Message(Chat::White, "The account was deleted."); + uint32 account_id = 0; + std::string account_name; + + if (sep->IsNumber(1)) { + account_id = std::stoul(sep->arg[1]); + auto a = AccountRepository::FindOne(content_db, account_id); + if (!a.id) { + c->Message( + Chat::White, + fmt::format( + "Account ID {} does not exist or is invalid.", + account_id + ).c_str() + ); + return; } - else { - c->Message(Chat::White, "Unable to delete account."); + + account_name = a.name; + } else { + account_name = sep->arg[1]; + auto a = AccountRepository::GetWhere( + content_db, + fmt::format( + "`name` = '{}'", + account_name + ) + ); + + if (a.empty() || !a[0].id) { + c->Message( + Chat::White, + fmt::format( + "Account {} does not exist or is invalid.", + account_name + ).c_str() + ); + return; } + + account_id = a[0].id; } + + if (!AccountRepository::DeleteOne(content_db, account_id)) { + c->Message( + Chat::White, + fmt::format( + "Failed to delete account {} ({}).", + account_name, + account_id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Successfully deleted account {} ({}).", + account_name, + account_id + ).c_str() + ); } diff --git a/zone/gm_commands/deletegraveyard.cpp b/zone/gm_commands/deletegraveyard.cpp deleted file mode 100755 index 43560eb6f..000000000 --- a/zone/gm_commands/deletegraveyard.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "../client.h" - -void command_deletegraveyard(Client *c, const Seperator *sep) -{ - uint32 zoneid = 0; - uint32 graveyard_id = 0; - - if (!sep->arg[1][0]) { - c->Message(Chat::White, "Usage: #deletegraveyard [zonename]"); - return; - } - - zoneid = ZoneID(sep->arg[1]); - graveyard_id = content_db.GetZoneGraveyardID(zoneid, 0); - - if (zoneid > 0 && graveyard_id > 0) { - if (content_db.DeleteGraveyard(zoneid, graveyard_id)) { - c->Message(Chat::White, "Successfuly deleted graveyard %u for zone %s.", graveyard_id, sep->arg[1]); - } - else { - c->Message(Chat::White, "Unable to delete graveyard %u for zone %s.", graveyard_id, sep->arg[1]); - } - } - else { - if (zoneid <= 0) { - c->Message(Chat::White, "Unable to retrieve a ZoneID for the zone: %s", sep->arg[1]); - } - else if (graveyard_id <= 0) { - c->Message(Chat::White, "Unable to retrieve a valid GraveyardID for the zone: %s", sep->arg[1]); - } - } - - return; -} - diff --git a/zone/gm_commands/depop.cpp b/zone/gm_commands/depop.cpp index 3a1693205..a2bb85676 100755 --- a/zone/gm_commands/depop.cpp +++ b/zone/gm_commands/depop.cpp @@ -3,12 +3,25 @@ void command_depop(Client *c, const Seperator *sep) { - if (c->GetTarget() == 0 || !(c->GetTarget()->IsNPC() || c->GetTarget()->IsNPCCorpse())) { - c->Message(Chat::White, "You must have a NPC target for this command. (maybe you meant #depopzone?)"); + if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { + c->Message(Chat::White, "You must target an NPC to use this command."); + return; } - else { - c->Message(Chat::White, "Depoping '%s'.", c->GetTarget()->GetName()); - c->GetTarget()->Depop(); - } -} + auto start_spawn_timer = false; + + if (sep->IsNumber(1)) { + start_spawn_timer = std::stoi(sep->arg[1]) ? true : false; + } + + c->Message( + Chat::White, + fmt::format( + "Depopping {}{}.", + c->GetTargetDescription(c->GetTarget()), + start_spawn_timer ? " and starting their spawn timer" : "" + ).c_str() + ); + + c->GetTarget()->Depop(start_spawn_timer); +} diff --git a/zone/gm_commands/depopzone.cpp b/zone/gm_commands/depopzone.cpp index 518ef42db..e24c45f46 100755 --- a/zone/gm_commands/depopzone.cpp +++ b/zone/gm_commands/depopzone.cpp @@ -2,7 +2,20 @@ void command_depopzone(Client *c, const Seperator *sep) { - zone->Depop(); - c->Message(Chat::White, "Zone depoped."); + auto start_spawn_timers = false; + + if (sep->IsNumber(1)) { + start_spawn_timers = std::stoi(sep->arg[1]) ? true : false; + } + + zone->Depop(start_spawn_timers); + + c->Message( + Chat::White, + fmt::format( + "Zone depopped{}.", + start_spawn_timers ? " and spawn timers started" : "" + ).c_str() + ); } diff --git a/zone/gm_commands/devtools.cpp b/zone/gm_commands/devtools.cpp index da46b4f77..2ac34c6d1 100755 --- a/zone/gm_commands/devtools.cpp +++ b/zone/gm_commands/devtools.cpp @@ -3,18 +3,11 @@ void command_devtools(Client *c, const Seperator *sep) { - std::string dev_tools_key = StringFormat("%i-dev-tools-disabled", c->AccountID()); + bool is_disable = !strcasecmp(sep->arg[1], "disable"); + bool is_enable = !strcasecmp(sep->arg[1], "enable"); - /** - * Handle window toggle - */ - if (strcasecmp(sep->arg[1], "disable") == 0) { - DataBucket::SetData(dev_tools_key, "true"); - c->SetDevToolsEnabled(false); - } - if (strcasecmp(sep->arg[1], "enable") == 0) { - DataBucket::DeleteData(dev_tools_key); - c->SetDevToolsEnabled(true); + if (is_disable || is_enable) { + c->SetDevToolsEnabled(is_enable); } c->ShowDevToolsMenu(); diff --git a/zone/gm_commands/doanim.cpp b/zone/gm_commands/doanim.cpp index d48725a97..ec57650ff 100755 --- a/zone/gm_commands/doanim.cpp +++ b/zone/gm_commands/doanim.cpp @@ -1,20 +1,98 @@ #include "../client.h" +#include "../dialogue_window.h" void command_doanim(Client *c, const Seperator *sep) { - if (!sep->IsNumber(1)) { - c->Message(Chat::White, "Usage: #DoAnim [number]"); + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #doanim [Name|Number] [Speed]"); + return; } - else if (c->Admin() >= commandDoAnimOthers) { - if (c->GetTarget() == 0) { - c->Message(Chat::White, "Error: You need a target."); + + Mob* t = c; + if (c->GetTarget() && c->Admin() >= commandDoAnimOthers) { + t = c->GetTarget(); + } + + int animation_id = -1; + std::string animation_name; + auto animation_speed = 0; + + if (sep->IsNumber(1)) { + animation_id = std::stoi(sep->arg[1]); + + const auto& a = animation_names_map.find(animation_id); + if (a != animation_names_map.end()) { + animation_name = a->second; } - else { - c->GetTarget()->DoAnim(atoi(sep->arg[1]), atoi(sep->arg[2])); + + if (animation_name.empty()) { + c->Message( + Chat::White, + fmt::format( + "Animation ID {} does not exist or is invalid.", + animation_id + ).c_str() + ); + return; + } + } else { + const std::string search_criteria = sep->arg[1]; + + const auto& a = animations.find(Strings::ToLower(search_criteria)); + if (a != animations.end()) { + animation_id = a->second; + const auto& b = animation_names_map.find(animation_id); + if (b != animation_names_map.end()) { + animation_name = b->second; + } + } else { + for (const auto& b : animation_names_map) { + if (Strings::ToLower(b.second).find(Strings::ToLower(search_criteria)) != std::string::npos) { + animation_id = b.first; + animation_name = b.second; + break; + } + } + + if (animation_id == -1) { + c->Message( + Chat::White, + fmt::format( + "No Animation could be found matching '{}'.", + search_criteria + ).c_str() + ); + return; + } } } - else { - c->DoAnim(atoi(sep->arg[1]), atoi(sep->arg[2])); + + if (sep->IsNumber(2)) { + animation_speed = std::stoi(sep->arg[2]); } + + const auto speed_message = ( + animation_speed ? + fmt::format( + " at speed {}", + animation_speed + ) : + "" + ); + + c->Message( + Chat::White, + fmt::format( + "{} {} now performing the {} ({}) animation{}.", + c->GetTargetDescription(t, TargetDescriptionType::UCYou), + c == t ? "are" : "is", + animation_name, + animation_id, + speed_message + ).c_str() + ); + + t->DoAnim(animation_id, animation_speed); } diff --git a/zone/gm_commands/door_manipulation.cpp b/zone/gm_commands/door_manipulation.cpp index a724fb61f..c0e7c48ba 100644 --- a/zone/gm_commands/door_manipulation.cpp +++ b/zone/gm_commands/door_manipulation.cpp @@ -34,80 +34,10 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) ); } - // option - if (arg1.empty()) { - DoorManipulation::CommandHeader(c); - c->Message( - Chat::White, - "#door create | Creates a door from a model. (Example IT78 creates a campfire)" - ); - c->Message(Chat::White, "#door setinvertstate [0|1] | Sets selected door invert state"); - c->Message(Chat::White, "#door setincline | Sets selected door incline"); - c->Message(Chat::White, "#door opentype | Sets selected door opentype"); - c->Message( - Chat::White, - fmt::format( - "#door model | Changes door model for selected door or select from [{}] or [{}]", - EQ::SayLinkEngine::GenerateQuestSaylink("#door showmodelszone", false, "local zone"), - EQ::SayLinkEngine::GenerateQuestSaylink("#door showmodelsglobal", false, "global") - ).c_str() - ); - c->Message( - Chat::White, - "#door showmodelsfromfile | Shows models from s3d or eqg file. Example tssequip.eqg or wallet01.eqg" - ); - - c->Message( - Chat::White, - fmt::format( - "{} | Shows available models in the current zone that you are in", - EQ::SayLinkEngine::GenerateQuestSaylink("#door showmodelszone", false, "#door showmodelszone") - ).c_str() - ); - - c->Message( - Chat::White, - fmt::format( - "{} | Shows available models globally by first listing all global model files", - EQ::SayLinkEngine::GenerateQuestSaylink("#door showmodelsglobal", false, "#door showmodelsglobal") - ).c_str() - ); - - c->Message(Chat::White, "#door save | Creates database entry for selected door"); - c->Message( - Chat::White, - fmt::format( - "{} - Brings up editing interface for selected door", - EQ::SayLinkEngine::GenerateQuestSaylink("#door edit", false, "#door edit") - ).c_str() - ); - c->Message( - Chat::White, - fmt::format( - "{} - lists doors in zone", - EQ::SayLinkEngine::GenerateQuestSaylink("#list doors", false, "#list doors") - ).c_str() - ); - - return; - } - // edit menu if (arg1 == "edit") { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { - c->Message( - Chat::White, - fmt::format( - "Door Selected ID [{}] Name [{}] OpenType [{}] Invertstate [{} | {}/{}] ", - c->GetDoorToolEntityId(), - door->GetDoorName(), - door->GetOpenType(), - door->GetInvertState(), - EQ::SayLinkEngine::GenerateQuestSaylink("#door setinvertstate 0", false, "0"), - EQ::SayLinkEngine::GenerateQuestSaylink("#door setinvertstate 1", false, "1") - ).c_str() - ); const std::string move_x_action = "move_x"; const std::string move_y_action = "move_y"; @@ -115,191 +45,8 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) const std::string move_h_action = "move_h"; const std::string set_size_action = "set_size"; - std::vector move_options = { - move_x_action, - move_y_action, - move_z_action, - move_h_action, - set_size_action - }; - std::vector move_x_options_positive; - std::vector move_x_options_negative; - std::vector move_y_options_positive; - std::vector move_y_options_negative; - std::vector move_z_options_positive; - std::vector move_z_options_negative; - std::vector move_h_options_positive; - std::vector move_h_options_negative; - std::vector set_size_options_positive; - std::vector set_size_options_negative; - for (const auto &move_option : move_options) { - if (move_option == move_x_action) { - move_x_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} .25", move_option), - false, - ".25" - ) - ); - - for (int move_index = 0; move_index <= 15; move_index += 5) { - int value = (move_index == 0 ? 1 : move_index); - move_x_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - for (int move_index = -15; move_index <= 0; move_index += 5) { - int value = (move_index == 0 ? 1 : move_index); - move_x_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - move_x_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} -.25", move_option), - false, - ".25" - ) - ); - } - else if (move_option == move_y_action) { - move_y_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} .25", move_option), - false, - ".25" - ) - ); - - for (int move_index = 0; move_index <= 15; move_index += 5) { - int value = (move_index == 0 ? 1 : move_index); - move_y_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - for (int move_index = -15; move_index <= 0; move_index += 5) { - int value = (move_index == 0 ? -1 : move_index); - move_y_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - move_y_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} -.25", move_option), - false, - ".25" - ) - ); - } - else if (move_option == move_z_action) { - move_z_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} .25", move_option), - false, - ".25" - ) - ); - - for (int move_index = 0; move_index <= 15; move_index += 5) { - int value = (move_index == 0 ? 1 : move_index); - move_z_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - for (int move_index = -15; move_index <= 0; move_index += 5) { - int value = (move_index == 0 ? -1 : move_index); - move_z_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - move_z_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} -.25", move_option), - false, - ".25" - ) - ); - } - else if (move_option == move_h_action) { - for (int move_index = 0; move_index <= 50; move_index += 5) { - int value = (move_index == 0 ? 1 : move_index); - move_h_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - for (int move_index = -50; move_index <= 0; move_index += 5) { - int value = (move_index == 0 ? -1 : move_index); - move_h_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - } - else if (move_option == set_size_action) { - for (int move_index = 0; move_index <= 100; move_index += 10) { - int value = (move_index == 0 ? 1 : move_index); - set_size_options_positive.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - - for (int move_index = -100; move_index <= 0; move_index += 10) { - int value = (move_index == 0 ? -1 : move_index); - set_size_options_negative.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#door edit {} {}", move_option, value), - false, - fmt::format("{}", std::abs(value)) - ) - ); - } - } - } - // we're passing a move action here - if (!arg3.empty() && StringIsNumber(arg3)) { + if (!arg3.empty() && Strings::IsNumber(arg3)) { float x_move = 0.0f; float y_move = 0.0f; float z_move = 0.0f; @@ -336,73 +83,192 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) door_position.w = door_position.w + h_move; door->SetPosition(door_position); door->SetSize(door->GetSize() + set_size); + + // spawn and move helpers + uint16 helper_mob_x_negative = 0; + uint16 helper_mob_x_positive = 0; + uint16 helper_mob_y_positive = 0; + uint16 helper_mob_y_negative = 0; + + for (auto &n: entity_list.GetNPCList()) { + NPC *npc = n.second; + std::string npc_name = npc->GetName(); + if (npc_name.find("-X") != std::string::npos) { + helper_mob_x_negative = npc->GetID(); + } + if (npc_name.find("-Y") != std::string::npos) { + helper_mob_y_negative = npc->GetID(); + } + if (npc_name.find("+X") != std::string::npos) { + helper_mob_x_positive = npc->GetID(); + } + if (npc_name.find("+Y") != std::string::npos) { + helper_mob_y_positive = npc->GetID(); + } + } + + // -X + door_position = door->GetPosition(); + if (helper_mob_x_negative == 0) { + door_position.x = door_position.x - 15; + helper_mob_x_negative = NPC::SpawnNodeNPC("-X", "", door_position)->GetID(); + } + else { + auto n = entity_list.GetNPCByID(helper_mob_x_negative); + n->GMMove(door->GetX() - 15, door->GetY(), door->GetZ(), n->GetHeading()); + } + + // +X + door_position = door->GetPosition(); + if (helper_mob_x_positive == 0) { + door_position.x = door_position.x + 15; + helper_mob_x_positive = NPC::SpawnNodeNPC("+X", "", door_position)->GetID(); + } + else { + auto n = entity_list.GetNPCByID(helper_mob_x_positive); + n->GMMove(door->GetX() + 15, door->GetY(), door->GetZ(), n->GetHeading()); + } + + // -Y + door_position = door->GetPosition(); + if (helper_mob_y_negative == 0) { + door_position.y = door_position.y - 15; + helper_mob_y_negative = NPC::SpawnNodeNPC("-Y", "", door_position)->GetID(); + } + else { + auto n = entity_list.GetNPCByID(helper_mob_y_negative); + n->GMMove(door->GetX(), door->GetY() - 15, door->GetZ(), n->GetHeading()); + } + + // +Y + door_position = door->GetPosition(); + if (helper_mob_y_positive == 0) { + door_position.y = door_position.y + 15; + helper_mob_y_positive = NPC::SpawnNodeNPC("+Y", "", door_position)->GetID(); + } + else { + auto n = entity_list.GetNPCByID(helper_mob_y_positive); + n->GMMove(door->GetX(), door->GetY() + 15, door->GetZ(), n->GetHeading()); + } + + return; } - // spawn and move helpers - uint16 helper_mob_x_negative = 0; - uint16 helper_mob_x_positive = 0; - uint16 helper_mob_y_positive = 0; - uint16 helper_mob_y_negative = 0; + c->Message( + Chat::White, + fmt::format( + "Door Selected ID [{}] Name [{}] OpenType [{}] Invertstate [{} | {}/{}] ", + c->GetDoorToolEntityId(), + door->GetDoorName(), + door->GetOpenType(), + door->GetInvertState(), + Saylink::Silent("#door setinvertstate 0", "0"), + Saylink::Silent("#door setinvertstate 1", "1") + ).c_str() + ); - for (auto &n: entity_list.GetNPCList()) { - NPC *npc = n.second; - std::string npc_name = npc->GetName(); - if (npc_name.find("-X") != std::string::npos) { - helper_mob_x_negative = npc->GetID(); - } - if (npc_name.find("-Y") != std::string::npos) { - helper_mob_y_negative = npc->GetID(); - } - if (npc_name.find("+X") != std::string::npos) { - helper_mob_x_positive = npc->GetID(); - } - if (npc_name.find("+Y") != std::string::npos) { - helper_mob_y_positive = npc->GetID(); + + std::vector move_options = { + move_x_action, + move_y_action, + move_z_action, + move_h_action, + set_size_action + }; + std::vector move_x_options_positive; + std::vector move_x_options_negative; + std::vector move_y_options_positive; + std::vector move_y_options_negative; + std::vector move_z_options_positive; + std::vector move_z_options_negative; + std::vector move_h_options_positive; + std::vector move_h_options_negative; + std::vector set_size_options_positive; + std::vector set_size_options_negative; + + std::vector xyz_values = { + ".1", "1", "5", "10", "25", "50", "100" + }; + + // build positive options x/y/z + for (const auto &v: xyz_values) { + for (const auto &o: move_options) { + if (o == move_x_action) { + move_x_options_positive.emplace_back( + Saylink::Silent(fmt::format("#door edit {} {}", o, v), v) + ); + } + else if (o == move_y_action) { + move_y_options_positive.emplace_back( + Saylink::Silent(fmt::format("#door edit {} {}", o, v), v) + ); + } + else if (o == move_z_action) { + move_z_options_positive.emplace_back( + Saylink::Silent(fmt::format("#door edit {} {}", o, v), v) + ); + } } } - // -X - glm::vec4 door_position = door->GetPosition(); - if (helper_mob_x_negative == 0) { - door_position.x = door_position.x - 15; - helper_mob_x_negative = NPC::SpawnNodeNPC("-X", "", door_position)->GetID(); - } - else { - auto n = entity_list.GetNPCByID(helper_mob_x_negative); - n->GMMove(door->GetX() - 15, door->GetY(), door->GetZ(), n->GetHeading()); + // loop through vector in reverse order + // build negative options x/y/z + for (auto v = xyz_values.rbegin(); v != xyz_values.rend(); ++v) { + for (const auto &o: move_options) { + if (o == move_x_action) { + move_x_options_negative.emplace_back( + Saylink::Silent(fmt::format("#door edit {} -{}", o, *v), *v) + ); + } + else if (o == move_y_action) { + move_y_options_negative.emplace_back( + Saylink::Silent(fmt::format("#door edit {} -{}", o, *v), *v) + ); + } + else if (o == move_z_action) { + move_z_options_negative.emplace_back( + Saylink::Silent(fmt::format("#door edit {} -{}", o, *v), *v) + ); + } + } } - // +X - door_position = door->GetPosition(); - if (helper_mob_x_positive == 0) { - door_position.x = door_position.x + 15; - helper_mob_x_positive = NPC::SpawnNodeNPC("+X", "", door_position)->GetID(); - } - else { - auto n = entity_list.GetNPCByID(helper_mob_x_positive); - n->GMMove(door->GetX() + 15, door->GetY(), door->GetZ(), n->GetHeading()); + std::vector heading_values = { + "1", "5", "32.5", "63.75", "130", + }; + + // build positive options h + for (const auto &v: heading_values) { + move_h_options_positive.emplace_back( + Saylink::Silent(fmt::format("#door edit {} {}", move_h_action, v), v) + ); } - // -Y - door_position = door->GetPosition(); - if (helper_mob_y_negative == 0) { - door_position.y = door_position.y - 15; - helper_mob_y_negative = NPC::SpawnNodeNPC("-Y", "", door_position)->GetID(); - } - else { - auto n = entity_list.GetNPCByID(helper_mob_y_negative); - n->GMMove(door->GetX(), door->GetY() - 15, door->GetZ(), n->GetHeading()); + // loop through vector in reverse order + // build negative options h + for (auto v = heading_values.rbegin(); v != heading_values.rend(); ++v) { + move_h_options_negative.emplace_back( + Saylink::Silent(fmt::format("#door edit {} -{}", move_h_action, *v), *v) + ); } - // +Y - door_position = door->GetPosition(); - if (helper_mob_y_positive == 0) { - door_position.y = door_position.y + 15; - helper_mob_y_positive = NPC::SpawnNodeNPC("+Y", "", door_position)->GetID(); + std::vector size_values = { + "1", "5", "10", "25", "50", "100", "1000" + }; + + // build positive options size + for (const auto &v: size_values) { + set_size_options_positive.emplace_back( + Saylink::Silent(fmt::format("#door edit {} {}", set_size_action, v), v) + ); } - else { - auto n = entity_list.GetNPCByID(helper_mob_y_positive); - n->GMMove(door->GetX(), door->GetY() + 15, door->GetZ(), n->GetHeading()); + + // loop through vector in reverse order + // build negative options size + for (auto v = size_values.rbegin(); v != size_values.rend(); ++v) { + set_size_options_negative.emplace_back( + Saylink::Silent(fmt::format("#door edit {} -{}", set_size_action, *v), *v) + ); } c->Message( @@ -410,61 +276,49 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) fmt::format( "Name [{}] [{}] [{}] [{}]", door->GetDoorName(), - EQ::SayLinkEngine::GenerateQuestSaylink( - "#door save", - false, - "Save" - ), - EQ::SayLinkEngine::GenerateQuestSaylink( - "#door changemodelqueue", - false, - "Change Model" - ), - EQ::SayLinkEngine::GenerateQuestSaylink( - "#door setinclineinc", - false, - "Incline" - ) + Saylink::Silent("#door save", "Save"), + Saylink::Silent("#door changemodelqueue", "Change Model"), + Saylink::Silent("#door setinclineinc", "Incline") ).c_str() ); c->Message( Chat::White, fmt::format( "[{}] - [X] + [{}]", - implode(" | ", move_x_options_negative), - implode(" | ", move_x_options_positive) + Strings::Implode(" | ", move_x_options_negative), + Strings::Implode(" | ", move_x_options_positive) ).c_str() ); c->Message( Chat::White, fmt::format( "[{}] - [Y] + [{}]", - implode(" | ", move_y_options_negative), - implode(" | ", move_y_options_positive) + Strings::Implode(" | ", move_y_options_negative), + Strings::Implode(" | ", move_y_options_positive) ).c_str() ); c->Message( Chat::White, fmt::format( "[{}] - [Z] + [{}]", - implode(" | ", move_z_options_negative), - implode(" | ", move_z_options_positive) + Strings::Implode(" | ", move_z_options_negative), + Strings::Implode(" | ", move_z_options_positive) ).c_str() ); c->Message( Chat::White, fmt::format( "[{}] - [H] + [{}]", - implode(" | ", move_h_options_negative), - implode(" | ", move_h_options_positive) + Strings::Implode(" | ", move_h_options_negative), + Strings::Implode(" | ", move_h_options_positive) ).c_str() ); c->Message( Chat::White, fmt::format( "[{}] - [Size] + [{}]", - implode(" | ", set_size_options_negative), - implode(" | ", set_size_options_positive) + Strings::Implode(" | ", set_size_options_negative), + Strings::Implode(" | ", set_size_options_positive) ).c_str() ); @@ -476,7 +330,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) // create if (arg1 == "create") { - std::string model = str_toupper(arg2); + std::string model = Strings::ToUpper(arg2); uint16 entity_id = entity_list.CreateDoor( model.c_str(), c->GetPosition(), @@ -493,7 +347,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) // set model if (arg1 == "model") { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); - std::string model = str_toupper(arg2); + std::string model = Strings::ToUpper(arg2); if (door) { door->SetDoorName(model.c_str()); } @@ -505,14 +359,14 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) Chat::White, fmt::format( "#door model | Changes door model for selected door or select from [{}] or [{}]", - EQ::SayLinkEngine::GenerateQuestSaylink("#door showmodelszone", false, "local zone"), - EQ::SayLinkEngine::GenerateQuestSaylink("#door showmodelsglobal", false, "global") + Saylink::Silent("#door showmodelszone", "local zone"), + Saylink::Silent("#door showmodelsglobal", "global") ).c_str() ); } // open type - if (arg1 == "opentype" && !arg2.empty() && StringIsNumber(arg2)) { + if (arg1 == "opentype" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { door->SetOpenType(std::atoi(arg2.c_str())); @@ -520,15 +374,15 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) } // incline - if (arg1 == "setincline" && !arg2.empty() && StringIsNumber(arg2)) { + if (arg1 == "setincline" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { door->SetIncline(std::atoi(arg2.c_str())); } } - // incline - if (arg1 == "setinvertstate" && !arg2.empty() && StringIsNumber(arg2)) { + // invertstate + if (arg1 == "setinvertstate" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { door->SetInvertState(std::atoi(arg2.c_str())); @@ -545,12 +399,13 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) } // incline incremental - if (arg1 == "setinclineinc" && !arg2.empty() && StringIsNumber(arg2)) { + if (arg1 == "setinclineinc" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { door->SetIncline(door->GetIncline() + std::atoi(arg2.c_str())); } } + if (arg1 == "setinclineinc") { std::map incline_values = { {.01, "Upright"}, @@ -567,14 +422,13 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) std::vector incline_normal_options; std::vector incline_positive_options; std::vector incline_negative_options; - for (auto incline_value : incline_values) { + for (auto incline_value: incline_values) { incline_normal_options.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( fmt::format( "#door setincline {}", incline_value.first ), - false, incline_value.second ) ); @@ -583,12 +437,11 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) for (int incline_index = 0; incline_index <= 100; incline_index += 10) { int incline_value = (incline_index == 0 ? 1 : incline_index); incline_positive_options.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( fmt::format( "#door setinclineinc {}", incline_value ), - false, itoa(std::abs(incline_value)) ) ); @@ -597,12 +450,11 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) for (int incline_index = -100; incline_index <= 1; incline_index += 10) { int incline_value = (incline_index == 0 ? -1 : incline_index); incline_negative_options.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( fmt::format( "#door setinclineinc {}", incline_value ), - false, itoa(std::abs(incline_value)) ) ); @@ -612,7 +464,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) Chat::White, fmt::format( "[Incline] [{}]", - implode(" | ", incline_normal_options) + Strings::Implode(" | ", incline_normal_options) ).c_str() ); @@ -620,8 +472,8 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) Chat::White, fmt::format( "[Incline Increments] [{}] - | + [{}]", - implode(" | ", incline_negative_options), - implode(" | ", incline_positive_options) + Strings::Implode(" | ", incline_negative_options), + Strings::Implode(" | ", incline_positive_options) ).c_str() ); } @@ -680,6 +532,64 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) DisplayObjectResultToClient(c, game_objects); } + + // help menu + if (arg1.empty()) { + DoorManipulation::CommandHeader(c); + c->Message( + Chat::White, + "#door create | Creates a door from a model. (Example IT78 creates a campfire)" + ); + c->Message(Chat::White, "#door setinvertstate [0|1] | Sets selected door invert state"); + c->Message(Chat::White, "#door setincline | Sets selected door incline"); + c->Message(Chat::White, "#door opentype | Sets selected door opentype"); + c->Message( + Chat::White, + fmt::format( + "#door model | Changes door model for selected door or select from [{}] or [{}]", + Saylink::Silent("#door showmodelszone", "local zone"), + Saylink::Silent("#door showmodelsglobal", "global") + ).c_str() + ); + c->Message( + Chat::White, + "#door showmodelsfromfile | Shows models from s3d or eqg file. Example tssequip.eqg or wallet01.eqg" + ); + + c->Message( + Chat::White, + fmt::format( + "{} | Shows available models in the current zone that you are in", + Saylink::Silent("#door showmodelszone") + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "{} | Shows available models globally by first listing all global model files", + Saylink::Silent("#door showmodelsglobal") + ).c_str() + ); + + c->Message(Chat::White, "#door save | Creates database entry for selected door"); + c->Message( + Chat::White, + fmt::format( + "{} - Brings up editing interface for selected door", + Saylink::Silent("#door edit") + ).c_str() + ); + c->Message( + Chat::White, + fmt::format( + "{} - lists doors in zone", + Saylink::Silent("#list doors") + ).c_str() + ); + + return; + } } void DoorManipulation::CommandHeader(Client *c) @@ -700,9 +610,8 @@ void DoorManipulation::DisplayObjectResultToClient( say_links.emplace_back( fmt::format( "[{}] ", - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( fmt::format("#door model {}", g.object_name), - false, g.object_name ) ) @@ -733,7 +642,7 @@ void DoorManipulation::DisplayObjectResultToClient( } if (!buffered_links.empty()) { - c->Message(Chat::White, implode(" ", buffered_links).c_str()); + c->Message(Chat::White, Strings::Implode(" ", buffered_links).c_str()); } } @@ -748,9 +657,8 @@ void DoorManipulation::DisplayModelsFromFileResults( say_links.emplace_back( fmt::format( "[{}] ", - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( fmt::format("#door showmodelsfromfile {}", g.file_from), - false, g.file_from ) ) @@ -781,6 +689,6 @@ void DoorManipulation::DisplayModelsFromFileResults( } if (!buffered_links.empty()) { - c->Message(Chat::White, implode(" ", buffered_links).c_str()); + c->Message(Chat::White, Strings::Implode(" ", buffered_links).c_str()); } } diff --git a/zone/gm_commands/dye.cpp b/zone/gm_commands/dye.cpp index ecc04f7ca..195792f16 100755 --- a/zone/gm_commands/dye.cpp +++ b/zone/gm_commands/dye.cpp @@ -41,7 +41,7 @@ void command_dye(Client *c, const Seperator *sep) fmt::format( "{} {}", "Slots are as follows:", - implode(", ", slot_messages) + Strings::Implode(", ", slot_messages) ).c_str() ); return; diff --git a/zone/gm_commands/dz.cpp b/zone/gm_commands/dz.cpp index 506a203fb..cab117b6d 100755 --- a/zone/gm_commands/dz.cpp +++ b/zone/gm_commands/dz.cpp @@ -42,12 +42,19 @@ void command_dz(Client *c, const Seperator *sep) continue; } - auto leader_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto leader_saylink = Saylink::Silent( fmt::format( - "#goto {}", expedition->GetLeaderName()), false, expedition->GetLeaderName()); - auto zone_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + "#goto {}", + expedition->GetLeaderName() + ), + expedition->GetLeaderName() + ); + auto zone_saylink = Saylink::Silent( fmt::format( - "#zoneinstance {}", dz->GetInstanceID()), false, "zone" + "#zoneinstance {}", + dz->GetInstanceID() + ), + "zone" ); auto seconds = dz->GetSecondsRemaining(); @@ -123,8 +130,12 @@ void command_dz(Client *c, const Seperator *sep) for (const auto &dz : dynamic_zones) { auto seconds = dz->GetSecondsRemaining(); - auto zone_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#zoneinstance {}", dz->GetInstanceID()), false, "zone" + auto zone_saylink = Saylink::Silent( + fmt::format( + "#zoneinstance {}", + dz->GetInstanceID() + ), + "zone" ); std::string aligned_type = fmt::format( @@ -159,8 +170,12 @@ void command_dz(Client *c, const Seperator *sep) bool is_expired = now > expire_time; if (!is_expired || strcasecmp(sep->arg[2], "all") == 0) { - auto zone_saylink = is_expired ? "zone" : EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#zoneinstance {}", dz.instance), false, "zone" + auto zone_saylink = is_expired ? "zone" : Saylink::Silent( + fmt::format( + "#zoneinstance {}", + dz.instance + ), + "zone" ); c->Message( diff --git a/zone/gm_commands/editmassrespawn.cpp b/zone/gm_commands/editmassrespawn.cpp index 41fcc6613..32e29cd32 100755 --- a/zone/gm_commands/editmassrespawn.cpp +++ b/zone/gm_commands/editmassrespawn.cpp @@ -126,7 +126,7 @@ void command_editmassrespawn(Client *c, const Seperator *sep) c->Message( Chat::Yellow, "To apply these changes, click <%s> or type [%s]", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Apply").c_str(), + Saylink::Silent(saylink, "Apply").c_str(), saylink.c_str() ); } diff --git a/zone/gm_commands/emote.cpp b/zone/gm_commands/emote.cpp index 6deda54b5..f04e2fa3f 100755 --- a/zone/gm_commands/emote.cpp +++ b/zone/gm_commands/emote.cpp @@ -5,41 +5,53 @@ extern WorldServer worldserver; void command_emote(Client *c, const Seperator *sep) { - if (sep->arg[3][0] == 0) { - c->Message(Chat::White, "Usage: #emote [name | world | zone] type# message"); + auto arguments = sep->argnum; + if (arguments < 3 || !sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #emote [Name] [Type] [Message]"); + c->Message(Chat::White, "Usage: #emote world [Type] [Message]"); + c->Message(Chat::White, "Usage: #emote zone [Type] [Message]"); + return; } - else { - if (strcasecmp(sep->arg[1], "zone") == 0) { - char *newmessage = 0; - if (strstr(sep->arg[3], "^") == 0) { - entity_list.Message(0, atoi(sep->arg[2]), sep->argplus[3]); - } - else { - for (newmessage = strtok((char *) sep->arg[3], "^"); - newmessage != nullptr; - newmessage = strtok(nullptr, "^")) - entity_list.Message(0, atoi(sep->arg[2]), newmessage); - } + + if (!worldserver.Connected()) { + c->Message(Chat::White, "Error: World server disconnected!"); + return; + } + + bool is_world = !strcasecmp(sep->arg[1], "world"); + bool is_zone = !strcasecmp(sep->arg[1], "zone"); + + const std::string emote_message = sep->argplus[3]; + const auto emote_type = std::stoul(sep->arg[2]); + + if (is_zone) { + if (!Strings::Contains(emote_message, "^")) { + entity_list.Message(0, emote_type, emote_message.c_str()); + return; } - else if (!worldserver.Connected()) { - c->Message(Chat::White, "Error: World server disconnected"); + + for (const auto& m : Strings::Split(emote_message, "^")) { + entity_list.Message(0, emote_type, m.c_str()); } - else if (!strcasecmp(sep->arg[1], "world")) { + } else { + if (!Strings::Contains(emote_message, "^")) { worldserver.SendEmoteMessage( + is_world ? 0 : sep->arg[1], 0, - 0, - atoi(sep->arg[2]), - sep->argplus[3] + emote_type, + emote_message.c_str() ); + return; } - else { + + for (const auto& m : Strings::Split(emote_message, "^")) { worldserver.SendEmoteMessage( - sep->arg[1], + is_world ? 0 : sep->arg[1], 0, - atoi(sep->arg[2]), - sep->argplus[3] + emote_type, + m.c_str() ); - } + } } } diff --git a/zone/gm_commands/emotesearch.cpp b/zone/gm_commands/emotesearch.cpp index 40d5bfac6..5b8e9d09e 100755 --- a/zone/gm_commands/emotesearch.cpp +++ b/zone/gm_commands/emotesearch.cpp @@ -2,77 +2,141 @@ void command_emotesearch(Client *c, const Seperator *sep) { - if (sep->arg[1][0] == 0) { - c->Message(Chat::White, "Usage: #emotesearch [search string or emoteid]"); + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #emotesearch [Emote ID]"); + c->Message(Chat::White, "Usage: #emotesearch [Search Crteria]"); + return; } - else { - const char *search_criteria = sep->argplus[1]; - int count = 0; - if (Seperator::IsNumber(search_criteria)) { - uint16 emoteid = atoi(search_criteria); - LinkedListIterator iterator(zone->NPCEmoteList); - iterator.Reset(); - while (iterator.MoreElements()) { - NPC_Emote_Struct *nes = iterator.GetData(); - if (emoteid == nes->emoteid) { - c->Message( - Chat::White, - "EmoteID: %i Event: %i Type: %i Text: %s", - nes->emoteid, - nes->event_, - nes->type, - nes->text - ); - count++; - } - iterator.Advance(); + auto emote_count = 0; + auto emote_number = 1; + + std::string search_criteria = sep->argplus[1]; + bool found_by_id = false; + + if (!sep->IsNumber(1)) { + LinkedListIterator iterator(zone->NPCEmoteList); + iterator.Reset(); + while (iterator.MoreElements()) { + auto &e = iterator.GetData(); + auto current_text = Strings::ToLower(e->text); + + if (Strings::Contains(current_text, Strings::ToLower(search_criteria))) { + c->Message( + Chat::White, + fmt::format( + "Emote {} | Emote ID: {}", + emote_number, + e->emoteid + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Emote {} | Event: {} ({}) Type: {} ({})", + emote_number, + EQ::constants::GetEmoteEventTypeName(e->event_), + e->event_, + EQ::constants::GetEmoteTypeName(e->type), + e->type + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Emote {} | Text: {}", + emote_number, + e->text + ).c_str() + ); + + emote_count++; + emote_number++; } - if (count == 0) { - c->Message(Chat::White, "No emotes found."); - } - else { - c->Message(Chat::White, "%i emote(s) found", count); + + if (emote_count == 50) { + break; } + + iterator.Advance(); } - else { - char sText[64]; - char sCriteria[515]; - strn0cpy(sCriteria, search_criteria, sizeof(sCriteria)); - strupr(sCriteria); - char *pdest; + } else { + auto emote_id = std::stoul(search_criteria); + + LinkedListIterator iterator(zone->NPCEmoteList); + iterator.Reset(); + while (iterator.MoreElements()) { + auto &e = iterator.GetData(); + if (emote_id == e->emoteid) { + found_by_id = true; - LinkedListIterator iterator(zone->NPCEmoteList); - iterator.Reset(); - while (iterator.MoreElements()) { - NPC_Emote_Struct *nes = iterator.GetData(); - strn0cpy(sText, nes->text, sizeof(sText)); - strupr(sText); - pdest = strstr(sText, sCriteria); - if (pdest != nullptr) { - c->Message( - Chat::White, - "EmoteID: %i Event: %i Type: %i Text: %s", - nes->emoteid, - nes->event_, - nes->type, - nes->text - ); - count++; - } - if (count == 50) { - break; - } + c->Message( + Chat::White, + fmt::format( + "Emote {} | Event: {} ({}) Type: {} ({})", + emote_number, + EQ::constants::GetEmoteEventTypeName(e->event_), + e->event_, + EQ::constants::GetEmoteTypeName(e->type), + e->type + ).c_str() + ); - iterator.Advance(); + c->Message( + Chat::White, + fmt::format( + "Emote {} | Text: {}", + emote_number, + e->text + ).c_str() + ); + + emote_count++; + emote_number++; } - if (count == 50) { - c->Message(Chat::White, "50 emotes shown...too many results."); - } - else { - c->Message(Chat::White, "%i emote(s) found", count); + + if (emote_count == 50) { + break; } + + iterator.Advance(); } } + + auto found_string = ( + found_by_id ? + fmt::format("ID {}", search_criteria) : + search_criteria + ); + + if (!emote_count) { + c->Message( + Chat::White, + fmt::format( + "No Emotes found matching {}.", + found_string + ).c_str() + ); + } else if (emote_count == 50) { + c->Message( + Chat::White, + fmt::format( + "50 Emotes shown matching {}, too many results.", + found_string + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "{} Emote{} found matching {}.", + emote_count, + emote_count != 1 ? "s" : "", + found_string + ).c_str() + ); + } } - diff --git a/zone/gm_commands/emoteview.cpp b/zone/gm_commands/emoteview.cpp index afbec21aa..c1116f026 100755 --- a/zone/gm_commands/emoteview.cpp +++ b/zone/gm_commands/emoteview.cpp @@ -3,37 +3,70 @@ void command_emoteview(Client *c, const Seperator *sep) { if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { - c->Message(Chat::White, "You must target a NPC to view their emotes."); + c->Message(Chat::White, "You must target an NPC to view their emotes."); return; } - if (c->GetTarget() && c->GetTarget()->IsNPC()) { - int count = 0; - int emoteid = c->GetTarget()->CastToNPC()->GetEmoteID(); + auto target = c->GetTarget()->CastToNPC(); - LinkedListIterator iterator(zone->NPCEmoteList); - iterator.Reset(); - while (iterator.MoreElements()) { - NPC_Emote_Struct *nes = iterator.GetData(); - if (emoteid == nes->emoteid) { - c->Message( - Chat::White, - "EmoteID: %i Event: %i Type: %i Text: %s", - nes->emoteid, - nes->event_, - nes->type, - nes->text - ); - count++; - } - iterator.Advance(); - } - if (count == 0) { - c->Message(Chat::White, "No emotes found."); - } - else { - c->Message(Chat::White, "%i emote(s) found", count); + auto emote_count = 0; + auto emote_id = target->GetEmoteID(); + + auto emote_number = 1; + + LinkedListIterator iterator(zone->NPCEmoteList); + iterator.Reset(); + while (iterator.MoreElements()) { + auto &e = iterator.GetData(); + if (emote_id == e->emoteid) { + c->Message( + Chat::White, + fmt::format( + "Emote {} | Event: {} ({}) Type: {} ({})", + emote_number, + EQ::constants::GetEmoteEventTypeName(e->event_), + e->event_, + EQ::constants::GetEmoteTypeName(e->type), + e->type + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Emote {} | Text: {}", + emote_number, + e->text + ).c_str() + ); + + emote_count++; + emote_number++; } + + iterator.Advance(); } -} + if (!emote_count) { + c->Message( + Chat::White, + fmt::format( + "{} has no emotes on Emote ID {}.", + c->GetTargetDescription(target), + emote_id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "{} has {} emote{} on Emote ID {}.", + c->GetTargetDescription(target), + emote_count, + emote_count != 1 ? "s" : "", + emote_id + ).c_str() + ); +} diff --git a/zone/gm_commands/emptyinventory.cpp b/zone/gm_commands/emptyinventory.cpp new file mode 100644 index 000000000..582512289 --- /dev/null +++ b/zone/gm_commands/emptyinventory.cpp @@ -0,0 +1,54 @@ +#include "../client.h" + +void command_emptyinventory(Client *c, const Seperator *sep) +{ + auto target = c; + if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) { + target = c->GetTarget()->CastToClient(); + } + + EQ::ItemInstance *item = nullptr; + static const int16 slots[][2] = { + { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, + { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, + { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, + { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, + { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, + { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, + { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, + }; + int removed_count = 0; + const size_t size = sizeof(slots) / sizeof(slots[0]); + for (int slot_index = 0; slot_index < size; ++slot_index) { + for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { + item = target->GetInv().GetItem(slot_id); + if (item) { + int stack_size = std::max(static_cast(item->GetCharges()), 1); + removed_count += stack_size; + target->DeleteItemInInventory(slot_id, 0, true); + } + } + } + + if (!removed_count) { + c->Message( + Chat::White, + fmt::format( + "{} {} no items to delete.", + c->GetTargetDescription(target, TargetDescriptionType::UCYou), + c == target ? "have" : "has" + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Inventory cleared for {}, {} item{} deleted.", + c->GetTargetDescription(target), + removed_count, + removed_count != 1 ? "s" : "" + ).c_str() + ); +} \ No newline at end of file diff --git a/zone/gm_commands/exptoggle.cpp b/zone/gm_commands/exptoggle.cpp new file mode 100644 index 000000000..b267b4f7e --- /dev/null +++ b/zone/gm_commands/exptoggle.cpp @@ -0,0 +1,28 @@ +#include "../client.h" + +void command_exptoggle(Client *c, const Seperator *sep) +{ + auto arguments = sep->argnum; + if (!arguments || arguments > 1) { + c->Message(Chat::White, "Usage: #exptoggle [Toggle] - Toggle your or your target's experience gain."); + return; + } + + auto t = c; + if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { + t = c->GetTarget()->CastToClient(); + } + + const auto is_exp_enabled = Strings::ToBool(sep->arg[1]); + + t->SetEXPEnabled(is_exp_enabled); + + c->Message( + Chat::White, + fmt::format( + "Experience gain for {} is now {}abled.", + c->GetTargetDescription(t, TargetDescriptionType::LCSelf), + is_exp_enabled ? "en" : "dis" + ).c_str() + ); +} diff --git a/zone/gm_commands/faction.cpp b/zone/gm_commands/faction.cpp index 43aec7904..87a8ef5aa 100755 --- a/zone/gm_commands/faction.cpp +++ b/zone/gm_commands/faction.cpp @@ -18,7 +18,7 @@ void command_faction(Client *c, const Seperator *sep) std::string faction_filter; if (sep->arg[2]) { - faction_filter = str_tolower(sep->arg[2]); + faction_filter = Strings::ToLower(sep->arg[2]); } if (!strcasecmp(sep->arg[1], "review")) { @@ -56,9 +56,8 @@ void command_faction(Client *c, const Seperator *sep) auto faction_id = std::stoul(row[0]); std::string faction_name = row[1]; std::string faction_value = row[2]; - std::string reset_link = EQ::SayLinkEngine::GenerateQuestSaylink( + std::string reset_link = Saylink::Silent( fmt::format("#faction reset {}", faction_id), - false, "Reset" ); diff --git a/zone/gm_commands/faction_association.cpp b/zone/gm_commands/faction_association.cpp new file mode 100644 index 000000000..47410f248 --- /dev/null +++ b/zone/gm_commands/faction_association.cpp @@ -0,0 +1,18 @@ +#include "../client.h" + +void command_faction_association(Client *c, const Seperator *sep) +{ + if (sep->argnum < 2 || !sep->IsNumber(1) || !sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #factionassociation "); + c->Message(Chat::White, " Defaults to self, unless target is also a client."); + return; + } + + // default to self unless target is also a client + auto target = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + target = c->GetTarget()->CastToClient(); + } + + target->RewardFaction(atoi(sep->arg[1]), atoi(sep->arg[2])); +} diff --git a/zone/gm_commands/feature.cpp b/zone/gm_commands/feature.cpp index 83d0adb1c..55b6648d9 100644 --- a/zone/gm_commands/feature.cpp +++ b/zone/gm_commands/feature.cpp @@ -2,13 +2,14 @@ void command_feature(Client *c, const Seperator *sep) { + // nested command aliasing + std::string command = sep->arg[0] ? sep->arg[0] : ""; + bool is_size_alias = sep->arg[0] && Strings::Contains(command, "#size"); + bool is_nested_alias = (is_size_alias); + int arguments = sep->argnum; - if (arguments < 2 || !sep->IsNumber(2)) { - auto feature_save_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#npcedit featuresave", - false, - "#npcedit featuresave" - ); + if ((arguments < 2 || !sep->IsNumber(2)) && !is_nested_alias) { + auto feature_save_link = Saylink::Silent("#npcedit featuresave"); c->Message(Chat::White, "Usage: #feature beard [Beard] - Change your or your target's Beard"); c->Message(Chat::White, "Usage: #feature beardcolor [Beard Color] - Change your or your target's Beard Color"); @@ -47,7 +48,7 @@ void command_feature(Client *c, const Seperator *sep) bool is_helm = !strcasecmp(sep->arg[1], "helm"); bool is_heritage = !strcasecmp(sep->arg[1], "heritage"); bool is_race = !strcasecmp(sep->arg[1], "race"); - bool is_size = !strcasecmp(sep->arg[1], "size"); + bool is_size = !strcasecmp(sep->arg[1], "size") || is_size_alias; bool is_tattoo = !strcasecmp(sep->arg[1], "tattoo"); bool is_texture = !strcasecmp(sep->arg[1], "texture"); @@ -67,11 +68,7 @@ void command_feature(Client *c, const Seperator *sep) !is_tattoo && !is_texture ) { - auto feature_save_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#npcedit featuresave", - false, - "#npcedit featuresave" - ); + auto feature_save_link = Saylink::Silent("#npcedit featuresave"); c->Message(Chat::White, "Usage: #feature beard [Beard] - Change your or your target's Beard"); c->Message(Chat::White, "Usage: #feature beardcolor [Beard Color] - Change your or your target's Beard Color"); @@ -173,7 +170,16 @@ void command_feature(Client *c, const Seperator *sep) feature_changed = "Race"; value_changed = race; } else if (is_size) { - size = std::stof(sep->arg[2]); + // handle aliased input + if (is_size_alias) { + c->Message(Chat::White, "Usage: #feature size [Size] - Change your or your target's Size temporarily (Valid values are 0 to 255, decimal increments are allowed.)"); + if (sep->arg[1] && Strings::IsFloat(sep->arg[1])) { + size = std::stof(sep->arg[1]); + } + } + else { + size = std::stof(sep->arg[2]); + } if (size < 0 || size > 255) { c->Message(Chat::White, "Usage: #feature size [Size] - Change your or your target's Size temporarily (Valid values are 0 to 255, decimal increments are allowed.)"); diff --git a/zone/gm_commands/findaa.cpp b/zone/gm_commands/findaa.cpp new file mode 100755 index 000000000..c5d15437c --- /dev/null +++ b/zone/gm_commands/findaa.cpp @@ -0,0 +1,100 @@ +#include "../client.h" + +void command_findaa(Client *c, const Seperator *sep) +{ + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Command Syntax: #findaa [Search Criteria]"); + return; + } + + if (sep->IsNumber(1)) { + int aa_id = std::stoi(sep->arg[1]); + auto aa_name = zone->GetAAName(aa_id); + if (!aa_name.empty()) { + c->Message( + Chat::White, + fmt::format( + "AA {}: {}", + aa_id, + aa_name + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "AA ID {} was not found.", + aa_id + ).c_str() + ); + } + } else { + const auto search_criteria = Strings::ToLower(sep->argplus[1]); + if (!search_criteria.empty()) { + std::map ordered_aas; + + for (const auto& a : zone->aa_abilities) { + ordered_aas[a.second.get()->id] = a.second.get()->name; + } + + int found_count = 0; + for (const auto& a : ordered_aas) { + auto aa_name = zone->GetAAName(a.first); + if (!aa_name.empty()) { + auto aa_name_lower = Strings::ToLower(aa_name); + if (aa_name_lower.find(search_criteria) == std::string::npos) { + continue; + } + + c->Message( + Chat::White, + fmt::format( + "AA {}: {}", + a.first, + aa_name + ).c_str() + ); + found_count++; + + if (found_count == 50) { + break; + } + } + } + + if (!found_count) { + c->Message( + Chat::White, + fmt::format( + "No AAs were found matching '{}'.", + search_criteria + ).c_str() + ); + return; + } + + if (found_count == 50) { + c->Message( + Chat::White, + fmt::format( + "50 AAs were found matching '{}', max reached.", + search_criteria + ).c_str() + ); + } else { + auto skill_message = found_count == 1 ? "An AA was" : fmt::format("{} AAs were", found_count); + + c->Message( + Chat::White, + fmt::format( + "{} found matching '{}'.", + skill_message, + search_criteria + ).c_str() + ); + } + } + } +} + diff --git a/zone/gm_commands/findcharacter.cpp b/zone/gm_commands/findcharacter.cpp new file mode 100755 index 000000000..811978af5 --- /dev/null +++ b/zone/gm_commands/findcharacter.cpp @@ -0,0 +1,93 @@ +#include "../client.h" +#include "../../common/repositories/character_data_repository.h" + +void command_findcharacter(Client *c, const Seperator *sep) +{ + const auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #findcharacter [Search Criteria]"); + return; + } + + if (sep->IsNumber(1)) { + const auto character_id = std::stoul(sep->arg[1]); + + const auto& e = CharacterDataRepository::FindOne(content_db, character_id); + if (!e.id) { + c->Message( + Chat::White, + fmt::format( + "Character ID {} does not exist or is invalid.", + character_id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Character ID {} | {}", + character_id, + e.name + ).c_str() + ); + } else { + const auto search_criteria = Strings::ToLower(sep->argplus[1]); + const auto& l = CharacterDataRepository::GetWhere( + content_db, + fmt::format( + "LOWER(`name`) LIKE '%%{}%%'", + search_criteria + ).c_str() + ); + if (l.empty()) { + c->Message( + Chat::White, + fmt::format( + "No characters found matching '{}'.", + sep->argplus[1] + ).c_str() + ); + } + + auto found_count = 0; + for (const auto& e : l) { + c->Message( + Chat::White, + fmt::format( + "Character ID {} | {}", + e.id, + e.name + ).c_str() + ); + + found_count++; + + if (found_count == 50) { + break; + } + } + + if (found_count == 50) { + c->Message( + Chat::White, + fmt::format( + "50 Characters found matching '{}', max reached.", + sep->argplus[1] + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "{} Character{} found matching '{}'.", + found_count, + found_count != 1 ? "s" : "", + sep->argplus[1] + ).c_str() + ); + } + } +} + diff --git a/zone/gm_commands/findclass.cpp b/zone/gm_commands/findclass.cpp index a220f5ded..62e484e81 100755 --- a/zone/gm_commands/findclass.cpp +++ b/zone/gm_commands/findclass.cpp @@ -3,22 +3,29 @@ void command_findclass(Client *c, const Seperator *sep) { int arguments = sep->argnum; - - if (arguments == 0) { - c->Message(Chat::White, "Command Syntax: #findclass [search criteria]"); + if (!arguments) { + c->Message(Chat::White, "Command Syntax: #findclass [Search Criteria]"); return; } if (sep->IsNumber(1)) { int class_id = std::stoi(sep->arg[1]); - if (class_id >= WARRIOR && class_id <= MERCERNARY_MASTER) { + if (class_id >= WARRIOR && class_id <= MERCENARY_MASTER) { std::string class_name = GetClassIDName(class_id); c->Message( Chat::White, fmt::format( - "Class {}: {}", + "Class {} | {}{}", class_id, - class_name + class_name, + ( + c->IsPlayerClass(class_id) ? + fmt::format( + " ({})", + GetPlayerClassBit(class_id) + ) : + "" + ) ).c_str() ); } @@ -31,51 +38,52 @@ void command_findclass(Client *c, const Seperator *sep) ).c_str() ); } - } - else { - std::string search_criteria = str_tolower(sep->argplus[1]); - int found_count = 0; - for (int class_id = WARRIOR; class_id <= MERCERNARY_MASTER; class_id++) { - std::string class_name = GetClassIDName(class_id); - std::string class_name_lower = str_tolower(class_name); - if (search_criteria.length() > 0 && class_name_lower.find(search_criteria) == std::string::npos) { + } else { + auto search_criteria = Strings::ToLower(sep->argplus[1]); + int found_count = 0; + for (uint16 class_id = WARRIOR; class_id <= MERCENARY_MASTER; class_id++) { + std::string class_name = GetClassIDName(class_id); + auto class_name_lower = Strings::ToLower(class_name); + if ( + search_criteria.length() && + class_name_lower.find(search_criteria) == std::string::npos + ) { continue; } c->Message( Chat::White, fmt::format( - "Class {}: {}", + "Class {} | {}{}", class_id, - class_name + class_name, + ( + c->IsPlayerClass(class_id) ? + fmt::format( + " ({})", + GetPlayerClassBit(class_id) + ) : + "" + ) ).c_str() ); + found_count++; - if (found_count == 20) { + if (found_count == 50) { break; } } - if (found_count == 20) { - c->Message(Chat::White, "20 Classes found... max reached."); - } - else { - auto class_message = ( - found_count > 0 ? - ( - found_count == 1 ? - "A Class was" : - fmt::format("{} Classes were", found_count) - ) : - "No Classes were" - ); - + if (found_count == 50) { + c->Message(Chat::White, "50 Classes found, max reached."); + } else { c->Message( Chat::White, fmt::format( - "{} found.", - class_message + "{} Class{} found.", + found_count, + found_count != 1 ? "es" : "" ).c_str() ); } diff --git a/zone/gm_commands/findfaction.cpp b/zone/gm_commands/findfaction.cpp index 29b72f441..8038a2e00 100755 --- a/zone/gm_commands/findfaction.cpp +++ b/zone/gm_commands/findfaction.cpp @@ -33,12 +33,12 @@ void command_findfaction(Client *c, const Seperator *sep) } } else { - std::string search_criteria = str_tolower(sep->argplus[1]); + std::string search_criteria = Strings::ToLower(sep->argplus[1]); int found_count = 0; int max_faction_id = content_db.GetMaxFaction(); for (int faction_id = 0; faction_id < max_faction_id; faction_id++) { std::string faction_name = content_db.GetFactionName(faction_id); - std::string faction_name_lower = str_tolower(faction_name); + std::string faction_name_lower = Strings::ToLower(faction_name); if (faction_name.empty()) { continue; } diff --git a/zone/gm_commands/findrace.cpp b/zone/gm_commands/findrace.cpp index 413687160..6e02a7041 100755 --- a/zone/gm_commands/findrace.cpp +++ b/zone/gm_commands/findrace.cpp @@ -3,26 +3,35 @@ void command_findrace(Client *c, const Seperator *sep) { int arguments = sep->argnum; - - if (arguments == 0) { - c->Message(Chat::White, "Command Syntax: #findrace [search criteria]"); + if (!arguments) { + c->Message(Chat::White, "Command Syntax: #findrace [Search Criteria]"); return; } if (sep->IsNumber(1)) { - int race_id = std::stoi(sep->arg[1]); + auto race_id = static_cast(std::stoul(sep->arg[1])); std::string race_name = GetRaceIDName(race_id); - if (race_id >= RACE_HUMAN_1 && race_id <= RACE_PEGASUS_732) { + if ( + race_id >= RACE_HUMAN_1 && + race_id <= RACE_PEGASUS_732 + ) { c->Message( Chat::White, fmt::format( - "Race {}: {}", + "Race {} | {}{}", race_id, - race_name + race_name, + ( + c->IsPlayerRace(race_id) ? + fmt::format( + " ({})", + GetPlayerRaceBit(race_id) + ) : + "" + ) ).c_str() ); - } - else { + } else { c->Message( Chat::White, fmt::format( @@ -31,51 +40,52 @@ void command_findrace(Client *c, const Seperator *sep) ).c_str() ); } - } - else { - std::string search_criteria = str_tolower(sep->argplus[1]); - int found_count = 0; - for (int race_id = RACE_HUMAN_1; race_id <= RACE_PEGASUS_732; race_id++) { - std::string race_name = GetRaceIDName(race_id); - std::string race_name_lower = str_tolower(race_name); - if (search_criteria.length() > 0 && race_name_lower.find(search_criteria) == std::string::npos) { + } else { + auto search_criteria = Strings::ToLower(sep->argplus[1]); + int found_count = 0; + for (uint16 race_id = RACE_HUMAN_1; race_id <= RACE_PEGASUS_732; race_id++) { + std::string race_name = GetRaceIDName(race_id); + auto race_name_lower = Strings::ToLower(race_name); + if ( + search_criteria.length() && + race_name_lower.find(search_criteria) == std::string::npos + ) { continue; } c->Message( Chat::White, fmt::format( - "Race {}: {}", + "Race {} | {}{}", race_id, - race_name + race_name, + ( + c->IsPlayerRace(race_id) ? + fmt::format( + " ({})", + GetPlayerRaceBit(race_id) + ) : + "" + ) ).c_str() ); + found_count++; - if (found_count == 20) { + if (found_count == 50) { break; } } - if (found_count == 20) { - c->Message(Chat::White, "20 Races found... max reached."); - } - else { - auto race_message = ( - found_count > 0 ? - ( - found_count == 1 ? - "A Race was" : - fmt::format("{} Races were", found_count) - ) : - "No Races were" - ); - + if (found_count == 50) { + c->Message(Chat::White, "50 Races found, max reached."); + } else { c->Message( Chat::White, fmt::format( - "{} found.", - race_message + "{} Race{} found.", + found_count, + found_count != 1 ? "s" : "" ).c_str() ); } diff --git a/zone/gm_commands/findrecipe.cpp b/zone/gm_commands/findrecipe.cpp new file mode 100755 index 000000000..fdcdb9169 --- /dev/null +++ b/zone/gm_commands/findrecipe.cpp @@ -0,0 +1,96 @@ +#include "../client.h" +#include "../command.h" +#include "../../common/repositories/tradeskill_recipe_repository.h" + +void command_findrecipe(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Command Syntax: #findrecipe [Search Criteria]"); + return; + } + + if (sep->IsNumber(1)) { + auto recipe_id = static_cast(std::stoul(sep->arg[1])); + auto r = TradeskillRecipeRepository::GetWhere( + database, + fmt::format("id = {}", recipe_id) + ); + + if (r.empty() || !r[0].id) { + c->Message( + Chat::White, + fmt::format( + "Recipe ID {} could not be found.", + Strings::Commify(std::to_string(recipe_id)) + ).c_str() + ); + return; + } + + bool can_view_recipes = c->Admin() >= GetCommandStatus(c, "viewrecipe"); + + c->Message( + Chat::White, + fmt::format( + "Recipe {} | {}{}", + Strings::Commify(std::to_string(recipe_id)), + r[0].name, + can_view_recipes ? fmt::format(" | {}", Saylink::Silent(fmt::format("#viewrecipe {}", r[0].id), "View")) : "" + ).c_str() + ); + } else { + auto search_criteria = Strings::ToLower(sep->argplus[1]); + int found_count = 0; + + auto rl = TradeskillRecipeRepository::GetWhere( + database, + fmt::format("`name` LIKE '%{}%' ORDER BY `id` ASC", search_criteria) + ); + + if (rl.empty() || !rl[0].id) { + c->Message( + Chat::White, + fmt::format( + "No recipes were found matching '{}'.", + search_criteria + ).c_str() + ); + return; + } + + bool can_view_recipes = c->Admin() >= GetCommandStatus(c, "viewrecipe"); + + for (const auto& r : rl) { + c->Message( + Chat::White, + fmt::format( + "Recipe {} | {}{}", + Strings::Commify(std::to_string(r.id)), + r.name, + can_view_recipes ? fmt::format(" | {}", Saylink::Silent(fmt::format("#viewrecipe {}", r.id), "View")) : "" + ).c_str() + ); + + if (found_count == 50) { + break; + } + + found_count++; + } + + if (found_count == 50) { + c->Message(Chat::White, "50 Recipes found, max reached."); + } else { + c->Message( + Chat::White, + fmt::format( + "{} Recipe{} found.", + found_count, + found_count != 1 ? "s" : "" + ).c_str() + ); + } + } +} + diff --git a/zone/gm_commands/findskill.cpp b/zone/gm_commands/findskill.cpp index b26ad3ab1..5c9a3b50e 100755 --- a/zone/gm_commands/findskill.cpp +++ b/zone/gm_commands/findskill.cpp @@ -38,11 +38,11 @@ void command_findskill(Client *c, const Seperator *sep) } } else { - std::string search_criteria = str_tolower(sep->argplus[1]); + std::string search_criteria = Strings::ToLower(sep->argplus[1]); if (!search_criteria.empty()) { int found_count = 0; for (auto skill : skills) { - std::string skill_name_lower = str_tolower(skill.second); + std::string skill_name_lower = Strings::ToLower(skill.second); if (skill_name_lower.find(search_criteria) == std::string::npos) { continue; } diff --git a/zone/gm_commands/findspell.cpp b/zone/gm_commands/findspell.cpp index 78374a224..0585bda1c 100755 --- a/zone/gm_commands/findspell.cpp +++ b/zone/gm_commands/findspell.cpp @@ -37,13 +37,13 @@ void command_findspell(Client *c, const Seperator *sep) } } else { - std::string search_criteria = str_tolower(sep->argplus[1]); + std::string search_criteria = Strings::ToLower(sep->argplus[1]); int found_count = 0; for (int spell_id = 0; spell_id < SPDAT_RECORDS; spell_id++) { auto current_spell = spells[spell_id]; if (current_spell.name[0] != 0) { std::string spell_name = current_spell.name; - std::string spell_name_lower = str_tolower(spell_name); + std::string spell_name_lower = Strings::ToLower(spell_name); if (search_criteria.length() > 0 && spell_name_lower.find(search_criteria) == std::string::npos) { continue; } diff --git a/zone/gm_commands/findtask.cpp b/zone/gm_commands/findtask.cpp index 5edf0dcde..a643b28a3 100755 --- a/zone/gm_commands/findtask.cpp +++ b/zone/gm_commands/findtask.cpp @@ -13,31 +13,32 @@ void command_findtask(Client *c, const Seperator *sep) if (sep->IsNumber(1)) { auto task_id = std::stoul(sep->arg[1]); auto task_name = task_manager->GetTaskName(task_id); - auto task_message = ( + + std::string task_message = ( !task_name.empty() ? fmt::format( "Task {}: {}", task_id, task_name - ).c_str() : + ) : fmt::format( "Task ID {} was not found.", task_id - ).c_str() + ) ); c->Message( Chat::White, - task_message + task_message.c_str() ); } else { - std::string search_criteria = str_tolower(sep->argplus[1]); + std::string search_criteria = Strings::ToLower(sep->argplus[1]); if (!search_criteria.empty()) { - int found_count = 0; - for (uint32 task_id = 1; task_id <= MAXTASKS; task_id++) { - auto task_name = task_manager->GetTaskName(task_id); - std::string task_name_lower = str_tolower(task_name); + int found_count = 0; + for (const auto &task: task_manager->GetTaskData()) { + auto task_name = task.second.title; + std::string task_name_lower = Strings::ToLower(task_name); if (task_name_lower.find(search_criteria) == std::string::npos) { continue; } @@ -46,7 +47,7 @@ void command_findtask(Client *c, const Seperator *sep) Chat::White, fmt::format( "Task {}: {}", - task_id, + task.first, task_name ).c_str() ); diff --git a/zone/gm_commands/findzone.cpp b/zone/gm_commands/findzone.cpp index 53dacc52d..c80346159 100755 --- a/zone/gm_commands/findzone.cpp +++ b/zone/gm_commands/findzone.cpp @@ -27,8 +27,8 @@ void command_findzone(Client *c, const Seperator *sep) if (id == 0) { query = fmt::format( "SELECT zoneidnumber, short_name, long_name, version FROM zone WHERE long_name LIKE '%{}%' OR `short_name` LIKE '%{}%'", - EscapeString(sep->arg[1]), - EscapeString(sep->arg[1]) + Strings::Escape(sep->arg[1]), + Strings::Escape(sep->arg[1]) ); } else { @@ -60,10 +60,13 @@ void command_findzone(Client *c, const Seperator *sep) break; } - std::string command_zone = EQ::SayLinkEngine::GenerateQuestSaylink("#zone " + short_name, false, "zone"); - std::string command_gmzone = EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#gmzone {} {}", short_name, version), - false, + std::string command_zone = Saylink::Silent("#zone " + short_name, "zone"); + std::string command_gmzone = Saylink::Silent( + fmt::format( + "#gmzone {} {}", + short_name, + version + ), "gmzone" ); diff --git a/zone/gm_commands/flagedit.cpp b/zone/gm_commands/flagedit.cpp index af87b7df6..85d76392a 100755 --- a/zone/gm_commands/flagedit.cpp +++ b/zone/gm_commands/flagedit.cpp @@ -4,7 +4,7 @@ void command_flagedit(Client *c, const Seperator *sep) { int arguments = sep->argnum; if (!arguments) { - auto flags_link = EQ::SayLinkEngine::GenerateQuestSaylink("#flags", false, "#flags"); + auto flags_link = Saylink::Silent("#flags"); c->Message( Chat::White, "Usage: #flagedit lock [Zone ID|Zone Short Name] [Flag Name] - Set the specified flag name on the zone, locking the zone" @@ -48,7 +48,7 @@ void command_flagedit(Client *c, const Seperator *sep) !is_take && !is_unlock ) { - auto flags_link = EQ::SayLinkEngine::GenerateQuestSaylink("#flags", false, "#flags"); + auto flags_link = Saylink::Silent("#flags"); c->Message( Chat::White, "Usage: #flagedit lock [Zone ID|Zone Short Name] [Flag Name] - Set the specified flag name on the zone, locking the zone" @@ -85,7 +85,7 @@ void command_flagedit(Client *c, const Seperator *sep) std::stoul(sep->arg[2]) : ZoneID(sep->arg[2]) ); - std::string zone_short_name = str_tolower(ZoneName(zone_id, true)); + std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; if (zone_id && !is_unknown_zone) { std::string zone_long_name = ZoneLongName(zone_id); @@ -120,7 +120,7 @@ void command_flagedit(Client *c, const Seperator *sep) } std::string popup_text = ""; - + popup_text += ""; for (auto row : results) { @@ -154,7 +154,7 @@ void command_flagedit(Client *c, const Seperator *sep) std::stoul(sep->arg[2]) : ZoneID(sep->arg[2]) ); - std::string zone_short_name = str_tolower(ZoneName(zone_id, true)); + std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; if (zone_id && !is_unknown_zone) { if (arguments < 3) { @@ -164,8 +164,8 @@ void command_flagedit(Client *c, const Seperator *sep) ); return; } - - std::string flag_name = EscapeString(sep->argplus[3]); + + std::string flag_name = Strings::Escape(sep->argplus[3]); std::string zone_long_name = ZoneLongName(zone_id); auto query = fmt::format( @@ -209,7 +209,7 @@ void command_flagedit(Client *c, const Seperator *sep) std::stoul(sep->arg[2]) : ZoneID(sep->arg[2]) ); - std::string zone_short_name = str_tolower(ZoneName(zone_id, true)); + std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; if (zone_id && !is_unknown_zone) { std::string zone_long_name = ZoneLongName(zone_id); @@ -237,7 +237,7 @@ void command_flagedit(Client *c, const Seperator *sep) std::stoul(sep->arg[2]) : ZoneID(sep->arg[2]) ); - std::string zone_short_name = str_tolower(ZoneName(zone_id, true)); + std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; if (zone_id && !is_unknown_zone) { std::string zone_long_name = ZoneLongName(zone_id); diff --git a/zone/gm_commands/flymode.cpp b/zone/gm_commands/flymode.cpp index 58dcf0c7b..591977939 100755 --- a/zone/gm_commands/flymode.cpp +++ b/zone/gm_commands/flymode.cpp @@ -1,4 +1,5 @@ #include "../client.h" +#include "../../common/data_verification.h" void command_flymode(Client *c, const Seperator *sep) { @@ -13,10 +14,7 @@ void command_flymode(Client *c, const Seperator *sep) } auto flymode_id = std::stoul(sep->arg[1]); - if ( - flymode_id < EQ::constants::GravityBehavior::Ground && - flymode_id > EQ::constants::GravityBehavior::LevitateWhileRunning - ) { + if (!EQ::ValueWithin(flymode_id, EQ::constants::GravityBehavior::Ground, EQ::constants::GravityBehavior::LevitateWhileRunning)) { c->Message(Chat::White, "Usage:: #flymode [Flymode ID]"); c->Message(Chat::White, "0 = Ground, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating While Running"); return; @@ -24,6 +22,8 @@ void command_flymode(Client *c, const Seperator *sep) target->SetFlyMode(static_cast(flymode_id)); target->SendAppearancePacket(AT_Levitate, flymode_id); + uint32 account = c->AccountID(); + database.SetGMFlymode(account, flymode_id); c->Message( Chat::White, fmt::format( diff --git a/zone/gm_commands/gearup.cpp b/zone/gm_commands/gearup.cpp index e02ba600d..36817ad91 100755 --- a/zone/gm_commands/gearup.cpp +++ b/zone/gm_commands/gearup.cpp @@ -2,9 +2,22 @@ #include "../../common/http/httplib.h" #include "../../common/content/world_content_service.h" +#include "../bot.h" + void command_gearup(Client *c, const Seperator *sep) { - std::string tool_table_name = "tool_gearup_armor_sets"; + Mob* t = c; + if ( + c->GetTarget() && + ( + (c->GetTarget()->IsClient() && c->GetGM()) || + c->GetTarget()->IsBot() + ) + ) { + t = c->GetTarget(); + } + + const std::string tool_table_name = "tool_gearup_armor_sets"; if (!database.DoesTableExist(tool_table_name)) { c->Message( Chat::Yellow, @@ -25,8 +38,8 @@ void command_gearup(Client *c, const Seperator *sep) if (auto res = cli.Get(url.c_str())) { if (res->status == 200) { - for (auto &s: SplitString(res->body, ';')) { - if (!trim(s).empty()) { + for (auto &s: Strings::Split(res->body, ';')) { + if (!Strings::Trim(s).empty()) { auto results = database.QueryDatabase(s); if (!results.ErrorMessage().empty()) { c->Message( @@ -41,8 +54,7 @@ void command_gearup(Client *c, const Seperator *sep) } } } - } - else { + } else { c->Message( Chat::Yellow, fmt::format( @@ -55,74 +67,89 @@ void command_gearup(Client *c, const Seperator *sep) c->Message( Chat::Yellow, fmt::format( - "Table [{}] installed. Sourced [{}] queries", - tool_table_name, sourced_queries + "Table [{}] installed. Sourced [{}] quer{}", + tool_table_name, + sourced_queries, + sourced_queries != 1 ? "ies" : "y" ).c_str() ); } - std::string expansion_arg = sep->arg[1]; + const std::string expansion_arg = sep->arg[1]; std::string expansion_filter; - if (expansion_arg.length() > 0) { - expansion_filter = fmt::format("and `expansion` = {}", expansion_arg); + if (!expansion_arg.empty()) { + expansion_filter = fmt::format(" AND `expansion` = {}", expansion_arg); } - auto results = database.QueryDatabase( - fmt::format( - SQL ( - select - item_id, - slot - from - {} - where - `class` = {} - and `level` = {} - {} - order by score desc, expansion desc - ), - tool_table_name, - c->GetClass(), - c->GetLevel(), - expansion_filter - ) + auto query = fmt::format( + "SELECT item_id, slot FROM {} WHERE " + "`class` = {} AND `level` = {}{} " + "ORDER BY score DESC, expansion DESC", + tool_table_name, + t->GetClass(), + t->GetLevel(), + expansion_filter ); + auto results = database.QueryDatabase(query); int items_equipped = 0; int items_already_have = 0; std::set equipped; - for (auto row = results.begin(); row != results.end(); ++row) { - int item_id = atoi(row[0]); - int slot_id = atoi(row[1]); + for (auto row : results) { + auto item_id = std::stoul(row[0]); + auto slot_id = static_cast(std::stoul(row[1])); if (equipped.find(slot_id) != equipped.end()) { if (slot_id == EQ::invslot::slotEar1) { slot_id = EQ::invslot::slotEar2; - } - if (slot_id == EQ::invslot::slotFinger1) { + } else if (slot_id == EQ::invslot::slotFinger1) { slot_id = EQ::invslot::slotFinger2; - } - if (slot_id == EQ::invslot::slotWrist1) { + } else if (slot_id == EQ::invslot::slotWrist1) { slot_id = EQ::invslot::slotWrist2; } } if (equipped.find(slot_id) == equipped.end()) { - const EQ::ItemData *item = database.GetItem(item_id); - bool has_item = (c->GetInv().HasItem(item_id, 1, invWhereWorn) != INVALID_INDEX); - bool can_wear_item = !c->CheckLoreConflict(item) && !has_item; + const auto *item = database.GetItem(item_id); + bool has_item = false; + if (t->IsClient()) { + has_item = t->CastToClient()->GetInv().HasItem(item_id, 1, invWhereWorn) != INVALID_INDEX; + } else if (t->IsBot()) { + has_item = t->CastToBot()->HasBotItem(item_id); + } + + bool can_wear_item = false; + if (t->IsClient()) { + can_wear_item = !t->CastToClient()->CheckLoreConflict(item) && !has_item; + } else if (t->IsBot()) { + can_wear_item = !t->CastToBot()->CheckLoreConflict(item) && !has_item; + } + if (!can_wear_item) { items_already_have++; } - if (c->CastToMob()->CanClassEquipItem(item_id) && can_wear_item) { + if ( + can_wear_item && + t->CanClassEquipItem(item_id) && + ( + t->CanRaceEquipItem(item_id) || + (t->IsBot() && !t->CanRaceEquipItem(item_id) && RuleB(Bots, AllowBotEquipAnyRaceGear)) + ) + ) { equipped.insert(slot_id); - c->SummonItem( - item_id, - 0, 0, 0, 0, 0, 0, 0, 0, - slot_id - ); + + if (t->IsClient()) { + t->CastToClient()->SummonItem( + item_id, + 0, 0, 0, 0, 0, 0, 0, 0, + slot_id + ); + } else if (t->IsBot()) { + t->CastToBot()->AddBotItem(slot_id, item_id); + } + items_equipped++; } } @@ -138,44 +165,36 @@ void command_gearup(Client *c, const Seperator *sep) ); if (expansion_arg.empty()) { - results = database.QueryDatabase( - fmt::format( - SQL ( - select - expansion - from - {} - where - class = {} - and level = {} - group by - expansion; - ), - tool_table_name, - c->GetClass(), - c->GetLevel() - ) + query = fmt::format( + "SELECT expansion FROM {} WHERE " + "class = {} AND level = {} " + "GROUP BY expansion", + tool_table_name, + t->GetClass(), + t->GetLevel() ); + results = database.QueryDatabase(query); - c->Message(Chat::White, "Choose armor from a specific era"); + c->Message(Chat::White, "Choose Armor by Expansion:"); std::string message; - for (auto row = results.begin(); row != results.end(); ++row) { - int expansion = atoi(row[0]); - message += "[" + EQ::SayLinkEngine::GenerateQuestSaylink( - fmt::format("#gearup {}", expansion), - false, - Expansion::ExpansionName[expansion] - ) + "] "; + for (auto row : results) { + const auto expansion = std::stoi(row[0]); + message += fmt::format( + "[{}] ", + Saylink::Silent( + fmt::format("#gearup {}", expansion), + Expansion::ExpansionName[expansion] + ) + ); if (message.length() > 2000) { c->Message(Chat::White, message.c_str()); - message = ""; + message = std::string(); } } - if (message.length() > 0) { + + if (!message.empty()) { c->Message(Chat::White, message.c_str()); } } - } - diff --git a/zone/gm_commands/givemoney.cpp b/zone/gm_commands/givemoney.cpp index 701bd2412..9aa17e76d 100755 --- a/zone/gm_commands/givemoney.cpp +++ b/zone/gm_commands/givemoney.cpp @@ -8,7 +8,7 @@ void command_givemoney(Client *c, const Seperator *sep) return; } - + Client *target = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { target = c->GetTarget()->CastToClient(); @@ -30,12 +30,17 @@ void command_givemoney(Client *c, const Seperator *sep) platinum, true ); - + c->Message( Chat::White, fmt::format( "Added {} to {}.", - ConvertMoneyToString(platinum, gold, silver, copper), + Strings::Money( + platinum, + gold, + silver, + copper + ), c->GetTargetDescription(target) ).c_str() ); diff --git a/zone/gm_commands/gmzone.cpp b/zone/gm_commands/gmzone.cpp index 223f04fb3..94b462706 100755 --- a/zone/gm_commands/gmzone.cpp +++ b/zone/gm_commands/gmzone.cpp @@ -9,12 +9,12 @@ void command_gmzone(Client *c, const Seperator *sep) return; } - std::string zone_short_name = str_tolower( + std::string zone_short_name = Strings::ToLower( sep->IsNumber(1) ? - ZoneName(std::stoul(sep->arg[1]), true) : - sep->arg[1] + ZoneName(std::stoul(sep->arg[1]), true) : + sep->arg[1] ); - bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; + bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; if (is_unknown_zone) { c->Message( Chat::White, @@ -41,16 +41,16 @@ void command_gmzone(Client *c, const Seperator *sep) auto zone_version = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : - 0 + std::stoul(sep->arg[2]) : + 0 ); - + std::string instance_identifier = ( sep->arg[3] ? - sep->arg[3] : - "gmzone" + sep->arg[3] : + "gmzone" ); - + auto bucket_key = fmt::format( "{}-{}-{}-instance", zone_short_name, @@ -58,9 +58,9 @@ void command_gmzone(Client *c, const Seperator *sep) zone_version ); - auto existing_zone_instance = DataBucket::GetData(bucket_key); - uint16 instance_id = 0; - uint32 duration = 100000000; + auto existing_zone_instance = DataBucket::GetData(bucket_key); + uint16 instance_id = 0; + uint32 duration = 100000000; if (!existing_zone_instance.empty()) { instance_id = std::stoi(existing_zone_instance); @@ -106,21 +106,12 @@ void command_gmzone(Client *c, const Seperator *sep) if (instance_id) { float target_x = -1, target_y = -1, target_z = -1, target_heading = -1; - int16 min_status = AccountStatus::Player; - uint8 min_level = 0; - if ( - !content_db.GetSafePoints( - zone_short_name.c_str(), - zone_version, - &target_x, - &target_y, - &target_z, - &target_heading, - &min_status, - &min_level - ) - ) { + auto z = GetZoneVersionWithFallback( + ZoneID(zone_short_name.c_str()), + zone_version + ); + if (!z) { c->Message( Chat::White, fmt::format( @@ -130,8 +121,14 @@ void command_gmzone(Client *c, const Seperator *sep) zone_short_name ).c_str() ); + return; } + target_x = z->safe_x; + target_y = z->safe_y; + target_z = z->safe_z; + target_heading = z->safe_heading; + c->Message( Chat::White, fmt::format( diff --git a/zone/gm_commands/godmode.cpp b/zone/gm_commands/godmode.cpp new file mode 100644 index 000000000..81ecbe93d --- /dev/null +++ b/zone/gm_commands/godmode.cpp @@ -0,0 +1,33 @@ +#include "../client.h" +#include "../../common/repositories/account_repository.h" + +void command_godmode(Client *c, const Seperator *sep) +{ + bool state = atobool(sep->arg[1]); + uint32 account_id = c->AccountID(); + + if (sep->arg[1][0] != 0) { + auto a = AccountRepository::FindOne(database, c->AccountID()); + if (a.id > 0) { + a.flymode = state ? 1 : 0; + a.gmspeed = state ? 1 : 0; + a.invulnerable = state ? 1 : 0; + a.hideme = state ? 1 : 0; + } + + c->SetInvul(state); + c->SendAppearancePacket(AT_Levitate, state); + c->SetHideMe(state); + c->Message( + Chat::White, + "Turning GodMode %s for %s (zone for gmspeed to take effect)", + state ? "On" : "Off", + c->GetName() + ); + + AccountRepository::UpdateOne(database, a); + } + else { + c->Message(Chat::White, "Usage: #godmode [on/off]"); + } +} diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index c1afc7259..13fd07cb4 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -8,24 +8,15 @@ extern WorldServer worldserver; void command_guild(Client *c, const Seperator *sep) { - int arguments = sep->argnum; + const auto arguments = sep->argnum; if (!arguments) { - c->Message(Chat::White, "#guild create [Character ID|Character Name] [Guild Name]"); - c->Message(Chat::White, "#guild delete [Guild ID]"); - c->Message(Chat::White, "#guild help"); - c->Message(Chat::White, "#guild info [Guild ID]"); - c->Message(Chat::White, "#guild list"); - c->Message(Chat::White, "#guild rename [Guild ID] [New Name]"); - c->Message(Chat::White, "#guild set [Character ID|Character Name] [Guild ID] (Guild ID 0 is Guildless)"); - c->Message(Chat::White, "#guild setleader [Guild ID] [Character ID|Character Name]"); - c->Message(Chat::White, "#guild setrank [Character ID|Character Name] [Rank]"); - c->Message(Chat::White, "#guild status [Character ID|Character Name]"); + SendGuildSubCommands(c); return; } - auto target = c; + auto t = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { - target = c->GetTarget()->CastToClient(); + t = c->GetTarget()->CastToClient(); } bool is_create = !strcasecmp(sep->arg[1], "create"); @@ -34,6 +25,7 @@ void command_guild(Client *c, const Seperator *sep) bool is_info = !strcasecmp(sep->arg[1], "info"); bool is_list = !strcasecmp(sep->arg[1], "list"); bool is_rename = !strcasecmp(sep->arg[1], "rename"); + bool is_search = !strcasecmp(sep->arg[1], "search"); bool is_set = !strcasecmp(sep->arg[1], "set"); bool is_set_leader = !strcasecmp(sep->arg[1], "setleader"); bool is_set_rank = !strcasecmp(sep->arg[1], "setrank"); @@ -45,21 +37,13 @@ void command_guild(Client *c, const Seperator *sep) !is_info && !is_list && !is_rename && + !is_search && !is_set && !is_set_leader && !is_set_rank && !is_status ) { - c->Message(Chat::White, "#guild create [Character ID|Character Name] [Guild Name]"); - c->Message(Chat::White, "#guild delete [Guild ID]"); - c->Message(Chat::White, "#guild help"); - c->Message(Chat::White, "#guild info [Guild ID]"); - c->Message(Chat::White, "#guild list"); - c->Message(Chat::White, "#guild rename [Guild ID] [New Name]"); - c->Message(Chat::White, "#guild set [Character ID|Character Name] [Guild ID] (Guild ID 0 is Guildless)"); - c->Message(Chat::White, "#guild setleader [Guild ID] [Character ID|Character Name]"); - c->Message(Chat::White, "#guild setrank [Character ID|Character Name] [Rank]"); - c->Message(Chat::White, "#guild status [Character ID|Character Name]"); + SendGuildSubCommands(c); return; } @@ -188,16 +172,7 @@ void command_guild(Client *c, const Seperator *sep) ); } } else if (is_help) { - c->Message(Chat::White, "#guild create [Character ID|Character Name] [Guild Name]"); - c->Message(Chat::White, "#guild delete [Guild ID]"); - c->Message(Chat::White, "#guild help"); - c->Message(Chat::White, "#guild info [Guild ID]"); - c->Message(Chat::White, "#guild list"); - c->Message(Chat::White, "#guild rename [Guild ID] [New Name]"); - c->Message(Chat::White, "#guild set [Character ID|Character Name] [Guild ID] (Guild ID 0 is Guildless)"); - c->Message(Chat::White, "#guild setleader [Guild ID] [Character ID|Character Name]"); - c->Message(Chat::White, "#guild setrank [Character ID|Character Name] [Rank]"); - c->Message(Chat::White, "#guild status [Character ID|Character Name]"); + SendGuildSubCommands(c); } else if (is_info) { if (arguments != 2 && c->IsInAGuild()) { if (c->Admin() >= minStatusToEditOtherGuilds) { @@ -223,7 +198,7 @@ void command_guild(Client *c, const Seperator *sep) return; } - guild_mgr.ListGuilds(c); + guild_mgr.ListGuilds(c, std::string()); } else if (is_rename) { if (!sep->IsNumber(2)) { c->Message(Chat::White, "Usage: #guild rename [Guild ID] [New Guild Name]"); @@ -269,6 +244,16 @@ void command_guild(Client *c, const Seperator *sep) ).c_str() ); } + } else if (is_search) { + if (Strings::IsNumber(sep->arg[2])) { + const auto guild_id = std::stoul(sep->arg[2]); + + guild_mgr.ListGuilds(c, guild_id); + } else { + const std::string search_criteria = sep->argplus[2]; + + guild_mgr.ListGuilds(c, search_criteria); + } } else if (is_set) { if ( arguments != 3 || @@ -292,7 +277,7 @@ void command_guild(Client *c, const Seperator *sep) } auto character_id = ( - sep->IsNumber(2) ? + sep->IsNumber(2) ? std::stoul(sep->arg[2]) : database.GetCharacterID(sep->arg[2]) ); @@ -330,7 +315,7 @@ void command_guild(Client *c, const Seperator *sep) guild_id ); } - + if (guild_id && guild_id != GUILD_NONE) { c->Message( Chat::White, @@ -360,7 +345,7 @@ void command_guild(Client *c, const Seperator *sep) !sep->IsNumber(2) ) { c->Message(Chat::White, "Usage: #guild setleader [Guild ID] [Character ID|Character Name]"); - } else { + } else { auto leader_id = ( sep->IsNumber(2) ? std::stoul(sep->arg[2]) : @@ -404,7 +389,7 @@ void command_guild(Client *c, const Seperator *sep) return; } - if (c->Admin() < minStatusToEditOtherGuilds) { + if (c->Admin() < minStatusToEditOtherGuilds) { if (c->GuildID() != guild_id) { c->Message(Chat::White, "You cannot edit other peoples' guilds."); return; @@ -502,8 +487,8 @@ void command_guild(Client *c, const Seperator *sep) } } else if (is_status) { auto client = ( - target ? - target : + t ? + t : ( arguments == 2 ? entity_list.GetClientByName(sep->arg[2]) : @@ -521,7 +506,7 @@ void command_guild(Client *c, const Seperator *sep) fmt::format( "{} {} not in a guild.", c->GetTargetDescription(client, TargetDescriptionType::UCYou), - c == target ? "are" : "is" + c == t ? "are" : "is" ).c_str() ); } else if (guild_mgr.IsGuildLeader(client->GuildID(), client->CharacterID())) { @@ -530,17 +515,17 @@ void command_guild(Client *c, const Seperator *sep) fmt::format( "{} {} the leader of {}.", c->GetTargetDescription(client, TargetDescriptionType::UCYou), - c == target ? "are" : "is", + c == t ? "are" : "is", guild_mgr.GetGuildNameByID(client->GuildID()) ).c_str() ); } else { - c->Message( + c->Message( Chat::White, fmt::format( "{} {} a(n) {} of {}.", c->GetTargetDescription(client, TargetDescriptionType::UCYou), - c == target ? "are" : "is", + c == t ? "are" : "is", guild_mgr.GetRankName(client->GuildID(), client->GuildRank()), guild_mgr.GetGuildNameByID(client->GuildID()) ).c_str() @@ -549,3 +534,18 @@ void command_guild(Client *c, const Seperator *sep) } } } + +void SendGuildSubCommands(Client *c) +{ + c->Message(Chat::White, "#guild create [Character ID|Character Name] [Guild Name]"); + c->Message(Chat::White, "#guild delete [Guild ID]"); + c->Message(Chat::White, "#guild help"); + c->Message(Chat::White, "#guild info [Guild ID]"); + c->Message(Chat::White, "#guild list"); + c->Message(Chat::White, "#guild rename [Guild ID] [New Name]"); + c->Message(Chat::White, "#guild search [Search Criteria]"); + c->Message(Chat::White, "#guild set [Character ID|Character Name] [Guild ID] (Guild ID 0 is Guildless)"); + c->Message(Chat::White, "#guild setleader [Guild ID] [Character ID|Character Name]"); + c->Message(Chat::White, "#guild setrank [Character ID|Character Name] [Rank]"); + c->Message(Chat::White, "#guild status [Character ID|Character Name]"); +} diff --git a/zone/gm_commands/heromodel.cpp b/zone/gm_commands/heromodel.cpp index 33ea72c2c..45b9048c1 100755 --- a/zone/gm_commands/heromodel.cpp +++ b/zone/gm_commands/heromodel.cpp @@ -2,33 +2,42 @@ void command_heromodel(Client *c, const Seperator *sep) { - if (sep->argnum < 1) { - c->Message(Chat::White, "Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63)"); + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #heromodel [Hero Model]"); + c->Message(Chat::White, "Usage: #heromodel [Hero Model] [Slot]"); + c->Message( + Chat::White, + fmt::format( + "Example: {}", + Saylink::Silent("#heromodel 63") + ).c_str() + ); + return; } - else if (c->GetTarget() == nullptr) { - c->Message(Chat::Red, "You must have a target to do a wear change for Hero's Forge Models."); + + Mob* t = c; + if (c->GetTarget()) { + t = c->GetTarget(); } - else { - uint32 hero_forge_model = atoi(sep->arg[1]); - if (sep->argnum > 1) { - uint8 wearslot = (uint8) atoi(sep->arg[2]); - c->GetTarget()->SendTextureWC(wearslot, 0, hero_forge_model, 0, 0, 0); - } - else { - if (hero_forge_model > 0) { - // Conversion to simplify the command arguments - // Hero's Forge model is actually model * 1000 + texture * 100 + wearslot - // Hero's Forge Model slot 7 is actually for Robes, but it still needs to use wearslot 1 in the packet - hero_forge_model *= 100; + auto hero_forge_model = std::stoul(sep->arg[1]); - for (uint8 wearslot = 0; wearslot < 7; wearslot++) { - c->GetTarget()->SendTextureWC(wearslot, 0, (hero_forge_model + wearslot), 0, 0, 0); - } - } - else { - c->Message(Chat::Red, "Hero's Forge Model must be greater than 0."); + if (arguments > 1) { + auto slot = static_cast(std::stoul(sep->arg[2])); + c->GetTarget()->SendTextureWC(slot, 0, hero_forge_model, 0, 0, 0); + } else { + if (hero_forge_model) { + // Conversion to simplify the command arguments + // Hero's Forge model is actually model * 1000 + texture * 100 + wearslot + // Hero's Forge Model slot 7 is actually for Robes, but it still needs to use wearslot 1 in the packet + hero_forge_model *= 100; + + for (uint8 slot = 0; slot < 7; slot++) { + c->GetTarget()->SendTextureWC(slot, 0, (hero_forge_model + slot), 0, 0, 0); } + } else { + c->Message(Chat::White, "Hero's Forge Model must be greater than 0."); } } } diff --git a/zone/gm_commands/instance.cpp b/zone/gm_commands/instance.cpp index 1777ef652..83ca06d9e 100755 --- a/zone/gm_commands/instance.cpp +++ b/zone/gm_commands/instance.cpp @@ -97,10 +97,10 @@ void command_instance(Client *c, const Seperator *sep) return; } - uint32 zone_id = database.ZoneIDFromInstanceID(instance_id); - uint32 version = database.VersionFromInstanceID(instance_id); - uint32 current_id = database.GetInstanceID(zone_id, character_id, version); - if (!current_id) { + auto zone_id = database.GetInstanceZoneID(instance_id); + auto version = database.GetInstanceVersion(instance_id); + auto current_id = database.GetInstanceID(zone_id, character_id, version); + if (!current_id) { c->Message( Chat::White, ( @@ -109,7 +109,7 @@ void command_instance(Client *c, const Seperator *sep) "Added {} to Instance ID {}.", c->GetTargetDescription(target), instance_id - ) : + ) : fmt::format( "Failed to add {} to Instance ID {}.", c->GetTargetDescription(target), @@ -182,7 +182,7 @@ void command_instance(Client *c, const Seperator *sep) ZoneLongName(zone_id), zone_id, ( - version ? + version ? fmt::format( " Version: {}", version @@ -197,7 +197,7 @@ void command_instance(Client *c, const Seperator *sep) fmt::format( "Instance {} Created | Duration: {} ({})", instance_id, - ConvertSecondsToTime(duration), + Strings::SecondsToTime(duration), duration ).c_str() ); @@ -295,7 +295,7 @@ void command_instance(Client *c, const Seperator *sep) "Removed {} from Instance ID {}.", c->GetTargetDescription(target), instance_id - ) : + ) : fmt::format( "Failed to remove {} from Instance ID {}.", c->GetTargetDescription(target), diff --git a/zone/gm_commands/invul.cpp b/zone/gm_commands/invul.cpp index 18fa2aa6a..398cd5174 100755 --- a/zone/gm_commands/invul.cpp +++ b/zone/gm_commands/invul.cpp @@ -1,7 +1,6 @@ #include "../client.h" -void command_invul(Client *c, const Seperator *sep) -{ +void command_invul(Client *c, const Seperator *sep) { int arguments = sep->argnum; if (!arguments) { c->Message(Chat::White, "Usage: #invul [On|Off]"); @@ -15,6 +14,8 @@ void command_invul(Client *c, const Seperator *sep) } target->SetInvul(invul_flag); + uint32 account = target->AccountID(); + database.SetGMInvul(account, invul_flag); c->Message( Chat::White, fmt::format( @@ -25,4 +26,3 @@ void command_invul(Client *c, const Seperator *sep) ).c_str() ); } - diff --git a/zone/gm_commands/ipban.cpp b/zone/gm_commands/ipban.cpp index 40307539b..40c9ed500 100755 --- a/zone/gm_commands/ipban.cpp +++ b/zone/gm_commands/ipban.cpp @@ -25,8 +25,10 @@ void command_ipban(Client *c, const Seperator *sep) } else { c->Message( Chat::White, - "IP '{}' has failed to be banned, the IP address may already be in the table.", - ip + fmt::format( + "IP '{}' has failed to be banned, the IP address may already be in the table.", + ip + ).c_str() ); } } diff --git a/zone/gm_commands/iteminfo.cpp b/zone/gm_commands/iteminfo.cpp deleted file mode 100755 index 683c23075..000000000 --- a/zone/gm_commands/iteminfo.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "../client.h" -#include "../groups.h" - -void command_iteminfo(Client *c, const Seperator *sep) -{ - auto inst = c->GetInv()[EQ::invslot::slotCursor]; - if (!inst) { - c->Message(Chat::Red, "Error: You need an item on your cursor for this command"); - return; - } - auto item = inst->GetItem(); - if (!item) { - LogInventory("([{}]) Command #iteminfo processed an item with no data pointer"); - c->Message(Chat::Red, "Error: This item has no data reference"); - return; - } - - EQ::SayLinkEngine linker; - linker.SetLinkType(EQ::saylink::SayLinkItemInst); - linker.SetItemInst(inst); - - c->Message(Chat::White, "*** Item Info for [%s] ***", linker.GenerateLink().c_str()); - c->Message(Chat::White, ">> ID: %u, ItemUseType: %u, ItemClassType: %u", item->ID, item->ItemType, item->ItemClass); - c->Message(Chat::White, ">> IDFile: '%s', IconID: %u", item->IDFile, item->Icon); - c->Message( - Chat::White, - ">> Size: %u, Weight: %u, Price: %u, LDoNPrice: %u", - item->Size, - item->Weight, - item->Price, - item->LDoNPrice - ); - c->Message( - Chat::White, - ">> Material: 0x%02X, Color: 0x%08X, Tint: 0x%08X, Light: 0x%02X", - item->Material, - item->Color, - inst->GetColor(), - item->Light - ); - c->Message( - Chat::White, - ">> IsLore: %s, LoreGroup: %u, Lore: '%s'", - (item->LoreFlag ? "TRUE" : "FALSE"), - item->LoreGroup, - item->Lore - ); - c->Message( - Chat::White, ">> NoDrop: %u, NoRent: %u, NoPet: %u, NoTransfer: %u, FVNoDrop: %u", - item->NoDrop, item->NoRent, (uint8) item->NoPet, (uint8) item->NoTransfer, item->FVNoDrop - ); - - if (item->IsClassBook()) { - c->Message(Chat::White, "*** This item is a Book (filename:'%s') ***", item->Filename); - } - else if (item->IsClassBag()) { - c->Message(Chat::White, "*** This item is a Container (%u slots) ***", item->BagSlots); - } - else { - c->Message(Chat::White, "*** This item is Common ***"); - c->Message(Chat::White, ">> Classes: %u, Races: %u, Slots: %u", item->Classes, item->Races, item->Slots); - c->Message( - Chat::White, - ">> ReqSkill: %u, ReqLevel: %u, RecLevel: %u", - item->RecSkill, - item->ReqLevel, - item->RecLevel - ); - c->Message(Chat::White, ">> SkillModType: %u, SkillModValue: %i", item->SkillModType, item->SkillModValue); - c->Message( - Chat::White, ">> BaneRaceType: %u, BaneRaceDamage: %u, BaneBodyType: %u, BaneBodyDamage: %i", - item->BaneDmgRace, item->BaneDmgRaceAmt, item->BaneDmgBody, item->BaneDmgAmt - ); - c->Message( - Chat::White, - ">> Magic: %s, SpellID: %i, ProcLevel: %u, Charges: %u, MaxCharges: %u", - (item->Magic ? "TRUE" : "FALSE"), - item->Click.Effect, - item->Click.Level, - inst->GetCharges(), - item->MaxCharges - ); - c->Message( - Chat::White, - ">> EffectType: 0x%02X, CastTime: %.2f", - (uint8) item->Click.Type, - ((double) item->CastTime / 1000)); - } - - if (c->Admin() >= AccountStatus::GMMgmt) { - c->Message(Chat::White, ">> MinStatus: %u", item->MinStatus); - } -} - diff --git a/zone/gm_commands/itemsearch.cpp b/zone/gm_commands/itemsearch.cpp index 4617e2397..be720275f 100755 --- a/zone/gm_commands/itemsearch.cpp +++ b/zone/gm_commands/itemsearch.cpp @@ -19,9 +19,8 @@ void command_itemsearch(Client *c, const Seperator *sep) std::string item_id = std::to_string(item->ID); std::string saylink_commands = "[" + - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( "#si " + item_id, - false, "X" ) + "] "; @@ -30,9 +29,8 @@ void command_itemsearch(Client *c, const Seperator *sep) std::string stack_size = std::to_string(item->StackSize); saylink_commands += "[" + - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( "#si " + item_id + " " + stack_size, - false, stack_size ) + "]"; @@ -77,9 +75,8 @@ void command_itemsearch(Client *c, const Seperator *sep) std::string item_id = std::to_string(item->ID); std::string saylink_commands = "[" + - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( "#si " + item_id, - false, "X" ) + "] "; @@ -87,9 +84,8 @@ void command_itemsearch(Client *c, const Seperator *sep) std::string stack_size = std::to_string(item->StackSize); saylink_commands += "[" + - EQ::SayLinkEngine::GenerateQuestSaylink( + Saylink::Silent( "#si " + item_id + " " + stack_size, - false, stack_size ) + "]"; diff --git a/zone/gm_commands/kick.cpp b/zone/gm_commands/kick.cpp index dfd7be64b..a0dd45b18 100755 --- a/zone/gm_commands/kick.cpp +++ b/zone/gm_commands/kick.cpp @@ -17,6 +17,7 @@ void command_kick(Client *c, const Seperator *sep) if (client->Admin() <= c->Admin()) { auto outapp = new EQApplicationPacket(OP_GMKick, 0); client->QueuePacket(outapp); + safe_delete(outapp); client->Kick("Ordered kicked by command"); c->Message( Chat::White, diff --git a/zone/gm_commands/kill.cpp b/zone/gm_commands/kill.cpp index d54245662..989df7294 100755 --- a/zone/gm_commands/kill.cpp +++ b/zone/gm_commands/kill.cpp @@ -2,11 +2,27 @@ void command_kill(Client *c, const Seperator *sep) { - if (!c->GetTarget()) { - c->Message(Chat::White, "Error: #Kill: No target."); + auto target = c->GetTarget(); + if (!target) { + c->Message(Chat::White, "You must have a target to use this command."); + return; } - else if (!c->GetTarget()->IsClient() || c->GetTarget()->CastToClient()->Admin() <= c->Admin()) { - c->GetTarget()->Kill(); + + if ( + !target->IsClient() || + target->CastToClient()->Admin() <= c->Admin() + ) { + if (c != target) { + c->Message( + Chat::White, + fmt::format( + "Killing {}.", + c->GetTargetDescription(target) + ).c_str() + ); + } + + target->Kill(); } } diff --git a/zone/gm_commands/killallnpcs.cpp b/zone/gm_commands/killallnpcs.cpp index c01bd67f3..146ee1e2d 100755 --- a/zone/gm_commands/killallnpcs.cpp +++ b/zone/gm_commands/killallnpcs.cpp @@ -4,7 +4,7 @@ void command_killallnpcs(Client *c, const Seperator *sep) { std::string search_string; if (sep->arg[1]) { - search_string = str_tolower(sep->arg[1]); + search_string = Strings::ToLower(sep->arg[1]); } int killed_count = 0; @@ -15,7 +15,7 @@ void command_killallnpcs(Client *c, const Seperator *sep) continue; } - std::string entity_name = str_tolower(entity->GetName()); + std::string entity_name = Strings::ToLower(entity->GetName()); if ((!search_string.empty() && entity_name.find(search_string) == std::string::npos) || !entity->IsAttackAllowed(c)) { continue; diff --git a/zone/gm_commands/lastname.cpp b/zone/gm_commands/lastname.cpp index 8dd3c7dd0..070f5023a 100755 --- a/zone/gm_commands/lastname.cpp +++ b/zone/gm_commands/lastname.cpp @@ -9,20 +9,31 @@ void command_lastname(Client *c, const Seperator *sep) LogInfo("#lastname request from [{}] for [{}]", c->GetCleanName(), target->GetCleanName()); - std::string last_name = sep->arg[1]; + bool is_remove = !strcasecmp(sep->argplus[1], "-1"); + std::string last_name = is_remove ? "" : sep->argplus[1]; + if (last_name.size() > 64) { - c->Message(Chat::White, "Usage: #lastname [Last Name] (Last Name must be 64 characters or less)"); + c->Message(Chat::White, "Last name must be 64 characters or less."); return; } - target->ChangeLastName(last_name.c_str()); + target->ChangeLastName(last_name); + c->Message( Chat::White, fmt::format( - "{} now {} a last name of '{}'.", - c->GetTargetDescription(target, TargetDescriptionType::UCYou), - c == target ? "have" : "has", - last_name + "Last name has been {}{} for {}{}", + is_remove ? "removed" : "changed", + !is_remove ? " and saved" : "", + c->GetTargetDescription(target), + ( + is_remove ? + "." : + fmt::format( + " to '{}'.", + last_name + ) + ) ).c_str() ); } diff --git a/zone/gm_commands/level.cpp b/zone/gm_commands/level.cpp new file mode 100644 index 000000000..663633cd7 --- /dev/null +++ b/zone/gm_commands/level.cpp @@ -0,0 +1,48 @@ +#include "../client.h" + +void command_level(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #level [Level]"); + return; + } + + auto target = c->GetTarget(); + if (!target) { + c->Message(Chat::White, "You must have a target to use this command."); + return; + } + + auto level = static_cast(std::stoul(sep->arg[1])); + auto max_level = static_cast(RuleI(Character, MaxLevel)); + + if (c->Admin() < RuleI(GM, MinStatusToLevelTarget)) { + c->Message(Chat::White, "Your status is not high enough to change another person's level."); + return; + } + + if ( + level > max_level && + c->Admin() < commandLevelAboveCap + ) { + c->Message( + Chat::White, + fmt::format( + "Level {} is above the Maximum Level of {} and your status is not high enough to go beyond the cap.", + level, + max_level + ).c_str() + ); + return; + } + + target->SetLevel(level, true); + if (target->IsClient()) { + target->CastToClient()->SendLevelAppearance(); + + if (RuleB(Bots, Enabled) && RuleB(Bots, BotLevelsWithOwner)) { + Bot::LevelBotWithClient(target->CastToClient(), level, true); + } + } +} diff --git a/zone/gm_commands/list.cpp b/zone/gm_commands/list.cpp index a38b3ddc3..fe675ae9c 100755 --- a/zone/gm_commands/list.cpp +++ b/zone/gm_commands/list.cpp @@ -69,7 +69,7 @@ void command_list(Client *c, const Seperator *sep) c->Message( 0, "| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(), + Saylink::Silent(saylink, "Goto").c_str(), entity->GetID(), entity->GetName(), entity->GetX(), @@ -110,7 +110,7 @@ void command_list(Client *c, const Seperator *sep) c->Message( 0, "| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(), + Saylink::Silent(saylink, "Goto").c_str(), entity->GetID(), entity->GetName(), entity->GetX(), @@ -151,7 +151,7 @@ void command_list(Client *c, const Seperator *sep) c->Message( 0, "| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(), + Saylink::Silent(saylink, "Goto").c_str(), entity->GetID(), entity->GetName(), entity->GetX(), @@ -192,7 +192,7 @@ void command_list(Client *c, const Seperator *sep) c->Message( 0, "| %s | Entity ID %5d | Door ID %i | %s | x %.0f | y %0.f | z %.0f", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(), + Saylink::Silent(saylink, "Goto").c_str(), entity->GetID(), entity->GetDoorID(), entity->GetDoorName(), @@ -234,7 +234,7 @@ void command_list(Client *c, const Seperator *sep) c->Message( 0, "| %s | Entity ID %5d | Object DBID %i | %s | x %.0f | y %0.f | z %.0f", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Goto").c_str(), + Saylink::Silent(saylink, "Goto").c_str(), entity->GetID(), entity->GetDBID(), entity->GetModelName(), diff --git a/zone/gm_commands/loc.cpp b/zone/gm_commands/loc.cpp index 48b232498..8928b8051 100755 --- a/zone/gm_commands/loc.cpp +++ b/zone/gm_commands/loc.cpp @@ -20,5 +20,123 @@ void command_loc(Client *c, const Seperator *sep) target_position.w ).c_str() ); + + if (!zone->zonemap) { + c->Message(Chat::White, "Map not loaded for this zone."); + } else { + auto z = target->GetZ() + (target->GetSize() == 0.0 ? 6 : target->GetSize()) * HEAD_POSITION; + auto tarloc = glm::vec3(target->GetX(), target->GetY(), z); + glm::vec3 hit; + + auto best_z = zone->zonemap->FindBestZ(tarloc, &hit); + + if (best_z != BEST_Z_INVALID) { + c->Message( + Chat::White, + fmt::format( + "Best Z for {} | {:.2f}", + c->GetTargetDescription(target, TargetDescriptionType::UCSelf), + best_z + ).c_str() + ); + } else { + c->Message(Chat::White, "Could not find Best Z."); + } + } + + if (!zone->watermap) { + c->Message(Chat::White, "Water Map not loaded for this zone."); + } else { + auto position = glm::vec3(target->GetX(), target->GetY(), target->GetZ()); + auto region_type = zone->watermap->ReturnRegionType(position); + auto position_string = fmt::format( + "{} {}", + c->GetTargetDescription(target, TargetDescriptionType::UCYou), + c == target ? "are" : "is" + ); + + switch (region_type) { + case RegionTypeIce: { + c->Message( + Chat::White, + fmt::format( + "{} in Ice.", + position_string + ).c_str() + ); + break; + } + case RegionTypeLava: { + c->Message( + Chat::White, + fmt::format( + "{} in Lava.", + position_string + ).c_str() + ); + break; + } + case RegionTypeNormal: { + c->Message( + Chat::White, + fmt::format( + "{} in a Normal Region.", + position_string + ).c_str() + ); + break; + } + case RegionTypePVP: { + c->Message( + Chat::White, + fmt::format( + "{} in a PvP Area.", + position_string + ).c_str() + ); + break; + } + case RegionTypeSlime: { + c->Message( + Chat::White, + fmt::format( + "{} in Slime.", + position_string + ).c_str() + ); + break; + } + case RegionTypeVWater: { + c->Message( + Chat::White, + fmt::format( + "{} in VWater (Icy Water?).", + position_string + ).c_str() + ); + break; + } + case RegionTypeWater: { + c->Message( + Chat::White, + fmt::format( + "{} in Water.", + position_string + ).c_str() + ); + break; + } + default: { + c->Message( + Chat::White, + fmt::format( + "{} in an Unknown Region.", + position_string + ).c_str() + ); + break; + } + } + } } diff --git a/zone/gm_commands/lock.cpp b/zone/gm_commands/lock.cpp deleted file mode 100755 index 1fda53841..000000000 --- a/zone/gm_commands/lock.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "../client.h" -#include "../worldserver.h" - -extern WorldServer worldserver; - -void command_lock(Client *c, const Seperator *sep) -{ - auto outpack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); - ServerLock_Struct *lss = (ServerLock_Struct *) outpack->pBuffer; - strcpy(lss->myname, c->GetName()); - lss->mode = 1; - worldserver.SendPacket(outpack); - safe_delete(outpack); -} - diff --git a/zone/gm_commands/logcommand.cpp b/zone/gm_commands/logcommand.cpp index 3b85e2ff3..33fe83516 100755 --- a/zone/gm_commands/logcommand.cpp +++ b/zone/gm_commands/logcommand.cpp @@ -1,85 +1,89 @@ #include "../client.h" -void command_logcommand(Client *c, const char *message) +void command_logcommand(Client *c, std::string message) { int admin = c->Admin(); - bool continueevents = false; + bool log = false; switch (zone->loglevelvar) { //catch failsafe case 9: { // log only LeadGM if ( admin >= AccountStatus::GMLeadAdmin && admin < AccountStatus::GMMgmt - ) { - continueevents = true; + ) { + log = true; } + break; } case 8: { // log only GM if ( admin >= AccountStatus::GMAdmin && admin < AccountStatus::GMLeadAdmin - ) { - continueevents = true; + ) { + log = true; } + break; } case 1: { if (admin >= AccountStatus::GMMgmt) { - continueevents = true; + log = true; } + break; } case 2: { if (admin >= AccountStatus::GMLeadAdmin) { - continueevents = true; + log = true; } + break; } case 3: { if (admin >= AccountStatus::GMAdmin) { - continueevents = true; + log = true; } + break; } case 4: { if (admin >= AccountStatus::QuestTroupe) { - continueevents = true; + log = true; } + break; } case 5: { if (admin >= AccountStatus::ApprenticeGuide) { - continueevents = true; + log = true; } + break; } case 6: { if (admin >= AccountStatus::Steward) { - continueevents = true; + log = true; } + break; } case 7: { - continueevents = true; + log = true; break; } } - if (continueevents) { + if (log) { database.logevents( c->AccountName(), c->AccountID(), - admin, c->GetName(), + admin, + c->GetName(), c->GetTarget() ? c->GetTarget()->GetName() : "None", "Command", - message, + message.c_str(), 1 ); } } - - -/* - * commands go below here - */ diff --git a/zone/gm_commands/logs.cpp b/zone/gm_commands/logs.cpp index 2460ab62d..9a05745e6 100755 --- a/zone/gm_commands/logs.cpp +++ b/zone/gm_commands/logs.cpp @@ -25,10 +25,10 @@ void command_logs(Client *c, const Seperator *sep) ); return; } - - bool is_list = !strcasecmp(sep->arg[1], "list"); + + bool is_list = !strcasecmp(sep->arg[1], "list"); bool is_reload = !strcasecmp(sep->arg[1], "reload"); - bool is_set = !strcasecmp(sep->arg[1], "set"); + bool is_set = !strcasecmp(sep->arg[1], "set"); if (!is_list && !is_reload && !is_set) { c->Message( @@ -58,45 +58,98 @@ void command_logs(Client *c, const Seperator *sep) uint32 max_category_id = (start_category_id + 49); - std::string popup_text = "
ZoneFlag Required
"; - - popup_text += ""; - popup_text += ""; - popup_text += ""; - popup_text += ""; - popup_text += ""; - popup_text += ""; - popup_text += ""; + c->Message(Chat::White, "------------------------------------------------"); for (int index = start_category_id; index <= max_category_id; index++) { if (index >= Logs::LogCategory::MaxCategoryID) { max_category_id = (Logs::LogCategory::MaxCategoryID - 1); break; } - - popup_text += fmt::format( - "", - index, - Logs::LogCategoryName[index], - LogSys.log_settings[index].log_to_console, - LogSys.log_settings[index].log_to_file, - LogSys.log_settings[index].log_to_gmsay + + bool is_deprecated_category = Strings::Contains( + fmt::format("{}", Logs::LogCategoryName[index]), + "Deprecated" + ); + if (is_deprecated_category) { + continue; + } + + std::vector gmsay; + for (int i = 0; i <= 2; i++) { + if (LogSys.log_settings[index].log_to_gmsay == i) { + gmsay.emplace_back(std::to_string(i)); + continue; + } + + gmsay.emplace_back( + EQ::SayLinkEngine::GenerateQuestSaylink( + fmt::format("#logs set gmsay {} {}", index, i), false, std::to_string(i) + ) + ); + } + + std::vector file; + for (int i = 0; i <= 2; i++) { + if (LogSys.log_settings[index].log_to_file == i) { + file.emplace_back(std::to_string(i)); + continue; + } + + file.emplace_back( + EQ::SayLinkEngine::GenerateQuestSaylink( + fmt::format("#logs set file {} {}", index, i), false, std::to_string(i) + ) + ); + } + + std::vector console; + for (int i = 0; i <= 2; i++) { + if (LogSys.log_settings[index].log_to_console == i) { + console.emplace_back(std::to_string(i)); + continue; + } + + console.emplace_back( + EQ::SayLinkEngine::GenerateQuestSaylink( + fmt::format("#logs set console {} {}", index, i), false, std::to_string(i) + ) + ); + } + + std::vector discord; + for (int i = 0; i <= 2; i++) { + if (LogSys.log_settings[index].log_to_discord == i) { + discord.emplace_back(std::to_string(i)); + continue; + } + + discord.emplace_back( + EQ::SayLinkEngine::GenerateQuestSaylink( + fmt::format("#logs set discord {} {}", index, i), false, std::to_string(i) + ) + ); + } + + std::string gmsay_string = Strings::Join(gmsay, "-"); + std::string console_string = Strings::Join(console, "-"); + std::string file_string = Strings::Join(file, "-"); + std::string discord_string = Strings::Join(discord, "-"); + + c->Message( + 0, + fmt::format( + "[{}] GM [{}] Console [{}] File [{}] Discord [{}] [{}] ", + index, + Strings::RTrim(gmsay_string, "-"), + Strings::RTrim(console_string, "-"), + Strings::RTrim(file_string, "-"), + Strings::RTrim(discord_string, "-"), + Logs::LogCategoryName[index] + ).c_str() ); } - popup_text += "
IDNameConsoleFileGM Say
{}{}{}{}{}
"; - - std::string popup_title = fmt::format( - "Log Settings [{} to {}]", - start_category_id, - max_category_id - ); - - c->SendPopupToClient( - popup_title.c_str(), - popup_text.c_str() - ); - + c->Message(Chat::White, "------------------------------------------------"); c->Message( Chat::White, fmt::format( @@ -107,6 +160,7 @@ void command_logs(Client *c, const Seperator *sep) max_category_id ).c_str() ); + c->Message(Chat::White, "------------------------------------------------"); int next_category_id = (max_category_id + 1); if (next_category_id < Logs::LogCategory::MaxCategoryID) { @@ -115,11 +169,7 @@ void command_logs(Client *c, const Seperator *sep) next_category_id ); - auto next_list_link = EQ::SayLinkEngine::GenerateQuestSaylink( - next_list_string, - false, - next_list_string - ); + auto next_list_link = Saylink::Silent(next_list_string, next_list_string); c->Message( Chat::White, @@ -129,18 +179,21 @@ void command_logs(Client *c, const Seperator *sep) ).c_str() ); } - } else if (is_reload) { + } + else if (is_reload) { c->Message(Chat::White, "Attempting to reload Log Settings globally."); auto pack = new ServerPacket(ServerOP_ReloadLogs, 0); worldserver.SendPacket(pack); safe_delete(pack); - } else if (is_set && sep->IsNumber(3)) { - auto logs_set = false; + } + else if (is_set && sep->IsNumber(3)) { + auto logs_set = false; bool is_console = !strcasecmp(sep->arg[2], "console"); - bool is_file = !strcasecmp(sep->arg[2], "file"); - bool is_gmsay = !strcasecmp(sep->arg[2], "gmsay"); + bool is_file = !strcasecmp(sep->arg[2], "file"); + bool is_gmsay = !strcasecmp(sep->arg[2], "gmsay"); + bool is_discord = !strcasecmp(sep->arg[2], "discord"); - if (!sep->IsNumber(4) || (!is_console && !is_file && !is_gmsay)) { + if (!sep->IsNumber(4) || (!is_console && !is_file && !is_gmsay && !is_discord)) { c->Message( Chat::White, "#logs set [console|file|gmsay] [Category ID] [Debug Level (1-3)] - Sets log settings during the lifetime of the zone" @@ -152,21 +205,26 @@ void command_logs(Client *c, const Seperator *sep) logs_set = true; auto category_id = std::stoul(sep->arg[3]); - auto setting = std::stoul(sep->arg[4]); + auto setting = std::stoul(sep->arg[4]); if (is_console) { LogSys.log_settings[category_id].log_to_console = setting; - } else if (is_file) { + } + else if (is_file) { LogSys.log_settings[category_id].log_to_file = setting; - } else if (is_gmsay) { + } + else if (is_gmsay) { LogSys.log_settings[category_id].log_to_gmsay = setting; } + else if (is_discord) { + LogSys.log_settings[category_id].log_to_discord = setting; + } if (logs_set) { c->Message( Chat::White, fmt::format( - "{} ({}) is now set to Debug Level {} for {}.", + "{} ({}) is now set to Debug Level {} for {}. This is temporary and only in memory for the current zone.", Logs::LogCategoryName[category_id], category_id, setting, diff --git a/zone/gm_commands/lootsim.cpp b/zone/gm_commands/lootsim.cpp new file mode 100755 index 000000000..2213c12a1 --- /dev/null +++ b/zone/gm_commands/lootsim.cpp @@ -0,0 +1,198 @@ +#include "../client.h" + +void command_lootsim(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + if (arguments < 3 || !sep->IsNumber(1) || !sep->IsNumber(2) || !sep->IsNumber(3)) { + c->Message(Chat::White, "Usage: #lootsim [npc_type_id] [loottable_id] [iterations] [loot_log_enabled=0]"); + return; + } + + auto npc_id = std::stoul(sep->arg[1]); + auto loottable_id = std::stoul(sep->arg[2]); + auto iterations = std::stoul(sep->arg[3]) > 1000 ? 1000 : std::stoul(sep->arg[3]); + auto log_enabled = arguments > 3 ? std::stoul(sep->arg[4]) : false; + + // temporarily disable loot logging unless set explicitly + LogSys.log_settings[Logs::Loot].log_to_console = log_enabled ? LogSys.log_settings[Logs::Loot].log_to_console : 0; + LogSys.log_settings[Logs::Loot].log_to_file = log_enabled ? LogSys.log_settings[Logs::Loot].log_to_file : 0; + LogSys.log_settings[Logs::Loot].log_to_gmsay = log_enabled ? LogSys.log_settings[Logs::Loot].log_to_gmsay : 0; + + auto npc_type = content_db.LoadNPCTypesData(npc_id); + if (npc_type) { + auto npc = new NPC(npc_type, nullptr, c->GetPosition(), GravityBehavior::Water); + if (npc) { + + BenchTimer benchmark; + + npc->SetRecordLootStats(true); + for (int i = 0; i < iterations; i++) { + npc->AddLootTable(loottable_id); + + for (auto &id: zone->GetGlobalLootTables(npc)) { + npc->AddLootTable(id); + } + } + + entity_list.AddNPC(npc); + + c->SendChatLineBreak(); + c->Message( + Chat::White, + fmt::format( + "# [Loot Simulator] NPC [{}] ({}) Loot Table ID [{}] Dropped Items [{}] iterations [{}]", + npc->GetCleanName(), + npc_id, + loottable_id, + npc->GetRolledItems().size(), + iterations + ).c_str() + ); + c->SendChatLineBreak(); + + // npc level loot table + auto loot_table = database.GetLootTable(loottable_id); + if (!loot_table) { + c->Message(Chat::Red, "Loot table not found"); + return; + } + + for (uint32 i = 0; i < loot_table->NumEntries; i++) { + auto le = loot_table->Entries[i]; + + c->Message( + Chat::White, + fmt::format( + "# Lootdrop ID [{}] drop_limit [{}] min_drop [{}] mult [{}] probability [{}]", + le.lootdrop_id, + le.droplimit, + le.mindrop, + le.multiplier, + le.probability + ).c_str() + ); + + auto loot_drop = database.GetLootDrop(le.lootdrop_id); + if (!loot_drop) { + continue; + } + + for (uint32 ei = 0; ei < loot_drop->NumEntries; ei++) { + auto e = loot_drop->Entries[ei]; + int rolled_count = npc->GetRolledItemCount(e.item_id); + const EQ::ItemData *item = database.GetItem(e.item_id); + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemData); + linker.SetItemData(item); + + auto rolled_percentage = (float) ((float) ((float) rolled_count / (float) iterations) * 100); + + c->Message( + Chat::White, + fmt::format( + "-- [{}] item_id [{}] chance [{}] rolled_count [{}] ({:.2f}%) name [{}]", + ei, + e.item_id, + e.chance, + rolled_count, + rolled_percentage, + linker.GenerateLink() + ).c_str() + ); + } + } + + + // global loot + auto tables = zone->GetGlobalLootTables(npc); + if (!tables.empty()) { + c->SendChatLineBreak(); + c->Message(Chat::White, "# [Loot Simulator] Global Loot"); + } + + for (auto &id: tables) { + c->SendChatLineBreak(); + c->Message(Chat::White, fmt::format("# Global Loot Table ID [{}]", id).c_str()); + c->SendChatLineBreak(); + + loot_table = database.GetLootTable(id); + if (!loot_table) { + c->Message(Chat::Red, fmt::format("Global Loot table not found [{}]", id).c_str()); + continue; + } + + for (uint32 i = 0; i < loot_table->NumEntries; i++) { + auto le = loot_table->Entries[i]; + + c->Message( + Chat::White, + fmt::format( + "# Lootdrop ID [{}] drop_limit [{}] min_drop [{}] mult [{}] probability [{}]", + le.lootdrop_id, + le.droplimit, + le.mindrop, + le.multiplier, + le.probability + ).c_str() + ); + + auto loot_drop = database.GetLootDrop(le.lootdrop_id); + if (!loot_drop) { + continue; + } + + for (uint32 ei = 0; ei < loot_drop->NumEntries; ei++) { + auto e = loot_drop->Entries[ei]; + int rolled_count = npc->GetRolledItemCount(e.item_id); + const EQ::ItemData *item = database.GetItem(e.item_id); + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemData); + linker.SetItemData(item); + + auto rolled_percentage = (float) ((float) ((float) rolled_count / (float) iterations) * 100); + + c->Message( + Chat::White, + fmt::format( + "-- [{}] item_id [{}] chance [{}] rolled_count [{}] ({:.2f}%) name [{}]", + ei, + e.item_id, + e.chance, + rolled_count, + rolled_percentage, + linker.GenerateLink() + ).c_str() + ); + } + } + } + + + c->SendChatLineBreak(); + c->Message( + Chat::White, + fmt::format( + "# Global Loot Benchmark End [{}] iterations took [{}](s)", + iterations, + benchmark.elapsed() + ).c_str() + ); + c->SendChatLineBreak(); + + LogSys.LoadLogDatabaseSettings(); + } + } + else { + c->Message( + Chat::White, + fmt::format( + "Failed to spawn NPC ID {}.", + npc_id + ).c_str() + ); + } +} + + diff --git a/zone/gm_commands/max_all_skills.cpp b/zone/gm_commands/max_all_skills.cpp index 6c63c60ca..d032265ec 100755 --- a/zone/gm_commands/max_all_skills.cpp +++ b/zone/gm_commands/max_all_skills.cpp @@ -2,19 +2,19 @@ void command_max_all_skills(Client *c, const Seperator *sep) { - if (c) { - Client *client_target = (c->GetTarget() ? (c->GetTarget()->IsClient() ? c->GetTarget()->CastToClient() : c) - : c); - auto Skills = EQ::skills::GetSkillTypeMap(); - for (auto &skills_iter : Skills) { - auto skill_id = skills_iter.first; - auto current_skill_value = ( - (EQ::skills::IsSpecializedSkill(skill_id)) ? - 50 : - content_db.GetSkillCap(client_target->GetClass(), skill_id, client_target->GetLevel()) - ); - client_target->SetSkill(skill_id, current_skill_value); - } + auto t = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); } + + t->MaxSkills(); + + c->Message( + Chat::White, + fmt::format( + "Maxed skills for {}.", + c->GetTargetDescription(t) + ).c_str() + ); } diff --git a/zone/gm_commands/modifynpcstat.cpp b/zone/gm_commands/modifynpcstat.cpp index 5cde6e8f3..75047caf9 100755 --- a/zone/gm_commands/modifynpcstat.cpp +++ b/zone/gm_commands/modifynpcstat.cpp @@ -2,29 +2,129 @@ void command_modifynpcstat(Client *c, const Seperator *sep) { - if (!c) { + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #modifynpcstat [Stat] [Value]"); + ListModifyNPCStatMap(c); return; } - if (sep->arg[1][0] == '\0') { - c->Message(Chat::White, "usage #modifynpcstat arg value"); + if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { + c->Message(Chat::White, "You must target an NPC to use this command."); + return; + } + + auto target = c->GetTarget()->CastToNPC(); + + std::string stat = sep->arg[1]; + std::string value = sep->arg[2] ? sep->arg[2] : ""; + + auto stat_description = GetModifyNPCStatDescription(stat); + if (!stat_description.length()) { c->Message( Chat::White, - "Args: ac, str, sta, agi, dex, wis, _int, cha, max_hp, mr, fr, cr, pr, dr, runspeed, special_attacks, " - "attack_speed, atk, accuracy, trackable, min_hit, max_hit, see_invis_undead, see_hide, see_improved_hide, " - "hp_regen, mana_regen, aggro, assist, slow_mitigation, loottable_id, healscale, spellscale" + fmt::format( + "Stat '{}' does not exist.", + stat + ).c_str() ); return; } - if (!c->GetTarget()) { - return; - } + target->ModifyNPCStat(stat, value); - if (!c->GetTarget()->IsNPC()) { - return; - } + c->Message( + Chat::White, + fmt::format( + "Stat Modified | Target: {}", + c->GetTargetDescription(target) + ).c_str() + ); - c->GetTarget()->CastToNPC()->ModifyNPCStat(sep->arg[1], sep->arg[2]); + c->Message( + Chat::White, + fmt::format( + "Stat Modified | Stat: {} ({}) Value: {}", + GetModifyNPCStatDescription(stat), + stat, + value + ).c_str() + ); } +std::map GetModifyNPCStatMap() +{ + std::map identifiers_map = { + { "ac", "Armor Class" }, + { "accuracy", "Accuracy" }, + { "aggro", "Aggro" }, + { "agi", "Agility" }, + { "assist", "Assist" }, + { "atk", "Attack" }, + { "attack_count", "Attack Count" }, + { "attack_delay", "Attack Delay" }, + { "attack_speed", "Attack Speed" }, + { "avoidance", "Avoidance" }, + { "cha", "Charisma" }, + { "cr", "Cold Resist" }, + { "dex", "Dexterity" }, + { "dr", "Disease Resist" }, + { "fr", "Fire Resist" }, + { "healscale", "Heal Scale" }, + { "heroic_strikethrough", "Heroic Strikethrough" }, + { "hp_regen", "HP Regen" }, + { "hp_regen_per_second", "HP Regen Per Second" }, + { "int", "Intelligence" }, + { "_int", "Intelligence" }, + { "keeps_sold_items", "Keeps Sold Items" }, + { "level", "Level" }, + { "loottable_id", "Loottable ID" }, + { "mana_regen", "Mana Regen" }, + { "max_hit", "Maximum Damage" }, + { "max_hp", "Maximum Hit Points" }, + { "min_hit", "Minimum Damage" }, + { "mr", "Magic Resist" }, + { "npc_spells_id", "NPC Spells ID" }, + { "npc_spells_effects_id", "NPC Spells Effects ID" }, + { "phr", "Physical Resist" }, + { "pr", "Poison Resist" }, + { "runspeed", "Run Speed" }, + { "see_invis", "See Invisible" }, + { "see_invis_undead", "See Invisible vs. Undead" }, + { "see_hide", "See Hide" }, + { "see_improved_hide", "See Improved Hide" }, + { "slow_mitigation", "Slow Mitigation" }, + { "special_attacks", "Special Attacks" }, + { "special_abilities", "Special Abilities" }, + { "spellscale", "Spell Scale" }, + { "sta", "Stamina" }, + { "str", "Strength" }, + { "trackable", "Trackable" }, + { "wis", "Wisdom" } + }; + + return identifiers_map; +} + +std::string GetModifyNPCStatDescription(std::string stat) +{ + if (GetModifyNPCStatMap().find(stat) != GetModifyNPCStatMap().end()) { + return GetModifyNPCStatMap().find(stat)->second; + } + + return std::string(); +} + +void ListModifyNPCStatMap(Client *c) +{ + for (const auto& s : GetModifyNPCStatMap()) { + c->Message( + Chat::White, + fmt::format( + "Usage: #modifynpcstat {} [Value] - Modifies an NPC's {}", + s.first, + s.second + ).c_str() + ); + } +} diff --git a/zone/gm_commands/motd.cpp b/zone/gm_commands/motd.cpp index fdfba84b4..55a6d8ccc 100755 --- a/zone/gm_commands/motd.cpp +++ b/zone/gm_commands/motd.cpp @@ -5,11 +5,11 @@ extern WorldServer worldserver; void command_motd(Client *c, const Seperator *sep) { - auto outpack = new ServerPacket(ServerOP_Motd, sizeof(ServerMotd_Struct)); - ServerMotd_Struct *mss = (ServerMotd_Struct *) outpack->pBuffer; - strn0cpy(mss->myname, c->GetName(), 64); - strn0cpy(mss->motd, sep->argplus[1], 512); - worldserver.SendPacket(outpack); - safe_delete(outpack); + auto pack = new ServerPacket(ServerOP_Motd, sizeof(ServerMotd_Struct)); + auto m = (ServerMotd_Struct *) pack->pBuffer; + strn0cpy(m->myname, c->GetName(), sizeof(m->myname)); + strn0cpy(m->motd, sep->argplus[1], sizeof(m->motd)); + worldserver.SendPacket(pack); + safe_delete(pack); } diff --git a/zone/gm_commands/movechar.cpp b/zone/gm_commands/movechar.cpp index cec371b83..83e72cc37 100755 --- a/zone/gm_commands/movechar.cpp +++ b/zone/gm_commands/movechar.cpp @@ -7,7 +7,7 @@ void command_movechar(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #movechar [Character ID|Character Name] [Zone ID|Zone Short Name]"); return; } - + std::string character_name = ( sep->IsNumber(1) ? database.GetCharNameByID(std::stoul(sep->arg[1])) : @@ -27,7 +27,7 @@ void command_movechar(Client *c, const Seperator *sep) auto account_id = database.GetAccountIDByChar(character_name.c_str()); - std::string zone_short_name = str_tolower( + std::string zone_short_name = Strings::ToLower( sep->IsNumber(2) ? ZoneName(std::stoul(sep->arg[2]), true) : sep->arg[2] diff --git a/zone/gm_commands/mysql.cpp b/zone/gm_commands/mysql.cpp index 3c2bb8724..38cb60430 100755 --- a/zone/gm_commands/mysql.cpp +++ b/zone/gm_commands/mysql.cpp @@ -17,7 +17,7 @@ void command_mysql(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #mysql [Help|Query] [SQL Query]"); return; } - + if (is_help) { c->Message(Chat::White, "Usage: #mysql query \"Query goes here quoted\""); c->Message(Chat::White, "Note: To use 'LIKE \"%%something%%\" replace the %% with a #"); @@ -32,14 +32,14 @@ void command_mysql(Client *c, const Seperator *sep) } std::string query = sep->arg[2]; - find_replace(query, "#", "%"); + Strings::FindReplace(query, "#", "%"); auto results = database.QueryDatabase(query); if (!results.Success()) { return; } - query = sep->arg[2]; - find_replace(query, "#", "%%"); + query = sep->arg[2]; + Strings::FindReplace(query, "#", "%%"); c->Message( Chat::White, diff --git a/zone/gm_commands/npcedit.cpp b/zone/gm_commands/npcedit.cpp index 1332a61e6..ddabd6380 100755 --- a/zone/gm_commands/npcedit.cpp +++ b/zone/gm_commands/npcedit.cpp @@ -1,1444 +1,1791 @@ #include "../client.h" #include "../groups.h" -#include "../mob_movement_manager.h" -#include "../raids.h" #include "../raids.h" +#include "../../common/repositories/npc_types_repository.h" void command_npcedit(Client *c, const Seperator *sep) { if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { - c->Message(Chat::White, "Error: Must have NPC targeted"); + c->Message(Chat::White, "You must target an NPC to use this command."); return; } - if (strcasecmp(sep->arg[1], "help") == 0) { + int arguments = sep->argnum; - c->Message(Chat::White, "Help File for #npcedit. Syntax for commands are:"); - c->Message(Chat::White, "#npcedit name - Sets an NPC's Name"); - c->Message(Chat::White, "#npcedit lastname - Sets an NPC's Lastname"); - c->Message(Chat::White, "#npcedit level - Sets an NPC's Level"); - c->Message(Chat::White, "#npcedit race - Sets an NPC's Race"); - c->Message(Chat::White, "#npcedit class - Sets an NPC's Class"); - c->Message(Chat::White, "#npcedit bodytype - Sets an NPC's Bodytype"); - c->Message(Chat::White, "#npcedit hp - Sets an NPC's Hitpoints"); - c->Message(Chat::White, "#npcedit mana - Sets an NPC's Mana"); - c->Message(Chat::White, "#npcedit gender - Sets an NPC's Gender"); - c->Message(Chat::White, "#npcedit texture - Sets an NPC's Texture"); - c->Message(Chat::White, "#npcedit helmtexture - Sets an NPC's Helmet Texture"); - c->Message(Chat::White, "#npcedit herosforgemodel - Sets an NPC's Hero's Forge Model"); - c->Message(Chat::White, "#npcedit size - Sets an NPC's Size"); - c->Message(Chat::White, "#npcedit hpregen - Sets an NPC's Hitpoints Regeneration Rate Per Tick"); - c->Message(Chat::White, "#npcedit hp_regen_per_second - Sets an NPC's HP regeneration per second"); - c->Message(Chat::White, "#npcedit manaregen - Sets an NPC's Mana Regeneration Rate Per Tick"); - c->Message(Chat::White, "#npcedit loottable - Sets an NPC's Loottable ID"); - c->Message(Chat::White, "#npcedit merchantid - Sets an NPC's Merchant ID"); - c->Message(Chat::White, "#npcedit alt_currency_id - Sets an NPC's Alternate Currency ID"); - c->Message(Chat::White, "#npcedit spell - Sets an NPC's Spells List ID"); - c->Message(Chat::White, "#npcedit npc_spells_effects_id - Sets an NPC's Spell Effects ID"); - c->Message(Chat::White, "#npcedit faction - Sets an NPC's Faction ID"); - c->Message(Chat::White, "#npcedit adventure_template_id - Sets an NPC's Adventure Template ID"); - c->Message(Chat::White, "#npcedit trap_template - Sets an NPC's Trap Template ID"); - c->Message(Chat::White, "#npcedit damage [minimum] [maximum] - Sets an NPC's Damage"); - c->Message(Chat::White, "#npcedit attackcount - Sets an NPC's Attack Count"); - c->Message(Chat::White, "#npcedit special_attacks - Sets an NPC's Special Attacks"); - c->Message(Chat::White, "#npcedit special_abilities - Sets an NPC's Special Abilities"); - c->Message(Chat::White, "#npcedit aggroradius - Sets an NPC's Aggro Radius"); - c->Message(Chat::White, "#npcedit assistradius - Sets an NPC's Assist Radius"); - c->Message(Chat::White, "#npcedit featuresave - Saves an NPC's current facial features to the database"); - c->Message(Chat::White, "#npcedit armortint_id - Sets an NPC's Armor Tint ID"); - c->Message(Chat::White, "#npcedit color [red] [green] [blue] - Sets an NPC's Red, Green, and Blue armor tint"); - c->Message(Chat::White, "#npcedit ammoidfile - Sets an NPC's Ammo ID File"); - c->Message( - Chat::White, - "#npcedit weapon [primary_model] [secondary_model] - Sets an NPC's Primary and Secondary Weapon Model" - ); - c->Message(Chat::White, "#npcedit meleetype [primary_type] [secondary_type] - Sets an NPC's Melee Types"); - c->Message(Chat::White, "#npcedit rangedtype - Sets an NPC's Ranged Type"); - c->Message(Chat::White, "#npcedit runspeed - Sets an NPC's Run Speed"); - c->Message(Chat::White, "#npcedit mr - Sets an NPC's Magic Resistance"); - c->Message(Chat::White, "#npcedit pr - Sets an NPC's Poison Resistance"); - c->Message(Chat::White, "#npcedit dr - Sets an NPC's Disease Resistance"); - c->Message(Chat::White, "#npcedit fr - Sets an NPC's Fire Resistance"); - c->Message(Chat::White, "#npcedit cr - Sets an NPC's Cold Resistance"); - c->Message(Chat::White, "#npcedit corrup - Sets an NPC's Corruption Resistance"); - c->Message(Chat::White, "#npcedit phr - Sets and NPC's Physical Resistance"); - c->Message( - Chat::White, - "#npcedit seeinvis - Sets an NPC's See Invisible Flag [0 = Cannot See Invisible, 1 = Can See Invisible]" - ); - c->Message( - Chat::White, - "#npcedit seeinvisundead - Sets an NPC's See Invisible vs. Undead Flag [0 = Cannot See Invisible vs. Undead, 1 = Can See Invisible vs. Undead]" - ); - c->Message( - Chat::White, - "#npcedit qglobal - Sets an NPC's Quest Global Flag [0 = Quest Globals Off, 1 = Quest Globals On]" - ); - c->Message(Chat::White, "#npcedit ac - Sets an NPC's Armor Class"); - c->Message( - Chat::White, - "#npcedit npcaggro - Sets an NPC's NPC Aggro Flag [0 = Aggro NPCs Off, 1 = Aggro NPCs On]" - ); - c->Message(Chat::White, "#npcedit spawn_limit - Sets an NPC's Spawn Limit Counter"); - c->Message(Chat::White, "#npcedit attackspeed - Sets an NPC's Attack Speed Modifier"); - c->Message(Chat::White, "#npcedit attackdelay - Sets an NPC's Attack Delay"); - c->Message(Chat::White, "#npcedit findable - Sets an NPC's Findable Flag [0 = Not Findable, 1 = Findable]"); - c->Message(Chat::White, "#npcedit str - Sets an NPC's Strength"); - c->Message(Chat::White, "#npcedit sta - Sets an NPC's Stamina"); - c->Message(Chat::White, "#npcedit dex - Sets an NPC's Dexterity"); - c->Message(Chat::White, "#npcedit agi - Sets an NPC's Agility"); - c->Message(Chat::White, "#npcedit int - Sets an NPC's Intelligence"); - c->Message(Chat::White, "#npcedit wis - Sets an NPC's Wisdom"); - c->Message(Chat::White, "#npcedit cha - Sets an NPC's Charisma"); - c->Message( - Chat::White, - "#npcedit seehide - Sets an NPC's See Hide Flag [0 = Cannot See Hide, 1 = Can See Hide]" - ); - c->Message( - Chat::White, - "#npcedit seeimprovedhide - Sets an NPC's See Improved Hide Flag [0 = Cannot See Improved Hide, 1 = Can See Improved Hide]" - ); - c->Message(Chat::White, "#npcedit trackable - Sets an NPC's Trackable Flag [0 = Not Trackable, 1 = Trackable]"); - c->Message(Chat::White, "#npcedit atk - Sets an NPC's Attack"); - c->Message(Chat::White, "#npcedit accuracy - Sets an NPC's Accuracy"); - c->Message(Chat::White, "#npcedit avoidance - Sets an NPC's Avoidance"); - c->Message(Chat::White, "#npcedit slow_mitigation - Sets an NPC's Slow Mitigation"); - c->Message(Chat::White, "#npcedit version - Sets an NPC's Version"); - c->Message(Chat::White, "#npcedit maxlevel - Sets an NPC's Maximum Level"); - c->Message(Chat::White, "#npcedit scalerate - Sets an NPC's Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]"); - c->Message( - Chat::White, - "#npcedit spellscale - Sets an NPC's Spell Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" - ); - c->Message( - Chat::White, - "#npcedit healscale - Sets an NPC's Heal Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" - ); - c->Message( - Chat::White, - "#npcedit no_target - Sets an NPC's No Target Hotkey Flag [0 = Not Targetable with Target Hotkey, 1 = Targetable with Target Hotkey]" - ); - c->Message( - Chat::White, - "#npcedit raidtarget - Sets an NPC's Raid Target Flag [0 = Not a Raid Target, 1 = Raid Target]" - ); - c->Message(Chat::White, "#npcedit armtexture - Sets an NPC's Arm Texture"); - c->Message(Chat::White, "#npcedit bracertexture - Sets an NPC's Bracer Texture"); - c->Message(Chat::White, "#npcedit handtexture - Sets an NPC's Hand Texture"); - c->Message(Chat::White, "#npcedit legtexture - Sets an NPC's Leg Texture"); - c->Message(Chat::White, "#npcedit feettexture - Sets an NPC's Feet Texture"); - c->Message(Chat::White, "#npcedit walkspeed - Sets an NPC's Walk Speed"); - c->Message(Chat::White, "#npcedit show_name - Sets an NPC's Show Name Flag [0 = Hidden, 1 = Shown]"); - c->Message( - Chat::White, - "#npcedit untargetable - Sets an NPC's Untargetable Flag [0 = Targetable, 1 = Untargetable]" - ); - c->Message(Chat::White, "#npcedit charm_ac - Sets an NPC's Armor Class while Charmed"); - c->Message(Chat::White, "#npcedit charm_min_dmg - Sets an NPC's Minimum Damage while Charmed"); - c->Message(Chat::White, "#npcedit charm_max_dmg - Sets an NPC's Max Damage while Charmed"); - c->Message(Chat::White, "#npcedit charm_attack_delay - Sets an NPC's Attack Delay while Charmed"); - c->Message(Chat::White, "#npcedit charm_accuracy_rating - Sets an NPC's Accuracy Rating while Charmed"); - c->Message(Chat::White, "#npcedit charm_avoidance_rating - Sets an NPC's Avoidance Rating while Charmed"); - c->Message(Chat::White, "#npcedit charm_atk - Sets an NPC's Attack while Charmed"); - c->Message( - Chat::White, - "#npcedit skip_global_loot - Sets an NPC's Skip Global Loot Flag [0 = Don't Skip, 1 = Skip" - ); - c->Message( - Chat::White, - "#npcedit rarespawn - Sets an NPC's Rare Spawn Flag [0 = Not a Rare Spawn, 1 = Rare Spawn]" - ); - c->Message( - Chat::White, - "#npcedit stuck_behavior - Sets an NPC's Stuck Behavior [0 = Run to Target, 1 = Warp to Target, 2 = Take No Action, 3 = Evade Combat]" - ); - c->Message( - Chat::White, - "#npcedit flymode - Sets an NPC's Fly Mode [0 = Ground, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating While Running]" - ); - c->Message( - Chat::White, - "#npcedit always_aggro - Sets an NPC's Always Aggro Flag [0 = Does not Always Aggro, 1 = Always Aggro]" - ); - c->Message( - Chat::White, - "#npcedit exp_mod - Sets an NPC's Experience Modifier [50 = 50%, 100 = 100%, 200 = 200%]" - ); - c->Message(Chat::White, "#npcedit setanimation - Sets an NPC's Animation on Spawn (Stored in spawn2 table)"); - c->Message( - Chat::White, - "#npcedit respawntime - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)" - ); - } - - uint32 npc_id = c->GetTarget()->CastToNPC()->GetNPCTypeID(); - if (strcasecmp(sep->arg[1], "name") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has the name '{}'.", npc_id, sep->arg[2]).c_str()); - std::string query = fmt::format("UPDATE npc_types SET name = '{}' WHERE id = {}", sep->arg[2], npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "lastname") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has the lastname '{}'.", npc_id, sep->arg[2]).c_str()); - std::string query = fmt::format("UPDATE npc_types SET lastname = '{}' WHERE id = {}", sep->arg[2], npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "level") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} is now level {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET level = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "race") == 0) { - auto race_id = atoi(sep->arg[2]); - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now a {} ({}).", npc_id, GetRaceIDName(race_id), race_id).c_str()); - std::string query = fmt::format("UPDATE npc_types SET race = {} WHERE id = {}", race_id, npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "class") == 0) { - auto class_id = atoi(sep->arg[2]); - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now a {} ({}).", npc_id, GetClassIDName(class_id), class_id).c_str()); - std::string query = fmt::format("UPDATE npc_types SET class = {} WHERE id = {}", class_id, npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "bodytype") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is now using Bodytype {} ({}).", - npc_id, - EQ::constants::GetBodyTypeName(static_cast(std::stoul(sep->arg[2]))), - std::stoul(sep->arg[2]) - ).c_str() - ); - std::string query = fmt::format( - "UPDATE npc_types SET bodytype = {} WHERE id = {}", - std::stoul(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "hp") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now has {} Health.", - npc_id, - std::strtoll(sep->arg[2], nullptr, 10) - ).c_str() - ); - std::string query = fmt::format("UPDATE npc_types SET hp = {} WHERE id = {}", strtoull(sep->arg[2], nullptr, 10), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "mana") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Mana.", npc_id, std::strtoll(sep->arg[2], nullptr, 10)).c_str()); - std::string query = fmt::format("UPDATE npc_types SET mana = {} WHERE id = {}", std::strtoll(sep->arg[2], nullptr, 10), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "gender") == 0) { - auto gender_id = atoi(sep->arg[2]); - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now a {} ({}).", npc_id, gender_id, GetGenderName(gender_id)).c_str()); - std::string query = fmt::format("UPDATE npc_types SET gender = {} WHERE id = {}", gender_id, npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "texture") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} is now using Texture {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET texture = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "helmtexture") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Helmet Texture {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET helmtexture = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "herosforgemodel") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Hero's Forge Model {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET herosforgemodel = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "size") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} is now Size {:.2f}.", npc_id, atof(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET size = {:.2f} WHERE id = {}", atof(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "hpregen") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now regenerates {} Health per Tick.", npc_id, std::strtoll(sep->arg[2], nullptr, 10)).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET hp_regen_rate = {} WHERE id = {}", - std::strtoll(sep->arg[2], nullptr, 10), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "hp_regen_per_second") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now regenerates {} HP per second.", - npc_id, - std::strtoll(sep->arg[2], nullptr, 10)).c_str() - ); - std::string query = fmt::format( - "UPDATE npc_types SET hp_regen_per_second = {} WHERE id = {}", - std::strtoll(sep->arg[2], nullptr, 10), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "manaregen") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now regenerates {} Mana per Tick.", npc_id, std::strtoll(sep->arg[2], nullptr, 10)).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET mana_regen_rate = {} WHERE id = {}", - std::strtoll(sep->arg[2], nullptr, 10), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "loottable") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using loottable ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET loottable_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "merchantid") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using merchant ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET merchant_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "alt_currency_id") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Alternate Currency ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET alt_currency_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "spell") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Spell List ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET npc_spells_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "npc_spells_effects_id") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using NPC Spells Effects ID {}.", npc_id, sep->arg[2]).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET npc_spells_effects_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "faction") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Faction ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET npc_faction_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "adventure_template_id") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Adventure Template ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET adventure_template_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "trap_template") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Trap Template ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET trap_template = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "damage") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now hits from {} to {} damage.", - npc_id, - atoi(sep->arg[2]), - atoi(sep->arg[3])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET mindmg = {}, maxdmg = {} WHERE id = {}", - atoi(sep->arg[2]), - atoi(sep->arg[3]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "attackcount") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has an Attack Count of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET attack_count = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "special_attacks") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is now using the following Special Attacks '{}'.", - npc_id, - sep->arg[2] - ).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET npcspecialattks = '{}' WHERE id = {}", - sep->arg[2], - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "special_abilities") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is now using the following Special Abilities '{}'.", - npc_id, - sep->arg[2] - ).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET special_abilities = '{}' WHERE id = {}", - sep->arg[2], - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "aggroradius") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has an Aggro Radius of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET aggroradius = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "assistradius") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has an Assist Radius of {}", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET assistradius = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "featuresave") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} saved with all current body and facial feature settings.", npc_id).c_str()); - Mob *target = c->GetTarget(); - std::string query = fmt::format( - "UPDATE npc_types " - "SET luclin_haircolor = {}, luclin_beardcolor = {}, " - "luclin_eyecolor = {}, luclin_eyecolor2 = {}, " - "luclin_hairstyle = {}, luclin_beard = {}, " - "face = {}, drakkin_heritage = {}, " - "drakkin_tattoo = {}, drakkin_details = {}, " - "texture = {}, helmtexture = {}, " - "gender = {}, size = {:.2f} " - "WHERE id = {}", - target->GetHairColor(), - target->GetBeardColor(), - target->GetEyeColor1(), - target->GetEyeColor2(), - target->GetHairStyle(), - target->GetBeard(), - target->GetLuclinFace(), - target->GetDrakkinHeritage(), - target->GetDrakkinTattoo(), - target->GetDrakkinDetails(), - target->GetTexture(), - target->GetHelmTexture(), - target->GetGender(), - target->GetSize(), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "armortint_id") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Armor Tint ID {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET armortint_id = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "color") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now has {} Red, {} Green, and {} Blue tinting on their armor.", - npc_id, - atoi(sep->arg[2]), - atoi(sep->arg[3]), - atoi(sep->arg[4])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET armortint_red = {}, armortint_green = {}, armortint_blue = {} WHERE id = {}", - atoi(sep->arg[2]), - atoi(sep->arg[3]), - atoi(sep->arg[4]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "ammoidfile") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Ammo ID File {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET ammo_idfile = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "weapon") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} will have Model {} set to their Primary and Model {} set to their Secondary on repop.", - npc_id, - atoi(sep->arg[2]), - atoi(sep->arg[3])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET d_melee_texture1 = {}, d_melee_texture2 = {} WHERE id = {}", - atoi(sep->arg[2]), - atoi(sep->arg[3]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "meleetype") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now has a Primary Melee Type of {} and a Secondary Melee Type of {}.", - npc_id, - atoi(sep->arg[2]), - atoi(sep->arg[3])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET prim_melee_type = {}, sec_melee_type = {} WHERE id = {}", - atoi(sep->arg[2]), - atoi(sep->arg[3]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "rangedtype") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Ranged Type of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET ranged_type = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "runspeed") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now runs at {:.2f}.", npc_id, atof(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET runspeed = {:.2f} WHERE id = {}", - atof(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "mr") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Magic Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET MR = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "pr") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Poison Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET PR = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "dr") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Disease Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET DR = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "fr") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Fire Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET FR = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "cr") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Cold Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET CR = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "corrup") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Corruption Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET corrup = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "phr") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Physical Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET PhR = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "seeinvis") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} can {} See Invisible.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format("UPDATE npc_types SET see_invis = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "seeinvisundead") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} can {} See Invisible vs. Undead.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET see_invis_undead = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "qglobal") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} can {} use Quest Globals.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format("UPDATE npc_types SET qglobal = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "ac") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Armor Class.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET ac = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "npcaggro") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} will {} aggro other NPCs that have a hostile faction.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format("UPDATE npc_types SET npc_aggro = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "spawn_limit") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Spawn Limit of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET spawn_limit = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "attackspeed") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has an Attack Speed of {:.2f}.", npc_id, atof(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET attack_speed = {:.2f} WHERE id = {}", - atof(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "attackdelay") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has an Attack Delay of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET attack_delay = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "findable") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is {} Findable.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format("UPDATE npc_types SET findable = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "str") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Strength.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET STR = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "sta") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Stamina.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET STA = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "agi") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Agility.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET AGI = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "dex") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Dexterity.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET DEX = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "int") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Intelligence.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET _INT = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "wis") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Magic Resistance of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET WIS = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "cha") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Charisma.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET CHA = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "seehide") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} can {} See Hide.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format("UPDATE npc_types SET see_hide = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "seeimprovedhide") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} can {} See Improved Hide.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET see_improved_hide = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "trackable") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is {} Trackable.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format("UPDATE npc_types SET trackable = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "atk") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Attack.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET atk = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "accuracy") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Accuracy.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET accuracy = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "avoidance") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now has {} Avoidance.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET avoidance = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "slow_mitigation") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has {} Slow Mitigation.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET slow_mitigation = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "version") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} is now using Version {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET version = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "maxlevel") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Maximum Level of {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET maxlevel = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "scalerate") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Scaling Rate of {}%%.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET scalerate = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "spellscale") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Spell Scaling Rate of {}%%.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET spellscale = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "healscale") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has a Heal Scaling Rate of {}%%.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET healscale = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } + bool is_help = (!arguments || !strcasecmp(sep->arg[1], "help")); - if (strcasecmp(sep->arg[1], "no_target") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is {} Targetable with Target Hotkey.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET no_target_hotkey = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); + if (is_help) { + SendNPCEditSubCommands(c); return; } - if (strcasecmp(sep->arg[1], "raidtarget") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is {} designated as a Raid Target.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET raid_target = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } + std::string sub_command = sep->arg[1]; - if (strcasecmp(sep->arg[1], "armtexture") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Arm Texture {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET armtexture = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "bracertexture") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Bracer Texture {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET bracertexture = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } + auto t = c->GetTarget()->CastToNPC(); + auto npc_id = t->GetNPCTypeID(); + auto npc_id_string = fmt::format( + "NPC ID {}", + Strings::Commify(std::to_string(npc_id)) + ); - if (strcasecmp(sep->arg[1], "handtexture") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Hand Texture {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET handtexture = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); + auto n = NpcTypesRepository::FindOne(content_db, npc_id); + if (!n.id) { + c->Message(Chat::White, "You must target a valid NPC to use this command."); return; } - if (strcasecmp(sep->arg[1], "legtexture") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Leg Texture {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET legtexture = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "feettexture") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} is now using Feet Texture {}.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET feettexture = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "walkspeed") == 0) { - c->Message(Chat::Yellow, fmt::format("NPC ID {} now walks at {:.2f}.", npc_id, atof(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET walkspeed = {:.2f} WHERE id = {}", - atof(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "show_name") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} will {} show their name.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format("UPDATE npc_types SET show_name = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "untargetable") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} will {} be untargetable.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET untargetable = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "charm_ac") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has {} Armor Class while Charmed.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET charm_ac = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "charm_min_dmg") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now does {} Minimum Damage while Charmed.", - npc_id, - atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET charm_min_dmg = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "charm_max_dmg") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now does {} Maximum Damage while Charmed.", - npc_id, - atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET charm_max_dmg = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "charm_attack_delay") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has {} Attack Delay while Charmed.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET charm_attack_delay = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "charm_accuracy_rating") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now has {} Accuracy Rating while Charmed.", - npc_id, - atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET charm_accuracy_rating = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "charm_avoidance_rating") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now has {} Avoidance Rating while Charmed.", - npc_id, - atoi(sep->arg[2])).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET charm_avoidance_rating = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "charm_atk") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has {} Attack while Charmed.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET charm_atk = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "skip_global_loot") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} will {} skip Global Loot.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET skip_global_loot = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "rarespawn") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is {} designated as a Rare Spawn.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET rare_spawn = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } + std::string d; - if (strcasecmp(sep->arg[1], "stuck_behavior") == 0) { - auto behavior_id = atoi(sep->arg[2]); - std::string behavior_name = "Unknown"; - if (behavior_id == MobStuckBehavior::RunToTarget) { - behavior_name = "Run To Target"; + if (!strcasecmp(sep->arg[1], "name")) { + std::string name = sep->argplus[2]; + if (!name.empty()) { + n.name = name; + d = fmt::format( + "{} is now named '{}'.", + npc_id_string, + name + ); + } else { + c->Message(Chat::White, "Usage: #npcedit name [Name] - Sets an NPC's Name"); + return; } - else if (behavior_id == MobStuckBehavior::WarpToTarget) { - behavior_name = "Warp To Target"; - } - else if (behavior_id == MobStuckBehavior::TakeNoAction) { - behavior_name = "Take No Action"; - } - else if (behavior_id == MobStuckBehavior::EvadeCombat) { - behavior_name = "Evade Combat"; - } - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is now using Stuck Behavior {} ({}).", - npc_id, - behavior_name, - behavior_id - ).c_str()); - std::string query = fmt::format("UPDATE npc_types SET stuck_behavior = {} WHERE id = {}", behavior_id, npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "flymode") == 0) { - auto flymode_id = static_cast(std::stoul(sep->arg[2])); - std::string flymode_name = EQ::constants::GetFlyModeName(flymode_id); - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} is now using Fly Mode {} ({}).", - npc_id, - flymode_name, - flymode_id - ).c_str() + } else if (!strcasecmp(sep->arg[1], "lastname")) { + std::string last_name = sep->argplus[2]; + n.lastname = last_name; + d = fmt::format( + "{} now has the lastname '{}'.", + npc_id_string, + last_name ); - std::string query = fmt::format("UPDATE npc_types SET flymode = {} WHERE id = {}", flymode_id, npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "always_aggro") == 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} will {} Always Aggro.", - npc_id, - (atoi(sep->arg[2]) == 1 ? "now" : "no longer")).c_str()); - std::string query = fmt::format( - "UPDATE npc_types SET always_aggro = {} WHERE id = {}", - atoi(sep->arg[2]), - npc_id - ); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "exp_mod") == 0) { - c->Message( - Chat::Yellow, - fmt::format("NPC ID {} now has an Experience Modifier of {}%%.", npc_id, atoi(sep->arg[2])).c_str()); - std::string query = fmt::format("UPDATE npc_types SET exp_mod = {} WHERE id = {}", atoi(sep->arg[2]), npc_id); - content_db.QueryDatabase(query); - return; - } - - if (strcasecmp(sep->arg[1], "setanimation") == 0) { - int animation = 0; - std::string animation_name = "Unknown"; - if (sep->arg[2] && atoi(sep->arg[2]) <= 4) { - if (strcasecmp(sep->arg[2], "stand") == 0 || atoi(sep->arg[2]) == 0) { // Stand - animation = 0; - animation_name = "Standing"; - } - else if (strcasecmp(sep->arg[2], "sit") == 0 || atoi(sep->arg[2]) == 1) { // Sit - animation = 1; - animation_name = "Sitting"; - } - else if (strcasecmp(sep->arg[2], "crouch") == 0 || atoi(sep->arg[2]) == 2) { // Crouch - animation = 2; - animation_name = "Crouching"; - } - else if (strcasecmp(sep->arg[2], "dead") == 0 || atoi(sep->arg[2]) == 3) { // Dead - animation = 3; - animation_name = "Dead"; - } - else if (strcasecmp(sep->arg[2], "loot") == 0 || atoi(sep->arg[2]) == 4) { // Looting Animation - animation = 4; - animation_name = "Looting"; - } + } else if (!strcasecmp(sep->arg[1], "level")) { + if (sep->IsNumber(2)) { + auto level = static_cast(std::stoul(sep->arg[2])); + n.level = level; + d = fmt::format( + "{} is now level {}.", + npc_id_string, + level + ); + } else { + c->Message(Chat::White, "Usage: #npcedit level [Level] - Sets an NPC's Level"); + return; } - else { + } else if (!strcasecmp(sep->arg[1], "race")) { + if (sep->IsNumber(2)) { + auto race_id = static_cast(std::stoul(sep->arg[2])); + n.race = race_id; + d = fmt::format( + "{} is now a(n) {} ({}).", + npc_id_string, + GetRaceIDName(race_id), + race_id + ); + } else { + c->Message(Chat::White, "Usage: #npcedit race [Race ID] - Sets an NPC's Race"); + return; + } + } else if (!strcasecmp(sep->arg[1], "class")) { + if (sep->IsNumber(2)) { + auto class_id = static_cast(std::stoul(sep->arg[2])); + n.class_ = class_id; + d = fmt::format( + "{} is now a(n) {} ({}).", + npc_id_string, + GetClassIDName(class_id), + class_id + ); + } else { + c->Message(Chat::White, "Usage: #npcedit class [Class ID] - Sets an NPC's Class"); + return; + } + } else if (!strcasecmp(sep->arg[1], "bodytype")) { + if (sep->IsNumber(2)) { + auto body_type_id = static_cast(std::stoul(sep->arg[2])); + auto body_type_name = EQ::constants::GetBodyTypeName(static_cast(body_type_id)); + n.bodytype = body_type_id; + d = fmt::format( + "{} is now using Body Type {}.", + npc_id_string, + ( + !body_type_name.empty() ? + fmt::format( + "{} ({})", + body_type_name, + body_type_id + ) : + std::to_string(body_type_id) + ) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit bodytype [Body Type ID] - Sets an NPC's Bodytype"); + return; + } + } else if (!strcasecmp(sep->arg[1], "hp")) { + if (sep->IsNumber(2)) { + auto hp = std::stoll(sep->arg[2]); + n.hp = hp; + d = fmt::format( + "{} now has {} Health.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit hp [HP] - Sets an NPC's HP"); + return; + } + } else if (!strcasecmp(sep->arg[1], "mana")) { + if (sep->IsNumber(2)) { + auto mana = std::stoll(sep->arg[2]); + n.mana = mana; + d = fmt::format( + "{} now has {} Mana.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit mana [Mana] - Sets an NPC's Mana"); + return; + } + } else if (!strcasecmp(sep->arg[1], "gender")) { + if (sep->IsNumber(2)) { + auto gender_id = static_cast(std::stoul(sep->arg[2])); + n.gender = gender_id; + d = fmt::format( + "{} is now a {} ({}).", + npc_id_string, + gender_id, + GetGenderName(gender_id) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit gender [Gender ID] - Sets an NPC's Gender"); + return; + } + } else if (!strcasecmp(sep->arg[1], "texture")) { + if (sep->IsNumber(2)) { + auto texture = static_cast(std::stoul(sep->arg[2])); + n.texture = texture; + d = fmt::format( + "{} is now using Texture {}.", + npc_id_string, + texture + ); + } else { + c->Message(Chat::White, "Usage: #npcedit texture [Texture] - Sets an NPC's Texture"); + return; + } + } else if (!strcasecmp(sep->arg[1], "helmtexture")) { + if (sep->IsNumber(2)) { + auto helmet_texture = static_cast(std::stoul(sep->arg[2])); + n.helmtexture = helmet_texture; + d = fmt::format( + "{} is now using Helmet Texture {}.", + npc_id_string, + helmet_texture + ); + } else { + c->Message(Chat::White, "Usage: #npcedit helmtexture [Helmet Texture] - Sets an NPC's Helmet Texture"); + return; + } + } else if (!strcasecmp(sep->arg[1], "herosforgemodel")) { + if (sep->IsNumber(2)) { + auto heros_forge_model = std::stoi(sep->arg[2]); + n.herosforgemodel = heros_forge_model; + d = fmt::format( + "{} is now using Hero's Forge Model {}.", + npc_id_string, + heros_forge_model + ); + } else { c->Message( Chat::White, - "You must specify an Animation (0 = Stand, 1 = Sit, 2 = Crouch, 3 = Dead, 4 = Loot)" + "Usage: #npcedit herosforgemodel [Model Number] - Sets an NPC's Hero's Forge Model" ); - c->Message(Chat::White, "Example: #npcedit setanimation sit"); - c->Message(Chat::White, "Example: #npcedit setanimation 0"); return; } - + } else if (!strcasecmp(sep->arg[1], "size")) { + if (sep->IsNumber(2)) { + auto size = std::stof(sep->arg[2]); + n.size = size; + d = fmt::format( + "{} is now Size {:.2f}.", + npc_id_string, + size + ); + } else { + c->Message(Chat::White, "Usage: #npcedit size [Size] - Sets an NPC's Size"); + return; + } + } else if (!strcasecmp(sep->arg[1], "hpregen")) { + if (sep->IsNumber(2)) { + auto hp_regen = std::stoll(sep->arg[2]); + n.hp_regen_rate = hp_regen; + d = fmt::format( + "{} now regenerates {} Health per Tick.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit hpregen [HP Regen] - Sets an NPC's HP Regen Rate Per Tick"); + return; + } + } else if (!strcasecmp(sep->arg[1], "hp_regen_per_second")) { + if (sep->IsNumber(2)) { + auto hp_regen_per_second = std::stoll(sep->arg[2]); + n.hp_regen_per_second = hp_regen_per_second; + d = fmt::format( + "{} now regenerates {} HP per Second.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit hp_regen_per_second [HP Regen] - Sets an NPC's HP Regen Rate Per Second" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "manaregen")) { + if (sep->IsNumber(2)) { + auto mana_regen = std::stoll(sep->arg[2]); + n.mana_regen_rate = mana_regen; + d = fmt::format( + "{} now regenerates {} Mana per Tick.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit manaregen [Mana Regen] - Sets an NPC's Mana Regen Rate Per Tick"); + return; + } + } else if (!strcasecmp(sep->arg[1], "loottable")) { + if (sep->IsNumber(2)) { + auto loottable_id = std::stoul(sep->arg[2]); + n.loottable_id = loottable_id; + d = fmt::format( + "{} is now using Loottable ID {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit loottable [Loottable ID] - Sets an NPC's Loottable ID"); + return; + } + } else if (!strcasecmp(sep->arg[1], "merchantid")) { + if (sep->IsNumber(2)) { + auto merchant_id = std::stoul(sep->arg[2]); + n.merchant_id = merchant_id; + d = fmt::format( + "{} is now using Merchant ID {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit merchantid [Merchant ID] - Sets an NPC's Merchant ID"); + return; + } + } else if (!strcasecmp(sep->arg[1], "alt_currency_id")) { + if (sep->IsNumber(2)) { + auto alternate_currency_id = std::stoul(sep->arg[2]); + auto alternate_currency_item_id = zone->GetCurrencyItemID(alternate_currency_id); + n.alt_currency_id = alternate_currency_id; + d = fmt::format( + "{} is now using Alternate Currency {}.", + npc_id_string, + ( + alternate_currency_item_id ? + fmt::format( + "{} ({})", + database.CreateItemLink(alternate_currency_item_id), + alternate_currency_id + ) : + std::to_string(alternate_currency_id) + ) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit alt_currency_id [Alternate Currency ID] - Sets an NPC's Alternate Currency ID" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "spell")) { + if (sep->IsNumber(2)) { + auto spell_list_id = std::stoul(sep->arg[2]); + n.npc_spells_id = spell_list_id; + d = fmt::format( + "{} is now using Spell List ID {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit spell [Spell List ID] - Sets an NPC's Spells List ID"); + return; + } + } else if (!strcasecmp(sep->arg[1], "npc_spells_effects_id")) { + if (sep->IsNumber(2)) { + auto spell_effects_id = std::stoul(sep->arg[2]); + n.npc_spells_effects_id = spell_effects_id; + d = fmt::format( + "{} is now using Spells Effects ID {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit npc_spells_effects_id [Spell Effects ID] - Sets an NPC's Spell Effects ID" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "faction")) { + if (sep->IsNumber(2)) { + auto faction_id = std::stoi(sep->arg[2]); + auto faction_name = content_db.GetFactionName(faction_id); + n.npc_faction_id = faction_id; + d = fmt::format( + "{} is now using Faction {}.", + npc_id_string, + ( + !faction_name.empty() ? + fmt::format( + "{} ({})", + faction_name, + faction_id + ) : + Strings::Commify(sep->arg[2]) + ) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit faction [Faction ID] - Sets an NPC's Faction ID"); + return; + } + } else if (!strcasecmp(sep->arg[1], "adventure_template_id")) { + if (sep->IsNumber(2)) { + auto adventure_template_id = std::stoul(sep->arg[2]); + n.adventure_template_id = adventure_template_id; + d = fmt::format( + "{} is now using Adventure Template ID {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit adventure_template_id [Template ID] - Sets an NPC's Adventure Template ID" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "trap_template")) { + if (sep->IsNumber(2)) { + auto trap_template = std::stoul(sep->arg[2]); + n.trap_template = trap_template; + d = fmt::format( + "{} is now using Trap Template ID {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit trap_template [Template ID] - Sets an NPC's Trap Template ID"); + return; + } + } else if (!strcasecmp(sep->arg[1], "damage")) { + if (sep->IsNumber(2) && sep->IsNumber(3)) { + auto minimum_damage = std::stoul(sep->arg[2]); + auto maximum_damage = std::stoul(sep->arg[3]); + n.mindmg = minimum_damage; + n.maxdmg = maximum_damage; + d = fmt::format( + "{} now hits from {} to {} damage.", + npc_id_string, + Strings::Commify(sep->arg[2]), + Strings::Commify(sep->arg[3]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit damage [Minimum] [Maximum] - Sets an NPC's Damage"); + return; + } + } else if (!strcasecmp(sep->arg[1], "attackcount")) { + if (sep->IsNumber(2)) { + auto attack_count = static_cast(std::stoi(sep->arg[2])); + n.attack_count = attack_count; + d = fmt::format( + "{} now has an Attack Count of {}.", + npc_id_string, + attack_count + ); + } else { + c->Message(Chat::White, "Usage: #npcedit attackcount [Attack Count] - Sets an NPC's Attack Count"); + return; + } + } else if (!strcasecmp(sep->arg[1], "special_attacks")) { + std::string special_attacks = sep->argplus[2]; + n.npcspecialattks = special_attacks; c->Message( Chat::Yellow, fmt::format( - "NPC ID {} now has their Spawn Animation set to {} ({}) on Spawn Group ID {}.", - npc_id, - animation_name, - animation, - c->GetTarget()->CastToNPC()->GetSpawnGroupId() + "{} is now using the following Special Attacks '{}'.", + npc_id_string, + special_attacks ).c_str() ); - std::string query = fmt::format( - "UPDATE spawn2 SET animation = {} WHERE spawngroupID = {}", - animation, - c->GetTarget()->CastToNPC()->GetSpawnGroupId() + } else if (!strcasecmp(sep->arg[1], "special_abilities")) { + std::string special_abilities = sep->argplus[2]; + n.special_abilities = special_abilities; + c->Message( + Chat::Yellow, + fmt::format( + "{} is now using the following Special Abilities '{}'.", + npc_id_string, + special_abilities + ).c_str() + ); + } else if (!strcasecmp(sep->arg[1], "aggroradius")) { + if (sep->IsNumber(2)) { + auto aggro_radius = std::stoul(sep->arg[2]); + n.aggroradius = aggro_radius; + d = fmt::format( + "{} now has an Aggro Radius of {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit aggroradius [Radius] - Sets an NPC's Aggro Radius"); + return; + } + } else if (!strcasecmp(sep->arg[1], "assistradius")) { + if (sep->IsNumber(2)) { + auto assist_radius = std::stoul(sep->arg[2]); + n.assistradius = assist_radius; + d = fmt::format( + "{} now has an Assist Radius of {}", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit assistradius [Radius] - Sets an NPC's Assist Radius"); + return; + } + } else if (!strcasecmp(sep->arg[1], "featuresave")) { + d = fmt::format( + "{} saved with all current body and facial feature settings.", + npc_id ); - content_db.QueryDatabase(query); - c->GetTarget()->SetAppearance(EmuAppearance(animation)); + n.gender = t->GetGender(); + n.texture = t->GetTexture(); + n.helmtexture = t->GetHelmTexture(); + n.size = t->GetSize(); + n.face = t->GetLuclinFace(); + n.luclin_hairstyle = t->GetHairStyle(); + n.luclin_haircolor = t->GetHairColor(); + n.luclin_eyecolor = t->GetEyeColor1(); + n.luclin_eyecolor2 = t->GetEyeColor2(); + n.luclin_beardcolor = t->GetBeardColor(); + n.luclin_beard = t->GetBeard(); + n.drakkin_heritage = t->GetDrakkinHeritage(); + n.drakkin_tattoo = t->GetDrakkinTattoo(); + n.drakkin_details = t->GetDrakkinDetails(); + } else if (!strcasecmp(sep->arg[1], "armortint_id")) { + if (sep->IsNumber(2)) { + auto armor_tint_id = std::stoul(sep->arg[2]); + n.armortint_id = armor_tint_id; + d = fmt::format( + "{} is now using Armor Tint ID {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit armortint_id [Armor Tint ID] - Sets an NPC's Armor Tint ID"); + return; + } + } else if (!strcasecmp(sep->arg[1], "color")) { + if (sep->IsNumber(2)) { + auto red = static_cast(std::stoul(sep->arg[2])); + uint8_t green = sep->IsNumber(3) ? static_cast(std::stoul(sep->arg[3])) : 0; + uint8_t blue = sep->IsNumber(4) ? static_cast(std::stoul(sep->arg[4])) : 0; + n.armortint_red = red; + n.armortint_green = green; + n.armortint_blue = blue; + d = fmt::format( + "{} now has {} Red, {} Green, and {} Blue tinting on their armor.", + npc_id_string, + red, + green, + blue + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit color [Red] [Green] [Blue] - Sets an NPC's Red, Green, and Blue armor tint" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "ammoidfile")) { + if (sep->IsNumber(2)) { + auto ammo_id_file = std::stoul(sep->arg[2]); + n.ammo_idfile = ammo_id_file; + d = fmt::format( + "{} is now using Ammo ID File {}.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit ammoidfile [ID File] - Sets an NPC's Ammo ID File"); + return; + } + } else if (!strcasecmp(sep->arg[1], "weapon")) { + if (sep->IsNumber(2)) { + auto primary_model = std::stoul(sep->arg[2]); + uint32_t secondary_model = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : 0; + n.d_melee_texture1 = primary_model; + n.d_melee_texture2 = secondary_model; + d = fmt::format( + "{} will have Model {} set to their Primary and Model {} set to their Secondary on repop.", + npc_id_string, + Strings::Commify(sep->arg[2]), + sep->IsNumber(3) ? Strings::Commify(sep->arg[3]) : 0 + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit weapon [Primary Model] [Secondary Model] - Sets an NPC's Primary and Secondary Weapon Model" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "meleetype")) { + if (sep->IsNumber(2)) { + auto primary_type = std::stoul(sep->arg[2]); + uint32_t secondary_type = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : 0; + + auto primary_skill = EQ::skills::GetSkillName(static_cast(primary_type)); + auto secondary_skill = EQ::skills::GetSkillName(static_cast(secondary_type)); + + n.prim_melee_type = primary_type; + n.sec_melee_type = secondary_type; + + d = fmt::format( + "{} now has a Primary Melee Type of {} and a Secondary Melee Type of {}.", + npc_id_string, + ( + !primary_skill.empty() ? + fmt::format( + "{} ({})", + primary_skill, + primary_type + ) : + std::to_string(primary_type) + ), + ( + !secondary_skill.empty() ? + fmt::format( + "{} ({})", + secondary_skill, + secondary_type + ) : + std::to_string(secondary_type) + ) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit meleetype [Primary Type] [Secondary Type] - Sets an NPC's Melee Skill Types" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "rangedtype")) { + if (sep->IsNumber(2)) { + auto ranged_type = std::stoul(sep->arg[2]); + + auto ranged_skill = EQ::skills::GetSkillName(static_cast(ranged_type)); + + n.ranged_type = ranged_type; + + d = fmt::format( + "{} now has a Ranged Type of {}.", + npc_id_string, + ( + !ranged_skill.empty() ? + fmt::format( + "{} ({})", + ranged_skill, + ranged_type + ) : + std::to_string(ranged_type) + ) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit rangedtype [Type] - Sets an NPC's Ranged Skill Type"); + return; + } + } else if (!strcasecmp(sep->arg[1], "runspeed")) { + if (sep->IsNumber(2)) { + auto run_speed = std::stof(sep->arg[2]); + n.runspeed = run_speed; + d = fmt::format( + "{} now runs at a Run Speed of {:.2f}.", + npc_id_string, + run_speed + ); + } else { + c->Message(Chat::White, "Usage: #npcedit runspeed [Run Speed] - Sets an NPC's Run Speed"); + return; + } + } else if (!strcasecmp(sep->arg[1], "mr")) { + if (sep->IsNumber(2)) { + auto magic_resist = static_cast(std::stoul(sep->arg[2])); + n.MR = magic_resist; + d = fmt::format( + "{} now has a Magic Resistance of {}.", + npc_id_string, + magic_resist + ); + } else { + c->Message(Chat::White, "Usage: #npcedit mr [Resistance] - Sets an NPC's Magic Resistance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "pr")) { + if (sep->IsNumber(2)) { + auto poison_resist = static_cast(std::stoul(sep->arg[2])); + n.PR = poison_resist; + d = fmt::format( + "{} now has a Poison Resistance of {}.", + npc_id_string, + poison_resist + ); + } else { + c->Message(Chat::White, "Usage: #npcedit pr [Resistance] - Sets an NPC's Poison Resistance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "dr")) { + if (sep->IsNumber(2)) { + auto disease_resist = static_cast(std::stoul(sep->arg[2])); + n.DR = disease_resist; + d = fmt::format( + "{} now has a Disease Resistance of {}.", + npc_id_string, + disease_resist + ); + } else { + c->Message(Chat::White, "Usage: #npcedit dr [Resistance] - Sets an NPC's Disease Resistance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "fr")) { + if (sep->IsNumber(2)) { + auto fire_resist = static_cast(std::stoul(sep->arg[2])); + n.FR = fire_resist; + d = fmt::format( + "{} now has a Fire Resistance of {}.", + npc_id_string, + fire_resist + ); + } else { + c->Message(Chat::White, "Usage: #npcedit fr [Resistance] - Sets an NPC's Fire Resistance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "cr")) { + if (sep->IsNumber(2)) { + auto cold_resist = static_cast(std::stoul(sep->arg[2])); + n.CR = cold_resist; + d = fmt::format( + "{} now has a Cold Resistance of {}.", + npc_id_string, + cold_resist + ); + } else { + c->Message(Chat::White, "Usage: #npcedit cr [Resistance] - Sets an NPC's Cold Resistance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "corrup")) { + if (sep->IsNumber(2)) { + auto corruption_resist = static_cast(std::stoul(sep->arg[2])); + n.Corrup = corruption_resist; + d = fmt::format( + "{} now has a Corruption Resistance of {}.", + npc_id_string, + corruption_resist + ); + } else { + c->Message(Chat::White, "Usage: #npcedit corrup [Resistance] - Sets an NPC's Corruption Resistance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "phr")) { + if (sep->IsNumber(2)) { + auto physical_resist = static_cast(std::stoul(sep->arg[2])); + n.PhR = physical_resist; + d = fmt::format( + "{} now has a Physical Resistance of {}.", + npc_id_string, + physical_resist + ); + } else { + c->Message(Chat::White, "Usage: #npcedit phr [Resistance] - Sets and NPC's Physical Resistance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "seeinvis")) { + if (sep->IsNumber(2)) { + auto see_invisible = static_cast(std::stoul(sep->arg[2])); + n.see_invis = see_invisible; + d = fmt::format( + "{} can {} See Invisible.", + npc_id_string, + see_invisible ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit seeinvis [Flag] - Sets an NPC's See Invisible Flag [0 = Cannot See Invisible, 1 = Can See Invisible]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "seeinvisundead")) { + if (sep->IsNumber(2)) { + auto see_invisible_undead = static_cast(std::stoul(sep->arg[2])); + n.see_invis_undead = see_invisible_undead; + d = fmt::format( + "{} can {} See Invisible vs. Undead.", + npc_id_string, + see_invisible_undead ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit seeinvisundead [Flag] - Sets an NPC's See Invisible vs. Undead Flag [0 = Cannot See Invisible vs. Undead, 1 = Can See Invisible vs. Undead]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "qglobal")) { + if (sep->IsNumber(2)) { + auto use_qglobals = std::stoul(sep->arg[2]); + n.qglobal = use_qglobals; + d = fmt::format( + "{} can {} use Quest Globals.", + npc_id_string, + use_qglobals ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit qglobal [Flag] - Sets an NPC's Quest Global Flag [0 = Quest Globals Off, 1 = Quest Globals On]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "ac")) { + if (sep->IsNumber(2)) { + auto armor_class = static_cast(std::stoul(sep->arg[2])); + n.AC = armor_class; + d = fmt::format( + "{} now has {} Armor Class.", + npc_id_string, + armor_class + ); + } else { + c->Message(Chat::White, "Usage: #npcedit ac [Armor Class] - Sets an NPC's Armor Class"); + return; + } + } else if (!strcasecmp(sep->arg[1], "npcaggro")) { + if (sep->IsNumber(2)) { + auto aggro_npcs = static_cast(std::stoul(sep->arg[2])); + n.npc_aggro = aggro_npcs; + d = fmt::format( + "{} will {} aggro other NPCs that have a hostile faction.", + npc_id_string, + aggro_npcs ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit npcaggro [Flag] - Sets an NPC's NPC Aggro Flag [0 = Aggro NPCs Off, 1 = Aggro NPCs On]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "spawn_limit")) { + if (sep->IsNumber(2)) { + auto spawn_limit = static_cast(std::stoul(sep->arg[2])); + n.spawn_limit = spawn_limit; + d = fmt::format( + "{} now has a Spawn Limit of {}.", + npc_id_string, + spawn_limit + ); + } else { + c->Message(Chat::White, "Usage: #npcedit spawn_limit [Limit] - Sets an NPC's Spawn Limit Counter"); + return; + } + } else if (!strcasecmp(sep->arg[1], "attackspeed")) { + if (sep->IsNumber(2)) { + auto attack_speed = std::stof(sep->arg[2]); + n.attack_speed = attack_speed; + d = fmt::format( + "{} now has an Attack Speed of {:.2f}.", + npc_id_string, + attack_speed + ); + } else { + c->Message(Chat::White, "Usage: #npcedit attackspeed [Attack Speed] - Sets an NPC's Attack Speed Modifier"); + return; + } + } else if (!strcasecmp(sep->arg[1], "attackdelay")) { + if (sep->IsNumber(2)) { + auto attack_delay = static_cast(std::stoul(sep->arg[2])); + n.attack_delay = attack_delay; + d = fmt::format( + "{} now has an Attack Delay of {}.", + npc_id_string, + attack_delay + ); + } else { + c->Message(Chat::White, "Usage: #npcedit attackdelay [Attack Delay] - Sets an NPC's Attack Delay"); + return; + } + } else if (!strcasecmp(sep->arg[1], "findable")) { + if (sep->IsNumber(2)) { + auto is_findable = static_cast(std::stoul(sep->arg[2])); + n.findable = is_findable; + d = fmt::format( + "{} is {} Findable.", + npc_id_string, + is_findable ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit findable [Flag] - Sets an NPC's Findable Flag [0 = Not Findable, 1 = Findable]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "str")) { + if (sep->IsNumber(2)) { + auto strength = std::stoul(sep->arg[2]); + n.STR = strength; + d = fmt::format( + "{} now has {} Strength.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit str [Strength] - Sets an NPC's Strength"); + return; + } + } else if (!strcasecmp(sep->arg[1], "sta")) { + if (sep->IsNumber(2)) { + auto stamina = std::stoul(sep->arg[2]); + n.STA = stamina; + d = fmt::format( + "{} now has {} Stamina.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit sta [Stamina] - Sets an NPC's Stamina"); + return; + } + } else if (!strcasecmp(sep->arg[1], "agi")) { + if (sep->IsNumber(2)) { + auto agility = std::stoul(sep->arg[2]); + n.AGI = agility; + d = fmt::format( + "{} now has {} Agility.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit agi [Agility] - Sets an NPC's Agility"); + return; + } + } else if (!strcasecmp(sep->arg[1], "dex")) { + if (sep->IsNumber(2)) { + auto dexterity = std::stoul(sep->arg[2]); + n.DEX = dexterity; + d = fmt::format( + "{} now has {} Dexterity.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit dex [Dexterity] - Sets an NPC's Dexterity"); + return; + } + } else if (!strcasecmp(sep->arg[1], "int")) { + if (sep->IsNumber(2)) { + auto intelligence = std::stoul(sep->arg[2]); + n._INT = intelligence; + d = fmt::format( + "{} now has {} Intelligence.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit int [Intelligence] - Sets an NPC's Intelligence"); + return; + } + } else if (!strcasecmp(sep->arg[1], "wis")) { + if (sep->IsNumber(2)) { + auto wisdom = std::stoul(sep->arg[2]); + n.WIS = wisdom; + d = fmt::format( + "{} now has {} Wisdom.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit wis [Wisdom] - Sets an NPC's Wisdom"); + return; + } + } else if (!strcasecmp(sep->arg[1], "cha")) { + if (sep->IsNumber(2)) { + auto charisma = std::stoul(sep->arg[2]); + n.CHA = charisma; + d = fmt::format( + "{} now has {} Charisma.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit cha [Charisma] - Sets an NPC's Charisma"); + return; + } + } else if (!strcasecmp(sep->arg[1], "seehide")) { + if (sep->IsNumber(2)) { + auto see_hide = static_cast(std::stoi(sep->arg[2])); + n.see_hide = see_hide; + d = fmt::format( + "{} can {} See Hide.", + npc_id_string, + see_hide ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit seehide [Flag] - Sets an NPC's See Hide Flag [0 = Cannot See Hide, 1 = Can See Hide]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "seeimprovedhide")) { + if (sep->IsNumber(2)) { + auto see_improved_hide = static_cast(std::stoi(sep->arg[2])); + n.see_improved_hide = see_improved_hide; + d = fmt::format( + "{} can {} See Improved Hide.", + npc_id_string, + see_improved_hide ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit seeimprovedhide [Flag] - Sets an NPC's See Improved Hide Flag [0 = Cannot See Improved Hide, 1 = Can See Improved Hide]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "trackable")) { + if (sep->IsNumber(2)) { + auto is_trackable = static_cast(std::stoi(sep->arg[2])); + n.trackable = is_trackable; + d = fmt::format( + "{} is {} Trackable.", + npc_id_string, + is_trackable ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit trackable [Flag] - Sets an NPC's Trackable Flag [0 = Not Trackable, 1 = Trackable]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "atk")) { + if (sep->IsNumber(2)) { + auto attack = std::stoi(sep->arg[2]); + n.ATK = attack; + d = fmt::format( + "{} now has {} Attack.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit atk [Attack] - Sets an NPC's Attack"); + return; + } + } else if (!strcasecmp(sep->arg[1], "accuracy")) { + if (sep->IsNumber(2)) { + auto accuracy = std::stoi(sep->arg[2]); + n.Accuracy = accuracy; + d = fmt::format( + "{} now has {} Accuracy.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit accuracy [Accuracy] - Sets an NPC's Accuracy"); + return; + } + } else if (!strcasecmp(sep->arg[1], "avoidance")) { + if (sep->IsNumber(2)) { + auto avoidance = std::stoul(sep->arg[2]); + n.Avoidance = avoidance; + d = fmt::format( + "{} now has {} Avoidance.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit avoidance [Avoidance] - Sets an NPC's Avoidance"); + return; + } + } else if (!strcasecmp(sep->arg[1], "slow_mitigation")) { + if (sep->IsNumber(2)) { + auto slow_mitigation = static_cast(std::stoi(sep->arg[2])); + n.slow_mitigation = slow_mitigation; + d = fmt::format( + "{} now has {} Slow Mitigation.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit slow_mitigation [Slow Mitigation] - Sets an NPC's Slow Mitigation" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "version")) { + if (sep->IsNumber(2)) { + auto version = static_cast(std::stoul(sep->arg[2])); + n.version = version; + d = fmt::format( + "{} is now using Version {}.", + npc_id_string, + version + ); + } else { + c->Message(Chat::White, "Usage: #npcedit version [Version] - Sets an NPC's Version"); + return; + } + } else if (!strcasecmp(sep->arg[1], "maxlevel")) { + if (sep->IsNumber(2)) { + auto max_level = static_cast(std::stoi(sep->arg[2])); + n.maxlevel = max_level; + d = fmt::format( + "{} now has a Maximum Level of {}.", + npc_id_string, + max_level + ); + } else { + c->Message(Chat::White, "Usage: #npcedit maxlevel [Max Level] - Sets an NPC's Maximum Level"); + return; + } + } else if (!strcasecmp(sep->arg[1], "scalerate")) { + if (sep->IsNumber(2)) { + auto scale_rate = std::stoi(sep->arg[2]); + n.scalerate = scale_rate; + d = fmt::format( + "{} now has a Scaling Rate of {}%%.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit scalerate [Scale Rate] - Sets an NPC's Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "spellscale")) { + if (sep->IsNumber(2)) { + auto spell_scale = std::stoul(sep->arg[2]); + n.spellscale = static_cast(spell_scale); + d = fmt::format( + "{} now has a Spell Scaling Rate of {}%%.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit spellscale [Scale Rate] - Sets an NPC's Spell Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "healscale")) { + if (sep->IsNumber(2)) { + auto heal_scale = std::stoul(sep->arg[2]); + n.healscale = static_cast(heal_scale); + d = fmt::format( + "{} now has a Heal Scaling Rate of {}%%.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit healscale [Scale Rate] - Sets an NPC's Heal Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "no_target")) { + if (sep->IsNumber(2)) { + auto is_no_target = static_cast(std::stoul(sep->arg[2])); + n.no_target_hotkey = is_no_target; + d = fmt::format( + "{} is {} Targetable with Target Hotkey.", + npc_id_string, + is_no_target ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit no_target [Flag] - Sets an NPC's No Target Hotkey Flag [0 = Not Targetable with Target Hotkey, 1 = Targetable with Target Hotkey]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "raidtarget")) { + if (sep->IsNumber(2)) { + auto is_raid_target = static_cast(std::stoul(sep->arg[2])); + n.raid_target = is_raid_target; + d = fmt::format( + "{} is {} designated as a Raid Target.", + npc_id_string, + is_raid_target ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit raidtarget [Flag] - Sets an NPC's Raid Target Flag [0 = Not a Raid Target, 1 = Raid Target]" + ); + } + return; + } else if (!strcasecmp(sep->arg[1], "armtexture")) { + if (sep->IsNumber(2)) { + auto arm_texture = static_cast(std::stoi(sep->arg[2])); + n.armtexture = arm_texture; + d = fmt::format( + "{} is now using Arm Texture {}.", + npc_id_string, + arm_texture + ); + } else { + c->Message(Chat::White, "Usage: #npcedit armtexture [Texture] - Sets an NPC's Arm Texture"); + return; + } + } else if (!strcasecmp(sep->arg[1], "bracertexture")) { + if (sep->IsNumber(2)) { + auto bracer_texture = static_cast(std::stoi(sep->arg[2])); + n.bracertexture = bracer_texture; + d = fmt::format( + "{} is now using Bracer Texture {}.", + npc_id_string, + bracer_texture + ); + } else { + c->Message(Chat::White, "Usage: #npcedit bracertexture [Texture] - Sets an NPC's Bracer Texture"); + return; + } + } else if (!strcasecmp(sep->arg[1], "handtexture")) { + if (sep->IsNumber(2)) { + auto hand_texture = static_cast(std::stoi(sep->arg[2])); + n.handtexture = hand_texture; + d = fmt::format( + "{} is now using Hand Texture {}.", + npc_id_string, + hand_texture + ); + } else { + c->Message(Chat::White, "Usage: #npcedit handtexture [Texture] - Sets an NPC's Hand Texture"); + return; + } + } else if (!strcasecmp(sep->arg[1], "legtexture")) { + if (sep->IsNumber(2)) { + auto leg_texture = static_cast(std::stoi(sep->arg[2])); + n.legtexture = leg_texture; + d = fmt::format( + "{} is now using Leg Texture {}.", + npc_id_string, + leg_texture + ); + } else { + c->Message(Chat::White, "Usage: #npcedit legtexture [Texture] - Sets an NPC's Leg Texture"); + return; + } + } else if (!strcasecmp(sep->arg[1], "feettexture")) { + if (sep->IsNumber(2)) { + auto feet_texture = static_cast(std::stoi(sep->arg[2])); + n.feettexture = feet_texture; + d = fmt::format( + "{} is now using Feet Texture {}.", + npc_id_string, + feet_texture + ); + } else { + c->Message(Chat::White, "Usage: #npcedit feettexture [Texture] - Sets an NPC's Feet Texture"); + return; + } + } else if (!strcasecmp(sep->arg[1], "walkspeed")) { + if (sep->IsNumber(2)) { + auto walk_speed = static_cast(std::stoi(sep->arg[2])); + n.walkspeed = walk_speed; + d = fmt::format( + "{} now walks at a Walk Speed of {}.", + npc_id_string, + walk_speed + ); + } else { + c->Message(Chat::White, "Usage: #npcedit walkspeed [Walk Speed] - Sets an NPC's Walk Speed"); + return; + } + } else if (!strcasecmp(sep->arg[1], "show_name")) { + if (sep->IsNumber(2)) { + auto show_name = static_cast(std::stoi(sep->arg[2])); + n.show_name = show_name; + d = fmt::format( + "{} will {} show their name.", + npc_id_string, + show_name ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit show_name [Flag] - Sets an NPC's Show Name Flag [0 = Hidden, 1 = Shown]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "untargetable")) { + if (sep->IsNumber(2)) { + auto is_untargetable = static_cast(std::stoi(sep->arg[2])); + n.untargetable = is_untargetable; + d = fmt::format( + "{} will {} be untargetable.", + npc_id_string, + is_untargetable ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit untargetable [Flag] - Sets an NPC's Untargetable Flag [0 = Targetable, 1 = Untargetable]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "charm_ac")) { + if (sep->IsNumber(2)) { + auto charm_armor_class = static_cast(std::stoi(sep->arg[2])); + n.charm_ac = charm_armor_class; + d = fmt::format( + "{} now has {} Armor Class while Charmed.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit charm_ac [Armor Class] - Sets an NPC's Armor Class while Charmed"); + return; + } + } else if (!strcasecmp(sep->arg[1], "charm_min_dmg")) { + if (sep->IsNumber(2)) { + auto charm_minimum_damage = std::stoi(sep->arg[2]); + n.charm_min_dmg = charm_minimum_damage; + d = fmt::format( + "{} now does {} Minimum Damage while Charmed.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit charm_min_dmg [Damage] - Sets an NPC's Minimum Damage while Charmed" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "charm_max_dmg")) { + if (sep->IsNumber(2)) { + auto charm_maximum_damage = std::stoi(sep->arg[2]); + n.charm_max_dmg = charm_maximum_damage; + d = fmt::format( + "{} now does {} Maximum Damage while Charmed.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit charm_max_dmg [Damage] - Sets an NPC's Maximum Damage while Charmed" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "charm_attack_delay")) { + if (sep->IsNumber(2)) { + auto charm_attack_delay = static_cast(std::stoi(sep->arg[2])); + n.charm_attack_delay = charm_attack_delay; + d = fmt::format( + "{} now has {} Attack Delay while Charmed.", + npc_id_string, + charm_attack_delay + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit charm_attack_delay [Attack Delay] - Sets an NPC's Attack Delay while Charmed" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "charm_accuracy_rating")) { + if (sep->IsNumber(2)) { + auto charm_accuracy_rating = std::stoi(sep->arg[2]); + n.charm_accuracy_rating = charm_accuracy_rating; + d = fmt::format( + "{} now has {} Accuracy Rating while Charmed.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit charm_accuracy_rating [Accuracy] - Sets an NPC's Accuracy Rating while Charmed" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "charm_avoidance_rating")) { + if (sep->IsNumber(2)) { + auto charm_avoidance_rating = std::stoi(sep->arg[2]); + n.charm_avoidance_rating = charm_avoidance_rating; + d = fmt::format( + "{} now has {} Avoidance Rating while Charmed.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit charm_avoidance_rating [Avoidance] - Sets an NPC's Avoidance Rating while Charmed" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "charm_atk")) { + if (sep->IsNumber(2)) { + auto charm_attack = std::stoi(sep->arg[2]); + n.charm_atk = charm_attack; + d = fmt::format( + "{} now has {} Attack while Charmed.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message(Chat::White, "Usage: #npcedit charm_atk [Attack] - Sets an NPC's Attack while Charmed"); + return; + } + } else if (!strcasecmp(sep->arg[1], "skip_global_loot")) { + if (sep->IsNumber(2)) { + auto skip_global_loot = static_cast(std::stoi(sep->arg[2])); + n.skip_global_loot = skip_global_loot; + d = fmt::format( + "{} will {} skip Global Loot.", + npc_id_string, + skip_global_loot ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit skip_global_loot [Flag] - Sets an NPC's Skip Global Loot Flag [0 = Don't Skip, 1 = Skip" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "rarespawn")) { + if (sep->IsNumber(2)) { + auto is_rare_spawn = static_cast(std::stoi(sep->arg[2])); + n.rare_spawn = is_rare_spawn; + d = fmt::format( + "{} is {} designated as a Rare Spawn.", + npc_id_string, + is_rare_spawn ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit rarespawn [Flag] - Sets an NPC's Rare Spawn Flag [0 = Not a Rare Spawn, 1 = Rare Spawn]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "stuck_behavior")) { + if (sep->IsNumber(2)) { + auto behavior_id = static_cast(std::stoi(sep->arg[2])); + if (behavior_id > EQ::constants::StuckBehavior::EvadeCombat) { + behavior_id = EQ::constants::StuckBehavior::EvadeCombat; + } + + auto behavior_name = EQ::constants::GetStuckBehaviorName(behavior_id); + n.stuck_behavior = behavior_id; + d = fmt::format( + "{} is now using Stuck Behavior {}.", + npc_id_string, + ( + !behavior_name.empty() ? + fmt::format( + "{} ({})", + behavior_name, + behavior_id + ) : + std::to_string(behavior_id) + ) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit stuck_behavior [Stuck Behavior] - Sets an NPC's Stuck Behavior [0 = Run to Target, 1 = Warp to Target, 2 = Take No Action, 3 = Evade Combat]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "flymode")) { + if (sep->IsNumber(2)) { + auto flymode_id = static_cast(std::stoi(sep->arg[2])); + if (flymode_id > GravityBehavior::LevitateWhileRunning) { + flymode_id = GravityBehavior::LevitateWhileRunning; + } + + auto flymode_name = EQ::constants::GetFlyModeName(flymode_id); + n.flymode = flymode_id; + d = fmt::format( + "{} is now using Fly Mode {}.", + npc_id_string, + ( + !flymode_name.empty() ? + fmt::format( + "{} ({})", + flymode_name, + flymode_id + ) : + std::to_string(flymode_id) + ) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit flymode [Fly Mode] - Sets an NPC's Fly Mode [0 = Ground, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating While Running]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "always_aggro")) { + if (sep->IsNumber(2)) { + auto always_aggro = static_cast(std::stoi(sep->arg[2])); + n.always_aggro = always_aggro; + d = fmt::format( + "{} will {} Always Aggro.", + npc_id_string, + always_aggro ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit always_aggro [Flag] - Sets an NPC's Always Aggro Flag [0 = Does not Always Aggro, 1 = Always Aggro]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "exp_mod")) { + if (sep->IsNumber(2)) { + auto experience_modifier = std::stoi(sep->arg[2]); + n.exp_mod = experience_modifier; + d = fmt::format( + "{} now has an Experience Modifier of {}%%.", + npc_id_string, + Strings::Commify(sep->arg[2]) + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit exp_mod [Modifier] - Sets an NPC's Experience Modifier [50 = 50%, 100 = 100%, 200 = 200%]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "keeps_sold_items")) { + if (sep->IsNumber(2)) { + auto keeps_sold_items = static_cast(std::stoul(sep->arg[2])); + n.keeps_sold_items = keeps_sold_items; + d = fmt::format( + "{} will {} Keep Sold Items.", + npc_id_string, + keeps_sold_items ? "now" : "no longer" + ); + } else { + c->Message( + Chat::White, + "Usage: #npcedit keeps_sold_items [Flag] - Sets an NPC's Keeps Sold Items Flag [0 = False, 1 = True]" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "setanimation")) { + if (sep->IsNumber(2)) { + auto animation_id = std::stoul(sep->arg[2]); + if (animation_id > EQ::constants::SpawnAnimations::Looting) { + animation_id = EQ::constants::SpawnAnimations::Looting; + } + + auto animation_name = EQ::constants::GetSpawnAnimationName(animation_id); + d = fmt::format( + "{} is now using Spawn Animation {} on Spawn Group ID {}.", + npc_id_string, + ( + !animation_name.empty() ? + fmt::format( + "{} ({})", + animation_name, + animation_id + ) : + std::to_string(animation_id) + ), + Strings::Commify(std::to_string(c->GetTarget()->CastToNPC()->GetSpawnGroupId())) + ); + auto query = fmt::format( + "UPDATE spawn2 SET animation = {} WHERE spawngroupID = {}", + animation_id, + c->GetTarget()->CastToNPC()->GetSpawnGroupId() + ); + content_db.QueryDatabase(query); + + c->GetTarget()->SetAppearance(EmuAppearance(animation_id)); + } else { + c->Message( + Chat::White, + "Usage: #npcedit setanimation [Animation ID] - Sets an NPC's Animation on Spawn (Stored in spawn2 table)" + ); + return; + } + } else if (!strcasecmp(sep->arg[1], "respawntime")) { + if (sep->IsNumber(2)) { + auto respawn_time = std::stoul(sep->arg[2]); + if (respawn_time) { + d = fmt::format( + "{} now has a Respawn Timer of {} ({}) on Spawn Group ID {}.", + npc_id_string, + Strings::SecondsToTime(respawn_time), + respawn_time, + Strings::Commify(std::to_string(t->GetSpawnGroupId())) + ); + auto query = fmt::format( + "UPDATE spawn2 SET respawntime = {} WHERE spawngroupID = {} AND version = {}", + respawn_time, + t->GetSpawnGroupId(), + zone->GetInstanceVersion() + ); + content_db.QueryDatabase(query); + } else { + c->Message(Chat::White, "Respawn Timer must be greater than 0 seconds."); + return; + } + } else { + c->Message( + Chat::White, + "Usage: #npcedit respawntime [Respawn Time] - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)" + ); + return; + } + } else { + SendNPCEditSubCommands(c); return; } - if (strcasecmp(sep->arg[1], "respawntime") == 0) { - if (sep->arg[2][0] && sep->IsNumber(sep->arg[2]) && atoi(sep->arg[2]) > 0) { - c->Message( - Chat::Yellow, - fmt::format( - "NPC ID {} now has a Respawn Timer of {} Seconds on Spawn Group ID {}.", - npc_id, - atoi(sep->arg[2]), - c->GetTarget()->CastToNPC()->GetSpawnGroupId()).c_str()); - std::string query = fmt::format( - "UPDATE spawn2 SET respawntime = {} WHERE spawngroupID = {} AND version = {}", - atoi(sep->arg[2]), - c->GetTarget()->CastToNPC()->GetSpawnGroupId(), - zone->GetInstanceVersion()); - content_db.QueryDatabase(query); - return; - } - } - - if ((sep->arg[1][0] == 0 || strcasecmp(sep->arg[1], "*") == 0) || - ((c->GetTarget() == 0) || (c->GetTarget()->IsClient()))) { - c->Message(Chat::White, "Type #npcedit help for more info"); + if (!NpcTypesRepository::UpdateOne(content_db, n)) { + c->Message( + Chat::White, + fmt::format( + "Failed to update {}.", + npc_id_string + ).c_str() + ); } + c->Message(Chat::White, d.c_str()); } +void SendNPCEditSubCommands(Client *c) +{ + c->Message(Chat::White, "Usage: #npcedit name [Name] - Sets an NPC's Name"); + c->Message(Chat::White, "Usage: #npcedit lastname [Last Name] - Sets an NPC's Last Name"); + c->Message(Chat::White, "Usage: #npcedit level [Level] - Sets an NPC's Level"); + c->Message(Chat::White, "Usage: #npcedit race [Race ID] - Sets an NPC's Race"); + c->Message(Chat::White, "Usage: #npcedit class [Class ID] - Sets an NPC's Class"); + c->Message(Chat::White, "Usage: #npcedit bodytype [Body Type ID] - Sets an NPC's Bodytype"); + c->Message(Chat::White, "Usage: #npcedit hp [HP] - Sets an NPC's HP"); + c->Message(Chat::White, "Usage: #npcedit mana [Mana] - Sets an NPC's Mana"); + c->Message(Chat::White, "Usage: #npcedit gender [Gender ID] - Sets an NPC's Gender"); + c->Message(Chat::White, "Usage: #npcedit texture [Texture] - Sets an NPC's Texture"); + c->Message(Chat::White, "Usage: #npcedit helmtexture [Helmet Texture] - Sets an NPC's Helmet Texture"); + c->Message(Chat::White, "Usage: #npcedit herosforgemodel [Model Number] - Sets an NPC's Hero's Forge Model"); + c->Message(Chat::White, "Usage: #npcedit size [Size] - Sets an NPC's Size"); + c->Message(Chat::White, "Usage: #npcedit hpregen [HP Regen] - Sets an NPC's HP Regen Rate Per Tick"); + c->Message(Chat::White, "Usage: #npcedit hp_regen_per_second [HP Regen] - Sets an NPC's HP Regen Rate Per Second"); + c->Message(Chat::White, "Usage: #npcedit manaregen [Mana Regen] - Sets an NPC's Mana Regen Rate Per Tick"); + c->Message(Chat::White, "Usage: #npcedit loottable [Loottable ID] - Sets an NPC's Loottable ID"); + c->Message(Chat::White, "Usage: #npcedit merchantid [Merchant ID] - Sets an NPC's Merchant ID"); + c->Message( + Chat::White, + "Usage: #npcedit alt_currency_id [Alternate Currency ID] - Sets an NPC's Alternate Currency ID" + ); + c->Message(Chat::White, "Usage: #npcedit spell [Spell List ID] - Sets an NPC's Spells List ID"); + c->Message( + Chat::White, + "Usage: #npcedit npc_spells_effects_id [Spell Effects ID] - Sets an NPC's Spell Effects ID" + ); + c->Message(Chat::White, "Usage: #npcedit faction [Faction ID] - Sets an NPC's Faction ID"); + c->Message( + Chat::White, + "Usage: #npcedit adventure_template_id [Template ID] - Sets an NPC's Adventure Template ID" + ); + c->Message(Chat::White, "Usage: #npcedit trap_template [Template ID] - Sets an NPC's Trap Template ID"); + c->Message(Chat::White, "Usage: #npcedit damage [Minimum] [Maximum] - Sets an NPC's Damage"); + c->Message(Chat::White, "Usage: #npcedit attackcount [Attack Count] - Sets an NPC's Attack Count"); + c->Message(Chat::White, "Usage: #npcedit special_attacks [Special Attacks] - Sets an NPC's Special Attacks"); + c->Message(Chat::White, "Usage: #npcedit special_abilities [Special Abilities] - Sets an NPC's Special Abilities"); + c->Message(Chat::White, "Usage: #npcedit aggroradius [Radius] - Sets an NPC's Aggro Radius"); + c->Message(Chat::White, "Usage: #npcedit assistradius [Radius] - Sets an NPC's Assist Radius"); + c->Message(Chat::White, "Usage: #npcedit featuresave - Saves an NPC's current facial features to the database"); + c->Message(Chat::White, "Usage: #npcedit armortint_id [Armor Tint ID] - Sets an NPC's Armor Tint ID"); + c->Message( + Chat::White, + "Usage: #npcedit color [Red] [Green] [Blue] - Sets an NPC's Red, Green, and Blue armor tint" + ); + c->Message(Chat::White, "Usage: #npcedit ammoidfile [ID File] - Sets an NPC's Ammo ID File"); + c->Message( + Chat::White, + "Usage: #npcedit weapon [Primary Model] [Secondary Model] - Sets an NPC's Primary and Secondary Weapon Model" + ); + c->Message( + Chat::White, + "Usage: #npcedit meleetype [Primary Type] [Secondary Type] - Sets an NPC's Melee Skill Types" + ); + c->Message(Chat::White, "Usage: #npcedit rangedtype [Type] - Sets an NPC's Ranged Skill Type"); + c->Message(Chat::White, "Usage: #npcedit runspeed [Run Speed] - Sets an NPC's Run Speed"); + c->Message(Chat::White, "Usage: #npcedit mr [Resistance] - Sets an NPC's Magic Resistance"); + c->Message(Chat::White, "Usage: #npcedit pr [Resistance] - Sets an NPC's Poison Resistance"); + c->Message(Chat::White, "Usage: #npcedit dr [Resistance] - Sets an NPC's Disease Resistance"); + c->Message(Chat::White, "Usage: #npcedit fr [Resistance] - Sets an NPC's Fire Resistance"); + c->Message(Chat::White, "Usage: #npcedit cr [Resistance] - Sets an NPC's Cold Resistance"); + c->Message(Chat::White, "Usage: #npcedit corrup [Resistance] - Sets an NPC's Corruption Resistance"); + c->Message(Chat::White, "Usage: #npcedit phr [Resistance] - Sets and NPC's Physical Resistance"); + c->Message( + Chat::White, + "Usage: #npcedit seeinvis [Flag] - Sets an NPC's See Invisible Flag [0 = Cannot See Invisible, 1 = Can See Invisible]" + ); + c->Message( + Chat::White, + "Usage: #npcedit seeinvisundead [Flag] - Sets an NPC's See Invisible vs. Undead Flag [0 = Cannot See Invisible vs. Undead, 1 = Can See Invisible vs. Undead]" + ); + c->Message( + Chat::White, + "Usage: #npcedit qglobal [Flag] - Sets an NPC's Quest Global Flag [0 = Quest Globals Off, 1 = Quest Globals On]" + ); + c->Message(Chat::White, "Usage: #npcedit ac [Armor Class] - Sets an NPC's Armor Class"); + c->Message( + Chat::White, + "Usage: #npcedit npcaggro [Flag] - Sets an NPC's NPC Aggro Flag [0 = Aggro NPCs Off, 1 = Aggro NPCs On]" + ); + c->Message(Chat::White, "Usage: #npcedit spawn_limit [Limit] - Sets an NPC's Spawn Limit Counter"); + c->Message(Chat::White, "Usage: #npcedit attackspeed [Attack Speed] - Sets an NPC's Attack Speed Modifier"); + c->Message(Chat::White, "Usage: #npcedit attackdelay [Attack Delay] - Sets an NPC's Attack Delay"); + c->Message( + Chat::White, + "Usage: #npcedit findable [Flag] - Sets an NPC's Findable Flag [0 = Not Findable, 1 = Findable]" + ); + c->Message(Chat::White, "Usage: #npcedit str [Strength] - Sets an NPC's Strength"); + c->Message(Chat::White, "Usage: #npcedit sta [Stamina] - Sets an NPC's Stamina"); + c->Message(Chat::White, "Usage: #npcedit agi [Agility] - Sets an NPC's Agility"); + c->Message(Chat::White, "Usage: #npcedit dex [Dexterity] - Sets an NPC's Dexterity"); + c->Message(Chat::White, "Usage: #npcedit int [Intelligence] - Sets an NPC's Intelligence"); + c->Message(Chat::White, "Usage: #npcedit wis [Wisdom] - Sets an NPC's Wisdom"); + c->Message(Chat::White, "Usage: #npcedit cha [Charisma] - Sets an NPC's Charisma"); + c->Message( + Chat::White, + "Usage: #npcedit seehide [Flag] - Sets an NPC's See Hide Flag [0 = Cannot See Hide, 1 = Can See Hide]" + ); + c->Message( + Chat::White, + "Usage: #npcedit seeimprovedhide [Flag] - Sets an NPC's See Improved Hide Flag [0 = Cannot See Improved Hide, 1 = Can See Improved Hide]" + ); + c->Message( + Chat::White, + "Usage: #npcedit trackable [Flag] - Sets an NPC's Trackable Flag [0 = Not Trackable, 1 = Trackable]" + ); + c->Message(Chat::White, "Usage: #npcedit atk [Attack] - Sets an NPC's Attack"); + c->Message(Chat::White, "Usage: #npcedit accuracy [Accuracy] - Sets an NPC's Accuracy"); + c->Message(Chat::White, "Usage: #npcedit avoidance [Avoidance] - Sets an NPC's Avoidance"); + c->Message(Chat::White, "Usage: #npcedit slow_mitigation [Slow Mitigation] - Sets an NPC's Slow Mitigation"); + c->Message(Chat::White, "Usage: #npcedit version [Version] - Sets an NPC's Version"); + c->Message(Chat::White, "Usage: #npcedit maxlevel [Max Level] - Sets an NPC's Maximum Level"); + c->Message( + Chat::White, + "Usage: #npcedit scalerate [Scale Rate] - Sets an NPC's Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" + ); + c->Message( + Chat::White, + "Usage: #npcedit spellscale [Scale Rate] - Sets an NPC's Spell Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" + ); + c->Message( + Chat::White, + "Usage: #npcedit healscale [Scale Rate] - Sets an NPC's Heal Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" + ); + c->Message( + Chat::White, + "Usage: #npcedit no_target [Flag] - Sets an NPC's No Target Hotkey Flag [0 = Not Targetable with Target Hotkey, 1 = Targetable with Target Hotkey]" + ); + c->Message( + Chat::White, + "Usage: #npcedit raidtarget [Flag] - Sets an NPC's Raid Target Flag [0 = Not a Raid Target, 1 = Raid Target]" + ); + c->Message(Chat::White, "Usage: #npcedit armtexture [Texture] - Sets an NPC's Arm Texture"); + c->Message(Chat::White, "Usage: #npcedit bracertexture [Texture] - Sets an NPC's Bracer Texture"); + c->Message(Chat::White, "Usage: #npcedit handtexture [Texture] - Sets an NPC's Hand Texture"); + c->Message(Chat::White, "Usage: #npcedit legtexture [Texture] - Sets an NPC's Leg Texture"); + c->Message(Chat::White, "Usage: #npcedit feettexture [Texture] - Sets an NPC's Feet Texture"); + c->Message(Chat::White, "Usage: #npcedit walkspeed [Walk Speed] - Sets an NPC's Walk Speed"); + c->Message(Chat::White, "Usage: #npcedit show_name [Flag] - Sets an NPC's Show Name Flag [0 = Hidden, 1 = Shown]"); + c->Message( + Chat::White, + "Usage: #npcedit untargetable [Flag] - Sets an NPC's Untargetable Flag [0 = Targetable, 1 = Untargetable]" + ); + c->Message(Chat::White, "Usage: #npcedit charm_ac [Armor Class] - Sets an NPC's Armor Class while Charmed"); + c->Message(Chat::White, "Usage: #npcedit charm_min_dmg [Damage] - Sets an NPC's Minimum Damage while Charmed"); + c->Message(Chat::White, "Usage: #npcedit charm_max_dmg [Damage] - Sets an NPC's Maximum Damage while Charmed"); + c->Message( + Chat::White, + "Usage: #npcedit charm_attack_delay [Attack Delay] - Sets an NPC's Attack Delay while Charmed" + ); + c->Message( + Chat::White, + "Usage: #npcedit charm_accuracy_rating [Accuracy] - Sets an NPC's Accuracy Rating while Charmed" + ); + c->Message( + Chat::White, + "Usage: #npcedit charm_avoidance_rating [Avoidance] - Sets an NPC's Avoidance Rating while Charmed" + ); + c->Message(Chat::White, "Usage: #npcedit charm_atk [Attack] - Sets an NPC's Attack while Charmed"); + c->Message( + Chat::White, + "Usage: #npcedit skip_global_loot [Flag] - Sets an NPC's Skip Global Loot Flag [0 = Don't Skip, 1 = Skip" + ); + c->Message( + Chat::White, + "Usage: #npcedit rarespawn [Flag] - Sets an NPC's Rare Spawn Flag [0 = Not a Rare Spawn, 1 = Rare Spawn]" + ); + c->Message( + Chat::White, + "Usage: #npcedit stuck_behavior [Stuck Behavior] - Sets an NPC's Stuck Behavior [0 = Run to Target, 1 = Warp to Target, 2 = Take No Action, 3 = Evade Combat]" + ); + c->Message( + Chat::White, + "Usage: #npcedit flymode [Fly Mode] - Sets an NPC's Fly Mode [0 = Ground, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating While Running]" + ); + c->Message( + Chat::White, + "Usage: #npcedit always_aggro [Flag] - Sets an NPC's Always Aggro Flag [0 = Does not Always Aggro, 1 = Always Aggro]" + ); + c->Message( + Chat::White, + "Usage: #npcedit exp_mod [Modifier] - Sets an NPC's Experience Modifier [50 = 50%, 100 = 100%, 200 = 200%]" + ); + c->Message( + Chat::White, + "Usage: #npcedit keeps_sold_items [Flag] - Sets an NPC's Keeps Sold Items Flag [0 = False, 1 = True]" + ); + c->Message( + Chat::White, + "Usage: #npcedit setanimation [Animation ID] - Sets an NPC's Animation on Spawn (Stored in spawn2 table)" + ); + c->Message( + Chat::White, + "Usage: #npcedit respawntime [Respawn Time] - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)" + ); +} diff --git a/zone/gm_commands/npceditmass.cpp b/zone/gm_commands/npceditmass.cpp index c76f209e0..a8542c9e4 100755 --- a/zone/gm_commands/npceditmass.cpp +++ b/zone/gm_commands/npceditmass.cpp @@ -72,7 +72,7 @@ void command_npceditmass(Client *c, const Seperator *sep) Chat::Yellow, fmt::format( "Possible columns [{}]", - implode(options_glue, possible_column_options) + Strings::Implode(options_glue, possible_column_options) ).c_str() ); return; @@ -91,7 +91,7 @@ void command_npceditmass(Client *c, const Seperator *sep) Chat::Yellow, fmt::format( "Possible columns [{}]", - implode(options_glue, possible_column_options) + Strings::Implode(options_glue, possible_column_options) ).c_str() ); return; @@ -139,7 +139,7 @@ void command_npceditmass(Client *c, const Seperator *sep) for (auto row : results) { std::string npc_id = row[0]; std::string npc_name = row[1]; - std::string search_column_value = str_tolower(row[2]); + std::string search_column_value = Strings::ToLower(row[2]); std::string change_column_current_value = row[3]; if (exact_match) { @@ -183,7 +183,7 @@ void command_npceditmass(Client *c, const Seperator *sep) ); if (strcasecmp(sep->arg[5], "apply") == 0) { - std::string npc_ids_string = implode(",", npc_ids); + std::string npc_ids_string = Strings::Implode(",", npc_ids); if (npc_ids_string.empty()) { c->Message(Chat::Red, "Error: Ran into an unknown error compiling NPC IDs"); return; @@ -223,7 +223,7 @@ void command_npceditmass(Client *c, const Seperator *sep) Chat::Yellow, fmt::format( "Would you like to {} these changes?", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "apply") + Saylink::Silent(saylink, "apply") ).c_str() ); diff --git a/zone/gm_commands/npcloot.cpp b/zone/gm_commands/npcloot.cpp index 30ff7da4a..a3c50854f 100755 --- a/zone/gm_commands/npcloot.cpp +++ b/zone/gm_commands/npcloot.cpp @@ -8,7 +8,7 @@ void command_npcloot(Client *c, const Seperator *sep) c->Message(Chat::White, "You must target an NPC or a Corpse to use this command."); return; } - + int arguments = sep->argnum; if (!arguments) { c->Message(Chat::White, "Usage: #npcloot add [Item ID] [Charges] [Equip] [Augment 1 ID] [Augment 2 ID] [Augment 3 ID] [Augment 4 ID] [Augment 5 ID] [Augment 6 ID] - Adds the specified item to an NPC's loot"); @@ -132,12 +132,12 @@ void command_npcloot(Client *c, const Seperator *sep) gold || platinum ) ? - ConvertMoneyToString( - platinum, - gold, - silver, - copper - ) : + Strings::Money( + platinum, + gold, + silver, + copper + ) : "no money" ); diff --git a/zone/gm_commands/nudge.cpp b/zone/gm_commands/nudge.cpp index e8f4bfaa0..0d80acacd 100755 --- a/zone/gm_commands/nudge.cpp +++ b/zone/gm_commands/nudge.cpp @@ -2,67 +2,74 @@ void command_nudge(Client *c, const Seperator *sep) { - if (sep->arg[1][0] == 0) { - c->Message(Chat::White, "Usage: #nudge [x=f] [y=f] [z=f] [h=f] (partial/mixed arguments allowed)"); - } - else { - - auto target = c->GetTarget(); - if (!target) { - - c->Message(Chat::Yellow, "This command requires a target."); - return; - } - if (target->IsMoving()) { - - c->Message(Chat::Yellow, "This command requires a stationary target."); - return; - } - - glm::vec4 position_offset(0.0f, 0.0f, 0.0f, 0.0f); - for (auto index = 1; index <= 4; ++index) { - - if (!sep->arg[index]) { - continue; - } - - Seperator argsep(sep->arg[index], '='); - if (!argsep.arg[1][0]) { - continue; - } - - switch (argsep.arg[0][0]) { - case 'x': - position_offset.x = atof(argsep.arg[1]); - break; - case 'y': - position_offset.y = atof(argsep.arg[1]); - break; - case 'z': - position_offset.z = atof(argsep.arg[1]); - break; - case 'h': - position_offset.w = atof(argsep.arg[1]); - break; - default: - break; - } - } - - const auto ¤t_position = target->GetPosition(); - glm::vec4 new_position( - (current_position.x + position_offset.x), - (current_position.y + position_offset.y), - (current_position.z + position_offset.z), - (current_position.w + position_offset.w) - ); - - target->GMMove(new_position.x, new_position.y, new_position.z, new_position.w); - + int arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #nudge [x=float] [y=float] [z=float] [h=float]"); c->Message( Chat::White, - "Nudging '%s' to {%1.3f, %1.3f, %1.3f, %1.2f} (adjustment: {%1.3f, %1.3f, %1.3f, %1.2f})", - target->GetName(), + fmt::format( + "Note: Partial or mixed arguments allowed, example {}.", + Saylink::Silent("#nudge x=5.0") + ).c_str() + ); + return; + } + + auto target = c->GetTarget(); + if (!target) { + c->Message(Chat::White, "You must have a target to use this command."); + return; + } + + if (target->IsMoving()) { + c->Message(Chat::White, "This command requires a stationary target."); + return; + } + + glm::vec4 position_offset(0.0f, 0.0f, 0.0f, 0.0f); + for (auto index = 1; index <= 4; ++index) { + if (!sep->arg[index]) { + continue; + } + + Seperator argsep(sep->arg[index], '='); + if (!argsep.arg[1][0]) { + continue; + } + + switch (argsep.arg[0][0]) { + case 'x': + position_offset.x = std::stof(argsep.arg[1]); + break; + case 'y': + position_offset.y = std::stof(argsep.arg[1]); + break; + case 'z': + position_offset.z = std::stof(argsep.arg[1]); + break; + case 'h': + position_offset.w = std::stof(argsep.arg[1]); + break; + default: + break; + } + } + + const auto& current_position = target->GetPosition(); + glm::vec4 new_position( + (current_position.x + position_offset.x), + (current_position.y + position_offset.y), + (current_position.z + position_offset.z), + (current_position.w + position_offset.w) + ); + + target->GMMove(new_position.x, new_position.y, new_position.z, new_position.w); + + c->Message( + Chat::White, + fmt::format( + "Nudging {} to {:.2f}, {:.2f}, {:.2f}, {:.2f} with offsets of {:.2f}, {:.2f}, {:.2f}, {:.2f}.", + c->GetTargetDescription(target), new_position.x, new_position.y, new_position.z, @@ -71,7 +78,7 @@ void command_nudge(Client *c, const Seperator *sep) position_offset.y, position_offset.z, position_offset.w - ); - } + ).c_str() + ); } diff --git a/zone/gm_commands/nukebuffs.cpp b/zone/gm_commands/nukebuffs.cpp index c28504755..27db600fb 100755 --- a/zone/gm_commands/nukebuffs.cpp +++ b/zone/gm_commands/nukebuffs.cpp @@ -1,13 +1,13 @@ #include "../client.h" void command_nukebuffs(Client *c, const Seperator *sep) -{ +{ Mob* target = c; if (c->GetTarget()) { target = c->GetTarget(); } - std::string buff_identifier = str_tolower(sep->arg[1]); + std::string buff_identifier = Strings::ToLower(sep->arg[1]); std::string buff_type; bool is_beneficial = buff_identifier.find("beneficial") != std::string::npos; bool is_detrimental = buff_identifier.find("detrimental") != std::string::npos; diff --git a/zone/gm_commands/object.cpp b/zone/gm_commands/object.cpp index 9c233cd80..0784ec2d2 100755 --- a/zone/gm_commands/object.cpp +++ b/zone/gm_commands/object.cpp @@ -1122,8 +1122,8 @@ void command_object(Client *c, const Seperator *sep) app = new EQApplicationPacket(); o->CreateDeSpawnPacket(app); entity_list.QueueClients(nullptr, app); - entity_list.RemoveObject(o->GetID()); + safe_delete(app); // Verifying ZoneID and Version in case someone else ended up adding an object with our ID // from a different zone/version. Don't want to delete someone else's work. diff --git a/zone/gm_commands/oocmute.cpp b/zone/gm_commands/oocmute.cpp index a1e1199a2..a19f424ec 100755 --- a/zone/gm_commands/oocmute.cpp +++ b/zone/gm_commands/oocmute.cpp @@ -5,14 +5,24 @@ extern WorldServer worldserver; void command_oocmute(Client *c, const Seperator *sep) { - if (sep->arg[1][0] == 0 || !(sep->arg[1][0] == '1' || sep->arg[1][0] == '0')) { - c->Message(Chat::White, "Usage: #oocmute [1/0]"); - } - else { - auto outapp = new ServerPacket(ServerOP_OOCMute, 1); - *(outapp->pBuffer) = atoi(sep->arg[1]); - worldserver.SendPacket(outapp); - safe_delete(outapp); + if (!sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #oocmute [0|1] - Enable or Disable Server OOC"); + return; } + + bool is_muted = std::stoi(sep->arg[1]) ? true : false; + + ServerPacket pack(ServerOP_OOCMute, sizeof(ServerOOCMute_Struct)); + auto o = (ServerOOCMute_Struct*) pack.pBuffer; + o->is_muted = is_muted; + worldserver.SendPacket(&pack); + + c->Message( + Chat::White, + fmt::format( + "Server OOC is {} muted.", + is_muted ? "now" : "no longer" + ).c_str() + ); } diff --git a/zone/gm_commands/opcode.cpp b/zone/gm_commands/opcode.cpp index 8c8601e96..f98c39ef1 100755 --- a/zone/gm_commands/opcode.cpp +++ b/zone/gm_commands/opcode.cpp @@ -3,9 +3,7 @@ void command_opcode(Client *c, const Seperator *sep) { - if (!strcasecmp(sep->arg[1], "reload")) { - ReloadAllPatches(); - c->Message(Chat::White, "Opcodes for all patches have been reloaded"); - } + ReloadAllPatches(); + c->Message(Chat::White, "Opcodes for all patches have been reloaded"); } diff --git a/zone/gm_commands/path.cpp b/zone/gm_commands/path.cpp index 80207e07c..79d33c3cd 100755 --- a/zone/gm_commands/path.cpp +++ b/zone/gm_commands/path.cpp @@ -7,21 +7,3 @@ void command_path(Client *c, const Seperator *sep) } } -void Client::Undye() -{ - for (int cur_slot = EQ::textures::textureBegin; cur_slot <= EQ::textures::LastTexture; cur_slot++) { - uint8 slot2 = SlotConvert(cur_slot); - EQ::ItemInstance *inst = m_inv.GetItem(slot2); - - if (inst != nullptr) { - inst->SetColor(inst->GetItem()->Color); - database.SaveInventory(CharacterID(), inst, slot2); - } - - m_pp.item_tint.Slot[cur_slot].Color = 0; - SendWearChange(cur_slot); - } - - database.DeleteCharacterDye(CharacterID()); -} - diff --git a/zone/gm_commands/peqzone.cpp b/zone/gm_commands/peqzone.cpp index 9dfb31651..cf4d66c4f 100755 --- a/zone/gm_commands/peqzone.cpp +++ b/zone/gm_commands/peqzone.cpp @@ -16,7 +16,7 @@ void command_peqzone(Client *c, const Seperator *sep) Chat::White, fmt::format( "You must wait {} before using this command again.", - ConvertSecondsToTime(time_left) + Strings::SecondsToTime(time_left) ).c_str() ); return; diff --git a/zone/gm_commands/profilereset.cpp b/zone/gm_commands/profilereset.cpp deleted file mode 100755 index 0f98dae23..000000000 --- a/zone/gm_commands/profilereset.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "../client.h" - -void command_profilereset(Client *c, const Seperator *sep) -{ - ResetZoneProfile(); -} -#endif - diff --git a/zone/gm_commands/qglobal.cpp b/zone/gm_commands/qglobal.cpp index 301ef4a84..e065b23ff 100755 --- a/zone/gm_commands/qglobal.cpp +++ b/zone/gm_commands/qglobal.cpp @@ -29,7 +29,7 @@ void command_qglobal(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #qglobal on - Enables target NPC's ability to view quest globals"); c->Message(Chat::White, "Usage: #qglobal off - Disables target NPC's ability to view quest globals"); c->Message(Chat::White, "Usage: #qglobal view - View target NPC's ability to view quest globals"); - return; + return; } if (is_off) { @@ -50,11 +50,7 @@ void command_qglobal(Client *c, const Seperator *sep) return; } - auto repop_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#repop", - false, - "repop" - ); + auto repop_link = Saylink::Silent("#repop", "repop"); c->Message( Chat::White, @@ -83,11 +79,7 @@ void command_qglobal(Client *c, const Seperator *sep) return; } - auto repop_link = EQ::SayLinkEngine::GenerateQuestSaylink( - "#repop", - false, - "repop" - ); + auto repop_link = Saylink::Silent("#repop", "repop"); c->Message( Chat::White, diff --git a/zone/gm_commands/raidloot.cpp b/zone/gm_commands/raidloot.cpp index 9dfb1c21c..b75eb43c2 100755 --- a/zone/gm_commands/raidloot.cpp +++ b/zone/gm_commands/raidloot.cpp @@ -22,7 +22,7 @@ void command_raidloot(Client *c, const Seperator *sep) return; } - std::string raid_loot_type = str_tolower(sep->arg[1]); + std::string raid_loot_type = Strings::ToLower(sep->arg[1]); bool is_all = raid_loot_type.find("all") != std::string::npos; bool is_group_leader = raid_loot_type.find("groupleader") != std::string::npos; bool is_raid_leader = raid_loot_type.find("raidleader") != std::string::npos; diff --git a/zone/gm_commands/reload.cpp b/zone/gm_commands/reload.cpp index 16526152e..2f4e9511e 100644 --- a/zone/gm_commands/reload.cpp +++ b/zone/gm_commands/reload.cpp @@ -2,42 +2,49 @@ void command_reload(Client *c, const Seperator *sep) { - int arguments = sep->argnum; - if (!arguments) { + std::string command = sep->arg[0] ? sep->arg[0] : ""; + int arguments = sep->argnum; + if (!arguments && Strings::Contains(command, "#reload")) { c->SendReloadCommandMessages(); return; } - bool is_aa = !strcasecmp(sep->arg[1], "aa"); + bool is_rq_alias = sep->arg[0] && Strings::Contains(command, "#rq"); + bool is_logs_reload_alias = sep->arg[0] && Strings::Contains(command, "#rl"); + bool is_aa = !strcasecmp(sep->arg[1], "aa"); bool is_alternate_currencies = !strcasecmp(sep->arg[1], "alternate_currencies"); - bool is_blocked_spells = !strcasecmp(sep->arg[1], "blocked_spells"); - bool is_content_flags = !strcasecmp(sep->arg[1], "content_flags"); - bool is_doors = !strcasecmp(sep->arg[1], "doors"); - bool is_ground_spawns = !strcasecmp(sep->arg[1], "ground_spawns"); - bool is_level_mods = !strcasecmp(sep->arg[1], "level_mods"); - bool is_logs = !strcasecmp(sep->arg[1], "logs"); - bool is_merchants = !strcasecmp(sep->arg[1], "merchants"); - bool is_npc_emotes = !strcasecmp(sep->arg[1], "npc_emotes"); - bool is_objects = !strcasecmp(sep->arg[1], "objects"); - bool is_perl_export = !strcasecmp(sep->arg[1], "perl_export"); - bool is_quest = !strcasecmp(sep->arg[1], "quest"); - bool is_rules = !strcasecmp(sep->arg[1], "rules"); - bool is_static = !strcasecmp(sep->arg[1], "static"); - bool is_tasks = !strcasecmp(sep->arg[1], "tasks"); - bool is_titles = !strcasecmp(sep->arg[1], "titles"); - bool is_traps = !strcasecmp(sep->arg[1], "traps"); - bool is_variables = !strcasecmp(sep->arg[1], "variables"); - bool is_veteran_rewards = !strcasecmp(sep->arg[1], "veteran_rewards"); - bool is_world = !strcasecmp(sep->arg[1], "world"); - bool is_zone = !strcasecmp(sep->arg[1], "zone"); - bool is_zone_points = !strcasecmp(sep->arg[1], "zone_points"); + bool is_blocked_spells = !strcasecmp(sep->arg[1], "blocked_spells"); + bool is_commands = !strcasecmp(sep->arg[1], "commands"); + bool is_content_flags = !strcasecmp(sep->arg[1], "content_flags"); + bool is_doors = !strcasecmp(sep->arg[1], "doors"); + bool is_dztemplates = !strcasecmp(sep->arg[1], "dztemplates"); + bool is_ground_spawns = !strcasecmp(sep->arg[1], "ground_spawns"); + bool is_level_mods = !strcasecmp(sep->arg[1], "level_mods"); + bool is_logs = !strcasecmp(sep->arg[1], "logs") || is_logs_reload_alias; + bool is_merchants = !strcasecmp(sep->arg[1], "merchants"); + bool is_npc_emotes = !strcasecmp(sep->arg[1], "npc_emotes"); + bool is_objects = !strcasecmp(sep->arg[1], "objects"); + bool is_perl_export = !strcasecmp(sep->arg[1], "perl_export"); + bool is_quest = !strcasecmp(sep->arg[1], "quest") || (is_rq_alias); + bool is_rules = !strcasecmp(sep->arg[1], "rules"); + bool is_static = !strcasecmp(sep->arg[1], "static"); + bool is_tasks = !strcasecmp(sep->arg[1], "tasks"); + bool is_titles = !strcasecmp(sep->arg[1], "titles"); + bool is_traps = !strcasecmp(sep->arg[1], "traps"); + bool is_variables = !strcasecmp(sep->arg[1], "variables"); + bool is_veteran_rewards = !strcasecmp(sep->arg[1], "veteran_rewards"); + bool is_world = !strcasecmp(sep->arg[1], "world"); + bool is_zone = !strcasecmp(sep->arg[1], "zone"); + bool is_zone_points = !strcasecmp(sep->arg[1], "zone_points"); if ( !is_aa && !is_alternate_currencies && !is_blocked_spells && + !is_commands && !is_content_flags && !is_doors && + !is_dztemplates && !is_ground_spawns && !is_level_mods && !is_logs && @@ -56,55 +63,75 @@ void command_reload(Client *c, const Seperator *sep) !is_world && !is_zone && !is_zone_points - ) { + ) { c->SendReloadCommandMessages(); return; } - auto pack = new ServerPacket; + ServerPacket *pack = nullptr; if (is_aa) { - c->Message(Chat::White, "Attempting to reload Alternate Advancement Data globally."); + c->Message(Chat::White, "Attempting to reload Alternate Advancement Data globally."); pack = new ServerPacket(ServerOP_ReloadAAData, 0); - } else if (is_alternate_currencies) { - c->Message(Chat::White, "Attempting to reload Alternate Currencies globally."); + } + else if (is_alternate_currencies) { + c->Message(Chat::White, "Attempting to reload Alternate Currencies globally."); pack = new ServerPacket(ServerOP_ReloadAlternateCurrencies, 0); - } else if (is_blocked_spells) { - c->Message(Chat::White, "Attempting to reload Blocked Spells globally."); + } + else if (is_blocked_spells) { + c->Message(Chat::White, "Attempting to reload Blocked Spells globally."); pack = new ServerPacket(ServerOP_ReloadBlockedSpells, 0); - } else if (is_content_flags) { + } + else if (is_commands) { + c->Message(Chat::White, "Attempting to reload Commands globally."); + pack = new ServerPacket(ServerOP_ReloadCommands, 0); + } + else if (is_content_flags) { c->Message(Chat::White, "Attempting to reload Content Flags globally."); pack = new ServerPacket(ServerOP_ReloadContentFlags, 0); - } else if (is_doors) { - c->Message(Chat::White, "Attempting to reload Doors globally."); + } + else if (is_doors) { + c->Message(Chat::White, "Attempting to reload Doors globally."); pack = new ServerPacket(ServerOP_ReloadDoors, 0); - } else if (is_ground_spawns) { - c->Message(Chat::White, "Attempting to reload Ground Spawns globally."); + } + else if (is_dztemplates) { + c->Message(Chat::White, "Attempting to reload Dynamic Zone Templates globally."); + pack = new ServerPacket(ServerOP_ReloadDzTemplates, 0); + } + else if (is_ground_spawns) { + c->Message(Chat::White, "Attempting to reload Ground Spawns globally."); pack = new ServerPacket(ServerOP_ReloadGroundSpawns, 0); - } else if (is_level_mods) { + } + else if (is_level_mods) { if (!RuleB(Zone, LevelBasedEXPMods)) { c->Message(Chat::White, "Level Based Experience Modifiers are disabled."); return; } - + c->Message(Chat::White, "Attempting to reload Level Based Experience Modifiers globally."); pack = new ServerPacket(ServerOP_ReloadLevelEXPMods, 0); - } else if (is_logs) { + } + else if (is_logs) { c->Message(Chat::White, "Attempting to reload Log Settings globally."); pack = new ServerPacket(ServerOP_ReloadLogs, 0); - } else if (is_merchants) { + } + else if (is_merchants) { c->Message(Chat::White, "Attempting to reload Merchants globally."); pack = new ServerPacket(ServerOP_ReloadMerchants, 0); - } else if (is_npc_emotes) { + } + else if (is_npc_emotes) { c->Message(Chat::White, "Attempting to reload NPC Emotes globally."); pack = new ServerPacket(ServerOP_ReloadNPCEmotes, 0); - } else if (is_objects) { + } + else if (is_objects) { c->Message(Chat::White, "Attempting to reload Objects globally."); pack = new ServerPacket(ServerOP_ReloadObjects, 0); - } else if (is_perl_export) { + } + else if (is_perl_export) { c->Message(Chat::White, "Attempting to reload Perl Event Export Settings globally."); pack = new ServerPacket(ServerOP_ReloadPerlExportSettings, 0); - } else if (is_quest) { + } + else if (is_quest) { bool stop_timers = false; if (sep->IsNumber(2)) { @@ -124,28 +151,34 @@ void command_reload(Client *c, const Seperator *sep) entity_list.ClearAreas(); parse->ReloadQuests(stop_timers); - } else if (is_rules) { + } + else if (is_rules) { c->Message(Chat::White, "Attempting to reload Rules globally."); pack = new ServerPacket(ServerOP_ReloadRules, 0); - } else if (is_static) { + } + else if (is_static) { c->Message(Chat::White, "Attempting to reload Static Zone Data globally."); pack = new ServerPacket(ServerOP_ReloadStaticZoneData, 0); - } else if (is_tasks) { + } + else if (is_tasks) { uint32 task_id = 0; if (!sep->IsNumber(2)) { c->Message(Chat::White, "Attempting to reload Tasks globally."); pack = new ServerPacket(ServerOP_ReloadTasks, sizeof(ReloadTasks_Struct)); - } else { + } + else { task_id = std::stoul(sep->arg[2]); } - - auto rts = (ReloadTasks_Struct*) pack->pBuffer; + + auto rts = (ReloadTasks_Struct *) pack->pBuffer; rts->reload_type = RELOADTASKS; - rts->task_id = task_id; - } else if (is_titles) { + rts->task_id = task_id; + } + else if (is_titles) { c->Message(Chat::White, "Attempting to reload Titles globally."); pack = new ServerPacket(ServerOP_ReloadTitles, 0); - } else if (is_traps) { + } + else if (is_traps) { if (arguments < 2 || !sep->IsNumber(2)) { entity_list.UpdateAllTraps(true, true); c->Message( @@ -174,13 +207,16 @@ void command_reload(Client *c, const Seperator *sep) c->Message(Chat::White, "Attempting to reload Traps globally."); pack = new ServerPacket(ServerOP_ReloadTraps, 0); - } else if (is_variables) { + } + else if (is_variables) { c->Message(Chat::White, "Attempting to reload Variables globally."); pack = new ServerPacket(ServerOP_ReloadVariables, 0); - } else if (is_veteran_rewards) { + } + else if (is_veteran_rewards) { c->Message(Chat::White, "Attempting to reload Veteran Rewards globally."); pack = new ServerPacket(ServerOP_ReloadVeteranRewards, 0); - } else if (is_world) { + } + else if (is_world) { uint8 global_repop = ReloadWorld::NoRepop; if (sep->IsNumber(2)) { @@ -197,20 +233,23 @@ void command_reload(Client *c, const Seperator *sep) "Attempting to reload Quests {}worldwide.", ( global_repop ? - ( - global_repop == ReloadWorld::Repop ? - "and repop NPCs " : - "and forcefully repop NPCs " - ) : - "" + ( + global_repop == ReloadWorld::Repop ? + "and repop NPCs " : + "and forcefully repop NPCs " + ) : + "" ) ).c_str() ); pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); - auto RW = (ReloadWorld_Struct *) pack->pBuffer; + auto RW = (ReloadWorld_Struct *) pack->pBuffer; RW->global_repop = global_repop; - } else if (is_zone) { + } + else if (is_zone) { + zone_store.LoadZones(content_db); + if (arguments < 2) { c->Message( Chat::White, @@ -218,8 +257,8 @@ void command_reload(Client *c, const Seperator *sep) "Zone Header Load {} | Zone: {}", ( zone->LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion()) ? - "Suceeded" : - "Failed" + "Succeeded" : + "Failed" ), zone->GetZoneDescription() ).c_str() @@ -229,8 +268,8 @@ void command_reload(Client *c, const Seperator *sep) auto zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : - ZoneID(sep->arg[2]) + std::stoul(sep->arg[2]) : + ZoneID(sep->arg[2]) ); if (!zone_id) { c->Message( @@ -244,13 +283,13 @@ void command_reload(Client *c, const Seperator *sep) } auto zone_short_name = ZoneName(zone_id); - auto zone_long_name = ZoneLongName(zone_id); - auto version = ( + auto zone_long_name = ZoneLongName(zone_id); + auto version = ( sep->IsNumber(3) ? - std::stoul(sep->arg[3]) : - 0 + std::stoul(sep->arg[3]) : + 0 ); - + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); @@ -262,27 +301,28 @@ void command_reload(Client *c, const Seperator *sep) "Zone Header Load {} | Zone: {} ({}){}", ( zone->LoadZoneCFG(zone_short_name, version) ? - "Suceeded" : - "Failed" + "Succeeded" : + "Failed" ), zone_long_name, zone_short_name, ( version ? - fmt::format( - " Version: {}", - version - ) : - "" + fmt::format( + " Version: {}", + version + ) : + "" ) ).c_str() ); - } else if (is_zone_points) { + } + else if (is_zone_points) { c->Message(Chat::White, "Attempting to reloading Zone Points globally."); pack = new ServerPacket(ServerOP_ReloadZonePoints, 0); } - - if (pack->opcode) { + + if (pack) { worldserver.SendPacket(pack); } diff --git a/zone/gm_commands/repop.cpp b/zone/gm_commands/repop.cpp index e1d4d6dbe..aa98b105d 100755 --- a/zone/gm_commands/repop.cpp +++ b/zone/gm_commands/repop.cpp @@ -4,9 +4,9 @@ void command_repop(Client *c, const Seperator *sep) { int arguments = sep->argnum; if (!arguments) { + entity_list.ClearAreas(); c->Message(Chat::White, "Zone depopped, repopping now."); zone->Repop(); - zone->spawn2_timer.Trigger(); return; } @@ -15,11 +15,10 @@ void command_repop(Client *c, const Seperator *sep) if (is_force) { zone->ClearSpawnTimers(); c->Message(Chat::White, "Zone depopped, forcefully repopping now."); - } else { + } else { c->Message(Chat::White, "Zone depopped, repopping now."); } zone->Repop(); - zone->spawn2_timer.Trigger(); } diff --git a/zone/gm_commands/roambox.cpp b/zone/gm_commands/roambox.cpp index e3056c223..1955fb09c 100755 --- a/zone/gm_commands/roambox.cpp +++ b/zone/gm_commands/roambox.cpp @@ -91,7 +91,7 @@ void command_roambox(Client *c, const Seperator *sep) box_size, c->GetTargetDescription(target), spawn_group_id, - ConvertMillisecondsToTime(delay), + Strings::MillisecondsToTime(delay), delay ).c_str() ); diff --git a/zone/gm_commands/rules.cpp b/zone/gm_commands/rules.cpp index 65ef8bc37..e14e95e8d 100755 --- a/zone/gm_commands/rules.cpp +++ b/zone/gm_commands/rules.cpp @@ -1,232 +1,451 @@ #include "../client.h" +#include "../command.h" + +#include "../../common/repositories/rule_sets_repository.h" +#include "../../common/repositories/rule_values_repository.h" void command_rules(Client *c, const Seperator *sep) { - //super-command for managing rules settings - if (sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help")) { - c->Message(Chat::White, "Syntax: #rules [subcommand]."); - c->Message(Chat::White, "-- Rule Set Manipulation --"); - c->Message(Chat::White, "...listsets - List avaliable rule sets"); - c->Message(Chat::White, "...current - gives the name of the ruleset currently running in this zone"); - c->Message(Chat::White, "...reload - Reload the selected ruleset in this zone"); - c->Message(Chat::White, "...switch (ruleset name) - Change the selected ruleset and load it"); - c->Message( - Chat::White, - "...load (ruleset name) - Load a ruleset in just this zone without changing the selected set" - ); -//too lazy to write this right now: -// c->Message(Chat::White, "...wload (ruleset name) - Load a ruleset in all zones without changing the selected set"); - c->Message(Chat::White, "...store [ruleset name] - Store the running ruleset as the specified name"); - c->Message(Chat::White, "---------------------"); - c->Message(Chat::White, "-- Running Rule Manipulation --"); - c->Message(Chat::White, "...reset - Reset all rules to their default values"); - c->Message(Chat::White, "...get [rule] - Get the specified rule's local value"); - c->Message(Chat::White, "...set (rule) (value) - Set the specified rule to the specified value locally only"); - c->Message( - Chat::White, - "...setdb (rule) (value) - Set the specified rule to the specified value locally and in the DB" - ); - c->Message( - Chat::White, - "...list [catname] - List all rules in the specified category (or all categiries if omitted)" - ); - c->Message(Chat::White, "...values [catname] - List the value of all rules in the specified category"); + auto arguments = sep->argnum; + bool is_help = !strcasecmp(sep->arg[1], "help"); + if (!arguments || is_help) { + SendRuleSubCommands(c); return; } - if (!strcasecmp(sep->arg[1], "current")) { - c->Message( - Chat::White, "Currently running ruleset '%s' (%d)", RuleManager::Instance()->GetActiveRuleset(), - RuleManager::Instance()->GetActiveRulesetID()); + bool is_current = !strcasecmp(sep->arg[1], "current"); + bool is_get = !strcasecmp(sep->arg[1], "get"); + bool is_list = !strcasecmp(sep->arg[1], "list"); + bool is_list_sets = !strcasecmp(sep->arg[1], "listsets"); + bool is_load = !strcasecmp(sep->arg[1], "load"); + bool is_reload = !strcasecmp(sep->arg[1], "reload"); + bool is_reset = !strcasecmp(sep->arg[1], "reset"); + bool is_set = !strcasecmp(sep->arg[1], "set"); + bool is_set_db = !strcasecmp(sep->arg[1], "setdb"); + bool is_store = !strcasecmp(sep->arg[1], "store"); + bool is_switch = !strcasecmp(sep->arg[1], "switch"); + bool is_values = !strcasecmp(sep->arg[1], "values"); + if ( + !is_current && + !is_get && + !is_list && + !is_list_sets && + !is_load && + !is_reload && + !is_reset && + !is_set && + !is_set_db && + !is_store && + !is_switch && + !is_values + ) { + SendRuleSubCommands(c); + return; } - else if (!strcasecmp(sep->arg[1], "listsets")) { - std::map sets; - if (!RuleManager::Instance()->ListRulesets(&database, sets)) { - c->Message(Chat::Red, "Failed to list rule sets!"); + + if (is_current) { + c->Message( + Chat::White, + fmt::format( + "Currently running Rule Set {} ({}).", + RuleManager::Instance()->GetActiveRuleset(), + RuleManager::Instance()->GetActiveRulesetID() + ).c_str() + ); + } else if (is_list_sets) { + std::map m; + if (!RuleManager::Instance()->ListRulesets(&database, m)) { + c->Message(Chat::White, "Failed to list Rule Sets!"); return; } - c->Message(Chat::White, "Avaliable rule sets:"); - std::map::iterator cur, end; - cur = sets.begin(); - end = sets.end(); - for (; cur != end; ++cur) { - c->Message(Chat::White, "(%d) %s", cur->first, cur->second.c_str()); + if (m.empty()) { + c->Message(Chat::White, "There are no available Rule Sets!"); + return; } - } - else if (!strcasecmp(sep->arg[1], "reload")) { + + c->Message(Chat::White, "Available Rule Sets:"); + + auto rule_set_count = 0; + auto rule_set_number = 1; + + for (const auto& e : m) { + c->Message( + Chat::White, + fmt::format( + "Rule Set {} ({})", + e.second, + e.first + ).c_str() + ); + } + + c->Message( + Chat::White, + fmt::format( + "There are {} available Rule Set{}.", + rule_set_count, + rule_set_count != 1 ? "s" : "" + ).c_str() + ); + } else if (is_reload) { RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true); c->Message( - Chat::White, "The active ruleset (%s (%d)) has been reloaded", RuleManager::Instance()->GetActiveRuleset(), - RuleManager::Instance()->GetActiveRulesetID()); - } - else if (!strcasecmp(sep->arg[1], "switch")) { + Chat::White, + fmt::format( + "Active Rule Set {} ({}) has been reloaded.", + RuleManager::Instance()->GetActiveRuleset(), + RuleManager::Instance()->GetActiveRulesetID() + ).c_str() + ); + } else if (is_switch) { //make sure this is a valid rule set.. - int rsid = RuleManager::Instance()->GetRulesetID(&database, sep->arg[2]); + const auto rsid = RuleSetsRepository::GetRuleSetID(database, sep->arg[2]); if (rsid < 0) { - c->Message(Chat::Red, "Unknown rule set '%s'", sep->arg[2]); - return; - } - if (!database.SetVariable("RuleSet", sep->arg[2])) { - c->Message(Chat::Red, "Failed to update variables table to change selected rule set"); + c->Message( + Chat::White, + fmt::format( + "Rule Set '{}' does not exist or is invalid.", + sep->arg[2] + ).c_str() + ); + return; + } + + if (!database.SetVariable("RuleSet", sep->arg[2])) { + c->Message(Chat::White, "Failed to update variables table to change selected Rule Set."); return; } - //TODO: we likely want to reload this ruleset everywhere... RuleManager::Instance()->LoadRules(&database, sep->arg[2], true); c->Message( Chat::White, - "The selected ruleset has been changed to (%s (%d)) and reloaded locally", + "The selected ruleset has been changed to {} ({}) and reloaded locally.", sep->arg[2], rsid ); - } - else if (!strcasecmp(sep->arg[1], "load")) { - //make sure this is a valid rule set.. - int rsid = RuleManager::Instance()->GetRulesetID(&database, sep->arg[2]); + } else if (is_load) { + const auto rsid = RuleSetsRepository::GetRuleSetID(database, sep->arg[2]); if (rsid < 0) { - c->Message(Chat::Red, "Unknown rule set '%s'", sep->arg[2]); + c->Message( + Chat::White, + fmt::format( + "Rule Set '{}' does not exist or is invalid.", + sep->arg[2] + ).c_str() + ); return; } + RuleManager::Instance()->LoadRules(&database, sep->arg[2], true); - c->Message(Chat::White, "Loaded ruleset '%s' (%d) locally", sep->arg[2], rsid); - } - else if (!strcasecmp(sep->arg[1], "store")) { - if (sep->argnum == 1) { - //store current rule set. - RuleManager::Instance()->SaveRules(&database); - c->Message(Chat::White, "Rules saved"); - } - else if (sep->argnum == 2) { + c->Message( + Chat::White, + fmt::format( + "Loaded Rule Set {} ({}) locally.", + sep->arg[2], + rsid + ).c_str() + ); + } else if (is_store) { + if (arguments == 1) { + RuleManager::Instance()->SaveRules(&database, ""); + c->Message(Chat::White, "Rules saved."); + } else if (arguments == 2) { RuleManager::Instance()->SaveRules(&database, sep->arg[2]); - int prersid = RuleManager::Instance()->GetActiveRulesetID(); - int rsid = RuleManager::Instance()->GetRulesetID(&database, sep->arg[2]); + const auto prersid = RuleManager::Instance()->GetActiveRulesetID(); + const auto rsid = RuleSetsRepository::GetRuleSetID(database, sep->arg[2]); if (rsid < 0) { - c->Message(Chat::Red, "Unable to query ruleset ID after store, it most likely failed."); - } - else { - c->Message(Chat::White, "Stored rules as ruleset '%s' (%d)", sep->arg[2], rsid); + c->Message(Chat::White, "Unable to query Rule Set ID after store."); + } else { + c->Message( + Chat::White, + fmt::format( + "Stored rules as Rule Set {} ({}).", + sep->arg[2], + rsid + ).c_str() + ); + if (prersid != rsid) { - c->Message(Chat::White, "Rule set %s (%d) is now active in this zone", sep->arg[2], rsid); + c->Message( + Chat::White, + fmt::format( + "Rule Set {} ({}) is now active locally.", + sep->arg[2], + rsid + ).c_str() + ); } } - } - else { - c->Message(Chat::Red, "Invalid argument count, see help."); + } else { + SendRuleSubCommands(c); return; } - } - else if (!strcasecmp(sep->arg[1], "reset")) { + } else if (is_reset) { RuleManager::Instance()->ResetRules(true); - c->Message(Chat::White, "The running ruleset has been set to defaults"); - - } - else if (!strcasecmp(sep->arg[1], "get")) { - if (sep->argnum != 2) { - c->Message(Chat::Red, "Invalid argument count, see help."); + c->Message( + Chat::White, + fmt::format( + "Rule Set {} ({}) has been set to defaults.", + RuleManager::Instance()->GetActiveRuleset(), + RuleManager::Instance()->GetActiveRulesetID() + ).c_str() + ); + } else if (is_get) { + if (arguments == 2) { + std::string value; + if (!RuleManager::Instance()->GetRule(sep->arg[2], value)) { + c->Message( + Chat::White, + fmt::format( + "Unable to find rule '{}'.", + sep->arg[2] + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "{} has a value of {}.", + sep->arg[2], + value + ).c_str() + ); + } + } else { + SendRuleSubCommands(c); return; } - std::string value; - if (!RuleManager::Instance()->GetRule(sep->arg[2], value)) { - c->Message(Chat::Red, "Unable to find rule %s", sep->arg[2]); - } - else { - c->Message(Chat::White, "%s - %s", sep->arg[2], value.c_str()); - } - - } - else if (!strcasecmp(sep->arg[1], "set")) { - if (sep->argnum != 3) { - c->Message(Chat::Red, "Invalid argument count, see help."); + } else if (is_set) { + if (arguments == 3) { + if (!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], nullptr, false, true)) { + c->Message( + Chat::White, + fmt::format( + "Failed to modify Rule {} to a value of {}.", + sep->arg[2], + sep->arg[3] + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "Rule {} modified locally to a value of {}.", + sep->arg[2], + sep->arg[3] + ).c_str() + ); + } + } else { + SendRuleSubCommands(c); return; } - if (!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], nullptr, false, true)) { - c->Message(Chat::Red, "Failed to modify rule"); - } - else { - c->Message(Chat::White, "Rule modified locally."); - } - } - else if (!strcasecmp(sep->arg[1], "setdb")) { - if (sep->argnum != 3) { - c->Message(Chat::Red, "Invalid argument count, see help."); + } else if (is_set_db) { + if (arguments == 3) { + if (!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true, true)) { + c->Message( + Chat::White, + fmt::format( + "Failed to modify Rule {} to a value of {}.", + sep->arg[2], + sep->arg[3] + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "Rule {} modified locally and in database to a value of {}.", + sep->arg[2], + sep->arg[3] + ).c_str() + ); + } + } else { + SendRuleSubCommands(c); return; } - if (!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true, true)) { - c->Message(Chat::Red, "Failed to modify rule"); - } - else { - c->Message(Chat::White, "Rule modified locally and in the database."); - } - } - else if (!strcasecmp(sep->arg[1], "list")) { - if (sep->argnum == 1) { - std::vector rule_list; - if (!RuleManager::Instance()->ListCategories(rule_list)) { - c->Message(Chat::Red, "Failed to list categories!"); + } else if (is_list) { + if (arguments == 1) { + std::vector l; + if (!RuleManager::Instance()->ListCategories(l)) { + c->Message(Chat::White, "Failed to list Rule Categories!"); return; } + + if (l.empty()) { + c->Message(Chat::White, "There are no Rule Categories to list!"); + return; + } + c->Message(Chat::White, "Rule Categories:"); - std::vector::iterator cur, end; - cur = rule_list.begin(); - end = rule_list.end(); - for (; cur != end; ++cur) { - c->Message(Chat::White, " %s", *cur); + + auto rule_category_count = 0; + auto rule_category_number = 1; + + for (const auto& e : l) { + c->Message( + Chat::White, + fmt::format( + "Rule Category {} | {}", + rule_category_number, + e + ).c_str() + ); + + rule_category_count++; + rule_category_number++; } - } - else if (sep->argnum == 2) { - const char *catfilt = nullptr; + + c->Message( + Chat::White, + fmt::format( + "There {} {} available Rule Categor{}.", + rule_category_count != 1 ? "are" : "is", + rule_category_count, + rule_category_count != 1 ? "ies" : "y" + ).c_str() + ); + } else if (arguments == 2) { + std::string category_name; if (std::string("all") != sep->arg[2]) { - catfilt = sep->arg[2]; + category_name = sep->arg[2]; } - std::vector rule_list; - if (!RuleManager::Instance()->ListRules(catfilt, rule_list)) { - c->Message(Chat::Red, "Failed to list rules!"); + + std::vector l; + if (!RuleManager::Instance()->ListRules(category_name, l)) { + c->Message(Chat::White, "Failed to list rules!"); return; } - c->Message(Chat::White, "Rules in category %s:", sep->arg[2]); - std::vector::iterator cur, end; - cur = rule_list.begin(); - end = rule_list.end(); - for (; cur != end; ++cur) { - c->Message(Chat::White, " %s", *cur); + + c->Message( + Chat::White, + fmt::format( + "Rules in {} Category:", + category_name + ).c_str() + ); + + auto rule_count = 0; + auto rule_number = 1; + + for (const auto& e : l) { + c->Message( + Chat::White, + fmt::format( + "Rule {} | {}", + rule_number, + e + ).c_str() + ); + + rule_count++; + rule_number++; } - } - else { - c->Message(Chat::Red, "Invalid argument count, see help."); - } - } - else if (!strcasecmp(sep->arg[1], "values")) { - if (sep->argnum != 2) { - c->Message(Chat::Red, "Invalid argument count, see help."); + + c->Message( + Chat::White, + fmt::format( + "There {} {} available Rule{} in the {} Category.", + rule_count != 1 ? "are" : "is", + rule_count, + rule_count != 1 ? "s" : "", + category_name + ).c_str() + ); + } else { + SendRuleSubCommands(c); return; } - else { - const char *catfilt = nullptr; + } else if (is_values) { + if (arguments == 2) { + std::string category_name; if (std::string("all") != sep->arg[2]) { - catfilt = sep->arg[2]; + category_name = sep->arg[2]; } - std::vector rule_list; - if (!RuleManager::Instance()->ListRules(catfilt, rule_list)) { - c->Message(Chat::Red, "Failed to list rules!"); + + std::vector l; + if (!RuleManager::Instance()->ListRules(category_name, l)) { + c->Message(Chat::White, "Failed to list rules!"); return; } - c->Message(Chat::White, "Rules & values in category %s:", sep->arg[2]); - std::vector::iterator cur, end; - cur = rule_list.begin(); - end = rule_list.end(); - for (std::string tmp_value; cur != end; ++cur) { - if (RuleManager::Instance()->GetRule(*cur, tmp_value)) { - c->Message(Chat::White, " %s - %s", *cur, tmp_value.c_str()); + + c->Message( + Chat::White, + fmt::format( + "Rule Values in {} Category:", + category_name + ).c_str() + ); + + auto rule_count = 0; + auto rule_number = 1; + std::string rule_value; + + for (const auto& e : l) { + if (RuleManager::Instance()->GetRule(e, rule_value)) { + c->Message( + Chat::White, + fmt::format( + "Rule {} | Name: {} Value: {}", + rule_number, + e, + rule_value + ).c_str() + ); + + rule_count++; + rule_number++; } } - } - } - else { - c->Message(Chat::Yellow, "Invalid action specified. use '#rules help' for help"); + c->Message( + Chat::White, + fmt::format( + "There {} {} available Rule{} in the {} Category.", + rule_count != 1 ? "are" : "is", + rule_count, + rule_count != 1 ? "s" : "", + category_name + ).c_str() + ); + } else { + SendRuleSubCommands(c); + return; + } } } - +void SendRuleSubCommands(Client *c) +{ + c->Message(Chat::White, "Usage: #rule listsets - List available rule sets"); + c->Message(Chat::White, "Usage: #rule current - gives the name of the ruleset currently running in this zone"); + c->Message(Chat::White, "Usage: #rule reload - Reload the selected ruleset in this zone"); + c->Message(Chat::White, "Usage: #rule switch [Ruleset Name] - Change the selected ruleset and load it"); + c->Message( + Chat::White, + "Usage: #rule load [Ruleset Name] - Load a ruleset in just this zone without changing the selected set" + ); + c->Message(Chat::White, "Usage: #rule store [Ruleset Name] - Store the running ruleset as the specified name"); + c->Message(Chat::White, "Usage: #rule reset - Reset all rules to their default values"); + c->Message(Chat::White, "Usage: #rule get [Rule] - Get the specified rule's local value"); + c->Message( + Chat::White, + "Usage: #rule set [Rule) [Value] - Set the specified rule to the specified value locally only" + ); + c->Message( + Chat::White, + "Usage: #rule setdb [Rule] [Value] - Set the specified rule to the specified value locally and in the DB" + ); + c->Message( + Chat::White, + "Usage: #rule list [Category Name] - List all rules in the specified category (or all categiries if omitted)" + ); + c->Message( + Chat::White, + "Usage: #rule values [Category Name] - List the value of all rules in the specified category" + ); + return; +} diff --git a/zone/gm_commands/scale.cpp b/zone/gm_commands/scale.cpp index d260a25e4..792d12066 100755 --- a/zone/gm_commands/scale.cpp +++ b/zone/gm_commands/scale.cpp @@ -3,134 +3,182 @@ void command_scale(Client *c, const Seperator *sep) { - if (sep->argnum == 0) { - c->Message(Chat::Yellow, "# Usage # "); - c->Message(Chat::Yellow, "#scale [static/dynamic] (With targeted NPC)"); - c->Message(Chat::Yellow, "#scale [npc_name_search] [static/dynamic] (To make zone-wide changes)"); - c->Message(Chat::Yellow, "#scale all [static/dynamic]"); + auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #scale [Scale Type] - Must target an NPC"); + c->Message(Chat::White, "Usage: #scale [Search Criteria] [Scale Type] - Zone-wide Changes"); + c->Message(Chat::White, "Usage: #scale all [Scale Type] - Scale every NPC in the zone"); + c->Message(Chat::White, "Note: Scale Type can be \"dynamic\" or \"static\"."); return; } - /** - * Targeted changes - */ - if (c->GetTarget() && c->GetTarget()->IsNPC() && sep->argnum < 2) { - NPC *npc = c->GetTarget()->CastToNPC(); + if (c->GetTarget() && c->GetTarget()->IsNPC() && arguments < 2) { + auto n = c->GetTarget()->CastToNPC(); bool apply_status = false; - if (strcasecmp(sep->arg[1], "dynamic") == 0) { - c->Message(Chat::Yellow, "Applying global base scaling to npc dynamically (All stats set to zeroes)..."); - apply_status = npc_scale_manager->ApplyGlobalBaseScalingToNPCDynamically(npc); - } - else if (strcasecmp(sep->arg[1], "static") == 0) { - c->Message(Chat::Yellow, "Applying global base scaling to npc statically (Copying base stats onto NPC)..."); - apply_status = npc_scale_manager->ApplyGlobalBaseScalingToNPCStatically(npc); - } - else { + + bool is_dynamic = !strcasecmp(sep->arg[1], "dynamic"); + bool is_static = !strcasecmp(sep->arg[1], "static"); + + if (is_dynamic || is_static) { + c->Message( + Chat::White, + fmt::format( + "Applying global base scaling to {} {}ally, all stats set to zeroes.", + c->GetTargetDescription(n), + sep->arg[1] + ).c_str() + ); + + if (is_dynamic) { + apply_status = npc_scale_manager->ApplyGlobalBaseScalingToNPCDynamically(n); + } else { + apply_status = npc_scale_manager->ApplyGlobalBaseScalingToNPCStatically(n); + } + } else { + c->Message(Chat::White, "Usage: #scale [Scale Type] - Must target an NPC"); + c->Message(Chat::White, "Usage: #scale [Search Criteria] [Scale Type] - Zone-wide Changes"); + c->Message(Chat::White, "Usage: #scale all [Scale Type] - Scale every NPC in the zone"); + c->Message(Chat::White, "Note: Scale Type can be \"dynamic\" or \"static\"."); return; } if (apply_status) { - c->Message(Chat::Yellow, "Applied to NPC '%s' successfully!", npc->GetName()); - } - else { c->Message( - Chat::Yellow, "Failed to load scaling data from the database " - "for this npc / type, see 'NPCScaling' log for more info" + Chat::White, + fmt::format( + "Applied global base scaling to {} {}ally successfully.", + c->GetTargetDescription(n), + sep->arg[1] + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "Failed to load scaling data from the database for {}, see 'NPCScaling' log for more info.", + c->GetTargetDescription(n) + ).c_str() ); } - } - else if (c->GetTarget() && sep->argnum < 2) { - c->Message(Chat::Yellow, "Target must be an npc!"); + } else if (c->GetTarget() && arguments < 2) { + c->Message(Chat::White, "You must target an NPC to use targeted scaling!"); } - /** - * Zonewide - */ - if (sep->argnum > 1) { - + if (arguments > 1) { std::string scale_type; - if (strcasecmp(sep->arg[2], "dynamic") == 0) { - scale_type = "dynamic"; - } - else if (strcasecmp(sep->arg[2], "static") == 0) { - scale_type = "static"; - } - if (scale_type.length() <= 0) { - c->Message( - Chat::Yellow, - "You must first set if you intend on using static versus dynamic for these changes" - ); - c->Message(Chat::Yellow, "#scale [npc_name_search] [static/dynamic]"); - c->Message(Chat::Yellow, "#scale all [static/dynamic]"); + bool is_all = !strcasecmp(sep->arg[1], "all"); + bool is_dynamic = !strcasecmp(sep->arg[2], "dynamic"); + bool is_static = !strcasecmp(sep->arg[2], "static"); + + bool is_apply = arguments == 3 && !strcasecmp(sep->arg[3], "apply"); + + if (is_dynamic) { + scale_type = "dynamic"; + } else if (is_static) { + scale_type = "static"; + } else { + c->Message(Chat::White, "Usage: #scale [Scale Type] - Must target an NPC"); + c->Message(Chat::White, "Usage: #scale [Search Criteria] [Scale Type] - Zone-wide Changes"); + c->Message(Chat::White, "Usage: #scale all [Scale Type] - Scale every NPC in the zone"); + c->Message(Chat::White, "Note: Scale Type can be \"dynamic\" or \"static\"."); return; } - std::string search_string = sep->arg[1]; + const std::string search_string = sep->arg[1]; - auto &entity_list_search = entity_list.GetNPCList(); + const auto& l = entity_list.GetNPCList(); - int found_count = 0; - for (auto &itr : entity_list_search) { - NPC *entity = itr.second; + auto found_count = 0; + auto found_number = 1; - std::string entity_name = entity->GetName(); + for (const auto &e : l) { + auto n = e.second; - /** - * Filter by name - */ - if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos && - strcasecmp(sep->arg[1], "all") != 0) { + std::string entity_name = n->GetName(); + + if ( + !search_string.empty() && + !Strings::Contains(entity_name, search_string) && + !is_all + ) { continue; } std::string status = "(Searching)"; - if (strcasecmp(sep->arg[3], "apply") == 0) { + if (is_apply) { status = "(Applying)"; - if (strcasecmp(sep->arg[2], "dynamic") == 0) { - npc_scale_manager->ApplyGlobalBaseScalingToNPCDynamically(entity); - } - if (strcasecmp(sep->arg[2], "static") == 0) { - npc_scale_manager->ApplyGlobalBaseScalingToNPCStatically(entity); + if (is_dynamic) { + npc_scale_manager->ApplyGlobalBaseScalingToNPCDynamically(n); + } else if (is_static) { + npc_scale_manager->ApplyGlobalBaseScalingToNPCStatically(n); } } c->Message( - 15, - "| ID %5d | %s | x %.0f | y %0.f | z %.0f | DBID %u %s", - entity->GetID(), - entity->GetName(), - entity->GetX(), - entity->GetY(), - entity->GetZ(), - entity->GetNPCTypeID(), - status.c_str() + Chat::White, + fmt::format( + "Entity {} | Name: {} | NPC ID: {} | Position: {:.2f}, {:.2f}, {:.2f}, {:.2f} {}", + found_number, + c->GetTargetDescription(n), + n->GetNPCTypeID(), + n->GetX(), + n->GetY(), + n->GetZ(), + n->GetHeading(), + status + ).c_str() ); found_count++; + found_number++; } - if (strcasecmp(sep->arg[3], "apply") == 0) { - c->Message(Chat::Yellow, "%s scaling applied against (%i) NPC's", sep->arg[2], found_count); - } - else { - - std::string saylink = StringFormat( - "#scale %s %s apply", - sep->arg[1], - sep->arg[2] + if (is_apply) { + c->Message( + Chat::White, + fmt::format( + "{} scaling applied against {} NPC{}.", + Strings::UcFirst(sep->arg[2]), + found_count, + found_count != 1 ? "s" : "" + ).c_str() + ); + } else { + c->Message( + Chat::White, + fmt::format( + "Found {} NPC{}{}.", + found_count, + found_count != 1 ? "s" : "", + ( + is_all ? + "" : + fmt::format( + " matching '{}'", + search_string + ) + ) + ).c_str() ); - c->Message(Chat::Yellow, "Found (%i) NPC's that match this search...", found_count); c->Message( - Chat::Yellow, "To apply these changes, click <%s> or type %s", - EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Apply").c_str(), - saylink.c_str() + Chat::White, + fmt::format( + "Would you like to {} these changes?", + Saylink::Silent( + fmt::format( + "#scale {} {} apply", + sep->arg[1], + sep->arg[2] + ), + "apply" + ) + ).c_str() ); } } } - diff --git a/zone/gm_commands/scribespell.cpp b/zone/gm_commands/scribespell.cpp index 5acfd3a8d..a5c843f49 100755 --- a/zone/gm_commands/scribespell.cpp +++ b/zone/gm_commands/scribespell.cpp @@ -2,65 +2,92 @@ void command_scribespell(Client *c, const Seperator *sep) { - uint16 spell_id = 0; - uint16 book_slot = -1; - Client *t = c; + auto arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #scribespell [Spell ID]"); + return; + } + auto t = c; if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { t = c->GetTarget()->CastToClient(); } - if (!sep->arg[1][0]) { - c->Message(Chat::White, "FORMAT: #scribespell "); - return; - } - - spell_id = atoi(sep->arg[1]); + const auto spell_id = std::stoul(sep->arg[1]); if (IsValidSpell(spell_id)) { - t->Message(Chat::White, "Scribing spell: %s (%i) to spellbook.", spells[spell_id].name, spell_id); + t->Message( + Chat::White, + fmt::format( + "Scribing {} ({}) to spellbook.", + spells[spell_id].name, + spell_id + ).c_str() + ); if (t != c) { - c->Message(Chat::White, "Scribing spell: %s (%i) for %s.", spells[spell_id].name, spell_id, t->GetName()); + c->Message( + Chat::White, + fmt::format( + "Scribing {} ({}) for {}.", + spells[spell_id].name, + spell_id, + t->GetName() + ).c_str() + ); } - LogInfo("Scribe spell: [{}] ([{}]) request for [{}] from [{}]", - spells[spell_id].name, - spell_id, - t->GetName(), - c->GetName()); + LogInfo( + "Scribe spell: [{}] ([{}]) request for [{}] from [{}]", + spells[spell_id].name, + spell_id, + t->GetName(), + c->GetName() + ); - if (spells[spell_id].classes[WARRIOR] != 0 && spells[spell_id].skill != 52 && - spells[spell_id].classes[t->GetPP().class_ - 1] > 0 && !IsDiscipline(spell_id)) { - book_slot = t->GetNextAvailableSpellBookSlot(); + if ( + spells[spell_id].classes[WARRIOR] != 0 && + spells[spell_id].skill != EQ::skills::SkillTigerClaw && + spells[spell_id].classes[t->GetPP().class_ - 1] > 0 && + !IsDiscipline(spell_id) + ) { + auto book_slot = t->GetNextAvailableSpellBookSlot(); if (book_slot >= 0 && t->FindSpellBookSlotBySpellID(spell_id) < 0) { t->ScribeSpell(spell_id, book_slot); - } - else { + } else { t->Message( - Chat::Red, - "Unable to scribe spell: %s (%i) to your spellbook.", - spells[spell_id].name, - spell_id + Chat::White, + fmt::format( + "Unable to scribe {} ({}) to your spellbook.", + spells[spell_id].name, + spell_id + ).c_str() ); if (t != c) { c->Message( - Chat::Red, - "Unable to scribe spell: %s (%i) for %s.", - spells[spell_id].name, - spell_id, - t->GetName()); + Chat::White, + fmt::format( + "Unable to scribe {} ({}) for {}.", + spells[spell_id].name, + spell_id, + t->GetName() + ).c_str() + ); } } + } else { + c->Message(Chat::White, "Your target cannot scribe this spell."); } - else { - c->Message(Chat::Red, "Your target can not scribe this spell."); - } - } - else { - c->Message(Chat::Red, "Spell ID: %i is an unknown spell and cannot be scribed.", spell_id); + } else { + c->Message( + Chat::White, + fmt::format( + "Spell ID {} is an unknown spell and cannot be scribed.", + spell_id + ).c_str() + ); } } diff --git a/zone/gm_commands/scribespells.cpp b/zone/gm_commands/scribespells.cpp index 89ba25f93..2a141de4b 100755 --- a/zone/gm_commands/scribespells.cpp +++ b/zone/gm_commands/scribespells.cpp @@ -2,21 +2,22 @@ void command_scribespells(Client *c, const Seperator *sep) { - Client *target = c; - if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { - target = c->GetTarget()->CastToClient(); - } - - if (sep->argnum < 1 || !sep->IsNumber(1)) { + auto arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1)) { c->Message(Chat::White, "Usage: #scribespells [Max Level] [Min Level]"); return; } - uint8 rule_max_level = (uint8) RuleI(Character, MaxLevel); - uint8 max_level = (uint8) std::stoi(sep->arg[1]); + auto t = c; + if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { + t = c->GetTarget()->CastToClient(); + } + + uint8 rule_max_level = RuleI(Character, MaxLevel); + auto max_level = static_cast(std::stoul(sep->arg[1])); uint8 min_level = ( sep->IsNumber(2) ? - (uint8) std::stoi(sep->arg[2]) : + static_cast(std::stoul(sep->arg[2])) : 1 ); // Default to Level 1 if there isn't a 2nd argument @@ -31,35 +32,38 @@ void command_scribespells(Client *c, const Seperator *sep) } if (max_level < 1 || min_level < 1) { - c->Message(Chat::White, "Level must be greater than or equal to 1."); + c->Message(Chat::White, "Maximum Level and Minimum Level must be greater than 0."); return; } if (min_level > max_level) { - c->Message(Chat::White, "Minimum Level must be less than or equal to Maximum Level."); + c->Message(Chat::White, "Maximum Level must be greater than Minimum Level."); return; } - uint16 scribed_spells = target->ScribeSpells(min_level, max_level); - if (c != target) { - std::string spell_message = ( - scribed_spells > 0 ? - ( - scribed_spells == 1 ? - "A new spell" : + const auto scribed_spells = t->ScribeSpells(min_level, max_level); + + if (c != t) { + const auto target_description = c->GetTargetDescription(t); + + if (!scribed_spells) { + c->Message( + Chat::White, fmt::format( - "{} New spells", - scribed_spells - ) - ) : - "No new spells" - ); + "No new spells scribed for {}.", + target_description + ).c_str() + ); + return; + } + c->Message( Chat::White, fmt::format( - "{} scribed for {}.", - spell_message, - c->GetTargetDescription(target) + "{} New spell{} scribed for {}.", + scribed_spells, + scribed_spells != 1 ? "s" : "", + target_description ).c_str() ); } diff --git a/zone/gm_commands/serverinfo.cpp b/zone/gm_commands/serverinfo.cpp index 7ca20e26b..3832aa7d3 100755 --- a/zone/gm_commands/serverinfo.cpp +++ b/zone/gm_commands/serverinfo.cpp @@ -1,4 +1,5 @@ #include "../client.h" +#include "../dialogue_window.h" #include "../../common/serverinfo.h" void command_serverinfo(Client *c, const Seperator *sep) @@ -9,86 +10,113 @@ void command_serverinfo(Client *c, const Seperator *sep) auto rss = EQ::GetRSS() / 1048576.0; auto uptime = static_cast(EQ::GetUptime()); - std::string popup_text; + std::string popup_table; + auto popup_text = DialogueWindow::CenterMessage( + DialogueWindow::ColorMessage("green", "Operating System Information") + ); - popup_text.append("Operating System Information"); - - popup_text.append(""); - - popup_text.append( - fmt::format( - "", - os.sysname + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell("Machine") + + DialogueWindow::TableCell(os.machine) ).c_str() ); - popup_text.append( - fmt::format( - "", - os.release - ) + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell("System") + + DialogueWindow::TableCell(os.sysname) + ).c_str() ); - popup_text.append( - fmt::format( - "", - os.version - ) + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell("Release") + + DialogueWindow::TableCell(os.release) + ).c_str() ); - popup_text.append( - fmt::format( - "", - os.machine - ) + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell("Uptime") + + DialogueWindow::TableCell(Strings::SecondsToTime(uptime)) + ).c_str() ); - popup_text.append( - fmt::format( - "", - ConvertSecondsToTime(uptime) - ) + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell("Version") + + DialogueWindow::TableCell(os.version) + ).c_str() ); - popup_text.append("
System{}
Release{}
Version{}
Machine{}
Uptime{}
"); + popup_text.append(DialogueWindow::Table(popup_table)); - popup_text.append("CPU Information"); + popup_table = std::string(); - popup_text.append(""); + popup_text.append(DialogueWindow::Break()); + + popup_text.append( + DialogueWindow::CenterMessage( + DialogueWindow::ColorMessage("green", "CPU Information") + ) + ); for (size_t cpu = 0; cpu < cpus.size(); ++cpu) { auto ¤t_cpu = cpus[cpu]; - popup_text.append( - fmt::format( - "", - cpu, - current_cpu.model, - current_cpu.speed + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell( + fmt::format( + "CPU {}", + cpu + ) + ) + + DialogueWindow::TableCell( + fmt::format( + "{} ({:.2f}GHz)", + current_cpu.model, + current_cpu.speed + ) + ) ) ); } - popup_text.append("
CPU {}{} ({:.2f}GHz)
"); + popup_text.append(DialogueWindow::Table(popup_table)); - popup_text.append("Process Information"); + popup_table = std::string(); + + popup_text.append(DialogueWindow::Break()); + + popup_text.append( + DialogueWindow::CenterMessage( + DialogueWindow::ColorMessage("green", "CPU Information") + ) + ); popup_text.append(""); - popup_text.append( - fmt::format( - "", - process_id + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell("Process ID") + + DialogueWindow::TableCell(std::to_string(process_id)) ) ); - popup_text.append( - fmt::format( - "", - rss + popup_table.append( + DialogueWindow::TableRow( + DialogueWindow::TableCell("RSS") + + DialogueWindow::TableCell( + fmt::format( + "{:.2f} MB", + rss + ) + ) ) ); - popup_text.append("
Process ID{}
RSS{:.2f} MB
"); + popup_text.append(DialogueWindow::Table(popup_table)); c->SendPopupToClient( "Server Information", diff --git a/zone/gm_commands/serverlock.cpp b/zone/gm_commands/serverlock.cpp new file mode 100644 index 000000000..59a43f912 --- /dev/null +++ b/zone/gm_commands/serverlock.cpp @@ -0,0 +1,22 @@ +#include "../client.h" +#include "../worldserver.h" + +extern WorldServer worldserver; + +void command_serverlock(Client *c, const Seperator *sep) +{ + if (!sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #serverlock [0|1] - Lock or Unlock the World Server (0 = Unlocked, 1 = Locked)"); + return; + } + + auto is_locked = std::stoi(sep->arg[1]) ? true : false; + + auto pack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); + auto l = (ServerLock_Struct *) pack->pBuffer; + strn0cpy(l->character_name, c->GetCleanName(), sizeof(l->character_name)); + l->is_locked = is_locked; + worldserver.SendPacket(pack); + safe_delete(pack); +} + diff --git a/zone/gm_commands/setaapts.cpp b/zone/gm_commands/setaapts.cpp index f47745a4a..c1c730a5f 100755 --- a/zone/gm_commands/setaapts.cpp +++ b/zone/gm_commands/setaapts.cpp @@ -16,7 +16,7 @@ void command_setaapts(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - std::string aa_type = str_tolower(sep->arg[1]); + std::string aa_type = Strings::ToLower(sep->arg[1]); std::string group_raid_string; uint32 aa_points = static_cast(std::min(std::stoull(sep->arg[2]), (unsigned long long) 2000000000)); bool is_aa = aa_type.find("aa") != std::string::npos; diff --git a/zone/gm_commands/setaaxp.cpp b/zone/gm_commands/setaaxp.cpp index 57b57cf76..12339c3ed 100755 --- a/zone/gm_commands/setaaxp.cpp +++ b/zone/gm_commands/setaaxp.cpp @@ -16,7 +16,7 @@ void command_setaaxp(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - std::string aa_type = str_tolower(sep->arg[1]); + std::string aa_type = Strings::ToLower(sep->arg[1]); std::string group_raid_string; uint32 aa_experience = static_cast(std::min( std::stoull(sep->arg[2]), diff --git a/zone/gm_commands/setanon.cpp b/zone/gm_commands/setanon.cpp new file mode 100755 index 000000000..955bbd884 --- /dev/null +++ b/zone/gm_commands/setanon.cpp @@ -0,0 +1,102 @@ +#include "../client.h" +#include "../../common/repositories/character_data_repository.h" + +void command_setanon(Client *c, const Seperator *sep) +{ + auto arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1) || arguments > 2) { + c->Message(Chat::White, "Usage: #setanon [Anonymous Flag]"); + c->Message(Chat::White, "Usage: #setanon [Character ID] [Anonymous Flag]"); + c->Message(Chat::White, "Note: 0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying"); + return; + } + + if (arguments == 1) { + const uint8 anon_flag = static_cast(std::stoul(sep->arg[1])); + auto t = c; + if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { + t = c->GetTarget()->CastToClient(); + } + + std::string anon_setting; + if (anon_flag == Anonymity::NotAnonymous) { + anon_setting = "no longer Anonymous or Roleplaying"; + } else if (anon_flag == Anonymity::Anonymous) { + anon_setting = "now Anonymous"; + } else if (anon_flag == Anonymity::Roleplaying) { + anon_setting = "now Roleplaying"; + } else { + c->Message(Chat::White, "Usage: #setanon [Anonymous Flag]"); + c->Message(Chat::White, "Usage: #setanon [Character ID] [Anonymous Flag]"); + c->Message(Chat::White, "Note: 0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying"); + return; + } + + c->SetAnon(anon_flag); + + c->Message( + Chat::White, + fmt::format( + "{} {} {}.", + c->GetTargetDescription(t, TargetDescriptionType::UCYou), + c == t ? "are" : "is", + anon_setting + ).c_str() + ); + } else if (arguments == 2) { + const auto character_id = std::stoi(sep->arg[1]); + const uint8 anon_flag = static_cast(std::stoul(sep->arg[2])); + + auto e = CharacterDataRepository::FindOne(content_db, character_id); + if (!e.id) { + c->Message( + Chat::White, + fmt::format( + "Character ID {} does not exist or is invalid.", + character_id + ).c_str() + ); + return; + } + + e.anon = anon_flag; + + auto updated = CharacterDataRepository::UpdateOne(content_db, e); + + if (!updated) { + c->Message( + Chat::White, + fmt::format( + "Failed to change Anonymous Flag for {} ({}).", + e.name, + character_id + ).c_str() + ); + return; + } + + std::string anon_setting; + if (anon_flag == Anonymity::NotAnonymous) { + anon_setting = "no longer Anonymous or Roleplaying"; + } else if (anon_flag == Anonymity::Anonymous) { + anon_setting = "now Anonymous"; + } else if (anon_flag == Anonymity::Roleplaying) { + anon_setting = "now Roleplaying"; + } else { + c->Message(Chat::White, "Usage: #setanon [Anonymous Flag]"); + c->Message(Chat::White, "Usage: #setanon [Character ID] [Anonymous Flag]"); + c->Message(Chat::White, "Note: 0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying"); + return; + } + + c->Message( + Chat::White, + fmt::format( + "{} ({}) is {}.", + e.name, + character_id, + anon_setting + ).c_str() + ); + } +} diff --git a/zone/gm_commands/setcrystals.cpp b/zone/gm_commands/setcrystals.cpp index fd3306acd..95a537e9a 100755 --- a/zone/gm_commands/setcrystals.cpp +++ b/zone/gm_commands/setcrystals.cpp @@ -13,7 +13,7 @@ void command_setcrystals(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - std::string crystal_type = str_tolower(sep->arg[1]); + std::string crystal_type = Strings::ToLower(sep->arg[1]); uint32 crystal_amount = static_cast(std::min( std::stoull(sep->arg[2]), (unsigned long long) 2000000000 diff --git a/zone/gm_commands/setgraveyard.cpp b/zone/gm_commands/setgraveyard.cpp deleted file mode 100755 index e1b043e4b..000000000 --- a/zone/gm_commands/setgraveyard.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "../client.h" - -void command_setgraveyard(Client *c, const Seperator *sep) -{ - uint32 zoneid = 0; - uint32 graveyard_id = 0; - Client *t = c; - - if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { - t = c->GetTarget()->CastToClient(); - } - - if (!sep->arg[1][0]) { - c->Message(Chat::White, "Usage: #setgraveyard [zonename]"); - return; - } - - zoneid = ZoneID(sep->arg[1]); - - if (zoneid > 0) { - graveyard_id = content_db.CreateGraveyardRecord(zoneid, t->GetPosition()); - - if (graveyard_id > 0) { - c->Message(Chat::White, "Successfuly added a new record for this graveyard!"); - if (content_db.AddGraveyardIDToZone(zoneid, graveyard_id) > 0) { - c->Message(Chat::White, "Successfuly added this new graveyard for the zone %s.", sep->arg[1]); - // TODO: Set graveyard data to the running zone process. - c->Message(Chat::White, "Done!"); - } - else { - c->Message(Chat::White, "Unable to add this new graveyard to the zone %s.", sep->arg[1]); - } - } - else { - c->Message(Chat::White, "Unable to create a new graveyard record in the database."); - } - } - else { - c->Message(Chat::White, "Unable to retrieve a ZoneID for the zone: %s", sep->arg[1]); - } - - return; -} - diff --git a/zone/gm_commands/setlanguage.cpp b/zone/gm_commands/setlanguage.cpp index f3242c1e9..5b8073b8d 100755 --- a/zone/gm_commands/setlanguage.cpp +++ b/zone/gm_commands/setlanguage.cpp @@ -1,39 +1,36 @@ #include "../client.h" #include "../../common/languages.h" +#include "../../common/data_verification.h" void command_setlanguage(Client *c, const Seperator *sep) { - Client *target = c; + auto target = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { target = c->GetTarget()->CastToClient(); } - auto language_id = sep->IsNumber(1) ? std::stoi(sep->arg[1]) : -1; + auto language_id = sep->IsNumber(1) ? std::stoi(sep->arg[1]) : -1; auto language_value = sep->IsNumber(2) ? std::stoi(sep->arg[2]) : -1; if (!strcasecmp(sep->arg[1], "list")) { - for (int language = LANG_COMMON_TONGUE; language <= LANG_UNKNOWN; language++) { + for (const auto& language : EQ::constants::GetLanguageMap()) { c->Message( Chat::White, fmt::format( "Language {}: {}", - language, - EQ::constants::GetLanguageName(language) + language.first, + language.second ).c_str() ); } - } - else if ( - language_id < LANG_COMMON_TONGUE || - language_id > LANG_UNKNOWN || - language_value < 0 || - language_value > 100 - ) { + } else if ( + !EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN) || + !EQ::ValueWithin(language_value, 0, 100) + ) { c->Message(Chat::White, "Usage: #setlanguage [Language ID] [Language Value]"); c->Message(Chat::White, "Usage: #setlanguage [List]"); - c->Message(Chat::White, "Language ID = 0 to 27", LANG_UNKNOWN); - c->Message(Chat::White, "Language Value = 0 to 100", HIGHEST_CAN_SET_SKILL); - } - else { + c->Message(Chat::White, "Language ID = 0 to 27"); + c->Message(Chat::White, "Language Value = 0 to 100"); + } else { LogInfo( "Set language request from [{}], Target: [{}] Language ID: [{}] Language Value: [{}]", c->GetCleanName(), @@ -58,4 +55,3 @@ void command_setlanguage(Client *c, const Seperator *sep) } } } - diff --git a/zone/gm_commands/setlsinfo.cpp b/zone/gm_commands/setlsinfo.cpp index 101fd295c..280c3e6f1 100755 --- a/zone/gm_commands/setlsinfo.cpp +++ b/zone/gm_commands/setlsinfo.cpp @@ -18,6 +18,7 @@ void command_setlsinfo(Client *c, const Seperator *sep) strn0cpy(s->user_email, sep->arg[1], 100); strn0cpy(s->userpassword, sep->arg[2], 50); worldserver.SendPacket(pack); + safe_delete(pack); c->Message(Chat::White, "Your email and local loginserver password have been set."); } diff --git a/zone/gm_commands/showskills.cpp b/zone/gm_commands/showskills.cpp index 68c1c92e3..d4c23d91a 100755 --- a/zone/gm_commands/showskills.cpp +++ b/zone/gm_commands/showskills.cpp @@ -55,7 +55,7 @@ void command_showskills(Client *c, const Seperator *sep) popup_title.c_str(), popup_text.c_str() ); - + c->Message( Chat::White, @@ -76,22 +76,14 @@ void command_showskills(Client *c, const Seperator *sep) next_skill_id ); - auto next_list_link = EQ::SayLinkEngine::GenerateQuestSaylink( - next_list_string, - false, - next_list_string - ); + auto next_list_link = Saylink::Silent(next_list_string, next_list_string); auto next_list_all_string = fmt::format( "#showskills {} all", next_skill_id ); - auto next_list_all_link = EQ::SayLinkEngine::GenerateQuestSaylink( - next_list_all_string, - false, - next_list_all_string - ); + auto next_list_all_link = Saylink::Silent(next_list_all_string, next_list_all_string); c->Message( Chat::White, diff --git a/zone/gm_commands/showzonepoints.cpp b/zone/gm_commands/showzonepoints.cpp index d1e8c2428..4b98217a0 100755 --- a/zone/gm_commands/showzonepoints.cpp +++ b/zone/gm_commands/showzonepoints.cpp @@ -5,7 +5,7 @@ void command_showzonepoints(Client *c, const Seperator *sep) auto &mob_list = entity_list.GetMobList(); for (auto itr : mob_list) { Mob *mob = itr.second; - if (mob->IsNPC() && mob->GetRace() == 2254) { + if (mob->IsNPC() && mob->GetRace() == RACE_NODE_2254) { mob->Depop(); } } @@ -15,94 +15,102 @@ void command_showzonepoints(Client *c, const Seperator *sep) c->Message(Chat::White, "Listing zone points..."); c->SendChatLineBreak(); - for (auto &virtual_zone_point : zone->virtual_zone_point_list) { - std::string zone_long_name = ZoneLongName(virtual_zone_point.target_zone_id); + for (auto &p : zone->virtual_zone_point_list) { + std::string zone_long_name = ZoneLongName(p.target_zone_id); + + std::string saylink = fmt::format( + "#goto {:.0f} {:.0f} {:.0f}", + p.x, + p.y, + p.z + ); c->Message( Chat::White, fmt::format( - "Virtual Zone Point x [{}] y [{}] z [{}] h [{}] width [{}] height [{}] | To [{}] ({}) x [{}] y [{}] z [{}] h [{}]", - virtual_zone_point.x, - virtual_zone_point.y, - virtual_zone_point.z, - virtual_zone_point.heading, - virtual_zone_point.width, - virtual_zone_point.height, + "Virtual Zone Point [{}] x [{}] y [{}] z [{}] h [{}] width [{}] height [{}] | To [{}] ({}) x [{}] y [{}] z [{}] h [{}]", + Saylink::Silent(saylink, "Goto").c_str(), + p.x, + p.y, + p.z, + p.heading, + p.width, + p.height, zone_long_name.c_str(), - virtual_zone_point.target_zone_id, - virtual_zone_point.target_x, - virtual_zone_point.target_y, - virtual_zone_point.target_z, - virtual_zone_point.target_heading + p.target_zone_id, + p.target_x, + p.target_y, + p.target_z, + p.target_heading ).c_str() ); std::string node_name = fmt::format("ZonePoint To [{}]", zone_long_name); - float half_width = ((float) virtual_zone_point.width / 2); + float half_width = ((float) p.width / 2); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x + half_width, - (float) virtual_zone_point.y + half_width, - virtual_zone_point.z, - virtual_zone_point.heading + (float) p.x + half_width, + (float) p.y + half_width, + p.z, + p.heading )); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x + half_width, - (float) virtual_zone_point.y - half_width, - virtual_zone_point.z, - virtual_zone_point.heading + (float) p.x + half_width, + (float) p.y - half_width, + p.z, + p.heading )); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x - half_width, - (float) virtual_zone_point.y - half_width, - virtual_zone_point.z, - virtual_zone_point.heading + (float) p.x - half_width, + (float) p.y - half_width, + p.z, + p.heading )); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x - half_width, - (float) virtual_zone_point.y + half_width, - virtual_zone_point.z, - virtual_zone_point.heading + (float) p.x - half_width, + (float) p.y + half_width, + p.z, + p.heading )); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x + half_width, - (float) virtual_zone_point.y + half_width, - (float) virtual_zone_point.z + (float) virtual_zone_point.height, - virtual_zone_point.heading + (float) p.x + half_width, + (float) p.y + half_width, + (float) p.z + (float) p.height, + p.heading )); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x + half_width, - (float) virtual_zone_point.y - half_width, - (float) virtual_zone_point.z + (float) virtual_zone_point.height, - virtual_zone_point.heading + (float) p.x + half_width, + (float) p.y - half_width, + (float) p.z + (float) p.height, + p.heading )); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x - half_width, - (float) virtual_zone_point.y - half_width, - (float) virtual_zone_point.z + (float) virtual_zone_point.height, - virtual_zone_point.heading + (float) p.x - half_width, + (float) p.y - half_width, + (float) p.z + (float) p.height, + p.heading )); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - (float) virtual_zone_point.x - half_width, - (float) virtual_zone_point.y + half_width, - (float) virtual_zone_point.z + (float) virtual_zone_point.height, - virtual_zone_point.heading + (float) p.x - half_width, + (float) p.y + half_width, + (float) p.z + (float) p.height, + p.heading )); found_zone_points++; @@ -111,34 +119,44 @@ void command_showzonepoints(Client *c, const Seperator *sep) LinkedListIterator iterator(zone->zone_point_list); iterator.Reset(); while (iterator.MoreElements()) { - ZonePoint *zone_point = iterator.GetData(); - std::string zone_long_name = ZoneLongName(zone_point->target_zone_id); + ZonePoint *p = iterator.GetData(); + std::string zone_long_name = ZoneLongName(p->target_zone_id); std::string node_name = fmt::format("ZonePoint To [{}]", zone_long_name); NPC::SpawnZonePointNodeNPC( node_name, glm::vec4( - zone_point->x, - zone_point->y, - zone_point->z, - zone_point->heading + p->x, + p->y, + p->z, + p->heading ) ); + // {:.0f} + + std::string saylink = fmt::format( + "#goto {:.0f} {:.0f} {:.0f}", + p->x, + p->y, + p->z + ); + c->Message( Chat::White, fmt::format( - "Client Side Zone Point x [{}] y [{}] z [{}] h [{}] number [{}] | To [{}] ({}) x [{}] y [{}] z [{}] h [{}]", - zone_point->x, - zone_point->y, - zone_point->z, - zone_point->heading, - zone_point->number, + "Client Side Zone Point [{}] x [{}] y [{}] z [{}] h [{}] number [{}] | To [{}] ({}) x [{}] y [{}] z [{}] h [{}]", + Saylink::Silent(saylink, "Goto").c_str(), + p->x, + p->y, + p->z, + p->heading, + p->number, zone_long_name.c_str(), - zone_point->target_zone_id, - zone_point->target_x, - zone_point->target_y, - zone_point->target_z, - zone_point->target_heading + p->target_zone_id, + p->target_x, + p->target_y, + p->target_z, + p->target_heading ).c_str() ); diff --git a/zone/gm_commands/spawneditmass.cpp b/zone/gm_commands/spawneditmass.cpp new file mode 100644 index 000000000..8321cf840 --- /dev/null +++ b/zone/gm_commands/spawneditmass.cpp @@ -0,0 +1,148 @@ +#include "../client.h" + +void command_spawneditmass(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + if (arguments < 3) { + c->Message(Chat::Yellow, "Usage: #spawneditmass [Search Criteria] [Edit Option] [Edit Value] [Apply]"); + return; + } + + std::string search_criteria = sep->arg[1]; + std::string edit_option = sep->arg[2]; + std::string edit_value = sep->arg[3]; + bool is_apply = sep->arg[4] ? !strcasecmp(sep->arg[4], "apply") : false; + + if (edit_option != "respawn_time") { // Remove this when other options are added, here so people know there's only one option at the moment. + c->Message(Chat::Yellow, "The only edit option currently implemented is \"respawn_time\", more will be added in the future."); + return; + } + + auto query = fmt::format( + SQL( + SELECT + npc_types.id, + npc_types.name, + spawn2.respawntime, + spawn2.id + FROM + npc_types + JOIN spawnentry ON spawnentry.npcID = npc_types.id + JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID + WHERE + spawn2.zone = '{}' AND spawn2.version = {} + GROUP BY npc_types.id + ), + zone->GetShortName(), + zone->GetInstanceVersion() + ); + + std::vector spawn2_ids; + + auto results = database.QueryDatabase(query); + + c->Message( + Chat::Yellow, + fmt::format( + "Spawn Edit Mass ({})", + is_apply ? "Applying" : "Searching" + ).c_str() + ); + + for (auto row : results) { + std::string npc_id = row[0]; + std::string npc_name = row[1]; + std::string respawn_time = row[2]; + std::string spawn2_id = row[3]; + + if (npc_name.find(search_criteria) == std::string::npos) { + continue; + } + + c->Message( + Chat::Yellow, + fmt::format( + "Spawn2 ID: {} NPC ID: {} Name: {} Respawn Time: {} ({})", + Strings::Commify(spawn2_id), + Strings::Commify(npc_id), + npc_name, + Strings::SecondsToTime(std::stoi(respawn_time)), + Strings::Commify(respawn_time) + ).c_str() + ); + + spawn2_ids.push_back(spawn2_id); + } + + if (!spawn2_ids.size()) { + c->Message( + Chat::Yellow, + fmt::format( + "No NPC Spawn2 entries were found matching '{}' in this zone.", + search_criteria + ).c_str() + ); + return; + } + + c->Message( + Chat::Yellow, + fmt::format( + "Found {} NPC Spawn2 entr{} matching '{}' in this zone", + spawn2_ids.size(), + spawn2_ids.size() != 1 ? "ies" : "y", + search_criteria + ).c_str() + ); + + if (!is_apply) { + auto edit_link = fmt::format( + "#spawneditmass {} {} {} apply", + search_criteria, + edit_option, + edit_value + ); + + c->Message( + Chat::Yellow, + fmt::format( + "To apply these changes, click {} or type \"{}\".", + Saylink::Silent(edit_link, "apply"), + edit_link + ).c_str() + ); + } + + if (edit_option == "respawn_time" && is_apply) { + auto spawn2_ids_string = Strings::Implode(", ", spawn2_ids); + if (spawn2_ids_string.empty()) { + c->Message( + Chat::Yellow, + fmt::format( + "No NPC Spawn2 entries were found matching '{}' in this zone.", + search_criteria + ).c_str() + ); + return; + } + + database.QueryDatabase( + fmt::format( + SQL( + UPDATE spawn2 SET respawntime = {} WHERE id IN ({}) + ), + std::stoi(edit_value), + spawn2_ids_string + ) + ); + + c->Message( + Chat::Yellow, + fmt::format( + "Updated {} NPC spawn{} in this zone.", + spawn2_ids.size(), + spawn2_ids.size() != 1 ? "s" : "" + ).c_str() + ); + } +} diff --git a/zone/gm_commands/spawnstatus.cpp b/zone/gm_commands/spawnstatus.cpp index 6c90fb353..ed465899c 100755 --- a/zone/gm_commands/spawnstatus.cpp +++ b/zone/gm_commands/spawnstatus.cpp @@ -36,7 +36,7 @@ void command_spawnstatus(Client *c, const Seperator *sep) filter_type = "Enabled"; } - uint32 spawn_id = 0; + uint32 spawn_id = 0; if (is_search) { spawn_id = std::stoul(sep->arg[1]); } @@ -84,7 +84,7 @@ void command_spawnstatus(Client *c, const Seperator *sep) fmt::format( "Spawn {} | Respawn: {} ({} Second{})", spawn_number, - ConvertSecondsToTime(seconds_remaining), + Strings::SecondsToTime(seconds_remaining), seconds_remaining, seconds_remaining != 1 ? "s" : "" ).c_str() @@ -112,7 +112,7 @@ void command_spawnstatus(Client *c, const Seperator *sep) ); return; } - + if (is_all) { c->Message( Chat::White, diff --git a/zone/gm_commands/spellinfo.cpp b/zone/gm_commands/spellinfo.cpp index a40a3be66..7b9720fe1 100755 --- a/zone/gm_commands/spellinfo.cpp +++ b/zone/gm_commands/spellinfo.cpp @@ -6,7 +6,7 @@ void command_spellinfo(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #spellinfo [spell_id]"); } else { - short int spell_id = atoi(sep->arg[1]); + int32_t spell_id = atoi(sep->arg[1]); const struct SPDat_Spell_Struct *s = &spells[spell_id]; c->Message(Chat::White, "Spell info for spell #%d:", spell_id); c->Message(Chat::White, " name: %s", s->name); diff --git a/zone/gm_commands/stun.cpp b/zone/gm_commands/stun.cpp index cf8cd8a97..8468aad60 100755 --- a/zone/gm_commands/stun.cpp +++ b/zone/gm_commands/stun.cpp @@ -31,7 +31,7 @@ void command_stun(Client *c, const Seperator *sep) fmt::format( "You stunned {} for {}.", c->GetTargetDescription(target), - ConvertMillisecondsToTime(duration) + Strings::MillisecondsToTime(duration) ) : fmt::format( "You unstunned {}.", diff --git a/zone/gm_commands/suspend.cpp b/zone/gm_commands/suspend.cpp index 49721507e..c11daff53 100755 --- a/zone/gm_commands/suspend.cpp +++ b/zone/gm_commands/suspend.cpp @@ -1,98 +1,89 @@ #include "../client.h" #include "../worldserver.h" +#include "../../common/repositories/account_repository.h" extern WorldServer worldserver; void command_suspend(Client *c, const Seperator *sep) { - if ((sep->arg[1][0] == 0) || (sep->arg[2][0] == 0)) { + auto arguments = sep->argnum; + if (arguments < 2 || !sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #suspend [Character Name] [Days] [Reason]"); + c->Message(Chat::White, "Note: Specify 0 days to lift a suspension"); + return; + } + + const std::string character_name = Strings::ToLower(sep->arg[1]); + auto days = std::stoul(sep->arg[2]); + + const std::string reason = sep->arg[3] ? sep->argplus[3] : ""; + + auto l = AccountRepository::GetWhere( + content_db, + fmt::format( + "LOWER(charname) = '{}'", + Strings::Escape(character_name) + ) + ); + + if (l.empty()) { c->Message( Chat::White, - "Usage: #suspend (Specify 0 days to lift the suspension immediately) " + fmt::format( + "Character '{}' does not exist.", + sep->arg[1] + ).c_str() ); return; } - int duration = atoi(sep->arg[2]); + l[0].status = -1; + l[0].suspendeduntil = std::time(nullptr) + (days * 86400); + l[0].suspend_reason = reason; - if (duration < 0) { - duration = 0; - } - - std::string message; - - if (duration > 0) { - int i = 3; - while (1) { - if (sep->arg[i][0] == 0) { - break; - } - - if (message.length() > 0) { - message.push_back(' '); - } - - message += sep->arg[i]; - ++i; - } - - if (message.length() == 0) { - c->Message( - Chat::White, - "Usage: #suspend (Specify 0 days to lift the suspension immediately) " - ); - return; - } - } - - auto escName = new char[strlen(sep->arg[1]) * 2 + 1]; - database.DoEscapeString(escName, sep->arg[1], strlen(sep->arg[1])); - int accountID = database.GetAccountIDByChar(escName); - safe_delete_array(escName); - - if (accountID <= 0) { - c->Message(Chat::Red, "Character does not exist."); + if (!AccountRepository::UpdateOne(content_db, l[0])) { + c->Message( + Chat::White, + fmt::format( + "Failed to suspend {}.", + character_name + ).c_str() + ); return; } - std::string query = StringFormat( - "UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY), " - "suspend_reason = '%s' WHERE `id` = %i", - duration, EscapeString(message).c_str(), accountID + c->Message( + Chat::White, + fmt::format( + "Account {} ({}) with the character {} {}.", + l[0].name, + l[0].id, + character_name, + ( + days ? + fmt::format( + "has been temporarily suspended for {} day{}.", + days, + days != 1 ? "s" : "" + ) : + "is no longer suspended" + ) + ).c_str() ); - auto results = database.QueryDatabase(query); - if (duration) { - c->Message( - Chat::Red, - "Account number %i with the character %s has been temporarily suspended for %i day(s).", - accountID, - sep->arg[1], - duration - ); - } - else { - c->Message( - Chat::Red, - "Account number %i with the character %s is no longer suspended.", - accountID, - sep->arg[1] - ); - } + auto* b = entity_list.GetClientByName(character_name.c_str()); - Client *bannedClient = entity_list.GetClientByName(sep->arg[1]); - - if (bannedClient) { - bannedClient->WorldKick(); + if (b) { + b->WorldKick(); return; } - auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); - ServerKickPlayer_Struct *sks = (ServerKickPlayer_Struct *) pack->pBuffer; + auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); + auto* k = (ServerKickPlayer_Struct *) pack->pBuffer; - strn0cpy(sks->adminname, c->GetName(), sizeof(sks->adminname)); - strn0cpy(sks->name, sep->arg[1], sizeof(sks->name)); - sks->adminrank = c->Admin(); + strn0cpy(k->adminname, c->GetName(), sizeof(k->adminname)); + strn0cpy(k->name, character_name.c_str(), sizeof(k->name)); + k->adminrank = c->Admin(); worldserver.SendPacket(pack); diff --git a/zone/gm_commands/suspendmulti.cpp b/zone/gm_commands/suspendmulti.cpp new file mode 100755 index 000000000..9f77aaf7c --- /dev/null +++ b/zone/gm_commands/suspendmulti.cpp @@ -0,0 +1,93 @@ +#include "../client.h" +#include "../worldserver.h" +#include "../../common/repositories/account_repository.h" + +extern WorldServer worldserver; + +void command_suspendmulti(Client *c, const Seperator *sep) +{ + auto arguments = sep->argnum; + if (arguments < 2 || !sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #suspendmulti [Character Name|Character Name Two|etc] [Days] [Reason]"); + c->Message(Chat::White, "Note: Specify 0 days to lift a suspension"); + return; + } + + const auto& n = Strings::Split(sep->arg[1], "|"); + std::vector v; + for (const auto& c : n) { + v.push_back(fmt::format("'{}'", Strings::ToLower(c))); + } + + auto days = std::stoul(sep->arg[2]); + + const std::string reason = sep->arg[3] ? sep->argplus[3] : ""; + + auto l = AccountRepository::GetWhere( + database, + fmt::format( + "LOWER(charname) IN ({})", + Strings::Implode(", ", v) + ) + ); + + if (l.empty()) { + c->Message(Chat::White, "No characters found."); + return; + } + + for (auto a : l) { + a.status = -1; + a.suspendeduntil = std::time(nullptr) + (days * 86400); + a.suspend_reason = reason; + + if (!AccountRepository::UpdateOne(database, a)) { + c->Message( + Chat::White, + fmt::format( + "Failed to suspend Account {} ({}).", + a.name, + a.id + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Account {} ({}) {}.", + a.name, + a.id, + ( + days ? + fmt::format( + "has been temporarily suspended for {} day{}.", + days, + days != 1 ? "s" : "" + ) : + "is no longer suspended" + ) + ).c_str() + ); + + auto *b = entity_list.GetClientByAccID(a.id); + + if (b) { + b->WorldKick(); + return; + } + + auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); + auto *k = (ServerKickPlayer_Struct *) pack->pBuffer; + + strn0cpy(k->adminname, c->GetName(), sizeof(k->adminname)); + k->account_id = a.id; + k->adminrank = c->Admin(); + + worldserver.SendPacket(pack); + + safe_delete(pack); + } +} + diff --git a/zone/gm_commands/task.cpp b/zone/gm_commands/task.cpp index 9f6077fca..6ae2c7d69 100755 --- a/zone/gm_commands/task.cpp +++ b/zone/gm_commands/task.cpp @@ -18,7 +18,7 @@ void command_task(Client *c, const Seperator *sep) Chat::White, fmt::format( "--- [{}] List active tasks for a client", - EQ::SayLinkEngine::GenerateQuestSaylink("#task show", false, "show") + Saylink::Silent("#task show", "show") ).c_str() ); c->Message(Chat::White, "--- update [count] | Updates task"); @@ -28,42 +28,35 @@ void command_task(Client *c, const Seperator *sep) Chat::White, fmt::format( "--- [{}] Reload all Task information from the database", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reloadall", false, "reloadall") + Saylink::Silent("#task reloadall", "reloadall") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Reload Task and Activity information for a single task", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload task", false, "reload task") + Saylink::Silent("#task reload task", "reload task") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Reload goal/reward list information", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload lists", false, "reload lists") - ).c_str() - ); - c->Message( - Chat::White, - fmt::format( - "--- [{}] Reload proximity information", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload prox", false, "reload prox") + Saylink::Silent("#task reload lists", "reload lists") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Reload task set information", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload sets", false, "reload sets") + Saylink::Silent("#task reload sets", "reload sets") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Purges targeted characters task timers", - EQ::SayLinkEngine::GenerateQuestSaylink("#task purgetimers", false, "purgetimers") + Saylink::Silent("#task purgetimers", "purgetimers") ).c_str() ); @@ -74,7 +67,7 @@ void command_task(Client *c, const Seperator *sep) Chat::White, fmt::format( "--- [{}] Purges all active Shared Tasks in memory and database ", - EQ::SayLinkEngine::GenerateQuestSaylink("#task sharedpurge", false, "sharedpurge") + Saylink::Silent("#task sharedpurge", "sharedpurge") ).c_str() ); return; @@ -112,7 +105,7 @@ void command_task(Client *c, const Seperator *sep) Chat::White, fmt::format( "--- [{}] List active tasks for a client", - EQ::SayLinkEngine::GenerateQuestSaylink("#task show", false, "show") + Saylink::Silent("#task show", "show") ).c_str() ); c->Message(Chat::White, "--- update [count] | Updates task"); @@ -122,42 +115,35 @@ void command_task(Client *c, const Seperator *sep) Chat::White, fmt::format( "--- [{}] Reload all Task information from the database", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reloadall", false, "reloadall") + Saylink::Silent("#task reloadall", "reloadall") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Reload Task and Activity information for a single task", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload task", false, "reload task") + Saylink::Silent("#task reload task", "reload task") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Reload goal/reward list information", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload lists", false, "reload lists") - ).c_str() - ); - c->Message( - Chat::White, - fmt::format( - "--- [{}] Reload proximity information", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload prox", false, "reload prox") + Saylink::Silent("#task reload lists", "reload lists") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Reload task set information", - EQ::SayLinkEngine::GenerateQuestSaylink("#task reload sets", false, "reload sets") + Saylink::Silent("#task reload sets", "reload sets") ).c_str() ); c->Message( Chat::White, fmt::format( "--- [{}] Purges targeted characters task timers", - EQ::SayLinkEngine::GenerateQuestSaylink("#task purgetimers", false, "purgetimers") + Saylink::Silent("#task purgetimers", "purgetimers") ).c_str() ); @@ -168,15 +154,15 @@ void command_task(Client *c, const Seperator *sep) Chat::White, fmt::format( "--- [{}] Purges all active Shared Tasks in memory and database ", - EQ::SayLinkEngine::GenerateQuestSaylink("#task sharedpurge", false, "sharedpurge") + Saylink::Silent("#task sharedpurge", "sharedpurge") ).c_str() ); return; } if (is_assign) { - auto task_id = std::stoul(sep->arg[2]); - if (task_id && task_id < MAXTASKS) { + auto task_id = std::strtoul(sep->arg[2], nullptr, 10); + if (task_id) { target->AssignTask(task_id, 0, false); c->Message( Chat::Yellow, @@ -205,24 +191,14 @@ void command_task(Client *c, const Seperator *sep) return; } else if (is_reload) { if (arguments >= 2) { - if (!strcasecmp(sep->arg[2], "lists")) { - c->Message(Chat::Yellow, "Attempting to reload goal lists."); - worldserver.SendReloadTasks(RELOADTASKGOALLISTS); - c->Message(Chat::Yellow, "Successfully reloaded goal lists."); - return; - } else if (!strcasecmp(sep->arg[2], "prox")) { - c->Message(Chat::Yellow, "Attempting to reload task proximites."); - worldserver.SendReloadTasks(RELOADTASKPROXIMITIES); - c->Message(Chat::Yellow, "Successfully reloaded task proximites."); - return; - } else if (!strcasecmp(sep->arg[2], "sets")) { + if (!strcasecmp(sep->arg[2], "sets")) { c->Message(Chat::Yellow, "Attempting to reload task sets."); worldserver.SendReloadTasks(RELOADTASKSETS); c->Message(Chat::Yellow, "Successfully reloaded task sets."); return; } else if (!strcasecmp(sep->arg[2], "task") && arguments == 3) { - int task_id = std::stoul(sep->arg[3]); - if (task_id && task_id < MAXTASKS) { + int task_id = std::strtoul(sep->arg[3], nullptr, 10); + if (task_id) { c->Message( Chat::Yellow, fmt::format( @@ -260,7 +236,7 @@ void command_task(Client *c, const Seperator *sep) Chat::White, fmt::format( "[WARNING] This will purge all active Shared Tasks [{}]?", - EQ::SayLinkEngine::GenerateQuestSaylink("#task sharedpurge confirm", false, "confirm") + Saylink::Silent("#task sharedpurge confirm", "confirm") ).c_str() ); @@ -271,14 +247,14 @@ void command_task(Client *c, const Seperator *sep) } else if (is_uncomplete) { if (sep->IsNumber(2)) { auto task_id = std::stoul(sep->arg[2]); - if (!task_id || task_id > MAXTASKS) { + if (!task_id) { c->Message(Chat::White, "Invalid task ID specified."); return; } if ( CompletedTasksRepository::DeleteWhere( - database, + database, fmt::format( "charid = {} AND taskid = {}", target->CharacterID(), @@ -308,12 +284,12 @@ void command_task(Client *c, const Seperator *sep) } } else if (is_update) { if (arguments >= 3) { - auto task_id = std::stoul(sep->arg[2]); - auto activity_id = std::stoul(sep->arg[3]); + auto task_id = std::strtoul(sep->arg[2], nullptr, 10); + auto activity_id = std::strtoul(sep->arg[3], nullptr, 10); int count = 1; if (arguments >= 4) { - count = std::stoi(sep->arg[4]); + count = std::strtol(sep->arg[4], nullptr, 10); if (count <= 0) { count = 1; } diff --git a/zone/gm_commands/timers.cpp b/zone/gm_commands/timers.cpp index 6f66feeae..efee6da55 100755 --- a/zone/gm_commands/timers.cpp +++ b/zone/gm_commands/timers.cpp @@ -1,40 +1,48 @@ #include "../client.h" +#include "../dialogue_window.h" void command_timers(Client *c, const Seperator *sep) { - auto target = c; + auto t = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { - target = c->GetTarget()->CastToClient(); + t = c->GetTarget()->CastToClient(); } - std::vector> timers; - target->GetPTimers().ToVector(timers); + std::vector> l; + t->GetPTimers().ToVector(l); - std::string popup_title = fmt::format( - "Recast Timers for {}", - c->GetTargetDescription(target, TargetDescriptionType::UCSelf) + if (l.empty()) { + c->Message( + Chat::White, + fmt::format( + "{} {} no recast timers.", + c->GetTargetDescription(t, TargetDescriptionType::UCYou), + c == t ? "have" : "has" + ).c_str() + ); + return; + } + + auto m = DialogueWindow::TableRow( + DialogueWindow::TableCell("Timer ID") + + DialogueWindow::TableCell("Remaining Time") ); - std::string popup_text = ""; - - popup_text += ""; - - for (const auto& timer : timers) { - auto remaining_time = timer.second->GetRemainingTime(); - if (remaining_time) { - popup_text += fmt::format( - "", - timer.first, - ConvertSecondsToTime(remaining_time) + for (const auto& e : l) { + auto r = e.second->GetRemainingTime(); + if (r) { + m += DialogueWindow::TableRow( + DialogueWindow::TableCell(std::to_string(e.first)) + + DialogueWindow::TableCell(Strings::SecondsToTime(r)) ); } } - popup_text += "
Timer IDRemaining
{}{}
"; - c->SendPopupToClient( - popup_title.c_str(), - popup_text.c_str() + fmt::format( + "Recast Timers for {}", + c->GetTargetDescription(t, TargetDescriptionType::UCSelf) + ).c_str(), + DialogueWindow::Table(m).c_str() ); } - diff --git a/zone/gm_commands/title.cpp b/zone/gm_commands/title.cpp index bd0503008..653355608 100755 --- a/zone/gm_commands/title.cpp +++ b/zone/gm_commands/title.cpp @@ -5,17 +5,13 @@ void command_title(Client *c, const Seperator *sep) { int arguments = sep->argnum; if (!arguments) { - c->Message( - Chat::White, - "Usage: #title [Remove|Title] [Save (0 = False, 1 = True)]" - ); + c->Message(Chat::White, "Usage: #title [Title] (use \"-1\" to remove title)"); return; } - - bool is_remove = !strcasecmp(sep->arg[1], "remove"); - std::string title = is_remove ? "" : sep->arg[1]; - bool save_title = sep->IsNumber(2) ? atobool(sep->arg[2]) : false; - + + bool is_remove = !strcasecmp(sep->argplus[1], "-1"); + std::string title = is_remove ? "" : sep->argplus[1]; + auto target = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { target = c->GetTarget()->CastToClient(); @@ -27,13 +23,13 @@ void command_title(Client *c, const Seperator *sep) } if (!title.empty()) { - find_replace(title, "_", " "); + Strings::FindReplace(title, "_", " "); } - if (!save_title || is_remove) { - target->SetAATitle(title.c_str()); - } else if (save_title) { - title_manager.CreateNewPlayerTitle(target, title.c_str()); + if (is_remove) { + target->SetAATitle(title); + } else { + title_manager.CreateNewPlayerTitle(target, title); } target->Save(); @@ -43,7 +39,7 @@ void command_title(Client *c, const Seperator *sep) fmt::format( "Title has been {}{} for {}{}", is_remove ? "removed" : "changed", - !is_remove && save_title ? " and saved" : "", + !is_remove ? " and saved" : "", c->GetTargetDescription(target), ( is_remove ? diff --git a/zone/gm_commands/titlesuffix.cpp b/zone/gm_commands/titlesuffix.cpp index b2e6cb4bf..cc5581d96 100755 --- a/zone/gm_commands/titlesuffix.cpp +++ b/zone/gm_commands/titlesuffix.cpp @@ -7,15 +7,14 @@ void command_titlesuffix(Client *c, const Seperator *sep) if (!arguments) { c->Message( Chat::White, - "Usage: #titlesuffix [Remove|Title] [Save (0 = False, 1 = True)]" + "Usage: #titlesuffix [Title Suffix] (use \"-1\" to remove title suffix)" ); return; } - - bool is_remove = !strcasecmp(sep->arg[1], "remove"); - std::string suffix = is_remove ? "" : sep->arg[1]; - bool save_suffix = sep->IsNumber(2) ? atobool(sep->arg[2]) : false; - + + bool is_remove = !strcasecmp(sep->argplus[1], "-1"); + std::string suffix = is_remove ? "" : sep->argplus[1]; + auto target = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { target = c->GetTarget()->CastToClient(); @@ -27,13 +26,13 @@ void command_titlesuffix(Client *c, const Seperator *sep) } if (!suffix.empty()) { - find_replace(suffix, "_", " "); + Strings::FindReplace(suffix, "_", " "); } - if (!save_suffix || is_remove) { - target->SetTitleSuffix(suffix.c_str()); - } else if (save_suffix) { - title_manager.CreateNewPlayerSuffix(target, suffix.c_str()); + if (is_remove) { + target->SetTitleSuffix(suffix); + } else { + title_manager.CreateNewPlayerSuffix(target, suffix); } target->Save(); @@ -43,7 +42,7 @@ void command_titlesuffix(Client *c, const Seperator *sep) fmt::format( "Title suffix has been {}{} for {}{}", is_remove ? "removed" : "changed", - !is_remove && save_suffix ? " and saved" : "", + !is_remove ? " and saved" : "", c->GetTargetDescription(target), ( is_remove ? diff --git a/zone/gm_commands/unlock.cpp b/zone/gm_commands/unlock.cpp deleted file mode 100755 index 2d35220e6..000000000 --- a/zone/gm_commands/unlock.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "../client.h" -#include "../worldserver.h" - -extern WorldServer worldserver; - -void command_unlock(Client *c, const Seperator *sep) -{ - auto outpack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); - ServerLock_Struct *lss = (ServerLock_Struct *) outpack->pBuffer; - strcpy(lss->myname, c->GetName()); - lss->mode = 0; - worldserver.SendPacket(outpack); - safe_delete(outpack); -} - diff --git a/zone/gm_commands/viewcurrencies.cpp b/zone/gm_commands/viewcurrencies.cpp index b665a5d14..a19c72ffe 100644 --- a/zone/gm_commands/viewcurrencies.cpp +++ b/zone/gm_commands/viewcurrencies.cpp @@ -1,7 +1,7 @@ #include "../client.h" void command_viewcurrencies(Client *c, const Seperator *sep) -{ +{ Client *target = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { target = c->GetTarget()->CastToClient(); @@ -13,19 +13,19 @@ void command_viewcurrencies(Client *c, const Seperator *sep) target->GetMoney(3, 2) + target->GetMoney(3, 3) ); - + auto gold = ( target->GetMoney(2, 0) + target->GetMoney(2, 1) + target->GetMoney(2, 2) ); - + auto silver = ( target->GetMoney(1, 0) + target->GetMoney(1, 1) + target->GetMoney(1, 2) ); - + auto copper = ( target->GetMoney(0, 0) + target->GetMoney(0, 1) + @@ -43,7 +43,7 @@ void command_viewcurrencies(Client *c, const Seperator *sep) fmt::format( "Money for {} | {}", c->GetTargetDescription(target, TargetDescriptionType::UCSelf), - ConvertMoneyToString( + Strings::Money( platinum, gold, silver, diff --git a/zone/gm_commands/viewnpctype.cpp b/zone/gm_commands/viewnpctype.cpp index 70447c145..bf3cc8fef 100755 --- a/zone/gm_commands/viewnpctype.cpp +++ b/zone/gm_commands/viewnpctype.cpp @@ -13,6 +13,7 @@ void command_viewnpctype(Client *c, const Seperator *sep) GravityBehavior::Water ); npc->ShowStats(c); + safe_delete(npc); } else { c->Message( diff --git a/zone/gm_commands/viewrecipe.cpp b/zone/gm_commands/viewrecipe.cpp new file mode 100755 index 000000000..d8eb820f3 --- /dev/null +++ b/zone/gm_commands/viewrecipe.cpp @@ -0,0 +1,120 @@ +#include "../client.h" +#include "../command.h" +#include "../../common/repositories/tradeskill_recipe_repository.h" +#include "../../common/repositories/tradeskill_recipe_entries_repository.h" + +void command_viewrecipe(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1)) { + c->Message(Chat::White, "Command Syntax: #viewrecipe [Recipe ID]"); + return; + } + + auto recipe_id = static_cast(std::stoul(sep->arg[1])); + auto re = TradeskillRecipeEntriesRepository::GetWhere( + database, + fmt::format("recipe_id = {} ORDER BY id ASC", recipe_id) + ); + auto r = TradeskillRecipeRepository::GetWhere( + database, + fmt::format("id = {}", recipe_id) + ); + + if (re.empty() || r.empty() || !re[0].id || !r[0].id) { + c->Message( + Chat::White, + fmt::format( + "Recipe ID {} has no entries or could not be found.", + Strings::Commify(std::to_string(recipe_id)) + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Recipe {} | {}", + Strings::Commify(std::to_string(recipe_id)), + r[0].name + ).c_str() + ); + + auto entry_number = 1; + bool can_summon_items = c->Admin() >= GetCommandStatus(c, "summonitem"); + + for (const auto& e : re) { + c->Message( + Chat::White, + fmt::format( + "Entry {}{} | {}{}", + entry_number, + e.iscontainer > 0 ? " (Container)" : "", + e.item_id > 1000 ? database.CreateItemLink(e.item_id) : EQ::constants::GetObjectTypeName(e.item_id), + can_summon_items && e.item_id > 1000 ? fmt::format(" | {}", Saylink::Silent(fmt::format("#si {}", e.item_id), "Summon")) : "" + ).c_str() + ); + + std::vector emv; + bool has_message = false; + + if (e.componentcount) { + emv.push_back( + fmt::format( + "Component: {}", + e.componentcount + ) + ); + + has_message = true; + } + + if (e.failcount) { + emv.push_back( + fmt::format( + "Fail: {}", + e.failcount + ) + ); + + has_message = true; + } + + if (e.salvagecount) { + emv.push_back( + fmt::format( + "Salvage: {}", + e.salvagecount + ) + ); + + has_message = true; + } + + if (e.successcount) { + emv.push_back( + fmt::format( + "Success: {}", + e.successcount + ) + ); + + has_message = true; + } + + if (has_message) { + c->Message( + Chat::White, + fmt::format( + "Entry {} Counts | {}", + entry_number, + Strings::Implode(" | ", emv) + ).c_str() + ); + } + + entry_number++; + } +} + diff --git a/zone/gm_commands/viewzoneloot.cpp b/zone/gm_commands/viewzoneloot.cpp index 89518750a..24818663c 100755 --- a/zone/gm_commands/viewzoneloot.cpp +++ b/zone/gm_commands/viewzoneloot.cpp @@ -30,7 +30,7 @@ void command_viewzoneloot(Client *c, const Seperator *sep) std::string npc_name = current_npc->GetCleanName(); uint32 instance_id = zone->GetInstanceID(); uint32 zone_id = zone->GetZoneID(); - std::string command_link = EQ::SayLinkEngine::GenerateQuestSaylink( + std::string command_link = Saylink::Silent( fmt::format( "#{} {} {} {} {}", (instance_id != 0 ? "zoneinstance" : "zone"), @@ -39,7 +39,6 @@ void command_viewzoneloot(Client *c, const Seperator *sep) current_npc->GetY(), current_npc->GetZ() ), - false, "Goto" ); npc_link = fmt::format( diff --git a/zone/gm_commands/weather.cpp b/zone/gm_commands/weather.cpp index 2590c51e3..7c06255a7 100755 --- a/zone/gm_commands/weather.cpp +++ b/zone/gm_commands/weather.cpp @@ -2,67 +2,104 @@ void command_weather(Client *c, const Seperator *sep) { - if (!(sep->arg[1][0] == '0' || sep->arg[1][0] == '1' || sep->arg[1][0] == '2' || sep->arg[1][0] == '3')) { - c->Message(Chat::White, "Usage: #weather <0/1/2/3> - Off/Rain/Snow/Manual."); + if (!sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #weather [0|1|2] - [Off|Rain|Snow]"); + c->Message(Chat::White, "Usage: #weather 3 [Type] [Intensity] - Manually set weather type and intensity"); + return; } - else if (zone->zone_weather == 0) { - if (sep->arg[1][0] == - '3') { // Put in modifications here because it had a very good chance at screwing up the client's weather system if rain was sent during snow -T7 - if (sep->arg[2][0] != 0 && sep->arg[3][0] != 0) { - c->Message(Chat::White, "Sending weather packet... TYPE=%s, INTENSITY=%s", sep->arg[2], sep->arg[3]); - zone->zone_weather = atoi(sep->arg[2]); - auto outapp = new EQApplicationPacket(OP_Weather, 8); - outapp->pBuffer[0] = atoi(sep->arg[2]); - outapp->pBuffer[4] = atoi(sep->arg[3]); // This number changes in the packets, intensity? - entity_list.QueueClients(c, outapp); - safe_delete(outapp); + + int arguments = sep->argnum; + if (arguments == 1) { + auto new_weather = static_cast(std::stoul(sep->arg[1])); + uint8 new_intensity = 0; + std::string weather_message = "The sky clears."; + + if (new_weather == EQ::constants::WeatherTypes::Snowing) { + weather_message = "Snowflakes begin to fall from the sky."; + new_weather = EQ::constants::WeatherTypes::Snowing; + new_intensity = 0x02; + } else if (new_weather == EQ::constants::WeatherTypes::Raining) { + weather_message = "Raindrops begin to fall from the sky."; + new_weather = EQ::constants::WeatherTypes::Raining; + new_intensity = 0x01; // This is how it's done in Fear, and you can see a decent distance with it at this value + } else { + c->Message(Chat::White, "Usage: #weather [0|1|2] - [Off|Rain|Snow]"); + c->Message(Chat::White, "Usage: #weather 3 [Type] [Intensity] - Manually set weather type and intensity"); + return; + } + + zone->zone_weather = new_weather; + auto outapp = new EQApplicationPacket(OP_Weather, 8); + + if (new_weather != EQ::constants::WeatherTypes::None) { + if (new_weather == EQ::constants::WeatherTypes::Snowing) { + outapp->pBuffer[0] = EQ::constants::WeatherTypes::Snowing; } - else { - c->Message(Chat::White, "Manual Usage: #weather 3 "); + + outapp->pBuffer[4] = new_intensity; + } + + + c->Message(Chat::White, weather_message.c_str()); + entity_list.QueueClients(c, outapp); + + safe_delete(outapp); + } else if (arguments == 3) { + auto command_type = static_cast(std::stoul(sep->arg[1])); + uint8 new_weather = EQ::constants::WeatherTypes::None; + uint8 new_intensity = 0; + std::string weather_message; + + if (zone->zone_weather == EQ::constants::WeatherTypes::None) { + if (command_type > EQ::constants::WeatherTypes::Snowing) { + new_weather = static_cast(std::stoul(sep->arg[2])); + new_intensity = static_cast(std::stoul(sep->arg[3])); + + weather_message = fmt::format( + "Sending {} ({}) with an intensity of {}.", + EQ::constants::GetWeatherTypeName(new_weather), + new_weather, + new_intensity + ); + } else if (command_type == EQ::constants::WeatherTypes::Snowing) { + weather_message = "Snowflakes begin to fall from the sky."; + new_weather = EQ::constants::WeatherTypes::Snowing; + new_intensity = 0x02; + } else if (command_type == EQ::constants::WeatherTypes::Raining) { + weather_message = "Raindrops begin to fall from the sky."; + new_weather = EQ::constants::WeatherTypes::Raining; + new_intensity = 0x01; // This is how it's done in Fear, and you can see a decent distance with it at this value } - } - else if (sep->arg[1][0] == '2') { - entity_list.Message(0, 0, "Snowflakes begin to fall from the sky."); - zone->zone_weather = 2; + + zone->zone_weather = new_weather; auto outapp = new EQApplicationPacket(OP_Weather, 8); - outapp->pBuffer[0] = 0x01; - outapp->pBuffer[4] = 0x02; // This number changes in the packets, intensity? + + if (new_weather != EQ::constants::WeatherTypes::Raining) { + outapp->pBuffer[0] = new_weather; + } + + outapp->pBuffer[4] = new_intensity; + + c->Message(Chat::White, weather_message.c_str()); entity_list.QueueClients(c, outapp); + safe_delete(outapp); - } - else if (sep->arg[1][0] == '1') { - entity_list.Message(0, 0, "Raindrops begin to fall from the sky."); - zone->zone_weather = 1; + } else { auto outapp = new EQApplicationPacket(OP_Weather, 8); - outapp->pBuffer[4] = 0x01; // This is how it's done in Fear, and you can see a decent distance with it at this value - entity_list.QueueClients(c, outapp); - safe_delete(outapp); - } - } - else { - if (zone->zone_weather == 1) { // Doing this because if you have rain/snow on, you can only turn one off. - entity_list.Message(0, 0, "The sky clears as the rain ceases to fall."); - zone->zone_weather = 0; - auto outapp = new EQApplicationPacket(OP_Weather, 8); - // To shutoff weather you send an empty 8 byte packet (You get this everytime you zone even if the sky is clear) - entity_list.QueueClients(c, outapp); - safe_delete(outapp); - } - else if (zone->zone_weather == 2) { - entity_list.Message(0, 0, "The sky clears as the snow stops falling."); - zone->zone_weather = 0; - auto outapp = new EQApplicationPacket(OP_Weather, 8); - // To shutoff weather you send an empty 8 byte packet (You get this everytime you zone even if the sky is clear) - outapp->pBuffer[0] = 0x01; // Snow has it's own shutoff packet - entity_list.QueueClients(c, outapp); - safe_delete(outapp); - } - else { - entity_list.Message(0, 0, "The sky clears."); - zone->zone_weather = 0; - auto outapp = new EQApplicationPacket(OP_Weather, 8); - // To shutoff weather you send an empty 8 byte packet (You get this everytime you zone even if the sky is clear) + weather_message = "The sky clears."; + + if (zone->zone_weather == EQ::constants::WeatherTypes::Snowing) { + weather_message = "The sky clears as the snow stops falling."; + outapp->pBuffer[0] = 0x01; // Snow has it's own shutoff packet + } else if (zone->zone_weather == EQ::constants::WeatherTypes::Raining) { + weather_message = "The sky clears as the rain ceases to fall."; + } + + zone->zone_weather = EQ::constants::WeatherTypes::None; + + c->Message(Chat::White, weather_message.c_str()); entity_list.QueueClients(c, outapp); + safe_delete(outapp); } } diff --git a/zone/gm_commands/who.cpp b/zone/gm_commands/who.cpp index 43077573e..0b833eaad 100755 --- a/zone/gm_commands/who.cpp +++ b/zone/gm_commands/who.cpp @@ -55,7 +55,7 @@ void command_who(Client *c, const Seperator *sep) std::string search_string; if (sep->arg[1]) { - search_string = str_tolower(sep->arg[1]); + search_string = Strings::ToLower(sep->arg[1]); } int found_count = 0; @@ -82,13 +82,13 @@ void command_who(Client *c, const Seperator *sep) if (search_string.length()) { bool found_search_term = ( - str_tolower(player_name).find(search_string) != std::string::npos || - str_tolower(zone_short_name).find(search_string) != std::string::npos || - str_tolower(displayed_race_name).find(search_string) != std::string::npos || - str_tolower(base_class_name).find(search_string) != std::string::npos || - str_tolower(guild_name).find(search_string) != std::string::npos || - str_tolower(account_name).find(search_string) != std::string::npos || - str_tolower(account_ip).find(search_string) != std::string::npos + Strings::ToLower(player_name).find(search_string) != std::string::npos || + Strings::ToLower(zone_short_name).find(search_string) != std::string::npos || + Strings::ToLower(displayed_race_name).find(search_string) != std::string::npos || + Strings::ToLower(base_class_name).find(search_string) != std::string::npos || + Strings::ToLower(guild_name).find(search_string) != std::string::npos || + Strings::ToLower(account_name).find(search_string) != std::string::npos || + Strings::ToLower(account_ip).find(search_string) != std::string::npos ); if (!found_search_term) { @@ -98,12 +98,11 @@ void command_who(Client *c, const Seperator *sep) std::string displayed_guild_name; if (guild_name.length()) { - displayed_guild_name = EQ::SayLinkEngine::GenerateQuestSaylink( + displayed_guild_name = Saylink::Silent( fmt::format( "#who \"{}\"", guild_name ), - false, fmt::format( "<{}>", guild_name @@ -111,21 +110,19 @@ void command_who(Client *c, const Seperator *sep) ); } - auto goto_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto goto_saylink = Saylink::Silent( fmt::format( "#goto {}", player_name ), - false, "Goto" ); - auto summon_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto summon_saylink = Saylink::Silent( fmt::format( "#summon {}", player_name ), - false, "Summon" ); @@ -134,48 +131,43 @@ void command_who(Client *c, const Seperator *sep) static_cast(player_level) ); - auto class_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto class_saylink = Saylink::Silent( fmt::format( "#who {}", base_class_name ), - false, display_class_name ); - auto race_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto race_saylink = Saylink::Silent( fmt::format( "#who %s", displayed_race_name ), - false, displayed_race_name ); - auto zone_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto zone_saylink = Saylink::Silent( fmt::format( "#who {}", zone_short_name ), - false, zone_long_name ); - auto account_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto account_saylink = Saylink::Silent( fmt::format( "#who {}", account_name ), - false, account_name ); - auto account_ip_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto account_ip_saylink = Saylink::Silent( fmt::format( "#who {}", account_ip ), - false, account_ip ); diff --git a/zone/gm_commands/xtargets.cpp b/zone/gm_commands/xtargets.cpp index bd300e819..c352b26b3 100755 --- a/zone/gm_commands/xtargets.cpp +++ b/zone/gm_commands/xtargets.cpp @@ -1,28 +1,40 @@ #include "../client.h" +#include "../../common/data_verification.h" void command_xtargets(Client *c, const Seperator *sep) { - Client *t; - + auto t = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { t = c->GetTarget()->CastToClient(); } - else { - t = c; - } - if (sep->arg[1][0]) { - uint8 NewMax = atoi(sep->arg[1]); - - if ((NewMax < 5) || (NewMax > XTARGET_HARDCAP)) { - c->Message(Chat::Red, "Number of XTargets must be between 5 and %i", XTARGET_HARDCAP); - return; - } - t->SetMaxXTargets(NewMax); - c->Message(Chat::White, "Max number of XTargets set to %i", NewMax); - } - else { + auto arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1)) { t->ShowXTargets(c); + return; } -} + const auto new_max = static_cast(std::stoul(sep->arg[1])); + + if (!EQ::ValueWithin(new_max, 5, XTARGET_HARDCAP)) { + c->Message( + Chat::White, + fmt::format( + "Number of XTargets must be between 5 and {}.", + XTARGET_HARDCAP + ).c_str() + ); + return; + } + + t->SetMaxXTargets(new_max); + + c->Message( + Chat::White, + fmt::format( + "Max number of XTargets set to {} for {}.", + new_max, + c->GetTargetDescription(t, TargetDescriptionType::LCSelf) + ).c_str() + ); +} diff --git a/zone/gm_commands/zheader.cpp b/zone/gm_commands/zheader.cpp index 6965a758a..f7449344c 100755 --- a/zone/gm_commands/zheader.cpp +++ b/zone/gm_commands/zheader.cpp @@ -31,19 +31,21 @@ void command_zheader(Client *c, const Seperator *sep) std::stoul(sep->arg[3]) : 0 ); - + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); safe_delete(outapp); + zone_store.LoadZones(content_db); + c->Message( Chat::White, fmt::format( "Zone Header Load {} | Zone: {} ({}){}", ( zone->LoadZoneCFG(zone_short_name, version) ? - "Suceeded" : + "Succeeded" : "Failed" ), zone_long_name, diff --git a/zone/gm_commands/zone.cpp b/zone/gm_commands/zone.cpp new file mode 100644 index 000000000..19deb4554 --- /dev/null +++ b/zone/gm_commands/zone.cpp @@ -0,0 +1,83 @@ +#include "../client.h" + +void command_zone(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #zone [Zone ID|Zone Short Name] [X] [Y] [Z]"); + return; + } + + // input: (first arg) + // zone identifier can be a string of a zone name or its ID + std::string zone_input = sep->arg[1]; + uint32 zone_id = 0; + + // if input is id + if (Strings::IsNumber(zone_input)) { + zone_id = std::stoi(zone_input); + + // validate + if (zone_id != 0 && !GetZone(zone_id)) { + c->Message(Chat::White, fmt::format("Could not find zone by id [{}]", zone_id).c_str()); + return; + } + } + else { + // validate + if (!zone_store.GetZone(zone_input)) { + c->Message(Chat::White, fmt::format("Could not find zone by short_name [{}]", zone_input).c_str()); + return; + } + + // validate we got id + zone_id = ZoneID(zone_input); + if (zone_id == 0) { + c->Message(Chat::White, fmt::format("Could not find zone id by short_name [{}]", zone_input).c_str()); + return; + } + } + + // if zone identifier is a number and the id is 0, send to safe coordinates of the local zone + if (Strings::IsNumber(zone_input) && zone_id == 0) { + c->Message(Chat::White, "Sending you to the safe coordinates of this zone."); + + c->MovePC( + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0, + ZoneToSafeCoords + ); + return; + } + + // This block is necessary to clean up any bot objects owned by a Client + if (RuleB(Bots, Enabled) && zone_id != c->GetZoneID()) { + Bot::ProcessClientZoneChange(c); + } + + // fetch zone data + auto zd = GetZoneVersionWithFallback(zone_id, 0); + if (zone_id == 0) { + c->Message(Chat::White, fmt::format("Failed to find zone with fallback [{}]", zone_id).c_str()); + return; + } + + // coordinates + auto x = sep->IsNumber(2) ? std::stof(sep->arg[2]) : 0.0f; + auto y = sep->IsNumber(3) ? std::stof(sep->arg[3]) : 0.0f; + auto z = sep->IsNumber(4) ? std::stof(sep->arg[4]) : 0.0f; + auto zone_mode = sep->IsNumber(2) ? ZoneSolicited : ZoneToSafeCoords; + + c->MovePC( + zone_id, + x, + y, + z, + zd ? zd->safe_heading : 0.0f, + 0, + zone_mode + ); +} diff --git a/zone/gm_commands/zone_instance.cpp b/zone/gm_commands/zone_instance.cpp new file mode 100644 index 000000000..e18d43990 --- /dev/null +++ b/zone/gm_commands/zone_instance.cpp @@ -0,0 +1,70 @@ +#include "../client.h" + +void command_zone_instance(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #zoneinstance [Instance ID] [X] [Y] [Z]"); + return; + } + + auto instance_id = std::stoul(sep->arg[1]); + if (!instance_id) { + c->Message(Chat::White, "You must enter a valid Instance ID."); + return; + } + + if (!database.CheckInstanceExists(instance_id)) { + c->Message( + Chat::White, + fmt::format( + "Instance ID {} does not exist.", + instance_id + ).c_str() + ); + return; + } + + auto zone_id = database.GetInstanceZoneID(instance_id); + if (!zone_id) { + c->Message( + Chat::White, + fmt::format( + "Instance ID {} not found or zone is set to null.", + instance_id + ).c_str() + ); + return; + } + + if (!database.CheckInstanceByCharID(instance_id, c->CharacterID())) { + database.AddClientToInstance(instance_id, c->CharacterID()); + } + + if (!database.VerifyInstanceAlive(instance_id, c->CharacterID())) { + c->Message( + Chat::White, + fmt::format( + "Instance ID {} expired.", + instance_id + ).c_str() + ); + return; + } + + auto x = sep->IsNumber(2) ? std::stof(sep->arg[2]) : 0.0f; + auto y = sep->IsNumber(3) ? std::stof(sep->arg[3]) : 0.0f; + auto z = sep->IsNumber(4) ? std::stof(sep->arg[4]) : 0.0f; + auto zone_mode = sep->IsNumber(2) ? ZoneSolicited : ZoneToSafeCoords; + + c->MovePC( + zone_id, + instance_id, + x, + y, + z, + 0.0f, + 0, + zone_mode + ); +} diff --git a/zone/gm_commands/zonelock.cpp b/zone/gm_commands/zonelock.cpp index f89f1e9ad..b304f1a0f 100755 --- a/zone/gm_commands/zonelock.cpp +++ b/zone/gm_commands/zonelock.cpp @@ -21,7 +21,7 @@ void command_zonelock(Client *c, const Seperator *sep) return; } - std::string lock_type = str_tolower(sep->arg[1]); + std::string lock_type = Strings::ToLower(sep->arg[1]); bool is_list = lock_type.find("list") != std::string::npos; bool is_lock = lock_type.find("lock") != std::string::npos; bool is_unlock = lock_type.find("unlock") != std::string::npos; @@ -54,7 +54,7 @@ void command_zonelock(Client *c, const Seperator *sep) static_cast(std::stoul(sep->arg[2])) : static_cast(ZoneID(sep->arg[2])) ); - std::string zone_short_name = str_tolower(ZoneName(zone_id, true)); + std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; if (zone_id && !is_unknown_zone) { lock_zone->op = is_lock ? ServerLockType::Lock : ServerLockType::Unlock; @@ -65,7 +65,7 @@ void command_zonelock(Client *c, const Seperator *sep) c->Message( Chat::White, fmt::format( - "Usage: #zonelock {} [Zone ID] or #zonelock {} [Zone Short Name]", + "Usage: #zonelock {0} [Zone ID] or #zonelock {0} [Zone Short Name]", is_lock ? "lock" : "unlock" ).c_str() ); diff --git a/zone/gm_commands/zstats.cpp b/zone/gm_commands/zstats.cpp index 7468cf1b2..ab9c65ec9 100755 --- a/zone/gm_commands/zstats.cpp +++ b/zone/gm_commands/zstats.cpp @@ -159,7 +159,7 @@ void command_zstats(Client *c, const Seperator *sep) Chat::White, fmt::format( "Suspend Buffs: {}", - zone->newzone_data.SuspendBuffs + zone->newzone_data.suspend_buffs ).c_str() ); @@ -168,9 +168,9 @@ void command_zstats(Client *c, const Seperator *sep) Chat::White, fmt::format( "Regen | Health: {} Mana: {} Endurance: {}", - zone->newzone_data.FastRegenHP, - zone->newzone_data.FastRegenMana, - zone->newzone_data.FastRegenEndurance + zone->newzone_data.fast_regen_hp, + zone->newzone_data.fast_regen_mana, + zone->newzone_data.fast_regen_endurance ).c_str() ); @@ -179,7 +179,7 @@ void command_zstats(Client *c, const Seperator *sep) Chat::White, fmt::format( "NPC Max Aggro Distance: {}", - zone->newzone_data.NPCAggroMaxDist + zone->newzone_data.npc_aggro_max_dist ).c_str() ); @@ -197,8 +197,8 @@ void command_zstats(Client *c, const Seperator *sep) Chat::White, fmt::format( "Lava Damage | Min: {} Max: {}", - zone->newzone_data.MinLavaDamage, - zone->newzone_data.LavaDamage + zone->newzone_data.min_lava_damage, + zone->newzone_data.lava_damage ).c_str() ); } diff --git a/zone/groups.cpp b/zone/groups.cpp index c82e56406..910d5b21c 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -23,8 +23,9 @@ #include "npc_ai.h" #include "../common/packet_functions.h" #include "../common/packet_dump.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "worldserver.h" +#include "string_ids.h" extern EntityList entity_list; extern WorldServer worldserver; @@ -116,91 +117,76 @@ Group::~Group() //Split money used in OP_Split (/split and /autosplit). void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter) { //avoid unneeded work - if(copper == 0 && silver == 0 && gold == 0 && platinum == 0) + if ( + !copper && + !silver && + !gold && + !platinum + ) { return; + } - uint32 i; - uint8 membercount = 0; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + uint8 member_count = 0; + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { // Don't split with Mercs or Bots - if (members[i] != nullptr && members[i]->IsClient()) { - membercount++; + if (members[i] && members[i]->IsClient()) { + member_count++; } } - if (membercount == 0) + if (!member_count) { return; + } - uint32 mod; - //try to handle round off error a little better - if(membercount > 1) { - mod = platinum % membercount; - if((mod) > 0) { - platinum -= mod; - gold += 10 * mod; + uint32 modifier; + if (member_count > 1) { + modifier = platinum % member_count; + + if (modifier) { + platinum -= modifier; + gold += 10 * modifier; } - mod = gold % membercount; - if((mod) > 0) { - gold -= mod; - silver += 10 * mod; + + modifier = gold % member_count; + + if (modifier) { + gold -= modifier; + silver += 10 * modifier; } - mod = silver % membercount; - if((mod) > 0) { - silver -= mod; - copper += 10 * mod; + + modifier = silver % member_count; + + if (modifier) { + silver -= modifier; + copper += 10 * modifier; } } - //calculate the splits - //We can still round off copper pieces, but I dont care - uint32 sc; - uint32 cpsplit = copper / membercount; - sc = copper % membercount; - uint32 spsplit = silver / membercount; - uint32 gpsplit = gold / membercount; - uint32 ppsplit = platinum / membercount; + auto copper_split = copper / member_count; + auto silver_split = silver / member_count; + auto gold_split = gold / member_count; + auto platinum_split = platinum / member_count; - char buf[128]; - buf[63] = '\0'; - std::string msg = "You receive"; - bool one = false; + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] && members[i]->IsClient()) { // If Group Member is Client + members[i]->CastToClient()->AddMoneyToPP( + copper_split, + silver_split, + gold_split, + platinum_split, + true + ); - if(ppsplit > 0) { - snprintf(buf, 63, " %u platinum", ppsplit); - msg += buf; - one = true; - } - if(gpsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u gold", gpsplit); - msg += buf; - one = true; - } - if(spsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u silver", spsplit); - msg += buf; - one = true; - } - if(cpsplit > 0) { - if(one) - msg += ","; - //this message is not 100% accurate for the splitter - //if they are receiving any roundoff - snprintf(buf, 63, " %u copper", cpsplit); - msg += buf; - one = true; - } - msg += " as your split"; - - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i]->IsClient()) { // If Group Member is Client - Client *c = members[i]->CastToClient(); - //I could not get MoneyOnCorpse to work, so we use this - c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); - c->Message(Chat::Green, msg.c_str()); + members[i]->CastToClient()->MessageString( + Chat::MoneySplit, + YOU_RECEIVE_AS_SPLIT, + Strings::Money( + platinum_split, + gold_split, + silver_split, + copper_split + ).c_str() + ); } } } @@ -357,9 +343,9 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte safe_delete(outapp); -#ifdef BOTS - Bot::UpdateGroupCastingRoles(this); -#endif + if (RuleB(Bots, Enabled)) { + Bot::UpdateGroupCastingRoles(this); + } return true; } @@ -538,9 +524,9 @@ bool Group::UpdatePlayer(Mob* update){ if (update->IsClient() && !mentoree && mentoree_name.length() && !mentoree_name.compare(update->GetName())) mentoree = update->CastToClient(); -#ifdef BOTS - Bot::UpdateGroupCastingRoles(this); -#endif + if (RuleB(Bots, Enabled)) { + Bot::UpdateGroupCastingRoles(this); + } return updateSuccess; } @@ -575,9 +561,9 @@ void Group::MemberZoned(Mob* removemob) { if (removemob->IsClient() && removemob == mentoree) mentoree = nullptr; -#ifdef BOTS - Bot::UpdateGroupCastingRoles(this); -#endif + if (RuleB(Bots, Enabled)) { + Bot::UpdateGroupCastingRoles(this); + } } void Group::SendGroupJoinOOZ(Mob* NewMember) { @@ -796,9 +782,9 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) ClearAllNPCMarks(); } -#ifdef BOTS - Bot::UpdateGroupCastingRoles(this); -#endif + if (RuleB(Bots, Enabled)) { + Bot::UpdateGroupCastingRoles(this); + } return true; } @@ -847,26 +833,28 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { disbandcheck = true; } -bool Group::IsGroupMember(Mob* client) +bool Group::IsGroupMember(Mob* c) { - bool Result = false; - - if(client) { - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == client) - Result = true; + if (c) { + for (const auto &m: members) { + if (m == c) { + return true; + } } } - return Result; + return false; } -bool Group::IsGroupMember(const char *Name) +bool Group::IsGroupMember(const char *name) { - if(Name) - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) - if((strlen(Name) == strlen(membername[i])) && !strncmp(membername[i], Name, strlen(Name))) + if (name) { + for (const auto& m : membername) { + if (!strcmp(m, name)) { return true; + } + } + } return false; } @@ -907,9 +895,9 @@ uint32 Group::GetTotalGroupDamage(Mob* other) { } void Group::DisbandGroup(bool joinraid) { -#ifdef BOTS - Bot::UpdateGroupCastingRoles(this, true); -#endif + if (RuleB(Bots, Enabled)) { + Bot::UpdateGroupCastingRoles(this, true); + } auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate_Struct)); @@ -1002,7 +990,6 @@ void Group::GetClientList(std::list& client_list, bool clear_list) } } -#ifdef BOTS void Group::GetBotList(std::list& bot_list, bool clear_list) { if (clear_list) @@ -1013,7 +1000,6 @@ void Group::GetBotList(std::list& bot_list, bool clear_list) bot_list.push_back(bot_iter->CastToBot()); } } -#endif bool Group::Process() { if(disbandcheck && !GroupCount()) @@ -2488,3 +2474,15 @@ bool Group::DoesAnyMemberHaveExpeditionLockout( } return false; } + +bool Group::IsLeader(const char* name) { + if (name) { + for (const auto& m : membername) { + if (!strcmp(m, name)) { + return true; + } + } + } + + return false; +} diff --git a/zone/groups.h b/zone/groups.h index 1a90b13ae..51d9164c9 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -62,30 +62,29 @@ public: void DisbandGroup(bool joinraid = false); void GetMemberList(std::list& member_list, bool clear_list = true); void GetClientList(std::list& client_list, bool clear_list = true); -#ifdef BOTS void GetBotList(std::list& bot_list, bool clear_list = true); -#endif - bool IsGroupMember(Mob* client); - bool IsGroupMember(const char *Name); + bool IsGroupMember(Mob* c); + bool IsGroupMember(const char* name); bool Process(); bool IsGroup() { return true; } void SendGroupJoinOOZ(Mob* NewMember); void CastGroupSpell(Mob* caster,uint16 spellid); - void SplitExp(uint32 exp, Mob* other); + void SplitExp(const uint64 exp, Mob* other); void GroupMessage(Mob* sender,uint8 language,uint8 lang_skill,const char* message); void GroupMessageString(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0); uint32 GetTotalGroupDamage(Mob* other); void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr); - inline void SetLeader(Mob* newleader){ leader=newleader; }; + inline void SetLeader(Mob* c){ leader = c; }; inline Mob* GetLeader() { return leader; }; const char* GetLeaderName() { return membername[0]; }; void SendHPManaEndPacketsTo(Mob* newmember); void SendHPPacketsFrom(Mob* member); void SendManaPacketFrom(Mob* member); - void SendEndurancePacketFrom(Mob* member); + void SendEndurancePacketFrom(Mob* member); bool UpdatePlayer(Mob* update); void MemberZoned(Mob* removemob); - inline bool IsLeader(Mob* leadertest) { return leadertest==leader; }; + bool IsLeader(const char* name); + inline bool IsLeader(Mob* m) { return m == leader; }; uint8 GroupCount(); uint32 GetHighestLevel(); uint32 GetLowestLevel(); @@ -142,10 +141,10 @@ public: void QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required = true, bool ignore_sender = true, float distance = 0); void ChangeLeader(Mob* newleader); const char *GetClientNameByIndex(uint8 index); - void UpdateXTargetMarkedNPC(uint32 Number, Mob *m); - void SetDirtyAutoHaters(); + void UpdateXTargetMarkedNPC(uint32 Number, Mob *m); + void SetDirtyAutoHaters(); inline XTargetAutoHaters *GetXTargetAutoMgr() { return &m_autohatermgr; } - void JoinRaidXTarget(Raid *raid, bool first = false); + void JoinRaidXTarget(Raid *raid, bool first = false); void SetGroupMentor(int percent, char *name); void ClearGroupMentor(); diff --git a/zone/guild.cpp b/zone/guild.cpp index 76e22b4f5..82790811e 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -18,7 +18,7 @@ #include "../common/database.h" #include "../common/guilds.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "guild_mgr.h" #include "worldserver.h" @@ -175,6 +175,7 @@ void Client::SendGuildList() { outapp->pBuffer = guild_mgr.MakeGuildList(/*GetName()*/"", outapp->size); if(outapp->pBuffer == nullptr) { LogGuilds("Unable to make guild list!"); + safe_delete(outapp); return; } diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index f17bf499b..e778647e3 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -17,14 +17,14 @@ */ #include "../common/servertalk.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "entity.h" #include "guild_mgr.h" #include "worldserver.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" ZoneGuildManager guild_mgr; GuildBankManager *GuildBanks; @@ -189,19 +189,70 @@ uint8 *ZoneGuildManager::MakeGuildMembers(uint32 guild_id, const char *prefix_na return(retbuffer); } -void ZoneGuildManager::ListGuilds(Client *c) const { +void ZoneGuildManager::ListGuilds(Client *c, uint32 guild_id) const { if (m_guilds.size()) { + const auto& g = m_guilds.find(guild_id); + if (g == m_guilds.end()) { + c->Message( + Chat::White, + fmt::format( + "Guild ID {} does not exist or is invalid.", + guild_id + ).c_str() + ); + return; + } + + const auto leader_name = database.GetCharNameByID(g->second->leader_char_id); c->Message( Chat::White, fmt::format( - "Listing {} Guild{}.", - m_guilds.size(), - m_guilds.size() != 1 ? "s" : "" + "Guild {} | {}Name: {}", + g->first, + ( + !leader_name.empty() ? + fmt::format( + "Leader: {} ({}) ", + leader_name, + g->second->leader_char_id + ) : + "" + ), + g->second->name ).c_str() ); + } else { + c->Message(Chat::White, "There are no Guilds to list."); + } +} + +void ZoneGuildManager::ListGuilds(Client *c, std::string search_criteria) const { + if (m_guilds.size()) { + if (search_criteria.empty()) { + c->Message( + Chat::White, + fmt::format( + "Listing {} Guild{}.", + m_guilds.size(), + m_guilds.size() != 1 ? "s" : "" + ).c_str() + ); + } + + auto found_count = 0; for (const auto& guild : m_guilds) { - auto leader_name = database.GetCharNameByID(guild.second->leader_char_id); + if ( + !search_criteria.empty() && + !Strings::Contains( + Strings::ToLower(guild.second->name), + Strings::ToLower(search_criteria) + ) + ) { + continue; + } + + const auto leader_name = database.GetCharNameByID(guild.second->leader_char_id); c->Message( Chat::White, fmt::format( @@ -219,7 +270,26 @@ void ZoneGuildManager::ListGuilds(Client *c) const { guild.second->name ).c_str() ); + + found_count++; } + + c->Message( + Chat::White, + fmt::format( + "Found {} Guild{}{}.", + found_count, + found_count != 1 ? "s" : "", + ( + !search_criteria.empty() ? + fmt::format( + " matching '{}'", + search_criteria + ) : + "" + ) + ).c_str() + ); } else { c->Message(Chat::White, "There are no Guilds to list."); } diff --git a/zone/guild_mgr.h b/zone/guild_mgr.h index 60f9ba98f..2e6a12de1 100644 --- a/zone/guild_mgr.h +++ b/zone/guild_mgr.h @@ -80,7 +80,8 @@ public: //called by worldserver when it receives a message from world. void ProcessWorldPacket(ServerPacket *pack); - void ListGuilds(Client *c) const; + void ListGuilds(Client *c, std::string search_criteria = std::string()) const; + void ListGuilds(Client *c, uint32 guild_id = 0) const; void DescribeGuild(Client *c, uint32 guild_id) const; diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 64be84925..fba3c1e0d 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -257,8 +257,9 @@ bool HateList::RemoveEntFromHateList(Mob *in_entity) return is_found; } -void HateList::DoFactionHits(int64 npc_faction_level_id) { - if (npc_faction_level_id <= 0) +// so if faction_id and faction_value are set, we do RewardFaction, otherwise old stuff +void HateList::DoFactionHits(int64 npc_faction_level_id, int32 faction_id, int32 faction_value) { + if (npc_faction_level_id <= 0 && faction_id <= 0 && faction_value == 0) return; auto iterator = list.begin(); while (iterator != list.end()) @@ -270,8 +271,13 @@ void HateList::DoFactionHits(int64 npc_faction_level_id) { else client = nullptr; - if (client) - client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity()); + if (client) { + if (faction_id != 0 && faction_value != 0) { + client->RewardFaction(faction_id, faction_value); + } else { + client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity()); + } + } ++iterator; } } @@ -377,19 +383,10 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip, bool skip_mezzed int64 current_hate = cur->stored_hate_amount; -#ifdef BOTS if (cur->entity_on_hatelist->IsClient() || cur->entity_on_hatelist->IsBot()){ - if (cur->entity_on_hatelist->IsClient() && cur->entity_on_hatelist->CastToClient()->IsSitting()){ aggro_mod += RuleI(Aggro, SittingAggroMod); } -#else - if (cur->entity_on_hatelist->IsClient()){ - - if (cur->entity_on_hatelist->CastToClient()->IsSitting()){ - aggro_mod += RuleI(Aggro, SittingAggroMod); - } -#endif if (center){ if (center->GetTarget() == cur->entity_on_hatelist) @@ -439,14 +436,12 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip, bool skip_mezzed if (top_client_type_in_range != nullptr && top_hate != nullptr) { bool isTopClientType = top_hate->IsClient(); -#ifdef BOTS if (!isTopClientType) { if (top_hate->IsBot()) { isTopClientType = true; top_client_type_in_range = top_hate; } } -#endif //BOTS if (!isTopClientType) { if (top_hate->IsMerc()) { @@ -844,20 +839,6 @@ void HateList::RemoveStaleEntries(int time_ms, float dist) } } -std::list HateList::GetHateListByDistance(int distance) -{ - std::list hate_list; - int squared_distance = (distance * distance); - for (auto hate_iterator : list) { - auto hate_entry = hate_iterator->entity_on_hatelist; - if (distance == 0 || (distance > 0 && DistanceSquaredNoZ(hate_owner->GetPosition(), hate_entry->GetPosition()) <= squared_distance)) { - hate_list.push_back(hate_iterator); - } - } - return hate_list; -} - -#ifdef BOTS Bot* HateList::GetRandomBotOnHateList(bool skip_mezzed) { int count = list.size(); @@ -906,7 +887,6 @@ Bot* HateList::GetRandomBotOnHateList(bool skip_mezzed) return nullptr; } -#endif Client* HateList::GetRandomClientOnHateList(bool skip_mezzed) { @@ -1005,3 +985,56 @@ NPC* HateList::GetRandomNPCOnHateList(bool skip_mezzed) return nullptr; } + +void HateList::DamageHateList(int64 damage, uint32 distance, EntityFilterType filter_type, bool is_percentage) +{ + if (damage <= 0) { + return; + } + + const auto& l = GetFilteredHateList(filter_type, distance); + for (const auto& h : l) { + auto e = h->entity_on_hatelist; + if (is_percentage) { + const auto damage_percentage = EQ::Clamp(damage, static_cast(1), static_cast(100)); + const auto total_damage = (e->GetMaxHP() / 100) * damage_percentage; + e->Damage(hate_owner, total_damage, SPELL_UNKNOWN, EQ::skills::SkillEagleStrike); + } else { + e->Damage(hate_owner, damage, SPELL_UNKNOWN, EQ::skills::SkillEagleStrike); + } + } +} + +std::list HateList::GetFilteredHateList(EntityFilterType filter_type, uint32 distance) +{ + std::list l; + const auto squared_distance = (distance * distance); + for (auto h : list) { + auto e = h->entity_on_hatelist; + if (!e) { + continue; + } + + if ( + distance && + DistanceSquaredNoZ( + hate_owner->GetPosition(), + e->GetPosition() + ) > squared_distance + ) { + continue; + } + + if ( + (filter_type == EntityFilterType::Bots && !e->IsBot()) || + (filter_type == EntityFilterType::Clients && !e->IsClient()) || + (filter_type == EntityFilterType::NPCs && !e->IsNPC()) + ) { + continue; + } + + l.push_back(h); + } + + return l; +} diff --git a/zone/hate_list.h b/zone/hate_list.h index a6a4f93e4..9af5d27b0 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -19,6 +19,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef HATELIST_H #define HATELIST_H +#include "../common/emu_constants.h" + class Client; class Group; class Mob; @@ -47,9 +49,7 @@ public: Mob *GetEscapingEntOnHateList(); // returns first eligble entity Mob *GetEscapingEntOnHateList(Mob *center, float range = 0.0f, bool first = false); -#ifdef BOTS Bot* GetRandomBotOnHateList(bool skip_mezzed = false); -#endif Client *GetRandomClientOnHateList(bool skip_mezzed = false); NPC *GetRandomNPCOnHateList(bool skip_mezzed = false); @@ -64,7 +64,18 @@ public: int64 GetEntHateAmount(Mob *ent, bool in_damage = false); std::list &GetHateList() { return list; } - std::list GetHateListByDistance(int distance = 0); + + std::list GetFilteredHateList( + EntityFilterType filter_type = EntityFilterType::All, + uint32 distance = 0 + ); + + void DamageHateList( + int64 damage, + uint32 distance = 0, + EntityFilterType filter_type = EntityFilterType::All, + bool is_percentage = false + ); void AddEntToHateList( Mob *ent, @@ -73,7 +84,7 @@ public: bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true ); - void DoFactionHits(int64 npc_faction_level_id); + void DoFactionHits(int64 npc_faction_level_id, int32 faction_id, int32 faction_value); void IsEntityInFrenzyMode(); void PrintHateListToClient(Client *c); void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage); diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index 3de331623..3ca89b67f 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -16,8 +16,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef BOTS - #include "bot.h" #define SAFE_HP_RATIO_CLOTH 95.0f @@ -122,7 +120,7 @@ bool HealRotation::RemoveMemberFromPool(Bot* hr_member) { if (!hr_member) return true; - + for (auto member_iter : m_member_pool) { if (member_iter != hr_member) continue; @@ -145,7 +143,7 @@ bool HealRotation::RemoveTargetFromPool(Mob* hr_target) for (auto target_iter : m_target_pool) { if (target_iter != hr_target) continue; - + if (m_hot_target == hr_target) { m_hot_target = nullptr; m_hot_active = false; @@ -168,9 +166,9 @@ bool HealRotation::ClearMemberPool() m_cycle_pool.clear(); m_casting_target_poke = false; m_active_heal_target = false; - + if (!ClearTargetPool()) - LogError("HealRotation::ClearTargetPool() failed to clear m_target_pool (size: [{}])", m_target_pool.size()); + LogError("failed to clear m_target_pool (size: [{}])", m_target_pool.size()); auto clear_list = const_cast&>(m_member_pool); for (auto member_iter : clear_list) @@ -184,7 +182,7 @@ bool HealRotation::ClearTargetPool() m_hot_target = nullptr; m_hot_active = false; m_is_active = false; - + auto clear_list = const_cast&>(m_target_pool); for (auto target_iter : clear_list) target_iter->LeaveHealRotationTargetPool(); @@ -251,7 +249,7 @@ Bot* HealRotation::CastingMember() { if (!m_is_active && !m_hot_active) return nullptr; - + if (m_cycle_pool.empty()) { cycle_refresh(); @@ -266,7 +264,7 @@ bool HealRotation::PokeCastingTarget() { if (m_hot_target && m_hot_active) return true; - + if (!m_is_active) return false; @@ -295,7 +293,7 @@ Mob* HealRotation::CastingTarget() { if (m_hot_target && m_hot_active) return m_hot_target; - + if (!m_is_active) return nullptr; if (!m_active_heal_target) @@ -549,7 +547,7 @@ void HealRotation::ResetArmorTypeHPLimits() m_safe_hp_ratio[ARMOR_TYPE_LEATHER] = SAFE_HP_RATIO_LEATHER; m_safe_hp_ratio[ARMOR_TYPE_CHAIN] = SAFE_HP_RATIO_CHAIN; m_safe_hp_ratio[ARMOR_TYPE_PLATE] = SAFE_HP_RATIO_PLATE; - + m_critical_hp_ratio[ARMOR_TYPE_UNKNOWN] = CRITICAL_HP_RATIO_BASE; m_critical_hp_ratio[ARMOR_TYPE_CLOTH] = CRITICAL_HP_RATIO_CLOTH; m_critical_hp_ratio[ARMOR_TYPE_LEATHER] = CRITICAL_HP_RATIO_LEATHER; @@ -561,7 +559,7 @@ bool HealRotation::valid_state() { m_member_pool.remove(nullptr); m_member_pool.remove_if([](Mob* l) {return (!IsHealRotationMemberClass(l->GetClass())); }); - + cycle_refresh(); if (m_member_pool.empty() && !m_consumed) { // Consumes HealRotation at this point @@ -578,7 +576,7 @@ void HealRotation::cycle_refresh() m_cycle_pool.clear(); if (m_member_pool.empty()) return; - + m_cycle_pool = m_member_pool; m_is_active = true; @@ -654,7 +652,7 @@ void HealRotation::bias_targets() m_active_heal_target = false; return; } - + // attempt to clear invalid target pool entries m_target_pool.remove(nullptr); m_target_pool.remove_if([](Mob* l) { @@ -798,7 +796,7 @@ void HealRotation::bias_targets() }); if (healable_target(true, true)) break; - + sort_type = 106; m_target_pool.sort([](Mob* l, Mob* r) { if (GT_ALIVE(l, r)) @@ -960,5 +958,3 @@ bool IsHealRotationTargetMobType(Mob* target_mob) return true; } - -#endif // BOTS diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index 19a3f8311..888e45edb 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -20,8 +20,6 @@ #ifndef HEAL_ROTATION_H #define HEAL_ROTATION_H -#ifdef BOTS - #include "mob.h" #define CASTING_CYCLE_MINIMUM_INTERVAL 1000 @@ -161,5 +159,3 @@ bool IsHealRotationMemberClass(uint8 class_id); bool IsHealRotationTargetMobType(Mob* target_mob); #endif - -#endif // BOTS diff --git a/zone/horse.cpp b/zone/horse.cpp index a31c58901..43c04202f 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -19,7 +19,7 @@ #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/linked_list.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "entity.h" @@ -174,6 +174,7 @@ void Client::SetHorseId(uint16 horseid_in) { void Mob::CreateHorseSpawnPacket(EQApplicationPacket* app, const char* ownername, uint16 ownerid, Mob* ForWho) { app->SetOpcode(OP_NewSpawn); + safe_delete_array(app->pBuffer); app->pBuffer = new uchar[sizeof(NewSpawn_Struct)]; app->size = sizeof(NewSpawn_Struct); memset(app->pBuffer, 0, sizeof(NewSpawn_Struct)); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 12b87ffab..397bc3863 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -19,11 +19,13 @@ #include "../common/global_define.h" #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "quest_parser_collection.h" #include "worldserver.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" + +#include "bot.h" extern WorldServer worldserver; @@ -170,7 +172,7 @@ bool Client::CheckLoreConflict(const EQ::ItemData* item) if (!item->LoreFlag) { return false; } if (item->LoreGroup == 0) { return false; } - if (item->LoreGroup == 0xFFFFFFFF) // Standard lore items; look everywhere except the shared bank, return the result + if (item->LoreGroup == -1) // Standard lore items; look everywhere except the shared bank, return the result return (m_inv.HasItem(item->ID, 0, ~invWhereSharedBank) != INVALID_INDEX); // If the item has a lore group, we check for other items with the same group and return the result @@ -814,8 +816,7 @@ void Client::DropItem(int16 slot_id, bool recurse) LogInventory("[{}] (char_id: [{}]) Attempting to drop item from slot [{}] on the ground", GetCleanName(), CharacterID(), slot_id); - if(GetInv().CheckNoDrop(slot_id, recurse) && RuleI(World, FVNoDropFlag) == 0 || - RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) + if(GetInv().CheckNoDrop(slot_id, recurse) && !CanTradeFVNoDropItem()) { auto invalid_drop = m_inv.GetItem(slot_id); if (!invalid_drop) { @@ -1072,7 +1073,7 @@ void Client::SendCursorBuffer() if (test_item == nullptr) { return; } bool lore_pass = true; - if (test_item->LoreGroup == 0xFFFFFFFF) { + if (test_item->LoreGroup == -1) { lore_pass = (m_inv.HasItem(test_item->ID, 0, ~(invWhereSharedBank | invWhereCursor)) == INVALID_INDEX); } else if (test_item->LoreGroup != 0) { @@ -1799,7 +1800,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (!test_item->LoreFlag) { return true; } bool lore_pass = true; - if (test_item->LoreGroup == 0xFFFFFFFF) { + if (test_item->LoreGroup == -1) { lore_pass = (m_inv.HasItem(test_item->ID, 0, ~(invWhereSharedBank | invWhereCursor)) == INVALID_INDEX); } else if (test_item->LoreGroup != 0) { @@ -1960,10 +1961,10 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Check for No Drop Hacks Mob* with = trade->With(); - if (((with && with->IsClient() && dst_slot_id >= EQ::invslot::TRADE_BEGIN && dst_slot_id <= EQ::invslot::TRADE_END) || + if (((with && with->IsClient() && !with->CastToClient()->IsBecomeNPC() && dst_slot_id >= EQ::invslot::TRADE_BEGIN && dst_slot_id <= EQ::invslot::TRADE_END) || (dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= EQ::invbag::SHARED_BANK_BAGS_END)) && GetInv().CheckNoDrop(src_slot_id) - && RuleI(World, FVNoDropFlag) == 0 || RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) { + && !CanTradeFVNoDropItem()) { auto ndh_inst = m_inv[src_slot_id]; std::string ndh_item_data; if (ndh_inst == nullptr) { @@ -3685,7 +3686,6 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool if (log) { LogError("Target interrogate inventory flag: [{}]", (GetInterrogateInvState() ? "TRUE" : "FALSE")); - LogDebug("[CLIENT] Client::InterrogateInventory() -- End"); } if (!silent) { requester->Message(Chat::Default, "Target interrogation flag: %s", (GetInterrogateInvState() ? "TRUE" : "FALSE")); @@ -3868,340 +3868,767 @@ std::string EQ::InventoryProfile::GetCustomItemData(int16 slot_id, std::string i return ""; } -int EQ::InventoryProfile::GetItemStatValue(uint32 item_id, const char* identifier) { - const EQ::ItemInstance* inst = database.CreateItem(item_id); - if (!inst) +const int EQ::InventoryProfile::GetItemStatValue(uint32 item_id, std::string identifier) { + if (identifier.empty()) { return 0; - - const EQ::ItemData* item = inst->GetItem(); - if (!item) - return 0; - - if (!identifier) - return 0; - - int32 stat = 0; - - std::string id = identifier; - for(uint32 i = 0; i < id.length(); ++i) { - id[i] = tolower(id[i]); } - if (id == "itemclass") - stat = int32(item->ItemClass); - if (id == "id") - stat = int32(item->ID); - if (id == "idfile") - stat = atoi(&item->IDFile[2]); - if (id == "weight") - stat = int32(item->Weight); - if (id == "norent") - stat = int32(item->NoRent); - if (id == "nodrop") - stat = int32(item->NoDrop); - if (id == "size") - stat = int32(item->Size); - if (id == "slots") - stat = int32(item->Slots); - if (id == "price") - stat = int32(item->Price); - if (id == "icon") - stat = int32(item->Icon); - if (id == "loregroup") - stat = int32(item->LoreGroup); - if (id == "loreflag") - stat = int32(item->LoreFlag); - if (id == "pendingloreflag") - stat = int32(item->PendingLoreFlag); - if (id == "artifactflag") - stat = int32(item->ArtifactFlag); - if (id == "summonedflag") - stat = int32(item->SummonedFlag); - if (id == "fvnodrop") - stat = int32(item->FVNoDrop); - if (id == "favor") - stat = int32(item->Favor); - if (id == "guildfavor") - stat = int32(item->GuildFavor); - if (id == "pointtype") - stat = int32(item->PointType); - if (id == "bagtype") - stat = int32(item->BagType); - if (id == "bagslots") - stat = int32(item->BagSlots); - if (id == "bagsize") - stat = int32(item->BagSize); - if (id == "bagwr") - stat = int32(item->BagWR); - if (id == "benefitflag") - stat = int32(item->BenefitFlag); - if (id == "tradeskills") - stat = int32(item->Tradeskills); - if (id == "cr") - stat = int32(item->CR); - if (id == "dr") - stat = int32(item->DR); - if (id == "pr") - stat = int32(item->PR); - if (id == "mr") - stat = int32(item->MR); - if (id == "fr") - stat = int32(item->FR); - if (id == "astr") - stat = int32(item->AStr); - if (id == "asta") - stat = int32(item->ASta); - if (id == "aagi") - stat = int32(item->AAgi); - if (id == "adex") - stat = int32(item->ADex); - if (id == "acha") - stat = int32(item->ACha); - if (id == "aint") - stat = int32(item->AInt); - if (id == "awis") - stat = int32(item->AWis); - if (id == "hp") - stat = int32(item->HP); - if (id == "mana") - stat = int32(item->Mana); - if (id == "ac") - stat = int32(item->AC); - if (id == "deity") - stat = int32(item->Deity); - if (id == "skillmodvalue") - stat = int32(item->SkillModValue); - if (id == "skillmodtype") - stat = int32(item->SkillModType); - if (id == "banedmgrace") - stat = int32(item->BaneDmgRace); - if (id == "banedmgamt") - stat = int32(item->BaneDmgAmt); - if (id == "banedmgbody") - stat = int32(item->BaneDmgBody); - if (id == "magic") - stat = int32(item->Magic); - if (id == "casttime_") - stat = int32(item->CastTime_); - if (id == "reqlevel") - stat = int32(item->ReqLevel); - if (id == "bardtype") - stat = int32(item->BardType); - if (id == "bardvalue") - stat = int32(item->BardValue); - if (id == "light") - stat = int32(item->Light); - if (id == "delay") - stat = int32(item->Delay); - if (id == "reclevel") - stat = int32(item->RecLevel); - if (id == "recskill") - stat = int32(item->RecSkill); - if (id == "elemdmgtype") - stat = int32(item->ElemDmgType); - if (id == "elemdmgamt") - stat = int32(item->ElemDmgAmt); - if (id == "range") - stat = int32(item->Range); - if (id == "damage") - stat = int32(item->Damage); - if (id == "color") - stat = int32(item->Color); - if (id == "classes") - stat = int32(item->Classes); - if (id == "races") - stat = int32(item->Races); - if (id == "maxcharges") - stat = int32(item->MaxCharges); - if (id == "itemtype") - stat = int32(item->ItemType); - if (id == "material") - stat = int32(item->Material); - if (id == "casttime") - stat = int32(item->CastTime); - if (id == "elitematerial") - stat = int32(item->EliteMaterial); - if (id == "herosforgemodel") - stat = int32(item->HerosForgeModel); - if (id == "procrate") - stat = int32(item->ProcRate); - if (id == "combateffects") - stat = int32(item->CombatEffects); - if (id == "shielding") - stat = int32(item->Shielding); - if (id == "stunresist") - stat = int32(item->StunResist); - if (id == "strikethrough") - stat = int32(item->StrikeThrough); - if (id == "extradmgskill") - stat = int32(item->ExtraDmgSkill); - if (id == "extradmgamt") - stat = int32(item->ExtraDmgAmt); - if (id == "spellshield") - stat = int32(item->SpellShield); - if (id == "avoidance") - stat = int32(item->Avoidance); - if (id == "accuracy") - stat = int32(item->Accuracy); - if (id == "charmfileid") - stat = int32(item->CharmFileID); - if (id == "factionmod1") - stat = int32(item->FactionMod1); - if (id == "factionmod2") - stat = int32(item->FactionMod2); - if (id == "factionmod3") - stat = int32(item->FactionMod3); - if (id == "factionmod4") - stat = int32(item->FactionMod4); - if (id == "factionamt1") - stat = int32(item->FactionAmt1); - if (id == "factionamt2") - stat = int32(item->FactionAmt2); - if (id == "factionamt3") - stat = int32(item->FactionAmt3); - if (id == "factionamt4") - stat = int32(item->FactionAmt4); - if (id == "augtype") - stat = int32(item->AugType); - if (id == "ldontheme") - stat = int32(item->LDoNTheme); - if (id == "ldonprice") - stat = int32(item->LDoNPrice); - if (id == "ldonsold") - stat = int32(item->LDoNSold); - if (id == "banedmgraceamt") - stat = int32(item->BaneDmgRaceAmt); - if (id == "augrestrict") - stat = int32(item->AugRestrict); - if (id == "endur") - stat = int32(item->Endur); - if (id == "dotshielding") - stat = int32(item->DotShielding); - if (id == "attack") - stat = int32(item->Attack); - if (id == "regen") - stat = int32(item->Regen); - if (id == "manaregen") - stat = int32(item->ManaRegen); - if (id == "enduranceregen") - stat = int32(item->EnduranceRegen); - if (id == "haste") - stat = int32(item->Haste); - if (id == "damageshield") - stat = int32(item->DamageShield); - if (id == "recastdelay") - stat = int32(item->RecastDelay); - if (id == "recasttype") - stat = int32(item->RecastType); - if (id == "augdistiller") - stat = int32(item->AugDistiller); - if (id == "attuneable") - stat = int32(item->Attuneable); - if (id == "nopet") - stat = int32(item->NoPet); - if (id == "potionbelt") - stat = int32(item->PotionBelt); - if (id == "stackable") - stat = int32(item->Stackable); - if (id == "notransfer") - stat = int32(item->NoTransfer); - if (id == "questitemflag") - stat = int32(item->QuestItemFlag); - if (id == "stacksize") - stat = int32(item->StackSize); - if (id == "potionbeltslots") - stat = int32(item->PotionBeltSlots); - if (id == "book") - stat = int32(item->Book); - if (id == "booktype") - stat = int32(item->BookType); - if (id == "svcorruption") - stat = int32(item->SVCorruption); - if (id == "purity") - stat = int32(item->Purity); - if (id == "backstabdmg") - stat = int32(item->BackstabDmg); - if (id == "dsmitigation") - stat = int32(item->DSMitigation); - if (id == "heroicstr") - stat = int32(item->HeroicStr); - if (id == "heroicint") - stat = int32(item->HeroicInt); - if (id == "heroicwis") - stat = int32(item->HeroicWis); - if (id == "heroicagi") - stat = int32(item->HeroicAgi); - if (id == "heroicdex") - stat = int32(item->HeroicDex); - if (id == "heroicsta") - stat = int32(item->HeroicSta); - if (id == "heroiccha") - stat = int32(item->HeroicCha); - if (id == "heroicmr") - stat = int32(item->HeroicMR); - if (id == "heroicfr") - stat = int32(item->HeroicFR); - if (id == "heroiccr") - stat = int32(item->HeroicCR); - if (id == "heroicdr") - stat = int32(item->HeroicDR); - if (id == "heroicpr") - stat = int32(item->HeroicPR); - if (id == "heroicsvcorrup") - stat = int32(item->HeroicSVCorrup); - if (id == "healamt") - stat = int32(item->HealAmt); - if (id == "spelldmg") - stat = int32(item->SpellDmg); - if (id == "ldonsellbackrate") - stat = int32(item->LDoNSellBackRate); - if (id == "scriptfileid") - stat = int32(item->ScriptFileID); - if (id == "expendablearrow") - stat = int32(item->ExpendableArrow); - if (id == "clairvoyance") - stat = int32(item->Clairvoyance); - // Begin Effects - if (id == "clickeffect") - stat = int32(item->Click.Effect); - if (id == "clicktype") - stat = int32(item->Click.Type); - if (id == "clicklevel") - stat = int32(item->Click.Level); - if (id == "clicklevel2") - stat = int32(item->Click.Level2); - if (id == "proceffect") - stat = int32(item->Proc.Effect); - if (id == "proctype") - stat = int32(item->Proc.Type); - if (id == "proclevel") - stat = int32(item->Proc.Level); - if (id == "proclevel2") - stat = int32(item->Proc.Level2); - if (id == "worneffect") - stat = int32(item->Worn.Effect); - if (id == "worntype") - stat = int32(item->Worn.Type); - if (id == "wornlevel") - stat = int32(item->Worn.Level); - if (id == "wornlevel2") - stat = int32(item->Worn.Level2); - if (id == "focuseffect") - stat = int32(item->Focus.Effect); - if (id == "focustype") - stat = int32(item->Focus.Type); - if (id == "focuslevel") - stat = int32(item->Focus.Level); - if (id == "focuslevel2") - stat = int32(item->Focus.Level2); - if (id == "scrolleffect") - stat = int32(item->Scroll.Effect); - if (id == "scrolltype") - stat = int32(item->Scroll.Type); - if (id == "scrolllevel") - stat = int32(item->Scroll.Level); - if (id == "scrolllevel2") - stat = int32(item->Scroll.Level2); + + const auto* inst = database.CreateItem(item_id); + if (!inst) { + return 0; + } + + const auto* item = inst->GetItem(); + if (!item) { + return 0; + } + + int stat = 0; + + if (Strings::EqualFold(identifier, "itemclass")) { + stat = static_cast(item->ItemClass); + } + + if (Strings::EqualFold(identifier, "id")) { + stat = static_cast(item->ID); + } + + if (Strings::EqualFold(identifier, "idfile")) { + stat = Strings::IsNumber(&item->IDFile[2]) ? std::stoi(&item->IDFile[2]) : 0; + } + + if (Strings::EqualFold(identifier, "weight")) { + stat = static_cast(item->Weight); + } + + if (Strings::EqualFold(identifier, "norent")) { + stat = static_cast(item->NoRent); + } + + if (Strings::EqualFold(identifier, "nodrop")) { + stat = static_cast(item->NoDrop); + } + + if (Strings::EqualFold(identifier, "size")) { + stat = static_cast(item->Size); + } + + if (Strings::EqualFold(identifier, "slots")) { + stat = static_cast(item->Slots); + } + + if (Strings::EqualFold(identifier, "price")) { + stat = static_cast(item->Price); + } + + if (Strings::EqualFold(identifier, "icon")) { + stat = static_cast(item->Icon); + } + + if (Strings::EqualFold(identifier, "loregroup")) { + stat = static_cast(item->LoreGroup); + } + + if (Strings::EqualFold(identifier, "loreflag")) { + stat = static_cast(item->LoreFlag); + } + + if (Strings::EqualFold(identifier, "pendingloreflag")) { + stat = static_cast(item->PendingLoreFlag); + } + + if (Strings::EqualFold(identifier, "artifactflag")) { + stat = static_cast(item->ArtifactFlag); + } + + if (Strings::EqualFold(identifier, "summonedflag")) { + stat = static_cast(item->SummonedFlag); + } + + if (Strings::EqualFold(identifier, "fvnodrop")) { + stat = static_cast(item->FVNoDrop); + } + + if (Strings::EqualFold(identifier, "favor")) { + stat = static_cast(item->Favor); + } + + if (Strings::EqualFold(identifier, "guildfavor")) { + stat = static_cast(item->GuildFavor); + } + + if (Strings::EqualFold(identifier, "pointtype")) { + stat = static_cast(item->PointType); + } + + if (Strings::EqualFold(identifier, "bagtype")) { + stat = static_cast(item->BagType); + } + + if (Strings::EqualFold(identifier, "bagslots")) { + stat = static_cast(item->BagSlots); + } + + if (Strings::EqualFold(identifier, "bagsize")) { + stat = static_cast(item->BagSize); + } + + if (Strings::EqualFold(identifier, "bagwr")) { + stat = static_cast(item->BagWR); + } + + if (Strings::EqualFold(identifier, "benefitflag")) { + stat = static_cast(item->BenefitFlag); + } + + if (Strings::EqualFold(identifier, "tradeskills")) { + stat = static_cast(item->Tradeskills); + } + + if (Strings::EqualFold(identifier, "cr")) { + stat = static_cast(item->CR); + } + + if (Strings::EqualFold(identifier, "dr")) { + stat = static_cast(item->DR); + } + + if (Strings::EqualFold(identifier, "pr")) { + stat = static_cast(item->PR); + } + + if (Strings::EqualFold(identifier, "mr")) { + stat = static_cast(item->MR); + } + + if (Strings::EqualFold(identifier, "fr")) { + stat = static_cast(item->FR); + } + + if (Strings::EqualFold(identifier, "astr")) { + stat = static_cast(item->AStr); + } + + if (Strings::EqualFold(identifier, "asta")) { + stat = static_cast(item->ASta); + } + + if (Strings::EqualFold(identifier, "aagi")) { + stat = static_cast(item->AAgi); + } + + if (Strings::EqualFold(identifier, "adex")) { + stat = static_cast(item->ADex); + } + + if (Strings::EqualFold(identifier, "acha")) { + stat = static_cast(item->ACha); + } + + if (Strings::EqualFold(identifier, "aint")) { + stat = static_cast(item->AInt); + } + + if (Strings::EqualFold(identifier, "awis")) { + stat = static_cast(item->AWis); + } + + if (Strings::EqualFold(identifier, "hp")) { + stat = static_cast(item->HP); + } + + if (Strings::EqualFold(identifier, "mana")) { + stat = static_cast(item->Mana); + } + + if (Strings::EqualFold(identifier, "ac")) { + stat = static_cast(item->AC); + } + + if (Strings::EqualFold(identifier, "deity")) { + stat = static_cast(item->Deity); + } + + if (Strings::EqualFold(identifier, "skillmodvalue")) { + stat = static_cast(item->SkillModValue); + } + + if (Strings::EqualFold(identifier, "skillmodtype")) { + stat = static_cast(item->SkillModType); + } + + if (Strings::EqualFold(identifier, "banedmgrace")) { + stat = static_cast(item->BaneDmgRace); + } + + if (Strings::EqualFold(identifier, "banedmgamt")) { + stat = static_cast(item->BaneDmgAmt); + } + + if (Strings::EqualFold(identifier, "banedmgbody")) { + stat = static_cast(item->BaneDmgBody); + } + + if (Strings::EqualFold(identifier, "magic")) { + stat = static_cast(item->Magic); + } + + if (Strings::EqualFold(identifier, "casttime_")) { + stat = static_cast(item->CastTime_); + } + + if (Strings::EqualFold(identifier, "reqlevel")) { + stat = static_cast(item->ReqLevel); + } + + if (Strings::EqualFold(identifier, "bardtype")) { + stat = static_cast(item->BardType); + } + + if (Strings::EqualFold(identifier, "bardvalue")) { + stat = static_cast(item->BardValue); + } + + if (Strings::EqualFold(identifier, "light")) { + stat = static_cast(item->Light); + } + + if (Strings::EqualFold(identifier, "delay")) { + stat = static_cast(item->Delay); + } + + if (Strings::EqualFold(identifier, "reclevel")) { + stat = static_cast(item->RecLevel); + } + + if (Strings::EqualFold(identifier, "recskill")) { + stat = static_cast(item->RecSkill); + } + + if (Strings::EqualFold(identifier, "elemdmgtype")) { + stat = static_cast(item->ElemDmgType); + } + + if (Strings::EqualFold(identifier, "elemdmgamt")) { + stat = static_cast(item->ElemDmgAmt); + } + + if (Strings::EqualFold(identifier, "range")) { + stat = static_cast(item->Range); + } + + if (Strings::EqualFold(identifier, "damage")) { + stat = static_cast(item->Damage); + } + + if (Strings::EqualFold(identifier, "color")) { + stat = static_cast(item->Color); + } + + if (Strings::EqualFold(identifier, "classes")) { + stat = static_cast(item->Classes); + } + + if (Strings::EqualFold(identifier, "races")) { + stat = static_cast(item->Races); + } + + if (Strings::EqualFold(identifier, "maxcharges")) { + stat = static_cast(item->MaxCharges); + } + + if (Strings::EqualFold(identifier, "itemtype")) { + stat = static_cast(item->ItemType); + } + + if (Strings::EqualFold(identifier, "material")) { + stat = static_cast(item->Material); + } + + if (Strings::EqualFold(identifier, "casttime")) { + stat = static_cast(item->CastTime); + } + + if (Strings::EqualFold(identifier, "elitematerial")) { + stat = static_cast(item->EliteMaterial); + } + + if (Strings::EqualFold(identifier, "herosforgemodel")) { + stat = static_cast(item->HerosForgeModel); + } + + if (Strings::EqualFold(identifier, "procrate")) { + stat = static_cast(item->ProcRate); + } + + if (Strings::EqualFold(identifier, "combateffects")) { + stat = static_cast(item->CombatEffects); + } + + if (Strings::EqualFold(identifier, "shielding")) { + stat = static_cast(item->Shielding); + } + + if (Strings::EqualFold(identifier, "stunresist")) { + stat = static_cast(item->StunResist); + } + + if (Strings::EqualFold(identifier, "strikethrough")) { + stat = static_cast(item->StrikeThrough); + } + + if (Strings::EqualFold(identifier, "extradmgskill")) { + stat = static_cast(item->ExtraDmgSkill); + } + + if (Strings::EqualFold(identifier, "extradmgamt")) { + stat = static_cast(item->ExtraDmgAmt); + } + + if (Strings::EqualFold(identifier, "spellshield")) { + stat = static_cast(item->SpellShield); + } + + if (Strings::EqualFold(identifier, "avoidance")) { + stat = static_cast(item->Avoidance); + } + + if (Strings::EqualFold(identifier, "accuracy")) { + stat = static_cast(item->Accuracy); + } + + if (Strings::EqualFold(identifier, "charmfileid")) { + stat = static_cast(item->CharmFileID); + } + + if (Strings::EqualFold(identifier, "factionmod1")) { + stat = static_cast(item->FactionMod1); + } + + if (Strings::EqualFold(identifier, "factionmod2")) { + stat = static_cast(item->FactionMod2); + } + + if (Strings::EqualFold(identifier, "factionmod3")) { + stat = static_cast(item->FactionMod3); + } + + if (Strings::EqualFold(identifier, "factionmod4")) { + stat = static_cast(item->FactionMod4); + } + + if (Strings::EqualFold(identifier, "factionamt1")) { + stat = static_cast(item->FactionAmt1); + } + + if (Strings::EqualFold(identifier, "factionamt2")) { + stat = static_cast(item->FactionAmt2); + } + + if (Strings::EqualFold(identifier, "factionamt3")) { + stat = static_cast(item->FactionAmt3); + } + + if (Strings::EqualFold(identifier, "factionamt4")) { + stat = static_cast(item->FactionAmt4); + } + + if (Strings::EqualFold(identifier, "augtype")) { + stat = static_cast(item->AugType); + } + + if (Strings::EqualFold(identifier, "ldontheme")) { + stat = static_cast(item->LDoNTheme); + } + + if (Strings::EqualFold(identifier, "ldonprice")) { + stat = static_cast(item->LDoNPrice); + } + + if (Strings::EqualFold(identifier, "ldonsold")) { + stat = static_cast(item->LDoNSold); + } + + if (Strings::EqualFold(identifier, "banedmgraceamt")) { + stat = static_cast(item->BaneDmgRaceAmt); + } + + if (Strings::EqualFold(identifier, "augrestrict")) { + stat = static_cast(item->AugRestrict); + } + + if (Strings::EqualFold(identifier, "endur")) { + stat = static_cast(item->Endur); + } + + if (Strings::EqualFold(identifier, "dotshielding")) { + stat = static_cast(item->DotShielding); + } + + if (Strings::EqualFold(identifier, "attack")) { + stat = static_cast(item->Attack); + } + + if (Strings::EqualFold(identifier, "regen")) { + stat = static_cast(item->Regen); + } + + if (Strings::EqualFold(identifier, "manaregen")) { + stat = static_cast(item->ManaRegen); + } + + if (Strings::EqualFold(identifier, "enduranceregen")) { + stat = static_cast(item->EnduranceRegen); + } + + if (Strings::EqualFold(identifier, "haste")) { + stat = static_cast(item->Haste); + } + + if (Strings::EqualFold(identifier, "damageshield")) { + stat = static_cast(item->DamageShield); + } + + if (Strings::EqualFold(identifier, "recastdelay")) { + stat = static_cast(item->RecastDelay); + } + + if (Strings::EqualFold(identifier, "recasttype")) { + stat = static_cast(item->RecastType); + } + + if (Strings::EqualFold(identifier, "augdistiller")) { + stat = static_cast(item->AugDistiller); + } + + if (Strings::EqualFold(identifier, "attuneable")) { + stat = static_cast(item->Attuneable); + } + + if (Strings::EqualFold(identifier, "nopet")) { + stat = static_cast(item->NoPet); + } + + if (Strings::EqualFold(identifier, "potionbelt")) { + stat = static_cast(item->PotionBelt); + } + + if (Strings::EqualFold(identifier, "stackable")) { + stat = static_cast(item->Stackable); + } + + if (Strings::EqualFold(identifier, "notransfer")) { + stat = static_cast(item->NoTransfer); + } + + if (Strings::EqualFold(identifier, "questitemflag")) { + stat = static_cast(item->QuestItemFlag); + } + + if (Strings::EqualFold(identifier, "stacksize")) { + stat = static_cast(item->StackSize); + } + + if (Strings::EqualFold(identifier, "potionbeltslots")) { + stat = static_cast(item->PotionBeltSlots); + } + + if (Strings::EqualFold(identifier, "book")) { + stat = static_cast(item->Book); + } + + if (Strings::EqualFold(identifier, "booktype")) { + stat = static_cast(item->BookType); + } + + if (Strings::EqualFold(identifier, "svcorruption")) { + stat = static_cast(item->SVCorruption); + } + + if (Strings::EqualFold(identifier, "purity")) { + stat = static_cast(item->Purity); + } + + if (Strings::EqualFold(identifier, "backstabdmg")) { + stat = static_cast(item->BackstabDmg); + } + + if (Strings::EqualFold(identifier, "dsmitigation")) { + stat = static_cast(item->DSMitigation); + } + + if (Strings::EqualFold(identifier, "heroicstr")) { + stat = static_cast(item->HeroicStr); + } + + if (Strings::EqualFold(identifier, "heroicint")) { + stat = static_cast(item->HeroicInt); + } + + if (Strings::EqualFold(identifier, "heroicwis")) { + stat = static_cast(item->HeroicWis); + } + + if (Strings::EqualFold(identifier, "heroicagi")) { + stat = static_cast(item->HeroicAgi); + } + + if (Strings::EqualFold(identifier, "heroicdex")) { + stat = static_cast(item->HeroicDex); + } + + if (Strings::EqualFold(identifier, "heroicsta")) { + stat = static_cast(item->HeroicSta); + } + + if (Strings::EqualFold(identifier, "heroiccha")) { + stat = static_cast(item->HeroicCha); + } + + if (Strings::EqualFold(identifier, "heroicmr")) { + stat = static_cast(item->HeroicMR); + } + + if (Strings::EqualFold(identifier, "heroicfr")) { + stat = static_cast(item->HeroicFR); + } + + if (Strings::EqualFold(identifier, "heroiccr")) { + stat = static_cast(item->HeroicCR); + } + + if (Strings::EqualFold(identifier, "heroicdr")) { + stat = static_cast(item->HeroicDR); + } + + if (Strings::EqualFold(identifier, "heroicpr")) { + stat = static_cast(item->HeroicPR); + } + + if (Strings::EqualFold(identifier, "heroicsvcorrup")) { + stat = static_cast(item->HeroicSVCorrup); + } + + if (Strings::EqualFold(identifier, "healamt")) { + stat = static_cast(item->HealAmt); + } + + if (Strings::EqualFold(identifier, "spelldmg")) { + stat = static_cast(item->SpellDmg); + } + + if (Strings::EqualFold(identifier, "ldonsellbackrate")) { + stat = static_cast(item->LDoNSellBackRate); + } + + if (Strings::EqualFold(identifier, "scriptfileid")) { + stat = static_cast(item->ScriptFileID); + } + + if (Strings::EqualFold(identifier, "expendablearrow")) { + stat = static_cast(item->ExpendableArrow); + } + + if (Strings::EqualFold(identifier, "clairvoyance")) { + stat = static_cast(item->Clairvoyance); + } + + if (Strings::EqualFold(identifier, "clickeffect")) { + stat = static_cast(item->Click.Effect); + } + + if (Strings::EqualFold(identifier, "clicktype")) { + stat = static_cast(item->Click.Type); + } + + if (Strings::EqualFold(identifier, "clicklevel")) { + stat = static_cast(item->Click.Level); + } + + if (Strings::EqualFold(identifier, "clicklevel2")) { + stat = static_cast(item->Click.Level2); + } + + if (Strings::EqualFold(identifier, "proceffect")) { + stat = static_cast(item->Proc.Effect); + } + + if (Strings::EqualFold(identifier, "proctype")) { + stat = static_cast(item->Proc.Type); + } + + if (Strings::EqualFold(identifier, "proclevel")) { + stat = static_cast(item->Proc.Level); + } + + if (Strings::EqualFold(identifier, "proclevel2")) { + stat = static_cast(item->Proc.Level2); + } + + if (Strings::EqualFold(identifier, "worneffect")) { + stat = static_cast(item->Worn.Effect); + } + + if (Strings::EqualFold(identifier, "worntype")) { + stat = static_cast(item->Worn.Type); + } + + if (Strings::EqualFold(identifier, "wornlevel")) { + stat = static_cast(item->Worn.Level); + } + + if (Strings::EqualFold(identifier, "wornlevel2")) { + stat = static_cast(item->Worn.Level2); + } + + if (Strings::EqualFold(identifier, "focuseffect")) { + stat = static_cast(item->Focus.Effect); + } + + if (Strings::EqualFold(identifier, "focustype")) { + stat = static_cast(item->Focus.Type); + } + + if (Strings::EqualFold(identifier, "focuslevel")) { + stat = static_cast(item->Focus.Level); + } + + if (Strings::EqualFold(identifier, "focuslevel2")) { + stat = static_cast(item->Focus.Level2); + } + + if (Strings::EqualFold(identifier, "scrolleffect")) { + stat = static_cast(item->Scroll.Effect); + } + + if (Strings::EqualFold(identifier, "scrolltype")) { + stat = static_cast(item->Scroll.Type); + } + + if (Strings::EqualFold(identifier, "scrolllevel")) { + stat = static_cast(item->Scroll.Level); + } + + if (Strings::EqualFold(identifier, "scrolllevel2")) { + stat = static_cast(item->Scroll.Level2); + } + + if (Strings::EqualFold(identifier, "augslot1type")) { + stat = static_cast(item->AugSlotType[0]); + } + + if (Strings::EqualFold(identifier, "augslot2type")) { + stat = static_cast(item->AugSlotType[1]); + } + + if (Strings::EqualFold(identifier, "augslot3type")) { + stat = static_cast(item->AugSlotType[2]); + } + + if (Strings::EqualFold(identifier, "augslot4type")) { + stat = static_cast(item->AugSlotType[3]); + } + + if (Strings::EqualFold(identifier, "augslot5type")) { + stat = static_cast(item->AugSlotType[4]); + } + + if (Strings::EqualFold(identifier, "augslot6type")) { + stat = static_cast(item->AugSlotType[5]); + } + + if (Strings::EqualFold(identifier, "augslot1visible")) { + stat = static_cast(item->AugSlotVisible[0]); + } + + if (Strings::EqualFold(identifier, "augslot2visible")) { + stat = static_cast(item->AugSlotVisible[1]); + } + + if (Strings::EqualFold(identifier, "augslot3visible")) { + stat = static_cast(item->AugSlotVisible[2]); + } + + if (Strings::EqualFold(identifier, "augslot4visible")) { + stat = static_cast(item->AugSlotVisible[3]); + } + + if (Strings::EqualFold(identifier, "augslot5visible")) { + stat = static_cast(item->AugSlotVisible[4]); + } + + if (Strings::EqualFold(identifier, "augslot6visible")) { + stat = static_cast(item->AugSlotVisible[5]); + } safe_delete(inst); return stat; } + +// Returns a slot's item ID (returns INVALID_ID if not found) +int32 Bot::GetItemIDAt(int16 slot_id) { + if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { + if ((((uint64)1 << slot_id) & GetInv().GetLookup()->PossessionsBitmask) == 0) { + return INVALID_ID; + } + } + else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) { + auto temp_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); + if ((((uint64)1 << temp_slot) & GetInv().GetLookup()->PossessionsBitmask) == 0) { + return INVALID_ID; + } + } + else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) { + if ((slot_id - EQ::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank) { + return INVALID_ID; + } + } + else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { + auto temp_slot = (slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT; + if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank) { + return INVALID_ID; + } + } + + const EQ::ItemInstance* inst = m_inv[slot_id]; + if (inst) + return inst->GetItem()->ID; + + // None found + return INVALID_ID; +} + +// Returns an augment's ID that's in an item (returns INVALID_ID if not found) +// Pass in the slot ID of the item and which augslot you want to check (0-5) +int32 Bot::GetAugmentIDAt(int16 slot_id, uint8 augslot) { + if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { + if ((((uint64)1 << slot_id) & GetInv().GetLookup()->PossessionsBitmask) == 0) { + return INVALID_ID; + } + } + else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) { + auto temp_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); + if ((((uint64)1 << temp_slot) & GetInv().GetLookup()->PossessionsBitmask) == 0) { + return INVALID_ID; + } + } + else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) { + if ((slot_id - EQ::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank) { + return INVALID_ID; + } + } + else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { + auto temp_slot = (slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT; + if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank) { + return INVALID_ID; + } + } + + const EQ::ItemInstance* inst = m_inv[slot_id]; + if (inst && inst->GetAugmentItemID(augslot)) { + return inst->GetAugmentItemID(augslot); + } + + // None found + return INVALID_ID; +} diff --git a/zone/loottables.cpp b/zone/loottables.cpp index d83557a93..7afe959ff 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -26,7 +26,7 @@ #include "mob.h" #include "npc.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "global_loot_manager.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/say_link.h" @@ -39,7 +39,7 @@ #endif // Queries the loottable: adds item & coin to the npc -void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) { +void ZoneDatabase::AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) { const LootTable_Struct* lts = nullptr; // global loot passes nullptr for these bool bGlobal = copper == nullptr && silver == nullptr && gold == nullptr && plat == nullptr; @@ -164,12 +164,21 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item droplimit = mindrop; } - float roll_t = 0.0f; - bool active_item_list = false; - for (uint32 i = 0; i < loot_drop->NumEntries; ++i) { + float roll_t = 0.0f; + float no_loot_prob = 1.0f; + bool roll_table_chance_bypass = false; + bool active_item_list = false; + + for (uint32 i = 0; i < loot_drop->NumEntries; ++i) { const EQ::ItemData *db_item = GetItem(loot_drop->Entries[i].item_id); if (db_item && npc->MeetsLootDropLevelRequirements(loot_drop->Entries[i])) { roll_t += loot_drop->Entries[i].chance; + if (loot_drop->Entries[i].chance >= 100) { + roll_table_chance_bypass = true; + } + else { + no_loot_prob *= (100 - loot_drop->Entries[i].chance) / 100.0f; + } active_item_list = true; } } @@ -183,103 +192,51 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item // The roll isn't 0-100, its 0-total and it picks the item, we're just // looping to find the lucky item, descremening otherwise. This is ok, // items with chance 60 are 6 times more likely than items chance 10. - for (int i = 0; i < mindrop; ++i) { - float roll = (float) zone->random.Real(0.0, roll_t); - for (uint32 j = 0; j < loot_drop->NumEntries; ++j) { - const EQ::ItemData *db_item = GetItem(loot_drop->Entries[j].item_id); - if (db_item) { - // if it doesn't meet the requirements do nothing - if (!npc->MeetsLootDropLevelRequirements(loot_drop->Entries[j])) - continue; + int drops = 0; - if (roll < loot_drop->Entries[j].chance) { - npc->AddLootDrop( - db_item, - item_list, - loot_drop->Entries[j] - ); - - int charges = (int) loot_drop->Entries[i].multiplier; - charges = EQ::ClampLower(charges, 1); - - for (int k = 1; k < charges; ++k) { - float c_roll = (float) zone->random.Real(0.0, 100.0); - if (c_roll <= loot_drop->Entries[i].chance) { - npc->AddLootDrop( - db_item, - item_list, - loot_drop->Entries[i] - ); - } + for (int i = 0; i < droplimit; ++i) { + if (drops < mindrop || roll_table_chance_bypass || (float) zone->random.Real(0.0, 1.0) >= no_loot_prob) { + float roll = (float) zone->random.Real(0.0, roll_t); + for (uint32 j = 0; j < loot_drop->NumEntries; ++j) { + const EQ::ItemData *db_item = GetItem(loot_drop->Entries[j].item_id); + if (db_item) { + // if it doesn't meet the requirements do nothing + if (!npc->MeetsLootDropLevelRequirements(loot_drop->Entries[j])) { + continue; } - j = loot_drop->NumEntries; - break; - } - else { - roll -= loot_drop->Entries[j].chance; - } - } - } - } - - // Now that mindrop has been established see if we get any more based - // on item odds. Pick a random entry to start at so no one entry is favored. - // Look at all items until we hit droplimit or look at all items. - - if (droplimit <= mindrop) { - return; - } - - int start_index = zone->random.Int(0,loot_drop->NumEntries-1); - int j = start_index; - int dropped = mindrop; - - do { - - LogLootDetail("DropLimit Starting at [{}] out of [{}]", j, - loot_drop->NumEntries); - - const EQ::ItemData *db_item = GetItem(loot_drop->Entries[j].item_id); - if (db_item && - npc->MeetsLootDropLevelRequirements(loot_drop->Entries[j])) { - - float iroll = (float) zone->random.Real(0.0, 100.0); - - LogLootDetail("Rolled [{}] Needed [{}]", iroll, loot_drop->Entries[j].chance); - // If this item succeeds the chance roll - if (iroll < loot_drop->Entries[j].chance) { - - ++dropped; - LogLootDetail("Dropping item [{}]", loot_drop->Entries[j].item_id); - npc->AddLootDrop( - db_item, - item_list, - loot_drop->Entries[j] - ); - - int charges = (int) loot_drop->Entries[j].multiplier; - charges = EQ::ClampLower(charges, 1); - - for (int k = 1; k < charges; ++k) { - float c_roll = (float) zone->random.Real(0.0, 100.0); - if (c_roll <= loot_drop->Entries[j].chance) { + if (roll < loot_drop->Entries[j].chance) { npc->AddLootDrop( db_item, item_list, loot_drop->Entries[j] ); + drops++; + + int charges = (int) loot_drop->Entries[i].multiplier; + charges = EQ::ClampLower(charges, 1); + + for (int k = 1; k < charges; ++k) { + float c_roll = (float) zone->random.Real(0.0, 100.0); + if (c_roll <= loot_drop->Entries[i].chance) { + npc->AddLootDrop( + db_item, + item_list, + loot_drop->Entries[i] + ); + } + } + + j = loot_drop->NumEntries; + break; + } + else { + roll -= loot_drop->Entries[j].chance; } } } } - - // Wrap the loop back to catch the start of loop - if (++j >= loot_drop->NumEntries) { - j = 0; - } - - } while (dropped < droplimit && j != start_index); + } npc->UpdateEquipmentLight(); // no wearchange associated with this function..so, this should not be needed @@ -365,7 +322,7 @@ void NPC::AddLootDrop( linker.SetItemData(item2); LogLoot( - "[NPC::AddLootDrop] NPC [{}] Item ({}) [{}] charges [{}] chance [{}] trivial min/max [{}/{}] npc min/max [{}/{}]", + "NPC [{}] Item ({}) [{}] charges [{}] chance [{}] trivial min/max [{}/{}] npc min/max [{}/{}]", GetName(), item2->ID, linker.GenerateLink(), @@ -400,6 +357,16 @@ void NPC::AddLootDrop( item->trivial_max_level = loot_drop.trivial_max_level; item->equip_slot = EQ::invslot::SLOT_INVALID; + + // unsure if required to equip, YOLO for now + if (item2->ItemType == EQ::item::ItemTypeBow) { + SetBowEquipped(true); + } + + if (item2->ItemType == EQ::item::ItemTypeArrow) { + SetArrowEquipped(true); + } + if (loot_drop.equip_item > 0) { uint8 eslot = 0xFF; char newid[20]; @@ -473,8 +440,6 @@ void NPC::AddLootDrop( } if (foundslot == EQ::invslot::slotPrimary) { - if (item2->Proc.Effect != 0) - CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = EQ::textures::weaponPrimary; if (item2->Damage > 0) { @@ -489,8 +454,6 @@ void NPC::AddLootDrop( && (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && (item2->IsType1HWeapon() || item2->ItemType == EQ::item::ItemTypeShield || item2->ItemType == EQ::item::ItemTypeLight)) { - if (item2->Proc.Effect!=0) - CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = EQ::textures::weaponSecondary; if (item2->Damage > 0) @@ -553,6 +516,10 @@ void NPC::AddLootDrop( } else safe_delete(item); + if (IsRecordLootStats()) { + m_rolled_items.emplace_back(item->item_id); + } + if (wear_change && outapp) { entity_list.QueueClients(this, outapp); safe_delete(outapp); @@ -651,12 +618,14 @@ void ZoneDatabase::LoadGlobalLoot() return; } + LogInfo("Loaded [{}] global loot entries", Strings::Commify(results.RowCount())); + // we might need this, lets not keep doing it in a loop auto zoneid = std::to_string(zone->GetZoneID()); for (auto row = results.begin(); row != results.end(); ++row) { // checking zone limits if (row[10]) { - auto zones = SplitString(row[10], '|'); + auto zones = Strings::Split(row[10], '|'); auto it = std::find(zones.begin(), zones.end(), zoneid); if (it == zones.end()) { // not in here, skip @@ -687,21 +656,21 @@ void ZoneDatabase::LoadGlobalLoot() } if (row[7]) { - auto races = SplitString(row[7], '|'); + auto races = Strings::Split(row[7], '|'); for (auto &r : races) e.AddRule(GlobalLoot::RuleTypes::Race, std::stoi(r)); } if (row[8]) { - auto classes = SplitString(row[8], '|'); + auto classes = Strings::Split(row[8], '|'); for (auto &c : classes) e.AddRule(GlobalLoot::RuleTypes::Class, std::stoi(c)); } if (row[9]) { - auto bodytypes = SplitString(row[9], '|'); + auto bodytypes = Strings::Split(row[9], '|'); for (auto &b : bodytypes) e.AddRule(GlobalLoot::RuleTypes::BodyType, std::stoi(b)); diff --git a/zone/lua_bot.cpp b/zone/lua_bot.cpp index 1e1ab1e89..096fcd9e7 100644 --- a/zone/lua_bot.cpp +++ b/zone/lua_bot.cpp @@ -1,4 +1,3 @@ -#ifdef BOTS #ifdef LUA_EQEMU #include "lua.hpp" @@ -6,7 +5,9 @@ #include "bot.h" #include "lua_bot.h" +#include "lua_iteminst.h" #include "lua_mob.h" +#include "lua_group.h" void Lua_Bot::AddBotItem(uint16 slot_id, uint32 item_id) { Lua_Safe_Call_Void(); @@ -73,6 +74,325 @@ void Lua_Bot::RemoveBotItem(uint32 item_id) { self->RemoveBotItem(item_id); } +Lua_ItemInst Lua_Bot::GetBotItem(uint16 slot_id) { + Lua_Safe_Call_Class(Lua_ItemInst); + return self->GetBotItem(slot_id); +} + +uint32 Lua_Bot::GetBotItemIDBySlot(uint16 slot_id) { + Lua_Safe_Call_Int(); + return self->GetBotItemBySlot(slot_id); +} + +void Lua_Bot::Signal(int signal_id) { + Lua_Safe_Call_Void(); + self->Signal(signal_id); +} + +void Lua_Bot::OwnerMessage(std::string message) { + Lua_Safe_Call_Void(); + self->OwnerMessage(message); +} + +int Lua_Bot::GetExpansionBitmask() { + Lua_Safe_Call_Int(); + return self->GetExpansionBitmask(); +} + +void Lua_Bot::SetExpansionBitmask(int expansion_bitmask) { + Lua_Safe_Call_Void(); + self->SetExpansionBitmask(expansion_bitmask); +} + +void Lua_Bot::SetExpansionBitmask(int expansion_bitmask, bool save) { + Lua_Safe_Call_Void(); + self->SetExpansionBitmask(expansion_bitmask, save); +} + +bool Lua_Bot::ReloadBotDataBuckets() { + Lua_Safe_Call_Bool(); + return self->GetBotDataBuckets(); +} + +bool Lua_Bot::ReloadBotOwnerDataBuckets() { + Lua_Safe_Call_Bool(); + return self->GetBotOwnerDataBuckets(); +} + +bool Lua_Bot::ReloadBotSpells() { + Lua_Safe_Call_Bool(); + return self->AI_AddBotSpells(self->GetBotSpellID()); +} + +void Lua_Bot::ReloadBotSpellSettings() { + Lua_Safe_Call_Void(); + self->LoadBotSpellSettings(); +} + +bool Lua_Bot::HasBotSpellEntry(uint16 spellid) { + Lua_Safe_Call_Bool(); + return self->HasBotSpellEntry(spellid); +} + +void Lua_Bot::SendPayload(int payload_id) { + Lua_Safe_Call_Void(); + self->SendPayload(payload_id); +} + +void Lua_Bot::SendPayload(int payload_id, std::string payload_value) { + Lua_Safe_Call_Void(); + self->SendPayload(payload_id, payload_value); +} + +void Lua_Bot::ApplySpell(int spell_id) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id); +} + +void Lua_Bot::ApplySpell(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration); +} + +void Lua_Bot::ApplySpell(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Lua_Bot::ApplySpellGroup(int spell_id) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, 0, ApplySpellType::Group); +} + +void Lua_Bot::ApplySpellGroup(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Group); +} + +void Lua_Bot::ApplySpellGroup(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +void Lua_Bot::SetSpellDuration(int spell_id) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id); +} + +void Lua_Bot::SetSpellDuration(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration); +} + +void Lua_Bot::SetSpellDuration(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Lua_Bot::SetSpellDurationGroup(int spell_id) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, 0, ApplySpellType::Group); +} + +void Lua_Bot::SetSpellDurationGroup(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group); +} + +void Lua_Bot::SetSpellDurationGroup(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +int Lua_Bot::CountAugmentEquippedByID(uint32 item_id) { + Lua_Safe_Call_Int(); + return self->GetInv().CountAugmentEquippedByID(item_id); +} + +bool Lua_Bot::HasAugmentEquippedByID(uint32 item_id) { + Lua_Safe_Call_Bool(); + return self->GetInv().HasAugmentEquippedByID(item_id); +} + +int Lua_Bot::CountItemEquippedByID(uint32 item_id) { + Lua_Safe_Call_Int(); + return self->GetInv().CountItemEquippedByID(item_id); +} + +bool Lua_Bot::HasItemEquippedByID(uint32 item_id) { + Lua_Safe_Call_Bool(); + return self->GetInv().HasItemEquippedByID(item_id); +} + +void Lua_Bot::Escape() { + Lua_Safe_Call_Void(); + self->Escape(); +} + +void Lua_Bot::Fling(float target_x, float target_y, float target_z) { + Lua_Safe_Call_Void(); + self->Fling(0, target_x, target_y, target_z, false, false, true); +} + +void Lua_Bot::Fling(float target_x, float target_y, float target_z, bool ignore_los) { + Lua_Safe_Call_Void(); + self->Fling(0, target_x, target_y, target_z, ignore_los, false, true); +} + +void Lua_Bot::Fling(float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) { + Lua_Safe_Call_Void(); + self->Fling(0, target_x, target_y, target_z, ignore_los, clip_through_walls, true); +} + +void Lua_Bot::Fling(float value, float target_x, float target_y, float target_z) { + Lua_Safe_Call_Void(); + self->Fling(value, target_x, target_y, target_z); +} + +void Lua_Bot::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los) { + Lua_Safe_Call_Void(); + self->Fling(value, target_x, target_y, target_z, ignore_los); +} + +void Lua_Bot::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) { + Lua_Safe_Call_Void(); + self->Fling(value, target_x, target_y, target_z, ignore_los, clip_through_walls); +} + +int Lua_Bot::GetBaseSTR() { + Lua_Safe_Call_Int(); + return self->GetBaseSTR(); +} + +int Lua_Bot::GetBaseSTA() { + Lua_Safe_Call_Int(); + return self->GetBaseSTA(); +} + +int Lua_Bot::GetBaseCHA() { + Lua_Safe_Call_Int(); + return self->GetBaseCHA(); +} + +int Lua_Bot::GetBaseDEX() { + Lua_Safe_Call_Int(); + return self->GetBaseDEX(); +} + +int Lua_Bot::GetBaseINT() { + Lua_Safe_Call_Int(); + return self->GetBaseINT(); +} + +int Lua_Bot::GetBaseAGI() { + Lua_Safe_Call_Int(); + return self->GetBaseAGI(); +} + +int Lua_Bot::GetBaseWIS() { + Lua_Safe_Call_Int(); + return self->GetBaseWIS(); +} + +Lua_Group Lua_Bot::GetGroup() { + Lua_Safe_Call_Class(Lua_Group); + return self->GetGroup(); +} + +int Lua_Bot::GetHealAmount() { + Lua_Safe_Call_Int(); + return self->GetHealAmt(); +} + +int Lua_Bot::GetSpellDamage() { + Lua_Safe_Call_Int(); + return self->GetSpellDmg(); +} + +int Lua_Bot::GetInstrumentMod(int spell_id) { + Lua_Safe_Call_Int(); + return self->GetInstrumentMod(spell_id); +} + +int Lua_Bot::GetRawItemAC() { + Lua_Safe_Call_Int(); + return self->GetRawItemAC(); +} + +bool Lua_Bot::IsGrouped() { + Lua_Safe_Call_Bool(); + return self->IsGrouped(); +} + +bool Lua_Bot::IsStanding() { + Lua_Safe_Call_Bool(); + return self->IsStanding(); +} + +bool Lua_Bot::IsSitting() { + Lua_Safe_Call_Bool(); + return self->IsSitting(); +} + +void Lua_Bot::Sit() { + Lua_Safe_Call_Void(); + self->Sit(); +} + +void Lua_Bot::Stand() { + Lua_Safe_Call_Void(); + self->Stand(); +} + +uint32 Lua_Bot::GetBotID() { + Lua_Safe_Call_Int(); + return self->GetBotID(); +} + +void Lua_Bot::Camp() { + Lua_Safe_Call_Void(); + self->Camp(); +} + +void Lua_Bot::Camp(bool save_to_database) { + Lua_Safe_Call_Void(); + self->Camp(save_to_database); +} + +Lua_ItemInst Lua_Bot::GetAugmentAt(int16 slot_id, uint8 augment_index) +{ + Lua_Safe_Call_Class(Lua_ItemInst); + + auto* inst = self->GetInv().GetItem(slot_id); + if (inst) { + return Lua_ItemInst(inst->GetAugment(augment_index)); + } + + return Lua_ItemInst(); +} + +int Lua_Bot::GetAugmentIDAt(int16 slot_id, uint8 augment_index) { + Lua_Safe_Call_Int(); + return self->GetAugmentIDAt(slot_id, augment_index); +} + +int Lua_Bot::GetItemIDAt(int16 slot_id) { + Lua_Safe_Call_Int(); + return self->GetItemIDAt(slot_id); +} + +Lua_ItemInst Lua_Bot::GetItemAt(int16 slot_id) // @categories Inventory and Items +{ + Lua_Safe_Call_Class(Lua_ItemInst); + return Lua_ItemInst(self->GetInv().GetItem(slot_id)); +} + +void Lua_Bot::SendSpellAnim(uint16 target_id, uint16 spell_id) +{ + Lua_Safe_Call_Void(); + self->SendSpellAnim(target_id, spell_id); +} + luabind::scope lua_register_bot() { return luabind::class_("Bot") .def(luabind::constructor<>()) @@ -85,11 +405,71 @@ luabind::scope lua_register_bot() { .def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem) .def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem) .def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem) + .def("ApplySpell", (void(Lua_Bot::*)(int))&Lua_Bot::ApplySpell) + .def("ApplySpell", (void(Lua_Bot::*)(int,int))&Lua_Bot::ApplySpell) + .def("ApplySpell", (void(Lua_Bot::*)(int,int,bool))&Lua_Bot::ApplySpell) + .def("ApplySpellGroup", (void(Lua_Bot::*)(int))&Lua_Bot::ApplySpellGroup) + .def("ApplySpellGroup", (void(Lua_Bot::*)(int,int))&Lua_Bot::ApplySpellGroup) + .def("ApplySpellGroup", (void(Lua_Bot::*)(int,int,bool))&Lua_Bot::ApplySpellGroup) + .def("Camp", (void(Lua_Bot::*)(void))&Lua_Bot::Camp) + .def("Camp", (void(Lua_Bot::*)(bool))&Lua_Bot::Camp) .def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem) + .def("CountItemEquippedByID", (int(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID) + .def("Escape", (void(Lua_Bot::*)(void))&Lua_Bot::Escape) + .def("Fling", (void(Lua_Bot::*)(float,float,float))&Lua_Bot::Fling) + .def("Fling", (void(Lua_Bot::*)(float,float,float,bool))&Lua_Bot::Fling) + .def("Fling", (void(Lua_Bot::*)(float,float,float,bool,bool))&Lua_Bot::Fling) + .def("Fling", (void(Lua_Bot::*)(float,float,float,float))&Lua_Bot::Fling) + .def("Fling", (void(Lua_Bot::*)(float,float,float,float,bool))&Lua_Bot::Fling) + .def("Fling", (void(Lua_Bot::*)(float,float,float,float,bool,bool))&Lua_Bot::Fling) + .def("GetAugmentAt", (Lua_ItemInst(Lua_Bot::*)(int16,uint8))&Lua_Bot::GetAugmentAt) + .def("GetAugmentIDAt", (int(Lua_Bot::*)(int16,uint8))&Lua_Bot::GetAugmentIDAt) + .def("GetBaseAGI", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseAGI) + .def("GetBaseCHA", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseCHA) + .def("GetBaseDEX", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseDEX) + .def("GetBaseINT", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseINT) + .def("GetBaseSTA", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseSTA) + .def("GetBaseSTR", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseSTR) + .def("GetBaseWIS", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseWIS) + .def("GetBotID", (uint32(Lua_Bot::*)(void))&Lua_Bot::GetBotID) + .def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItem) + .def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItemIDBySlot) + .def("GetExpansionBitmask", (int(Lua_Bot::*)(void))&Lua_Bot::GetExpansionBitmask) + .def("GetGroup", (Lua_Group(Lua_Bot::*)(void))&Lua_Bot::GetGroup) + .def("GetHealAmount", (int(Lua_Bot::*)(void))&Lua_Bot::GetHealAmount) + .def("GetInstrumentMod", (int(Lua_Bot::*)(int))&Lua_Bot::GetInstrumentMod) + .def("GetItemAt", (Lua_ItemInst(Lua_Bot::*)(int16))&Lua_Bot::GetItemAt) + .def("GetItemIDAt", (int(Lua_Bot::*)(int16))&Lua_Bot::GetItemIDAt) .def("GetOwner", (Lua_Mob(Lua_Bot::*)(void))&Lua_Bot::GetOwner) + .def("GetRawItemAC", (int(Lua_Bot::*)(void))&Lua_Bot::GetRawItemAC) + .def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage) + .def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID) .def("HasBotItem", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem) - .def("RemoveBotItem", (void(Lua_Bot::*)(uint32))&Lua_Bot::RemoveBotItem); + .def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry) + .def("HasItemEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItemEquippedByID) + .def("IsGrouped", (bool(Lua_Bot::*)(void))&Lua_Bot::IsGrouped) + .def("IsSitting", (bool(Lua_Bot::*)(void))&Lua_Bot::IsSitting) + .def("IsStanding", (bool(Lua_Bot::*)(void))&Lua_Bot::IsStanding) + .def("OwnerMessage", (void(Lua_Bot::*)(std::string))&Lua_Bot::OwnerMessage) + .def("ReloadBotDataBuckets", (bool(Lua_Bot::*)(void))&Lua_Bot::ReloadBotDataBuckets) + .def("ReloadBotOwnerDataBuckets", (bool(Lua_Bot::*)(void))&Lua_Bot::ReloadBotOwnerDataBuckets) + .def("ReloadBotSpells", (bool(Lua_Bot::*)(void))&Lua_Bot::ReloadBotSpells) + .def("ReloadBotSpellSettings", (void(Lua_Bot::*)(void))&Lua_Bot::ReloadBotSpellSettings) + .def("RemoveBotItem", (void(Lua_Bot::*)(uint32))&Lua_Bot::RemoveBotItem) + .def("SendSpellAnim", (void(Lua_Bot::*)(uint16,uint16))&Lua_Bot::SendSpellAnim) + .def("SetExpansionBitmask", (void(Lua_Bot::*)(int))&Lua_Bot::SetExpansionBitmask) + .def("SetExpansionBitmask", (void(Lua_Bot::*)(int,bool))&Lua_Bot::SetExpansionBitmask) + .def("SetSpellDuration", (void(Lua_Bot::*)(int))&Lua_Bot::SetSpellDuration) + .def("SetSpellDuration", (void(Lua_Bot::*)(int,int))&Lua_Bot::SetSpellDuration) + .def("SetSpellDuration", (void(Lua_Bot::*)(int,int,bool))&Lua_Bot::SetSpellDuration) + .def("SetSpellDurationGroup", (void(Lua_Bot::*)(int))&Lua_Bot::SetSpellDurationGroup) + .def("SetSpellDurationGroup", (void(Lua_Bot::*)(int,int))&Lua_Bot::SetSpellDurationGroup) + .def("SetSpellDurationGroup", (void(Lua_Bot::*)(int,int,bool))&Lua_Bot::SetSpellDurationGroup) + .def("SendPayload", (void(Lua_Bot::*)(int))&Lua_Bot::SendPayload) + .def("SendPayload", (void(Lua_Bot::*)(int,std::string))&Lua_Bot::SendPayload) + .def("Signal", (void(Lua_Bot::*)(int))&Lua_Bot::Signal) + .def("Sit", (void(Lua_Bot::*)(void))&Lua_Bot::Sit) + .def("Stand", (void(Lua_Bot::*)(void))&Lua_Bot::Stand); } #endif -#endif diff --git a/zone/lua_bot.h b/zone/lua_bot.h index 7123e5270..8e25f5b5e 100644 --- a/zone/lua_bot.h +++ b/zone/lua_bot.h @@ -1,4 +1,3 @@ -#ifdef BOTS #ifndef EQEMU_LUA_BOT_H #define EQEMU_LUA_BOT_H #ifdef LUA_EQEMU @@ -8,6 +7,7 @@ class Bot; class Lua_Bot; class Lua_Mob; +class Lua_Group; namespace luabind { struct scope; @@ -37,11 +37,87 @@ public: void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five); void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six); uint32 CountBotItem(uint32 item_id); + Lua_ItemInst GetBotItem(uint16 slot_id); + uint32 GetBotItemIDBySlot(uint16 slot_id); + int GetExpansionBitmask(); Lua_Mob GetOwner(); bool HasBotItem(uint32 item_id); + void OwnerMessage(std::string message); + bool ReloadBotDataBuckets(); + bool ReloadBotOwnerDataBuckets(); + bool ReloadBotSpells(); + void ReloadBotSpellSettings(); void RemoveBotItem(uint32 item_id); + void SetExpansionBitmask(int expansion_bitmask); + void SetExpansionBitmask(int expansion_bitmask, bool save); + void Signal(int signal_id); + bool HasBotSpellEntry(uint16 spellid); + void SendPayload(int payload_id); + void SendPayload(int payload_id, std::string payload_value); + uint32 GetBotID(); + void Camp(); + void Camp(bool save_to_database); + Lua_ItemInst GetAugmentAt(int16 slot_id, uint8 augment_index); + int GetAugmentIDAt(int16 slot_id, uint8 augment_index); + Lua_ItemInst GetItemAt(int16 slot_id); + int GetItemIDAt(int16 slot_id); + void SendSpellAnim(uint16 target_id, uint16 spell_id); + + void ApplySpell(int spell_id); + void ApplySpell(int spell_id, int duration); + void ApplySpell(int spell_id, int duration, bool allow_pets); + + void ApplySpellGroup(int spell_id); + void ApplySpellGroup(int spell_id, int duration); + void ApplySpellGroup(int spell_id, int duration, bool allow_pets); + + void SetSpellDuration(int spell_id); + void SetSpellDuration(int spell_id, int duration); + void SetSpellDuration(int spell_id, int duration, bool allow_pets); + + void SetSpellDurationGroup(int spell_id); + void SetSpellDurationGroup(int spell_id, int duration); + void SetSpellDurationGroup(int spell_id, int duration, bool allow_pets); + + void SetSpellDurationRaid(int spell_id); + void SetSpellDurationRaid(int spell_id, int duration); + void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets); + void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only); + + int CountAugmentEquippedByID(uint32 item_id); + int CountItemEquippedByID(uint32 item_id); + bool HasAugmentEquippedByID(uint32 item_id); + bool HasItemEquippedByID(uint32 item_id); + int GetHealAmount(); + int GetSpellDamage(); + + void Escape(); + int GetInstrumentMod(int spell_id); + + int GetBaseSTR(); + int GetBaseSTA(); + int GetBaseCHA(); + int GetBaseDEX(); + int GetBaseINT(); + int GetBaseAGI(); + int GetBaseWIS(); + + Lua_Group GetGroup(); + int GetRawItemAC(); + + bool IsGrouped(); + bool IsStanding(); + bool IsSitting(); + void Sit(); + void Stand(); + + void Fling(float target_x, float target_y, float target_z); + void Fling(float target_x, float target_y, float target_z, bool ignore_los); + void Fling(float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls); + void Fling(float value, float target_x, float target_y, float target_z); + void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los); + void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls); }; #endif #endif -#endif \ No newline at end of file diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 68b55ba8c..bc5884427 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -16,6 +16,7 @@ #include "lua_raid.h" #include "lua_packet.h" #include "dialogue_window.h" +#include "titles.h" #include "../common/expedition_lockout_timer.h" struct InventoryWhere { }; @@ -265,12 +266,12 @@ void Lua_Client::AddEXP(uint32 add_exp, int conlevel, bool resexp) { self->AddEXP(add_exp, conlevel, resexp); } -void Lua_Client::SetEXP(uint32 set_exp, uint32 set_aaxp) { +void Lua_Client::SetEXP(uint64 set_exp, uint64 set_aaxp) { Lua_Safe_Call_Void(); self->SetEXP(set_exp, set_aaxp); } -void Lua_Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp) { +void Lua_Client::SetEXP(uint64 set_exp, uint64 set_aaxp, bool resexp) { Lua_Safe_Call_Void(); self->SetEXP(set_exp, set_aaxp, resexp); } @@ -385,39 +386,9 @@ void Lua_Client::MovePCInstance(int zone, int instance, float x, float y, float self->MovePC(zone, instance, x, y, z, heading); } -void Lua_Client::MoveZone(const char *zone_short_name) { +void Lua_Client::ChangeLastName(std::string last_name) { Lua_Safe_Call_Void(); - self->MoveZone(zone_short_name); -} - -void Lua_Client::MoveZoneGroup(const char *zone_short_name) { - Lua_Safe_Call_Void(); - self->MoveZoneGroup(zone_short_name); -} - -void Lua_Client::MoveZoneRaid(const char *zone_short_name) { - Lua_Safe_Call_Void(); - self->MoveZoneRaid(zone_short_name); -} - -void Lua_Client::MoveZoneInstance(uint16 instance_id) { - Lua_Safe_Call_Void(); - self->MoveZoneInstance(instance_id); -} - -void Lua_Client::MoveZoneInstanceGroup(uint16 instance_id) { - Lua_Safe_Call_Void(); - self->MoveZoneInstanceGroup(instance_id); -} - -void Lua_Client::MoveZoneInstanceRaid(uint16 instance_id) { - Lua_Safe_Call_Void(); - self->MoveZoneInstanceRaid(instance_id); -} - -void Lua_Client::ChangeLastName(const char *in) { - Lua_Safe_Call_Void(); - self->ChangeLastName(in); + self->ChangeLastName(last_name); } int Lua_Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 race, uint32 class_, uint32 deity, uint32 faction, Lua_NPC npc) { @@ -435,6 +406,11 @@ void Lua_Client::SetFactionLevel2(uint32 char_id, int faction_id, int char_class self->SetFactionLevel2(char_id, faction_id, char_class, char_race, char_deity, value, temp); } +void Lua_Client::RewardFaction(int id, int amount) { + Lua_Safe_Call_Void(); + self->RewardFaction(id, amount); +} + int Lua_Client::GetRawItemAC() { Lua_Safe_Call_Int(); return self->GetRawItemAC(); @@ -455,8 +431,8 @@ int Lua_Client::GetAccountAge() { return time(nullptr) - self->GetAccountCreation(); } -int Lua_Client::Admin() { - Lua_Safe_Call_Bool(); +int16 Lua_Client::Admin() { + Lua_Safe_Call_Int(); return self->Admin(); } @@ -674,7 +650,7 @@ luabind::object Lua_Client::GetLearnableDisciplines(lua_State* L) { if (d_) { auto self = reinterpret_cast(d_); auto learnable_disciplines = self->GetLearnableDisciplines(); - int index = 0; + int index = 1; for (auto spell_id : learnable_disciplines) { lua_table[index] = spell_id; index++; @@ -688,7 +664,7 @@ luabind::object Lua_Client::GetLearnableDisciplines(lua_State* L, uint8 min_leve if (d_) { auto self = reinterpret_cast(d_); auto learnable_disciplines = self->GetLearnableDisciplines(min_level); - int index = 0; + int index = 1; for (auto spell_id : learnable_disciplines) { lua_table[index] = spell_id; index++; @@ -702,7 +678,7 @@ luabind::object Lua_Client::GetLearnableDisciplines(lua_State* L, uint8 min_leve if (d_) { auto self = reinterpret_cast(d_); auto learnable_disciplines = self->GetLearnableDisciplines(min_level, max_level); - int index = 0; + int index = 1; for (auto spell_id : learnable_disciplines) { lua_table[index] = spell_id; index++; @@ -716,7 +692,7 @@ luabind::object Lua_Client::GetLearnedDisciplines(lua_State* L) { if (d_) { auto self = reinterpret_cast(d_); auto learned_disciplines = self->GetLearnedDisciplines(); - int index = 0; + int index = 1; for (auto spell_id : learned_disciplines) { lua_table[index] = spell_id; index++; @@ -730,7 +706,7 @@ luabind::object Lua_Client::GetMemmedSpells(lua_State* L) { if (d_) { auto self = reinterpret_cast(d_); auto memmed_spells = self->GetMemmedSpells(); - int index = 0; + int index = 1; for (auto spell_id : memmed_spells) { lua_table[index] = spell_id; index++; @@ -744,7 +720,7 @@ luabind::object Lua_Client::GetScribeableSpells(lua_State* L) { if (d_) { auto self = reinterpret_cast(d_); auto scribeable_spells = self->GetScribeableSpells(); - int index = 0; + int index = 1; for (auto spell_id : scribeable_spells) { lua_table[index] = spell_id; index++; @@ -758,7 +734,7 @@ luabind::object Lua_Client::GetScribeableSpells(lua_State* L, uint8 min_level) { if (d_) { auto self = reinterpret_cast(d_); auto scribeable_spells = self->GetScribeableSpells(min_level); - int index = 0; + int index = 1; for (auto spell_id : scribeable_spells) { lua_table[index] = spell_id; index++; @@ -772,7 +748,7 @@ luabind::object Lua_Client::GetScribeableSpells(lua_State* L, uint8 min_level, u if (d_) { auto self = reinterpret_cast(d_); auto scribeable_spells = self->GetScribeableSpells(min_level, max_level); - int index = 0; + int index = 1; for (auto spell_id : scribeable_spells) { lua_table[index] = spell_id; index++; @@ -786,7 +762,7 @@ luabind::object Lua_Client::GetScribedSpells(lua_State* L) { if (d_) { auto self = reinterpret_cast(d_); auto scribed_spells = self->GetScribedSpells(); - int index = 0; + int index = 1; for (auto spell_id : scribed_spells) { lua_table[index] = spell_id; index++; @@ -1120,11 +1096,20 @@ void Lua_Client::SendZoneFlagInfo(Lua_Client to) { self->SendZoneFlagInfo(to); } -void Lua_Client::SetAATitle(const char *title) { +void Lua_Client::SetAATitle(std::string title) { Lua_Safe_Call_Void(); self->SetAATitle(title); } +void Lua_Client::SetAATitle(std::string title, bool save_to_database) { + Lua_Safe_Call_Void(); + if (!save_to_database) { + self->SetAATitle(title); + } else { + title_manager.CreateNewPlayerTitle(self, title); + } +} + int Lua_Client::GetClientVersion() { Lua_Safe_Call_Int(); return static_cast(self->ClientVersion()); @@ -1345,6 +1330,11 @@ bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ig return self->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); } +void Lua_Client::ResetAlternateAdvancementRank(int aa_id) { + Lua_Safe_Call_Void(); + self->ResetAlternateAdvancementRank(aa_id); +} + void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { Lua_Safe_Call_Void(); self->MarkSingleCompassLoc(in_x, in_y, in_z); @@ -1420,6 +1410,21 @@ bool Lua_Client::IsTaskActivityActive(int task, int activity) { return self->IsTaskActivityActive(task, activity); } +void Lua_Client::LockSharedTask(bool lock) { + Lua_Safe_Call_Void(); + return self->LockSharedTask(lock); +} + +void Lua_Client::EndSharedTask() { + Lua_Safe_Call_Void(); + self->EndSharedTask(); +} + +void Lua_Client::EndSharedTask(bool send_fail) { + Lua_Safe_Call_Void(); + self->EndSharedTask(send_fail); +} + int Lua_Client::GetCorpseCount() { Lua_Safe_Call_Int(); return self->GetCorpseCount(); @@ -1480,9 +1485,9 @@ void Lua_Client::NotifyNewTitlesAvailable() { self->NotifyNewTitlesAvailable(); } -void Lua_Client::Signal(uint32 id) { +void Lua_Client::Signal(int signal_id) { Lua_Safe_Call_Void(); - self->Signal(id); + self->Signal(signal_id); } void Lua_Client::AddAlternateCurrencyValue(uint32 currency, int amount) { @@ -1597,11 +1602,6 @@ void Lua_Client::SetConsumption(int in_hunger, int in_thirst) { self->SetConsumption(in_hunger, in_thirst); } -void Lua_Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg) { - Lua_Safe_Call_Void(); - self->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, msg); -} - void Lua_Client::SendColoredText(uint32 type, std::string msg) { Lua_Safe_Call_Void(); self->SendColoredText(type, msg); @@ -1663,98 +1663,63 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) { QuestReward_Struct quest_reward; quest_reward.mob_id = 0; quest_reward.target_id = self->GetID(); - quest_reward.copper = 0; - quest_reward.silver = 0; - quest_reward.gold = 0; - quest_reward.platinum = 0; - quest_reward.exp_reward = 0; + quest_reward.copper = luabind::type(reward["copper"]) != LUA_TNIL ? luabind::object_cast(reward["copper"]) : 0; + quest_reward.silver = luabind::type(reward["silver"]) != LUA_TNIL ? luabind::object_cast(reward["silver"]) : 0; + quest_reward.gold = luabind::type(reward["gold"]) != LUA_TNIL ? luabind::object_cast(reward["gold"]) : 0; + quest_reward.platinum = luabind::type(reward["platinum"]) != LUA_TNIL ? luabind::object_cast(reward["platinum"]) : 0; + quest_reward.exp_reward = luabind::type(reward["exp"]) != LUA_TNIL ? luabind::object_cast(reward["exp"]) : 0; quest_reward.faction = 0; quest_reward.faction_mod = 0; bool faction = false; std::fill(std::begin(quest_reward.item_id), std::end(quest_reward.item_id), -1); - auto cur = reward["copper"]; - if (luabind::type(cur) != LUA_TNIL) { - try { - quest_reward.copper = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { - } - } - - cur = reward["silver"]; - if (luabind::type(cur) != LUA_TNIL) { - try { - quest_reward.silver = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { - } - } - - cur = reward["gold"]; - if (luabind::type(cur) != LUA_TNIL) { - try { - quest_reward.gold = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { - } - } - - cur = reward["platinum"]; - if (luabind::type(cur) != LUA_TNIL) { - try { - quest_reward.platinum = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { - } - } - - cur = reward["itemid"]; - if (luabind::type(cur) != LUA_TNIL) { - try { - quest_reward.item_id[0] = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { - } + auto item_id = reward["itemid"]; + if (luabind::type(item_id) != LUA_TNIL) { + quest_reward.item_id[0] = luabind::object_cast(item_id); } // if you define both an itemid and items table, the itemid is thrown away // should we error? - cur = reward["items"]; - if (luabind::type(cur) == LUA_TTABLE) { - try { - // assume they defined a compatible table - for (int i = 1; i <= QUESTREWARD_COUNT; ++i) { - auto item = cur[i]; - int cur_value = -1; - if (luabind::type(item) != LUA_TNIL) { - try { - cur_value = luabind::object_cast(item); - } catch (luabind::cast_failed &) { - } - } else { - break; - } - quest_reward.item_id[i - 1] = cur_value; + auto items = reward["items"]; + if (luabind::type(items) == LUA_TTABLE) { + // assume they defined a compatible table + for (int i = 1; i <= QUESTREWARD_COUNT; ++i) { + auto item = items[i]; + int cur_value = -1; + if (luabind::type(item) != LUA_TNIL) { + cur_value = luabind::object_cast(item); + } else { + break; } - } catch (luabind::cast_failed &) { + quest_reward.item_id[i - 1] = cur_value; } } - cur = reward["exp"]; - if (luabind::type(cur) != LUA_TNIL) { - try { - quest_reward.exp_reward = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { - } - } - - cur = reward["faction"]; - if (luabind::type(cur) != LUA_TNIL) { - try { - faction = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { + auto lua_faction = reward["faction"]; + if (luabind::type(lua_faction) != LUA_TNIL) { + // if it's a table it will be {faction, faction_mod} + if (luabind::type(lua_faction) == LUA_TTABLE) { + auto item = lua_faction[1]; + if (luabind::type(item) != LUA_TNIL) { + quest_reward.faction = luabind::object_cast(item); + } + item = lua_faction[2]; + if (luabind::type(item) != LUA_TNIL) { + quest_reward.faction_mod = luabind::object_cast(item); + } + } else { + faction = luabind::object_cast(lua_faction); } } self->QuestReward(target, quest_reward, faction); } +void Lua_Client::CashReward(uint32 copper, uint32 silver, uint32 gold, uint32 platinum) { + Lua_Safe_Call_Void(); + self->CashReward(copper, silver, gold, platinum); +} + bool Lua_Client::IsDead() { Lua_Safe_Call_Bool(); return self->IsDead(); @@ -1834,12 +1799,12 @@ void Lua_Client::SetSecondaryWeaponOrnamentation(uint32 model_id) { self->SetSecondaryWeaponOrnamentation(model_id); } -void Lua_Client::SetClientMaxLevel(int value) { +void Lua_Client::SetClientMaxLevel(uint8 max_level) { Lua_Safe_Call_Void(); - self->SetClientMaxLevel(value); + self->SetClientMaxLevel(max_level); } -int Lua_Client::GetClientMaxLevel() { +uint8 Lua_Client::GetClientMaxLevel() { Lua_Safe_Call_Int(); return self->GetClientMaxLevel(); } @@ -1929,6 +1894,11 @@ Lua_Expedition Lua_Client::CreateExpedition(luabind::object expedition_table) { dz.SetZoneInLocation(zonein_loc); } + if (luabind::type(expedition_table["switchid"]) == LUA_TNUMBER) + { + dz.SetSwitchID(luabind::object_cast(expedition_table["switchid"])); + } + bool disable_messages = false; if (luabind::type(expedition_info["disable_messages"]) == LUA_TBOOLEAN) { @@ -1948,6 +1918,11 @@ Lua_Expedition Lua_Client::CreateExpedition(std::string zone_name, uint32 versio return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players, disable_messages); } +Lua_Expedition Lua_Client::CreateExpeditionFromTemplate(uint32_t dz_template_id) { + Lua_Safe_Call_Class(Lua_Expedition); + return self->CreateExpeditionFromTemplate(dz_template_id); +} + Lua_Expedition Lua_Client::GetExpedition() { Lua_Safe_Call_Class(Lua_Expedition); return self->GetExpedition(); @@ -2120,9 +2095,29 @@ void Lua_Client::CreateTaskDynamicZone(int task_id, luabind::object dz_table) { dz.SetZoneInLocation(zonein_loc); } + if (luabind::type(dz_table["switchid"]) == LUA_TNUMBER) + { + dz.SetSwitchID(luabind::object_cast(dz_table["switchid"])); + } + self->CreateTaskDynamicZone(task_id, dz); } +void Lua_Client::Fling(float target_x, float target_y, float target_z) { + Lua_Safe_Call_Void(); + self->Fling(0, target_x, target_y, target_z, false, false, true); +} + +void Lua_Client::Fling(float target_x, float target_y, float target_z, bool ignore_los) { + Lua_Safe_Call_Void(); + self->Fling(0, target_x, target_y, target_z, ignore_los, false, true); +} + +void Lua_Client::Fling(float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) { + Lua_Safe_Call_Void(); + self->Fling(0, target_x, target_y, target_z, ignore_los, clip_through_walls, true); +} + void Lua_Client::Fling(float value, float target_x, float target_y, float target_z) { Lua_Safe_Call_Void(); self->Fling(value, target_x, target_y, target_z); @@ -2133,9 +2128,9 @@ void Lua_Client::Fling(float value, float target_x, float target_y, float target self->Fling(value, target_x, target_y, target_z, ignore_los); } -void Lua_Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clipping) { +void Lua_Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) { Lua_Safe_Call_Void(); - self->Fling(value, target_x, target_y, target_z, ignore_los, clipping); + self->Fling(value, target_x, target_y, target_z, ignore_los, clip_through_walls); } double Lua_Client::GetAAEXPModifier(uint32 zone_id) { @@ -2143,21 +2138,41 @@ double Lua_Client::GetAAEXPModifier(uint32 zone_id) { return self->GetAAEXPModifier(zone_id); } +double Lua_Client::GetAAEXPModifier(uint32 zone_id, int16 instance_version) { + Lua_Safe_Call_Real(); + return self->GetAAEXPModifier(zone_id, instance_version); +} + double Lua_Client::GetEXPModifier(uint32 zone_id) { Lua_Safe_Call_Real(); return self->GetEXPModifier(zone_id); } +double Lua_Client::GetEXPModifier(uint32 zone_id, int16 instance_version) { + Lua_Safe_Call_Real(); + return self->GetEXPModifier(zone_id, instance_version); +} + void Lua_Client::SetAAEXPModifier(uint32 zone_id, double aa_modifier) { Lua_Safe_Call_Void(); self->SetAAEXPModifier(zone_id, aa_modifier); } +void Lua_Client::SetAAEXPModifier(uint32 zone_id, double aa_modifier, int16 instance_version) { + Lua_Safe_Call_Void(); + self->SetAAEXPModifier(zone_id, aa_modifier, instance_version); +} + void Lua_Client::SetEXPModifier(uint32 zone_id, double exp_modifier) { Lua_Safe_Call_Void(); self->SetEXPModifier(zone_id, exp_modifier); } +void Lua_Client::SetEXPModifier(uint32 zone_id, double exp_modifier, int16 instance_version) { + Lua_Safe_Call_Void(); + self->SetEXPModifier(zone_id, exp_modifier, instance_version); +} + void Lua_Client::AddLDoNLoss(uint32 theme_id) { Lua_Safe_Call_Void(); self->UpdateLDoNWinLoss(theme_id); @@ -2233,9 +2248,14 @@ void Lua_Client::RemoveItem(uint32 item_id, uint32 quantity) { self->RemoveItem(item_id, quantity); } -void Lua_Client::SetGMStatus(uint32 newStatus) { +void Lua_Client::SetGMStatus(int16 new_status) { Lua_Safe_Call_Void(); - self->SetGMStatus(newStatus); + self->SetGMStatus(new_status); +} + +int16 Lua_Client::GetGMStatus() { + Lua_Safe_Call_Int(); + return self->Admin(); } void Lua_Client::UntrainDiscBySpellID(uint16 spell_id) { @@ -2492,32 +2512,506 @@ int Lua_Client::GetSpellDamage() { } void Lua_Client::TaskSelector(luabind::adl::object table) { + TaskSelector(table, false); +} + +void Lua_Client::TaskSelector(luabind::adl::object table, bool ignore_cooldown) { Lua_Safe_Call_Void(); if(luabind::type(table) != LUA_TTABLE) { return; } - int tasks[MAXCHOOSERENTRIES] = { 0 }; - int task_count = 0; - + std::vector tasks; for(int i = 1; i <= MAXCHOOSERENTRIES; ++i) { auto cur = table[i]; - int cur_value = 0; - if(luabind::type(cur) != LUA_TNIL) { - try { - cur_value = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { - } - } else { - task_count = i - 1; - break; + if (luabind::type(cur) == LUA_TNUMBER) { + tasks.push_back(luabind::object_cast(cur)); } - - tasks[i - 1] = cur_value; } - self->TaskQuestSetSelector(self, task_count, tasks); + self->TaskQuestSetSelector(self, tasks, ignore_cooldown); +} + +bool Lua_Client::TeleportToPlayerByCharID(uint32 character_id) { + Lua_Safe_Call_Bool(); + return self->GotoPlayer(database.GetCharNameByID(character_id)); +} + +bool Lua_Client::TeleportToPlayerByName(std::string player_name) { + Lua_Safe_Call_Bool(); + return self->GotoPlayer(player_name); +} + +bool Lua_Client::TeleportGroupToPlayerByCharID(uint32 character_id) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerGroup(database.GetCharNameByID(character_id)); +} + +bool Lua_Client::TeleportGroupToPlayerByName(std::string player_name) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerGroup(player_name); +} + +bool Lua_Client::TeleportRaidToPlayerByCharID(uint32 character_id) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerRaid(database.GetCharNameByID(character_id)); +} + +bool Lua_Client::TeleportRaidToPlayerByName(std::string player_name) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerRaid(player_name); +} + +int Lua_Client::GetRecipeMadeCount(uint32 recipe_id) { + Lua_Safe_Call_Int(); + return self->GetRecipeMadeCount(recipe_id); +} + +bool Lua_Client::HasRecipeLearned(uint32 recipe_id) { + Lua_Safe_Call_Bool(); + return self->HasRecipeLearned(recipe_id); +} + +bool Lua_Client::SendGMCommand(std::string message) { + Lua_Safe_Call_Bool(); + return self->SendGMCommand(message); +} + +bool Lua_Client::SendGMCommand(std::string message, bool ignore_status) { + Lua_Safe_Call_Bool(); + return self->SendGMCommand(message, ignore_status); +} + +void Lua_Client::SendMarqueeMessage(uint32 type, std::string message) { + Lua_Safe_Call_Void(); + self->SendMarqueeMessage(type, message); +} + +void Lua_Client::SendMarqueeMessage(uint32 type, std::string message, uint32 duration) { + Lua_Safe_Call_Void(); + self->SendMarqueeMessage(type, message, duration); +} + +void Lua_Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) { + Lua_Safe_Call_Void(); + self->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, message); +} + +void Lua_Client::MoveZone(const char *zone_short_name) { + Lua_Safe_Call_Void(); + self->MoveZone(zone_short_name); +} + +void Lua_Client::MoveZone(const char *zone_short_name, float x, float y, float z) { + Lua_Safe_Call_Void(); + self->MoveZone(zone_short_name, glm::vec4(x, y, z, 0.0f)); +} + +void Lua_Client::MoveZone(const char *zone_short_name, float x, float y, float z, float heading) { + Lua_Safe_Call_Void(); + self->MoveZone(zone_short_name, glm::vec4(x, y, z, heading)); +} + +void Lua_Client::MoveZoneGroup(const char *zone_short_name) { + Lua_Safe_Call_Void(); + self->MoveZoneGroup(zone_short_name); +} + +void Lua_Client::MoveZoneGroup(const char *zone_short_name, float x, float y, float z) { + Lua_Safe_Call_Void(); + self->MoveZoneGroup(zone_short_name, glm::vec4(x, y, z, 0.0f)); +} + +void Lua_Client::MoveZoneGroup(const char *zone_short_name, float x, float y, float z, float heading) { + Lua_Safe_Call_Void(); + self->MoveZoneGroup(zone_short_name, glm::vec4(x, y, z, heading)); +} + +void Lua_Client::MoveZoneRaid(const char *zone_short_name) { + Lua_Safe_Call_Void(); + self->MoveZoneRaid(zone_short_name); +} + +void Lua_Client::MoveZoneRaid(const char *zone_short_name, float x, float y, float z) { + Lua_Safe_Call_Void(); + self->MoveZoneRaid(zone_short_name, glm::vec4(x, y, z, 0.0f)); +} + +void Lua_Client::MoveZoneRaid(const char *zone_short_name, float x, float y, float z, float heading) { + Lua_Safe_Call_Void(); + self->MoveZoneRaid(zone_short_name, glm::vec4(x, y, z, heading)); +} + +void Lua_Client::MoveZoneInstance(uint16 instance_id) { + Lua_Safe_Call_Void(); + self->MoveZoneInstance(instance_id); +} + +void Lua_Client::MoveZoneInstance(uint16 instance_id, float x, float y, float z) { + Lua_Safe_Call_Void(); + self->MoveZoneInstance(instance_id, glm::vec4(x, y, z, 0.0f)); +} + +void Lua_Client::MoveZoneInstance(uint16 instance_id, float x, float y, float z, float heading) { + Lua_Safe_Call_Void(); + self->MoveZoneInstance(instance_id, glm::vec4(x, y, z, heading)); +} + +void Lua_Client::MoveZoneInstanceGroup(uint16 instance_id) { + Lua_Safe_Call_Void(); + self->MoveZoneInstanceGroup(instance_id); +} + +void Lua_Client::MoveZoneInstanceGroup(uint16 instance_id, float x, float y, float z) { + Lua_Safe_Call_Void(); + self->MoveZoneInstanceGroup(instance_id, glm::vec4(x, y, z, 0.0f)); +} + +void Lua_Client::MoveZoneInstanceGroup(uint16 instance_id, float x, float y, float z, float heading) { + Lua_Safe_Call_Void(); + self->MoveZoneInstanceGroup(instance_id, glm::vec4(x, y, z, heading)); +} + +void Lua_Client::MoveZoneInstanceRaid(uint16 instance_id) { + Lua_Safe_Call_Void(); + self->MoveZoneInstanceRaid(instance_id); +} + +void Lua_Client::MoveZoneInstanceRaid(uint16 instance_id, float x, float y, float z) { + Lua_Safe_Call_Void(); + self->MoveZoneInstanceRaid(instance_id, glm::vec4(x, y, z, 0.0f)); +} + +void Lua_Client::MoveZoneInstanceRaid(uint16 instance_id, float x, float y, float z, float heading) { + Lua_Safe_Call_Void(); + self->MoveZoneInstanceRaid(instance_id, glm::vec4(x, y, z, heading)); +} + +void Lua_Client::ApplySpell(int spell_id) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id); +} + +void Lua_Client::ApplySpell(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration); +} + +void Lua_Client::ApplySpell(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Lua_Client::ApplySpell(int spell_id, int duration, bool allow_pets, bool allow_bots) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots); +} + +void Lua_Client::ApplySpellGroup(int spell_id) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, 0, ApplySpellType::Group); +} + +void Lua_Client::ApplySpellGroup(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Group); +} + +void Lua_Client::ApplySpellGroup(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +void Lua_Client::ApplySpellGroup(int spell_id, int duration, bool allow_pets, bool allow_bots) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots); +} + +void Lua_Client::ApplySpellRaid(int spell_id) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, 0, ApplySpellType::Raid); +} + +void Lua_Client::ApplySpellRaid(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Raid); +} + +void Lua_Client::ApplySpellRaid(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets); +} + +void Lua_Client::ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only); +} + +void Lua_Client::ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots) { + Lua_Safe_Call_Void(); + self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only, allow_bots); +} + +void Lua_Client::SetSpellDuration(int spell_id) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id); +} + +void Lua_Client::SetSpellDuration(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration); +} + +void Lua_Client::SetSpellDuration(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Lua_Client::SetSpellDuration(int spell_id, int duration, bool allow_pets, bool allow_bots) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots); +} + +void Lua_Client::SetSpellDurationGroup(int spell_id) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, 0, ApplySpellType::Group); +} + +void Lua_Client::SetSpellDurationGroup(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group); +} + +void Lua_Client::SetSpellDurationGroup(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +void Lua_Client::SetSpellDurationGroup(int spell_id, int duration, bool allow_pets, bool allow_bots) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots); +} + +void Lua_Client::SetSpellDurationRaid(int spell_id) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, 0, ApplySpellType::Raid); +} + +void Lua_Client::SetSpellDurationRaid(int spell_id, int duration) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid); +} + +void Lua_Client::SetSpellDurationRaid(int spell_id, int duration, bool allow_pets) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets); +} + +void Lua_Client::SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only); +} + +void Lua_Client::SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots) { + Lua_Safe_Call_Void(); + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets, is_raid_group_only, allow_bots); +} + +void Lua_Client::UpdateAdmin() { + Lua_Safe_Call_Void(); + self->UpdateAdmin(); +} + +void Lua_Client::UpdateAdmin(bool from_database) { + Lua_Safe_Call_Void(); + self->UpdateAdmin(from_database); +} + +luabind::object Lua_Client::GetPEQZoneFlags(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetPEQZoneFlags(); + auto i = 0; + for (const auto& f : l) { + t[i] = f; + i++; + } + } + + return t; +} + +luabind::object Lua_Client::GetZoneFlags(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetZoneFlags(); + auto i = 0; + for (const auto& f : l) { + t[i] = f; + i++; + } + } + + return t; +} + +void Lua_Client::SendPayload(int payload_id) { + Lua_Safe_Call_Void(); + self->SendPayload(payload_id); +} + +void Lua_Client::SendPayload(int payload_id, std::string payload_value) { + Lua_Safe_Call_Void(); + self->SendPayload(payload_id, payload_value); +} + +std::string Lua_Client::GetGuildPublicNote() +{ + Lua_Safe_Call_String(); + return self->GetGuildPublicNote(); +} + +void Lua_Client::MaxSkills() +{ + Lua_Safe_Call_Void(); + self->MaxSkills(); +} + +luabind::object Lua_Client::GetAugmentIDsBySlotID(lua_State* L, int16 slot_id) { + auto lua_table = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto augments = self->GetInv().GetAugmentIDsBySlotID(slot_id); + int index = 1; + for (auto item_id : augments) { + lua_table[index] = item_id; + index++; + } + } + return lua_table; +} + +bool Lua_Client::IsEXPEnabled() { + Lua_Safe_Call_Bool(); + return self->IsEXPEnabled(); +} + +void Lua_Client::SetEXPEnabled(bool is_exp_enabled) { + Lua_Safe_Call_Void(); + self->SetEXPEnabled(is_exp_enabled); +} + +uint64 Lua_Client::CalcEXP(uint8 consider_level) { + Lua_Safe_Call_Int(); + return self->CalcEXP(consider_level); +} + +uint64 Lua_Client::CalcEXP(uint8 consider_level, bool ignore_modifiers) { + Lua_Safe_Call_Int(); + return self->CalcEXP(consider_level, ignore_modifiers); +} + +bool Lua_Client::CanEnterZone(std::string zone_short_name) { + Lua_Safe_Call_Bool(); + return self->CanEnterZone(zone_short_name); +} + +bool Lua_Client::CanEnterZone(std::string zone_short_name, int16 instance_version) { + Lua_Safe_Call_Bool(); + return self->CanEnterZone(zone_short_name, instance_version); +} + +void Lua_Client::SendPath(Lua_Mob target) +{ + Lua_Safe_Call_Void(); + self->SendPath(target); +} + +int Lua_Client::GetBotRequiredLevel() +{ + Lua_Safe_Call_Int(); + return self->GetBotRequiredLevel(); +} + +int Lua_Client::GetBotRequiredLevel(uint8 class_id) +{ + Lua_Safe_Call_Int(); + return self->GetBotRequiredLevel(class_id); +} + +uint32 Lua_Client::GetBotCreationLimit() +{ + Lua_Safe_Call_Int(); + return self->GetBotCreationLimit(); +} + +uint32 Lua_Client::GetBotCreationLimit(uint8 class_id) +{ + Lua_Safe_Call_Int(); + return self->GetBotCreationLimit(class_id); +} + +int Lua_Client::GetBotSpawnLimit() +{ + Lua_Safe_Call_Int(); + return self->GetBotSpawnLimit(); +} + +int Lua_Client::GetBotSpawnLimit(uint8 class_id) +{ + Lua_Safe_Call_Int(); + return self->GetBotSpawnLimit(class_id); +} + +void Lua_Client::SetBotRequiredLevel(int new_required_level) +{ + Lua_Safe_Call_Void(); + self->SetBotRequiredLevel(new_required_level); +} + +void Lua_Client::SetBotRequiredLevel(int new_required_level, uint8 class_id) +{ + Lua_Safe_Call_Void(); + self->SetBotRequiredLevel(new_required_level, class_id); +} + +void Lua_Client::SetBotCreationLimit(uint32 new_creation_limit) +{ + Lua_Safe_Call_Void(); + self->SetBotCreationLimit(new_creation_limit); +} + +void Lua_Client::SetBotCreationLimit(uint32 new_creation_limit, uint8 class_id) +{ + Lua_Safe_Call_Void(); + self->SetBotCreationLimit(new_creation_limit, class_id); +} + +void Lua_Client::SetBotSpawnLimit(int new_spawn_limit) +{ + Lua_Safe_Call_Void(); + self->SetBotSpawnLimit(new_spawn_limit); +} + +void Lua_Client::SetBotSpawnLimit(int new_spawn_limit, uint8 class_id) +{ + Lua_Safe_Call_Void(); + self->SetBotSpawnLimit(new_spawn_limit, class_id); +} + +void Lua_Client::CampAllBots() +{ + Lua_Safe_Call_Void(); + self->CampAllBots(); +} + +void Lua_Client::CampAllBots(uint8 class_id) +{ + Lua_Safe_Call_Void(); + self->CampAllBots(class_id); } luabind::scope lua_register_client() { @@ -2547,7 +3041,20 @@ luabind::scope lua_register_client() { .def("AddPlatinum", (void(Lua_Client::*)(uint32,bool))&Lua_Client::AddPlatinum) .def("AddPVPPoints", (void(Lua_Client::*)(uint32))&Lua_Client::AddPVPPoints) .def("AddSkill", (void(Lua_Client::*)(int,int))&Lua_Client::AddSkill) - .def("Admin", (int(Lua_Client::*)(void))&Lua_Client::Admin) + .def("Admin", (int16(Lua_Client::*)(void))&Lua_Client::Admin) + .def("ApplySpell", (void(Lua_Client::*)(int))&Lua_Client::ApplySpell) + .def("ApplySpell", (void(Lua_Client::*)(int,int))&Lua_Client::ApplySpell) + .def("ApplySpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ApplySpell) + .def("ApplySpell", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::ApplySpell) + .def("ApplySpellGroup", (void(Lua_Client::*)(int))&Lua_Client::ApplySpellGroup) + .def("ApplySpellGroup", (void(Lua_Client::*)(int,int))&Lua_Client::ApplySpellGroup) + .def("ApplySpellGroup", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ApplySpellGroup) + .def("ApplySpellGroup", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::ApplySpellGroup) + .def("ApplySpellRaid", (void(Lua_Client::*)(int))&Lua_Client::ApplySpellRaid) + .def("ApplySpellRaid", (void(Lua_Client::*)(int,int))&Lua_Client::ApplySpellRaid) + .def("ApplySpellRaid", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ApplySpellRaid) + .def("ApplySpellRaid", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::ApplySpellRaid) + .def("ApplySpellRaid", (void(Lua_Client::*)(int,int,bool,bool,bool))&Lua_Client::ApplySpellRaid) .def("AssignTask", (void(Lua_Client::*)(int))&Lua_Client::AssignTask) .def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask) .def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask) @@ -2556,9 +3063,16 @@ luabind::scope lua_register_client() { .def("BreakInvis", (void(Lua_Client::*)(void))&Lua_Client::BreakInvis) .def("CalcATK", &Lua_Client::CalcATK) .def("CalcCurrentWeight", &Lua_Client::CalcCurrentWeight) + .def("CalcEXP", (uint64(Lua_Client::*)(uint8))&Lua_Client::CalcEXP) + .def("CalcEXP", (uint64(Lua_Client::*)(uint8,bool))&Lua_Client::CalcEXP) .def("CalcPriceMod", (float(Lua_Client::*)(Lua_Mob,bool))&Lua_Client::CalcPriceMod) + .def("CampAllBots", (void(Lua_Client::*)(void))&Lua_Client::CampAllBots) + .def("CampAllBots", (void(Lua_Client::*)(uint8))&Lua_Client::CampAllBots) + .def("CanEnterZone", (bool(Lua_Client::*)(std::string))&Lua_Client::CanEnterZone) + .def("CanEnterZone", (bool(Lua_Client::*)(std::string,int16))&Lua_Client::CanEnterZone) .def("CanHaveSkill", (bool(Lua_Client::*)(int))&Lua_Client::CanHaveSkill) - .def("ChangeLastName", (void(Lua_Client::*)(const char *in))&Lua_Client::ChangeLastName) + .def("CashReward", &Lua_Client::CashReward) + .def("ChangeLastName", (void(Lua_Client::*)(std::string))&Lua_Client::ChangeLastName) .def("CharacterID", (uint32(Lua_Client::*)(void))&Lua_Client::CharacterID) .def("CheckIncreaseSkill", (void(Lua_Client::*)(int,Lua_Mob))&Lua_Client::CheckIncreaseSkill) .def("CheckIncreaseSkill", (void(Lua_Client::*)(int,Lua_Mob,int))&Lua_Client::CheckIncreaseSkill) @@ -2573,6 +3087,7 @@ luabind::scope lua_register_client() { .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(luabind::object))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32, bool))&Lua_Client::CreateExpedition) + .def("CreateExpeditionFromTemplate", &Lua_Client::CreateExpeditionFromTemplate) .def("CreateTaskDynamicZone", &Lua_Client::CreateTaskDynamicZone) .def("DecreaseByID", (bool(Lua_Client::*)(uint32,int))&Lua_Client::DecreaseByID) .def("DeleteItemInInventory", (void(Lua_Client::*)(int,int))&Lua_Client::DeleteItemInInventory) @@ -2592,6 +3107,8 @@ luabind::scope lua_register_client() { .def("EnableAreaHPRegen", &Lua_Client::EnableAreaHPRegen) .def("EnableAreaManaRegen", &Lua_Client::EnableAreaManaRegen) .def("EnableAreaRegens", &Lua_Client::EnableAreaRegens) + .def("EndSharedTask", (void(Lua_Client::*)(void))&Lua_Client::EndSharedTask) + .def("EndSharedTask", (void(Lua_Client::*)(bool))&Lua_Client::EndSharedTask) .def("Escape", (void(Lua_Client::*)(void))&Lua_Client::Escape) .def("FailTask", (void(Lua_Client::*)(int))&Lua_Client::FailTask) .def("FilteredMessage", &Lua_Client::FilteredMessage) @@ -2599,6 +3116,9 @@ luabind::scope lua_register_client() { .def("FindMemmedSpellBySlot", (uint16(Lua_Client::*)(int))&Lua_Client::FindMemmedSpellBySlot) .def("FindMemmedSpellBySpellID", (int(Lua_Client::*)(uint16))&Lua_Client::FindMemmedSpellBySpellID) .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) + .def("Fling", (void(Lua_Client::*)(float,float,float))&Lua_Client::Fling) + .def("Fling", (void(Lua_Client::*)(float,float,float,bool))&Lua_Client::Fling) + .def("Fling", (void(Lua_Client::*)(float,float,float,bool,bool))&Lua_Client::Fling) .def("Fling", (void(Lua_Client::*)(float,float,float,float))&Lua_Client::Fling) .def("Fling", (void(Lua_Client::*)(float,float,float,float,bool))&Lua_Client::Fling) .def("Fling", (void(Lua_Client::*)(float,float,float,float,bool,bool))&Lua_Client::Fling) @@ -2606,6 +3126,7 @@ luabind::scope lua_register_client() { .def("ForageItem", (void(Lua_Client::*)(void))&Lua_Client::ForageItem) .def("Freeze", (void(Lua_Client::*)(void))&Lua_Client::Freeze) .def("GetAAEXPModifier", (double(Lua_Client::*)(uint32))&Lua_Client::GetAAEXPModifier) + .def("GetAAEXPModifier", (double(Lua_Client::*)(uint32,int16))&Lua_Client::GetAAEXPModifier) .def("GetAAExp", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAExp) .def("GetAAPercent", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAPercent) .def("GetAAPoints", (int(Lua_Client::*)(void))&Lua_Client::GetAAPoints) @@ -2617,6 +3138,7 @@ luabind::scope lua_register_client() { .def("GetAlternateCurrencyValue", (int(Lua_Client::*)(uint32))&Lua_Client::GetAlternateCurrencyValue) .def("GetAnon", (int(Lua_Client::*)(void))&Lua_Client::GetAnon) .def("GetAugmentIDAt", (int(Lua_Client::*)(int,int))&Lua_Client::GetAugmentIDAt) + .def("GetAugmentIDsBySlotID", (luabind::object(Lua_Client::*)(lua_State* L,int16))&Lua_Client::GetAugmentIDsBySlotID) .def("GetBaseAGI", (int(Lua_Client::*)(void))&Lua_Client::GetBaseAGI) .def("GetBaseCHA", (int(Lua_Client::*)(void))&Lua_Client::GetBaseCHA) .def("GetBaseDEX", (int(Lua_Client::*)(void))&Lua_Client::GetBaseDEX) @@ -2635,6 +3157,12 @@ luabind::scope lua_register_client() { .def("GetBindZ", (float(Lua_Client::*)(void))&Lua_Client::GetBindZ) .def("GetBindZoneID", (uint32(Lua_Client::*)(int))&Lua_Client::GetBindZoneID) .def("GetBindZoneID", (uint32(Lua_Client::*)(void))&Lua_Client::GetBindZoneID) + .def("GetBotCreationLimit", (uint32(Lua_Client::*)(void))&Lua_Client::GetBotCreationLimit) + .def("GetBotCreationLimit", (uint32(Lua_Client::*)(uint8))&Lua_Client::GetBotCreationLimit) + .def("GetBotRequiredLevel", (int(Lua_Client::*)(void))&Lua_Client::GetBotRequiredLevel) + .def("GetBotRequiredLevel", (int(Lua_Client::*)(uint8))&Lua_Client::GetBotRequiredLevel) + .def("GetBotSpawnLimit", (int(Lua_Client::*)(void))&Lua_Client::GetBotSpawnLimit) + .def("GetBotSpawnLimit", (int(Lua_Client::*)(uint8))&Lua_Client::GetBotSpawnLimit) .def("GetCarriedMoney", (uint64(Lua_Client::*)(void))&Lua_Client::GetCarriedMoney) .def("GetCarriedPlatinum", (uint32(Lua_Client::*)(void))&Lua_Client::GetCarriedPlatinum) .def("GetCharacterFactionLevel", (int(Lua_Client::*)(int))&Lua_Client::GetCharacterFactionLevel) @@ -2650,6 +3178,7 @@ luabind::scope lua_register_client() { .def("GetDuelTarget", (int(Lua_Client::*)(void))&Lua_Client::GetDuelTarget) .def("GetEXP", (uint32(Lua_Client::*)(void))&Lua_Client::GetEXP) .def("GetEXPModifier", (double(Lua_Client::*)(uint32))&Lua_Client::GetEXPModifier) + .def("GetEXPModifier", (double(Lua_Client::*)(uint32,int16))&Lua_Client::GetEXPModifier) .def("GetEbonCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetEbonCrystals) .def("GetEndurance", (int(Lua_Client::*)(void))&Lua_Client::GetEndurance) .def("GetEndurancePercent", (int(Lua_Client::*)(void))&Lua_Client::GetEndurancePercent) @@ -2661,8 +3190,10 @@ luabind::scope lua_register_client() { .def("GetFactionLevel", (int(Lua_Client::*)(uint32,uint32,uint32,uint32,uint32,uint32,Lua_NPC))&Lua_Client::GetFactionLevel) .def("GetFeigned", (bool(Lua_Client::*)(void))&Lua_Client::GetFeigned) .def("GetGM", (bool(Lua_Client::*)(void))&Lua_Client::GetGM) + .def("GetGMStatus", (int16(Lua_Client::*)(void))&Lua_Client::GetGMStatus) .def("GetGroup", (Lua_Group(Lua_Client::*)(void))&Lua_Client::GetGroup) .def("GetGroupPoints", (uint32(Lua_Client::*)(void))&Lua_Client::GetGroupPoints) + .def("GetGuildPublicNote", (std::string(Lua_Client::*)(void))&Lua_Client::GetGuildPublicNote) .def("GetHorseId", (int(Lua_Client::*)(void))&Lua_Client::GetHorseId) .def("GetHealAmount", (int(Lua_Client::*)(void))&Lua_Client::GetHealAmount) .def("GetHunger", (int(Lua_Client::*)(void))&Lua_Client::GetHunger) @@ -2700,6 +3231,7 @@ luabind::scope lua_register_client() { .def("GetRaidPoints", (uint32(Lua_Client::*)(void))&Lua_Client::GetRaidPoints) .def("GetRawItemAC", (int(Lua_Client::*)(void))&Lua_Client::GetRawItemAC) .def("GetRawSkill", (int(Lua_Client::*)(int))&Lua_Client::GetRawSkill) + .def("GetRecipeMadeCount", (int(Lua_Client::*)(uint32))&Lua_Client::GetRecipeMadeCount) .def("GetScribeableSpells", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetScribeableSpells) .def("GetScribeableSpells", (luabind::object(Lua_Client::*)(lua_State* L,uint8))&Lua_Client::GetScribeableSpells) .def("GetScribeableSpells", (luabind::object(Lua_Client::*)(lua_State* L,uint8,uint8))&Lua_Client::GetScribeableSpells) @@ -2715,6 +3247,8 @@ luabind::scope lua_register_client() { .def("GetThirst", (int(Lua_Client::*)(void))&Lua_Client::GetThirst) .def("GetTotalSecondsPlayed", (uint32(Lua_Client::*)(void))&Lua_Client::GetTotalSecondsPlayed) .def("GetWeight", (int(Lua_Client::*)(void))&Lua_Client::GetWeight) + .def("GetPEQZoneFlags", (luabind::object(Lua_Client::*)(lua_State*))&Lua_Client::GetPEQZoneFlags) + .def("GetZoneFlags", (luabind::object(Lua_Client::*)(lua_State*))&Lua_Client::GetZoneFlags) .def("GoFish", (void(Lua_Client::*)(void))&Lua_Client::GoFish) .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int))&Lua_Client::GrantAlternateAdvancementAbility) .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int, bool))&Lua_Client::GrantAlternateAdvancementAbility) @@ -2725,6 +3259,7 @@ luabind::scope lua_register_client() { .def("HasExpeditionLockout", (bool(Lua_Client::*)(std::string, std::string))&Lua_Client::HasExpeditionLockout) .def("HasItemEquippedByID", (bool(Lua_Client::*)(uint32))&Lua_Client::HasItemEquippedByID) .def("HasPEQZoneFlag", (bool(Lua_Client::*)(uint32))&Lua_Client::HasPEQZoneFlag) + .def("HasRecipeLearned", (bool(Lua_Client::*)(uint32))&Lua_Client::HasRecipeLearned) .def("HasSkill", (bool(Lua_Client::*)(int))&Lua_Client::HasSkill) .def("HasSpellScribed", (bool(Lua_Client::*)(int))&Lua_Client::HasSpellScribed) .def("HasZoneFlag", (bool(Lua_Client::*)(uint32))&Lua_Client::HasZoneFlag) @@ -2739,6 +3274,7 @@ luabind::scope lua_register_client() { .def("IsCrouching", (bool(Lua_Client::*)(void))&Lua_Client::IsCrouching) .def("IsDead", &Lua_Client::IsDead) .def("IsDueling", (bool(Lua_Client::*)(void))&Lua_Client::IsDueling) + .def("IsEXPEnabled", (bool(Lua_Client::*)(void))&Lua_Client::IsEXPEnabled) .def("IsGrouped", (bool(Lua_Client::*)(void))&Lua_Client::IsGrouped) .def("IsLD", (bool(Lua_Client::*)(void))&Lua_Client::IsLD) .def("IsMedding", (bool(Lua_Client::*)(void))&Lua_Client::IsMedding) @@ -2756,9 +3292,14 @@ luabind::scope lua_register_client() { .def("LeaveGroup", (void(Lua_Client::*)(void))&Lua_Client::LeaveGroup) .def("LoadPEQZoneFlags", (void(Lua_Client::*)(void))&Lua_Client::LoadPEQZoneFlags) .def("LoadZoneFlags", (void(Lua_Client::*)(void))&Lua_Client::LoadZoneFlags) + .def("LockSharedTask", &Lua_Client::LockSharedTask) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float))&Lua_Client::MarkSingleCompassLoc) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float,int))&Lua_Client::MarkSingleCompassLoc) + .def("Marquee", (void(Lua_Client::*)(uint32, std::string))&Lua_Client::SendMarqueeMessage) + .def("Marquee", (void(Lua_Client::*)(uint32, std::string, uint32))&Lua_Client::SendMarqueeMessage) + .def("Marquee", (void(Lua_Client::*)(uint32, uint32, uint32, uint32, uint32, std::string))&Lua_Client::SendMarqueeMessage) .def("MaxSkill", (int(Lua_Client::*)(int))&Lua_Client::MaxSkill) + .def("MaxSkills", (void(Lua_Client::*)(void))&Lua_Client::MaxSkills) .def("MemSpell", (void(Lua_Client::*)(int,int))&Lua_Client::MemSpell) .def("MemSpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::MemSpell) .def("MemmedCount", (int(Lua_Client::*)(void))&Lua_Client::MemmedCount) @@ -2771,11 +3312,23 @@ luabind::scope lua_register_client() { .def("MovePCDynamicZone", (void(Lua_Client::*)(uint32, int, bool))&Lua_Client::MovePCDynamicZone) .def("MovePCInstance", (void(Lua_Client::*)(int,int,float,float,float,float))&Lua_Client::MovePCInstance) .def("MoveZone", (void(Lua_Client::*)(const char*))&Lua_Client::MoveZone) + .def("MoveZone", (void(Lua_Client::*)(const char*,float,float,float))&Lua_Client::MoveZone) + .def("MoveZone", (void(Lua_Client::*)(const char*,float,float,float,float))&Lua_Client::MoveZone) .def("MoveZoneGroup", (void(Lua_Client::*)(const char*))&Lua_Client::MoveZoneGroup) + .def("MoveZoneGroup", (void(Lua_Client::*)(const char*,float,float,float))&Lua_Client::MoveZoneGroup) + .def("MoveZoneGroup", (void(Lua_Client::*)(const char*,float,float,float,float))&Lua_Client::MoveZoneGroup) .def("MoveZoneInstance", (void(Lua_Client::*)(uint16))&Lua_Client::MoveZoneInstance) + .def("MoveZoneInstance", (void(Lua_Client::*)(uint16,float,float,float))&Lua_Client::MoveZoneInstance) + .def("MoveZoneInstance", (void(Lua_Client::*)(uint16,float,float,float,float))&Lua_Client::MoveZoneInstance) .def("MoveZoneInstanceGroup", (void(Lua_Client::*)(uint16))&Lua_Client::MoveZoneInstanceGroup) + .def("MoveZoneInstanceGroup", (void(Lua_Client::*)(uint16,float,float,float))&Lua_Client::MoveZoneInstanceGroup) + .def("MoveZoneInstanceGroup", (void(Lua_Client::*)(uint16,float,float,float,float))&Lua_Client::MoveZoneInstanceGroup) .def("MoveZoneInstanceRaid", (void(Lua_Client::*)(uint16))&Lua_Client::MoveZoneInstanceRaid) + .def("MoveZoneInstanceRaid", (void(Lua_Client::*)(uint16,float,float,float))&Lua_Client::MoveZoneInstanceRaid) + .def("MoveZoneInstanceRaid", (void(Lua_Client::*)(uint16,float,float,float,float))&Lua_Client::MoveZoneInstanceRaid) .def("MoveZoneRaid", (void(Lua_Client::*)(const char*))&Lua_Client::MoveZoneRaid) + .def("MoveZoneRaid", (void(Lua_Client::*)(const char*,float,float,float))&Lua_Client::MoveZoneRaid) + .def("MoveZoneRaid", (void(Lua_Client::*)(const char*,float,float,float,float))&Lua_Client::MoveZoneRaid) .def("NotifyNewTitlesAvailable", (void(Lua_Client::*)(void))&Lua_Client::NotifyNewTitlesAvailable) .def("NukeItem", (void(Lua_Client::*)(uint32))&Lua_Client::NukeItem) .def("NukeItem", (void(Lua_Client::*)(uint32,int))&Lua_Client::NukeItem) @@ -2816,10 +3369,12 @@ luabind::scope lua_register_client() { .def("ResetAA", (void(Lua_Client::*)(void))&Lua_Client::ResetAA) .def("ResetAllDisciplineTimers", (void(Lua_Client::*)(void))&Lua_Client::ResetAllDisciplineTimers) .def("ResetAllCastbarCooldowns", (void(Lua_Client::*)(void))&Lua_Client::ResetAllCastbarCooldowns) + .def("ResetAlternateAdvancementRank", &Lua_Client::ResetAlternateAdvancementRank) .def("ResetCastbarCooldownBySlot", (void(Lua_Client::*)(int))&Lua_Client::ResetCastbarCooldownBySlot) .def("ResetCastbarCooldownBySpellID", (void(Lua_Client::*)(uint32))&Lua_Client::ResetCastbarCooldownBySpellID) .def("ResetDisciplineTimer", (void(Lua_Client::*)(uint32))&Lua_Client::ResetDisciplineTimer) .def("ResetTrade", (void(Lua_Client::*)(void))&Lua_Client::ResetTrade) + .def("RewardFaction", (void(Lua_Client::*)(int,int))&Lua_Client::RewardFaction) .def("Save", (void(Lua_Client::*)(int))&Lua_Client::Save) .def("Save", (void(Lua_Client::*)(void))&Lua_Client::Save) .def("SaveBackup", (void(Lua_Client::*)(void))&Lua_Client::SaveBackup) @@ -2828,17 +3383,26 @@ luabind::scope lua_register_client() { .def("ScribeSpells", (uint16(Lua_Client::*)(uint8,uint8))&Lua_Client::ScribeSpells) .def("SendColoredText", (void(Lua_Client::*)(uint32, std::string))&Lua_Client::SendColoredText) .def("SendItemScale", (void(Lua_Client::*)(Lua_ItemInst))&Lua_Client::SendItemScale) + .def("SendGMCommand", (bool(Lua_Client::*)(std::string))&Lua_Client::SendGMCommand) + .def("SendGMCommand", (bool(Lua_Client::*)(std::string,bool))&Lua_Client::SendGMCommand) + .def("SendMarqueeMessage", (void(Lua_Client::*)(uint32, std::string))&Lua_Client::SendMarqueeMessage) + .def("SendMarqueeMessage", (void(Lua_Client::*)(uint32, std::string, uint32))&Lua_Client::SendMarqueeMessage) .def("SendMarqueeMessage", (void(Lua_Client::*)(uint32, uint32, uint32, uint32, uint32, std::string))&Lua_Client::SendMarqueeMessage) .def("SendOPTranslocateConfirm", (void(Lua_Client::*)(Lua_Mob,int))&Lua_Client::SendOPTranslocateConfirm) + .def("SendPath", (void(Lua_Client::*)(Lua_Mob))&Lua_Client::SendPath) .def("SendPEQZoneFlagInfo", (void(Lua_Client::*)(Lua_Client))&Lua_Client::SendPEQZoneFlagInfo) .def("SendSound", (void(Lua_Client::*)(void))&Lua_Client::SendSound) .def("SendToGuildHall", (void(Lua_Client::*)(void))&Lua_Client::SendToGuildHall) .def("SendToInstance", (void(Lua_Client::*)(std::string,std::string,uint32,float,float,float,float,std::string,uint32))&Lua_Client::SendToInstance) + .def("SendPayload", (void(Lua_Client::*)(int))&Lua_Client::SendPayload) + .def("SendPayload", (void(Lua_Client::*)(int,std::string))&Lua_Client::SendPayload) .def("SendWebLink", (void(Lua_Client::*)(const char *))&Lua_Client::SendWebLink) .def("SendZoneFlagInfo", (void(Lua_Client::*)(Lua_Client))&Lua_Client::SendZoneFlagInfo) .def("SetAAEXPModifier", (void(Lua_Client::*)(uint32,double))&Lua_Client::SetAAEXPModifier) + .def("SetAAEXPModifier", (void(Lua_Client::*)(uint32,double,int16))&Lua_Client::SetAAEXPModifier) .def("SetAAPoints", (void(Lua_Client::*)(int))&Lua_Client::SetAAPoints) - .def("SetAATitle", (void(Lua_Client::*)(const char *))&Lua_Client::SetAATitle) + .def("SetAATitle", (void(Lua_Client::*)(std::string))&Lua_Client::SetAATitle) + .def("SetAATitle", (void(Lua_Client::*)(std::string,bool))&Lua_Client::SetAATitle) .def("SetAFK", (void(Lua_Client::*)(uint8))&Lua_Client::SetAFK) .def("SetAccountFlag", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetAccountFlag) .def("SetAccountFlag", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetAccountFlag) @@ -2854,14 +3418,22 @@ luabind::scope lua_register_client() { .def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float,float))&Lua_Client::SetBindPoint) .def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float,float,float))&Lua_Client::SetBindPoint) .def("SetBindPoint", (void(Lua_Client::*)(void))&Lua_Client::SetBindPoint) + .def("SetBotCreationLimit", (void(Lua_Client::*)(uint32))&Lua_Client::SetBotCreationLimit) + .def("SetBotCreationLimit", (void(Lua_Client::*)(uint32,uint8))&Lua_Client::SetBotCreationLimit) + .def("SetBotRequiredLevel", (void(Lua_Client::*)(int))&Lua_Client::SetBotRequiredLevel) + .def("SetBotRequiredLevel", (void(Lua_Client::*)(int,uint8))&Lua_Client::SetBotRequiredLevel) + .def("SetBotSpawnLimit", (void(Lua_Client::*)(int))&Lua_Client::SetBotSpawnLimit) + .def("SetBotSpawnLimit", (void(Lua_Client::*)(int,uint8))&Lua_Client::SetBotSpawnLimit) .def("SetClientMaxLevel", (void(Lua_Client::*)(int))&Lua_Client::SetClientMaxLevel) .def("SetConsumption", (void(Lua_Client::*)(int, int))&Lua_Client::SetConsumption) .def("SetDeity", (void(Lua_Client::*)(int))&Lua_Client::SetDeity) .def("SetDuelTarget", (void(Lua_Client::*)(int))&Lua_Client::SetDuelTarget) .def("SetDueling", (void(Lua_Client::*)(bool))&Lua_Client::SetDueling) - .def("SetEXP", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::SetEXP) - .def("SetEXP", (void(Lua_Client::*)(uint32,uint32,bool))&Lua_Client::SetEXP) + .def("SetEXP", (void(Lua_Client::*)(uint64,uint64))&Lua_Client::SetEXP) + .def("SetEXP", (void(Lua_Client::*)(uint64,uint64,bool))&Lua_Client::SetEXP) + .def("SetEXPEnabled", (void(Lua_Client::*)(bool))&Lua_Client::SetEXPEnabled) .def("SetEXPModifier", (void(Lua_Client::*)(uint32,double))&Lua_Client::SetEXPModifier) + .def("SetEXPModifier", (void(Lua_Client::*)(uint32,double,int16))&Lua_Client::SetEXPModifier) .def("SetEbonCrystals", (void(Lua_Client::*)(uint32))&Lua_Client::SetEbonCrystals) .def("SetEndurance", (void(Lua_Client::*)(int))&Lua_Client::SetEndurance) .def("SetEnvironmentDamageModifier", (void(Lua_Client::*)(int))&Lua_Client::SetEnvironmentDamageModifier) @@ -2869,7 +3441,7 @@ luabind::scope lua_register_client() { .def("SetFactionLevel2", (void(Lua_Client::*)(uint32,int,int,int,int,int,int))&Lua_Client::SetFactionLevel2) .def("SetFeigned", (void(Lua_Client::*)(bool))&Lua_Client::SetFeigned) .def("SetGM", (void(Lua_Client::*)(bool))&Lua_Client::SetGM) - .def("SetGMStatus", (void(Lua_Client::*)(int32))&Lua_Client::SetGMStatus) + .def("SetGMStatus", (void(Lua_Client::*)(int16))&Lua_Client::SetGMStatus) .def("SetHideMe", (void(Lua_Client::*)(bool))&Lua_Client::SetHideMe) .def("SetHorseId", (void(Lua_Client::*)(int))&Lua_Client::SetHorseId) .def("SetHunger", (void(Lua_Client::*)(int))&Lua_Client::SetHunger) @@ -2884,6 +3456,19 @@ luabind::scope lua_register_client() { .def("SetSecondaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetSecondaryWeaponOrnamentation) .def("SetSkill", (void(Lua_Client::*)(int,int))&Lua_Client::SetSkill) .def("SetSkillPoints", (void(Lua_Client::*)(int))&Lua_Client::SetSkillPoints) + .def("SetSpellDuration", (void(Lua_Client::*)(int))&Lua_Client::SetSpellDuration) + .def("SetSpellDuration", (void(Lua_Client::*)(int,int))&Lua_Client::SetSpellDuration) + .def("SetSpellDuration", (void(Lua_Client::*)(int,int,bool))&Lua_Client::SetSpellDuration) + .def("SetSpellDuration", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::SetSpellDuration) + .def("SetSpellDurationGroup", (void(Lua_Client::*)(int))&Lua_Client::SetSpellDurationGroup) + .def("SetSpellDurationGroup", (void(Lua_Client::*)(int,int))&Lua_Client::SetSpellDurationGroup) + .def("SetSpellDurationGroup", (void(Lua_Client::*)(int,int,bool))&Lua_Client::SetSpellDurationGroup) + .def("SetSpellDurationGroup", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::SetSpellDurationGroup) + .def("SetSpellDurationRaid", (void(Lua_Client::*)(int))&Lua_Client::SetSpellDurationRaid) + .def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int))&Lua_Client::SetSpellDurationRaid) + .def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int,bool))&Lua_Client::SetSpellDurationRaid) + .def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::SetSpellDurationRaid) + .def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int,bool,bool,bool))&Lua_Client::SetSpellDurationRaid) .def("SetStartZone", (void(Lua_Client::*)(int))&Lua_Client::SetStartZone) .def("SetStartZone", (void(Lua_Client::*)(int,float))&Lua_Client::SetStartZone) .def("SetStartZone", (void(Lua_Client::*)(int,float,float))&Lua_Client::SetStartZone) @@ -2893,7 +3478,7 @@ luabind::scope lua_register_client() { .def("SetTint", (void(Lua_Client::*)(int,uint32))&Lua_Client::SetTint) .def("SetTitleSuffix", (void(Lua_Client::*)(const char *))&Lua_Client::SetTitleSuffix) .def("SetZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::SetZoneFlag) - .def("Signal", (void(Lua_Client::*)(uint32))&Lua_Client::Signal) + .def("Signal", (void(Lua_Client::*)(int))&Lua_Client::Signal) .def("Sit", (void(Lua_Client::*)(void))&Lua_Client::Sit) .def("Stand", (void(Lua_Client::*)(void))&Lua_Client::Stand) .def("SummonBaggedItems", (void(Lua_Client::*)(uint32,luabind::adl::object))&Lua_Client::SummonBaggedItems) @@ -2912,6 +3497,13 @@ luabind::scope lua_register_client() { .def("TakePlatinum", (bool(Lua_Client::*)(uint32))&Lua_Client::TakePlatinum) .def("TakePlatinum", (bool(Lua_Client::*)(uint32,bool))&Lua_Client::TakePlatinum) .def("TaskSelector", (void(Lua_Client::*)(luabind::adl::object))&Lua_Client::TaskSelector) + .def("TaskSelector", (void(Lua_Client::*)(luabind::adl::object, bool))&Lua_Client::TaskSelector) + .def("TeleportToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportToPlayerByCharID) + .def("TeleportToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportToPlayerByName) + .def("TeleportGroupToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportGroupToPlayerByCharID) + .def("TeleportGroupToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportGroupToPlayerByName) + .def("TeleportRaidToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportRaidToPlayerByCharID) + .def("TeleportRaidToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportRaidToPlayerByName) .def("Thirsty", (bool(Lua_Client::*)(void))&Lua_Client::Thirsty) .def("TrainDisc", (void(Lua_Client::*)(int))&Lua_Client::TrainDisc) .def("TrainDiscBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::TrainDiscBySpellID) @@ -2934,6 +3526,8 @@ luabind::scope lua_register_client() { .def("UntrainDiscAll", (void(Lua_Client::*)(void))&Lua_Client::UntrainDiscAll) .def("UntrainDiscBySpellID", (void(Lua_Client::*)(uint16))&Lua_Client::UntrainDiscBySpellID) .def("UntrainDiscBySpellID", (void(Lua_Client::*)(uint16,bool))&Lua_Client::UntrainDiscBySpellID) + .def("UpdateAdmin", (void(Lua_Client::*)(void))&Lua_Client::UpdateAdmin) + .def("UpdateAdmin", (void(Lua_Client::*)(bool))&Lua_Client::UpdateAdmin) .def("UpdateGroupAAs", (void(Lua_Client::*)(int,uint32))&Lua_Client::UpdateGroupAAs) .def("UpdateLDoNPoints", (void(Lua_Client::*)(uint32,int))&Lua_Client::UpdateLDoNPoints) .def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity) @@ -2944,13 +3538,13 @@ luabind::scope lua_register_client() { luabind::scope lua_register_inventory_where() { return luabind::class_("InventoryWhere") .enum_("constants") - [ + [( luabind::value("Personal", static_cast(invWherePersonal)), luabind::value("Bank", static_cast(invWhereBank)), luabind::value("SharedBank", static_cast(invWhereSharedBank)), luabind::value("Trading", static_cast(invWhereTrading)), luabind::value("Cursor", static_cast(invWhereCursor)) - ]; + )]; } diff --git a/zone/lua_client.h b/zone/lua_client.h index 0060631b8..187b841a4 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -73,9 +73,13 @@ public: int GetWeight(); uint32 GetEXP(); double GetEXPModifier(uint32 zone_id); + double GetEXPModifier(uint32 zone_id, int16 instance_version); double GetAAEXPModifier(uint32 zone_id); + double GetAAEXPModifier(uint32 zone_id, int16 instance_version); void SetAAEXPModifier(uint32 zone_id, double aa_modifier); + void SetAAEXPModifier(uint32 zone_id, double aa_modifier, int16 instance_version); void SetEXPModifier(uint32 zone_id, double exp_modifier); + void SetEXPModifier(uint32 zone_id, double exp_modifier, int16 instance_version); uint32 GetAAExp(); uint32 GetAAPercent(); uint32 GetTotalSecondsPlayed(); @@ -88,8 +92,8 @@ public: void AddEXP(uint32 add_exp); void AddEXP(uint32 add_exp, int conlevel); void AddEXP(uint32 add_exp, int conlevel, bool resexp); - void SetEXP(uint32 set_exp, uint32 set_aaxp); - void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp); + void SetEXP(uint64 set_exp, uint64 set_aaxp); + void SetEXP(uint64 set_exp, uint64 set_aaxp, bool resexp); void SetBindPoint(); void SetBindPoint(int to_zone); void SetBindPoint(int to_zone, int to_instance); @@ -113,19 +117,38 @@ public: void MovePC(int zone, float x, float y, float z, float heading); void MovePCInstance(int zone, int instance, float x, float y, float z, float heading); void MoveZone(const char *zone_short_name); + void MoveZone(const char *zone_short_name, float x, float y, float z); + void MoveZone(const char *zone_short_name, float x, float y, float z, float heading); void MoveZoneGroup(const char *zone_short_name); + void MoveZoneGroup(const char *zone_short_name, float x, float y, float z); + void MoveZoneGroup(const char *zone_short_name, float x, float y, float z, float heading); void MoveZoneRaid(const char *zone_short_name); + void MoveZoneRaid(const char *zone_short_name, float x, float y, float z); + void MoveZoneRaid(const char *zone_short_name, float x, float y, float z, float heading); void MoveZoneInstance(uint16 instance_id); + void MoveZoneInstance(uint16 instance_id, float x, float y, float z); + void MoveZoneInstance(uint16 instance_id, float x, float y, float z, float heading); void MoveZoneInstanceGroup(uint16 instance_id); + void MoveZoneInstanceGroup(uint16 instance_id, float x, float y, float z); + void MoveZoneInstanceGroup(uint16 instance_id, float x, float y, float z, float heading); void MoveZoneInstanceRaid(uint16 instance_id); - void ChangeLastName(const char *in); + void MoveZoneInstanceRaid(uint16 instance_id, float x, float y, float z); + void MoveZoneInstanceRaid(uint16 instance_id, float x, float y, float z, float heading); + bool TeleportToPlayerByCharID(uint32 character_id); + bool TeleportToPlayerByName(std::string player_name); + bool TeleportGroupToPlayerByCharID(uint32 character_id); + bool TeleportGroupToPlayerByName(std::string player_name); + bool TeleportRaidToPlayerByCharID(uint32 character_id); + bool TeleportRaidToPlayerByName(std::string player_name); + void ChangeLastName(std::string last_name); int GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 race, uint32 class_, uint32 deity, uint32 faction, Lua_NPC npc); void SetFactionLevel(uint32 char_id, uint32 npc_id, int char_class, int char_race, int char_deity); void SetFactionLevel2(uint32 char_id, int faction_id, int char_class, int char_race, int char_deity, int value, int temp); + void RewardFaction(int id, int amount); int GetRawItemAC(); uint32 AccountID(); const char *AccountName(); - int Admin(); + int16 Admin(); uint32 CharacterID(); int GuildRank(); uint32 GuildID(); @@ -265,7 +288,8 @@ public: void LoadPEQZoneFlags(); void SendPEQZoneFlagInfo(Lua_Client to); void SetPEQZoneFlag(uint32 zone_id); - void SetAATitle(const char *title); + void SetAATitle(std::string title); + void SetAATitle(std::string title, bool save_to_database); int GetClientVersion(); uint32 GetClientVersionBit(); void SetTitleSuffix(const char *text); @@ -299,7 +323,9 @@ public: void UpdateGroupAAs(int points, uint32 type); uint32 GetGroupPoints(); uint32 GetRaidPoints(); - void LearnRecipe(uint32 recipe); + void LearnRecipe(uint32 recipe_id); + int GetRecipeMadeCount(uint32 recipe_id); + bool HasRecipeLearned(uint32 recipe_id); int GetEndurance(); int GetMaxEndurance(); int GetEndurancePercent(); @@ -315,6 +341,7 @@ public: void IncrementAA(int aa); bool GrantAlternateAdvancementAbility(int aa_id, int points); bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost); + void ResetAlternateAdvancementRank(int aa_id); void MarkSingleCompassLoc(float in_x, float in_y, float in_z); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count); void ClearCompassMark(); @@ -332,6 +359,9 @@ public: bool IsTaskCompleted(int task); bool IsTaskActive(int task); bool IsTaskActivityActive(int task, int activity); + void LockSharedTask(bool lock); + void EndSharedTask(); + void EndSharedTask(bool send_fail); int GetCorpseCount(); int GetCorpseID(int corpse); int GetCorpseItemAt(int corpse, int slot); @@ -345,7 +375,7 @@ public: uint32 GetMoney(uint8 type, uint8 subtype); void OpenLFGuildWindow(); void NotifyNewTitlesAvailable(); - void Signal(uint32 id); + void Signal(int signal_id); void AddAlternateCurrencyValue(uint32 currency, int amount); void SetAlternateCurrencyValue(uint32 currency, int amount); int GetAlternateCurrencyValue(uint32 currency); @@ -369,7 +399,9 @@ public: void SetHunger(int in_hunger); void SetThirst(int in_thirst); void SetConsumption(int in_hunger, int in_thirst); - void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg); + void SendMarqueeMessage(uint32 type, std::string message); + void SendMarqueeMessage(uint32 type, std::string message, uint32 duration); + void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message); void SendColoredText(uint32 type, std::string msg); void PlayMP3(std::string file); void QuestReward(Lua_Mob target); @@ -381,6 +413,7 @@ public: void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp); void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction); void QuestReward(Lua_Mob target, luabind::adl::object reward); + void CashReward(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); bool IsDead(); int CalcCurrentWeight(); int CalcATK(); @@ -404,7 +437,8 @@ public: int CountItem(uint32 item_id); void RemoveItem(uint32 item_id); void RemoveItem(uint32 item_id, uint32 quantity); - void SetGMStatus(uint32 newStatus); + void SetGMStatus(int16 new_status); + int16 GetGMStatus(); void AddItem(luabind::object item_table); int CountAugmentEquippedByID(uint32 item_id); int CountItemEquippedByID(uint32 item_id); @@ -412,6 +446,55 @@ public: bool HasItemEquippedByID(uint32 item_id); int GetHealAmount(); int GetSpellDamage(); + void UpdateAdmin(); + void UpdateAdmin(bool from_database); + luabind::object GetPEQZoneFlags(lua_State* L); + luabind::object GetZoneFlags(lua_State* L); + void SendPayload(int payload_id); + void SendPayload(int payload_id, std::string payload_value); + std::string GetGuildPublicNote(); + void MaxSkills(); + luabind::object GetAugmentIDsBySlotID(lua_State* L, int16 slot_id); + bool IsEXPEnabled(); + void SetEXPEnabled(bool is_exp_enabled); + uint64 CalcEXP(uint8 consider_level); + uint64 CalcEXP(uint8 consider_level, bool ignore_modifiers); + bool CanEnterZone(std::string zone_short_name); + bool CanEnterZone(std::string zone_short_name, int16 instance_version); + void SendPath(Lua_Mob target); + + void ApplySpell(int spell_id); + void ApplySpell(int spell_id, int duration); + void ApplySpell(int spell_id, int duration, bool allow_pets); + void ApplySpell(int spell_id, int duration, bool allow_pets, bool allow_bots); + + void ApplySpellGroup(int spell_id); + void ApplySpellGroup(int spell_id, int duration); + void ApplySpellGroup(int spell_id, int duration, bool allow_pets); + void ApplySpellGroup(int spell_id, int duration, bool allow_pets, bool allow_bots); + + void ApplySpellRaid(int spell_id); + void ApplySpellRaid(int spell_id, int duration); + void ApplySpellRaid(int spell_id, int duration, bool allow_pets); + void ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only); + void ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots); + + void SetSpellDuration(int spell_id); + void SetSpellDuration(int spell_id, int duration); + void SetSpellDuration(int spell_id, int duration, bool allow_pets); + void SetSpellDuration(int spell_id, int duration, bool allow_pets, bool allow_bots); + + void SetSpellDurationGroup(int spell_id); + void SetSpellDurationGroup(int spell_id, int duration); + void SetSpellDurationGroup(int spell_id, int duration, bool allow_pets); + void SetSpellDurationGroup(int spell_id, int duration, bool allow_pets, bool allow_bots); + + void SetSpellDurationRaid(int spell_id); + void SetSpellDurationRaid(int spell_id, int duration); + void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets); + void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only); + void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots); + int GetEnvironmentDamageModifier(); void SetEnvironmentDamageModifier(int value); @@ -421,15 +504,35 @@ public: void SetPrimaryWeaponOrnamentation(uint32 model_id); void SetSecondaryWeaponOrnamentation(uint32 model_id); void TaskSelector(luabind::adl::object table); + void TaskSelector(luabind::adl::object table, bool ignore_cooldown); - void SetClientMaxLevel(int value); - int GetClientMaxLevel(); + void SetClientMaxLevel(uint8 max_level); + uint8 GetClientMaxLevel(); + + bool SendGMCommand(std::string message); + bool SendGMCommand(std::string message, bool ignore_status); + + int GetBotRequiredLevel(); + int GetBotRequiredLevel(uint8 class_id); + uint32 GetBotCreationLimit(); + uint32 GetBotCreationLimit(uint8 class_id); + int GetBotSpawnLimit(); + int GetBotSpawnLimit(uint8 class_id); + void SetBotRequiredLevel(int new_required_level); + void SetBotRequiredLevel(int new_required_level, uint8 class_id); + void SetBotCreationLimit(uint32 new_creation_limit); + void SetBotCreationLimit(uint32 new_creation_limit, uint8 class_id); + void SetBotSpawnLimit(int new_spawn_limit); + void SetBotSpawnLimit(int new_spawn_limit, uint8 class_id); + void CampAllBots(); + void CampAllBots(uint8 class_id); void DialogueWindow(std::string markdown); Lua_Expedition CreateExpedition(luabind::object expedition_info); Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players); Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages); + Lua_Expedition CreateExpeditionFromTemplate(uint32_t dz_template_id); Lua_Expedition GetExpedition(); luabind::object GetExpeditionLockouts(lua_State* L); luabind::object GetExpeditionLockouts(lua_State* L, std::string expedition_name); @@ -449,9 +552,12 @@ public: void MovePCDynamicZone(std::string zone_name, int zone_version); void MovePCDynamicZone(std::string zone_name, int zone_version, bool msg_if_invalid); void CreateTaskDynamicZone(int task_id, luabind::object dz_table); + void Fling(float target_x, float target_y, float target_z); + void Fling(float target_x, float target_y, float target_z, bool ignore_los); + void Fling(float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls); void Fling(float value, float target_x, float target_y, float target_z); void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los); - void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clipping); + void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls); }; #endif diff --git a/zone/lua_corpse.cpp b/zone/lua_corpse.cpp index d1f5039c7..b1bb650ad 100644 --- a/zone/lua_corpse.cpp +++ b/zone/lua_corpse.cpp @@ -82,6 +82,16 @@ uint32 Lua_Corpse::CountItems() { return self->CountItems(); } +void Lua_Corpse::AddItem(uint32 itemnum, uint16 charges) { + Lua_Safe_Call_Void(); + self->AddItem(itemnum, charges); +} + +void Lua_Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot) { + Lua_Safe_Call_Void(); + self->AddItem(itemnum, charges, slot); +} + void Lua_Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) { Lua_Safe_Call_Void(); self->AddItem(itemnum, charges, slot, aug1, aug2, aug3, aug4, aug5); @@ -112,6 +122,11 @@ bool Lua_Corpse::IsEmpty() { return self->IsEmpty(); } +void Lua_Corpse::ResetDecayTimer() { + Lua_Safe_Call_Void(); + self->ResetDecayTimer(); +} + void Lua_Corpse::SetDecayTimer(uint32 decaytime) { Lua_Safe_Call_Void(); self->SetDecayTimer(decaytime); @@ -204,6 +219,8 @@ luabind::scope lua_register_corpse() { .def(luabind::constructor<>()) .property("null", &Lua_Corpse::Null) .property("valid", &Lua_Corpse::Valid) + .def("AddItem", (void(Lua_Corpse::*)(uint32, uint16))&Lua_Corpse::AddItem) + .def("AddItem", (void(Lua_Corpse::*)(uint32, uint16, int16))&Lua_Corpse::AddItem) .def("AddItem", (void(Lua_Corpse::*)(uint32, uint16, int16, uint32, uint32, uint32, uint32, uint32))&Lua_Corpse::AddItem) .def("AddLooter", (void(Lua_Corpse::*)(Lua_Mob))&Lua_Corpse::AddLooter) .def("AllowMobLoot", (void(Lua_Corpse::*)(Lua_Mob, uint8))&Lua_Corpse::AllowMobLoot) @@ -234,6 +251,7 @@ luabind::scope lua_register_corpse() { .def("RemoveItem", (void(Lua_Corpse::*)(uint16))&Lua_Corpse::RemoveItem) .def("RemoveItemByID", (void(Lua_Corpse::*)(uint32))&Lua_Corpse::RemoveItemByID) .def("RemoveItemByID", (void(Lua_Corpse::*)(uint32,int))&Lua_Corpse::RemoveItemByID) + .def("ResetDecayTimer", &Lua_Corpse::ResetDecayTimer) .def("ResetLooter", (void(Lua_Corpse::*)(void))&Lua_Corpse::ResetLooter) .def("Save", (bool(Lua_Corpse::*)(void))&Lua_Corpse::Save) .def("SetCash", (void(Lua_Corpse::*)(uint32, uint32, uint32, uint32))&Lua_Corpse::SetCash) diff --git a/zone/lua_corpse.h b/zone/lua_corpse.h index 0df694b51..e569f7b7c 100644 --- a/zone/lua_corpse.h +++ b/zone/lua_corpse.h @@ -41,6 +41,8 @@ public: void Bury(); void Depop(); uint32 CountItems(); + void AddItem(uint32 itemnum, uint16 charges); + void AddItem(uint32 itemnum, uint16 charges, int16 slot); void AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5); uint32 GetWornItem(int16 equipSlot); void RemoveItem(uint16 lootslot); @@ -49,6 +51,7 @@ public: void SetCash(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); void RemoveCash(); bool IsEmpty(); + void ResetDecayTimer(); void SetDecayTimer(uint32 decaytime); bool CanMobLoot(int charid); void AllowMobLoot(Lua_Mob them, uint8 slot); diff --git a/zone/lua_door.cpp b/zone/lua_door.cpp index bb10e4035..a19ab8609 100644 --- a/zone/lua_door.cpp +++ b/zone/lua_door.cpp @@ -176,6 +176,11 @@ void Lua_Door::ForceClose(Lua_Mob sender, bool alt_mode) { self->ForceClose(sender, alt_mode); } +uint32 Lua_Door::GetID() { + Lua_Safe_Call_Int(); + return self->GetID(); +} + luabind::scope lua_register_door() { return luabind::class_("Door") .def(luabind::constructor<>()) @@ -191,6 +196,7 @@ luabind::scope lua_register_door() { .def("GetDoorID", (uint32(Lua_Door::*)(void))&Lua_Door::GetDoorID) .def("GetDoorName", (const char*(Lua_Door::*)(void))&Lua_Door::GetDoorName) .def("GetHeading", (float(Lua_Door::*)(void))&Lua_Door::GetHeading) + .def("GetID", (uint32(Lua_Door::*)(void))&Lua_Door::GetID) .def("GetIncline", (uint32(Lua_Door::*)(void))&Lua_Door::GetIncline) .def("GetKeyItem", (uint32(Lua_Door::*)(void))&Lua_Door::GetKeyItem) .def("GetLockPick", (uint32(Lua_Door::*)(void))&Lua_Door::GetLockPick) diff --git a/zone/lua_door.h b/zone/lua_door.h index f445e48ea..96b5784f0 100644 --- a/zone/lua_door.h +++ b/zone/lua_door.h @@ -62,6 +62,7 @@ public: void ForceOpen(Lua_Mob sender, bool alt_mode); void ForceClose(Lua_Mob sender); void ForceClose(Lua_Mob sender, bool alt_mode); + uint32 GetID(); }; #endif diff --git a/zone/lua_entity.cpp b/zone/lua_entity.cpp index 045a7e6a7..d0ce95c7f 100644 --- a/zone/lua_entity.cpp +++ b/zone/lua_entity.cpp @@ -12,9 +12,7 @@ #include "lua_object.h" #include "lua_door.h" -#ifdef BOTS #include "lua_bot.h" -#endif bool Lua_Entity::IsClient() { Lua_Safe_Call_Bool(); @@ -122,22 +120,18 @@ Lua_Door Lua_Entity::CastToDoor() { return Lua_Door(m); } -#ifdef BOTS Lua_Bot Lua_Entity::CastToBot() { void *d = GetLuaPtrData(); Bot *b = reinterpret_cast(d); return Lua_Bot(b); } -#endif luabind::scope lua_register_entity() { return luabind::class_("Entity") .def(luabind::constructor<>()) .property("null", &Lua_Entity::Null) .property("valid", &Lua_Entity::Valid) -#ifdef BOTS .def("CastToBot", &Lua_Entity::CastToBot) -#endif .def("CastToClient", &Lua_Entity::CastToClient) .def("CastToCorpse", &Lua_Entity::CastToCorpse) .def("CastToDoor", &Lua_Entity::CastToDoor) diff --git a/zone/lua_entity.h b/zone/lua_entity.h index 4954d13ff..5d7d5447e 100644 --- a/zone/lua_entity.h +++ b/zone/lua_entity.h @@ -6,9 +6,7 @@ class Entity; class Lua_Client; -#ifdef BOTS class Lua_Bot; -#endif class Lua_NPC; class Lua_Mob; struct Lua_HateList; @@ -57,10 +55,8 @@ public: Lua_Corpse CastToCorpse(); Lua_Object CastToObject(); Lua_Door CastToDoor(); -#ifdef BOTS Lua_Bot CastToBot(); -#endif }; #endif -#endif \ No newline at end of file +#endif diff --git a/zone/lua_entity_list.cpp b/zone/lua_entity_list.cpp index fac099959..a860131c5 100644 --- a/zone/lua_entity_list.cpp +++ b/zone/lua_entity_list.cpp @@ -17,9 +17,7 @@ #include "lua_raid.h" #include "lua_spawn.h" -#ifdef BOTS #include "lua_bot.h" -#endif struct Lua_Mob_List { std::vector entries; @@ -33,11 +31,9 @@ struct Lua_Client_List { std::vector entries; }; -#ifdef BOTS struct Lua_Bot_List { std::vector entries; }; -#endif struct Lua_Corpse_List { std::vector entries; @@ -227,7 +223,16 @@ void Lua_EntityList::MessageStatus(uint32 guild_dbid, int min_status, uint32 typ void Lua_EntityList::MessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, const char *message) { Lua_Safe_Call_Void(); - self->MessageClose(sender, skip_sender, dist, type, message); + + if (RuleB(Chat, AutoInjectSaylinksToClientMessage)) + { + std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(message); + self->MessageClose(sender, skip_sender, dist, type, new_message.c_str()); + } + else + { + self->MessageClose(sender, skip_sender, dist, type, message); + } } void Lua_EntityList::FilteredMessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, int filter, const char *message) @@ -272,9 +277,9 @@ std::string Lua_EntityList::RemoveNumbers(const char *name) { return self->RemoveNumbers(t_name); } -void Lua_EntityList::SignalMobsByNPCID(uint32 npc_id, int signal) { +void Lua_EntityList::SignalMobsByNPCID(uint32 npc_id, int signal_id) { Lua_Safe_Call_Void(); - self->SignalMobsByNPCID(npc_id, signal); + self->SignalMobsByNPCID(npc_id, signal_id); } uint32 Lua_EntityList::DeleteNPCCorpses() { @@ -322,6 +327,11 @@ void Lua_EntityList::MessageGroup(Lua_Mob who, bool skip_close, uint32 type, con self->MessageGroup(who, skip_close, type, message); } +Lua_Client Lua_EntityList::GetRandomClient() { + Lua_Safe_Call_Class(Lua_Client); + return self->GetRandomClient(); +} + Lua_Client Lua_EntityList::GetRandomClient(float x, float y, float z, float distance) { Lua_Safe_Call_Class(Lua_Client); return self->GetRandomClient(glm::vec3(x, y, z), distance); @@ -360,7 +370,6 @@ Lua_Client_List Lua_EntityList::GetClientList() { return ret; } -#ifdef BOTS Lua_Bot Lua_EntityList::GetBotByID(uint32 bot_id) { Lua_Safe_Call_Class(Lua_Bot); return Lua_Bot(self->GetBotByBotID(bot_id)); @@ -385,6 +394,16 @@ Lua_Bot_List Lua_EntityList::GetBotList() { return ret; } +Lua_Client Lua_EntityList::GetBotOwnerByBotEntityID(uint32 entity_id) { + Lua_Safe_Call_Class(Lua_Client); + return Lua_Client(self->GetBotOwnerByBotEntityID(entity_id)); +} + +Lua_Client Lua_EntityList::GetBotOwnerByBotID(uint32 bot_id) { + Lua_Safe_Call_Class(Lua_Client); + return Lua_Client(self->GetBotOwnerByBotID(bot_id)); +} + Lua_Bot_List Lua_EntityList::GetBotListByCharacterID(uint32 character_id) { Lua_Safe_Call_Class(Lua_Bot_List); Lua_Bot_List ret; @@ -399,6 +418,20 @@ Lua_Bot_List Lua_EntityList::GetBotListByCharacterID(uint32 character_id) { return ret; } +Lua_Bot_List Lua_EntityList::GetBotListByCharacterID(uint32 character_id, uint8 class_id) { + Lua_Safe_Call_Class(Lua_Bot_List); + Lua_Bot_List ret; + auto bot_list = self->GetBotListByCharacterID(character_id, class_id); + + if (bot_list.size()) { + for (auto bot : bot_list) { + ret.entries.push_back(Lua_Bot(bot)); + } + } + + return ret; +} + Lua_Bot_List Lua_EntityList::GetBotListByClientName(std::string client_name) { Lua_Safe_Call_Class(Lua_Bot_List); Lua_Bot_List ret; @@ -412,7 +445,40 @@ Lua_Bot_List Lua_EntityList::GetBotListByClientName(std::string client_name) { return ret; } -#endif + +Lua_Bot_List Lua_EntityList::GetBotListByClientName(std::string client_name, uint8 class_id) { + Lua_Safe_Call_Class(Lua_Bot_List); + Lua_Bot_List ret; + auto bot_list = self->GetBotListByClientName(client_name, class_id); + + if (bot_list.size()) { + for (auto bot : bot_list) { + ret.entries.push_back(Lua_Bot(bot)); + } + } + + return ret; +} + +void Lua_EntityList::SignalAllBotsByOwnerCharacterID(uint32 character_id, int signal_id) { + Lua_Safe_Call_Void(); + self->SignalAllBotsByOwnerCharacterID(character_id, signal_id); +} + +void Lua_EntityList::SignalAllBotsByOwnerName(std::string owner_name, int signal_id) { + Lua_Safe_Call_Void(); + self->SignalAllBotsByOwnerName(owner_name, signal_id); +} + +void Lua_EntityList::SignalBotByBotID(uint32 bot_id, int signal_id) { + Lua_Safe_Call_Void(); + self->SignalBotByBotID(bot_id, signal_id); +} + +void Lua_EntityList::SignalBotByBotName(std::string bot_name, int signal_id) { + Lua_Safe_Call_Void(); + self->SignalBotByBotName(bot_name, signal_id); +} Lua_Client_List Lua_EntityList::GetShuffledClientList() { Lua_Safe_Call_Class(Lua_Client_List); @@ -501,9 +567,9 @@ Lua_Spawn_List Lua_EntityList::GetSpawnList() { return ret; } -void Lua_EntityList::SignalAllClients(int signal) { +void Lua_EntityList::SignalAllClients(int signal_id) { Lua_Safe_Call_Void(); - self->SignalAllClients(signal); + self->SignalAllClients(signal_id); } void Lua_EntityList::ChannelMessage(Lua_Mob from, int channel_num, int language, const char *message) { @@ -511,6 +577,11 @@ void Lua_EntityList::ChannelMessage(Lua_Mob from, int channel_num, int language, self->ChannelMessage(from, channel_num, language, message); } +Lua_Mob Lua_EntityList::GetRandomMob() { + Lua_Safe_Call_Class(Lua_Mob); + return self->GetRandomMob(); +} + Lua_Mob Lua_EntityList::GetRandomMob(float x, float y, float z, float distance) { Lua_Safe_Call_Class(Lua_Mob); return self->GetRandomMob(glm::vec3(x, y, z), distance); @@ -521,6 +592,11 @@ Lua_Mob Lua_EntityList::GetRandomMob(float x, float y, float z, float distance, return self->GetRandomMob(glm::vec3(x, y, z), distance, exclude_mob); } +Lua_NPC Lua_EntityList::GetRandomNPC() { + Lua_Safe_Call_Class(Lua_NPC); + return self->GetRandomNPC(); +} + Lua_NPC Lua_EntityList::GetRandomNPC(float x, float y, float z, float distance) { Lua_Safe_Call_Class(Lua_NPC); return self->GetRandomNPC(glm::vec3(x, y, z), distance); @@ -531,6 +607,36 @@ Lua_NPC Lua_EntityList::GetRandomNPC(float x, float y, float z, float distance, return self->GetRandomNPC(glm::vec3(x, y, z), distance, exclude_npc); } +void Lua_EntityList::Marquee(uint32 type, std::string message) { + Lua_Safe_Call_Void(); + self->Marquee(type, message); +} + +void Lua_EntityList::Marquee(uint32 type, std::string message, uint32 duration) { + Lua_Safe_Call_Void(); + self->Marquee(type, message, duration); +} + +void Lua_EntityList::Marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) { + Lua_Safe_Call_Void(); + self->Marquee(type, priority, fade_in, fade_out, duration, message); +} + +Lua_Bot Lua_EntityList::GetRandomBot() { + Lua_Safe_Call_Class(Lua_Bot); + return self->GetRandomBot(); +} + +Lua_Bot Lua_EntityList::GetRandomBot(float x, float y, float z, float distance) { + Lua_Safe_Call_Class(Lua_Bot); + return self->GetRandomBot(glm::vec3(x, y, z), distance); +} + +Lua_Bot Lua_EntityList::GetRandomBot(float x, float y, float z, float distance, Lua_Bot exclude_bot) { + Lua_Safe_Call_Class(Lua_Bot); + return self->GetRandomBot(glm::vec3(x, y, z), distance, exclude_bot); +} + luabind::scope lua_register_entity_list() { return luabind::class_("EntityList") .def(luabind::constructor<>()) @@ -546,13 +652,15 @@ luabind::scope lua_register_entity_list() { .def("Fighting", (bool(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::Fighting) .def("FilteredMessageClose", &Lua_EntityList::FilteredMessageClose) .def("FindDoor", (Lua_Door(Lua_EntityList::*)(uint32))&Lua_EntityList::FindDoor) -#ifdef BOTS .def("GetBotByID", (Lua_Bot(Lua_EntityList::*)(uint32))&Lua_EntityList::GetBotByID) .def("GetBotByName", (Lua_Bot(Lua_EntityList::*)(std::string))&Lua_EntityList::GetBotByName) .def("GetBotList", (Lua_Bot_List(Lua_EntityList::*)(void))&Lua_EntityList::GetBotList) + .def("GetBotOwnerByBotEntityID", (Lua_Client(Lua_EntityList::*)(uint32))&Lua_EntityList::GetBotOwnerByBotEntityID) + .def("GetBotOwnerByBotID", (Lua_Client(Lua_EntityList::*)(uint32))&Lua_EntityList::GetBotOwnerByBotID) .def("GetBotListByCharacterID", (Lua_Bot_List(Lua_EntityList::*)(uint32))&Lua_EntityList::GetBotListByCharacterID) + .def("GetBotListByCharacterID", (Lua_Bot_List(Lua_EntityList::*)(uint32,uint8))&Lua_EntityList::GetBotListByCharacterID) .def("GetBotListByClientName", (Lua_Bot_List(Lua_EntityList::*)(std::string))&Lua_EntityList::GetBotListByClientName) -#endif + .def("GetBotListByClientName", (Lua_Bot_List(Lua_EntityList::*)(std::string,uint8))&Lua_EntityList::GetBotListByClientName) .def("GetClientByAccID", (Lua_Client(Lua_EntityList::*)(uint32))&Lua_EntityList::GetClientByAccID) .def("GetClientByCharID", (Lua_Client(Lua_EntityList::*)(uint32))&Lua_EntityList::GetClientByCharID) .def("GetClientByID", (Lua_Client(Lua_EntityList::*)(int))&Lua_EntityList::GetClientByID) @@ -585,10 +693,16 @@ luabind::scope lua_register_entity_list() { .def("GetObjectList", (Lua_Object_List(Lua_EntityList::*)(void))&Lua_EntityList::GetObjectList) .def("GetRaidByClient", (Lua_Raid(Lua_EntityList::*)(Lua_Client))&Lua_EntityList::GetRaidByClient) .def("GetRaidByID", (Lua_Raid(Lua_EntityList::*)(int))&Lua_EntityList::GetRaidByID) - .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float))&Lua_EntityList::GetRandomClient) - .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float, Lua_Client))&Lua_EntityList::GetRandomClient) + .def("GetRandomBot", (Lua_Bot(Lua_EntityList::*)(void))&Lua_EntityList::GetRandomBot) + .def("GetRandomBot", (Lua_Bot(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomBot) + .def("GetRandomBot", (Lua_Bot(Lua_EntityList::*)(float,float,float,float,Lua_Bot))&Lua_EntityList::GetRandomBot) + .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(void))&Lua_EntityList::GetRandomClient) + .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomClient) + .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float,float,float,float,Lua_Client))&Lua_EntityList::GetRandomClient) + .def("GetRandomMob", (Lua_Mob(Lua_EntityList::*)(void))&Lua_EntityList::GetRandomMob) .def("GetRandomMob", (Lua_Mob(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomMob) .def("GetRandomMob", (Lua_Mob(Lua_EntityList::*)(float,float,float,float,Lua_Mob))&Lua_EntityList::GetRandomMob) + .def("GetRandomNPC", (Lua_NPC(Lua_EntityList::*)(void))&Lua_EntityList::GetRandomNPC) .def("GetRandomNPC", (Lua_NPC(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomNPC) .def("GetRandomNPC", (Lua_NPC(Lua_EntityList::*)(float,float,float,float,Lua_NPC))&Lua_EntityList::GetRandomNPC) .def("GetShuffledClientList", (Lua_Client_List(Lua_EntityList::*)(void))&Lua_EntityList::GetShuffledClientList) @@ -597,6 +711,9 @@ luabind::scope lua_register_entity_list() { .def("HalveAggro", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::HalveAggro) .def("IsMobSpawnedByNpcTypeID", (bool(Lua_EntityList::*)(int))&Lua_EntityList::IsMobSpawnedByNpcTypeID) .def("MakeNameUnique", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::MakeNameUnique) + .def("Marquee", (void(Lua_EntityList::*)(uint32, std::string))&Lua_EntityList::Marquee) + .def("Marquee", (void(Lua_EntityList::*)(uint32, std::string, uint32))&Lua_EntityList::Marquee) + .def("Marquee", (void(Lua_EntityList::*)(uint32, uint32, uint32, uint32, uint32, std::string))&Lua_EntityList::Marquee) .def("Message", (void(Lua_EntityList::*)(uint32, uint32, const char*))&Lua_EntityList::Message) .def("MessageClose", (void(Lua_EntityList::*)(Lua_Mob, bool, float, uint32, const char*))&Lua_EntityList::MessageClose) .def("MessageGroup", (void(Lua_EntityList::*)(Lua_Mob, bool, uint32, const char*))&Lua_EntityList::MessageGroup) @@ -608,7 +725,11 @@ luabind::scope lua_register_entity_list() { .def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob, bool))&Lua_EntityList::RemoveFromTargets) .def("RemoveNumbers", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::RemoveNumbers) .def("ReplaceWithTarget", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob))&Lua_EntityList::ReplaceWithTarget) + .def("SignalAllBotsByOwnerCharacterID", (void(Lua_EntityList::*)(uint32, int))&Lua_EntityList::SignalAllBotsByOwnerCharacterID) + .def("SignalAllBotsByOwnerName", (void(Lua_EntityList::*)(std::string, int))&Lua_EntityList::SignalAllBotsByOwnerName) .def("SignalAllClients", (void(Lua_EntityList::*)(int))&Lua_EntityList::SignalAllClients) + .def("SignalBotByBotID", (void(Lua_EntityList::*)(uint32, int))&Lua_EntityList::SignalBotByBotID) + .def("SignalBotByBotName", (void(Lua_EntityList::*)(std::string, int))&Lua_EntityList::SignalBotByBotName) .def("SignalMobsByNPCID", (void(Lua_EntityList::*)(uint32, int))&Lua_EntityList::SignalMobsByNPCID); } @@ -622,12 +743,10 @@ luabind::scope lua_register_client_list() { .def_readwrite("entries", &Lua_Client_List::entries, luabind::return_stl_iterator); } -#ifdef BOTS luabind::scope lua_register_bot_list() { return luabind::class_("BotList") .def_readwrite("entries", &Lua_Bot_List::entries, luabind::return_stl_iterator); } -#endif luabind::scope lua_register_npc_list() { return luabind::class_("NPCList") diff --git a/zone/lua_entity_list.h b/zone/lua_entity_list.h index 09c525db7..11dac40a9 100644 --- a/zone/lua_entity_list.h +++ b/zone/lua_entity_list.h @@ -7,9 +7,7 @@ class EntityList; class Lua_Mob; class Lua_Client; -#ifdef BOTS class Lua_Bot; -#endif class Lua_NPC; class Lua_Door; class Lua_Corpse; @@ -19,9 +17,7 @@ class Lua_Raid; class Lua_Spawn; struct Lua_Mob_List; struct Lua_Client_List; -#ifdef BOTS struct Lua_Bot_List; -#endif struct Lua_NPC_List; struct Lua_Corpse_List; struct Lua_Object_List; @@ -40,10 +36,7 @@ luabind::scope lua_register_corpse_list(); luabind::scope lua_register_object_list(); luabind::scope lua_register_door_list(); luabind::scope lua_register_spawn_list(); - -#ifdef BOTS luabind::scope lua_register_bot_list(); -#endif class Lua_EntityList : public Lua_Ptr { @@ -88,6 +81,9 @@ public: Lua_Spawn GetSpawnByID(uint32 id); void ClearClientPetitionQueue(); bool CanAddHateForMob(Lua_Mob p); + void Marquee(uint32 type, std::string message); + void Marquee(uint32 type, std::string message, uint32 duration); + void Marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message); void Message(uint32 guild_dbid, uint32 type, const char *message); void MessageStatus(uint32 guild_dbid, int min_status, uint32 type, const char *message); void MessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, const char *message); @@ -98,7 +94,7 @@ public: void OpenDoorsNear(Lua_Mob opener); std::string MakeNameUnique(const char *name); std::string RemoveNumbers(const char *name); - void SignalMobsByNPCID(uint32 npc_id, int signal); + void SignalMobsByNPCID(uint32 npc_id, int signal_id); uint32 DeleteNPCCorpses(); uint32 DeletePlayerCorpses(); void HalveAggro(Lua_Mob who); @@ -108,10 +104,13 @@ public: void RemoveFromHateLists(Lua_Mob who); void RemoveFromHateLists(Lua_Mob who, bool set_to_one); void MessageGroup(Lua_Mob who, bool skip_close, uint32 type, const char *message); + Lua_Client GetRandomClient(); Lua_Client GetRandomClient(float x, float y, float z, float distance); Lua_Client GetRandomClient(float x, float y, float z, float distance, Lua_Client exclude_client); + Lua_Mob GetRandomMob(); Lua_Mob GetRandomMob(float x, float y, float z, float distance); Lua_Mob GetRandomMob(float x, float y, float z, float distance, Lua_Mob exclude_mob); + Lua_NPC GetRandomNPC(); Lua_NPC GetRandomNPC(float x, float y, float z, float distance); Lua_NPC GetRandomNPC(float x, float y, float z, float distance, Lua_NPC exclude_npc); Lua_Mob_List GetMobList(); @@ -122,15 +121,24 @@ public: Lua_Object_List GetObjectList(); Lua_Doors_List GetDoorsList(); Lua_Spawn_List GetSpawnList(); - void SignalAllClients(int signal); + void SignalAllClients(int signal_id); void ChannelMessage(Lua_Mob from, int channel_num, int language, const char *message); -#ifdef BOTS Lua_Bot GetBotByID(uint32 bot_id); Lua_Bot GetBotByName(std::string bot_name); + Lua_Client GetBotOwnerByBotEntityID(uint32 entity_id); + Lua_Client GetBotOwnerByBotID(uint32 bot_id); Lua_Bot_List GetBotList(); Lua_Bot_List GetBotListByCharacterID(uint32 character_id); + Lua_Bot_List GetBotListByCharacterID(uint32 character_id, uint8 class_id); Lua_Bot_List GetBotListByClientName(std::string client_name); -#endif + Lua_Bot_List GetBotListByClientName(std::string client_name, uint8 class_id); + Lua_Bot GetRandomBot(); + Lua_Bot GetRandomBot(float x, float y, float z, float distance); + Lua_Bot GetRandomBot(float x, float y, float z, float distance, Lua_Bot exclude_bot); + void SignalAllBotsByOwnerCharacterID(uint32 character_id, int signal_id); + void SignalAllBotsByOwnerName(std::string owner_name, int signal_id); + void SignalBotByBotID(uint32 bot_id, int signal_id); + void SignalBotByBotName(std::string bot_name, int signal_id); }; #endif diff --git a/zone/lua_expedition.cpp b/zone/lua_expedition.cpp index 0ed63782b..fca207077 100644 --- a/zone/lua_expedition.cpp +++ b/zone/lua_expedition.cpp @@ -2,7 +2,7 @@ #include "lua_expedition.h" #include "expedition.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "lua.hpp" #include #include @@ -212,6 +212,12 @@ void Lua_Expedition::SetSecondsRemaining(uint32_t seconds_remaining) self->GetDynamicZone()->SetSecondsRemaining(seconds_remaining); } +void Lua_Expedition::SetSwitchID(int dz_switch_id) +{ + Lua_Safe_Call_Void(); + self->GetDynamicZone()->SetSwitchID(dz_switch_id, true); +} + void Lua_Expedition::SetZoneInLocation(float x, float y, float z, float heading) { Lua_Safe_Call_Void(); self->GetDynamicZone()->SetZoneInLocation(x, y, z, heading, true); @@ -269,6 +275,7 @@ luabind::scope lua_register_expedition() { .def("SetSafeReturn", (void(Lua_Expedition::*)(uint32_t, float, float, float, float))&Lua_Expedition::SetSafeReturn) .def("SetSafeReturn", (void(Lua_Expedition::*)(std::string, float, float, float, float))&Lua_Expedition::SetSafeReturn) .def("SetSecondsRemaining", &Lua_Expedition::SetSecondsRemaining) + .def("SetSwitchID", &Lua_Expedition::SetSwitchID) .def("SetZoneInLocation", (void(Lua_Expedition::*)(float, float, float, float))&Lua_Expedition::SetZoneInLocation) .def("UpdateLockoutDuration", (void(Lua_Expedition::*)(std::string, uint32_t))&Lua_Expedition::UpdateLockoutDuration) .def("UpdateLockoutDuration", (void(Lua_Expedition::*)(std::string, uint32_t, bool))&Lua_Expedition::UpdateLockoutDuration); @@ -277,11 +284,11 @@ luabind::scope lua_register_expedition() { luabind::scope lua_register_expedition_lock_messages() { return luabind::class_("ExpeditionLockMessage") .enum_("constants") - [ + [( luabind::value("None", static_cast(ExpeditionLockMessage::None)), luabind::value("Close", static_cast(ExpeditionLockMessage::Close)), luabind::value("Begin", static_cast(ExpeditionLockMessage::Begin)) - ]; + )]; } #endif // LUA_EQEMU diff --git a/zone/lua_expedition.h b/zone/lua_expedition.h index d154f9323..a338e3272 100644 --- a/zone/lua_expedition.h +++ b/zone/lua_expedition.h @@ -90,6 +90,7 @@ public: void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading); void SetSafeReturn(std::string zone_name, float x, float y, float z, float heading); void SetSecondsRemaining(uint32_t seconds_remaining); + void SetSwitchID(int dz_switch_id); void SetZoneInLocation(float x, float y, float z, float heading); void UpdateLockoutDuration(std::string event_name, uint32_t duration); void UpdateLockoutDuration(std::string event_name, uint32_t duration, bool members_only); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index f62c1de9f..086c5dc5e 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -27,6 +27,7 @@ #include "lua_encounter.h" #include "data_bucket.h" #include "expedition.h" +#include "dialogue_window.h" struct Events { }; struct Factions { }; @@ -75,7 +76,7 @@ void load_encounter_with_data(std::string name, std::string info_str) { entity_list.AddEncounter(enc); lua_encounters[name] = enc; lua_encounters_loaded[name] = true; - std::vector info_ptrs; + std::vector info_ptrs; info_ptrs.push_back(&info_str); parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, "", 0, &info_ptrs); } @@ -137,7 +138,7 @@ void unload_encounter_with_data(std::string name, std::string info_str) { lua_encounters[name]->Depop(); lua_encounters.erase(name); lua_encounters_loaded.erase(name); - std::vector info_ptrs; + std::vector info_ptrs; info_ptrs.push_back(&info_str); parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, "", 0, &info_ptrs); } @@ -541,8 +542,8 @@ void lua_set_proximity(float min_x, float max_x, float min_y, float max_y, float quest_manager.set_proximity(min_x, max_x, min_y, max_y, min_z, max_z); } -void lua_set_proximity(float min_x, float max_x, float min_y, float max_y, float min_z, float max_z, bool say) { - quest_manager.set_proximity(min_x, max_x, min_y, max_y, min_z, max_z, say); +void lua_set_proximity(float min_x, float max_x, float min_y, float max_y, float min_z, float max_z, bool enable_say) { + quest_manager.set_proximity(min_x, max_x, min_y, max_y, min_z, max_z, enable_say); } void lua_clear_proximity() { @@ -597,36 +598,35 @@ bool lua_bury_player_corpse(uint32 char_id) { return quest_manager.buryplayercorpse(char_id); } -void lua_task_selector(luabind::adl::object table) { +void lua_task_selector(luabind::adl::object table, bool ignore_cooldown) { if(luabind::type(table) != LUA_TTABLE) { return; } - int tasks[MAXCHOOSERENTRIES] = { 0 }; - int count = 0; - - for(int i = 1; i <= MAXCHOOSERENTRIES; ++i) { - auto cur = table[i]; - int cur_value = 0; - if(luabind::type(cur) != LUA_TNIL) { - try { - cur_value = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { - } - } else { - count = i - 1; - break; + std::vector tasks; + for (int i = 1; i <= MAXCHOOSERENTRIES; ++i) + { + if (luabind::type(table[i]) == LUA_TNUMBER) + { + tasks.push_back(luabind::object_cast(table[i])); } - - tasks[i - 1] = cur_value; } - quest_manager.taskselector(count, tasks); + + quest_manager.taskselector(tasks, ignore_cooldown); +} + +void lua_task_selector(luabind::adl::object table) { + lua_task_selector(table, false); } void lua_task_set_selector(int task_set) { quest_manager.tasksetselector(task_set); } +void lua_task_set_selector(int task_set, bool ignore_cooldown) { + quest_manager.tasksetselector(task_set, ignore_cooldown); +} + void lua_enable_task(luabind::adl::object table) { if(luabind::type(table) != LUA_TTABLE) { return; @@ -705,10 +705,6 @@ void lua_reset_task_activity(int task, int activity) { quest_manager.resettaskactivity(task, activity); } -void lua_task_explored_area(int explore_id) { - quest_manager.taskexploredarea(explore_id); -} - void lua_assign_task(int task_id) { quest_manager.assigntask(task_id); } @@ -765,6 +761,30 @@ std::string lua_get_task_name(uint32 task_id) { return quest_manager.gettaskname(task_id); } +int lua_get_dz_task_id() { + return quest_manager.GetCurrentDzTaskID(); +} + +void lua_end_dz_task() { + quest_manager.EndCurrentDzTask(); +} + +void lua_end_dz_task(bool send_fail) { + quest_manager.EndCurrentDzTask(send_fail); +} + +void lua_popup(const char *title, const char *text) { + quest_manager.popup(title, text, 0, 0, 0); +} + +void lua_popup(const char *title, const char *text, uint32 id) { + quest_manager.popup(title, text, id, 0, 0); +} + +void lua_popup(const char *title, const char *text, uint32 id, uint32 buttons) { + quest_manager.popup(title, text, id, buttons, 0); +} + void lua_popup(const char *title, const char *text, uint32 id, uint32 buttons, uint32 duration) { quest_manager.popup(title, text, id, buttons, duration); } @@ -793,32 +813,40 @@ int lua_get_level(int type) { return quest_manager.getlevel(type); } -void lua_create_ground_object(uint32 item_id, float x, float y, float z, float h) { - quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, h)); +uint16 lua_create_ground_object(uint32 item_id, float x, float y, float z, float h) { + return quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, h)); } -void lua_create_ground_object(uint32 item_id, float x, float y, float z, float h, uint32 decay_time) { - quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, h), decay_time); +uint16 lua_create_ground_object(uint32 item_id, float x, float y, float z, float h, uint32 decay_time) { + return quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, h), decay_time); } -void lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h) { - quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h)); +uint16 lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h) { + return quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h)); } -void lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h, int type) { - quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h), type); +uint16 lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h, uint8 type) { + return quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h), type); } -void lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h, int type, uint32 decay_time) { - quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h), type, decay_time); +uint16 lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h, uint8 type, uint32 decay_time) { + return quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h), type, decay_time); } -void lua_create_door(const char *model, float x, float y, float z, float h, int open_type, int size) { - quest_manager.CreateDoor(model, x, y, z, h, open_type, size); +uint16 lua_create_door(const char *model, float x, float y, float z, float h) { + return quest_manager.CreateDoor(model, x, y, z, h, 58, 100); } -void lua_modify_npc_stat(const char *id, const char *value) { - quest_manager.ModifyNPCStat(id, value); +uint16 lua_create_door(const char *model, float x, float y, float z, float h, uint8 open_type) { + return quest_manager.CreateDoor(model, x, y, z, h, open_type, 100); +} + +uint16 lua_create_door(const char *model, float x, float y, float z, float h, uint8 open_type, uint16 size) { + return quest_manager.CreateDoor(model, x, y, z, h, open_type, size); +} + +void lua_modify_npc_stat(std::string stat, std::string value) { + quest_manager.ModifyNPCStat(stat, value); } int lua_collect_items(uint32 item_id, bool remove) { @@ -853,12 +881,6 @@ int lua_merchant_count_item(uint32 npc_id, uint32 item_id) { return quest_manager.MerchantCountItem(npc_id, item_id); } -std::string lua_item_link(int item_id) { - char text[250] = { 0 }; - - return quest_manager.varlink(text, item_id); -} - std::string lua_get_item_name(uint32 item_id) { return quest_manager.getitemname(item_id); } @@ -982,16 +1004,46 @@ int lua_get_instance_id(const char *zone, uint32 version) { return quest_manager.GetInstanceID(zone, version); } -int lua_get_instance_id_by_char_id(const char *zone, uint32 version, uint32 char_id) { - return quest_manager.GetInstanceIDByCharID(zone, version, char_id); +uint8 lua_get_instance_version_by_id(uint16 instance_id) { + return database.GetInstanceVersion(instance_id); +} + +uint32 lua_get_instance_zone_id_by_id(uint16 instance_id) { + return database.GetInstanceZoneID(instance_id); +} + +luabind::adl::object lua_get_instance_ids(lua_State* L, std::string zone_name) { + luabind::adl::object ret = luabind::newtable(L); + + auto instance_ids = quest_manager.GetInstanceIDs(zone_name); + for (int i = 0; i < instance_ids.size(); i++) { + ret[i] = instance_ids[i]; + } + + return ret; +} + +luabind::adl::object lua_get_instance_ids_by_char_id(lua_State* L, std::string zone_name, uint32 character_id) { + luabind::adl::object ret = luabind::newtable(L); + + auto instance_ids = quest_manager.GetInstanceIDs(zone_name, character_id); + for (int i = 0; i < instance_ids.size(); i++) { + ret[i] = instance_ids[i]; + } + + return ret; +} + +int lua_get_instance_id_by_char_id(const char *zone, uint32 version, uint32 character_id) { + return quest_manager.GetInstanceIDByCharID(zone, version, character_id); } void lua_assign_to_instance(uint32 instance_id) { quest_manager.AssignToInstance(instance_id); } -void lua_assign_to_instance_by_char_id(uint32 instance_id, uint32 char_id) { - quest_manager.AssignToInstanceByCharID(instance_id, char_id); +void lua_assign_to_instance_by_char_id(uint32 instance_id, uint32 character_id) { + quest_manager.AssignToInstanceByCharID(instance_id, character_id); } void lua_assign_group_to_instance(uint32 instance_id) { @@ -1006,12 +1058,12 @@ void lua_remove_from_instance(uint32 instance_id) { quest_manager.RemoveFromInstance(instance_id); } -void lua_remove_from_instance_by_char_id(uint32 instance_id, uint32 char_id) { - quest_manager.RemoveFromInstanceByCharID(instance_id, char_id); +void lua_remove_from_instance_by_char_id(uint32 instance_id, uint32 character_id) { + quest_manager.RemoveFromInstanceByCharID(instance_id, character_id); } -bool lua_check_instance_by_char_id(uint32 instance_id, uint32 char_id) { - return quest_manager.CheckInstanceByCharID(instance_id, char_id); +bool lua_check_instance_by_char_id(uint32 instance_id, uint32 character_id) { + return quest_manager.CheckInstanceByCharID(instance_id, character_id); } void lua_remove_all_from_instance(uint32 instance_id) { @@ -1195,11 +1247,11 @@ int lua_get_zone_instance_version() { luabind::adl::object lua_get_characters_in_instance(lua_State *L, uint16 instance_id) { luabind::adl::object ret = luabind::newtable(L); - std::list charid_list; + std::list character_ids; uint16 i = 1; - database.GetCharactersInInstance(instance_id,charid_list); - auto iter = charid_list.begin(); - while(iter != charid_list.end()) { + database.GetCharactersInInstance(instance_id, character_ids); + auto iter = character_ids.begin(); + while(iter != character_ids.end()) { ret[i] = *iter; ++i; ++iter; @@ -1208,8 +1260,9 @@ luabind::adl::object lua_get_characters_in_instance(lua_State *L, uint16 instanc } int lua_get_zone_weather() { - if(!zone) - return 0; + if (!zone) { + return EQ::constants::WeatherTypes::None; + } return zone->zone_weather; } @@ -1527,6 +1580,10 @@ void lua_log_combat(std::string message) { Log(Logs::General, Logs::Combat, message.c_str()); } +void lua_log_spells(std::string message) { + Log(Logs::General, Logs::Spells, message.c_str()); +} + void lua_update_zone_header(std::string type, std::string value) { quest_manager.UpdateZoneHeader(type, value); } @@ -1872,7 +1929,11 @@ void lua_remove_all_expedition_lockouts_by_char_id(uint32 char_id, std::string e } std::string lua_seconds_to_time(int duration) { - return quest_manager.secondstotime(duration); + return Strings::SecondsToTime(duration); +} + +uint32 lua_time_to_seconds(std::string time_string) { + return Strings::TimeToSeconds(time_string); } std::string lua_get_hex_color_code(std::string color_name) { @@ -1883,18 +1944,34 @@ double lua_get_aa_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id) { return database.GetAAEXPModifier(character_id, zone_id); } +double lua_get_aa_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, int16 instance_version) { + return database.GetAAEXPModifier(character_id, zone_id, instance_version); +} + double lua_get_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id) { return database.GetEXPModifier(character_id, zone_id); } +double lua_get_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, int16 instance_version) { + return database.GetEXPModifier(character_id, zone_id, instance_version); +} + void lua_set_aa_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, double aa_modifier) { database.SetAAEXPModifier(character_id, zone_id, aa_modifier); } +void lua_set_aa_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, double aa_modifier, int16 instance_version) { + database.SetAAEXPModifier(character_id, zone_id, aa_modifier, instance_version); +} + void lua_set_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, double exp_modifier) { database.SetEXPModifier(character_id, zone_id, exp_modifier); } +void lua_set_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, double exp_modifier, int16 instance_version) { + database.SetEXPModifier(character_id, zone_id, exp_modifier, instance_version); +} + void lua_add_ldon_loss(uint32 theme_id) { quest_manager.addldonloss(theme_id); } @@ -1939,8 +2016,8 @@ std::string lua_get_data_remaining(std::string bucket_name) { return DataBucket::GetDataRemaining(bucket_name); } -int lua_get_item_stat(uint32 item_id, std::string stat_identifier) { - return quest_manager.getitemstat(item_id, stat_identifier); +const int lua_get_item_stat(uint32 item_id, std::string identifier) { + return quest_manager.getitemstat(item_id, identifier); } int lua_get_spell_stat(uint32 spell_id, std::string stat_identifier) { @@ -2797,40 +2874,40 @@ void lua_cross_zone_set_entity_variable_by_client_name(const char* character_nam quest_manager.CrossZoneSetEntityVariable(update_type, update_identifier, variable_name, variable_value, character_name); } -void lua_cross_zone_signal_client_by_char_id(uint32 character_id, int signal) { +void lua_cross_zone_signal_client_by_char_id(uint32 character_id, int signal_id) { uint8 update_type = CZUpdateType_Character; - quest_manager.CrossZoneSignal(update_type, character_id, signal); + quest_manager.CrossZoneSignal(update_type, character_id, signal_id); } -void lua_cross_zone_signal_client_by_group_id(uint32 group_id, int signal) { +void lua_cross_zone_signal_client_by_group_id(uint32 group_id, int signal_id) { uint8 update_type = CZUpdateType_Group; - quest_manager.CrossZoneSignal(update_type, group_id, signal); + quest_manager.CrossZoneSignal(update_type, group_id, signal_id); } -void lua_cross_zone_signal_client_by_raid_id(uint32 raid_id, int signal) { +void lua_cross_zone_signal_client_by_raid_id(uint32 raid_id, int signal_id) { uint8 update_type = CZUpdateType_Raid; - quest_manager.CrossZoneSignal(update_type, raid_id, signal); + quest_manager.CrossZoneSignal(update_type, raid_id, signal_id); } -void lua_cross_zone_signal_client_by_guild_id(uint32 guild_id, int signal) { +void lua_cross_zone_signal_client_by_guild_id(uint32 guild_id, int signal_id) { uint8 update_type = CZUpdateType_Guild; - quest_manager.CrossZoneSignal(update_type, guild_id, signal); + quest_manager.CrossZoneSignal(update_type, guild_id, signal_id); } -void lua_cross_zone_signal_client_by_expedition_id(uint32 expedition_id, int signal) { +void lua_cross_zone_signal_client_by_expedition_id(uint32 expedition_id, int signal_id) { uint8 update_type = CZUpdateType_Expedition; - quest_manager.CrossZoneSignal(update_type, expedition_id, signal); + quest_manager.CrossZoneSignal(update_type, expedition_id, signal_id); } -void lua_cross_zone_signal_client_by_name(const char* client_name, int signal) { +void lua_cross_zone_signal_client_by_name(const char* client_name, int signal_id) { uint8 update_type = CZUpdateType_ClientName; int update_identifier = 0; - quest_manager.CrossZoneSignal(update_type, update_identifier, signal, client_name); + quest_manager.CrossZoneSignal(update_type, update_identifier, signal_id, client_name); } -void lua_cross_zone_signal_npc_by_npctype_id(uint32 npctype_id, int signal) { +void lua_cross_zone_signal_npc_by_npctype_id(uint32 npctype_id, int signal_id) { uint8 update_type = CZUpdateType_NPC; - quest_manager.CrossZoneSignal(update_type, npctype_id, signal); + quest_manager.CrossZoneSignal(update_type, npctype_id, signal_id); } void lua_cross_zone_update_activity_by_char_id(int character_id, uint32 task_id, int activity_id) { @@ -3258,24 +3335,24 @@ void lua_world_wide_set_entity_variable_npc(const char* variable_name, const cha quest_manager.WorldWideSetEntityVariable(update_type, variable_name, variable_value); } -void lua_world_wide_signal_client(uint32 signal) { +void lua_world_wide_signal_client(int signal_id) { uint8 update_type = WWSignalUpdateType_Character; - quest_manager.WorldWideSignal(update_type, signal); + quest_manager.WorldWideSignal(update_type, signal_id); } -void lua_world_wide_signal_client(uint32 signal, uint8 min_status) { +void lua_world_wide_signal_client(int signal_id, uint8 min_status) { uint8 update_type = WWSignalUpdateType_Character; - quest_manager.WorldWideSignal(update_type, signal, min_status); + quest_manager.WorldWideSignal(update_type, signal_id, min_status); } -void lua_world_wide_signal_client(uint32 signal, uint8 min_status, uint8 max_status) { +void lua_world_wide_signal_client(int signal_id, uint8 min_status, uint8 max_status) { uint8 update_type = WWSignalUpdateType_Character; - quest_manager.WorldWideSignal(update_type, signal, min_status, max_status); + quest_manager.WorldWideSignal(update_type, signal_id, min_status, max_status); } -void lua_world_wide_signal_npc(uint32 signal) { +void lua_world_wide_signal_npc(int signal_id) { uint8 update_type = WWSignalUpdateType_NPC; - quest_manager.WorldWideSignal(update_type, signal); + quest_manager.WorldWideSignal(update_type, signal_id); } void lua_world_wide_update_activity(uint32 task_id, int activity_id) { @@ -3389,7 +3466,238 @@ std::string lua_get_environmental_damage_name(uint8 damage_type) { } std::string lua_commify(std::string number) { - return commify(number); + return Strings::Commify(number); +} + +bool lua_check_name_filter(std::string name) { + return database.CheckNameFilter(name); +} + +void lua_discord_send(std::string webhook_name, std::string message) { + zone->SendDiscordMessage(webhook_name, message); +} + +void lua_track_npc(uint32 entity_id) { + quest_manager.TrackNPC(entity_id); +} + +int lua_get_recipe_made_count(uint32 recipe_id) { + return quest_manager.GetRecipeMadeCount(recipe_id); +} + +std::string lua_get_recipe_name(uint32 recipe_id) { + return quest_manager.GetRecipeName(recipe_id); +} + +bool lua_has_recipe_learned(uint32 recipe_id) { + return quest_manager.HasRecipeLearned(recipe_id); +} + +bool lua_is_raining() { + if (!zone) { + return false; + } + + return zone->IsRaining(); +} + +bool lua_is_snowing() { + if (!zone) { + return false; + } + + return zone->IsSnowing(); +} + +std::string lua_get_aa_name(int aa_id) { + if (!zone) { + return std::string(); + } + + return zone->GetAAName(aa_id); +} + +std::string lua_popup_break() { + return DialogueWindow::Break(); +} + +std::string lua_popup_break(uint32 break_count) { + return DialogueWindow::Break(break_count); +} + +std::string lua_popup_center_message(std::string message) { + return DialogueWindow::CenterMessage(message); +} + +std::string lua_popup_color_message(std::string color, std::string message) { + return DialogueWindow::ColorMessage(color, message); +} + +std::string lua_popup_indent() { + return DialogueWindow::Indent(); +} + +std::string lua_popup_indent(uint32 indent_count) { + return DialogueWindow::Indent(indent_count); +} + +std::string lua_popup_link(std::string link) { + return DialogueWindow::Link(link); +} + +std::string lua_popup_link(std::string link, std::string message) { + return DialogueWindow::Link(link, message); +} + +std::string lua_popup_table(std::string message) { + return DialogueWindow::Table(message); +} + +std::string lua_popup_table_cell() { + return DialogueWindow::TableCell(); +} + +std::string lua_popup_table_cell(std::string message) { + return DialogueWindow::TableCell(message); +} + +std::string lua_popup_table_row(std::string message) { + return DialogueWindow::TableRow(message); +} + +void lua_marquee(uint32 type, std::string message) { + quest_manager.marquee(type, message); +} + +void lua_marquee(uint32 type, std::string message, uint32 duration) { + quest_manager.marquee(type, message, duration); +} + +void lua_marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) { + quest_manager.marquee(type, priority, fade_in, fade_out, duration, message); +} + +void lua_zone_marquee(uint32 type, std::string message) { + if (!zone) { + return; + } + + entity_list.Marquee(type, message); +} + +void lua_zone_marquee(uint32 type, std::string message, uint32 duration) { + if (!zone) { + return; + } + + entity_list.Marquee(type, message, duration); +} + +void lua_zone_marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) { + if (!zone) { + return; + } + + entity_list.Marquee(type, priority, fade_in, fade_out, duration, message); +} + +bool lua_is_hotzone() +{ + if (!zone) { + return false; + } + + return zone->IsHotzone(); +} + +void lua_set_hotzone(bool is_hotzone) +{ + if (!zone) { + return; + } + + zone->SetIsHotzone(is_hotzone); +} + +void lua_set_proximity_range(float x_range, float y_range) +{ + quest_manager.set_proximity_range(x_range, y_range); +} + +void lua_set_proximity_range(float x_range, float y_range, float z_range) +{ + quest_manager.set_proximity_range(x_range, y_range, z_range); +} + +void lua_set_proximity_range(float x_range, float y_range, float z_range, bool enable_say) +{ + quest_manager.set_proximity_range(x_range, y_range, z_range, enable_say); +} + +void lua_do_anim(int animation_id) +{ + quest_manager.doanim(animation_id); +} + +void lua_do_anim(int animation_id, int animation_speed) +{ + quest_manager.doanim(animation_id, animation_speed); +} + +void lua_do_anim(int animation_id, int animation_speed, bool ackreq) +{ + quest_manager.doanim(animation_id, animation_speed, ackreq); +} + +void lua_do_anim(int animation_id, int animation_speed, bool ackreq, int filter) +{ + quest_manager.doanim(animation_id, animation_speed, ackreq, static_cast(filter)); +} + +std::string lua_item_link(uint32 item_id) { + return quest_manager.varlink(item_id); +} + +std::string lua_item_link(uint32 item_id, int16 charges) { + return quest_manager.varlink(item_id, charges); +} + +std::string lua_item_link(uint32 item_id, int16 charges, uint32 aug1) { + return quest_manager.varlink(item_id, charges, aug1); +} + +std::string lua_item_link(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2) { + return quest_manager.varlink(item_id, charges, aug1, aug2); +} + +std::string lua_item_link(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3) { + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3); +} + +std::string lua_item_link(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4) { + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4); +} + +std::string lua_item_link(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) { + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5); +} + +std::string lua_item_link(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6) { + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6); +} + +std::string lua_item_link(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, bool attuned) { + return quest_manager.varlink(item_id, charges, aug1, aug2, aug3, aug4, aug5, aug6, attuned); +} + +bool lua_do_augment_slots_match(uint32 item_one, uint32 item_two) +{ + return quest_manager.DoAugmentSlotsMatch(item_one, item_two); +} + +int8 lua_does_augment_fit(Lua_ItemInst inst, uint32 augment_id) +{ + return quest_manager.DoesAugmentFit(inst, augment_id); } #define LuaCreateNPCParse(name, c_type, default_value) do { \ @@ -3572,7 +3880,7 @@ bool get_ruleb(int rule) { luabind::scope lua_register_general() { return luabind::namespace_("eq") - [ + [( luabind::def("load_encounter", &load_encounter), luabind::def("unload_encounter", &unload_encounter), luabind::def("load_encounter_with_data", &load_encounter_with_data), @@ -3660,6 +3968,9 @@ luabind::scope lua_register_general() { luabind::def("set_proximity", (void(*)(float,float,float,float))&lua_set_proximity), luabind::def("set_proximity", (void(*)(float,float,float,float,float,float))&lua_set_proximity), luabind::def("set_proximity", (void(*)(float,float,float,float,float,float,bool))&lua_set_proximity), + luabind::def("set_proximity_range", (void(*)(float,float))&lua_set_proximity_range), + luabind::def("set_proximity_range", (void(*)(float,float,float))&lua_set_proximity_range), + luabind::def("set_proximity_range", (void(*)(float,float,float,bool))&lua_set_proximity_range), luabind::def("clear_proximity", &lua_clear_proximity), luabind::def("enable_proximity_say", &lua_enable_proximity_say), luabind::def("disable_proximity_say", &lua_disable_proximity_say), @@ -3673,8 +3984,10 @@ luabind::scope lua_register_general() { luabind::def("get_player_corpse_count_by_zone_id", &lua_get_player_corpse_count_by_zone_id), luabind::def("get_player_buried_corpse_count", &lua_get_player_buried_corpse_count), luabind::def("bury_player_corpse", &lua_bury_player_corpse), - luabind::def("task_selector", &lua_task_selector), - luabind::def("task_set_selector", &lua_task_set_selector), + luabind::def("task_selector", (void(*)(luabind::adl::object))&lua_task_selector), + luabind::def("task_selector", (void(*)(luabind::adl::object, bool))&lua_task_selector), + luabind::def("task_set_selector", (void(*)(int))&lua_task_set_selector), + luabind::def("task_set_selector", (void(*)(int, bool))&lua_task_set_selector), luabind::def("enable_task", &lua_enable_task), luabind::def("disable_task", &lua_disable_task), luabind::def("is_task_enabled", &lua_is_task_enabled), @@ -3683,7 +3996,6 @@ luabind::scope lua_register_general() { luabind::def("get_task_activity_done_count", &lua_get_task_activity_done_count), luabind::def("update_task_activity", &lua_update_task_activity), luabind::def("reset_task_activity", &lua_reset_task_activity), - luabind::def("task_explored_area", &lua_task_explored_area), luabind::def("assign_task", &lua_assign_task), luabind::def("fail_task", &lua_fail_task), luabind::def("task_time_left", &lua_task_time_left), @@ -3698,19 +4010,23 @@ luabind::scope lua_register_general() { luabind::def("completed_tasks_in_set", &lua_completed_tasks_in_set), luabind::def("is_task_appropriate", &lua_is_task_appropriate), luabind::def("get_task_name", (std::string(*)(uint32))&lua_get_task_name), - luabind::def("popup", &lua_popup), + luabind::def("get_dz_task_id", &lua_get_dz_task_id), + luabind::def("end_dz_task", (void(*)())&lua_end_dz_task), + luabind::def("end_dz_task", (void(*)(bool))&lua_end_dz_task), luabind::def("clear_spawn_timers", &lua_clear_spawn_timers), luabind::def("zone_emote", &lua_zone_emote), luabind::def("world_emote", &lua_world_emote), luabind::def("message", &lua_message), luabind::def("whisper", &lua_whisper), luabind::def("get_level", &lua_get_level), - luabind::def("create_ground_object", (void(*)(uint32,float,float,float,float))&lua_create_ground_object), - luabind::def("create_ground_object", (void(*)(uint32,float,float,float,float,uint32))&lua_create_ground_object), - luabind::def("create_ground_object_from_model", (void(*)(const char*,float,float,float,float))&lua_create_ground_object_from_model), - luabind::def("create_ground_object_from_model", (void(*)(const char*,float,float,float,float,int))&lua_create_ground_object_from_model), - luabind::def("create_ground_object_from_model", (void(*)(const char*,float,float,float,float,int,uint32))&lua_create_ground_object_from_model), - luabind::def("create_door", &lua_create_door), + luabind::def("create_ground_object", (uint16(*)(uint32,float,float,float,float))&lua_create_ground_object), + luabind::def("create_ground_object", (uint16(*)(uint32,float,float,float,float,uint32))&lua_create_ground_object), + luabind::def("create_ground_object_from_model", (uint16(*)(const char*,float,float,float,float))&lua_create_ground_object_from_model), + luabind::def("create_ground_object_from_model", (uint16(*)(const char*,float,float,float,float,uint8))&lua_create_ground_object_from_model), + luabind::def("create_ground_object_from_model", (uint16(*)(const char*,float,float,float,float,uint8,uint32))&lua_create_ground_object_from_model), + luabind::def("create_door", (uint16(*)(const char*,float,float,float,float))&lua_create_door), + luabind::def("create_door", (uint16(*)(const char*,float,float,float,float,uint8))&lua_create_door), + luabind::def("create_door", (uint16(*)(const char*,float,float,float,float,uint8,uint16))&lua_create_door), luabind::def("modify_npc_stat", &lua_modify_npc_stat), luabind::def("collect_items", &lua_collect_items), luabind::def("count_item", &lua_count_item), @@ -3720,7 +4036,15 @@ luabind::scope lua_register_general() { luabind::def("merchant_set_item", (void(*)(uint32,uint32))&lua_merchant_set_item), luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item), luabind::def("merchant_count_item", &lua_merchant_count_item), - luabind::def("item_link", &lua_item_link), + luabind::def("item_link", (std::string(*)(uint32))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16,uint32))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32,uint32))&lua_item_link), + luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32,uint32,bool))&lua_item_link), luabind::def("get_item_name", (std::string(*)(uint32))&lua_get_item_name), luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link), luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link), @@ -3749,8 +4073,12 @@ luabind::scope lua_register_general() { luabind::def("update_instance_timer", &lua_update_instance_timer), luabind::def("get_instance_id", &lua_get_instance_id), luabind::def("get_instance_id_by_char_id", &lua_get_instance_id_by_char_id), + luabind::def("get_instance_ids", &lua_get_instance_ids), + luabind::def("get_instance_ids_by_char_id", &lua_get_instance_id_by_char_id), luabind::def("get_instance_timer", &lua_get_instance_timer), luabind::def("get_instance_timer_by_id", &lua_get_instance_timer_by_id), + luabind::def("get_instance_version_by_id", &lua_get_instance_version_by_id), + luabind::def("get_instance_zone_id_by_id", &lua_get_instance_zone_id_by_id), luabind::def("get_characters_in_instance", &lua_get_characters_in_instance), luabind::def("assign_to_instance", &lua_assign_to_instance), luabind::def("assign_to_instance_by_char_id", &lua_assign_to_instance_by_char_id), @@ -3818,12 +4146,18 @@ luabind::scope lua_register_general() { luabind::def("debug", (void(*)(std::string))&lua_debug), luabind::def("debug", (void(*)(std::string, int))&lua_debug), luabind::def("log_combat", (void(*)(std::string))&lua_log_combat), + luabind::def("log_spells", (void(*)(std::string))&lua_log_spells), luabind::def("seconds_to_time", &lua_seconds_to_time), + luabind::def("time_to_seconds", &lua_time_to_seconds), luabind::def("get_hex_color_code", &lua_get_hex_color_code), - luabind::def("get_aa_exp_modifier_by_char_id", &lua_get_aa_exp_modifier_by_char_id), - luabind::def("get_exp_modifier_by_char_id", &lua_get_exp_modifier_by_char_id), - luabind::def("set_aa_exp_modifier_by_char_id", &lua_set_aa_exp_modifier_by_char_id), - luabind::def("set_exp_modifier_by_char_id", &lua_set_exp_modifier_by_char_id), + luabind::def("get_aa_exp_modifier_by_char_id", (double(*)(uint32,uint32))&lua_get_aa_exp_modifier_by_char_id), + luabind::def("get_aa_exp_modifier_by_char_id", (double(*)(uint32,uint32,int16))&lua_get_aa_exp_modifier_by_char_id), + luabind::def("get_exp_modifier_by_char_id", (double(*)(uint32,uint32))&lua_get_exp_modifier_by_char_id), + luabind::def("get_exp_modifier_by_char_id", (double(*)(uint32,uint32,int16))&lua_get_exp_modifier_by_char_id), + luabind::def("set_aa_exp_modifier_by_char_id", (void(*)(uint32,uint32,double))&lua_set_aa_exp_modifier_by_char_id), + luabind::def("set_aa_exp_modifier_by_char_id", (void(*)(uint32,uint32,double,int16))&lua_set_aa_exp_modifier_by_char_id), + luabind::def("set_exp_modifier_by_char_id", (void(*)(uint32,uint32,double))&lua_set_exp_modifier_by_char_id), + luabind::def("set_exp_modifier_by_char_id", (void(*)(uint32,uint32,double,int16))&lua_set_exp_modifier_by_char_id), luabind::def("add_ldon_loss", &lua_add_ldon_loss), luabind::def("add_ldon_points", &lua_add_ldon_points), luabind::def("add_ldon_win", &lua_add_ldon_win), @@ -3845,7 +4179,45 @@ luabind::scope lua_register_general() { luabind::def("get_consider_level_name", &lua_get_consider_level_name), luabind::def("get_environmental_damage_name", &lua_get_environmental_damage_name), luabind::def("commify", &lua_commify), - + luabind::def("check_name_filter", &lua_check_name_filter), + luabind::def("discord_send", &lua_discord_send), + luabind::def("track_npc", &lua_track_npc), + luabind::def("get_recipe_made_count", &lua_get_recipe_made_count), + luabind::def("get_recipe_name", &lua_get_recipe_name), + luabind::def("has_recipe_learned", &lua_has_recipe_learned), + luabind::def("is_raining", &lua_is_raining), + luabind::def("is_snowing", &lua_is_snowing), + luabind::def("get_aa_name", &lua_get_aa_name), + luabind::def("popup", (void(*)(const char*,const char*))&lua_popup), + luabind::def("popup", (void(*)(const char*,const char*,uint32))&lua_popup), + luabind::def("popup", (void(*)(const char*,const char*,uint32,uint32))&lua_popup), + luabind::def("popup", (void(*)(const char*,const char*,uint32,uint32,uint32))&lua_popup), + luabind::def("popup_break", (std::string(*)(void))&lua_popup_break), + luabind::def("popup_break", (std::string(*)(uint32))&lua_popup_break), + luabind::def("popup_center_message", &lua_popup_center_message), + luabind::def("popup_color_message", &lua_popup_color_message), + luabind::def("popup_indent", (std::string(*)(void))&lua_popup_indent), + luabind::def("popup_indent", (std::string(*)(uint32))&lua_popup_indent), + luabind::def("popup_link", (std::string(*)(std::string))&lua_popup_link), + luabind::def("popup_link", (std::string(*)(std::string,std::string))&lua_popup_link), + luabind::def("popup_table", &lua_popup_table), + luabind::def("popup_table_cell", (std::string(*)(void))&lua_popup_table_cell), + luabind::def("popup_table_cell", (std::string(*)(std::string))&lua_popup_table_cell), + luabind::def("popup_table_row", &lua_popup_table_row), + luabind::def("marquee", (void(*)(uint32,std::string))&lua_marquee), + luabind::def("marquee", (void(*)(uint32,std::string,uint32))&lua_marquee), + luabind::def("marquee", (void(*)(uint32,uint32,uint32,uint32,uint32,std::string))&lua_marquee), + luabind::def("zone_marquee", (void(*)(uint32,std::string))&lua_zone_marquee), + luabind::def("zone_marquee", (void(*)(uint32,std::string,uint32))&lua_zone_marquee), + luabind::def("zone_marquee", (void(*)(uint32,uint32,uint32,uint32,uint32,std::string))&lua_zone_marquee), + luabind::def("is_hotzone", (bool(*)(void))&lua_is_hotzone), + luabind::def("set_hotzone", (void(*)(bool))&lua_set_hotzone), + luabind::def("do_anim", (void(*)(int))&lua_do_anim), + luabind::def("do_anim", (void(*)(int,int))&lua_do_anim), + luabind::def("do_anim", (void(*)(int,int,bool))&lua_do_anim), + luabind::def("do_anim", (void(*)(int,int,bool,int))&lua_do_anim), + luabind::def("do_augment_slots_match", &lua_do_augment_slots_match), + luabind::def("does_augment_fit", &lua_does_augment_fit), /* Cross Zone */ @@ -4045,9 +4417,9 @@ luabind::scope lua_register_general() { luabind::def("world_wide_set_entity_variable_client", (void(*)(const char*,const char*,uint8))&lua_world_wide_set_entity_variable_client), luabind::def("world_wide_set_entity_variable_client", (void(*)(const char*,const char*,uint8,uint8))&lua_world_wide_set_entity_variable_client), luabind::def("world_wide_set_entity_variable_npc", &lua_world_wide_set_entity_variable_npc), - luabind::def("world_wide_signal_client", (void(*)(uint32))&lua_world_wide_signal_client), - luabind::def("world_wide_signal_client", (void(*)(uint32,uint8))&lua_world_wide_signal_client), - luabind::def("world_wide_signal_client", (void(*)(uint32,uint8,uint8))&lua_world_wide_signal_client), + luabind::def("world_wide_signal_client", (void(*)(int))&lua_world_wide_signal_client), + luabind::def("world_wide_signal_client", (void(*)(int,uint8))&lua_world_wide_signal_client), + luabind::def("world_wide_signal_client", (void(*)(int,uint8,uint8))&lua_world_wide_signal_client), luabind::def("world_wide_signal_npc", &lua_world_wide_signal_npc), luabind::def("world_wide_update_activity", (void(*)(uint32,int))&lua_world_wide_update_activity), luabind::def("world_wide_update_activity", (void(*)(uint32,int,int))&lua_world_wide_update_activity), @@ -4132,25 +4504,25 @@ luabind::scope lua_register_general() { luabind::def("remove_expedition_lockout_by_char_id", &lua_remove_expedition_lockout_by_char_id), luabind::def("remove_all_expedition_lockouts_by_char_id", (void(*)(uint32))&lua_remove_all_expedition_lockouts_by_char_id), luabind::def("remove_all_expedition_lockouts_by_char_id", (void(*)(uint32, std::string))&lua_remove_all_expedition_lockouts_by_char_id) - ]; + )]; } luabind::scope lua_register_random() { return luabind::namespace_("Random") - [ + [( luabind::def("Int", &random_int), luabind::def("Real", &random_real), luabind::def("Roll", &random_roll_int), luabind::def("RollReal", &random_roll_real), luabind::def("Roll0", &random_roll0) - ]; + )]; } luabind::scope lua_register_events() { return luabind::class_("Event") .enum_("constants") - [ + [( luabind::value("say", static_cast(EVENT_SAY)), luabind::value("trade", static_cast(EVENT_TRADE)), luabind::value("death", static_cast(EVENT_DEATH)), @@ -4237,14 +4609,30 @@ luabind::scope lua_register_events() { luabind::value("equip_item_client", static_cast(EVENT_EQUIP_ITEM_CLIENT)), luabind::value("unequip_item_client", static_cast(EVENT_UNEQUIP_ITEM_CLIENT)), luabind::value("skill_up", static_cast(EVENT_SKILL_UP)), - luabind::value("language_skill_up", static_cast(EVENT_LANGUAGE_SKILL_UP)) - ]; + luabind::value("language_skill_up", static_cast(EVENT_LANGUAGE_SKILL_UP)), + luabind::value("alt_currency_merchant_buy", static_cast(EVENT_ALT_CURRENCY_MERCHANT_BUY)), + luabind::value("alt_currency_merchant_sell", static_cast(EVENT_ALT_CURRENCY_MERCHANT_SELL)), + luabind::value("merchant_buy", static_cast(EVENT_MERCHANT_BUY)), + luabind::value("merchant_sell", static_cast(EVENT_MERCHANT_SELL)), + luabind::value("inspect", static_cast(EVENT_INSPECT)), + luabind::value("task_before_update", static_cast(EVENT_TASK_BEFORE_UPDATE)), + luabind::value("aa_buy", static_cast(EVENT_AA_BUY)), + luabind::value("aa_gain", static_cast(EVENT_AA_GAIN)), + luabind::value("payload", static_cast(EVENT_PAYLOAD)), + luabind::value("level_down", static_cast(EVENT_LEVEL_DOWN)), + luabind::value("gm_command", static_cast(EVENT_GM_COMMAND)), + luabind::value("despawn", static_cast(EVENT_DESPAWN)), + luabind::value("despawn_zone", static_cast(EVENT_DESPAWN_ZONE)), + luabind::value("bot_create", static_cast(EVENT_BOT_CREATE)), + luabind::value("augment_insert_client", static_cast(EVENT_AUGMENT_INSERT_CLIENT)), + luabind::value("augment_remove_client", static_cast(EVENT_AUGMENT_REMOVE_CLIENT)) + )]; } luabind::scope lua_register_faction() { return luabind::class_("Faction") .enum_("constants") - [ + [( luabind::value("Ally", static_cast(FACTION_ALLY)), luabind::value("Warmly", static_cast(FACTION_WARMLY)), luabind::value("Kindly", static_cast(FACTION_KINDLY)), @@ -4254,13 +4642,13 @@ luabind::scope lua_register_faction() { luabind::value("Dubious", static_cast(FACTION_DUBIOUSLY)), luabind::value("Threatenly", static_cast(FACTION_THREATENINGLY)), luabind::value("Scowls", static_cast(FACTION_SCOWLS)) - ]; + )]; } luabind::scope lua_register_slot() { return luabind::class_("Slot") .enum_("constants") - [ + [( luabind::value("Charm", static_cast(EQ::invslot::slotCharm)), luabind::value("Ear1", static_cast(EQ::invslot::slotEar1)), luabind::value("Head", static_cast(EQ::invslot::slotHead)), @@ -4351,13 +4739,13 @@ luabind::scope lua_register_slot() { luabind::value("PersonalBegin", static_cast(EQ::invslot::GENERAL_BEGIN)), // deprecated luabind::value("PersonalEnd", static_cast(EQ::invslot::GENERAL_END)), // deprecated luabind::value("CursorEnd", 0xFFFE) // deprecated (not in use..and never valid vis-a-vis client behavior) - ]; + )]; } luabind::scope lua_register_material() { return luabind::class_("Material") .enum_("constants") - [ + [( luabind::value("Head", static_cast(EQ::textures::armorHead)), luabind::value("Chest", static_cast(EQ::textures::armorChest)), luabind::value("Arms", static_cast(EQ::textures::armorArms)), @@ -4372,13 +4760,13 @@ luabind::scope lua_register_material() { luabind::value("Bracer", static_cast(EQ::textures::armorWrist)), // deprecated luabind::value("Max", static_cast(EQ::textures::materialCount)) // deprecated - ]; + )]; } luabind::scope lua_register_client_version() { return luabind::class_("ClientVersion") .enum_("constants") - [ + [( luabind::value("Unknown", static_cast(EQ::versions::ClientVersion::Unknown)), luabind::value("Titanium", static_cast(EQ::versions::ClientVersion::Titanium)), luabind::value("SoF", static_cast(EQ::versions::ClientVersion::SoF)), @@ -4387,25 +4775,25 @@ luabind::scope lua_register_client_version() { luabind::value("UF", static_cast(EQ::versions::ClientVersion::UF)), luabind::value("RoF", static_cast(EQ::versions::ClientVersion::RoF)), luabind::value("RoF2", static_cast(EQ::versions::ClientVersion::RoF2)) - ]; + )]; } luabind::scope lua_register_appearance() { return luabind::class_("Appearance") .enum_("constants") - [ + [( luabind::value("Standing", static_cast(eaStanding)), luabind::value("Sitting", static_cast(eaSitting)), luabind::value("Crouching", static_cast(eaCrouching)), luabind::value("Dead", static_cast(eaDead)), luabind::value("Looting", static_cast(eaLooting)) - ]; + )]; } luabind::scope lua_register_classes() { return luabind::class_("Class") .enum_("constants") - [ + [( luabind::value("WARRIOR", WARRIOR), luabind::value("CLERIC", CLERIC), luabind::value("PALADIN", PALADIN), @@ -4441,24 +4829,23 @@ luabind::scope lua_register_classes() { luabind::value("BANKER", BANKER), luabind::value("MERCHANT", MERCHANT), luabind::value("DISCORD_MERCHANT", DISCORD_MERCHANT), - luabind::value("ADVENTURERECRUITER", ADVENTURERECRUITER), - luabind::value("ADVENTUREMERCHANT", ADVENTUREMERCHANT), + luabind::value("ADVENTURE_RECRUITER", ADVENTURE_RECRUITER), + luabind::value("ADVENTURE_MERCHANT", ADVENTURE_MERCHANT), luabind::value("LDON_TREASURE", LDON_TREASURE), - luabind::value("CORPSE_CLASS", CORPSE_CLASS), luabind::value("TRIBUTE_MASTER", TRIBUTE_MASTER), luabind::value("GUILD_TRIBUTE_MASTER", GUILD_TRIBUTE_MASTER), luabind::value("NORRATHS_KEEPERS_MERCHANT", NORRATHS_KEEPERS_MERCHANT), luabind::value("DARK_REIGN_MERCHANT", DARK_REIGN_MERCHANT), luabind::value("FELLOWSHIP_MASTER", FELLOWSHIP_MASTER), luabind::value("ALT_CURRENCY_MERCHANT", ALT_CURRENCY_MERCHANT), - luabind::value("MERCERNARY_MASTER", MERCERNARY_MASTER) - ]; + luabind::value("MERCENARY_MASTER", MERCENARY_MASTER) + )]; } luabind::scope lua_register_skills() { return luabind::class_("Skill") .enum_("constants") - [ + [( luabind::value("1HBlunt", EQ::skills::Skill1HBlunt), luabind::value("Blunt1H", EQ::skills::Skill1HBlunt), luabind::value("1HSlashing", EQ::skills::Skill1HSlashing), @@ -4545,13 +4932,13 @@ luabind::scope lua_register_skills() { luabind::value("2HPiercing", EQ::skills::Skill2HPiercing), luabind::value("Piercing2H", EQ::skills::Skill2HPiercing), luabind::value("HIGHEST_SKILL", EQ::skills::HIGHEST_SKILL) - ]; + )]; } luabind::scope lua_register_bodytypes() { return luabind::class_("BT") .enum_("constants") - [ + [( luabind::value("Humanoid", 1), luabind::value("Lycanthrope", 2), luabind::value("Undead", 3), @@ -4586,13 +4973,13 @@ luabind::scope lua_register_bodytypes() { luabind::value("SwarmPet", 63), luabind::value("InvisMan", 66), luabind::value("Special", 67) - ]; + )]; } luabind::scope lua_register_filters() { return luabind::class_("Filter") .enum_("constants") - [ + [( luabind::value("None", FilterNone), luabind::value("GuildChat", FilterGuildChat), luabind::value("Socials", FilterSocials), @@ -4622,13 +5009,13 @@ luabind::scope lua_register_filters() { luabind::value("Unknown26", FilterUnknown26), luabind::value("Unknown27", FilterUnknown27), luabind::value("Unknown28", FilterUnknown28) - ]; + )]; } luabind::scope lua_register_message_types() { return luabind::class_("MT") .enum_("constants") - [ + [( luabind::value("White", Chat::White), luabind::value("DimGray", Chat::DimGray), luabind::value("Default", Chat::Default), @@ -4732,13 +5119,13 @@ luabind::scope lua_register_message_types() { luabind::value("ItemSpeech", Chat::ItemSpeech), luabind::value("StrikeThrough", Chat::StrikeThrough), luabind::value("Stun", Chat::Stun) - ]; + )]; } luabind::scope lua_register_rules_const() { return luabind::class_("Rule") .enum_("constants") - [ + [( #define RULE_INT(cat, rule, default_value, notes) \ luabind::value(#rule, RuleManager::Int__##rule), #include "../common/ruletypes.h" @@ -4753,7 +5140,7 @@ luabind::scope lua_register_rules_const() { luabind::value(#rule, RuleManager::Bool__##rule), #include "../common/ruletypes.h" luabind::value("_BoolRuleCount", RuleManager::_BoolRuleCount) - ]; + )]; } luabind::scope lua_register_rulei() { @@ -4780,24 +5167,24 @@ luabind::scope lua_register_ruleb() { luabind::scope lua_register_journal_speakmode() { return luabind::class_("SpeakMode") .enum_("constants") - [ + [( luabind::value("Raw", static_cast(Journal::SpeakMode::Raw)), luabind::value("Say", static_cast(Journal::SpeakMode::Say)), luabind::value("Shout", static_cast(Journal::SpeakMode::Shout)), luabind::value("EmoteAlt", static_cast(Journal::SpeakMode::EmoteAlt)), luabind::value("Emote", static_cast(Journal::SpeakMode::Emote)), luabind::value("Group", static_cast(Journal::SpeakMode::Group)) - ]; + )]; } luabind::scope lua_register_journal_mode() { return luabind::class_("JournalMode") .enum_("constants") - [ + [( luabind::value("None", static_cast(Journal::Mode::None)), luabind::value("Log1", static_cast(Journal::Mode::Log1)), luabind::value("Log2", static_cast(Journal::Mode::Log2)) - ]; + )]; } #endif diff --git a/zone/lua_group.cpp b/zone/lua_group.cpp index 668067b59..4a3907960 100644 --- a/zone/lua_group.cpp +++ b/zone/lua_group.cpp @@ -1,5 +1,7 @@ #ifdef LUA_EQEMU +#include "../common/data_verification.h" + #include "lua.hpp" #include #include @@ -17,9 +19,14 @@ void Lua_Group::DisbandGroup() { self->DisbandGroup(); } -bool Lua_Group::IsGroupMember(Lua_Mob mob) { +bool Lua_Group::IsGroupMember(const char* name) { Lua_Safe_Call_Bool(); - return self->IsGroupMember(mob); + return self->IsGroupMember(name); +} + +bool Lua_Group::IsGroupMember(Lua_Mob c) { + Lua_Safe_Call_Bool(); + return self->IsGroupMember(c); } void Lua_Group::CastGroupSpell(Lua_Mob caster, int spell_id) { @@ -27,12 +34,17 @@ void Lua_Group::CastGroupSpell(Lua_Mob caster, int spell_id) { self->CastGroupSpell(caster, spell_id); } -void Lua_Group::SplitExp(uint32 exp, Lua_Mob other) { +void Lua_Group::SplitExp(uint64 exp, Lua_Mob other) { Lua_Safe_Call_Void(); self->SplitExp(exp, other); } -void Lua_Group::GroupMessage(Lua_Mob sender, int language, const char *message) { +void Lua_Group::GroupMessage(Lua_Mob sender, const char* message) { + Lua_Safe_Call_Void(); + self->GroupMessage(sender, 0, 100, message); +} + +void Lua_Group::GroupMessage(Lua_Mob sender, int language, const char* message) { Lua_Safe_Call_Void(); self->GroupMessage(sender, language, 100, message); } @@ -52,9 +64,9 @@ void Lua_Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 pla self->SplitMoney(copper, silver, gold, platinum, splitter); } -void Lua_Group::SetLeader(Lua_Mob leader) { +void Lua_Group::SetLeader(Lua_Mob c) { Lua_Safe_Call_Void(); - self->SetLeader(leader); + self->SetLeader(c); } Lua_Mob Lua_Group::GetLeader() { @@ -67,9 +79,14 @@ const char *Lua_Group::GetLeaderName() { return self->GetLeaderName(); } -bool Lua_Group::IsLeader(Lua_Mob leader) { +bool Lua_Group::IsLeader(const char* name) { Lua_Safe_Call_Bool(); - return self->IsLeader(leader); + return self->IsLeader(name); +} + +bool Lua_Group::IsLeader(Lua_Mob c) { + Lua_Safe_Call_Bool(); + return self->IsLeader(c); } int Lua_Group::GroupCount() { @@ -77,12 +94,12 @@ int Lua_Group::GroupCount() { return self->GroupCount(); } -int Lua_Group::GetHighestLevel() { +uint32 Lua_Group::GetHighestLevel() { Lua_Safe_Call_Int(); return self->GetHighestLevel(); } -int Lua_Group::GetLowestLevel() { +uint32 Lua_Group::GetLowestLevel() { Lua_Safe_Call_Int(); return self->GetLowestLevel(); } @@ -97,14 +114,14 @@ int Lua_Group::GetID() { return self->GetID(); } -Lua_Mob Lua_Group::GetMember(int index) { +Lua_Mob Lua_Group::GetMember(int member_index) { Lua_Safe_Call_Class(Lua_Mob); - if(index >= 6 || index < 0) { + if (!EQ::ValueWithin(member_index, 0, 5)) { return Lua_Mob(); } - return self->members[index]; + return self->members[member_index]; } bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name) @@ -119,6 +136,11 @@ bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count); } +uint32 Lua_Group::GetAverageLevel() { + Lua_Safe_Call_Int(); + return self->GetAvgLevel(); +} + luabind::scope lua_register_group() { return luabind::class_("Group") .def(luabind::constructor<>()) @@ -128,16 +150,20 @@ luabind::scope lua_register_group() { .def("DisbandGroup", (void(Lua_Group::*)(void))&Lua_Group::DisbandGroup) .def("DoesAnyMemberHaveExpeditionLockout", (bool(Lua_Group::*)(std::string, std::string))&Lua_Group::DoesAnyMemberHaveExpeditionLockout) .def("DoesAnyMemberHaveExpeditionLockout", (bool(Lua_Group::*)(std::string, std::string, int))&Lua_Group::DoesAnyMemberHaveExpeditionLockout) - .def("GetHighestLevel", (int(Lua_Group::*)(void))&Lua_Group::GetHighestLevel) + .def("GetAverageLevel", (uint32(Lua_Group::*)(void))&Lua_Group::GetAverageLevel) + .def("GetHighestLevel", (uint32(Lua_Group::*)(void))&Lua_Group::GetHighestLevel) .def("GetID", (int(Lua_Group::*)(void))&Lua_Group::GetID) .def("GetLeader", (Lua_Mob(Lua_Group::*)(void))&Lua_Group::GetLeader) .def("GetLeaderName", (const char*(Lua_Group::*)(void))&Lua_Group::GetLeaderName) - .def("GetLowestLevel", (int(Lua_Group::*)(void))&Lua_Group::GetLowestLevel) + .def("GetLowestLevel", (uint32(Lua_Group::*)(void))&Lua_Group::GetLowestLevel) .def("GetMember", (Lua_Mob(Lua_Group::*)(int))&Lua_Group::GetMember) .def("GetTotalGroupDamage", (uint32(Lua_Group::*)(Lua_Mob))&Lua_Group::GetTotalGroupDamage) .def("GroupCount", (int(Lua_Group::*)(void))&Lua_Group::GroupCount) - .def("GroupMessage", (void(Lua_Group::*)(Lua_Mob,int,const char* message))&Lua_Group::GroupMessage) + .def("GroupMessage", (void(Lua_Group::*)(Lua_Mob,const char*))&Lua_Group::GroupMessage) + .def("GroupMessage", (void(Lua_Group::*)(Lua_Mob,int,const char*))&Lua_Group::GroupMessage) + .def("IsGroupMember", (bool(Lua_Group::*)(const char*))&Lua_Group::IsGroupMember) .def("IsGroupMember", (bool(Lua_Group::*)(Lua_Mob))&Lua_Group::IsGroupMember) + .def("IsLeader", (bool(Lua_Group::*)(const char*))&Lua_Group::IsLeader) .def("IsLeader", (bool(Lua_Group::*)(Lua_Mob))&Lua_Group::IsLeader) .def("SetLeader", (void(Lua_Group::*)(Lua_Mob))&Lua_Group::SetLeader) .def("SplitExp", (void(Lua_Group::*)(uint32,Lua_Mob))&Lua_Group::SplitExp) diff --git a/zone/lua_group.h b/zone/lua_group.h index 46bc48f50..e0948b7a3 100644 --- a/zone/lua_group.h +++ b/zone/lua_group.h @@ -7,6 +7,7 @@ class Group; class Lua_Mob; class Lua_Client; +class Lua_Bot; namespace luabind { struct scope; @@ -27,23 +28,27 @@ public: } void DisbandGroup(); - bool IsGroupMember(Lua_Mob mob); + bool IsGroupMember(const char* name); + bool IsGroupMember(Lua_Mob c); void CastGroupSpell(Lua_Mob caster, int spell_id); - void SplitExp(uint32 exp, Lua_Mob other); - void GroupMessage(Lua_Mob sender, int language, const char *message); + void SplitExp(uint64 exp, Lua_Mob other); + void GroupMessage(Lua_Mob sender, const char* message); + void GroupMessage(Lua_Mob sender, int language, const char* message); uint32 GetTotalGroupDamage(Lua_Mob other); void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Lua_Client splitter); - void SetLeader(Lua_Mob leader); + void SetLeader(Lua_Mob c); Lua_Mob GetLeader(); const char *GetLeaderName(); - bool IsLeader(Lua_Mob leader); + bool IsLeader(const char* name); + bool IsLeader(Lua_Mob c); int GroupCount(); - int GetHighestLevel(); - int GetLowestLevel(); + uint32 GetAverageLevel(); + uint32 GetHighestLevel(); + uint32 GetLowestLevel(); void TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h); int GetID(); - Lua_Mob GetMember(int index); + Lua_Mob GetMember(int member_index); bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name); bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count); }; diff --git a/zone/lua_inventory.cpp b/zone/lua_inventory.cpp index 9c5b9c599..48987de68 100644 --- a/zone/lua_inventory.cpp +++ b/zone/lua_inventory.cpp @@ -184,6 +184,20 @@ bool Lua_Inventory::HasItemEquippedByID(uint32 item_id) { return self->HasItemEquippedByID(item_id); } +luabind::object Lua_Inventory::GetAugmentIDsBySlotID(lua_State* L, int16 slot_id) { + auto lua_table = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto augments = self->GetAugmentIDsBySlotID(slot_id); + int index = 1; + for (auto item_id : augments) { + lua_table[index] = item_id; + index++; + } + } + return lua_table; +} + luabind::scope lua_register_inventory() { return luabind::class_("Inventory") .def(luabind::constructor<>()) @@ -201,6 +215,7 @@ luabind::scope lua_register_inventory() { .def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool))&Lua_Inventory::FindFreeSlot) .def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool,int))&Lua_Inventory::FindFreeSlot) .def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool,int,bool))&Lua_Inventory::FindFreeSlot) + .def("GetAugmentIDsBySlotID", (luabind::object(Lua_Inventory::*)(lua_State* L,int16))&Lua_Inventory::GetAugmentIDsBySlotID) .def("GetItem", (Lua_ItemInst(Lua_Inventory::*)(int))&Lua_Inventory::GetItem) .def("GetItem", (Lua_ItemInst(Lua_Inventory::*)(int,int))&Lua_Inventory::GetItem) .def("GetSlotByItemInst", (int(Lua_Inventory::*)(Lua_ItemInst))&Lua_Inventory::GetSlotByItemInst) diff --git a/zone/lua_inventory.h b/zone/lua_inventory.h index 17966b4f4..472447e62 100644 --- a/zone/lua_inventory.h +++ b/zone/lua_inventory.h @@ -68,6 +68,7 @@ public: bool CanItemFitInContainer(Lua_Item item, Lua_Item container); bool SupportsContainers(int slot_id); int GetSlotByItemInst(Lua_ItemInst inst); + luabind::object GetAugmentIDsBySlotID(lua_State* L, int16 slot_id); }; #endif diff --git a/zone/lua_item.cpp b/zone/lua_item.cpp index f693407d9..57ae9083b 100644 --- a/zone/lua_item.cpp +++ b/zone/lua_item.cpp @@ -76,7 +76,7 @@ uint32 Lua_Item::GetIcon() { return self->Icon; } -uint32 Lua_Item::GetLoreGroup() { +int32 Lua_Item::GetLoreGroup() { Lua_Safe_Call_Int(); return self->LoreGroup; } @@ -531,42 +531,42 @@ uint32 Lua_Item::GetAugRestrict() { return self->AugRestrict; } -uint32 Lua_Item::GetEndur() { +int32 Lua_Item::GetEndur() { Lua_Safe_Call_Int(); return self->Endur; } -uint32 Lua_Item::GetDotShielding() { +int32 Lua_Item::GetDotShielding() { Lua_Safe_Call_Int(); return self->DotShielding; } -uint32 Lua_Item::GetAttack() { +int32 Lua_Item::GetAttack() { Lua_Safe_Call_Int(); return self->Attack; } -uint32 Lua_Item::GetRegen() { +int32 Lua_Item::GetRegen() { Lua_Safe_Call_Int(); return self->Regen; } -uint32 Lua_Item::GetManaRegen() { +int32 Lua_Item::GetManaRegen() { Lua_Safe_Call_Int(); return self->ManaRegen; } -uint32 Lua_Item::GetEnduranceRegen() { +int32 Lua_Item::GetEnduranceRegen() { Lua_Safe_Call_Int(); return self->EnduranceRegen; } -uint32 Lua_Item::GetHaste() { +int32 Lua_Item::GetHaste() { Lua_Safe_Call_Int(); return self->Haste; } -uint32 Lua_Item::GetDamageShield() { +int32 Lua_Item::GetDamageShield() { Lua_Safe_Call_Int(); return self->DamageShield; } diff --git a/zone/lua_item.h b/zone/lua_item.h index 6a55c80b3..ec7e33dac 100644 --- a/zone/lua_item.h +++ b/zone/lua_item.h @@ -41,7 +41,7 @@ public: uint32 GetSlots(); uint32 GetPrice(); uint32 GetIcon(); - uint32 GetLoreGroup(); + int32 GetLoreGroup(); bool GetLoreFlag(); bool GetPendingLoreFlag(); bool GetArtifactFlag(); @@ -129,14 +129,14 @@ public: uint32 GetLDoNSold(); uint32 GetBaneDmgRaceAmt(); uint32 GetAugRestrict(); - uint32 GetEndur(); - uint32 GetDotShielding(); - uint32 GetAttack(); - uint32 GetRegen(); - uint32 GetManaRegen(); - uint32 GetEnduranceRegen(); - uint32 GetHaste(); - uint32 GetDamageShield(); + int32 GetEndur(); + int32 GetDotShielding(); + int32 GetAttack(); + int32 GetRegen(); + int32 GetManaRegen(); + int32 GetEnduranceRegen(); + int32 GetHaste(); + int32 GetDamageShield(); uint32 GetRecastDelay(); uint32 GetRecastType(); uint32 GetAugDistiller(); diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 149c087b6..54f7deef4 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -274,6 +274,16 @@ int Lua_ItemInst::CountAugmentByID(uint32 item_id) { return self->CountAugmentByID(item_id); } +int Lua_ItemInst::GetTaskDeliveredCount() { + Lua_Safe_Call_Int(); + return self->GetTaskDeliveredCount(); +} + +int Lua_ItemInst::RemoveTaskDeliveredItems() { + Lua_Safe_Call_Int(); + return self->RemoveTaskDeliveredItems(); +} + luabind::scope lua_register_iteminst() { return luabind::class_("ItemInst") .def(luabind::constructor<>()) @@ -303,6 +313,7 @@ luabind::scope lua_register_iteminst() { .def("GetKillsNeeded", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetKillsNeeded) .def("GetMaxEvolveLvl", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetMaxEvolveLvl) .def("GetPrice", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetPrice) + .def("GetTaskDeliveredCount", &Lua_ItemInst::GetTaskDeliveredCount) .def("GetTotalItemCount", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetTotalItemCount) .def("GetUnscaledItem", (Lua_ItemInst(Lua_ItemInst::*)(int))&Lua_ItemInst::GetUnscaledItem) .def("IsAmmo", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::IsAmmo) @@ -315,6 +326,7 @@ luabind::scope lua_register_iteminst() { .def("IsStackable", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::IsStackable) .def("IsType", (bool(Lua_ItemInst::*)(int))&Lua_ItemInst::IsType) .def("IsWeapon", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::IsWeapon) + .def("RemoveTaskDeliveredItems", &Lua_ItemInst::RemoveTaskDeliveredItems) .def("SetCharges", (void(Lua_ItemInst::*)(int))&Lua_ItemInst::SetCharges) .def("SetColor", (void(Lua_ItemInst::*)(uint32))&Lua_ItemInst::SetColor) .def("SetCustomData", (void(Lua_ItemInst::*)(std::string,bool))&Lua_ItemInst::SetCustomData) diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index c0a4d50c4..04138dafd 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -82,6 +82,8 @@ public: void ClearTimers(); bool ContainsAugmentByID(uint32 item_id); int CountAugmentByID(uint32 item_id); + int GetTaskDeliveredCount(); + int RemoveTaskDeliveredItems(); private: bool cloned_; diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index b36499a71..07b5163c8 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -5,9 +5,8 @@ #include "client.h" #include "npc.h" -#ifdef BOTS +#include "bot.h" #include "lua_bot.h" -#endif #include "lua_item.h" #include "lua_iteminst.h" #include "lua_mob.h" @@ -64,7 +63,7 @@ void Lua_Mob::SetLevel(int level, bool command) { self->SetLevel(level, command); } -void Lua_Mob::SendWearChange(int material_slot) { +void Lua_Mob::SendWearChange(uint8 material_slot) { Lua_Safe_Call_Void(); self->SendWearChange(material_slot); } @@ -242,24 +241,24 @@ void Lua_Mob::SetHP(int64 hp) { self->SetHP(hp); } -void Lua_Mob::DoAnim(int anim_num) { +void Lua_Mob::DoAnim(int animation_id) { Lua_Safe_Call_Void(); - self->DoAnim(anim_num); + self->DoAnim(animation_id); } -void Lua_Mob::DoAnim(int anim_num, int type) { +void Lua_Mob::DoAnim(int animation_id, int animation_speed) { Lua_Safe_Call_Void(); - self->DoAnim(anim_num, type); + self->DoAnim(animation_id, animation_speed); } -void Lua_Mob::DoAnim(int anim_num, int type, bool ackreq) { +void Lua_Mob::DoAnim(int animation_id, int animation_speed, bool ackreq) { Lua_Safe_Call_Void(); - self->DoAnim(anim_num, type, ackreq); + self->DoAnim(animation_id, animation_speed, ackreq); } -void Lua_Mob::DoAnim(int anim_num, int type, bool ackreq, int filter) { +void Lua_Mob::DoAnim(int animation_id, int animation_speed, bool ackreq, int filter) { Lua_Safe_Call_Void(); - self->DoAnim(anim_num, type, ackreq, static_cast(filter)); + self->DoAnim(animation_id, animation_speed, ackreq, static_cast(filter)); } void Lua_Mob::ChangeSize(double in_size) { @@ -272,11 +271,6 @@ void Lua_Mob::ChangeSize(double in_size, bool no_restriction) { self->ChangeSize(static_cast(in_size), no_restriction); } -void Lua_Mob::RandomizeFeatures(bool send_illusion, bool save_variables) { - Lua_Safe_Call_Void(); - self->RandomizeFeatures(send_illusion, save_variables); -} - void Lua_Mob::GMMove(double x, double y, double z) { Lua_Safe_Call_Void(); self->GMMove(static_cast(x), static_cast(y), static_cast(z)); @@ -327,11 +321,6 @@ uint16 Lua_Mob::FindBuffBySlot(int slot) { return self->FindBuffBySlot(slot); } -uint32 Lua_Mob::BuffCount() { - Lua_Safe_Call_Int(); - return self->BuffCount(); -} - bool Lua_Mob::FindType(int type) { Lua_Safe_Call_Bool(); return self->FindType(type); @@ -482,22 +471,22 @@ bool Lua_Mob::IsWarriorClass() { return self->IsWarriorClass(); } -int Lua_Mob::GetHP() { +int64 Lua_Mob::GetHP() { Lua_Safe_Call_Int(); return self->GetHP(); } -int Lua_Mob::GetMaxHP() { +int64 Lua_Mob::GetMaxHP() { Lua_Safe_Call_Int(); return self->GetMaxHP(); } -int Lua_Mob::GetItemHPBonuses() { +int64 Lua_Mob::GetItemHPBonuses() { Lua_Safe_Call_Int(); return self->GetItemHPBonuses(); } -int Lua_Mob::GetSpellHPBonuses() { +int64 Lua_Mob::GetSpellHPBonuses() { Lua_Safe_Call_Int(); return self->GetSpellHPBonuses(); } @@ -753,7 +742,7 @@ double Lua_Mob::GetSize() { return self->GetSize(); } -void Lua_Mob::Message(int type, const char *message) { +void Lua_Mob::Message(uint32 type, const char *message) { Lua_Safe_Call_Void(); // auto inject saylinks @@ -770,7 +759,7 @@ void Lua_Mob::Message(int type, const char *message) { } } -void Lua_Mob::MessageString(int type, int string_id, uint32 distance) { +void Lua_Mob::MessageString(uint32 type, uint32 string_id, uint32 distance) { Lua_Safe_Call_Void(); self->MessageString(type, string_id, distance); } @@ -1356,33 +1345,20 @@ bool Lua_Mob::DivineAura() { return self->DivineAura(); } -void Lua_Mob::SetOOCRegen(int regen) { +void Lua_Mob::SetOOCRegen(int64 new_ooc_regen) { Lua_Safe_Call_Void(); - self->SetOOCRegen(regen); + self->SetOOCRegen(new_ooc_regen); } -const char* Lua_Mob::GetEntityVariable(const char *name) { - Lua_Safe_Call_String(); - return self->GetEntityVariable(name); -} - -void Lua_Mob::SetEntityVariable(const char *name, const char *value) { - Lua_Safe_Call_Void(); - self->SetEntityVariable(name, value); -} - -bool Lua_Mob::EntityVariableExists(const char *name) { - Lua_Safe_Call_Bool(); - return self->EntityVariableExists(name); -} - -void Lua_Mob::Signal(uint32 id) { +void Lua_Mob::Signal(int signal_id) { Lua_Safe_Call_Void(); - if(self->IsClient()) { - self->CastToClient()->Signal(id); - } else if(self->IsNPC()) { - self->CastToNPC()->SignalNPC(id); + if (self->IsClient()) { + self->CastToClient()->Signal(signal_id); + } else if (self->IsNPC()) { + self->CastToNPC()->SignalNPC(signal_id); + } else if (self->IsBot()) { + self->CastToBot()->Signal(signal_id); } } @@ -1591,7 +1567,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) { return; } - int race = 0; + int race = RACE_DOUG_0; int gender = 255; int texture = 255; int helmtexture = 255; @@ -1810,17 +1786,17 @@ void Lua_Mob::ChangeDrakkinDetails(int in) { self->ChangeDrakkinDetails(in); } -void Lua_Mob::CameraEffect(uint32 duration, uint32 intensity) { +void Lua_Mob::CameraEffect(uint32 duration, float intensity) { Lua_Safe_Call_Void(); self->CameraEffect(duration, intensity); } -void Lua_Mob::CameraEffect(uint32 duration, uint32 intensity, Lua_Client c) { +void Lua_Mob::CameraEffect(uint32 duration, float intensity, Lua_Client c) { Lua_Safe_Call_Void(); self->CameraEffect(duration, intensity, c); } -void Lua_Mob::CameraEffect(uint32 duration, uint32 intensity, Lua_Client c, bool global) { +void Lua_Mob::CameraEffect(uint32 duration, float intensity, Lua_Client c, bool global) { Lua_Safe_Call_Void(); self->CameraEffect(duration, intensity, c, global); } @@ -1881,11 +1857,21 @@ void Lua_Mob::SetSlotTint(int material_slot, int red_tint, int green_tint, int b self->SetSlotTint(material_slot, red_tint, green_tint, blue_tint); } -void Lua_Mob::WearChange(int material_slot, int texture, uint32 color) { +void Lua_Mob::WearChange(uint8 material_slot, uint16 texture) { + Lua_Safe_Call_Void(); + self->WearChange(material_slot, texture); +} + +void Lua_Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color) { Lua_Safe_Call_Void(); self->WearChange(material_slot, texture, color); } +void Lua_Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 heros_forge_model) { + Lua_Safe_Call_Void(); + self->WearChange(material_slot, texture, color, heros_forge_model); +} + void Lua_Mob::DoKnockback(Lua_Mob caster, uint32 push_back, uint32 push_up) { Lua_Safe_Call_Void(); self->DoKnockback(caster, push_back, push_up); @@ -2223,9 +2209,9 @@ int Lua_Mob::GetWeaponDamageBonus(Lua_Item weapon, bool offhand) { return self->GetWeaponDamageBonus(weapon, offhand); } -int Lua_Mob::GetItemStat(uint32 itemid, const char* identifier) { +const int Lua_Mob::GetItemStat(uint32 item_id, std::string identifier) { Lua_Safe_Call_Int(); - return self->GetItemStat(itemid, identifier); + return self->GetItemStat(item_id, identifier); } Lua_StatBonuses Lua_Mob::GetItemBonuses() @@ -2258,11 +2244,6 @@ int16 Lua_Mob::GetMeleeMinDamageMod_SE(uint16 skill) return self->GetMeleeMinDamageMod_SE(skill); } -bool Lua_Mob::IsAttackAllowed(Lua_Mob target, bool isSpellAttack) { - Lua_Safe_Call_Bool(); - return self->IsAttackAllowed(target, isSpellAttack); -} - bool Lua_Mob::IsCasting() { Lua_Safe_Call_Bool(); return self->IsCasting(); @@ -2362,22 +2343,26 @@ Lua_Mob Lua_Mob::GetHateClosest() { Lua_HateList Lua_Mob::GetHateListByDistance() { Lua_Safe_Call_Class(Lua_HateList); Lua_HateList ret; - auto list = self->GetHateListByDistance(); - for (auto hate_entry : list) { - Lua_HateEntry entry(hate_entry); - ret.entries.push_back(entry); + + auto h_list = self->GetFilteredHateList(); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); } + return ret; } -Lua_HateList Lua_Mob::GetHateListByDistance(int distance) { +Lua_HateList Lua_Mob::GetHateListByDistance(uint32 distance) { Lua_Safe_Call_Class(Lua_HateList); Lua_HateList ret; - auto list = self->GetHateListByDistance(distance); - for (auto hate_entry : list) { - Lua_HateEntry entry(hate_entry); - ret.entries.push_back(entry); + + auto h_list = self->GetFilteredHateList(EntityFilterType::All, distance); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); } + return ret; } @@ -2401,12 +2386,10 @@ void Lua_Mob::RemoveAllNimbusEffects() { self->RemoveAllNimbusEffects(); } -#ifdef BOTS Lua_Bot Lua_Mob::GetHateRandomBot() { Lua_Safe_Call_Class(Lua_Bot); return Lua_Bot(self->GetHateRandomBot()); } -#endif Lua_Client Lua_Mob::GetHateRandomClient() { Lua_Safe_Call_Class(Lua_Client); @@ -2473,6 +2456,373 @@ void Lua_Mob::SetBuffDuration(int spell_id, int duration) { self->SetBuffDuration(spell_id, duration); } +Lua_Mob Lua_Mob::GetUltimateOwner() { + Lua_Safe_Call_Class(Lua_Mob); + return Lua_Mob(self->GetUltimateOwner()); +} + +bool Lua_Mob::RandomizeFeatures() { + Lua_Safe_Call_Bool(); + return self->RandomizeFeatures(); +} + +bool Lua_Mob::RandomizeFeatures(bool send_illusion) { + Lua_Safe_Call_Bool(); + return self->RandomizeFeatures(send_illusion); +} + +bool Lua_Mob::RandomizeFeatures(bool send_illusion, bool save_variables) { + Lua_Safe_Call_Bool(); + return self->RandomizeFeatures(send_illusion, save_variables); +} + +void Lua_Mob::CloneAppearance(Lua_Mob other) { + Lua_Safe_Call_Void(); + self->CloneAppearance(other); +} + +void Lua_Mob::CloneAppearance(Lua_Mob other, bool clone_name) { + Lua_Safe_Call_Void(); + self->CloneAppearance(other, clone_name); +} + +uint16 Lua_Mob::GetOwnerID() { + Lua_Safe_Call_Int(); + return self->GetOwnerID(); +} + +void Lua_Mob::DamageHateList(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage); +} + +void Lua_Mob::DamageHateList(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance); +} + +void Lua_Mob::DamageHateListClients(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, 0, EntityFilterType::Clients); +} + +void Lua_Mob::DamageHateListClients(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance, EntityFilterType::Clients); +} + +void Lua_Mob::DamageHateListNPCs(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, 0, EntityFilterType::NPCs); +} + +void Lua_Mob::DamageHateListNPCs(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance, EntityFilterType::NPCs); +} + +void Lua_Mob::DamageHateListPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, 0, EntityFilterType::All, true); +} + +void Lua_Mob::DamageHateListPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance, EntityFilterType::All, true); +} + +void Lua_Mob::DamageHateListClientsPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, 0, EntityFilterType::Clients, true); +} + +void Lua_Mob::DamageHateListClientsPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance, EntityFilterType::Clients, true); +} + +void Lua_Mob::DamageHateListNPCsPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, 0, EntityFilterType::NPCs, true); +} + +void Lua_Mob::DamageHateListNPCsPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance, EntityFilterType::NPCs, true); +} + +Lua_HateList Lua_Mob::GetHateListClients() { + Lua_Safe_Call_Class(Lua_HateList); + Lua_HateList ret; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Clients); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); + } + + return ret; +} + +Lua_HateList Lua_Mob::GetHateListClients(uint32 distance) { + Lua_Safe_Call_Class(Lua_HateList); + Lua_HateList ret; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Clients, distance); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); + } + + return ret; +} + +Lua_HateList Lua_Mob::GetHateListNPCs() { + Lua_Safe_Call_Class(Lua_HateList); + Lua_HateList ret; + + auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); + } + + return ret; +} + +Lua_HateList Lua_Mob::GetHateListNPCs(uint32 distance) { + Lua_Safe_Call_Class(Lua_HateList); + Lua_HateList ret; + + auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs, distance); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); + } + + return ret; +} + +void Lua_Mob::DamageArea(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage); +} + +void Lua_Mob::DamageArea(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance); +} + +void Lua_Mob::DamageAreaPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, 0, EntityFilterType::All, true); +} + +void Lua_Mob::DamageAreaPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance, EntityFilterType::All, true); +} + +void Lua_Mob::DamageAreaClients(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, 0, EntityFilterType::Clients); +} + +void Lua_Mob::DamageAreaClients(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance, EntityFilterType::Clients); +} + +void Lua_Mob::DamageAreaClientsPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, 0, EntityFilterType::Clients, true); +} + +void Lua_Mob::DamageAreaClientsPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance, EntityFilterType::Clients, true); +} + +void Lua_Mob::DamageAreaNPCs(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, 0, EntityFilterType::NPCs); +} + +void Lua_Mob::DamageAreaNPCs(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance, EntityFilterType::NPCs); +} + +void Lua_Mob::DamageAreaNPCsPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, 0, EntityFilterType::NPCs, true); +} + +void Lua_Mob::DamageAreaNPCsPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance, EntityFilterType::NPCs, true); +} + +std::string Lua_Mob::GetEntityVariable(std::string variable_name) { + Lua_Safe_Call_String(); + return self->GetEntityVariable(variable_name); +} + +luabind::object Lua_Mob::GetEntityVariables(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetEntityVariables(); + auto i = 0; + for (const auto& v : l) { + t[i] = v; + i++; + } + } + + return t; +} + +bool Lua_Mob::ClearEntityVariables() { + Lua_Safe_Call_Bool(); + return self->ClearEntityVariables(); +} + +bool Lua_Mob::DeleteEntityVariable(std::string variable_name) { + Lua_Safe_Call_Bool(); + return self->DeleteEntityVariable(variable_name); +} + +void Lua_Mob::SetEntityVariable(std::string variable_name, std::string variable_value) { + Lua_Safe_Call_Void(); + self->SetEntityVariable(variable_name, variable_value); +} + +bool Lua_Mob::EntityVariableExists(std::string variable_name) { + Lua_Safe_Call_Bool(); + return self->EntityVariableExists(variable_name); +} + +void Lua_Mob::SendPayload(int payload_id) { + Lua_Safe_Call_Void(); + + if (self->IsClient()) { + self->CastToClient()->SendPayload(payload_id); + } else if (self->IsNPC()) { + self->CastToNPC()->SendPayload(payload_id); + } else if (self->IsBot()) { + self->CastToBot()->SendPayload(payload_id); + } +} + +void Lua_Mob::SendPayload(int payload_id, std::string payload_value) { + Lua_Safe_Call_Void(); + + if (self->IsClient()) { + self->CastToClient()->SendPayload(payload_id, payload_value); + } else if (self->IsNPC()) { + self->CastToNPC()->SendPayload(payload_id, payload_value); + } else if (self->IsBot()) { + self->CastToBot()->SendPayload(payload_id, payload_value); + } +} + +void Lua_Mob::CopyHateList(Lua_Mob to) { + Lua_Safe_Call_Void(); + self->CopyHateList(to); +} + +bool Lua_Mob::IsAttackAllowed(Lua_Mob target) { + Lua_Safe_Call_Bool(); + return self->IsAttackAllowed(target); +} + +bool Lua_Mob::IsAttackAllowed(Lua_Mob target, bool is_spell_attack) { + Lua_Safe_Call_Bool(); + return self->IsAttackAllowed(target, is_spell_attack); +} + +uint32 Lua_Mob::BuffCount() { + Lua_Safe_Call_Int(); + return self->BuffCount(); +} + +uint32 Lua_Mob::BuffCount(bool is_beneficial) { + Lua_Safe_Call_Int(); + return self->BuffCount(is_beneficial); +} + +uint32 Lua_Mob::BuffCount(bool is_beneficial, bool is_detrimental) { + Lua_Safe_Call_Int(); + return self->BuffCount(is_beneficial, is_detrimental); +} + +void Lua_Mob::DamageAreaBots(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, 0, EntityFilterType::Bots); +} + +void Lua_Mob::DamageAreaBots(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance, EntityFilterType::Bots); +} + +void Lua_Mob::DamageAreaBotsPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, 0, EntityFilterType::Bots, true); +} + +void Lua_Mob::DamageAreaBotsPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageArea(damage, distance, EntityFilterType::Bots, true); +} + +void Lua_Mob::DamageHateListBots(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, 0, EntityFilterType::Bots); +} + +void Lua_Mob::DamageHateListBots(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance, EntityFilterType::Bots); +} + +void Lua_Mob::DamageHateListBotsPercentage(int64 damage) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, 0, EntityFilterType::Bots, true); +} + +void Lua_Mob::DamageHateListBotsPercentage(int64 damage, uint32 distance) { + Lua_Safe_Call_Void(); + self->DamageHateList(damage, distance, EntityFilterType::Bots, true); +} + +Lua_HateList Lua_Mob::GetHateListBots() { + Lua_Safe_Call_Class(Lua_HateList); + Lua_HateList ret; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Bots); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); + } + + return ret; +} + +Lua_HateList Lua_Mob::GetHateListBots(uint32 distance) { + Lua_Safe_Call_Class(Lua_HateList); + Lua_HateList ret; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Bots, distance); + for (auto h : h_list) { + Lua_HateEntry e(h); + ret.entries.push_back(e); + } + + return ret; +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2496,7 +2846,9 @@ luabind::scope lua_register_mob() { .def("BehindMob", (bool(Lua_Mob::*)(Lua_Mob,float))&Lua_Mob::BehindMob) .def("BehindMob", (bool(Lua_Mob::*)(Lua_Mob,float,float))&Lua_Mob::BehindMob) .def("BehindMob", (bool(Lua_Mob::*)(void))&Lua_Mob::BehindMob) - .def("BuffCount", &Lua_Mob::BuffCount) + .def("BuffCount", (uint32(Lua_Mob::*)(void))&Lua_Mob::BuffCount) + .def("BuffCount", (uint32(Lua_Mob::*)(bool))&Lua_Mob::BuffCount) + .def("BuffCount", (uint32(Lua_Mob::*)(bool,bool))&Lua_Mob::BuffCount) .def("BuffFadeAll", (void(Lua_Mob::*)(void))&Lua_Mob::BuffFadeAll) .def("BuffFadeByEffect", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeByEffect) .def("BuffFadeByEffect", (void(Lua_Mob::*)(int,int))&Lua_Mob::BuffFadeByEffect) @@ -2505,9 +2857,9 @@ luabind::scope lua_register_mob() { .def("BuffFadeBySpellID", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeBySpellID) .def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance) .def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget) - .def("CameraEffect", (void(Lua_Mob::*)(uint32,uint32))&Lua_Mob::CameraEffect) - .def("CameraEffect", (void(Lua_Mob::*)(uint32,uint32,Lua_Client))&Lua_Mob::CameraEffect) - .def("CameraEffect", (void(Lua_Mob::*)(uint32,uint32,Lua_Client,bool))&Lua_Mob::CameraEffect) + .def("CameraEffect", (void(Lua_Mob::*)(uint32,float))&Lua_Mob::CameraEffect) + .def("CameraEffect", (void(Lua_Mob::*)(uint32,float,Lua_Client))&Lua_Mob::CameraEffect) + .def("CameraEffect", (void(Lua_Mob::*)(uint32,float,Lua_Client,bool))&Lua_Mob::CameraEffect) .def("CanBuffStack", (int(Lua_Mob::*)(int,int))&Lua_Mob::CanBuffStack) .def("CanBuffStack", (int(Lua_Mob::*)(int,int,bool))&Lua_Mob::CanBuffStack) .def("CanClassEquipItem", &Lua_Mob::CanClassEquipItem) @@ -2551,14 +2903,51 @@ luabind::scope lua_register_mob() { .def("CheckLoSToLoc", (bool(Lua_Mob::*)(double,double,double))&Lua_Mob::CheckLoSToLoc) .def("CheckLoSToLoc", (bool(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CheckLoSToLoc) .def("CheckNumHitsRemaining", &Lua_Mob::CheckNumHitsRemaining) + .def("ClearEntityVariables", (bool(Lua_Mob::*)(void))&Lua_Mob::ClearEntityVariables) .def("ClearSpecialAbilities", (void(Lua_Mob::*)(void))&Lua_Mob::ClearSpecialAbilities) + .def("CloneAppearance", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::CloneAppearance) + .def("CloneAppearance", (void(Lua_Mob::*)(Lua_Mob,bool))&Lua_Mob::CloneAppearance) .def("CombatRange", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::CombatRange) + .def("CopyHateList", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::CopyHateList) .def("Damage", (void(Lua_Mob::*)(Lua_Mob,int64,int,int))&Lua_Mob::Damage) .def("Damage", (void(Lua_Mob::*)(Lua_Mob,int64,int,int,bool))&Lua_Mob::Damage) .def("Damage", (void(Lua_Mob::*)(Lua_Mob,int64,int,int,bool,int))&Lua_Mob::Damage) .def("Damage", (void(Lua_Mob::*)(Lua_Mob,int64,int,int,bool,int,bool))&Lua_Mob::Damage) + .def("DamageArea", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageArea) + .def("DamageArea", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageArea) + .def("DamageAreaPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageAreaPercentage) + .def("DamageAreaPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageAreaPercentage) + .def("DamageAreaBots", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageAreaBots) + .def("DamageAreaBots", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageAreaBots) + .def("DamageAreaBotsPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageAreaBotsPercentage) + .def("DamageAreaBotsPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageAreaBotsPercentage) + .def("DamageAreaClients", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageAreaClients) + .def("DamageAreaClients", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageAreaClients) + .def("DamageAreaClientsPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageAreaClientsPercentage) + .def("DamageAreaClientsPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageAreaClientsPercentage) + .def("DamageAreaNPCs", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageAreaNPCs) + .def("DamageAreaNPCs", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageAreaNPCs) + .def("DamageAreaNPCsPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageAreaNPCsPercentage) + .def("DamageAreaNPCsPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageAreaNPCsPercentage) + .def("DamageHateList", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateList) + .def("DamageHateList", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateList) + .def("DamageHateListBots", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateListBots) + .def("DamageHateListBots", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateListBots) + .def("DamageHateListBotsPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateListBots) + .def("DamageHateListBotsPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateListBots) + .def("DamageHateListClients", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateListClients) + .def("DamageHateListClients", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateListClients) + .def("DamageHateListClientsPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateListClientsPercentage) + .def("DamageHateListClientsPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateListClientsPercentage) + .def("DamageHateListNPCs", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateListNPCs) + .def("DamageHateListNPCs", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateListNPCs) + .def("DamageHateListNPCsPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateListNPCsPercentage) + .def("DamageHateListNPCsPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateListNPCsPercentage) + .def("DamageHateListPercentage", (void(Lua_Mob::*)(int64))&Lua_Mob::DamageHateListPercentage) + .def("DamageHateListPercentage", (void(Lua_Mob::*)(int64,uint32))&Lua_Mob::DamageHateListPercentage) .def("DelGlobal", (void(Lua_Mob::*)(const char*))&Lua_Mob::DelGlobal) .def("DeleteBucket", (void(Lua_Mob::*)(std::string))&Lua_Mob::DeleteBucket) + .def("DeleteEntityVariable", (bool(Lua_Mob::*)(std::string))&Lua_Mob::DeleteEntityVariable) .def("Depop", (void(Lua_Mob::*)(bool))&Lua_Mob::Depop) .def("Depop", (void(Lua_Mob::*)(void))&Lua_Mob::Depop) .def("DivineAura", (bool(Lua_Mob::*)(void))&Lua_Mob::DivineAura) @@ -2589,7 +2978,7 @@ luabind::scope lua_register_mob() { .def("DoThrowingAttackDmg", (void(Lua_Mob::*)(Lua_Mob,Lua_ItemInst,Lua_Item,int,int,int))&Lua_Mob::DoThrowingAttackDmg) .def("DoubleAggro", &Lua_Mob::DoubleAggro) .def("Emote", &Lua_Mob::Emote) - .def("EntityVariableExists", (bool(Lua_Mob::*)(const char*))&Lua_Mob::EntityVariableExists) + .def("EntityVariableExists", &Lua_Mob::EntityVariableExists) .def("FaceTarget", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::FaceTarget) .def("FindBuff", &Lua_Mob::FindBuff) .def("FindBuffBySlot", (uint16(Lua_Mob::*)(int))&Lua_Mob::FindBuffBySlot) @@ -2638,7 +3027,8 @@ luabind::scope lua_register_mob() { .def("GetDrakkinDetails", &Lua_Mob::GetDrakkinDetails) .def("GetDrakkinHeritage", &Lua_Mob::GetDrakkinHeritage) .def("GetDrakkinTattoo", &Lua_Mob::GetDrakkinTattoo) - .def("GetEntityVariable", (const char*(Lua_Mob::*)(const char*))&Lua_Mob::GetEntityVariable) + .def("GetEntityVariable", &Lua_Mob::GetEntityVariable) + .def("GetEntityVariables",&Lua_Mob::GetEntityVariables) .def("GetEyeColor1", &Lua_Mob::GetEyeColor1) .def("GetEyeColor2", &Lua_Mob::GetEyeColor2) .def("GetFR", &Lua_Mob::GetFR) @@ -2658,12 +3048,16 @@ luabind::scope lua_register_mob() { .def("GetHateClosest", &Lua_Mob::GetHateClosest) .def("GetHateDamageTop", (Lua_Mob(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetHateDamageTop) .def("GetHateList", &Lua_Mob::GetHateList) - .def("GetHateListByDistance", (Lua_HateList(Lua_Mob::*)(int))&Lua_Mob::GetHateListByDistance) + .def("GetHateListBots", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListBots) + .def("GetHateListBots", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListBots) + .def("GetHateListClients", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListClients) + .def("GetHateListClients", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListClients) + .def("GetHateListNPCs", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListNPCs) + .def("GetHateListNPCs", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListNPCs) .def("GetHateListByDistance", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListByDistance) + .def("GetHateListByDistance", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListByDistance) .def("GetHateRandom", (Lua_Mob(Lua_Mob::*)(void))&Lua_Mob::GetHateRandom) -#ifdef BOTS .def("GetHateRandomBot", (Lua_Bot(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomBot) -#endif .def("GetHateRandomClient", (Lua_Client(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomClient) .def("GetHateRandomNPC", (Lua_NPC(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomNPC) .def("GetHateTop", (Lua_Mob(Lua_Mob::*)(void))&Lua_Mob::GetHateTop) @@ -2676,7 +3070,7 @@ luabind::scope lua_register_mob() { .def("GetInvul", (bool(Lua_Mob::*)(void))&Lua_Mob::GetInvul) .def("GetItemBonuses", &Lua_Mob::GetItemBonuses) .def("GetItemHPBonuses", &Lua_Mob::GetItemHPBonuses) - .def("GetItemStat", (int(Lua_Mob::*)(uint32,const char*))&Lua_Mob::GetItemStat) + .def("GetItemStat", &Lua_Mob::GetItemStat) .def("GetLastName", &Lua_Mob::GetLastName) .def("GetLevel", &Lua_Mob::GetLevel) .def("GetLevelCon", (uint32(Lua_Mob::*)(int))&Lua_Mob::GetLevelCon) @@ -2706,6 +3100,7 @@ luabind::scope lua_register_mob() { .def("GetNimbusEffect3", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect3) .def("GetOrigBodyType", &Lua_Mob::GetOrigBodyType) .def("GetOwner", &Lua_Mob::GetOwner) + .def("GetOwnerID", &Lua_Mob::GetOwnerID) .def("GetPR", &Lua_Mob::GetPR) .def("GetPet", &Lua_Mob::GetPet) .def("GetPetOrder", (int(Lua_Mob::*)(void))&Lua_Mob::GetPetOrder) @@ -2729,6 +3124,7 @@ luabind::scope lua_register_mob() { .def("GetSpellHPBonuses", &Lua_Mob::GetSpellHPBonuses) .def("GetTarget", &Lua_Mob::GetTarget) .def("GetTexture", &Lua_Mob::GetTexture) + .def("GetUltimateOwner", &Lua_Mob::GetUltimateOwner) .def("GetWIS", &Lua_Mob::GetWIS) .def("GetWalkspeed", &Lua_Mob::GetWalkspeed) .def("GetWaypointH", &Lua_Mob::GetWaypointH) @@ -2758,7 +3154,8 @@ luabind::scope lua_register_mob() { .def("InterruptSpell", (void(Lua_Mob::*)(void))&Lua_Mob::InterruptSpell) .def("IsAIControlled", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAIControlled) .def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad) - .def("IsAttackAllowed", &Lua_Mob::IsAttackAllowed) + .def("IsAttackAllowed", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsAttackAllowed) + .def("IsAttackAllowed", (bool(Lua_Mob::*)(Lua_Mob,bool))&Lua_Mob::IsAttackAllowed) .def("IsBeneficialAllowed", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsBeneficialAllowed) .def("IsBerserk", &Lua_Mob::IsBerserk) .def("IsBlind", (bool(Lua_Mob::*)(void))&Lua_Mob::IsBlind) @@ -2803,7 +3200,9 @@ luabind::scope lua_register_mob() { .def("ProjectileAnimation", (void(Lua_Mob::*)(Lua_Mob,int,bool,double,double,double,double))&Lua_Mob::ProjectileAnimation) .def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *))&Lua_Mob::QuestSay) .def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *,luabind::adl::object))&Lua_Mob::QuestSay) - .def("RandomizeFeatures", (void(Lua_Mob::*)(bool,bool))&Lua_Mob::RandomizeFeatures) + .def("RandomizeFeatures", (bool(Lua_Mob::*)(void))&Lua_Mob::RandomizeFeatures) + .def("RandomizeFeatures", (bool(Lua_Mob::*)(bool))&Lua_Mob::RandomizeFeatures) + .def("RandomizeFeatures", (bool(Lua_Mob::*)(bool,bool))&Lua_Mob::RandomizeFeatures) .def("RangedAttack", &Lua_Mob::RangedAttack) .def("RemoveAllNimbusEffects", &Lua_Mob::RemoveAllNimbusEffects) .def("RemoveNimbusEffect", (void(Lua_Mob::*)(int))&Lua_Mob::RemoveNimbusEffect) @@ -2823,8 +3222,11 @@ luabind::scope lua_register_mob() { .def("SetSeeInvisibleUndeadLevel", (void(Lua_Mob::*)(uint8))&Lua_Mob::SetSeeInvisibleUndeadLevel) .def("SendAppearanceEffect", (void(Lua_Mob::*)(uint32,uint32,uint32,uint32,uint32))&Lua_Mob::SendAppearanceEffect) .def("SendAppearanceEffect", (void(Lua_Mob::*)(uint32,uint32,uint32,uint32,uint32,Lua_Client))&Lua_Mob::SendAppearanceEffect) + .def("SendWearChange", (void(Lua_Mob::*)(uint8))&Lua_Mob::SendWearChange) .def("SendBeginCast", &Lua_Mob::SendBeginCast) .def("SendIllusionPacket", (void(Lua_Mob::*)(luabind::adl::object))&Lua_Mob::SendIllusionPacket) + .def("SendPayload", (void(Lua_Mob::*)(int))&Lua_Mob::SendPayload) + .def("SendPayload", (void(Lua_Mob::*)(int,std::string))&Lua_Mob::SendPayload) .def("SendSpellEffect", (void(Lua_Mob::*)(uint32,uint32,uint32,bool,uint32))&Lua_Mob::SendSpellEffect) .def("SendSpellEffect", (void(Lua_Mob::*)(uint32,uint32,uint32,bool,uint32,bool))&Lua_Mob::SendSpellEffect) .def("SendSpellEffect", (void(Lua_Mob::*)(uint32,uint32,uint32,bool,uint32,bool,Lua_Client))&Lua_Mob::SendSpellEffect) @@ -2843,7 +3245,7 @@ luabind::scope lua_register_mob() { .def("SetCurrentWP", &Lua_Mob::SetCurrentWP) .def("SetDestructibleObject", (void(Lua_Mob::*)(bool))&Lua_Mob::SetDestructibleObject) .def("SetDisableMelee", (void(Lua_Mob::*)(bool))&Lua_Mob::SetDisableMelee) - .def("SetEntityVariable", (void(Lua_Mob::*)(const char*,const char*))&Lua_Mob::SetEntityVariable) + .def("SetEntityVariable", &Lua_Mob::SetEntityVariable) .def("SetExtraHaste", (void(Lua_Mob::*)(int))&Lua_Mob::SetExtraHaste) .def("SetFlurryChance", (void(Lua_Mob::*)(int))&Lua_Mob::SetFlurryChance) .def("SetFlyMode", (void(Lua_Mob::*)(int))&Lua_Mob::SetFlyMode) @@ -2860,7 +3262,7 @@ luabind::scope lua_register_mob() { .def("SetLevel", (void(Lua_Mob::*)(int))&Lua_Mob::SetLevel) .def("SetLevel", (void(Lua_Mob::*)(int,bool))&Lua_Mob::SetLevel) .def("SetMana", &Lua_Mob::SetMana) - .def("SetOOCRegen", (void(Lua_Mob::*)(int))&Lua_Mob::SetOOCRegen) + .def("SetOOCRegen", (void(Lua_Mob::*)(int64))&Lua_Mob::SetOOCRegen) .def("SetPet", &Lua_Mob::SetPet) .def("SetPetOrder", (void(Lua_Mob::*)(int))&Lua_Mob::SetPetOrder) .def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot) @@ -2874,7 +3276,7 @@ luabind::scope lua_register_mob() { .def("SetTexture", (void(Lua_Mob::*)(int))&Lua_Mob::SetTexture) .def("Shout", (void(Lua_Mob::*)(const char*))& Lua_Mob::Shout) .def("Shout", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Shout) - .def("Signal", (void(Lua_Mob::*)(uint32))&Lua_Mob::Signal) + .def("Signal", (void(Lua_Mob::*)(int))&Lua_Mob::Signal) .def("SpellEffect", &Lua_Mob::SpellEffect) .def("SpellFinished", (bool(Lua_Mob::*)(int,Lua_Mob))&Lua_Mob::SpellFinished) .def("SpellFinished", (bool(Lua_Mob::*)(int,Lua_Mob,int))&Lua_Mob::SpellFinished) @@ -2894,7 +3296,9 @@ luabind::scope lua_register_mob() { .def("TryMoveAlong", (void(Lua_Mob::*)(float,float,bool))&Lua_Mob::TryMoveAlong) .def("UnStun", (void(Lua_Mob::*)(void))&Lua_Mob::UnStun) .def("WalkTo", (void(Lua_Mob::*)(double, double, double))&Lua_Mob::WalkTo) - .def("WearChange", (void(Lua_Mob::*)(int,int,uint32))&Lua_Mob::WearChange) + .def("WearChange", (void(Lua_Mob::*)(uint8,uint16))&Lua_Mob::WearChange) + .def("WearChange", (void(Lua_Mob::*)(uint8,uint16,uint32))&Lua_Mob::WearChange) + .def("WearChange", (void(Lua_Mob::*)(uint8,uint16,uint32,uint32))&Lua_Mob::WearChange) .def("WipeHateList", (void(Lua_Mob::*)(void))&Lua_Mob::WipeHateList); } @@ -2902,7 +3306,7 @@ luabind::scope lua_register_special_abilities() { return luabind::class_("SpecialAbility") .enum_("constants") - [ + [( luabind::value("summon", static_cast(SPECATK_SUMMON)), luabind::value("enrage", static_cast(SPECATK_ENRAGE)), luabind::value("rampage", static_cast(SPECATK_RAMPAGE)), @@ -2952,8 +3356,9 @@ luabind::scope lua_register_special_abilities() { luabind::value("immune_damage_npc", static_cast(IMMUNE_DAMAGE_NPC)), luabind::value("immune_aggro_client", static_cast(IMMUNE_AGGRO_CLIENT)), luabind::value("immune_aggro_npc", static_cast(IMMUNE_AGGRO_NPC)), - luabind::value("modify_avoid_damage", static_cast(MODIFY_AVOID_DAMAGE)) - ]; + luabind::value("modify_avoid_damage", static_cast(MODIFY_AVOID_DAMAGE)), + luabind::value("immune_open", static_cast(IMMUNE_OPEN)) + )]; } #endif diff --git a/zone/lua_mob.h b/zone/lua_mob.h index d1925917e..fb3dbead5 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -9,9 +9,7 @@ struct Lua_HateList; class Lua_Item; class Lua_ItemInst; class Lua_StatBonuses; -#ifdef BOTS class Lua_Bot; -#endif class Lua_NPC; class Lua_Client; @@ -46,7 +44,7 @@ public: bool BehindMob(Lua_Mob other, float x, float y); void SetLevel(int level); void SetLevel(int level, bool command); - void SendWearChange(int material_slot); + void SendWearChange(uint8 material_slot); bool IsMoving(); bool IsFeared(); bool IsBlind(); @@ -70,13 +68,15 @@ public: uint32 GetLevelCon(int other); uint32 GetLevelCon(int my, int other); void SetHP(int64 hp); - void DoAnim(int anim_num); - void DoAnim(int anim_num, int type); - void DoAnim(int anim_num, int type, bool ackreq); - void DoAnim(int anim_num, int type, bool ackreq, int filter); + void DoAnim(int animation_id); + void DoAnim(int animation_id, int animation_speed); + void DoAnim(int animation_id, int animation_speed, bool ackreq); + void DoAnim(int animation_id, int animation_speed, bool ackreq, int filter); void ChangeSize(double in_size); void ChangeSize(double in_size, bool no_restriction); - void RandomizeFeatures(bool send_illusion, bool save_variables); + bool RandomizeFeatures(); + bool RandomizeFeatures(bool send_illusion); + bool RandomizeFeatures(bool send_illusion, bool save_variables); void GMMove(double x, double y, double z); void GMMove(double x, double y, double z, double heading); void TryMoveAlong(float distance, float heading); @@ -84,7 +84,7 @@ public: bool HasProcs(); bool IsInvisible(); bool IsInvisible(Lua_Mob other); - void SetInvisible(int state); + void SetInvisible(int state); uint8 GetInvisibleLevel(); uint8 GetInvisibleUndeadLevel(); void SetSeeInvisibleLevel(uint8 invisible_level); @@ -92,7 +92,9 @@ public: bool FindBuff(int spell_id); uint16 FindBuffBySlot(int slot); uint32 BuffCount(); - bool FindType(int type); + uint32 BuffCount(bool is_beneficial); + uint32 BuffCount(bool is_beneficial, bool is_detrimental); + bool FindType(int type); bool FindType(int type, bool offensive); bool FindType(int type, bool offensive, int threshold); int GetBuffSlotFromType(int slot); @@ -123,10 +125,10 @@ public: void SetTarget(Lua_Mob t); double GetHPRatio(); bool IsWarriorClass(); - int GetHP(); - int GetMaxHP(); - int GetItemHPBonuses(); - int GetSpellHPBonuses(); + int64 GetHP(); + int64 GetMaxHP(); + int64 GetItemHPBonuses(); + int64 GetSpellHPBonuses(); double GetWalkspeed(); double GetRunspeed(); int GetCasterLevel(int spell_id); @@ -177,8 +179,8 @@ public: int GetWaypointID(); void SetCurrentWP(int wp); double GetSize(); - void Message(int type, const char *message); - void MessageString(int type, int string_id, uint32 distance); + void Message(uint32 type, const char *message); + void MessageString(uint32 type, uint32 string_id, uint32 distance); void Say(const char *message); void Say(const char* message, int language); void QuestSay(Lua_Client client, const char *message); @@ -206,16 +208,22 @@ public: void SpellEffect(Lua_Mob caster, int spell_id, double partial); Lua_Mob GetPet(); Lua_Mob GetOwner(); + uint16 GetOwnerID(); + Lua_Mob GetUltimateOwner(); Lua_HateList GetHateList(); + Lua_HateList GetHateListBots(); + Lua_HateList GetHateListBots(uint32 distance); + Lua_HateList GetHateListClients(); + Lua_HateList GetHateListClients(uint32 distance); + Lua_HateList GetHateListNPCs(); + Lua_HateList GetHateListNPCs(uint32 distance); Lua_HateList GetShuffledHateList(); Lua_HateList GetHateListByDistance(); - Lua_HateList GetHateListByDistance(int distance); + Lua_HateList GetHateListByDistance(uint32 distance); Lua_Mob GetHateTop(); Lua_Mob GetHateDamageTop(Lua_Mob other); Lua_Mob GetHateRandom(); -#ifdef BOTS Lua_Bot GetHateRandomBot(); -#endif Lua_Client GetHateRandomClient(); Lua_NPC GetHateRandomNPC(); Lua_Mob GetHateClosest(); @@ -288,11 +296,16 @@ public: bool SetAA(int rank_id, int new_value); bool SetAA(int rank_id, int new_value, int charges); bool DivineAura(); - void SetOOCRegen(int regen); - const char* GetEntityVariable(const char *name); - void SetEntityVariable(const char *name, const char *value); - bool EntityVariableExists(const char *name); - void Signal(uint32 id); + void SetOOCRegen(int64 new_ooc_regen); + bool ClearEntityVariables(); + bool DeleteEntityVariable(std::string variable_name); + std::string GetEntityVariable(std::string variable_name); + luabind::object GetEntityVariables(lua_State* L); + void SetEntityVariable(std::string variable_name, std::string variable_value); + bool EntityVariableExists(std::string variable_name); + void Signal(int signal_id); + void SendPayload(int payload_id); + void SendPayload(int payload_id, std::string payload_value); bool CombatRange(Lua_Mob other); void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage); void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage); @@ -347,9 +360,9 @@ public: void ChangeDrakkinHeritage(int in); void ChangeDrakkinTattoo(int in); void ChangeDrakkinDetails(int in); - void CameraEffect(uint32 duration, uint32 intensity); - void CameraEffect(uint32 duration, uint32 intensity, Lua_Client c); - void CameraEffect(uint32 duration, uint32 intensity, Lua_Client c, bool global); + void CameraEffect(uint32 duration, float intensity); + void CameraEffect(uint32 duration, float intensity, Lua_Client c); + void CameraEffect(uint32 duration, float intensity, Lua_Client c, bool global); void SendSpellEffect(uint32 effect_id, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk020); void SendSpellEffect(uint32 effect_id, uint32 duration, uint32 finish_delay, bool zone_wide, @@ -364,7 +377,9 @@ public: void TarGlobal(const char *varname, const char *value, const char *duration, int npc_id, int char_id, int zone_id); void DelGlobal(const char *varname); void SetSlotTint(int material_slot, int red_tint, int green_tint, int blue_tint); - void WearChange(int material_slot, int texture, uint32 color); + void WearChange(uint8 material_slot, uint16 texture); + void WearChange(uint8 material_slot, uint16 texture, uint32 color); + void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 heros_forge_model); void DoKnockback(Lua_Mob caster, uint32 push_back, uint32 push_up); void AddNimbusEffect(int effect_id); void RemoveNimbusEffect(int effect_id); @@ -431,13 +446,12 @@ public: bool IsAmnesiad(); int32 GetMeleeMitigation(); int GetWeaponDamageBonus(Lua_Item weapon, bool offhand); - int GetItemStat(uint32 itemid, const char* identifier); + const int GetItemStat(uint32 item_id, std::string identifier); Lua_StatBonuses GetItemBonuses(); Lua_StatBonuses GetSpellBonuses(); Lua_StatBonuses GetAABonuses(); int16 GetMeleeDamageMod_SE(uint16 skill); int16 GetMeleeMinDamageMod_SE(uint16 skill); - bool IsAttackAllowed(Lua_Mob target, bool isSpellAttack); bool IsCasting(); int AttackAnimation(int Hand, Lua_ItemInst weapon); int GetWeaponDamage(Lua_Mob against, Lua_ItemInst weapon); @@ -462,6 +476,43 @@ public: int GetBuffStatValueBySpell(int spell_id, const char* identifier); void SetBuffDuration(int spell_id); void SetBuffDuration(int spell_id, int duration); + void CloneAppearance(Lua_Mob other); + void CloneAppearance(Lua_Mob other, bool clone_name); + void DamageArea(int64 damage); + void DamageArea(int64 damage, uint32 distance); + void DamageAreaPercentage(int64 damage); + void DamageAreaPercentage(int64 damage, uint32 distance); + void DamageAreaBots(int64 damage); + void DamageAreaBots(int64 damage, uint32 distance); + void DamageAreaBotsPercentage(int64 damage); + void DamageAreaBotsPercentage(int64 damage, uint32 distance); + void DamageAreaClients(int64 damage); + void DamageAreaClients(int64 damage, uint32 distance); + void DamageAreaClientsPercentage(int64 damage); + void DamageAreaClientsPercentage(int64 damage, uint32 distance); + void DamageAreaNPCs(int64 damage); + void DamageAreaNPCs(int64 damage, uint32 distance); + void DamageAreaNPCsPercentage(int64 damage); + void DamageAreaNPCsPercentage(int64 damage, uint32 distance); + void DamageHateList(int64 damage); + void DamageHateList(int64 damage, uint32 distance); + void DamageHateListPercentage(int64 damage); + void DamageHateListPercentage(int64 damage, uint32 distance); + void DamageHateListBots(int64 damage); + void DamageHateListBots(int64 damage, uint32 distance); + void DamageHateListBotsPercentage(int64 damage); + void DamageHateListBotsPercentage(int64 damage, uint32 distance); + void DamageHateListClients(int64 damage); + void DamageHateListClients(int64 damage, uint32 distance); + void DamageHateListClientsPercentage(int64 damage); + void DamageHateListClientsPercentage(int64 damage, uint32 distance); + void DamageHateListNPCs(int64 damage); + void DamageHateListNPCs(int64 damage, uint32 distance); + void DamageHateListNPCsPercentage(int64 damage); + void DamageHateListNPCsPercentage(int64 damage, uint32 distance); + void CopyHateList(Lua_Mob to); + bool IsAttackAllowed(Lua_Mob target); + bool IsAttackAllowed(Lua_Mob target, bool is_spell_attack); }; #endif diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index 382f8adba..147a3a046 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -45,6 +45,7 @@ void LuaMod::Init() m_has_get_exp_for_level = parser_->HasFunction("GetEXPForLevel", package_name_); m_has_get_experience_for_kill = parser_->HasFunction("GetExperienceForKill", package_name_); m_has_common_outgoing_hit_success = parser_->HasFunction("CommonOutgoingHitSuccess", package_name_); + m_has_calc_spell_effect_value_formula = parser_->HasFunction("CalcSpellEffectValue_formula", package_name_); } void PutDamageHitInfo(lua_State *L, luabind::adl::object &e, DamageHitInfo &hit) { @@ -206,7 +207,7 @@ void LuaMod::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, Extra if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -253,7 +254,7 @@ void LuaMod::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -301,7 +302,7 @@ void LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &return if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -354,7 +355,7 @@ void LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ret if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -409,7 +410,7 @@ void LuaMod::CommonOutgoingHitSuccess(Mob *self, Mob *other, DamageHitInfo &hit, if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -459,7 +460,7 @@ void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraA if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -505,7 +506,7 @@ void LuaMod::GetRequiredAAExperience(Client *self, uint32 &returnValue, bool &ig if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -553,7 +554,7 @@ void LuaMod::GetEXPForLevel(Client *self, uint16 level, uint32 &returnValue, boo if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -581,10 +582,9 @@ void LuaMod::GetEXPForLevel(Client *self, uint16 level, uint32 &returnValue, boo } } -void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint32 &returnValue, bool &ignoreDefault) +void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint64 &returnValue, bool &ignoreDefault) { int start = lua_gettop(L); - uint32 retval = 0; try { if (!m_has_get_experience_for_kill) { @@ -604,7 +604,7 @@ void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint32 &returnValu if (lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); parser_->AddError(error); - lua_pop(L, 1); + lua_pop(L, 2); return; } @@ -617,7 +617,62 @@ void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint32 &returnValu auto returnValueObj = ret["ReturnValue"]; if (luabind::type(returnValueObj) == LUA_TNUMBER) { - returnValue = luabind::object_cast(returnValueObj); + returnValue = luabind::object_cast(returnValueObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, int64 &returnValue, bool &ignoreDefault) +{ + int start = lua_gettop(L); + int64 retval = 0; + + try { + if (!m_has_calc_spell_effect_value_formula) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "CalcSpellEffectValue_formula"); + + Lua_Mob l_self(self); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["formula"] = formula; + e["base_value"] = base_value; + e["max_value"] = max_value; + e["caster_level"] = caster_level; + e["spell_id"] = spell_id; + e["ticsremaining"] = ticsremaining; + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 2); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TNUMBER) { + returnValue = luabind::object_cast(returnValueObj); } } } diff --git a/zone/lua_mod.h b/zone/lua_mod.h index defc5edab..2028d8aed 100644 --- a/zone/lua_mod.h +++ b/zone/lua_mod.h @@ -25,7 +25,8 @@ public: void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); void GetRequiredAAExperience(Client *self, uint32 &returnValue, bool &ignoreDefault); void GetEXPForLevel(Client *self, uint16 level, uint32 &returnValue, bool &ignoreDefault); - void GetExperienceForKill(Client *self, Mob *against, uint32 &returnValue, bool &ignoreDefault); + void GetExperienceForKill(Client *self, Mob *against, uint64 &returnValue, bool &ignoreDefault); + void CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, int64 &returnValue, bool &ignoreDefault); private: LuaParser *parser_; lua_State *L; @@ -40,4 +41,5 @@ private: bool m_has_get_required_aa_experience; bool m_has_get_exp_for_level; bool m_has_get_experience_for_kill; + bool m_has_calc_spell_effect_value_formula; }; diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index c84cfe82e..8e1ac586f 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -12,9 +12,9 @@ struct Lua_NPC_Loot_List { std::vector entries; }; -void Lua_NPC::Signal(int id) { +void Lua_NPC::Signal(int signal_id) { Lua_Safe_Call_Void(); - self->SignalNPC(id); + self->SignalNPC(signal_id); } int Lua_NPC::CheckNPCFactionAlly(int faction) { @@ -318,6 +318,16 @@ void Lua_NPC::NextGuardPosition() { self->NextGuardPosition(); } +void Lua_NPC::SaveGuardSpot() { + Lua_Safe_Call_Void(); + self->SaveGuardSpot(); +} + +void Lua_NPC::SaveGuardSpot(bool clear) { + Lua_Safe_Call_Void(); + self->SaveGuardSpot(clear); +} + void Lua_NPC::SaveGuardSpot(float x, float y, float z, float heading) { Lua_Safe_Call_Void(); self->SaveGuardSpot(glm::vec4(x, y, z, heading)); @@ -448,7 +458,7 @@ void Lua_NPC::SetSwarmTarget(int target) { self->SetSwarmTarget(target); } -void Lua_NPC::ModifyNPCStat(const char *stat, const char *value) { +void Lua_NPC::ModifyNPCStat(std::string stat, std::string value) { Lua_Safe_Call_Void(); self->ModifyNPCStat(stat, value); } @@ -575,10 +585,10 @@ bool Lua_NPC::IsRaidTarget() return self->IsRaidTarget(); } -void Lua_NPC::ChangeLastName(const char *lastname) +void Lua_NPC::ChangeLastName(std::string last_name) { Lua_Safe_Call_Void(); - self->ChangeLastName(lastname); + self->ChangeLastName(last_name); } void Lua_NPC::ClearLastName() @@ -653,10 +663,42 @@ bool Lua_NPC::HasAISpellEffect(int spell_effect_id) return self->HasAISpellEffect(spell_effect_id); } -float Lua_NPC::GetNPCStat(const char* identifier) +float Lua_NPC::GetNPCStat(std::string stat) { Lua_Safe_Call_Real(); - return self->GetNPCStat(identifier); + return self->GetNPCStat(stat); +} + +bool Lua_NPC::IsRareSpawn() +{ + Lua_Safe_Call_Bool(); + return self->IsRareSpawn(); +} + +void Lua_NPC::ReloadSpells() +{ + Lua_Safe_Call_Void(); + self->ReloadSpells(); +} + +void Lua_NPC::SendPayload(int payload_id) { + Lua_Safe_Call_Void(); + self->SendPayload(payload_id); +} + +void Lua_NPC::SendPayload(int payload_id, std::string payload_value) { + Lua_Safe_Call_Void(); + self->SendPayload(payload_id, payload_value); +} + +bool Lua_NPC::GetKeepsSoldItems() { + Lua_Safe_Call_Bool(); + return self->GetKeepsSoldItems(); +} + +void Lua_NPC::SetKeepsSoldItems(bool keeps_sold_items) { + Lua_Safe_Call_Void(); + self->SetKeepsSoldItems(keeps_sold_items); } luabind::scope lua_register_npc() { @@ -680,7 +722,7 @@ luabind::scope lua_register_npc() { .def("AddLootTable", (void(Lua_NPC::*)(void))&Lua_NPC::AddLootTable) .def("AssignWaypoints", (void(Lua_NPC::*)(int))&Lua_NPC::AssignWaypoints) .def("CalculateNewWaypoint", (void(Lua_NPC::*)(void))&Lua_NPC::CalculateNewWaypoint) - .def("ChangeLastName", (void(Lua_NPC::*)(const char*))&Lua_NPC::ChangeLastName) + .def("ChangeLastName", (void(Lua_NPC::*)(std::string))&Lua_NPC::ChangeLastName) .def("CheckNPCFactionAlly", (int(Lua_NPC::*)(int))&Lua_NPC::CheckNPCFactionAlly) .def("ClearItemList", (void(Lua_NPC::*)(void))&Lua_NPC::ClearItemList) .def("ClearLastName", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLastName) @@ -704,6 +746,7 @@ luabind::scope lua_register_npc() { .def("GetGuardPointZ", (float(Lua_NPC::*)(void))&Lua_NPC::GetGuardPointZ) .def("GetHealScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetHealScale) .def("GetItemIDBySlot", (uint32(Lua_NPC::*)(uint16))&Lua_NPC::GetItemIDBySlot) + .def("GetKeepsSoldItems", (bool(Lua_NPC::*)(void))&Lua_NPC::GetKeepsSoldItems) .def("GetLootList", (Lua_NPC_Loot_List(Lua_NPC::*)(lua_State* L))&Lua_NPC::GetLootList) .def("GetLoottableID", (int(Lua_NPC::*)(void))&Lua_NPC::GetLoottableID) .def("GetMaxDMG", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetMaxDMG) @@ -714,7 +757,7 @@ luabind::scope lua_register_npc() { .def("GetNPCHate", (int64(Lua_NPC::*)(Lua_Mob))&Lua_NPC::GetNPCHate) .def("GetNPCSpellsID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID) .def("GetNPCSpellsID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID) - .def("GetNPCStat", (float(Lua_NPC::*)(const char*))&Lua_NPC::GetNPCStat) + .def("GetNPCStat", (float(Lua_NPC::*)(std::string))&Lua_NPC::GetNPCStat) .def("GetPetSpellID", (int(Lua_NPC::*)(void))&Lua_NPC::GetPetSpellID) .def("GetPlatinum", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetPlatinum) .def("GetPrimSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetPrimSkill) @@ -743,15 +786,17 @@ luabind::scope lua_register_npc() { .def("IsGuarding", (bool(Lua_NPC::*)(void))&Lua_NPC::IsGuarding) .def("IsOnHatelist", (bool(Lua_NPC::*)(Lua_Mob))&Lua_NPC::IsOnHatelist) .def("IsRaidTarget", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRaidTarget) + .def("IsRareSpawn", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRareSpawn) .def("IsTaunting", (bool(Lua_NPC::*)(void))&Lua_NPC::IsTaunting) .def("MerchantCloseShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantCloseShop) .def("MerchantOpenShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantOpenShop) - .def("ModifyNPCStat", (void(Lua_NPC::*)(const char*,const char*))&Lua_NPC::ModifyNPCStat) + .def("ModifyNPCStat", (void(Lua_NPC::*)(std::string,std::string))&Lua_NPC::ModifyNPCStat) .def("MoveTo", (void(Lua_NPC::*)(float,float,float,float,bool))&Lua_NPC::MoveTo) .def("NextGuardPosition", (void(Lua_NPC::*)(void))&Lua_NPC::NextGuardPosition) .def("PauseWandering", (void(Lua_NPC::*)(int))&Lua_NPC::PauseWandering) .def("PickPocket", (void(Lua_NPC::*)(Lua_Client))&Lua_NPC::PickPocket) .def("RecalculateSkills", (void(Lua_NPC::*)(void))&Lua_NPC::RecalculateSkills) + .def("ReloadSpells", (void(Lua_NPC::*)(void))&Lua_NPC::ReloadSpells) .def("RemoveAISpell", (void(Lua_NPC::*)(int))&Lua_NPC::RemoveAISpell) .def("RemoveAISpellEffect", (void(Lua_NPC::*)(int))&Lua_NPC::RemoveAISpellEffect) .def("RemoveCash", (void(Lua_NPC::*)(void))&Lua_NPC::RemoveCash) @@ -759,14 +804,19 @@ luabind::scope lua_register_npc() { .def("RemoveItem", (void(Lua_NPC::*)(int,int))&Lua_NPC::RemoveItem) .def("RemoveItem", (void(Lua_NPC::*)(int,int,int))&Lua_NPC::RemoveItem) .def("ResumeWandering", (void(Lua_NPC::*)(void))&Lua_NPC::ResumeWandering) + .def("SaveGuardSpot", (void(Lua_NPC::*)(void))&Lua_NPC::SaveGuardSpot) + .def("SaveGuardSpot", (void(Lua_NPC::*)(bool))&Lua_NPC::SaveGuardSpot) .def("SaveGuardSpot", (void(Lua_NPC::*)(float,float,float,float))&Lua_NPC::SaveGuardSpot) .def("ScaleNPC", (void(Lua_NPC::*)(uint8))&Lua_NPC::ScaleNPC) + .def("SendPayload", (void(Lua_NPC::*)(int))&Lua_NPC::SendPayload) + .def("SendPayload", (void(Lua_NPC::*)(int,std::string))&Lua_NPC::SendPayload) .def("SetCopper", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetCopper) .def("SetFollowCanRun", (void(Lua_NPC::*)(bool))&Lua_NPC::SetFollowCanRun) .def("SetFollowDistance", (void(Lua_NPC::*)(int))&Lua_NPC::SetFollowDistance) .def("SetFollowID", (void(Lua_NPC::*)(int))&Lua_NPC::SetFollowID) .def("SetGold", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetGold) .def("SetGrid", (void(Lua_NPC::*)(int))&Lua_NPC::SetGrid) + .def("SetKeepsSoldItems", (void(Lua_NPC::*)(bool))&Lua_NPC::SetKeepsSoldItems) .def("SetNPCFactionID", (void(Lua_NPC::*)(int))&Lua_NPC::SetNPCFactionID) .def("SetPetSpellID", (void(Lua_NPC::*)(int))&Lua_NPC::SetPetSpellID) .def("SetPlatinum", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetPlatinum) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 6b1e71363..ad42c5cee 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -29,7 +29,7 @@ public: return reinterpret_cast(GetLuaPtrData()); } - void Signal(int id); + void Signal(int signal_id); int CheckNPCFactionAlly(int faction); void AddItem(int item_id, int charges); void AddItem(int item_id, int charges, bool equip); @@ -90,6 +90,8 @@ public: void PauseWandering(int pause_time); void MoveTo(float x, float y, float z, float h, bool save); void NextGuardPosition(); + void SaveGuardSpot(); + void SaveGuardSpot(bool clear); void SaveGuardSpot(float x, float y, float z, float heading); bool IsGuarding(); void AI_SetRoambox(float dist, float max_x, float min_x, float max_y, float min_y); @@ -116,7 +118,7 @@ public: int GetSwarmOwner(); int GetSwarmTarget(); void SetSwarmTarget(int target); - void ModifyNPCStat(const char *stat, const char *value); + void ModifyNPCStat(std::string stat, std::string value); void AddAISpell(int priority, int spell_id, int type, int mana_cost, int recast_delay, int resist_adjust); void AddAISpell(int priority, int spell_id, int type, int mana_cost, int recast_delay, int resist_adjust, int min_hp, int max_hp); void RemoveAISpell(int spell_id); @@ -138,9 +140,11 @@ public: void SetSimpleRoamBox(float box_size, float move_distance); void SetSimpleRoamBox(float box_size, float move_distance, int move_delay); void RecalculateSkills(); + void ReloadSpells(); void ScaleNPC(uint8 npc_level); bool IsRaidTarget(); - void ChangeLastName(const char *lastname); + bool IsRareSpawn(); + void ChangeLastName(std::string last_name); void ClearLastName(); bool HasItem(uint32 item_id); uint16 CountItem(uint32 item_id); @@ -152,7 +156,11 @@ public: void AddAISpellEffect(int spell_effect_id, int base_value, int limit_value, int max_value); void RemoveAISpellEffect(int spell_effect_id); bool HasAISpellEffect(int spell_effect_id); - float GetNPCStat(const char* identifier); + float GetNPCStat(std::string stat); + void SendPayload(int payload_id); + void SendPayload(int payload_id, std::string payload_value); + bool GetKeepsSoldItems(); + void SetKeepsSoldItems(bool keeps_sold_items); }; #endif diff --git a/zone/lua_object.cpp b/zone/lua_object.cpp index 09599ecac..d5870a800 100644 --- a/zone/lua_object.cpp +++ b/zone/lua_object.cpp @@ -163,19 +163,44 @@ void Lua_Object::Close() { self->Close(); } -const char *Lua_Object::GetEntityVariable(const char *name) { +std::string Lua_Object::GetEntityVariable(std::string variable_name) { Lua_Safe_Call_String(); - return self->GetEntityVariable(name); + return self->GetEntityVariable(variable_name); } -void Lua_Object::SetEntityVariable(const char *name, const char *value) { +luabind::object Lua_Object::GetEntityVariables(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetEntityVariables(); + auto i = 0; + for (const auto& v : l) { + t[i] = v; + i++; + } + } + + return t; +} + +bool Lua_Object::ClearEntityVariables() { + Lua_Safe_Call_Bool(); + return self->ClearEntityVariables(); +} + +bool Lua_Object::DeleteEntityVariable(std::string variable_name) { + Lua_Safe_Call_Bool(); + return self->DeleteEntityVariable(variable_name); +} + +void Lua_Object::SetEntityVariable(std::string variable_name, std::string variable_value) { Lua_Safe_Call_Void(); - self->SetEntityVariable(name, value); + self->SetEntityVariable(variable_name, variable_value); } -bool Lua_Object::EntityVariableExists(const char *name) { +bool Lua_Object::EntityVariableExists(std::string variable_name) { Lua_Safe_Call_Int(); - return self->EntityVariableExists(name); + return self->EntityVariableExists(variable_name); } luabind::scope lua_register_object() { @@ -183,15 +208,18 @@ luabind::scope lua_register_object() { .def(luabind::constructor<>()) .property("null", &Lua_Object::Null) .property("valid", &Lua_Object::Valid) + .def("ClearEntityVariables", (bool(Lua_Object::*)(void))&Lua_Object::ClearEntityVariables) .def("ClearUser", (void(Lua_Object::*)(void))&Lua_Object::ClearUser) .def("Close", (void(Lua_Object::*)(void))&Lua_Object::Close) .def("Delete", (void(Lua_Object::*)(bool))&Lua_Object::Delete) .def("Delete", (void(Lua_Object::*)(void))&Lua_Object::Delete) + .def("DeleteEntityVariable", (bool(Lua_Object::*)(std::string))&Lua_Object::DeleteEntityVariable) .def("DeleteItem", (void(Lua_Object::*)(int))&Lua_Object::DeleteItem) .def("Depop", (void(Lua_Object::*)(void))&Lua_Object::Depop) - .def("EntityVariableExists", (bool(Lua_Object::*)(const char*))&Lua_Object::EntityVariableExists) + .def("EntityVariableExists", (bool(Lua_Object::*)(std::string))&Lua_Object::EntityVariableExists) .def("GetDBID", (uint32(Lua_Object::*)(void))&Lua_Object::GetDBID) - .def("GetEntityVariable", (const char*(Lua_Object::*)(const char*))&Lua_Object::GetEntityVariable) + .def("GetEntityVariable", (std::string(Lua_Object::*)(std::string))&Lua_Object::GetEntityVariable) + .def("GetEntityVariables", (luabind::object(Lua_Object::*)(lua_State*))&Lua_Object::GetEntityVariables) .def("GetHeading", (float(Lua_Object::*)(void))&Lua_Object::GetHeading) .def("GetID", (int(Lua_Object::*)(void))&Lua_Object::GetID) .def("GetIcon", (uint32(Lua_Object::*)(void))&Lua_Object::GetIcon) @@ -204,7 +232,7 @@ luabind::scope lua_register_object() { .def("IsGroundSpawn", (bool(Lua_Object::*)(void))&Lua_Object::IsGroundSpawn) .def("Repop", (void(Lua_Object::*)(void))&Lua_Object::Repop) .def("Save", (bool(Lua_Object::*)(void))&Lua_Object::Save) - .def("SetEntityVariable", (void(Lua_Object::*)(const char*,const char*))&Lua_Object::SetEntityVariable) + .def("SetEntityVariable", (void(Lua_Object::*)(std::string,std::string))&Lua_Object::SetEntityVariable) .def("SetHeading", (void(Lua_Object::*)(float))&Lua_Object::SetHeading) .def("SetID", (void(Lua_Object::*)(int))&Lua_Object::SetID) .def("SetIcon", (void(Lua_Object::*)(uint32))&Lua_Object::SetIcon) diff --git a/zone/lua_object.h b/zone/lua_object.h index b93c3e761..65f5fbe80 100644 --- a/zone/lua_object.h +++ b/zone/lua_object.h @@ -60,9 +60,12 @@ public: void Delete(bool reset_state); bool IsGroundSpawn(); void Close(); - const char *GetEntityVariable(const char *name); - void SetEntityVariable(const char *name, const char *value); - bool EntityVariableExists(const char *name); + bool ClearEntityVariables(); + bool DeleteEntityVariable(std::string variable_name); + std::string GetEntityVariable(std::string variable_name); + luabind::object GetEntityVariables(lua_State* L); + void SetEntityVariable(std::string variable_name, std::string variable_value); + bool EntityVariableExists(std::string variable_name); }; #endif diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index b07a7011f..1ebb3489e 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -365,7 +365,7 @@ luabind::scope lua_register_packet() { luabind::scope lua_register_packet_opcodes() { return luabind::class_("Opcode") .enum_("constants") - [ + [( luabind::value("ExploreUnknown", static_cast(OP_ExploreUnknown)), luabind::value("Heartbeat", static_cast(OP_Heartbeat)), luabind::value("ReloadUI", static_cast(OP_ReloadUI)), @@ -911,7 +911,7 @@ luabind::scope lua_register_packet_opcodes() { luabind::value("ClientTimeStamp", static_cast(OP_ClientTimeStamp)), luabind::value("GuildPromote", static_cast(OP_GuildPromote)), luabind::value("Fling", static_cast(OP_Fling)) - ]; + )]; } #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 34ef62fbd..bbd7aa33d 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -39,10 +39,9 @@ #include "lua_general.h" #include "lua_encounter.h" #include "lua_stat_bonuses.h" +#include "../common/path_manager.h" -#ifdef BOTS #include "lua_bot.h" -#endif const char *LuaEvents[_LargestEventID] = { "event_say", @@ -140,7 +139,23 @@ const char *LuaEvents[_LargestEventID] = { "event_equip_item_client", "event_unequip_item_client", "event_skill_up", - "event_language_skill_up" + "event_language_skill_up", + "event_alt_currency_merchant_buy", + "event_alt_currency_merchant_sell", + "event_merchant_buy", + "event_merchant_sell", + "event_inspect", + "event_task_before_update", + "event_aa_buy", + "event_aa_gain", + "event_payload", + "event_level_down", + "event_gm_command", + "event_despawn", + "event_despawn_zone", + "event_bot_create", + "event_augment_insert_client", + "event_augment_remove_client", }; extern Zone *zone; @@ -162,6 +177,7 @@ LuaParser::LuaParser() { ItemArgumentDispatch[i] = handle_item_null; SpellArgumentDispatch[i] = handle_spell_null; EncounterArgumentDispatch[i] = handle_encounter_null; + BotArgumentDispatch[i] = handle_bot_null; } NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say; @@ -185,12 +201,16 @@ LuaParser::LuaParser() { NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer; NPCArgumentDispatch[EVENT_DEATH] = handle_npc_death; NPCArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_npc_death; + NPCArgumentDispatch[EVENT_DEATH_ZONE] = handle_npc_death; NPCArgumentDispatch[EVENT_CAST] = handle_npc_cast; NPCArgumentDispatch[EVENT_CAST_BEGIN] = handle_npc_cast; NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client; NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area; NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area; NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone; + NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone; + NPCArgumentDispatch[EVENT_PAYLOAD] = handle_npc_payload; + NPCArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_npc_despawn_zone; PlayerArgumentDispatch[EVENT_SAY] = handle_player_say; PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage; @@ -216,6 +236,7 @@ LuaParser::LuaParser() { PlayerArgumentDispatch[EVENT_TASK_STAGE_COMPLETE] = handle_player_task_stage_complete; PlayerArgumentDispatch[EVENT_TASK_COMPLETE] = handle_player_task_update; PlayerArgumentDispatch[EVENT_TASK_UPDATE] = handle_player_task_update; + PlayerArgumentDispatch[EVENT_TASK_BEFORE_UPDATE] = handle_player_task_update; PlayerArgumentDispatch[EVENT_COMMAND] = handle_player_command; PlayerArgumentDispatch[EVENT_COMBINE_SUCCESS] = handle_player_combine; PlayerArgumentDispatch[EVENT_COMBINE_FAILURE] = handle_player_combine; @@ -236,6 +257,20 @@ LuaParser::LuaParser() { PlayerArgumentDispatch[EVENT_UNEQUIP_ITEM_CLIENT] = handle_player_equip_item; PlayerArgumentDispatch[EVENT_SKILL_UP] = handle_player_skill_up; PlayerArgumentDispatch[EVENT_LANGUAGE_SKILL_UP] = handle_player_skill_up; + PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_BUY] = handle_player_alt_currency_merchant; + PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_SELL] = handle_player_alt_currency_merchant; + PlayerArgumentDispatch[EVENT_MERCHANT_BUY] = handle_player_merchant; + PlayerArgumentDispatch[EVENT_MERCHANT_SELL] = handle_player_merchant; + PlayerArgumentDispatch[EVENT_INSPECT] = handle_player_inspect; + PlayerArgumentDispatch[EVENT_AA_BUY] = handle_player_aa_buy; + PlayerArgumentDispatch[EVENT_AA_GAIN] = handle_player_aa_gain; + PlayerArgumentDispatch[EVENT_PAYLOAD] = handle_player_payload; + PlayerArgumentDispatch[EVENT_LEVEL_UP] = handle_player_level_up; + PlayerArgumentDispatch[EVENT_LEVEL_DOWN] = handle_player_level_down; + PlayerArgumentDispatch[EVENT_GM_COMMAND] = handle_player_gm_command; + PlayerArgumentDispatch[EVENT_BOT_CREATE] = handle_player_bot_create; + PlayerArgumentDispatch[EVENT_AUGMENT_INSERT_CLIENT] = handle_player_augment_insert; + PlayerArgumentDispatch[EVENT_AUGMENT_REMOVE_CLIENT] = handle_player_augment_remove; ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click; @@ -258,6 +293,23 @@ LuaParser::LuaParser() { EncounterArgumentDispatch[EVENT_ENCOUNTER_LOAD] = handle_encounter_load; EncounterArgumentDispatch[EVENT_ENCOUNTER_UNLOAD] = handle_encounter_unload; + BotArgumentDispatch[EVENT_CAST] = handle_bot_cast; + BotArgumentDispatch[EVENT_CAST_BEGIN] = handle_bot_cast; + BotArgumentDispatch[EVENT_CAST_ON] = handle_bot_cast; + BotArgumentDispatch[EVENT_COMBAT] = handle_bot_combat; + BotArgumentDispatch[EVENT_DEATH] = handle_bot_death; + BotArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_bot_death; + BotArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_bot_popup_response; + BotArgumentDispatch[EVENT_SAY] = handle_bot_say; + BotArgumentDispatch[EVENT_SIGNAL] = handle_bot_signal; + BotArgumentDispatch[EVENT_SLAY] = handle_bot_slay; + BotArgumentDispatch[EVENT_TARGET_CHANGE] = handle_bot_target_change; + BotArgumentDispatch[EVENT_TIMER] = handle_bot_timer; + BotArgumentDispatch[EVENT_TRADE] = handle_bot_trade; + BotArgumentDispatch[EVENT_USE_SKILL] = handle_bot_use_skill; + BotArgumentDispatch[EVENT_PAYLOAD] = handle_bot_payload; +#endif + L = nullptr; } @@ -272,7 +324,7 @@ LuaParser::~LuaParser() { } int LuaParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -291,7 +343,7 @@ int LuaParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, } int LuaParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -309,7 +361,7 @@ int LuaParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string } int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::adl::object *l_func) { + std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -340,6 +392,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M std::string error = lua_tostring(L, -1); AddError(error); quest_manager.EndQuest(); + lua_pop(L, npop); return 0; } quest_manager.EndQuest(); @@ -368,7 +421,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M } int LuaParser::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -386,7 +439,7 @@ int LuaParser::EventPlayer(QuestEventID evt, Client *client, std::string data, u } int LuaParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -404,7 +457,7 @@ int LuaParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string d } int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::adl::object *l_func) { + std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -433,6 +486,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * std::string error = lua_tostring(L, -1); AddError(error); quest_manager.EndQuest(); + lua_pop(L, npop); return 0; } quest_manager.EndQuest(); @@ -461,7 +515,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * } int LuaParser::EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -481,7 +535,7 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *ite } int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, - std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func) { + std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -493,6 +547,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl } else { lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str()); lua_getfield(L, -1, sub_name); + npop = 2; } lua_createtable(L, 0, 0); @@ -516,6 +571,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl std::string error = lua_tostring(L, -1); AddError(error); quest_manager.EndQuest(); + lua_pop(L, npop); return 0; } quest_manager.EndQuest(); @@ -543,8 +599,8 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl return 0; } -int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +int LuaParser::EventSpell(QuestEventID evt, Mob* mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -556,11 +612,11 @@ int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spe return 0; } - return _EventSpell(package_name, evt, npc, client, spell_id, data, extra_data, extra_pointers); + return _EventSpell(package_name, evt, mob, client, spell_id, data, extra_data, extra_pointers); } -int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::adl::object *l_func) { +int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, Mob* mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -590,13 +646,14 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, lua_setfield(L, -2, "self"); auto arg_function = SpellArgumentDispatch[evt]; - arg_function(this, L, npc, client, spell_id, data, extra_data, extra_pointers); + arg_function(this, L, mob, client, spell_id, data, extra_data, extra_pointers); - quest_manager.StartQuest(npc, client, nullptr, const_cast(&spells[spell_id])); + quest_manager.StartQuest(mob, client, nullptr, const_cast(&spells[spell_id])); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); AddError(error); quest_manager.EndQuest(); + lua_pop(L, npop); return 0; } quest_manager.EndQuest(); @@ -624,7 +681,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, return 0; } -int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { +int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -640,7 +697,7 @@ int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, std: } int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -663,6 +720,7 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std:: std::string error = lua_tostring(L, -1); AddError(error); quest_manager.EndQuest(); + lua_pop(L, 2); return 0; } quest_manager.EndQuest(); @@ -903,7 +961,7 @@ void LuaParser::ReloadQuests() { #error Incompatible lua version #endif -#ifdef WINDOWS +#ifdef _WINDOWS const char libext[] = ".dll"; #else // lua doesn't care OSX doesn't use sonames @@ -913,11 +971,11 @@ void LuaParser::ReloadQuests() { lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); std::string module_path = lua_tostring(L,-1); - module_path += ";./" + Config->LuaModuleDir + "?.lua;./" + Config->LuaModuleDir + "?/init.lua"; + module_path += ";" + path.GetLuaModulesPath() + "/?.lua;" + path.GetLuaModulesPath() + "/?/init.lua"; // luarock paths using lua_modules as tree // to path it adds foo/share/lua/5.1/?.lua and foo/share/lua/5.1/?/init.lua - module_path += ";./" + Config->LuaModuleDir + "share/lua/" + lua_version + "/?.lua"; - module_path += ";./" + Config->LuaModuleDir + "share/lua/" + lua_version + "/?/init.lua"; + module_path += ";" + path.GetLuaModulesPath() + "/share/lua/" + lua_version + "/?.lua"; + module_path += ";" + path.GetLuaModulesPath() + "/share/lua/" + lua_version + "/?/init.lua"; lua_pop(L, 1); lua_pushstring(L, module_path.c_str()); lua_setfield(L, -2, "path"); @@ -926,10 +984,10 @@ void LuaParser::ReloadQuests() { lua_getglobal(L, "package"); lua_getfield(L, -1, "cpath"); module_path = lua_tostring(L, -1); - module_path += ";./" + Config->LuaModuleDir + "?" + libext; + module_path += ";" + path.GetLuaModulesPath() + "/?" + libext; // luarock paths using lua_modules as tree // luarocks adds foo/lib/lua/5.1/?.so for cpath - module_path += ";./" + Config->LuaModuleDir + "lib/lua/" + lua_version + "/?" + libext; + module_path += ";" + path.GetLuaModulesPath() + "/lib/lua/" + lua_version + "/?" + libext; lua_pop(L, 1); lua_pushstring(L, module_path.c_str()); lua_setfield(L, -2, "cpath"); @@ -937,17 +995,14 @@ void LuaParser::ReloadQuests() { MapFunctions(L); - //load init - std::string path = Config->QuestDir; - path += "/"; - path += QUEST_GLOBAL_DIRECTORY; - path += "/script_init.lua"; + // load init + std::string filename = fmt::format("{}/{}/script_init.lua", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); - FILE *f = fopen(path.c_str(), "r"); + FILE *f = fopen(filename.c_str(), "r"); if(f) { fclose(f); - if(luaL_dofile(L, path.c_str())) { + if(luaL_dofile(L, filename.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); } @@ -955,12 +1010,13 @@ void LuaParser::ReloadQuests() { //zone init - always loads after global if(zone) { - std::string zone_script = Config->QuestDir; - zone_script += "/"; - zone_script += zone->GetShortName(); - zone_script += "/script_init_v"; - zone_script += std::to_string(zone->GetInstanceVersion()); - zone_script += ".lua"; + std::string zone_script = fmt::format( + "{}/{}/script_init_v{}.lua", + path.GetQuestsPath(), + zone->GetShortName(), + zone->GetInstanceVersion() + ); + f = fopen(zone_script.c_str(), "r"); if(f) { fclose(f); @@ -971,10 +1027,8 @@ void LuaParser::ReloadQuests() { } } else { - zone_script = Config->QuestDir; - zone_script += "/"; - zone_script += zone->GetShortName(); - zone_script += "/script_init.lua"; + zone_script = fmt::format("{}/{}/script_init.lua", path.GetQuestsPath(), zone->GetShortName()); + f = fopen(zone_script.c_str(), "r"); if (f) { fclose(f); @@ -987,20 +1041,20 @@ void LuaParser::ReloadQuests() { } } - FILE *load_order = fopen("mods/load_order.txt", "r"); + FILE *load_order = fopen(fmt::format("{}/load_order.txt", path.GetLuaModsPath()).c_str(), "r"); if (load_order) { char file_name[256] = { 0 }; while (fgets(file_name, 256, load_order) != nullptr) { - for (int i = 0; i < 256; ++i) { - auto c = file_name[i]; + for (char & i : file_name) { + auto c = i; if (c == '\n' || c == '\r' || c == ' ') { - file_name[i] = 0; + i = 0; break; } } - LoadScript("mods/" + std::string(file_name), file_name); - mods_.push_back(LuaMod(L, this, file_name)); + LoadScript(fmt::format("{}/{}", path.GetLuaModsPath(), std::string(file_name)), file_name); + mods_.emplace_back(L, this, file_name); } fclose(load_order); @@ -1089,13 +1143,26 @@ bool LuaParser::HasFunction(std::string subname, std::string package_name) { return false; } +bool LuaParser::HasEncounterSub(const std::string& package_name, QuestEventID evt) +{ + auto it = lua_encounter_events_registered.find(package_name); + if (it != lua_encounter_events_registered.end()) { + for (auto & riter : it->second) { + if (riter.event_id == evt) { + return true; + } + } + } + return false; +} + void LuaParser::MapFunctions(lua_State *L) { try { luabind::open(L); luabind::module(L) - [ + [( lua_register_general(), lua_register_random(), lua_register_events(), @@ -1115,9 +1182,7 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_special_abilities(), lua_register_npc(), lua_register_client(), -#ifdef BOTS lua_register_bot(), -#endif lua_register_inventory(), lua_register_inventory_where(), lua_register_iteminst(), @@ -1129,9 +1194,7 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_entity_list(), lua_register_mob_list(), lua_register_client_list(), -#ifdef BOTS lua_register_bot_list(), -#endif lua_register_npc_list(), lua_register_corpse_list(), lua_register_object_list(), @@ -1155,7 +1218,7 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_journal_mode(), lua_register_expedition(), lua_register_expedition_lock_messages() - ]; + )]; } catch(std::exception &ex) { std::string error = ex.what(); @@ -1164,7 +1227,7 @@ void LuaParser::MapFunctions(lua_State *L) { } int LuaParser::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -1210,7 +1273,7 @@ int LuaParser::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::stri } int LuaParser::DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -1239,7 +1302,7 @@ int LuaParser::DispatchEventPlayer(QuestEventID evt, Client *client, std::string } int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -1284,8 +1347,8 @@ int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, EQ::ItemInsta return ret; } -int LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +int LuaParser::DispatchEventSpell(QuestEventID evt, Mob* mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -1300,7 +1363,7 @@ int LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, ui while(riter != iter->second.end()) { if(riter->event_id == evt) { std::string package_name = "encounter_" + riter->encounter_name; - int i = _EventSpell(package_name, evt, npc, client, spell_id, data, extra_data, extra_pointers, &riter->lua_reference); + int i = _EventSpell(package_name, evt, mob, client, spell_id, data, extra_data, extra_pointers, &riter->lua_reference); if(i != 0) { ret = i; } @@ -1318,7 +1381,7 @@ int LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, ui while(riter != iter->second.end()) { if(riter->event_id == evt) { std::string package_name = "encounter_" + riter->encounter_name; - int i = _EventSpell(package_name, evt, npc, client, spell_id, data, extra_data, extra_pointers, &riter->lua_reference); + int i = _EventSpell(package_name, evt, mob, client, spell_id, data, extra_data, extra_pointers, &riter->lua_reference); if(i != 0) ret = i; } @@ -1333,10 +1396,12 @@ QuestEventID LuaParser::ConvertLuaEvent(QuestEventID evt) { case EVENT_NPC_SLAY: return EVENT_SLAY; break; + case EVENT_SPELL_EFFECT_BOT: case EVENT_SPELL_EFFECT_CLIENT: case EVENT_SPELL_EFFECT_NPC: return EVENT_SPELL_EFFECT_CLIENT; break; + case EVENT_SPELL_EFFECT_BUFF_TIC_BOT: case EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT: case EVENT_SPELL_EFFECT_BUFF_TIC_NPC: return EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT; @@ -1414,13 +1479,200 @@ uint32 LuaParser::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault return retval; } -uint32 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault) +uint64 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault) { - uint32 retval = 0; + uint64 retval = 0; for (auto &mod : mods_) { mod.GetExperienceForKill(self, against, retval, ignoreDefault); } return retval; } -#endif +int64 LuaParser::CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, bool &ignoreDefault) +{ + int64 retval = 0; + for (auto &mod : mods_) { + mod.CalcSpellEffectValue_formula(self, formula, base_value, max_value, caster_level, spell_id, ticsremaining, retval, ignoreDefault); + } + return retval; +} + +int LuaParser::EventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return 0; + } + + if (!bot) { + return 0; + } + + if (!BotHasQuestSub(evt)) { + return 0; + } + + return _EventBot("bot", evt, bot, init, data, extra_data, extra_pointers); +} + +int LuaParser::EventGlobalBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return 0; + } + + if (!bot) { + return 0; + } + + if (!GlobalBotHasQuestSub(evt)) { + return 0; + } + + return _EventBot("global_bot", evt, bot, init, data, extra_data, extra_pointers); +} + +int LuaParser::_EventBot( + std::string package_name, + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers, + luabind::adl::object *l_func +) { + const char *sub_name = LuaEvents[evt]; + int start = lua_gettop(L); + + try { + int npop = 1; + if(l_func != nullptr) { + l_func->push(L); + } else { + lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str()); + lua_getfield(L, -1, sub_name); + npop = 2; + } + + lua_createtable(L, 0, 0); + //push self + Lua_Bot l_bot(bot); + luabind::adl::object l_bot_o = luabind::adl::object(L, l_bot); + l_bot_o.push(L); + lua_setfield(L, -2, "self"); + + auto arg_function = BotArgumentDispatch[evt]; + arg_function(this, L, bot, init, data, extra_data, extra_pointers); + auto* c = (init && init->IsClient()) ? init->CastToClient() : nullptr; + + quest_manager.StartQuest(bot, c); + if(lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + AddError(error); + quest_manager.EndQuest(); + lua_pop(L, npop); + return 0; + } + quest_manager.EndQuest(); + + if(lua_isnumber(L, -1)) { + int ret = static_cast(lua_tointeger(L, -1)); + lua_pop(L, npop); + return ret; + } + + lua_pop(L, npop); + } catch(std::exception &ex) { + std::string error = "Lua Exception: "; + error += std::string(ex.what()); + AddError(error); + + //Restore our stack to the best of our ability + int end = lua_gettop(L); + int n = end - start; + if(n > 0) { + lua_pop(L, n); + } + } + + return 0; +} + +int LuaParser::DispatchEventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return 0; + } + + std::string package_name = "bot"; + + auto iter = lua_encounter_events_registered.find(package_name); + if (iter == lua_encounter_events_registered.end()) { + return 0; + } + + int ret = 0; + auto riter = iter->second.begin(); + while (riter != iter->second.end()) { + if (riter->event_id == evt) { + package_name = fmt::format("encounter_{}", riter->encounter_name); + int i = _EventBot(package_name, evt, bot, init, data, extra_data, extra_pointers, &riter->lua_reference); + if (i != 0) { + ret = i; + } + } + + ++riter; + } + + return ret; +} + +bool LuaParser::BotHasQuestSub(QuestEventID evt) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return false; + } + + const char *subname = LuaEvents[evt]; + return HasFunction(subname, "bot"); +} + +bool LuaParser::GlobalBotHasQuestSub(QuestEventID evt) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return false; + } + + const char *subname = LuaEvents[evt]; + return HasFunction(subname, "global_bot"); +} + +void LuaParser::LoadBotScript(std::string filename) { + LoadScript(filename, "bot"); +} + +void LuaParser::LoadGlobalBotScript(std::string filename) { + LoadScript(filename, "global_bot"); +} diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 831f22061..646c9f803 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -36,20 +36,77 @@ class LuaParser : public QuestInterface { public: ~LuaParser(); - virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, - std::vector *extra_pointers); + virtual int EventNPC( + QuestEventID evt, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventGlobalNPC( + QuestEventID evt, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventPlayer( + QuestEventID evt, + Client *client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventGlobalPlayer( + QuestEventID evt, + Client *client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventItem( + QuestEventID evt, + Client *client, + EQ::ItemInstance *item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventSpell( + QuestEventID evt, + Mob* mob, + Client *client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventEncounter( + QuestEventID evt, + std::string encounter_name, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int EventGlobalBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); virtual bool HasQuestSub(uint32 npc_id, QuestEventID evt); virtual bool HasGlobalQuestSub(QuestEventID evt); @@ -58,6 +115,9 @@ public: virtual bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt); virtual bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt); virtual bool EncounterHasQuestSub(std::string encounter_name, QuestEventID evt); + virtual bool HasEncounterSub(const std::string& package_name, QuestEventID evt); + virtual bool BotHasQuestSub(QuestEventID evt); + virtual bool GlobalBotHasQuestSub(QuestEventID evt); virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadGlobalNPCScript(std::string filename); @@ -66,6 +126,8 @@ public: virtual void LoadItemScript(std::string filename, EQ::ItemInstance *item); virtual void LoadSpellScript(std::string filename, uint32 spell_id); virtual void LoadEncounterScript(std::string filename, std::string encounter_name); + virtual void LoadBotScript(std::string filename); + virtual void LoadGlobalBotScript(std::string filename); virtual void AddVar(std::string name, std::string val); virtual std::string GetVar(std::string name); @@ -74,14 +136,47 @@ public: virtual void RemoveEncounter(const std::string &name); virtual uint32 GetIdentifier() { return 0xb0712acc; } - virtual int DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int DispatchEventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); - virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers); + virtual int DispatchEventNPC( + QuestEventID evt, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int DispatchEventPlayer( + QuestEventID evt, + Client *client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int DispatchEventItem( + QuestEventID evt, + Client *client, + EQ::ItemInstance *item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int DispatchEventSpell( + QuestEventID evt, + Mob* mob, + Client *client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + virtual int DispatchEventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); static LuaParser* Instance() { static LuaParser inst; @@ -99,23 +194,73 @@ public: void CommonOutgoingHitSuccess(Mob *self, Mob* other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault); uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault); - uint32 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault); + uint64 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault); + int64 CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, bool &ignoreDefault); private: LuaParser(); LuaParser(const LuaParser&); LuaParser& operator=(const LuaParser&); - int _EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); - int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); - int _EventItem(std::string package_name, QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, - uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); - int _EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); - int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, - std::vector *extra_pointers); + int _EventNPC( + std::string package_name, + QuestEventID evt, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers, + luabind::adl::object *l_func = nullptr + ); + int _EventPlayer( + std::string package_name, + QuestEventID evt, + Client *client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers, + luabind::adl::object *l_func = nullptr + ); + int _EventItem( + std::string package_name, + QuestEventID evt, + Client *client, + EQ::ItemInstance *item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers, + luabind::adl::object *l_func = nullptr + ); + int _EventSpell( + std::string package_name, + QuestEventID evt, + Mob* mob, + Client *client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers, + luabind::adl::object *l_func = nullptr + ); + int _EventEncounter( + std::string package_name, + QuestEventID evt, + std::string encounter_name, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + int _EventBot( + std::string package_name, + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers, + luabind::adl::object *l_func = nullptr + ); void LoadScript(std::string filename, std::string package_name); void MapFunctions(lua_State *L); @@ -131,7 +276,7 @@ private: ItemArgumentHandler ItemArgumentDispatch[_LargestEventID]; SpellArgumentHandler SpellArgumentDispatch[_LargestEventID]; EncounterArgumentHandler EncounterArgumentDispatch[_LargestEventID]; - + BotArgumentHandler BotArgumentDispatch[_LargestEventID]; }; #endif diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index a286586fd..f12f11159 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -27,8 +27,15 @@ #include "lua_parser_events.h" //NPC -void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_event_say( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { npc->DoQuestPause(init); Lua_Client l_client(reinterpret_cast(init)); @@ -43,22 +50,28 @@ void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in lua_setfield(L, -2, "language"); } -void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_event_trade( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Client l_client(reinterpret_cast(init)); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); - + lua_createtable(L, 0, 0); - std::stringstream ident; - ident << npc->GetNPCTypeID(); - - if(extra_pointers) { + const auto npc_id = npc->GetNPCTypeID(); + + if (extra_pointers) { size_t sz = extra_pointers->size(); - for(size_t i = 0; i < sz; ++i) { - std::string prefix = "item" + std::to_string(i + 1); - EQ::ItemInstance *inst = EQ::any_cast(extra_pointers->at(i)); + for (size_t i = 0; i < sz; ++i) { + auto prefix = fmt::format("item{}", i + 1); + auto* inst = std::any_cast(extra_pointers->at(i)); Lua_ItemInst l_inst = inst; luabind::adl::object l_inst_o = luabind::adl::object(L, l_inst); @@ -68,22 +81,42 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob * } } - lua_pushinteger(L, std::stoul(parse->GetVar("platinum." + ident.str()))); + auto money_string = fmt::format("platinum.{}", npc_id); + uint32 money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); lua_setfield(L, -2, "platinum"); - lua_pushinteger(L, std::stoul(parse->GetVar("gold." + ident.str()))); + money_string = fmt::format("gold.{}", npc_id); + money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); lua_setfield(L, -2, "gold"); - lua_pushinteger(L, std::stoul(parse->GetVar("silver." + ident.str()))); + money_string = fmt::format("silver.{}", npc_id); + money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); lua_setfield(L, -2, "silver"); - lua_pushinteger(L, std::stoul(parse->GetVar("copper." + ident.str()))); + money_string = fmt::format("copper.{}", npc_id); + money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); lua_setfield(L, -2, "copper"); + lua_setfield(L, -2, "trade"); } -void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_event_hp( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { if(extra_data == 1) { lua_pushinteger(L, -1); lua_setfield(L, -2, "hp_event"); @@ -99,32 +132,60 @@ void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini } } -void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_single_mob( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Mob l_mob(init); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); } -void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_single_client( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Client l_client(reinterpret_cast(init)); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); } -void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_single_npc( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_NPC l_npc(reinterpret_cast(init)); luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); lua_setfield(L, -2, "other"); } -void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_task_accepted( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Client l_client(reinterpret_cast(init)); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); @@ -134,8 +195,15 @@ void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob lua_setfield(L, -2, "task_id"); } -void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_popup( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Mob l_mob(init); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); @@ -145,8 +213,15 @@ void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, lua_setfield(L, -2, "popup_id"); } -void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_waypoint( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Mob l_mob(init); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); @@ -156,8 +231,15 @@ void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini lua_setfield(L, -2, "wp"); } -void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_hate( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Mob l_mob(init); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); @@ -168,20 +250,59 @@ void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s } -void handle_npc_signal(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_signal( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "signal"); } -void handle_npc_timer(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_payload( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "payload_id"); + + lua_pushstring(L, sep.argplus[1]); + lua_setfield(L, -2, "payload_value"); +} + +void handle_npc_timer( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushstring(L, data.c_str()); lua_setfield(L, -2, "timer"); } -void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_npc_death( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Mob l_mob(init); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); @@ -189,104 +310,7 @@ void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, Seperator sep(data.c_str()); lua_pushinteger(L, std::stoi(sep.arg[0])); - lua_setfield(L, -2, "damage"); - - int spell_id = std::stoi(sep.arg[1]); - if(IsValidSpell(spell_id)) { - Lua_Spell l_spell(&spells[spell_id]); - luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); - l_spell_o.push(L); - lua_setfield(L, -2, "spell"); - } else { - Lua_Spell l_spell(nullptr); - luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); - l_spell_o.push(L); - lua_setfield(L, -2, "spell"); - } - - lua_pushinteger(L, std::stoi(sep.arg[2])); - lua_setfield(L, -2, "skill_id"); -} - -void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - int spell_id = std::stoi(data); - if(IsValidSpell(spell_id)) { - Lua_Spell l_spell(&spells[spell_id]); - luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); - l_spell_o.push(L); - lua_setfield(L, -2, "spell"); - } else { - Lua_Spell l_spell(nullptr); - luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); - l_spell_o.push(L); - lua_setfield(L, -2, "spell"); - } -} - -void handle_npc_area(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - lua_pushinteger(L, *EQ::any_cast(extra_pointers->at(0))); - lua_setfield(L, -2, "area_id"); - - lua_pushinteger(L, *EQ::any_cast(extra_pointers->at(1))); - lua_setfield(L, -2, "area_type"); -} - -void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { -} - -void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_Client l_client(reinterpret_cast(init)); - luabind::adl::object l_client_o = luabind::adl::object(L, l_client); - l_client_o.push(L); - lua_setfield(L, -2, "other"); - - Lua_ItemInst l_item(EQ::any_cast(extra_pointers->at(0))); - luabind::adl::object l_item_o = luabind::adl::object(L, l_item); - l_item_o.push(L); - lua_setfield(L, -2, "item"); - - Lua_Corpse l_corpse(EQ::any_cast(extra_pointers->at(1))); - luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); - l_corpse_o.push(L); - lua_setfield(L, -2, "corpse"); -} - -//Player -void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - lua_pushstring(L, data.c_str()); - lua_setfield(L, -2, "message"); - - lua_pushinteger(L, extra_data); - lua_setfield(L, -2, "language"); -} - -void handle_player_environmental_damage(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers){ - Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); - lua_setfield(L, -2, "env_damage"); - - lua_pushinteger(L, std::stoi(sep.arg[1])); - lua_setfield(L, -2, "env_damage_type"); - - lua_pushinteger(L, std::stoi(sep.arg[2])); - lua_setfield(L, -2, "env_final_damage"); -} - -void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Seperator sep(data.c_str()); - - Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0])); - Lua_Mob l_mob(o); - luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); - l_mob_o.push(L); - lua_setfield(L, -2, "other"); + lua_setfield(L, -2, "killer_id"); lua_pushinteger(L, std::stoi(sep.arg[1])); lua_setfield(L, -2, "damage"); @@ -305,17 +329,224 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st } lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_setfield(L, -2, "skill_id"); + + if (extra_pointers && extra_pointers->size() >= 1) + { + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); + l_corpse_o.push(L); + lua_setfield(L, -2, "corpse"); + } + + if (extra_pointers && extra_pointers->size() >= 2) + { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "killed"); + } +} + +void handle_npc_cast( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + int spell_id = std::stoi(data); + if(IsValidSpell(spell_id)) { + Lua_Spell l_spell(&spells[spell_id]); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } else { + Lua_Spell l_spell(nullptr); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } +} + +void handle_npc_area( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, *std::any_cast(extra_pointers->at(0))); + lua_setfield(L, -2, "area_id"); + + lua_pushinteger(L, *std::any_cast(extra_pointers->at(1))); + lua_setfield(L, -2, "area_type"); +} + +void handle_npc_null( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { +} + +void handle_npc_loot_zone( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(reinterpret_cast(init)); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); + + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); + l_corpse_o.push(L); + lua_setfield(L, -2, "corpse"); +} + +void handle_npc_spawn_zone( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_NPC l_npc(std::any_cast(init->CastToNPC())); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_npc_despawn_zone( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Mob l_mob(init); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); +} + +// Player +void handle_player_say( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "message"); + + lua_pushinteger(L, extra_data); + lua_setfield(L, -2, "language"); +} + +void handle_player_environmental_damage( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "env_damage"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "env_damage_type"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "env_final_damage"); +} + +void handle_player_death( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0])); + Lua_Mob l_mob(o); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "killer_id"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "damage"); + + int spell_id = std::stoi(sep.arg[3]); + if(IsValidSpell(spell_id)) { + Lua_Spell l_spell(&spells[spell_id]); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } else { + Lua_Spell l_spell(nullptr); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } + + lua_pushinteger(L, std::stoi(sep.arg[4])); lua_setfield(L, -2, "skill"); } -void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_timer( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushstring(L, data.c_str()); lua_setfield(L, -2, "timer"); } -void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_discover_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { const EQ::ItemData *item = database.GetItem(extra_data); if(item) { Lua_Item l_item(item); @@ -330,52 +561,111 @@ void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* cl } } -void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_ItemInst l_item(EQ::any_cast(extra_pointers->at(0))); +void handle_player_fish_forage_success( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); } -void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_Object l_object(EQ::any_cast(extra_pointers->at(0))); +void handle_player_click_object( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Object l_object(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_object_o = luabind::adl::object(L, l_object); l_object_o.push(L); lua_setfield(L, -2, "object"); } -void handle_player_click_door(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_Door l_door(EQ::any_cast(extra_pointers->at(0))); +void handle_player_click_door( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Door l_door(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_door_o = luabind::adl::object(L, l_door); l_door_o.push(L); lua_setfield(L, -2, "door"); } -void handle_player_signal(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_signal( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "signal"); } -void handle_player_popup_response(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_payload( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "payload_id"); + + lua_pushstring(L, sep.argplus[1]); + lua_setfield(L, -2, "payload_value"); +} + +void handle_player_popup_response( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "popup_id"); } -void handle_player_pick_up(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_ItemInst l_item(EQ::any_cast(extra_pointers->at(0))); +void handle_player_pick_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); } -void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_cast( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); int spell_id = std::stoi(sep.arg[0]); @@ -390,62 +680,110 @@ void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std } lua_setfield(L, -2, "spell"); - + lua_pushinteger(L, std::stoi(sep.arg[1])); lua_setfield(L, -2, "caster_id"); - + lua_pushinteger(L, std::stoi(sep.arg[2])); lua_setfield(L, -2, "caster_level"); } -void handle_player_task_fail(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_task_fail( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "task_id"); } -void handle_player_zone(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_zone( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushinteger(L, std::stoi(sep.arg[0])); lua_setfield(L, -2, "from_zone_id"); lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "from_instance_id"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "from_instance_version"); + + lua_pushinteger(L, std::stoi(sep.arg[3])); lua_setfield(L, -2, "zone_id"); + + lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_setfield(L, -2, "instance_id"); + + lua_pushinteger(L, std::stoi(sep.arg[5])); + lua_setfield(L, -2, "instance_version"); } -void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_Client l_client(EQ::any_cast(extra_pointers->at(1))); +void handle_player_duel_win( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(std::any_cast(extra_pointers->at(1))); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); } -void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_Client l_client(EQ::any_cast(extra_pointers->at(0))); +void handle_player_duel_loss( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); } -void handle_player_loot(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_ItemInst l_item(EQ::any_cast(extra_pointers->at(0))); +void handle_player_loot( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); - Lua_Corpse l_corpse(EQ::any_cast(extra_pointers->at(1))); + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(1))); luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); l_corpse_o.push(L); lua_setfield(L, -2, "corpse"); } -void handle_player_task_stage_complete(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_task_stage_complete( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushinteger(L, std::stoi(sep.arg[0])); lua_setfield(L, -2, "task_id"); @@ -454,8 +792,14 @@ void handle_player_task_stage_complete(QuestInterface *parse, lua_State* L, Clie lua_setfield(L, -2, "activity_id"); } -void handle_player_task_update(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_task_update( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushinteger(L, std::stoi(sep.arg[0])); lua_setfield(L, -2, "count"); @@ -467,8 +811,14 @@ void handle_player_task_update(QuestInterface *parse, lua_State* L, Client* clie lua_setfield(L, -2, "task_id"); } -void handle_player_command(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str(), ' ', 10, 100, true); std::string command(sep.arg[0] + 1); lua_pushstring(L, command.c_str()); @@ -486,34 +836,58 @@ void handle_player_command(QuestInterface *parse, lua_State* L, Client* client, lua_setfield(L, -2, "args"); } -void handle_player_combine(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_combine( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, extra_data); lua_setfield(L, -2, "recipe_id"); lua_pushstring(L, data.c_str()); - lua_setfield(L, -2, "recipe_name"); + lua_setfield(L, -2, "recipe_name"); } -void handle_player_feign(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_NPC l_npc(EQ::any_cast(extra_pointers->at(0))); +void handle_player_feign( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); lua_setfield(L, -2, "other"); } -void handle_player_area(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - lua_pushinteger(L, *EQ::any_cast(extra_pointers->at(0))); +void handle_player_area( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, *std::any_cast(extra_pointers->at(0))); lua_setfield(L, -2, "area_id"); - lua_pushinteger(L, *EQ::any_cast(extra_pointers->at(1))); + lua_pushinteger(L, *std::any_cast(extra_pointers->at(1))); lua_setfield(L, -2, "area_type"); } -void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_respawn( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "option"); @@ -521,9 +895,15 @@ void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client, lua_setfield(L, -2, "resurrect"); } -void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_Packet l_packet(EQ::any_cast(extra_pointers->at(0))); +void handle_player_packet( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Packet l_packet(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_packet_o = luabind::adl::object(L, l_packet); l_packet_o.push(L); lua_setfield(L, -2, "packet"); @@ -532,11 +912,24 @@ void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, s lua_setfield(L, -2, "connecting"); } -void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_null( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { } -void handle_player_use_skill(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { +void handle_player_use_skill( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushinteger(L, std::stoi(sep.arg[0])); lua_setfield(L, -2, "skill_id"); @@ -545,11 +938,24 @@ void handle_player_use_skill(QuestInterface *parse, lua_State* L, Client* client lua_setfield(L, -2, "skill_level"); } -void handle_test_buff(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector* extra_pointers) { +void handle_test_buff( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { } -void handle_player_combine_validate(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers) { +void handle_player_combine_validate( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushinteger(L, extra_data); lua_setfield(L, -2, "recipe_id"); @@ -573,8 +979,14 @@ void handle_player_combine_validate(QuestInterface* parse, lua_State* L, Client* lua_setfield(L, -2, "tradeskill_id"); } -void handle_player_bot_command(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers) { +void handle_player_bot_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str(), ' ', 10, 100, true); std::string bot_command(sep.arg[0] + 1); lua_pushstring(L, bot_command.c_str()); @@ -592,7 +1004,14 @@ void handle_player_bot_command(QuestInterface* parse, lua_State* L, Client* clie lua_setfield(L, -2, "args"); } -void handle_player_warp(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector* extra_pointers) { +void handle_player_warp( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushnumber(L, std::stof(sep.arg[0])); lua_setfield(L, -2, "from_x"); @@ -604,37 +1023,190 @@ void handle_player_warp(QuestInterface* parse, lua_State* L, Client* client, std lua_setfield(L, -2, "from_z"); } -void handle_player_quest_combine(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector* extra_pointers) { +void handle_player_quest_combine( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "container_slot"); } - -void handle_player_consider(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector* extra_pointers) { + +void handle_player_consider( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "entity_id"); } -void handle_player_consider_corpse(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector* extra_pointers) { +void handle_player_consider_corpse( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, std::stoi(data)); lua_setfield(L, -2, "corpse_entity_id"); } -//Item -void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_player_inspect( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Mob l_mob(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_player_aa_buy( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "aa_cost"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "aa_id"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "aa_previous_id"); + + lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_setfield(L, -2, "aa_next_id"); +} + +void handle_player_aa_gain( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, std::stoi(data)); + lua_setfield(L, -2, "aa_gained"); +} + +void handle_player_level_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, std::stoul(data)); + lua_setfield(L, -2, "levels_gained"); +} + +void handle_player_level_down( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, std::stoul(data)); + lua_setfield(L, -2, "levels_lost"); +} + +void handle_player_gm_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "message"); +} + +void handle_player_bot_create( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + lua_pushstring(L, sep.arg[0]); + lua_setfield(L, -2, "bot_name"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "bot_id"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "bot_race"); + + lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_setfield(L, -2, "bot_class"); + + lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_setfield(L, -2, "bot_gender"); +} + +// Item +void handle_item_click( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, extra_data); lua_setfield(L, -2, "slot_id"); } -void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_item_timer( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushstring(L, data.c_str()); lua_setfield(L, -2, "timer"); } -void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - +void handle_item_proc( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Lua_Mob l_mob(mob); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); @@ -653,8 +1225,16 @@ void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, EQ::I } } -void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_item_loot( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { if(mob && mob->IsCorpse()) { Lua_Corpse l_corpse(mob->CastToCorpse()); luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); @@ -668,15 +1248,31 @@ void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, EQ::I } } -void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_item_equip( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushinteger(L, extra_data); lua_setfield(L, -2, "slot_id"); } -void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_ItemInst l_item(EQ::any_cast(extra_pointers->at(0))); +void handle_item_augment( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "aug"); @@ -685,9 +1281,17 @@ void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, EQ lua_setfield(L, -2, "slot_id"); } -void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_ItemInst l_item(EQ::any_cast(extra_pointers->at(0))); +void handle_item_augment_insert( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -696,9 +1300,17 @@ void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* cli lua_setfield(L, -2, "slot_id"); } -void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - Lua_ItemInst l_item(EQ::any_cast(extra_pointers->at(0))); +void handle_item_augment_remove( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -706,20 +1318,37 @@ void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* cli lua_pushinteger(L, extra_data); lua_setfield(L, -2, "slot_id"); - lua_pushboolean(L, *EQ::any_cast(extra_pointers->at(1))); + lua_pushboolean(L, *std::any_cast(extra_pointers->at(1))); lua_setfield(L, -2, "destroyed"); } -void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_item_null( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { } -//Spell -void handle_spell_event(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, std::string data, uint32 extra_data, std::vector *extra_pointers) { - if(npc) { - Lua_Mob l_npc(npc); - luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); - l_npc_o.push(L); +// Spell +void handle_spell_event( + QuestInterface *parse, + lua_State* L, + Mob* mob, + Client* client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + if (mob) { + Lua_Mob l_mob(mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); } else if(client) { Lua_Mob l_client(client); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); @@ -748,18 +1377,27 @@ void handle_spell_event(QuestInterface *parse, lua_State* L, NPC* npc, Client* c lua_pushinteger(L, std::stoi(sep.arg[3])); lua_setfield(L, -2, "buff_slot"); - + Lua_Spell l_spell(spell_id); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } -void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, std::string data, uint32 extra_data, std::vector *extra_pointers) { - if(npc) { - Lua_Mob l_npc(npc); - luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); - l_npc_o.push(L); +void handle_translocate_finish( + QuestInterface *parse, + lua_State* L, + Mob* mob, + Client* client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + if (mob) { + Lua_Mob l_mob(mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); } else if(client) { Lua_Mob l_client(client); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); @@ -773,7 +1411,14 @@ void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Cl lua_setfield(L, -2, "target"); } -void handle_player_equip_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { +void handle_player_equip_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushnumber(L, extra_data); lua_setfield(L, -2, "item_id"); @@ -784,23 +1429,45 @@ void handle_player_equip_item(QuestInterface *parse, lua_State* L, Client* clien lua_pushnumber(L, std::stoi(sep.arg[1])); lua_setfield(L, -2, "slot_id"); - + Lua_ItemInst l_item(extra_data); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); } -void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, std::string data, uint32 extra_data, std::vector *extra_pointers) { } +void handle_spell_null( + QuestInterface *parse, + lua_State* L, + Mob* mob, + Client* client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { +} -void handle_encounter_timer(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_encounter_timer( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { lua_pushstring(L, data.c_str()); lua_setfield(L, -2, "timer"); } -void handle_encounter_load(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_encounter_load( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { if (encounter) { Lua_Encounter l_enc(encounter); luabind::adl::object l_enc_o = luabind::adl::object(L, l_enc); @@ -808,27 +1475,45 @@ void handle_encounter_load(QuestInterface *parse, lua_State* L, Encounter* encou lua_setfield(L, -2, "encounter"); } if (extra_pointers) { - std::string *str = EQ::any_cast(extra_pointers->at(0)); + std::string *str = std::any_cast(extra_pointers->at(0)); lua_pushstring(L, str->c_str()); lua_setfield(L, -2, "data"); } } -void handle_encounter_unload(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +void handle_encounter_unload( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { if (extra_pointers) { - std::string *str = EQ::any_cast(extra_pointers->at(0)); + std::string *str = std::any_cast(extra_pointers->at(0)); lua_pushstring(L, str->c_str()); lua_setfield(L, -2, "data"); } } -void handle_encounter_null(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - +void handle_encounter_null( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { } -void handle_player_skill_up(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector* extra_pointers) { +void handle_player_skill_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushinteger(L, std::stoi(sep.arg[0])); lua_setfield(L, -2, "skill_id"); @@ -843,7 +1528,14 @@ void handle_player_skill_up(QuestInterface* parse, lua_State* L, Client* client, lua_setfield(L, -2, "is_tradeskill"); } -void handle_player_language_skill_up(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector* extra_pointers) { +void handle_player_language_skill_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { Seperator sep(data.c_str()); lua_pushinteger(L, std::stoi(sep.arg[0])); lua_setfield(L, -2, "skill_id"); @@ -855,4 +1547,408 @@ void handle_player_language_skill_up(QuestInterface* parse, lua_State* L, Client lua_setfield(L, -2, "skill_max"); } +void handle_player_alt_currency_merchant( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "currency_id"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "npc_id"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "merchant_id"); + + lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_setfield(L, -2, "item_id"); + + lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_setfield(L, -2, "item_cost"); +} + +void handle_player_merchant( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "npc_id"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "merchant_id"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "item_id"); + + lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_setfield(L, -2, "item_quantity"); + + lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_setfield(L, -2, "item_cost"); +} + +void handle_player_augment_insert( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + + Lua_ItemInst l_augment(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_augment_o = luabind::adl::object(L, l_augment); + l_augment_o.push(L); + lua_setfield(L, -2, "augment"); + + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoul(sep.arg[0])); + lua_setfield(L, -2, "item_id"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "item_slot"); + + lua_pushinteger(L, std::stoul(sep.arg[2])); + lua_setfield(L, -2, "augment_id"); + + lua_pushinteger(L, std::stoul(sep.arg[3])); + lua_setfield(L, -2, "augment_slot"); +} + +void handle_player_augment_remove( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + + Lua_ItemInst l_augment(std::any_cast(extra_pointers->at(2))); + luabind::adl::object l_augment_o = luabind::adl::object(L, l_augment); + l_augment_o.push(L); + lua_setfield(L, -2, "augment"); + + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoul(sep.arg[0])); + lua_setfield(L, -2, "item_id"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "item_slot"); + + lua_pushinteger(L, std::stoul(sep.arg[2])); + lua_setfield(L, -2, "augment_id"); + + lua_pushinteger(L, std::stoul(sep.arg[3])); + lua_setfield(L, -2, "augment_slot"); + + lua_pushboolean(L, Strings::ToBool(sep.arg[4])); + lua_setfield(L, -2, "destroyed"); +} + +// Bot + +void handle_bot_null( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { +} + +void handle_bot_cast( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + int spell_id = std::stoi(sep.arg[0]); + if (IsValidSpell(spell_id)) { + Lua_Spell l_spell(&spells[spell_id]); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + } else { + Lua_Spell l_spell(nullptr); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + } + + lua_setfield(L, -2, "spell"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "caster_id"); + + lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_setfield(L, -2, "caster_level"); +} + +void handle_bot_combat( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Mob l_mob(init); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + + lua_pushboolean(L, std::stoi(data) == 0 ? false : true); + lua_setfield(L, -2, "joined"); +} + +void handle_bot_death( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0])); + Lua_Mob l_mob(o); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "damage"); + + int spell_id = std::stoi(sep.arg[2]); + if (IsValidSpell(spell_id)) { + Lua_Spell l_spell(&spells[spell_id]); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } else { + Lua_Spell l_spell(nullptr); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } + + lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_setfield(L, -2, "skill"); +} + +void handle_bot_popup_response( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Mob l_mob(init); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + + lua_pushinteger(L, std::stoi(data)); + lua_setfield(L, -2, "popup_id"); +} + +void handle_bot_say( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(reinterpret_cast(init)); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); + + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "message"); + + lua_pushinteger(L, extra_data); + lua_setfield(L, -2, "language"); +} + +void handle_bot_signal( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, std::stoi(data)); + lua_setfield(L, -2, "signal"); +} + +void handle_bot_payload( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "payload_id"); + + lua_pushstring(L, sep.argplus[1]); + lua_setfield(L, -2, "payload_value"); +} + +void handle_bot_slay( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Mob l_mob(init); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_bot_target_change( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Mob l_mob(init); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_bot_timer( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "timer"); +} + +void handle_bot_trade( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(reinterpret_cast(init)); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); + + lua_createtable(L, 0, 0); + const auto bot_id = bot->GetBotID(); + + if (extra_pointers) { + size_t sz = extra_pointers->size(); + for (size_t i = 0; i < sz; ++i) { + auto prefix = fmt::format("item{}", i + 1); + auto* inst = std::any_cast(extra_pointers->at(i)); + + Lua_ItemInst l_inst = inst; + luabind::adl::object l_inst_o = luabind::adl::object(L, l_inst); + l_inst_o.push(L); + + lua_setfield(L, -2, prefix.c_str()); + } + } + + auto money_string = fmt::format("platinum.{}", bot_id); + uint32 money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); + lua_setfield(L, -2, "platinum"); + + money_string = fmt::format("gold.{}", bot_id); + money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); + lua_setfield(L, -2, "gold"); + + money_string = fmt::format("silver.{}", bot_id); + money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); + lua_setfield(L, -2, "silver"); + + money_string = fmt::format("copper.{}", bot_id); + money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + + lua_pushinteger(L, money_value); + lua_setfield(L, -2, "copper"); + + lua_setfield(L, -2, "trade"); +} + +void handle_bot_use_skill( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "skill_id"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "skill_level"); +} + #endif diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 2b6848def..b32683c7a 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -2,162 +2,958 @@ #define _EQE_LUA_PARSER_EVENTS_H #ifdef LUA_EQEMU -typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::string, uint32, std::vector*); -typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector*); -typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, EQ::ItemInstance*, Mob*, std::string, uint32, std::vector*); -typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, std::string, uint32, std::vector*); -typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector*); +typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::string, uint32, std::vector*); +typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector*); +typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, EQ::ItemInstance*, Mob*, std::string, uint32, std::vector*); +typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, Mob*, Client*, uint32, std::string, uint32, std::vector*); +typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector*); +typedef void(*BotArgumentHandler)(QuestInterface*, lua_State*, Bot*, Mob*, std::string, uint32, std::vector*); -//NPC -void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_signal(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_timer(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_area(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); +// NPC +void handle_npc_event_say( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); -//Player -void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_environmental_damage(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_click_door(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_signal(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_popup_response(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_pick_up(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_task_fail(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_zone(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_loot(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_task_stage_complete(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_task_update(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_command(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_combine(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_feign(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_area(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_use_skill(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_test_buff(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_combine_validate(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_bot_command(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_player_warp(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_quest_combine(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_consider(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_consider_corpse(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_equip_item(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_skill_up(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); -void handle_player_language_skill_up(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, - std::vector* extra_pointers); +void handle_npc_event_trade( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); -//Item -void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, EQ::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); +void handle_npc_event_hp( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); -//Spell -void handle_spell_event(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers); +void handle_npc_single_mob( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_single_client( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_single_npc( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_task_accepted( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_popup( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_waypoint( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_hate( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_signal( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_timer( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_death( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_cast( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_area( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_null( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_loot_zone( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_spawn_zone( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_payload( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_npc_despawn_zone( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +// Player +void handle_player_say( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_environmental_damage( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_death( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_timer( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_discover_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_fish_forage_success( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_click_object( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_click_door( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_signal( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_popup_response( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_pick_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_cast( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_task_fail( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_zone( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_duel_win( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_duel_loss( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_loot( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_task_stage_complete( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_task_update( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_combine( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_feign( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_area( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_respawn( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_packet( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_null( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_use_skill( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_test_buff( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_combine_validate( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_bot_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_warp( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_quest_combine( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_consider( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_consider_corpse( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_equip_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_skill_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_language_skill_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_alt_currency_merchant( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_merchant( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_inspect( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_aa_buy( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_aa_gain( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_payload( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_level_up( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_level_down( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_gm_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_bot_create( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_augment_insert( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_augment_remove( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); -//Encounter -void handle_encounter_timer(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_encounter_load(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_encounter_unload(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers); -void handle_encounter_null(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, - std::vector *extra_pointers); +// Item +void handle_item_click( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_timer( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_proc( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_loot( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_equip( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_augment( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_augment_insert( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_augment_remove( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_item_null( + QuestInterface *parse, + lua_State* L, + Client* client, + EQ::ItemInstance* item, + Mob *mob, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +// Spell +void handle_spell_event( + QuestInterface *parse, + lua_State* L, + Mob* mob, + Client* client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_translocate_finish( + QuestInterface *parse, + lua_State* L, + Mob* mob, + Client* client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_spell_null( + QuestInterface *parse, + lua_State* L, + Mob* mob, + Client* client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +// Encounter +void handle_encounter_timer( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_encounter_load( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_encounter_unload( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_encounter_null( + QuestInterface *parse, + lua_State* L, + Encounter* encounter, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +// Bot +void handle_bot_null( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_cast( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_combat( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_death( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_popup_response( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_say( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_signal( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_slay( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_target_change( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_timer( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_trade( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_use_skill( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_payload( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); #endif #endif diff --git a/zone/lua_raid.cpp b/zone/lua_raid.cpp index 4bc99a7cd..716d7ce12 100644 --- a/zone/lua_raid.cpp +++ b/zone/lua_raid.cpp @@ -1,5 +1,7 @@ #ifdef LUA_EQEMU +#include "../common/data_verification.h" + #include "lua.hpp" #include #include @@ -16,6 +18,11 @@ bool Lua_Raid::IsRaidMember(const char *name) { return self->IsRaidMember(name); } +bool Lua_Raid::IsRaidMember(Lua_Client c) { + Lua_Safe_Call_Bool(); + return self->IsRaidMember(c); +} + void Lua_Raid::CastGroupSpell(Lua_Mob caster, int spell_id, uint32 group_id) { Lua_Safe_Call_Void(); self->CastGroupSpell(caster, spell_id, group_id); @@ -41,7 +48,7 @@ int Lua_Raid::GetGroup(Lua_Client c) { return self->GetGroup(c); } -void Lua_Raid::SplitExp(uint32 exp, Lua_Mob other) { +void Lua_Raid::SplitExp(uint64 exp, Lua_Mob other) { Lua_Safe_Call_Void(); self->SplitExp(exp, other); } @@ -76,11 +83,26 @@ bool Lua_Raid::IsLeader(Lua_Client c) { return self->IsLeader(c); } +Lua_Client Lua_Raid::GetLeader() { + Lua_Safe_Call_Class(Lua_Client); + return self->GetLeader(); +} + +std::string Lua_Raid::GetLeaderName() { + Lua_Safe_Call_String(); + return self->GetLeaderName(); +} + bool Lua_Raid::IsGroupLeader(const char *name) { Lua_Safe_Call_Bool(); return self->IsGroupLeader(name); } +bool Lua_Raid::IsGroupLeader(Lua_Client c) { + Lua_Safe_Call_Bool(); + return self->IsGroupLeader(c); +} + int Lua_Raid::GetHighestLevel() { Lua_Safe_Call_Int(); return self->GetHighestLevel(); @@ -91,9 +113,9 @@ int Lua_Raid::GetLowestLevel() { return self->GetLowestLevel(); } -Lua_Client Lua_Raid::GetClientByIndex(int index) { +Lua_Client Lua_Raid::GetClientByIndex(int member_index) { Lua_Safe_Call_Class(Lua_Client); - return self->GetClientByIndex(index); + return self->GetClientByIndex(member_index); } void Lua_Raid::TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h, uint32 group_id) { @@ -111,24 +133,27 @@ int Lua_Raid::GetID() { return self->GetID(); } -Lua_Client Lua_Raid::GetMember(int index) { +Lua_Client Lua_Raid::GetMember(int member_index) { Lua_Safe_Call_Class(Lua_Client); - if(index >= 72 || index < 0) { + if (!EQ::ValueWithin(member_index, 0, 71)) { return Lua_Client(); } - return self->members[index].member; + return self->members[member_index].member; } -int Lua_Raid::GetGroupNumber(int index) { +int Lua_Raid::GetGroupNumber(int member_index) { Lua_Safe_Call_Int(); - if(index >= 72 || index < 0 || self->members[index].GroupNumber == RAID_GROUPLESS) { + if ( + !EQ::ValueWithin(member_index, 0, 71) || + self->members[member_index].GroupNumber == RAID_GROUPLESS + ) { return -1; } - return self->members[index].GroupNumber; + return self->members[member_index].GroupNumber; } bool Lua_Raid::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name) @@ -163,8 +188,13 @@ luabind::scope lua_register_raid() { .def("GetTotalRaidDamage", (uint32(Lua_Raid::*)(Lua_Mob))&Lua_Raid::GetTotalRaidDamage) .def("GroupCount", (int(Lua_Raid::*)(uint32))&Lua_Raid::GroupCount) .def("IsGroupLeader", (bool(Lua_Raid::*)(const char*))&Lua_Raid::IsGroupLeader) + .def("IsGroupLeader", (bool(Lua_Raid::*)(Lua_Client))&Lua_Raid::IsGroupLeader) .def("IsLeader", (bool(Lua_Raid::*)(const char*))&Lua_Raid::IsLeader) + .def("IsLeader", (bool(Lua_Raid::*)(Lua_Client))&Lua_Raid::IsLeader) + .def("GetLeader", (Lua_Client(Lua_Raid::*)(void))&Lua_Raid::GetLeader) + .def("GetLeaderName", (std::string(Lua_Raid::*)(void)) & Lua_Raid::GetLeaderName) .def("IsRaidMember", (bool(Lua_Raid::*)(const char*))&Lua_Raid::IsRaidMember) + .def("IsRaidMember", (bool(Lua_Raid::*)(Lua_Client))&Lua_Raid::IsRaidMember) .def("RaidCount", (int(Lua_Raid::*)(void))&Lua_Raid::RaidCount) .def("SplitExp", (void(Lua_Raid::*)(uint32,Lua_Mob))&Lua_Raid::SplitExp) .def("SplitMoney", (void(Lua_Raid::*)(uint32,uint32,uint32,uint32,uint32))&Lua_Raid::SplitMoney) diff --git a/zone/lua_raid.h b/zone/lua_raid.h index 9eb100f59..ca9718a59 100644 --- a/zone/lua_raid.h +++ b/zone/lua_raid.h @@ -27,27 +27,31 @@ public: } bool IsRaidMember(const char *name); + bool IsRaidMember(Lua_Client c); void CastGroupSpell(Lua_Mob caster, int spell_id, uint32 group_id); int GroupCount(uint32 group_id); int RaidCount(); int GetGroup(const char *c); int GetGroup(Lua_Client c); - void SplitExp(uint32 exp, Lua_Mob other); + void SplitExp(uint64 exp, Lua_Mob other); uint32 GetTotalRaidDamage(Lua_Mob other); void SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum); void SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Lua_Client splitter); void BalanceHP(int penalty, uint32 group_id); bool IsLeader(const char *c); bool IsLeader(Lua_Client c); + Lua_Client GetLeader(); + std::string GetLeaderName(); bool IsGroupLeader(const char *name); + bool IsGroupLeader(Lua_Client c); int GetHighestLevel(); int GetLowestLevel(); - Lua_Client GetClientByIndex(int index); + Lua_Client GetClientByIndex(int member_index); void TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h, uint32 group_id); void TeleportRaid(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h); int GetID(); - Lua_Client GetMember(int index); - int GetGroupNumber(int index); + Lua_Client GetMember(int member_index); + int GetGroupNumber(int member_index); bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name); bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count); }; diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp index 891f30ad3..92099a47e 100644 --- a/zone/lua_stat_bonuses.cpp +++ b/zone/lua_stat_bonuses.cpp @@ -380,7 +380,7 @@ uint32 Lua_StatBonuses::GetsongModCap() const { return self->songModCap; } -int8 Lua_StatBonuses::Gethatemod() const { +int32 Lua_StatBonuses::Gethatemod() const { Lua_Safe_Call_Int(); return self->hatemod; } diff --git a/zone/lua_stat_bonuses.h b/zone/lua_stat_bonuses.h index 09a38ede0..8f83f1c25 100644 --- a/zone/lua_stat_bonuses.h +++ b/zone/lua_stat_bonuses.h @@ -100,7 +100,7 @@ public: uint32 GetwindMod() const; uint32 GetstringedMod() const; uint32 GetsongModCap() const; - int8 Gethatemod() const; + int32 Gethatemod() const; int64 GetEnduranceReduction() const; int32 GetStrikeThrough() const; int32 GetMeleeMitigation() const; diff --git a/zone/main.cpp b/zone/main.cpp index f92ea9ea8..d8f8ed1af 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -31,11 +31,12 @@ #include "../common/patches/patches.h" #include "../common/rulesys.h" #include "../common/profanity_manager.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/crash.h" #include "../common/memory_mapped_file.h" #include "../common/spdat.h" #include "../common/eqemu_logsys.h" +#include "../common/misc.h" #include "api_service.h" #include "zone_config.h" @@ -44,11 +45,9 @@ #include "zone.h" #include "queryserv.h" #include "command.h" -#ifdef BOTS #include "bot_command.h" -#endif #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "titles.h" #include "guild_mgr.h" #include "task_manager.h" @@ -77,8 +76,6 @@ #else #include #include "../common/unix.h" -#include "zone_store.h" -#include "zone_event_scheduler.h" #endif @@ -89,21 +86,28 @@ volatile bool RunLoops = true; extern volatile bool is_zone_loaded; -EntityList entity_list; +#include "zone_event_scheduler.h" +#include "../common/file.h" +#include "../common/path_manager.h" + +EntityList entity_list; WorldServer worldserver; -ZoneStore zone_store; -uint32 numclients = 0; -char errorname[32]; -extern Zone* zone; -npcDecayTimes_Struct npcCorpseDecayTimes[100]; -TitleManager title_manager; -QueryServ *QServ = 0; -TaskManager *task_manager = 0; -NpcScaleManager *npc_scale_manager; -QuestParserCollection *parse = 0; -EQEmuLogSys LogSys; -ZoneEventScheduler event_scheduler; -WorldContentService content_service; +ZoneStore zone_store; +uint32 numclients = 0; +char errorname[32]; +extern Zone *zone; + +npcDecayTimes_Struct npcCorpseDecayTimes[100]; +TitleManager title_manager; +QueryServ *QServ = 0; +TaskManager *task_manager = 0; +NpcScaleManager *npc_scale_manager; +QuestParserCollection *parse = 0; +EQEmuLogSys LogSys; +ZoneEventScheduler event_scheduler; +WorldContentService content_service; +PathManager path; + const SPDat_Spell_Struct* spells; int32 SPDAT_RECORDS = -1; const ZoneConfig *Config; @@ -121,6 +125,8 @@ int main(int argc, char** argv) { set_exception_handler(); + path.LoadPaths(); + #ifdef USE_MAP_MMFS if (argc == 3 && strcasecmp(argv[1], "convert_map") == 0) { if (!ZoneConfig::LoadConfig()) @@ -143,7 +149,7 @@ int main(int argc, char** argv) { QServ = new QueryServ; - LogInfo("Loading server configuration.."); + LogInfo("Loading server configuration"); if (!ZoneConfig::LoadConfig()) { LogError("Loading server configuration failed"); return 1; @@ -156,7 +162,7 @@ int main(int argc, char** argv) { if (argc == 4) { instance_id = atoi(argv[3]); worldserver.SetLauncherName(argv[2]); - auto zone_port = SplitString(argv[1], ':'); + auto zone_port = Strings::Split(argv[1], ':'); if (!zone_port.empty()) { z_name = zone_port[0]; @@ -177,7 +183,7 @@ int main(int argc, char** argv) { } else if (argc == 3) { worldserver.SetLauncherName(argv[2]); - auto zone_port = SplitString(argv[1], ':'); + auto zone_port = Strings::Split(argv[1], ':'); if (!zone_port.empty()) { z_name = zone_port[0]; @@ -198,7 +204,7 @@ int main(int argc, char** argv) { } else if (argc == 2) { worldserver.SetLauncherName("NONE"); - auto zone_port = SplitString(argv[1], ':'); + auto zone_port = Strings::Split(argv[1], ':'); if (!zone_port.empty()) { z_name = zone_port[0]; @@ -223,7 +229,7 @@ int main(int argc, char** argv) { worldserver.SetLauncherName("NONE"); } - LogInfo("Connecting to MySQL... "); + LogInfo("Connecting to MySQL"); if (!database.Connect( Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), @@ -255,6 +261,7 @@ int main(int argc, char** argv) { /* Register Log System and Settings */ LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->SetGMSayHandler(&Zone::GMSayHookCallBackProcess) ->StartFileLogs(); @@ -267,7 +274,7 @@ int main(int argc, char** argv) { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif - LogInfo("CURRENT_VERSION: {}", CURRENT_VERSION); + LogInfo("CURRENT_VERSION [{}]", CURRENT_VERSION); /* * Setup nice signal handlers @@ -287,10 +294,8 @@ int main(int argc, char** argv) { } #endif - LogInfo("Mapping Incoming Opcodes"); MapOpcodes(); - LogInfo("Loading Variables"); database.LoadVariables(); std::string hotfix_name; @@ -300,69 +305,66 @@ int main(int argc, char** argv) { } } - LogInfo("Loading zone names"); + zone_store.LoadZones(content_db); - zone_store.LoadZones(); + if (zone_store.GetZones().empty()) { + LogError("Failed to load zones data, check your schema for possible errors"); + return 1; + } + + // load these here for now until spells and items can be truly repointed to "content_db" + database.SetSharedItemsCount(content_db.GetItemsCount()); + database.SetSharedSpellsCount(content_db.GetSpellsCount()); - LogInfo("Loading items"); if (!database.LoadItems(hotfix_name)) { LogError("Loading items failed!"); LogError("Failed. But ignoring error and going on.."); } - LogInfo("Loading npc faction lists"); if (!content_db.LoadNPCFactionLists(hotfix_name)) { LogError("Loading npcs faction lists failed!"); return 1; } - LogInfo("Loading loot tables"); + if (!content_db.LoadFactionAssociation(hotfix_name)) { + LogError("Loading faction association hits failed!"); + return 1; + } if (!database.LoadLoot(hotfix_name)) { LogError("Loading loot failed!"); return 1; } - LogInfo("Loading skill caps"); if (!content_db.LoadSkillCaps(std::string(hotfix_name))) { LogError("Loading skill caps failed!"); return 1; } - - LogInfo("Loading spells"); if (!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) { LogError("Loading spells failed!"); return 1; } - LogInfo("Loading base data"); if (!database.LoadBaseData(hotfix_name)) { LogError("Loading base data failed!"); return 1; } - LogInfo("Loading guilds"); guild_mgr.LoadGuilds(); - - LogInfo("Loading factions"); content_db.LoadFactionData(); - - LogInfo("Loading titles"); title_manager.LoadTitles(); - - LogInfo("Loading tributes"); content_db.LoadTributes(); - LogInfo("Loading corpse timers"); database.GetDecayTimes(npcCorpseDecayTimes); - LogInfo("Loading profanity list"); - if (!EQ::ProfanityManager::LoadProfanityList(&database)) + if (!EQ::ProfanityManager::LoadProfanityList(&database)) { LogError("Loading profanity list failed!"); + } - LogInfo("Loading commands"); int retval = command_init(); - if (retval < 0) + if (retval < 0) { LogError("Command loading failed"); - else - LogInfo("{} commands loaded", retval); + } + else { + LogInfo("Loaded [{}] commands loaded", Strings::Commify(std::to_string(retval))); + } //rules: { @@ -377,13 +379,9 @@ int main(int argc, char** argv) { if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { LogInfo("No rule set configured, using default rules"); } - else { - LogInfo("Loaded default rule set 'default'"); - } } EQ::InitializeDynamicLookups(); - LogInfo("Initialized dynamic dictionary entries"); } content_service.SetDatabase(&database) @@ -394,18 +392,21 @@ int main(int argc, char** argv) { EQ::SayLinkEngine::LoadCachedSaylinks(); -#ifdef BOTS - LogInfo("Loading bot commands"); - int botretval = bot_command_init(); - if (botretval<0) - LogError("Bot command loading failed"); - else - LogInfo("[{}] bot commands loaded", botretval); + if (RuleB(Bots, Enabled) && database.DoesTableExist("bot_command_settings")) { + LogInfo("Loading bot commands"); + int botretval = bot_command_init(); + if (botretval < 0) { + LogError("Bot command loading failed"); + } + else { + LogInfo("[{}] bot commands loaded", botretval); + } - LogInfo("Loading bot spell casting chances"); - if (!database.botdb.LoadBotSpellCastingChances()) - LogError("Bot spell casting chances loading failed"); -#endif + LogInfo("Loading bot spell casting chances"); + if (!database.botdb.LoadBotSpellCastingChances()) { + LogError("Bot spell casting chances loading failed"); + } + } /** * NPC Scale Manager @@ -491,7 +492,7 @@ int main(int argc, char** argv) { * Websocket server */ if (!websocker_server_opened && Config->ZonePort != 0) { - LogInfo("Websocket Server listener started ([{}]:[{}])", Config->TelnetIP.c_str(), Config->ZonePort); + LogInfo("Websocket Server listener started on address [{}] port [{}]", Config->TelnetIP.c_str(), Config->ZonePort); ws_server = std::make_unique(Config->TelnetIP, Config->ZonePort); RegisterApiService(ws_server); websocker_server_opened = true; @@ -501,7 +502,7 @@ int main(int argc, char** argv) { * EQStreamManager */ if (!eqsf_open && Config->ZonePort != 0) { - LogInfo("Starting EQ Network server on port {}", Config->ZonePort); + LogInfo("Starting EQ Network server on port [{}]", Config->ZonePort); EQStreamManagerInterfaceOptions opts(Config->ZonePort, false, RuleB(Network, CompressZoneStream)); opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); @@ -512,10 +513,16 @@ int main(int argc, char** argv) { eqsm = std::make_unique(opts); eqsf_open = true; - eqsm->OnNewConnection([&stream_identifier](std::shared_ptr stream) { - stream_identifier.AddStream(stream); - LogF(Logs::Detail, Logs::WorldServer, "New connection from IP {0}:{1}", stream->GetRemoteIP(), ntohs(stream->GetRemotePort())); - }); + eqsm->OnNewConnection( + [&stream_identifier](std::shared_ptr stream) { + stream_identifier.AddStream(stream); + LogInfo( + "New connection from address [{}] port [{}]", + long2ip(stream->GetRemoteIP()), + ntohs(stream->GetRemotePort()) + ); + } + ); } //give the stream identifier a chance to do its work.... @@ -598,9 +605,7 @@ int main(int argc, char** argv) { safe_delete(task_manager); safe_delete(npc_scale_manager); command_deinit(); -#ifdef BOTS bot_command_deinit(); -#endif safe_delete(parse); LogInfo("Proper zone shutdown complete."); LogSys.CloseFileLogs(); diff --git a/zone/map.cpp b/zone/map.cpp index 3d35aeabc..c92710fa8 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -5,6 +5,8 @@ #include "map.h" #include "raycast_mesh.h" #include "zone.h" +#include "../common/file.h" +#include "../common/path_manager.h" #include #include @@ -46,16 +48,16 @@ float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result) const { if(hit) { return result->z; } - + // Find nearest Z above us - + to.z = -BEST_Z_INVALID; hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); if (hit) { return result->z; } - + return BEST_Z_INVALID; } @@ -64,25 +66,25 @@ float Map::FindClosestZ(glm::vec3 &start, glm::vec3 *result) const { // if (!imp) return false; - + float ClosestZ = BEST_Z_INVALID; - + glm::vec3 tmp; if (!result) result = &tmp; - + glm::vec3 from(start.x, start.y, start.z); glm::vec3 to(start.x, start.y, BEST_Z_INVALID); float hit_distance; bool hit = false; - + // first check is below us hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); if (hit) { ClosestZ = result->z; - + } - + // Find nearest Z above us to.z = -BEST_Z_INVALID; hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); @@ -103,7 +105,7 @@ bool Map::LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::ve bool Map::LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const { if (!imp) return false; - + float z = BEST_Z_INVALID; glm::vec3 step; glm::vec3 cur; @@ -200,28 +202,9 @@ bool Map::DoCollisionCheck(glm::vec3 myloc, glm::vec3 oloc, glm::vec3 &outnorm, return imp->rm->raycast((const RmReal*)&myloc, (const RmReal*)&oloc, nullptr, (RmReal *)&outnorm, (RmReal *)&distance); } -inline bool file_exists(const std::string& name) { - std::ifstream f(name.c_str()); - return f.good(); -} - Map *Map::LoadMapFile(std::string file) { - - std::string filename = ""; - if (file_exists("maps")) { - filename = "maps"; - } - else if (file_exists("Maps")) { - filename = "Maps"; - } - else { - filename = Config->MapDir; - } - std::transform(file.begin(), file.end(), file.begin(), ::tolower); - filename += "/base/"; - filename += file; - filename += ".map"; + std::string filename = fmt::format("{}/base/{}.map", path.GetMapsPath(), file); LogInfo("Attempting to load Map File [{}]", filename.c_str()); @@ -308,19 +291,19 @@ bool Map::LoadV1(FILE *f) { uint32 face_count; uint16 node_count; uint32 facelist_count; - + if(fread(&face_count, sizeof(face_count), 1, f) != 1) { return false; } - + if(fread(&node_count, sizeof(node_count), 1, f) != 1) { return false; } - + if(fread(&facelist_count, sizeof(facelist_count), 1, f) != 1) { return false; } - + std::vector verts; std::vector indices; for(uint32 i = 0; i < face_count; ++i) { @@ -354,22 +337,22 @@ bool Map::LoadV1(FILE *f) { verts.push_back(c); indices.push_back((uint32)sz + 2); } - + if(imp) { imp->rm->release(); imp->rm = nullptr; } else { imp = new impl; } - + imp->rm = createRaycastMesh((RmUint32)verts.size(), (const RmReal*)&verts[0], face_count, &indices[0]); - + if(!imp->rm) { delete imp; imp = nullptr; return false; } - + return true; } @@ -978,7 +961,7 @@ bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to load Map MMF file: [{}] - f@file_version", mmf_file_name.c_str()); return false; } - + uint32 rm_buffer_size; if (fread(&rm_buffer_size, sizeof(uint32), 1, f) != 1) { fclose(f); @@ -1011,7 +994,7 @@ bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to load Map MMF file: [{}] - f@mmf_buffer", mmf_file_name.c_str()); return false; } - + fclose(f); std::vector rm_buffer(rm_buffer_size); @@ -1055,14 +1038,14 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to save Map MMF file: [{}]", mmf_file_name.c_str()); return false; } - + FILE* f = fopen(mmf_file_name.c_str(), "rb"); if (f) { fclose(f); if (!force_mmf_overwrite) return true; } - + std::vector rm_buffer; // size set in MyRaycastMesh::serialize() serializeRaycastMesh(imp->rm, rm_buffer); if (rm_buffer.empty()) { @@ -1074,19 +1057,19 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) uint32 mmf_buffer_size = EstimateDeflateBuffer(rm_buffer.size()); std::vector mmf_buffer(mmf_buffer_size); - + mmf_buffer_size = DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size()); if (!mmf_buffer_size) { LogInfo("Failed to save Map MMF file: [{}] - null MMF buffer size", mmf_file_name.c_str()); return false; } - + f = fopen(mmf_file_name.c_str(), "wb"); if (!f) { LogInfo("Failed to save Map MMF file: [{}] - could not open file", mmf_file_name.c_str()); return false; } - + uint32 file_version = 0; if (fwrite(&file_version, sizeof(uint32), 1, f) != 1) { fclose(f); @@ -1094,7 +1077,7 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to save Map MMF file: [{}] - f@file_version", mmf_file_name.c_str()); return false; } - + if (fwrite(&rm_buffer_size, sizeof(uint32), 1, f) != 1) { fclose(f); std::remove(mmf_file_name.c_str()); @@ -1116,7 +1099,7 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to save Map MMF file: [{}] - f@mmf_buffer_size", mmf_file_name.c_str()); return false; } - + if (fwrite(mmf_buffer.data(), mmf_buffer_size, 1, f) != 1) { fclose(f); std::remove(mmf_file_name.c_str()); @@ -1125,7 +1108,7 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) } fclose(f); - + return true; } diff --git a/zone/masterentity.h b/zone/masterentity.h index 8c238ed34..bdfa23b10 100644 --- a/zone/masterentity.h +++ b/zone/masterentity.h @@ -13,7 +13,4 @@ #include "beacon.h" #include "horse.h" -#ifdef BOTS #include "bot.h" -#endif - diff --git a/zone/maxskill.h b/zone/maxskill.h deleted file mode 100644 index e37cccac0..000000000 --- a/zone/maxskill.h +++ /dev/null @@ -1,2906 +0,0 @@ -// This file needs more than just 'std' updates - -uint16 Mob::MaxSkill_weapon(uint16 skillid, uint16 class_, uint16 level) const -{ - if (skillid > HIGHEST_SKILL) { - return 0; - } - uint16 r_value = 0; - switch (skillid) { - case _1H_BLUNT: - case _2H_BLUNT: - case PIERCING: - case HAND_TO_HAND: - case _1H_SLASHING: - case _2H_SLASHING: { - switch (class_) { - // Pure melee classes - case WARRIOR: - case WARRIORGM: { - r_value = 5 + (level * 5); - if ( level < 51 && r_value > 200) { - r_value = 200; - } - if ( level > 50 && r_value > 250 ) { - r_value = 250; - } - switch (skillid) { - case PIERCING: { - if ( r_value > 240 ) { - r_value = 240; - } - break; - } - case HAND_TO_HAND: { - if ( r_value > 100 ) { - r_value = 100; - } - break; - } - default: - break; - } - break; - } - case MONK: - case MONKGM: { - r_value = 5 + (level * 5); - if ( level < 51 && r_value > 240) - if ( r_value > 240 ) { - r_value = 240; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 225 && level < 51 ) { - r_value = 225; - } - break; - } - case PIERCING: - case _1H_SLASHING: - case _2H_SLASHING: { - r_value = 0; - break; - } - default: - break; - } - break; - } - case ROGUE: - case ROGUEGM: { - r_value = 5 + (level * 5); - if ( level > 50 && r_value > 250 ) { - r_value = 250; - } - if ( level < 51 ) { - if ( r_value > 200 && skillid != PIERCING ) { - r_value = 200; - } - if ( r_value > 210 && skillid == PIERCING ) { - r_value = 210; - } - } - if (skillid == HAND_TO_HAND && r_value > 100) { - r_value = 100; - } - break; - } - case BERSERKER: - case BERSERKERGM: { - r_value = 5 + (level * 5); - if ( level < 51 && r_value > 240) { - r_value = 240; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 198) { - r_value = 198; - } - break; - } - case PIERCING: { - if ( r_value > 240) { - r_value = 240; - } - break; - } - case _2H_BLUNT: - case _2H_SLASHING: { - if ( r_value > 252 ) { - r_value = 252; - } - break; - } - default: - r_value = 0; - break; - } - break; - } - // Priest classes - case CLERIC: - case CLERICGM: { - r_value = 4 + (level * 4); - if ( r_value > 175 ) { - r_value = 175; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 75 ) { - r_value = 75; - } - break; - } - case PIERCING: - case _1H_SLASHING: - case _2H_SLASHING: { - r_value = 0; - break; - } - default: - break; - } - break; - } - case DRUID: - case DRUIDGM: { - r_value = 4 + (level * 4); - if ( r_value > 175 ) { - r_value = 175; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 75 ) { - r_value = 75; - } - } - case PIERCING: - case _2H_SLASHING: { - r_value = 0; - break; - } - default: - break; - } - break; - } - case SHAMAN: - case SHAMANGM: { - r_value = 4 + (level * 4); - if ( r_value > 200 ) { - r_value = 200; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 75 ) { - r_value = 75; - } - } - case _1H_SLASHING: - case _2H_SLASHING: { - r_value = 0; - break; - } - default: - break; - } - break; - } - // Hybrids - case RANGER: - case RANGERGM: { - r_value = 5 + (level * 5); - if ( level > 50 ) { - if ( r_value > 250 ) { - r_value = 250; - } - switch (skillid) { - case PIERCING: { - if ( r_value > 240 ) { - r_value = 240; - } - break; - } - default: - break; - } - } else if ( level < 51 ) { - if ( r_value > 200 ) { - r_value = 200; - } - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 100 ) { - r_value = 100; - } - break; - } - default: - break; - } - break; - } - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - r_value = 5 + (level * 5); - if ( level > 50 && r_value > 225 ) { - r_value = 225; - } - if ( level < 51 && r_value > 200 ) { - r_value = 200; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 100 ) { - r_value = 100; - } - break; - } - default: - break; - } - break; - } - case BARD: - case BARDGM: { - r_value = 5 + (level * 5); - if ( level > 51 && r_value > 225 ) { - r_value = 225; - } - if ( level < 51 && r_value > 200 ) { - r_value = 200; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 100 ) { - r_value = 100; - } - break; - } - case _2H_BLUNT: - case _2H_SLASHING: { - r_value = 0; - } - default: - break; - } - break; - } - case BEASTLORD: - case BEASTLORDGM: { - r_value = 4 + (level * 4); - if ( level > 51 ) { - if ( r_value > 225 ) { - r_value = 225; - } - } - if ( level < 51 && r_value > 200 ) { - r_value = 200; - } - switch (skillid) { - case HAND_TO_HAND: { - r_value = 5 + (level * 5); // Beastlords use different max skill formula only for h2h 200/250 - if ( level < 51 ) { - r_value = 200; - } - break; - } - case _1H_SLASHING: - case _2H_SLASHING: { - r_value = 0; - break; - } - default: - break; - } - if ( r_value > 250 ) { - r_value = 250; - } - break; - } - // Pure casters - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: { - r_value = 3 + (level * 3); - if ( r_value > 110 ) { - r_value = 110; - } - switch (skillid) { - case HAND_TO_HAND: { - if ( r_value > 75 ) { - r_value = 75; - } - } - case _1H_SLASHING: - case _2H_SLASHING: { - r_value = 0; - break; - } - default: - break; - } - break; - } - default: - #if EQDEBUG - std::cout << "MaxSkill_Weapon() Unknown class: " << class_ << std::endl; - #endif - break; - } - break;// Switch Class - } - default: - #if EQDEBUG - std::cout << "Unknown weapon skill: " << skillid << std::endl; - #endif - break; - }// Switch skill - if (r_value > 252) { - r_value = 252; - } - return r_value; -} - -uint16 Mob::MaxSkill_offensive(uint16 skillid, uint16 class_, uint16 level) const -{ - uint16 r_value = 0; - switch (skillid) { - case OFFENSE: { - switch (class_) { - // Melee - case WARRIOR: - case WARRIORGM: - case BERSERKER: - case BERSERKERGM: - case ROGUE: - case ROGUEGM: { - // 210 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case MONK: - case MONKGM: { - // 230 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 230) { - r_value = 230; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: { - // 200 200 4*level+4 - r_value = ((level * 4) + 4); - if (r_value > 200) { - r_value = 200; - } - break; - } - // Hybrid - case BEASTLORD: - case BEASTLORDGM: { - // 200 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: - case BARD: - case BARDGM: { - // 200 225 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 225) { - r_value = 225; - } - break; - } - case RANGER: - case RANGERGM: { - // 210 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: { - // 140 140 level*4 - r_value = (level * 4); - if (r_value > 140) { - r_value = 140; - } - break; - } - default: - break; - } - break; - } - case THROWING: { - switch (class_) { - // Melee - case BERSERKER: - case BERSERKERGM: - case ROGUE: - case ROGUEGM: { - // 220 250 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 220) { - r_value = 220; - } - } - if (r_value > 250) { - r_value = 250; - } - break; - } - case WARRIOR: - case WARRIORGM: - case MONK: - case MONKGM: { - // 113 200 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 113) { - r_value = 113; - } - } - if (r_value > 200) { - r_value = 200; - } - break; - } - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - case BARD: - case BARDGM: - case RANGER: - case RANGERGM: { - // 113 - r_value = ((level * 5) + 5); - if ( r_value > 113 ) { - r_value = 113; - } - break; - } - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: { - // 75 - r_value = ((level * 3) + 3); - if ( r_value > 75 ) { - r_value = 75; - } - break; - } - // No skill classes - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: - default: - r_value = 0; - break; - } - break; - } -///////////////////////////////////////////////// - case ARCHERY: { - switch (class_) { - // Melee - case ROGUE: - case ROGUEGM: - case WARRIOR: - case WARRIORGM: { - // 200 240 - r_value = ((level * 5) + 5); - if ( level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 240) { - r_value = 240; - } - break; - } - // Hybrid - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 75 75 - r_value = ((level * 5) + 5); - if ( r_value > 75 ) { - r_value = 75; - } - break; - } - case RANGER: - case RANGERGM: { - // 240 240 - r_value = ((level * 5) + 5); - if ( r_value > 240 ) { - r_value = 240; - } - break; - } - // Pure - // No skill classes - // Melee - case MONK: - case MONKGM: - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - case BARD: - case BARDGM: - default: - r_value = 0; - break; - } - break; - } -///////////////////////////////////////////////// - case DOUBLE_ATTACK: { - switch (class_) { - // Melee - case ROGUE: - case ROGUEGM: { - // 16 200 240 - r_value = ((level * 5) + 5); - if ( level < 16 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 240) { - r_value = 240; - } - break; - } - case BERSERKER: - case BERSERKERGM: - case WARRIOR: - case WARRIORGM: { - // 15 205 245 - r_value = ((level * 5) + 5); - if ( level < 15 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 245) { - r_value = 245; - } - break; - } - case MONK: - case MONKGM: { - // 15 210 250 - r_value = ((level * 5) + 5); - if ( level < 15 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 250) { - r_value = 250; - } - break; - } - // Hybrid - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 20 200 235 - r_value = ((level * 5) + 5); - if ( level < 20 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 235) { - r_value = 235; - } - break; - } - case RANGER: - case RANGERGM: { - // 20 200 245 - r_value = ((level * 5) + 5); - if ( level < 20 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 245) { - r_value = 245; - } - break; - } - // Pure - // No skill classes - // Melee - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - case BARD: - case BARDGM: - default: - r_value = 0; - break; - } - break; - } -///////////////////////////////////////////////// - case DUAL_WIELD: { - switch (class_) { - // Melee - case MONK: - case MONKGM: { - // 1 252 252 - r_value = level * 7; // This can't be right can it? - break - ; - } - case WARRIOR: - case WARRIORGM: - case ROGUE: - case ROGUEGM: { - // 15 210 245 - r_value = ((level * 5) + 5); - if ( level < 13 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 245) { - r_value = 245; - } - break; - } - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - // 17 210 245 - case RANGER: - case RANGERGM: { - // 17 210 245 - r_value = ((level * 5) + 5); - if ( level < 17 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 245) { - r_value = 245; - } - break; - } - case BARD: - case BARDGM: { - // 17 210 210 - r_value = ((level * 5) + 5); - if ( level < 17 ) { - r_value = 0; - } - if (r_value > 210) { - r_value = 210; - } - break; - } - // No skill classes - // Melee - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: - default: { - r_value = 0; - break; - } - }// end Class switch - break; - } // end case DUAL_WIELD: -//////////////////////////////////////////////////////// - case KICK: { - switch (class_) { - // Melee - case BERSERKER: - case BERSERKERGM: - case WARRIOR: - case WARRIORGM: { - // 1 149 210 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 149) { - r_value = 149; - } - } - if (r_value > 210) { - r_value = 210; - } - break; - } - case MONK: - case MONKGM: { - // 1 200 250 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 250) { - r_value = 250; - } - break; - } - // Hybrid - case RANGER: - case RANGERGM: { - // 5 149 205 - r_value = ((level * 5) + 5); - if ( level < 5 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 149) { - r_value = 149; - } - } - if (r_value > 205) { - r_value = 205; - } - break; - } - case BEASTLORD: - case BEASTLORDGM: { - // 5 180 230 - r_value = ((level * 5) + 5); - if ( level < 5 ) { - r_value = 0; - } - if ( level < 51 ) { - if (r_value > 180) { - r_value = 180; - } - } - if (r_value > 230) { - r_value = 230; - } - break; - } - // Pure - // No skill classes - case ROGUE: - case ROGUEGM: - // Melee - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: - case BARD: - case BARDGM: - default: - r_value = 0; - break; - } - break; - } -//////////////////////////////////////////////////////// - case BASH: { - r_value = ((level * 5) + 5); - switch (class_) { - // Melee - case WARRIOR: - case WARRIORGM: { - // 6 220 240 - if (level < 6) { - r_value = 0; - } - if (level < 51 && r_value > 220) { - r_value = 220; - } - if (r_value > 240) { - r_value = 240; - } - break; - } - // Priest - case CLERIC: - case CLERICGM: { - // 25 180 200 - if (level < 25) { - r_value = 0; - } - if (level < 51 && r_value > 180) { - r_value = 180; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - // Hybrid - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 6 175 200 - if (level < 6) { - r_value = 0; - } - if (level < 51 && r_value > 175) { - r_value = 175; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - // Pure - // No skill classes - // Melee - case MONK: - case MONKGM: - case ROGUE: - case ROGUEGM: - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - case RANGER: - case RANGERGM: - case BARD: - case BARDGM: { - // switch (race) { - // case BARBARIAN: - // case TROLL: - //case OGRE:{ - // r_value = 50; - //break; - //} - //default: break; - //} - r_value = 0; - break; - } - } - break; - } -//////////////////////////////////////////////////////// - default: - #if EQDEBUG >= 1 - std::cout << "Unknown Offensive skill: " << skillid << std::endl; - #endif - break; - }// Switch skill - if (r_value > 252) { - r_value = 252; - } - return r_value; -} - -uint16 Mob::MaxSkill_defensive(uint16 skillid, uint16 class_, uint16 level) const -{ - uint16 r_value = 0; - switch (skillid) { - case DEFENSE: { - switch (class_) { - // Melee - case WARRIOR: - case WARRIORGM: { - // 210 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case ROGUE: - case ROGUEGM: { - // 200 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case MONK: - case MONKGM: { - // 230 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 230) { - r_value = 230; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case BERSERKER: - case BERSERKERGM: { - // 230 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 230) { - r_value = 230; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: { - // 200 200 4*level+4 - r_value = ((level * 4) + 4); - if (r_value > 200) { - r_value = 200; - } - break; - } - // Hybrid - case BEASTLORD: - case BEASTLORDGM: { - // 210 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 210 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 210) { - r_value = 210; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case BARD: - case BARDGM: { - // 200 252 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 51 ) { - if (r_value > 200) { - r_value = 200; - } - } - if (r_value > 252) { - r_value = 252; - } - break; - } - case RANGER: - case RANGERGM: { - // 200 200 5*level+5 - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: { - // 145 145 level*4 - r_value = (level * 4); - if (r_value > 140) { - r_value = 140; - } - break; - } - default: - break; - } - break; - } - case PARRY: { - switch (class_) { - // Melee - case ROGUE: - case ROGUEGM: { - // 12 200 230 - r_value = ((level * 5) + 5); - if ( level < 12 ) { - r_value = 0; - } - if (r_value > 200 && level < 51 ) { - r_value = 200; - } - if (r_value > 230) { - r_value = 230; - } - break; - } - case WARRIOR: - case WARRIORGM: { - // 10 200 230 - r_value = ((level * 5) + 5); - if ( level < 10 ) { - r_value = 0; - } - if (r_value > 200 && level < 51 ) { - r_value = 200; - } - if (r_value > 230) { - r_value = 230; - } - break; - } - case BERSERKER: - case BERSERKERGM: { - r_value = ((level * 5) + 5); - if ( level < 10 ) { - r_value = 0; - } - if (r_value > 175) { - r_value = 175; - } - break; - } - // Hybrid - case BARD: - case BARDGM: { - // 53 0 75 - r_value = ((level * 5) + 5); - if ( level < 53 ) { - r_value = 0; - } - if (r_value > 75) { - r_value = 75; - } - break; - } - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 17 175 205 - r_value = ((level * 5) + 5); - if ( level < 17 ) { - r_value = 0; - } - if (r_value > 175 && level < 51 ) { - r_value = 175; - } - if (r_value > 205) { - r_value = 205; - } - break; - } - case RANGER: - case RANGERGM: { - // 18 185 220 - r_value = ((level * 5) + 5); - if ( level < 18 ) { - r_value = 0; - } - if (r_value > 185 && level < 51 ) { - r_value = 185; - } - if (r_value > 220) { - r_value = 220; - } - break; - } - // Pure - // No skill classes - // Melee - case MONK: - case MONKGM: - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - default: - r_value = 0; - break; - } - break; - } - case RIPOSTE: { - switch (class_) { - // Melee - case BERSERKER: - case BERSERKERGM: - case WARRIOR: - case WARRIORGM: { - // 25 200 225 - r_value = ((level * 5) + 5); - if ( level < 25 ) { - r_value = 0; - } - if (r_value > 200 && level < 51 ) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - case ROGUE: - case ROGUEGM: { - // 30 200 225 - r_value = ((level * 5) + 5); - if ( level < 30 ) { - r_value = 0; - } - if (r_value > 200 && level < 51 ) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - case MONK: - case MONKGM: { - // 35 200 225 - r_value = ((level * 5) + 5); - if ( level < 35 ) { - r_value = 0; - } - if (r_value > 200 && level < 51 ) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - // Hybrid - case BEASTLORD: - case BEASTLORDGM: { - // 40 150 185 - r_value = ((level * 5) + 5); - if ( level < 40 ) { - r_value = 0; - } - if (r_value > 150 && level < 51 ) { - r_value = 150; - } - if (r_value > 185) { - r_value = 185; - } - break; - } - case BARD: - case BARDGM: { - // 58 75 75 - r_value = ((level * 5) + 5); - if ( level < 58 ) { - r_value = 0; - } - if (r_value > 75) { - r_value = 75; - } - break; - } - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 30 175 200 - r_value = ((level * 5) + 5); - if ( level < 30 ) { - r_value = 0; - } - if (r_value > 175 && level < 51 ) { - r_value = 175; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - case RANGER: - case RANGERGM: { - // 35 150 150 - r_value = ((level * 5) + 5); - if ( level < 35 ) { - r_value = 0; - } - if (r_value > 150) { - r_value = 150; - } - break; - } - // Pure - // No skill classes - // Melee - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - default: - r_value = 0; - break; - } - break; - } - case DODGE: { - switch (class_) { - // Melee - case BERSERKER: - case BERSERKERGM: - case WARRIOR: - case WARRIORGM: { - // 6 140 175 - r_value = ((level * 5) + 5); - if ( level < 6 ) { - r_value = 0; - } - if (r_value > 140 && level < 51 ) { - r_value = 140; - } - if (r_value > 175) { - r_value = 175; - } - break; - } - case ROGUE: - case ROGUEGM: { - // 4 150 210 - r_value = ((level * 5) + 5); - if ( level < 4 ) { - r_value = 0; - } - if (r_value > 150 && level < 51 ) { - r_value = 150; - } - if (r_value > 210) { - r_value = 210; - } - break; - } - case MONK: - case MONKGM: { - // 1 200 230 - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - if (r_value > 230) { - r_value = 230; - } - break; - } - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: { - // 15 75 75 4*level+4 - r_value = ((level * 4) + 4); - if ( level < 15 ) { - r_value = 0; - } - if (r_value > 75) { - r_value = 75; - } - break; - } - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: - case BARD: - case BARDGM: { - // 10 125 155 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 10 ) { - r_value = 0; - } - if (r_value > 125 && level < 51 ) { - r_value = 125; - } - if (r_value > 155) { - r_value = 155; - } - break; - } - case RANGER: - case RANGERGM: { - // 8 137 170 5*level+5 - r_value = ((level * 5) + 5); - if ( level < 8 ) { - r_value = 0; - } - if (r_value > 137 && level < 51 ) { - r_value = 137; - } - if (r_value > 170) { - r_value = 170; - } - break; - } - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: { - // 22 75 75 3*level+3 - r_value = ((level * 3) + 3); - if ( level < 22 ) { - r_value = 0; - } - if (r_value > 75) { - r_value = 75; - } - break; - } - // No skill classes - // Melee - // Priest - // Pure - // Hybrid - default: - break; - } - break; - } - // Other - case TAUNT: { - switch (class_) { - // Melee - case WARRIOR: - case WARRIORGM: { - // 1 200 200 - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - // Priest - // Hybrid - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 1 180 180 - r_value = ((level * 5) + 5); - if (r_value > 180) { - r_value = 180; - } - break; - } - case RANGER: - case RANGERGM: { - // 1 150 150 - r_value = ((level * 5) + 5); - if (r_value > 150) { - r_value = 150; - } - break; - } - // Pure - // No skill classes - // Melee - case ROGUE: - case ROGUEGM: - case MONK: - case MONKGM: - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case BEASTLORD: - case BEASTLORDGM: - case BARD: - case BARDGM: - default: - break; - } - break; - } - case DISARM: { - switch (class_) { - // Melee - case WARRIOR: - case WARRIORGM: { - // 35 200 200 - r_value = ((level * 5) + 5); - if (level < 35) { - r_value = 0; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - case ROGUE: - case ROGUEGM: - case MONK: - case MONKGM: { - // 27 200 200 - r_value = ((level * 5) + 5); - if (level < 27) { - r_value = 0; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - case BERSERKER: - case BERSERKERGM: { - // 35 65 65 - r_value = ((level * 5) + 5); - if (level < 35) { - r_value = 0; - } - if (r_value > 65) { - r_value = 65; - } - break; - } - // Priest - // Hybrid - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 40 70 70 - r_value = ((level * 5) + 5); - if (level < 40) { - r_value = 0; - } - if (r_value > 70) { - r_value = 70; - } - break; - } - case RANGER: - case RANGERGM: { - // 35 55 55 - r_value = ((level * 5) + 5); - if (level < 35) { - r_value = 0; - } - if (r_value > 55) { - r_value = 55; - } - break; - } - // Pure - // No skill classes - // Melee - // Priest - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - case CLERIC: - case CLERICGM: - // Pure - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - // Hybrid - case BARD: - case BARDGM: - case BEASTLORD: - case BEASTLORDGM: - default: - break; - } - break; - } -//////////////////////////////////////////////////////// - default: - #if EQDEBUG - std::cout << "Unknown Defensive skill: " << skillid << std::endl; - #endif - break; - }// Switch skill - if (r_value > 252) { - r_value = 252; - } - return r_value; -} - -uint16 Mob::MaxSkill_arcane(uint16 skillid, uint16 class_, uint16 level) const -{ - uint16 r_value = 0; - switch (skillid) { - case MEDITATE: - case ABJURE: - case ALTERATION: - case CHANNELING: - case CONJURATION: - case DIVINATION: - case EVOCATION: { - r_value = ((level * 5) + 5); - switch (class_) { - // Hybrid - case RANGER: - case RANGERGM: { - // 9 235 235 - // Channel 9 200 215 - // Med 12 185 235 - if (level < 9) { - r_value = 0; - } - if (level < 12 && skillid == MEDITATE) { - r_value = 0; - } - if (r_value > 0 && skillid == CHANNELING) { - if ( level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 215) { - r_value = 215; - } - } - if (r_value > 0 && skillid == MEDITATE) { - if ( level < 51 && r_value > 185) { - r_value = 185; - } - if (r_value > 235) { - r_value = 235; - } - } - break; - } - case BEASTLORD: - case BEASTLORDGM: - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - // 9 235 235 - // Channel 9 200 220 - // Med 12 185 235 - if (level < 9) { - r_value = 0; - } - if (level < 12 && skillid == MEDITATE) { - r_value = 0; - } - if (r_value > 0 && skillid == CHANNELING) { - if ( level < 51 && r_value > 185) { - r_value = 185; - } - if (r_value > 220) { - r_value = 220; - } - } - if (r_value > 0 && skillid == MEDITATE) { - if ( level < 51 && r_value > 185) { - r_value = 185; - } - if (r_value > 235) { - r_value = 235; - } - } - break; - } - // Priest - case CLERIC: - case CLERICGM: - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: { - // 1 235 235 - // Channel 4 200 220 - // Med 8 235 252 - if (level < 4 && skillid == CHANNELING) { - r_value = 0; - } - if (level < 8 && skillid == MEDITATE) { - r_value = 0; - } - if (r_value > 0 && skillid == CHANNELING) { - if ( level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 220) { - r_value = 220; - } - } - if (r_value > 0 && skillid == MEDITATE) { - if ( level < 51 && r_value > 235) { - r_value = 235; - } - if (r_value > 252) { - r_value = 252; - } - } - break; - } - // Int caster - case ENCHANTER: - case ENCHANTERGM: - case MAGICIAN: - case MAGICIANGM: - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: { - // 1 235 235 - // Channel 1 200 220 - // Med 4 235 252 - if (level < 4 && skillid == MEDITATE) { - r_value = 0; - } - if (r_value > 0 && skillid == CHANNELING) { - if ( level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 220) { - r_value = 220; - } - } - if (r_value > 0 && skillid == MEDITATE) { - if ( level < 51 && r_value > 235) { - r_value = 235; - } - if (r_value > 252) { - r_value = 252; - } - } - break; - } - case BARD: - case BARDGM: { - r_value = 0; - if (level > 9 && skillid == MEDITATE) { - r_value = 1; - } - break; - } - default: - // Unknown class - r_value = 0; - break; - }// Class Switch - break; - } - case SPECIALIZE_ABJURE: - case SPECIALIZE_ALTERATION: - case SPECIALIZE_CONJURATION: - case SPECIALIZE_DIVINATION: - case SPECIALIZE_EVOCATION: { - r_value = ((level * 5) + 5); - switch (class_) { - // Non-int casters - case CLERIC: - case CLERICGM: - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: - if (level < 30) { - r_value = 0; - break; - } - // Int caster - case ENCHANTER: - case ENCHANTERGM: - case MAGICIAN: - case MAGICIANGM: - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: { - if (level < 20) { - r_value = 0; - break; - } - //make sure only 1 skill can be over 50 - uint16 hskill = 0; - uint16 high = 0; - uint16 cur; - cur = GetSkill(SPECIALIZE_ABJURE); - if (cur > high) { - hskill = SPECIALIZE_ABJURE; - high = cur; - } - cur = GetSkill(SPECIALIZE_ALTERATION); - if (cur > high) { - hskill = SPECIALIZE_ALTERATION; - high = cur; - } - cur = GetSkill(SPECIALIZE_CONJURATION); - if (cur > high) { - hskill = SPECIALIZE_CONJURATION; - high = cur; - } - cur = GetSkill(SPECIALIZE_DIVINATION); - if (cur > high) { - hskill = SPECIALIZE_DIVINATION; - high = cur; - } - cur = GetSkill(SPECIALIZE_EVOCATION); - if (cur > high) { - hskill = SPECIALIZE_EVOCATION; - high = cur; - } - if (high > 50 && hskill != skillid) { - r_value = 50; - break; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - default: { - r_value = 0; - break; - } - }// Class Switch - break; - } - case RESEARCH: { - r_value = ((level * 5) + 5); - switch (class_) { - // Int caster - case ENCHANTER: - case ENCHANTERGM: - case MAGICIAN: - case MAGICIANGM: - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: { - // Res 16 200 200 - if (level < 16) { - r_value = 0; - } - if (r_value > 200) { - r_value = 200; - } - // FIXME Only let one SPEC go above what ever limit theres supposed to be - break; - } - default: { - r_value = 0; - break; - } - }// Class Switch - break; - } - case BRASS_INSTRUMENTS: - case SINGING: - case STRINGED_INSTRUMENTS: - case WIND_INSTRUMENTS: - case PERCUSSION_INSTRUMENTS: { - switch (class_) { - case BARD: - case BARDGM: { - r_value = ((level * 5) + 5); - if (level < 5 && skillid == PERCUSSION_INSTRUMENTS) { - r_value = 0; - } - if (level < 8 && skillid == STRINGED_INSTRUMENTS) { - r_value = 0; - } - if (level < 11 && skillid == BRASS_INSTRUMENTS) { - r_value = 0; - } - if (level < 14 && skillid == WIND_INSTRUMENTS) { - r_value = 0; - } - if (r_value > 235) { - r_value = 235; - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } -//////////////////////////////////////////////////////// - default: - #if EQDEBUG - std::cout << "Unknown arcane skill: " << skillid << std::endl; - #endif - break; - }// Switch skill - if (r_value > 252) { - r_value = 252; - } - return r_value; -} - -uint16 Mob::MaxSkill_class(uint16 skillid, uint16 class_, uint16 level) const -{ - uint16 r_value = 0; - switch (skillid) { - // Rogue - case APPLY_POISON: - case MAKE_POISON: - case PICK_POCKETS: - case BACKSTAB: { - switch (class_) { - // Melee - case ROGUE: - case ROGUEGM: { - r_value = ((level * 5) + 5); - switch (skillid) { - case APPLY_POISON: { - // 18 200 200 - if (level < 18) { - r_value = 0; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - case MAKE_POISON: { - // 20 200 250 - if (level < 20) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 250) { - r_value = 250; - } - break; - } - case PICK_POCKETS: { - // 7 200 210 - if (level < 7) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 210) { - r_value = 210; - } - break; - } - case BACKSTAB: { - // 10 200 225 - if (level < 10) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - default: - r_value = 0; - break; - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } - // Monk - case BLOCKSKILL: { - switch (class_) { - case BEASTLORD: - case BEASTLORDGM: { - r_value = (((level - 25) * 5) + 5); - // 12 200 230 - if (level < 25) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 230) { - r_value = 230; - } - break; - } - case MONK: - case MONKGM: { - r_value = ((level * 5) + 5); - // 12 200 230 - if (level < 12) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 230) { - r_value = 230; - } - break; - } - } - break; - } - case FEIGN_DEATH: - case MEND: - case DRAGON_PUNCH: - case EAGLE_STRIKE: - case FLYING_KICK: - case ROUND_KICK: - case TIGER_CLAW: { - switch (class_) { - case MONK: - case MONKGM: { - r_value = ((level * 5) + 5); - switch (skillid) { - case MEND: { - // 1 200 200 - if (r_value > 200) { - r_value = 200; - } - break; - } - case ROUND_KICK: { - // 5 200 225 - if (level < 5) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - case TIGER_CLAW: { - // 10 200 225 - if (level < 10) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - case FEIGN_DEATH: { - // 17 200 200 - if (level < 17) { - r_value = 0; - } - if (r_value > 200) { - r_value = 200; - } - break; - } - case EAGLE_STRIKE: { - // 20 200 225 - if (level < 20) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - case DRAGON_PUNCH: { - // 25 200 225 - if (level < 25) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - case FLYING_KICK: { - // 30 200 225 - if (level < 30) { - r_value = 0; - } - if (level < 51 && r_value > 200) { - r_value = 200; - } - if (r_value > 225) { - r_value = 225; - } - break; - } - default: - r_value = 0; - break; - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } - //Berzerkers - case BERSERKING: { - switch (class_) { - case BERSERKER: - case BERSERKERGM: { - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - } - default: - r_value = 0; - break; - } - break; - } - // Shaman - case ALCHEMY: { - switch (class_) { - case SHAMAN: - case SHAMANGM: { - // 25 130 180 - r_value = ((level * 5) + 5); - if (level < 25) { - r_value = 0; - } - if (level < 51 && r_value > 130) { - r_value = 130; - } - if (r_value > 180) { - r_value = 180; - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } -/////////////////////////////////////////// -////////////////////////////////////////// -// Shared skill - // Shared Rogue - case HIDE: { - switch (class_) { - // True class - case ROGUE: - case ROGUEGM: { - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - // Hybrids - case RANGER: - case RANGERGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { //75 cap - if (level >= 35) { - r_value = (((level - 35) * 5) + 5); - if (r_value > 75) { - r_value = 75; - } - } - break; - } - case BARD: - case BARDGM: { //40 cap - if (level > 25) { - r_value = (((level - 25) * 5) + 5); - if (r_value > 40) { - r_value = 40; - } - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } - case SNEAK: { - switch (class_) { - // True class - case ROGUE: - case ROGUEGM: { - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - // Hybrids - case MONK: - case MONKGM: { //113 cap - if (level >= 8) { - r_value = (((level - 8) * 5) + 5); - if (r_value > 113) { - r_value = 113; - } - } - break; - } - case RANGER: - case RANGERGM: { //75 cap - if (level >= 10) { - r_value = (((level - 10) * 5) + 5); - if (r_value > 75) { - r_value = 75; - } - } - break; - } - case BARD: - case BARDGM: { //75 cap - if (level >= 17) { - r_value = (((level - 17) * 5) + 5); - if (r_value > 75) { - r_value = 75; - } - } - break; - } - case BEASTLORD: - case BEASTLORDGM: { //50 cap - if (level >= 50) { - r_value = (((level - 50) * 5) + 5); - if (r_value > 50) { - r_value = 50; - } - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } - case SENSE_TRAPS: - case PICK_LOCK: - case DISARM_TRAPS: { - switch (class_) { - // True class - case ROGUE: - case ROGUEGM: { - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - // Hybrids - case BARD: - case BARDGM: { //100 cap - if (level >= 30) { //this is wrong I think... - r_value = (((level - 30) * 5) + 5); - if (r_value > 100) { - r_value = 100; - } - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } - case SAFE_FALL: { - switch (class_) { - // Hybrids - case BARD: - case BARDGM: { //40 cap - if (level >= 24) { - r_value = (((level - 24) * 5) + 5); - if (r_value > 40) { - r_value = 40; - } - } - break; - } - // Melee - case MONK: - case MONKGM: { - if (level >= 3) { - r_value = (((level - 3) * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - } - break; - } - case ROGUE: - case ROGUEGM: { //100 cap - if (level >= 12) { - r_value = (((level - 12) * 5) + 5); - if (r_value > 100) { - r_value = 100; - } - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } - case INTIMIDATION: { - switch (class_) { - case BARD: - case BARDGM: { //100 cap - if (level >= 26) { - r_value = (((level - 26) * 5) + 5); - if (r_value > 100) { - r_value = 100; - } - } - break; - } - // Melee - case MONK: - case MONKGM: { - if (level >= 18) { - r_value = (((level - 18) * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - } - break; - } - case BERSERKER: - case BERSERKERGM: { - if (level >= 20) { - r_value = (((level - 20) * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - } - break; - } - case ROGUE: - case ROGUEGM: { - if (level >= 22) { - r_value = (((level - 22) * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - } - break; - } - default: - r_value = 0; - break; - }// Class Switch - break; - } - // Druid/Ranger/Bard - case FORAGE: { - switch (class_) { - case RANGER: - case RANGERGM: { - if (level > 3) { - r_value = (((level - 3) * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - } - break; - } - case DRUID: - case DRUIDGM: { - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - case MONK: - case MONKGM: - case BARD: - case BARDGM: - r_value = 55; - break; - default: - r_value = 50; - break; - }// Class Switch - break; - } - case TRACKING: { - switch (class_) { - case RANGER: - case RANGERGM: - case BARD: - case BARDGM: - case DRUID: - case DRUIDGM: - r_value = 200; - break; - default: - r_value = 0; - break; - }// Class Switch - break; - } -//////////////////////////////////////////////////////// - default: - #if EQDEBUG - std::cout << "Unknown class skill: " << skillid << std::endl; - #endif - break; - }// Switch skill - if (r_value > 252) { - r_value = 252; - } - return r_value; -} - -uint16 Mob::MaxSkill(uint16 skillid, uint16 class_, uint16 level) const -{ - uint16 r_value = 0; - switch (skillid) { - case _1H_BLUNT: - case _2H_BLUNT: - case PIERCING: - case HAND_TO_HAND: - case _1H_SLASHING: - case _2H_SLASHING: { - r_value = MaxSkill_weapon(skillid, class_, level); - break; - } - case OFFENSE: - case THROWING: - case ARCHERY: - case DOUBLE_ATTACK: - case DUAL_WIELD: - case KICK: - case BASH: { - r_value = MaxSkill_offensive(skillid, class_, level); - break; - } - case DEFENSE: - case PARRY: - case RIPOSTE: - case DODGE: - case TAUNT: - case DISARM: { - r_value = MaxSkill_defensive(skillid, class_, level); - break; - } - case MEDITATE: - case ABJURE: - case ALTERATION: - case CHANNELING: - case CONJURATION: - case DIVINATION: - case EVOCATION: - case SPECIALIZE_ABJURE: - case SPECIALIZE_ALTERATION: - case SPECIALIZE_CONJURATION: - case SPECIALIZE_DIVINATION: - case SPECIALIZE_EVOCATION: - case RESEARCH: - case BRASS_INSTRUMENTS: - case SINGING: - case STRINGED_INSTRUMENTS: - case WIND_INSTRUMENTS: - case PERCUSSION_INSTRUMENTS: { - r_value = MaxSkill_arcane(skillid, class_, level); - break; - } -/////////////////////////////////////////// -/////////////////////////////////////////// -// Class skills - // Rogue - case APPLY_POISON: - case MAKE_POISON: - case PICK_POCKETS: - case BACKSTAB: - // Monk - case FEIGN_DEATH: - case MEND: - case DRAGON_PUNCH: - case EAGLE_STRIKE: - case FLYING_KICK: - case ROUND_KICK: - case TIGER_CLAW: - case BLOCKSKILL: - case ALCHEMY: - case HIDE: - case SNEAK: - case SENSE_TRAPS: - case PICK_LOCK: - case DISARM_TRAPS: - case SAFE_FALL: - case INTIMIDATION: - // Druid/Ranger/Bard - case FORAGE: - case TRACKING: { - r_value = MaxSkill_class(skillid, class_, level); - break; - } -/////////////////////////////////////////// -/////////////////////////////////////////// -// Tradeskills - case BAKING: - case TAILORING: - case BLACKSMITHING: - case FLETCHING: - case BREWING: - case JEWELRY_MAKING: - case POTTERY: - case FISHING: { - // Check for Any Trade above 200, check for X (aa skill) Trades above 200 - r_value = 250; - break; - } -///////////////////////////////////// -///////////////////////////////////// - // Gnome - case TINKERING: { - if ( race == GNOME && level > 24 ) { - r_value = ((level * 5) + 5); - break; - } - r_value = 0; - break; - } -///////////////////////////////////////// -// Common -///////////////////////////////////////// - case BIND_WOUND: { - switch (class_) { - case BARD: - case BARDGM: { - r_value = ((level * 5) + 5); - if (level >= 50) { - if (r_value > 210) { - r_value = 210; - } - } else { - if (r_value > 200) { - r_value = 200; - } - } - break; - } - case CLERIC: - case CLERICGM: { - r_value = ((level * 5) + 5); - if (level >= 50) { - if (r_value > 201) { - r_value = 201; - } - } else { - if (r_value > 200) { - r_value = 200; - } - } - break; - } - case DRUID: - case DRUIDGM: - case SHAMAN: - case SHAMANGM: { - r_value = ((level * 5) + 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - case MAGICIAN: - case MAGICIANGM: - case ENCHANTER: - case ENCHANTERGM: - case NECROMANCER: - case NECROMANCERGM: - case WIZARD: - case WIZARDGM: { - r_value = ((level * 5) + 5); - if (r_value > 100) { - r_value = 100; - } - break; - } - case BEASTLORD: - case BEASTLORDGM: - case BERSERKER: - case BERSERKERGM: - case MONK: - case MONKGM: { - r_value = ((level * 5) + 5); - if (level >= 50) { - if (r_value > 210) { - r_value = 210; - } - } else { - if (r_value > 200) { - r_value = 200; - } - } - break; - } - case PALADIN: - case PALADINGM: { - if (level > 10) { - r_value = (((level - 10) * 5) + 5); - if (level >= 50) { - if (r_value > 210) { - r_value = 210; - } - } else { - if (r_value > 200) { - r_value = 200; - } - } - } - break; - } - case RANGER: - case RANGERGM: { - if (level > 15) { - r_value = (((level - 15) * 5) + 5); - if (level >= 50) { - if (r_value > 200) { - r_value = 200; - } - } else { - if (r_value > 150) { - r_value = 150; - } - } - } - break; - } - case ROGUE: - case ROGUEGM: { - r_value = ((level * 5) + 5); - if (level >= 50) { - if (r_value > 210) { - r_value = 210; - } - } else { - if (r_value > 176) { - r_value = 176; - } - } - break; - } - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: { - r_value = ((level * 5) + 5); - if (level >= 50) { - if (r_value > 200) { - r_value = 200; - } - } else { - if (r_value > 150) { - r_value = 150; - } - } - break; - } - case WARRIOR: - case WARRIORGM: { - if (level > 5) { - r_value = (((level - 5) * 5) + 5); - if (level >= 50) { - if (r_value > 210) { - r_value = 210; - } - } else { - if (r_value > 175) { - r_value = 175; - } - } - } - break; - } - default: - r_value = 0; - break; - } - break; - } - case SENSE_HEADING: - case SWIMMING: - case ALCOHOL_TOLERANCE: - case BEGGING: { - r_value = 5 + (level * 5); - if (r_value > 200) { - r_value = 200; - } - break; - } - //case BERSERKING: - default: { - // Unknown skill we should like print something to a log/debug here - r_value = 0; - break; - } - } - if (r_value >= 253) { - r_value = 252; - } - return r_value; -} - diff --git a/zone/merc.cpp b/zone/merc.cpp index af34e3c2e..203bb33a4 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -15,7 +15,7 @@ #include "zone.h" #include "string_ids.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/rulesys.h" extern volatile bool is_zone_loaded; @@ -351,7 +351,7 @@ void Merc::AddItemBonuses(const EQ::ItemData *item, StatBonuses* newbon) { } //FatherNitwit: New style haste, shields, and regens - if(newbon->haste < (int16)item->Haste) { + if(newbon->haste < item->Haste) { newbon->haste = item->Haste; } if(item->Regen > 0) @@ -911,9 +911,6 @@ int64 Merc::CalcMaxMana() current_mana = curMana_cap; } -#if EQDEBUG >= 11 - LogDebug("Merc::CalcMaxMana() called for [{}] - returning [{}]", GetName(), max_mana); -#endif return max_mana; } @@ -1168,11 +1165,11 @@ void Merc::CalcRestState() { } } - RestRegenHP = 6 * (GetMaxHP() / zone->newzone_data.FastRegenHP); + RestRegenHP = 6 * (GetMaxHP() / zone->newzone_data.fast_regen_hp); - RestRegenMana = 6 * (GetMaxMana() / zone->newzone_data.FastRegenMana); + RestRegenMana = 6 * (GetMaxMana() / zone->newzone_data.fast_regen_mana); - RestRegenEndurance = 6 * (GetMaxEndurance() / zone->newzone_data.FastRegenEndurance); + RestRegenEndurance = 6 * (GetMaxEndurance() / zone->newzone_data.fast_regen_endurance); } bool Merc::HasSkill(EQ::skills::SkillType skill_id) const { @@ -1269,13 +1266,11 @@ bool Merc::Process() if(tic_timer.Check()) { //6 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting - if(!IsMoving() && !IsEngaged()) + if (!IsEngaged()) { SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0); - if(IsSitting()) { - if(!rest_timer.Enabled()) { - rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } + if (!rest_timer.Enabled()) { + rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); } } @@ -1688,7 +1683,7 @@ void Merc::AI_Process() { if (AI_movement_timer->Check()) { if(!IsRooted()) { - LogAI("Pursuing [{}] while engaged", GetTarget()->GetCleanName()); + LogAIDetail("Pursuing [{}] while engaged", GetTarget()->GetCleanName()); RunTo(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ()); return; } @@ -1807,7 +1802,7 @@ bool Merc::AI_EngagedCastCheck() { { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - LogAI("Merc Engaged autocast check triggered"); + LogAIDetail("Merc Engaged autocast check triggered"); int8 mercClass = GetClass(); @@ -1862,7 +1857,7 @@ bool Merc::AI_IdleCastCheck() { if (AIautocastspell_timer->Check(false)) { #if MercAI_DEBUG_Spells >= 25 - LogAI("Merc Non-Engaged autocast check triggered: [{}]", GetCleanName()); + LogAIDetail("Merc Non-Engaged autocast check triggered: [{}]", GetCleanName()); #endif AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. @@ -2138,11 +2133,11 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) { } else { //check for heal over time. if not present, try it first - if(!tar->FindType(SE_HealOverTime)) { + if (!tar->FindType(SE_HealOverTime)) { selectedMercSpell = GetBestMercSpellForHealOverTime(this); //get regular heal - if(selectedMercSpell.spellid == 0) { + if (selectedMercSpell.spellid == 0) { selectedMercSpell = GetBestMercSpellForRegularSingleTargetHeal(this); } } @@ -2616,7 +2611,7 @@ int64 Merc::GetFocusEffect(focusType type, uint16 spell_id, bool from_buff_tic) realTotal = CalcFocusEffect(type, UsedFocusID, spell_id); if (realTotal != 0 && UsedItem) - MessageString(Chat::Spells, BEGINS_TO_GLOW, UsedItem->Name); + MessageString(Chat::FocusEffect, BEGINS_TO_GLOW, UsedItem->Name); } //Check if spell focus effect exists for the client. @@ -2708,53 +2703,6 @@ int64 Merc::GetFocusEffect(focusType type, uint16 spell_id, bool from_buff_tic) return realTotal + realTotal2 + realTotal3; } -int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost) -{ - // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) - { - int16 mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; - // Doesnt generate mana, so best case is a free spell - if(mana_back > cost) - mana_back = cost; - - cost -= mana_back; - } - - // This formula was derived from the following resource: - // http://www.eqsummoners.com/eq1/specialization-library.html - // WildcardX - float PercentManaReduction = 0; - - int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); - - if(focus_redux > 0) - { - PercentManaReduction += zone->random.Real(1, (double)focus_redux); - } - - cost -= (cost * (PercentManaReduction / 100)); - - // Gift of Mana - reduces spell cost to 1 mana - if(focus_redux >= 100) { - uint32 buff_max = GetMaxTotalSlots(); - for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) { - if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS) - continue; - - if(IsEffectInSpell(buffs[buffSlot].spellid, SE_ReduceManaCost)) { - if(CalcFocusEffect(focusManaCost, buffs[buffSlot].spellid, spell_id) == 100) - cost = 1; - } - } - } - - if(cost < 0) - cost = 0; - - return cost; -} - int8 Merc::GetChanceToCastBySpellType(uint32 spellType) { int mercStance = (int)GetStance(); int8 mercClass = GetClass(); @@ -2904,7 +2852,7 @@ std::list Merc::GetMercSpellsBySpellType(Merc* caster, uint32 spellTy std::vector mercSpellList = caster->GetMercSpells(); for (int i = mercSpellList.size() - 1; i >= 0; i--) { - if (mercSpellList[i].spellid <= 0 || mercSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(mercSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; @@ -2941,7 +2889,7 @@ MercSpell Merc::GetFirstMercSpellBySpellType(Merc* caster, uint32 spellType) { std::vector mercSpellList = caster->GetMercSpells(); for (int i = mercSpellList.size() - 1; i >= 0; i--) { - if (mercSpellList[i].spellid <= 0 || mercSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(mercSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; @@ -2979,7 +2927,7 @@ MercSpell Merc::GetMercSpellBySpellID(Merc* caster, uint16 spellid) { std::vector mercSpellList = caster->GetMercSpells(); for (int i = mercSpellList.size() - 1; i >= 0; i--) { - if (mercSpellList[i].spellid <= 0 || mercSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(mercSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; @@ -3009,7 +2957,7 @@ std::list Merc::GetMercSpellsForSpellEffect(Merc* caster, int spellEf std::vector mercSpellList = caster->GetMercSpells(); for (int i = mercSpellList.size() - 1; i >= 0; i--) { - if (mercSpellList[i].spellid <= 0 || mercSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(mercSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; @@ -3039,7 +2987,7 @@ std::list Merc::GetMercSpellsForSpellEffectAndTargetType(Merc* caster std::vector mercSpellList = caster->GetMercSpells(); for (int i = mercSpellList.size() - 1; i >= 0; i--) { - if (mercSpellList[i].spellid <= 0 || mercSpellList[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(mercSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here continue; @@ -4305,33 +4253,27 @@ void Merc::MercMeditate(bool isSitting) { { return; } - if(isSitting) { + if (isSitting) { // If the merc is a caster and has less than 99% mana while its not engaged, he needs to sit to meditate - if(GetManaRatio() < 99.0f) + if (GetManaRatio() < 99.0f) { - if(!IsSitting()) + if(!IsSitting()) { Sit(); + } } else { - if(IsSitting()) + if (IsSitting()) { Stand(); + } } } else { - if(IsSitting()) + if (IsSitting()) { Stand(); - } - - if(IsSitting()) { - if(!rest_timer.Enabled()) { - rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); } } - else { - rest_timer.Disable(); - } } @@ -4371,19 +4313,23 @@ bool Merc::IsStanding() { float Merc::GetMaxMeleeRangeToTarget(Mob* target) { float result = 0; - if(target) { + if (target) { float size_mod = GetSize(); float other_size_mod = target->GetSize(); - if(GetRace() == 49 || GetRace() == 158 || GetRace() == 196) //For races with a fixed size + if (GetRace() == RACE_LAVA_DRAGON_49 || GetRace() == RACE_WURM_158 || GetRace() == RACE_GHOST_DRAGON_196) //For races with a fixed size + { size_mod = 60.0f; - else if (size_mod < 6.0) + } else if (size_mod < 6.0) { size_mod = 8.0f; + } - if(target->GetRace() == 49 || target->GetRace() == 158 || target->GetRace() == 196) //For races with a fixed size + if (target->GetRace() == RACE_LAVA_DRAGON_49 || target->GetRace() == RACE_WURM_158 || target->GetRace() == RACE_GHOST_DRAGON_196) //For races with a fixed size + { other_size_mod = 60.0f; - else if (other_size_mod < 6.0) + } else if (other_size_mod < 6.0) { other_size_mod = 8.0f; + } if (other_size_mod > size_mod) { size_mod = other_size_mod; @@ -4391,12 +4337,13 @@ float Merc::GetMaxMeleeRangeToTarget(Mob* target) { // this could still use some work, but for now it's an improvement.... - if (size_mod > 29) + if (size_mod > 29) { size_mod *= size_mod; - else if (size_mod > 19) + } else if (size_mod > 19) { size_mod *= size_mod * 2; - else + } else { size_mod *= size_mod * 4; + } // prevention of ridiculously sized hit boxes if (size_mod > 10000) @@ -6097,7 +6044,7 @@ void Client::SendMercMerchantResponsePacket(int32 response_type) { MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; mmr->ResponseType = response_type; // send specified response type FastQueuePacket(&outapp); - Log(Logs::Moderate, Logs::Mercenaries, "Sent SendMercMerchantResponsePacket ResponseType: %i, Client: %s.", response_type, GetName()); + Log(Logs::Detail, Logs::Mercenaries, "Sent SendMercMerchantResponsePacket ResponseType: %i, Client: %s.", response_type, GetName()); } } @@ -6106,7 +6053,7 @@ void Client::SendMercenaryUnknownPacket(uint8 type) { auto outapp = new EQApplicationPacket(OP_MercenaryUnknown1, 1); outapp->WriteUInt8(type); FastQueuePacket(&outapp); - Log(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnknownPacket Type: %i, Client: %s.", type, GetName()); + Log(Logs::Detail, Logs::Mercenaries, "Sent SendMercenaryUnknownPacket Type: %i, Client: %s.", type, GetName()); } @@ -6115,7 +6062,7 @@ void Client::SendMercenaryUnsuspendPacket(uint8 type) { auto outapp = new EQApplicationPacket(OP_MercenaryUnsuspendResponse, 1); outapp->WriteUInt8(type); FastQueuePacket(&outapp); - Log(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnsuspendPacket Type: %i, Client: %s.", type, GetName()); + Log(Logs::Detail, Logs::Mercenaries, "Sent SendMercenaryUnsuspendPacket Type: %i, Client: %s.", type, GetName()); } @@ -6125,7 +6072,7 @@ void Client::SendMercSuspendResponsePacket(uint32 suspended_time) { SuspendMercenaryResponse_Struct* smr = (SuspendMercenaryResponse_Struct*)outapp->pBuffer; smr->SuspendTime = suspended_time; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp FastQueuePacket(&outapp); - Log(Logs::Moderate, Logs::Mercenaries, "Sent SendMercSuspendResponsePacket Time: %i, Client: %s.", suspended_time, GetName()); + Log(Logs::Detail, Logs::Mercenaries, "Sent SendMercSuspendResponsePacket Time: %i, Client: %s.", suspended_time, GetName()); } @@ -6140,7 +6087,7 @@ void Client::SendMercTimerPacket(int32 entity_id, int32 merc_state, int32 suspen mss->UpdateInterval = update_interval; // Seen 900000 - 15 minutes in ms mss->MercUnk01 = unk01; // Seen 180000 - 3 minutes in ms - Used for the unsuspend button refresh timer FastQueuePacket(&outapp); - Log(Logs::Moderate, Logs::Mercenaries, "Sent SendMercTimerPacket EndID: %i, State: %i, SuspendTime: %i, Interval: %i, Unk1: %i, Client: %s.", entity_id, merc_state, suspended_time, update_interval, unk01, GetName()); + Log(Logs::Detail, Logs::Mercenaries, "Sent SendMercTimerPacket EndID: %i, State: %i, SuspendTime: %i, Interval: %i, Unk1: %i, Client: %s.", entity_id, merc_state, suspended_time, update_interval, unk01, GetName()); } @@ -6151,7 +6098,7 @@ void Client::SendMercAssignPacket(uint32 entityID, uint32 unk01, uint32 unk02) { mas->MercUnk01 = unk01; mas->MercUnk02 = unk02; FastQueuePacket(&outapp); - Log(Logs::Moderate, Logs::Mercenaries, "Sent SendMercAssignPacket EndID: %i, Unk1: %i, Unk2: %i, Client: %s.", entityID, unk01, unk02, GetName()); + Log(Logs::Detail, Logs::Mercenaries, "Sent SendMercAssignPacket EndID: %i, Unk1: %i, Unk2: %i, Client: %s.", entityID, unk01, unk02, GetName()); } void NPC::LoadMercTypes() { diff --git a/zone/merc.h b/zone/merc.h index 8dd7bd98c..b05fa32d3 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -83,7 +83,6 @@ public: Corpse* GetGroupMemberCorpse(); // Merc Spell Casting Methods - virtual int32 GetActSpellCost(uint16 spell_id, int32 cost); int8 GetChanceToCastBySpellType(uint32 spellType); void SetSpellRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay); void SetDisciplineRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay); diff --git a/zone/mob.cpp b/zone/mob.cpp index dc0032256..05a84fb99 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -17,7 +17,7 @@ */ #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/misc_functions.h" #include "data_bucket.h" @@ -33,9 +33,7 @@ #include #include -#ifdef BOTS #include "bot.h" -#endif extern EntityList entity_list; @@ -97,6 +95,8 @@ Mob::Mob( uint8 in_feettexture, uint16 in_usemodel, bool in_always_aggro, + int32 in_heroic_strikethrough, + bool in_keeps_sold_items, int64 in_hp_regen_per_second ) : attack_timer(2000), @@ -251,38 +251,40 @@ Mob::Mob( aa_title = 0xFF; } - AC = in_ac; - ATK = in_atk; - STR = in_str; - STA = in_sta; - DEX = in_dex; - AGI = in_agi; - INT = in_int; - WIS = in_wis; - CHA = in_cha; - MR = CR = FR = DR = PR = Corrup = PhR = 0; - ExtraHaste = 0; - bEnraged = false; - current_mana = 0; - max_mana = 0; - hp_regen = in_hp_regen; - hp_regen_per_second = in_hp_regen_per_second; - mana_regen = in_mana_regen; - ooc_regen = RuleI(NPC, OOCRegen); //default Out of Combat Regen - maxlevel = in_maxlevel; - scalerate = in_scalerate; - invisible = 0; - invisible_undead = 0; - invisible_animals = 0; - sneaking = false; - hidden = false; - improved_hidden = false; - invulnerable = false; - IsFullHP = (current_hp == max_hp); - qglobal = 0; - spawned = false; - rare_spawn = false; - always_aggro = in_always_aggro; + AC = in_ac; + ATK = in_atk; + STR = in_str; + STA = in_sta; + DEX = in_dex; + AGI = in_agi; + INT = in_int; + WIS = in_wis; + CHA = in_cha; + MR = CR = FR = DR = PR = Corrup = PhR = 0; + ExtraHaste = 0; + bEnraged = false; + current_mana = 0; + max_mana = 0; + hp_regen = in_hp_regen; + hp_regen_per_second = in_hp_regen_per_second; + mana_regen = in_mana_regen; + ooc_regen = RuleI(NPC, OOCRegen); //default Out of Combat Regen + maxlevel = in_maxlevel; + scalerate = in_scalerate; + invisible = 0; + invisible_undead = 0; + invisible_animals = 0; + sneaking = false; + hidden = false; + improved_hidden = false; + invulnerable = false; + IsFullHP = (current_hp == max_hp); + qglobal = 0; + spawned = false; + rare_spawn = false; + always_aggro = in_always_aggro; + heroic_strikethrough = in_heroic_strikethrough; + keeps_sold_items = in_keeps_sold_items; InitializeBuffSlots(); @@ -505,13 +507,13 @@ Mob::Mob( queue_wearchange_slot = -1; -#ifdef BOTS m_manual_follow = false; -#endif mob_close_scan_timer.Trigger(); SetCanOpenDoors(true); + + is_boat = IsBoat(); } Mob::~Mob() @@ -558,9 +560,7 @@ Mob::~Mob() close_mobs.clear(); -#ifdef BOTS LeaveHealRotationTargetPool(); -#endif } uint32 Mob::GetAppearanceValue(EmuAppearance iAppearance) { @@ -762,11 +762,7 @@ int Mob::_GetWalkSpeed() const { return(0); //runspeed cap. -#ifdef BOTS if (IsClient() || IsBot()) -#else - if(IsClient()) -#endif { if(speed_mod > runspeedcap) speed_mod = runspeedcap; @@ -825,11 +821,7 @@ int Mob::_GetRunSpeed() const { if (!has_horse && movemod != 0) { -#ifdef BOTS if (IsClient() || IsBot()) -#else - if (IsClient()) -#endif { speed_mod += (speed_mod * movemod / 100); } else { @@ -858,11 +850,7 @@ int Mob::_GetRunSpeed() const { return(0); } //runspeed cap. -#ifdef BOTS if (IsClient() || IsBot()) -#else - if(IsClient()) -#endif { if(speed_mod > runspeedcap) speed_mod = runspeedcap; @@ -981,8 +969,8 @@ int64 Mob::GetItemHPBonuses() { return item_hp; } -int32 Mob::GetSpellHPBonuses() { - int32 spell_hp = 0; +int64 Mob::GetSpellHPBonuses() { + int64 spell_hp = 0; spell_hp = spellbonuses.HP; spell_hp += spell_hp * spellbonuses.MaxHPChange / 10000; return spell_hp; @@ -1074,164 +1062,127 @@ uint8 Mob::GetArchetype() const { } } +void Mob::SetSpawnLastNameByClass(NewSpawn_Struct* ns) +{ + switch (ns->spawn.class_) { + case TRIBUTE_MASTER: + strcpy(ns->spawn.lastName, "Tribute Master"); + break; + case GUILD_TRIBUTE_MASTER: + strcpy(ns->spawn.lastName, "Guild Tribute Master"); + break; + case GUILD_BANKER: + strcpy(ns->spawn.lastName, "Guild Banker"); + break; + case ADVENTURE_RECRUITER: + strcpy(ns->spawn.lastName, "Adventure Recruiter"); + break; + case ADVENTURE_MERCHANT: + strcpy(ns->spawn.lastName, "Adventure Merchant"); + break; + case BANKER: + strcpy(ns->spawn.lastName, "Banker"); + break; + case WARRIORGM: + strcpy(ns->spawn.lastName, "Warrior Guildmaster"); + break; + case CLERICGM: + strcpy(ns->spawn.lastName, "Cleric Guildmaster"); + break; + case PALADINGM: + strcpy(ns->spawn.lastName, "Paladin Guildmaster"); + break; + case RANGERGM: + strcpy(ns->spawn.lastName, "Ranger Guildmaster"); + break; + case SHADOWKNIGHTGM: + strcpy(ns->spawn.lastName, "Shadow Knight Guildmaster"); + break; + case DRUIDGM: + strcpy(ns->spawn.lastName, "Druid Guildmaster"); + break; + case MONKGM: + strcpy(ns->spawn.lastName, "Monk Guildmaster"); + break; + case BARDGM: + strcpy(ns->spawn.lastName, "Bard Guildmaster"); + break; + case ROGUEGM: + strcpy(ns->spawn.lastName, "Rogue Guildmaster"); + break; + case SHAMANGM: + strcpy(ns->spawn.lastName, "Shaman Guildmaster"); + break; + case NECROMANCERGM: + strcpy(ns->spawn.lastName, "Necromancer Guildmaster"); + break; + case WIZARDGM: + strcpy(ns->spawn.lastName, "Wizard Guildmaster"); + break; + case MAGICIANGM: + strcpy(ns->spawn.lastName, "Magician Guildmaster"); + break; + case ENCHANTERGM: + strcpy(ns->spawn.lastName, "Enchanter Guildmaster"); + break; + case BEASTLORDGM: + strcpy(ns->spawn.lastName, "Beastlord Guildmaster"); + break; + case BERSERKERGM: + strcpy(ns->spawn.lastName, "Berserker Guildmaster"); + break; + case MERCENARY_MASTER: + strcpy(ns->spawn.lastName, "Mercenary Liaison"); + break; + default: + strcpy(ns->spawn.lastName, ns->spawn.lastName); + break; + } +} + void Mob::CreateSpawnPacket(EQApplicationPacket *app, Mob *ForWho) { app->SetOpcode(OP_NewSpawn); - app->size = sizeof(NewSpawn_Struct); + app->size = sizeof(NewSpawn_Struct); + safe_delete_array(app->pBuffer); app->pBuffer = new uchar[app->size]; memset(app->pBuffer, 0, app->size); - NewSpawn_Struct *ns = (NewSpawn_Struct *) app->pBuffer; + auto ns = (NewSpawn_Struct *) app->pBuffer; FillSpawnStruct(ns, ForWho); - if (RuleB(NPC, UseClassAsLastName) && strlen(ns->spawn.lastName) == 0) { - switch (ns->spawn.class_) { - case TRIBUTE_MASTER: - strcpy(ns->spawn.lastName, "Tribute Master"); - break; - case ADVENTURERECRUITER: - strcpy(ns->spawn.lastName, "Adventure Recruiter"); - break; - case BANKER: - strcpy(ns->spawn.lastName, "Banker"); - break; - case ADVENTUREMERCHANT: - strcpy(ns->spawn.lastName, "Adventure Merchant"); - break; - case WARRIORGM: - strcpy(ns->spawn.lastName, "GM Warrior"); - break; - case PALADINGM: - strcpy(ns->spawn.lastName, "GM Paladin"); - break; - case RANGERGM: - strcpy(ns->spawn.lastName, "GM Ranger"); - break; - case SHADOWKNIGHTGM: - strcpy(ns->spawn.lastName, "GM Shadowknight"); - break; - case DRUIDGM: - strcpy(ns->spawn.lastName, "GM Druid"); - break; - case BARDGM: - strcpy(ns->spawn.lastName, "GM Bard"); - break; - case ROGUEGM: - strcpy(ns->spawn.lastName, "GM Rogue"); - break; - case SHAMANGM: - strcpy(ns->spawn.lastName, "GM Shaman"); - break; - case NECROMANCERGM: - strcpy(ns->spawn.lastName, "GM Necromancer"); - break; - case WIZARDGM: - strcpy(ns->spawn.lastName, "GM Wizard"); - break; - case MAGICIANGM: - strcpy(ns->spawn.lastName, "GM Magician"); - break; - case ENCHANTERGM: - strcpy(ns->spawn.lastName, "GM Enchanter"); - break; - case BEASTLORDGM: - strcpy(ns->spawn.lastName, "GM Beastlord"); - break; - case BERSERKERGM: - strcpy(ns->spawn.lastName, "GM Berserker"); - break; - case MERCERNARY_MASTER: - strcpy(ns->spawn.lastName, "Mercenary Recruiter"); - break; - default: - break; - } + if ( + !RuleB(NPC, DisableLastNames) && + RuleB(NPC, UseClassAsLastName) && + !strlen(ns->spawn.lastName) + ) { + SetSpawnLastNameByClass(ns); } } void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) { app->SetOpcode(OP_NewSpawn); app->size = sizeof(NewSpawn_Struct); - + safe_delete_array(app->pBuffer); app->pBuffer = new uchar[sizeof(NewSpawn_Struct)]; // Copy ns directly into packet memcpy(app->pBuffer, ns, sizeof(NewSpawn_Struct)); // Custom packet data - NewSpawn_Struct* ns2 = (NewSpawn_Struct*)app->pBuffer; + auto ns2 = (NewSpawn_Struct*) app->pBuffer; strcpy(ns2->spawn.name, ns->spawn.name); // Set default Last Names for certain Classes if not defined - if (RuleB(NPC, UseClassAsLastName) && strlen(ns->spawn.lastName) == 0) - { - switch (ns->spawn.class_) - { - case TRIBUTE_MASTER: - strcpy(ns2->spawn.lastName, "Tribute Master"); - break; - case ADVENTURERECRUITER: - strcpy(ns2->spawn.lastName, "Adventure Recruiter"); - break; - case BANKER: - strcpy(ns2->spawn.lastName, "Banker"); - break; - case ADVENTUREMERCHANT: - strcpy(ns2->spawn.lastName, "Adventure Merchant"); - break; - case WARRIORGM: - strcpy(ns2->spawn.lastName, "GM Warrior"); - break; - case PALADINGM: - strcpy(ns2->spawn.lastName, "GM Paladin"); - break; - case RANGERGM: - strcpy(ns2->spawn.lastName, "GM Ranger"); - break; - case SHADOWKNIGHTGM: - strcpy(ns2->spawn.lastName, "GM Shadowknight"); - break; - case DRUIDGM: - strcpy(ns2->spawn.lastName, "GM Druid"); - break; - case BARDGM: - strcpy(ns2->spawn.lastName, "GM Bard"); - break; - case ROGUEGM: - strcpy(ns2->spawn.lastName, "GM Rogue"); - break; - case SHAMANGM: - strcpy(ns2->spawn.lastName, "GM Shaman"); - break; - case NECROMANCERGM: - strcpy(ns2->spawn.lastName, "GM Necromancer"); - break; - case WIZARDGM: - strcpy(ns2->spawn.lastName, "GM Wizard"); - break; - case MAGICIANGM: - strcpy(ns2->spawn.lastName, "GM Magician"); - break; - case ENCHANTERGM: - strcpy(ns2->spawn.lastName, "GM Enchanter"); - break; - case BEASTLORDGM: - strcpy(ns2->spawn.lastName, "GM Beastlord"); - break; - case BERSERKERGM: - strcpy(ns2->spawn.lastName, "GM Berserker"); - break; - case MERCERNARY_MASTER: - strcpy(ns2->spawn.lastName, "Mercenary liaison"); - break; - default: - strcpy(ns2->spawn.lastName, ns->spawn.lastName); - break; - } - } - else - { + if ( + !RuleB(NPC, DisableLastNames) && + RuleB(NPC, UseClassAsLastName) && + !strlen(ns->spawn.lastName) + ) { + SetSpawnLastNameByClass(ns2); + } else { strcpy(ns2->spawn.lastName, ns->spawn.lastName); } + memset(&app->pBuffer[sizeof(Spawn_Struct)-7], 0xFF, 7); } @@ -1403,6 +1354,7 @@ void Mob::CreateDespawnPacket(EQApplicationPacket* app, bool Decay) { app->SetOpcode(OP_DeleteSpawn); app->size = sizeof(DeleteSpawn_Struct); + safe_delete_array(app->pBuffer); app->pBuffer = new uchar[app->size]; memset(app->pBuffer, 0, app->size); DeleteSpawn_Struct* ds = (DeleteSpawn_Struct*)app->pBuffer; @@ -1416,6 +1368,7 @@ void Mob::CreateHPPacket(EQApplicationPacket* app) IsFullHP=(current_hp>=max_hp); app->SetOpcode(OP_MobHealth); app->size = sizeof(SpawnHPUpdate_Struct2); + safe_delete_array(app->pBuffer); app->pBuffer = new uchar[app->size]; memset(app->pBuffer, 0, sizeof(SpawnHPUpdate_Struct2)); SpawnHPUpdate_Struct2* ds = (SpawnHPUpdate_Struct2*)app->pBuffer; @@ -1454,7 +1407,7 @@ void Mob::SendHPUpdate(bool force_update_all) if (current_hp != last_hp || force_update_all) { LogHPUpdate( - "[SendHPUpdate] Update HP of self [{}] current_hp [{}] max_hp [{}] last_hp [{}]", + "Update HP of self [{}] current_hp [{}] max_hp [{}] last_hp [{}]", GetCleanName(), current_hp, max_hp, @@ -1482,14 +1435,14 @@ void Mob::SendHPUpdate(bool force_update_all) auto current_hp_percent = GetIntHPRatio(); LogHPUpdateDetail( - "[SendHPUpdate] Client [{}] HP is [{}] last [{}]", + "Client [{}] HP is [{}] last [{}]", GetCleanName(), current_hp_percent, last_hp_percent ); if (current_hp_percent == last_hp_percent && !force_update_all) { - LogHPUpdateDetail("[SendHPUpdate] Same HP for mob [{}] skipping update", GetCleanName()); + LogHPUpdateDetail("Same HP for mob [{}] skipping update", GetCleanName()); ResetHPUpdateTimer(); return; } @@ -1499,7 +1452,7 @@ void Mob::SendHPUpdate(bool force_update_all) CastToClient()->SendHPUpdateMarquee(); } - LogHPUpdate("[SendHPUpdate] HP Changed for mob [{}] send update", GetCleanName()); + LogHPUpdate("HP Changed for mob [{}] send update", GetCleanName()); last_hp_percent = current_hp_percent; } @@ -1549,8 +1502,7 @@ void Mob::SendHPUpdate(bool force_update_all) } } -#ifdef BOTS - if (GetOwner() && GetOwner()->IsBot() && GetOwner()->CastToBot()->GetBotOwner() && GetOwner()->CastToBot()->GetBotOwner()->IsClient()) { + if (RuleB(Bots, Enabled) && GetOwner() && GetOwner()->IsBot() && GetOwner()->CastToBot()->GetBotOwner() && GetOwner()->CastToBot()->GetBotOwner()->IsClient()) { auto bot_owner = GetOwner()->CastToBot()->GetBotOwner()->CastToClient(); if (bot_owner) { bot_owner->QueuePacket(&hp_packet, false); @@ -1566,7 +1518,6 @@ void Mob::SendHPUpdate(bool force_update_all) } } } -#endif if (GetPet() && GetPet()->IsClient()) { GetPet()->CastToClient()->QueuePacket(&hp_packet, false); @@ -1671,11 +1622,7 @@ void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) { spu->delta_y = FloatToEQ13(m_Delta.y); spu->delta_z = FloatToEQ13(m_Delta.z); spu->heading = FloatToEQ12(m_Position.w); -#ifdef BOTS if (IsClient() || IsBot()) -#else - if (IsClient()) -#endif spu->animation = animation; else spu->animation = pRunAnimSpeed;//animation; @@ -1720,104 +1667,9 @@ void Mob::ShowStats(Client* client) target->GetCharmedMinDamage() != 0 ); - // Spawn Data - if ( - target->GetGrid() || - target->GetSpawnGroupId() || - target->GetSpawnPointID() - ) { - client->Message( - Chat::White, - fmt::format( - "Spawn | Group: {} Point: {} Grid: {}", - target->GetSpawnGroupId(), - target->GetSpawnPointID(), - target->GetGrid() - ).c_str() - ); - } - - client->Message( - Chat::White, - fmt::format( - "Spawn | Raid: {} Rare: {}", - target->IsRaidTarget() ? "Yes" : "No", - target->IsRareSpawn() ? "Yes" : "No", - target->GetSkipGlobalLoot() ? "Yes" : "No" - ).c_str() - ); - - client->Message( - Chat::White, - fmt::format( - "Spawn | Skip Global Loot: {} Ignore Despawn: {}", - target->GetSkipGlobalLoot() ? "Yes" : "No", - target->GetIgnoreDespawn() ? "Yes" : "No" - ).c_str() - ); - - client->Message( - Chat::White, - fmt::format( - "Spawn | Findable: {} Trackable: {} Underwater: {}", - target->IsFindable() ? "Yes" : "No", - target->IsTrackable() ? "Yes" : "No", - target->IsUnderwaterOnly() ? "Yes" : "No" - ).c_str() - ); - - client->Message( - Chat::White, - fmt::format( - "Spawn | Stuck Behavior: {} Fly Mode: {}", - target->GetStuckBehavior(), - static_cast(target->GetFlyMode()) - ).c_str() - ); - - client->Message( - Chat::White, - fmt::format( - "Spawn | Aggro NPCs: {} Always Aggro: {}", - target->GetNPCAggro() ? "Yes" : "No", - target->GetAlwaysAggro() ? "Yes" : "No" - ).c_str() - ); - - // NPC - client->Message( - Chat::White, - fmt::format( - "NPC | ID: {} Entity ID: {} Name: {}{} Level: {}", - target->GetNPCTypeID(), - target->GetID(), - target_name, - ( - !target_last_name.empty() ? - fmt::format(" ({})", target_last_name) : - "" - ), - target->GetLevel() - ).c_str() - ); - - // Race / Class / Gender - client->Message( - Chat::White, - fmt::format( - "Race: {} ({}) Class: {} ({}) Gender: {} ({})", - GetRaceIDName(target->GetRace()), - target->GetRace(), - GetClassIDName(target->GetClass()), - target->GetClass(), - GetGenderName(target->GetGender()), - target->GetGender() - ).c_str() - ); - // Faction if (target->GetNPCFactionID()) { - auto faction_id = target->GetNPCFactionID(); + auto faction_id = target->GetPrimaryFaction(); auto faction_name = content_db.GetFactionName(faction_id); client->Message( Chat::White, @@ -2348,27 +2200,116 @@ void Mob::ShowStats(Client* client) ).c_str() ); } + + // Spawn Data + if ( + target->GetGrid() || + target->GetSpawnGroupId() || + target->GetSpawnPointID() + ) { + client->Message( + Chat::White, + fmt::format( + "Spawn | Group: {} Point: {} Grid: {}", + target->GetSpawnGroupId(), + target->GetSpawnPointID(), + target->GetGrid() + ).c_str() + ); + } + + client->Message( + Chat::White, + fmt::format( + "Spawn | Raid: {} Rare: {}", + target->IsRaidTarget() ? "Yes" : "No", + target->IsRareSpawn() ? "Yes" : "No", + target->GetSkipGlobalLoot() ? "Yes" : "No" + ).c_str() + ); + + client->Message( + Chat::White, + fmt::format( + "Spawn | Skip Global Loot: {} Ignore Despawn: {}", + target->GetSkipGlobalLoot() ? "Yes" : "No", + target->GetIgnoreDespawn() ? "Yes" : "No" + ).c_str() + ); + + client->Message( + Chat::White, + fmt::format( + "Spawn | Findable: {} Trackable: {} Underwater: {}", + target->IsFindable() ? "Yes" : "No", + target->IsTrackable() ? "Yes" : "No", + target->IsUnderwaterOnly() ? "Yes" : "No" + ).c_str() + ); + + client->Message( + Chat::White, + fmt::format( + "Spawn | Stuck Behavior: {} Fly Mode: {}", + target->GetStuckBehavior(), + static_cast(target->GetFlyMode()) + ).c_str() + ); + + client->Message( + Chat::White, + fmt::format( + "Spawn | Aggro NPCs: {} Always Aggro: {}", + target->GetNPCAggro() ? "Yes" : "No", + target->GetAlwaysAggro() ? "Yes" : "No" + ).c_str() + ); + + // Race / Class / Gender + client->Message( + Chat::White, + fmt::format( + "Race: {} ({}) Class: {} ({}) Gender: {} ({})", + GetRaceIDName(target->GetRace()), + target->GetRace(), + GetClassIDName(target->GetClass()), + target->GetClass(), + GetGenderName(target->GetGender()), + target->GetGender() + ).c_str() + ); + + // NPC + client->Message( + Chat::White, + fmt::format( + "NPC | ID: {} Entity ID: {} Name: {}{} Level: {}", + target->GetNPCTypeID(), + target->GetID(), + target_name, + ( + !target_last_name.empty() ? + fmt::format(" ({})", target_last_name) : + "" + ), + target->GetLevel() + ).c_str() + ); } } -void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) +void Mob::DoAnim(const int animation_id, int animation_speed, bool ackreq, eqFilterType filter) { if (!attack_anim_timer.Check()) { return; } auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); - auto *anim = (Animation_Struct *) outapp->pBuffer; - anim->spawnid = GetID(); + auto *a = (Animation_Struct *) outapp->pBuffer; - if (type == 0) { - anim->action = animnum; - anim->speed = 10; - } - else { - anim->action = animnum; - anim->speed = type; - } + a->spawnid = GetID(); + a->action = animation_id; + a->speed = animation_speed ? animation_speed : 10; entity_list.QueueCloseClients( this, /* Sender */ @@ -2854,6 +2795,16 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) return false; } +bool Mob::IsPlayerClass(uint16 in_class) { + if ( + in_class >= WARRIOR && + in_class <= BERSERKER + ) { + return true; + } + + return false; +} bool Mob::IsPlayerRace(uint16 in_race) { @@ -2900,6 +2851,7 @@ uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) { in_race == RACE_FAYGUARD_112 || in_race == RACE_ERUDITE_GHOST_118 || in_race == RACE_IKSAR_CITIZEN_139 || + in_race == RACE_SHADE_224 || in_race == RACE_TROLL_CREW_MEMBER_331 || in_race == RACE_PIRATE_DECKHAND_332 || in_race == RACE_GNOME_PIRATE_338 || @@ -2912,7 +2864,12 @@ uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) { in_race == RACE_WARLOCK_OF_HATE_352 || in_race == RACE_UNDEAD_VAMPIRE_359 || in_race == RACE_VAMPIRE_360 || + in_race == RACE_SAND_ELF_364 || + in_race == RACE_TAELOSIAN_NATIVE_385 || + in_race == RACE_TAELOSIAN_EVOKER_386 || + in_race == RACE_DRACHNID_461 || in_race == RACE_ZOMBIE_471 || + in_race == RACE_ELDDAR_489 || in_race == RACE_VAMPIRE_497 || in_race == RACE_KERRAN_562 || in_race == RACE_BROWNIE_568 || @@ -2939,11 +2896,22 @@ uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) { in_race == RACE_SPECTRAL_IKSAR_147 || in_race == RACE_INVISIBLE_MAN_127 || in_race == RACE_VAMPYRE_208 || + in_race == RACE_RECUSO_237 || in_race == RACE_BROKEN_SKULL_PIRATE_333 || + in_race == RACE_INVISIBLE_MAN_OF_ZOMM_600 || + in_race == RACE_OGRE_NPC_MALE_624 || + in_race == RACE_BEEFEATER_667 || in_race == RACE_ERUDITE_678 ) { // Male only races return 0; - } else if (in_race == RACE_FAIRY_25 || in_race == RACE_PIXIE_56) { // Female only races + } else if ( + in_race == RACE_FAIRY_25 || + in_race == RACE_PIXIE_56 || + in_race == RACE_BANSHEE_487 || + in_race == RACE_BANSHEE_488 || + in_race == RACE_AYONAE_RO_498 || + in_race == RACE_SULLON_ZEK_499 + ) { // Female only races return 1; } else { // Neutral default for NPC Races return 2; @@ -3155,7 +3123,7 @@ void Mob::SendTargetable(bool on, Client *specific_target) { safe_delete(outapp); } -void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global) { +void Mob::CameraEffect(uint32 duration, float intensity, Client *c, bool global) { if(global == true) @@ -3172,7 +3140,7 @@ void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global auto outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer; cs->duration = duration; // Duration in milliseconds - cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10. + cs->intensity = intensity; if(c) c->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); @@ -3269,10 +3237,6 @@ const int64& Mob::SetMana(int64 amount) CalcMaxMana(); int64 mmana = GetMaxMana(); current_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); -/* - if(IsClient()) - LogFile->write(EQEMuLog::Debug, "Setting mana for %s to %d (%4.1f%%)", GetName(), amount, GetManaRatio()); -*/ return current_mana; } @@ -3752,7 +3716,7 @@ bool Mob::HateSummon() { void Mob::FaceTarget(Mob* mob_to_face /*= 0*/) { - if (IsBoat()) { + if (GetIsBoat()) { return; } @@ -3870,6 +3834,9 @@ void Mob::Say(const char *format, ...) if (RuleB(Chat, QuestDialogueUsesDialogueWindow)) { for (auto &e : entity_list.GetCloseMobList(talker, (distance * distance))) { Mob *mob = e.second; + if (!mob) { + continue; + } if (!mob->IsClient()) { continue; @@ -4064,37 +4031,6 @@ void Mob::SetNextIncHPEvent( int inchpevent ) nextinchpevent = inchpevent; } -int16 Mob::GetResist(uint8 type) const -{ - if (IsNPC()) - { - if (type == 1) - return MR + spellbonuses.MR + itembonuses.MR; - else if (type == 2) - return FR + spellbonuses.FR + itembonuses.FR; - else if (type == 3) - return CR + spellbonuses.CR + itembonuses.CR; - else if (type == 4) - return PR + spellbonuses.PR + itembonuses.PR; - else if (type == 5) - return DR + spellbonuses.DR + itembonuses.DR; - } - else if (IsClient()) - { - if (type == 1) - return CastToClient()->GetMR(); - else if (type == 2) - return CastToClient()->GetFR(); - else if (type == 3) - return CastToClient()->GetCR(); - else if (type == 4) - return CastToClient()->GetPR(); - else if (type == 5) - return CastToClient()->GetDR(); - } - return 25; -} - uint32 Mob::GetLevelHP(uint8 tlevel) { int multiplier = 0; @@ -4170,7 +4106,7 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, if(!IsValidSpell(spell_id)) { // Check for a valid spell otherwise it will crash through the function if(IsClient()){ Message(0, "Invalid spell proc %u", spell_id); - LogSpells("Player [{}], Weapon Procced invalid spell [{}]", GetName(), spell_id); + LogSpells("Player [{}] Weapon Procced invalid spell [{}]", GetName(), spell_id); } return; } @@ -4198,8 +4134,8 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, bool twinproc = false; int32 twinproc_chance = 0; - if (IsClient()) { - twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id); + if (IsClient() || IsBot()) { + twinproc_chance = GetFocusEffect(focusTwincast, spell_id); } if (twinproc_chance && zone->random.Roll(twinproc_chance)) { @@ -4305,9 +4241,9 @@ void Mob::SetTarget(Mob *mob) DisplayInfo(mob); } -#ifdef BOTS CastToClient()->SetBotPrecombat(false); // Any change in target will nullify this flag (target == mob checked above) -#endif + } else if (IsBot()) { + parse->EventBot(EVENT_TARGET_CHANGE, CastToBot(), mob, "", 0); } if (IsPet() && GetOwner() && GetOwner()->IsClient()) { @@ -4466,31 +4402,82 @@ void Mob::SetDelta(const glm::vec4& delta) { m_Delta = delta; } -void Mob::SetEntityVariable(const char *id, const char *m_var) +bool Mob::ClearEntityVariables() { - std::string n_m_var = m_var; - m_EntityVariables[id] = n_m_var; -} - -const char *Mob::GetEntityVariable(const char *id) -{ - auto iter = m_EntityVariables.find(id); - if (iter != m_EntityVariables.end()) { - return iter->second.c_str(); + if (m_EntityVariables.empty()) { + return false; } - return nullptr; + + m_EntityVariables.clear(); + return true; } -bool Mob::EntityVariableExists(const char *id) +bool Mob::DeleteEntityVariable(std::string variable_name) { - auto iter = m_EntityVariables.find(id); - if(iter != m_EntityVariables.end()) - { + if (m_EntityVariables.empty() || variable_name.empty()) { + return false; + } + + auto v = m_EntityVariables.find(variable_name); + if (v == m_EntityVariables.end()) { + return false; + } + + m_EntityVariables.erase(v); + return true; +} + +std::string Mob::GetEntityVariable(std::string variable_name) +{ + if (m_EntityVariables.empty() || variable_name.empty()) { + return std::string(); + } + + const auto& v = m_EntityVariables.find(variable_name); + if (v != m_EntityVariables.end()) { + return v->second; + } + + return std::string(); +} + +std::vector Mob::GetEntityVariables() +{ + std::vector l; + if (m_EntityVariables.empty()) { + return l; + } + + for (const auto& v : m_EntityVariables) { + l.push_back(v.first); + } + + return l; +} + +bool Mob::EntityVariableExists(std::string variable_name) +{ + if (m_EntityVariables.empty() || variable_name.empty()) { + return false; + } + + const auto& v = m_EntityVariables.find(variable_name); + if (v != m_EntityVariables.end()) { return true; } + return false; } +void Mob::SetEntityVariable(std::string variable_name, std::string variable_value) +{ + if (variable_name.empty()) { + return; + } + + m_EntityVariables[variable_name] = variable_value; +} + void Mob::SetFlyMode(GravityBehavior flymode) { flymode = flymode; @@ -4539,9 +4526,9 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) /*The effects SE_SpellTrigger (SPA 340) and SE_Chance_Best_in_Spell_Grp (SPA 469) work as follows, you typically will have 2-3 different spells each with their own chance to be triggered with all chances equaling up to 100 pct, with only 1 spell out of the group being ultimately cast. (ie Effect1 trigger spellA with 30% chance, Effect2 triggers spellB with 20% chance, Effect3 triggers spellC with 50% chance). - The following function ensures a stastically accurate chance for each spell to be cast based on their chance values. These effects are also used in spells where there + The following function ensures a statistically accurate chance for each spell to be cast based on their chance values. These effects are also used in spells where there is only 1 effect using the trigger effect. In those situations we simply roll a chance for that spell to be cast once. - Note: Both SPA 340 and 469 can be in same spell and both cummulative add up to 100 pct chances. SPA469 only difference being the spell cast will + Note: Both SPA 340 and 469 can be in same spell and both cumulative add up to 100 pct chances. SPA469 only difference being the spell cast will be "best in spell group", instead of a defined spell_id.*/ int chance_array[EFFECT_COUNT] = {}; @@ -4558,15 +4545,13 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) if (total_chance == 100) { int current_chance = 0; - int cummulative_chance = 0; for (int i = 0; i < EFFECT_COUNT; i++){ - //Find spells with SPA 340 and add the cummulative percent chances to the roll array + //Find spells with SPA 340 and add the cumulative percent chances to the roll array if ((spells[spell_id].effect_id[i] == SE_SpellTrigger) || (spells[spell_id].effect_id[i] == SE_Chance_Best_in_Spell_Grp)){ - - cummulative_chance = current_chance + spells[spell_id].base_value[i]; - chance_array[i] = cummulative_chance; - current_chance = cummulative_chance; + const int cumulative_chance = current_chance + spells[spell_id].base_value[i]; + chance_array[i] = cumulative_chance; + current_chance = cumulative_chance; } } int random_roll = zone->random.Int(1, 100); @@ -4590,7 +4575,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) SpellFinished(spells[spell_id].limit_value[effect_slot], target, EQ::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].limit_value[effect_slot]].resist_difficulty); return true; } - else if (IsClient() & spells[spell_id].effect_id[effect_slot] == SE_Chance_Best_in_Spell_Grp) { + else if (IsClient() && spells[spell_id].effect_id[effect_slot] == SE_Chance_Best_in_Spell_Grp) { uint32 best_spell_id = CastToClient()->GetHighestScribedSpellinSpellGroup(spells[spell_id].limit_value[effect_slot]); if (IsValidSpell(best_spell_id)) { SpellFinished(best_spell_id, target, EQ::spells::CastingSlot::Item, 0, -1, spells[best_spell_id].resist_difficulty); @@ -4627,18 +4612,21 @@ void Mob::TryTriggerOnCastRequirement() //Twincast Focus effects should stack across different types (Spell, AA - when implemented ect) void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) { - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) { return; + } - if(IsClient()) + if (IsClient() || IsBot()) { - int focus = CastToClient()->GetFocusEffect(focusTwincast, spell_id); + int focus = GetFocusEffect(focusTwincast, spell_id); if (focus > 0) { - if(zone->random.Roll(focus)) + if (zone->random.Roll(focus)) { - Message(Chat::Spells,"You twincast %s!", spells[spell_id].name); + if (IsClient()) { + Message(Chat::Spells,"You twincast %s!", spells[spell_id].name); + } SpellFinished(spell_id, target, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty); } } @@ -4956,9 +4944,9 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell); } -int32 Mob::GetItemStat(uint32 itemid, const char *identifier) +const int Mob::GetItemStat(uint32 item_id, std::string identifier) { - return EQ::InventoryProfile::GetItemStatValue(itemid, identifier); + return EQ::InventoryProfile::GetItemStatValue(item_id, identifier); } std::string Mob::GetGlobal(const char *varname) { @@ -5320,11 +5308,14 @@ bool Mob::TrySpellOnDeath() if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) { if(zone->random.Roll(static_cast(spellbonuses.SpellOnDeath[i + 1]))) { SpellFinished(spellbonuses.SpellOnDeath[i], this, EQ::spells::CastingSlot::Item, 0, -1, spells[spellbonuses.SpellOnDeath[i]].resist_difficulty); - } } } + } + + if (RuleB(Spells, BuffsFadeOnDeath)) { + BuffFadeNonPersistDeath(); + } - BuffFadeNonPersistDeath(); return false; //You should not be able to use this effect and survive (ALWAYS return false), //attempting to place a heal in these effects will still result @@ -5478,7 +5469,7 @@ int16 Mob::GetSkillReuseTime(uint16 skill) return skill_reduction; } -int16 Mob::GetSkillDmgAmt(uint16 skill) +int Mob::GetSkillDmgAmt(uint16 skill) { int skill_dmg = 0; @@ -6236,37 +6227,44 @@ void Mob::ClearSpecialAbilities() { void Mob::ProcessSpecialAbilities(const std::string &str) { ClearSpecialAbilities(); - std::vector sp = SplitString(str, '^'); - for(auto iter = sp.begin(); iter != sp.end(); ++iter) { - std::vector sub_sp = SplitString((*iter), ','); - if(sub_sp.size() >= 2) { - int ability = std::stoi(sub_sp[0]); + const auto& sp = Strings::Split(str, '^'); + for (const auto& s : sp) { + const auto& sub_sp = Strings::Split(s, ','); + if ( + sub_sp.size() >= 2 && + Strings::IsNumber(sub_sp[0]) && + Strings::IsNumber(sub_sp[1]) + ) { + int ability_id = std::stoi(sub_sp[0]); int value = std::stoi(sub_sp[1]); - SetSpecialAbility(ability, value); - switch(ability) { - case SPECATK_QUAD: - if(value > 0) { - SetSpecialAbility(SPECATK_TRIPLE, 1); - } - break; - case DESTRUCTIBLE_OBJECT: - if(value == 0) { - SetDestructibleObject(false); - } else { - SetDestructibleObject(true); - } - break; - default: - break; + SetSpecialAbility(ability_id, value); + + switch (ability_id) { + case SPECATK_QUAD: + if (value > 0) { + SetSpecialAbility(SPECATK_TRIPLE, 1); + } + break; + case DESTRUCTIBLE_OBJECT: + if (value == 0) { + SetDestructibleObject(false); + } else { + SetDestructibleObject(true); + } + break; + default: + break; } - for(size_t i = 2, p = 0; i < sub_sp.size(); ++i, ++p) { - if(p >= MAX_SPECIAL_ATTACK_PARAMS) { + for (size_t i = 2, param_id = 0; i < sub_sp.size(); ++i, ++param_id) { + if (param_id >= MAX_SPECIAL_ATTACK_PARAMS) { break; } - SetSpecialAbilityParam(ability, p, std::stoi(sub_sp[i])); + if (Strings::IsNumber(sub_sp[i])) { + SetSpecialAbilityParam(ability_id, param_id, std::stoi(sub_sp[i])); + } } } } @@ -6685,7 +6683,7 @@ bool Mob::ShieldAbility(uint32 target_id, int shielder_max_distance, int shield_ entity_list.MessageCloseString(this, false, 100, 0, START_SHIELDING, GetCleanName(), shield_target->GetCleanName()); SetShieldTargetID(shield_target->GetID()); - SetShielderMitigation(shield_target_mitigation); + SetShielderMitigation(shielder_mitigation); SetShielderMaxDistance(shielder_max_distance); shield_target->SetShielderID(GetID()); @@ -6763,7 +6761,6 @@ void Mob::SetFeigned(bool in_feigned) { feigned = in_feigned; } -#ifdef BOTS bool Mob::JoinHealRotationTargetPool(std::shared_ptr* heal_rotation) { if (IsHealRotationTarget()) @@ -6827,7 +6824,6 @@ float Mob::HealRotationExtendedHealFrequency() return m_target_of_heal_rotation->ExtendedHealFrequency(this); } -#endif bool Mob::CanOpenDoors() const { @@ -6867,6 +6863,8 @@ std::string Mob::GetBucketKey() { return fmt::format("character-{}", CastToClient()->CharacterID()); } else if (IsNPC()) { return fmt::format("npc-{}", GetNPCTypeID()); + } else if (IsBot()) { + return fmt::format("bot-{}", CastToBot()->GetBotID()); } return std::string(); } @@ -6895,3 +6893,145 @@ std::string Mob::GetMobDescription() GetID() ); } + +uint8 Mob::ConvertItemTypeToSkillID(uint8 item_type) +{ + if (item_type >= EQ::item::ItemTypeCount) { + return EQ::skills::SkillHandtoHand; + } + + std::map convert_item_types_map = { + { EQ::item::ItemType1HSlash, EQ::skills::Skill1HSlashing }, + { EQ::item::ItemType2HSlash, EQ::skills::Skill2HSlashing }, + { EQ::item::ItemType1HPiercing, EQ::skills::Skill1HPiercing }, + { EQ::item::ItemType2HPiercing, EQ::skills::Skill2HPiercing }, + { EQ::item::ItemType1HBlunt, EQ::skills::Skill1HBlunt }, + { EQ::item::ItemType2HBlunt, EQ::skills::Skill2HBlunt }, + { EQ::item::ItemTypeBow, EQ::skills::SkillArchery }, + { EQ::item::ItemTypeSmallThrowing, EQ::skills::SkillThrowing }, + { EQ::item::ItemTypeLargeThrowing, EQ::skills::SkillThrowing }, + { EQ::item::ItemTypeShield, EQ::skills::SkillBash }, + { EQ::item::ItemTypeArmor, EQ::skills::SkillHandtoHand }, + { EQ::item::ItemTypeMartial, EQ::skills::SkillHandtoHand } + }; + + const auto& s = convert_item_types_map.find(item_type); + if (s != convert_item_types_map.end()) { + return s->second; + } + + return EQ::skills::SkillHandtoHand; +} + +void Mob::CloneAppearance(Mob* other, bool clone_name) +{ + if (!other) { + return; + } + + SendIllusionPacket( + other->GetRace(), + other->GetGender(), + other->GetTexture(), + other->GetHelmTexture(), + other->GetHairColor(), + other->GetBeardColor(), + other->GetEyeColor1(), + other->GetEyeColor2(), + other->GetHairStyle(), + other->GetBeard(), + 0xFF, + other->GetRace() == DRAKKIN ? other->GetDrakkinHeritage() : 0xFFFFFFFF, + other->GetRace() == DRAKKIN ? other->GetDrakkinTattoo() : 0xFFFFFFFF, + other->GetRace() == DRAKKIN ? other->GetDrakkinDetails() : 0xFFFFFFFF, + other->GetSize() + ); + + for ( + uint8 slot = EQ::textures::armorHead; + slot <= EQ::textures::armorFeet; + slot++ + ) { + auto color = 0; + auto material = 0; + if (other->IsClient()) { + color = other->CastToClient()->GetEquipmentColor(slot); + material = other->CastToClient()->GetEquipmentMaterial(slot); + } else { + color = other->GetArmorTint(slot); + material = !slot ? other->GetHelmTexture() : other->GetTexture(); + } + + WearChange(slot, material, color); + } + + WearChange( + EQ::textures::weaponPrimary, + other->GetEquipmentMaterial(EQ::textures::weaponPrimary), + other->GetEquipmentColor(EQ::textures::weaponPrimary) + ); + + WearChange( + EQ::textures::weaponSecondary, + other->GetEquipmentMaterial(EQ::textures::weaponSecondary), + other->GetEquipmentColor(EQ::textures::weaponSecondary) + ); + + if (IsNPC()) { + auto primary_skill = ( + other->IsNPC() ? + other->CastToNPC()->GetPrimSkill() : + ConvertItemTypeToSkillID(other->GetEquipmentType(EQ::textures::weaponSecondary)) + ); + + auto secondary_skill = ( + other->IsNPC() ? + other->CastToNPC()->GetSecSkill() : + ConvertItemTypeToSkillID(other->GetEquipmentType(EQ::textures::weaponSecondary)) + ); + + CastToNPC()->SetPrimSkill(primary_skill); + CastToNPC()->SetSecSkill(secondary_skill); + } + + if (clone_name) { + TempName(other->GetCleanName()); + } +} + +void Mob::CopyHateList(Mob* to) { + if (hate_list.IsHateListEmpty() || !to || to->IsClient()) { + return; + } + + for (const auto& h : hate_list.GetHateList()) { + if (h->entity_on_hatelist) { + to->AddToHateList(h->entity_on_hatelist, h->stored_hate_amount, h->hatelist_damage); + } + } +} + +int Mob::DispatchZoneControllerEvent( + QuestEventID evt, + Mob* init, + const std::string& data, + uint32 extra, + std::vector* pointers +) { + auto ret = 0; + + if ( + RuleB(Zone, UseZoneController) && + ( + !IsNPC() || + (IsNPC() && GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID) + ) + ) { + auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID); + if (controller) { + ret = parse->EventNPC(evt, controller, init, data, extra, pointers); + } + } + + return ret; +} diff --git a/zone/mob.h b/zone/mob.h index 9ad8c7ab0..556edbf63 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -29,13 +29,14 @@ #include "../common/light_source.h" #include "../common/emu_constants.h" #include "combat_record.h" +#include "event_codes.h" + +#include #include #include #include -#ifdef BOTS #include "heal_rotation.h" -#endif char* strn0cpy(char* dest, const char* source, uint32 size); @@ -164,6 +165,8 @@ public: uint8 in_feettexture, uint16 in_usemodel, bool in_always_aggros_foes, + int32 in_heroic_strikethrough, + bool keeps_sold_items, int64 in_hp_regen_per_second = 0 ); virtual ~Mob(); @@ -196,7 +199,7 @@ public: virtual void ThrowingAttack(Mob* other) { } // 13 = Primary (default), 14 = secondary virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr); void DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr, bool FromRiposte = false); int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); @@ -295,10 +298,10 @@ public: virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0); virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr); virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint); - virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model = 0); + virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color = 0, uint32 hero_forge_model = 0); void ChangeSize(float in_size, bool bNoRestriction = false); - void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone); + void DoAnim(const int animation_id, int animation_speed = 0, bool ackreq = true, eqFilterType filter = FilterNone); void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, EQ::skills::SkillType skillInUse = EQ::skills::SkillArchery); void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr, uint32 value1slot = 1, uint32 value1ground = 1, uint32 value2slot = 1, uint32 value2ground = 1, uint32 value3slot = 1, uint32 value3ground = 1, uint32 value4slot = 1, uint32 value4ground = 1, uint32 value5slot = 1, uint32 value5ground = 1); @@ -317,13 +320,13 @@ public: bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0); void NegateSpellEffectBonuses(uint16 spell_id); bool NegateSpellEffect(uint16 spell_id, int effect_id); - virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false); - virtual int64 GetActSpellDamage(uint16 spell_id, int64 value, Mob* target = nullptr); - virtual int64 GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_buff_tic = true); - virtual int64 GetActSpellHealing(uint16 spell_id, int64 value, Mob* target = nullptr, bool from_buff_tic = false); - virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;} + float GetActSpellRange(uint16 spell_id, float range); + int64 GetActSpellDamage(uint16 spell_id, int64 value, Mob* target = nullptr); + int64 GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_buff_tic = true); + int64 GetActSpellHealing(uint16 spell_id, int64 value, Mob* target = nullptr, bool from_buff_tic = false); + int32 GetActSpellCost(uint16 spell_id, int32 cost); virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration); - virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); + int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); virtual int64 GetActReflectedSpellDamage(int32 spell_id, int64 value, int effectiveness); float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false, int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false, @@ -345,21 +348,30 @@ public: int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 resist_adjust = 0, uint32 aa_id = 0); - void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQ::spells::CastingSlot slot, uint16 mana_used, + void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQ::spells::CastingSlot slot, int mana_used, uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0); - bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, uint16 mana_used = 0, + bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int mana_used = 0, uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, bool from_casted_spell = false, uint32 aa_id = 0); void SendBeginCast(uint16 spell_id, uint32 casttime); - virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, int reflect_effectiveness = 0, - bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, int32 duration_override = 0, bool disable_buff_overrwrite = false); - virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1, int reflect_effectiveness = 0, int32 duration_override = 0, bool disable_buff_overrwrite = false); + virtual bool SpellOnTarget( + uint16 spell_id, + Mob* spelltar, + int reflect_effectiveness = 0, + bool use_resist_adjust = false, + int16 resist_adjust = 0, + bool isproc = false, + int level_override = -1, + int duration_override = 0, + bool disable_buff_overwrite = false + ); + virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1, int reflect_effectiveness = 0, int32 duration_override = 0, bool disable_buff_overwrite = false); virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQ::spells::CastingSlot slot, bool isproc = false); bool DoCastingChecksOnCaster(int32 spell_id, EQ::spells::CastingSlot slot); bool DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id); bool DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob* spell_target); virtual bool CheckFizzle(uint16 spell_id); - virtual bool CheckSpellLevelRestriction(uint16 spell_id); + virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); virtual float GetAOERange(uint16 spell_id); void InterruptSpell(uint16 spellid = SPELL_UNKNOWN); @@ -408,7 +420,7 @@ public: bool IsAffectedByBuff(uint16 spell_id); bool IsAffectedByBuffByGlobalGroup(GlobalGroup group); void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration); - int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1, bool disable_buff_overrwrite = false); + int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1, bool disable_buff_overwrite = false); int CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite = false); int CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caster_level_override = -1); void SendPetBuffsToClient(); @@ -432,7 +444,7 @@ public: int32 RuneAbsorb(int64 damage, uint16 type); bool FindBuff(uint16 spell_id); uint16 FindBuffBySlot(int slot); - uint32 BuffCount(); + uint32 BuffCount(bool is_beneficial = true, bool is_detrimental = true); bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100); int16 GetBuffSlotFromType(uint16 type); uint16 GetSpellIDFromSlot(uint8 slot); @@ -463,8 +475,8 @@ public: void GetAppearenceEffects(); void ClearAppearenceEffects(); void SendSavedAppearenceEffects(Client *receiver); - void SetBuffDuration(int32 spell_id, int32 duration = 0); - void ApplySpellBuff(int32 spell_id, int32 duration = 0); + void SetBuffDuration(int spell_id, int duration = 0); + void ApplySpellBuff(int spell_id, int duration = 0); int GetBuffStatValueBySpell(int32 spell_id, const char* stat_identifier); int GetBuffStatValueBySlot(uint8 slot, const char* stat_identifier); @@ -480,12 +492,19 @@ public: bool HasTwoHanderEquipped() { return has_twohanderequipped; } void SetTwoHanderEquipped(bool val) { has_twohanderequipped = val; } bool HasDualWeaponsEquiped() const { return has_duelweaponsequiped; } + bool HasBowEquipped() const { return has_bowequipped; } + void SetBowEquipped(bool val) { has_bowequipped = val; } + bool HasArrowEquipped() const { return has_arrowequipped; } + void SetArrowEquipped(bool val) { has_arrowequipped = val; } + bool HasBowAndArrowEquipped() const { return HasBowEquipped() && HasArrowEquipped(); } inline void SetDuelWeaponsEquiped(bool val) { has_duelweaponsequiped = val; } bool CanFacestab() { return can_facestab; } void SetFacestab(bool val) { can_facestab = val; } + virtual uint8 ConvertItemTypeToSkillID(uint8 item_type); virtual uint16 GetSkill(EQ::skills::SkillType skill_num) const { return 0; } virtual uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const { return(0); } virtual int32 GetEquipmentMaterial(uint8 material_slot) const; + virtual uint8 GetEquipmentType(uint8 material_slot) const; virtual int32 GetHerosForgeModel(uint8 material_slot) const; virtual uint32 GetEquipmentColor(uint8 material_slot) const; virtual uint32 IsEliteMaterialItem(uint8 material_slot) const; @@ -497,7 +516,7 @@ public: bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) = 0; virtual void SetHP(int64 hp); bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); - inline void SetOOCRegen(int32 newoocregen) {ooc_regen = newoocregen;} + inline void SetOOCRegen(int64 new_ooc_regen) { ooc_regen = new_ooc_regen; } virtual void Heal(); virtual void HealDamage(uint64 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN); virtual void SetMaxHP() { current_hp = max_hp; } @@ -608,7 +627,7 @@ public: virtual int64 GetMaxEndurance() const { return 0; } virtual void SetEndurance(int32 newEnd) { return; } int64 GetItemHPBonuses(); - int32 GetSpellHPBonuses(); + int64 GetSpellHPBonuses(); virtual const int64& SetMana(int64 amount); inline float GetManaRatio() const { return max_mana == 0 ? 100 : ((static_cast(current_mana) / max_mana) * 100); } @@ -630,9 +649,16 @@ public: inline const float GetSize() const { return size; } inline const float GetBaseSize() const { return base_size; } inline const GravityBehavior GetFlyMode() const { return flymode; } - bool IsBoat() const; + bool IsBoat() const; // Checks races - used on mob instantiation + bool GetIsBoat() const { return is_boat; } // Set on instantiation for speed + void SetIsBoat(bool boat) { is_boat = boat; } bool IsControllableBoat() const; inline const bool AlwaysAggro() const { return always_aggro; } + inline int32 GetHeroicStrikethrough() const { return heroic_strikethrough; } + inline const bool GetKeepsSoldItems() const { return keeps_sold_items; } + inline void SetKeepsSoldItems(bool in_keeps_sold_items) { keeps_sold_items = in_keeps_sold_items; } + + void CopyHateList(Mob* to); //Group virtual bool HasRaid() = 0; @@ -682,7 +708,7 @@ public: //AI static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel); inline uint32 GetLevelCon(uint8 iOtherLevel) const { return GetLevelCon(GetLevel(), iOtherLevel); } - virtual void AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true, + void AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false); bool RemoveFromHateList(Mob* mob); void SetHateAmountOnEnt(Mob* other, int64 hate = 0, int64 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);} @@ -697,9 +723,7 @@ public: Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} Client* GetHateRandomClient() { return hate_list.GetRandomClientOnHateList(); } NPC* GetHateRandomNPC() { return hate_list.GetRandomNPCOnHateList(); } -#ifdef BOTS Bot* GetHateRandomBot() { return hate_list.GetRandomBotOnHateList(); } -#endif Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} Mob* GetHateClosest() { return hate_list.GetClosestEntOnHateList(this); } bool IsEngaged() { return(!hate_list.IsHateListEmpty()); } @@ -716,7 +740,6 @@ public: bool IsOnFeignMemory(Mob *attacker) const; void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); } std::list& GetHateList() { return hate_list.GetHateList(); } - std::list GetHateListByDistance(int distance = 0) { return hate_list.GetHateListByDistance(distance); } bool CheckLosFN(Mob* other); bool CheckLosFN(float posX, float posY, float posZ, float mobSize); static bool CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget); @@ -724,8 +747,33 @@ public: inline bool CheckLastLosState() const { return last_los_check; } std::string GetMobDescription(); + std::list GetFilteredHateList( + EntityFilterType filter_type = EntityFilterType::All, + uint32 distance = 0 + ) { + return hate_list.GetFilteredHateList(filter_type, distance); + } + + void DamageHateList( + int64 damage, + uint32 distance = 0, + EntityFilterType filter_type = EntityFilterType::All, + bool is_percentage = false + ) { + hate_list.DamageHateList(damage, distance, filter_type, is_percentage); + } + + void DamageArea( + int64 damage, + uint32 distance = 0, + EntityFilterType filter_type = EntityFilterType::All, + bool is_percentage = false + ) { + entity_list.DamageArea(this, damage, distance, filter_type, is_percentage); + } + //Quest - void CameraEffect(uint32 duration, uint32 intensity, Client *c = nullptr, bool global = false); + void CameraEffect(uint32 duration, float intensity, Client *c = nullptr, bool global = false); inline bool GetQglobal() const { return qglobal; } //Other Packet @@ -737,10 +785,12 @@ public: void CreateHPPacket(EQApplicationPacket* app); void SendHPUpdate(bool force_update_all = false); virtual void ResetHPUpdateTimer() {}; // does nothing + static void SetSpawnLastNameByClass(NewSpawn_Struct* ns); //Util static uint32 RandomTimer(int min, int max); static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF); + static bool IsPlayerClass(uint16 in_class); static bool IsPlayerRace(uint16 in_race); EQ::skills::SkillType GetSkillByItemType(int ItemType); uint8 GetItemTypeBySkill(EQ::skills::SkillType skill); @@ -825,15 +875,30 @@ public: void Shout(const char *format, ...); void Emote(const char *format, ...); void QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts); - int32 GetItemStat(uint32 itemid, const char *identifier); + const int GetItemStat(uint32 item_id, std::string identifier); int64 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false, uint16 casterid = 0, Mob *caster = nullptr); uint8 IsFocusEffect(uint16 spellid, int effect_index, bool AA=false,uint32 aa_effect=0); - void SendIllusionPacket(uint16 in_race, uint8 in_gender = 0xFF, uint8 in_texture = 0xFF, uint8 in_helmtexture = 0xFF, - uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF, - uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF, - uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF, - uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f, bool send_appearance_effects = true); + void SendIllusionPacket( + uint16 in_race, + uint8 in_gender = 0xFF, + uint8 in_texture = 0xFF, + uint8 in_helmtexture = 0xFF, + uint8 in_haircolor = 0xFF, + uint8 in_beardcolor = 0xFF, + uint8 in_eyecolor1 = 0xFF, + uint8 in_eyecolor2 = 0xFF, + uint8 in_hairstyle = 0xFF, + uint8 in_luclinface = 0xFF, + uint8 in_beard = 0xFF, + uint8 in_aa_title = 0xFF, + uint32 in_drakkin_heritage = 0xFFFFFFFF, + uint32 in_drakkin_tattoo = 0xFFFFFFFF, + uint32 in_drakkin_details = 0xFFFFFFFF, + float in_size = -1.0f, + bool send_appearance_effects = true + ); + void CloneAppearance(Mob* other, bool clone_name = false); void SetFaceAppearance(const FaceChange_Struct& face, bool skip_sender = false); bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true); virtual void Stun(int duration); @@ -879,10 +944,10 @@ public: int16 GetMeleeDmgPositionMod(Mob* defender); int16 GetSkillReuseTime(uint16 skill); int GetCriticalChanceBonus(uint16 skill); - int16 GetSkillDmgAmt(uint16 skill); + int GetSkillDmgAmt(uint16 skill); int16 GetPositionalDmgAmt(Mob* defender); inline bool CanBlockSpell() const { return(spellbonuses.FocusEffects[focusBlockNextSpell]); } - bool DoHPToManaCovert(uint16 mana_cost = 0); + bool DoHPToManaCovert(int32 mana_cost = 0); int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect); int64 GetExtraSpellAmt(uint16 spell_id, int64 extra_spell_amt, int64 base_spell_dmg); void MeleeLifeTap(int64 damage); @@ -983,7 +1048,7 @@ public: inline uint16 GetOwnerID() const { return ownerid; } inline virtual bool HasOwner() { if(GetOwnerID()==0){return false;} return( entity_list.GetMob(GetOwnerID()) != 0); } inline virtual bool IsPet() { return(HasOwner() && !IsMerc()); } - inline bool HasPet() const { if(GetPetID()==0){return false;} return (entity_list.GetMob(GetPetID()) != 0);} + bool HasPet() const; inline bool HasTempPetsActive() const { return(hasTempPet); } inline void SetTempPetsActive(bool i) { hasTempPet = i; } inline int16 GetTempPetCount() const { return count_TempPet; } @@ -1069,9 +1134,12 @@ public: virtual void AI_ShutDown(); virtual void AI_Process(); - const char* GetEntityVariable(const char *id); - void SetEntityVariable(const char *id, const char *m_var); - bool EntityVariableExists(const char *id); + bool ClearEntityVariables(); + bool DeleteEntityVariable(std::string variable_name); + std::string GetEntityVariable(std::string variable_name); + std::vector GetEntityVariables(); + void SetEntityVariable(std::string variable_name, std::string variable_value); + bool EntityVariableExists(std::string variable_name); void AI_Event_Engaged(Mob* attacker, bool yell_for_help = true); void AI_Event_NoLongerEngaged(); @@ -1163,7 +1231,6 @@ public: bool CheckWillAggro(Mob *mob); void InstillDoubt(Mob *who); - int16 GetResist(uint8 type) const; bool Charmed() const { return typeofpet == petCharmed; } static uint32 GetLevelHP(uint8 tlevel); uint32 GetZoneID() const; //for perl @@ -1173,7 +1240,7 @@ public: //uint32 GetInstrumentMod(uint16 spell_id) const; uint32 GetInstrumentMod(uint16 spell_id); int64 CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0,uint16 casterid=0); - int64 CalcSpellEffectValue_formula(int64 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining = 0); + int64 CalcSpellEffectValue_formula(uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining = 0); virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1); uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; } @@ -1239,16 +1306,16 @@ public: inline uint8 GetManaPercent() { return (uint8)((float)current_mana / (float)max_mana * 100.0f); } virtual uint8 GetEndurancePercent() { return 0; } - inline virtual bool IsBlockedBuff(int16 SpellID) { return false; } - inline virtual bool IsBlockedPetBuff(int16 SpellID) { return false; } + inline virtual bool IsBlockedBuff(int32 SpellID) { return false; } + inline virtual bool IsBlockedPetBuff(int32 SpellID) { return false; } std::string GetGlobal(const char *varname); void SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Mob *other = nullptr); void TarGlobal(const char *varname, const char *value, const char *duration, int npcid, int charid, int zoneid); void DelGlobal(const char *varname); - inline void SetEmoteID(uint16 emote) { emoteid = emote; } - inline uint16 GetEmoteID() { return emoteid; } + inline void SetEmoteID(uint32 emote) { emoteid = emote; } + inline uint32 GetEmoteID() { return emoteid; } bool HasSpellEffect(int effect_id); int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob *caster, uint16 caster_id); @@ -1336,6 +1403,7 @@ public: int GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in); void ExpendAlternateAdvancementCharge(uint32 aa_id); void CalcAABonuses(StatBonuses* newbon); + int64 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); bool CheckAATimer(int timer); @@ -1345,6 +1413,7 @@ public: void ResetAssistCap() { npc_assist_cap = 0; } int64 GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item); int64 GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, int64 *hate = nullptr); + int64 DoDamageCaps(int64 base_damage); int64 GetHPRegen() const; int64 GetManaRegen() const; @@ -1363,7 +1432,8 @@ public: std::string GetBucketRemaining(std::string bucket_name); void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration = ""); -#ifdef BOTS + int DispatchZoneControllerEvent(QuestEventID evt, Mob* init, const std::string& data, uint32 extra, std::vector* pointers); + // Bots HealRotation methods bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); } bool JoinHealRotationTargetPool(std::shared_ptr* heal_rotation); @@ -1380,7 +1450,6 @@ public: // not Bots HealRotation methods void SetManualFollow(bool flag) { m_manual_follow = flag; } bool GetManualFollow() const { return m_manual_follow; } -#endif protected: void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None); @@ -1447,7 +1516,7 @@ protected: int64 hp_regen; int64 hp_regen_per_second; int64 mana_regen; - int32 ooc_regen; + int64 ooc_regen; uint8 maxlevel; uint32 scalerate; Buffs_Struct *buffs; @@ -1464,6 +1533,8 @@ protected: bool follow_run; bool no_target_hotkey; bool rare_spawn; + int32 heroic_strikethrough; + bool keeps_sold_items; uint32 m_PlayerState; uint32 GetPlayerState() { return m_PlayerState; } @@ -1521,11 +1592,9 @@ protected: virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQ::invslot::slotPrimary, Mob *on = nullptr); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); -#ifdef BOTS - virtual -#endif - int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr); - virtual int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false) { return 0; } + virtual int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr); + virtual int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false); + virtual EQ::InventoryProfile& GetInv() { return m_inv; } void CalculateNewFearpoint(); float FindGroundZ(float new_x, float new_y, float z_offset=0.0); float FindDestGroundZ(glm::vec3 dest, float z_offset=0.0); @@ -1599,7 +1668,7 @@ protected: bool delaytimer; uint16 casting_spell_targetid; EQ::spells::CastingSlot casting_spell_slot; - uint16 casting_spell_mana; + int32 casting_spell_mana; uint32 casting_spell_inventory_slot; uint32 casting_spell_timer; uint32 casting_spell_timer_duration; @@ -1651,6 +1720,8 @@ protected: bool has_twohandbluntequiped; bool has_twohanderequipped; bool has_duelweaponsequiped; + bool has_bowequipped = false; + bool has_arrowequipped = false; bool use_double_melee_round_dmg_bonus; bool can_facestab; bool has_numhits; @@ -1662,6 +1733,7 @@ protected: bool endur_upkeep; bool degenerating_effects; // true if we have a buff that needs to be recalced every tick bool spawned_in_water; + bool is_boat; CombatRecord combat_record{}; @@ -1768,7 +1840,7 @@ protected: bool m_targetable; int QGVarDuration(const char *fmt); void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate); - uint16 emoteid; + uint32 emoteid; SpecialAbility SpecialAbilities[MAX_SPECIAL_ATTACK]; bool bEnraged; @@ -1791,14 +1863,9 @@ protected: private: Mob* target; - - -#ifdef BOTS + EQ::InventoryProfile m_inv; std::shared_ptr m_target_of_heal_rotation; - bool m_manual_follow; -#endif - }; #endif diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 8b9fd08db..6b8f85bba 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -19,7 +19,7 @@ #include "../common/global_define.h" #include "../common/features.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "entity.h" @@ -32,6 +32,8 @@ #include "fastmath.h" #include "../common/data_verification.h" +#include "bot.h" + #include #include #include @@ -84,7 +86,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates float manaR = GetManaRatio(); for (int i = static_cast(AIspells.size()) - 1; i >= 0; i--) { - if (AIspells[i].spellid <= 0 || AIspells[i].spellid >= SPDAT_RECORDS) { + if (!IsValidSpell(AIspells[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here //return false; @@ -127,10 +129,8 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates && (AIspells[i].time_cancast + (zone->random.Int(0, 4) * 500)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time. ) { -#if MobAI_DEBUG_Spells >= 21 - LogAI("Mob::AICastSpell: Casting: spellid=[{}], tar=[{}], dist2[[{}]]<=[{}], mana_cost[[{}]]<=[{}], cancast[[{}]]<=[{}], type=[{}]", + LogAI("Casting: spellid [{}] tar [{}] dist2[[{}]]<=[{}] mana_cost[[{}]]<=[{}] cancast[[{}]]<=[{}] type [{}]", AIspells[i].spellid, tar->GetName(), dist2, (spells[AIspells[i].spellid].range * spells[AIspells[i].spellid].range), mana_cost, GetMana(), AIspells[i].time_cancast, Timer::GetCurrentTime(), AIspells[i].type); -#endif switch (AIspells[i].type) { case SpellType_Heal: { @@ -360,21 +360,17 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates } } } -#if MobAI_DEBUG_Spells >= 21 else { - LogAI("Mob::AICastSpell: NotCasting: spellid=[{}], tar=[{}], dist2[[{}]]<=[{}], mana_cost[[{}]]<=[{}], cancast[[{}]]<=[{}], type=[{}]", + LogAI("NotCasting: spellid [{}] tar [{}] dist2[[{}]]<=[{}] mana_cost[[{}]]<=[{}] cancast[[{}]]<=[{}] type [{}]", AIspells[i].spellid, tar->GetName(), dist2, (spells[AIspells[i].spellid].range * spells[AIspells[i].spellid].range), mana_cost, GetMana(), AIspells[i].time_cancast, Timer::GetCurrentTime(), AIspells[i].type); } -#endif } } return false; } bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { -#if MobAI_DEBUG_Spells >= 1 - LogAI("Mob::AIDoSpellCast: spellid = [{}], tar = [{}], mana = [{}], Name: [{}]", AIspells[i].spellid, tar->GetName(), mana_cost, spells[AIspells[i].spellid].name); -#endif + LogAI("spellid [{}] tar [{}] mana [{}] Name [{}]", AIspells[i].spellid, tar->GetName(), mana_cost, spells[AIspells[i].spellid].name); casting_spell_AIindex = i; return CastSpell(AIspells[i].spellid, tar->GetID(), EQ::spells::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust)); @@ -806,14 +802,14 @@ void Client::AI_Process() FaceTarget(); } } - if (GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { + if (GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned() && IsAttackAllowed(GetTarget())) { if (attack_timer.Check()) { // Should charmed clients not be procing? DoAttackRounds(GetTarget(), EQ::invslot::slotPrimary); } } - if (CanThisClassDualWield() && GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { + if (CanThisClassDualWield() && GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned() && IsAttackAllowed(GetTarget())) { if (attack_dw_timer.Check()) { if (CheckDualWield()) { // Should charmed clients not be procing? @@ -1075,7 +1071,7 @@ void Mob::AI_Process() { // NPCs will forget people after 10 mins of not interacting with them or out of range // both of these maybe zone specific, hardcoded for now if (hate_list_cleanup_timer.Check()) { - hate_list.RemoveStaleEntries(600000, static_cast(zone->newzone_data.NPCAggroMaxDist)); + hate_list.RemoveStaleEntries(600000, static_cast(zone->newzone_data.npc_aggro_max_dist)); if (hate_list.IsHateListEmpty()) { AI_Event_NoLongerEngaged(); zone->DelAggroMob(); @@ -1121,14 +1117,12 @@ void Mob::AI_Process() { return; } -#ifdef BOTS if (IsPet() && GetOwner() && GetOwner()->IsBot() && target == GetOwner()) { // this blocks all pet attacks against owner..bot pet test (copied above check) RemoveFromHateList(this); return; } -#endif //BOTS if (DivineAura()) return; @@ -1336,9 +1330,11 @@ void Mob::AI_Process() { // See if we can summon the mob to us if (!HateSummon()) { + //could not summon them, check ranged... - if (GetSpecialAbility(SPECATK_RANGED_ATK)) + if (GetSpecialAbility(SPECATK_RANGED_ATK) || HasBowAndArrowEquipped()) { doranged = true; + } // Now pursue // TODO: Check here for another person on hate list with close hate value @@ -1353,7 +1349,7 @@ void Mob::AI_Process() { (GetOwnerID() || IsBot() || IsTempPet() || CastToNPC()->GetCombatEvent())) { if (!IsRooted()) { - LogAI("Pursuing [{}] while engaged", target->GetName()); + LogAIDetail("Pursuing [{}] while engaged", target->GetName()); RunTo(target->GetX(), target->GetY(), target->GetZ()); } @@ -1600,9 +1596,8 @@ void NPC::AI_DoMovement() { move_delay_max ); - Log( - Logs::Detail, - Logs::NPCRoamBox, "(%s) Timer calc | random_timer [%i] roambox_move_delay [%i] move_min [%i] move_max [%i]", + LogNPCRoamBoxDetail( + "({}) Timer calc | random_timer [{}] roambox_move_delay [{}] move_min [{}] move_max [{}]", GetCleanName(), random_timer, roambox_move_delay, @@ -1659,9 +1654,7 @@ void NPC::AI_DoMovement() { } if (zone->watermap->InLiquid(position)) { - Log(Logs::Detail, - Logs::NPCRoamBox, "%s | My destination is in water and I don't belong there!", - GetCleanName()); + LogNPCRoamBoxDetail("[{}] | My destination is in water and I don't belong there!", GetCleanName()); return; } @@ -1681,39 +1674,12 @@ void NPC::AI_DoMovement() { } } - PathfinderOptions opts; - opts.smooth_path = true; - opts.step_size = RuleR(Pathing, NavmeshStepSize); - opts.offset = GetZOffset(); - opts.flags = PathingNotDisabled ^ PathingZoneLine; + LogNPCRoamBox("[{}] | Pathing to [{}] [{}] [{}]", GetCleanName(), + roambox_destination_x, roambox_destination_y, + roambox_destination_z); - auto partial = false; - auto stuck = false; - auto route = zone->pathing->FindPath( - glm::vec3(GetX(), GetY(), GetZ()), - glm::vec3( - roambox_destination_x, - roambox_destination_y, - roambox_destination_z - ), - partial, - stuck, - opts - ); - - if (route.empty()) { - Log( - Logs::Detail, - Logs::NPCRoamBox, "(%s) We don't have a path route... exiting...", - GetCleanName() - ); - return; - } - - Log( - Logs::General, - Logs::NPCRoamBox, - "NPC (%s) distance [%.0f] X (min/max) [%.0f / %.0f] Y (min/max) [%.0f / %.0f] | Dest x/y/z [%.0f / %.0f / %.0f]", + LogNPCRoamBox( + "NPC ({}) distance [{}] X (min/max) [{} / {}] Y (min/max) [{} / {}] | Dest x/y/z [{} / {} / {}]", GetCleanName(), roambox_distance, roambox_min_x, @@ -1746,7 +1712,7 @@ void NPC::AI_DoMovement() { else if (!(AI_walking_timer->Enabled())) { // currently moving bool doMove = true; if(IsPositionEqual(glm::vec2(m_CurrentWayPoint.x, m_CurrentWayPoint.y), glm::vec2(GetX(), GetY()))) { - LogAI("We have reached waypoint [{}] ({},{},{}) on grid [{}]", + LogAIDetail("We have reached waypoint [{}] ({},{},{}) on grid [{}]", cur_wp, GetX(), GetY(), @@ -1834,7 +1800,7 @@ void NPC::AI_DoMovement() { if (at_gp) { if (moved) { - LogAI("Reached guard point ({},{},{})", m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z); + LogAIDetail("Reached guard point ({},{},{})", m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z); ClearFeignMemory(); moved = false; @@ -1951,10 +1917,11 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help) if (attacker->GetHP() > 0) { if (!CastToNPC()->GetCombatEvent() && GetHP() > 0) { parse->EventNPC(EVENT_COMBAT, CastToNPC(), attacker, "1", 0); - uint16 emoteid = GetEmoteID(); - if (emoteid != 0) { - CastToNPC()->DoNPCEmote(ENTERCOMBAT, emoteid); + auto emote_id = GetEmoteID(); + if (emote_id) { + CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emoteid); } + std::string mob_name = GetCleanName(); combat_record.Start(mob_name); CastToNPC()->SetCombatEvent(true); @@ -1962,18 +1929,26 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help) } } } + + if (IsBot()) { + parse->EventBot(EVENT_COMBAT, CastToBot(), attacker, "1", 0); + } } // Note: Hate list may not be actually clear until after this function call completes void Mob::AI_Event_NoLongerEngaged() { - if (!IsAIControlled()) + if (!IsAIControlled()) { return; + } + AI_walking_timer->Start(RandomTimer(3000,20000)); time_until_can_move = Timer::GetCurrentTime(); - if (minLastFightingDelayMoving == maxLastFightingDelayMoving) + + if (minLastFightingDelayMoving == maxLastFightingDelayMoving) { time_until_can_move += minLastFightingDelayMoving; - else + } else { time_until_can_move += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving); + } StopNavigation(); ClearRampage(); @@ -1982,16 +1957,19 @@ void Mob::AI_Event_NoLongerEngaged() { SetPrimaryAggro(false); SetAssistAggro(false); if (CastToNPC()->GetCombatEvent() && GetHP() > 0) { - if (entity_list.GetNPCByID(this->GetID())) { - uint16 emoteid = CastToNPC()->GetEmoteID(); + if (entity_list.GetNPCByID(GetID())) { + auto emote_id = CastToNPC()->GetEmoteID(); parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0); - if (emoteid != 0) { - CastToNPC()->DoNPCEmote(LEAVECOMBAT, emoteid); + if (emote_id) { + CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::LeaveCombat, emoteid); } + combat_record.Stop(); CastToNPC()->SetCombatEvent(false); } } + } else if (IsBot()) { + parse->EventBot(EVENT_COMBAT, CastToBot(), nullptr, "0", 0); } } @@ -2025,7 +2003,7 @@ bool NPC::AI_EngagedCastCheck() { if (AIautocastspell_timer->Check(false)) { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - LogAI("Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells"); + LogAIDetail("Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells"); // first try innate (spam) spells if(!AICastSpell(GetTarget(), 0, SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root, true)) { @@ -2054,7 +2032,7 @@ bool NPC::AI_PursueCastCheck() { if (AIautocastspell_timer->Check(false)) { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - LogAI("Engaged (pursuing) autocast check triggered. Trying to cast offensive spells"); + LogAIDetail("Engaged (pursuing) autocast check triggered. Trying to cast offensive spells"); // checking innate (spam) spells first if(!AICastSpell(GetTarget(), AISpellVar.pursue_detrimental_chance, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff, true)) { if(!AICastSpell(GetTarget(), AISpellVar.pursue_detrimental_chance, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff)) { @@ -2076,7 +2054,7 @@ bool NPC::AI_IdleCastCheck() { //last duration it was set to... try to put up a more reasonable timer... AIautocastspell_timer->Start(RandomTimer(AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max), false); - LogSpells("Triggering AI_IdleCastCheck :: Mob [{}] - Min : [{}] Max : [{}]", GetCleanName(), AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max); + LogSpells("Mob [{}] Min [{}] Max [{}]", GetCleanName(), AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max); } //else, spell casting finishing will reset the timer. } //else, spell casting finishing will reset the timer. @@ -2142,12 +2120,12 @@ bool Mob::Flurry(ExtraAttackOptions *opts) // this is wrong, flurry is extra attacks on the current target Mob *target = GetTarget(); if (target) { - if (!IsPet()) { + if (IsPet() || IsTempPet() || IsCharmed() || IsAnimation()) { entity_list.MessageCloseString( this, true, 200, - Chat::NPCFlurry, + Chat::PetFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); @@ -2156,7 +2134,7 @@ bool Mob::Flurry(ExtraAttackOptions *opts) this, true, 200, - Chat::PetFlurry, + Chat::NPCFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); @@ -2195,11 +2173,11 @@ void Mob::ClearRampage() bool Mob::Rampage(ExtraAttackOptions *opts) { int index_hit = 0; - if (!IsPet()) - entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, NPC_RAMPAGE, GetCleanName()); - else + if (IsPet() || IsTempPet() || IsCharmed() || IsAnimation()){ entity_list.MessageCloseString(this, true, 200, Chat::PetFlurry, NPC_RAMPAGE, GetCleanName()); - + } else { + entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, NPC_RAMPAGE, GetCleanName()); + } int rampage_targets = GetSpecialAbilityParam(SPECATK_RAMPAGE, 1); if (rampage_targets == 0) // if set to 0 or not set in the DB rampage_targets = RuleI(Combat, DefaultRampageTargets); @@ -2252,10 +2230,10 @@ bool Mob::Rampage(ExtraAttackOptions *opts) void Mob::AreaRampage(ExtraAttackOptions *opts) { int index_hit = 0; - if (!IsPet()) { // do not know every pet AA so thought it safer to add this - entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, AE_RAMPAGE, GetCleanName()); - } else { + if (IsPet() || IsTempPet() || IsCharmed() || IsAnimation()) { // do not know every pet AA so thought it safer to add this entity_list.MessageCloseString(this, true, 200, Chat::PetFlurry, AE_RAMPAGE, GetCleanName()); + } else { + entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, AE_RAMPAGE, GetCleanName()); } int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); @@ -2485,37 +2463,11 @@ void NPC::CheckSignal() { if (!signal_q.empty()) { int signal_id = signal_q.front(); signal_q.pop_front(); - std::string export_string = fmt::format("{}", signal_id); + const auto export_string = fmt::format("{}", signal_id); parse->EventNPC(EVENT_SIGNAL, this, nullptr, export_string, 0); } } - - -/* -alter table npc_types drop column usedspells; -alter table npc_types add column npc_spells_id int(11) unsigned not null default 0 after merchant_id; -Create Table npc_spells ( - id int(11) unsigned not null auto_increment primary key, - name tinytext, - parent_list int(11) unsigned not null default 0, - attack_proc smallint(5) not null default -1, - proc_chance tinyint(3) not null default 3 - ); -create table npc_spells_entries ( - id int(11) unsigned not null auto_increment primary key, - npc_spells_id int(11) not null, - spellid smallint(5) not null default 0, - type smallint(5) unsigned not null default 0, - minlevel tinyint(3) unsigned not null default 0, - maxlevel tinyint(3) unsigned not null default 255, - manacost smallint(5) not null default '-1', - recast_delay int(11) not null default '-1', - priority smallint(5) not null default 0, - index npc_spells_id (npc_spells_id) - ); -*/ - bool IsSpellInList(DBnpcspells_Struct* spell_list, uint16 iSpellID); bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base_value, int32 limit, int32 max_value); @@ -2533,7 +2485,6 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { return false; } DBnpcspells_Struct* parentlist = content_db.GetNPCSpells(spell_list->parent_list); -#if MobAI_DEBUG_Spells >= 10 std::string debug_msg = StringFormat("Loading NPCSpells onto %s: dbspellsid=%u, level=%u", GetName(), iDBSpellsID, GetLevel()); if (spell_list) { debug_msg.append(StringFormat(" (found, %u), parentlist=%u", spell_list->entries.size(), spell_list->parent_list)); @@ -2549,22 +2500,19 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { } LogAI("[{}]", debug_msg.c_str()); -#ifdef MobAI_DEBUG_Spells >= 25 if (parentlist) { for (const auto &iter : parentlist->entries) { - LogAI("([{}]) [{}]", iter.spellid, spells[iter.spellid].name); + LogAIDetail("([{}]) [{}]", iter.spellid, spells[iter.spellid].name); } } LogAI("fin (parent list)"); if (spell_list) { for (const auto &iter : spell_list->entries) { - LogAI("([{}]) [{}]", iter.spellid, spells[iter.spellid].name); + LogAIDetail("([{}]) [{}]", iter.spellid, spells[iter.spellid].name); } } LogAI("fin (spell list)"); -#endif -#endif uint16 attack_proc_spell = -1; int8 proc_chance = 3; uint16 range_proc_spell = -1; @@ -2708,7 +2656,6 @@ bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) { DBnpcspellseffects_Struct* parentlist = content_db.GetNPCSpellsEffects(spell_effects_list->parent_list); uint32 i; -#if MobAI_DEBUG_Spells >= 10 std::string debug_msg = StringFormat("Loading NPCSpellsEffects onto %s: dbspellseffectid=%u", GetName(), iDBSpellsEffectsID); if (spell_effects_list) { debug_msg.append(StringFormat(" (found, %u), parentlist=%u", spell_effects_list->numentries, spell_effects_list->parent_list)); @@ -2723,7 +2670,6 @@ bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) { debug_msg.append(" (not found)"); } LogAI("[{}]", debug_msg.c_str()); -#endif if (parentlist) { for (i=0; inumentries; i++) { @@ -2924,7 +2870,7 @@ void NPC::AISpellsList(Client *c) c->Message( Chat::White, fmt::format( - "Spell {} | Resist Adjust : {}", + "Spell {} | Resist Adjust: {}", spell_slot, ai_spell.resist_adjust ).c_str() @@ -3016,16 +2962,9 @@ DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) query = StringFormat( "SELECT spellid, type, minlevel, maxlevel, " "manacost, recast_delay, priority, min_hp, max_hp, resist_adjust " -#ifdef BOTS - "FROM %s " - "WHERE npc_spells_id=%d ORDER BY minlevel", - (iDBSpellsID >= 3001 && iDBSpellsID <= 3016 ? "bot_spells_entries" : "npc_spells_entries"), - iDBSpellsID); -#else "FROM npc_spells_entries " "WHERE npc_spells_id=%d ORDER BY minlevel", iDBSpellsID); -#endif results = QueryDatabase(query); if (!results.Success()) { diff --git a/zone/mob_appearance.cpp b/zone/mob_appearance.cpp index 1af45e727..192e5d002 100644 --- a/zone/mob_appearance.cpp +++ b/zone/mob_appearance.cpp @@ -18,20 +18,19 @@ * */ +#include "../common/data_verification.h" #include "../common/eqemu_logsys.h" - +#include "../common/item_data.h" #include "../common/misc_functions.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "mob.h" #include "quest_parser_collection.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" -#ifdef BOTS #include "bot.h" -#endif /** * Stores internal representation of mob texture by material slot @@ -44,7 +43,7 @@ void Mob::SetMobTextureProfile(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model) { Log(Logs::Detail, Logs::MobAppearance, - "Mob::SetMobTextureProfile [%s] material_slot: %u texture: %u color: %u hero_forge_model: %u", + "[%s] material_slot: %u texture: %u color: %u hero_forge_model: %u", GetCleanName(), material_slot, texture, @@ -213,7 +212,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const int32 texture_profile_material = GetTextureProfileMaterial(material_slot); Log(Logs::Detail, Logs::MobAppearance, - "Mob::GetEquipmentMaterial [%s] material_slot: %u texture_profile_material: %i", + "[%s] material_slot: %u texture_profile_material: %i", clean_name, material_slot, texture_profile_material @@ -225,39 +224,31 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const auto item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot)); - if (item != nullptr) { + if (item) { + const auto is_equipped_weapon = EQ::ValueWithin(material_slot, EQ::textures::weaponPrimary, EQ::textures::weaponSecondary); - /** - * Handle primary / secondary texture - */ - bool is_primary_or_secondary_weapon = - material_slot == EQ::textures::weaponPrimary || - material_slot == EQ::textures::weaponSecondary; - - if (is_primary_or_secondary_weapon) { + if (is_equipped_weapon) { if (IsClient()) { - - int16 inventory_slot = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot); + const auto inventory_slot = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot); if (inventory_slot == INVALID_INDEX) { return 0; } - const EQ::ItemInstance *item_instance = CastToClient()->m_inv[inventory_slot]; - if (item_instance) { - if (item_instance->GetOrnamentationAug(ornamentation_augment_type)) { - item = item_instance->GetOrnamentationAug(ornamentation_augment_type)->GetItem(); - if (item && strlen(item->IDFile) > 2) { - equipment_material = atoi(&item->IDFile[2]); + const auto* inst = CastToClient()->m_inv[inventory_slot]; + if (inst) { + if (inst->GetOrnamentationAug(ornamentation_augment_type)) { + item = inst->GetOrnamentationAug(ornamentation_augment_type)->GetItem(); + if (item && strlen(item->IDFile) > 2 && Strings::IsNumber(&item->IDFile[2])) { + equipment_material = std::stoi(&item->IDFile[2]); } - } - else if (item_instance->GetOrnamentationIDFile()) { - equipment_material = item_instance->GetOrnamentationIDFile(); + } else if (inst->GetOrnamentationIDFile()) { + equipment_material = inst->GetOrnamentationIDFile(); } } } - if (equipment_material == 0 && strlen(item->IDFile) > 2) { - equipment_material = atoi(&item->IDFile[2]); + if (!equipment_material && strlen(item->IDFile) > 2 && Strings::IsNumber(&item->IDFile[2])) { + equipment_material = std::stoi(&item->IDFile[2]); } } else { @@ -268,6 +259,32 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const return equipment_material; } +uint8 Mob::GetEquipmentType(uint8 material_slot) const +{ + auto item_type = static_cast(EQ::item::ItemType2HBlunt); + auto item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot)); + + if (item) { + const auto is_equipped_weapon = EQ::ValueWithin(material_slot, EQ::textures::weaponPrimary, EQ::textures::weaponSecondary); + + if (is_equipped_weapon) { + if (IsClient()) { + const auto inventory_slot = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot); + if (inventory_slot == INVALID_INDEX) { + return item_type; + } + + const auto* inst = CastToClient()->m_inv[inventory_slot]; + if (inst) { + item_type = inst->GetItemType(); + } + } + } + } + + return item_type; +} + /** * @param material_slot * @return @@ -378,7 +395,7 @@ void Mob::SendArmorAppearance(Client *one_client) * The other packets work for primary/secondary. */ - LogMobAppearance("[SendArmorAppearance] [{}]", GetCleanName()); + LogMobAppearance("[{}]", GetCleanName()); if (IsPlayerRace(race)) { if (!IsClient()) { @@ -407,7 +424,7 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client) auto packet = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); auto *wear_change = (WearChange_Struct *) packet->pBuffer; - Log(Logs::Detail, Logs::MobAppearance, "Mob::SendWearChange [%s]", + Log(Logs::Detail, Logs::MobAppearance, "[%s]", GetCleanName() ); @@ -416,7 +433,6 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client) wear_change->elite_material = IsEliteMaterialItem(material_slot); wear_change->hero_forge_model = static_cast(GetHerosForgeModel(material_slot)); -#ifdef BOTS if (IsBot()) { auto item_inst = CastToBot()->GetBotItem(EQ::InventoryProfile::CalcSlotFromMaterial(material_slot)); if (item_inst) @@ -427,9 +443,6 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client) else { wear_change->color.Color = GetEquipmentColor(material_slot); } -#else - wear_change->color.Color = GetEquipmentColor(material_slot); -#endif wear_change->wear_slot_id = material_slot; diff --git a/zone/mob_info.cpp b/zone/mob_info.cpp index 45dfe2719..ef5f58063 100644 --- a/zone/mob_info.cpp +++ b/zone/mob_info.cpp @@ -22,23 +22,23 @@ #include "mob.h" #include "../common/races.h" #include "../common/say_link.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "npc_scale_manager.h" inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribute) { std::string entity_variable = "modify_stat_" + attribute; std::string scaling_modified; - if (mob->GetEntityVariable(entity_variable.c_str())) { + if (mob->EntityVariableExists(entity_variable)) { scaling_modified = " *"; } if (attribute == "ac") { - if (mob->GetEntityVariable(std::string("modify_stat_max_hp").c_str())) { + if (mob->EntityVariableExists("modify_stat_max_hp")) { scaling_modified = " *"; } - return commify(std::to_string(mob->GetAC())) + scaling_modified; + return Strings::Commify(std::to_string(mob->GetAC())) + scaling_modified; } if (attribute == "atk") { @@ -51,127 +51,129 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut endurance = mob->CastToClient()->GetEndurance(); } - return commify(std::to_string(endurance)); + return Strings::Commify(std::to_string(endurance)); } if (attribute == "hp") { - return commify(std::to_string(mob->GetHP())); + return Strings::Commify(std::to_string(mob->GetHP())); } if (attribute == "hp_min_max") { - if (mob->GetEntityVariable(std::string("modify_stat_max_hp").c_str())) { + if (mob->EntityVariableExists("modify_stat_max_hp")) { scaling_modified = " *"; } - return commify(std::to_string(mob->GetHP())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxHP())) + " (" + + return Strings::Commify(std::to_string(mob->GetHP())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxHP())) + " (" + std::to_string((int) mob->GetHPRatio()) + "%)"; } if (attribute == "mana") { - return commify(std::to_string(mob->GetMana())); + return Strings::Commify(std::to_string(mob->GetMana())); } if (attribute == "mp_min_max") { - return commify(std::to_string(mob->GetMana())) + " / " + commify(std::to_string(mob->GetMaxMana())) + " (" + + return Strings::Commify(std::to_string(mob->GetMana())) + " / " + + Strings::Commify(std::to_string(mob->GetMaxMana())) + " (" + std::to_string((int) mob->GetManaPercent()) + "%)"; } if (attribute == "end_min_max") { - return commify(std::to_string(mob->GetEndurance())) + " / " + commify(std::to_string(mob->GetMaxEndurance())) + " (" + + return Strings::Commify(std::to_string(mob->GetEndurance())) + " / " + + Strings::Commify(std::to_string(mob->GetMaxEndurance())) + " (" + std::to_string((int)mob->GetEndurancePercent()) + "%)"; } if (attribute == "str") { - return commify(std::to_string(mob->GetSTR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxSTR())) + " +" + - commify(std::to_string(mob->GetHeroicSTR())); + return Strings::Commify(std::to_string(mob->GetSTR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxSTR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicSTR())); } if (attribute == "sta") { - return commify(std::to_string(mob->GetSTA())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxSTA())) + " +" + - commify(std::to_string(mob->GetHeroicSTA())); + return Strings::Commify(std::to_string(mob->GetSTA())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxSTA())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicSTA())); } if (attribute == "dex") { - return commify(std::to_string(mob->GetDEX())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxDEX())) + " +" + - commify(std::to_string(mob->GetHeroicDEX())); + return Strings::Commify(std::to_string(mob->GetDEX())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxDEX())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicDEX())); } if (attribute == "agi") { - return commify(std::to_string(mob->GetAGI())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxAGI())) + " +" + - commify(std::to_string(mob->GetHeroicAGI())); + return Strings::Commify(std::to_string(mob->GetAGI())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxAGI())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicAGI())); } if (attribute == "int") { - return commify(std::to_string(mob->GetINT())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxINT())) + " +" + - commify(std::to_string(mob->GetHeroicINT())); + return Strings::Commify(std::to_string(mob->GetINT())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxINT())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicINT())); } if (attribute == "wis") { - return commify(std::to_string(mob->GetWIS())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxWIS())) + " +" + - commify(std::to_string(mob->GetHeroicWIS())); + return Strings::Commify(std::to_string(mob->GetWIS())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxWIS())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicWIS())); } if (attribute == "cha") { - return commify(std::to_string(mob->GetCHA())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxCHA())) + " +" + - commify(std::to_string(mob->GetHeroicCHA())); + return Strings::Commify(std::to_string(mob->GetCHA())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxCHA())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicCHA())); } if (attribute == "mr") { - return commify(std::to_string(mob->GetMR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxMR())) + " +" + - commify(std::to_string(mob->GetHeroicMR())); + return Strings::Commify(std::to_string(mob->GetMR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxMR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicMR())); } if (attribute == "cr") { - return commify(std::to_string(mob->GetCR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxCR())) + " +" + - commify(std::to_string(mob->GetHeroicCR())); + return Strings::Commify(std::to_string(mob->GetCR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxCR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicCR())); } if (attribute == "fr") { - return commify(std::to_string(mob->GetFR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxFR())) + " +" + - commify(std::to_string(mob->GetHeroicFR())); + return Strings::Commify(std::to_string(mob->GetFR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxFR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicFR())); } if (attribute == "pr") { - return commify(std::to_string(mob->GetPR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxPR())) + " +" + - commify(std::to_string(mob->GetHeroicPR())); + return Strings::Commify(std::to_string(mob->GetPR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxPR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicPR())); } if (attribute == "dr") { - return commify(std::to_string(mob->GetDR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxDR())) + " +" + - commify(std::to_string(mob->GetHeroicDR())); + return Strings::Commify(std::to_string(mob->GetDR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxDR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicDR())); } if (attribute == "cr") { - return commify(std::to_string(mob->GetCR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxCR())) + " +" + - commify(std::to_string(mob->GetHeroicCR())); + return Strings::Commify(std::to_string(mob->GetCR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxCR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicCR())); } if (attribute == "pr") { - return commify(std::to_string(mob->GetPR())) + scaling_modified + " / " + - commify(std::to_string(mob->GetMaxPR())) + " +" + - commify(std::to_string(mob->GetHeroicPR())); + return Strings::Commify(std::to_string(mob->GetPR())) + scaling_modified + " / " + + Strings::Commify(std::to_string(mob->GetMaxPR())) + " +" + + Strings::Commify(std::to_string(mob->GetHeroicPR())); } if (attribute == "cor") { - return commify(std::to_string(mob->GetCorrup())) + scaling_modified; + return Strings::Commify(std::to_string(mob->GetCorrup())) + scaling_modified; } if (attribute == "phy") { - return commify(std::to_string(mob->GetPhR())) + scaling_modified; + return Strings::Commify(std::to_string(mob->GetPhR())) + scaling_modified; } if (attribute == "name") { @@ -350,56 +352,56 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut return std::to_string((int)npc->GetAccuracyRating()) + scaling_modified; } if (attribute == "slow_mitigation") { - if (mob->GetEntityVariable(std::string("modify_stat_slow_mitigation").c_str())) { + if (mob->EntityVariableExists("modify_stat_slow_mitigation")) { scaling_modified = " *"; } return std::to_string((int)npc->GetSlowMitigation()) + scaling_modified; } if (attribute == "min_hit") { - if (mob->GetEntityVariable(std::string("modify_stat_min_hit").c_str())) { + if (mob->EntityVariableExists("modify_stat_min_hit")) { scaling_modified = " *"; } - return commify(std::to_string((int)npc->GetMinDMG())) + scaling_modified; + return Strings::Commify(std::to_string((int) npc->GetMinDMG())) + scaling_modified; } if (attribute == "max_hit") { - if (mob->GetEntityVariable(std::string("modify_stat_max_hit").c_str())) { + if (mob->EntityVariableExists("modify_stat_max_hit")) { scaling_modified = " *"; } - return commify(std::to_string((int)npc->GetMaxDMG())) + scaling_modified; + return Strings::Commify(std::to_string((int) npc->GetMaxDMG())) + scaling_modified; } if (attribute == "hp_regen") { - if (mob->GetEntityVariable(std::string("modify_stat_hp_regen").c_str())) { + if (mob->EntityVariableExists("modify_stat_hp_regen")) { scaling_modified = " *"; } - return commify(std::to_string((int)npc->GetHPRegen())) + scaling_modified; + return Strings::Commify(std::to_string((int) npc->GetHPRegen())) + scaling_modified; } if (attribute == "attack_delay") { - if (mob->GetEntityVariable(std::string("modify_stat_attack_delay").c_str())) { + if (mob->EntityVariableExists("modify_stat_attack_delay")) { scaling_modified = " *"; } - return commify(std::to_string(npc->GetAttackDelay())) + scaling_modified; + return Strings::Commify(std::to_string(npc->GetAttackDelay())) + scaling_modified; } if (attribute == "spell_scale") { - if (mob->GetEntityVariable(std::string("modify_stat_spell_scale").c_str())) { + if (mob->EntityVariableExists("modify_stat_spell_scale")) { scaling_modified = " *"; } - return commify(std::to_string((int)npc->GetSpellScale())) + scaling_modified; + return Strings::Commify(std::to_string((int) npc->GetSpellScale())) + scaling_modified; } if (attribute == "heal_scale") { - if (mob->GetEntityVariable(std::string("modify_stat_heal_scale").c_str())) { + if (mob->EntityVariableExists("modify_stat_heal_scale")) { scaling_modified = " *"; } - return commify(std::to_string((int)npc->GetHealScale())) + scaling_modified; + return Strings::Commify(std::to_string((int) npc->GetHealScale())) + scaling_modified; } if (attribute == "avoidance") { - return commify(std::to_string((int)npc->GetAvoidanceRating())) + scaling_modified; + return Strings::Commify(std::to_string((int) npc->GetAvoidanceRating())) + scaling_modified; } npc->GetNPCEmote(npc->GetEmoteID(), 0); @@ -409,68 +411,68 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut Client *client = mob->CastToClient(); if (attribute == "shielding") { - return commify(std::to_string((int)client->GetShielding())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemShieldingCap))); + return Strings::Commify(std::to_string((int) client->GetShielding())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemShieldingCap))); } if (attribute == "spell_shielding") { - return commify(std::to_string((int)client->GetSpellShield())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemSpellShieldingCap))); + return Strings::Commify(std::to_string((int) client->GetSpellShield())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemSpellShieldingCap))); } if (attribute == "dot_shielding") { - return commify(std::to_string((int)client->GetDoTShield())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemDoTShieldingCap))); + return Strings::Commify(std::to_string((int) client->GetDoTShield())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemDoTShieldingCap))); } if (attribute == "stun_resist") { - return commify(std::to_string((int)client->GetStunResist())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemStunResistCap))); + return Strings::Commify(std::to_string((int) client->GetStunResist())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemStunResistCap))); } if (attribute == "damage_shield") { - return commify(std::to_string((int)client->GetDS())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemDamageShieldCap))); + return Strings::Commify(std::to_string((int) client->GetDS())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemDamageShieldCap))); } if (attribute == "avoidance") { - return commify(std::to_string((int) client->GetAvoidance())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemAvoidanceCap))); + return Strings::Commify(std::to_string((int) client->GetAvoidance())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemAvoidanceCap))); } if (attribute == "strikethrough") { - return commify(std::to_string((int) client->GetStrikeThrough())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemStrikethroughCap))); + return Strings::Commify(std::to_string((int) client->GetStrikeThrough())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemStrikethroughCap))); } if (attribute == "accuracy") { - return commify(std::to_string((int) client->GetAccuracy())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemAccuracyCap))); + return Strings::Commify(std::to_string((int) client->GetAccuracy())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemAccuracyCap))); } if (attribute == "combat_effects") { - return commify(std::to_string((int) client->GetCombatEffects())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemCombatEffectsCap))); + return Strings::Commify(std::to_string((int) client->GetCombatEffects())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemCombatEffectsCap))); } if (attribute == "heal_amount") { - return commify(std::to_string((int) client->GetHealAmt())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemHealAmtCap))); + return Strings::Commify(std::to_string((int) client->GetHealAmt())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemHealAmtCap))); } if (attribute == "spell_dmg") { - return commify(std::to_string((int) client->GetSpellDmg())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemSpellDmgCap))); + return Strings::Commify(std::to_string((int) client->GetSpellDmg())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemSpellDmgCap))); } if (attribute == "clairvoyance") { - return commify(std::to_string((int) client->GetClair())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemClairvoyanceCap))); + return Strings::Commify(std::to_string((int) client->GetClair())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemClairvoyanceCap))); } if (attribute == "ds_mitigation") { - return commify(std::to_string((int) client->GetDSMit())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemDSMitigationCap))); + return Strings::Commify(std::to_string((int) client->GetDSMit())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemDSMitigationCap))); } if (attribute == "hp_regen") { - return commify(std::to_string((int64) client->GetHPRegen())) + " / " + - commify(std::to_string((int) RuleI(Character, ItemHealthRegenCap))); + return Strings::Commify(std::to_string((int64) client->GetHPRegen())) + " / " + + Strings::Commify(std::to_string((int) RuleI(Character, ItemHealthRegenCap))); } if (attribute == "mana_regen") { - return commify(std::to_string((int64) client->GetManaRegen())) + " / " + - commify(std::to_string((int64) RuleI(Character, ItemManaRegenCap))); + return Strings::Commify(std::to_string((int64) client->GetManaRegen())) + " / " + + Strings::Commify(std::to_string((int64) RuleI(Character, ItemManaRegenCap))); } if (attribute == "end_regen") { - return commify(std::to_string((int) client->CalcEnduranceRegen())) + " / " + - commify(std::to_string((int) client->CalcEnduranceRegenCap())); + return Strings::Commify(std::to_string((int) client->CalcEnduranceRegen())) + " / " + + Strings::Commify(std::to_string((int) client->CalcEnduranceRegenCap())); } } @@ -528,17 +530,17 @@ inline std::string WriteDisplayInfoSection( std::string attribute_name = attribute; - find_replace(attribute_name, "_min_max", std::string("")); + Strings::FindReplace(attribute_name, "_min_max", std::string("")); /** * Translate attribute names with underscores * "total_to_hit" = "Total To Hit" */ if (attribute_name.find('_') != std::string::npos) { - auto split_string = SplitString(attribute_name, '_'); + auto split_string = Strings::Split(attribute_name, '_'); std::string new_attribute_name; for (std::string &string_value : split_string) { - new_attribute_name += ucfirst(string_value) + " "; + new_attribute_name += Strings::UcFirst(string_value) + " "; } attribute_name = new_attribute_name; } @@ -548,7 +550,7 @@ inline std::string WriteDisplayInfoSection( * "hp" = "HP" */ if (attribute_name.length() <= 3) { - attribute_name = str_toupper(attribute_name); + attribute_name = Strings::ToUpper(attribute_name); } /** @@ -556,11 +558,11 @@ inline std::string WriteDisplayInfoSection( * "avoidance" = "Avoidance" */ if (attribute_name.length() > 3) { - attribute_name = ucfirst(attribute_name); + attribute_name = Strings::UcFirst(attribute_name); } - find_replace(attribute_name, "Proximity", std::string("")); - find_replace(attribute_name, "Roambox", std::string("")); + Strings::FindReplace(attribute_name, "Proximity", std::string("")); + Strings::FindReplace(attribute_name, "Roambox", std::string("")); std::string attribute_value = GetMobAttributeByString(mob, attribute); @@ -588,25 +590,31 @@ inline void NPCCommandsMenu(Client* client, NPC* npc) std::string menu_commands; if (npc->GetGrid() > 0) { - menu_commands += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#grid show", false, "Grid Points") + "] "; + menu_commands += "[" + Saylink::Silent("#grid show", "Grid Points") + "] "; } if (npc->GetEmoteID() > 0) { - std::string saylink = StringFormat("#emotesearch %u", npc->GetEmoteID()); - menu_commands += "[" + EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Emotes") + "] "; + menu_commands += "[" + Saylink::Silent(fmt::format("#emotesearch {}", npc->GetEmoteID()), "Emotes") + "] "; } if (npc->GetLoottableID() > 0) { - menu_commands += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#npcloot show", false, "Loot") + "] "; + menu_commands += "[" + Saylink::Silent("#npcloot show", "Loot") + "] "; } if (npc->IsProximitySet()) { - menu_commands += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#proximity show", false, "Proximity") + "] "; + menu_commands += "[" + Saylink::Silent("#proximity show", "Proximity") + "] "; } if (menu_commands.length() > 0) { - std::string dev_menu = "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools", false, "DevTools") + "] ";; - client->Message(Chat::White, "| %s [Show Commands] %s", dev_menu.c_str(), menu_commands.c_str()); + const auto& dev_menu = Saylink::Silent("#devtools", "DevTools"); + client->Message( + Chat::White, + fmt::format( + "| [{}] [Show Commands] {}", + dev_menu, + menu_commands + ).c_str() + ); } } diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index c323a13c2..001bee9db 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -1075,7 +1075,7 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove return; } - if (who->IsBoat()) { + if (who->GetIsBoat()) { UpdatePathBoat(who, x, y, z, mob_movement_mode); } else if (who->IsUnderwaterOnly()) { diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index 8e5e7316a..9b7520f67 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -99,7 +99,7 @@ void Client::mod_client_death_duel(Mob* killerMob) { return; } void Client::mod_client_death_env() { return; } //Calculated xp before consider modifier, called whenever a client gets XP for killing a mob. -int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } +int64 Client::mod_client_xp(int64 in_xp, NPC *npc) { return(in_xp); } //Client XP formula. Changes here will cause clients to change level after gaining or losing xp. //Either modify this before your server goes live, or be prepared to write a quest script that fixes levels. @@ -128,7 +128,6 @@ float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychan //Final dodge chance float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } -//Monk AC Bonus weight cap. Defined in Combat:MonkACBonusWeight //Usually 15, a monk under this weight threshold gets an AC bonus float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } diff --git a/zone/mod_functions_base.cpp b/zone/mod_functions_base.cpp index a328a868f..fc6d915c9 100644 --- a/zone/mod_functions_base.cpp +++ b/zone/mod_functions_base.cpp @@ -8,7 +8,7 @@ #include "zone.h" #include "spawngroup.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "npc.h" #include "mob.h" #include "client.h" @@ -104,7 +104,7 @@ void Client::mod_client_death_duel(Mob* killerMob) { return; } void Client::mod_client_death_env() { return; } //Calculated xp before consider modifier, called whenever a client gets XP for killing a mob. -int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } +int64 Client::mod_client_xp(int64 in_xp, NPC *npc) { return(in_xp); } //Client XP formula. Changes here will cause clients to change level after gaining or losing xp. //Either modify this before your server goes live, or be prepared to write a quest script that fixes levels. @@ -129,7 +129,6 @@ float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychan //Final dodge chance float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } -//Monk AC Bonus weight cap. Defined in Combat:MonkACBonusWeight //Usually 15, a monk under this weight threshold gets an AC bonus float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } diff --git a/zone/npc.cpp b/zone/npc.cpp index faaf29ea2..d09e1bd45 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -23,7 +23,7 @@ #include "../common/rulesys.h" #include "../common/seperator.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/emu_versions.h" #include "../common/features.h" #include "../common/item_instance.h" @@ -31,6 +31,7 @@ #include "../common/linked_list.h" #include "../common/servertalk.h" #include "../common/say_link.h" +#include "../common/data_verification.h" #include "client.h" #include "entity.h" @@ -42,6 +43,8 @@ #include "water_map.h" #include "npc_scale_manager.h" +#include "bot.h" + #include #include #include @@ -61,62 +64,64 @@ extern EntityList entity_list; NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &position, GravityBehavior iflymode, bool IsCorpse) : Mob( - npc_type_data->name, - npc_type_data->lastname, - npc_type_data->max_hp, - npc_type_data->max_hp, - npc_type_data->gender, - npc_type_data->race, - npc_type_data->class_, - (bodyType) npc_type_data->bodytype, - npc_type_data->deity, - npc_type_data->level, - npc_type_data->npc_id, - npc_type_data->size, - npc_type_data->runspeed, - position, - npc_type_data->light, // innate_light - npc_type_data->texture, - npc_type_data->helmtexture, - npc_type_data->AC, - npc_type_data->ATK, - npc_type_data->STR, - npc_type_data->STA, - npc_type_data->DEX, - npc_type_data->AGI, - npc_type_data->INT, - npc_type_data->WIS, - npc_type_data->CHA, - npc_type_data->haircolor, - npc_type_data->beardcolor, - npc_type_data->eyecolor1, - npc_type_data->eyecolor2, - npc_type_data->hairstyle, - npc_type_data->luclinface, - npc_type_data->beard, - npc_type_data->drakkin_heritage, - npc_type_data->drakkin_tattoo, - npc_type_data->drakkin_details, - npc_type_data->armor_tint, - 0, - npc_type_data->see_invis, // pass see_invis/see_ivu flags to mob constructor - npc_type_data->see_invis_undead, - npc_type_data->see_hide, - npc_type_data->see_improved_hide, - npc_type_data->hp_regen, - npc_type_data->mana_regen, - npc_type_data->qglobal, - npc_type_data->maxlevel, - npc_type_data->scalerate, - npc_type_data->armtexture, - npc_type_data->bracertexture, - npc_type_data->handtexture, - npc_type_data->legtexture, - npc_type_data->feettexture, - npc_type_data->use_model, - npc_type_data->always_aggro, - npc_type_data->hp_regen_per_second -), + npc_type_data->name, + npc_type_data->lastname, + npc_type_data->max_hp, + npc_type_data->max_hp, + npc_type_data->gender, + npc_type_data->race, + npc_type_data->class_, + (bodyType) npc_type_data->bodytype, + npc_type_data->deity, + npc_type_data->level, + npc_type_data->npc_id, + npc_type_data->size, + npc_type_data->runspeed, + position, + npc_type_data->light, // innate_light + npc_type_data->texture, + npc_type_data->helmtexture, + npc_type_data->AC, + npc_type_data->ATK, + npc_type_data->STR, + npc_type_data->STA, + npc_type_data->DEX, + npc_type_data->AGI, + npc_type_data->INT, + npc_type_data->WIS, + npc_type_data->CHA, + npc_type_data->haircolor, + npc_type_data->beardcolor, + npc_type_data->eyecolor1, + npc_type_data->eyecolor2, + npc_type_data->hairstyle, + npc_type_data->luclinface, + npc_type_data->beard, + npc_type_data->drakkin_heritage, + npc_type_data->drakkin_tattoo, + npc_type_data->drakkin_details, + npc_type_data->armor_tint, + 0, + npc_type_data->see_invis, // pass see_invis/see_ivu flags to mob constructor + npc_type_data->see_invis_undead, + npc_type_data->see_hide, + npc_type_data->see_improved_hide, + npc_type_data->hp_regen, + npc_type_data->mana_regen, + npc_type_data->qglobal, + npc_type_data->maxlevel, + npc_type_data->scalerate, + npc_type_data->armtexture, + npc_type_data->bracertexture, + npc_type_data->handtexture, + npc_type_data->legtexture, + npc_type_data->feettexture, + npc_type_data->use_model, + npc_type_data->always_aggro, + npc_type_data->heroic_strikethrough, + npc_type_data->keeps_sold_items, + npc_type_data->hp_regen_per_second + ), attacked_timer(CombatEventTimer_expire), swarm_timer(100), classattack_timer(1000), @@ -149,6 +154,12 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi size = GetRaceGenderDefaultHeight(race, gender); } + // lava dragon is a fixed size model and should always use its default + // otherwise pathing issues + if (race == RACE_LAVA_DRAGON_49) { + size = 5; + } + taunting = false; proximity = nullptr; copper = 0; @@ -198,11 +209,13 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi LevelScale(); } - base_damage = round((max_dmg - min_dmg) / 1.9); - min_damage = min_dmg - round(base_damage / 10.0); - accuracy_rating = npc_type_data->accuracy_rating; - avoidance_rating = npc_type_data->avoidance_rating; - ATK = npc_type_data->ATK; + base_damage = round((max_dmg - min_dmg) / 1.9); + min_damage = min_dmg - round(base_damage / 10.0); + accuracy_rating = npc_type_data->accuracy_rating; + avoidance_rating = npc_type_data->avoidance_rating; + ATK = npc_type_data->ATK; + heroic_strikethrough = npc_type_data->heroic_strikethrough; + keeps_sold_items = npc_type_data->keeps_sold_items; // used for when switch back to charm default_ac = npc_type_data->AC; @@ -236,7 +249,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi if (npc_type_data->flymode >= 0) { flymode = static_cast(npc_type_data->flymode); } - else if (IsBoat()) { + else if (GetIsBoat()) { flymode = GravityBehavior::Floating; } @@ -257,6 +270,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi rare_spawn = npc_type_data->rare_spawn; no_target_hotkey = npc_type_data->no_target_hotkey; primary_faction = 0; + faction_amount = npc_type_data->faction_amount; SetNPCFactionID(npc_type_data->npc_faction_id); @@ -264,8 +278,9 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi HasAISpell = false; HasAISpellEffects = false; innate_proc_spell_id = 0; + m_record_loot_stats = false; - if (GetClass() == MERCERNARY_MASTER && RuleB(Mercs, AllowMercs)) { + if (GetClass() == MERCENARY_MASTER && RuleB(Mercs, AllowMercs)) { LoadMercTypes(); LoadMercs(); } @@ -299,8 +314,14 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi AISpellVar.idle_no_sp_recast_max = static_cast(RuleI(Spells, AI_IdleNoSpellMaxRecast)); AISpellVar.idle_beneficial_chance = static_cast (RuleI(Spells, AI_IdleBeneficialChance)); - AI_Init(); - AI_Start(); + // It's possible for IsBot() to not be set yet during Bot loading, so have to use an alternative to catch Bots + if (!EQ::ValueWithin(npc_type_data->npc_spells_id, EQ::constants::BotSpellIDs::Warrior, EQ::constants::BotSpellIDs::Berserker)) { + AI_Init(); + AI_Start(); + } else { + CastToBot()->AI_Bot_Init(); + CastToBot()->AI_Bot_Start(); + } d_melee_texture1 = npc_type_data->d_melee_texture1; d_melee_texture2 = npc_type_data->d_melee_texture2; @@ -399,7 +420,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi qGlobals = nullptr; - SetEmoteID(static_cast(npc_type_data->emoteid)); + SetEmoteID(static_cast(npc_type_data->emoteid)); InitializeBuffSlots(); CalcBonuses(); @@ -693,18 +714,17 @@ void NPC::QueryLoot(Client* to, bool is_pet_query) } if (!is_pet_query) { - bool has_money = ( - platinum > 0 || - gold > 0 || - silver > 0 || - copper > 0 - ); - if (has_money) { + if ( + platinum || + gold || + silver || + copper + ) { to->Message( Chat::White, fmt::format( "Money | {}", - ConvertMoneyToString( + Strings::Money( platinum, gold, silver, @@ -885,10 +905,10 @@ bool NPC::Process() ProcessFlee(); } - uint32 npc_sitting_regen_bonus = 0; - uint32 pet_regen_bonus = 0; - uint64 npc_regen = 0; - int64 npc_hp_regen = GetNPCHPRegen(); + int64 npc_sitting_regen_bonus = 0; + int64 pet_regen_bonus = 0; + int64 npc_regen = 0; + int64 npc_hp_regen = GetNPCHPRegen(); if (GetAppearance() == eaSitting) { npc_sitting_regen_bonus += 3; @@ -1087,14 +1107,23 @@ void NPC::UpdateEquipmentLight() m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); } -void NPC::Depop(bool StartSpawnTimer) { - uint16 emoteid = GetEmoteID(); - if(emoteid != 0) - DoNPCEmote(ONDESPAWN,emoteid); +void NPC::Depop(bool start_spawn_timer) { + const auto emote_id = GetEmoteID(); + if (emote_id) { + DoNPCEmote(EQ::constants::EmoteEventTypes::OnDespawn, emoteid); + } + + if (IsNPC()) { + parse->EventNPC(EVENT_DESPAWN, this, nullptr, "", 0); + DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); + } else if (IsBot()) { + parse->EventBot(EVENT_DESPAWN, CastToBot(), nullptr, "", 0); + DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); + } + p_depop = true; - if (respawn2) - { - if (StartSpawnTimer) { + if (respawn2) { + if (start_spawn_timer) { respawn2->DeathReset(); } else { respawn2->Depop(); @@ -1213,8 +1242,8 @@ void NPC::SpawnGridNodeNPC(const glm::vec4 &position, int32 grid_id, int32 grid_ auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); - std::string str_zoffset = numberToWords(zoffset); - std::string str_number = numberToWords(grid_number); + std::string str_zoffset = Strings::NumberToWords(zoffset); + std::string str_number = Strings::NumberToWords(grid_number); strcpy(npc_type->name, str_number.c_str()); if (zoffset != 0) { @@ -1552,7 +1581,7 @@ uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand( std::string query = fmt::format( "INSERT INTO spawngroup (name) VALUES('{}{}{}')", zone, - EscapeString(spawn->GetName()), + Strings::Escape(spawn->GetName()), Timer::GetCurrentTime() ); @@ -1768,7 +1797,7 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { int32 texture_profile_material = GetTextureProfileMaterial(material_slot); - Log(Logs::Detail, Logs::MobAppearance, "NPC::GetEquipmentMaterial [%s] material_slot: %u", + Log(Logs::Detail, Logs::MobAppearance, "[%s] material_slot: %u", clean_name, material_slot ); @@ -1868,7 +1897,7 @@ void NPC::PickPocket(Client* thief) continue; auto item_test = database.GetItem(item_iter->item_id); - if (item_test->Magic || !item_test->NoDrop || item_test->IsClassBag() || thief->CheckLoreConflict(item_test)) + if (item_test->Magic || !item_test->NoDrop || item_test->IsClassBag() || thief->CheckLoreConflict(item_test) || item_iter->equip_slot != EQ::invslot::SLOT_INVALID) continue; loot_selection.push_back(std::make_pair(item_test, ((item_test->Stackable) ? (1) : (item_iter->charges)))); @@ -1904,6 +1933,7 @@ void NPC::PickPocket(Client* thief) } RemoveItem(item_inst->GetID()); thief->SendPickPocketResponse(this, 0, PickPocketItem, item_inst->GetItem()); + safe_delete(item_inst); return; } @@ -2422,54 +2452,57 @@ void NPC::SetLevel(uint8 in_level, bool command) SendAppearancePacket(AT_WhoLevel, in_level); } -void NPC::ModifyNPCStat(const char *identifier, const char *new_value) +void NPC::ModifyNPCStat(std::string stat, std::string value) { - std::string id = str_tolower(identifier); - std::string val = new_value; + auto stat_lower = Strings::ToLower(stat); - std::string variable_key = StringFormat("modify_stat_%s", id.c_str()); - SetEntityVariable(variable_key.c_str(), new_value); + auto variable_key = fmt::format( + "modify_stat_{}", + stat_lower + ); - LogNPCScaling("NPC::ModifyNPCStat key: [{}] val: [{}] ", variable_key.c_str(), new_value); + SetEntityVariable(variable_key, value); - if (id == "ac") { - AC = atoi(val.c_str()); + LogNPCScaling("NPC::ModifyNPCStat: Key [{}] Value [{}] ", variable_key, value); + + if (stat_lower == "ac") { + AC = atoi(value.c_str()); CalcAC(); return; } - else if (id == "str") { - STR = atoi(val.c_str()); + else if (stat_lower == "str") { + STR = atoi(value.c_str()); return; } - else if (id == "sta") { - STA = atoi(val.c_str()); + else if (stat_lower == "sta") { + STA = atoi(value.c_str()); return; } - else if (id == "agi") { - AGI = atoi(val.c_str()); + else if (stat_lower == "agi") { + AGI = atoi(value.c_str()); CalcAC(); return; } - else if (id == "dex") { - DEX = atoi(val.c_str()); + else if (stat_lower == "dex") { + DEX = atoi(value.c_str()); return; } - else if (id == "wis") { - WIS = atoi(val.c_str()); + else if (stat_lower == "wis") { + WIS = atoi(value.c_str()); CalcMaxMana(); return; } - else if (id == "int" || id == "_int") { - INT = atoi(val.c_str()); + else if (stat_lower == "int" || stat_lower == "_int") { + INT = atoi(value.c_str()); CalcMaxMana(); return; } - else if (id == "cha") { - CHA = atoi(val.c_str()); + else if (stat_lower == "cha") { + CHA = atoi(value.c_str()); return; } - else if (id == "max_hp") { - base_hp = std::stoull(val.c_str()); + else if (stat_lower == "max_hp") { + base_hp = std::stoull(value.c_str()); CalcMaxHP(); if (current_hp > max_hp) { @@ -2478,48 +2511,44 @@ void NPC::ModifyNPCStat(const char *identifier, const char *new_value) return; } - else if (id == "max_mana") { - npc_mana = std::stoull(val.c_str()); + else if (stat_lower == "max_mana") { + npc_mana = std::stoull(value.c_str()); CalcMaxMana(); if (current_mana > max_mana) { current_mana = max_mana; } return; } - else if (id == "mr") { - MR = atoi(val.c_str()); + else if (stat_lower == "mr") { + MR = atoi(value.c_str()); return; } - else if (id == "fr") { - FR = atoi(val.c_str()); + else if (stat_lower == "fr") { + FR = atoi(value.c_str()); return; } - else if (id == "cr") { - CR = atoi(val.c_str()); + else if (stat_lower == "cr") { + CR = atoi(value.c_str()); return; } - else if (id == "cor") { - Corrup = atoi(val.c_str()); + else if (stat_lower == "cor") { + Corrup = atoi(value.c_str()); return; } - else if (id == "phr") { - PhR = atoi(val.c_str()); + else if (stat_lower == "pr") { + PR = atoi(value.c_str()); return; } - else if (id == "pr") { - PR = atoi(val.c_str()); + else if (stat_lower == "dr") { + DR = atoi(value.c_str()); return; } - else if (id == "dr") { - DR = atoi(val.c_str()); + else if (stat_lower == "phr") { + PhR = atoi(value.c_str()); return; } - else if (id == "phr") { - PhR = atoi(val.c_str()); - return; - } - else if (id == "runspeed") { - runspeed = (float) atof(val.c_str()); + else if (stat_lower == "runspeed") { + runspeed = (float) atof(value.c_str()); base_runspeed = (int) ((float) runspeed * 40.0f); base_walkspeed = base_runspeed * 100 / 265; walkspeed = ((float) base_walkspeed) * 0.025f; @@ -2528,283 +2557,296 @@ void NPC::ModifyNPCStat(const char *identifier, const char *new_value) CalcBonuses(); return; } - else if (id == "special_attacks") { - NPCSpecialAttacks(val.c_str(), 0, 1); + else if (stat_lower == "special_attacks") { + NPCSpecialAttacks(value.c_str(), 0, 1); return; } - else if (id == "special_abilities") { - ProcessSpecialAbilities(val.c_str()); + else if (stat_lower == "special_abilities") { + ProcessSpecialAbilities(value.c_str()); return; } - else if (id == "attack_speed") { - attack_speed = (float) atof(val.c_str()); + else if (stat_lower == "attack_speed") { + attack_speed = (float) atof(value.c_str()); CalcBonuses(); return; } - else if (id == "attack_delay") { + else if (stat_lower == "attack_delay") { /* TODO: fix DB */ - attack_delay = atoi(val.c_str()) * 100; + attack_delay = atoi(value.c_str()) * 100; CalcBonuses(); return; } - else if (id == "atk") { - ATK = atoi(val.c_str()); + else if (stat_lower == "atk") { + ATK = atoi(value.c_str()); return; } - else if (id == "accuracy") { - accuracy_rating = atoi(val.c_str()); + else if (stat_lower == "accuracy") { + accuracy_rating = atoi(value.c_str()); return; } - else if (id == "avoidance") { - avoidance_rating = atoi(val.c_str()); + else if (stat_lower == "avoidance") { + avoidance_rating = atoi(value.c_str()); return; } - else if (id == "trackable") { - trackable = atoi(val.c_str()); + else if (stat_lower == "trackable") { + trackable = atoi(value.c_str()); return; } - else if (id == "min_hit") { - min_dmg = atoi(val.c_str()); + else if (stat_lower == "min_hit") { + min_dmg = atoi(value.c_str()); // TODO: fix DB base_damage = round((max_dmg - min_dmg) / 1.9); min_damage = min_dmg - round(base_damage / 10.0); return; } - else if (id == "max_hit") { - max_dmg = atoi(val.c_str()); + else if (stat_lower == "max_hit") { + max_dmg = atoi(value.c_str()); // TODO: fix DB base_damage = round((max_dmg - min_dmg) / 1.9); min_damage = min_dmg - round(base_damage / 10.0); return; } - else if (id == "attack_count") { - attack_count = atoi(val.c_str()); + else if (stat_lower == "attack_count") { + attack_count = atoi(value.c_str()); return; } - else if (id == "see_invis") { - see_invis = atoi(val.c_str()); + else if (stat_lower == "see_invis") { + see_invis = atoi(value.c_str()); return; } - else if (id == "see_invis_undead") { - see_invis_undead = atoi(val.c_str()); + else if (stat_lower == "see_invis_undead") { + see_invis_undead = atoi(value.c_str()); return; } - else if (id == "see_hide") { - see_hide = atoi(val.c_str()); + else if (stat_lower == "see_hide") { + see_hide = atoi(value.c_str()); return; } - else if (id == "see_improved_hide") { - see_improved_hide = atoi(val.c_str()); + else if (stat_lower == "see_improved_hide") { + see_improved_hide = atoi(value.c_str()); return; } - else if (id == "hp_regen") { - hp_regen = strtoll(val.c_str(), nullptr, 10); + else if (stat_lower == "hp_regen") { + hp_regen = strtoll(value.c_str(), nullptr, 10); return; } - else if (id == "hp_regen_per_second") { - hp_regen_per_second = strtoll(val.c_str(), nullptr, 10); + else if (stat_lower == "hp_regen_per_second") { + hp_regen_per_second = strtoll(value.c_str(), nullptr, 10); return; } - else if (id == "mana_regen") { - mana_regen = strtoll(val.c_str(), nullptr, 10); + else if (stat_lower == "mana_regen") { + mana_regen = strtoll(value.c_str(), nullptr, 10); return; } - else if (id == "level") { - SetLevel(atoi(val.c_str())); + else if (stat_lower == "level") { + SetLevel(atoi(value.c_str())); return; } - else if (id == "aggro") { - pAggroRange = atof(val.c_str()); + else if (stat_lower == "aggro") { + pAggroRange = atof(value.c_str()); return; } - else if (id == "assist") { - pAssistRange = atof(val.c_str()); + else if (stat_lower == "assist") { + pAssistRange = atof(value.c_str()); return; } - else if (id == "slow_mitigation") { - slow_mitigation = atoi(val.c_str()); + else if (stat_lower == "slow_mitigation") { + slow_mitigation = atoi(value.c_str()); return; } - else if (id == "loottable_id") { - loottable_id = atof(val.c_str()); + else if (stat_lower == "loottable_id") { + loottable_id = atof(value.c_str()); return; } - else if (id == "healscale") { - healscale = atof(val.c_str()); + else if (stat_lower == "healscale") { + healscale = atof(value.c_str()); return; } - else if (id == "spellscale") { - spellscale = atof(val.c_str()); + else if (stat_lower == "spellscale") { + spellscale = atof(value.c_str()); return; } - else if (id == "npc_spells_id") { - AI_AddNPCSpells(atoi(val.c_str())); + else if (stat_lower == "npc_spells_id") { + AI_AddNPCSpells(atoi(value.c_str())); return; } - else if (id == "npc_spells_effects_id") { - AI_AddNPCSpellsEffects(atoi(val.c_str())); + else if (stat_lower == "npc_spells_effects_id") { + AI_AddNPCSpellsEffects(atoi(value.c_str())); CalcBonuses(); return; } + else if (stat_lower == "heroic_strikethrough") { + heroic_strikethrough = atoi(value.c_str()); + return; + } + else if (stat_lower == "keeps_sold_items") { + SetKeepsSoldItems(Strings::ToBool(value)); + return; + } } -float NPC::GetNPCStat(const char *identifier) +float NPC::GetNPCStat(std::string stat) { - std::string id = str_tolower(identifier); + auto stat_lower = Strings::ToLower(stat); - if (id == "ac") { + if (stat_lower == "ac") { return AC; } - else if (id == "str") { + else if (stat_lower == "str") { return STR; } - else if (id == "sta") { + else if (stat_lower == "sta") { return STA; } - else if (id == "agi") { + else if (stat_lower == "agi") { return AGI; } - else if (id == "dex") { + else if (stat_lower == "dex") { return DEX; } - else if (id == "wis") { + else if (stat_lower == "wis") { return WIS; } - else if (id == "int" || id == "_int") { + else if (stat_lower == "int" || stat_lower == "_int") { return INT; } - else if (id == "cha") { + else if (stat_lower == "cha") { return CHA; } - else if (id == "max_hp") { + else if (stat_lower == "max_hp") { return base_hp; } - else if (id == "max_mana") { + else if (stat_lower == "max_mana") { return npc_mana; } - else if (id == "mr") { + else if (stat_lower == "mr") { return MR; } - else if (id == "fr") { + else if (stat_lower == "fr") { return FR; } - else if (id == "cr") { + else if (stat_lower == "cr") { return CR; } - else if (id == "cor") { + else if (stat_lower == "cor") { return Corrup; } - else if (id == "phr") { + else if (stat_lower == "phr") { return PhR; } - else if (id == "pr") { + else if (stat_lower == "pr") { return PR; } - else if (id == "dr") { + else if (stat_lower == "dr") { return DR; } - else if (id == "phr") { + else if (stat_lower == "phr") { return PhR; } - else if (id == "runspeed") { + else if (stat_lower == "runspeed") { return runspeed; } - - else if (id == "attack_speed") { + else if (stat_lower == "attack_speed") { return attack_speed; } - else if (id == "attack_delay") { + else if (stat_lower == "attack_delay") { return attack_delay; } - else if (id == "atk") { + else if (stat_lower == "atk") { return ATK; } - else if (id == "accuracy") { + else if (stat_lower == "accuracy") { return accuracy_rating; } - else if (id == "avoidance") { + else if (stat_lower == "avoidance") { return avoidance_rating; } - else if (id == "trackable") { + else if (stat_lower == "trackable") { return trackable; } - else if (id == "min_hit") { + else if (stat_lower == "min_hit") { return min_dmg; } - else if (id == "max_hit") { + else if (stat_lower == "max_hit") { return max_dmg; } - else if (id == "attack_count") { + else if (stat_lower == "attack_count") { return attack_count; } - else if (id == "see_invis") { + else if (stat_lower == "see_invis") { return see_invis; } - else if (id == "see_invis_undead") { + else if (stat_lower == "see_invis_undead") { return see_invis_undead; } - else if (id == "see_hide") { + else if (stat_lower == "see_hide") { return see_hide; } - else if (id == "see_improved_hide") { + else if (stat_lower == "see_improved_hide") { return see_improved_hide; } - else if (id == "hp_regen") { + else if (stat_lower == "hp_regen") { return hp_regen; } - else if (id == "hp_regen_per_second") { + else if (stat_lower == "hp_regen_per_second") { return hp_regen_per_second; } - else if (id == "mana_regen") { + else if (stat_lower == "mana_regen") { return mana_regen; } - else if (id == "level") { + else if (stat_lower == "level") { return GetOrigLevel(); } - else if (id == "aggro") { + else if (stat_lower == "aggro") { return pAggroRange; } - else if (id == "assist") { + else if (stat_lower == "assist") { return pAssistRange; } - else if (id == "slow_mitigation") { + else if (stat_lower == "slow_mitigation") { return slow_mitigation; } - else if (id == "loottable_id") { + else if (stat_lower == "loottable_id") { return loottable_id; } - else if (id == "healscale") { + else if (stat_lower == "healscale") { return healscale; } - else if (id == "spellscale") { + else if (stat_lower == "spellscale") { return spellscale; } - else if (id == "npc_spells_id") { + else if (stat_lower == "npc_spells_id") { return npc_spells_id; } - else if (id == "npc_spells_effects_id") { + else if (stat_lower == "npc_spells_effects_id") { return npc_spells_effects_id; } + else if (stat_lower == "heroic_strikethrough") { + return heroic_strikethrough; + } + else if (stat_lower == "keeps_sold_items") { + return keeps_sold_items; + } //default values - else if (id == "default_ac") { + else if (stat_lower == "default_ac") { return default_ac; } - else if (id == "default_min_hit") { + else if (stat_lower == "default_min_hit") { return default_min_dmg; } - else if (id == "default_max_hit") { + else if (stat_lower == "default_max_hit") { return default_max_dmg; } - else if (id == "default_attack_delay") { + else if (stat_lower == "default_attack_delay") { return default_attack_delay; } - else if (id == "default_accuracy") { + else if (stat_lower == "default_accuracy") { return default_accuracy_rating; } - else if (id == "default_avoidance") { + else if (stat_lower == "default_avoidance") { return default_avoidance_rating; } - else if (id == "default_atk") { + else if (stat_lower == "default_atk") { return default_atk; } @@ -2927,13 +2969,13 @@ uint32 NPC::GetSpawnPointID() const void NPC::NPCSlotTexture(uint8 slot, uint16 texture) { - if (slot == 7) { + if (slot == EQ::invslot::slotNeck) { d_melee_texture1 = texture; } - else if (slot == 8) { + else if (slot == EQ::invslot::slotBack) { d_melee_texture2 = texture; } - else if (slot < 6) { + else if (slot < EQ::invslot::slotShoulders) { // Reserved for texturing individual armor slots } } @@ -3012,7 +3054,13 @@ void NPC::SignalNPC(int _signal_id) signal_q.push_back(_signal_id); } -NPC_Emote_Struct* NPC::GetNPCEmote(uint16 emoteid, uint8 event_) { +void NPC::SendPayload(int payload_id, std::string payload_value) +{ + const auto export_string = fmt::format("{} {}", payload_id, payload_value); + parse->EventNPC(EVENT_PAYLOAD, this, nullptr, export_string, 0); +} + +NPC_Emote_Struct* NPC::GetNPCEmote(uint32 emoteid, uint8 event_) { LinkedListIterator iterator(zone->NPCEmoteList); iterator.Reset(); while(iterator.MoreElements()) @@ -3026,7 +3074,7 @@ NPC_Emote_Struct* NPC::GetNPCEmote(uint16 emoteid, uint8 event_) { return (nullptr); } -void NPC::DoNPCEmote(uint8 event_, uint16 emoteid) +void NPC::DoNPCEmote(uint8 event_, uint32 emoteid) { if(this == nullptr || emoteid == 0) { @@ -3231,27 +3279,29 @@ void NPC::DoQuestPause(Mob *other) { } -void NPC::ChangeLastName(const char* in_lastname) +void NPC::ChangeLastName(std::string last_name) { - auto outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); - GMLastName_Struct* gmn = (GMLastName_Struct*)outapp->pBuffer; - strcpy(gmn->name, GetName()); - strcpy(gmn->gmname, GetName()); - strcpy(gmn->lastname, in_lastname); - gmn->unknown[0]=1; - gmn->unknown[1]=1; - gmn->unknown[2]=1; - gmn->unknown[3]=1; + auto gmn = (GMLastName_Struct*) outapp->pBuffer; + + strn0cpy(gmn->name, GetName(), sizeof(gmn->name)); + strn0cpy(gmn->gmname, GetName(), sizeof(gmn->gmname)); + strn0cpy(gmn->lastname, last_name.c_str(), sizeof(gmn->lastname)); + + gmn->unknown[0] = 1; + gmn->unknown[1] = 1; + gmn->unknown[2] = 1; + gmn->unknown[3] = 1; + entity_list.QueueClients(this, outapp, false); + safe_delete(outapp); } void NPC::ClearLastName() { - std::string WT; - WT = '\0'; //Clear Last Name - ChangeLastName( WT.c_str()); + std::string empty; + ChangeLastName(empty); } void NPC::DepopSwarmPets() @@ -3444,6 +3494,9 @@ bool NPC::AICheckCloseBeneficialSpells( */ for (auto & close_mob : entity_list.GetCloseMobList(caster, cast_range)) { Mob *mob = close_mob.second; + if (!mob) { + continue; + } if (mob->IsClient()) { continue; @@ -3520,6 +3573,10 @@ void NPC::AIYellForHelp(Mob *sender, Mob *attacker) for (auto &close_mob : entity_list.GetCloseMobList(sender)) { Mob *mob = close_mob.second; + if (!mob) { + continue; + } + float distance = DistanceSquared(m_Position, mob->GetPosition()); if (mob->IsClient()) { @@ -3630,10 +3687,18 @@ void NPC::RecalculateSkills() } } +void NPC::ReloadSpells() { + AI_AddNPCSpells(GetNPCSpellsID()); + AI_AddNPCSpellsEffects(GetNPCSpellsEffectsID()); +} + void NPC::ScaleNPC(uint8 npc_level) { if (GetLevel() != npc_level) { SetLevel(npc_level); + RecalculateSkills(); + ReloadSpells(); } + npc_scale_manager->ResetNPCScaling(this); npc_scale_manager->ScaleNPC(this); } @@ -3687,3 +3752,35 @@ std::vector NPC::GetLootList() { } return npc_items; } + +bool NPC::IsRecordLootStats() const +{ + return m_record_loot_stats; +} + +void NPC::SetRecordLootStats(bool record_loot_stats) +{ + NPC::m_record_loot_stats = record_loot_stats; +} + +void NPC::FlushLootStats() +{ + m_rolled_items = {}; +} + +const std::vector &NPC::GetRolledItems() const +{ + return m_rolled_items; +} + +int NPC::GetRolledItemCount(uint32 item_id) +{ + int rolled_count = 0; + for (auto &e: m_rolled_items) { + if (item_id == e) { + rolled_count++; + } + } + + return rolled_count; +} diff --git a/zone/npc.h b/zone/npc.h index bb47093d2..aeaa2de1b 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -23,7 +23,7 @@ #include "mob.h" #include "qglobals.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "zonedump.h" #include "../common/loottable.h" @@ -35,25 +35,15 @@ #define M_PI 3.141592 #endif -#define LEAVECOMBAT 0 -#define ENTERCOMBAT 1 -#define ONDEATH 2 -#define AFTERDEATH 3 -#define HAILED 4 -#define KILLEDPC 5 -#define KILLEDNPC 6 -#define ONSPAWN 7 -#define ONDESPAWN 8 - typedef struct { - float min_x; - float max_x; - float min_y; - float max_y; - float min_z; - float max_z; - bool say; - bool proximity_set; + float min_x; + float max_x; + float min_y; + float max_y; + float min_z; + float max_z; + bool say; + bool proximity_set; } NPCProximity; struct AISpells_Struct { @@ -76,17 +66,17 @@ struct AISpellsEffects_Struct { }; struct AISpellsVar_Struct { - uint32 fail_recast; + uint32 fail_recast; uint32 engaged_no_sp_recast_min; uint32 engaged_no_sp_recast_max; uint8 engaged_beneficial_self_chance; uint8 engaged_beneficial_other_chance; uint8 engaged_detrimental_chance; - uint32 pursue_no_sp_recast_min; - uint32 pursue_no_sp_recast_max; - uint8 pursue_detrimental_chance; - uint32 idle_no_sp_recast_min; - uint32 idle_no_sp_recast_max; + uint32 pursue_no_sp_recast_min; + uint32 pursue_no_sp_recast_max; + uint8 pursue_detrimental_chance; + uint32 idle_no_sp_recast_min; + uint32 idle_no_sp_recast_max; uint8 idle_beneficial_chance; }; @@ -109,6 +99,13 @@ public: static bool SpawnZoneController(); static int8 GetAILevel(bool iForceReRead = false); + // loot recording / simulator + bool IsRecordLootStats() const; + void SetRecordLootStats(bool record_loot_stats); + void FlushLootStats(); + const std::vector &GetRolledItems() const; + int GetRolledItemCount(uint32 item_id); + NPC(const NPCType* npc_type_data, Spawn2* respawn, const glm::vec4& position, GravityBehavior iflymode, bool IsCorpse = false); virtual ~NPC(); @@ -120,9 +117,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill); virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); - virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr); - virtual bool HasRaid() { return false; } + bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override; + virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } virtual Group* GetGroup() { return 0; } @@ -253,7 +250,7 @@ public: inline void MerchantOpenShop() { merchant_open = true; } inline void MerchantCloseShop() { merchant_open = false; } inline bool IsMerchantOpen() { return merchant_open; } - void Depop(bool StartSpawnTimer = false); + void Depop(bool start_spawn_timer = false); void Stun(int duration); void UnStun(); uint32 GetSwarmOwner(); @@ -264,6 +261,7 @@ public: void PetOnSpawn(NewSpawn_Struct* ns); void SignalNPC(int _signal_id); + void SendPayload(int payload_id, std::string payload_value = std::string()); inline int32 GetNPCFactionID() const { return npc_faction_id; } @@ -271,6 +269,9 @@ public: inline int32 GetPrimaryFaction() const { return primary_faction; } + inline int32 GetFactionAmount() const + { return faction_amount; } + int64 GetNPCHate(Mob *in_ent) { return hate_list.GetEntHateAmount(in_ent); } @@ -283,8 +284,6 @@ public: content_db.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); } - int64 GetFocusEffect(focusType type, uint16 spell_id, Mob* caster = nullptr); - glm::vec4 m_SpawnPoint; uint32 GetMaxDMG() const {return max_dmg;} @@ -320,8 +319,9 @@ public: bool MeetsLootDropLevelRequirements(LootDropEntries_Struct loot_drop, bool verbose=false); + void CheckSignal(); + virtual void DoClassAttacks(Mob *target); - void CheckSignal(); inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; } int64 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; } inline const char* GetAmmoIDfile() const { return ammo_idfile; } @@ -348,6 +348,7 @@ public: int32 GetEquipmentMaterial(uint8 material_slot) const; void NextGuardPosition(); + void SaveGuardSpot(bool ClearGuardSpot = false); void SaveGuardSpot(const glm::vec4 &pos); inline bool IsGuarding() const { return(m_GuardPoint.w != 0); } void SaveGuardSpotCharm(); @@ -408,8 +409,8 @@ public: void SetAvoidanceRating(int32 d) { avoidance_rating = d;} int32 GetRawAC() const { return AC; } - float GetNPCStat(const char *identifier); - void ModifyNPCStat(const char *identifier, const char *new_value); + float GetNPCStat(std::string stat); + void ModifyNPCStat(std::string stat, std::string value); virtual void SetLevel(uint8 in_level, bool command = false); bool IsLDoNTrapped() const { return (ldon_trapped); } @@ -441,7 +442,7 @@ public: virtual int GetKillExpMod() const { return NPCTypedata_ours ? NPCTypedata_ours->exp_mod : NPCTypedata->exp_mod; } - void ChangeLastName(const char* in_lastname); + void ChangeLastName(std::string last_name); void ClearLastName(); bool GetDepop() { return p_depop; } @@ -457,8 +458,8 @@ public: Timer *GetRefaceTimer() const { return reface_timer; } const uint32 GetAltCurrencyType() const { return NPCTypedata->alt_currency_type; } - NPC_Emote_Struct* GetNPCEmote(uint16 emoteid, uint8 event_); - void DoNPCEmote(uint8 event_, uint16 emoteid); + NPC_Emote_Struct* GetNPCEmote(uint32 emoteid, uint8 event_); + void DoNPCEmote(uint8 event_, uint32 emoteid); bool CanTalk(); void DoQuestPause(Mob *other); @@ -487,6 +488,7 @@ public: void SetHeroForgeModel(uint32 model) { herosforgemodel = model; } bool IsRaidTarget() const { return raid_target; }; + bool IsRareSpawn() const { return rare_spawn; } void ResetHPUpdateTimer() { send_hp_update_timer.Start(); } bool IgnoreDespawn() { return ignore_despawn; } @@ -532,8 +534,10 @@ public: void ScaleNPC(uint8 npc_level); void RecalculateSkills(); + void ReloadSpells(); static LootDropEntries_Struct NewLootDropEntry(); + protected: const NPCType* NPCTypedata; @@ -552,6 +556,7 @@ protected: int32 npc_faction_id; int32 primary_faction; + int32 faction_amount; Timer attacked_timer; //running while we are being attacked (damaged) Timer swarm_timer; @@ -575,7 +580,7 @@ protected: virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates = false); virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); AISpellsVar_Struct AISpellVar; - int64 GetFocusEffect(focusType type, uint16 spell_id, Mob* caster, bool from_buff_tic = false); + int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false) override; uint16 innate_proc_spell_id; uint32 npc_spells_effects_id; @@ -676,10 +681,12 @@ protected: private: - uint32 loottable_id; - bool skip_global_loot; - bool skip_auto_scale; - bool p_depop; + uint32 loottable_id; + bool skip_global_loot; + bool skip_auto_scale; + bool p_depop; + bool m_record_loot_stats; + std::vector m_rolled_items = {}; }; #endif diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index 086abf75d..ac9cd3bee 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -19,7 +19,7 @@ */ #include "npc_scale_manager.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/repositories/npc_scale_global_base_repository.h" #include "../common/repositories/npc_types_repository.h" @@ -28,7 +28,7 @@ */ void NpcScaleManager::ScaleNPC(NPC *npc) { - if (npc->IsSkipAutoScale()) { + if (npc->IsSkipAutoScale() || npc->GetNPCTypeID() == 0) { return; } @@ -149,9 +149,9 @@ void NpcScaleManager::ScaleNPC(NPC *npc) std::string scale_log; for (const auto &stat : scaling_stats) { - std::string variable = StringFormat("modify_stat_%s", stat.c_str()); - if (npc->EntityVariableExists(variable.c_str())) { - scale_log += stat + ": " + npc->GetEntityVariable(variable.c_str()) + " "; + auto v = fmt::format("modify_stat_{}", stat); + if (npc->EntityVariableExists(v)) { + scale_log += fmt::format("{}: {} ", stat, npc->GetEntityVariable(v)); } } @@ -169,9 +169,9 @@ void NpcScaleManager::ScaleNPC(NPC *npc) void NpcScaleManager::ResetNPCScaling(NPC *npc) { for (const auto &scaling_stat : scaling_stats) { - std::string stat_name = fmt::format("modify_stat_{}", scaling_stat); - std::string reset_value = "0"; - if (npc->EntityVariableExists(stat_name.c_str())) { + auto stat_name = fmt::format("modify_stat_{}", scaling_stat); + auto reset_value = std::to_string(0); + if (npc->EntityVariableExists(stat_name)) { npc->ModifyNPCStat(scaling_stat.c_str(), reset_value.c_str()); } } @@ -179,7 +179,8 @@ void NpcScaleManager::ResetNPCScaling(NPC *npc) bool NpcScaleManager::LoadScaleData() { - for (auto &s: NpcScaleGlobalBaseRepository::All(content_db)) { + auto rows = NpcScaleGlobalBaseRepository::All(content_db); + for (auto &s: rows) { global_npc_scale scale_data; scale_data.type = s.type; @@ -222,7 +223,7 @@ bool NpcScaleManager::LoadScaleData() ); } - LogNPCScaling("Global Base Scaling Data Loaded"); + LogInfo("Loaded [{}] global scaling data entries", Strings::Commify(rows.size())); return true; } @@ -463,7 +464,7 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc) if (!g.level) { LogNPCScaling( - "NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically NPC: [{}] - scaling data not found for type: [{}] level: [{}]", + "NPC: [{}] - scaling data not found for type: [{}] level: [{}]", npc->GetCleanName(), npc_type, npc_level @@ -521,7 +522,7 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc) if (!d.level) { LogNPCScaling( - "NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically NPC: [{}] - scaling data not found for type: [{}] level: [{}]", + "NPC: [{}] - scaling data not found for type: [{}] level: [{}]", npc->GetCleanName(), npc_type, npc_level diff --git a/zone/object.cpp b/zone/object.cpp index 7962c7ef9..be6974934 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -17,7 +17,7 @@ */ #include "../common/global_define.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "entity.h" @@ -26,7 +26,7 @@ #include "quest_parser_collection.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include @@ -144,8 +144,8 @@ Object::Object(Client* client, const EQ::ItemInstance* inst) // Set object name if (inst) { const EQ::ItemData* item = inst->GetItem(); - if (item && item->IDFile) { - if (strlen(item->IDFile) == 0) { + if (item) { + if (item->IDFile[0] == '\0') { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); } else { @@ -200,8 +200,8 @@ Object::Object(const EQ::ItemInstance *inst, float x, float y, float z, float he // Set object name if (inst) { const EQ::ItemData* item = inst->GetItem(); - if (item && item->IDFile) { - if (strlen(item->IDFile) == 0) { + if (item) { + if (item->IDFile[0] == '\0') { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); } else { @@ -341,7 +341,7 @@ const EQ::ItemInstance* Object::GetItem(uint8 index) { void Object::PutItem(uint8 index, const EQ::ItemInstance* inst) { if (index > 9) { - LogError("Object::PutItem: Invalid index specified ([{}])", index); + LogError("Invalid index specified ([{}])", index); return; } @@ -412,6 +412,7 @@ EQ::ItemInstance* Object::PopItem(uint8 index) void Object::CreateSpawnPacket(EQApplicationPacket* app) { app->SetOpcode(OP_GroundSpawn); + safe_delete_array(app->pBuffer); app->pBuffer = new uchar[sizeof(Object_Struct)]; app->size = sizeof(Object_Struct); memcpy(app->pBuffer, &m_data, sizeof(Object_Struct)); @@ -420,6 +421,7 @@ void Object::CreateSpawnPacket(EQApplicationPacket* app) void Object::CreateDeSpawnPacket(EQApplicationPacket* app) { app->SetOpcode(OP_ClickObject); + safe_delete_array(app->pBuffer); app->pBuffer = new uchar[sizeof(ClickObject_Struct)]; app->size = sizeof(ClickObject_Struct); memset(app->pBuffer, 0, sizeof(ClickObject_Struct)); @@ -475,7 +477,7 @@ void Object::RandomSpawn(bool send_packet) { } } - LogInfo("Object::RandomSpawn([{}]): [{}] ([{}], [{}], [{}])", m_data.object_name, m_inst->GetID(), m_data.x, m_data.y, m_data.z); + LogInfo("[{}] [{}] ([{}] [{}] [{}])", m_data.object_name, m_inst->GetID(), m_data.x, m_data.y, m_data.z); respawn_timer.Disable(); @@ -510,7 +512,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) database.GetItemRecastTimestamp(sender->CharacterID(), item->RecastType)); std::string export_string = fmt::format("{}", item->ID); - std::vector args; + std::vector args; args.push_back(m_inst); if(parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, export_string, GetID(), &args)) { @@ -533,6 +535,15 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) sender->PutItemInInventory(EQ::invslot::slotCursor, *m_inst, false); sender->SendItemPacket(EQ::invslot::slotCursor, m_inst, ItemPacketTrade); + // Could be an undiscovered ground_spawn + if (m_ground_spawn && (RuleB(Character, EnableDiscoveredItems))) + { + if (!sender->GetGM() && !sender->IsDiscovered(item->ID)) + { + sender->DiscoverItem(item->ID); + } + } + if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet sender->DeleteItemInInventory(EQ::invslot::slotCursor); @@ -1055,34 +1066,78 @@ void Object::SetHeading(float heading) safe_delete(app2); } -void Object::SetEntityVariable(const char *id, const char *m_var) +bool Object::ClearEntityVariables() { - std::string n_m_var = m_var; - o_EntityVariables[id] = n_m_var; -} - -const char* Object::GetEntityVariable(const char *id) -{ - if(!id) - return nullptr; - - auto iter = o_EntityVariables.find(id); - if(iter != o_EntityVariables.end()) - { - return iter->second.c_str(); - } - return nullptr; -} - -bool Object::EntityVariableExists(const char * id) -{ - if(!id) + if (o_EntityVariables.empty()) { return false; + } - auto iter = o_EntityVariables.find(id); - if(iter != o_EntityVariables.end()) - { + o_EntityVariables.clear(); + return true; +} + +bool Object::DeleteEntityVariable(std::string variable_name) +{ + if (o_EntityVariables.empty() || variable_name.empty()) { + return false; + } + + auto v = o_EntityVariables.find(variable_name); + if (v == o_EntityVariables.end()) { + return false; + } + + o_EntityVariables.erase(v); + return true; +} + +std::string Object::GetEntityVariable(std::string variable_name) +{ + if (o_EntityVariables.empty() || variable_name.empty()) { + return std::string(); + } + + const auto& v = o_EntityVariables.find(variable_name); + if (v != o_EntityVariables.end()) { + return v->second; + } + + return std::string(); +} + +std::vector Object::GetEntityVariables() +{ + std::vector l; + if (o_EntityVariables.empty()) { + return l; + } + + for (const auto& v : o_EntityVariables) { + l.push_back(v.first); + } + + return l; +} + +bool Object::EntityVariableExists(std::string variable_name) +{ + if (o_EntityVariables.empty() || variable_name.empty()) { + return false; + } + + const auto& v = o_EntityVariables.find(variable_name); + if (v != o_EntityVariables.end()) { return true; } + return false; } + +void Object::SetEntityVariable(std::string variable_name, std::string variable_value) +{ + if (variable_name.empty()) { + return; + } + + o_EntityVariables[variable_name] = variable_value; +} diff --git a/zone/object.h b/zone/object.h index 1ab4463f1..13232dc24 100644 --- a/zone/object.h +++ b/zone/object.h @@ -171,9 +171,12 @@ public: void SetDisplayName(const char *in_name); const char *GetDisplayName() const { return m_display_name; } - const char* GetEntityVariable(const char *id); - void SetEntityVariable(const char *id, const char *m_var); - bool EntityVariableExists(const char *id); + bool ClearEntityVariables(); + bool DeleteEntityVariable(std::string variable_name); + std::string GetEntityVariable(std::string variable_name); + std::vector GetEntityVariables(); + void SetEntityVariable(std::string variable_name, std::string variable_value); + bool EntityVariableExists(std::string variable_name); protected: void ResetState(); // Set state back to original diff --git a/zone/pathfinder_interface.cpp b/zone/pathfinder_interface.cpp index 68696b9d6..3a5c07506 100644 --- a/zone/pathfinder_interface.cpp +++ b/zone/pathfinder_interface.cpp @@ -3,15 +3,16 @@ #include "pathfinder_null.h" #include "pathfinder_nav_mesh.h" #include "pathfinder_waypoint.h" +#include "../common/path_manager.h" #include #include IPathfinder *IPathfinder::Load(const std::string &zone) { struct stat statbuffer; - std::string navmesh_path = fmt::format("maps/nav/{0}.nav", zone); + std::string navmesh_path = fmt::format("{}/maps/nav/{}.nav", path.GetServerPath(), zone); if (stat(navmesh_path.c_str(), &statbuffer) == 0) { return new PathfinderNavmesh(navmesh_path); } - + return new PathfinderNull(); } diff --git a/zone/pathfinder_nav_mesh.cpp b/zone/pathfinder_nav_mesh.cpp index c644a45e0..9877b8323 100644 --- a/zone/pathfinder_nav_mesh.cpp +++ b/zone/pathfinder_nav_mesh.cpp @@ -34,19 +34,19 @@ PathfinderNavmesh::~PathfinderNavmesh() IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags) { partial = false; - + if (!m_impl->nav_mesh) { return IPath(); } - + if (!m_impl->query) { m_impl->query = dtAllocNavMeshQuery(); } - + m_impl->query->init(m_impl->nav_mesh, RuleI(Pathing, MaxNavmeshNodes)); glm::vec3 current_location(start.x, start.z, start.y); glm::vec3 dest_location(end.x, end.z, end.y); - + dtQueryFilter filter; filter.setIncludeFlags(flags); filter.setAreaCost(0, 1.0f); //Normal @@ -59,48 +59,48 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl filter.setAreaCost(8, 1.0f); //General Area filter.setAreaCost(9, 0.1f); //Portal filter.setAreaCost(10, 0.1f); //Prefer - + dtPolyRef start_ref; dtPolyRef end_ref; glm::vec3 ext(5.0f, 100.0f, 5.0f); - + m_impl->query->findNearestPoly(¤t_location[0], &ext[0], &filter, &start_ref, 0); m_impl->query->findNearestPoly(&dest_location[0], &ext[0], &filter, &end_ref, 0); - + if (!start_ref || !end_ref) { return IPath(); } - + int npoly = 0; dtPolyRef path[1024] = { 0 }; auto status = m_impl->query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &filter, path, &npoly, 1024); - + if (npoly) { glm::vec3 epos = dest_location; if (path[npoly - 1] != end_ref) { m_impl->query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0); partial = true; - + auto dist = DistanceSquared(epos, current_location); if (dist < 10000.0f) { stuck = true; } } - + float straight_path[2048 * 3]; unsigned char straight_path_flags[2048]; - + int n_straight_polys; dtPolyRef straight_path_polys[2048]; - + status = m_impl->query->findStraightPath(¤t_location[0], &epos[0], path, npoly, straight_path, straight_path_flags, straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS); - + if (dtStatusFailed(status)) { return IPath(); } - + if (n_straight_polys) { IPath Route; for (int i = 0; i < n_straight_polys; ++i) @@ -109,9 +109,9 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl node.x = straight_path[i * 3]; node.z = straight_path[i * 3 + 1]; node.y = straight_path[i * 3 + 2]; - + Route.push_back(node); - + unsigned short flag = 0; if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) { if (flag & 512) { @@ -119,11 +119,11 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl } } } - + return Route; } } - + IPath Route; Route.push_back(end); return Route; @@ -132,19 +132,19 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions &opts) { partial = false; - + if (!m_impl->nav_mesh) { return IPath(); } - + if (!m_impl->query) { m_impl->query = dtAllocNavMeshQuery(); } - + m_impl->query->init(m_impl->nav_mesh, RuleI(Pathing, MaxNavmeshNodes)); glm::vec3 current_location(start.x, start.z, start.y); glm::vec3 dest_location(end.x, end.z, end.y); - + dtQueryFilter filter; filter.setIncludeFlags(opts.flags); filter.setAreaCost(0, opts.flag_cost[0]); //Normal @@ -157,83 +157,83 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm filter.setAreaCost(8, opts.flag_cost[7]); //General Area filter.setAreaCost(9, opts.flag_cost[8]); //Portal filter.setAreaCost(10, opts.flag_cost[9]); //Prefer - + static const int max_polys = 256; dtPolyRef start_ref; dtPolyRef end_ref; glm::vec3 ext(10.0f, 200.0f, 10.0f); - + m_impl->query->findNearestPoly(¤t_location[0], &ext[0], &filter, &start_ref, 0); m_impl->query->findNearestPoly(&dest_location[0], &ext[0], &filter, &end_ref, 0); - + if (!start_ref || !end_ref) { return IPath(); } - + int npoly = 0; dtPolyRef path[max_polys] = { 0 }; auto status = m_impl->query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &filter, path, &npoly, max_polys); - + if (npoly) { glm::vec3 epos = dest_location; if (path[npoly - 1] != end_ref) { m_impl->query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0); partial = true; - + auto dist = DistanceSquared(epos, current_location); if (dist < 10000.0f) { stuck = true; } } - + int n_straight_polys; glm::vec3 straight_path[max_polys]; unsigned char straight_path_flags[max_polys]; dtPolyRef straight_path_polys[max_polys]; - + auto status = m_impl->query->findStraightPath(¤t_location[0], &epos[0], path, npoly, (float*)&straight_path[0], straight_path_flags, straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS); - + if (dtStatusFailed(status)) { return IPath(); } - + if (n_straight_polys) { if (opts.smooth_path) { IPath Route; - + //Add the first point { auto &flag = straight_path_flags[0]; if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) { auto &p = straight_path[0]; - + Route.push_back(glm::vec3(p.x, p.z, p.y)); } else { auto &p = straight_path[0]; - + float h = 0.0f; if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, p, &h))) { p.y = h + opts.offset; } - + Route.push_back(glm::vec3(p.x, p.z, p.y)); } } - + for (int i = 0; i < n_straight_polys - 1; ++i) { auto &flag = straight_path_flags[i]; - + if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) { auto &poly = straight_path_polys[i]; - + auto &p2 = straight_path[i + 1]; glm::vec3 node(p2.x, p2.z, p2.y); Route.push_back(node); - + unsigned short pflag = 0; if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &pflag))) { if (pflag & 512) { @@ -248,12 +248,12 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm auto dir = glm::normalize(p2 - p1); float total = 0.0f; glm::vec3 previous_pt = p1; - + while (total < dist) { glm::vec3 current_pt; float dist_to_move = opts.step_size; float ff = opts.step_size / 2.0f; - + if (total + dist_to_move + ff >= dist) { current_pt = p2; total = dist; @@ -262,18 +262,18 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm total += dist_to_move; current_pt = p1 + dir * total; } - + float h = 0.0f; if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, current_pt, &h))) { current_pt.y = h + opts.offset; } - + Route.push_back(glm::vec3(current_pt.x, current_pt.z, current_pt.y)); previous_pt = current_pt; } } } - + return Route; } else { @@ -283,7 +283,7 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm auto ¤t = straight_path[i]; glm::vec3 node(current.x, current.z, current.y); Route.push_back(node); - + unsigned short flag = 0; if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) { if (flag & 512) { @@ -291,7 +291,7 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm } } } - + return Route; } } diff --git a/zone/pathfinder_waypoint.cpp b/zone/pathfinder_waypoint.cpp index 58dcd1582..19ad3b135 100644 --- a/zone/pathfinder_waypoint.cpp +++ b/zone/pathfinder_waypoint.cpp @@ -12,7 +12,7 @@ #include "zone.h" #include "client.h" #include "../common/eqemu_logsys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/rulesys.h" extern Zone *zone; @@ -123,26 +123,26 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g if (result_start_n.size() == 0) { return IPath(); } - + std::vector result_end_n; m_impl->Tree.query(boost::geometry::index::nearest(Point(end.x, end.y, end.z), 1), std::back_inserter(result_end_n)); if (result_end_n.size() == 0) { return IPath(); } - + auto &nearest_start = *result_start_n.begin(); auto &nearest_end = *result_end_n.begin(); - + if (nearest_start.second == nearest_end.second) { IPath Route; Route.push_back(start); Route.push_back(end); return Route; } - + std::vector p(boost::num_vertices(m_impl->Graph)); try { - boost::astar_search(m_impl->Graph, nearest_start.second, + boost::astar_search(m_impl->Graph, nearest_start.second, distance_heuristic(&m_impl->Nodes[0], nearest_end.second), boost::predecessor_map(&p[0]) .visitor(astar_goal_visitor(nearest_end.second))); @@ -150,7 +150,7 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g catch (found_goal) { IPath Route; - + Route.push_front(end); for (size_t v = nearest_end.second;; v = p[v]) { if (p[v] == v) { @@ -159,7 +159,7 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g } else { auto &node = m_impl->Nodes[v]; - + auto iter = node.edges.find((int)p[v + 1]); if (iter != node.edges.end()) { auto &edge = iter->second; @@ -176,11 +176,11 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g } } } - + Route.push_front(start); return Route; } - + return IPath(); } @@ -192,7 +192,7 @@ glm::vec3 PathfinderWaypoint::GetRandomLocation(const glm::vec3 &start) return node.v; } - + return glm::vec3(); } @@ -205,32 +205,32 @@ void PathfinderWaypoint::DebugCommand(Client *c, const Seperator *sep) c->Message(Chat::White, "#path info node_id: Gives information about node info (requires shownode target)."); return; } - + if(!strcasecmp(sep->arg[1], "shownodes")) { - ShowNodes(); + ShowNodes(); return; } - + if (!strcasecmp(sep->arg[1], "show")) { if (c->GetTarget() != nullptr) { auto target = c->GetTarget(); glm::vec3 start(c->GetX(), c->GetY(), c->GetZ()); glm::vec3 end(target->GetX(), target->GetY(), target->GetZ()); - + ShowPath(c, start, end); } - + return; } - + if (!strcasecmp(sep->arg[1], "reload")) { Load(m_impl->FileName); return; } - + if (!strcasecmp(sep->arg[1], "info")) { NodeInfo(c); @@ -242,25 +242,25 @@ void PathfinderWaypoint::Load(const std::string &filename) { PathFileHeader Head; Head.PathNodeCount = 0; Head.version = 2; - + FILE *f = fopen(filename.c_str(), "rb"); if (f) { char Magic[10]; - + fread(&Magic, 9, 1, f); - + if (strncmp(Magic, "EQEMUPATH", 9)) { LogError("Bad Magic String in .path file"); fclose(f); return; } - + fread(&Head, sizeof(Head), 1, f); - + LogInfo("Path File Header: Version [{}], PathNodes [{}]", (long)Head.version, (long)Head.PathNodeCount); - + if (Head.version == 2) { LoadV2(f, Head); @@ -281,13 +281,13 @@ void PathfinderWaypoint::Load(const std::string &filename) { void PathfinderWaypoint::LoadV2(FILE *f, const PathFileHeader &header) { std::unique_ptr PathNodes(new PathNode[header.PathNodeCount]); - + fread(PathNodes.get(), sizeof(PathNode), header.PathNodeCount, f); - + int MaxNodeID = header.PathNodeCount - 1; - + m_impl->PathFileValid = true; - + m_impl->Nodes.reserve(header.PathNodeCount); for (uint32 i = 0; i < header.PathNodeCount; ++i) { @@ -298,7 +298,7 @@ void PathfinderWaypoint::LoadV2(FILE *f, const PathFileHeader &header) node.bestz = n.bestz; m_impl->Nodes.push_back(node); } - + auto weightmap = boost::get(boost::edge_weight, m_impl->Graph); for (uint32 i = 0; i < header.PathNodeCount; ++i) { for (uint32 j = 0; j < 50; ++j) @@ -309,18 +309,18 @@ void PathfinderWaypoint::LoadV2(FILE *f, const PathFileHeader &header) LogError("Path Node [{}], Neighbour [{}] ([{}]) out of range", i, j, PathNodes[i].Neighbours[j].id); m_impl->PathFileValid = false; } - + if (PathNodes[i].Neighbours[j].id > 0) { Edge edge; edge.distance = PathNodes[i].Neighbours[j].distance; edge.door_id = PathNodes[i].Neighbours[j].DoorID; edge.teleport = PathNodes[i].Neighbours[j].Teleport; - + node.edges[PathNodes[i].Neighbours[j].id] = edge; } } } - + BuildGraph(); fclose(f); } @@ -339,7 +339,7 @@ void PathfinderWaypoint::LoadV3(FILE *f, const PathFileHeader &header) float y = 0.0f; float z = 0.0f; float best_z = 0.0f; - + fread(&id, sizeof(uint32), 1, f); fread(&x, sizeof(float), 1, f); fread(&y, sizeof(float), 1, f); @@ -352,7 +352,7 @@ void PathfinderWaypoint::LoadV3(FILE *f, const PathFileHeader &header) n.v.x = x; n.v.y = y; n.v.z = z; - + m_impl->Nodes.push_back(n); } @@ -377,10 +377,10 @@ void PathfinderWaypoint::LoadV3(FILE *f, const PathFileHeader &header) auto &n = m_impl->Nodes[from]; n.edges[to] = e; } - + m_impl->PathFileValid = true; - - BuildGraph(); + + BuildGraph(); fclose(f); } diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 87f8977f7..5a44b2832 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -40,14 +40,14 @@ void CullPoints(std::vector &points) { } void Client::SendPathPacket(const std::vector &points) { - EQ::Any data(points); + std::any data(points); EQ::Task([=](EQ::Task::ResolveFn resolve, EQ::Task::RejectFn reject) { - auto points = EQ::any_cast>(data); + auto points = std::any_cast>(data); CullPoints(points); resolve(points); }) - .Then([this](const EQ::Any &result) { - auto points = EQ::any_cast>(result); + .Then([this](const std::any &result) { + auto points = std::any_cast>(result); if (points.size() < 2) { if (Admin() > AccountStatus::Steward) { Message(Chat::System, "Too few points"); diff --git a/zone/perl_bot.cpp b/zone/perl_bot.cpp index 7edfdd82c..ccbb0a936 100644 --- a/zone/perl_bot.cpp +++ b/zone/perl_bot.cpp @@ -1,179 +1,471 @@ -#ifdef BOTS #include "../common/features.h" #ifdef EMBPERL_XS_CLASSES #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "bot.h" -#ifdef THIS -#undef THIS -#endif - -#define VALIDATE_THIS_IS_BOT \ - do { \ - if (sv_derived_from(ST(0), "Bot")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Bot*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Bot"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Bot_GetOwner); -XS(XS_Bot_GetOwner) +Mob* Perl_Bot_GetOwner(Bot* self) // @categories Script Utility, Bot { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Bot::GetOwner(THIS)"); // @categories Script Utility, Bot - { - Bot* THIS; - Mob* bot_owner; - VALIDATE_THIS_IS_BOT; - bot_owner = THIS->GetBotOwner(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void*)bot_owner); - } - XSRETURN(1); + return self->GetBotOwner(); } -XS(XS_Bot_AddBotItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Bot_AddBotItem) { - dXSARGS; - if (items < 3 || items > 11) - Perl_croak(aTHX_ "Usage: Bot::AddBotItem(THIS, uint16 slot_id, uint32 item_id, [int16 charges = -1], [bool attuned = false], [uint32 augment_one = 0], [uint32 augment_two = 0], [uint32 augment_three = 0], [uint32 augment_four = 0], [uint32 augment_five = 0], [uint32 augment_six = 0])"); // @categories Inventory and Items, Script Utility - { - Bot* THIS; - uint16 slot_id = (uint16) SvUV(ST(1)); - uint32 item_id = (uint32) SvUV(ST(2)); - int16 charges = -1; - bool attuned = false; - uint32 augment_one = 0; - uint32 augment_two = 0; - uint32 augment_three = 0; - uint32 augment_four = 0; - uint32 augment_five = 0; - uint32 augment_six = 0; - VALIDATE_THIS_IS_BOT; - - if (items > 3) { - charges = (int16) SvIV(ST(3)); - } - - if (items > 4) { - attuned = (bool) SvTRUE(ST(4)); - } - - if (items > 5) { - augment_one = (uint32) SvUV(ST(5)); - } - - if (items > 6) { - augment_two = (uint32) SvUV(ST(6)); - } - - if (items > 7) { - augment_three = (uint32) SvUV(ST(7)); - } - - if (items > 8) { - augment_four = (uint32) SvUV(ST(8)); - } - - if (items > 9) { - augment_five = (uint32) SvUV(ST(9)); - } - - if (items > 10) { - augment_six = (uint32) SvUV(ST(10)); - } - - THIS->AddBotItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six); - } - XSRETURN_EMPTY; -} - -XS(XS_Bot_CountBotItem); -XS(XS_Bot_CountBotItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Bot::CountBotItem(THIS, uint32 item_id)"); - { - Bot* THIS; - int item_count = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_BOT; - item_count = THIS->CountBotItem(item_id); - XSprePUSH; - PUSHu((UV) item_count); - } - XSRETURN(1); -} - -XS(XS_Bot_HasBotItem); -XS(XS_Bot_HasBotItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Bot:HasBotItem(THIS, uint32 item_id)"); - { - Bot* THIS; - bool has_item = false; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_BOT; - has_item = THIS->HasBotItem(item_id); - ST(0) = boolSV(has_item); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Bot_RemoveBotItem); -XS(XS_Bot_RemoveBotItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Bot::RemoveBotItem(THIS, uint32 item_id)"); // @categories Spells and Disciplines - { - Bot* THIS; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_BOT; - THIS->RemoveBotItem(item_id); - } - XSRETURN_EMPTY; -} - -#ifdef __cplusplus -extern "C" -#endif - -XS(boot_Bot); -XS(boot_Bot) +// todo: should just take a hash instead of all these overloads +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id) // @categories Inventory and Items { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; + self->AddBotItem(slot_id, item_id); +} - if (items != 1) - fprintf(stderr, "boot_Bot does not take any arguments."); +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges); +} - char buf[128]; +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges, bool attuned) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges, attuned); +} - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "AddBotItem"), XS_Bot_AddBotItem, file, "$$$;$$$$$$$$"); - newXSproto(strcpy(buf, "CountBotItem"), XS_Bot_CountBotItem, file, "$$"); - newXSproto(strcpy(buf, "GetOwner"), XS_Bot_GetOwner, file, "$"); - newXSproto(strcpy(buf, "HasBotItem"), XS_Bot_HasBotItem, file, "$$"); - newXSproto(strcpy(buf, "RemoveBotItem"), XS_Bot_RemoveBotItem, file, "$$"); - XSRETURN_YES; +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges, bool attuned, uint32 aug1) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges, attuned, aug1); +} + +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges, bool attuned, uint32 aug1, uint32 aug2) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges, attuned, aug1, aug2); +} + +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges, bool attuned, uint32 aug1, uint32 aug2, uint32 aug3) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges, attuned, aug1, aug2, aug3); +} + +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges, bool attuned, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges, attuned, aug1, aug2, aug3, aug4); +} + +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges, bool attuned, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges, attuned, aug1, aug2, aug3, aug4, aug5); +} + +void Perl_Bot_AddBotItem(Bot* self, uint16 slot_id, uint32 item_id, uint16 charges, bool attuned, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6) // @categories Inventory and Items +{ + self->AddBotItem(slot_id, item_id, charges, attuned, aug1, aug2, aug3, aug4, aug5, aug6); +} + +void Perl_Bot_ApplySpell(Bot* self, int spell_id) +{ + self->ApplySpell(spell_id); +} + +void Perl_Bot_ApplySpell(Bot* self, int spell_id, int duration) +{ + self->ApplySpell(spell_id, duration); +} + +void Perl_Bot_ApplySpell(Bot* self, int spell_id, int duration, bool allow_pets) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Perl_Bot_ApplySpellGroup(Bot* self, int spell_id) +{ + self->ApplySpell(spell_id, 0, ApplySpellType::Group); +} + +void Perl_Bot_ApplySpellGroup(Bot* self, int spell_id, int duration) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Group); +} + +void Perl_Bot_ApplySpellGroup(Bot* self, int spell_id, int duration, bool allow_pets) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +uint32 Perl_Bot_CountBotItem(Bot* self, uint32 item_id) +{ + return self->CountBotItem(item_id); +} + +bool Perl_Bot_HasBotItem(Bot* self, uint32 item_id) +{ + return self->HasBotItem(item_id); +} + +void Perl_Bot_RemoveBotItem(Bot* self, uint32 item_id) +{ + return self->RemoveBotItem(item_id); +} + +EQ::ItemInstance* Perl_Bot_GetAugmentAt(Bot* self, int16 slot_id, uint8 augment_index) +{ + auto* inst = self->GetInv().GetItem(slot_id); + if (inst) { + return inst->GetAugment(augment_index); + } + + return nullptr; +} + +int Perl_Bot_CountAugmentEquippedByID(Bot* self, uint32 item_id) +{ + return self->GetInv().CountAugmentEquippedByID(item_id); +} + +bool Perl_Bot_HasAugmentEquippedByID(Bot* self, uint32 item_id) +{ + return self->GetInv().HasAugmentEquippedByID(item_id); +} + +int Perl_Bot_CountItemEquippedByID(Bot* self, uint32 item_id) +{ + return self->GetInv().CountItemEquippedByID(item_id); +} + +bool Perl_Bot_HasItemEquippedByID(Bot* self, uint32 item_id) +{ + return self->GetInv().HasItemEquippedByID(item_id); +} + +int Perl_Bot_GetRawItemAC(Bot* self) // @categories Inventory and Items +{ + return self->GetRawItemAC(); +} + +EQ::ItemInstance* Perl_Bot_GetBotItem(Bot* self, uint16 slot_id) +{ + return self->GetBotItem(slot_id); +} + +uint32 Perl_Bot_GetBotItemIDBySlot(Bot* self, uint16 slot_id) +{ + return self->GetBotItemBySlot(slot_id); +} + +bool Perl_Bot_IsStanding(Bot* self) // @categories Account and Character +{ + return self->IsStanding(); +} + +void Perl_Bot_Sit(Bot* self) +{ + self->Sit(); +} + +bool Perl_Bot_IsSitting(Bot* self) // @categories Account and Character +{ + return self->IsSitting(); +} + +void Perl_Bot_SendSpellAnim(Bot* self, uint16 target_id, uint16 spell_id) +{ + self->SendSpellAnim(target_id, spell_id); +} + +void Perl_Bot_Signal(Bot* self, int signal_id) +{ + self->Signal(signal_id); +} + +void Perl_Bot_OwnerMessage(Bot* self, std::string message) +{ + self->OwnerMessage(message); +} + +int Perl_Bot_GetExpansionBitmask(Bot* self) +{ + return self->GetExpansionBitmask(); +} + +void Perl_Bot_Escape(Bot* self) // @categories Account and Character, Skills and Recipes +{ + self->Escape(); +} + +void Perl_Bot_Fling(Bot* self, float target_x, float target_y, float target_z) +{ + self->Fling(0, target_x, target_y, target_z, false, false, true); +} + +void Perl_Bot_Fling(Bot* self, float target_x, float target_y, float target_z, bool ignore_los) +{ + self->Fling(0, target_x, target_y, target_z, ignore_los, false, true); +} + +void Perl_Bot_Fling(Bot* self, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) +{ + self->Fling(0, target_x, target_y, target_z, ignore_los, clip_through_walls, true); +} + +void Perl_Bot_Fling(Bot* self, float value, float target_x, float target_y, float target_z) +{ + self->Fling(value, target_x, target_y, target_z); +} + +void Perl_Bot_Fling(Bot* self, float value, float target_x, float target_y, float target_z, bool ignore_los) +{ + self->Fling(value, target_x, target_y, target_z, ignore_los); +} + +void Perl_Bot_Fling(Bot* self, float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) +{ + self->Fling(value, target_x, target_y, target_z, ignore_los, clip_through_walls); +} + +void Perl_Bot_Stand(Bot* self) // @categories Script Utility +{ + self->Stand(); +} + +int Perl_Bot_GetItemIDAt(Bot* self, int16 slot_id) // @categories Inventory and Items +{ + return self->GetItemIDAt(slot_id); +} + +int Perl_Bot_GetAugmentIDAt(Bot* self, int16 slot_id, uint8 aug_slot) // @categories Inventory and Items +{ + return self->GetAugmentIDAt(slot_id, aug_slot); +} + +int Perl_Bot_GetBaseSTR(Bot* self) // @categories Stats and Attributes +{ + return self->GetBaseSTR(); +} + +int Perl_Bot_GetBaseSTA(Bot* self) // @categories Stats and Attributes +{ + return self->GetBaseSTA(); +} + +int Perl_Bot_GetBaseCHA(Bot* self) // @categories Stats and Attributes +{ + return self->GetBaseCHA(); +} + +int Perl_Bot_GetBaseDEX(Bot* self) // @categories Stats and Attributes +{ + return self->GetBaseDEX(); +} + +int Perl_Bot_GetBaseINT(Bot* self) // @categories Stats and Attributes +{ + return self->GetBaseINT(); +} + +int Perl_Bot_GetBaseAGI(Bot* self) // @categories Stats and Attributes +{ + return self->GetBaseAGI(); +} + +int Perl_Bot_GetBaseWIS(Bot* self) // @categories Stats and Attributes +{ + return self->GetBaseWIS(); +} + +Group* Perl_Bot_GetGroup(Bot* self) // @categories Account and Character, Group +{ + return self->GetGroup(); +} + +int Perl_Bot_GetHealAmount(Bot* self) +{ + return self->GetHealAmt(); +} + +int Perl_Bot_GetSpellDamage(Bot* self) +{ + return self->GetSpellDmg(); +} + +int Perl_Bot_GetInstrumentMod(Bot* self, uint16 spell_id) // @categories Spells and Disciplines +{ + return self->GetInstrumentMod(spell_id); +} + +EQ::ItemInstance* Perl_Bot_GetItemAt(Bot* self, int16 slot_id) // @categories Inventory and Items +{ + return self->GetInv().GetItem(slot_id); +} + +bool Perl_Bot_IsGrouped(Bot* self) // @categories Account and Character, Group +{ + return self->IsGrouped(); +} + +void Perl_Bot_SetExpansionBitmask(Bot* self, int expansion_bitmask) +{ + self->SetExpansionBitmask(expansion_bitmask); +} + +void Perl_Bot_SetExpansionBitmask(Bot* self, int expansion_bitmask, bool save) +{ + self->SetExpansionBitmask(expansion_bitmask, save); +} + +void Perl_Bot_SetSpellDuration(Bot* self, int spell_id) +{ + self->SetSpellDuration(spell_id); +} + +void Perl_Bot_SetSpellDuration(Bot* self, int spell_id, int duration) +{ + self->SetSpellDuration(spell_id, duration); +} + +void Perl_Bot_SetSpellDuration(Bot* self, int spell_id, int duration, bool allow_pets) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Perl_Bot_SetSpellDurationGroup(Bot* self, int spell_id) +{ + self->SetSpellDuration(spell_id, 0, ApplySpellType::Group); +} + +void Perl_Bot_SetSpellDurationGroup(Bot* self, int spell_id, int duration) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group); +} + +void Perl_Bot_SetSpellDurationGroup(Bot* self, int spell_id, int duration, bool allow_pets) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +bool Perl_Bot_ReloadBotDataBuckets(Bot* self) +{ + return self->GetBotDataBuckets(); +} + +bool Perl_Bot_ReloadBotOwnerDataBuckets(Bot* self) +{ + return self->GetBotOwnerDataBuckets(); +} + +bool Perl_Bot_ReloadBotSpells(Bot* self) +{ + return self->AI_AddBotSpells(self->GetBotSpellID()); +} + +void Perl_Bot_ReloadBotSpellSettings(Bot* self) +{ + self->LoadBotSpellSettings(); +} + +bool Perl_Bot_HasBotSpellEntry(Bot* self, uint16 spellid) +{ + return self->HasBotSpellEntry(spellid); +} + +void Perl_Bot_SendPayload(Bot* self, int payload_id) // @categories Script Utility +{ + self->SendPayload(payload_id); +} + +void Perl_Bot_SendPayload(Bot* self, int payload_id, std::string payload_value) // @categories Script Utility +{ + self->SendPayload(payload_id, payload_value); +} + +uint32 Perl_Bot_GetBotID(Bot* self) // @categories Script Utility +{ + return self->GetBotID(); +} + +void Perl_Bot_Camp(Bot* self) // @categories Script Utility +{ + self->Camp(); +} + +void Perl_Bot_Camp(Bot* self, bool save_to_database) // @categories Script Utility +{ + self->Camp(save_to_database); +} + +void perl_register_bot() +{ + perl::interpreter state(PERL_GET_THX); + + auto package = state.new_class("Bot"); + package.add_base_class("NPC"); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem); + package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem); + package.add("ApplySpell", (void(*)(Bot*, int))&Perl_Bot_ApplySpell); + package.add("ApplySpell", (void(*)(Bot*, int, int))&Perl_Bot_ApplySpell); + package.add("ApplySpell", (void(*)(Bot*, int, int, bool))&Perl_Bot_ApplySpell); + package.add("ApplySpellGroup", (void(*)(Bot*, int))&Perl_Bot_ApplySpellGroup); + package.add("ApplySpellGroup", (void(*)(Bot*, int, int))&Perl_Bot_ApplySpellGroup); + package.add("ApplySpellGroup", (void(*)(Bot*, int, int, bool))&Perl_Bot_ApplySpellGroup); + package.add("Camp", (void(*)(Bot*))&Perl_Bot_Camp); + package.add("Camp", (void(*)(Bot*, bool))&Perl_Bot_Camp); + package.add("CountAugmentEquippedByID", &Perl_Bot_CountAugmentEquippedByID); + package.add("CountBotItem", &Perl_Bot_CountBotItem); + package.add("CountItemEquippedByID", &Perl_Bot_CountItemEquippedByID); + package.add("Escape", &Perl_Bot_Escape); + package.add("Fling", (void(*)(Bot*, float, float, float))&Perl_Bot_Fling); + package.add("Fling", (void(*)(Bot*, float, float, float, bool))&Perl_Bot_Fling); + package.add("Fling", (void(*)(Bot*, float, float, float, bool, bool))&Perl_Bot_Fling); + package.add("Fling", (void(*)(Bot*, float, float, float, float))&Perl_Bot_Fling); + package.add("Fling", (void(*)(Bot*, float, float, float, float, bool))&Perl_Bot_Fling); + package.add("Fling", (void(*)(Bot*, float, float, float, float, bool, bool))&Perl_Bot_Fling); + package.add("GetAugmentAt", &Perl_Bot_GetAugmentAt); + package.add("GetAugmentIDAt", &Perl_Bot_GetAugmentIDAt); + package.add("GetBaseAGI", &Perl_Bot_GetBaseAGI); + package.add("GetBaseCHA", &Perl_Bot_GetBaseCHA); + package.add("GetBaseDEX", &Perl_Bot_GetBaseDEX); + package.add("GetBaseINT", &Perl_Bot_GetBaseINT); + package.add("GetBaseSTA", &Perl_Bot_GetBaseSTA); + package.add("GetBaseSTR", &Perl_Bot_GetBaseSTR); + package.add("GetBaseWIS", &Perl_Bot_GetBaseWIS); + package.add("GetBotID", &Perl_Bot_GetBotID); + package.add("GetBotItem", &Perl_Bot_GetBotItem); + package.add("GetBotItemIDBySlot", &Perl_Bot_GetBotItemIDBySlot); + package.add("GetExpansionBitmask", &Perl_Bot_GetExpansionBitmask); + package.add("GetGroup", &Perl_Bot_GetGroup); + package.add("GetHealAmount", &Perl_Bot_GetHealAmount); + package.add("GetInstrumentMod", &Perl_Bot_GetInstrumentMod); + package.add("GetItemAt", &Perl_Bot_GetItemAt); + package.add("GetItemIDAt", &Perl_Bot_GetItemIDAt); + package.add("GetOwner", &Perl_Bot_GetOwner); + package.add("GetRawItemAC", &Perl_Bot_GetRawItemAC); + package.add("GetSpellDamage", &Perl_Bot_GetSpellDamage); + package.add("HasAugmentEquippedByID", &Perl_Bot_HasAugmentEquippedByID); + package.add("HasBotItem", &Perl_Bot_HasBotItem); + package.add("HasBotSpellEntry", &Perl_Bot_HasBotSpellEntry); + package.add("HasItemEquippedByID", &Perl_Bot_HasItemEquippedByID); + package.add("IsGrouped", &Perl_Bot_IsGrouped); + package.add("IsSitting", &Perl_Bot_IsSitting); + package.add("IsStanding", &Perl_Bot_IsStanding); + package.add("OwnerMessage", &Perl_Bot_OwnerMessage); + package.add("ReloadBotDataBuckets", &Perl_Bot_ReloadBotDataBuckets); + package.add("ReloadBotOwnerDataBuckets", &Perl_Bot_ReloadBotOwnerDataBuckets); + package.add("ReloadBotSpells", &Perl_Bot_ReloadBotSpells); + package.add("ReloadBotSpellSettings", &Perl_Bot_ReloadBotSpellSettings); + package.add("RemoveBotItem", &Perl_Bot_RemoveBotItem); + package.add("SendPayload", (void(*)(Bot*, int))&Perl_Bot_SendPayload); + package.add("SendPayload", (void(*)(Bot*, int, std::string))&Perl_Bot_SendPayload); + package.add("SendSpellAnim", &Perl_Bot_SendSpellAnim); + package.add("SetExpansionBitmask", (void(*)(Bot*, int))&Perl_Bot_SetExpansionBitmask); + package.add("SetExpansionBitmask", (void(*)(Bot*, int, bool))&Perl_Bot_SetExpansionBitmask); + package.add("SetSpellDuration", (void(*)(Bot*, int))&Perl_Bot_SetSpellDuration); + package.add("SetSpellDuration", (void(*)(Bot*, int, int))&Perl_Bot_SetSpellDuration); + package.add("SetSpellDuration", (void(*)(Bot*, int, int, bool))&Perl_Bot_SetSpellDuration); + package.add("SetSpellDurationGroup", (void(*)(Bot*, int))&Perl_Bot_SetSpellDurationGroup); + package.add("SetSpellDurationGroup", (void(*)(Bot*, int, int))&Perl_Bot_SetSpellDurationGroup); + package.add("SetSpellDurationGroup", (void(*)(Bot*, int, int, bool))&Perl_Bot_SetSpellDurationGroup); + package.add("Signal", &Perl_Bot_Signal); + package.add("Sit", &Perl_Bot_Sit); + package.add("Stand", &Perl_Bot_Stand); } #endif //EMBPERL_XS_CLASSES -#endif //BOTS diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 1a82f34ec..117437e90 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4,6740 +4,3399 @@ #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "client.h" #include "expedition.h" #include "titles.h" #include "dialogue_window.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_CLIENT \ - do { \ - if (sv_derived_from(ST(0), "Client")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Client*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Client"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Client_SendSound); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendSound) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::SendSound(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->SendSound(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_Save); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Save) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::Save(THIS, uint8 commit_now)"); // @categories Script Utility - { - Client *THIS; - bool RETVAL; - uint8 iCommitNow = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->Save(iCommitNow); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_SaveBackup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SaveBackup) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::SaveBackup(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->SaveBackup(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_Connected); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Connected) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Connected(THIS)"); // @categories Script Utility - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->Connected(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_InZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_InZone) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::InZone(THIS)"); // @categories Script Utility - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->InZone(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_Kick); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Kick) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Kick(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->Kick("Perl Quest"); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_Disconnect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Disconnect) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Disconnect(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->Disconnect(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_IsLD); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsLD) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsLD(THIS)"); // @categories Account and Character - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsLD(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_WorldKick); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_WorldKick) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::WorldKick(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->WorldKick(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SendToGuildHall); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendToGuildHall) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::SendToGuildHall(THIS)"); // @categories Script Utility, Guild - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->SendToGuildHall(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetAnon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAnon) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetAnon(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAnon(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_SetAnon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetAnon) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetAnon(THIS, uint8 anon_flag)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 anon_flag = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetAnon(anon_flag); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetAFK); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAFK) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetAFK(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAFK(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_SetAFK); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetAFK) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetAFK(THIS, uint8 afk_flag)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 afk_flag = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetAFK(afk_flag); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_Duck); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Duck) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Duck(THIS)"); // @categories Account and Character - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->Duck(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_DyeArmorBySlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_DyeArmorBySlot) { - dXSARGS; - if (items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: Client::DyeArmorBySlot(THIS, uint8 slot, uint8 red, uint8 green, uint8 blue, [uint8 use_tint = 0x00])"); // @categories Account and Character, Inventory and Items - { - Client *THIS; - uint8 slot = (uint8) SvUV(ST(1)); - uint8 red = (uint8) SvUV(ST(2)); - uint8 green = (uint8) SvUV(ST(3)); - uint8 blue = (uint8) SvUV(ST(4)); - uint8 use_tint = 0x00; - if (items == 6) { - use_tint = (uint8) SvUV(ST(5)); - } - VALIDATE_THIS_IS_CLIENT; - THIS->DyeArmorBySlot(slot, red, green, blue, use_tint); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_Stand); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Stand) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Stand(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->Stand(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetGM); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetGM) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetGM(THIS, bool toggle)"); // @categories Account and Character - { - Client *THIS; - bool toggle = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetGM(toggle); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetPVP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetPVP) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetPVP(THIS, bool toggle)"); // @categories Account and Character - { - Client *THIS; - bool toggle = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetPVP(toggle); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetPVP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetPVP) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetPVP(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetPVP(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_GetGM); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetGM) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetGM(THIS)"); // @categories Account and Character - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetGM(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_SetBaseClass); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetBaseClass) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetBaseClass(THIS, uint32 class_id)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint32 i = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetBaseClass(i); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetBaseRace); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetBaseRace) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetBaseRace(THIS, uint32 race_id)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint32 i = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetBaseRace(i); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetBaseGender); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetBaseGender) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetBaseGender(THIS, uint32 gender_id)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint32 i = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetBaseGender(i); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetBaseFace); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseFace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseFace(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseFace(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetLanguageSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetLanguageSkill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetLanguageSkill(THIS, uint16 lanuage_id)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - uint16 n = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetLanguageSkill(n); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetLDoNPointsTheme); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetLDoNPointsTheme) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetLDoNPointsTheme(THIS, int32 theme)"); // @categories Currency and Points - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - int32 theme_out = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetLDoNPointsTheme(theme_out); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBaseSTR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseSTR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseSTR(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseSTR(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBaseSTA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseSTA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseSTA(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseSTA(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBaseCHA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseCHA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseCHA(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseCHA(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBaseDEX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseDEX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseDEX(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseDEX(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBaseINT); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseINT) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseINT(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseINT(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBaseAGI); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseAGI) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseAGI(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseAGI(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBaseWIS); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBaseWIS) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBaseWIS(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBaseWIS(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetWeight); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetWeight) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetWeight(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetWeight(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetEXP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetEXP) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetEXP(THIS)"); // @categories Experience and Level - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetEXP(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetAAExp); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAAExp) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetAAExp(THIS)"); // @categories Alternative Advancement, Experience and Level - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAAXP(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetAAPercent); -XS(XS_Client_GetAAPercent) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetAAPercent(THIS)"); // @categories Alternative Advancement, Experience and Level - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAAPercent(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetTotalSecondsPlayed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetTotalSecondsPlayed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetTotalSecondsPlayed(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetTotalSecondsPlayed(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_UpdateLDoNPoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UpdateLDoNPoints) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::UpdateLDoNPoints(THIS, uint32 theme_id, int points)"); // @categories Currency and Points - { - Client *THIS; - bool RETVAL; - uint32 theme_id = (uint32) SvUV(ST(1)); - int points = (int) SvIV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->UpdateLDoNPoints(theme_id, points); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_SetDeity); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetDeity) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetDeity(THIS, uint32 deity_id)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint32 i = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetDeity(i); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_AddEXP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AddEXP) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Client::AddEXP(THIS, uint32 experience_points)"); // @categories Experience and Level - { - Client *THIS; - uint32 add_exp = (uint32) SvUV(ST(1)); - uint8 conlevel; - bool resexp; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - conlevel = 0xFF; - else { - conlevel = (uint8) SvUV(ST(2)); - } - - if (items < 4) - resexp = false; - else { - resexp = (bool) SvTRUE(ST(3)); - } - - THIS->AddEXP(add_exp, conlevel, resexp); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetEXP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetEXP) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Client::SetEXP(THIS, uint32 experience_points, uint32 aa_experience_points, [bool resexp=false])"); // @categories Experience and Level - { - Client *THIS; - uint32 set_exp = (uint32) SvUV(ST(1)); - uint32 set_aaxp = (uint32) SvUV(ST(2)); - bool resexp; - VALIDATE_THIS_IS_CLIENT; - if (items < 4) - resexp = false; - else { - resexp = (bool) SvTRUE(ST(3)); - } - - THIS->SetEXP(set_exp, set_aaxp, resexp); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetBindPoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetBindPoint) { - dXSARGS; - if (items < 1 || items > 7) - Perl_croak(aTHX_ "Usage: Client::SetBindPoint(THIS, [int to_zone = -1, int to_instance = 0, float new_x = 0.0f, float new_y = 0.0f, float new_z = 0.0f, float new_heading = 0.0f])"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - int to_zone = -1; - int to_instance = 0; - float new_x = 0.0f, new_y = 0.0f, new_z = 0.0f, new_heading = 0.0f; - VALIDATE_THIS_IS_CLIENT; - if (items > 1) - to_zone = (int) SvIV(ST(1)); - if (items > 2) - to_instance = (int) SvIV(ST(2)); - if (items > 3) - new_x = (float) SvNV(ST(3)); - if (items > 4) - new_y = (float) SvNV(ST(4)); - if (items > 5) - new_z = (float) SvNV(ST(5)); - if (items > 6) - new_heading = (float) SvNV(ST(6)); - - THIS->SetBindPoint2(0, to_zone, to_instance, glm::vec4(new_x, new_y, new_z, new_heading)); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetBindX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBindX) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::GetBindX(int index = 0)"); // @categories Account and Character - { - Client *THIS; - int index = 0; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items == 1) - index = 0; - else if (items == 2) { - index = (uint32) SvUV(ST(1)); - } - - RETVAL = THIS->GetBindX(index); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBindY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBindY) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::GetBindY(int index = 0)"); // @categories Account and Character - { - Client *THIS; - int index = 0; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items == 1) - index = 0; - else if (items == 2) { - index = (uint32) SvUV(ST(1));; - } - - RETVAL = THIS->GetBindY(index); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBindZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBindZ) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::GetBindZ(int index = 0)"); // @categories Account and Character - { - Client *THIS; - int index = 0; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items == 1) - index = 0; - else if (items == 2) { - index = (uint32) SvUV(ST(1)); - } - - RETVAL = THIS->GetBindZ(index); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBindHeading); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBindHeading) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::GetBindHeading(int index = 0)"); // @categories Account and Character - { - Client *THIS; - int index = 0; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items == 1) - index = 0; - else if (items == 2) { - index = (uint32) SvUV(ST(1)); - } - - RETVAL = THIS->GetBindHeading(index); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetBindZoneID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBindZoneID) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::GetBindZoneID(int index = 0)"); // @categories Account and Character - { - Client *THIS; - uint32 index = 0; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items == 1) - index = 0; - else if (items == 2) { - index = (uint32) SvUV(ST(1)); - } - - RETVAL = THIS->GetBindZoneID(index); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Client_MovePC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MovePC) { - dXSARGS; - if (items != 6) - Perl_croak(aTHX_ "Usage: Client::MovePC(THIS, uint32 zone_id, float x, float y, float z, float heading)"); // @categories Script Utility - { - Client *THIS; - uint32 zoneID = (uint32) SvUV(ST(1)); - float x = (float) SvNV(ST(2)); - float y = (float) SvNV(ST(3)); - float z = (float) SvNV(ST(4)); - float heading = (float) SvNV(ST(5)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MovePC(zoneID, x, y, z, heading); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MovePC) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MovePC) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MovePC) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MovePC) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MovePCInstance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MovePCInstance) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: Client::MovePCInstance(THIS, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading)"); // @categories Adventures and Expeditions, Script Utility - { - Client *THIS; - uint32 zoneID = (uint32) SvUV(ST(1)); - uint32 instanceID = (uint32) SvUV(ST(2)); - float x = (float) SvNV(ST(3)); - float y = (float) SvNV(ST(4)); - float z = (float) SvNV(ST(5)); - float heading = (float) SvNV(ST(6)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MovePC(zoneID, instanceID, x, y, z, heading); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MoveZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MoveZone) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::MoveZone(THIS, string zone_short_name)"); // @categories Script Utility - { - Client *THIS; - const char *zone_short_name = (const char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MoveZone(zone_short_name); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZone) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZone) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZone) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MoveZone) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MoveZoneGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MoveZoneGroup) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::MoveZoneGroup(THIS, string zone_short_name)"); // @categories Script Utility, Group - { - Client *THIS; - const char *zone_short_name = (const char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MoveZoneGroup(zone_short_name); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneGroup) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneGroup) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneGroup) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneGroup) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MoveZoneRaid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MoveZoneRaid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::MoveZoneRaid(THIS, string zone_short_name)"); // @categories Script Utility, Raid - { - Client *THIS; - const char *zone_short_name = (const char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MoveZoneRaid(zone_short_name); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneRaid) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneRaid) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneRaid) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneRaid) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MoveZoneInstance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MoveZoneInstance) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::MoveZoneInstance(THIS, uint16 instance_id)"); // @categories Adventures and Expeditions, Script Utility - { - Client *THIS; - uint16 instance_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MoveZoneInstance(instance_id); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstance) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstance) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstance) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstance) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MoveZoneInstanceGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MoveZoneInstanceGroup) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::MoveZoneInstanceGroup(THIS, uint16 instance_id)"); // @categories Adventures and Expeditions, Script Utility, Group - { - Client *THIS; - uint16 instance_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MoveZoneInstanceGroup(instance_id); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceGroup) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceGroup) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceGroup) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceGroup) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MoveZoneInstanceRaid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MoveZoneInstanceRaid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::MoveZoneInstanceRaid(THIS, uint16 instance_id)"); // @categories Adventures and Expeditions, Script Utility, Raid - { - Client *THIS; - uint16 instance_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - if (THIS->IsClient()) { - THIS->MoveZoneInstanceRaid(instance_id); - } else { - if (THIS->IsMerc()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceRaid) attempted to process a type Merc reference"); - } -#ifdef BOTS - else if (THIS->IsBot()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceRaid) attempted to process a type Bot reference"); - } -#endif - else if (THIS->IsNPC()) { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceRaid) attempted to process a type NPC reference"); - } - else { - LogDebug("[CLIENT] Perl(XS_Client_MoveZoneInstanceRaid) attempted to process an Unknown type reference"); - } - - Perl_croak(aTHX_ "THIS is not of type Client"); - } - - } - XSRETURN_EMPTY; -} - -XS(XS_Client_ChangeLastName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ChangeLastName) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::ChangeLastName(THIS, string last_name)"); // @categories Account and Character - { - Client *THIS; - char *in_lastname = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->ChangeLastName(in_lastname); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetFactionLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetFactionLevel) { - dXSARGS; - if (items != 8) - Perl_croak(aTHX_ "Usage: Client::GetFactionLevel(THIS, uint32 character_id, uint32 npc_id, uint32 player_race_id, uint32 player_class_id, uint32 player_deity_id, uint32 player_faction_id, Mob*)"); // @categories Faction - { - Client *THIS; - FACTION_VALUE RETVAL; - dXSTARG; - uint32 char_id = (uint32) SvUV(ST(1)); - uint32 npc_id = (uint32) SvUV(ST(2)); - uint32 p_race = (uint32) SvUV(ST(3)); - uint32 p_class = (uint32) SvUV(ST(4)); - uint32 p_deity = (uint32) SvUV(ST(5)); - int32 pFaction = (int32) SvIV(ST(6)); - Mob *tnpc; - VALIDATE_THIS_IS_CLIENT; - if (sv_derived_from(ST(7), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(7))); - tnpc = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "tnpc is not of type Mob"); - if (tnpc == nullptr) - Perl_croak(aTHX_ "tnpc is nullptr, avoiding crash."); - - RETVAL = THIS->GetFactionLevel(char_id, npc_id, p_race, p_class, p_deity, pFaction, tnpc); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_SetFactionLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetFactionLevel) { - dXSARGS; - if (items != 6) - Perl_croak(aTHX_ "Usage: Client::SetFactionLevel(THIS, uint32 character_id, uint32 npc_id, uint8 character_class, uint8 character_race, uint8 character_deity)"); // @categories Faction - { - Client *THIS; - uint32 char_id = (uint32) SvUV(ST(1)); - uint32 npc_id = (uint32) SvUV(ST(2)); - uint8 char_class = (uint8) SvUV(ST(3)); - uint8 char_race = (uint8) SvUV(ST(4)); - uint8 char_deity = (uint8) SvUV(ST(5)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetFactionLevel(char_id, npc_id, char_class, char_race, char_deity); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetFactionLevel2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetFactionLevel2) { - dXSARGS; - if (items < 7 || items > 8) - Perl_croak(aTHX_ "Usage: Client::SetFactionLevel2(THIS, uint32 character_id, int32 faction_id, uint8 character_class, uint8 character_race, uint8 character_deity, int32 value, uint8 temp)"); // @categories Faction - { - Client *THIS; - uint32 char_id = (uint32) SvUV(ST(1)); - int32 faction_id = (int32) SvIV(ST(2)); - uint8 char_class = (uint8) SvUV(ST(3)); - uint8 char_race = (uint8) SvUV(ST(4)); - uint8 char_deity = (uint8) SvUV(ST(5)); - int32 value = (int32) SvIV(ST(6)); - uint8 temp; - VALIDATE_THIS_IS_CLIENT; - if (items == 7) - temp = 0; - else { - temp = (uint8) SvUV(ST(7)); - } - - THIS->SetFactionLevel2(char_id, faction_id, char_class, char_race, char_deity, value, temp); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetRawItemAC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetRawItemAC) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetRawItemAC(THIS)"); // @categories Inventory and Items - { - Client *THIS; - int16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetRawItemAC(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_AccountID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AccountID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::AccountID(THIS)"); // @categories Account and Character - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->AccountID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_AccountName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AccountName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::AccountName(THIS)"); // @categories Account and Character - { - Client *THIS; - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->AccountName(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Client_Admin); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Admin) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Admin(THIS)"); // @categories Account and Character - { - Client *THIS; - int16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->Admin(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_CharacterID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_CharacterID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::CharacterID(THIS)"); // @categories Account and Character - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->CharacterID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_UpdateAdmin); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UpdateAdmin) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::UpdateAdmin(THIS, bool from_db = true)"); // @categories Account and Character - { - Client *THIS; - bool iFromDB; - VALIDATE_THIS_IS_CLIENT; - if (items < 2) - iFromDB = true; - else { - iFromDB = (bool) SvTRUE(ST(1)); - } - - THIS->UpdateAdmin(iFromDB); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UpdateWho); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UpdateWho) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::UpdateWho(THIS, uint8 remove = 0)"); // @categories Script Utility - { - Client *THIS; - uint8 remove; - VALIDATE_THIS_IS_CLIENT; - if (items < 2) - remove = 0; - else { - remove = (uint8) SvUV(ST(1)); - } - - THIS->UpdateWho(remove); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GuildRank); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GuildRank) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GuildRank(THIS)"); // @categories Account and Character, Guild - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GuildRank(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GuildID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GuildID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GuildID(THIS)"); // @categories Account and Character, Guild - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GuildID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetFace); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetFace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetFace(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetFace(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_TakeMoneyFromPP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_TakeMoneyFromPP) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::TakeMoneyFromPP(THIS, uint32 copper, [bool update_client = false])"); // @categories Currency and Points - { - Client *THIS; - bool has_money; - bool update_client = false; - uint64 copper = (uint64) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - - if (items == 3) { - update_client = (bool) SvTRUE(ST(2)); - } - - has_money = THIS->TakeMoneyFromPP(copper, update_client); - ST(0) = boolSV(has_money); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_AddMoneyToPP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AddMoneyToPP) { - dXSARGS; - if (items < 5 || items > 6) - Perl_croak(aTHX_ "Usage: Client::AddMoneyToPP(THIS, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, [bool update_client = false])"); // @categories Currency and Points - { - Client *THIS; - uint32 copper = (uint32) SvUV(ST(1)); - uint32 silver = (uint32) SvUV(ST(2)); - uint32 gold = (uint32) SvUV(ST(3)); - uint32 platinum = (uint32) SvUV(ST(4)); - bool update_client = false; - VALIDATE_THIS_IS_CLIENT; - - if (items == 6) { - update_client = (bool) SvTRUE(ST(5)); - } - - THIS->AddMoneyToPP(copper, silver, gold, platinum, update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_TGB); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_TGB) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::TGB(THIS)"); // @categories Spells and Disciplines - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->TGB(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_GetSkillPoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetSkillPoints) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetSkillPoints(THIS)"); // @categories Skills and Recipes - { - Client *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetSkillPoints(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_SetSkillPoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetSkillPoints) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetSkillPoints(THIS, inp)"); // @categories Skills and Recipes - { - Client *THIS; - int inp = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetSkillPoints(inp); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_IncreaseSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IncreaseSkill) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::IncreaseSkill(THIS, int skill_id, int value = 1)"); // @categories Skills and Recipes - { - Client *THIS; - int skill_id = (int) SvIV(ST(1)); - int value; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - value = 1; - else { - value = (int) SvIV(ST(2)); - } - - THIS->IncreaseSkill(skill_id, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_IncreaseLanguageSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IncreaseLanguageSkill) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::IncreaseLanguageSkill(THIS, int skill_id, int value = 1)"); // @categories Skills and Recipes - { - Client *THIS; - int skill_id = (int) SvIV(ST(1)); - int value; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - value = 1; - else { - value = (int) SvIV(ST(2)); - } - - THIS->IncreaseLanguageSkill(skill_id, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetRawSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetRawSkill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetRawSkill(THIS, int skill_id)"); // @categories Skills and Recipes - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - EQ::skills::SkillType skill_id = (EQ::skills::SkillType) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetRawSkill(skill_id); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_HasSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_HasSkill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::HasSkill(THIS, int skill_id)"); // @categories Skills and Recipes - { - Client *THIS; - bool RETVAL; - EQ::skills::SkillType skill_id = (EQ::skills::SkillType) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->HasSkill(skill_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_CanHaveSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_CanHaveSkill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::CanHaveSkill(THIS, int skill_id)"); // @categories Skills and Recipes - { - Client *THIS; - bool RETVAL; - EQ::skills::SkillType skill_id = (EQ::skills::SkillType) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->CanHaveSkill(skill_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_SetSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetSkill) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetSkill(THIS, int skill_id, uint16 value)"); // @categories Skills and Recipes - { - Client *THIS; - EQ::skills::SkillType skill_num = (EQ::skills::SkillType) SvUV(ST(1)); - uint16 value = (uint16) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetSkill(skill_num, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_AddSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AddSkill) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::AddSkill(THIS, int skill_id, uint16 value)"); // @categories Skills and Recipes - { - Client *THIS; - EQ::skills::SkillType skillid = (EQ::skills::SkillType) SvUV(ST(1)); - uint16 value = (uint16) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->AddSkill(skillid, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_CheckSpecializeIncrease); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_CheckSpecializeIncrease) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::CheckSpecializeIncrease(THIS, uint16 spell_id)"); // @categories Spells and Disciplines - { - Client *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->CheckSpecializeIncrease(spell_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_CheckIncreaseSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_CheckIncreaseSkill) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::CheckIncreaseSkill(THIS, int skill_id, int chance_modifier = 0)"); // @categories Skills and Recipes - { - Client *THIS; - bool RETVAL; - EQ::skills::SkillType skillid = (EQ::skills::SkillType) SvUV(ST(1)); - int chancemodi; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - chancemodi = 0; - else { - chancemodi = (int) SvIV(ST(2)); - } - - RETVAL = THIS->CheckIncreaseSkill(skillid, nullptr, chancemodi); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_SetLanguageSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetLanguageSkill) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetLanguageSkill(THIS, int language_id, int value)"); // @categories Account and Character, Skills and Recipes, Stats and Attributes - { - Client *THIS; - int langid = (int) SvIV(ST(1)); - int value = (int) SvIV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetLanguageSkill(langid, value); - } - XSRETURN_EMPTY; - -} - -XS(XS_Client_MaxSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MaxSkill) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Client::MaxSkill(THIS, uint16 skill_id, uint16 class_id, uint16 level)"); // @categories Skills and Recipes - { - Client *THIS; - uint16 RETVAL; - EQ::skills::SkillType skillid = (EQ::skills::SkillType) SvUV(ST(1)); - uint16 class_ = 0; - uint16 level = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items > 2) - class_ = (uint16) SvUV(ST(2)); - else - class_ = THIS->GetClass(); - - if (items > 3) - level = (uint16) SvUV(ST(3)); - else - level = THIS->GetLevel(); - - RETVAL = THIS->MaxSkill(skillid, class_, level); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GMKill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GMKill) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GMKill(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->GMKill(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_IsMedding); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsMedding) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsMedding(THIS)"); // @categories Account and Character - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsMedding(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_GetDuelTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetDuelTarget) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetDuelTarget(THIS)"); // @categories Account and Character, Script Utility - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetDuelTarget(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_IsDueling); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsDueling) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsDueling(THIS)"); // @categories Account and Character - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsDueling(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_SetDuelTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetDuelTarget) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetDuelTarget(THIS, set_id)"); // @categories Account and Character - { - Client *THIS; - uint32 set_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetDuelTarget(set_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetDueling); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetDueling) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetDueling(THIS, duel)"); // @categories Account and Character, Script Utility - { - Client *THIS; - bool duel = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetDueling(duel); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_ResetAA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ResetAA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::ResetAA(THIS)"); // @categories Alternative Advancement - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->ResetAA(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_MemSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MemSpell) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Client::MemSpell(THIS, uint16 spell_id, int slot, [bool update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - int slot = (int) SvIV(ST(2)); - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 4) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(3)); - } - - THIS->MemSpell(spell_id, slot, update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UnmemSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UnmemSpell) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::UnmemSpell(THIS, int slot, [bool update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - int slot = (int) SvIV(ST(1)); - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(2)); - } - - THIS->UnmemSpell(slot, update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UnmemSpellBySpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UnmemSpellBySpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::UnmemSpellBySpellID(THIS, int32 spell_id)"); // @categories Spells and Disciplines - { - Client *THIS; - int32 spell_id = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->UnmemSpellBySpellID(spell_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UnmemSpellAll); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UnmemSpellAll) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::UnmemSpellAll(THIS, [bool update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 2) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(1)); - } - - THIS->UnmemSpellAll(update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_FindEmptyMemSlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_FindEmptyMemSlot) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::FindEmptyMemSlot(THIS)"); // @categories Account and Character, Spells and Disciplines - { - Client *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->FindEmptyMemSlot(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_FindMemmedSpellBySlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_FindMemmedSpellBySlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::FindMemmedSpellBySlot(THIS, int slot)"); // @categories Account and Character, Spells and Disciplines - { - Client *THIS; - uint16 RETVAL; - dXSTARG; - int slot = SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->FindMemmedSpellBySlot(slot); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_FindMemmedSpellBySpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_FindMemmedSpellBySpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::FindMemmedSpellBySpellID(THIS, uint16 spell_id)"); // @categories Account and Character, Spells and Disciplines - { - Client *THIS; - int RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->FindMemmedSpellBySpellID(spell_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_MemmedCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_MemmedCount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::MemmedCount(THIS)"); // @categories Spells and Disciplines - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->MemmedCount(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_ScribeSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ScribeSpell) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Client::ScribeSpell(THIS, uint16 spell_id, int slot, [bool update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - int slot = (int) SvIV(ST(2)); - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 4) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(3)); - } - - THIS->ScribeSpell(spell_id, slot, update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UnscribeSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UnscribeSpell) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::UnscribeSpell(THIS, int slot, [bool update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - int slot = (int) SvIV(ST(1)); - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(2)); - } - - THIS->UnscribeSpell(slot, update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UnscribeSpellAll); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UnscribeSpellAll) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::UnscribeSpellAll(THIS, [bool update_client = true])"); - { - Client *THIS; - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 2) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(1)); - } - - THIS->UnscribeSpellAll(update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_TrainDiscBySpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_TrainDiscBySpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::TrainDiscBySpellID(THIS, int32 spell_id)"); // @categories Spells and Disciplines - { - Client *THIS; - int32 spell_id = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->TrainDiscBySpellID(spell_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetDiscSlotBySpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetDiscSlotBySpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetDiscSlotBySpellID(THIS, int32 spell_id)"); // @categories Spells and Disciplines - { - Client *THIS; - int RETVAL; - int32 spell_id = (int32) SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetDiscSlotBySpellID(spell_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_UntrainDisc); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UntrainDisc) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::UntrainDisc(THIS, int slot, [bool update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - int slot = (int) SvIV(ST(1)); - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(2)); - } - - THIS->UntrainDisc(slot, update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UntrainDiscAll); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UntrainDiscAll) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::UntrainDiscAll(THIS, [update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - bool update_client; - VALIDATE_THIS_IS_CLIENT; - if (items < 2) - update_client = true; - else { - update_client = (bool) SvTRUE(ST(1)); - } - - THIS->UntrainDiscAll(update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_IsStanding); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsStanding) +void Perl_Client_SendSound(Client* self) // @categories Script Utility { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsStanding(THIS)"); // @categories Account and Character - { - Client * THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsStanding(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); + self->SendSound(); } -XS(XS_Client_Sit); -XS(XS_Client_Sit) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Sit(THIS)"); - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->Sit(); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_IsSitting); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsSitting) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsSitting(THIS)"); // @categories Account and Character - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsSitting(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Client_IsCrouching); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsCrouching) +bool Perl_Client_Save(Client* self, uint8 commit_now) // @categories Script Utility { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsCrouching(THIS)"); // @categories Account and Character - { - Client * THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsCrouching(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); + return self->Save(commit_now); } -XS(XS_Client_IsBecomeNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsBecomeNPC) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsBecomeNPC(THIS)"); // @categories Account and Character - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsBecomeNPC(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_SaveBackup(Client* self) // @categories Script Utility +{ + self->SaveBackup(); } -XS(XS_Client_GetBecomeNPCLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetBecomeNPCLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetBecomeNPCLevel(THIS)"); // @categories Experience and Level - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetBecomeNPCLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +bool Perl_Client_Connected(Client* self) // @categories Script Utility +{ + return self->Connected(); } -XS(XS_Client_SetBecomeNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetBecomeNPC) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetBecomeNPC(THIS, flag)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - bool flag = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetBecomeNPC(flag); - } - XSRETURN_EMPTY; +bool Perl_Client_InZone(Client* self) // @categories Script Utility +{ + return self->InZone(); } -XS(XS_Client_SetBecomeNPCLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetBecomeNPCLevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetBecomeNPCLevel(THIS, level)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 level = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetBecomeNPCLevel(level); - } - XSRETURN_EMPTY; +void Perl_Client_Kick(Client* self) // @categories Script Utility +{ + self->Kick("Perl Quest"); } -XS(XS_Client_SetFeigned); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetFeigned) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetFeigned(THIS, in_feigned)"); // @categories Script Utility - { - Client *THIS; - bool in_feigned = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetFeigned(in_feigned); - } - XSRETURN_EMPTY; +void Perl_Client_Disconnect(Client* self) // @categories Script Utility +{ + self->Disconnect(); +} + +bool Perl_Client_IsLD(Client* self) // @categories Account and Character +{ + return self->IsLD(); +} + +void Perl_Client_WorldKick(Client* self) // @categories Script Utility +{ + self->WorldKick(); +} + +void Perl_Client_SendToGuildHall(Client* self) // @categories Script Utility, Guild +{ + self->SendToGuildHall(); +} + +int Perl_Client_GetAnon(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetAnon(); +} + +void Perl_Client_SetAnon(Client* self, uint8 anon_flag) // @categories Account and Character, Stats and Attributes +{ + self->SetAnon(anon_flag); +} + +int Perl_Client_GetAFK(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetAFK(); +} + +void Perl_Client_SetAFK(Client* self, uint8 afk_flag) // @categories Account and Character, Stats and Attributes +{ + self->SetAFK(afk_flag); +} + +void Perl_Client_Duck(Client* self) // @categories Account and Character +{ + self->Duck(); +} + +void Perl_Client_DyeArmorBySlot(Client* self, uint8 slot, uint8 red, uint8 green, uint8 blue) // @categories Account and Character, Inventory and Items +{ + self->DyeArmorBySlot(slot, red, green, blue); +} + +void Perl_Client_DyeArmorBySlot(Client* self, uint8 slot, uint8 red, uint8 green, uint8 blue, uint8 use_tint) // @categories Account and Character, Inventory and Items +{ + self->DyeArmorBySlot(slot, red, green, blue, use_tint); +} + +void Perl_Client_Stand(Client* self) // @categories Script Utility +{ + self->Stand(); +} + +void Perl_Client_SetGM(Client* self, bool on) // @categories Account and Character +{ + self->SetGM(on); +} + +void Perl_Client_SetPVP(Client* self, bool on) // @categories Account and Character +{ + self->SetPVP(on); +} + +bool Perl_Client_GetPVP(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetPVP(); +} + +bool Perl_Client_GetGM(Client* self) // @categories Account and Character +{ + return self->GetGM(); +} + +void Perl_Client_SetBaseClass(Client* self, uint32 class_id) // @categories Account and Character, Stats and Attributes +{ + self->SetBaseClass(class_id); +} + +void Perl_Client_SetBaseRace(Client* self, uint32 race_id) // @categories Account and Character, Stats and Attributes +{ + self->SetBaseRace(race_id); +} + +void Perl_Client_SetBaseGender(Client* self, uint32 gender_id) // @categories Account and Character, Stats and Attributes +{ + self->SetBaseGender(gender_id); +} + +int Perl_Client_GetBaseFace(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseFace(); +} + +int Perl_Client_GetLanguageSkill(Client* self, uint16 lanuage_id) // @categories Account and Character, Stats and Attributes +{ + return self->GetLanguageSkill(lanuage_id); +} + +uint32_t Perl_Client_GetLDoNPointsTheme(Client* self, int theme) // @categories Currency and Points +{ + return self->GetLDoNPointsTheme(theme); +} + +int Perl_Client_GetBaseSTR(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseSTR(); +} + +int Perl_Client_GetBaseSTA(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseSTA(); +} + +int Perl_Client_GetBaseCHA(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseCHA(); +} + +int Perl_Client_GetBaseDEX(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseDEX(); +} + +int Perl_Client_GetBaseINT(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseINT(); +} + +int Perl_Client_GetBaseAGI(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseAGI(); +} + +int Perl_Client_GetBaseWIS(Client* self) // @categories Stats and Attributes +{ + return self->GetBaseWIS(); +} + +int Perl_Client_GetWeight(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetWeight(); +} + +uint32_t Perl_Client_GetEXP(Client* self) // @categories Experience and Level +{ + return self->GetEXP(); +} + +uint32_t Perl_Client_GetAAExp(Client* self) // @categories Alternative Advancement, Experience and Level +{ + return self->GetAAXP(); +} + +uint32_t Perl_Client_GetAAPercent(Client* self) // @categories Alternative Advancement, Experience and Level +{ + return self->GetAAPercent(); +} + +uint32_t Perl_Client_GetTotalSecondsPlayed(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetTotalSecondsPlayed(); +} + +bool Perl_Client_UpdateLDoNPoints(Client* self, uint32 theme_id, int points) // @categories Currency and Points +{ + return self->UpdateLDoNPoints(theme_id, points); +} + +void Perl_Client_SetDeity(Client* self, uint32 deity_id) // @categories Account and Character, Stats and Attributes +{ + self->SetDeity(deity_id); +} + +void Perl_Client_AddEXP(Client* self, uint32 add_exp) // @categories Experience and Level +{ + self->AddEXP(add_exp); +} + +void Perl_Client_AddEXP(Client* self, uint32 add_exp, uint8 conlevel) // @categories Experience and Level +{ + self->AddEXP(add_exp, conlevel); +} + +void Perl_Client_AddEXP(Client* self, uint32 add_exp, uint8 conlevel, bool resexp) // @categories Experience and Level +{ + self->AddEXP(add_exp, conlevel, resexp); +} + +void Perl_Client_SetEXP(Client* self, uint64 set_exp, uint64 set_aaxp) // @categories Experience and Level +{ + self->SetEXP(set_exp, set_aaxp); +} + +void Perl_Client_SetEXP(Client* self, uint64 set_exp, uint64 set_aaxp, bool resexp) // @categories Experience and Level +{ + self->SetEXP(set_exp, set_aaxp, resexp); +} + +void Perl_Client_SetBindPoint(Client* self) // @categories Account and Character, Stats and Attributes +{ + self->SetBindPoint2(0); +} + +void Perl_Client_SetBindPoint(Client* self, int to_zone) // @categories Account and Character, Stats and Attributes +{ + self->SetBindPoint2(0, to_zone); +} + +void Perl_Client_SetBindPoint(Client* self, int to_zone, int to_instance) // @categories Account and Character, Stats and Attributes +{ + self->SetBindPoint2(0, to_zone, to_instance); +} + +void Perl_Client_SetBindPoint(Client* self, int to_zone, int to_instance, float new_x) // @categories Account and Character, Stats and Attributes +{ + self->SetBindPoint2(0, to_zone, to_instance, glm::vec4(new_x, 0.0f, 0.0f, 0.0f)); +} + +void Perl_Client_SetBindPoint(Client* self, int to_zone, int to_instance, float new_x, float new_y) // @categories Account and Character, Stats and Attributes +{ + self->SetBindPoint2(0, to_zone, to_instance, glm::vec4(new_x, new_y, 0.0f, 0.0f)); +} + +void Perl_Client_SetBindPoint(Client* self, int to_zone, int to_instance, float new_x, float new_y, float new_z) // @categories Account and Character, Stats and Attributes +{ + self->SetBindPoint2(0, to_zone, to_instance, glm::vec4(new_x, new_y, new_z, 0.0f)); +} + +void Perl_Client_SetBindPoint(Client* self, int to_zone, int to_instance, float new_x, float new_y, float new_z, float new_heading) // @categories Account and Character, Stats and Attributes +{ + self->SetBindPoint2(0, to_zone, to_instance, glm::vec4(new_x, new_y, new_z, new_heading)); +} + +float Perl_Client_GetBindX(Client* self) // @categories Account and Character +{ + return self->GetBindX(); +} + +float Perl_Client_GetBindX(Client* self, int index) // @categories Account and Character +{ + return self->GetBindX(index); +} + +float Perl_Client_GetBindY(Client* self) // @categories Account and Character +{ + return self->GetBindY(); +} + +float Perl_Client_GetBindY(Client* self, int index) // @categories Account and Character +{ + return self->GetBindY(index); +} + +float Perl_Client_GetBindZ(Client* self) // @categories Account and Character +{ + return self->GetBindZ(); +} + +float Perl_Client_GetBindZ(Client* self, int index) // @categories Account and Character +{ + return self->GetBindZ(index); +} + +float Perl_Client_GetBindHeading(Client* self) // @categories Account and Character +{ + return self->GetBindHeading(); +} + +float Perl_Client_GetBindHeading(Client* self, int index) // @categories Account and Character +{ + return self->GetBindHeading(index); +} + +uint32_t Perl_Client_GetBindZoneID(Client* self) // @categories Account and Character +{ + return self->GetBindZoneID(); +} + +uint32_t Perl_Client_GetBindZoneID(Client* self, int index) // @categories Account and Character +{ + return self->GetBindZoneID(index); +} + +void Perl_Client_MovePC(Client* self, uint32 zone_id, float x, float y, float z, float heading) // @categories Script Utility +{ + self->MovePC(zone_id, x, y, z, heading); +} + +void Perl_Client_MovePCInstance(Client* self, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading) // @categories Adventures and Expeditions, Script Utility +{ + self->MovePC(zone_id, instance_id, x, y, z, heading); +} + +void Perl_Client_ChangeLastName(Client* self, std::string last_name) // @categories Account and Character +{ + self->ChangeLastName(last_name); +} + +int Perl_Client_GetFactionLevel(Client* self, uint32 char_id, uint32 npc_id, uint32 race_id, uint32 class_id, uint32 deity_id, uint32 faction_id, Mob* tnpc) // @categories Faction +{ + return self->GetFactionLevel(char_id, npc_id, race_id, class_id, deity_id, faction_id, tnpc); +} + +void Perl_Client_SetFactionLevel(Client* self, uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity) // @categories Faction +{ + self->SetFactionLevel(char_id, npc_id, char_class, char_race, char_deity); +} + +void Perl_Client_SetFactionLevel2(Client* self, uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value) // @categories Faction +{ + self->SetFactionLevel2(char_id, faction_id, char_class, char_race, char_deity, value, 0); +} + +void Perl_Client_SetFactionLevel2(Client* self, uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp) // @categories Faction +{ + self->SetFactionLevel2(char_id, faction_id, char_class, char_race, char_deity, value, temp); +} + +int Perl_Client_GetRawItemAC(Client* self) // @categories Inventory and Items +{ + return self->GetRawItemAC(); +} + +uint32_t Perl_Client_AccountID(Client* self) // @categories Account and Character +{ + return self->AccountID(); +} + +std::string Perl_Client_AccountName(Client* self) // @categories Account and Character +{ + return self->AccountName(); +} + +int16 Perl_Client_Admin(Client* self) // @categories Account and Character +{ + return self->Admin(); +} + +uint32_t Perl_Client_CharacterID(Client* self) // @categories Account and Character +{ + return self->CharacterID(); +} + +void Perl_Client_UpdateAdmin(Client* self) // @categories Account and Character +{ + self->UpdateAdmin(); +} + +void Perl_Client_UpdateAdmin(Client* self, bool from_database) // @categories Account and Character +{ + self->UpdateAdmin(from_database); +} + +void Perl_Client_UpdateWho(Client* self) // @categories Script Utility +{ + self->UpdateWho(); +} + +void Perl_Client_UpdateWho(Client* self, uint8 remove) // @categories Script Utility +{ + self->UpdateWho(remove); +} + +int Perl_Client_GuildRank(Client* self) // @categories Account and Character, Guild +{ + return self->GuildRank(); +} + +uint32_t Perl_Client_GuildID(Client* self) // @categories Account and Character, Guild +{ + return self->GuildID(); +} + +int Perl_Client_GetFace(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetFace(); +} + +bool Perl_Client_TakeMoneyFromPP(Client* self, uint64 copper) // @categories Currency and Points +{ + return self->TakeMoneyFromPP(copper); +} + +bool Perl_Client_TakeMoneyFromPP(Client* self, uint64 copper, bool update_client) // @categories Currency and Points +{ + return self->TakeMoneyFromPP(copper, update_client); +} + +void Perl_Client_AddMoneyToPP(Client* self, uint32 copper, uint32 silver, uint32 gold, uint32 platinum) // @categories Currency and Points +{ + self->AddMoneyToPP(copper, silver, gold, platinum); +} + +void Perl_Client_AddMoneyToPP(Client* self, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool update_client) // @categories Currency and Points +{ + self->AddMoneyToPP(copper, silver, gold, platinum, update_client); +} + +bool Perl_Client_TGB(Client* self) // @categories Spells and Disciplines +{ + return self->TGB(); +} + +int Perl_Client_GetSkillPoints(Client* self) // @categories Skills and Recipes +{ + return self->GetSkillPoints(); +} + +void Perl_Client_SetSkillPoints(Client* self, int points) // @categories Skills and Recipes +{ + self->SetSkillPoints(points); +} + +void Perl_Client_IncreaseSkill(Client* self, int skill_id) // @categories Skills and Recipes +{ + self->IncreaseSkill(skill_id); +} + +void Perl_Client_IncreaseSkill(Client* self, int skill_id, int value) // @categories Skills and Recipes +{ + self->IncreaseSkill(skill_id, value); +} + +void Perl_Client_IncreaseLanguageSkill(Client* self, int skill_id) // @categories Skills and Recipes +{ + self->IncreaseLanguageSkill(skill_id); +} + +void Perl_Client_IncreaseLanguageSkill(Client* self, int skill_id, int value) // @categories Skills and Recipes +{ + self->IncreaseLanguageSkill(skill_id, value); +} + +uint32_t Perl_Client_GetRawSkill(Client* self, int skill_id) // @categories Skills and Recipes +{ + return self->GetRawSkill(static_cast(skill_id)); +} + +bool Perl_Client_HasSkill(Client* self, int skill_id) // @categories Skills and Recipes +{ + return self->HasSkill(static_cast(skill_id)); +} + +bool Perl_Client_CanHaveSkill(Client* self, int skill_id) // @categories Skills and Recipes +{ + return self->CanHaveSkill(static_cast(skill_id)); +} + +void Perl_Client_SetSkill(Client* self, int skill_id, uint16 value) // @categories Skills and Recipes +{ + self->SetSkill(static_cast(skill_id), value); +} + +void Perl_Client_AddSkill(Client* self, int skill_id, uint16 value) // @categories Skills and Recipes +{ + self->AddSkill(static_cast(skill_id), value); +} + +void Perl_Client_CheckSpecializeIncrease(Client* self, uint16 spell_id) // @categories Spells and Disciplines +{ + self->CheckSpecializeIncrease(spell_id); +} + +bool Perl_Client_CheckIncreaseSkill(Client* self, int skill_id) // @categories Skills and Recipes +{ + return self->CheckIncreaseSkill(static_cast(skill_id), nullptr); +} + +bool Perl_Client_CheckIncreaseSkill(Client* self, int skill_id, int chance_modifier) // @categories Skills and Recipes +{ + return self->CheckIncreaseSkill(static_cast(skill_id), nullptr, chance_modifier); +} + +void Perl_Client_SetLanguageSkill(Client* self, int language_id, int value) // @categories Account and Character, Skills and Recipes, Stats and Attributes +{ + self->SetLanguageSkill(language_id, value); +} + +int Perl_Client_MaxSkill(Client* self, uint16 skill_id) // @categories Skills and Recipes +{ + return self->MaxSkill(static_cast(skill_id), self->GetClass(), self->GetLevel()); +} + +int Perl_Client_MaxSkill(Client* self, uint16 skill_id, uint16 class_id) // @categories Skills and Recipes +{ + return self->MaxSkill(static_cast(skill_id), class_id, self->GetLevel()); +} + +int Perl_Client_MaxSkill(Client* self, uint16 skill_id, uint16 class_id, uint16 level) // @categories Skills and Recipes +{ + return self->MaxSkill(static_cast(skill_id), class_id, level); +} + +void Perl_Client_GMKill(Client* self) // @categories Script Utility +{ + self->GMKill(); +} + +bool Perl_Client_IsMedding(Client* self) // @categories Account and Character +{ + return self->IsMedding(); +} + +uint32_t Perl_Client_GetDuelTarget(Client* self) // @categories Account and Character, Script Utility +{ + return self->GetDuelTarget(); +} + +bool Perl_Client_IsDueling(Client* self) // @categories Account and Character +{ + return self->IsDueling(); +} + +void Perl_Client_SetDuelTarget(Client* self, uint32_t set_id) // @categories Account and Character +{ + self->SetDuelTarget(set_id); +} + +void Perl_Client_SetDueling(Client* self, bool duel) // @categories Account and Character, Script Utility +{ + self->SetDueling(duel); +} + +void Perl_Client_ResetAA(Client* self) // @categories Alternative Advancement +{ + self->ResetAA(); +} + +void Perl_Client_MemSpell(Client* self, uint16 spell_id, int slot) // @categories Spells and Disciplines +{ + self->MemSpell(spell_id, slot); +} + +void Perl_Client_MemSpell(Client* self, uint16 spell_id, int slot, bool update_client) // @categories Spells and Disciplines +{ + self->MemSpell(spell_id, slot, update_client); +} + +void Perl_Client_UnmemSpell(Client* self, int slot) // @categories Spells and Disciplines +{ + self->UnmemSpell(slot); +} + +void Perl_Client_UnmemSpell(Client* self, int slot, bool update_client) // @categories Spells and Disciplines +{ + self->UnmemSpell(slot, update_client); +} + +void Perl_Client_UnmemSpellBySpellID(Client* self, int spell_id) // @categories Spells and Disciplines +{ + self->UnmemSpellBySpellID(spell_id); +} + +void Perl_Client_UnmemSpellAll(Client* self) // @categories Spells and Disciplines +{ + self->UnmemSpellAll(); +} + +void Perl_Client_UnmemSpellAll(Client* self, bool update_client) // @categories Spells and Disciplines +{ + self->UnmemSpellAll(update_client); +} + +int Perl_Client_FindEmptyMemSlot(Client* self) // @categories Account and Character, Spells and Disciplines +{ + return self->FindEmptyMemSlot(); +} + +int Perl_Client_FindMemmedSpellBySlot(Client* self, int slot) // @categories Account and Character, Spells and Disciplines +{ + return self->FindMemmedSpellBySlot(slot); +} + +int Perl_Client_FindMemmedSpellBySpellID(Client* self, uint16 spell_id) // @categories Account and Character, Spells and Disciplines +{ + return self->FindMemmedSpellBySpellID(spell_id); +} + +int Perl_Client_MemmedCount(Client* self) // @categories Spells and Disciplines +{ + return self->MemmedCount(); +} + +void Perl_Client_ScribeSpell(Client* self, uint16 spell_id, int slot) // @categories Spells and Disciplines +{ + self->ScribeSpell(spell_id, slot); +} + +void Perl_Client_ScribeSpell(Client* self, uint16 spell_id, int slot, bool update_client) // @categories Spells and Disciplines +{ + self->ScribeSpell(spell_id, slot, update_client); +} + +void Perl_Client_UnscribeSpell(Client* self, int slot) // @categories Spells and Disciplines +{ + self->UnscribeSpell(slot); +} + +void Perl_Client_UnscribeSpell(Client* self, int slot, bool update_client) // @categories Spells and Disciplines +{ + self->UnscribeSpell(slot, update_client); +} + +void Perl_Client_UnscribeSpellAll(Client* self) +{ + self->UnscribeSpellAll(); +} + +void Perl_Client_UnscribeSpellAll(Client* self, bool update_client) +{ + self->UnscribeSpellAll(update_client); +} + +void Perl_Client_TrainDiscBySpellID(Client* self, int spell_id) // @categories Spells and Disciplines +{ + self->TrainDiscBySpellID(spell_id); +} + +int Perl_Client_GetDiscSlotBySpellID(Client* self, int spell_id) // @categories Spells and Disciplines +{ + return self->GetDiscSlotBySpellID(spell_id); +} + +void Perl_Client_UntrainDisc(Client* self, int slot) // @categories Spells and Disciplines +{ + self->UntrainDisc(slot); +} + +void Perl_Client_UntrainDisc(Client* self, int slot, bool update_client) // @categories Spells and Disciplines +{ + self->UntrainDisc(slot, update_client); +} + +void Perl_Client_UntrainDiscAll(Client* self) // @categories Spells and Disciplines +{ + self->UntrainDiscAll(); +} + +void Perl_Client_UntrainDiscAll(Client* self, bool update_client) // @categories Spells and Disciplines +{ + self->UntrainDiscAll(update_client); +} + +bool Perl_Client_IsStanding(Client* self) // @categories Account and Character +{ + return self->IsStanding(); +} + +void Perl_Client_Sit(Client* self) +{ + self->Sit(); +} + +bool Perl_Client_IsSitting(Client* self) // @categories Account and Character +{ + return self->IsSitting(); +} + +bool Perl_Client_IsCrouching(Client* self) // @categories Account and Character +{ + return self->IsCrouching(); +} + +bool Perl_Client_IsBecomeNPC(Client* self) // @categories Account and Character +{ + return self->IsBecomeNPC(); +} + +int Perl_Client_GetBecomeNPCLevel(Client* self) // @categories Experience and Level +{ + return self->GetBecomeNPCLevel(); +} + +void Perl_Client_SetBecomeNPC(Client* self, bool flag) // @categories Account and Character, Stats and Attributes +{ + self->SetBecomeNPC(flag); +} + +void Perl_Client_SetBecomeNPCLevel(Client* self, uint8 level) // @categories Account and Character, Stats and Attributes +{ + self->SetBecomeNPCLevel(level); +} + +void Perl_Client_SetFeigned(Client* self, bool feigned) // @categories Script Utility +{ + self->SetFeigned(feigned); +} + +bool Perl_Client_GetFeigned(Client* self) // @categories Script Utility +{ + return self->GetFeigned(); +} + +bool Perl_Client_AutoSplitEnabled(Client* self) // @categories Currency and Points +{ + return self->AutoSplitEnabled(); +} + +void Perl_Client_SetHorseId(Client* self, uint16_t horseid) // @categories Script Utility +{ + self->SetHorseId(horseid); +} + +int Perl_Client_GetHorseId(Client* self) // @categories Account and Character, Script Utility +{ + return self->GetHorseId(); +} + +uint32 Perl_Client_NukeItem(Client* self, uint32 item_id) // @categories Inventory and Items +{ + return self->NukeItem(item_id, 0xFF); +} + +uint32 Perl_Client_NukeItem(Client* self, uint32 item_id, uint8 slot_to_check) // @categories Inventory and Items +{ + return self->NukeItem(item_id, slot_to_check); +} + +void Perl_Client_SetTint(Client* self, int16 slot_id, uint32 color) // @categories Inventory and Items +{ + self->SetTint(slot_id, color); +} + +void Perl_Client_SetMaterial(Client* self, int16 slot_id, uint32 item_id) // @categories Inventory and Items +{ + self->SetMaterial(slot_id, item_id); +} + +void Perl_Client_Undye(Client* self) // @categories Script Utility +{ + self->Undye(); +} + +int Perl_Client_GetItemIDAt(Client* self, int16 slot_id) // @categories Inventory and Items +{ + return self->GetItemIDAt(slot_id); +} + +int Perl_Client_GetAugmentIDAt(Client* self, int16 slot_id, uint8 aug_slot) // @categories Inventory and Items +{ + return self->GetAugmentIDAt(slot_id, aug_slot); +} + +void Perl_Client_DeleteItemInInventory(Client* self, int16 slot_id) // @categories Inventory and Items +{ + self->DeleteItemInInventory(slot_id); +} + +void Perl_Client_DeleteItemInInventory(Client* self, int16 slot_id, int16 quantity) // @categories Inventory and Items +{ + self->DeleteItemInInventory(slot_id, quantity); +} + +void Perl_Client_DeleteItemInInventory(Client* self, int16 slot_id, int16 quantity, bool client_update) // @categories Inventory and Items +{ + self->DeleteItemInInventory(slot_id, quantity, client_update); +} + +void Perl_Client_SummonItem(Client* self, uint32 item_id) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id); +} + +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges); +} + +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges, bool attune) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges, 0, 0, 0, 0, 0, 0, attune); +} + +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges, bool attune, uint32 aug1) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges, aug1, 0, 0, 0, 0, 0, attune); +} + +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges, bool attune, uint32 aug1, uint32 aug2) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges, aug1, aug2, 0, 0, 0, 0, attune); +} + +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges, bool attune, uint32 aug1, uint32 aug2, uint32 aug3) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges, aug1, aug2, aug3, 0, 0, 0, attune); +} + +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges, bool attune, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, 0, 0, attune); } -XS(XS_Client_GetFeigned); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetFeigned) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetFeigned(THIS)"); // @categories Script Utility - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetFeigned(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges, bool attune, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, 0, attune); } -XS(XS_Client_AutoSplitEnabled); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AutoSplitEnabled) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::AutoSplitEnabled(THIS)"); // @categories Currency and Points - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->AutoSplitEnabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_SummonItem(Client* self, uint32 item_id, int16 charges, bool attune, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint16 slot_id) // @categories Inventory and Items, Script Utility +{ + self->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, 0, attune, slot_id); } -XS(XS_Client_SetHorseId); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetHorseId) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetHorseId(THIS, horseid_in)"); // @categories Script Utility - { - Client *THIS; - uint16 horseid_in = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetHorseId(horseid_in); - } - XSRETURN_EMPTY; +void Perl_Client_SetStats(Client* self, uint8 type, uint16 increase_val) // @categories Account and Character, Stats and Attributes +{ + self->SetStats(type, increase_val); } -XS(XS_Client_GetHorseId); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetHorseId) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetHorseId(THIS)"); // @categories Account and Character, Script Utility - { - Client *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetHorseId(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_IncStats(Client* self, uint8 type, uint16 increase_val) // @categories Account and Character, Stats and Attributes +{ + self->IncStats(type, increase_val); } -XS(XS_Client_NukeItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_NukeItem) { - dXSARGS; - if (items != 3 && items != 2) - Perl_croak(aTHX_ "Usage: Client::NukeItem(THIS, uint32 item_id, [uint8 slot_to_check])"); // @categories Inventory and Items - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - uint32 itemnum = (uint32) SvUV(ST(1)); - uint8 where_to_check; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) { - where_to_check = 0xFF; - } - if (items == 3) { - where_to_check = (uint8) SvUV(ST(2)); - } - - RETVAL = THIS->NukeItem(itemnum, where_to_check); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_DropItem(Client* self, int16 slot_id) // @categories Inventory and Items +{ + self->DropItem(slot_id); } -XS(XS_Client_SetTint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetTint) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetTint(THIS, int16 slot_id, uint32 color)"); // @categories Inventory and Items - { - Client *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - uint32 color = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetTint(slot_id, color); - } - XSRETURN_EMPTY; +void Perl_Client_BreakInvis(Client* self) // @categories Spells and Disciplines, Script Utility +{ + self->BreakInvis(); } -XS(XS_Client_SetMaterial); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetMaterial) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetMaterial(THIS, int16 slot_id, uint32 item_id)"); // @categories Inventory and Items - { - Client *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - uint32 item_id = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetMaterial(slot_id, item_id); - } - XSRETURN_EMPTY; +Group* Perl_Client_GetGroup(Client* self) // @categories Account and Character, Group +{ + return self->GetGroup(); } -XS(XS_Client_Undye); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Undye) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Undye(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->Undye(); - } - XSRETURN_EMPTY; +void Perl_Client_LeaveGroup(Client* self) // @categories Account and Character, Group +{ + self->LeaveGroup(); } -XS(XS_Client_GetItemIDAt); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetItemIDAt) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetItemIDAt(THIS, int16 slot_id)"); // @categories Inventory and Items - { - Client *THIS; - int32 RETVAL; - dXSTARG; - int16 slot_id = (int16) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetItemIDAt(slot_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +Raid* Perl_Client_GetRaid(Client* self) // @categories Account and Character, Raid +{ + return self->GetRaid(); } -XS(XS_Client_GetAugmentIDAt); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAugmentIDAt) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::GetAugmentIDAt(THIS, int16 slot_id, int16 aug_slot)"); // @categories Inventory and Items - { - Client *THIS; - int32 RETVAL; - dXSTARG; - int16 slot_id = (int16) SvIV(ST(1)); - int16 augslot = (uint8) SvIV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAugmentIDAt(slot_id, augslot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +bool Perl_Client_IsGrouped(Client* self) // @categories Account and Character, Group +{ + return self->IsGrouped(); } -XS(XS_Client_DeleteItemInInventory); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_DeleteItemInInventory) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Client::DeleteItemInInventory(THIS, int16 slot_id, [int16 quantity = 0], [bool client_update = false])"); // @categories Inventory and Items - { - Client *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - int16 quantity; - bool client_update; - VALIDATE_THIS_IS_CLIENT; - if (items < 3) - quantity = 0; - else { - quantity = (int16) SvIV(ST(2)); - } - - if (items < 4) - client_update = false; - else { - client_update = (bool) SvTRUE(ST(3)); - } - - THIS->DeleteItemInInventory(slot_id, quantity, client_update); - } - XSRETURN_EMPTY; +bool Perl_Client_IsRaidGrouped(Client* self) // @categories Account and Character, Group, Raid +{ + return self->IsRaidGrouped(); } -XS(XS_Client_SummonItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SummonItem) { - dXSARGS; - if (items < 2 || items > 10) - Perl_croak(aTHX_ "Usage: Client::SummonItem(THIS, uint32 item_id, [int16 charges = -1], [bool attune = false], [uint32 aug1 = 0], [uint32 aug2 = 0], [uint32 aug3 = 0], [uint32 aug4 = 0], [uint32 aug5 = 0], [uint16 slot_id = cursor])"); // @categories Inventory and Items, Script Utility - { - Client *THIS; - uint32 item_id = (uint32) SvUV(ST(1)); - int16 charges = -1; - bool attune = false; - uint32 aug1 = 0; - uint32 aug2 = 0; - uint32 aug3 = 0; - uint32 aug4 = 0; - uint32 aug5 = 0; - uint16 slot_id = EQ::invslot::slotCursor; - VALIDATE_THIS_IS_CLIENT; - if (items > 2) { - charges = (int16) SvIV(ST(2)); - } - if (items > 3) { - attune = (bool) SvTRUE(ST(3)); - } - if (items > 4) { - aug1 = (uint32) SvUV(ST(4)); - } - if (items > 5) { - aug2 = (uint32) SvUV(ST(5)); - } - if (items > 6) { - aug3 = (uint32) SvUV(ST(6)); - } - if (items > 7) { - aug4 = (uint32) SvUV(ST(7)); - } - if (items > 8) { - aug5 = (uint32) SvUV(ST(8)); - } - if (items > 9) { - slot_id = (uint16) SvUV(ST(9)); - } - - THIS->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, 0, attune, slot_id); - } - XSRETURN_EMPTY; +bool Perl_Client_Hungry(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->Hungry(); } -XS(XS_Client_SetStats); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetStats) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetStats(THIS, uint8 type, uint16 increase_val)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 type = (uint8) SvUV(ST(1)); - int16 increase_val = (int16) SvIV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetStats(type, increase_val); - } - XSRETURN_EMPTY; +bool Perl_Client_Thirsty(Client* self) // @categories Script Utility +{ + return self->Thirsty(); } -XS(XS_Client_IncStats); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IncStats) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::IncStats(THIS, uint8 type, uint16 increase_val)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint8 type = (uint8) SvUV(ST(1)); - int16 increase_val = (int16) SvIV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->IncStats(type, increase_val); - } - XSRETURN_EMPTY; +int Perl_Client_GetInstrumentMod(Client* self, uint16 spell_id) // @categories Spells and Disciplines +{ + return self->GetInstrumentMod(spell_id); } -XS(XS_Client_DropItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_DropItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::DropItem(THIS, int16 slot_id)"); // @categories Inventory and Items - { - Client *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->DropItem(slot_id); - } - XSRETURN_EMPTY; +bool Perl_Client_DecreaseByID(Client* self, uint32 type, int16 quantity) // @categories Script Utility +{ + return self->DecreaseByID(type, quantity); } -XS(XS_Client_BreakInvis); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_BreakInvis) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::BreakInvis(THIS)"); // @categories Spells and Disciplines, Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->BreakInvis(); - } - XSRETURN_EMPTY; +int Perl_Client_SlotConvert2(Client* self, uint8 slot) // @categories Inventory and Items +{ + return self->SlotConvert2(slot); } -XS(XS_Client_GetGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetGroup) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetGroup(THIS)"); // @categories Account and Character, Group - { - Client *THIS; - Group *RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetGroup(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Group", (void *) RETVAL); - } - XSRETURN(1); +void Perl_Client_Escape(Client* self) // @categories Account and Character, Skills and Recipes +{ + self->Escape(); } -XS(XS_Client_LeaveGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_LeaveGroup) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::LeaveGroup(THIS)"); // @categories Account and Character, Group - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->LeaveGroup(); - } - XSRETURN_EMPTY; +void Perl_Client_RemoveNoRent(Client* self) // @categories Inventory and Items +{ + self->RemoveNoRent(); } -XS(XS_Client_GetRaid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetRaid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetRaid(THIS)"); // @categories Account and Character, Raid - { - Client *THIS; - Raid *RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetRaid(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Raid", (void *) RETVAL); - } - XSRETURN(1); +void Perl_Client_GoFish(Client* self) // @categories Skills and Recipes +{ + self->GoFish(); } -XS(XS_Client_IsGrouped); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsGrouped) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsGrouped(THIS)"); // @categories Account and Character, Group - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsGrouped(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_ForageItem(Client* self) // @categories Skills and Recipes +{ + self->ForageItem(); } -XS(XS_Client_IsRaidGrouped); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsRaidGrouped) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::IsRaidGrouped(THIS)"); // @categories Account and Character, Group, Raid - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsRaidGrouped(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +float Perl_Client_CalcPriceMod(Client* self) // @categories Currency and Points +{ + return self->CalcPriceMod(); } -XS(XS_Client_Hungry); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Hungry) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Hungry(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->Hungry(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +float Perl_Client_CalcPriceMod(Client* self, Mob* other) // @categories Currency and Points +{ + return self->CalcPriceMod(other); } -XS(XS_Client_Thirsty); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Thirsty) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Thirsty(THIS)"); // @categories Script Utility - { - Client *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->Thirsty(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +float Perl_Client_CalcPriceMod(Client* self, Mob* other, bool reverse) // @categories Currency and Points +{ + return self->CalcPriceMod(other, reverse); } -XS(XS_Client_GetInstrumentMod); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetInstrumentMod) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetInstrumentMod(THIS, uint16 spell_id)"); // @categories Spells and Disciplines - { - Client *THIS; - uint16 RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetInstrumentMod(spell_id); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_ResetTrade(Client* self) // @categories Script Utility +{ + self->ResetTrade(); } -XS(XS_Client_DecreaseByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_DecreaseByID) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::DecreaseByID(THIS, uint32 type, int16 quantity)"); // @categories Script Utility - { - Client *THIS; - bool RETVAL; - uint32 type = (uint32) SvUV(ST(1)); - int16 quantity = (int16) SvIV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->DecreaseByID(type, quantity); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Client_UseDiscipline(Client* self, uint32 spell_id, uint32 target) // @categories Spells and Disciplines +{ + return self->UseDiscipline(spell_id, target); } -XS(XS_Client_SlotConvert2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SlotConvert2) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SlotConvert2(THIS, uint8 slot)"); // @categories Inventory and Items - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - uint8 slot = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->SlotConvert2(slot); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetDisciplineTimer(Client* self, uint32 timer_id) // @categories Spells and Disciplines +{ + return self->GetDisciplineTimer(timer_id); } -XS(XS_Client_Escape); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Escape) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Escape(THIS)"); // @categories Account and Character, Skills and Recipes - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->Escape(); - } - XSRETURN_EMPTY; +void Perl_Client_ResetDisciplineTimer(Client* self, uint32_t timer_id) // @categories Spells and Disciplines +{ + self->ResetDisciplineTimer(timer_id); } -XS(XS_Client_RemoveNoRent); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_RemoveNoRent) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::RemoveNoRent(THIS)"); // @categories Inventory and Items - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->RemoveNoRent(); - } - XSRETURN_EMPTY; +int Perl_Client_GetCharacterFactionLevel(Client* self, int faction_id) // @categories Faction +{ + return self->GetCharacterFactionLevel(faction_id); } -XS(XS_Client_GoFish); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GoFish) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GoFish(THIS)"); // @categories Skills and Recipes - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->GoFish(); - } - XSRETURN_EMPTY; +void Perl_Client_SetZoneFlag(Client* self, uint32 zone_id) // @categories Account and Character, Zones +{ + self->SetZoneFlag(zone_id); } -XS(XS_Client_ForageItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ForageItem) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::ForageItem(THIS)"); // @categories Skills and Recipes - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->ForageItem(); - } - XSRETURN_EMPTY; +void Perl_Client_ClearZoneFlag(Client* self, uint32 zone_id) // @categories Script Utility +{ + self->ClearZoneFlag(zone_id); } -XS(XS_Client_CalcPriceMod); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_CalcPriceMod) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: Client::CalcPriceMod(THIS, Mob*, [bool reverse = false])"); // @categories Currency and Points - { - Client *THIS; - float RETVAL; - dXSTARG; - Mob *other; - bool reverse; - VALIDATE_THIS_IS_CLIENT; - if (items < 2) - other = 0; - else { - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - } - - if (items < 3) - reverse = false; - else { - reverse = (bool) SvTRUE(ST(2)); - } - - RETVAL = THIS->CalcPriceMod(other, reverse); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +bool Perl_Client_HasZoneFlag(Client* self, uint32 zone_id) // @categories Account and Character +{ + return self->HasZoneFlag(zone_id); } -XS(XS_Client_ResetTrade); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ResetTrade) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::ResetTrade(THIS)"); // @categories Script Utility - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->ResetTrade(); - } - XSRETURN_EMPTY; +void Perl_Client_SendZoneFlagInfo(Client* self, Client* to) // @categories Account and Character, Zones +{ + self->SendZoneFlagInfo(to); } -XS(XS_Client_UseDiscipline); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UseDiscipline) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::UseDiscipline(THIS, int32 spell_id, int32 target)"); // @categories Spells and Disciplines - { - Client *THIS; - bool RETVAL; - uint32 spell_id = (uint32) SvUV(ST(1)); - uint32 target = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->UseDiscipline(spell_id, target); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_LoadZoneFlags(Client* self) // @categories Zones +{ + self->LoadZoneFlags(); } -XS(XS_Client_GetDisciplineTimer); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetDisciplineTimer) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetDisciplineTimer(THIS, uint32 timer_id)"); // @categories Spells and Disciplines +void Perl_Client_SetAATitle(Client* self, std::string title) // @categories Alternative Advancement +{ + if (title.size() > 31) { - Client *THIS; - uint32 RETVAL; - dXSTARG; - uint32 timer_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetDisciplineTimer(timer_id); - XSprePUSH; - PUSHu((UV) RETVAL); + throw std::runtime_error("Title must be 31 characters or less."); } - XSRETURN(1); + + self->SetAATitle(title); } -XS(XS_Client_ResetDisciplineTimer); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ResetDisciplineTimer) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::ResetDisciplineTimer(THIS, uint32 timer_id)"); // @categories Spells and Disciplines +void Perl_Client_SetAATitle(Client* self, std::string title, bool save) // @categories Alternative Advancement +{ + if (title.size() > 31) { - Client *THIS; - uint32 timer_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->ResetDisciplineTimer(timer_id); + throw std::runtime_error("Title must be 31 characters or less."); } - XSRETURN_EMPTY; -} -XS(XS_Client_GetCharacterFactionLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetCharacterFactionLevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetCharacterFactionLevel(THIS, int32 faction_id)"); // @categories Faction - { - Client *THIS; - int32 RETVAL; - dXSTARG; - int32 faction_id = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetCharacterFactionLevel(faction_id); - XSprePUSH; - PUSHi((IV) RETVAL); + if (!save) { + self->SetAATitle(title); + } else { + title_manager.CreateNewPlayerTitle(self, title); } - XSRETURN(1); } -XS(XS_Client_SetZoneFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetZoneFlag) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetZoneFlag(THIS, uint32 zone_id)"); // @categories Account and Character, Zones - { - Client *THIS; - uint32 zone_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetZoneFlag(zone_id); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetClientVersion(Client* self) // @categories Script Utility +{ + return static_cast(self->ClientVersion()); } -XS(XS_Client_ClearZoneFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ClearZoneFlag) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::ClearZoneFlag(THIS, uint32 zone_id)"); // @categories Script Utility - { - Client *THIS; - uint32 zone_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->ClearZoneFlag(zone_id); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetClientVersionBit(Client* self) // @categories Script Utility +{ + return self->ClientVersionBit(); } -XS(XS_Client_HasZoneFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_HasZoneFlag) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::HasZoneFlag(THIS, uint32 zone_id)"); // @categories Account and Character +void Perl_Client_SetTitleSuffix(Client* self, std::string suffix) // @categories Account and Character +{ + if (suffix.size() > 31) { - Client *THIS; - bool RETVAL; - uint32 zone_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->HasZoneFlag(zone_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); + throw std::runtime_error("Suffix must be 31 characters or less."); } - XSRETURN(1); + + self->SetTitleSuffix(suffix); } -XS(XS_Client_SendZoneFlagInfo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendZoneFlagInfo) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SendZoneFlagInfo(THIS, Client* to)"); // @categories Account and Character, Zones +void Perl_Client_SetTitleSuffix(Client* self, std::string suffix, bool save) // @categories Account and Character +{ + if (suffix.size() > 31) { - Client *THIS; - Client *to; - VALIDATE_THIS_IS_CLIENT; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - to = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "to is not of type Client"); - if (to == nullptr) - Perl_croak(aTHX_ "to is nullptr, avoiding crash."); - - THIS->SendZoneFlagInfo(to); + throw std::runtime_error("Suffix must be 31 characters or less."); } - XSRETURN_EMPTY; -} -XS(XS_Client_LoadZoneFlags); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_LoadZoneFlags) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::LoadZoneFlags(THIS)"); // @categories Zones - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->LoadZoneFlags(); + if (!save) { + self->SetTitleSuffix(suffix); + } else { + title_manager.CreateNewPlayerSuffix(self, suffix); } - XSRETURN_EMPTY; } -XS(XS_Client_SetAATitle); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetAATitle) { - dXSARGS; - if ((items < 2) || (items > 3)) - Perl_croak(aTHX_ "Usage: Client::SetAATitle(THIS, string text, [bool save = false])"); // @categories Alternative Advancement - { - Client *THIS; - char *txt = (char *) SvPV_nolen(ST(1)); - bool SaveTitle = false; - VALIDATE_THIS_IS_CLIENT; - if (strlen(txt) > 31) - Perl_croak(aTHX_ "Title must be 31 characters or less"); - - if (items == 3) - SaveTitle = (SvIV(ST(2)) != 0); - - if (!SaveTitle) - THIS->SetAATitle(txt); - else - title_manager.CreateNewPlayerTitle(THIS, txt); - } - XSRETURN_EMPTY; +void Perl_Client_SetAAPoints(Client* self, uint32 points) // @categories Alternative Advancement +{ + return self->SetAAPoints(points); } -XS(XS_Client_GetClientVersion); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetClientVersion) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetClientVersion(THIS)"); // @categories Script Utility - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = static_cast(THIS->ClientVersion()); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetAAPoints(Client* self) // @categories Alternative Advancement, Experience and Level +{ + return self->GetAAPoints(); } -XS(XS_Client_GetClientVersionBit); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetClientVersionBit) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetClientVersionBit(THIS)"); // @categories Script Utility - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->ClientVersionBit(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetSpentAA(Client* self) // @categories Alternative Advancement +{ + return self->GetSpentAA(); } -XS(XS_Client_SetTitleSuffix); -XS(XS_Client_SetTitleSuffix) { - dXSARGS; - if ((items < 2) || (items > 3)) - Perl_croak(aTHX_ "Usage: Client::SetTitleSuffix(THIS, string text, [bool save = false])"); // @categories Account and Character - { - Client *THIS; - char *txt = (char *) SvPV_nolen(ST(1)); - bool SaveSuffix = false; - VALIDATE_THIS_IS_CLIENT; - if (strlen(txt) > 31) - Perl_croak(aTHX_ "Title must be 31 characters or less"); - - if (items == 3) - SaveSuffix = (SvIV(ST(2)) != 0); - - if (!SaveSuffix) - THIS->SetTitleSuffix(txt); - else - title_manager.CreateNewPlayerSuffix(THIS, txt); - } - XSRETURN_EMPTY; +void Perl_Client_AddAAPoints(Client* self, uint32 points) // @categories Alternative Advancement +{ + self->AddAAPoints(points); } -XS(XS_Client_SetAAPoints); -XS(XS_Client_SetAAPoints) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetAAPoints(THIS, uint32 points)"); // @categories Alternative Advancement - { - Client *THIS; - uint32 points = SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetAAPoints(points); - } - XSRETURN_EMPTY; +void Perl_Client_RefundAA(Client* self) // @categories Alternative Advancement +{ + self->RefundAA(); } -XS(XS_Client_GetAAPoints); -XS(XS_Client_GetAAPoints) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetAAPoints(THIS)"); // @categories Alternative Advancement, Experience and Level - dXSTARG; - { - Client *THIS; - uint32 RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAAPoints(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_Client_GetModCharacterFactionLevel(Client* self, int faction_id) // @categories Faction +{ + return self->GetModCharacterFactionLevel(faction_id); } -XS(XS_Client_GetSpentAA); -XS(XS_Client_GetSpentAA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetSpentAA(THIS)"); // @categories Alternative Advancement - dXSTARG; - { - Client *THIS; - uint32 RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetSpentAA(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetLDoNWins(Client* self) // @categories Currency and Points +{ + return self->GetLDoNWins(); } -XS(XS_Client_AddAAPoints); -XS(XS_Client_AddAAPoints) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::AddAAPoints(THIS, uint32 points)"); // @categories Alternative Advancement - { - Client *THIS; - uint32 points = SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->AddAAPoints(points); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetLDoNLosses(Client* self) // @categories Currency and Points +{ + return self->GetLDoNLosses(); } -XS(XS_Client_RefundAA); -XS(XS_Client_RefundAA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::RefundAA(THIS)"); // @categories Alternative Advancement - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->RefundAA(); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetLDoNWinsTheme(Client* self, uint32_t theme) // @categories Currency and Points +{ + return self->GetLDoNWinsTheme(theme); } -XS(XS_Client_GetModCharacterFactionLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetModCharacterFactionLevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetModCharacterFactionLevel(THIS, int32 faction_id)"); // @categories Faction - { - Client *THIS; - int32 RETVAL; - dXSTARG; - int32 faction_id = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetModCharacterFactionLevel(faction_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetLDoNLossesTheme(Client* self, uint32_t theme) // @categories Currency and Points +{ + return self->GetLDoNLossesTheme(theme); } -XS(XS_Client_GetLDoNWins); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetLDoNWins) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetLDoNWins(THIS)"); // @categories Currency and Points - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetLDoNWins(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +EQ::ItemInstance* Perl_Client_GetItemAt(Client* self, uint32 slot) // @categories Inventory and Items +{ + return self->GetInv().GetItem(slot); } -XS(XS_Client_GetLDoNLosses); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetLDoNLosses) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetLDoNLosses(THIS)"); // @categories Currency and Points +EQ::ItemInstance* Perl_Client_GetAugmentAt(Client* self, uint32 slot, uint32 aug_slot) // @categories Inventory and Items +{ + EQ::ItemInstance* inst = self->GetInv().GetItem(slot); + if (inst) { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetLDoNLosses(); - XSprePUSH; - PUSHu((UV) RETVAL); + return inst->GetAugment(aug_slot); } - XSRETURN(1); + return nullptr; } -XS(XS_Client_GetLDoNWinsTheme); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetLDoNWinsTheme) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetLDoNWinsTheme(THIS, int32 theme)"); // @categories Currency and Points - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - int32 theme_out = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetLDoNWinsTheme(theme_out); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetStartZone(Client* self) // @categories Account and Character +{ + return self->GetStartZone(); } -XS(XS_Client_GetLDoNLossesTheme); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetLDoNLossesTheme) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetLDoNLossesTheme(THIS, int32 theme)"); // @categories Currency and Points - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - int32 theme_out = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetLDoNLossesTheme(theme_out); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_SetStartZone(Client* self, uint32 zone_id) +{ + self->SetStartZone(zone_id); } -XS(XS_Client_GetItemAt); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetItemAt) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetItemAt(THIS, uint32 slot)"); // @categories Inventory and Items - { - Client *THIS; - EQ::ItemInstance *RETVAL; - uint32 slot = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetInv().GetItem(slot); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "QuestItem", (void *) RETVAL); - } - XSRETURN(1); +void Perl_Client_SetStartZone(Client* self, uint32 zone_id, float x, float y, float z) +{ + self->SetStartZone(zone_id, x, y, z); } -XS(XS_Client_GetAugmentAt); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAugmentAt) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::GetAugmentAt(THIS, uint32 slot, uint32 aug_slot)"); // @categories Inventory and Items - { - Client *THIS; - EQ::ItemInstance *RETVAL; - uint32 slot = (int32) SvIV(ST(1)); - uint32 aug_slot = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - EQ::ItemInstance *inst = THIS->GetInv().GetItem(slot); - if (inst) { - RETVAL = inst->GetAugment(aug_slot); - } else { - RETVAL = nullptr; - } - - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "QuestItem", (void *) RETVAL); - } - XSRETURN(1); +void Perl_Client_SetStartZone(Client* self, uint32 zone_id, float x, float y, float z, float heading) +{ + self->SetStartZone(zone_id, x, y, z, heading); } -XS(XS_Client_GetStartZone); -XS(XS_Client_GetStartZone) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetStartZone(THIS)"); // @categories Account and Character - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetStartZone(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_KeyRingAdd(Client* self, uint32 item_id) // @categories Account and Character, Inventory and Items +{ + self->KeyRingAdd(item_id);; } -XS(XS_Client_SetStartZone); -XS(XS_Client_SetStartZone) { - dXSARGS; - if (items != 2 && items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: Client::SetStartZone(THIS, uint32 zone_id, [float x = 0, float y = 0, float z = 0, [float heading = 0]])"); - { - Client *THIS; - uint32 zoneid = (uint32) SvUV(ST(1)); - float x = 0.0f, y = 0.0f, z = 0.0f, heading = 0.0f; - VALIDATE_THIS_IS_CLIENT; - if (items == 5) { - x = (float) SvNV(ST(2)); - y = (float) SvNV(ST(3)); - z = (float) SvNV(ST(4)); - } - if (items == 6) - heading = (float) SvNV(ST(5)); - - THIS->SetStartZone(zoneid, x, y, z, heading); - } - XSRETURN_EMPTY; +bool Perl_Client_KeyRingCheck(Client* self, uint32 item_id) // @categories Account and Character, Inventory and Items +{ + return self->KeyRingCheck(item_id); } -XS(XS_Client_KeyRingAdd); -XS(XS_Client_KeyRingAdd) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::KeyRingAdd(THIS, uint32 item_id)"); // @categories Account and Character, Inventory and Items - { - Client *THIS; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->KeyRingAdd(item_id);; - } - XSRETURN_EMPTY; +void Perl_Client_AddPVPPoints(Client* self, uint32 points) // @categories Currency and Points +{ + self->AddPVPPoints(points);; } -XS(XS_Client_KeyRingCheck); -XS(XS_Client_KeyRingCheck) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::KeyRingCheck(THIS, uint32 item_id)"); // @categories Account and Character, Inventory and Items - { - Client *THIS; - bool RETVAL; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->KeyRingCheck(item_id);; - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_AddCrystals(Client* self, uint32 radiant_count, uint32 ebon_count) // @categories Currency and Points +{ + self->AddCrystals(radiant_count, ebon_count); } -XS(XS_Client_AddPVPPoints); -XS(XS_Client_AddPVPPoints) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::AddPVPPoints(THIS, uint32 points)"); // @categories Currency and Points - { - Client *THIS; - uint32 Points = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->AddPVPPoints(Points); - } - XSRETURN_EMPTY; +void Perl_Client_SetEbonCrystals(Client* self, uint32 value) +{ + self->SetEbonCrystals(value); } -XS(XS_Client_AddCrystals); -XS(XS_Client_AddCrystals) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::AddCrystals(THIS, uint32 radiant_count, uint32 ebon_count)"); // @categories Currency and Points - { - Client *THIS; - uint32 Radiant = (uint32) SvUV(ST(1)); - uint32 Ebon = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->AddCrystals(Radiant, Ebon); - } - XSRETURN_EMPTY; +void Perl_Client_SetRadiantCrystals(Client* self, uint32 value) +{ + self->SetRadiantCrystals(value); } -XS(XS_Client_SetEbonCrystals); -XS(XS_Client_SetEbonCrystals) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetEbonCrystals(THIS, uint32 value)"); - { - Client *THIS; - uint32 value = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetEbonCrystals(value); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetPVPPoints(Client* self) // @categories Currency and Points +{ + return self->GetPVPPoints(); } -XS(XS_Client_SetRadiantCrystals); -XS(XS_Client_SetRadiantCrystals) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetRadiantCrystals(THIS, uint32 value)"); - { - Client *THIS; - uint32 value = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetRadiantCrystals(value); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetRadiantCrystals(Client* self) // @categories Currency and Points +{ + return self->GetRadiantCrystals(); } -XS(XS_Client_GetPVPPoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetPVPPoints) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetPVPPoints(THIS)"); // @categories Currency and Points - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetPVPPoints(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetEbonCrystals(Client* self) // @categories Currency and Points +{ + return self->GetEbonCrystals(); } -XS(XS_Client_GetRadiantCrystals); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetRadiantCrystals) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetRadiantCrystals(THIS)"); // @categories Currency and Points - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetRadiantCrystals(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_ReadBook(Client* self, const char* book_text, uint8 type) // @categories Script Utility +{ + self->QuestReadBook(book_text, type); } -XS(XS_Client_GetEbonCrystals); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetEbonCrystals) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetEbonCrystals(THIS)"); // @categories Currency and Points - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetEbonCrystals(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_SetGMStatus(Client* self, int16 new_status) // @categories Script Utility +{ + self->SetGMStatus(new_status); } -XS(XS_Client_ReadBook); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ReadBook) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::ReadBook(THIS, char* book_test, uint8 type)"); // @categories Script Utility - { - Client *THIS; - char *in_txt = (char *) SvPV_nolen(ST(1)); - uint8 type = (uint8) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->QuestReadBook(in_txt, type); - } - XSRETURN_EMPTY; +int16 Perl_Client_GetGMStatus(Client* self) // @categories Account and Character +{ + return self->Admin(); } -XS(XS_Client_SetGMStatus); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetGMStatus) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetGMStatus(THIS, int newStatus)"); // @categories Script Utility - { - Client *THIS; - int newStatus = (int)SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetGMStatus(newStatus); - THIS->UpdateAdmin(true); - } - XSRETURN_EMPTY; +void Perl_Client_UpdateGroupAAs(Client* self, int points, uint32 type) // @categories Alternative Advancement, Group +{ + self->UpdateGroupAAs(points, type); } -XS(XS_Client_UpdateGroupAAs); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UpdateGroupAAs) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::UpdateGroupAAs(THIS, int32 points, uint32 type)"); // @categories Alternative Advancement, Group - { - Client *THIS; - int32 points = (int32) SvIV(ST(1)); - uint32 type = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->UpdateGroupAAs(points, type); - } - XSRETURN(1); +uint32_t Perl_Client_GetGroupPoints(Client* self) // @categories Account and Character, Group +{ + return self->GetGroupPoints(); } -XS(XS_Client_GetGroupPoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetGroupPoints) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetGroupPoints(THIS)"); // @categories Account and Character, Group - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetGroupPoints(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetRaidPoints(Client* self) // @categories Account and Character, Raid +{ + return self->GetRaidPoints(); } -XS(XS_Client_GetRaidPoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetRaidPoints) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetRaidPoints(THIS)"); // @categories Account and Character, Raid - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetRaidPoints(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_LearnRecipe(Client* self, uint32 recipe_id) // @categories Skills and Recipes +{ + self->LearnRecipe(recipe_id); } -XS(XS_Client_LearnRecipe); -XS(XS_Client_LearnRecipe) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::LearnRecipe(THIS, uint32 recipe_id)"); // @categories Skills and Recipes - { - Client *THIS; - uint32 recipe_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->LearnRecipe(recipe_id);; - } - XSRETURN_EMPTY; +int64_t Perl_Client_GetEndurance(Client* self) // @categories Stats and Attributes +{ + return self->GetEndurance(); } -XS(XS_Client_GetEndurance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetEndurance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetEndurance(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetEndurance(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int64_t Perl_Client_GetMaxEndurance(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetMaxEndurance(); } -XS(XS_Client_GetMaxEndurance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetMaxEndurance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetMaxEndurance(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetMaxEndurance(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_Client_GetEnduranceRatio(Client* self) // @categories Stats and Attributes +{ + return self->GetEndurancePercent(); } -XS(XS_Client_GetEnduranceRatio); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetEnduranceRatio) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetEnduranceRatio(THIS)"); // @categories Stats and Attributes - { - Client *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetEndurancePercent(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_SetEndurance(Client* self, int endurance) // @categories Account and Character, Stats and Attributes +{ + self->SetEndurance(endurance); } -XS(XS_Client_SetEndurance); -XS(XS_Client_SetEndurance) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetEndurance(THIS, Endurance)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - int32 Endurance = (int32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetEndurance(Endurance); - } - XSRETURN_EMPTY; +void Perl_Client_SendOPTranslocateConfirm(Client* self, Mob* caster, uint16 spell_id) // @categories Script Utility +{ + self->SendOPTranslocateConfirm(caster, spell_id); } -XS(XS_Client_SendOPTranslocateConfirm); -XS(XS_Client_SendOPTranslocateConfirm) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SendOPTranslocateConfirm(THIS, Mob* caster, int32 spell_id)"); // @categories Script Utility - { - Client *THIS; - Mob *caster = nullptr; - int32 spell_id = (int32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "caster is not of type Mob"); - if (caster == nullptr) - Perl_croak(aTHX_ "caster is nullptr, avoiding crash."); - - THIS->SendOPTranslocateConfirm(caster, spell_id); - } - XSRETURN_EMPTY; +void Perl_Client_NPCSpawn(Client* self, NPC* target_npc, const char* option) // @categories Script Utility, Spawns +{ + return self->NPCSpawn(target_npc, option, 1200); } -XS(XS_Client_NPCSpawn); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_NPCSpawn) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Client::NPCSpawn(THIS, NPC*, string option, uint32 respawn_time=1200)"); // @categories Script Utility, Spawns - { - Client *THIS; - NPC *target_npc = nullptr; - Const_char *option = (Const_char *) SvPV_nolen(ST(2)); - uint32 respawntime = 1200; - VALIDATE_THIS_IS_CLIENT; - if (sv_derived_from(ST(1), "NPC")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target_npc = INT2PTR(NPC *, tmp); - } else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if (target_npc == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items > 3) - respawntime = (uint32) SvUV(ST(3)); - - THIS->NPCSpawn(target_npc, option, respawntime); - } - XSRETURN_EMPTY; +void Perl_Client_NPCSpawn(Client* self, NPC* target_npc, const char* option, uint32 respawn_time) // @categories Script Utility, Spawns +{ + return self->NPCSpawn(target_npc, option, respawn_time); } -XS(XS_Client_GetIP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetIP) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetIP(THIS)"); // @categories Script Utility - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetIP(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetIP(Client* self) // @categories Script Utility +{ + return self->GetIP(); } -XS(XS_Client_AddLevelBasedExp); -XS(XS_Client_AddLevelBasedExp) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Client::AddLevelBasedExp(THIS, uint8 exp_percentage, uint8 max_level = 0, bool ignore_mods = false)"); // @categories Experience and Level - { - Client *THIS; - uint8 exp_percentage = (uint8) SvUV(ST(1)); - uint8 max_level = 0; - bool ignore_mods = false; - VALIDATE_THIS_IS_CLIENT; - if (items > 2) - max_level = (uint8) SvUV(ST(2)); - - if (items > 3) - ignore_mods = (bool) SvTRUE(ST(3)); - - THIS->AddLevelBasedExp(exp_percentage, max_level, ignore_mods); - } - XSRETURN_EMPTY; +void Perl_Client_AddLevelBasedExp(Client* self, uint8 exp_percentage) // @categories Experience and Level +{ + self->AddLevelBasedExp(exp_percentage); } -XS(XS_Client_IncrementAA); -XS(XS_Client_IncrementAA) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::IncrementAA(THIS, uint32 aa_skill_id)"); // @categories Alternative Advancement - { - Client *THIS; - uint32 aaskillid = SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->IncrementAlternateAdvancementRank(aaskillid); - } - XSRETURN_EMPTY; +void Perl_Client_AddLevelBasedExp(Client* self, uint8 exp_percentage, uint8 max_level) // @categories Experience and Level +{ + self->AddLevelBasedExp(exp_percentage, max_level); } -XS(XS_Client_GrantAlternateAdvancementAbility); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GrantAlternateAdvancementAbility) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Client::GrantAlternateAdvancementAbility(THIS, int aa_id, int points, [bool ignore_cost = false])"); // @categories Alternative Advancement - { - Client *THIS; - bool RETVAL; - int aa_id = (int) SvIV(ST(1)); - int points = (int) SvIV(ST(2)); - bool ignore_cost = false; - VALIDATE_THIS_IS_CLIENT; - if (items > 3) { - ignore_cost = (bool) SvTRUE(ST(3)); - } - - RETVAL = THIS->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_AddLevelBasedExp(Client* self, uint8 exp_percentage, uint8 max_level, bool ignore_mods) // @categories Experience and Level +{ + self->AddLevelBasedExp(exp_percentage, max_level, ignore_mods); } -XS(XS_Client_GetAALevel); -XS(XS_Client_GetAALevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetAALevel(THIS, uint32 aa_skill_id)"); // @categories Alternative Advancement, Experience and Level - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - uint32 aaskillid = SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAA(aaskillid); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_IncrementAA(Client* self, uint32 aa_skill_id) // @categories Alternative Advancement +{ + self->IncrementAlternateAdvancementRank(aa_skill_id); } -XS(XS_Client_MarkCompassLoc); -XS(XS_Client_MarkCompassLoc) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Client::MarkCompassLoc(THIS, float x, float y, float z)"); // @categories Adventures and Expeditions - { - Client *THIS; - float x = SvNV(ST(1)); - float y = SvNV(ST(2)); - float z = SvNV(ST(3)); - VALIDATE_THIS_IS_CLIENT; - THIS->MarkSingleCompassLoc(x, y, z); - } - XSRETURN_EMPTY; +bool Perl_Client_GrantAlternateAdvancementAbility(Client* self, int aa_id, int points) // @categories Alternative Advancement +{ + return self->GrantAlternateAdvancementAbility(aa_id, points); } -XS(XS_Client_ClearCompassMark); -XS(XS_Client_ClearCompassMark) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::ClearCompassMark(THIS)"); // @categories Adventures and Expeditions - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->MarkSingleCompassLoc(0, 0, 0, 0); - } - XSRETURN_EMPTY; +bool Perl_Client_GrantAlternateAdvancementAbility(Client* self, int aa_id, int points, bool ignore_cost) // @categories Alternative Advancement +{ + return self->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); } -XS(XS_Client_GetFreeSpellBookSlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetFreeSpellBookSlot) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::GetFreeSpellBookSlot(THIS, uint32 start_slot = 0)"); // @categories Spells and Disciplines - { - Client *THIS; - int RETVAL; - uint32 start_slot = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items > 1) - start_slot = SvUV(ST(1)); - - RETVAL = THIS->GetNextAvailableSpellBookSlot(start_slot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_ResetAlternateAdvancementRank(Client* self, int aa_id) // @categories Alternative Advancement +{ + return self->ResetAlternateAdvancementRank(aa_id); } -XS(XS_Client_GetSpellBookSlotBySpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetSpellBookSlotBySpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetSpellBookSlotBySpellID(THIS, uint32 spell_id)"); // @categories Spells and Disciplines - { - Client *THIS; - int RETVAL; - uint32 spell_id = SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->FindSpellBookSlotBySpellID(spell_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetAALevel(Client* self, uint32 aa_skill_id) // @categories Alternative Advancement, Experience and Level +{ + return self->GetAA(aa_skill_id); } -XS(XS_Client_GetSpellIDByBookSlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetSpellIDByBookSlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetSpellIDByBookSlot(THIS, int slot_id)"); - { - Client* THIS; - int RETVAL; - int slot_id = SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetSpellIDByBookSlot(slot_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_MarkCompassLoc(Client* self, float x, float y, float z) // @categories Adventures and Expeditions +{ + self->MarkSingleCompassLoc(x, y, z); } -XS(XS_Client_UpdateTaskActivity); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UpdateTaskActivity) { - dXSARGS; - if (items < 4) - Perl_croak(aTHX_ "Usage: Client::UpdateTaskActivity(THIS, int task_id, int activity_id, int count, [bool ignore_quest_update = false])"); // @categories Tasks and Activities - { - bool ignore_quest_update = false; +void Perl_Client_ClearCompassMark(Client* self) // @categories Adventures and Expeditions +{ + self->MarkSingleCompassLoc(0, 0, 0, 0); +} - Client *THIS; +int Perl_Client_GetFreeSpellBookSlot(Client* self) // @categories Spells and Disciplines +{ + return self->GetNextAvailableSpellBookSlot(); +} - int TaskID = (int) SvIV(ST(1)); - int ActivityID = (int) SvIV(ST(2)); - int Count = (int) SvUV(ST(3)); +int Perl_Client_GetFreeSpellBookSlot(Client* self, uint32 start_slot) // @categories Spells and Disciplines +{ + return self->GetNextAvailableSpellBookSlot(start_slot); +} - if (items == 5) { - ignore_quest_update = (bool) SvTRUE(ST(4)); - } - VALIDATE_THIS_IS_CLIENT; - THIS->UpdateTaskActivity(TaskID, ActivityID, Count, ignore_quest_update); - } - XSRETURN_EMPTY; +int Perl_Client_GetSpellBookSlotBySpellID(Client* self, uint32 spell_id) // @categories Spells and Disciplines +{ + return self->FindSpellBookSlotBySpellID(spell_id); } -XS(XS_Client_GetTaskActivityDoneCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetTaskActivityDoneCount) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::GetTaskActivityDoneCount(THIS, int task_id, int activity_id)"); // @categories Tasks and Activities - { - Client *THIS; - int RETVAL; - int TaskID = (int) SvIV(ST(1)); - int ActivityID = (int) SvIV(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - - RETVAL = THIS->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Client_GetSpellIDByBookSlot(Client* self, int slot_id) +{ + return self->GetSpellIDByBookSlot(slot_id); } -XS(XS_Client_AssignTask); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AssignTask) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Client::AssignTask(THIS, int task_id, [int npc_id = 0, bool enforce_level_requirement = false])"); // @categories Tasks and Activities - { - Client *THIS; - int task_id = (int) SvIV(ST(1)); - int npc_id = 0; - bool enforce_level_requirement = false; - VALIDATE_THIS_IS_CLIENT; +void Perl_Client_UpdateTaskActivity(Client* self, int task_id, int activity_id, int count) // @categories Tasks and Activities +{ + self->UpdateTaskActivity(task_id, activity_id, count); +} - if (items > 2) { - npc_id = (int) SvIV(ST(2)); - } +void Perl_Client_UpdateTaskActivity(Client* self, int task_id, int activity_id, int count, bool ignore_quest_update) // @categories Tasks and Activities +{ + self->UpdateTaskActivity(task_id, activity_id, count, ignore_quest_update); +} - if (items > 3) { - enforce_level_requirement = SvTRUE(ST(3)); - } +int Perl_Client_GetTaskActivityDoneCount(Client* self, int task_id, int activity_id) // @categories Tasks and Activities +{ + return self->GetTaskActivityDoneCountFromTaskID(task_id, activity_id); +} - THIS->AssignTask(task_id, npc_id, enforce_level_requirement); - } - XSRETURN_EMPTY; +void Perl_Client_AssignTask(Client* self, int task_id) // @categories Tasks and Activities +{ + self->AssignTask(task_id); } -XS(XS_Client_FailTask); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_FailTask) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::FailTask(THIS, int task_id)"); // @categories Tasks and Activities - { - Client *THIS; - int TaskID = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->FailTask(TaskID); - } - XSRETURN_EMPTY; +void Perl_Client_AssignTask(Client* self, int task_id, int npc_id) // @categories Tasks and Activities +{ + self->AssignTask(task_id, npc_id); } -XS(XS_Client_IsTaskCompleted); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsTaskCompleted) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::IsTaskCompleted(THIS, int task_id)"); // @categories Tasks and Activities - { - Client *THIS; - int RETVAL; - int TaskID = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsTaskCompleted(TaskID); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_AssignTask(Client* self, int task_id, int npc_id, bool enforce_level_requirement) // @categories Tasks and Activities +{ + self->AssignTask(task_id, npc_id, enforce_level_requirement); } -XS(XS_Client_IsTaskActive); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsTaskActive) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::IsTaskActive(THIS, int task_id)"); // @categories Tasks and Activities - { - Client *THIS; - bool RETVAL; - int TaskID = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsTaskActive(TaskID); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_FailTask(Client* self, int task_id) // @categories Tasks and Activities +{ + self->FailTask(task_id); } -XS(XS_Client_IsTaskActivityActive); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_IsTaskActivityActive) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::IsTaskActivityActive(THIS, int task_id, int activity_id)"); // @categories Tasks and Activities - { - Client *THIS; - bool RETVAL; - int TaskID = (int) SvIV(ST(1)); - int ActivityID = (int) SvIV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->IsTaskActivityActive(TaskID, ActivityID); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Client_IsTaskCompleted(Client* self, int task_id) // @categories Tasks and Activities +{ + return self->IsTaskCompleted(task_id); } -XS(XS_Client_GetCorpseCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetCorpseCount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetCorpseCount(THIS)"); // @categories Account and Character, Corpse - { - Client *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetCorpseCount(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +bool Perl_Client_IsTaskActive(Client* self, int task_id) // @categories Tasks and Activities +{ + return self->IsTaskActive(task_id); } -XS(XS_Client_GetCorpseID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetCorpseID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetCorpseID(THIS, uint8 corpse)"); // @categories Account and Character, Corpse - { - Client *THIS; - uint8 corpse = (uint8) SvIV(ST(1)); - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetCorpseID(corpse); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +bool Perl_Client_IsTaskActivityActive(Client* self, int task_id, int activity_id) // @categories Tasks and Activities +{ + return self->IsTaskActivityActive(task_id, activity_id); } -XS(XS_Client_GetCorpseItemAt); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetCorpseItemAt) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::GetCorpseItemAt(THIS, uint32 corpse_id, uint16 slot_id)"); // @categories Inventory and Items, Corpse - { - Client *THIS; - uint32 corpse_id = (uint32) SvIV(ST(1)); - uint16 slotid = (uint16) SvIV(ST(2)); - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetCorpseItemAt(corpse_id, slotid); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_LockSharedTask(Client* self, bool lock) +{ + return self->LockSharedTask(lock); } -XS(XS_Client_AssignToInstance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AssignToInstance) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::AssignToInstance(THIS, uint16 instance_id)"); // @categories Adventures and Expeditions - { - Client *THIS; - uint16 instance_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->AssignToInstance(instance_id); - } - XSRETURN_EMPTY; +void Perl_Client_EndSharedTask(Client* self) +{ + return self->EndSharedTask(); } -XS(XS_Client_RemoveFromInstance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_RemoveFromInstance) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::RemoveFromInstance(THIS, uint16 instance_id)"); // @categories Adventures and Expeditions - { - Client *THIS; - uint16 instance_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->RemoveFromInstance(instance_id); - } - XSRETURN_EMPTY; +void Perl_Client_EndSharedTask(Client* self, bool send_fail) +{ + return self->EndSharedTask(send_fail); } -XS(XS_Client_Freeze); -XS(XS_Client_Freeze) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Freeze(THIS)"); - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->SendAppearancePacket(AT_Anim, ANIM_FREEZE); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetCorpseCount(Client* self) // @categories Account and Character, Corpse +{ + return self->GetCorpseCount(); } -XS(XS_Client_UnFreeze); -XS(XS_Client_UnFreeze) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::UnFreeze(THIS)"); - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->SendAppearancePacket(AT_Anim, ANIM_STAND); - } - XSRETURN_EMPTY; +uint32_t Perl_Client_GetCorpseID(Client* self, uint8 corpse) // @categories Account and Character, Corpse +{ + return self->GetCorpseID(corpse); } +uint32_t Perl_Client_GetCorpseItemAt(Client* self, uint32 corpse_id, uint16 slot_id) // @categories Inventory and Items, Corpse +{ + return self->GetCorpseItemAt(corpse_id, slot_id); +} -XS(XS_Client_GetAggroCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAggroCount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetAggroCount(THIS)"); // @categories Script Utility, Hate and Aggro - { - Client *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAggroCount(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_AssignToInstance(Client* self, uint16 instance_id) // @categories Adventures and Expeditions +{ + self->AssignToInstance(instance_id); } +void Perl_Client_RemoveFromInstance(Client* self, uint16 instance_id) // @categories Adventures and Expeditions +{ + self->RemoveFromInstance(instance_id); +} -XS(XS_Client_GetCarriedMoney); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetCarriedMoney) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetCarriedMoney(THIS)"); // @categories Currency and Points - { - Client *THIS; - uint64 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetCarriedMoney(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Client_Freeze(Client* self) +{ + self->SendAppearancePacket(AT_Anim, ANIM_FREEZE); } +void Perl_Client_UnFreeze(Client* self) +{ + self->SendAppearancePacket(AT_Anim, ANIM_STAND); +} -XS(XS_Client_GetAllMoney); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAllMoney) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetAllMoney(THIS)"); // @categories Currency and Points - { - Client *THIS; - uint64 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAllMoney(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_Client_GetAggroCount(Client* self) // @categories Script Utility, Hate and Aggro +{ + return self->GetAggroCount(); } +uint64_t Perl_Client_GetCarriedMoney(Client* self) // @categories Currency and Points +{ + return self->GetCarriedMoney(); +} -XS(XS_Client_GetItemInInventory); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetItemInInventory) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetItemInInventory(THIS, int16 slot_id)"); // @categories Inventory and Items - { - Client *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - EQ::ItemInstance *RETVAL = nullptr; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetInv().GetItem(slot_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "QuestItem", (void *) RETVAL); - } - XSRETURN(1); +uint64_t Perl_Client_GetAllMoney(Client* self) // @categories Currency and Points +{ + return self->GetAllMoney(); } -XS(XS_Client_SetCustomItemData); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetCustomItemData) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Client::SetCustomItemData(THIS, int16 slot_id, string identifier, string value)"); // @categories Inventory and Items - { - Client *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - Const_char *identifier = SvPV_nolen(ST(2)); - Const_char *value = SvPV_nolen(ST(3)); - VALIDATE_THIS_IS_CLIENT; - THIS->GetInv().SetCustomItemData(THIS->CharacterID(), slot_id, std::string(identifier), std::string(value)); - } - XSRETURN_EMPTY; +EQ::ItemInstance* Perl_Client_GetItemInInventory(Client* self, int16 slot_id) // @categories Inventory and Items +{ + return self->GetInv().GetItem(slot_id); } -XS(XS_Client_GetCustomItemData); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetCustomItemData) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::GetCustomItemData(THIS, int16 slot_id, string identifier)"); // @categories Inventory and Items, Corpse - { - Client *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - Const_char *identifier = SvPV_nolen(ST(2)); - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - std::string ret_val = THIS->GetInv().GetCustomItemData(slot_id, std::string(identifier)); - RETVAL = ret_val.c_str(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +void Perl_Client_SetCustomItemData(Client* self, int16 slot_id, std::string identifier, std::string value) // @categories Inventory and Items +{ + self->GetInv().SetCustomItemData(self->CharacterID(), slot_id, identifier, value); } -XS(XS_Client_OpenLFGuildWindow); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_OpenLFGuildWindow) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::OpenLFGuildWindow(THIS)"); // @categories Script Utility, Guild - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->OpenLFGuildWindow(); - } - XSRETURN_EMPTY; +std::string Perl_Client_GetCustomItemData(Client* self, int16 slot_id, std::string identifier) // @categories Inventory and Items, Corpse +{ + return self->GetInv().GetCustomItemData(slot_id, identifier); } -XS(XS_Client_NotifyNewTitlesAvailable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_NotifyNewTitlesAvailable) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::NotifyNewTitlesAvailable(THIS)"); // @categories Account and Character - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->NotifyNewTitlesAvailable(); - } - XSRETURN_EMPTY; +void Perl_Client_OpenLFGuildWindow(Client* self) // @categories Script Utility, Guild +{ + self->OpenLFGuildWindow(); } -XS(XS_Client_AddAlternateCurrencyValue); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AddAlternateCurrencyValue) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::AddAlternateCurrencyValue(THIS, uint32 currency_id, int32 amount)"); // @categories Currency and Points - { - Client *THIS; - uint32 currency_id = (uint32) SvUV(ST(1)); - int32 amount = (int32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->AddAlternateCurrencyValue(currency_id, amount); - } - XSRETURN_EMPTY; +void Perl_Client_NotifyNewTitlesAvailable(Client* self) // @categories Account and Character +{ + self->NotifyNewTitlesAvailable(); } -XS(XS_Client_SetAlternateCurrencyValue); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetAlternateCurrencyValue) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetAlternateCurrencyValue(THIS, uint32 currency_id, int32 amount)"); // @categories Currency and Points - { - Client *THIS; - uint32 currency_id = (uint32) SvUV(ST(1)); - int32 amount = (int32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetAlternateCurrencyValue(currency_id, amount); - } - XSRETURN_EMPTY; +void Perl_Client_AddAlternateCurrencyValue(Client* self, uint32 currency_id, int32 amount) // @categories Currency and Points +{ + self->AddAlternateCurrencyValue(currency_id, amount); } -XS(XS_Client_GetAlternateCurrencyValue); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAlternateCurrencyValue) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetAlternateCurrencyValue(THIS, uint32 currency_id)"); // @categories Currency and Points - { - Client *THIS; - uint32 currency_id = (uint32) SvUV(ST(1)); - int32 RETVAL = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAlternateCurrencyValue(currency_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_SetAlternateCurrencyValue(Client* self, uint32 currency_id, int32 amount) // @categories Currency and Points +{ + self->SetAlternateCurrencyValue(currency_id, amount); } -XS(XS_Client_SendWebLink); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendWebLink) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::SendWebLink(THIS, string website_url)"); // @categories Script Utility - { - Client *THIS; - char *website = nullptr; - VALIDATE_THIS_IS_CLIENT; - if (items > 1) { website = (char *) SvPV_nolen(ST(1)); } +uint32 Perl_Client_GetAlternateCurrencyValue(Client* self, uint32_t currency_id) // @categories Currency and Points +{ + return self->GetAlternateCurrencyValue(currency_id); +} - THIS->SendWebLink(website); - } - XSRETURN_EMPTY; +void Perl_Client_SendWebLink(Client* self, const char* url) // @categories Script Utility +{ + self->SendWebLink(url); } -XS(XS_Client_GetInstanceID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetInstanceID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetInstanceID(THIS)"); // @categories Adventures and Expeditions - { - Client *THIS; - int8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetInstanceID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_Client_GetInstanceID(Client* self) // @categories Adventures and Expeditions +{ + return self->GetInstanceID(); } -XS(XS_Client_HasSpellScribed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_HasSpellScribed) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::HasSpellScribed(THIS, int spell_id)"); // @categories Spells and Disciplines - { - Client *THIS; - bool RETVAL; - int spell_id = (int) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->HasSpellScribed(spell_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Client_HasSpellScribed(Client* self, int spell_id) // @categories Spells and Disciplines +{ + return self->HasSpellScribed(spell_id); } -XS(XS_Client_SetAccountFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetAccountFlag) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetAccountFlag(THIS, string flag, string value)"); // @categories Account and Character - { - Client *THIS; - //char* flag = (char *)SvPV_nolen(ST(1)); - //char* value = (char *)SvTRUE(ST(2)); - - std::string flag((char *) SvPV_nolen(ST(1))); - std::string value((char *) SvTRUE(ST(2))); - VALIDATE_THIS_IS_CLIENT; - THIS->SetAccountFlag(flag, value); - } - XSRETURN_EMPTY; +void Perl_Client_SetAccountFlag(Client* self, std::string flag, std::string value) // @categories Account and Character +{ + self->SetAccountFlag(flag, value); } -XS(XS_Client_GetAccountFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetAccountFlag) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetAccountFlag(THIS, string flag)"); // @categories Account and Character - { - Client *THIS; - //char* flag = (char *)SvPV_nolen(ST(1)); - //char* value = (char *)SvTRUE(ST(2)); - - std::string flag((char *) SvPV_nolen(ST(1))); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - std::string value = THIS->GetAccountFlag(flag); - - sv_setpv(TARG, value.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +std::string Perl_Client_GetAccountFlag(Client* self, std::string flag) // @categories Account and Character +{ + return self->GetAccountFlag(flag); } -XS(XS_Client_GetHunger); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetHunger) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetHunger(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetHunger(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +int Perl_Client_GetHunger(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetHunger(); } -XS(XS_Client_GetThirst); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetThirst) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetThirst(THIS)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetThirst(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +int Perl_Client_GetThirst(Client* self) // @categories Account and Character, Stats and Attributes +{ + return self->GetThirst(); } -XS(XS_Client_SetHunger); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetHunger) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetHunger(THIS, in_hunger)"); // @categories Script Utility, Stats and Attributes - { - Client *THIS; - int32 in_hunger = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetHunger(in_hunger); - } - XSRETURN_EMPTY; +void Perl_Client_SetHunger(Client* self, int in_hunger) // @categories Script Utility, Stats and Attributes +{ + self->SetHunger(in_hunger); } -XS(XS_Client_SetThirst); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetThirst) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetThirst(THIS, int32 in_thirst)"); // @categories Account and Character, Stats and Attributes - { - Client *THIS; - int32 in_thirst = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetThirst(in_thirst); - } - XSRETURN_EMPTY; +void Perl_Client_SetThirst(Client* self, int in_thirst) // @categories Account and Character, Stats and Attributes +{ + self->SetThirst(in_thirst); } -XS(XS_Client_SendTargetCommand); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendTargetCommand) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SendTargetCommand(THIS, int32 entity_id)"); // @categories Script Utility - { - Client *THIS; - int32 in_entid = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SendTargetCommand(in_entid); - } - XSRETURN_EMPTY; +void Perl_Client_SendTargetCommand(Client* self, uint32 entity_id) // @categories Script Utility +{ + self->SendTargetCommand(entity_id); } -XS(XS_Client_SetConsumption); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetConsumption) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetHunger(THIS, int32 hunger_amount, int32 thirst_amount)"); // @categories Script Utility, Stats and Attributes - { - Client *THIS; - int32 in_hunger = (uint32) SvUV(ST(1)); - int32 in_thirst = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetConsumption(in_hunger, in_thirst); - } - XSRETURN_EMPTY; +void Perl_Client_SetConsumption(Client* self, int hunger_amount, int thirst_amount) // @categories Script Utility, Stats and Attributes +{ + self->SetConsumption(hunger_amount, thirst_amount); } -XS(XS_Client_SilentMessage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SilentMessage) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SilentMessage(THIS, string message)"); // @categories Script Utility - { - Client *THIS; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (THIS->GetTarget() != NULL) { - if (THIS->GetTarget()->IsNPC()) { - if (DistanceSquaredNoZ(THIS->GetPosition(), THIS->GetTarget()->GetPosition()) <= 200) { - if (THIS->GetTarget()->CastToNPC()->IsMoving() && - !THIS->GetTarget()->CastToNPC()->IsOnHatelist(THIS->GetTarget())) - THIS->GetTarget()->CastToNPC()->PauseWandering(RuleI(NPC, SayPauseTimeInSec)); - THIS->ChannelMessageReceived(8, 0, 100, SvPV_nolen(ST(1))); - } +void Perl_Client_SilentMessage(Client* self, const char* message) // @categories Script Utility +{ + if (self->GetTarget() != NULL) { + if (self->GetTarget()->IsNPC()) { + if (DistanceSquaredNoZ(self->GetPosition(), self->GetTarget()->GetPosition()) <= 200) { + if (self->GetTarget()->CastToNPC()->IsMoving() && + !self->GetTarget()->CastToNPC()->IsOnHatelist(self->GetTarget())) + self->GetTarget()->CastToNPC()->PauseWandering(RuleI(NPC, SayPauseTimeInSec)); + self->ChannelMessageReceived(8, 0, 100, message, nullptr, true); } } } - XSRETURN_EMPTY; } -XS(XS_Client_PlayMP3); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_PlayMP3) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Client::PlayMP3(THIS, string file)"); // @categories Script Utility - { - Client *THIS; - char *fname = nullptr; - VALIDATE_THIS_IS_CLIENT; - if (items > 1) { fname = (char *) SvPV_nolen(ST(1)); } - - THIS->PlayMP3(fname); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_ExpeditionMessage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ExpeditionMessage) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::ExpeditionMessage(THIS, int expedition_id, string message)"); // @categories Adventures and Expeditions - { - Client *THIS; - int ExpdID = (int) SvUV(ST(1)); - const char *Message = (const char *) SvPV_nolen(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - THIS->ExpeditionSay(Message, ExpdID); - } - XSRETURN_EMPTY; -} - -//Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg) - -XS(XS_Client_SendMarqueeMessage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendMarqueeMessage) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: Client::SendMarqueeMessage(THIS, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, string msg)"); // @categories Script Utility - { - Client *THIS; - uint32 type = (uint32) SvUV(ST(1)); - uint32 priority = (uint32) SvUV(ST(2)); - uint32 fade_in = (uint32) SvUV(ST(3)); - uint32 fade_out = (uint32) SvUV(ST(4)); - uint32 duration = (uint32) SvUV(ST(5)); - std::string msg = (std::string) SvPV_nolen(ST(6)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - THIS->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, msg); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SendColoredText); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendColoredText) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SendColoredText(uint32 color, string message)"); // @categories Script Utility - { - Client *THIS; - uint32 color = (uint32) SvUV(ST(1)); - std::string msg = (std::string) SvPV_nolen(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - THIS->SendColoredText(color, msg); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SendSpellAnim); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendSpellAnim) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: SendSpellAnim(uint16 target_id, uint32 spell_animation_id)"); - { - Client *THIS; - uint16 targetid = (uint16) SvUV(ST(1)); - uint16 spell_id = (uint16) SvUV(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - THIS->SendSpellAnim(targetid, spell_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetTargetRingX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetTargetRingX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetTargetRingX(THIS)"); // @categories Script Utility - { - Client *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetTargetRingX(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetTargetRingY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetTargetRingY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetTargetRingY(THIS)"); // @categories Script Utility - { - Client *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetTargetRingY(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetTargetRingZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetTargetRingZ) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetTargetRingZ(THIS)"); // @categories Script Utility - { - Client *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetTargetRingZ(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_CalcEXP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_CalcEXP) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: CalcEXP(THIS, uint8 conlevel)"); - { - Client *THIS; - uint8 conlevel = 0xFF; - uint32 RETVAL; - if (items == 2) - conlevel = (uint16) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->CalcEXP(conlevel); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_QuestReward); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_QuestReward) { - dXSARGS; - if (items < 1 || items > 9) - Perl_croak(aTHX_ "Usage: Client::QuestReward(THIS, int32 mob, int32 copper, int32 silver, int32 gold, int32 platinum, int32 item_id, int32 exp, [bool faction = false])"); // @categories Currency and Points, Experience and Level, Inventory and Items, Faction - { - Client *THIS; - Mob *mob = nullptr; - int32 copper = 0; - int32 silver = 0; - int32 gold = 0; - int32 platinum = 0; - int32 itemid = 0; - int32 exp = 0; - bool faction = false; - - if (sv_derived_from(ST(0), "THIS")) { - IV tmp = SvIV((SV *) SvRV(ST(0))); - THIS = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "THIS is not of type client"); - if (THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items > 1) { - if (sv_derived_from(ST(1), "mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - mob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "mob is not of type Mob"); - if (mob == nullptr) - Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); - } - if (items > 2) { copper = (int32) SvIV(ST(2)); } - if (items > 3) { silver = (int32) SvIV(ST(3)); } - if (items > 4) { gold = (int32) SvIV(ST(4)); } - if (items > 5) { platinum = (int32) SvIV(ST(5)); } - if (items > 6) { itemid = (int32) SvIV(ST(6)); } - if (items > 7) { exp = (int32) SvIV(ST(7)); } - if (items > 8) { faction = (bool) SvIV(ST(8)); } - - THIS->QuestReward(mob, copper, silver, gold, platinum, itemid, exp, faction); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetMoney); -XS(XS_Client_GetMoney) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: GetMoney(THIS, int8 type, int8 subtype)"); - { - Client *THIS; - uint32 RETVAL; - uint8 type = (uint8) SvUV(ST(1)); - uint8 subtype = (uint8) SvUV(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetMoney(type, subtype); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_GetAccountAge); -XS(XS_Client_GetAccountAge) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: GetAccountAge(THIS)"); - { - Client *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetAccountAge(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Client_Popup2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Popup2) { - dXSARGS; - if (items < 3 || items > 10) - Perl_croak(aTHX_ "Usage: Client::Popup2(THIS, string title, string text, uint32 popup_id, uint32 negative_id, uint32 buttons, uint32 duration, string button_name_0, string button_name_1, uint32 sound_controls)"); // @categories Script Utility - { - Client *THIS; - char *Title = (char *) SvPV_nolen(ST(1)); - char *Text = (char *) SvPV_nolen(ST(2)); - uint32 PopupID = 0; - uint32 NegativeID = 0; - uint32 Buttons = 0; - uint32 Duration = 0; - char *ButtonName0 = 0; - char *ButtonName1 = 0; - uint32 SoundControls = 0; - VALIDATE_THIS_IS_CLIENT; - if (items > 3) { PopupID = (uint32) SvUV(ST(3)); } - if (items > 4) { NegativeID = (uint32) SvUV(ST(4)); } - if (items > 5) { Buttons = (uint32) SvUV(ST(5)); } - if (items > 6) { Duration = (uint32) SvUV(ST(6)); } - if (items > 7) { ButtonName0 = (char *) SvPV_nolen(ST(7)); } - if (items > 8) { ButtonName1 = (char *) SvPV_nolen(ST(8)); } - if (items > 9) { SoundControls = (uint32) SvUV(ST(9)); } - - - THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Buttons, Duration, ButtonName0, ButtonName1, - SoundControls); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SetPrimaryWeaponOrnamentation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetPrimaryWeaponOrnamentation) +void Perl_Client_PlayMP3(Client* self, const char* file) // @categories Script Utility { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Client::SetPrimaryWeaponOrnamentation(THIS, model_id)"); // @categories Account and Character, Inventory and Items - } - { - Client *THIS; - uint32 model_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetPrimaryWeaponOrnamentation(model_id); - } - XSRETURN_EMPTY; + self->PlayMP3(file); } -XS(XS_Client_SetSecondaryWeaponOrnamentation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetSecondaryWeaponOrnamentation) +// todo: this is some legacy api for 'cust_inst_players' and can possibly be removed (not related to current expeditions) +void Perl_Client_ExpeditionMessage(Client* self, int expedition_id, const char* message) // @categories Adventures and Expeditions { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Client::SetSecondaryWeaponOrnamentation(THIS, model_id)"); // @categories Account and Character, Inventory and Items - } - { - Client *THIS; - uint32 model_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetSecondaryWeaponOrnamentation(model_id); - } - XSRETURN_EMPTY; + self->ExpeditionSay(message, expedition_id); } -XS(XS_Client_SetClientMaxLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetClientMaxLevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetClientMaxLevel(THIS, int in_level)"); - { - Client* THIS; - int in_level = (int)SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetClientMaxLevel(in_level); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_GetClientMaxLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetClientMaxLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetClientMaxLevel(THIS)"); - { - Client* THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetClientMaxLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -DynamicZoneLocation GetDynamicZoneLocationFromHash(HV* hash) +void Perl_Client_SendColoredText(Client* self, uint32 color, std::string msg) // @categories Script Utility { - // dynamic zone helper method (caller must validate hash) - SV** zone_ptr = hv_fetchs(hash, "zone", false); - SV** x_ptr = hv_fetchs(hash, "x", false); - SV** y_ptr = hv_fetchs(hash, "y", false); - SV** z_ptr = hv_fetchs(hash, "z", false); - SV** h_ptr = hv_fetchs(hash, "h", false); + self->SendColoredText(color, std::move(msg)); +} - uint32_t zone_id = 0; - if (zone_ptr && SvIOK(*zone_ptr)) - { - zone_id = static_cast(SvIV(*zone_ptr)); - } - else if (zone_ptr && SvPOK(*zone_ptr)) - { - zone_id = ZoneID(SvPV_nolen(*zone_ptr)); - } +void Perl_Client_SendSpellAnim(Client* self, uint16 targetid, uint16 spell_id) +{ + self->SendSpellAnim(targetid, spell_id); +} - // SvNIOK checks for number, integer or double - float x = (x_ptr && SvNIOK(*x_ptr)) ? static_cast(SvNV(*x_ptr)) : 0.0f; - float y = (y_ptr && SvNIOK(*y_ptr)) ? static_cast(SvNV(*y_ptr)) : 0.0f; - float z = (z_ptr && SvNIOK(*z_ptr)) ? static_cast(SvNV(*z_ptr)) : 0.0f; - float h = (h_ptr && SvNIOK(*h_ptr)) ? static_cast(SvNV(*h_ptr)) : 0.0f; +float Perl_Client_GetTargetRingX(Client* self) // @categories Script Utility +{ + return self->GetTargetRingX(); +} + +float Perl_Client_GetTargetRingY(Client* self) // @categories Script Utility +{ + return self->GetTargetRingY(); +} + +float Perl_Client_GetTargetRingZ(Client* self) // @categories Script Utility +{ + return self->GetTargetRingZ(); +} + +uint64_t Perl_Client_CalcEXP(Client* self, uint8 consider_level) +{ + return self->CalcEXP(consider_level); +} + +uint64_t Perl_Client_CalcEXP(Client* self, uint8 consider_level, bool ignore_modifiers) +{ + return self->CalcEXP(consider_level, ignore_modifiers); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob, uint32 copper) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob, copper); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob, uint32 copper, uint32 silver) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob, copper, silver); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob, uint32 copper, uint32 silver, uint32 gold) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob, copper, silver, gold); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob, uint32 copper, uint32 silver, uint32 gold, uint32 platinum) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob, copper, silver, gold, platinum); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 item_id) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob, copper, silver, gold, platinum, item_id); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 item_id, uint32 exp) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob, copper, silver, gold, platinum, item_id, exp); +} + +void Perl_Client_QuestReward(Client* self, Mob* mob, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 item_id, uint32 exp, bool faction) // @categories Currency and Points, Experience and Level, Inventory and Items, Faction +{ + self->QuestReward(mob, copper, silver, gold, platinum, item_id, exp, faction); +} + +void Perl_Client_CashReward(Client* self, uint32 copper, uint32 silver, uint32 gold, uint32 platinum) +{ + self->CashReward(copper, silver, gold, platinum); +} + +uint32_t Perl_Client_GetMoney(Client* self, int8 type, int8 subtype) +{ + return self->GetMoney(type, subtype); +} + +int Perl_Client_GetAccountAge(Client* self) +{ + return self->GetAccountAge(); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text) // @categories Script Utility +{ + self->SendFullPopup(title, text); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text, uint32 popup_id) // @categories Script Utility +{ + self->SendFullPopup(title, text, popup_id); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text, uint32 popup_id, uint32 negative_id) // @categories Script Utility +{ + self->SendFullPopup(title, text, popup_id, negative_id); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 buttons) // @categories Script Utility +{ + self->SendFullPopup(title, text, popup_id, negative_id, buttons); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 buttons, uint32 duration) // @categories Script Utility +{ + self->SendFullPopup(title, text, popup_id, negative_id, buttons, duration); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 buttons, uint32 duration, const char* button_name_0) // @categories Script Utility +{ + self->SendFullPopup(title, text, popup_id, negative_id, buttons, duration, button_name_0); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 buttons, uint32 duration, const char* button_name_0, const char* button_name_1) // @categories Script Utility +{ + self->SendFullPopup(title, text, popup_id, negative_id, buttons, duration, button_name_0, button_name_1); +} + +void Perl_Client_Popup2(Client* self, const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 buttons, uint32 duration, const char* button_name_0, const char* button_name_1, uint32 sound_controls) // @categories Script Utility +{ + self->SendFullPopup(title, text, popup_id, negative_id, buttons, duration, button_name_0, button_name_1, sound_controls); +} + +void Perl_Client_SetPrimaryWeaponOrnamentation(Client* self, int model_id) // @categories Account and Character, Inventory and Items +{ + self->SetPrimaryWeaponOrnamentation(model_id); +} + +void Perl_Client_SetSecondaryWeaponOrnamentation(Client* self, int model_id) // @categories Account and Character, Inventory and Items +{ + self->SetSecondaryWeaponOrnamentation(model_id); +} + +void Perl_Client_SetClientMaxLevel(Client* self, uint8 max_level) +{ + self->SetClientMaxLevel(max_level); +} + +int Perl_Client_GetClientMaxLevel(Client* self) +{ + return self->GetClientMaxLevel(); +} + +DynamicZoneLocation GetDynamicZoneLocationFromHash(perl::hash table) +{ + // dynamic zone helper method, defaults invalid/missing keys to 0 + perl::scalar zone = table["zone"]; + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); + + float x = table.exists("x") ? table["x"] : 0.0f; + float y = table.exists("y") ? table["y"] : 0.0f; + float z = table.exists("z") ? table["z"] : 0.0f; + float h = table.exists("h") ? table["h"] : 0.0f; return { zone_id, x, y, z, h }; } -Expedition* CreateExpeditionFromHash(Client* client, SV* hash_ref) +Expedition* Perl_Client_CreateExpedition(Client* self, perl::reference table_ref) { - if (!hash_ref || !SvROK(hash_ref)) // verify valid reference type + perl::hash table = table_ref; + perl::hash expedition = table["expedition"]; + perl::hash instance = table["instance"]; + + perl::scalar zone = instance["zone"]; + uint32_t version = instance["version"]; + uint32_t duration = instance["duration"]; + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); + + DynamicZone dz{ zone_id, version, duration, DynamicZoneType::Expedition }; + dz.SetName(expedition["name"]); + dz.SetMinPlayers(expedition["min_players"]); + dz.SetMaxPlayers(expedition["max_players"]); + + if (table.exists("compass")) { - Perl_croak(aTHX_ "Client::CreateExpedition argument is not a reference type"); + auto compass = GetDynamicZoneLocationFromHash(table["compass"]); + dz.SetCompass(compass); } - HV* hash = (HV*)SvRV(hash_ref); // dereference and verify type is hash - if (SvTYPE(hash) != SVt_PVHV) + if (table.exists("safereturn")) { - Perl_croak(aTHX_ "Client::CreateExpedition reference argument is not to a hash type"); + auto safereturn = GetDynamicZoneLocationFromHash(table["safereturn"]); + dz.SetSafeReturn(safereturn); } - SV** expedition_info_ptr = hv_fetchs(hash, "expedition", false); - if (!expedition_info_ptr) + if (table.exists("zonein")) { - Perl_croak(aTHX_ "Client::CreateExpedition required 'expedition' key missing from hash"); + auto zonein = GetDynamicZoneLocationFromHash(table["zonein"]); + dz.SetZoneInLocation(zonein); } - if (!SvROK(*expedition_info_ptr) || SvTYPE(SvRV(*expedition_info_ptr)) != SVt_PVHV) + if (table.exists("switchid")) { - Perl_croak(aTHX_ "Client::CreateExpedition 'expedition' entry must have a hash table value"); + dz.SetSwitchID(table["switchid"].as()); } - SV** instance_info_ptr = hv_fetchs(hash, "instance", false); - if (!instance_info_ptr) + if (expedition.exists("disable_messages")) { - Perl_croak(aTHX_ "Client::CreateExpedition required 'instance' key missing from hash"); + return self->CreateExpedition(dz, expedition["disable_messages"].as()); } - if (!SvROK(*instance_info_ptr) || SvTYPE(SvRV(*instance_info_ptr)) != SVt_PVHV) - { - Perl_croak(aTHX_ "Client::CreateExpedition 'instance' entry must have a hash table value"); - } - - // dereference the nested hash tables and validate required keys - HV* expedition_hash = (HV*)SvRV(*expedition_info_ptr); - SV** name_ptr = hv_fetchs(expedition_hash, "name", false); - SV** min_players_ptr = hv_fetchs(expedition_hash, "min_players", false); - SV** max_players_ptr = hv_fetchs(expedition_hash, "max_players", false); - SV** disable_msg_ptr = hv_fetchs(expedition_hash, "disable_messages", false); - if (!name_ptr || !min_players_ptr || !max_players_ptr) - { - Perl_croak(aTHX_ "Client::CreateExpedition 'expedition' hash table missing required keys (name, min_players, max_players)"); - } - - HV* instance_hash = (HV*)SvRV(*instance_info_ptr); - SV** instance_zone_ptr = hv_fetchs(instance_hash, "zone", false); - SV** version_ptr = hv_fetchs(instance_hash, "version", false); - SV** duration_ptr = hv_fetchs(instance_hash, "duration", false); - if (!instance_zone_ptr || !version_ptr || !duration_ptr) - { - Perl_croak(aTHX_ "Client::CreateExpedition 'instance' hash table missing required keys (zone, version, duration)"); - } - - uint32_t zone_id = 0; - if (SvIOK(*instance_zone_ptr)) - { - zone_id = static_cast(SvIV(*instance_zone_ptr)); - } - else if (SvPOK(*instance_zone_ptr)) - { - zone_id = ZoneID(SvPV_nolen(*instance_zone_ptr)); - } - else - { - Perl_croak(aTHX_ "Client::CreateExpedition zone value in 'instance' table must be int or string"); - } - - uint32_t zone_version = SvIOK(*version_ptr) ? static_cast(SvIV(*version_ptr)) : 0; - uint32_t zone_duration = SvIOK(*duration_ptr) ? static_cast(SvIV(*duration_ptr)) : 0; - - DynamicZone dz{ zone_id, zone_version, zone_duration, DynamicZoneType::Expedition }; - dz.SetName(SvPOK(*name_ptr) ? SvPV_nolen(*name_ptr) : ""); - dz.SetMinPlayers(SvIOK(*min_players_ptr) ? static_cast(SvIV(*min_players_ptr)) : 0); - dz.SetMaxPlayers(SvIOK(*max_players_ptr) ? static_cast(SvIV(*max_players_ptr)) : 0); - - SV** compass_ptr = hv_fetchs(hash, "compass", false); - if (compass_ptr && SvROK(*compass_ptr) && SvTYPE(SvRV(*compass_ptr)) == SVt_PVHV) - { - auto compass_loc = GetDynamicZoneLocationFromHash((HV*)SvRV(*compass_ptr)); - dz.SetCompass(compass_loc); - } - - SV** safereturn_ptr = hv_fetchs(hash, "safereturn", false); - if (safereturn_ptr && SvROK(*safereturn_ptr) && SvTYPE(SvRV(*safereturn_ptr)) == SVt_PVHV) - { - auto safereturn_loc = GetDynamicZoneLocationFromHash((HV*)SvRV(*safereturn_ptr)); - dz.SetSafeReturn(safereturn_loc); - } - - SV** zonein_ptr = hv_fetchs(hash, "zonein", false); - if (zonein_ptr && SvROK(*zonein_ptr) && SvTYPE(SvRV(*zonein_ptr)) == SVt_PVHV) - { - auto zonein_loc = GetDynamicZoneLocationFromHash((HV*)SvRV(*zonein_ptr)); - dz.SetZoneInLocation(zonein_loc); - } - - bool disable_messages = (disable_msg_ptr && SvIOK(*disable_msg_ptr)) ? SvTRUE(*disable_msg_ptr) : false; - - return client->CreateExpedition(dz, disable_messages); + return self->CreateExpedition(dz); } -XS(XS_Client_CreateExpedition); -XS(XS_Client_CreateExpedition) { - dXSARGS; - if (items != 2 && items != 7 && items != 8) { - Perl_croak(aTHX_ "Usage: Client::CreateExpedition(THIS, HASHREF expedition_info | string zone_name, uint32 zone_version, uint32 duration, string expedition_name, uint32 min_players, uint32 max_players, [bool disable_messages = false])"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - Expedition* RETVAL = nullptr; - if (items == 2) - { - RETVAL = CreateExpeditionFromHash(THIS, ST(1)); - } - else - { - std::string zone_name(SvPV_nolen(ST(1))); - uint32 zone_version = (uint32)SvUV(ST(2)); - uint32 duration = (uint32)SvUV(ST(3)); - std::string expedition_name(SvPV_nolen(ST(4))); - uint32 min_players = (uint32)SvUV(ST(5)); - uint32 max_players = (uint32)SvUV(ST(6)); - bool disable_messages = (items > 7) ? (bool)SvTRUE(ST(7)) : false; - - RETVAL = THIS->CreateExpedition(zone_name, zone_version, duration, - expedition_name, min_players, max_players, disable_messages); - } - - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); - - XSRETURN(1); +Expedition* Perl_Client_CreateExpedition(Client* self, std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players) +{ + return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players); } -XS(XS_Client_CreateTaskDynamicZone); -XS(XS_Client_CreateTaskDynamicZone) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Client::CreateTaskDynamicZone(THIS, int task_id, HASHREF dz_info)"); - } +Expedition* Perl_Client_CreateExpedition(Client* self, std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages) +{ + return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players, disable_messages); +} - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; +Expedition* Perl_Client_CreateExpeditionFromTemplate(Client* self, uint32_t dz_template_id) +{ + return self->CreateExpeditionFromTemplate(dz_template_id); +} - SV* hash_ref = ST(2); - if (!hash_ref || !SvROK(hash_ref)) - { - Perl_croak(aTHX_ "Client::CreateTaskDynamicZone argument is not a reference type"); - } +void Perl_Client_CreateTaskDynamicZone(Client* self, int task_id, perl::reference table_ref) +{ + perl::hash table = table_ref; + perl::hash instance = table["instance"]; - HV* hash = (HV*)SvRV(hash_ref); // dereference into hash - if (SvTYPE(hash) != SVt_PVHV) - { - Perl_croak(aTHX_ "Client::CreateTaskDynamicZone reference argument is not to a hash type"); - } - - SV** instance_info_ptr = hv_fetchs(hash, "instance", false); - if (!instance_info_ptr) - { - Perl_croak(aTHX_ "Client::CreateTaskDynamicZone required 'instance' key missing from hash"); - } - - if (!SvROK(*instance_info_ptr) || SvTYPE(SvRV(*instance_info_ptr)) != SVt_PVHV) - { - Perl_croak(aTHX_ "Client::CreateTaskDynamicZone 'instance' entry must have a hash table value"); - } - - HV* instance_hash = (HV*)SvRV(*instance_info_ptr); - SV** instance_zone_ptr = hv_fetchs(instance_hash, "zone", false); - SV** version_ptr = hv_fetchs(instance_hash, "version", false); - SV** duration_ptr = hv_fetchs(instance_hash, "duration", false); - if (!instance_zone_ptr || !version_ptr) - { - Perl_croak(aTHX_ "Client::CreateTaskDynamicZone 'instance' hash table missing required keys (zone, version, duration)"); - } - - uint32_t zone_id = 0; - SV* instance_zone = *instance_zone_ptr; - if (SvIOK(instance_zone)) - { - zone_id = static_cast(SvIV(instance_zone)); - } - else if (SvPOK(instance_zone)) - { - zone_id = ZoneID(SvPV_nolen(instance_zone)); - } - else - { - Perl_croak(aTHX_ "Client::CreateTaskDynamicZone zone value in 'instance' table must be int or string"); - } - - uint32_t zone_version = SvIOK(*version_ptr) ? static_cast(SvIV(*version_ptr)) : 0; + perl::scalar zone = instance["zone"]; + uint32_t version = instance["version"]; + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); // tasks override dz duration so duration is ignored here - DynamicZone dz{ zone_id, zone_version, 0, DynamicZoneType::None }; + DynamicZone dz{ zone_id, version, 0, DynamicZoneType::None }; - SV** compass_ptr = hv_fetchs(hash, "compass", false); - if (compass_ptr && SvROK(*compass_ptr) && SvTYPE(SvRV(*compass_ptr)) == SVt_PVHV) + if (table.exists("compass")) { - auto compass_loc = GetDynamicZoneLocationFromHash((HV*)SvRV(*compass_ptr)); - dz.SetCompass(compass_loc); + auto compass = GetDynamicZoneLocationFromHash(table["compass"]); + dz.SetCompass(compass); } - SV** safereturn_ptr = hv_fetchs(hash, "safereturn", false); - if (safereturn_ptr && SvROK(*safereturn_ptr) && SvTYPE(SvRV(*safereturn_ptr)) == SVt_PVHV) + if (table.exists("safereturn")) { - auto safereturn_loc = GetDynamicZoneLocationFromHash((HV*)SvRV(*safereturn_ptr)); - dz.SetSafeReturn(safereturn_loc); + auto safereturn = GetDynamicZoneLocationFromHash(table["safereturn"]); + dz.SetSafeReturn(safereturn); } - SV** zonein_ptr = hv_fetchs(hash, "zonein", false); - if (zonein_ptr && SvROK(*zonein_ptr) && SvTYPE(SvRV(*zonein_ptr)) == SVt_PVHV) + if (table.exists("zonein")) { - auto zonein_loc = GetDynamicZoneLocationFromHash((HV*)SvRV(*zonein_ptr)); - dz.SetZoneInLocation(zonein_loc); + auto zonein = GetDynamicZoneLocationFromHash(table["zonein"]); + dz.SetZoneInLocation(zonein); } - uint32_t task_id = static_cast(SvUV(ST(1))); + if (table.exists("switchid")) + { + dz.SetSwitchID(table["switchid"].as()); + } - THIS->CreateTaskDynamicZone(task_id, dz); + self->CreateTaskDynamicZone(task_id, dz); } -XS(XS_Client_GetExpedition); -XS(XS_Client_GetExpedition) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Client::GetExpedition(THIS)"); - } - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - Expedition* RETVAL = THIS->GetExpedition(); - - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); - - XSRETURN(1); +Expedition* Perl_Client_GetExpedition(Client* self) +{ + return self->GetExpedition(); } -XS(XS_Client_GetExpeditionLockouts); -XS(XS_Client_GetExpeditionLockouts) { - dXSARGS; - if (items != 1 && items != 2) { - Perl_croak(aTHX_ "Usage: Client::GetExpeditionLockouts(THIS, [string expedition_name])"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - HV* hash = newHV(); - SV* hash_ref = nullptr; // for expedition event hash if filtering on expedition - - std::string expedition_name; - if (items == 2) - { - expedition_name = SvPV_nolen(ST(1)); - } - - auto lockouts = THIS->GetExpeditionLockouts(); +perl::reference Perl_Client_GetExpeditionLockouts(Client* self) +{ + perl::hash lockout_hash; + auto lockouts = self->GetExpeditionLockouts(); for (const auto& lockout : lockouts) { - uint32_t name_len = static_cast(lockout.GetExpeditionName().size()); - uint32_t event_len = static_cast(lockout.GetEventName().size()); - - SV** entry = hv_fetch(hash, lockout.GetExpeditionName().c_str(), name_len, false); - if (!entry) + if (!lockout_hash.exists(lockout.GetExpeditionName())) { - SV* event_hash_ref = newRV_noinc((SV*)newHV()); // takes ownership of hash - if (!expedition_name.empty() && lockout.GetExpeditionName() == expedition_name) - { - hash_ref = event_hash_ref; // save ref to event hash for return - } - entry = hv_store(hash, lockout.GetExpeditionName().c_str(), name_len, event_hash_ref, 0); - } - - if (entry && SvROK(*entry) && SvTYPE(SvRV(*entry)) == SVt_PVHV) - { - HV* event_hash = (HV*)SvRV(*entry); - hv_store(event_hash, lockout.GetEventName().c_str(), event_len, - newSVuv(lockout.GetSecondsRemaining()), 0); + lockout_hash[lockout.GetExpeditionName()] = perl::reference(perl::hash()); } + perl::hash events = lockout_hash[lockout.GetExpeditionName()]; // nested + events[lockout.GetEventName()] = lockout.GetSecondsRemaining(); } - SV* rv = &PL_sv_undef; + return perl::reference(lockout_hash); +} - if (!expedition_name.empty()) +perl::reference Perl_Client_GetExpeditionLockouts(Client* self, std::string expedition_name) +{ + perl::hash event_hash; + + auto lockouts = self->GetExpeditionLockouts(expedition_name); + for (const auto& lockout : lockouts) { - rv = hash_ref ? sv_2mortal(hash_ref) : &PL_sv_undef; // ref that owns event hash for expedition + event_hash[lockout.GetEventName()] = lockout.GetSecondsRemaining(); } - else + + return perl::reference(event_hash); +} + +std::string Perl_Client_GetLockoutExpeditionUUID(Client* self, std::string expedition_name, std::string event_name) +{ + auto lockout = self->GetExpeditionLockout(expedition_name, event_name); + return lockout ? lockout->GetExpeditionUUID() : std::string{}; +} + +void Perl_Client_AddExpeditionLockout(Client* self, std::string expedition_name, std::string event_name, uint32 seconds) +{ + self->AddNewExpeditionLockout(expedition_name, event_name, seconds); +} + +void Perl_Client_AddExpeditionLockout(Client* self, std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) +{ + self->AddNewExpeditionLockout(expedition_name, event_name, seconds, uuid); +} + +void Perl_Client_AddExpeditionLockoutDuration(Client* self, std::string expedition_name, std::string event_name, int seconds) +{ + self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, {}, true); +} + +void Perl_Client_AddExpeditionLockoutDuration(Client* self, std::string expedition_name, std::string event_name, int seconds, std::string uuid) +{ + self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, uuid, true); +} + +void Perl_Client_RemoveAllExpeditionLockouts(Client* self) +{ + self->RemoveAllExpeditionLockouts({}, true); +} + +void Perl_Client_RemoveAllExpeditionLockouts(Client* self, std::string expedition_name) +{ + self->RemoveAllExpeditionLockouts(expedition_name, true); +} + +void Perl_Client_RemoveExpeditionLockout(Client* self, std::string expedition_name, std::string event_name) +{ + self->RemoveExpeditionLockout(expedition_name, event_name, true); +} + +bool Perl_Client_HasExpeditionLockout(Client* self, std::string expedition_name, std::string event_name) +{ + return self->HasExpeditionLockout(expedition_name, event_name); +} + +void Perl_Client_MovePCDynamicZone(Client* self, perl::scalar zone) +{ + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); + self->MovePCDynamicZone(zone_id); +} + +void Perl_Client_MovePCDynamicZone(Client* self, perl::scalar zone, int zone_version) +{ + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); + self->MovePCDynamicZone(zone_id, zone_version); +} + +void Perl_Client_MovePCDynamicZone(Client* self, perl::scalar zone, int zone_version, bool msg_if_invalid) +{ + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); + self->MovePCDynamicZone(zone_id, zone_version, msg_if_invalid); +} + +void Perl_Client_Fling(Client* self, float target_x, float target_y, float target_z) +{ + self->Fling(0, target_x, target_y, target_z, false, false, true); +} + +void Perl_Client_Fling(Client* self, float target_x, float target_y, float target_z, bool ignore_los) +{ + self->Fling(0, target_x, target_y, target_z, ignore_los, false, true); +} + +void Perl_Client_Fling(Client* self, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) +{ + self->Fling(0, target_x, target_y, target_z, ignore_los, clip_through_walls, true); +} + +void Perl_Client_Fling(Client* self, float value, float target_x, float target_y, float target_z) +{ + self->Fling(value, target_x, target_y, target_z); +} + +void Perl_Client_Fling(Client* self, float value, float target_x, float target_y, float target_z, bool ignore_los) +{ + self->Fling(value, target_x, target_y, target_z, ignore_los); +} + +void Perl_Client_Fling(Client* self, float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls) +{ + self->Fling(value, target_x, target_y, target_z, ignore_los, clip_through_walls); +} + +bool Perl_Client_HasDisciplineLearned(Client* self, uint16 spell_id) +{ + return self->HasDisciplineLearned(spell_id); +} + +uint32_t Perl_Client_GetClassBitmask(Client* self) +{ + return GetPlayerClassBit(self->GetClass()); +} + +uint32_t Perl_Client_GetRaceBitmask(Client* self) // @categories Stats and Attributes +{ + return GetPlayerRaceBit(self->GetBaseRace()); +} + +perl::array Perl_Client_GetLearnableDisciplines(Client* self) +{ + perl::array result; + auto learnable_disciplines = self->GetLearnableDisciplines(); + for (int i = 0; i < learnable_disciplines.size(); ++i) { - rv = sv_2mortal(newRV_noinc((SV*)hash)); // owns expedition hash + result.push_back(learnable_disciplines[i]); } - - ST(0) = rv; - XSRETURN(1); + return result; } -XS(XS_Client_GetLockoutExpeditionUUID); -XS(XS_Client_GetLockoutExpeditionUUID) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Client::GetLockoutExpeditionUUID(THIS, string expedition_name, string event_name)"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - std::string expedition_name = SvPV_nolen(ST(1)); - std::string event_name = SvPV_nolen(ST(2)); - - auto lockout = THIS->GetExpeditionLockout(expedition_name, event_name); - if (lockout) +perl::array Perl_Client_GetLearnableDisciplines(Client* self, uint8 min_level) +{ + perl::array result; + auto learnable_disciplines = self->GetLearnableDisciplines(min_level); + for (int i = 0; i < learnable_disciplines.size(); ++i) { - XSRETURN_PV(lockout->GetExpeditionUUID().c_str()); + result.push_back(learnable_disciplines[i]); } - - XSRETURN_UNDEF; + return result; } -XS(XS_Client_AddExpeditionLockout); -XS(XS_Client_AddExpeditionLockout) { - dXSARGS; - if (items != 4 && items != 5) { - Perl_croak(aTHX_ "Usage: Client::AddExpeditionLockout(THIS, string expedition_name, string event_name, uint32 seconds, [string uuid])"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - std::string expedition_name(SvPV_nolen(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - uint32 seconds = (uint32)SvUV(ST(3)); - std::string uuid; - - if (items == 5) +perl::array Perl_Client_GetLearnableDisciplines(Client* self, uint8 min_level, uint8 max_level) +{ + perl::array result; + auto learnable_disciplines = self->GetLearnableDisciplines(min_level, max_level); + for (int i = 0; i < learnable_disciplines.size(); ++i) { - uuid = SvPV_nolen(ST(4)); + result.push_back(learnable_disciplines[i]); } - - THIS->AddNewExpeditionLockout(expedition_name, event_name, seconds, uuid); - - XSRETURN_EMPTY; + return result; } -XS(XS_Client_AddExpeditionLockoutDuration); -XS(XS_Client_AddExpeditionLockoutDuration) { - dXSARGS; - if (items != 4 && items != 5) { - Perl_croak(aTHX_ "Usage: Client::AddExpeditionLockoutDuration(THIS, string expedition_name, string event_name, int seconds, [string uuid])"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - std::string expedition_name(SvPV_nolen(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - int seconds = static_cast(SvUV(ST(3))); - std::string uuid; - - if (items == 5) +perl::array Perl_Client_GetLearnedDisciplines(Client* self) +{ + perl::array result; + auto learned_disciplines = self->GetLearnedDisciplines(); + for (int i = 0; i < learned_disciplines.size(); ++i) { - uuid = SvPV_nolen(ST(4)); + result.push_back(learned_disciplines[i]); } - - THIS->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, uuid, true); - - XSRETURN_EMPTY; + return result; } -XS(XS_Client_RemoveAllExpeditionLockouts); -XS(XS_Client_RemoveAllExpeditionLockouts) { - dXSARGS; - if (items != 1 && items != 2) { - Perl_croak(aTHX_ "Usage: Client::RemoveAllExpeditionLockouts(THIS, [string expedition_name])"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - std::string expedition_name; - if (items == 2) +perl::array Perl_Client_GetMemmedSpells(Client* self) +{ + perl::array result; + auto memmed_spells = self->GetMemmedSpells(); + for (int i = 0; i < memmed_spells.size(); ++i) { - expedition_name = SvPV_nolen(ST(1)); + result.push_back(memmed_spells[i]); } - - THIS->RemoveAllExpeditionLockouts(expedition_name, true); - - XSRETURN_EMPTY; + return result; } -XS(XS_Client_RemoveExpeditionLockout); -XS(XS_Client_RemoveExpeditionLockout) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Client::RemoveExpeditionLockout(THIS, string expedition_name, string event_name)"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - std::string expedition_name(SvPV_nolen(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - - THIS->RemoveExpeditionLockout(expedition_name, event_name, true); - - XSRETURN_EMPTY; -} - -XS(XS_Client_HasExpeditionLockout); -XS(XS_Client_HasExpeditionLockout) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Client::HasExpeditionLockout(THIS, string expedition_name, string event_name)"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - std::string expedition_name(SvPV_nolen(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - - bool result = THIS->HasExpeditionLockout(expedition_name, event_name); - ST(0) = boolSV(result); - - XSRETURN(1); -} - -XS(XS_Client_MovePCDynamicZone); -XS(XS_Client_MovePCDynamicZone) { - dXSARGS; - if (items != 2 && items != 3 && items != 4) { - Perl_croak(aTHX_ "Usage: Client::MovePCDynamicZone(THIS, uint32 zone_id | string zone_name, [int zone_version = -1], [bool message_if_invalid = true])"); - } - - Client* THIS = nullptr; - VALIDATE_THIS_IS_CLIENT; - - if (SvTYPE(ST(1)) == SVt_PV) +perl::array Perl_Client_GetScribeableSpells(Client* self) +{ + perl::array result; + auto scribeable_spells = self->GetScribeableSpells(); + for (int i = 0; i < scribeable_spells.size(); ++i) { - std::string zone_name(SvPV_nolen(ST(1))); - int zone_version = (items >= 3) ? static_cast(SvIV(ST(2))) : -1; - if (items == 4) - { - THIS->MovePCDynamicZone(zone_name, zone_version, (bool)SvTRUE(ST(3))); - } - else - { - THIS->MovePCDynamicZone(zone_name, zone_version); - } + result.push_back(scribeable_spells[i]); } - else if (SvTYPE(ST(1)) == SVt_IV) + return result; +} + +perl::array Perl_Client_GetScribeableSpells(Client* self, uint8 min_level) +{ + perl::array result; + auto scribeable_spells = self->GetScribeableSpells(min_level); + for (int i = 0; i < scribeable_spells.size(); ++i) { - uint32 zone_id = (uint32)SvUV(ST(1)); - int zone_version = (items >= 3) ? static_cast(SvIV(ST(2))) : -1; - if (items == 3) - { - THIS->MovePCDynamicZone(zone_id, zone_version, (bool)SvTRUE(ST(2))); - } - else - { - THIS->MovePCDynamicZone(zone_id, zone_version); - } + result.push_back(scribeable_spells[i]); } - else + return result; +} + +perl::array Perl_Client_GetScribeableSpells(Client* self, uint8 min_level, uint8 max_level) +{ + perl::array result; + auto scribeable_spells = self->GetScribeableSpells(min_level, max_level); + for (int i = 0; i < scribeable_spells.size(); ++i) { - Perl_croak(aTHX_ "Client::MovePCDynamicZone expected an integer or string"); + result.push_back(scribeable_spells[i]); } - - XSRETURN_EMPTY; + return result; } -XS(XS_Client_Fling); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_Fling) { - dXSARGS; - if (items < 5 || items > 7) - Perl_croak(aTHX_ "Usage: Client::Fling(THIS, value, target_x, target_y, target_z, ignore_los, clipping)"); +perl::array Perl_Client_GetScribedSpells(Client* self) +{ + perl::array result; + auto scribed_spells = self->GetScribedSpells(); + for (int i = 0; i < scribed_spells.size(); ++i) { - Client* THIS; - float value = (float) SvNV(ST(1)); - float target_x = (float) SvNV(ST(2)); - float target_y = (float) SvNV(ST(3)); - float target_z = (float) SvNV(ST(4)); - bool ignore_los = false; - bool clipping = false; - VALIDATE_THIS_IS_CLIENT; - if (items > 5) - ignore_los = (bool) SvTRUE(ST(5)); - - if (items > 6) - clipping = (bool) SvTRUE(ST(6)); - - THIS->Fling(value, target_x, target_y, target_z, ignore_los, clipping); + result.push_back(scribed_spells[i]); } - XSRETURN_EMPTY; + return result; } -XS(XS_Client_HasDisciplineLearned); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_HasDisciplineLearned) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::HasDisciplineLearned(THIS, uint16 spell_id)"); - { - Client *THIS; - bool has_learned; - uint16 spell_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - has_learned = THIS->HasDisciplineLearned(spell_id); - ST(0) = boolSV(has_learned); - sv_2mortal(ST(0)); - } - XSRETURN(1); +EQ::InventoryProfile* Perl_Client_GetInventory(Client* self) +{ + return &self->GetInv(); } -XS(XS_Client_GetClassBitmask); -XS(XS_Client_GetClassBitmask) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetClassBitmask(THIS)"); - { - Client* THIS; - int client_bitmask = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - client_bitmask = GetPlayerClassBit(THIS->GetClass()); - XSprePUSH; - PUSHu((UV) client_bitmask); - } - XSRETURN(1); +double Perl_Client_GetAAEXPModifier(Client* self, uint32 zone_id) +{ + return self->GetAAEXPModifier(zone_id); } -XS(XS_Client_GetRaceBitmask); -XS(XS_Client_GetRaceBitmask) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetRaceBitmask(THIS)"); // @categories Stats and Attributes - { - Client* THIS; - int client_bitmask = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - client_bitmask = GetPlayerRaceBit(THIS->GetBaseRace()); - XSprePUSH; - PUSHu((UV) client_bitmask); - } - XSRETURN(1); +double Perl_Client_GetAAEXPModifier(Client* self, uint32 zone_id, int16 instance_version) +{ + return self->GetAAEXPModifier(zone_id, instance_version); } -XS(XS_Client_GetLearnableDisciplines); -XS(XS_Client_GetLearnableDisciplines) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: Client::GetLearnableDisciplines(THIS, [uint8 min_level, uint8 max_level])"); - - uint8 min_level = 1; - uint8 max_level = 0; - if (items > 1) - min_level = (uint8)SvUV(ST(1)); - if (items > 2) - max_level = (uint8)SvUV(ST(2)); - - Client* THIS; - VALIDATE_THIS_IS_CLIENT; - auto learnable_disciplines = THIS->GetLearnableDisciplines(min_level, max_level); - auto learnable_size = learnable_disciplines.size(); - if (learnable_size > 0) { - EXTEND(sp, learnable_size); - for (int index = 0; index < learnable_size; ++index) { - ST(index) = sv_2mortal(newSVuv(learnable_disciplines[index])); - } - XSRETURN(learnable_size); - } - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); +double Perl_Client_GetEXPModifier(Client* self, uint32 zone_id) +{ + return self->GetEXPModifier(zone_id); } -XS(XS_Client_GetLearnedDisciplines); -XS(XS_Client_GetLearnedDisciplines) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetLearnedDisciplines(THIS)"); - - Client* THIS; - VALIDATE_THIS_IS_CLIENT; - auto learned_disciplines = THIS->GetLearnedDisciplines(); - auto learned_size = learned_disciplines.size(); - if (learned_size > 0) { - EXTEND(sp, learned_size); - for (int index = 0; index < learned_size; ++index) { - ST(index) = sv_2mortal(newSVuv(learned_disciplines[index])); - } - XSRETURN(learned_size); - } - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); +double Perl_Client_GetEXPModifier(Client* self, uint32 zone_id, int16 instance_version) +{ + return self->GetEXPModifier(zone_id, instance_version); } -XS(XS_Client_GetMemmedSpells); -XS(XS_Client_GetMemmedSpells) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetMemmedSpells(THIS)"); - - Client* THIS; - VALIDATE_THIS_IS_CLIENT; - auto memmed_spells = THIS->GetMemmedSpells(); - auto memmed_size = memmed_spells.size(); - if (memmed_size > 0) { - EXTEND(sp, memmed_size); - for (int index = 0; index < memmed_size; ++index) { - ST(index) = sv_2mortal(newSVuv(memmed_spells[index])); - } - XSRETURN(memmed_size); - } - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); +void Perl_Client_SetAAEXPModifier(Client* self, uint32 zone_id, double aa_modifier) +{ + self->SetAAEXPModifier(zone_id, aa_modifier); } -XS(XS_Client_GetScribeableSpells); -XS(XS_Client_GetScribeableSpells) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: Client::GetScribeableSpells(THIS, [uint8 min_level, uint8 max_level])"); - - uint8 min_level = 1; - uint8 max_level = 0; - if (items > 1) - min_level = (uint8)SvUV(ST(1)); - if (items > 2) - max_level = (uint8)SvUV(ST(2)); - - Client* THIS; - VALIDATE_THIS_IS_CLIENT; - auto scribeable_spells = THIS->GetScribeableSpells(min_level, max_level); - auto scribeable_size = scribeable_spells.size(); - if (scribeable_size > 0) { - EXTEND(sp, scribeable_size); - for (int index = 0; index < scribeable_size; ++index) { - ST(index) = sv_2mortal(newSVuv(scribeable_spells[index])); - } - XSRETURN(scribeable_size); - } - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); +void Perl_Client_SetAAEXPModifier(Client* self, uint32 zone_id, double aa_modifier, int16 instance_version) +{ + self->SetAAEXPModifier(zone_id, aa_modifier, instance_version); } -XS(XS_Client_GetScribedSpells); -XS(XS_Client_GetScribedSpells) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetScribedSpells(THIS)"); - - Client* THIS; - VALIDATE_THIS_IS_CLIENT; - auto scribed_spells = THIS->GetScribedSpells(); - auto scribed_size = scribed_spells.size(); - if (scribed_size > 0) { - EXTEND(sp, scribed_size); - for (int index = 0; index < scribed_size; ++index) { - ST(index) = sv_2mortal(newSVuv(scribed_spells[index])); - } - XSRETURN(scribed_size); - } - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); +void Perl_Client_SetEXPModifier(Client* self, uint32 zone_id, double exp_modifier) +{ + self->SetEXPModifier(zone_id, exp_modifier); } -XS(XS_Client_GetInventory); -XS(XS_Client_GetInventory) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetInventory(THIS)"); - { - Client* THIS; - EQ::InventoryProfile* RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = &THIS->GetInv(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Inventory", (void *) RETVAL); - } - XSRETURN(1); +void Perl_Client_SetEXPModifier(Client* self, uint32 zone_id, double exp_modifier, int16 instance_version) +{ + self->SetEXPModifier(zone_id, exp_modifier, instance_version); } -XS(XS_Client_GetAAEXPModifier); -XS(XS_Client_GetAAEXPModifier) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetAAEXPModifier(THIS, uint32 zone_id)"); - { - Client* THIS; - double aa_modifier = 1.0f; - uint32 zone_id = (uint32)SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - aa_modifier = THIS->GetAAEXPModifier(zone_id); - XSprePUSH; - PUSHn((double) aa_modifier); - } - XSRETURN(1); +void Perl_Client_AddLDoNLoss(Client* self, uint32 theme_id) +{ + self->UpdateLDoNWinLoss(theme_id); } -XS(XS_Client_GetEXPModifier); -XS(XS_Client_GetEXPModifier) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::GetEXPModifier(THIS, uint32 zone_id)"); - { - Client* THIS; - double exp_modifier = 1.0f; - uint32 zone_id = (uint32)SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - exp_modifier = THIS->GetEXPModifier(zone_id); - XSprePUSH; - PUSHn((double) exp_modifier); - } - XSRETURN(1); +void Perl_Client_AddLDoNWin(Client* self, uint32 theme_id) +{ + self->UpdateLDoNWinLoss(theme_id, true); } -XS(XS_Client_SetAAEXPModifier); -XS(XS_Client_SetAAEXPModifier) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetAAEXPModifier(THIS, uint32 zone_id, float aa_modifier)"); - { - Client* THIS; - uint32 zone_id = (uint32)SvUV(ST(1)); - double aa_modifier = (double) SvNV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetAAEXPModifier(zone_id, aa_modifier); - } - XSRETURN_EMPTY; +void Perl_Client_SetHideMe(Client* self, bool hide_me_state) +{ + self->SetHideMe(hide_me_state); } -XS(XS_Client_SetEXPModifier); -XS(XS_Client_SetEXPModifier) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::SetEXPModifier(THIS, uint32 zone_id, float exp_modifier)"); - { - Client* THIS; - uint32 zone_id = (uint32)SvUV(ST(1)); - double exp_modifier = (double) SvNV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetEXPModifier(zone_id, exp_modifier); - } - XSRETURN_EMPTY; +void Perl_Client_ResetAllDisciplineTimers(Client* self) // @categories Spells and Disciplines +{ + self->ResetAllDisciplineTimers(); } -XS(XS_Client_AddLDoNLoss); -XS(XS_Client_AddLDoNLoss) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::AddLDoNLoss(THIS, uint32 theme_id)"); - { - Client* THIS; - uint32 theme_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->UpdateLDoNWinLoss(theme_id); - } - XSRETURN_EMPTY; +void Perl_Client_SendToInstance(Client* self, std::string instance_type, std::string zone_short_name, uint32 instance_version, float x, float y, float z, float heading, std::string instance_identifier, uint32 duration) +{ + self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration); } -XS(XS_Client_AddLDoNWin); -XS(XS_Client_AddLDoNWin) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::AddLDoNWin(THIS, uint32 theme_id)"); - { - Client* THIS; - uint32 theme_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->UpdateLDoNWinLoss(theme_id, true); - } - XSRETURN_EMPTY; +int Perl_Client_CountItem(Client* self, uint32 item_id) +{ + return self->CountItem(item_id); } -XS(XS_Client_SetHideMe); -XS(XS_Client_SetHideMe) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetHideMe(THIS, bool hide_me_state)"); - { - Client* THIS; - bool hide_me_state = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetHideMe(hide_me_state); - } - XSRETURN_EMPTY; +void Perl_Client_RemoveItem(Client* self, uint32 item_id) // @categories Spells and Disciplines +{ + self->RemoveItem(item_id); } -XS(XS_Client_ResetAllDisciplineTimers); -XS(XS_Client_ResetAllDisciplineTimers) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::ResetAllDisciplineTimers(THIS)"); // @categories Spells and Disciplines - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->ResetAllDisciplineTimers(); - } - XSRETURN_EMPTY; +void Perl_Client_RemoveItem(Client* self, uint32 item_id, uint32 quantity) // @categories Spells and Disciplines +{ + self->RemoveItem(item_id, quantity); } -XS(XS_Client_SendToInstance); -XS(XS_Client_SendToInstance) { - dXSARGS; - if (items != 10) - Perl_croak(aTHX_ "Usage: Client::SendToInstance(THIS, string instance_type, string zone_short_name, uint32 instance_version, float x, float y, float z, float heading, string instance_identifier, uint32 duration)"); - { - Client* THIS; - std::string instance_type = (std::string) SvPV_nolen(ST(1)); - std::string zone_short_name = (std::string) SvPV_nolen(ST(2)); - uint32 instance_version = (uint32) SvUV(ST(3)); - float x = (float) SvNV(ST(4)); - float y = (float) SvNV(ST(5)); - float z = (float) SvNV(ST(6)); - float heading = (float) SvNV(ST(7)); - std::string instance_identifier = (std::string) SvPV_nolen(ST(8)); - uint32 duration = (uint32) SvUV(ST(9)); - VALIDATE_THIS_IS_CLIENT; - THIS->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration); - } - XSRETURN_EMPTY; +void Perl_Client_DialogueWindow(Client* self, std::string window_markdown) // @categories Script Utility +{ + DialogueWindow::Render(self, std::move(window_markdown)); } -XS(XS_Client_CountItem); -XS(XS_Client_CountItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::CountItem(THIS, uint32 item_id)"); - { - Client* THIS; - int item_count = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - item_count = THIS->CountItem(item_id); - XSprePUSH; - PUSHu((UV) item_count); - } - XSRETURN(1); +void Perl_Client_DiaWind(Client* self, std::string window_markdown) // @categories Script Utility +{ + DialogueWindow::Render(self, std::move(window_markdown)); } -XS(XS_Client_RemoveItem); -XS(XS_Client_RemoveItem) { - dXSARGS; - if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: Client::RemoveItem(THIS, uint32 item_id, [uint32 quantity = 1])"); // @categories Spells and Disciplines - { - Client *THIS; - uint32 item_id = (uint32) SvUV(ST(1)); - uint32 quantity = 1; - VALIDATE_THIS_IS_CLIENT; - if (items == 3) { - quantity = (uint32) SvUV(ST(2)); - } - - THIS->RemoveItem(item_id, quantity); - } - XSRETURN_EMPTY; +int Perl_Client_GetIPExemption(Client* self) // @categories Account and Character +{ + return self->GetIPExemption(); } -XS(XS_Client_DialogueWindow); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_DialogueWindow) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::DialogueWindow(THIS, string window_markdown)"); // @categories Script Utility - { - Client *THIS; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - - std::string window_markdown(SvPV_nolen(ST(1))); - DialogueWindow::Render(THIS, window_markdown); - } - XSRETURN_EMPTY; +std::string Perl_Client_GetIPString(Client* self) // @categories Account and Character +{ + return self->GetIPString(); } -XS(XS_Client_DiaWind); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_DiaWind) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::DiaWind(THIS, string window_markdown)"); // @categories Script Utility - { - Client *THIS; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - - std::string window_markdown(SvPV_nolen(ST(1))); - DialogueWindow::Render(THIS, window_markdown); - - } - XSRETURN_EMPTY; +void Perl_Client_SetIPExemption(Client* self, int exemption_amount) // @categories Account and Character +{ + self->SetIPExemption(exemption_amount); } -XS(XS_Client_GetIPExemption); -XS(XS_Client_GetIPExemption) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetIPExemption(THIS)"); // @categories Account and Character - { - Client* THIS; - int exemption_amount = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - exemption_amount = THIS->GetIPExemption(); - XSprePUSH; - PUSHi((IV) exemption_amount); - } - XSRETURN(1); +void Perl_Client_ReadBookByName(Client* self, std::string book_name, uint8 book_type) // @categories Script Utility +{ + self->ReadBookByName(book_name, book_type); } -XS(XS_Client_GetIPString); -XS(XS_Client_GetIPString) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetIPString(THIS)"); // @categories Account and Character - { - Client *THIS; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - std::string ip_string = THIS->GetIPString(); - sv_setpv(TARG, ip_string.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +void Perl_Client_UntrainDiscBySpellID(Client* self, uint16 spell_id) // @categories Spells and Disciplines +{ + self->UntrainDiscBySpellID(spell_id); } -XS(XS_Client_SetIPExemption); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetIPExemption) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetIPExemption(THIS, int exemption_amount)"); // @categories Account and Character - { - Client *THIS; - int exemption_amount = (int) SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - THIS->SetIPExemption(exemption_amount); - } - XSRETURN_EMPTY; +void Perl_Client_UntrainDiscBySpellID(Client* self, uint16 spell_id, bool update_client) // @categories Spells and Disciplines +{ + self->UntrainDiscBySpellID(spell_id, update_client); } -XS(XS_Client_ReadBookByName); -XS(XS_Client_ReadBookByName) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::ReadBookByName(THIS, string book_name, uint8 book_type)"); // @categories Script Utility - { - Client *THIS; - std::string book_name(SvPV_nolen(ST(1))); - uint8 book_type = (uint8) SvUV(ST(2)); - VALIDATE_THIS_IS_CLIENT; - THIS->ReadBookByName(book_name, book_type); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_UntrainDiscBySpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_UntrainDiscBySpellID) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::UntrainDiscBySpellID(THIS, uint16 spell_id, [bool update_client = true])"); // @categories Spells and Disciplines - { - Client *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - bool update_client = true; - VALIDATE_THIS_IS_CLIENT; - if (items == 3) { - update_client = (bool) SvTRUE(ST(2)); - } - - THIS->UntrainDiscBySpellID(spell_id, update_client); - } - XSRETURN_EMPTY; -} - -XS(XS_Client_SummonBaggedItems); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SummonBaggedItems) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Client::SummonBaggedItems(THIS, uint32 bag_item_id, ARRAYREF bag_items_array)"); // @categories Inventory and Items, Script Utility - } - - Client* THIS; - VALIDATE_THIS_IS_CLIENT; - - uint32 bag_item_id = (uint32) SvUV(ST(1)); - - // verify we're receiving a reference to an array type - SV* bag_items_avref = ST(2); - if (!bag_items_avref || !SvROK(bag_items_avref) || SvTYPE(SvRV(bag_items_avref)) != SVt_PVAV) { - Perl_croak(aTHX_ "Client::SummonBaggedItems second argument is not a reference to an array"); - } - - // dereference into the array - AV* bag_items_av = (AV*)SvRV(bag_items_avref); - +void Perl_Client_SummonBaggedItems(Client* self, uint32 bag_item_id, perl::reference bag_items_ref) // @categories Inventory and Items, Script Utility +{ std::vector bagged_items; - auto count = av_len(bag_items_av) + 1; - for (int i = 0; i < count; ++i) { - SV** element = av_fetch(bag_items_av, i, 0); - - // verify array element is a hash reference containing item details - if (element && SvROK(*element) && SvTYPE(SvRV(*element)) == SVt_PVHV) { - HV* hash = (HV*)SvRV(*element); // dereference - - SV** item_id_ptr = hv_fetchs(hash, "item_id", false); - SV** item_charges_ptr = hv_fetchs(hash, "charges", false); - SV** attuned_ptr = hv_fetchs(hash, "attuned", false); - SV** augment_one_ptr = hv_fetchs(hash, "augment_one", false); - SV** augment_two_ptr = hv_fetchs(hash, "augment_two", false); - SV** augment_three_ptr = hv_fetchs(hash, "augment_three", false); - SV** augment_four_ptr = hv_fetchs(hash, "augment_four", false); - SV** augment_five_ptr = hv_fetchs(hash, "augment_five", false); - SV** augment_six_ptr = hv_fetchs(hash, "augment_six", false); - if (item_id_ptr && item_charges_ptr) { - ServerLootItem_Struct item{}; - item.item_id = static_cast(SvUV(*item_id_ptr)); - item.charges = static_cast(SvIV(*item_charges_ptr)); - item.attuned = attuned_ptr ? static_cast(SvUV(*attuned_ptr)) : 0; - item.aug_1 = augment_one_ptr ? static_cast(SvUV(*augment_one_ptr)) : 0; - item.aug_2 = augment_two_ptr ? static_cast(SvUV(*augment_two_ptr)) : 0; - item.aug_3 = augment_three_ptr ? static_cast(SvUV(*augment_three_ptr)) : 0; - item.aug_4 = augment_four_ptr ? static_cast(SvUV(*augment_four_ptr)) : 0; - item.aug_5 = augment_five_ptr ? static_cast(SvUV(*augment_five_ptr)) : 0; - item.aug_6 = augment_six_ptr ? static_cast(SvUV(*augment_six_ptr)) : 0; - bagged_items.emplace_back(item); - } + perl::array bag_items = bag_items_ref; + for (perl::hash bag_item : bag_items) // only works if all elements are hashrefs + { + if (bag_item.exists("item_id") && bag_item.exists("charges")) + { + ServerLootItem_Struct item{}; + item.item_id = bag_item["item_id"]; + item.charges = bag_item["charges"]; + item.attuned = bag_item.exists("attuned") ? bag_item["attuned"] : 0; + item.aug_1 = bag_item.exists("augment_one") ? bag_item["augment_one"] : 0; + item.aug_2 = bag_item.exists("augment_two") ? bag_item["augment_two"] : 0; + item.aug_3 = bag_item.exists("augment_three") ? bag_item["augment_three"] : 0; + item.aug_4 = bag_item.exists("augment_four") ? bag_item["augment_four"] : 0; + item.aug_5 = bag_item.exists("augment_five") ? bag_item["augment_five"] : 0; + item.aug_6 = bag_item.exists("augment_six") ? bag_item["augment_six"] : 0; + bagged_items.emplace_back(item); } } - THIS->SummonBaggedItems(bag_item_id, bagged_items); - - XSRETURN_EMPTY; + self->SummonBaggedItems(bag_item_id, bagged_items); } -XS(XS_Client_RemoveLDoNLoss); -XS(XS_Client_RemoveLDoNLoss) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::RemoveLDoNLoss(THIS, uint32 theme_id)"); +void Perl_Client_RemoveLDoNLoss(Client* self, uint32 theme_id) +{ + self->UpdateLDoNWinLoss(theme_id, false, true); +} + +void Perl_Client_RemoveLDoNWin(Client* self, uint32 theme_id) +{ + self->UpdateLDoNWinLoss(theme_id, true, true); +} + +int Perl_Client_GetFreeDisciplineSlot(Client* self) // @categories Spells and Disciplines +{ + return self->GetNextAvailableDisciplineSlot(); +} + +int Perl_Client_GetFreeDisciplineSlot(Client* self, int starting_slot) // @categories Spells and Disciplines +{ + return self->GetNextAvailableDisciplineSlot(starting_slot); +} + +int Perl_Client_ScribeSpells(Client* self, uint8 min_level, uint8 max_level) // @categories Spells and Disciplines +{ + return self->ScribeSpells(min_level, max_level); +} + +int Perl_Client_LearnDisciplines(Client* self, uint8 min_level, uint8 max_level) // @categories Spells and Disciplines +{ + return self->LearnDisciplines(min_level, max_level); +} + +void Perl_Client_ResetCastbarCooldownBySlot(Client* self, int slot) +{ + self->ResetCastbarCooldownBySlot(slot); +} + +void Perl_Client_ResetAllCastbarCooldowns(Client* self) +{ + self->ResetAllCastbarCooldowns(); +} + +void Perl_Client_ResetCastbarCooldownBySpellID(Client* self, uint32 spell_id) +{ + self->ResetCastbarCooldownBySpellID(spell_id); +} + +void Perl_Client_UnscribeSpellBySpellID(Client* self, uint16 spell_id) +{ + self->UnscribeSpellBySpellID(spell_id); +} + +void Perl_Client_UnscribeSpellBySpellID(Client* self, uint16 spell_id, bool update_client) +{ + self->UnscribeSpellBySpellID(spell_id, update_client); +} + +int Perl_Client_GetEnvironmentDamageModifier(Client* self) // @categories Script Utility +{ + return self->GetEnvironmentDamageModifier(); +} + +void Perl_Client_SetEnvironmentDamageModifier(Client* self, int modifier) // @categories Script Utility +{ + self->SetEnvironmentDamageModifier(modifier); +} + +bool Perl_Client_GetInvulnerableEnvironmentDamage(Client* self) // @categories Script Utility +{ + return self->GetInvulnerableEnvironmentDamage(); +} + +void Perl_Client_SetInvulnerableEnvironmentDamage(Client* self, bool invul) // @categories Script Utility +{ + self->SetInvulnerableEnvironmentDamage(invul); +} + +void Perl_Client_AddItem(Client* self, perl::reference table_ref) +{ + perl::hash table = table_ref; + if (!table.exists("item_id") || !table.exists("charges")) { - Client* THIS; - uint32 theme_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->UpdateLDoNWinLoss(theme_id, false, true); + return; } - XSRETURN_EMPTY; + + uint32 item_id = table["item_id"]; + int16 charges = table["charges"]; + uint32 augment_one = table.exists("augment_one") ? table["augment_one"] : 0; + uint32 augment_two = table.exists("augment_two") ? table["augment_two"] : 0; + uint32 augment_three = table.exists("augment_three") ? table["augment_three"] : 0; + uint32 augment_four = table.exists("augment_four") ? table["augment_four"] : 0; + uint32 augment_five = table.exists("augment_five") ? table["augment_five"] : 0; + uint32 augment_six = table.exists("augment_six") ? table["augment_six"] : 0; + bool attuned = table.exists("attuned") ? table["attuned"] : false; + uint16 slot_id = table.exists("slot_id") ? table["slot_id"] : EQ::invslot::slotCursor; + + self->SummonItem(item_id, charges, augment_one, augment_two, augment_three, + augment_four, augment_five, augment_six, attuned, slot_id); } -XS(XS_Client_RemoveLDoNWin); -XS(XS_Client_RemoveLDoNWin) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::RemoveLDoNWin(THIS, uint32 theme_id)"); +int Perl_Client_CountAugmentEquippedByID(Client* self, uint32 item_id) +{ + return self->GetInv().CountAugmentEquippedByID(item_id); +} + +bool Perl_Client_HasAugmentEquippedByID(Client* self, uint32 item_id) +{ + return self->GetInv().HasAugmentEquippedByID(item_id); +} + +int Perl_Client_CountItemEquippedByID(Client* self, uint32 item_id) +{ + return self->GetInv().CountItemEquippedByID(item_id); +} + +bool Perl_Client_HasItemEquippedByID(Client* self, uint32 item_id) +{ + return self->GetInv().HasItemEquippedByID(item_id); +} + +void Perl_Client_AddPlatinum(Client* self, uint32 platinum) +{ + self->AddPlatinum(platinum); +} + +void Perl_Client_AddPlatinum(Client* self, uint32 platinum, bool update_client) +{ + self->AddPlatinum(platinum, update_client); +} + +uint32 Perl_Client_GetCarriedPlatinum(Client* self) +{ + return self->GetCarriedPlatinum(); +} + +bool Perl_Client_TakePlatinum(Client* self, uint32 platinum) +{ + return self->TakePlatinum(platinum); +} + +bool Perl_Client_TakePlatinum(Client* self, uint32 platinum, bool update_client) +{ + return self->TakePlatinum(platinum, update_client); +} + +void Perl_Client_ClearPEQZoneFlag(Client* self, uint32 zone_id) +{ + self->ClearPEQZoneFlag(zone_id); +} + +bool Perl_Client_HasPEQZoneFlag(Client* self, uint32 zone_id) +{ + return self->HasPEQZoneFlag(zone_id); +} + +void Perl_Client_LoadPEQZoneFlags(Client* self) +{ + self->LoadPEQZoneFlags(); +} + +void Perl_Client_SendPEQZoneFlagInfo(Client* self, Client* to) +{ + self->SendPEQZoneFlagInfo(to); +} + +void Perl_Client_SetPEQZoneFlag(Client* self, uint32 zone_id) +{ + self->SetPEQZoneFlag(zone_id); +} + +int Perl_Client_GetHealAmount(Client* self) +{ + return self->GetHealAmt(); +} + +int Perl_Client_GetSpellDamage(Client* self) +{ + return self->GetSpellDmg(); +} + +void Perl_Client_TaskSelector(Client* self, perl::array task_ids) +{ + std::vector tasks; + for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i) { - Client* THIS; - uint32 theme_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->UpdateLDoNWinLoss(theme_id, true, true); + tasks.push_back(task_ids[i]); } - XSRETURN_EMPTY; + + self->TaskQuestSetSelector(self, tasks, false); } -XS(XS_Client_GetFreeDisciplineSlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetFreeDisciplineSlot) { - dXSARGS; - if (items != 1 || items != 2) - Perl_croak(aTHX_ "Usage: Client::GetFreeDisciplineSlot(THIS, [int starting_slot = 0])"); // @categories Spells and Disciplines +void Perl_Client_TaskSelectorNoCooldown(Client* self, perl::array task_ids) +{ + std::vector tasks; + for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i) { - Client *THIS; - int free_discipline_slot; - int starting_slot = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - if (items == 2) { - starting_slot = SvIV(ST(1)); - } - - free_discipline_slot = THIS->GetNextAvailableDisciplineSlot(starting_slot); - XSprePUSH; - PUSHi((IV) free_discipline_slot); + tasks.push_back(task_ids[i]); } - XSRETURN(1); + + self->TaskQuestSetSelector(self, tasks, true); } -XS(XS_Client_ScribeSpells); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ScribeSpells) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::ScribeSpells(THIS, uint8 min_level, uint8 max_level)"); // @categories Spells and Disciplines - { - Client *THIS; - uint8 min_level = (uint8) SvUV(ST(1)); - uint8 max_level = (uint8) SvUV(ST(2)); - uint16 scribed_spells = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - - scribed_spells = THIS->ScribeSpells(min_level, max_level); - XSprePUSH; - PUSHu((UV) scribed_spells); - } - XSRETURN(1); +bool Perl_Client_TeleportToPlayerByCharacterID(Client* self, uint32 character_id) +{ + return self->GotoPlayer(database.GetCharNameByID(character_id)); } -XS(XS_Client_LearnDisciplines); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_LearnDisciplines) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::LearnDisciplines(THIS, uint8 min_level, uint8 max_level)"); // @categories Spells and Disciplines - { - Client *THIS; - uint8 min_level = (uint8) SvUV(ST(1)); - uint8 max_level = (uint8) SvUV(ST(2)); - uint16 learned_disciplines = 0; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - - learned_disciplines = THIS->LearnDisciplines(min_level, max_level); - XSprePUSH; - PUSHu((UV) learned_disciplines); - } - XSRETURN(1); +bool Perl_Client_TeleportToPlayerByName(Client* self, std::string player_name) +{ + return self->GotoPlayer(player_name); } -XS(XS_Client_ResetCastbarCooldownBySlot); -XS(XS_Client_ResetCastbarCooldownBySlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::ResetCastbarCooldownBySlot(THIS, int slot)"); - { - Client* THIS; - int slot = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->ResetCastbarCooldownBySlot(slot); - } - XSRETURN_EMPTY; +bool Perl_Client_TeleportGroupToPlayerByCharacterID(Client* self, uint32 character_id) +{ + return self->GotoPlayerGroup(database.GetCharNameByID(character_id)); } -XS(XS_Client_ResetAllCastbarCooldowns); -XS(XS_Client_ResetAllCastbarCooldowns) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::ResetAllCastbarCooldowns(THIS)"); - { - Client* THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->ResetAllCastbarCooldowns(); - } - XSRETURN_EMPTY; +bool Perl_Client_TeleportGroupToPlayerByName(Client* self, std::string player_name) +{ + return self->GotoPlayerGroup(player_name); } -XS(XS_Client_ResetCastbarCooldownBySpellID); -XS(XS_Client_ResetCastbarCooldownBySpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::ResetCastbarCooldownBySpellID(THIS, uint32 spell_id)"); - { - Client* THIS; - uint32 spell_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->ResetCastbarCooldownBySpellID(spell_id); - } - XSRETURN_EMPTY; +bool Perl_Client_TeleportRaidToPlayerByCharacterID(Client* self, uint32 character_id) +{ + return self->GotoPlayerRaid(database.GetCharNameByID(character_id)); } -XS(XS_Client_UnscribeSpellBySpellID); -XS(XS_Client_UnscribeSpellBySpellID) { - dXSARGS; - if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: Client::UnscribeSpellBySpellID(THIS, uint16 spell_id, [bool update_client = true])"); - { - Client* THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - bool update_client = true; - VALIDATE_THIS_IS_CLIENT; - - if (items == 3) { - update_client = (bool) SvTRUE(ST(2)); - } - - THIS->UnscribeSpellBySpellID(spell_id, update_client); - } - XSRETURN_EMPTY; +bool Perl_Client_TeleportRaidToPlayerByName(Client* self, std::string player_name) +{ + return self->GotoPlayerRaid(player_name); } -XS(XS_Client_GetEnvironmentDamageModifier); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetEnvironmentDamageModifier) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetEnvironmentDamageModifier(THIS)"); // @categories Script Utility - { - Client* THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetEnvironmentDamageModifier(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +int Perl_Client_GetRecipeMadeCount(Client* self, uint32 recipe_id) // @categories Skills and Recipes +{ + return self->GetRecipeMadeCount(recipe_id); } -XS(XS_Client_SetEnvironmentDamageModifier); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetEnvironmentDamageModifier) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetEnvironmentDamageModifier(THIS, int32 modifier)"); // @categories Script Utility - { - Client* THIS; - int32 modifier = (int32)SvIV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetEnvironmentDamageModifier(modifier); - } - XSRETURN_EMPTY; +bool Perl_Client_HasRecipeLearned(Client* self, uint32 recipe_id) // @categories Skills and Recipes +{ + return self->HasRecipeLearned(recipe_id); } -XS(XS_Client_GetInvulnerableEnvironmentDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetInvulnerableEnvironmentDamage) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::InvulnerableEnvironmentDamage(THIS)"); // @categories Script Utility - { - Client* THIS; - bool RETVAL; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetInvulnerableEnvironmentDamage(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Client_SendGMCommand(Client* self, std::string message) // @categories Script Utility +{ + return self->SendGMCommand(message); } -XS(XS_Client_SetInvulnerableEnvironmentDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetInvulnerableEnvironmentDamage) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage:Client::SetInvulnerableEnvironmentDamage(THIS, bool invulnerable)"); // @categories Script Utility - { - Client *THIS; - bool invul = (bool)SvTRUE(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetInvulnerableEnvironmentDamage(invul); - } - XSRETURN_EMPTY; +bool Perl_Client_SendGMCommand(Client* self, std::string message, bool ignore_status) // @categories Script Utility +{ + return self->SendGMCommand(message, ignore_status); } -XS(XS_Client_AddItem); -XS(XS_Client_AddItem) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Client::AddItem(THIS, HASHREF item_table)"); - } - - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - - SV* item_table = ST(1); - if (!item_table || !SvROK(item_table)) { - Perl_croak(aTHX_ "Client::AddItem argument is not a reference type"); - } - - HV* item_table_hash = (HV*)SvRV(item_table); - if (SvTYPE(item_table_hash) != SVt_PVHV) { - Perl_croak(aTHX_ "Client::AddItem reference argument is not to a hash type"); - } - - SV** item_id_ptr = hv_fetchs(item_table_hash, "item_id", false); - SV** item_charges_ptr = hv_fetchs(item_table_hash, "charges", false); - SV** augment_one_ptr = hv_fetchs(item_table_hash, "augment_one", false); - SV** augment_two_ptr = hv_fetchs(item_table_hash, "augment_two", false); - SV** augment_three_ptr = hv_fetchs(item_table_hash, "augment_three", false); - SV** augment_four_ptr = hv_fetchs(item_table_hash, "augment_four", false); - SV** augment_five_ptr = hv_fetchs(item_table_hash, "augment_five", false); - SV** augment_six_ptr = hv_fetchs(item_table_hash, "augment_six", false); - SV** attuned_ptr = hv_fetchs(item_table_hash, "attuned", false); - SV** slot_id_ptr = hv_fetchs(item_table_hash, "slot_id", false); - if (item_id_ptr && item_charges_ptr) { - uint32 item_id = static_cast(SvUV(*item_id_ptr)); - int16 charges = static_cast(SvIV(*item_charges_ptr)); - uint32 augment_one = augment_one_ptr ? static_cast(SvUV(*augment_one_ptr)) : 0; - uint32 augment_two = augment_two_ptr ? static_cast(SvUV(*augment_two_ptr)) : 0; - uint32 augment_three = augment_three_ptr ? static_cast(SvUV(*augment_three_ptr)) : 0; - uint32 augment_four = augment_four_ptr ? static_cast(SvUV(*augment_four_ptr)) : 0; - uint32 augment_five = augment_five_ptr ? static_cast(SvUV(*augment_five_ptr)) : 0; - uint32 augment_six = augment_six_ptr ? static_cast(SvUV(*augment_six_ptr)) : 0; - bool attuned = attuned_ptr ? static_cast(SvTRUE(*attuned_ptr)) : false; - uint16 slot_id = slot_id_ptr ? static_cast(SvUV(*slot_id_ptr)) : EQ::invslot::slotCursor; - THIS->SummonItem( - item_id, - charges, - augment_one, - augment_two, - augment_three, - augment_four, - augment_five, - augment_six, - attuned, - slot_id - ); - } - - XSRETURN_EMPTY; +void Perl_Client_SendMarqueeMessage(Client* self, uint32 type, std::string message) // @categories Script Utility +{ + self->SendMarqueeMessage(type, message); } -XS(XS_Client_HasAugmentEquippedByID); -XS(XS_Client_HasAugmentEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::HasAugmentEquippedByID(THIS, uint32 item_id)"); - { - Client *THIS; - bool has_equipped = false; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - has_equipped = THIS->GetInv().HasAugmentEquippedByID(item_id); - ST(0) = boolSV(has_equipped); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_SendMarqueeMessage(Client* self, uint32 type, std::string message, uint32 duration) // @categories Script Utility +{ + self->SendMarqueeMessage(type, message, duration); } -XS(XS_Client_CountAugmentEquippedByID); -XS(XS_Client_CountAugmentEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::CountAugmentEquippedByID(THIS, uint32 item_id)"); - { - Client *THIS; - int quantity = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - quantity = THIS->GetInv().CountAugmentEquippedByID(item_id); - XSprePUSH; - PUSHi((IV) quantity); - } - XSRETURN(1); +void Perl_Client_SendMarqueeMessage(Client* self, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) // @categories Script Utility +{ + self->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, message); } -XS(XS_Client_AddPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_AddPlatinum) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::AddPlatinum(THIS, uint32 platinum, [bool update_client = false])"); // @categories Currency and Points - { - Client *THIS; - uint32 platinum = (uint32) SvUV(ST(1)); - bool update_client = false; - VALIDATE_THIS_IS_CLIENT; - - if (items == 3) { - update_client = (bool) SvTRUE(ST(2)); - } - - THIS->AddPlatinum(platinum, update_client); - } - XSRETURN_EMPTY; +void Perl_Client_MoveZone(Client* self, const char* zone_short_name) // @categories Script Utility +{ + self->MoveZone(zone_short_name); } -XS(XS_Client_GetCarriedPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_GetCarriedPlatinum) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetCarriedPlatinum(THIS)"); // @categories Currency and Points - { - Client *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetCarriedPlatinum(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_MoveZone(Client* self, const char* zone_short_name, float x, float y, float z) // @categories Script Utility +{ + self->MoveZone(zone_short_name, glm::vec4(x, y, z, 0.0f)); } -XS(XS_Client_HasItemEquippedByID); -XS(XS_Client_HasItemEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::HasItemEquippedByID(THIS, uint32 item_id)"); - { - Client *THIS; - bool has_equipped = false; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - has_equipped = THIS->GetInv().HasItemEquippedByID(item_id); - ST(0) = boolSV(has_equipped); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_MoveZone(Client* self, const char* zone_short_name, float x, float y, float z, float heading) // @categories Script Utility +{ + self->MoveZone(zone_short_name, glm::vec4(x, y, z, heading)); } -XS(XS_Client_CountItemEquippedByID); -XS(XS_Client_CountItemEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::CountItemEquippedByID(THIS, uint32 item_id)"); - { - Client *THIS; - int quantity = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - quantity = THIS->GetInv().CountItemEquippedByID(item_id); - XSprePUSH; - PUSHi((IV) quantity); - } - XSRETURN(1); +void Perl_Client_MoveZoneGroup(Client* self, const char* zone_short_name) // @categories Script Utility, Group +{ + self->MoveZoneGroup(zone_short_name); } -XS(XS_Client_TakePlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_TakePlatinum) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Client::TakePlatinum(THIS, uint32 platinum, [bool update_client = false])"); // @categories Currency and Points - { - Client *THIS; - uint32 platinum = (uint32) SvUV(ST(1)); - bool has_money = false; - bool update_client = false; - VALIDATE_THIS_IS_CLIENT; - - if (items == 3) { - update_client = (bool) SvTRUE(ST(2)); - } - - has_money = THIS->TakePlatinum(platinum, update_client); - ST(0) = boolSV(has_money); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_MoveZoneGroup(Client* self, const char* zone_short_name, float x, float y, float z) // @categories Script Utility +{ + self->MoveZoneGroup(zone_short_name, glm::vec4(x, y, z, 0.0f)); } -XS(XS_Client_ClearPEQZoneFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_ClearPEQZoneFlag) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::ClearPEQZoneFlag(THIS, uint32 zone_id)"); // @categories Script Utility - { - Client *THIS; - uint32 zone_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->ClearPEQZoneFlag(zone_id); - } - XSRETURN_EMPTY; +void Perl_Client_MoveZoneGroup(Client* self, const char* zone_short_name, float x, float y, float z, float heading) // @categories Script Utility +{ + self->MoveZoneGroup(zone_short_name, glm::vec4(x, y, z, heading)); } -XS(XS_Client_HasPEQZoneFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_HasPEQZoneFlag) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::HasPEQZoneFlag(THIS, uint32 zone_id)"); // @categories Account and Character - { - Client *THIS; - bool RETVAL; - uint32 zone_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->HasPEQZoneFlag(zone_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Client_MoveZoneRaid(Client* self, const char* zone_short_name) // @categories Script Utility, Raid +{ + self->MoveZoneRaid(zone_short_name); } -XS(XS_Client_LoadPEQZoneFlags); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_LoadPEQZoneFlags) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::LoadPEQZoneFlags(THIS)"); // @categories Zones - { - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - THIS->LoadPEQZoneFlags(); - } - XSRETURN_EMPTY; +void Perl_Client_MoveZoneRaid(Client* self, const char* zone_short_name, float x, float y, float z) // @categories Script Utility +{ + self->MoveZoneRaid(zone_short_name, glm::vec4(x, y, z, 0.0f)); } -XS(XS_Client_SendPEQZoneFlagInfo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SendPEQZoneFlagInfo) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SendPEQZoneFlagInfo(THIS, Client* to)"); // @categories Account and Character, Zones - { - Client *THIS; - Client *to; - VALIDATE_THIS_IS_CLIENT; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - to = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "to is not of type Client"); - if (to == nullptr) - Perl_croak(aTHX_ "to is nullptr, avoiding crash."); - - THIS->SendPEQZoneFlagInfo(to); - } - XSRETURN_EMPTY; +void Perl_Client_MoveZoneRaid(Client* self, const char* zone_short_name, float x, float y, float z, float heading) // @categories Script Utility +{ + self->MoveZoneRaid(zone_short_name, glm::vec4(x, y, z, heading)); } -XS(XS_Client_SetPEQZoneFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_SetPEQZoneFlag) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetPEQZoneFlag(THIS, uint32 zone_id)"); // @categories Account and Character, PEQZones - { - Client *THIS; - uint32 zone_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CLIENT; - THIS->SetPEQZoneFlag(zone_id); - } - XSRETURN_EMPTY; +void Perl_Client_MoveZoneInstance(Client* self, uint16 instance_id) // @categories Adventures and Expeditions, Script Utility +{ + self->MoveZoneInstance(instance_id); } -XS(XS_Client_GetHealAmount); -XS(XS_Client_GetHealAmount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetHealAmount(THIS)"); // @categories Stats and Attributes, Scriot Utility - { - Client *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetHealAmt(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_MoveZoneInstance(Client* self, uint16 instance_id, float x, float y, float z) // @categories Adventures and Expeditions, Script Utility +{ + self->MoveZoneInstance(instance_id, glm::vec4(x, y, z, 0.0f)); } -XS(XS_Client_GetSpellDamage); -XS(XS_Client_GetSpellDamage) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Client::GetSpellDamage(THIS)"); // @categories Stats and Attributes, Scriot Utility - { - Client *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CLIENT; - RETVAL = THIS->GetSpellDmg(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_Client_MoveZoneInstance(Client* self, uint16 instance_id, float x, float y, float z, float heading) // @categories Adventures and Expeditions, Script Utility +{ + self->MoveZoneInstance(instance_id, glm::vec4(x, y, z, heading)); } -XS(XS_Client_TaskSelector); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Client_TaskSelector) { - dXSARGS; - if (items < 2 || items > 41) { - Perl_croak(aTHX_ "Usage: Client::TaskSelector(THIS, int task_id, 2, 3, 4, 5 [up to 40])"); - } - - Client *THIS; - VALIDATE_THIS_IS_CLIENT; - - int tasks[MAXCHOOSERENTRIES]; - int task_count = (items - 1); - for (int i = 1; i <= task_count; i++) { - tasks[i] = (int) SvIV(ST(i)); - } - - THIS->TaskQuestSetSelector(THIS, task_count, tasks); - XSRETURN_EMPTY; +void Perl_Client_MoveZoneInstanceGroup(Client* self, uint16 instance_id) // @categories Adventures and Expeditions, Script Utility, Group +{ + self->MoveZoneInstanceGroup(instance_id); } -#ifdef __cplusplus -extern "C" -#endif -XS(boot_Client); /* prototype to pass -Wmissing-prototypes */ -XS(boot_Client) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; +void Perl_Client_MoveZoneInstanceGroup(Client* self, uint16 instance_id, float x, float y, float z) // @categories Adventures and Expeditions, Script Utility +{ + self->MoveZoneInstanceGroup(instance_id, glm::vec4(x, y, z, 0.0f)); +} - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; +void Perl_Client_MoveZoneInstanceGroup(Client* self, uint16 instance_id, float x, float y, float z, float heading) // @categories Adventures and Expeditions, Script Utility +{ + self->MoveZoneInstanceGroup(instance_id, glm::vec4(x, y, z, heading)); +} - //add the strcpy stuff to get rid of const warnings.... +void Perl_Client_MoveZoneInstanceRaid(Client* self, uint16 instance_id) // @categories Adventures and Expeditions, Script Utility, Raid +{ + self->MoveZoneInstanceRaid(instance_id); +} - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "AccountID"), XS_Client_AccountID, file, "$"); - newXSproto(strcpy(buf, "AccountName"), XS_Client_AccountName, file, "$"); - newXSproto(strcpy(buf, "AddAAPoints"), XS_Client_AddAAPoints, file, "$$"); - newXSproto(strcpy(buf, "AddAlternateCurrencyValue"), XS_Client_AddAlternateCurrencyValue, file, "$$$"); - newXSproto(strcpy(buf, "AddCrystals"), XS_Client_AddCrystals, file, "$$"); - newXSproto(strcpy(buf, "AddEXP"), XS_Client_AddEXP, file, "$$;$$"); - newXSproto(strcpy(buf, "AddExpeditionLockout"), XS_Client_AddExpeditionLockout, file, "$$$$;$"); - newXSproto(strcpy(buf, "AddExpeditionLockoutDuration"), XS_Client_AddExpeditionLockoutDuration, file, "$$$$;$"); - newXSproto(strcpy(buf, "AddItem"), XS_Client_AddItem, file, "$$"); - newXSproto(strcpy(buf, "AddLDoNLoss"), XS_Client_AddLDoNLoss, file, "$$"); - newXSproto(strcpy(buf, "AddLDoNWin"), XS_Client_AddLDoNWin, file, "$$"); - newXSproto(strcpy(buf, "AddLevelBasedExp"), XS_Client_AddLevelBasedExp, file, "$$;$$"); - newXSproto(strcpy(buf, "AddMoneyToPP"), XS_Client_AddMoneyToPP, file, "$$$$$;$"); - newXSproto(strcpy(buf, "AddPlatinum"), XS_Client_AddPlatinum, file, "$$;$"); - newXSproto(strcpy(buf, "AddPVPPoints"), XS_Client_AddPVPPoints, file, "$$"); - newXSproto(strcpy(buf, "AddSkill"), XS_Client_AddSkill, file, "$$$"); - newXSproto(strcpy(buf, "Admin"), XS_Client_Admin, file, "$"); - newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$;$$"); - newXSproto(strcpy(buf, "AssignToInstance"), XS_Client_AssignToInstance, file, "$$"); - newXSproto(strcpy(buf, "AutoSplitEnabled"), XS_Client_AutoSplitEnabled, file, "$"); - newXSproto(strcpy(buf, "BreakInvis"), XS_Client_BreakInvis, file, "$"); - newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$"); - newXSproto(strcpy(buf, "CalcPriceMod"), XS_Client_CalcPriceMod, file, "$;$$"); - newXSproto(strcpy(buf, "CanHaveSkill"), XS_Client_CanHaveSkill, file, "$$"); - newXSproto(strcpy(buf, "ChangeLastName"), XS_Client_ChangeLastName, file, "$$"); - newXSproto(strcpy(buf, "CharacterID"), XS_Client_CharacterID, file, "$"); - newXSproto(strcpy(buf, "CheckIncreaseSkill"), XS_Client_CheckIncreaseSkill, file, "$$;$"); - newXSproto(strcpy(buf, "CheckSpecializeIncrease"), XS_Client_CheckSpecializeIncrease, file, "$$"); - newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$"); - newXSproto(strcpy(buf, "ClearPEQZoneFlag"), XS_Client_ClearPEQZoneFlag, file, "$$"); - newXSproto(strcpy(buf, "ClearZoneFlag"), XS_Client_ClearZoneFlag, file, "$$"); - newXSproto(strcpy(buf, "Connected"), XS_Client_Connected, file, "$"); - newXSproto(strcpy(buf, "CountAugmentEquippedByID"), XS_Client_CountAugmentEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "CountItem"), XS_Client_CountItem, file, "$$"); - newXSproto(strcpy(buf, "CountItemEquippedByID"), XS_Client_CountItemEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "CreateExpedition"), XS_Client_CreateExpedition, file, "$$$$$$$;$"); - newXSproto(strcpy(buf, "CreateTaskDynamicZone"), XS_Client_CreateTaskDynamicZone, file, "$$"); - newXSproto(strcpy(buf, "DecreaseByID"), XS_Client_DecreaseByID, file, "$$$"); - newXSproto(strcpy(buf, "DeleteItemInInventory"), XS_Client_DeleteItemInInventory, file, "$$;$$"); - newXSproto(strcpy(buf, "DiaWind"), XS_Client_DiaWind, file, "$$"); - newXSproto(strcpy(buf, "DialogueWindow"), XS_Client_DialogueWindow, file, "$$"); - newXSproto(strcpy(buf, "Disconnect"), XS_Client_Disconnect, file, "$"); - newXSproto(strcpy(buf, "DropItem"), XS_Client_DropItem, file, "$$"); - newXSproto(strcpy(buf, "Duck"), XS_Client_Duck, file, "$"); - newXSproto(strcpy(buf, "DyeArmorBySlot"), XS_Client_DyeArmorBySlot, file, "$$$$$;$"); - newXSproto(strcpy(buf, "Escape"), XS_Client_Escape, file, "$"); - newXSproto(strcpy(buf, "ExpeditionMessage"), XS_Client_ExpeditionMessage, file, "$$$"); - newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$"); - newXSproto(strcpy(buf, "FindEmptyMemSlot"), XS_Client_FindEmptyMemSlot, file, "$"); - newXSproto(strcpy(buf, "FindMemmedSpellBySlot"), XS_Client_FindMemmedSpellBySlot, file, "$$"); - newXSproto(strcpy(buf, "FindMemmedSpellBySpellID"), XS_Client_FindMemmedSpellBySpellID, file, "$$"); - newXSproto(strcpy(buf, "Fling"), XS_Client_Fling, file, "$$$$$;$$"); - newXSproto(strcpy(buf, "ForageItem"), XS_Client_ForageItem, file, "$"); - newXSproto(strcpy(buf, "Freeze"), XS_Client_Freeze, file, "$"); - newXSproto(strcpy(buf, "GMKill"), XS_Client_GMKill, file, "$"); - newXSproto(strcpy(buf, "GetAAEXPModifier"), XS_Client_GetAAEXPModifier, file, "$$"); - newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$"); - newXSproto(strcpy(buf, "GetAALevel"), XS_Client_GetAALevel, file, "$$"); - newXSproto(strcpy(buf, "GetAAPercent"), XS_Client_GetAAPercent, file, "$"); - newXSproto(strcpy(buf, "GetAAPoints"), XS_Client_GetAAPoints, file, "$$"); - newXSproto(strcpy(buf, "GetAFK"), XS_Client_GetAFK, file, "$"); - newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$"); - newXSproto(strcpy(buf, "GetAccountFlag"), XS_Client_GetAccountFlag, file, "$$"); - newXSproto(strcpy(buf, "GetAggroCount"), XS_Client_GetAggroCount, file, "$"); - newXSproto(strcpy(buf, "GetAllMoney"), XS_Client_GetAllMoney, file, "$"); - newXSproto(strcpy(buf, "GetAlternateCurrencyValue"), XS_Client_GetAlternateCurrencyValue, file, "$$"); - newXSproto(strcpy(buf, "GetAnon"), XS_Client_GetAnon, file, "$"); - newXSproto(strcpy(buf, "GetAugmentAt"), XS_Client_GetAugmentAt, file, "$$$"); - newXSproto(strcpy(buf, "GetAugmentIDAt"), XS_Client_GetAugmentIDAt, file, "$$$"); - newXSproto(strcpy(buf, "GetBaseAGI"), XS_Client_GetBaseAGI, file, "$"); - newXSproto(strcpy(buf, "GetBaseCHA"), XS_Client_GetBaseCHA, file, "$"); - newXSproto(strcpy(buf, "GetBaseDEX"), XS_Client_GetBaseDEX, file, "$"); - newXSproto(strcpy(buf, "GetBaseFace"), XS_Client_GetBaseFace, file, "$"); - newXSproto(strcpy(buf, "GetBaseINT"), XS_Client_GetBaseINT, file, "$"); - newXSproto(strcpy(buf, "GetBaseSTA"), XS_Client_GetBaseSTA, file, "$"); - newXSproto(strcpy(buf, "GetBaseSTR"), XS_Client_GetBaseSTR, file, "$"); - newXSproto(strcpy(buf, "GetBaseWIS"), XS_Client_GetBaseWIS, file, "$"); - newXSproto(strcpy(buf, "GetBecomeNPCLevel"), XS_Client_GetBecomeNPCLevel, file, "$"); - newXSproto(strcpy(buf, "GetBindHeading"), XS_Client_GetBindHeading, file, "$$"); - newXSproto(strcpy(buf, "GetBindX"), XS_Client_GetBindX, file, "$$"); - newXSproto(strcpy(buf, "GetBindY"), XS_Client_GetBindY, file, "$$"); - newXSproto(strcpy(buf, "GetBindZ"), XS_Client_GetBindZ, file, "$$"); - newXSproto(strcpy(buf, "GetBindZoneID"), XS_Client_GetBindZoneID, file, "$$"); - newXSproto(strcpy(buf, "GetCarriedMoney"), XS_Client_GetCarriedMoney, file, "$"); - newXSproto(strcpy(buf, "GetCarriedPlatinum"), XS_Client_GetCarriedPlatinum, file, "$"); - newXSproto(strcpy(buf, "GetCharacterFactionLevel"), XS_Client_GetCharacterFactionLevel, file, "$$"); - newXSproto(strcpy(buf, "GetClassBitmask"), XS_Client_GetClassBitmask, file, "$"); - newXSproto(strcpy(buf, "GetClientMaxLevel"), XS_Client_GetClientMaxLevel, file, "$"); - newXSproto(strcpy(buf, "GetClientVersion"), XS_Client_GetClientVersion, file, "$"); - newXSproto(strcpy(buf, "GetClientVersionBit"), XS_Client_GetClientVersionBit, file, "$"); - newXSproto(strcpy(buf, "GetCorpseCount"), XS_Client_GetCorpseCount, file, "$"); - newXSproto(strcpy(buf, "GetCorpseID"), XS_Client_GetCorpseID, file, "$$"); - newXSproto(strcpy(buf, "GetCorpseItemAt"), XS_Client_GetCorpseItemAt, file, "$$$"); - newXSproto(strcpy(buf, "GetCustomItemData"), XS_Client_GetCustomItemData, file, "$$$"); - newXSproto(strcpy(buf, "GetDiscSlotBySpellID"), XS_Client_GetDiscSlotBySpellID, file, "$$"); - newXSproto(strcpy(buf, "GetDisciplineTimer"), XS_Client_GetDisciplineTimer, file, "$$"); - newXSproto(strcpy(buf, "GetDuelTarget"), XS_Client_GetDuelTarget, file, "$"); - newXSproto(strcpy(buf, "GetEnvironmentDamageModifier"), XS_Client_GetEnvironmentDamageModifier, file, "$"); - newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$"); - newXSproto(strcpy(buf, "GetEXPModifier"), XS_Client_GetEXPModifier, file, "$$"); - newXSproto(strcpy(buf, "GetEbonCrystals"), XS_Client_GetEbonCrystals, file, "$"); - newXSproto(strcpy(buf, "GetEndurance"), XS_Client_GetEndurance, file, "$"); - newXSproto(strcpy(buf, "GetEnduranceRatio"), XS_Client_GetEnduranceRatio, file, "$"); - newXSproto(strcpy(buf, "GetExpedition"), XS_Client_GetExpedition, file, "$"); - newXSproto(strcpy(buf, "GetExpeditionLockouts"), XS_Client_GetExpeditionLockouts, file, "$;$"); - newXSproto(strcpy(buf, "GetFace"), XS_Client_GetFace, file, "$"); - newXSproto(strcpy(buf, "GetFactionLevel"), XS_Client_GetFactionLevel, file, "$$$$$$$$"); - newXSproto(strcpy(buf, "GetFeigned"), XS_Client_GetFeigned, file, "$"); - newXSproto(strcpy(buf, "GetFreeDisciplineSlot"), XS_Client_GetFreeDisciplineSlot, file, "$;$"); - newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$"); - newXSproto(strcpy(buf, "GetGM"), XS_Client_GetGM, file, "$"); - newXSproto(strcpy(buf, "GetGroup"), XS_Client_GetGroup, file, "$"); - newXSproto(strcpy(buf, "GetGroupPoints"), XS_Client_GetGroupPoints, file, "$"); - newXSproto(strcpy(buf, "GetHealAmount"), XS_Client_GetHealAmount, file, "$"); - newXSproto(strcpy(buf, "GetHorseId"), XS_Client_GetHorseId, file, "$"); - newXSproto(strcpy(buf, "GetHunger"), XS_Client_GetHunger, file, "$$"); - newXSproto(strcpy(buf, "GetIP"), XS_Client_GetIP, file, "$"); - newXSproto(strcpy(buf, "GetIPExemption"), XS_Client_GetIPExemption, file, "$"); - newXSproto(strcpy(buf, "GetIPString"), XS_Client_GetIPString, file, "$"); - newXSproto(strcpy(buf, "GetInstanceID"), XS_Client_GetInstanceID, file, "$$"); - newXSproto(strcpy(buf, "GetInstrumentMod"), XS_Client_GetInstrumentMod, file, "$$"); - newXSproto(strcpy(buf, "GetInventory"), XS_Client_GetInventory, file, "$"); - newXSproto(strcpy(buf, "GetInvulnerableEnvironmentDamage"), XS_Client_GetInvulnerableEnvironmentDamage, file, "$"); - newXSproto(strcpy(buf, "GetItemAt"), XS_Client_GetItemAt, file, "$$"); - newXSproto(strcpy(buf, "GetItemIDAt"), XS_Client_GetItemIDAt, file, "$$"); - newXSproto(strcpy(buf, "GetItemInInventory"), XS_Client_GetItemInInventory, file, "$$"); - newXSproto(strcpy(buf, "GetLDoNLosses"), XS_Client_GetLDoNLosses, file, "$"); - newXSproto(strcpy(buf, "GetLDoNLossesTheme"), XS_Client_GetLDoNLossesTheme, file, "$$"); - newXSproto(strcpy(buf, "GetLDoNPointsTheme"), XS_Client_GetLDoNPointsTheme, file, "$"); - newXSproto(strcpy(buf, "GetLDoNWins"), XS_Client_GetLDoNWins, file, "$"); - newXSproto(strcpy(buf, "GetLDoNWinsTheme"), XS_Client_GetLDoNWinsTheme, file, "$$"); - newXSproto(strcpy(buf, "GetLanguageSkill"), XS_Client_GetLanguageSkill, file, "$$"); - newXSproto(strcpy(buf, "GetLearnableDisciplines"), XS_Client_GetLearnableDisciplines, file, "$;$$"); - newXSproto(strcpy(buf, "GetLearnedDisciplines"), XS_Client_GetLearnedDisciplines, file, "$"); - newXSproto(strcpy(buf, "GetLockoutExpeditionUUID"), XS_Client_GetLockoutExpeditionUUID, file, "$$$"); - newXSproto(strcpy(buf, "GetMaxEndurance"), XS_Client_GetMaxEndurance, file, "$"); - newXSproto(strcpy(buf, "GetMemmedSpells"), XS_Client_GetMemmedSpells, file, "$"); - newXSproto(strcpy(buf, "GetModCharacterFactionLevel"), XS_Client_GetModCharacterFactionLevel, file, "$$"); - newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$"); - newXSproto(strcpy(buf, "GetPVP"), XS_Client_GetPVP, file, "$"); - newXSproto(strcpy(buf, "GetPVPPoints"), XS_Client_GetPVPPoints, file, "$"); - newXSproto(strcpy(buf, "GetRaceBitmask"), XS_Client_GetRaceBitmask, file, "$"); - newXSproto(strcpy(buf, "GetRadiantCrystals"), XS_Client_GetRadiantCrystals, file, "$"); - newXSproto(strcpy(buf, "GetRaid"), XS_Client_GetRaid, file, "$"); - newXSproto(strcpy(buf, "GetRaidPoints"), XS_Client_GetRaidPoints, file, "$"); - newXSproto(strcpy(buf, "GetRawItemAC"), XS_Client_GetRawItemAC, file, "$"); - newXSproto(strcpy(buf, "GetRawSkill"), XS_Client_GetRawSkill, file, "$$"); - newXSproto(strcpy(buf, "GetScribeableSpells"), XS_Client_GetScribeableSpells, file, "$;$$"); - newXSproto(strcpy(buf, "GetScribedSpells"), XS_Client_GetScribedSpells, file, "$"); - newXSproto(strcpy(buf, "GetSkillPoints"), XS_Client_GetSkillPoints, file, "$"); - newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$"); - newXSproto(strcpy(buf, "GetSpellDamage"), XS_Client_GetSpellDamage, file, "$"); - newXSproto(strcpy(buf, "GetSpellIDByBookSlot"), XS_Client_GetSpellIDByBookSlot, file, "$$"); - newXSproto(strcpy(buf, "GetSpentAA"), XS_Client_GetSpentAA, file, "$$"); - newXSproto(strcpy(buf, "GetStartZone"), XS_Client_GetStartZone, file, "$"); - newXSproto(strcpy(buf, "GetTargetRingX"), XS_Client_GetTargetRingX, file, "$"); - newXSproto(strcpy(buf, "GetTargetRingY"), XS_Client_GetTargetRingY, file, "$"); - newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$"); - newXSproto(strcpy(buf, "GetTaskActivityDoneCount"), XS_Client_GetTaskActivityDoneCount, file, "$$$"); - newXSproto(strcpy(buf, "GetThirst"), XS_Client_GetThirst, file, "$$"); - newXSproto(strcpy(buf, "GetTotalSecondsPlayed"), XS_Client_GetTotalSecondsPlayed, file, "$"); - newXSproto(strcpy(buf, "GetWeight"), XS_Client_GetWeight, file, "$"); - newXSproto(strcpy(buf, "GoFish"), XS_Client_GoFish, file, "$"); - newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$;$"); - newXSproto(strcpy(buf, "GuildID"), XS_Client_GuildID, file, "$"); - newXSproto(strcpy(buf, "GuildRank"), XS_Client_GuildRank, file, "$"); - newXSproto(strcpy(buf, "HasAugmentEquippedByID"), XS_Client_HasAugmentEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "HasDisciplineLearned"), XS_Client_HasDisciplineLearned, file, "$$"); - newXSproto(strcpy(buf, "HasExpeditionLockout"), XS_Client_HasExpeditionLockout, file, "$$$"); - newXSproto(strcpy(buf, "HasItemEquippedByID"), XS_Client_HasItemEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "HasPEQZoneFlag"), XS_Client_HasPEQZoneFlag, file, "$$"); - newXSproto(strcpy(buf, "HasSkill"), XS_Client_HasSkill, file, "$$"); - newXSproto(strcpy(buf, "HasSpellScribed"), XS_Client_HasSkill, file, "$$"); - newXSproto(strcpy(buf, "HasZoneFlag"), XS_Client_HasZoneFlag, file, "$$"); - newXSproto(strcpy(buf, "Hungry"), XS_Client_Hungry, file, "$"); - newXSproto(strcpy(buf, "InZone"), XS_Client_InZone, file, "$"); - newXSproto(strcpy(buf, "IncStats"), XS_Client_IncStats, file, "$$$"); - newXSproto(strcpy(buf, "IncreaseLanguageSkill"), XS_Client_IncreaseLanguageSkill, file, "$$;$"); - newXSproto(strcpy(buf, "IncreaseSkill"), XS_Client_IncreaseSkill, file, "$$;$"); - newXSproto(strcpy(buf, "IncrementAA"), XS_Client_IncrementAA, file, "$$"); - newXSproto(strcpy(buf, "IsBecomeNPC"), XS_Client_IsBecomeNPC, file, "$"); - newXSproto(strcpy(buf, "IsCrouching"), XS_Client_IsCrouching, file, "$"); - newXSproto(strcpy(buf, "IsDueling"), XS_Client_IsDueling, file, "$"); - newXSproto(strcpy(buf, "IsGrouped"), XS_Client_IsGrouped, file, "$"); - newXSproto(strcpy(buf, "IsLD"), XS_Client_IsLD, file, "$"); - newXSproto(strcpy(buf, "IsMedding"), XS_Client_IsMedding, file, "$"); - newXSproto(strcpy(buf, "IsRaidGrouped"), XS_Client_IsRaidGrouped, file, "$"); - newXSproto(strcpy(buf, "IsSitting"), XS_Client_IsSitting, file, "$"); - newXSproto(strcpy(buf, "IsStanding"), XS_Client_IsStanding, file, "$"); - newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$"); - newXSproto(strcpy(buf, "IsTaskActivityActive"), XS_Client_IsTaskActivityActive, file, "$$$"); - newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$"); - newXSproto(strcpy(buf, "KeyRingAdd"), XS_Client_KeyRingAdd, file, "$$"); - newXSproto(strcpy(buf, "KeyRingCheck"), XS_Client_KeyRingCheck, file, "$$"); - newXSproto(strcpy(buf, "Kick"), XS_Client_Kick, file, "$"); - newXSproto(strcpy(buf, "LearnDisciplines"), XS_Client_LearnDisciplines, file, "$$$"); - newXSproto(strcpy(buf, "LearnRecipe"), XS_Client_LearnRecipe, file, "$$"); - newXSproto(strcpy(buf, "LeaveGroup"), XS_Client_LeaveGroup, file, "$"); - newXSproto(strcpy(buf, "LoadPEQZoneFlags"), XS_Client_LoadPEQZoneFlags, file, "$"); - newXSproto(strcpy(buf, "LoadZoneFlags"), XS_Client_LoadZoneFlags, file, "$"); - newXSproto(strcpy(buf, "MarkCompassLoc"), XS_Client_MarkCompassLoc, file, "$$$$"); - newXSproto(strcpy(buf, "MaxSkill"), XS_Client_MaxSkill, file, "$$;$$"); - newXSproto(strcpy(buf, "MemSpell"), XS_Client_MemSpell, file, "$$$;$"); - newXSproto(strcpy(buf, "MemmedCount"), XS_Client_MemmedCount, file, "$"); - newXSproto(strcpy(buf, "MovePC"), XS_Client_MovePC, file, "$$$$$$"); - newXSproto(strcpy(buf, "MovePCDynamicZone"), XS_Client_MovePCDynamicZone, file, "$$;$$"); - newXSproto(strcpy(buf, "MovePCInstance"), XS_Client_MovePCInstance, file, "$$$$$$$"); - newXSproto(strcpy(buf, "MoveZone"), XS_Client_MoveZone, file, "$$"); - newXSproto(strcpy(buf, "MoveZoneGroup"), XS_Client_MoveZoneGroup, file, "$$"); - newXSproto(strcpy(buf, "MoveZoneInstance"), XS_Client_MoveZoneInstance, file, "$$"); - newXSproto(strcpy(buf, "MoveZoneInstanceGroup"), XS_Client_MoveZoneInstanceGroup, file, "$$"); - newXSproto(strcpy(buf, "MoveZoneInstanceRaid"), XS_Client_MoveZoneInstanceRaid, file, "$$"); - newXSproto(strcpy(buf, "MoveZoneRaid"), XS_Client_MoveZoneRaid, file, "$$"); - newXSproto(strcpy(buf, "NPCSpawn"), XS_Client_NPCSpawn, file, "$$$;$"); - newXSproto(strcpy(buf, "NotifyNewTitlesAvailable"), XS_Client_NotifyNewTitlesAvailable, file, "$"); - newXSproto(strcpy(buf, "NukeItem"), XS_Client_NukeItem, file, "$$;$"); - newXSproto(strcpy(buf, "OpenLFGuildWindow"), XS_Client_OpenLFGuildWindow, file, "$"); - newXSproto(strcpy(buf, "PlayMP3"), XS_Client_PlayMP3, file, "$;$"); - newXSproto(strcpy(buf, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$"); - newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$"); - newXSproto(strcpy(buf, "ReadBook"), XS_Client_ReadBook, file, "$$$"); - newXSproto(strcpy(buf, "ReadBookByName"), XS_Client_ReadBookByName, file, "$$$"); - newXSproto(strcpy(buf, "RefundAA"), XS_Client_RefundAA, file, "$$"); - newXSproto(strcpy(buf, "RemoveAllExpeditionLockouts"), XS_Client_RemoveAllExpeditionLockouts, file, "$;$"); - newXSproto(strcpy(buf, "RemoveExpeditionLockout"), XS_Client_RemoveExpeditionLockout, file, "$$$"); - newXSproto(strcpy(buf, "RemoveItem"), XS_Client_RemoveItem, file, "$$;$"); - newXSproto(strcpy(buf, "RemoveLDoNLoss"), XS_Client_RemoveLDoNLoss, file, "$$"); - newXSproto(strcpy(buf, "RemoveLDoNWin"), XS_Client_RemoveLDoNWin, file, "$$"); - newXSproto(strcpy(buf, "RemoveNoRent"), XS_Client_RemoveNoRent, file, "$"); - newXSproto(strcpy(buf, "ResetAA"), XS_Client_ResetAA, file, "$"); - newXSproto(strcpy(buf, "ResetAllDisciplineTimers"), XS_Client_ResetAllDisciplineTimers, file, "$"); - newXSproto(strcpy(buf, "ResetAllCastbarCooldowns"), XS_Client_ResetAllCastbarCooldowns, file, "$"); - newXSproto(strcpy(buf, "ResetCastbarCooldownBySlot"), XS_Client_ResetCastbarCooldownBySlot, file, "$$"); - newXSproto(strcpy(buf, "ResetCastbarCooldownBySpellID"), XS_Client_ResetCastbarCooldownBySpellID, file, "$$"); - newXSproto(strcpy(buf, "ResetDisciplineTimer"), XS_Client_ResetDisciplineTimer, file, "$$"); - newXSproto(strcpy(buf, "ResetTrade"), XS_Client_ResetTrade, file, "$"); - newXSproto(strcpy(buf, "Save"), XS_Client_Save, file, "$$"); - newXSproto(strcpy(buf, "SaveBackup"), XS_Client_SaveBackup, file, "$"); - newXSproto(strcpy(buf, "ScribeSpell"), XS_Client_ScribeSpell, file, "$$$;$"); - newXSproto(strcpy(buf, "ScribeSpells"), XS_Client_ScribeSpells, file, "$$$"); - newXSproto(strcpy(buf, "SendColoredText"), XS_Client_SendColoredText, file, "$$$"); - newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$"); - newXSproto(strcpy(buf, "SendOPTranslocateConfirm"), XS_Client_SendOPTranslocateConfirm, file, "$$$"); - newXSproto(strcpy(buf, "SendPEQZoneFlagInfo"), XS_Client_SendPEQZoneFlagInfo, file, "$$"); - newXSproto(strcpy(buf, "SendSound"), XS_Client_SendSound, file, "$"); - newXSproto(strcpy(buf, "SendSpellAnim"), XS_Client_SendSpellAnim, file, "$$$"); - newXSproto(strcpy(buf, "SendTargetCommand"), XS_Client_SendTargetCommand, file, "$$"); - newXSproto(strcpy(buf, "SendToGuildHall"), XS_Client_SendToGuildHall, file, "$"); - newXSproto(strcpy(buf, "SendToInstance"), XS_Client_SendToInstance, file, "$$$$$$$$$$"); - newXSproto(strcpy(buf, "SendWebLink"), XS_Client_SendWebLink, file, "$:$"); - newXSproto(strcpy(buf, "SendZoneFlagInfo"), XS_Client_SendZoneFlagInfo, file, "$$"); - newXSproto(strcpy(buf, "SetAAEXPModifier"), XS_Client_SetAAEXPModifier, file, "$$$"); - newXSproto(strcpy(buf, "SetAAPoints"), XS_Client_SetAAPoints, file, "$$"); - newXSproto(strcpy(buf, "SetAATitle"), XS_Client_SetAATitle, file, "$$;$"); - newXSproto(strcpy(buf, "SetAFK"), XS_Client_SetAFK, file, "$$"); - newXSproto(strcpy(buf, "SetAccountFlag"), XS_Client_SetAccountFlag, file, "$$"); - newXSproto(strcpy(buf, "SetAlternateCurrencyValue"), XS_Client_SetAlternateCurrencyValue, file, "$$$"); - newXSproto(strcpy(buf, "SetAnon"), XS_Client_SetAnon, file, "$$"); - newXSproto(strcpy(buf, "SetBaseClass"), XS_Client_SetBaseClass, file, "$$"); - newXSproto(strcpy(buf, "SetBaseGender"), XS_Client_SetBaseGender, file, "$$"); - newXSproto(strcpy(buf, "SetBaseRace"), XS_Client_SetBaseRace, file, "$$"); - newXSproto(strcpy(buf, "SetBecomeNPC"), XS_Client_SetBecomeNPC, file, "$$"); - newXSproto(strcpy(buf, "SetBecomeNPCLevel"), XS_Client_SetBecomeNPCLevel, file, "$$"); - newXSproto(strcpy(buf, "SetBindPoint"), XS_Client_SetBindPoint, file, "$;$$$$$$"); - newXSproto(strcpy(buf, "SetClientMaxLevel"), XS_Client_SetClientMaxLevel, file, "$$"); - newXSproto(strcpy(buf, "SetConsumption"), XS_Client_SetConsumption, file, "$$$"); - newXSproto(strcpy(buf, "SetCustomItemData"), XS_Client_SetCustomItemData, file, "$$$$"); - newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$"); - newXSproto(strcpy(buf, "SetDuelTarget"), XS_Client_SetDuelTarget, file, "$$"); - newXSproto(strcpy(buf, "SetDueling"), XS_Client_SetDueling, file, "$$"); - newXSproto(strcpy(buf, "SetEXP"), XS_Client_SetEXP, file, "$$$;$"); - newXSproto(strcpy(buf, "SetEXPModifier"), XS_Client_SetEXPModifier, file, "$$$"); - newXSproto(strcpy(buf, "SetEbonCrystals"), XS_Client_SetEbonCrystals, file, "$$"); - newXSproto(strcpy(buf, "SetEndurance"), XS_Client_SetEndurance, file, "$$"); - newXSproto(strcpy(buf, "SetEnvironmentDamageModifier"), XS_Client_SetEnvironmentDamageModifier, file, "$$"); - newXSproto(strcpy(buf, "SetFactionLevel"), XS_Client_SetFactionLevel, file, "$$$$$$"); - newXSproto(strcpy(buf, "SetFactionLevel2"), XS_Client_SetFactionLevel2, file, "$$$$$$$"); - newXSproto(strcpy(buf, "SetFeigned"), XS_Client_SetFeigned, file, "$$"); - newXSproto(strcpy(buf, "SetGM"), XS_Client_SetGM, file, "$$"); - newXSproto(strcpy(buf, "SetGMStatus"), XS_Client_SetGMStatus, file, "$$"); - newXSproto(strcpy(buf, "SetHideMe"), XS_Client_SetHideMe, file, "$$"); - newXSproto(strcpy(buf, "SetHorseId"), XS_Client_SetHorseId, file, "$$"); - newXSproto(strcpy(buf, "SetHunger"), XS_Client_SetHunger, file, "$$"); - newXSproto(strcpy(buf, "SetIPExemption"), XS_Client_SetIPExemption, file, "$$"); - newXSproto(strcpy(buf, "SetInvulnerableEnvironmentDamage"), XS_Client_SetInvulnerableEnvironmentDamage, file, "$$"); - newXSproto(strcpy(buf, "SetLanguageSkill"), XS_Client_SetLanguageSkill, file, "$$$"); - newXSproto(strcpy(buf, "SetMaterial"), XS_Client_SetMaterial, file, "$$$"); - newXSproto(strcpy(buf, "SetPEQZoneFlag"), XS_Client_SetPEQZoneFlag, file, "$$"); - newXSproto(strcpy(buf, "SetPVP"), XS_Client_SetPVP, file, "$$"); - newXSproto(strcpy(buf, "SetPrimaryWeaponOrnamentation"), XS_Client_SetPrimaryWeaponOrnamentation, file, "$$"); - newXSproto(strcpy(buf, "SetRadiantCrystals"), XS_Client_SetRadiantCrystals, file, "$$"); - newXSproto(strcpy(buf, "SetSecondaryWeaponOrnamentation"), XS_Client_SetSecondaryWeaponOrnamentation, file, "$$"); - newXSproto(strcpy(buf, "SetSkill"), XS_Client_SetSkill, file, "$$$"); - newXSproto(strcpy(buf, "SetSkillPoints"), XS_Client_SetSkillPoints, file, "$$"); - newXSproto(strcpy(buf, "SetStartZone"), XS_Client_SetStartZone, file, "$$;$$$$"); - newXSproto(strcpy(buf, "SetStats"), XS_Client_SetStats, file, "$$$"); - newXSproto(strcpy(buf, "SetThirst"), XS_Client_SetThirst, file, "$$"); - newXSproto(strcpy(buf, "SetTint"), XS_Client_SetTint, file, "$$$"); - newXSproto(strcpy(buf, "SetTitleSuffix"), XS_Client_SetTitleSuffix, file, "$$;$"); - newXSproto(strcpy(buf, "SetZoneFlag"), XS_Client_SetZoneFlag, file, "$$"); - newXSproto(strcpy(buf, "SilentMessage"), XS_Client_SilentMessage, file, "$$"); - newXSproto(strcpy(buf, "Sit"), XS_Client_Sit, file, "$"); - newXSproto(strcpy(buf, "SlotConvert2"), XS_Client_SlotConvert2, file, "$$"); - newXSproto(strcpy(buf, "Stand"), XS_Client_Stand, file, "$"); - newXSproto(strcpy(buf, "SummonBaggedItems"), XS_Client_SummonBaggedItems, file, "$$$"); - newXSproto(strcpy(buf, "SummonItem"), XS_Client_SummonItem, file, "$$;$$$$$$$$"); - newXSproto(strcpy(buf, "TGB"), XS_Client_TGB, file, "$"); - newXSproto(strcpy(buf, "TakeMoneyFromPP"), XS_Client_TakeMoneyFromPP, file, "$$;$"); - newXSproto(strcpy(buf, "TakePlatinum"), XS_Client_TakePlatinum, file, "$$;$"); - newXSproto(strcpy(buf, "TaskSelector"), XS_Client_TaskSelector, file, "$$;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"); - newXSproto(strcpy(buf, "Thirsty"), XS_Client_Thirsty, file, "$"); - newXSproto(strcpy(buf, "TrainDiscBySpellID"), XS_Client_TrainDiscBySpellID, file, "$$"); - newXSproto(strcpy(buf, "UnFreeze"), XS_Client_UnFreeze, file, "$"); - newXSproto(strcpy(buf, "Undye"), XS_Client_Undye, file, "$"); - newXSproto(strcpy(buf, "UnmemSpell"), XS_Client_UnmemSpell, file, "$$;$"); - newXSproto(strcpy(buf, "UnmemSpellAll"), XS_Client_UnmemSpellAll, file, "$;$"); - newXSproto(strcpy(buf, "UnmemSpellBySpellID"), XS_Client_UnmemSpellBySpellID, file, "$$"); - newXSproto(strcpy(buf, "UnscribeSpell"), XS_Client_UnscribeSpell, file, "$$;$"); - newXSproto(strcpy(buf, "UnscribeSpellAll"), XS_Client_UnscribeSpellAll, file, "$;$"); - newXSproto(strcpy(buf, "UnscribeSpellBySpellID"), XS_Client_UnscribeSpellBySpellID, file, "$$;$"); - newXSproto(strcpy(buf, "UntrainDisc"), XS_Client_UntrainDisc, file, "$$;$"); - newXSproto(strcpy(buf, "UntrainDiscAll"), XS_Client_UntrainDiscAll, file, "$;$"); - newXSproto(strcpy(buf, "UntrainDiscBySpellID"), XS_Client_UntrainDiscBySpellID, file, "$$;$"); - newXSproto(strcpy(buf, "UpdateAdmin"), XS_Client_UpdateAdmin, file, "$;$"); - newXSproto(strcpy(buf, "UpdateGroupAAs"), XS_Client_UpdateGroupAAs, file, "$$$"); - newXSproto(strcpy(buf, "UpdateLDoNPoints"), XS_Client_UpdateLDoNPoints, file, "$$$"); - newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$;$"); - newXSproto(strcpy(buf, "UpdateWho"), XS_Client_UpdateWho, file, "$;$"); - newXSproto(strcpy(buf, "UseDiscipline"), XS_Client_UseDiscipline, file, "$$$"); - newXSproto(strcpy(buf, "WorldKick"), XS_Client_WorldKick, file, "$"); - XSRETURN_YES; +void Perl_Client_MoveZoneInstanceRaid(Client* self, uint16 instance_id, float x, float y, float z) // @categories Adventures and Expeditions, Script Utility +{ + self->MoveZoneInstanceRaid(instance_id, glm::vec4(x, y, z, 0.0f)); +} + +void Perl_Client_MoveZoneInstanceRaid(Client* self, uint16 instance_id, float x, float y, float z, float heading) // @categories Adventures and Expeditions, Script Utility +{ + self->MoveZoneInstanceRaid(instance_id, glm::vec4(x, y, z, heading)); +} + +void Perl_Client_ApplySpell(Client* self, int spell_id) +{ + self->ApplySpell(spell_id); +} + +void Perl_Client_ApplySpell(Client* self, int spell_id, int duration) +{ + self->ApplySpell(spell_id, duration); +} + +void Perl_Client_ApplySpell(Client* self, int spell_id, int duration, bool allow_pets) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Perl_Client_ApplySpell(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots); +} + +void Perl_Client_ApplySpellGroup(Client* self, int spell_id) +{ + self->ApplySpell(spell_id, 0, ApplySpellType::Group); +} + +void Perl_Client_ApplySpellGroup(Client* self, int spell_id, int duration) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Group); +} + +void Perl_Client_ApplySpellGroup(Client* self, int spell_id, int duration, bool allow_pets) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +void Perl_Client_ApplySpellGroup(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots); +} + +void Perl_Client_ApplySpellRaid(Client* self, int spell_id) +{ + self->ApplySpell(spell_id, 0, ApplySpellType::Raid); +} + +void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Raid); +} + +void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration, bool allow_pets) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets); +} + +void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only); +} + +void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only, allow_bots); +} + +void Perl_Client_SetSpellDuration(Client* self, int spell_id) +{ + self->SetSpellDuration(spell_id); +} + +void Perl_Client_SetSpellDuration(Client* self, int spell_id, int duration) +{ + self->SetSpellDuration(spell_id, duration); +} + +void Perl_Client_SetSpellDuration(Client* self, int spell_id, int duration, bool allow_pets) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets); +} + +void Perl_Client_SetSpellDuration(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots); +} + +void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id) +{ + self->SetSpellDuration(spell_id, 0, ApplySpellType::Group); +} + +void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id, int duration) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group); +} + +void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id, int duration, bool allow_pets) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets); +} + +void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots); +} + +void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id) +{ + self->ApplySpell(spell_id, 0, ApplySpellType::Raid); +} + +void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration) +{ + self->ApplySpell(spell_id, duration, ApplySpellType::Raid); +} + +void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration, bool allow_pets) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets); +} + +void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only); +} + +void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots) +{ + self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only, allow_bots); +} + +perl::array Perl_Client_GetPEQZoneFlags(Client* self) +{ + perl::array a; + + auto l = self->GetPEQZoneFlags(); + for (const auto& f : l) { + a.push_back(f); + } + + return a; +} + +perl::array Perl_Client_GetZoneFlags(Client* self) +{ + perl::array a; + + auto l = self->GetZoneFlags(); + for (const auto& f : l) { + a.push_back(f); + } + + return a; +} + +void Perl_Client_SendPayload(Client* self, int payload_id) // @categories Script Utility +{ + self->SendPayload(payload_id); +} + +void Perl_Client_SendPayload(Client* self, int payload_id, std::string payload_value) // @categories Script Utility +{ + self->SendPayload(payload_id, payload_value); +} + +void Perl_Client_Signal(Client* self, int signal_id) +{ + self->Signal(signal_id); +} + +std::string Perl_Client_GetGuildPublicNote(Client* self) +{ + return self->GetGuildPublicNote(); +} + +void Perl_Client_MaxSkills(Client* self) +{ + self->MaxSkills(); +} + +perl::array Perl_Client_GetAugmentIDsBySlotID(Client* self, int16 slot_id) +{ + perl::array result; + auto augments = self->GetInv().GetAugmentIDsBySlotID(slot_id); + + for (int i = 0; i < augments.size(); ++i) { + result.push_back(augments[i]); + } + + return result; +} + +bool Perl_Client_IsEXPEnabled(Client* self) +{ + return self->IsEXPEnabled(); +} + +void Perl_Client_SetEXPEnabled(Client* self, bool is_exp_enabled) +{ + self->SetEXPEnabled(is_exp_enabled); +} + +bool Perl_Client_CanEnterZone(Client* self, std::string zone_short_name) +{ + return self->CanEnterZone(zone_short_name); +} + +bool Perl_Client_CanEnterZone(Client* self, std::string zone_short_name, int16 instance_version) +{ + return self->CanEnterZone(zone_short_name, instance_version); +} + +void Perl_Client_SendPath(Client* self, Mob* target) +{ + self->SendPath(target); +} + +int Perl_Client_GetBotRequiredLevel(Client* self) +{ + return self->GetBotRequiredLevel(); +} + +int Perl_Client_GetBotRequiredLevel(Client* self, uint8 class_id) +{ + return self->GetBotRequiredLevel(class_id); +} + +uint32 Perl_Client_GetBotCreationLimit(Client* self) +{ + return self->GetBotCreationLimit(); +} + +uint32 Perl_Client_GetBotCreationLimit(Client* self, uint8 class_id) +{ + return self->GetBotCreationLimit(class_id); +} + +int Perl_Client_GetBotSpawnLimit(Client* self) +{ + return self->GetBotSpawnLimit(); +} + +int Perl_Client_GetBotSpawnLimit(Client* self, uint8 class_id) +{ + return self->GetBotSpawnLimit(class_id); +} + +void Perl_Client_SetBotRequiredLevel(Client* self, int new_required_level) +{ + self->SetBotRequiredLevel(new_required_level); +} + +void Perl_Client_SetBotRequiredLevel(Client* self, int new_required_level, uint8 class_id) +{ + self->SetBotRequiredLevel(new_required_level, class_id); +} + +void Perl_Client_SetBotCreationLimit(Client* self, uint32 new_creation_limit) +{ + self->SetBotCreationLimit(new_creation_limit); +} + +void Perl_Client_SetBotCreationLimit(Client* self, uint32 new_creation_limit, uint8 class_id) +{ + self->SetBotCreationLimit(new_creation_limit, class_id); +} + +void Perl_Client_SetBotSpawnLimit(Client* self, int new_spawn_limit) +{ + self->SetBotSpawnLimit(new_spawn_limit); +} + +void Perl_Client_SetBotSpawnLimit(Client* self, int new_spawn_limit, uint8 class_id) +{ + self->SetBotSpawnLimit(new_spawn_limit, class_id); +} + +void Perl_Client_CampAllBots(Client* self) +{ + self->CampAllBots(); +} + +void Perl_Client_CampAllBots(Client* self, uint8 class_id) +{ + self->CampAllBots(class_id); +} + +void perl_register_client() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Client"); + package.add_base_class("Mob"); + package.add("AccountID", &Perl_Client_AccountID); + package.add("AccountName", &Perl_Client_AccountName); + package.add("AddAAPoints", &Perl_Client_AddAAPoints); + package.add("AddAlternateCurrencyValue", &Perl_Client_AddAlternateCurrencyValue); + package.add("AddCrystals", &Perl_Client_AddCrystals); + package.add("AddEXP", (void(*)(Client*, uint32))&Perl_Client_AddEXP); + package.add("AddEXP", (void(*)(Client*, uint32, uint8))&Perl_Client_AddEXP); + package.add("AddEXP", (void(*)(Client*, uint32, uint8, bool))&Perl_Client_AddEXP); + package.add("AddExpeditionLockout", (void(*)(Client*, std::string, std::string, uint32))&Perl_Client_AddExpeditionLockout); + package.add("AddExpeditionLockout", (void(*)(Client*, std::string, std::string, uint32, std::string))&Perl_Client_AddExpeditionLockout); + package.add("AddExpeditionLockoutDuration", (void(*)(Client*, std::string, std::string, int))&Perl_Client_AddExpeditionLockoutDuration); + package.add("AddExpeditionLockoutDuration", (void(*)(Client*, std::string, std::string, int, std::string))&Perl_Client_AddExpeditionLockoutDuration); + package.add("AddItem", &Perl_Client_AddItem); + package.add("AddLDoNLoss", &Perl_Client_AddLDoNLoss); + package.add("AddLDoNWin", &Perl_Client_AddLDoNWin); + package.add("AddLevelBasedExp", (void(*)(Client*, uint8))&Perl_Client_AddLevelBasedExp); + package.add("AddLevelBasedExp", (void(*)(Client*, uint8, uint8))&Perl_Client_AddLevelBasedExp); + package.add("AddLevelBasedExp", (void(*)(Client*, uint8, uint8, bool))&Perl_Client_AddLevelBasedExp); + package.add("AddMoneyToPP", (void(*)(Client*, uint32, uint32, uint32, uint32))&Perl_Client_AddMoneyToPP); + package.add("AddMoneyToPP", (void(*)(Client*, uint32, uint32, uint32, uint32, bool))&Perl_Client_AddMoneyToPP); + package.add("AddPlatinum", (void(*)(Client*, uint32))&Perl_Client_AddPlatinum); + package.add("AddPlatinum", (void(*)(Client*, uint32, bool))&Perl_Client_AddPlatinum); + package.add("AddPVPPoints", &Perl_Client_AddPVPPoints); + package.add("AddSkill", &Perl_Client_AddSkill); + package.add("Admin", &Perl_Client_Admin); + package.add("ApplySpell", (void(*)(Client*, int))&Perl_Client_ApplySpell); + package.add("ApplySpell", (void(*)(Client*, int, int))&Perl_Client_ApplySpell); + package.add("ApplySpell", (void(*)(Client*, int, int, bool))&Perl_Client_ApplySpell); + package.add("ApplySpell", (void(*)(Client*, int, int, bool, bool))&Perl_Client_ApplySpell); + package.add("ApplySpellGroup", (void(*)(Client*, int))&Perl_Client_ApplySpellGroup); + package.add("ApplySpellGroup", (void(*)(Client*, int, int))&Perl_Client_ApplySpellGroup); + package.add("ApplySpellGroup", (void(*)(Client*, int, int, bool))&Perl_Client_ApplySpellGroup); + package.add("ApplySpellGroup", (void(*)(Client*, int, int, bool, bool))&Perl_Client_ApplySpellGroup); + package.add("ApplySpellRaid", (void(*)(Client*, int))&Perl_Client_ApplySpellRaid); + package.add("ApplySpellRaid", (void(*)(Client*, int, int))&Perl_Client_ApplySpellRaid); + package.add("ApplySpellRaid", (void(*)(Client*, int, int, bool))&Perl_Client_ApplySpellRaid); + package.add("ApplySpellRaid", (void(*)(Client*, int, int, bool, bool))&Perl_Client_ApplySpellRaid); + package.add("ApplySpellRaid", (void(*)(Client*, int, int, bool, bool, bool))&Perl_Client_ApplySpellRaid); + package.add("AssignTask", (void(*)(Client*, int))&Perl_Client_AssignTask); + package.add("AssignTask", (void(*)(Client*, int, int))&Perl_Client_AssignTask); + package.add("AssignTask", (void(*)(Client*, int, int, bool))&Perl_Client_AssignTask); + package.add("AssignToInstance", &Perl_Client_AssignToInstance); + package.add("AutoSplitEnabled", &Perl_Client_AutoSplitEnabled); + package.add("BreakInvis", &Perl_Client_BreakInvis); + package.add("CalcEXP", (uint64(*)(Client*, uint8))&Perl_Client_CalcEXP); + package.add("CalcEXP", (uint64(*)(Client*, uint8, bool))&Perl_Client_CalcEXP); + package.add("CalcPriceMod", (float(*)(Client*))&Perl_Client_CalcPriceMod); + package.add("CalcPriceMod", (float(*)(Client*, Mob*))&Perl_Client_CalcPriceMod); + package.add("CalcPriceMod", (float(*)(Client*, Mob*, bool))&Perl_Client_CalcPriceMod); + package.add("CampAllBots", (void(*)(Client*))&Perl_Client_CampAllBots); + package.add("CampAllBots", (void(*)(Client*, uint8))&Perl_Client_CampAllBots); + package.add("CanEnterZone", (bool(*)(Client*, std::string))&Perl_Client_CanEnterZone); + package.add("CanEnterZone", (bool(*)(Client*, std::string, int16))&Perl_Client_CanEnterZone); + package.add("CanHaveSkill", &Perl_Client_CanHaveSkill); + package.add("CashReward", &Perl_Client_CashReward); + package.add("ChangeLastName", &Perl_Client_ChangeLastName); + package.add("CharacterID", &Perl_Client_CharacterID); + package.add("CheckIncreaseSkill", (bool(*)(Client*, int))&Perl_Client_CheckIncreaseSkill); + package.add("CheckIncreaseSkill", (bool(*)(Client*, int, int))&Perl_Client_CheckIncreaseSkill); + package.add("CheckSpecializeIncrease", &Perl_Client_CheckSpecializeIncrease); + package.add("ClearCompassMark", &Perl_Client_ClearCompassMark); + package.add("ClearPEQZoneFlag", &Perl_Client_ClearPEQZoneFlag); + package.add("ClearZoneFlag", &Perl_Client_ClearZoneFlag); + package.add("Connected", &Perl_Client_Connected); + package.add("CountAugmentEquippedByID", &Perl_Client_CountAugmentEquippedByID); + package.add("CountItem", &Perl_Client_CountItem); + package.add("CountItemEquippedByID", &Perl_Client_CountItemEquippedByID); + package.add("CreateExpedition", (Expedition*(*)(Client*, perl::reference))&Perl_Client_CreateExpedition); + package.add("CreateExpedition", (Expedition*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32))&Perl_Client_CreateExpedition); + package.add("CreateExpedition", (Expedition*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32, bool))&Perl_Client_CreateExpedition); + package.add("CreateExpeditionFromTemplate", &Perl_Client_CreateExpeditionFromTemplate); + package.add("CreateTaskDynamicZone", &Perl_Client_CreateTaskDynamicZone); + package.add("DecreaseByID", &Perl_Client_DecreaseByID); + package.add("DeleteItemInInventory", (void(*)(Client*, int16))&Perl_Client_DeleteItemInInventory); + package.add("DeleteItemInInventory", (void(*)(Client*, int16, int16))&Perl_Client_DeleteItemInInventory); + package.add("DeleteItemInInventory", (void(*)(Client*, int16, int16, bool))&Perl_Client_DeleteItemInInventory); + package.add("DiaWind", &Perl_Client_DiaWind); + package.add("DialogueWindow", &Perl_Client_DialogueWindow); + package.add("Disconnect", &Perl_Client_Disconnect); + package.add("DropItem", &Perl_Client_DropItem); + package.add("Duck", &Perl_Client_Duck); + package.add("DyeArmorBySlot", (void(*)(Client*, uint8, uint8, uint8, uint8))&Perl_Client_DyeArmorBySlot); + package.add("DyeArmorBySlot", (void(*)(Client*, uint8, uint8, uint8, uint8, uint8))&Perl_Client_DyeArmorBySlot); + package.add("EndSharedTask", (void(*)(Client*))&Perl_Client_EndSharedTask); + package.add("EndSharedTask", (void(*)(Client*, bool))&Perl_Client_EndSharedTask); + package.add("Escape", &Perl_Client_Escape); + package.add("ExpeditionMessage", &Perl_Client_ExpeditionMessage); + package.add("FailTask", &Perl_Client_FailTask); + package.add("FindEmptyMemSlot", &Perl_Client_FindEmptyMemSlot); + package.add("FindMemmedSpellBySlot", &Perl_Client_FindMemmedSpellBySlot); + package.add("FindMemmedSpellBySpellID", &Perl_Client_FindMemmedSpellBySpellID); + package.add("Fling", (void(*)(Client*, float, float, float))&Perl_Client_Fling); + package.add("Fling", (void(*)(Client*, float, float, float, bool))&Perl_Client_Fling); + package.add("Fling", (void(*)(Client*, float, float, float, bool, bool))&Perl_Client_Fling); + package.add("Fling", (void(*)(Client*, float, float, float, float))&Perl_Client_Fling); + package.add("Fling", (void(*)(Client*, float, float, float, float, bool))&Perl_Client_Fling); + package.add("Fling", (void(*)(Client*, float, float, float, float, bool, bool))&Perl_Client_Fling); + package.add("ForageItem", &Perl_Client_ForageItem); + package.add("Freeze", &Perl_Client_Freeze); + package.add("GMKill", &Perl_Client_GMKill); + package.add("GetAAEXPModifier", (double(*)(Client*, uint32))&Perl_Client_GetAAEXPModifier); + package.add("GetAAEXPModifier", (double(*)(Client*, uint32, int16))&Perl_Client_GetAAEXPModifier); + package.add("GetAAExp", &Perl_Client_GetAAExp); + package.add("GetAALevel", &Perl_Client_GetAALevel); + package.add("GetAAPercent", &Perl_Client_GetAAPercent); + package.add("GetAAPoints", &Perl_Client_GetAAPoints); + package.add("GetAFK", &Perl_Client_GetAFK); + package.add("GetAccountAge", &Perl_Client_GetAccountAge); + package.add("GetAccountFlag", &Perl_Client_GetAccountFlag); + package.add("GetAggroCount", &Perl_Client_GetAggroCount); + package.add("GetAllMoney", &Perl_Client_GetAllMoney); + package.add("GetAlternateCurrencyValue", &Perl_Client_GetAlternateCurrencyValue); + package.add("GetAnon", &Perl_Client_GetAnon); + package.add("GetAugmentAt", &Perl_Client_GetAugmentAt); + package.add("GetAugmentIDAt", &Perl_Client_GetAugmentIDAt); + package.add("GetAugmentIDsBySlotID", &Perl_Client_GetAugmentIDsBySlotID); + package.add("GetBaseAGI", &Perl_Client_GetBaseAGI); + package.add("GetBaseCHA", &Perl_Client_GetBaseCHA); + package.add("GetBaseDEX", &Perl_Client_GetBaseDEX); + package.add("GetBaseFace", &Perl_Client_GetBaseFace); + package.add("GetBaseINT", &Perl_Client_GetBaseINT); + package.add("GetBaseSTA", &Perl_Client_GetBaseSTA); + package.add("GetBaseSTR", &Perl_Client_GetBaseSTR); + package.add("GetBaseWIS", &Perl_Client_GetBaseWIS); + package.add("GetBecomeNPCLevel", &Perl_Client_GetBecomeNPCLevel); + package.add("GetBindHeading", (float(*)(Client*))&Perl_Client_GetBindHeading); + package.add("GetBindHeading", (float(*)(Client*, int))&Perl_Client_GetBindHeading); + package.add("GetBindX", (float(*)(Client*))&Perl_Client_GetBindX); + package.add("GetBindX", (float(*)(Client*, int))&Perl_Client_GetBindX); + package.add("GetBindY", (float(*)(Client*))&Perl_Client_GetBindY); + package.add("GetBindY", (float(*)(Client*, int))&Perl_Client_GetBindY); + package.add("GetBindZ", (float(*)(Client*))&Perl_Client_GetBindZ); + package.add("GetBindZ", (float(*)(Client*, int))&Perl_Client_GetBindZ); + package.add("GetBindZoneID", (uint32_t(*)(Client*))&Perl_Client_GetBindZoneID); + package.add("GetBindZoneID", (uint32_t(*)(Client*, int))&Perl_Client_GetBindZoneID); + package.add("GetBotCreationLimit", (uint32(*)(Client*))&Perl_Client_GetBotCreationLimit); + package.add("GetBotCreationLimit", (uint32(*)(Client*, uint8))&Perl_Client_GetBotCreationLimit); + package.add("GetBotRequiredLevel", (int(*)(Client*))&Perl_Client_GetBotRequiredLevel); + package.add("GetBotRequiredLevel", (int(*)(Client*, uint8))&Perl_Client_GetBotRequiredLevel); + package.add("GetBotSpawnLimit", (int(*)(Client*))&Perl_Client_GetBotSpawnLimit); + package.add("GetBotSpawnLimit", (int(*)(Client*, uint8))&Perl_Client_GetBotSpawnLimit); + package.add("GetCarriedMoney", &Perl_Client_GetCarriedMoney); + package.add("GetCarriedPlatinum", &Perl_Client_GetCarriedPlatinum); + package.add("GetCharacterFactionLevel", &Perl_Client_GetCharacterFactionLevel); + package.add("GetClassBitmask", &Perl_Client_GetClassBitmask); + package.add("GetClientMaxLevel", &Perl_Client_GetClientMaxLevel); + package.add("GetClientVersion", &Perl_Client_GetClientVersion); + package.add("GetClientVersionBit", &Perl_Client_GetClientVersionBit); + package.add("GetCorpseCount", &Perl_Client_GetCorpseCount); + package.add("GetCorpseID", &Perl_Client_GetCorpseID); + package.add("GetCorpseItemAt", &Perl_Client_GetCorpseItemAt); + package.add("GetCustomItemData", &Perl_Client_GetCustomItemData); + package.add("GetDiscSlotBySpellID", &Perl_Client_GetDiscSlotBySpellID); + package.add("GetDisciplineTimer", &Perl_Client_GetDisciplineTimer); + package.add("GetDuelTarget", &Perl_Client_GetDuelTarget); + package.add("GetEnvironmentDamageModifier", &Perl_Client_GetEnvironmentDamageModifier); + package.add("GetEXP", &Perl_Client_GetEXP); + package.add("GetEXPModifier", (double(*)(Client*, uint32))&Perl_Client_GetEXPModifier); + package.add("GetEXPModifier", (double(*)(Client*, uint32, int16))&Perl_Client_GetEXPModifier); + package.add("GetEbonCrystals", &Perl_Client_GetEbonCrystals); + package.add("GetEndurance", &Perl_Client_GetEndurance); + package.add("GetEnduranceRatio", &Perl_Client_GetEnduranceRatio); + package.add("GetExpedition", &Perl_Client_GetExpedition); + package.add("GetExpeditionLockouts", (perl::reference(*)(Client*))&Perl_Client_GetExpeditionLockouts); + package.add("GetExpeditionLockouts", (perl::reference(*)(Client*, std::string))&Perl_Client_GetExpeditionLockouts); + package.add("GetFace", &Perl_Client_GetFace); + package.add("GetFactionLevel", &Perl_Client_GetFactionLevel); + package.add("GetFeigned", &Perl_Client_GetFeigned); + package.add("GetFreeDisciplineSlot", (int(*)(Client*))&Perl_Client_GetFreeDisciplineSlot); + package.add("GetFreeDisciplineSlot", (int(*)(Client*, int))&Perl_Client_GetFreeDisciplineSlot); + package.add("GetFreeSpellBookSlot", (int(*)(Client*))&Perl_Client_GetFreeSpellBookSlot); + package.add("GetFreeSpellBookSlot", (int(*)(Client*, uint32))&Perl_Client_GetFreeSpellBookSlot); + package.add("GetGM", &Perl_Client_GetGM); + package.add("GetGMStatus", &Perl_Client_GetGMStatus); + package.add("GetGroup", &Perl_Client_GetGroup); + package.add("GetGroupPoints", &Perl_Client_GetGroupPoints); + package.add("GetGuildPublicNote", &Perl_Client_GetGuildPublicNote); + package.add("GetHorseId", &Perl_Client_GetHorseId); + package.add("GetHealAmount", &Perl_Client_GetHealAmount); + package.add("GetHunger", &Perl_Client_GetHunger); + package.add("GetIP", &Perl_Client_GetIP); + package.add("GetIPExemption", &Perl_Client_GetIPExemption); + package.add("GetIPString", &Perl_Client_GetIPString); + package.add("GetInstanceID", &Perl_Client_GetInstanceID); + package.add("GetInstrumentMod", &Perl_Client_GetInstrumentMod); + package.add("GetInventory", &Perl_Client_GetInventory); + package.add("GetInvulnerableEnvironmentDamage", &Perl_Client_GetInvulnerableEnvironmentDamage); + package.add("GetItemAt", &Perl_Client_GetItemAt); + package.add("GetItemIDAt", &Perl_Client_GetItemIDAt); + package.add("GetItemInInventory", &Perl_Client_GetItemInInventory); + package.add("GetLDoNLosses", &Perl_Client_GetLDoNLosses); + package.add("GetLDoNLossesTheme", &Perl_Client_GetLDoNLossesTheme); + package.add("GetLDoNPointsTheme", &Perl_Client_GetLDoNPointsTheme); + package.add("GetLDoNWins", &Perl_Client_GetLDoNWins); + package.add("GetLDoNWinsTheme", &Perl_Client_GetLDoNWinsTheme); + package.add("GetLanguageSkill", &Perl_Client_GetLanguageSkill); + package.add("GetLearnableDisciplines", (perl::array(*)(Client*))&Perl_Client_GetLearnableDisciplines); + package.add("GetLearnableDisciplines", (perl::array(*)(Client*, uint8))&Perl_Client_GetLearnableDisciplines); + package.add("GetLearnableDisciplines", (perl::array(*)(Client*, uint8, uint8))&Perl_Client_GetLearnableDisciplines); + package.add("GetLearnedDisciplines", &Perl_Client_GetLearnedDisciplines); + package.add("GetLockoutExpeditionUUID", &Perl_Client_GetLockoutExpeditionUUID); + package.add("GetMaxEndurance", &Perl_Client_GetMaxEndurance); + package.add("GetMemmedSpells", &Perl_Client_GetMemmedSpells); + package.add("GetModCharacterFactionLevel", &Perl_Client_GetModCharacterFactionLevel); + package.add("GetMoney", &Perl_Client_GetMoney); + package.add("GetPVP", &Perl_Client_GetPVP); + package.add("GetPVPPoints", &Perl_Client_GetPVPPoints); + package.add("GetRaceBitmask", &Perl_Client_GetRaceBitmask); + package.add("GetRadiantCrystals", &Perl_Client_GetRadiantCrystals); + package.add("GetRaid", &Perl_Client_GetRaid); + package.add("GetRaidPoints", &Perl_Client_GetRaidPoints); + package.add("GetRawItemAC", &Perl_Client_GetRawItemAC); + package.add("GetRawSkill", &Perl_Client_GetRawSkill); + package.add("GetRecipeMadeCount", &Perl_Client_GetRecipeMadeCount); + package.add("GetScribeableSpells", (perl::array(*)(Client*))&Perl_Client_GetScribeableSpells); + package.add("GetScribeableSpells", (perl::array(*)(Client*, uint8))&Perl_Client_GetScribeableSpells); + package.add("GetScribeableSpells", (perl::array(*)(Client*, uint8, uint8))&Perl_Client_GetScribeableSpells); + package.add("GetScribedSpells", &Perl_Client_GetScribedSpells); + package.add("GetSkillPoints", &Perl_Client_GetSkillPoints); + package.add("GetSpellDamage", &Perl_Client_GetSpellDamage); + package.add("GetSpellBookSlotBySpellID", &Perl_Client_GetSpellBookSlotBySpellID); + package.add("GetSpellIDByBookSlot", &Perl_Client_GetSpellIDByBookSlot); + package.add("GetSpentAA", &Perl_Client_GetSpentAA); + package.add("GetStartZone", &Perl_Client_GetStartZone); + package.add("GetTargetRingX", &Perl_Client_GetTargetRingX); + package.add("GetTargetRingY", &Perl_Client_GetTargetRingY); + package.add("GetTargetRingZ", &Perl_Client_GetTargetRingZ); + package.add("GetTaskActivityDoneCount", &Perl_Client_GetTaskActivityDoneCount); + package.add("GetThirst", &Perl_Client_GetThirst); + package.add("GetTotalSecondsPlayed", &Perl_Client_GetTotalSecondsPlayed); + package.add("GetWeight", &Perl_Client_GetWeight); + package.add("GetPEQZoneFlags", &Perl_Client_GetPEQZoneFlags); + package.add("GetZoneFlags", &Perl_Client_GetZoneFlags); + package.add("GoFish", &Perl_Client_GoFish); + package.add("GrantAlternateAdvancementAbility", (bool(*)(Client*, int, int))&Perl_Client_GrantAlternateAdvancementAbility); + package.add("GrantAlternateAdvancementAbility", (bool(*)(Client*, int, int, bool))&Perl_Client_GrantAlternateAdvancementAbility); + package.add("GuildID", &Perl_Client_GuildID); + package.add("GuildRank", &Perl_Client_GuildRank); + package.add("HasAugmentEquippedByID", &Perl_Client_HasAugmentEquippedByID); + package.add("HasDisciplineLearned", &Perl_Client_HasDisciplineLearned); + package.add("HasExpeditionLockout", &Perl_Client_HasExpeditionLockout); + package.add("HasItemEquippedByID", &Perl_Client_HasItemEquippedByID); + package.add("HasPEQZoneFlag", &Perl_Client_HasPEQZoneFlag); + package.add("HasRecipeLearned", &Perl_Client_HasRecipeLearned); + package.add("HasSkill", &Perl_Client_HasSkill); + package.add("HasSpellScribed", &Perl_Client_HasSpellScribed); + package.add("HasZoneFlag", &Perl_Client_HasZoneFlag); + package.add("Hungry", &Perl_Client_Hungry); + package.add("InZone", &Perl_Client_InZone); + package.add("IncStats", &Perl_Client_IncStats); + package.add("IncreaseLanguageSkill", (void(*)(Client*, int))&Perl_Client_IncreaseLanguageSkill); + package.add("IncreaseLanguageSkill", (void(*)(Client*, int, int))&Perl_Client_IncreaseLanguageSkill); + package.add("IncreaseSkill", (void(*)(Client*, int))&Perl_Client_IncreaseSkill); + package.add("IncreaseSkill", (void(*)(Client*, int, int))&Perl_Client_IncreaseSkill); + package.add("IncrementAA", &Perl_Client_IncrementAA); + package.add("IsBecomeNPC", &Perl_Client_IsBecomeNPC); + package.add("IsCrouching", &Perl_Client_IsCrouching); + package.add("IsDueling", &Perl_Client_IsDueling); + package.add("IsEXPEnabled", &Perl_Client_IsEXPEnabled); + package.add("IsGrouped", &Perl_Client_IsGrouped); + package.add("IsLD", &Perl_Client_IsLD); + package.add("IsMedding", &Perl_Client_IsMedding); + package.add("IsRaidGrouped", &Perl_Client_IsRaidGrouped); + package.add("IsSitting", &Perl_Client_IsSitting); + package.add("IsStanding", &Perl_Client_IsStanding); + package.add("IsTaskActive", &Perl_Client_IsTaskActive); + package.add("IsTaskActivityActive", &Perl_Client_IsTaskActivityActive); + package.add("IsTaskCompleted", &Perl_Client_IsTaskCompleted); + package.add("KeyRingAdd", &Perl_Client_KeyRingAdd); + package.add("KeyRingCheck", &Perl_Client_KeyRingCheck); + package.add("Kick", &Perl_Client_Kick); + package.add("LearnDisciplines", &Perl_Client_LearnDisciplines); + package.add("LearnRecipe", &Perl_Client_LearnRecipe); + package.add("LeaveGroup", &Perl_Client_LeaveGroup); + package.add("LoadPEQZoneFlags", &Perl_Client_LoadPEQZoneFlags); + package.add("LoadZoneFlags", &Perl_Client_LoadZoneFlags); + package.add("LockSharedTask", &Perl_Client_LockSharedTask); + package.add("MarkCompassLoc", &Perl_Client_MarkCompassLoc); + package.add("Marquee", (void(*)(Client*, uint32, std::string))&Perl_Client_SendMarqueeMessage); + package.add("Marquee", (void(*)(Client*, uint32, std::string, uint32))&Perl_Client_SendMarqueeMessage); + package.add("Marquee", (void(*)(Client*, uint32, uint32, uint32, uint32, uint32, std::string))&Perl_Client_SendMarqueeMessage); + package.add("MaxSkill", (int(*)(Client*, uint16))&Perl_Client_MaxSkill); + package.add("MaxSkill", (int(*)(Client*, uint16, uint16))&Perl_Client_MaxSkill); + package.add("MaxSkill", (int(*)(Client*, uint16, uint16, uint16))&Perl_Client_MaxSkill); + package.add("MaxSkills", &Perl_Client_MaxSkills); + package.add("MemSpell", (void(*)(Client*, uint16, int))&Perl_Client_MemSpell); + package.add("MemSpell", (void(*)(Client*, uint16, int, bool))&Perl_Client_MemSpell); + package.add("MemmedCount", &Perl_Client_MemmedCount); + package.add("MovePC", &Perl_Client_MovePC); + package.add("MovePCDynamicZone", (void(*)(Client*, perl::scalar))&Perl_Client_MovePCDynamicZone); + package.add("MovePCDynamicZone", (void(*)(Client*, perl::scalar, int))&Perl_Client_MovePCDynamicZone); + package.add("MovePCDynamicZone", (void(*)(Client*, perl::scalar, int, bool))&Perl_Client_MovePCDynamicZone); + package.add("MovePCInstance", &Perl_Client_MovePCInstance); + package.add("MoveZone", (void(*)(Client*, const char*))&Perl_Client_MoveZone); + package.add("MoveZone", (void(*)(Client*, const char*, float, float, float))&Perl_Client_MoveZone); + package.add("MoveZone", (void(*)(Client*, const char*, float, float, float, float))&Perl_Client_MoveZone); + package.add("MoveZoneGroup", (void(*)(Client*, const char*))&Perl_Client_MoveZoneGroup); + package.add("MoveZoneGroup", (void(*)(Client*, const char*, float, float, float))&Perl_Client_MoveZoneGroup); + package.add("MoveZoneGroup", (void(*)(Client*, const char*, float, float, float, float))&Perl_Client_MoveZoneGroup); + package.add("MoveZoneInstance", (void(*)(Client*, uint16))&Perl_Client_MoveZoneInstance); + package.add("MoveZoneInstance", (void(*)(Client*, uint16, float, float, float))&Perl_Client_MoveZoneInstance); + package.add("MoveZoneInstance", (void(*)(Client*, uint16, float, float, float, float))&Perl_Client_MoveZoneInstance); + package.add("MoveZoneInstanceGroup", (void(*)(Client*, uint16))&Perl_Client_MoveZoneInstanceGroup); + package.add("MoveZoneInstanceGroup", (void(*)(Client*, uint16, float, float, float))&Perl_Client_MoveZoneInstanceGroup); + package.add("MoveZoneInstanceGroup", (void(*)(Client*, uint16, float, float, float, float))&Perl_Client_MoveZoneInstanceGroup); + package.add("MoveZoneInstanceRaid", (void(*)(Client*, uint16))&Perl_Client_MoveZoneInstanceRaid); + package.add("MoveZoneInstanceRaid", (void(*)(Client*, uint16, float, float, float))&Perl_Client_MoveZoneInstanceRaid); + package.add("MoveZoneInstanceRaid", (void(*)(Client*, uint16, float, float, float, float))&Perl_Client_MoveZoneInstanceRaid); + package.add("MoveZoneRaid", (void(*)(Client*, const char*))&Perl_Client_MoveZoneRaid); + package.add("MoveZoneRaid", (void(*)(Client*, const char*, float, float, float))&Perl_Client_MoveZoneRaid); + package.add("MoveZoneRaid", (void(*)(Client*, const char*, float, float, float, float))&Perl_Client_MoveZoneRaid); + package.add("NPCSpawn", (void(*)(Client*, NPC*, const char*))&Perl_Client_NPCSpawn); + package.add("NPCSpawn", (void(*)(Client*, NPC*, const char*, uint32))&Perl_Client_NPCSpawn); + package.add("NotifyNewTitlesAvailable", &Perl_Client_NotifyNewTitlesAvailable); + package.add("NukeItem", (uint32_t(*)(Client*, uint32))&Perl_Client_NukeItem); + package.add("NukeItem", (uint32_t(*)(Client*, uint32, uint8))&Perl_Client_NukeItem); + package.add("OpenLFGuildWindow", &Perl_Client_OpenLFGuildWindow); + package.add("PlayMP3", &Perl_Client_PlayMP3); + package.add("Popup2", (void(*)(Client*, const char*, const char*))&Perl_Client_Popup2); + package.add("Popup2", (void(*)(Client*, const char*, const char*, uint32))&Perl_Client_Popup2); + package.add("Popup2", (void(*)(Client*, const char*, const char*, uint32, uint32))&Perl_Client_Popup2); + package.add("Popup2", (void(*)(Client*, const char*, const char*, uint32, uint32, uint32))&Perl_Client_Popup2); + package.add("Popup2", (void(*)(Client*, const char*, const char*, uint32, uint32, uint32, uint32))&Perl_Client_Popup2); + package.add("Popup2", (void(*)(Client*, const char*, const char*, uint32, uint32, uint32, uint32, const char*))&Perl_Client_Popup2); + package.add("Popup2", (void(*)(Client*, const char*, const char*, uint32, uint32, uint32, uint32, const char*, const char*))&Perl_Client_Popup2); + package.add("Popup2", (void(*)(Client*, const char*, const char*, uint32, uint32, uint32, uint32, const char*, const char*, uint32))&Perl_Client_Popup2); + package.add("QuestReward", (void(*)(Client*, Mob*))&Perl_Client_QuestReward); + package.add("QuestReward", (void(*)(Client*, Mob*, uint32))&Perl_Client_QuestReward); + package.add("QuestReward", (void(*)(Client*, Mob*, uint32, uint32))&Perl_Client_QuestReward); + package.add("QuestReward", (void(*)(Client*, Mob*, uint32, uint32, uint32))&Perl_Client_QuestReward); + package.add("QuestReward", (void(*)(Client*, Mob*, uint32, uint32, uint32, uint32))&Perl_Client_QuestReward); + package.add("QuestReward", (void(*)(Client*, Mob*, uint32, uint32, uint32, uint32, uint32))&Perl_Client_QuestReward); + package.add("QuestReward", (void(*)(Client*, Mob*, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Client_QuestReward); + package.add("QuestReward", (void(*)(Client*, Mob*, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Perl_Client_QuestReward); + package.add("ReadBook", &Perl_Client_ReadBook); + package.add("ReadBookByName", &Perl_Client_ReadBookByName); + package.add("RefundAA", &Perl_Client_RefundAA); + package.add("RemoveAllExpeditionLockouts", (void(*)(Client*))&Perl_Client_RemoveAllExpeditionLockouts); + package.add("RemoveAllExpeditionLockouts", (void(*)(Client*, std::string))&Perl_Client_RemoveAllExpeditionLockouts); + package.add("RemoveExpeditionLockout", &Perl_Client_RemoveExpeditionLockout); + package.add("RemoveFromInstance", &Perl_Client_RemoveFromInstance); + package.add("RemoveItem", (void(*)(Client*, uint32))&Perl_Client_RemoveItem); + package.add("RemoveItem", (void(*)(Client*, uint32, uint32))&Perl_Client_RemoveItem); + package.add("RemoveLDoNLoss", &Perl_Client_RemoveLDoNLoss); + package.add("RemoveLDoNWin", &Perl_Client_RemoveLDoNWin); + package.add("RemoveNoRent", &Perl_Client_RemoveNoRent); + package.add("ResetAA", &Perl_Client_ResetAA); + package.add("ResetAllDisciplineTimers", &Perl_Client_ResetAllDisciplineTimers); + package.add("ResetAllCastbarCooldowns", &Perl_Client_ResetAllCastbarCooldowns); + package.add("ResetAlternateAdvancementRank", &Perl_Client_ResetAlternateAdvancementRank); + package.add("ResetCastbarCooldownBySlot", &Perl_Client_ResetCastbarCooldownBySlot); + package.add("ResetCastbarCooldownBySpellID", &Perl_Client_ResetCastbarCooldownBySpellID); + package.add("ResetDisciplineTimer", &Perl_Client_ResetDisciplineTimer); + package.add("ResetTrade", &Perl_Client_ResetTrade); + package.add("Save", &Perl_Client_Save); + package.add("SaveBackup", &Perl_Client_SaveBackup); + package.add("ScribeSpell", (void(*)(Client*, uint16, int))&Perl_Client_ScribeSpell); + package.add("ScribeSpell", (void(*)(Client*, uint16, int, bool))&Perl_Client_ScribeSpell); + package.add("ScribeSpells", &Perl_Client_ScribeSpells); + package.add("SendColoredText", &Perl_Client_SendColoredText); + package.add("SendGMCommand", (bool(*)(Client*, std::string))&Perl_Client_SendGMCommand); + package.add("SendGMCommand", (bool(*)(Client*, std::string, bool))&Perl_Client_SendGMCommand); + package.add("SendMarqueeMessage", (void(*)(Client*, uint32, std::string))&Perl_Client_SendMarqueeMessage); + package.add("SendMarqueeMessage", (void(*)(Client*, uint32, std::string, uint32))&Perl_Client_SendMarqueeMessage); + package.add("SendMarqueeMessage", (void(*)(Client*, uint32, uint32, uint32, uint32, uint32, std::string))&Perl_Client_SendMarqueeMessage); + package.add("SendOPTranslocateConfirm", &Perl_Client_SendOPTranslocateConfirm); + package.add("SendPayload", (void(*)(Client*, int))&Perl_Client_SendPayload); + package.add("SendPayload", (void(*)(Client*, int, std::string))&Perl_Client_SendPayload); + package.add("SendPath", &Perl_Client_SendPath); + package.add("SendPEQZoneFlagInfo", &Perl_Client_SendPEQZoneFlagInfo); + package.add("SendSound", &Perl_Client_SendSound); + package.add("SendSpellAnim", &Perl_Client_SendSpellAnim); + package.add("SendTargetCommand", &Perl_Client_SendTargetCommand); + package.add("SendToGuildHall", &Perl_Client_SendToGuildHall); + package.add("SendToInstance", &Perl_Client_SendToInstance); + package.add("SendWebLink", &Perl_Client_SendWebLink); + package.add("SendZoneFlagInfo", &Perl_Client_SendZoneFlagInfo); + package.add("SetAAEXPModifier", (void(*)(Client*, uint32, double))&Perl_Client_SetAAEXPModifier); + package.add("SetAAEXPModifier", (void(*)(Client*, uint32, double, int16))&Perl_Client_SetAAEXPModifier); + package.add("SetAAPoints", &Perl_Client_SetAAPoints); + package.add("SetAATitle", (void(*)(Client*, std::string))&Perl_Client_SetAATitle); + package.add("SetAATitle", (void(*)(Client*, std::string, bool))&Perl_Client_SetAATitle); + package.add("SetAFK", &Perl_Client_SetAFK); + package.add("SetAccountFlag", &Perl_Client_SetAccountFlag); + package.add("SetAlternateCurrencyValue", &Perl_Client_SetAlternateCurrencyValue); + package.add("SetAnon", &Perl_Client_SetAnon); + package.add("SetBaseClass", &Perl_Client_SetBaseClass); + package.add("SetBaseGender", &Perl_Client_SetBaseGender); + package.add("SetBaseRace", &Perl_Client_SetBaseRace); + package.add("SetBecomeNPC", &Perl_Client_SetBecomeNPC); + package.add("SetBecomeNPCLevel", &Perl_Client_SetBecomeNPCLevel); + package.add("SetBindPoint", (void(*)(Client*))&Perl_Client_SetBindPoint); + package.add("SetBindPoint", (void(*)(Client*, int))&Perl_Client_SetBindPoint); + package.add("SetBindPoint", (void(*)(Client*, int, int))&Perl_Client_SetBindPoint); + package.add("SetBindPoint", (void(*)(Client*, int, int, float))&Perl_Client_SetBindPoint); + package.add("SetBindPoint", (void(*)(Client*, int, int, float, float))&Perl_Client_SetBindPoint); + package.add("SetBindPoint", (void(*)(Client*, int, int, float, float, float))&Perl_Client_SetBindPoint); + package.add("SetBindPoint", (void(*)(Client*, int, int, float, float, float, float))&Perl_Client_SetBindPoint); + package.add("SetBotCreationLimit", (void(*)(Client*, uint32))&Perl_Client_SetBotCreationLimit); + package.add("SetBotCreationLimit", (void(*)(Client*, uint32, uint8))&Perl_Client_SetBotCreationLimit); + package.add("SetBotRequiredLevel", (void(*)(Client*, int))&Perl_Client_SetBotRequiredLevel); + package.add("SetBotRequiredLevel", (void(*)(Client*, int, uint8))&Perl_Client_SetBotRequiredLevel); + package.add("SetBotSpawnLimit", (void(*)(Client*, int))&Perl_Client_SetBotSpawnLimit); + package.add("SetBotSpawnLimit", (void(*)(Client*, int, uint8))&Perl_Client_SetBotSpawnLimit); + package.add("SetClientMaxLevel", &Perl_Client_SetClientMaxLevel); + package.add("SetConsumption", &Perl_Client_SetConsumption); + package.add("SetCustomItemData", &Perl_Client_SetCustomItemData); + package.add("SetDeity", &Perl_Client_SetDeity); + package.add("SetDuelTarget", &Perl_Client_SetDuelTarget); + package.add("SetDueling", &Perl_Client_SetDueling); + package.add("SetEXP", (void(*)(Client*, uint64, uint64))&Perl_Client_SetEXP); + package.add("SetEXP", (void(*)(Client*, uint64, uint64, bool))&Perl_Client_SetEXP); + package.add("SetEXPModifier", (void(*)(Client*, uint32, double))&Perl_Client_SetEXPModifier); + package.add("SetEXPModifier", (void(*)(Client*, uint32, double, int16))&Perl_Client_SetEXPModifier); + package.add("SetEbonCrystals", &Perl_Client_SetEbonCrystals); + package.add("SetEndurance", &Perl_Client_SetEndurance); + package.add("SetEnvironmentDamageModifier", &Perl_Client_SetEnvironmentDamageModifier); + package.add("SetEXPEnabled", &Perl_Client_SetEXPEnabled); + package.add("SetFactionLevel", &Perl_Client_SetFactionLevel); + package.add("SetFactionLevel2", (void(*)(Client*, uint32, int32, uint8, uint8, uint8, int32))&Perl_Client_SetFactionLevel2); + package.add("SetFactionLevel2", (void(*)(Client*, uint32, int32, uint8, uint8, uint8, int32, uint8))&Perl_Client_SetFactionLevel2); + package.add("SetFeigned", &Perl_Client_SetFeigned); + package.add("SetGM", &Perl_Client_SetGM); + package.add("SetGMStatus", &Perl_Client_SetGMStatus); + package.add("SetHideMe", &Perl_Client_SetHideMe); + package.add("SetHorseId", &Perl_Client_SetHorseId); + package.add("SetHunger", &Perl_Client_SetHunger); + package.add("SetIPExemption", &Perl_Client_SetIPExemption); + package.add("SetInvulnerableEnvironmentDamage", &Perl_Client_SetInvulnerableEnvironmentDamage); + package.add("SetLanguageSkill", &Perl_Client_SetLanguageSkill); + package.add("SetMaterial", &Perl_Client_SetMaterial); + package.add("SetPEQZoneFlag", &Perl_Client_SetPEQZoneFlag); + package.add("SetPVP", &Perl_Client_SetPVP); + package.add("SetPrimaryWeaponOrnamentation", &Perl_Client_SetPrimaryWeaponOrnamentation); + package.add("SetRadiantCrystals", &Perl_Client_SetRadiantCrystals); + package.add("SetSecondaryWeaponOrnamentation", &Perl_Client_SetSecondaryWeaponOrnamentation); + package.add("SetSkill", &Perl_Client_SetSkill); + package.add("SetSkillPoints", &Perl_Client_SetSkillPoints); + package.add("SetSpellDuration", (void(*)(Client*, int))&Perl_Client_SetSpellDuration); + package.add("SetSpellDuration", (void(*)(Client*, int, int))&Perl_Client_SetSpellDuration); + package.add("SetSpellDuration", (void(*)(Client*, int, int, bool))&Perl_Client_SetSpellDuration); + package.add("SetSpellDuration", (void(*)(Client*, int, int, bool, bool))&Perl_Client_SetSpellDuration); + package.add("SetSpellDurationGroup", (void(*)(Client*, int))&Perl_Client_SetSpellDurationGroup); + package.add("SetSpellDurationGroup", (void(*)(Client*, int, int))&Perl_Client_SetSpellDurationGroup); + package.add("SetSpellDurationGroup", (void(*)(Client*, int, int, bool))&Perl_Client_SetSpellDurationGroup); + package.add("SetSpellDurationGroup", (void(*)(Client*, int, int, bool, bool))&Perl_Client_SetSpellDurationGroup); + package.add("SetSpellDurationRaid", (void(*)(Client*, int))&Perl_Client_SetSpellDurationRaid); + package.add("SetSpellDurationRaid", (void(*)(Client*, int, int))&Perl_Client_SetSpellDurationRaid); + package.add("SetSpellDurationRaid", (void(*)(Client*, int, int, bool))&Perl_Client_SetSpellDurationRaid); + package.add("SetSpellDurationRaid", (void(*)(Client*, int, int, bool, bool))&Perl_Client_SetSpellDurationRaid); + package.add("SetSpellDurationRaid", (void(*)(Client*, int, int, bool, bool, bool))&Perl_Client_SetSpellDurationRaid); + package.add("SetStartZone", (void(*)(Client*, uint32))&Perl_Client_SetStartZone); + package.add("SetStartZone", (void(*)(Client*, uint32, float, float, float))&Perl_Client_SetStartZone); + package.add("SetStartZone", (void(*)(Client*, uint32, float, float, float, float))&Perl_Client_SetStartZone); + package.add("SetStats", &Perl_Client_SetStats); + package.add("SetThirst", &Perl_Client_SetThirst); + package.add("SetTint", &Perl_Client_SetTint); + package.add("SetTitleSuffix", (void(*)(Client*, std::string))&Perl_Client_SetTitleSuffix); + package.add("SetTitleSuffix", (void(*)(Client*, std::string, bool))&Perl_Client_SetTitleSuffix); + package.add("SetZoneFlag", &Perl_Client_SetZoneFlag); + package.add("Signal", &Perl_Client_Signal); + package.add("SilentMessage", &Perl_Client_SilentMessage); + package.add("Sit", &Perl_Client_Sit); + package.add("SlotConvert2", &Perl_Client_SlotConvert2); + package.add("Stand", &Perl_Client_Stand); + package.add("SummonBaggedItems", &Perl_Client_SummonBaggedItems); + package.add("SummonItem", (void(*)(Client*, uint32))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16, bool))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32))&Perl_Client_SummonItem); + package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32, uint16))&Perl_Client_SummonItem); + package.add("TGB", &Perl_Client_TGB); + package.add("TakeMoneyFromPP", (bool(*)(Client*, uint64_t))&Perl_Client_TakeMoneyFromPP); + package.add("TakeMoneyFromPP", (bool(*)(Client*, uint64_t, bool))&Perl_Client_TakeMoneyFromPP); + package.add("TakePlatinum", (bool(*)(Client*, uint32))&Perl_Client_TakePlatinum); + package.add("TakePlatinum", (bool(*)(Client*, uint32, bool))&Perl_Client_TakePlatinum); + package.add("TeleportToPlayerByCharID", &Perl_Client_TeleportToPlayerByCharacterID); + package.add("TeleportToPlayerByName", &Perl_Client_TeleportToPlayerByName); + package.add("TeleportGroupToPlayerByCharID", &Perl_Client_TeleportGroupToPlayerByCharacterID); + package.add("TeleportGroupToPlayerByName", &Perl_Client_TeleportGroupToPlayerByName); + package.add("TeleportRaidToPlayerByCharID", &Perl_Client_TeleportRaidToPlayerByCharacterID); + package.add("TeleportRaidToPlayerByName", &Perl_Client_TeleportRaidToPlayerByName); + package.add("TaskSelector", &Perl_Client_TaskSelector); + package.add("TaskSelectorNoCooldown", &Perl_Client_TaskSelectorNoCooldown); + package.add("Thirsty", &Perl_Client_Thirsty); + package.add("TrainDiscBySpellID", &Perl_Client_TrainDiscBySpellID); + package.add("UnFreeze", &Perl_Client_UnFreeze); + package.add("Undye", &Perl_Client_Undye); + package.add("UnmemSpell", (void(*)(Client*, int))&Perl_Client_UnmemSpell); + package.add("UnmemSpell", (void(*)(Client*, int, bool))&Perl_Client_UnmemSpell); + package.add("UnmemSpellAll", (void(*)(Client*))&Perl_Client_UnmemSpellAll); + package.add("UnmemSpellAll", (void(*)(Client*, bool))&Perl_Client_UnmemSpellAll); + package.add("UnmemSpellBySpellID", &Perl_Client_UnmemSpellBySpellID); + package.add("UnscribeSpell", (void(*)(Client*, int))&Perl_Client_UnscribeSpell); + package.add("UnscribeSpell", (void(*)(Client*, int, bool))&Perl_Client_UnscribeSpell); + package.add("UnscribeSpellAll", (void(*)(Client*))&Perl_Client_UnscribeSpellAll); + package.add("UnscribeSpellAll", (void(*)(Client*, bool))&Perl_Client_UnscribeSpellAll); + package.add("UnscribeSpellBySpellID", (void(*)(Client*, uint16))&Perl_Client_UnscribeSpellBySpellID); + package.add("UnscribeSpellBySpellID", (void(*)(Client*, uint16, bool))&Perl_Client_UnscribeSpellBySpellID); + package.add("UntrainDisc", (void(*)(Client*, int))&Perl_Client_UntrainDisc); + package.add("UntrainDisc", (void(*)(Client*, int, bool))&Perl_Client_UntrainDisc); + package.add("UntrainDiscAll", (void(*)(Client*))&Perl_Client_UntrainDiscAll); + package.add("UntrainDiscAll", (void(*)(Client*, bool))&Perl_Client_UntrainDiscAll); + package.add("UntrainDiscBySpellID", (void(*)(Client*, uint16))&Perl_Client_UntrainDiscBySpellID); + package.add("UntrainDiscBySpellID", (void(*)(Client*, uint16, bool))&Perl_Client_UntrainDiscBySpellID); + package.add("UpdateAdmin", (void(*)(Client*))&Perl_Client_UpdateAdmin); + package.add("UpdateAdmin", (void(*)(Client*, bool))&Perl_Client_UpdateAdmin); + package.add("UpdateGroupAAs", &Perl_Client_UpdateGroupAAs); + package.add("UpdateLDoNPoints", &Perl_Client_UpdateLDoNPoints); + package.add("UpdateTaskActivity", (void(*)(Client*, int, int, int))&Perl_Client_UpdateTaskActivity); + package.add("UpdateTaskActivity", (void(*)(Client*, int, int, int, bool))&Perl_Client_UpdateTaskActivity); + package.add("UpdateWho", (void(*)(Client*))&Perl_Client_UpdateWho); + package.add("UpdateWho", (void(*)(Client*, uint8))&Perl_Client_UpdateWho); + package.add("UseDiscipline", &Perl_Client_UseDiscipline); + package.add("WorldKick", &Perl_Client_WorldKick); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_doors.cpp b/zone/perl_doors.cpp index 4325042d9..2a03a30ef 100644 --- a/zone/perl_doors.cpp +++ b/zone/perl_doors.cpp @@ -4,504 +4,219 @@ #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "doors.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_DOOR \ - do { \ - if (sv_derived_from(ST(0), "Doors")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Doors*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Doors"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Doors_GetDoorDBID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetDoorDBID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetDoorDBID(THIS)"); // @categories Doors - { - Doors *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetDoorDBID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Doors_GetDoorDBID(Doors* self) // @categories Doors +{ + return self->GetDoorDBID(); } -XS(XS_Doors_GetDoorID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetDoorID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetDoorID(THIS)"); // @categories Doors - { - Doors *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetDoorID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Doors_GetDoorID(Doors* self) // @categories Doors +{ + return self->GetDoorID(); } -XS(XS_Doors_GetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetID(THIS)"); // @categories Doors - { - Doors *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetEntityID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Doors_GetID(Doors* self) // @categories Doors +{ + return self->GetEntityID(); } -XS(XS_Doors_GetX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetX(THIS)"); // @categories Doors - { - Doors *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetPosition().x; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +float Perl_Doors_GetX(Doors* self) // @categories Doors +{ + return self->GetPosition().x; } -XS(XS_Doors_GetY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetY(THIS)"); // @categories Doors - { - Doors *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetPosition().y; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +float Perl_Doors_GetY(Doors* self) // @categories Doors +{ + return self->GetPosition().y; } -XS(XS_Doors_GetZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetZ) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetZ(THIS)"); // @categories Doors - { - Doors *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetPosition().z; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +float Perl_Doors_GetZ(Doors* self) // @categories Doors +{ + return self->GetPosition().z; } -XS(XS_Doors_GetHeading); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetHeading) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetHeading(THIS)"); // @categories Doors - { - Doors *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetPosition().w; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +float Perl_Doors_GetHeading(Doors* self) // @categories Doors +{ + return self->GetPosition().w; } -XS(XS_Doors_GetOpenType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetOpenType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetOpenType(THIS)"); // @categories Doors - { - Doors *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetOpenType(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Doors_GetOpenType(Doors* self) // @categories Doors +{ + return self->GetOpenType(); } -XS(XS_Doors_GetLockpick); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetLockpick) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetLockpick(THIS)"); // @categories Doors, Skills and Recipes - { - Doors *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetLockpick(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Doors_GetLockPick(Doors* self) // @categories Doors, Skills and Recipes +{ + return self->GetLockpick(); } -XS(XS_Doors_GetKeyItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetKeyItem) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetKeyItem(THIS)"); // @categories Doors - { - Doors *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetKeyItem(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Doors_GetKeyItem(Doors* self) // @categories Doors +{ + return self->GetKeyItem(); } -XS(XS_Doors_GetNoKeyring); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetNoKeyring) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::GetNoKeyring(THIS, uint8 type)"); // @categories Doors - { - Doors *THIS; - uint8 type = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_DOOR; - THIS->GetNoKeyring(); - } - XSRETURN_EMPTY; +uint8_t Perl_Doors_GetNoKeyring(Doors* self) // @categories Doors +{ + return self->GetNoKeyring(); } -XS(XS_Doors_GetIncline); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetIncline) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetIncline(THIS)"); // @categories Doors - { - Doors *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetIncline(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_Doors_GetIncline(Doors* self) // @categories Doors +{ + return self->GetIncline(); } -XS(XS_Doors_GetSize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetSize) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetSize(THIS)"); // @categories Doors - { - Doors *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetSize(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Doors_GetSize(Doors* self) // @categories Doors +{ + return self->GetSize(); } - -XS(XS_Doors_SetOpenType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetOpenType) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetOpenType(THIS, uint32 open_type)"); // @categories Doors - { - Doors *THIS; - uint32 type = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_DOOR; - THIS->SetOpenType(type); - } - XSRETURN_EMPTY; +void Perl_Doors_SetOpenType(Doors* self, uint32_t open_type) // @categories Doors +{ + self->SetOpenType(open_type); } -XS(XS_Doors_SetLockpick); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetLockpick) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetLockpick(THIS, uint32 lockpick_type)"); // @categories Doors - { - Doors *THIS; - uint32 type = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_DOOR; - THIS->SetLockpick(type); - } - XSRETURN_EMPTY; +void Perl_Doors_SetLockPick(Doors* self, uint32_t lockpick_type) // @categories Doors +{ + self->SetLockpick(lockpick_type); } -XS(XS_Doors_SetKeyItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetKeyItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetKeyItem(THIS, uint32 key_item_id)"); // @categories Doors - { - Doors *THIS; - uint32 type = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_DOOR; - THIS->SetKeyItem(type); - } - XSRETURN_EMPTY; +void Perl_Doors_SetKeyItem(Doors* self, uint32_t key_item_id) // @categories Doors +{ + self->SetKeyItem(key_item_id); } -XS(XS_Doors_SetNoKeyring); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetNoKeyring) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetNoKeyring(THIS, uint8 no_key_ring)"); // @categories Doors - { - Doors *THIS; - uint8 type = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_DOOR; - THIS->SetNoKeyring(type); - } - XSRETURN_EMPTY; +void Perl_Doors_SetNoKeyring(Doors* self, uint8_t no_key_ring) // @categories Doors +{ + self->SetNoKeyring(no_key_ring); } -XS(XS_Doors_SetIncline); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetIncline) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetIncline(THIS, uint32 incline)"); // @categories Doors - { - Doors *THIS; - uint32 type = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_DOOR; - THIS->SetIncline(type); - } - XSRETURN_EMPTY; +void Perl_Doors_SetIncline(Doors* self, uint32_t incline) // @categories Doors +{ + self->SetIncline(incline); } -XS(XS_Doors_SetSize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetSize) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetSize(THIS, uint32 size)"); // @categories Doors - { - Doors *THIS; - uint32 type = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_DOOR; - THIS->SetSize(type); - } - XSRETURN_EMPTY; +void Perl_Doors_SetSize(Doors* self, uint32_t size) // @categories Doors +{ + self->SetSize(size); } -XS(XS_Doors_SetLocation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetLocation) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Doors::SetLocation(THIS, float x, float y, float z)"); // @categories Doors - { - Doors *THIS; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - VALIDATE_THIS_IS_DOOR; - THIS->SetLocation(x, y, z); - } - XSRETURN_EMPTY; +void Perl_Doors_SetLocation(Doors* self, float x, float y, float z) // @categories Doors +{ + self->SetLocation(x, y, z); } -XS(XS_Doors_SetX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetX) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetX(THIS, float x)"); // @categories Doors - { - Doors *THIS; - float x = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_DOOR; - auto position = THIS->GetPosition(); - position.x = x; - THIS->SetPosition(position); - } - XSRETURN_EMPTY; +void Perl_Doors_SetX(Doors* self, float x) // @categories Doors +{ + auto position = self->GetPosition(); + position.x = x; + self->SetPosition(position); } -XS(XS_Doors_SetY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetY) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetY(THIS, float y)"); // @categories Doors - { - Doors *THIS; - float y = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_DOOR; - auto position = THIS->GetPosition(); - position.y = y; - THIS->SetPosition(position); - } - XSRETURN_EMPTY; +void Perl_Doors_SetY(Doors* self, float y) // @categories Doors +{ + auto position = self->GetPosition(); + position.y = y; + self->SetPosition(position); } -XS(XS_Doors_SetZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetZ) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetZ(THIS, float z)"); // @categories Doors - { - Doors *THIS; - float z = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_DOOR; - auto position = THIS->GetPosition(); - position.z = z; - THIS->SetPosition(position); - } - XSRETURN_EMPTY; +void Perl_Doors_SetZ(Doors* self, float z) // @categories Doors +{ + auto position = self->GetPosition(); + position.z = z; + self->SetPosition(position); } -XS(XS_Doors_SetHeading); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetHeading) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Doors::SetHeading(THIS, float heading)"); // @categories Doors - { - Doors *THIS; - float heading = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_DOOR; - auto position = THIS->GetPosition(); - position.w = heading; - THIS->SetPosition(position); - } - XSRETURN_EMPTY; +void Perl_Doors_SetHeading(Doors* self, float heading) // @categories Doors +{ + auto position = self->GetPosition(); + position.w = heading; + self->SetPosition(position); } -XS(XS_Doors_SetModelName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_SetModelName) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Doors::SetModelName(THIS, string name)"); // @categories Doors - { - Doors *THIS; - char *name = nullptr; - VALIDATE_THIS_IS_DOOR; - if (items > 1) { name = (char *) SvPV_nolen(ST(1)); } - - THIS->SetDoorName(name); - } - XSRETURN_EMPTY; -} -XS(XS_Doors_GetModelName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_GetModelName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::GetModelName(THIS)"); // @categories Doors - { - Doors *THIS; - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_DOOR; - RETVAL = THIS->GetDoorName(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +void Perl_Doors_SetModelName(Doors* self, const char* name) // @categories Doors +{ + self->SetDoorName(name); } -XS(XS_Doors_CreateDatabaseEntry); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Doors_CreateDatabaseEntry) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Doors::InsertDoor(THIS)"); // @categories Doors - { - Doors *THIS; - VALIDATE_THIS_IS_DOOR; - THIS->CreateDatabaseEntry(); - } - XSRETURN_EMPTY; +std::string Perl_Doors_GetModelName(Doors* self) // @categories Doors +{ + return self->GetDoorName(); } - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_Doors); /* prototype to pass -Wmissing-prototypes */ -XS(boot_Doors) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "CreateDatabaseEntry"), XS_Doors_CreateDatabaseEntry, file, "$"); - newXSproto(strcpy(buf, "GetDoorDBID"), XS_Doors_GetDoorDBID, file, "$"); - newXSproto(strcpy(buf, "GetDoorID"), XS_Doors_GetDoorID, file, "$"); - newXSproto(strcpy(buf, "GetHeading"), XS_Doors_GetHeading, file, "$"); - newXSproto(strcpy(buf, "GetID"), XS_Doors_GetID, file, "$"); - newXSproto(strcpy(buf, "GetIncline"), XS_Doors_GetIncline, file, "$"); - newXSproto(strcpy(buf, "GetKeyItem"), XS_Doors_GetKeyItem, file, "$"); - newXSproto(strcpy(buf, "GetLockPick"), XS_Doors_GetLockpick, file, "$"); - newXSproto(strcpy(buf, "GetModelName"), XS_Doors_GetModelName, file, "$"); - newXSproto(strcpy(buf, "GetNoKeyring"), XS_Doors_GetNoKeyring, file, "$"); - newXSproto(strcpy(buf, "GetOpenType"), XS_Doors_GetOpenType, file, "$"); - newXSproto(strcpy(buf, "GetSize"), XS_Doors_GetSize, file, "$"); - newXSproto(strcpy(buf, "GetX"), XS_Doors_GetX, file, "$"); - newXSproto(strcpy(buf, "GetY"), XS_Doors_GetY, file, "$"); - newXSproto(strcpy(buf, "GetZ"), XS_Doors_GetZ, file, "$"); - newXSproto(strcpy(buf, "SetHeading"), XS_Doors_SetHeading, file, "$$"); - newXSproto(strcpy(buf, "SetIncline"), XS_Doors_SetIncline, file, "$$"); - newXSproto(strcpy(buf, "SetKeyItem"), XS_Doors_SetKeyItem, file, "$$"); - newXSproto(strcpy(buf, "SetLocation"), XS_Doors_SetLocation, file, "$$$$"); - newXSproto(strcpy(buf, "SetLockPick"), XS_Doors_SetLockpick, file, "$$"); - newXSproto(strcpy(buf, "SetModelName"), XS_Doors_SetModelName, file, "$$"); - newXSproto(strcpy(buf, "SetNoKeyring"), XS_Doors_SetNoKeyring, file, "$$"); - newXSproto(strcpy(buf, "SetOpenType"), XS_Doors_SetOpenType, file, "$$"); - newXSproto(strcpy(buf, "SetSize"), XS_Doors_SetSize, file, "$$"); - newXSproto(strcpy(buf, "SetX"), XS_Doors_SetX, file, "$$"); - newXSproto(strcpy(buf, "SetY"), XS_Doors_SetY, file, "$$"); - newXSproto(strcpy(buf, "SetZ"), XS_Doors_SetZ, file, "$$"); - XSRETURN_YES; +void Perl_Doors_CreateDatabaseEntry(Doors* self) // @categories Doors +{ + self->CreateDatabaseEntry(); } + +void Perl_Doors_ForceClose(Doors* self, Mob* sender) +{ + self->ForceClose(sender); +} + +void Perl_Doors_ForceClose(Doors* self, Mob* sender, bool alt_mode) +{ + self->ForceClose(sender, alt_mode); +} + +void Perl_Doors_ForceOpen(Doors* self, Mob* sender) +{ + self->ForceOpen(sender); +} + +void Perl_Doors_ForceOpen(Doors* self, Mob* sender, bool alt_mode) +{ + self->ForceOpen(sender, alt_mode); +} + +bool Perl_Doors_GetDisableTimer(Doors* self) +{ + return self->GetDisableTimer(); +} + +void Perl_Doors_SetDisableTimer(Doors* self, bool disable_timer) +{ + self->SetDisableTimer(disable_timer); +} + +void perl_register_doors() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Doors"); + package.add("CreateDatabaseEntry", &Perl_Doors_CreateDatabaseEntry); + package.add("ForceClose", (void(*)(Doors*, Mob*))&Perl_Doors_ForceClose); + package.add("ForceClose", (void(*)(Doors*, Mob*, bool))&Perl_Doors_ForceClose); + package.add("ForceOpen", (void(*)(Doors*, Mob*))&Perl_Doors_ForceOpen); + package.add("ForceOpen", (void(*)(Doors*, Mob*, bool))&Perl_Doors_ForceOpen); + package.add("GetDisableTimer", &Perl_Doors_GetDisableTimer); + package.add("GetDoorDBID", &Perl_Doors_GetDoorDBID); + package.add("GetDoorID", &Perl_Doors_GetDoorID); + package.add("GetHeading", &Perl_Doors_GetHeading); + package.add("GetID", &Perl_Doors_GetID); + package.add("GetIncline", &Perl_Doors_GetIncline); + package.add("GetKeyItem", &Perl_Doors_GetKeyItem); + package.add("GetLockPick", &Perl_Doors_GetLockPick); + package.add("GetModelName", &Perl_Doors_GetModelName); + package.add("GetNoKeyring", &Perl_Doors_GetNoKeyring); + package.add("GetOpenType", &Perl_Doors_GetOpenType); + package.add("GetSize", &Perl_Doors_GetSize); + package.add("GetX", &Perl_Doors_GetX); + package.add("GetY", &Perl_Doors_GetY); + package.add("GetZ", &Perl_Doors_GetZ); + package.add("SetDisableTimer", &Perl_Doors_SetDisableTimer); + package.add("SetHeading", &Perl_Doors_SetHeading); + package.add("SetIncline", &Perl_Doors_SetIncline); + package.add("SetKeyItem", &Perl_Doors_SetKeyItem); + package.add("SetLocation", &Perl_Doors_SetLocation); + package.add("SetLockPick", &Perl_Doors_SetLockPick); + package.add("SetModelName", &Perl_Doors_SetModelName); + package.add("SetNoKeyring", &Perl_Doors_SetNoKeyring); + package.add("SetOpenType", &Perl_Doors_SetOpenType); + package.add("SetSize", &Perl_Doors_SetSize); + package.add("SetX", &Perl_Doors_SetX); + package.add("SetY", &Perl_Doors_SetY); + package.add("SetZ", &Perl_Doors_SetZ); +} + #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_entity.cpp b/zone/perl_entity.cpp index 9a73154ab..83f7fb9e7 100644 --- a/zone/perl_entity.cpp +++ b/zone/perl_entity.cpp @@ -2,1681 +2,721 @@ #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "entity.h" +#include "../common/global_define.h" +#include "../common/rulesys.h" +#include "../common/say_link.h" +#include "../common/strings.h" +#include -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_ENTITY \ - do { \ - if (sv_derived_from(ST(0), "EntityList")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(EntityList*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type EntityList"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_EntityList_GetMobID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetMobID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetMobID(THIS, id)"); // @categories Script Utility - { - EntityList *THIS; - Mob *RETVAL; - uint16 id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetMobID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); +Mob* Perl_EntityList_GetMobID(EntityList* self, uint16_t mob_id) // @categories Script Utility +{ + return self->GetMobID(mob_id); } -XS(XS_EntityList_GetMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetMob) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetMob(THIS, name)"); - { - EntityList *THIS; - Mob *RETVAL; - char *name = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetMob(name); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); +Mob* Perl_EntityList_GetMob(EntityList* self, const char* name) +{ + return self->GetMob(name); } -XS(XS_EntityList_GetMobByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetMobByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetMobByID(THIS, id)"); // @categories Script Utility - { - EntityList *THIS; - Mob *RETVAL; - uint16 id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetMob(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); +Mob* Perl_EntityList_GetMobByID(EntityList* self, uint16_t mob_id) // @categories Script Utility +{ + return self->GetMob(mob_id); } -XS(XS_EntityList_GetMobByNpcTypeID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetMobByNpcTypeID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetMobByNpcTypeID(THIS, get_id)"); // @categories Script Utility - { - EntityList *THIS; - Mob *RETVAL; - uint32 get_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetMobByNpcTypeID(get_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); +Mob* Perl_EntityList_GetMobByNpcTypeID(EntityList* self, uint32_t npc_type_id) // @categories Script Utility +{ + return self->GetMobByNpcTypeID(npc_type_id); } -XS(XS_EntityList_IsMobSpawnedByNpcTypeID); /* prototype pass -Wmissing-prototypes */ -XS(XS_EntityList_IsMobSpawnedByNpcTypeID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::IsMobSpawnedByNpcTypeID(THIS, get_id)"); // @categories Script Utility - { - EntityList *THIS; - bool RETVAL; - uint32 get_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->IsMobSpawnedByNpcTypeID(get_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_IsMobSpawnedByNpcTypeID(EntityList* self, uint32_t npc_type_id) // @categories Script Utility +{ + return self->IsMobSpawnedByNpcTypeID(npc_type_id); } -XS(XS_EntityList_GetNPCByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetNPCByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetNPCByID(THIS, id)"); // @categories Script Utility - { - EntityList *THIS; - NPC *RETVAL; - uint16 id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetNPCByID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "NPC", (void *) RETVAL); - } - XSRETURN(1); +NPC* Perl_EntityList_GetNPCByID(EntityList* self, uint16_t id) // @categories Script Utility +{ + return self->GetNPCByID(id); } -XS(XS_EntityList_GetNPCByNPCTypeID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetNPCByNPCTypeID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetNPCByNPCTypeID(THIS, npc_id)"); // @categories Script Utility - { - EntityList *THIS; - NPC *RETVAL; - uint32 npc_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetNPCByNPCTypeID(npc_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "NPC", (void *) RETVAL); - } - XSRETURN(1); +NPC* Perl_EntityList_GetNPCByNPCTypeID(EntityList* self, uint32_t npc_id) // @categories Script Utility +{ + return self->GetNPCByNPCTypeID(npc_id); } -XS(XS_EntityList_GetNPCBySpawnID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetNPCBySpawnID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetNPCBySpawnID(THIS, spawn_id)"); // @categories Script Utility, Spawns - { - EntityList *THIS; - NPC *RETVAL; - uint32 spawn_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetNPCBySpawnID(spawn_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "NPC", (void *) RETVAL); - } - XSRETURN(1); +NPC* Perl_EntityList_GetNPCBySpawnID(EntityList* self, uint32_t spawn_id) // @categories Script Utility, Spawns +{ + return self->GetNPCBySpawnID(spawn_id); } -XS(XS_EntityList_GetClientByName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetClientByName) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetClientByName(THIS, name)"); // @categories Account and Character, Script Utility - { - EntityList *THIS; - Client *RETVAL; - char *name = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetClientByName(name); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +Client* Perl_EntityList_GetClientByName(EntityList* self, const char* name) // @categories Account and Character, Script Utility +{ + return self->GetClientByName(name); } -XS(XS_EntityList_GetClientByAccID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetClientByAccID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetClientByAccID(THIS, uint32 account_id)"); // @categories Account and Character, Script Utility - { - EntityList *THIS; - Client *RETVAL; - uint32 accid = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetClientByAccID(accid); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +Client* Perl_EntityList_GetClientByAccID(EntityList* self, uint32_t account_id) // @categories Account and Character, Script Utility +{ + return self->GetClientByAccID(account_id); } -XS(XS_EntityList_GetClientByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetClientByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetClientByID(THIS, uint16 client_id)"); // @categories Account and Character, Script Utility - { - EntityList *THIS; - Client *RETVAL; - uint16 id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetClientByID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +Client* Perl_EntityList_GetClientByID(EntityList* self, uint16_t client_id) // @categories Account and Character, Script Utility +{ + return self->GetClientByID(client_id); } -XS(XS_EntityList_GetClientByCharID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetClientByCharID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetClientByCharID(THIS, uint32 character_id)"); // @categories Account and Character, Script Utility - { - EntityList *THIS; - Client *RETVAL; - uint32 iCharID = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetClientByCharID(iCharID); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +Client* Perl_EntityList_GetClientByCharID(EntityList* self, uint32_t character_id) // @categories Account and Character, Script Utility +{ + return self->GetClientByCharID(character_id); } -XS(XS_EntityList_GetClientByWID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetClientByWID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetClientByWID(THIS, uint32 wid)"); // @categories Account and Character, Script Utility - { - EntityList *THIS; - Client *RETVAL; - uint32 iWID = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetClientByWID(iWID); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +Client* Perl_EntityList_GetClientByWID(EntityList* self, uint32_t wid) // @categories Account and Character, Script Utility +{ + return self->GetClientByWID(wid); } -XS(XS_EntityList_GetObjectByDBID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetObjectByDBID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetObjectByDBID(THIS, uint32 database_id)"); // @categories Script Utility, Objects - { - EntityList *THIS; - Object *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetObjectByDBID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Object", (void *) RETVAL); - } - XSRETURN(1); +Object* Perl_EntityList_GetObjectByDBID(EntityList* self, uint32_t database_id) // @categories Script Utility, Objects +{ + return self->GetObjectByDBID(database_id); } -XS(XS_EntityList_GetObjectByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetObjectByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetObjectByID(THIS, uint32 entity_id)"); // @categories Script Utility, Objects - { - EntityList *THIS; - Object *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetObjectByID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Object", (void *) RETVAL); - } - XSRETURN(1); +Object* Perl_EntityList_GetObjectByID(EntityList* self, uint32_t entity_id) // @categories Script Utility, Objects +{ + return self->GetObjectByID(entity_id); } -XS(XS_EntityList_GetDoorsByDBID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetDoorsByDBID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetDoorsByDBID(THIS, uint32 database_id)"); // @categories Script Utility, Doors - { - EntityList *THIS; - Doors *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetDoorsByDBID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Doors", (void *) RETVAL); - } - XSRETURN(1); +Doors* Perl_EntityList_GetDoorsByDBID(EntityList* self, uint32_t database_id) // @categories Script Utility, Doors +{ + return self->GetDoorsByDBID(database_id); } -XS(XS_EntityList_GetDoorsByDoorID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetDoorsByDoorID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetDoorsByDoorID(THIS, uint32 door_id)"); // @categories Script Utility, Doors - { - EntityList *THIS; - Doors *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetDoorsByDoorID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Doors", (void *) RETVAL); - } - XSRETURN(1); +Doors* Perl_EntityList_GetDoorsByDoorID(EntityList* self, uint32_t door_id) // @categories Script Utility, Doors +{ + return self->GetDoorsByDoorID(door_id); } -XS(XS_EntityList_GetDoorsByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetDoorsByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetDoorsByID(THIS, uint32 entity_id)"); // @categories Script Utility, Doors - { - EntityList *THIS; - Doors *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetDoorsByID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Doors", (void *) RETVAL); - } - XSRETURN(1); +Doors* Perl_EntityList_GetDoorsByID(EntityList* self, uint32_t entity_id) // @categories Script Utility, Doors +{ + return self->GetDoorsByID(entity_id); } -XS(XS_EntityList_FindDoor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_FindDoor) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::FindDoor(THIS, uint32 door_id)"); // @categories Script Utility, Doors - { - EntityList *THIS; - Doors *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->FindDoor(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Doors", (void *) RETVAL); - } - XSRETURN(1); +Doors* Perl_EntityList_FindDoor(EntityList* self, uint32_t door_id) // @categories Script Utility, Doors +{ + return self->FindDoor(door_id); } -XS(XS_EntityList_GetGroupByMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetGroupByMob) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetGroupByMob(THIS, Mob* mob)"); // @categories Account and Character, Script Utility, Group - { - EntityList *THIS; - Group *RETVAL; - Mob *mob; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - mob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "mob is not of type Mob"); - if (mob == nullptr) - Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); - - RETVAL = THIS->GetGroupByMob(mob); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Group", (void *) RETVAL); - } - XSRETURN(1); +Group* Perl_EntityList_GetGroupByMob(EntityList* self, Mob* mob) // @categories Account and Character, Script Utility, Group +{ + return self->GetGroupByMob(mob); } -XS(XS_EntityList_GetGroupByClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetGroupByClient) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetGroupByClient(THIS, Client* client)"); // @categories Account and Character, Script Utility, Group - { - EntityList *THIS; - Group *RETVAL; - Client *client; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - client = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "client is not of type Client"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - - RETVAL = THIS->GetGroupByClient(client); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Group", (void *) RETVAL); - } - XSRETURN(1); +Group* Perl_EntityList_GetGroupByClient(EntityList* self, Client* client) // @categories Account and Character, Script Utility, Group +{ + return self->GetGroupByClient(client); } -XS(XS_EntityList_GetGroupByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetGroupByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetGroupByID(THIS, id)"); // @categories Account and Character, Script Utility, Group - { - EntityList *THIS; - Group *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetGroupByID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Group", (void *) RETVAL); - } - XSRETURN(1); +Group* Perl_EntityList_GetGroupByID(EntityList* self, uint32_t id) // @categories Account and Character, Script Utility, Group +{ + return self->GetGroupByID(id); } -XS(XS_EntityList_GetGroupByLeaderName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetGroupByLeaderName) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetGroupByLeaderName(THIS, leader)"); // @categories Account and Character, Script Utility, Group - { - EntityList *THIS; - Group *RETVAL; - char *leader = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetGroupByLeaderName(leader); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Group", (void *) RETVAL); - } - XSRETURN(1); +Group* Perl_EntityList_GetGroupByLeaderName(EntityList* self, const char* leader_name) // @categories Account and Character, Script Utility, Group +{ + return self->GetGroupByLeaderName(leader_name); } -XS(XS_EntityList_GetRaidByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetRaidByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetRaidByID(THIS, id)"); // @categories Script Utility, Raid - { - EntityList *THIS; - Raid *RETVAL; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetRaidByID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Raid", (void *) RETVAL); - } - XSRETURN(1); +Raid* Perl_EntityList_GetRaidByID(EntityList* self, uint32_t id) // @categories Script Utility, Raid +{ + return self->GetRaidByID(id); } -XS(XS_EntityList_GetRaidByClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetRaidByClient) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetRaidByClient(THIS, client)"); // @categories Account and Character, Script Utility, Raid - { - EntityList *THIS; - Raid *RETVAL; - Client *client; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - client = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "client is not of type Client"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - - RETVAL = THIS->GetRaidByClient(client); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Raid", (void *) RETVAL); - } - XSRETURN(1); +Raid* Perl_EntityList_GetRaidByClient(EntityList* self, Client* client) // @categories Account and Character, Script Utility, Raid +{ + return self->GetRaidByClient(client); } -XS(XS_EntityList_GetCorpseByOwner); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetCorpseByOwner) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetCorpseByOwner(THIS, client)"); // @categories Script Utility, Corpse - { - EntityList *THIS; - Corpse *RETVAL; - Client *client; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - client = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "client is not of type Client"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - - RETVAL = THIS->GetCorpseByOwner(client); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Corpse", (void *) RETVAL); - } - XSRETURN(1); +Corpse* Perl_EntityList_GetCorpseByOwner(EntityList* self, Client* client) // @categories Script Utility, Corpse +{ + return self->GetCorpseByOwner(client); } -XS(XS_EntityList_GetCorpseByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetCorpseByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetCorpseByID(THIS, id)"); // @categories Script Utility, Corpse - { - EntityList *THIS; - Corpse *RETVAL; - uint16 id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetCorpseByID(id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Corpse", (void *) RETVAL); - } - XSRETURN(1); +Corpse* Perl_EntityList_GetCorpseByID(EntityList* self, uint16_t id) // @categories Script Utility, Corpse +{ + return self->GetCorpseByID(id); } -XS(XS_EntityList_GetCorpseByName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetCorpseByName) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetCorpseByName(THIS, name)"); // @categories Script Utility, Corpse - { - EntityList *THIS; - Corpse *RETVAL; - char *name = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetCorpseByName(name); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Corpse", (void *) RETVAL); - } - XSRETURN(1); +Corpse* Perl_EntityList_GetCorpseByName(EntityList* self, const char* name) // @categories Script Utility, Corpse +{ + return self->GetCorpseByName(name); } -XS(XS_EntityList_ClearClientPetitionQueue); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_ClearClientPetitionQueue) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::ClearClientPetitionQueue(THIS)"); // @categories Script Utility - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->ClearClientPetitionQueue(); - } - XSRETURN_EMPTY; +void Perl_EntityList_ClearClientPetitionQueue(EntityList* self) // @categories Script Utility +{ + self->ClearClientPetitionQueue(); } -XS(XS_EntityList_CanAddHateForMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_CanAddHateForMob) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::CanAddHateForMob(THIS, Mob* target)"); // @categories Script Utility, Hate and Aggro - { - EntityList *THIS; - bool RETVAL; - Mob *p; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - p = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "p is not of type Mob"); - if (p == nullptr) - Perl_croak(aTHX_ "p is nullptr, avoiding crash."); - - RETVAL = THIS->CanAddHateForMob(p); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_CanAddHateForMob(EntityList* self, Mob* target) // @categories Script Utility, Hate and Aggro +{ + return self->CanAddHateForMob(target); } -XS(XS_EntityList_Clear); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_Clear) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::Clear(THIS)"); // @categories Script Utility - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->Clear(); - } - XSRETURN_EMPTY; +void Perl_EntityList_Clear(EntityList* self) // @categories Script Utility +{ + self->Clear(); } -XS(XS_EntityList_RemoveMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveMob) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveMob(THIS, delete_id)"); // @categories Script Utility - { - EntityList *THIS; - bool RETVAL; - uint16 delete_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveMob(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveMob(EntityList* self, uint16_t delete_id) // @categories Script Utility +{ + return self->RemoveMob(delete_id); } -XS(XS_EntityList_RemoveClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveClient) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveClient(THIS, delete_id)"); // @categories Account and Character, Script Utility - { - EntityList *THIS; - bool RETVAL; - uint16 delete_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveClient(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveClient(EntityList* self, uint16_t delete_id) // @categories Account and Character, Script Utility +{ + return self->RemoveClient(delete_id); } -XS(XS_EntityList_RemoveNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveNPC) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveNPC(THIS, delete_id)"); // @categories Script Utility - { - EntityList *THIS; - bool RETVAL; - uint16 delete_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveNPC(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveNPC(EntityList* self, uint16_t delete_id) // @categories Script Utility +{ + return self->RemoveNPC(delete_id); } -XS(XS_EntityList_RemoveGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveGroup) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveGroup(THIS, delete_id)"); // @categories Script Utility, Group - { - EntityList *THIS; - bool RETVAL; - uint32 delete_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveGroup(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveGroup(EntityList* self, uint32_t delete_id) // @categories Script Utility, Group +{ + return self->RemoveGroup(delete_id); } -XS(XS_EntityList_RemoveCorpse); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveCorpse) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveCorpse(THIS, delete_id)"); // @categories Corpse - { - EntityList *THIS; - bool RETVAL; - uint16 delete_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveCorpse(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveCorpse(EntityList* self, uint16_t delete_id) // @categories Corpse +{ + return self->RemoveCorpse(delete_id); } -XS(XS_EntityList_RemoveDoor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveDoor) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveDoor(THIS, delete_id)"); // @categories Doors - { - EntityList *THIS; - bool RETVAL; - uint16 delete_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveDoor(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveDoor(EntityList* self, uint16_t delete_id) // @categories Doors +{ + return self->RemoveDoor(delete_id); } -XS(XS_EntityList_RemoveTrap); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveTrap) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveTrap(THIS, delete_id)"); // @categories Script Utility - { - EntityList *THIS; - bool RETVAL; - uint16 delete_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveTrap(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveTrap(EntityList* self, uint16_t delete_id) // @categories Script Utility +{ + return self->RemoveTrap(delete_id); } -XS(XS_EntityList_RemoveObject); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveObject) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveObject(THIS, delete_id)"); // @categories Script Utility, Objects - { - EntityList *THIS; - bool RETVAL; - uint16 delete_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->RemoveObject(delete_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_EntityList_RemoveObject(EntityList* self, uint16_t delete_id) // @categories Script Utility, Objects +{ + return self->RemoveObject(delete_id); } -XS(XS_EntityList_RemoveAllMobs); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllMobs) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllMobs(THIS)"); // @categories Script Utility - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllMobs(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllMobs(EntityList* self) // @categories Script Utility +{ + self->RemoveAllMobs(); } -XS(XS_EntityList_RemoveAllClients); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllClients) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllClients(THIS)"); // @categories Script Utility - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllClients(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllClients(EntityList* self) // @categories Script Utility +{ + self->RemoveAllClients(); } -XS(XS_EntityList_RemoveAllNPCs); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllNPCs) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllNPCs(THIS)"); // @categories Script Utility - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllNPCs(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllNPCs(EntityList* self) // @categories Script Utility +{ + self->RemoveAllNPCs(); } -XS(XS_EntityList_RemoveAllGroups); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllGroups) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllGroups(THIS)"); // @categories Group - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllGroups(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllGroups(EntityList* self) // @categories Group +{ + self->RemoveAllGroups(); } -XS(XS_EntityList_RemoveAllCorpses); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllCorpses) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllCorpses(THIS)"); // @categories Corpse - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllCorpses(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllCorpses(EntityList* self) // @categories Corpse +{ + self->RemoveAllCorpses(); } -XS(XS_EntityList_RemoveAllDoors); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllDoors) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllDoors(THIS)"); // @categories Doors - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllDoors(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllDoors(EntityList* self) // @categories Doors +{ + self->RemoveAllDoors(); } -XS(XS_EntityList_RemoveAllTraps); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllTraps) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllTraps(THIS)"); // @categories Script Utility - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllTraps(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllTraps(EntityList* self) // @categories Script Utility +{ + self->RemoveAllTraps(); } -XS(XS_EntityList_RemoveAllObjects); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveAllObjects) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::RemoveAllObjects(THIS)"); // @categories Objects - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveAllObjects(); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveAllObjects(EntityList* self) // @categories Objects +{ + self->RemoveAllObjects(); } -XS(XS_EntityList_Message); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_Message) { - dXSARGS; - if (items < 4) - Perl_croak(aTHX_ "Usage: EntityList::Message(THIS, uint32 guild_id, uint32 emote_color_type, string message)"); // @categories Script Utility - { - EntityList *THIS; - uint32 to_guilddbid = (uint32) SvUV(ST(1)); - uint32 type = (uint32) SvUV(ST(2)); - char *message = (char *) SvPV_nolen(ST(3)); - VALIDATE_THIS_IS_ENTITY; - THIS->Message(to_guilddbid, type, message); - } - XSRETURN_EMPTY; +void Perl_EntityList_Message(EntityList* self, uint32 guild_id, uint32 color_type, const char* message) // @categories Script Utility +{ + self->Message(guild_id, color_type, message); } -XS(XS_EntityList_MessageStatus); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_MessageStatus) { - dXSARGS; - if (items < 5) - Perl_croak(aTHX_ "Usage: EntityList::MessageStatus(THIS, uint32 guild_id, uint32 emote_color_type, string message)"); // @categories Script Utility - { - EntityList *THIS; - uint32 to_guilddbid = (uint32) SvUV(ST(1)); - int to_minstatus = (int) SvIV(ST(2)); - uint32 type = (uint32) SvUV(ST(3)); - char *message = (char *) SvPV_nolen(ST(4)); - VALIDATE_THIS_IS_ENTITY; - THIS->MessageStatus( - to_guilddbid, - to_minstatus, - type, - message - ); - } - XSRETURN_EMPTY; +void Perl_EntityList_MessageStatus(EntityList* self, uint32 guild_id, int to_minstatus, uint32 color_type, const char* message) // @categories Script Utility +{ + self->MessageStatus(guild_id, to_minstatus, color_type, message); } -XS(XS_EntityList_MessageClose); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_MessageClose) { - dXSARGS; - if (items < 6) - Perl_croak(aTHX_ "Usage: EntityList::MessageClose(THIS, Mob* sender, bool skip_sender, float distance, uint32 emote_color_type, string message)"); +void Perl_EntityList_MessageClose(EntityList* self, Mob* sender, bool skip_sender, float distance, uint32 color_type, const char* message) +{ + if (RuleB(Chat, AutoInjectSaylinksToClientMessage)) { - EntityList *THIS; - Mob *sender; - bool skipsender = (bool) SvTRUE(ST(2)); - float dist = (float) SvNV(ST(3)); - uint32 type = (uint32) SvUV(ST(4)); - char *message = (char *) SvPV_nolen(ST(5)); - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - sender = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "sender is not of type Mob"); - if (sender == nullptr) - Perl_croak(aTHX_ "sender is nullptr, avoiding crash."); - - THIS->MessageClose(sender, skipsender, dist, type, message); + std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(message); + self->MessageClose(sender, skip_sender, distance, color_type, new_message.c_str()); } - XSRETURN_EMPTY; -} - -XS(XS_EntityList_RemoveFromTargets); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveFromTargets) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveFromTargets(THIS, Mob* target)"); // @categories Script Utility + else { - EntityList *THIS; - Mob *mob; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - mob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "mob is not of type Mob"); - if (mob == nullptr) - Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); - - THIS->RemoveFromTargets(mob); + self->MessageClose(sender, skip_sender, distance, color_type, message); } - XSRETURN_EMPTY; } -XS(XS_EntityList_ReplaceWithTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_ReplaceWithTarget) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EntityList::ReplaceWithTarget(THIS, Mob* old_mob, Mob* new_target)"); // @categories Script Utility - { - EntityList *THIS; - Mob *pOldMob; - Mob *pNewTarget; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - pOldMob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "pOldMob is not of type Mob"); - if (pOldMob == nullptr) - Perl_croak(aTHX_ "pOldMob is nullptr, avoiding crash."); - - if (sv_derived_from(ST(2), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(2))); - pNewTarget = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "pNewTarget is not of type Mob"); - if (pNewTarget == nullptr) - Perl_croak(aTHX_ "pNewTarget is nullptr, avoiding crash."); - - THIS->ReplaceWithTarget(pOldMob, pNewTarget); - } - XSRETURN_EMPTY; +void Perl_EntityList_RemoveFromTargets(EntityList* self, Mob* mob) // @categories Script Utility +{ + self->RemoveFromTargets(mob); } -XS(XS_EntityList_OpenDoorsNear); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_OpenDoorsNear) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::OpenDoorsNear(THIS, NPC* opener)"); // @categories Script Utility, Doors - { - EntityList *THIS; - Mob *opener; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - opener = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "opener is not of type Mob"); - if (opener == nullptr) - Perl_croak(aTHX_ "opener is nullptr, avoiding crash."); - - THIS->OpenDoorsNear(opener); - } - XSRETURN_EMPTY; +void Perl_EntityList_ReplaceWithTarget(EntityList* self, Mob* old_mob, Mob* new_target) // @categories Script Utility +{ + self->ReplaceWithTarget(old_mob, new_target); } -XS(XS_EntityList_MakeNameUnique); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_MakeNameUnique) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::MakeNameUnique(THIS, string name)"); // @categories Script Utility - { - EntityList *THIS; - char *RETVAL; - dXSTARG; - char *name = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->MakeNameUnique(name); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +void Perl_EntityList_OpenDoorsNear(EntityList* self, Mob* opener) // @categories Script Utility, Doors +{ + self->OpenDoorsNear(opener); } -XS(XS_EntityList_RemoveNumbers); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveNumbers) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityListDeprecated::RemoveNumbers(CLASS, name)"); - { - char *RETVAL; - dXSTARG; - char *name = (char *) SvPV_nolen(ST(1)); - - RETVAL = EntityList::RemoveNumbers(name); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +std::string Perl_EntityList_MakeNameUnique(EntityList* self, char* name) // @categories Script Utility +{ + char buf[64] = {0}; + strn0cpy(buf, name, sizeof(buf)); + return self->MakeNameUnique(buf); // todo: this function is unsafe } -XS(XS_EntityList_SignalMobsByNPCID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_SignalMobsByNPCID) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EntityList::SignalMobsByNPCID(THIS, uint32 npc_type_id, int signal_id)"); // @categories Script Utility - { - EntityList *THIS; - uint32 npc_type = (uint32) SvUV(ST(1)); - int signal_id = (int) SvIV(ST(2)); - VALIDATE_THIS_IS_ENTITY; - THIS->SignalMobsByNPCID(npc_type, signal_id); - } - XSRETURN_EMPTY; +std::string Perl_EntityList_RemoveNumbers(EntityList* self, char* name) +{ + char buf[64] = {0}; + strn0cpy(buf, name, sizeof(buf)); + return EntityList::RemoveNumbers(buf); // todo: this function is unsafe } -XS(XS_EntityList_RemoveEntity); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveEntity) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::RemoveEntity(THIS, uint16 id)"); // @categories Script Utility - { - EntityList *THIS; - uint16 id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - THIS->RemoveEntity(id); - } - XSRETURN_EMPTY; +void Perl_EntityList_SignalMobsByNPCID(EntityList* self, uint32 npc_type_id, int signal_id) // @categories Script Utility +{ + self->SignalMobsByNPCID(npc_type_id, signal_id); } -XS(XS_EntityList_DeleteNPCCorpses); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_DeleteNPCCorpses) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::DeleteNPCCorpses(THIS)"); // @categories Corpse - { - EntityList *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->DeleteNPCCorpses(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_EntityList_RemoveEntity(EntityList* self, uint16_t id) // @categories Script Utility +{ + self->RemoveEntity(id); } -XS(XS_EntityList_DeletePlayerCorpses); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_DeletePlayerCorpses) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::DeletePlayerCorpses(THIS)"); // @categories Account and Character, Corpse - { - EntityList *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->DeletePlayerCorpses(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_EntityList_DeleteNPCCorpses(EntityList* self) // @categories Corpse +{ + return self->DeleteNPCCorpses(); } -XS(XS_EntityList_HalveAggro); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_HalveAggro) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::HalveAggro(THIS, Mob* target)"); // @categories Script Utility, Hate and Aggro - { - EntityList *THIS; - Mob *who; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - who = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "who is not of type Mob"); - if (who == nullptr) - Perl_croak(aTHX_ "who is nullptr, avoiding crash."); - - THIS->HalveAggro(who); - } - XSRETURN_EMPTY; +uint32_t Perl_EntityList_DeletePlayerCorpses(EntityList* self) // @categories Account and Character, Corpse +{ + return self->DeletePlayerCorpses(); } -XS(XS_EntityList_DoubleAggro); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_DoubleAggro) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::DoubleAggro(THIS, *Mob target)"); // @categories Script Utility - { - EntityList *THIS; - Mob *who; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - who = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "who is not of type Mob"); - if (who == nullptr) - Perl_croak(aTHX_ "who is nullptr, avoiding crash."); - - THIS->DoubleAggro(who); - } - XSRETURN_EMPTY; +void Perl_EntityList_HalveAggro(EntityList* self, Mob* who) // @categories Script Utility, Hate and Aggro +{ + self->HalveAggro(who); } -XS(XS_EntityList_ClearFeignAggro); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_ClearFeignAggro) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::ClearFeignAggro(THIS, Mob* target)"); // @categories Script Utility - { - EntityList *THIS; - Mob *targ; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - targ = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "targ is not of type Mob"); - if (targ == nullptr) - Perl_croak(aTHX_ "targ is nullptr, avoiding crash."); - - THIS->ClearFeignAggro(targ); - } - XSRETURN_EMPTY; +void Perl_EntityList_DoubleAggro(EntityList* self, Mob* who) // @categories Script Utility +{ + self->DoubleAggro(who); } -XS(XS_EntityList_Fighting); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_Fighting) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::Fighting(THIS, Mob* target)"); // @categories Script Utility - { - EntityList *THIS; - bool RETVAL; - Mob *targ; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - targ = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "targ is not of type Mob"); - if (targ == nullptr) - Perl_croak(aTHX_ "targ is nullptr, avoiding crash."); - - RETVAL = THIS->Fighting(targ); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_EntityList_ClearFeignAggro(EntityList* self, Mob* target) // @categories Script Utility +{ + self->ClearFeignAggro(target); } -XS(XS_EntityList_RemoveFromHateLists); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_RemoveFromHateLists) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: EntityList::RemoveFromHateLists(THIS, Mob* mob, [bool set_to_one = false])"); // @categories Script Utility, Hate and Aggro - { - EntityList *THIS; - Mob *mob; - bool settoone; - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - mob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "mob is not of type Mob"); - if (mob == nullptr) - Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); - - if (items < 3) - settoone = false; - else { - settoone = (bool) SvTRUE(ST(2)); - } - - THIS->RemoveFromHateLists(mob, settoone); - } - XSRETURN_EMPTY; +bool Perl_EntityList_Fighting(EntityList* self, Mob* target) // @categories Script Utility +{ + return self->Fighting(target); +} + +void Perl_EntityList_RemoveFromHateLists(EntityList* self, Mob* mob) // @categories Script Utility, Hate and Aggro +{ + self->RemoveFromHateLists(mob); +} + +void Perl_EntityList_RemoveFromHateLists(EntityList* self, Mob* mob, bool set_to_one) // @categories Script Utility, Hate and Aggro +{ + self->RemoveFromHateLists(mob, set_to_one); } -XS(XS_EntityList_MessageGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_MessageGroup) { - dXSARGS; - if (items < 5) - Perl_croak(aTHX_ "Usage: EntityList::MessageGroup(THIS, Mob* sender, bool skip_close, uint32 emote_color_type, string message)"); // @categories Script Utility, Group +void Perl_EntityList_MessageGroup(EntityList* self, Mob* sender, bool skip_close, uint32_t emote_color_type, const char* message) // @categories Script Utility, Group +{ + self->MessageGroup(sender, skip_close, emote_color_type, message); +} + +Client* Perl_EntityList_GetRandomClient(EntityList* self) // @categories Account and Character, Script Utility +{ + return self->GetRandomClient(); +} + +Client* Perl_EntityList_GetRandomClient(EntityList* self, float x, float y, float z, float distance) // @categories Account and Character, Script Utility +{ + return self->GetRandomClient(glm::vec3(x, y, z), distance); +} + +Client* Perl_EntityList_GetRandomClient(EntityList* self, float x, float y, float z, float distance, Client* exclude_client) // @categories Account and Character, Script Utility +{ + return self->GetRandomClient(glm::vec3(x, y, z), distance, exclude_client); +} + +perl::array Perl_EntityList_GetMobList(EntityList* self) // @categories Script Utility +{ + perl::array result; + + std::list mob_list; + entity_list.GetMobList(mob_list); + for (Mob* entry : mob_list) { - EntityList *THIS; - Mob *sender; - bool skipclose = (bool) SvTRUE(ST(2)); - uint32 type = (uint32) SvUV(ST(3)); - char *message = (char *) SvPV_nolen(ST(4)); - VALIDATE_THIS_IS_ENTITY; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - sender = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "sender is not of type Mob"); - if (sender == nullptr) - Perl_croak(aTHX_ "sender is nullptr, avoiding crash."); - - THIS->MessageGroup(sender, skipclose, type, message); + result.push_back(entry); } - XSRETURN_EMPTY; + + return result; } -XS(XS_EntityList_GetRandomClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetRandomClient) { - dXSARGS; - if (items < 5 || items > 6) - Perl_croak(aTHX_ "Usage: EntityList::GetRandomClient(THIS, float x, float y, float z, float distance, [Client* exclude_client = nullptr])"); // @categories Account and Character, Script Utility +perl::array Perl_EntityList_GetClientList(EntityList* self) // @categories Account and Character, Script Utility +{ + perl::array result; + + std::list client_list; + entity_list.GetClientList(client_list); + for (Client* entry : client_list) { - EntityList *THIS; - Client *RETVAL, *exclude_client = nullptr; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float distance = (float) SvNV(ST(4)); - VALIDATE_THIS_IS_ENTITY; - - if (items == 6) { - if (sv_derived_from(ST(5), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(5))); - exclude_client = INT2PTR(Client *, tmp); - } - } - - RETVAL = entity_list.GetRandomClient(glm::vec3(x, y, z), (distance * distance), exclude_client); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); + result.push_back(entry); } - XSRETURN(1); + + return result; +} + +Bot* Perl_EntityList_GetBotByID(EntityList* self, uint32_t bot_id) // @categories Script Utility, Bot +{ + return self->GetBotByBotID(bot_id); +} + +Bot* Perl_EntityList_GetBotByName(EntityList* self, std::string bot_name) // @categories Script Utility, Bot +{ + return self->GetBotByBotName(bot_name); +} + +Client* Perl_EntityList_GetBotOwnerByBotEntityID(EntityList* self, uint32_t entity_id) // @categories Script Utility, Bot +{ + return self->GetBotOwnerByBotEntityID(entity_id); +} + +Client* Perl_EntityList_GetBotOwnerByBotID(EntityList* self, uint32_t bot_id) // @categories Script Utility, Bot +{ + return self->GetBotOwnerByBotID(bot_id); } -XS(XS_EntityList_GetMobList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetMobList) { - dXSARGS; - int num_mobs = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::GetMobList(THIS)"); // @categories Script Utility +perl::array Perl_EntityList_GetBotList(EntityList* self) // @categories Script Utility, Bot +{ + perl::array result; + auto current_bot_list = self->GetBotList(); + for (Bot* bot_iterator : current_bot_list) { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - std::list mob_list; - entity_list.GetMobList(mob_list); - auto iter = mob_list.begin(); - - while (iter != mob_list.end()) { - Mob *entry = (*iter); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) entry); - XPUSHs(ST(0)); - num_mobs++; - iter++; - } + result.push_back(bot_iterator); } - XSRETURN(num_mobs); + return result; } -XS(XS_EntityList_GetClientList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetClientList) { - dXSARGS; - int num_clients = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::GetClientList(THIS)"); // @categories Account and Character, Script Utility +perl::array Perl_EntityList_GetBotListByCharacterID(EntityList* self, uint32_t character_id) // @categories Script Utility, Bot +{ + perl::array result; + auto current_bot_list = self->GetBotListByCharacterID(character_id); + for (int i = 0; i < current_bot_list.size(); ++i) { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - std::list client_list; - entity_list.GetClientList(client_list); - auto iter = client_list.begin(); - - while (iter != client_list.end()) { - Client *entry = (*iter); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) entry); - XPUSHs(ST(0)); - num_clients++; - iter++; - } + result.push_back(current_bot_list[i]); } - XSRETURN(num_clients); + return result; } -#ifdef BOTS -XS(XS_EntityList_GetBotByID); -XS(XS_EntityList_GetBotByID) { - dXSARGS; - int bot_count = 0; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetBotByID(THIS, uint32 bot_id)"); // @categories Script Utility, Bot +perl::array Perl_EntityList_GetBotListByCharacterID(EntityList* self, uint32_t character_id, uint8_t class_id) // @categories Script Utility, Bot +{ + perl::array result; + auto current_bot_list = self->GetBotListByCharacterID(character_id, class_id); + for (int i = 0; i < current_bot_list.size(); ++i) { - EntityList* THIS; - Bot* RETVAL; - uint32 bot_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetBotByBotID(bot_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Bot", (void *) RETVAL); + result.push_back(current_bot_list[i]); } - XSRETURN(1); + return result; } -XS(XS_EntityList_GetBotByName); -XS(XS_EntityList_GetBotByName) { - dXSARGS; - int bot_count = 0; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::GetBotByName(THIS, string bot_name)"); // @categories Script Utility, Bot +perl::array Perl_EntityList_GetBotListByClientName(EntityList* self, std::string client_name) // @categories Script Utility, Bot +{ + perl::array result; + auto current_bot_list = self->GetBotListByClientName(client_name); + for (int i = 0; i < current_bot_list.size(); ++i) { - EntityList* THIS; - Bot* RETVAL; - std::string bot_name = (std::string) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_ENTITY; - RETVAL = THIS->GetBotByBotName(bot_name); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Bot", (void *) RETVAL); + result.push_back(current_bot_list[i]); } - XSRETURN(1); + return result; } -XS(XS_EntityList_GetBotList); -XS(XS_EntityList_GetBotList) { - dXSARGS; - int bot_count = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::GetBotList(THIS)"); // @categories Script Utility, Bot +perl::array Perl_EntityList_GetBotListByClientName(EntityList* self, std::string client_name, uint8 class_id) // @categories Script Utility, Bot +{ + perl::array result; + auto current_bot_list = self->GetBotListByClientName(client_name, class_id); + for (int i = 0; i < current_bot_list.size(); ++i) { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - auto current_bot_list = THIS->GetBotList(); - for (auto bot_iterator : current_bot_list) { - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Bot", (void *)bot_iterator); - XPUSHs(ST(0)); - bot_count++; - } + result.push_back(current_bot_list[i]); } - XSRETURN(bot_count); + return result; } -XS(XS_EntityList_GetBotListByCharacterID); -XS(XS_EntityList_GetBotListByCharacterID) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: EntityList::GetBotListByCharacterID(THIS, uint32 character_id)"); // @categories Script Utility, Bot - } +void Perl_EntityList_SignalAllBotsByOwnerCharacterID(EntityList* self, uint32_t character_id, int signal_id) // @categories Script Utility +{ + entity_list.SignalAllBotsByOwnerCharacterID(character_id, signal_id); +} - EntityList *THIS; - uint32 character_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - - auto current_bot_list = THIS->GetBotListByCharacterID(character_id); - auto bot_count = current_bot_list.size(); - - if (bot_count) { - EXTEND(sp, bot_count); - for (int index = 0; index < bot_count; ++index) { - ST(index) = sv_newmortal(); - sv_setref_pv(ST(index), "Bot", (void *) current_bot_list[index]); - XPUSHs(ST(index)); - } - XSRETURN(bot_count); - } - - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); -} - -XS(XS_EntityList_GetBotListByClientName); -XS(XS_EntityList_GetBotListByClientName) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: EntityList::GetBotListByClientName(THIS, string client_name)"); // @categories Script Utility, Bot - } +void Perl_EntityList_SignalAllBotsByOwnerName(EntityList* self, std::string owner_name, int signal_id) // @categories Script Utility +{ + entity_list.SignalAllBotsByOwnerName(owner_name, signal_id); +} - EntityList *THIS; - std::string client_name = (std::string) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_ENTITY; - - auto current_bot_list = THIS->GetBotListByClientName(client_name); - auto bot_count = current_bot_list.size(); - - if (bot_count) { - EXTEND(sp, bot_count); - for (int index = 0; index < bot_count; ++index) { - ST(index) = sv_newmortal(); - sv_setref_pv(ST(index), "Bot", (void *) current_bot_list[index]); - XPUSHs(ST(index)); - } - XSRETURN(bot_count); - } - - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); -} -#endif - -XS(XS_EntityList_GetNPCList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetNPCList) { - dXSARGS; - int num_npcs = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::GetNPCList(THIS)"); // @categories Script Utility - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - std::list npc_list; - entity_list.GetNPCList(npc_list); - auto iter = npc_list.begin(); - - while (iter != npc_list.end()) { - NPC *entry = (*iter); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "NPC", (void *) entry); - XPUSHs(ST(0)); - num_npcs++; - iter++; - } - } - XSRETURN(num_npcs); +void Perl_EntityList_SignalBotByBotID(EntityList* self, uint32_t bot_id, int signal_id) // @categories Script Utility +{ + entity_list.SignalBotByBotID(bot_id, signal_id); } -XS(XS_EntityList_GetCorpseList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetCorpseList) { - dXSARGS; - int num_corpses = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::GetCorpseList(THIS)"); // @categories Script Utility, Corpse - { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - std::list corpse_list; - entity_list.GetCorpseList(corpse_list); - auto iter = corpse_list.begin(); - - while (iter != corpse_list.end()) { - Corpse *entry = (*iter); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Corpse", (void *) entry); - XPUSHs(ST(0)); - num_corpses++; - iter++; - } - } - XSRETURN(num_corpses); +void Perl_EntityList_SignalBotByBotName(EntityList* self, std::string bot_name, int signal_id) // @categories Script Utility +{ + entity_list.SignalBotByBotName(bot_name, signal_id); } -XS(XS_EntityList_GetObjectList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetObjectList) { - dXSARGS; - int num_objects = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::GetObjectList(THIS)"); // @categories Script Utility, Objects +perl::array Perl_EntityList_GetNPCList(EntityList* self) // @categories Script Utility +{ + perl::array result; + + std::list npc_list; + entity_list.GetNPCList(npc_list); + for (NPC* entry : npc_list) { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - std::list object_list; - entity_list.GetObjectList(object_list); - auto iter = object_list.begin(); - - while (iter != object_list.end()) { - Object *entry = (*iter); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Object", (void *) entry); - XPUSHs(ST(0)); - num_objects++; - iter++; - } + result.push_back(entry); } - XSRETURN(num_objects); + + return result; } -XS(XS_EntityList_GetDoorsList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetDoorsList) { - dXSARGS; - int num_objects = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: EntityList::GetDoorsList(THIS)"); // @categories Script Utility, Doors +perl::array Perl_EntityList_GetCorpseList(EntityList* self) // @categories Script Utility, Corpse +{ + perl::array result; + + std::list corpse_list; + entity_list.GetCorpseList(corpse_list); + for (Corpse* entry : corpse_list) { - EntityList *THIS; - VALIDATE_THIS_IS_ENTITY; - std::list door_list; - entity_list.GetDoorsList(door_list); - auto iter = door_list.begin(); - - while (iter != door_list.end()) { - Doors *entry = (*iter); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Doors", (void *) entry); - XPUSHs(ST(0)); - num_objects++; - iter++; - } + result.push_back(entry); } - XSRETURN(num_objects); + + return result; } -XS(XS_EntityList_SignalAllClients); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_SignalAllClients) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EntityList::SignalAllClients(THIS, uint32 data)"); // @categories Script Utility +perl::array Perl_EntityList_GetObjectList(EntityList* self) // @categories Script Utility, Objects +{ + perl::array result; + + std::list object_list; + entity_list.GetObjectList(object_list); + for (Object* entry : object_list) { - EntityList *THIS; - uint32 data = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_ENTITY; - entity_list.SignalAllClients(data); + result.push_back(entry); } - XSRETURN_EMPTY; + + return result; } -XS(XS_EntityList_GetRandomMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetRandomMob) { - dXSARGS; - if (items < 5 || items > 6) - Perl_croak(aTHX_ "Usage: EntityList::GetRandomMob(THIS, float x, float y, float z, float distance, [Mob* exclude_mob = nullptr])"); // @categories Account and Character, Script Utility +perl::array Perl_EntityList_GetDoorsList(EntityList* self) // @categories Script Utility, Doors +{ + perl::array result; + + std::list door_list; + entity_list.GetDoorsList(door_list); + for (Doors* entry : door_list) { - EntityList *THIS; - Mob *RETVAL, *exclude_mob = nullptr; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float distance = (float) SvNV(ST(4)); - VALIDATE_THIS_IS_ENTITY; - - if (items == 6) { - if (sv_derived_from(ST(5), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(5))); - exclude_mob = INT2PTR(Mob*, tmp); - } - } - - RETVAL = entity_list.GetRandomMob(glm::vec3(x, y, z), (distance * distance), exclude_mob); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); + result.push_back(entry); } - XSRETURN(1); + + return result; } -XS(XS_EntityList_GetRandomNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EntityList_GetRandomNPC) { - dXSARGS; - if (items < 5 || items > 6) - Perl_croak(aTHX_ "Usage: EntityList::GetRandomNPC(THIS, float x, float y, float z, float distance, [NPC* exclude_npc = nullptr])"); // @categories Account and Character, Script Utility - { - EntityList *THIS; - NPC *RETVAL, *exclude_npc = nullptr; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float distance = (float) SvNV(ST(4)); - VALIDATE_THIS_IS_ENTITY; - - if (items == 6) { - if (sv_derived_from(ST(5), "NPC")) { - IV tmp = SvIV((SV *) SvRV(ST(5))); - exclude_npc = INT2PTR(NPC*, tmp); - } - } - - RETVAL = entity_list.GetRandomNPC(glm::vec3(x, y, z), (distance * distance), exclude_npc); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "NPC", (void *) RETVAL); - } - XSRETURN(1); -} - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_EntityList); /* prototype to pass -Wmissing-prototypes */ -XS(boot_EntityList) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "CanAddHateForMob"), XS_EntityList_CanAddHateForMob, file, "$$"); - newXSproto(strcpy(buf, "Clear"), XS_EntityList_Clear, file, "$"); - newXSproto(strcpy(buf, "ClearClientPetitionQueue"), XS_EntityList_ClearClientPetitionQueue, file, "$"); - newXSproto(strcpy(buf, "ClearFeignAggro"), XS_EntityList_ClearFeignAggro, file, "$$"); - newXSproto(strcpy(buf, "DeleteNPCCorpses"), XS_EntityList_DeleteNPCCorpses, file, "$"); - newXSproto(strcpy(buf, "DeletePlayerCorpses"), XS_EntityList_DeletePlayerCorpses, file, "$"); - newXSproto(strcpy(buf, "DoubleAggro"), XS_EntityList_DoubleAggro, file, "$$"); - newXSproto(strcpy(buf, "Fighting"), XS_EntityList_Fighting, file, "$$"); - newXSproto(strcpy(buf, "FindDoor"), XS_EntityList_FindDoor, file, "$$"); -#ifdef BOTS - newXSproto(strcpy(buf, "GetBotByID"), XS_EntityList_GetBotByID, file, "$$"); - newXSproto(strcpy(buf, "GetBotByName"), XS_EntityList_GetBotByName, file, "$$"); - newXSproto(strcpy(buf, "GetBotList"), XS_EntityList_GetBotList, file, "$"); - newXSproto(strcpy(buf, "GetBotListByCharacterID"), XS_EntityList_GetBotListByCharacterID, file, "$$"); - newXSproto(strcpy(buf, "GetBotListByClientName"), XS_EntityList_GetBotListByClientName, file, "$$"); -#endif - newXSproto(strcpy(buf, "GetClientByAccID"), XS_EntityList_GetClientByAccID, file, "$$"); - newXSproto(strcpy(buf, "GetClientByCharID"), XS_EntityList_GetClientByCharID, file, "$$"); - newXSproto(strcpy(buf, "GetClientByID"), XS_EntityList_GetClientByID, file, "$$"); - newXSproto(strcpy(buf, "GetClientByName"), XS_EntityList_GetClientByName, file, "$$"); - newXSproto(strcpy(buf, "GetClientByWID"), XS_EntityList_GetClientByWID, file, "$$"); - newXSproto(strcpy(buf, "GetClientList"), XS_EntityList_GetClientList, file, "$"); - newXSproto(strcpy(buf, "GetCorpseByID"), XS_EntityList_GetCorpseByID, file, "$$"); - newXSproto(strcpy(buf, "GetCorpseByName"), XS_EntityList_GetCorpseByName, file, "$$"); - newXSproto(strcpy(buf, "GetCorpseByOwner"), XS_EntityList_GetCorpseByOwner, file, "$$"); - newXSproto(strcpy(buf, "GetCorpseList"), XS_EntityList_GetCorpseList, file, "$"); - newXSproto(strcpy(buf, "GetDoorsByDBID"), XS_EntityList_GetDoorsByDBID, file, "$$"); - newXSproto(strcpy(buf, "GetDoorsByDoorID"), XS_EntityList_GetDoorsByDoorID, file, "$$"); - newXSproto(strcpy(buf, "GetDoorsByID"), XS_EntityList_GetDoorsByID, file, "$$"); - newXSproto(strcpy(buf, "GetDoorsList"), XS_EntityList_GetDoorsList, file, "$"); - newXSproto(strcpy(buf, "GetGroupByClient"), XS_EntityList_GetGroupByClient, file, "$$"); - newXSproto(strcpy(buf, "GetGroupByID"), XS_EntityList_GetGroupByID, file, "$$"); - newXSproto(strcpy(buf, "GetGroupByLeaderName"), XS_EntityList_GetGroupByLeaderName, file, "$$"); - newXSproto(strcpy(buf, "GetGroupByMob"), XS_EntityList_GetGroupByMob, file, "$$"); - newXSproto(strcpy(buf, "GetMob"), XS_EntityList_GetMob, file, "$$"); - newXSproto(strcpy(buf, "GetMobByID"), XS_EntityList_GetMobByID, file, "$$"); - newXSproto(strcpy(buf, "GetMobByNpcTypeID"), XS_EntityList_GetMobByNpcTypeID, file, "$$"); - newXSproto(strcpy(buf, "GetMobID"), XS_EntityList_GetMobID, file, "$$"); - newXSproto(strcpy(buf, "GetMobList"), XS_EntityList_GetMobList, file, "$"); - newXSproto(strcpy(buf, "GetNPCByID"), XS_EntityList_GetNPCByID, file, "$$"); - newXSproto(strcpy(buf, "GetNPCByNPCTypeID"), XS_EntityList_GetNPCByNPCTypeID, file, "$$"); - newXSproto(strcpy(buf, "GetNPCBySpawnID"), XS_EntityList_GetNPCBySpawnID, file, "$$"); - newXSproto(strcpy(buf, "GetNPCList"), XS_EntityList_GetNPCList, file, "$"); - newXSproto(strcpy(buf, "GetObjectByDBID"), XS_EntityList_GetObjectByDBID, file, "$"); - newXSproto(strcpy(buf, "GetObjectByID"), XS_EntityList_GetObjectByID, file, "$"); - newXSproto(strcpy(buf, "GetObjectList"), XS_EntityList_GetObjectList, file, "$"); - newXSproto(strcpy(buf, "GetRaidByClient"), XS_EntityList_GetRaidByClient, file, "$$"); - newXSproto(strcpy(buf, "GetRaidByID"), XS_EntityList_GetRaidByID, file, "$$"); - newXSproto(strcpy(buf, "GetRandomClient"), XS_EntityList_GetRandomClient, file, "$$$$$;$"); - newXSproto(strcpy(buf, "GetRandomMob"), XS_EntityList_GetRandomMob, file, "$$$$$;$"); - newXSproto(strcpy(buf, "GetRandomNPC"), XS_EntityList_GetRandomNPC, file, "$$$$$;$"); - newXSproto(strcpy(buf, "HalveAggro"), XS_EntityList_HalveAggro, file, "$$"); - newXSproto(strcpy(buf, "IsMobSpawnedByNpcTypeID"), XS_EntityList_IsMobSpawnedByNpcTypeID, file, "$$"); - newXSproto(strcpy(buf, "MakeNameUnique"), XS_EntityList_MakeNameUnique, file, "$$"); - newXSproto(strcpy(buf, "Message"), XS_EntityList_Message, file, "$$$$;@"); - newXSproto(strcpy(buf, "MessageClose"), XS_EntityList_MessageClose, file, "$$$$$$;@"); - newXSproto(strcpy(buf, "MessageGroup"), XS_EntityList_MessageGroup, file, "$$$$$;@"); - newXSproto(strcpy(buf, "MessageStatus"), XS_EntityList_MessageStatus, file, "$$$$$;@"); - newXSproto(strcpy(buf, "OpenDoorsNear"), XS_EntityList_OpenDoorsNear, file, "$$"); - newXSproto(strcpy(buf, "RemoveAllClients"), XS_EntityList_RemoveAllClients, file, "$"); - newXSproto(strcpy(buf, "RemoveAllCorpses"), XS_EntityList_RemoveAllCorpses, file, "$"); - newXSproto(strcpy(buf, "RemoveAllDoors"), XS_EntityList_RemoveAllDoors, file, "$"); - newXSproto(strcpy(buf, "RemoveAllGroups"), XS_EntityList_RemoveAllGroups, file, "$"); - newXSproto(strcpy(buf, "RemoveAllMobs"), XS_EntityList_RemoveAllMobs, file, "$"); - newXSproto(strcpy(buf, "RemoveAllNPCs"), XS_EntityList_RemoveAllNPCs, file, "$"); - newXSproto(strcpy(buf, "RemoveAllObjects"), XS_EntityList_RemoveAllObjects, file, "$"); - newXSproto(strcpy(buf, "RemoveAllTraps"), XS_EntityList_RemoveAllTraps, file, "$"); - newXSproto(strcpy(buf, "RemoveClient"), XS_EntityList_RemoveClient, file, "$$"); - newXSproto(strcpy(buf, "RemoveCorpse"), XS_EntityList_RemoveCorpse, file, "$$"); - newXSproto(strcpy(buf, "RemoveDoor"), XS_EntityList_RemoveDoor, file, "$$"); - newXSproto(strcpy(buf, "RemoveEntity"), XS_EntityList_RemoveEntity, file, "$$"); - newXSproto(strcpy(buf, "RemoveFromHateLists"), XS_EntityList_RemoveFromHateLists, file, "$$;$"); - newXSproto(strcpy(buf, "RemoveFromTargets"), XS_EntityList_RemoveFromTargets, file, "$$"); - newXSproto(strcpy(buf, "RemoveGroup"), XS_EntityList_RemoveGroup, file, "$$"); - newXSproto(strcpy(buf, "RemoveMob"), XS_EntityList_RemoveMob, file, "$$"); - newXSproto(strcpy(buf, "RemoveNPC"), XS_EntityList_RemoveNPC, file, "$$"); - newXSproto(strcpy(buf, "RemoveNumbers"), XS_EntityList_RemoveNumbers, file, "$$"); - newXSproto(strcpy(buf, "RemoveObject"), XS_EntityList_RemoveObject, file, "$$"); - newXSproto(strcpy(buf, "RemoveTrap"), XS_EntityList_RemoveTrap, file, "$$"); - newXSproto(strcpy(buf, "ReplaceWithTarget"), XS_EntityList_ReplaceWithTarget, file, "$$$"); - newXSproto(strcpy(buf, "SignalAllClients"), XS_EntityList_SignalAllClients, file, "$$"); - newXSproto(strcpy(buf, "SignalMobsByNPCID"), XS_EntityList_SignalMobsByNPCID, file, "$$$"); - XSRETURN_YES; +void Perl_EntityList_SignalAllClients(EntityList* self, int signal_id) // @categories Script Utility +{ + entity_list.SignalAllClients(signal_id); +} + +Mob* Perl_EntityList_GetRandomMob(EntityList* self) // @categories Account and Character, Script Utility +{ + return self->GetRandomMob(); +} + +Mob* Perl_EntityList_GetRandomMob(EntityList* self, float x, float y, float z, float distance) // @categories Account and Character, Script Utility +{ + return self->GetRandomMob(glm::vec3(x, y, z), distance); +} + +Mob* Perl_EntityList_GetRandomMob(EntityList* self, float x, float y, float z, float distance, Mob* exclude_mob) // @categories Account and Character, Script Utility +{ + return self->GetRandomMob(glm::vec3(x, y, z), distance, exclude_mob); +} + +NPC* Perl_EntityList_GetRandomNPC(EntityList* self) // @categories Account and Character, Script Utility +{ + return self->GetRandomNPC(); +} + +NPC* Perl_EntityList_GetRandomNPC(EntityList* self, float x, float y, float z, float distance) // @categories Account and Character, Script Utility +{ + return self->GetRandomNPC(glm::vec3(x, y, z), distance); +} + +NPC* Perl_EntityList_GetRandomNPC(EntityList* self, float x, float y, float z, float distance, NPC* exclude_npc) // @categories Account and Character, Script Utility +{ + return self->GetRandomNPC(glm::vec3(x, y, z), distance, exclude_npc); +} + +void Perl_EntityList_Marquee(EntityList* self, uint32 type, std::string message) +{ + self->Marquee(type, message); +} + +void Perl_EntityList_Marquee(EntityList* self, uint32 type, std::string message, uint32 duration) +{ + self->Marquee(type, message, duration); +} + +void Perl_EntityList_Marquee(EntityList* self, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) +{ + self->Marquee(type, priority, fade_in, fade_out, duration, message); +} + +Bot* Perl_EntityList_GetRandomBot(EntityList* self) // @categories Bots, Script Utility +{ + return self->GetRandomBot(); +} + +Bot* Perl_EntityList_GetRandomBot(EntityList* self, float x, float y, float z, float distance) // @categories Bot, Script Utility +{ + return self->GetRandomBot(glm::vec3(x, y, z), distance); +} + +Bot* Perl_EntityList_GetRandomBot(EntityList* self, float x, float y, float z, float distance, Bot* exclude_bot) // @categories Bot, Script Utility +{ + return self->GetRandomBot(glm::vec3(x, y, z), distance, exclude_bot); +} + +void perl_register_entitylist() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("EntityList"); + package.add("CanAddHateForMob", &Perl_EntityList_CanAddHateForMob); + package.add("Clear", &Perl_EntityList_Clear); + package.add("ClearClientPetitionQueue", &Perl_EntityList_ClearClientPetitionQueue); + package.add("ClearFeignAggro", &Perl_EntityList_ClearFeignAggro); + package.add("DeleteNPCCorpses", &Perl_EntityList_DeleteNPCCorpses); + package.add("DeletePlayerCorpses", &Perl_EntityList_DeletePlayerCorpses); + package.add("DoubleAggro", &Perl_EntityList_DoubleAggro); + package.add("Fighting", &Perl_EntityList_Fighting); + package.add("FindDoor", &Perl_EntityList_FindDoor); + package.add("GetBotByID", &Perl_EntityList_GetBotByID); + package.add("GetBotByName", &Perl_EntityList_GetBotByName); + package.add("GetBotList", &Perl_EntityList_GetBotList); + package.add("GetBotOwnerByBotEntityID", (Client*(*)(EntityList*, uint32))&Perl_EntityList_GetBotOwnerByBotEntityID); + package.add("GetBotOwnerByBotID", (Client*(*)(EntityList*, uint32))&Perl_EntityList_GetBotOwnerByBotID); + package.add("GetBotListByCharacterID", (perl::array(*)(EntityList*, uint32))&Perl_EntityList_GetBotListByCharacterID); + package.add("GetBotListByCharacterID", (perl::array(*)(EntityList*, uint32, uint8))&Perl_EntityList_GetBotListByCharacterID); + package.add("GetBotListByClientName", (perl::array(*)(EntityList*, std::string))&Perl_EntityList_GetBotListByClientName); + package.add("GetBotListByClientName", (perl::array(*)(EntityList*, std::string, uint8))&Perl_EntityList_GetBotListByClientName); + package.add("GetClientByAccID", &Perl_EntityList_GetClientByAccID); + package.add("GetClientByCharID", &Perl_EntityList_GetClientByCharID); + package.add("GetClientByID", &Perl_EntityList_GetClientByID); + package.add("GetClientByName", &Perl_EntityList_GetClientByName); + package.add("GetClientByWID", &Perl_EntityList_GetClientByWID); + package.add("GetClientList", &Perl_EntityList_GetClientList); + package.add("GetCorpseByID", &Perl_EntityList_GetCorpseByID); + package.add("GetCorpseByName", &Perl_EntityList_GetCorpseByName); + package.add("GetCorpseByOwner", &Perl_EntityList_GetCorpseByOwner); + package.add("GetCorpseList", &Perl_EntityList_GetCorpseList); + package.add("GetDoorsByDBID", &Perl_EntityList_GetDoorsByDBID); + package.add("GetDoorsByDoorID", &Perl_EntityList_GetDoorsByDoorID); + package.add("GetDoorsByID", &Perl_EntityList_GetDoorsByID); + package.add("GetDoorsList", &Perl_EntityList_GetDoorsList); + package.add("GetGroupByClient", &Perl_EntityList_GetGroupByClient); + package.add("GetGroupByID", &Perl_EntityList_GetGroupByID); + package.add("GetGroupByLeaderName", &Perl_EntityList_GetGroupByLeaderName); + package.add("GetGroupByMob", &Perl_EntityList_GetGroupByMob); + package.add("GetMob", &Perl_EntityList_GetMob); + package.add("GetMobByID", &Perl_EntityList_GetMobByID); + package.add("GetMobByNpcTypeID", &Perl_EntityList_GetMobByNpcTypeID); + package.add("GetMobID", &Perl_EntityList_GetMobID); + package.add("GetMobList", &Perl_EntityList_GetMobList); + package.add("GetNPCByID", &Perl_EntityList_GetNPCByID); + package.add("GetNPCByNPCTypeID", &Perl_EntityList_GetNPCByNPCTypeID); + package.add("GetNPCBySpawnID", &Perl_EntityList_GetNPCBySpawnID); + package.add("GetNPCList", &Perl_EntityList_GetNPCList); + package.add("GetObjectByDBID", &Perl_EntityList_GetObjectByDBID); + package.add("GetObjectByID", &Perl_EntityList_GetObjectByID); + package.add("GetObjectList", &Perl_EntityList_GetObjectList); + package.add("GetRaidByClient", &Perl_EntityList_GetRaidByClient); + package.add("GetRaidByID", &Perl_EntityList_GetRaidByID); + package.add("GetRandomBot", (Bot*(*)(EntityList*))&Perl_EntityList_GetRandomBot); + package.add("GetRandomBot", (Bot*(*)(EntityList*, float, float, float, float))&Perl_EntityList_GetRandomBot); + package.add("GetRandomBot", (Bot*(*)(EntityList*, float, float, float, float, Bot*))&Perl_EntityList_GetRandomBot); + package.add("GetRandomClient", (Client*(*)(EntityList*))&Perl_EntityList_GetRandomClient); + package.add("GetRandomClient", (Client*(*)(EntityList*, float, float, float, float))&Perl_EntityList_GetRandomClient); + package.add("GetRandomClient", (Client*(*)(EntityList*, float, float, float, float, Client*))&Perl_EntityList_GetRandomClient); + package.add("GetRandomMob", (Mob*(*)(EntityList*))&Perl_EntityList_GetRandomMob); + package.add("GetRandomMob", (Mob*(*)(EntityList*, float, float, float, float))&Perl_EntityList_GetRandomMob); + package.add("GetRandomMob", (Mob*(*)(EntityList*, float, float, float, float, Mob*))&Perl_EntityList_GetRandomMob); + package.add("GetRandomNPC", (NPC*(*)(EntityList*))&Perl_EntityList_GetRandomNPC); + package.add("GetRandomNPC", (NPC*(*)(EntityList*, float, float, float, float))&Perl_EntityList_GetRandomNPC); + package.add("GetRandomNPC", (NPC*(*)(EntityList*, float, float, float, float, NPC*))&Perl_EntityList_GetRandomNPC); + package.add("HalveAggro", &Perl_EntityList_HalveAggro); + package.add("IsMobSpawnedByNpcTypeID", &Perl_EntityList_IsMobSpawnedByNpcTypeID); + package.add("MakeNameUnique", &Perl_EntityList_MakeNameUnique); + package.add("Marquee", (void(*)(EntityList*, uint32, std::string))&Perl_EntityList_Marquee); + package.add("Marquee", (void(*)(EntityList*, uint32, std::string, uint32))&Perl_EntityList_Marquee); + package.add("Marquee", (void(*)(EntityList*, uint32, uint32, uint32, uint32, uint32, std::string))&Perl_EntityList_Marquee); + package.add("Message", &Perl_EntityList_Message); + package.add("MessageClose", &Perl_EntityList_MessageClose); + package.add("MessageGroup", &Perl_EntityList_MessageGroup); + package.add("MessageStatus", &Perl_EntityList_MessageStatus); + package.add("OpenDoorsNear", &Perl_EntityList_OpenDoorsNear); + package.add("RemoveAllClients", &Perl_EntityList_RemoveAllClients); + package.add("RemoveAllCorpses", &Perl_EntityList_RemoveAllCorpses); + package.add("RemoveAllDoors", &Perl_EntityList_RemoveAllDoors); + package.add("RemoveAllGroups", &Perl_EntityList_RemoveAllGroups); + package.add("RemoveAllMobs", &Perl_EntityList_RemoveAllMobs); + package.add("RemoveAllNPCs", &Perl_EntityList_RemoveAllNPCs); + package.add("RemoveAllObjects", &Perl_EntityList_RemoveAllObjects); + package.add("RemoveAllTraps", &Perl_EntityList_RemoveAllTraps); + package.add("RemoveClient", &Perl_EntityList_RemoveClient); + package.add("RemoveCorpse", &Perl_EntityList_RemoveCorpse); + package.add("RemoveDoor", &Perl_EntityList_RemoveDoor); + package.add("RemoveEntity", &Perl_EntityList_RemoveEntity); + package.add("RemoveFromHateLists", (void(*)(EntityList*, Mob*))&Perl_EntityList_RemoveFromHateLists); + package.add("RemoveFromHateLists", (void(*)(EntityList*, Mob*, bool))&Perl_EntityList_RemoveFromHateLists); + package.add("RemoveFromTargets", &Perl_EntityList_RemoveFromTargets); + package.add("RemoveGroup", &Perl_EntityList_RemoveGroup); + package.add("RemoveMob", &Perl_EntityList_RemoveMob); + package.add("RemoveNPC", &Perl_EntityList_RemoveNPC); + package.add("RemoveNumbers", &Perl_EntityList_RemoveNumbers); + package.add("RemoveObject", &Perl_EntityList_RemoveObject); + package.add("RemoveTrap", &Perl_EntityList_RemoveTrap); + package.add("ReplaceWithTarget", &Perl_EntityList_ReplaceWithTarget); + package.add("SignalAllBotsByOwnerCharacterID", &Perl_EntityList_SignalAllBotsByOwnerCharacterID); + package.add("SignalAllBotsByOwnerName", &Perl_EntityList_SignalAllBotsByOwnerName); + package.add("SignalAllClients", &Perl_EntityList_SignalAllClients); + package.add("SignalBotByBotID", &Perl_EntityList_SignalBotByBotID); + package.add("SignalBotByBotName", &Perl_EntityList_SignalBotByBotName); + package.add("SignalMobsByNPCID", &Perl_EntityList_SignalMobsByNPCID); } #endif //EMBPERL_XS_CLASSES - diff --git a/zone/perl_expedition.cpp b/zone/perl_expedition.cpp index 69cf7ac95..c46cb907c 100644 --- a/zone/perl_expedition.cpp +++ b/zone/perl_expedition.cpp @@ -2,669 +2,273 @@ #ifdef EMBPERL_XS_CLASSES -#include "expedition.h" -#include "zone_store.h" #include "embperl.h" +#include "expedition.h" +#include "../common/zone_store.h" #include "../common/global_define.h" -#ifdef seed -#undef seed -#endif - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_EXPEDITION \ - do { \ - if (sv_derived_from(ST(0), "Expedition")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Expedition*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Expedition"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Expedition_AddLockout); -XS(XS_Expedition_AddLockout) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Expedition::AddLockout(THIS, string event_name, uint32 seconds)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - std::string event_name(SvPV_nolen(ST(1))); - uint32_t seconds = static_cast(SvUV(ST(2))); - - THIS->AddLockout(event_name, seconds); - - XSRETURN_EMPTY; +void Perl_Expedition_AddLockout(Expedition* self, std::string event_name, uint32_t seconds) +{ + self->AddLockout(event_name, seconds); } -XS(XS_Expedition_AddLockoutDuration); -XS(XS_Expedition_AddLockoutDuration) { - dXSARGS; - if (items != 3 && items != 4) { - Perl_croak(aTHX_ "Usage: Expedition::AddLockout(THIS, string event_name, int seconds, [bool members_only = true])"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - std::string event_name(SvPV_nolen(ST(1))); - int seconds = static_cast(SvUV(ST(2))); - if (items == 4) - { - bool members_only = (bool)SvTRUE(ST(3)); - THIS->AddLockoutDuration(event_name, seconds, members_only); - } - else - { - THIS->AddLockoutDuration(event_name, seconds); - } - - XSRETURN_EMPTY; +void Perl_Expedition_AddLockoutDuration(Expedition* self, std::string event_name, int seconds) +{ + self->AddLockoutDuration(event_name, seconds); } -XS(XS_Expedition_AddReplayLockout); -XS(XS_Expedition_AddReplayLockout) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Expedition::AddReplayLockout(THIS, uint32 seconds)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - uint32_t seconds = static_cast(SvUV(ST(1))); - - THIS->AddReplayLockout(seconds); - - XSRETURN_EMPTY; +void Perl_Expedition_AddLockoutDuration(Expedition* self, std::string event_name, int seconds, bool members_only) +{ + self->AddLockoutDuration(event_name, seconds, members_only); } -XS(XS_Expedition_AddReplayLockoutDuration); -XS(XS_Expedition_AddReplayLockoutDuration) { - dXSARGS; - if (items != 2 && items != 3) { - Perl_croak(aTHX_ "Usage: Expedition::AddReplayLockoutDuration(THIS, int seconds, [bool members_only = true])"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - int seconds = static_cast(SvUV(ST(1))); - if (items == 3) - { - bool members_only = (bool)SvTRUE(ST(2)); - THIS->AddReplayLockoutDuration(seconds, members_only); - } - else - { - THIS->AddReplayLockoutDuration(seconds); - } - - XSRETURN_EMPTY; +void Perl_Expedition_AddReplayLockout(Expedition* self, uint32_t seconds) +{ + self->AddReplayLockout(seconds); } -XS(XS_Expedition_GetDynamicZoneID); -XS(XS_Expedition_GetDynamicZoneID) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetDynamicZoneID(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_UV(THIS->GetDynamicZone()->GetID()); +void Perl_Expedition_AddReplayLockoutDuration(Expedition* self, int seconds) +{ + self->AddReplayLockoutDuration(seconds); } -XS(XS_Expedition_GetID); -XS(XS_Expedition_GetID) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetID(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_UV(THIS->GetID()); +void Perl_Expedition_AddReplayLockoutDuration(Expedition* self, int seconds, bool members_only) +{ + self->AddReplayLockoutDuration(seconds, members_only); } -XS(XS_Expedition_GetInstanceID); -XS(XS_Expedition_GetInstanceID) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetInstanceID(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_UV(THIS->GetDynamicZone()->GetInstanceID()); +uint32_t Perl_Expedition_GetDynamicZoneID(Expedition* self) +{ + return self->GetDynamicZone()->GetID(); } -XS(XS_Expedition_GetLeaderName); -XS(XS_Expedition_GetLeaderName) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetLeaderName(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_PV(THIS->GetLeaderName().c_str()); +uint32_t Perl_Expedition_GetID(Expedition* self) +{ + return self->GetID(); } -XS(XS_Expedition_GetLockouts); -XS(XS_Expedition_GetLockouts) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetLockouts(THIS)"); - } +uint16_t Perl_Expedition_GetInstanceID(Expedition* self) +{ + return self->GetDynamicZone()->GetInstanceID(); +} - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; +std::string Perl_Expedition_GetLeaderName(Expedition* self) +{ + return self->GetLeaderName(); +} - HV* hash = newHV(); - - auto lockouts = THIS->GetLockouts(); +perl::reference Perl_Expedition_GetLockouts(Expedition* self) +{ + perl::hash table; + auto lockouts = self->GetLockouts(); for (const auto& lockout : lockouts) { - hv_store(hash, lockout.first.c_str(), static_cast(lockout.first.size()), - newSVuv(lockout.second.GetSecondsRemaining()), 0); + table[lockout.first] = lockout.second.GetSecondsRemaining(); } - - ST(0) = sv_2mortal(newRV_noinc((SV*)hash)); // take ownership of hash (refcnt remains 1) - XSRETURN(1); + return perl::reference(table); } -XS(XS_Expedition_GetLootEventByNPCTypeID); -XS(XS_Expedition_GetLootEventByNPCTypeID) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Expedition::GetLootEventByNPCTypeID(THIS, uint32 npc_type_id)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - uint32_t npc_type_id = static_cast(SvUV(ST(1))); - - XSRETURN_PV(THIS->GetLootEventByNPCTypeID(npc_type_id).c_str()); +std::string Perl_Expedition_GetLootEventByNPCTypeID(Expedition* self, uint32_t npc_type_id) +{ + return self->GetLootEventByNPCTypeID(npc_type_id); } -XS(XS_Expedition_GetLootEventBySpawnID); -XS(XS_Expedition_GetLootEventBySpawnID) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Expedition::GetLootEventBySpawnID(THIS, uint32 spawn_id)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - uint32_t spawn_id = static_cast(SvUV(ST(1))); - - XSRETURN_PV(THIS->GetLootEventBySpawnID(spawn_id).c_str()); +std::string Perl_Expedition_GetLootEventBySpawnID(Expedition* self, uint32_t spawn_id) +{ + return self->GetLootEventBySpawnID(spawn_id); } -XS(XS_Expedition_GetMemberCount); -XS(XS_Expedition_GetMemberCount) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetMemberCount(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_UV(THIS->GetDynamicZone()->GetMemberCount()); +uint32_t Perl_Expedition_GetMemberCount(Expedition* self) +{ + return self->GetDynamicZone()->GetMemberCount(); } -XS(XS_Expedition_GetMembers); -XS(XS_Expedition_GetMembers) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetMembers(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - HV* hash = newHV(); - - for (const auto& member : THIS->GetDynamicZone()->GetMembers()) +perl::reference Perl_Expedition_GetMembers(Expedition* self) +{ + perl::hash table; + for (const auto& member : self->GetDynamicZone()->GetMembers()) { - hv_store(hash, member.name.c_str(), static_cast(member.name.size()), - newSVuv(member.id), 0); + table[member.name] = member.id; } - - ST(0) = sv_2mortal(newRV_noinc((SV*)hash)); - XSRETURN(1); + return perl::reference(table); } -XS(XS_Expedition_GetName); -XS(XS_Expedition_GetName) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetName(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_PV(THIS->GetName().c_str()); +std::string Perl_Expedition_GetName(Expedition* self) +{ + return self->GetName(); } -XS(XS_Expedition_GetSecondsRemaining); -XS(XS_Expedition_GetSecondsRemaining) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetSecondsRemaining(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_UV(THIS->GetDynamicZone()->GetSecondsRemaining()); +uint32_t Perl_Expedition_GetSecondsRemaining(Expedition* self) +{ + return self->GetDynamicZone()->GetSecondsRemaining(); } -XS(XS_Expedition_GetUUID); -XS(XS_Expedition_GetUUID) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetUUID(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_PV(THIS->GetDynamicZone()->GetUUID().c_str()); +std::string Perl_Expedition_GetUUID(Expedition* self) +{ + return self->GetDynamicZone()->GetUUID(); } -XS(XS_Expedition_GetZoneID); -XS(XS_Expedition_GetZoneID) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetZoneID(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_UV(THIS->GetDynamicZone()->GetZoneID()); +uint16_t Perl_Expedition_GetZoneID(Expedition* self) +{ + return self->GetDynamicZone()->GetZoneID(); } -XS(XS_Expedition_GetZoneName); -XS(XS_Expedition_GetZoneName) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetZoneName(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_PV(ZoneName(THIS->GetDynamicZone()->GetZoneID())); +std::string Perl_Expedition_GetZoneName(Expedition* self) +{ + return ZoneName(self->GetDynamicZone()->GetZoneID()); } -XS(XS_Expedition_GetZoneVersion); -XS(XS_Expedition_GetZoneVersion) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::GetZoneVersion(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - XSRETURN_UV(THIS->GetDynamicZone()->GetZoneVersion()); +uint32_t Perl_Expedition_GetZoneVersion(Expedition* self) +{ + return self->GetDynamicZone()->GetZoneVersion(); } -XS(XS_Expedition_HasLockout); -XS(XS_Expedition_HasLockout) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Expedition::HasLockout(THIS, string event_name)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - std::string event_name(SvPV_nolen(ST(1))); - - bool result = THIS->HasLockout(event_name); - ST(0) = boolSV(result); - XSRETURN(1); +bool Perl_Expedition_HasLockout(Expedition* self, std::string event_name) +{ + return self->HasLockout(event_name); } -XS(XS_Expedition_HasReplayLockout); -XS(XS_Expedition_HasReplayLockout) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::HasReplayLockout(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - bool result = THIS->HasReplayLockout(); - ST(0) = boolSV(result); - XSRETURN(1); +bool Perl_Expedition_HasReplayLockout(Expedition* self) +{ + return self->HasReplayLockout(); } -XS(XS_Expedition_IsLocked); -XS(XS_Expedition_IsLocked) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::IsLocked(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - ST(0) = boolSV(THIS->IsLocked()); - XSRETURN(1); +bool Perl_Expedition_IsLocked(Expedition* self) +{ + return self->IsLocked(); } -XS(XS_Expedition_RemoveCompass); -XS(XS_Expedition_RemoveCompass) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Expedition::RemoveCompass(THIS)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - THIS->GetDynamicZone()->SetCompass(0, 0, 0, 0, true); - - XSRETURN_EMPTY; +void Perl_Expedition_RemoveCompass(Expedition* self) +{ + self->GetDynamicZone()->SetCompass(0, 0, 0, 0, true); } -XS(XS_Expedition_RemoveLockout); -XS(XS_Expedition_RemoveLockout) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Expedition::RemoveLockout(THIS, string event_name)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - std::string event_name(SvPV_nolen(ST(1))); - - THIS->RemoveLockout(event_name); - - XSRETURN_EMPTY; +void Perl_Expedition_RemoveLockout(Expedition* self, std::string event_name) +{ + self->RemoveLockout(event_name); } -XS(XS_Expedition_SetCompass); -XS(XS_Expedition_SetCompass) { - dXSARGS; - if (items != 5) { - Perl_croak(aTHX_ "Usage: Expedition::SetCompass(THIS, uint32 zone_id | string zone_name, float x, float y, float z)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - float x = static_cast(SvNV(ST(2))); - float y = static_cast(SvNV(ST(3))); - float z = static_cast(SvNV(ST(4))); - - if (SvTYPE(ST(1)) == SVt_PV) - { - std::string zone_name(SvPV_nolen(ST(1))); - THIS->GetDynamicZone()->SetCompass(ZoneID(zone_name), x, y, z, true); - } - else if (SvTYPE(ST(1)) == SVt_IV) - { - uint32_t zone_id = static_cast(SvUV(ST(1))); - THIS->GetDynamicZone()->SetCompass(zone_id, x, y, z, true); - } - else - { - Perl_croak(aTHX_ "Expedition::SetCompass expected an integer or string"); - } - - XSRETURN_EMPTY; +void Perl_Expedition_SetCompass(Expedition* self, perl::scalar zone, float x, float y, float z) +{ + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); + self->GetDynamicZone()->SetCompass(zone_id, x, y, z, true); } -XS(XS_Expedition_SetLocked); -XS(XS_Expedition_SetLocked) { - dXSARGS; - if (items != 2 && items != 3 && items != 4) { - Perl_croak(aTHX_ "Usage: Expedition::SetLocked(THIS, bool locked, [int lock_msg = 0], [uint32 color = 15])"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - bool locked = (bool)SvTRUE(ST(1)); - int lock_msg = (items == 3) ? static_cast(SvIV(ST(2))) : 0; - if (items == 4) - { - THIS->SetLocked(locked, static_cast(lock_msg), true, (uint32)SvUV(ST(3))); - } - else - { - THIS->SetLocked(locked, static_cast(lock_msg), true); - } - - XSRETURN_EMPTY; +void Perl_Expedition_SetLocked(Expedition* self, bool locked) +{ + self->SetLocked(locked, ExpeditionLockMessage::None); } -XS(XS_Expedition_SetLootEventByNPCTypeID); -XS(XS_Expedition_SetLootEventByNPCTypeID) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Expedition::SetLootEventByNPCTypeID(THIS, uint32 npc_type_id, string event_name)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - uint32_t npc_type_id = static_cast(SvUV(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - - THIS->SetLootEventByNPCTypeID(npc_type_id, event_name); - - XSRETURN_EMPTY; +void Perl_Expedition_SetLocked(Expedition* self, bool locked, int lock_msg) +{ + self->SetLocked(locked, static_cast(lock_msg), true); } -XS(XS_Expedition_SetLootEventBySpawnID); -XS(XS_Expedition_SetLootEventBySpawnID) { - dXSARGS; - if (items != 3) { - Perl_croak(aTHX_ "Usage: Expedition::SetLootEventBySpawnID(THIS, uint32 spawn_id, string event_name)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - uint32_t spawn_id = static_cast(SvUV(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - - THIS->SetLootEventBySpawnID(spawn_id, event_name); - - XSRETURN_EMPTY; +void Perl_Expedition_SetLocked(Expedition* self, bool locked, int lock_msg, uint32_t color) +{ + self->SetLocked(locked, static_cast(lock_msg), true, color); } -XS(XS_Expedition_SetReplayLockoutOnMemberJoin); -XS(XS_Expedition_SetReplayLockoutOnMemberJoin) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Expedition::SetReplayLockoutOnMemberJoin(THIS, bool enable)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - bool enable = (bool)SvTRUE(ST(1)); - - THIS->SetReplayLockoutOnMemberJoin(enable, true); - - XSRETURN_EMPTY; +void Perl_Expedition_SetLootEventByNPCTypeID(Expedition* self, uint32_t npc_type_id, std::string event_name) +{ + self->SetLootEventByNPCTypeID(npc_type_id, event_name); } -XS(XS_Expedition_SetSafeReturn); -XS(XS_Expedition_SetSafeReturn) { - dXSARGS; - if (items != 6) { - Perl_croak(aTHX_ "Usage: Expedition::SetSafeReturn(THIS, uint32 zone_id | string zone_name, float x, float y, float z, float heading)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - float x = static_cast(SvNV(ST(2))); - float y = static_cast(SvNV(ST(3))); - float z = static_cast(SvNV(ST(4))); - float heading = static_cast(SvNV(ST(5))); - - if (SvTYPE(ST(1)) == SVt_PV) - { - std::string zone_name(SvPV_nolen(ST(1))); - THIS->GetDynamicZone()->SetSafeReturn(ZoneID(zone_name), x, y, z, heading, true); - } - else if (SvTYPE(ST(1)) == SVt_IV) - { - uint32_t zone_id = static_cast(SvUV(ST(1))); - THIS->GetDynamicZone()->SetSafeReturn(zone_id, x, y, z, heading, true); - } - else - { - Perl_croak(aTHX_ "Expedition::SetSafeReturn expected an integer or string"); - } - - XSRETURN_EMPTY; +void Perl_Expedition_SetLootEventBySpawnID(Expedition* self, uint32_t entity_id, std::string event_name) +{ + self->SetLootEventBySpawnID(entity_id, event_name); } -XS(XS_Expedition_SetSecondsRemaining); -XS(XS_Expedition_SetSecondsRemaining) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Expedition::SetSecondsRemaining(THIS, uint32 seconds_remaining)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - uint32_t seconds_remaining = static_cast(SvUV(ST(1))); - THIS->GetDynamicZone()->SetSecondsRemaining(seconds_remaining); - - XSRETURN_EMPTY; +void Perl_Expedition_SetReplayLockoutOnMemberJoin(Expedition* self, bool enable) +{ + self->SetReplayLockoutOnMemberJoin(enable, true); } -XS(XS_Expedition_SetZoneInLocation); -XS(XS_Expedition_SetZoneInLocation) { - dXSARGS; - if (items != 5) { - Perl_croak(aTHX_ "Usage: Expedition::SetZoneInLocation(THIS, float x, float y, float z, float heading)"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - float x = static_cast(SvNV(ST(1))); - float y = static_cast(SvNV(ST(2))); - float z = static_cast(SvNV(ST(3))); - float heading = static_cast(SvNV(ST(4))); - - THIS->GetDynamicZone()->SetZoneInLocation(x, y, z, heading, true); - - XSRETURN_EMPTY; +void Perl_Expedition_SetSafeReturn(Expedition* self, perl::scalar zone, float x, float y, float z, float heading) +{ + uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as(); + self->GetDynamicZone()->SetSafeReturn(zone_id, x, y, z, heading, true); } -XS(XS_Expedition_UpdateLockoutDuration); -XS(XS_Expedition_UpdateLockoutDuration) { - dXSARGS; - if (items != 3 && items != 4) { - Perl_croak(aTHX_ "Usage: Expedition::UpdateLockoutDuration(THIS, string event_name, uint32 seconds, [bool members_only = true])"); - } - - Expedition* THIS = nullptr; - VALIDATE_THIS_IS_EXPEDITION; - - std::string event_name(SvPV_nolen(ST(1))); - uint32_t seconds = static_cast(SvUV(ST(2))); - - if (items == 4) - { - bool members_only = (bool)SvTRUE(ST(3)); - THIS->UpdateLockoutDuration(event_name, seconds, members_only); - } - else - { - THIS->UpdateLockoutDuration(event_name, seconds); - } - - XSRETURN_EMPTY; +void Perl_Expedition_SetSecondsRemaining(Expedition* self, uint32_t seconds_remaining) +{ + self->GetDynamicZone()->SetSecondsRemaining(seconds_remaining); } -XS(boot_Expedition); -XS(boot_Expedition) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; +void Perl_Expedition_SetSwitchID(Expedition* self, int dz_switch_id) +{ + self->GetDynamicZone()->SetSwitchID(dz_switch_id, true); +} - if (items != 1) { - fprintf(stderr, "boot_Expedition does not take any arguments."); - } - char buf[128]; +void Perl_Expedition_SetZoneInLocation(Expedition* self, float x, float y, float z, float heading) +{ + self->GetDynamicZone()->SetZoneInLocation(x, y, z, heading, true); +} - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "AddLockout"), XS_Expedition_AddLockout, file, "$$$"); - newXSproto(strcpy(buf, "AddLockoutDuration"), XS_Expedition_AddLockoutDuration, file, "$$$;$"); - newXSproto(strcpy(buf, "AddReplayLockout"), XS_Expedition_AddReplayLockout, file, "$$"); - newXSproto(strcpy(buf, "AddReplayLockoutDuration"), XS_Expedition_AddReplayLockoutDuration, file, "$$;$"); - newXSproto(strcpy(buf, "GetDynamicZoneID"), XS_Expedition_GetDynamicZoneID, file, "$"); - newXSproto(strcpy(buf, "GetID"), XS_Expedition_GetID, file, "$"); - newXSproto(strcpy(buf, "GetInstanceID"), XS_Expedition_GetInstanceID, file, "$"); - newXSproto(strcpy(buf, "GetLeaderName"), XS_Expedition_GetLeaderName, file, "$"); - newXSproto(strcpy(buf, "GetLockouts"), XS_Expedition_GetLockouts, file, "$"); - newXSproto(strcpy(buf, "GetLootEventByNPCTypeID"), XS_Expedition_GetLootEventByNPCTypeID, file, "$$"); - newXSproto(strcpy(buf, "GetLootEventBySpawnID"), XS_Expedition_GetLootEventBySpawnID, file, "$$"); - newXSproto(strcpy(buf, "GetMemberCount"), XS_Expedition_GetMemberCount, file, "$"); - newXSproto(strcpy(buf, "GetMembers"), XS_Expedition_GetMembers, file, "$"); - newXSproto(strcpy(buf, "GetName"), XS_Expedition_GetName, file, "$"); - newXSproto(strcpy(buf, "GetSecondsRemaining"), XS_Expedition_GetSecondsRemaining, file, "$"); - newXSproto(strcpy(buf, "GetUUID"), XS_Expedition_GetUUID, file, "$"); - newXSproto(strcpy(buf, "GetZoneID"), XS_Expedition_GetZoneID, file, "$"); - newXSproto(strcpy(buf, "GetZoneName"), XS_Expedition_GetZoneName, file, "$"); - newXSproto(strcpy(buf, "GetZoneVersion"), XS_Expedition_GetZoneVersion, file, "$"); - newXSproto(strcpy(buf, "HasLockout"), XS_Expedition_HasLockout, file, "$$"); - newXSproto(strcpy(buf, "HasReplayLockout"), XS_Expedition_HasReplayLockout, file, "$"); - newXSproto(strcpy(buf, "IsLocked"), XS_Expedition_IsLocked, file, "$"); - newXSproto(strcpy(buf, "RemoveCompass"), XS_Expedition_RemoveCompass, file, "$"); - newXSproto(strcpy(buf, "RemoveLockout"), XS_Expedition_RemoveLockout, file, "$$"); - newXSproto(strcpy(buf, "SetCompass"), XS_Expedition_SetCompass, file, "$$$$$"); - newXSproto(strcpy(buf, "SetLocked"), XS_Expedition_SetLocked, file, "$$;$$"); - newXSproto(strcpy(buf, "SetLootEventByNPCTypeID"), XS_Expedition_SetLootEventByNPCTypeID, file, "$$$"); - newXSproto(strcpy(buf, "SetLootEventBySpawnID"), XS_Expedition_SetLootEventBySpawnID, file, "$$$"); - newXSproto(strcpy(buf, "SetReplayLockoutOnMemberJoin"), XS_Expedition_SetReplayLockoutOnMemberJoin, file, "$$"); - newXSproto(strcpy(buf, "SetSafeReturn"), XS_Expedition_SetSafeReturn, file, "$$$$$$"); - newXSproto(strcpy(buf, "SetSecondsRemaining"), XS_Expedition_SetSecondsRemaining, file, "$$"); - newXSproto(strcpy(buf, "SetZoneInLocation"), XS_Expedition_SetZoneInLocation, file, "$$$$$"); - newXSproto(strcpy(buf, "UpdateLockoutDuration"), XS_Expedition_UpdateLockoutDuration, file, "$$$;$"); +void Perl_Expedition_UpdateLockoutDuration(Expedition* self, std::string event_name, uint32_t seconds) +{ + self->UpdateLockoutDuration(event_name, seconds); +} - HV* stash = gv_stashpvs("ExpeditionLockMessage", GV_ADD); - newCONSTSUB(stash, "None", newSViv(static_cast(ExpeditionLockMessage::None))); - newCONSTSUB(stash, "Close", newSViv(static_cast(ExpeditionLockMessage::Close))); - newCONSTSUB(stash, "Begin", newSViv(static_cast(ExpeditionLockMessage::Begin))); +void Perl_Expedition_UpdateLockoutDuration(Expedition* self, std::string event_name, uint32_t seconds, bool members_only) +{ + self->UpdateLockoutDuration(event_name, seconds, members_only); +} - XSRETURN_YES; +void perl_register_expedition() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Expedition"); + package.add("AddLockout", &Perl_Expedition_AddLockout); + package.add("AddLockoutDuration", (void(*)(Expedition*, std::string, int))&Perl_Expedition_AddLockoutDuration); + package.add("AddLockoutDuration", (void(*)(Expedition*, std::string, int, bool))&Perl_Expedition_AddLockoutDuration); + package.add("AddReplayLockout", &Perl_Expedition_AddReplayLockout); + package.add("AddReplayLockoutDuration", (void(*)(Expedition*, int))&Perl_Expedition_AddReplayLockoutDuration); + package.add("AddReplayLockoutDuration", (void(*)(Expedition*, int, bool))&Perl_Expedition_AddReplayLockoutDuration); + package.add("GetDynamicZoneID", &Perl_Expedition_GetDynamicZoneID); + package.add("GetID", &Perl_Expedition_GetID); + package.add("GetInstanceID", &Perl_Expedition_GetInstanceID); + package.add("GetLeaderName", &Perl_Expedition_GetLeaderName); + package.add("GetLockouts", &Perl_Expedition_GetLockouts); + package.add("GetLootEventByNPCTypeID", &Perl_Expedition_GetLootEventByNPCTypeID); + package.add("GetLootEventBySpawnID", &Perl_Expedition_GetLootEventBySpawnID); + package.add("GetMemberCount", &Perl_Expedition_GetMemberCount); + package.add("GetMembers", &Perl_Expedition_GetMembers); + package.add("GetName", &Perl_Expedition_GetName); + package.add("GetSecondsRemaining", &Perl_Expedition_GetSecondsRemaining); + package.add("GetUUID", &Perl_Expedition_GetUUID); + package.add("GetZoneID", &Perl_Expedition_GetZoneID); + package.add("GetZoneName", &Perl_Expedition_GetZoneName); + package.add("GetZoneVersion", &Perl_Expedition_GetZoneVersion); + package.add("HasLockout", &Perl_Expedition_HasLockout); + package.add("HasReplayLockout", &Perl_Expedition_HasReplayLockout); + package.add("IsLocked", &Perl_Expedition_IsLocked); + package.add("RemoveCompass", &Perl_Expedition_RemoveCompass); + package.add("RemoveLockout", &Perl_Expedition_RemoveLockout); + package.add("SetCompass", &Perl_Expedition_SetCompass); + package.add("SetLocked", (void(*)(Expedition*, bool))&Perl_Expedition_SetLocked); + package.add("SetLocked", (void(*)(Expedition*, bool, int))&Perl_Expedition_SetLocked); + package.add("SetLocked", (void(*)(Expedition*, bool, int, uint32_t))&Perl_Expedition_SetLocked); + package.add("SetLootEventByNPCTypeID", &Perl_Expedition_SetLootEventByNPCTypeID); + package.add("SetLootEventBySpawnID", &Perl_Expedition_SetLootEventBySpawnID); + package.add("SetReplayLockoutOnMemberJoin", &Perl_Expedition_SetReplayLockoutOnMemberJoin); + package.add("SetSafeReturn", &Perl_Expedition_SetSafeReturn); + package.add("SetSecondsRemaining", &Perl_Expedition_SetSecondsRemaining); + package.add("SetSwitchID", &Perl_Expedition_SetSwitchID); + package.add("SetZoneInLocation", &Perl_Expedition_SetZoneInLocation); + package.add("UpdateLockoutDuration", (void(*)(Expedition*, std::string, uint32_t))&Perl_Expedition_UpdateLockoutDuration); + package.add("UpdateLockoutDuration", (void(*)(Expedition*, std::string, uint32_t, bool))&Perl_Expedition_UpdateLockoutDuration); +} + +void perl_register_expedition_lock_messages() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_package("ExpeditionLockMessage"); + package.add_const("None", static_cast(ExpeditionLockMessage::None)); + package.add_const("Close", static_cast(ExpeditionLockMessage::Close)); + package.add_const("Begin", static_cast(ExpeditionLockMessage::Begin)); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_groups.cpp b/zone/perl_groups.cpp index c4b837aa7..a8411f64b 100644 --- a/zone/perl_groups.cpp +++ b/zone/perl_groups.cpp @@ -2,477 +2,182 @@ #ifdef EMBPERL_XS_CLASSES +#include "../common/data_verification.h" #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "groups.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_GROUP \ - do { \ - if (sv_derived_from(ST(0), "Group")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Group*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Group"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Group_DisbandGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_DisbandGroup) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Group::DisbandGroup(THIS)"); // @categories Script Utility, Group - { - Group *THIS; - VALIDATE_THIS_IS_GROUP; - THIS->DisbandGroup(); - } - XSRETURN_EMPTY; +void Perl_Group_DisbandGroup(Group* self) // @categories Script Utility, Group +{ + self->DisbandGroup(); } -XS(XS_Group_IsGroupMember); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_IsGroupMember) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Group::IsGroupMember(THIS, client)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - bool RETVAL; - Mob *client; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - client = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "client is not of type Mob"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - - RETVAL = THIS->IsGroupMember(client); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Group_IsGroupMember(Group* self, Mob* c) // @categories Account and Character, Script Utility, Group +{ + return self->IsGroupMember(c); } -XS(XS_Group_CastGroupSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_CastGroupSpell) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Group::CastGroupSpell(THIS, Mob* caster, uint16 spell_id)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - Mob *caster; - uint16 spellid = (uint16) SvUV(ST(2)); - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "caster is not of type Mob"); - if (caster == nullptr) - Perl_croak(aTHX_ "caster is nullptr, avoiding crash."); - - THIS->CastGroupSpell(caster, spellid); - } - XSRETURN_EMPTY; +bool Perl_Group_IsGroupMember(Group* self, const char* name) // @categories Account and Character, Script Utility, Group +{ + return self->IsGroupMember(name); } -XS(XS_Group_SplitExp); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_SplitExp) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Group::SplitExp(THIS, uint32 exp, Mob* other)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - uint32 exp = (uint32) SvUV(ST(1)); - Mob *other; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(2), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(2))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - THIS->SplitExp(exp, other); - } - XSRETURN_EMPTY; +void Perl_Group_CastGroupSpell(Group* self, Mob* caster, uint16 spell_id) // @categories Account and Character, Script Utility, Group +{ + self->CastGroupSpell(caster, spell_id); } -XS(XS_Group_GroupMessage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_GroupMessage) { - dXSARGS; - if ((items != 3) && (items != 4)) // the 3 item version is kept for backwards compatability - Perl_croak(aTHX_ "Usage: Group::GroupMessage(THIS, Mob* sender, uint8 language, string message)"); // @categories Script Utility, Group - { - Group *THIS; - Mob *sender; - uint8 language; - char *message; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - sender = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "sender is not of type Mob"); - if (sender == nullptr) - Perl_croak(aTHX_ "sender is nullptr, avoiding crash."); - - if (items == 4) { - language = (uint8) SvUV(ST(2)); - if ((language >= MAX_PP_LANGUAGE) || (language < 0)) - language = 0; - message = (char *) SvPV_nolen(ST(3)); - THIS->GroupMessage(sender, language, 100, message); - } else { // if no language is specificed, send it in common - message = (char *) SvPV_nolen(ST(2)); - THIS->GroupMessage(sender, 0, 100, message); - } - } - XSRETURN_EMPTY; +void Perl_Group_SplitExp(Group* self, uint32_t exp, Mob* other) // @categories Account and Character, Script Utility, Group +{ + self->SplitExp(exp, other); } -XS(XS_Group_GetTotalGroupDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_GetTotalGroupDamage) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Group::GetTotalGroupDamage(THIS, Mob* other)"); // @categories Script Utility, Group - { - Group *THIS; - uint32 RETVAL; - dXSTARG; - Mob *other; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - RETVAL = THIS->GetTotalGroupDamage(other); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Group_GroupMessage(Group* self, Mob* sender, const char* message) // @categories Script Utility, Group +{ + // if no language is specificed, send it in common + self->GroupMessage(sender, 0, 100, message); } -XS(XS_Group_SplitMoney); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_SplitMoney) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: Group::SplitMoney(THIS, uint32 copper, uint32 silver, uint32 gold, uint32 platinum)"); // @categories Currency and Points, Script Utility, Group - { - Group *THIS; - uint32 copper = (uint32) SvUV(ST(1)); - uint32 silver = (uint32) SvUV(ST(2)); - uint32 gold = (uint32) SvUV(ST(3)); - uint32 platinum = (uint32) SvUV(ST(4)); - VALIDATE_THIS_IS_GROUP; - THIS->SplitMoney(copper, silver, gold, platinum); - } - XSRETURN_EMPTY; -} - -XS(XS_Group_SetLeader); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_SetLeader) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Group::SetLeader(THIS, Mob* new_leader)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - Mob *newleader; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - newleader = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "newleader is not of type Mob"); - if (newleader == nullptr) - Perl_croak(aTHX_ "newleader is nullptr, avoiding crash."); - - THIS->SetLeader(newleader); - } - XSRETURN_EMPTY; -} - -XS(XS_Group_GetLeader); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_GetLeader) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Group::GetLeader(THIS)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - Mob *RETVAL; - VALIDATE_THIS_IS_GROUP; - RETVAL = THIS->GetLeader(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Group_GetLeaderName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_GetLeaderName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Group::GetLeaderName(THIS)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - const char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_GROUP; - RETVAL = THIS->GetLeaderName(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Group_SendHPPacketsTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_SendHPPacketsTo) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Group::SendHPPacketsTo(THIS, Mob* new_member)"); // @categories Script Utility, Group - { - Group *THIS; - Mob *newmember; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - newmember = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "newmember is not of type Mob"); - if (newmember == nullptr) - Perl_croak(aTHX_ "newmember is nullptr, avoiding crash."); - - THIS->SendHPManaEndPacketsTo(newmember); - } - XSRETURN_EMPTY; -} - -XS(XS_Group_SendHPPacketsFrom); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_SendHPPacketsFrom) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Group::SendHPPacketsFrom(THIS, Mob* new_member)"); // @categories Script Utility, Group - { - Group *THIS; - Mob *newmember; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - newmember = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "newmember is not of type Mob"); - if (newmember == nullptr) - Perl_croak(aTHX_ "newmember is nullptr, avoiding crash."); - - THIS->SendHPPacketsFrom(newmember); - } - XSRETURN_EMPTY; -} - -XS(XS_Group_IsLeader); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_IsLeader) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Group::IsLeader(THIS, Mob* target)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - bool RETVAL; - Mob *leadertest; - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - leadertest = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "leadertest is not of type Mob"); - if (leadertest == nullptr) - Perl_croak(aTHX_ "leadertest is nullptr, avoiding crash."); - - RETVAL = THIS->IsLeader(leadertest); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Group_GroupCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_GroupCount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Group::GroupCount(THIS)"); // @categories Script Utility, Group - { - Group *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_GROUP; - RETVAL = THIS->GroupCount(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Group_GetHighestLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_GetHighestLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Group::GetHighestLevel(THIS)"); // @categories Script Utility, Group - { - Group *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_GROUP; - RETVAL = THIS->GetHighestLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Group_TeleportGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_TeleportGroup) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: Group::TeleportGroup(THIS, Mob* sender, uint32 zone_id, float x, float y, float z, float heading)"); // @categories Script Utility, Group - { - Group *THIS; - Mob *sender; - uint32 zoneID = (uint32) SvUV(ST(2)); - float x = (float) SvNV(ST(3)); - float y = (float) SvNV(ST(4)); - float z = (float) SvNV(ST(5)); - float heading = (float) SvNV(ST(6)); - VALIDATE_THIS_IS_GROUP; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - sender = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "sender is not of type Mob"); - if (sender == nullptr) - Perl_croak(aTHX_ "sender is nullptr, avoiding crash."); - - THIS->TeleportGroup(sender, zoneID, 0, x, y, z, heading); - } - XSRETURN_EMPTY; -} - -XS(XS_Group_GetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Group_GetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Group::GetID(THIS)"); // @categories Script Utility, Group - { - Group *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_GROUP; - RETVAL = THIS->GetID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Group_GetMember); -XS(XS_Group_GetMember) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Group::GetMember(THIS, int group_index)"); // @categories Account and Character, Script Utility, Group - { - Group *THIS; - Mob *member; - Client *RETVAL = nullptr; - dXSTARG; - VALIDATE_THIS_IS_GROUP; - int index = (int) SvUV(ST(1)); - if (index < 0 || index > 5) - RETVAL = nullptr; - else { - member = THIS->members[index]; - if (member != nullptr) - RETVAL = member->CastToClient(); - } - - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Group_DoesAnyMemberHaveExpeditionLockout); -XS(XS_Group_DoesAnyMemberHaveExpeditionLockout) { - dXSARGS; - if (items != 3 && items != 4) { - Perl_croak(aTHX_ "Usage: Group::DoesAnyMemberHaveExpeditionLockout(THIS, string expedition_name, string event_name, [int max_check_count = 0])"); +void Perl_Group_GroupMessage(Group* self, Mob* sender, uint8_t language, const char* message) // @categories Script Utility, Group +{ + if (!EQ::ValueWithin(language, 0, (MAX_PP_LANGUAGE - 1))) { + language = 0; } - Group* THIS = nullptr; - VALIDATE_THIS_IS_GROUP; - std::string expedition_name(SvPV_nolen(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - int max_check_count = (items == 4) ? static_cast(SvIV(ST(3))) : 0; - - bool result = THIS->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count); - ST(0) = boolSV(result); - XSRETURN(1); + self->GroupMessage(sender, language, 100, message); } -#ifdef __cplusplus -extern "C" -#endif -XS(boot_Group); /* prototype to pass -Wmissing-prototypes */ -XS(boot_Group) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; +uint32_t Perl_Group_GetTotalGroupDamage(Group* self, Mob* other) // @categories Script Utility, Group +{ + return self->GetTotalGroupDamage(other); +} - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; +void Perl_Group_SplitMoney(Group* self, uint32 copper, uint32 silver, uint32 gold, uint32 platinum) // @categories Currency and Points, Script Utility, Group +{ + self->SplitMoney(copper, silver, gold, platinum); +} - //add the strcpy stuff to get rid of const warnings.... +void Perl_Group_SplitMoney(Group* self, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client* splitter) // @categories Currency and Points, Script Utility, Group +{ + self->SplitMoney(copper, silver, gold, platinum, splitter); +} - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "CastGroupSpell"), XS_Group_CastGroupSpell, file, "$$$"); - newXSproto(strcpy(buf, "DisbandGroup"), XS_Group_DisbandGroup, file, "$"); - newXSproto(strcpy(buf, "DoesAnyMemberHaveExpeditionLockout"), XS_Group_DoesAnyMemberHaveExpeditionLockout, file, "$$$;$"); - newXSproto(strcpy(buf, "GetHighestLevel"), XS_Group_GetHighestLevel, file, "$"); - newXSproto(strcpy(buf, "GetID"), XS_Group_GetID, file, "$"); - newXSproto(strcpy(buf, "GetLeader"), XS_Group_GetLeader, file, "$"); - newXSproto(strcpy(buf, "GetLeaderName"), XS_Group_GetLeaderName, file, "$"); - newXSproto(strcpy(buf, "GetMember"), XS_Group_GetMember, file, "$$"); - newXSproto(strcpy(buf, "GetTotalGroupDamage"), XS_Group_GetTotalGroupDamage, file, "$$"); - newXSproto(strcpy(buf, "GroupCount"), XS_Group_GroupCount, file, "$"); - newXSproto(strcpy(buf, "GroupMessage"), XS_Group_GroupMessage, file, "$$$"); - newXSproto(strcpy(buf, "IsGroupMember"), XS_Group_IsGroupMember, file, "$$"); - newXSproto(strcpy(buf, "IsLeader"), XS_Group_IsLeader, file, "$$"); - newXSproto(strcpy(buf, "SendHPPacketsFrom"), XS_Group_SendHPPacketsFrom, file, "$$"); - newXSproto(strcpy(buf, "SendHPPacketsTo"), XS_Group_SendHPPacketsTo, file, "$$"); - newXSproto(strcpy(buf, "SetLeader"), XS_Group_SetLeader, file, "$$"); - newXSproto(strcpy(buf, "SplitExp"), XS_Group_SplitExp, file, "$$$"); - newXSproto(strcpy(buf, "SplitMoney"), XS_Group_SplitMoney, file, "$$$$$"); - newXSproto(strcpy(buf, "TeleportGroup"), XS_Group_TeleportGroup, file, "$$$$$$$"); - XSRETURN_YES; +void Perl_Group_SetLeader(Group* self, Mob* new_leader) // @categories Account and Character, Script Utility, Group +{ + self->SetLeader(new_leader); +} + +Mob* Perl_Group_GetLeader(Group* self) // @categories Account and Character, Script Utility, Group +{ + return self->GetLeader(); +} + +std::string Perl_Group_GetLeaderName(Group* self) // @categories Account and Character, Script Utility, Group +{ + return self->GetLeaderName(); +} + +void Perl_Group_SendHPPacketsTo(Group* self, Mob* new_member) // @categories Script Utility, Group +{ + self->SendHPManaEndPacketsTo(new_member); +} + +void Perl_Group_SendHPPacketsFrom(Group* self, Mob* new_member) // @categories Script Utility, Group +{ + self->SendHPPacketsFrom(new_member); +} + +bool Perl_Group_IsLeader(Group* self, Mob* c) // @categories Account and Character, Script Utility, Group +{ + return self->IsLeader(c); +} + +bool Perl_Group_IsLeader(Group* self, const char* name) // @categories Account and Character, Script Utility, Group +{ + return self->IsLeader(name); +} + +int Perl_Group_GroupCount(Group* self) // @categories Script Utility, Group +{ + return self->GroupCount(); +} + +uint32_t Perl_Group_GetHighestLevel(Group* self) // @categories Script Utility, Group +{ + return self->GetHighestLevel(); +} + +void Perl_Group_TeleportGroup(Group* self, Mob* sender, uint32 zone_id, float x, float y, float z, float heading) // @categories Script Utility, Group +{ + self->TeleportGroup(sender, zone_id, 0, x, y, z, heading); +} + +uint32_t Perl_Group_GetID(Group* self) // @categories Script Utility, Group +{ + return self->GetID(); +} + +Client* Perl_Group_GetMember(Group* self, int member_index) // @categories Account and Character, Script Utility, Group +{ + Mob* member = nullptr; + if (EQ::ValueWithin(member_index, 0, 5)) { + member = self->members[member_index]; + } + + return member ? member->CastToClient() : nullptr; +} + +bool Perl_Group_DoesAnyMemberHaveExpeditionLockout(Group* self, std::string expedition_name, std::string event_name) +{ + return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name); +} + +bool Perl_Group_DoesAnyMemberHaveExpeditionLockout(Group* self, std::string expedition_name, std::string event_name, int max_check_count) +{ + return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count); +} + +uint32_t Perl_Group_GetLowestLevel(Group* self) // @categories Script Utility, Group +{ + return self->GetLowestLevel(); +} + +uint32_t Perl_Group_GetAverageLevel(Group* self) // @categories Script Utility, Group +{ + return self->GetAvgLevel(); +} + +void perl_register_group() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Group"); + package.add("CastGroupSpell", &Perl_Group_CastGroupSpell); + package.add("DisbandGroup", &Perl_Group_DisbandGroup); + package.add("DoesAnyMemberHaveExpeditionLockout", (bool(*)(Group*, std::string, std::string))&Perl_Group_DoesAnyMemberHaveExpeditionLockout); + package.add("DoesAnyMemberHaveExpeditionLockout", (bool(*)(Group*, std::string, std::string, int))&Perl_Group_DoesAnyMemberHaveExpeditionLockout); + package.add("GetAverageLevel", &Perl_Group_GetAverageLevel); + package.add("GetHighestLevel", &Perl_Group_GetHighestLevel); + package.add("GetID", &Perl_Group_GetID); + package.add("GetLeader", &Perl_Group_GetLeader); + package.add("GetLeaderName", &Perl_Group_GetLeaderName); + package.add("GetLowestLevel", &Perl_Group_GetLowestLevel); + package.add("GetMember", &Perl_Group_GetMember); + package.add("GetTotalGroupDamage", &Perl_Group_GetTotalGroupDamage); + package.add("GroupCount", &Perl_Group_GroupCount); + package.add("GroupMessage", (void(*)(Group*, Mob*, const char*))&Perl_Group_GroupMessage); + package.add("GroupMessage", (void(*)(Group*, Mob*, uint8_t, const char*))&Perl_Group_GroupMessage); + package.add("IsGroupMember", (bool(*)(Group*, const char*))&Perl_Group_IsGroupMember); + package.add("IsGroupMember", (bool(*)(Group*, Mob*))&Perl_Group_IsGroupMember); + package.add("IsLeader", (bool(*)(Group*, const char*))&Perl_Group_IsLeader); + package.add("IsLeader", (bool(*)(Group*, Mob*))&Perl_Group_IsLeader); + package.add("SendHPPacketsFrom", &Perl_Group_SendHPPacketsFrom); + package.add("SendHPPacketsTo", &Perl_Group_SendHPPacketsTo); + package.add("SetLeader", &Perl_Group_SetLeader); + package.add("SplitExp", &Perl_Group_SplitExp); + package.add("SplitMoney", (void(*)(Group*, uint32, uint32, uint32, uint32))&Perl_Group_SplitMoney); + package.add("SplitMoney", (void(*)(Group*, uint32, uint32, uint32, uint32, Client*))&Perl_Group_SplitMoney); + package.add("TeleportGroup", &Perl_Group_TeleportGroup); } #endif //EMBPERL_XS_CLASSES - diff --git a/zone/perl_hateentry.cpp b/zone/perl_hateentry.cpp index 388c9313a..8b8ec0ff8 100644 --- a/zone/perl_hateentry.cpp +++ b/zone/perl_hateentry.cpp @@ -4,104 +4,33 @@ #ifdef EMBPERL_XS_CLASSES #include "../common/global_define.h" -#include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "../common/linked_list.h" +#include "embperl.h" #include "hate_list.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_HATE \ - do { \ - if (sv_derived_from(ST(0), "HateEntry")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(struct_HateList*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type HateEntry"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_HateEntry_GetEnt); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HateEntry_GetEnt) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: HateEntry::GetEnt(THIS)"); // @categories Script Utility, Hate and Aggro - { - struct_HateList *THIS; - Mob *RETVAL; - VALIDATE_THIS_IS_HATE; - RETVAL = THIS->entity_on_hatelist; - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); +Mob* Perl_HateEntry_GetEnt(struct_HateList* self) // @categories Script Utility, Hate and Aggro +{ + return self->entity_on_hatelist; } -XS(XS_HateEntry_GetHate); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HateEntry_GetHate) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: HateEntry::GetHate(THIS)"); // @categories Script Utility, Hate and Aggro - { - struct_HateList *THIS; - int64 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_HATE; - RETVAL = THIS->stored_hate_amount; - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +int64_t Perl_HateEntry_GetHate(struct_HateList* self) // @categories Script Utility, Hate and Aggro +{ + return self->stored_hate_amount; } -XS(XS_HateEntry_GetDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HateEntry_GetDamage) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: HateEntry::GetDamage(THIS)"); // @categories Script Utility, Hate and Aggro - { - struct_HateList *THIS; - int64 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_HATE; - RETVAL = THIS->hatelist_damage; - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +int64_t Perl_HateEntry_GetDamage(struct_HateList* self) // @categories Script Utility, Hate and Aggro +{ + return self->hatelist_damage; } -#ifdef __cplusplus -extern "C" -#endif +void perl_register_hateentry() +{ + perl::interpreter perl(PERL_GET_THX); -XS(boot_HateEntry); -XS(boot_HateEntry) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "GetDamage"), XS_HateEntry_GetDamage, file, "$"); - newXSproto(strcpy(buf, "GetEnt"), XS_HateEntry_GetEnt, file, "$"); - newXSproto(strcpy(buf, "GetHate"), XS_HateEntry_GetHate, file, "$"); - XSRETURN_YES; + auto package = perl.new_class("HateEntry"); + package.add("GetDamage", &Perl_HateEntry_GetDamage); + package.add("GetEnt", &Perl_HateEntry_GetEnt); + package.add("GetHate", &Perl_HateEntry_GetHate); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_inventory.cpp b/zone/perl_inventory.cpp index 44323229b..39fd7665c 100644 --- a/zone/perl_inventory.cpp +++ b/zone/perl_inventory.cpp @@ -4,525 +4,217 @@ #ifdef EMBPERL_XS_CLASSES #include "../common/global_define.h" +#include "../common/inventory_profile.h" #include "embperl.h" -#ifdef seed -#undef seed -#endif - -#include "../common/inventory_profile.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_INVENTORY \ - do { \ - if (sv_derived_from(ST(0), "Inventory")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(EQ::InventoryProfile*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type EQ::InventoryProfile"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Inventory_CanItemFitInContainer); -XS(XS_Inventory_CanItemFitInContainer) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Inventory::CanItemFitInContainer(THIS, ItemInstance item_to_check, ItemInstance container_to_check)"); - { - EQ::InventoryProfile* THIS; - bool can_fit = false; - EQ::ItemInstance* item_to_check = (EQ::ItemInstance*)SvIV((SV*)SvRV(ST(1))); - EQ::ItemInstance* container_to_check = (EQ::ItemInstance*)SvIV((SV*)SvRV(ST(2))); - const EQ::ItemData* item_data = item_to_check->GetItem(); - const EQ::ItemData* container_data = container_to_check->GetItem(); - VALIDATE_THIS_IS_INVENTORY; - can_fit = THIS->CanItemFitInContainer(item_data, container_data); - ST(0) = boolSV(can_fit); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Inventory_CanItemFitInContainer(EQ::InventoryProfile* self, EQ::ItemInstance* item_to_check, EQ::ItemInstance* container_to_check) +{ + const EQ::ItemData* item_data = item_to_check->GetItem(); + const EQ::ItemData* container_data = container_to_check->GetItem(); + return self->CanItemFitInContainer(item_data, container_data); } -XS(XS_Inventory_CheckNoDrop); -XS(XS_Inventory_CheckNoDrop) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::CheckNoDrop(THIS, int16 slot_id)"); - { - EQ::InventoryProfile* THIS; - bool no_drop = false; - int16 slot_id = (int16)SvIV(ST(1)); - VALIDATE_THIS_IS_INVENTORY; - no_drop = THIS->CheckNoDrop(slot_id); - ST(0) = boolSV(no_drop); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Inventory_CheckNoDrop(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->CheckNoDrop(slot_id); } -XS(XS_Inventory_DeleteItem); -XS(XS_Inventory_DeleteItem) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Inventory::DeleteItem(THIS, int16 slot_id, [uint8 quantity = 0])"); - { - EQ::InventoryProfile* THIS; - bool item_deleted = false; - int16 slot_id = (int16)SvIV(ST(1)); - uint8 quantity = 0; - VALIDATE_THIS_IS_INVENTORY; - if (items > 2) - quantity = (uint8)SvUV(ST(2)); - - item_deleted = THIS->DeleteItem(slot_id, quantity); - ST(0) = boolSV(item_deleted); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Inventory_DeleteItem(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->DeleteItem(slot_id); } -XS(XS_Inventory_FindFreeSlot); -XS(XS_Inventory_FindFreeSlot) { - dXSARGS; - if (items < 3 || items > 5) - Perl_croak(aTHX_ "Usage: Inventory::FindFreeSlot(THIS, bool is_for_bag, bool try_cursor, [uint8 min_size = 0, bool is_arrow = false])"); - { - EQ::InventoryProfile* THIS; - int16 free_slot; - bool is_for_bag = (bool)SvNV(ST(1)); - bool try_cursor = (bool)SvNV(ST(2)); - uint8 min_size = 0; - bool is_arrow = false; - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - if (items > 3) - min_size = (uint8)SvUV(ST(3)); - if (items > 4) - is_arrow = (bool)SvNV(ST(4)); - - free_slot = THIS->FindFreeSlot(is_for_bag, try_cursor, min_size, is_arrow); - XSprePUSH; - PUSHi((IV)free_slot); - } - XSRETURN(1); +bool Perl_Inventory_DeleteItem(EQ::InventoryProfile* self, int16_t slot_id, uint8_t quantity) +{ + return self->DeleteItem(slot_id, quantity); } -XS(XS_Inventory_GetBagIndex); -XS(XS_Inventory_GetBagIndex) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::GetBagIndex(THIS, int16 slot_id)"); - { - EQ::InventoryProfile* THIS; - uint8 bag_index; - int16 slot_id = (int16)SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - bag_index = THIS->CalcBagIdx(slot_id); - XSprePUSH; - PUSHu((UV) bag_index); - } - XSRETURN(1); +int Perl_Inventory_FindFreeSlot(EQ::InventoryProfile* self, bool is_for_bag, bool try_cursor) +{ + return self->FindFreeSlot(is_for_bag, try_cursor); } -XS(XS_Inventory_GetItem); -XS(XS_Inventory_GetItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::GetItem(THIS, int16 slot_id)"); - { - EQ::InventoryProfile* THIS; - EQ::ItemInstance* item; - int16 slot_id = (int16)SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - item = THIS->GetItem(slot_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "QuestItem", (void*)item); - } - XSRETURN(1); +int Perl_Inventory_FindFreeSlot(EQ::InventoryProfile* self, bool is_for_bag, bool try_cursor, uint8_t min_size) +{ + return self->FindFreeSlot(is_for_bag, try_cursor, min_size); } -XS(XS_Inventory_GetMaterialFromSlot); -XS(XS_Inventory_GetMaterialFromSlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::GetMaterialFromSlot(THIS, int16 slot_id)"); - { - EQ::InventoryProfile* THIS; - uint8 material; - int16 slot_id = (int16)SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - material = THIS->CalcMaterialFromSlot(slot_id); - XSprePUSH; - PUSHu((UV) material); - } - XSRETURN(1); +int Perl_Inventory_FindFreeSlot(EQ::InventoryProfile* self, bool is_for_bag, bool try_cursor, uint8_t min_size, bool is_arrow) +{ + return self->FindFreeSlot(is_for_bag, try_cursor, min_size, is_arrow); } -XS(XS_Inventory_GetSlotByItemInst); -XS(XS_Inventory_GetSlotByItemInst) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::GetSlotByItemInst(THIS, ItemInstance item)"); - { - EQ::InventoryProfile* THIS; - int slot_id; - EQ::ItemInstance* item = (EQ::ItemInstance*)SvIV((SV*)SvRV(ST(1))); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - slot_id = THIS->GetSlotByItemInst(item); - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +int Perl_Inventory_GetBagIndex(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->CalcBagIdx(slot_id); } -XS(XS_Inventory_GetSlotFromMaterial); -XS(XS_Inventory_GetSlotFromMaterial) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::GetSlotFromMaterial(THIS, uint8 material)"); - { - EQ::InventoryProfile* THIS; - int16 slot_id; - uint8 material = (uint8)SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - slot_id = THIS->CalcSlotFromMaterial(material); - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +EQ::ItemInstance* Perl_Inventory_GetItem(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->GetItem(slot_id); } -XS(XS_Inventory_GetSlotID); -XS(XS_Inventory_GetSlotID) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Inventory::GetSlotID(THIS, int16 slot_id, [uint8 bag_index])"); - { - EQ::InventoryProfile* THIS; - int16 slot_id = (int16)SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - if (items == 2) - slot_id = THIS->CalcSlotId(slot_id); - - if (items == 3) { - uint8 bag_index = (uint8)SvUV(ST(2)); - slot_id = THIS->CalcSlotId(slot_id, bag_index); - } - - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +int Perl_Inventory_GetMaterialFromSlot(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->CalcMaterialFromSlot(slot_id); } -XS(XS_Inventory_HasItem); -XS(XS_Inventory_HasItem) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Inventory::HasItem(THIS, uint32 item_id, [uint8 quantity, uint8 where])"); - { - EQ::InventoryProfile* THIS; - int16 slot_id; - uint32 item_id = (uint32)SvUV(ST(1)); - uint8 quantity = 0; - uint8 where_to_look = 0xFF; - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - if (items > 2) - quantity = (uint8)SvUV(ST(2)); - if (items > 3) - where_to_look = (uint8)SvUV(ST(3)); - - slot_id = THIS->HasItem(item_id, quantity, where_to_look); - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +int Perl_Inventory_GetSlotByItemInst(EQ::InventoryProfile* self, EQ::ItemInstance* item) +{ + return self->GetSlotByItemInst(item); } -XS(XS_Inventory_HasItemByLoreGroup); -XS(XS_Inventory_HasItemByLoreGroup) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Inventory::HasItemByLoreGroup(THIS, uint32 loregroup, [uint8 where])"); - { - EQ::InventoryProfile* THIS; - int16 slot_id; - uint32 loregroup = (uint32)SvUV(ST(1)); - uint8 where_to_look = 0xFF; - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - if (items > 2) - where_to_look = (uint8)SvUV(ST(2)); - - slot_id = THIS->HasItemByLoreGroup(loregroup, where_to_look); - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +int Perl_Inventory_GetSlotFromMaterial(EQ::InventoryProfile* self, uint8_t material) +{ + return self->CalcSlotFromMaterial(material); } -XS(XS_Inventory_HasItemByUse); -XS(XS_Inventory_HasItemByUse) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Inventory::HasItemByUse(THIS, uint8 use, uint8 quantity, [uint8 where])"); - { - EQ::InventoryProfile* THIS; - int16 slot_id; - uint8 item_use = (uint8)SvUV(ST(1)); - uint8 quantity = (uint8)SvUV(ST(2)); - uint8 where_to_look = 0xFF; - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - if (items > 3) - where_to_look = (uint8)SvUV(ST(3)); - - slot_id = THIS->HasItemByUse(item_use, quantity, where_to_look); - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +int Perl_Inventory_GetSlotID(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->CalcSlotId(slot_id); } -XS(XS_Inventory_HasSpaceForItem); -XS(XS_Inventory_HasSpaceForItem) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Inventory::HasSpaceForItem(THIS, ItemInstance item_to_check, uint8 quantity)"); - { - EQ::InventoryProfile* THIS; - bool has_space = false; - EQ::ItemInstance* item_to_check = (EQ::ItemInstance*)SvIV((SV*)SvRV(ST(1))); - uint8 quantity = (uint8)SvUV(ST(2)); - const EQ::ItemData* item_data = item_to_check->GetItem(); - VALIDATE_THIS_IS_INVENTORY; - has_space = THIS->HasSpaceForItem(item_data, quantity); - ST(0) = boolSV(has_space); - sv_2mortal(ST(0)); - } - XSRETURN(1); +int Perl_Inventory_GetSlotID(EQ::InventoryProfile* self, int16_t slot_id, uint8_t bag_index) +{ + return self->CalcSlotId(slot_id, bag_index); } -XS(XS_Inventory_PopItem); -XS(XS_Inventory_PopItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::PopItem(THIS, int16 slot_id)"); - { - EQ::InventoryProfile* THIS; - EQ::ItemInstance* item; - int16 slot_id = (int16)SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - item = THIS->PopItem(slot_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "QuestItem", (void*)item); - } - XSRETURN(1); +int Perl_Inventory_HasItem(EQ::InventoryProfile* self, uint32_t item_id) +{ + return self->HasItem(item_id); } -XS(XS_Inventory_SupportsContainers); -XS(XS_Inventory_SupportsContainers) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::SupportsContainers(THIS, int16 slot_id)"); - { - EQ::InventoryProfile* THIS; - bool supports_containers = false; - int16 slot_id = (int16)SvIV(ST(1)); - VALIDATE_THIS_IS_INVENTORY; - supports_containers = THIS->SupportsContainers(slot_id); - ST(0) = boolSV(supports_containers); - sv_2mortal(ST(0)); - } - XSRETURN(1); +int Perl_Inventory_HasItem(EQ::InventoryProfile* self, uint32_t item_id, uint8_t quantity) +{ + return self->HasItem(item_id, quantity); } -XS(XS_Inventory_SwapItem); -XS(XS_Inventory_SwapItem) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Inventory::SwapItem(THIS, int16 source_slot_id, int16 destination_slot_id)"); - { - EQ::InventoryProfile* THIS; - bool item_swapped = false; - int16 source_slot_id = (int16)SvIV(ST(1)); - int16 destination_slot_id = (int16)SvIV(ST(2)); - EQ::InventoryProfile::SwapItemFailState fail_state = EQ::InventoryProfile::swapInvalid; - VALIDATE_THIS_IS_INVENTORY; - item_swapped = THIS->SwapItem(source_slot_id, destination_slot_id, fail_state); - ST(0) = boolSV(item_swapped); - sv_2mortal(ST(0)); - } - XSRETURN(1); +int Perl_Inventory_HasItem(EQ::InventoryProfile* self, uint32_t item_id, uint8_t quantity, uint8_t where_to_look) +{ + return self->HasItem(item_id, quantity, where_to_look); } -XS(XS_Inventory_PushCursor); -XS(XS_Inventory_PushCursor) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::PushCursor(THIS, ItemInstance item)"); - { - EQ::InventoryProfile* THIS; - int16 slot_id; - EQ::ItemInstance* item = (EQ::ItemInstance*)SvIV((SV*)SvRV(ST(1))); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - if (item) - slot_id = THIS->PushCursor(*item); - else - slot_id = 0; - - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +int Perl_Inventory_HasItemByLoreGroup(EQ::InventoryProfile* self, uint32_t loregroup) +{ + return self->HasItemByLoreGroup(loregroup); } -XS(XS_Inventory_PutItem); -XS(XS_Inventory_PutItem) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Inventory::PutItem(THIS, int16 slot_id, ItemInstance item)"); - { - EQ::InventoryProfile* THIS; - int16 slot_id = (int16)SvUV(ST(1)); - EQ::ItemInstance* item = (EQ::ItemInstance*)SvIV((SV*)SvRV(ST(2))); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - if (item) - slot_id = THIS->PutItem(slot_id, *item); - else - slot_id = 0; - - XSprePUSH; - PUSHi((IV) slot_id); - } - XSRETURN(1); +int Perl_Inventory_HasItemByLoreGroup(EQ::InventoryProfile* self, uint32_t loregroup, uint8_t where_to_look) +{ + return self->HasItemByLoreGroup(loregroup, where_to_look); } -XS(XS_Inventory_HasAugmentEquippedByID); -XS(XS_Inventory_HasAugmentEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::HasAugmentEquippedByID(THIS, uint32 item_id)"); - { - EQ::InventoryProfile* THIS; - bool has_equipped = false; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_INVENTORY; - has_equipped = THIS->HasAugmentEquippedByID(item_id); - ST(0) = boolSV(has_equipped); - sv_2mortal(ST(0)); - } - XSRETURN(1); +int Perl_Inventory_HasItemByUse(EQ::InventoryProfile* self, uint8_t item_use, uint8_t quantity) +{ + return self->HasItemByUse(item_use, quantity); } -XS(XS_Inventory_CountAugmentEquippedByID); -XS(XS_Inventory_CountAugmentEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::CountAugmentEquippedByID(THIS, uint32 item_id)"); - { - EQ::InventoryProfile* THIS; - int quantity = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - quantity = THIS->CountAugmentEquippedByID(item_id); - XSprePUSH; - PUSHi((IV) quantity); - } - XSRETURN(1); +int Perl_Inventory_HasItemByUse(EQ::InventoryProfile* self, uint8_t item_use, uint8_t quantity, uint8_t where_to_look) +{ + return self->HasItemByUse(item_use, quantity, where_to_look); } -XS(XS_Inventory_HasItemEquippedByID); -XS(XS_Inventory_HasItemEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::HasItemEquippedByID(THIS, uint32 item_id)"); - { - EQ::InventoryProfile* THIS; - bool has_equipped = false; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_INVENTORY; - has_equipped = THIS->HasItemEquippedByID(item_id); - ST(0) = boolSV(has_equipped); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Inventory_HasSpaceForItem(EQ::InventoryProfile* self, EQ::ItemInstance* item_to_check, uint8_t quantity) +{ + const EQ::ItemData* item_data = item_to_check->GetItem(); + return self->HasSpaceForItem(item_data, quantity); } -XS(XS_Inventory_CountItemEquippedByID); -XS(XS_Inventory_CountItemEquippedByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Inventory::CountItemEquippedByID(THIS, uint32 item_id)"); - { - EQ::InventoryProfile* THIS; - int quantity = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_INVENTORY; - quantity = THIS->CountItemEquippedByID(item_id); - XSprePUSH; - PUSHi((IV) quantity); - } - XSRETURN(1); +EQ::ItemInstance* Perl_Inventory_PopItem(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->PopItem(slot_id); } -#ifdef __cplusplus -extern "C" -#endif +bool Perl_Inventory_SupportsContainers(EQ::InventoryProfile* self, int16_t slot_id) +{ + return self->SupportsContainers(slot_id); +} -XS(boot_Inventory); -XS(boot_Inventory) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); +bool Perl_Inventory_SwapItem(EQ::InventoryProfile* self, int16_t source_slot_id, int16_t destination_slot_id) +{ + EQ::InventoryProfile::SwapItemFailState fail_state = EQ::InventoryProfile::swapInvalid; + return self->SwapItem(source_slot_id, destination_slot_id, fail_state); +} - char buf[128]; - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "CanItemFitInContainer"), XS_Inventory_CanItemFitInContainer, file, "$$$"); - newXSproto(strcpy(buf, "CountAugmentEquippedByID"), XS_Inventory_CountAugmentEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "CountItemEquippedByID"), XS_Inventory_CountItemEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "CheckNoDrop"), XS_Inventory_CheckNoDrop, file, "$$"); - newXSproto(strcpy(buf, "DeleteItem"), XS_Inventory_DeleteItem, file, "$$;$"); - newXSproto(strcpy(buf, "FindFreeSlot"), XS_Inventory_FindFreeSlot, file, "$$$;$$"); - newXSproto(strcpy(buf, "GetBagIndex"), XS_Inventory_GetBagIndex, file, "$$"); - newXSproto(strcpy(buf, "GetItem"), XS_Inventory_GetItem, file, "$$;$"); - newXSproto(strcpy(buf, "GetMaterialFromSlot"), XS_Inventory_GetMaterialFromSlot, file, "$$"); - newXSproto(strcpy(buf, "GetSlotByItemInst"), XS_Inventory_GetSlotByItemInst, file, "$$"); - newXSproto(strcpy(buf, "GetSlotFromMaterial"), XS_Inventory_GetSlotFromMaterial, file, "$$"); - newXSproto(strcpy(buf, "GetSlotID"), XS_Inventory_GetSlotID, file, "$$;$"); - newXSproto(strcpy(buf, "HasAugmentEquippedByID"), XS_Inventory_HasAugmentEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "HasItem"), XS_Inventory_HasItem, file, "$$;$$"); - newXSproto(strcpy(buf, "HasItemByLoreGroup"), XS_Inventory_HasItemByLoreGroup, file, "$$;$"); - newXSproto(strcpy(buf, "HasItemByUse"), XS_Inventory_HasItemByUse, file, "$$;$$"); - newXSproto(strcpy(buf, "HasItemEquippedByID"), XS_Inventory_HasItemEquippedByID, file, "$$"); - newXSproto(strcpy(buf, "HasSpaceForItem"), XS_Inventory_HasSpaceForItem, file, "$$$"); - newXSproto(strcpy(buf, "PopItem"), XS_Inventory_PopItem, file, "$$"); - newXSproto(strcpy(buf, "PushCursor"), XS_Inventory_PushCursor, file, "$$"); - newXSproto(strcpy(buf, "PutItem"), XS_Inventory_PutItem, file, "$$$"); - newXSproto(strcpy(buf, "SupportsContainers"), XS_Inventory_SupportsContainers, file, "$$"); - newXSproto(strcpy(buf, "SwapItem"), XS_Inventory_SwapItem, file, "$$$"); - XSRETURN_YES; +int Perl_Inventory_PushCursor(EQ::InventoryProfile* self, EQ::ItemInstance* item) +{ + return self->PushCursor(*item); +} + +int Perl_Inventory_PutItem(EQ::InventoryProfile* self, int16_t slot_id, EQ::ItemInstance* item) +{ + return self->PutItem(slot_id, *item); +} + +bool Perl_Inventory_HasAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) +{ + return self->HasAugmentEquippedByID(item_id); +} + +int Perl_Inventory_CountAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) +{ + return self->CountAugmentEquippedByID(item_id); +} + +bool Perl_Inventory_HasItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) +{ + return self->HasItemEquippedByID(item_id); +} + +int Perl_Inventory_CountItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) +{ + return self->CountItemEquippedByID(item_id); +} + +perl::array Perl_Inventory_GetAugmentIDsBySlotID(EQ::InventoryProfile* self, int16 slot_id) +{ + perl::array result; + auto augments = self->GetAugmentIDsBySlotID(slot_id); + + for (int i = 0; i < augments.size(); ++i) { + result.push_back(augments[i]); + } + + return result; +} + +void perl_register_inventory() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Inventory"); + package.add("CanItemFitInContainer", &Perl_Inventory_CanItemFitInContainer); + package.add("CountAugmentEquippedByID", &Perl_Inventory_CountAugmentEquippedByID); + package.add("CountItemEquippedByID", &Perl_Inventory_CountItemEquippedByID); + package.add("CheckNoDrop", &Perl_Inventory_CheckNoDrop); + package.add("DeleteItem", (bool(*)(EQ::InventoryProfile*, int16_t))&Perl_Inventory_DeleteItem); + package.add("DeleteItem", (bool(*)(EQ::InventoryProfile*, int16_t, uint8_t))&Perl_Inventory_DeleteItem); + package.add("FindFreeSlot", (int(*)(EQ::InventoryProfile*, bool, bool))&Perl_Inventory_FindFreeSlot); + package.add("FindFreeSlot", (int(*)(EQ::InventoryProfile*, bool, bool, uint8_t))&Perl_Inventory_FindFreeSlot); + package.add("FindFreeSlot", (int(*)(EQ::InventoryProfile*, bool, bool, uint8_t, bool))&Perl_Inventory_FindFreeSlot); + package.add("GetAugmentIDsBySlotID", &Perl_Inventory_GetAugmentIDsBySlotID); + package.add("GetBagIndex", &Perl_Inventory_GetBagIndex); + package.add("GetItem", &Perl_Inventory_GetItem); + package.add("GetMaterialFromSlot", &Perl_Inventory_GetMaterialFromSlot); + package.add("GetSlotByItemInst", &Perl_Inventory_GetSlotByItemInst); + package.add("GetSlotFromMaterial", &Perl_Inventory_GetSlotFromMaterial); + package.add("GetSlotID", (int(*)(EQ::InventoryProfile*, int16_t))&Perl_Inventory_GetSlotID); + package.add("GetSlotID", (int(*)(EQ::InventoryProfile*, int16_t, uint8_t))&Perl_Inventory_GetSlotID); + package.add("HasAugmentEquippedByID", &Perl_Inventory_HasAugmentEquippedByID); + package.add("HasItem", (int(*)(EQ::InventoryProfile*, uint32_t))&Perl_Inventory_HasItem); + package.add("HasItem", (int(*)(EQ::InventoryProfile*, uint32_t, uint8_t))&Perl_Inventory_HasItem); + package.add("HasItem", (int(*)(EQ::InventoryProfile*, uint32_t, uint8_t, uint8_t))&Perl_Inventory_HasItem); + package.add("HasItemByLoreGroup", (int(*)(EQ::InventoryProfile*, uint32_t))&Perl_Inventory_HasItemByLoreGroup); + package.add("HasItemByLoreGroup", (int(*)(EQ::InventoryProfile*, uint32_t, uint8_t))&Perl_Inventory_HasItemByLoreGroup); + package.add("HasItemByUse", (int(*)(EQ::InventoryProfile*, uint8_t, uint8_t))&Perl_Inventory_HasItemByUse); + package.add("HasItemByUse", (int(*)(EQ::InventoryProfile*, uint8_t, uint8_t, uint8_t))&Perl_Inventory_HasItemByUse); + package.add("HasItemEquippedByID", &Perl_Inventory_HasItemEquippedByID); + package.add("HasSpaceForItem", &Perl_Inventory_HasSpaceForItem); + package.add("PopItem", &Perl_Inventory_PopItem); + package.add("PushCursor", &Perl_Inventory_PushCursor); + package.add("PutItem", &Perl_Inventory_PutItem); + package.add("SupportsContainers", &Perl_Inventory_SupportsContainers); + package.add("SwapItem", &Perl_Inventory_SwapItem); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 767f67267..a97719b3d 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -3,7057 +3,3331 @@ #ifdef EMBPERL_XS_CLASSES #include "../common/global_define.h" +#include "../common/spdat.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - -typedef const char Const_char; - #include "mob.h" #include "client.h" -#include "../common/spdat.h" #include "dialogue_window.h" - -#ifdef BOTS #include "bot.h" -#endif -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_MOB \ - do { \ - if (sv_derived_from(ST(0), "Mob")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Mob*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Mob"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Mob_IsClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsClient) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsClient(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsClient(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsNPC) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsNPC(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsNPC(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsBot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsBot) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsBot(THIS)"); // @categories Script Utility - { - Mob* THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsBot(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsMob) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsMob(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsMob(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsCorpse); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsCorpse) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsCorpse(THIS)"); // @categories Script Utility, Corpse - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsCorpse(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsPlayerCorpse); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsPlayerCorpse) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsPlayerCorpse(THIS)"); // @categories Corpse - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsPlayerCorpse(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsNPCCorpse); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsNPCCorpse) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsNPCCorpse(THIS)"); // @categories Corpse - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsNPCCorpse(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsObject); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsObject) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsObject(THIS)"); // @categories Objects - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsObject(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsDoor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsDoor) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsDoor(THIS)"); // @categories Script Utility, Doors - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsDoor(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsTrap); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsTrap) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsTrap(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsTrap(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsBeacon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsBeacon) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsBeacon(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsBeacon(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CastToClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CastToClient) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CastToClient(THIS)"); // @categories Account and Character, Script Utility - { - Mob *THIS; - Client *RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CastToClient(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_CastToNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CastToNPC) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CastToNPC(THIS)"); // @categories Script Utility - { - Mob *THIS; - NPC *RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CastToNPC(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "NPC", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_CastToMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CastToMob) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CastToMob(THIS)"); // @categories Script Utility - { - Mob *THIS; - Mob *RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CastToMob(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_CastToCorpse); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CastToCorpse) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CastToCorpse(THIS)"); // @categories Script Utility, Corpse - { - Mob *THIS; - Corpse *RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CastToCorpse(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Corpse", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetID(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetName(THIS)"); // @categories Script Utility - { - Mob *THIS; - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetName(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_Depop); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Depop) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Mob::Depop(THIS, StartSpawnTimer = true)"); // @categories Spawns - { - Mob *THIS; - bool StartSpawnTimer; - VALIDATE_THIS_IS_MOB; - if (items < 2) - StartSpawnTimer = true; - else { - StartSpawnTimer = (bool) SvTRUE(ST(1)); - } - - THIS->Depop(StartSpawnTimer); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_RogueAssassinate); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RogueAssassinate) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::RogueAssassinate(THIS, other)"); // @categories Script Utility - { - Mob *THIS; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - THIS->RogueAssassinate(other); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_BehindMob); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_BehindMob) { - dXSARGS; - if (items < 1 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::BehindMob(THIS, Mob* other = 0, [float x = 0.0f], [float y= 0.0f])"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - Mob *other; - float playerx; - float playery; - VALIDATE_THIS_IS_MOB; - if (items < 2) - other = 0; - else { - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - } - - if (items < 3) - playerx = 0.0f; - else { - playerx = (float) SvNV(ST(2)); - } - - if (items < 4) - playery = 0.0f; - else { - playery = (float) SvNV(ST(3)); - } - - RETVAL = THIS->BehindMob(other, playerx, playery); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SetLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetLevel) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::SetLevel(THIS, uint8 in_level, [bool command = false])"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 in_level = (uint8) SvUV(ST(1)); - bool command; - VALIDATE_THIS_IS_MOB; - if (items < 3) - command = false; - else { - command = (bool) SvTRUE(ST(2)); - } - - THIS->SetLevel(in_level, command); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSkill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetSkill(THIS, int skill_id)"); // @categories Skills and Recipes, Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - EQ::skills::SkillType skill_num = (EQ::skills::SkillType) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSkill(skill_num); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SendWearChange); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SendWearChange) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SendWearChange(THIS, uint8 material_slot)"); // @categories Script Utility - { - Mob *THIS; - uint8 material_slot = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SendWearChange(material_slot); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetEquipment); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetEquipment) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetEquipment(THIS, uint8 material_slot)"); // @categories Inventory and Items - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint8 material_slot = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetEquippedItemFromTextureSlot(material_slot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetEquipmentMaterial); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetEquipmentMaterial) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetEquipmentMaterial(THIS, uint8 material_slot)"); // @categories Inventory and Items - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint8 material_slot = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetEquipmentMaterial(material_slot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetEquipmentColor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetEquipmentColor) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetEquipmentColor(THIS, uint8 material_slot)"); // @categories Inventory and Items - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint8 material_slot = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetEquipmentColor(material_slot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetArmorTint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetArmorTint) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetArmorTint(THIS, uint8 material_slot)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint8 material_slot = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetArmorTint(material_slot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsMoving); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsMoving) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsMoving(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsMoving(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GoToBind); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GoToBind) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GoToBind(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->GoToBind(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Gate); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Gate) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::Gate(THIS)"); // @categories Spells and Disciplines - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->Gate(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Attack); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Attack) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::Attack(THIS, Mob* other, [int hand = 13 [prim|sec]], [bool from_riposte = false])"); // @categories Script Utility, Hate and Aggro - { - Mob *THIS; - bool RETVAL; - Mob *other; - int Hand; - bool FromRiposte; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - if (items < 3) - Hand = 13; - else { - Hand = (int) SvIV(ST(2)); - } - - if (items < 4) - FromRiposte = false; - else { - FromRiposte = (bool) SvTRUE(ST(3)); - } - - RETVAL = THIS->Attack(other, Hand, FromRiposte); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_Damage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Damage) { - dXSARGS; - if (items < 5 || items > 8) - Perl_croak(aTHX_ "Usage: Mob::Damage(THIS, Mob* from, int64 damage, uint16 spell_id, int attack_skill, [bool avoidable = true], [int8 buffslot = -1], [bool buff_tic = false])"); // @categories Script Utility - { - Mob *THIS; - Mob *from; - int32 damage = (int32) SvIV(ST(2)); - uint16 spell_id = (uint16) SvUV(ST(3)); - EQ::skills::SkillType attack_skill = (EQ::skills::SkillType) SvUV(ST(4)); - bool avoidable; - int8 buffslot; - bool iBuffTic; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - from = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "from is not of type Mob"); - if (from == nullptr) - Perl_croak(aTHX_ "from is nullptr, avoiding crash."); - - if (items < 6) - avoidable = true; - else { - avoidable = (bool) SvTRUE(ST(5)); - } - - if (items < 7) - buffslot = -1; - else { - buffslot = (int8) SvIV(ST(6)); - } - - if (items < 8) - iBuffTic = false; - else { - iBuffTic = (bool) SvTRUE(ST(7)); - } - - THIS->Damage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_RangedAttack); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RangedAttack) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::RangedAttack(THIS, Mob* other)"); // @categories Skills and Recipes, Script Utility - { - Mob *THIS; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - THIS->RangedAttack(other); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ThrowingAttack); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ThrowingAttack) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::ThrowingAttack(THIS, Mob* other)"); // @categories Skills and Recipes, Script Utility - { - Mob *THIS; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - THIS->ThrowingAttack(other); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Heal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Heal) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::Heal(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->Heal(); - } - XSRETURN_EMPTY; -} - - -XS(XS_Mob_HealDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_HealDamage) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::HealDamage(THIS, int64 amount, [Mob* caster = 0])"); // @categories Script Utility - { - Mob *THIS; - int64 heal_amt = (int64) SvIV(ST(1)); - Mob *caster = nullptr; - VALIDATE_THIS_IS_MOB; - if (items == 3) { - if (sv_derived_from(ST(2), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(2))); - caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "caster is not of type Mob"); - if (caster == nullptr) - Perl_croak(aTHX_ "caster is nullptr, avoiding crash."); - } - - THIS->HealDamage(heal_amt, caster); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetMaxHP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetMaxHP) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::SetMaxHP(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->SetMaxHP(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetLevelCon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetLevelCon) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetLevelCon(THIS, uint8 other_level)"); // @categories Stats and Attributes - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - uint8 iOtherLevel = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetLevelCon(iOtherLevel); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetHP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetHP) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetHP(THIS, int64 hp)"); // @categories Stats and Attributes - { - Mob *THIS; - int64 hp = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetHP(hp); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_DoAnim); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DoAnim) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::DoAnim(THIS, int animation_number, [int type = 0])"); // @categories Script Utility - { - Mob *THIS; - int animnum = (int) SvIV(ST(1)); - int type; - VALIDATE_THIS_IS_MOB; - if (items < 3) - type = 0; - else { - type = (int) SvIV(ST(2)); - } - - THIS->DoAnim(animnum, type); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ChangeSize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ChangeSize) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::ChangeSize(THIS, float in_size, [bool no_restriction = false])"); // @categories Script Utility - { - Mob *THIS; - float in_size = (float) SvNV(ST(1)); - bool bNoRestriction; - VALIDATE_THIS_IS_MOB; - if (items < 3) - bNoRestriction = false; - else { - bNoRestriction = (bool) SvTRUE(ST(2)); - } - - THIS->ChangeSize(in_size, bNoRestriction); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_RandomizeFeatures); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RandomizeFeatures) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::RandomizeFeatures(THIS, bool send_illusion, set_variables)"); // @categories Script Utility - { - Mob *THIS; - bool send_illusion = (bool) SvNV(ST(1)); - bool set_variables = (bool) SvNV(ST(2)); - VALIDATE_THIS_IS_MOB; - THIS->RandomizeFeatures(send_illusion, set_variables); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GMMove); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GMMove) { - dXSARGS; - if (items < 4 || items > 5) - Perl_croak(aTHX_ "Usage: Mob::GMMove(THIS, float x, float y, float z, [float heading = 0.01])"); // @categories Script Utility - { - Mob *THIS; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float heading; - VALIDATE_THIS_IS_MOB; - if (items < 5) - heading = 0.01; - else { - heading = (float) SvNV(ST(4)); - } - - THIS->GMMove(x, y, z, heading); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_HasProcs); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_HasProcs) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::HasProcs(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HasProcs(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsInvisible); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsInvisible) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Mob::IsInvisible(THIS, [Mob* other = 0])"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (items < 2) - other = 0; - else { - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - } - - RETVAL = THIS->IsInvisible(other); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SetInvisible); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetInvisible) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetInvisible(THIS, uint8 state)"); // @categories Script Utility - { - Mob *THIS; - uint8 state = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetInvisible(state); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetSeeInvisibleLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetSeeInvisibleLevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetSeeInvisibleLevel(THIS, uint8 see_invis_level)"); // @categories Script Utility - { - Mob *THIS; - uint8 see_invis_level = (uint8)SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetInnateSeeInvisible(see_invis_level); - THIS->CalcSeeInvisibleLevel(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetSeeInvisibleUndeadLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetSeeInvisibleUndeadLevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetSeeInvisibleUndeadLevel(THIS, uint8 see_invis_undead_level)"); // @categories Script Utility - { - Mob *THIS; - uint8 see_invis_undead_level = (uint8)SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetSeeInvisibleUndead(see_invis_undead_level); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_FindBuff); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_FindBuff) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::FindBuff(THIS, uint16 spell_id)"); // @categories Spells and Disciplines, Script Utility - { - Mob *THIS; - bool RETVAL; - uint16 spellid = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->FindBuff(spellid); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_FindBuffBySlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_FindBuffBySlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::FindBuffBySlot(THIS, int slot)"); // @categories Spells and Disciplines, Script Utility - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - int slot = SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->FindBuffBySlot(slot); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_BuffCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_BuffCount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::BuffCount(THIS)"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->BuffCount(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_FindType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_FindType) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::FindType(THIS, uint8 type, [bool offensive = false], [uint16 threshold = 100])"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - uint8 type = (uint8) SvUV(ST(1)); - bool bOffensive; - uint16 threshold; - VALIDATE_THIS_IS_MOB; - if (items < 3) - bOffensive = false; - else { - bOffensive = (bool) SvTRUE(ST(2)); - } - - if (items < 4) - threshold = 100; - else { - threshold = (uint16) SvUV(ST(3)); - } - - RETVAL = THIS->FindType(type, bOffensive, threshold); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBuffSlotFromType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBuffSlotFromType) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetBuffSlotFromType(THIS, uint16 type)"); // @categories Spells and Disciplines, Script Utility - { - Mob *THIS; - int8 RETVAL; - dXSTARG; - uint16 type = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetBuffSlotFromType(type); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_MakePet); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_MakePet) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::MakePet(THIS, uint16 spell_id, string pet_type, [string name = nullptr])"); // @categories Pet - { - Mob *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - char *pettype = (char *) SvPV_nolen(ST(2)); - char *name; - VALIDATE_THIS_IS_MOB; - if (items < 4) - name = nullptr; - else { - name = (char *) SvPV_nolen(ST(3)); - } - - THIS->MakePet(spell_id, pettype, name); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_MakeTempPet); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_MakeTempPet) { - dXSARGS; - if (items < 2 || items > 6) - Perl_croak(aTHX_ "Usage: Mob::MakeTempPet(THIS, uint16 spell_id, [string name = nullptr], [uint32 duration = 0], [Mob* target = nullptr], [bool sticktarg = 0])"); // @categories Pet - { - Mob *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - char *name; - uint32 duration; - Mob *target; - bool sticktarg; - VALIDATE_THIS_IS_MOB; - if (items < 3) - name = nullptr; - else - name = (char *) SvPV_nolen(ST(2)); - - if (items < 4) - duration = 0; - else - duration = (uint32) SvUV(ST(3)); - - if (items < 5) - target = nullptr; - else if (sv_derived_from(ST(4), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(4))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "owner is not of type Mob"); - - if (items < 6) - sticktarg = false; - else { - sticktarg = (bool) SvTRUE(ST(5)); - } - - THIS->TemporaryPets(spell_id, target, name, duration, true, sticktarg); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_TypesTempPet); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_TypesTempPet) { - dXSARGS; - if (items < 2 || items > 7) - Perl_croak(aTHX_ "Usage: Mob::TypesTempPet(THIS, uint32 type_id, [string name = nullptr], [uint32 duration = 0], [bool follow = 0], [Mob* target = nullptr], [bool stick_targ = 0])"); // @categories Pet - { - Mob *THIS; - uint32 typesid = (uint32) SvUV(ST(1)); - char *name; - uint32 duration; - bool follow; - Mob *target; - bool sticktarg; - VALIDATE_THIS_IS_MOB; - if (items < 3) - name = nullptr; - else - name = (char *) SvPV_nolen(ST(2)); - - if (items < 4) - duration = 0; - else - duration = (uint32) SvUV(ST(3)); - - if (items < 5) - follow = true; - else { - follow = (bool) SvTRUE(ST(4)); - } - - if (items < 6) - target = nullptr; - else if (sv_derived_from(ST(5), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(5))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - - - if (items < 7) - sticktarg = false; - else { - sticktarg = (bool) SvTRUE(ST(6)); - } - - THIS->TypesTemporaryPets(typesid, target, name, duration, follow, sticktarg); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetBaseRace); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBaseRace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetBaseRace(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetBaseRace(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBaseGender); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBaseGender) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetBaseGender(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetBaseGender(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDeity); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDeity) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetDeity(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetDeity(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetRace); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetRace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetRace(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetRace(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetGender); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetGender) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetGender(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetGender(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetTexture); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetTexture) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetTexture(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetTexture(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHelmTexture); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHelmTexture) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHelmTexture(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHelmTexture(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHairColor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHairColor) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHairColor(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHairColor(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBeardColor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBeardColor) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetBeardColor(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetBeardColor(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetEyeColor1); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetEyeColor1) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetEyeColor1(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetEyeColor1(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetEyeColor2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetEyeColor2) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetEyeColor2(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetEyeColor2(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHairStyle); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHairStyle) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHairStyle(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHairStyle(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetLuclinFace); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetLuclinFace) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetLuclinFace(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetLuclinFace(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBeard); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBeard) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetBeard(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetBeard(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDrakkinHeritage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDrakkinHeritage) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetDrakkinHeritage(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetDrakkinHeritage(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDrakkinTattoo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDrakkinTattoo) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetDrakkinTattoo(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetDrakkinTattoo(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDrakkinDetails); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDrakkinDetails) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetDrakkinDetails(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetDrakkinDetails(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetClass); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetClass) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetClass(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetClass(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetLevel(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetCleanName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetCleanName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetCleanName(THIS)"); // @categories Script Utility - { - Mob *THIS; - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCleanName(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_GetTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetTarget) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetTarget(THIS)"); // @categories Script Utility - { - Mob *THIS; - Mob *RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetTarget(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetTarget) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetTarget(THIS, mob)"); // @categories Script Utility - { - Mob *THIS; - Mob *mob; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - mob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "mob is not of type Mob"); - if (mob == nullptr) - Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); - - THIS->SetTarget(mob); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetHPRatio); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHPRatio) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHPRatio(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHPRatio(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsWarriorClass); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsWarriorClass) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsWarriorClass(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsWarriorClass(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHP) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHP(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHP(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxHP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxHP) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxHP(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxHP(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetItemHPBonuses); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetItemHPBonuses) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetItemHPBonuses(THIS)"); // @categories Inventory and Items, Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetItemHPBonuses(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSpellHPBonuses); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSpellHPBonuses) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetSpellHPBonuses(THIS)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSpellHPBonuses(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSpellIDFromSlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSpellIDFromSlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetSpellIDFromSlot(THIS, slot)"); // @categories Spells and Disciplines - { - Mob *THIS; - int RETVAL; - dXSTARG; - uint8 slot = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - if (slot > THIS->GetMaxBuffSlots()) - RETVAL = -1; - else - RETVAL = THIS->GetSpellIDFromSlot(slot); - - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetWalkspeed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWalkspeed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWalkspeed(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetWalkspeed(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetRunspeed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetRunspeed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetRunspeed(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetRunspeed(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetCasterLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetCasterLevel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetCasterLevel(THIS, spell_id)"); // @categories Stats and Attributes - { - Mob *THIS; - int RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCasterLevel(spell_id); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxMana); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxMana) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxMana(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxMana(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMana); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMana) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMana(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMana(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetMana); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetMana) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetMana(THIS, amount)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 amount = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetMana(amount); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetManaRatio); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetManaRatio) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetManaRatio(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetManaRatio(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetAC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAC) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetAC(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAC(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDisplayAC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDisplayAC) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetDisplayAC(THIS)"); - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetDisplayAC(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetATK); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetATK) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetATK(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetATK(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSTR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSTR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetSTR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSTR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSTA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSTA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetSTA(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSTA(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDEX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDEX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetDEX(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetDEX(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetAGI); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAGI) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetAGI(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAGI(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetINT); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetINT) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetINT(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetINT(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetWIS); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWIS) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWIS(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetWIS(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetCHA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetCHA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetCHA(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCHA(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetFR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetFR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetFR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetFR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetDR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetDR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetPR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetPR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetPR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetPR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetCR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetCR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetCR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetCorruption); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetCorruption) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetCorruption(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCorrup(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetPhR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetPhR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetPhR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetPhR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxSTR); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxSTR) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxSTR(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxSTR(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxSTA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxSTA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxSTA(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxSTA(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxDEX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxDEX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxDEX(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxDEX(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxAGI); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxAGI) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxAGI(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxAGI(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxINT); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxINT) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxINT(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxINT(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxWIS); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxWIS) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxWIS(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxWIS(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMaxCHA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMaxCHA) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMaxCHA(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMaxCHA(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetActSpellRange); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetActSpellRange) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetActSpellRange(THIS, uint16 spell_id, float range)"); // @categories Spells and Disciplines - { - Mob *THIS; - float RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - float range = (float) SvNV(ST(2)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetActSpellRange(spell_id, range); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetActSpellDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetActSpellDamage) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetActSpellDamage(THIS, uint16 spell_id, int64 value)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - int64 value = (int64) SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetActSpellDamage(spell_id, value); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetActSpellHealing); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetActSpellHealing) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetActSpellHealing(THIS, uint16 spell_id, int64 value)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - int64 value = (int64) SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetActSpellHealing(spell_id, value); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetActSpellCost); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetActSpellCost) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetActSpellCost(THIS, uint16 spell_id, int32 cost)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - int32 cost = (int32) SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetActSpellCost(spell_id, cost); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetActSpellDuration); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetActSpellDuration) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetActSpellDuration(THIS, uint16 spell_id, int32 duration)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - int32 duration = (int32) SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetActSpellDuration(spell_id, duration); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetActSpellCasttime); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetActSpellCasttime) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetActSpellCasttime(THIS, uint16 spell_id, uint32 cast_time)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - int32 casttime = (int32) SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetActSpellCasttime(spell_id, casttime); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_ResistSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ResistSpell) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Mob::ResistSpell(THIS, uint8 resist_type, uint16 spell_id, [Mob* caster = nullptr])"); // @categories Spells and Disciplines, Script Utility - { - Mob *THIS; - double RETVAL; - dXSTARG; - uint8 ressit_type = (uint8) SvUV(ST(1)); - uint16 spell_id = (uint16) SvUV(ST(2)); - Mob *caster; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(3), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(3))); - caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "caster is not of type Mob"); - if (caster == nullptr) - Perl_croak(aTHX_ "caster is nullptr, avoiding crash."); - - RETVAL = THIS->ResistSpell(ressit_type, spell_id, caster); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSpecializeSkillValue); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSpecializeSkillValue) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetSpecializeSkillValue(THIS, uint16 spell_id)"); // @categories Skills and Recipes, Spells and Disciplines - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - uint16 spell_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSpecializeSkillValue(spell_id); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetNPCTypeID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetNPCTypeID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetNPCTypeID(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetNPCTypeID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsTargeted); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsTargeted) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsTargeted(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsTargeted(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetX(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetX(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetY(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetY(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetZ) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetZ(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetZ(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHeading); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHeading) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHeading(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHeading(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Mob_GetWaypointX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWaypointX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWaypointX(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCurrentWayPoint().x; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetWaypointY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWaypointY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWaypointY(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCurrentWayPoint().y; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetWaypointZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWaypointZ) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWaypointZ(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCurrentWayPoint().z; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetWaypointH); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWaypointH) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWaypointH(THIS)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCurrentWayPoint().w; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetWaypointPause); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWaypointPause) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWaypointPause(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCWPP(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetWaypointID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetWaypointID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetWaypointID(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetCWP(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetCurrentWP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetCurrentWP) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetCurrentWP(THIS, waypoint)"); // @categories Script Utility - { - Mob *THIS; - uint16 waypoint = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetCurrentWP(waypoint); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetSize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSize) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetSize(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSize(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetFollowID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetFollowID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetFollowID(THIS, id)"); // @categories Script Utility - { - Mob *THIS; - uint32 id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetFollowID(id); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetFollowID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetFollowID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetFollowID(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetFollowID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_Message); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Message) { - dXSARGS; - if (items < 3) - Perl_croak(aTHX_ "Usage: Mob::Message(THIS, uint32 emote_color_type, string message)"); // @categories Script Utility - { - Mob *THIS; - uint32 type = (uint32) SvUV(ST(1)); - char *message = (char *) SvPV_nolen(ST(2)); - VALIDATE_THIS_IS_MOB; - - if (RuleB(Chat, QuestDialogueUsesDialogueWindow) && THIS->IsClient()) { - std::string window_markdown = message; - DialogueWindow::Render(THIS->CastToClient(), window_markdown); - } - else if (RuleB(Chat, AutoInjectSaylinksToClientMessage)) { - std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(message); - THIS->Message(type, new_message.c_str()); - } - else { - THIS->Message(type, message); - } - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Message_StringID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Message_StringID) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::Message_StringID(THIS, uint32 emote_color_type, uint32 string_id, [uint32 distance = 0])"); // @categories Script Utility - { - Mob *THIS; - uint32 type = (uint32) SvUV(ST(1)); - uint32 string_id = (uint32) SvUV(ST(2)); - uint32 distance; - VALIDATE_THIS_IS_MOB; - if (items < 4) - distance = 0; - else { - distance = (uint32) SvUV(ST(3)); - } - - THIS->MessageString(type, string_id, distance); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Say); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Say) { - dXSARGS; - if (items < 2) - Perl_croak(aTHX_ "Usage: Mob::Say(THIS, string message)"); // @categories Script Utility - { - Mob *THIS; - char *format = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->Say(format); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Shout); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Shout) { - dXSARGS; - if (items < 2) - Perl_croak(aTHX_ "Usage: Mob::Shout(THIS, string message)"); // @categories Script Utility - { - Mob *THIS; - char *format = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->Shout(format); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Emote); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Emote) { - dXSARGS; - if (items < 2) - Perl_croak(aTHX_ "Usage: Mob::Emote(THIS, string message)"); // @categories Script Utility - { - Mob *THIS; - char *format = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->Emote(format); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_InterruptSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_InterruptSpell) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Mob::InterruptSpell(THIS, [uint16 spell_id = 0xFFFF])"); // @categories Script Utility - { - Mob *THIS; - uint16 spellid; - VALIDATE_THIS_IS_MOB; - if (items < 2) - spellid = 0xFFFF; - else { - spellid = (uint16) SvUV(ST(1)); - } - - THIS->InterruptSpell(spellid); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CastSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CastSpell) { - dXSARGS; - if (items < 3 || items > 7) - Perl_croak(aTHX_ "Usage: Mob::CastSpell(THIS, uint16 spell_id, uint16 target_id, [int slot = 22], [int32 cast_time = -1], [int32 mana_cost = -1], [int16 resist_adjust = 0])"); // @categories Spells and Disciplines - { - Mob *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - uint16 target_id = (uint16) SvUV(ST(2)); - EQ::spells::CastingSlot slot; - int32 casttime; - int32 mana_cost; - int16 resist_adjust; - VALIDATE_THIS_IS_MOB; - if (items < 4) - slot = EQ::spells::CastingSlot::Item; - else { - slot = static_cast(SvUV(ST(3))); - } - - if (items < 5) - casttime = -1; - else { - casttime = (int32) SvIV(ST(4)); - } - - if (items < 6) - mana_cost = -1; - else { - mana_cost = (int32) SvIV(ST(5)); - } - - if (items < 7) { - resist_adjust = 0; - } else { - resist_adjust = (int16) SvIV(ST(6)); - } - - if (resist_adjust == - 0)//If you do not pass resist adjust as nullptr it will ignore the spells default resist adjust - THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0); - else - THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, - &resist_adjust); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SpellFinished); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SpellFinished) { - dXSARGS; - if (items < 2 || items > 5) - Perl_croak(aTHX_ "Usage: Mob::SpellFinished(uint16 spell_id, [Mob* spell_target = this], [uint16 mana_cost = 0], [uint16 resist_diff = 0])"); // @categories Spells and Disciplines - { - Mob *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - Mob *spell_target; - uint16 mana_cost = 0; - int16 resist_diff; - VALIDATE_THIS_IS_MOB; - spell_target = THIS; - - if (items > 2) { - if (sv_derived_from(ST(2), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(2))); - spell_target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "spell_target is not of type Mob"); - if (spell_target == nullptr) - Perl_croak(aTHX_ "spell_target is nullptr, avoiding crash."); - - } - - if (items > 3) - mana_cost = (uint16) SvUV(ST(3)); - - if (items > 4) { - resist_diff = (int16) SvUV(ST(4)); - } else { - resist_diff = spells[spell_id].resist_difficulty; - } - - THIS->SpellFinished(spell_id, spell_target, EQ::spells::CastingSlot::Item, mana_cost, -1, resist_diff); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_IsImmuneToSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsImmuneToSpell) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::IsImmuneToSpell(THIS, uint16 spell_id, [Mob* caster = nullptr])"); // @categories Spells and Disciplines, Script Utility - { - Mob *THIS; - bool RETVAL; - uint16 spell_id = (uint16) SvUV(ST(1)); - Mob *caster; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(2), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(2))); - caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "caster is not of type Mob"); - if (caster == nullptr) - Perl_croak(aTHX_ "caster is nullptr, avoiding crash."); - - RETVAL = THIS->IsImmuneToSpell(spell_id, caster); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_BuffFadeBySpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_BuffFadeBySpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::BuffFadeBySpellID(THIS, uint16 spell_id)"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - uint16 spell_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->BuffFadeBySpellID(spell_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_BuffFadeByEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_BuffFadeByEffect) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::BuffFadeByEffect(THIS, int effect_id, int skip_slot = -1)"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - int effect_id = (int) SvIV(ST(1)); - int skipslot; - VALIDATE_THIS_IS_MOB; - if (items < 3) - skipslot = -1; - else { - skipslot = (int) SvIV(ST(2)); - } - - THIS->BuffFadeByEffect(effect_id, skipslot); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_BuffFadeAll); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_BuffFadeAll) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::BuffFadeAll(THIS)"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->BuffFadeAll(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_BuffFadeBySlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_BuffFadeBySlot) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::BuffFadeBySlot(THIS, int slot, bool recalc_bonuses = true)"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - int slot = (int) SvIV(ST(1)); - bool iRecalcBonuses; - VALIDATE_THIS_IS_MOB; - if (items < 3) - iRecalcBonuses = true; - else { - iRecalcBonuses = (bool) SvTRUE(ST(2)); - } - - THIS->BuffFadeBySlot(slot, iRecalcBonuses); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CanBuffStack); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanBuffStack) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::CanBuffStack(THIS, uint16 spell_id, uint8 caster_level, [bool fail_if_overwritten = false])"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - int RETVAL; - dXSTARG; - uint16 spellid = (uint16) SvUV(ST(1)); - uint8 caster_level = (uint8) SvUV(ST(2)); - bool iFailIfOverwrite; - VALIDATE_THIS_IS_MOB; - if (items < 4) - iFailIfOverwrite = false; - else { - iFailIfOverwrite = (bool) SvTRUE(ST(3)); - } - - RETVAL = THIS->CanBuffStack(spellid, caster_level, iFailIfOverwrite); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsCasting); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsCasting) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsCasting(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsCasting(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CastingSpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CastingSpellID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CastingSpellID(THIS)"); // @categories Spells and Disciplines - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CastingSpellID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetAppearance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetAppearance) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::SetAppearance(THIS, int appearance [0|1|2|3|4], [ignore_self = true])"); // @categories Stats and Attributes - { - Mob *THIS; - EmuAppearance app = (EmuAppearance) SvUV(ST(1)); - bool iIgnoreSelf; - VALIDATE_THIS_IS_MOB; - if (items < 3) - iIgnoreSelf = true; - else { - iIgnoreSelf = (bool) SvTRUE(ST(2)); - } - - THIS->SetAppearance(app, iIgnoreSelf); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetAppearance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAppearance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetAppearance(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - EmuAppearance RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAppearance(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetRunAnimSpeed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetRunAnimSpeed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetRunAnimSpeed(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetRunAnimSpeed(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetRunAnimSpeed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetRunAnimSpeed) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetRunAnimSpeed(THIS, int8 speed)"); // @categories Stats and Attributes - { - Mob *THIS; - int8 in = (int8) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetRunAnimSpeed(in); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetPetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetPetID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetPetID(THIS, uint16 new_pet_id)"); // @categories Pet - { - Mob *THIS; - uint16 NewPetID = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetPetID(NewPetID); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetPetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetPetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetPetID(THIS)"); // @categories Script Utility, Pet - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetPetID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetOwnerID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetOwnerID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetOwnerID(THIS, uint16 new_owner_id)"); // @categories Pet - { - Mob *THIS; - uint16 NewOwnerID = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetOwnerID(NewOwnerID); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetOwnerID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetOwnerID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetOwnerID(THIS)"); // @categories Script Utility, Pet - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetOwnerID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetPetType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetPetType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetPetType(THIS)"); // @categories Script Utility, Pet - { - Mob *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetPetType(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBodyType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBodyType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetBodyType(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetBodyType(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_Stun); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Stun) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::Stun(THIS, int duration)"); - { - Mob *THIS; - int duration = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->Stun(duration); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Spin); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Spin) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::Spin(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->Spin(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_Kill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Kill) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::Kill(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->Kill(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetInvul); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetInvul) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetInvul(THIS, bool set_invulnerable)"); // @categories Script Utility - { - Mob *THIS; - bool invul = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetInvul(invul); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetInvul); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetInvul) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetInvul(THIS)"); // @categories Script Utility, Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetInvul(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SetExtraHaste); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetExtraHaste) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetExtraHaste(THIS, int haste)"); // @categories Script Utility, Stats and Attributes - { - Mob *THIS; - int Haste = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetExtraHaste(Haste); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetHaste); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHaste) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHaste(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHaste(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHandToHandDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHandToHandDamage) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHandToHandDamage(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHandToHandDamage(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_CanThisClassDoubleAttack); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanThisClassDoubleAttack) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CanThisClassDoubleAttack(THIS)"); // @categories Skills and Recipes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CanThisClassDoubleAttack(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CanThisClassDualWield); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanThisClassDualWield) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CanThisClassDualWield(THIS)"); // @categories Skills and Recipes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CanThisClassDualWield(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CanThisClassRiposte); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanThisClassRiposte) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CanThisClassRiposte(THIS)"); // @categories Skills and Recipes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CanThisClassRiposte(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CanThisClassDodge); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanThisClassDodge) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CanThisClassDodge(THIS)"); // @categories Skills and Recipes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CanThisClassDodge(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CanThisClassParry); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanThisClassParry) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CanThisClassParry(THIS)"); // @categories Skills and Recipes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CanThisClassParry(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHandToHandDelay); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHandToHandDelay) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHandToHandDelay(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHandToHandDelay(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetClassLevelFactor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetClassLevelFactor) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetClassLevelFactor(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetClassLevelFactor(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_Mesmerize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Mesmerize) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::Mesmerize(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->Mesmerize(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_IsMezzed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsMezzed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsMezzed(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsMezzed(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsStunned); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsStunned) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsStunned(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsStunned(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - - -XS(XS_Mob_StartEnrage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_StartEnrage) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::StartEnrage(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->StartEnrage(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_IsEnraged); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsEnraged) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsEnraged(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsEnraged(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetReverseFactionCon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetReverseFactionCon) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetReverseFactionCon(THIS, iOther)"); // @categories Faction - { - Mob *THIS; - FACTION_VALUE RETVAL; - dXSTARG; - Mob *iOther; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - iOther = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "iOther is not of type Mob"); - if (iOther == nullptr) - Perl_croak(aTHX_ "iOther is nullptr, avoiding crash."); - - RETVAL = THIS->GetReverseFactionCon(iOther); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsAIControlled); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsAIControlled) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsAIControlled(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsAIControlled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetAggroRange); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAggroRange) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetAggroRange(THIS)"); // @categories Stats and Attributes, Hate and Aggro - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAggroRange(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetAssistRange); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAssistRange) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetAssistRange(THIS)"); // @categories Stats and Attributes, Hate and Aggro - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAssistRange(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetPetOrder); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetPetOrder) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetPetOrder(THIS, i)"); // @categories Pet - { - Mob *THIS; - Mob::eStandingPetOrder i = (Mob::eStandingPetOrder) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetPetOrder(i); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetPetOrder); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetPetOrder) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetPetOrder(THIS)"); // @categories Script Utility, Pet - { - Mob *THIS; - Mob::eStandingPetOrder RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetPetOrder(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsRoamer); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsRoamer) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsRoamer(THIS)"); // @categories Script Utility, Spawns - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsRoamer(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsRooted); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsRooted) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsRooted(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsRooted(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_AddToHateList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_AddToHateList) { - dXSARGS; - if (items < 2 || items > 7) - Perl_croak(aTHX_ "Usage: Mob::AddToHateList(THIS, Mob* other, [int64 hate = 0], [int64 damage = 0], [bool yell_for_help = true], [bool frenzy = false], [bool buff_tic = false])"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *other; - int64 hate; - int64 damage; - bool iYellForHelp; - bool bFrenzy; - bool iBuffTic; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - if (items < 3) - hate = 0; - else { - hate = (int64) SvIV(ST(2)); - } - - if (items < 4) - damage = 0; - else { - damage = (int64) SvIV(ST(3)); - } - - if (items < 5) - iYellForHelp = true; - else { - iYellForHelp = (bool) SvTRUE(ST(4)); - } - - if (items < 6) - bFrenzy = false; - else { - bFrenzy = (bool) SvTRUE(ST(5)); - } - - if (items < 7) - iBuffTic = false; - else { - iBuffTic = (bool) SvTRUE(ST(6)); - } - - THIS->AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetHate); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetHate) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::SetHate(THIS, Mob* other, [int64 hate = 0], [int64 damage = 0])"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *other; - int64 hate; - int64 damage; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - if (items < 3) - hate = 0; - else { - hate = (int64) SvIV(ST(2)); - } - - if (items < 4) - damage = 0; - else { - damage = (int64) SvIV(ST(3)); - } - - THIS->SetHateAmountOnEnt(other, hate, damage); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_HalveAggro); -XS(XS_Mob_HalveAggro) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::HalveAggro(THIS, Mob* other)"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - THIS->HalveAggro(other); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_DoubleAggro); -XS(XS_Mob_DoubleAggro) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::DoubleAggro(THIS, Mob* other)"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - THIS->DoubleAggro(other); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetHateAmount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateAmount) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::GetHateAmount(THIS, Mob* mob, [bool is_damage = false])"); // @categories Hate and Aggro - { - Mob *THIS; - int64 RETVAL; - dXSTARG; - Mob *tmob; - bool is_dam; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - tmob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "tmob is not of type Mob"); - if (tmob == nullptr) - Perl_croak(aTHX_ "tmob is nullptr, avoiding crash."); - - if (items < 3) - is_dam = false; - else { - is_dam = (bool) SvTRUE(ST(2)); - } - - RETVAL = THIS->GetHateAmount(tmob, is_dam); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetDamageAmount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetDamageAmount) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetDamageAmount(THIS, Mob* target_mob)"); // @categories Stats and Attributes - { - Mob *THIS; - uint64 RETVAL; - dXSTARG; - Mob *tmob; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - tmob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "tmob is not of type Mob"); - if (tmob == nullptr) - Perl_croak(aTHX_ "tmob is nullptr, avoiding crash."); - - RETVAL = THIS->GetDamageAmount(tmob); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHateTop); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateTop) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHateTop(THIS)"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHateTop(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHateDamageTop); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateDamageTop) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetHateDamageTop(THIS, Mob* other)"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *RETVAL; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - RETVAL = THIS->GetHateDamageTop(other); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHateRandom); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateRandom) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHateRandom(THIS)"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHateRandom(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsEngaged); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsEngaged) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsEngaged(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsEngaged(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_HateSummon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_HateSummon) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::HateSummon(THIS)"); // @categories Hate and Aggro - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HateSummon(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_FaceTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_FaceTarget) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::FaceTarget(THIS, [Mob* target = 0])"); // @categories Script Utility - { - Mob *THIS; - Mob *MobToFace; - VALIDATE_THIS_IS_MOB; - if (items < 2) - MobToFace = 0; - else { - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - MobToFace = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "MobToFace is not of type Mob"); - if (MobToFace == nullptr) - Perl_croak(aTHX_ "MobToFace is nullptr, avoiding crash."); - } - - THIS->FaceTarget(MobToFace); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetHeading); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetHeading) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetHeading(THIS, float heading)"); // @categories Script Utility - { - Mob *THIS; - float iHeading = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetHeading(iHeading); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_WipeHateList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_WipeHateList) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::WipeHateList(THIS)"); // @categories Hate and Aggro - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->WipeHateList(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CheckAggro); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CheckAggro) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::CheckAggro(THIS, Mob* other)"); // @categories Hate and Aggro - { - Mob *THIS; - bool RETVAL; - Mob *other; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - RETVAL = THIS->CheckAggro(other); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CalculateHeadingToTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CalculateHeadingToTarget) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::CalculateHeadingToTarget(THIS, float x, float y)"); // @categories Script Utility - { - Mob *THIS; - int8 RETVAL; - dXSTARG; - float in_x = (float) SvNV(ST(1)); - float in_y = (float) SvNV(ST(2)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CalculateHeadingToTarget(in_x, in_y); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_RunTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RunTo) { - dXSARGS; - if (items < 4 || items > 5) - Perl_croak(aTHX_ - "Usage: Mob::RunTo(THIS, float x, float y, float z)"); - { - Mob *THIS; - float x = (float)SvNV(ST(1)); - float y = (float)SvNV(ST(2)); - float z = (float)SvNV(ST(3)); - VALIDATE_THIS_IS_MOB; - THIS->RunTo(x, y, z); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_WalkTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_WalkTo) { - dXSARGS; - if (items < 4 || items > 5) - Perl_croak(aTHX_ - "Usage: Mob::WalkTo(THIS, float x, float y, float z)"); - { - Mob *THIS; - float x = (float)SvNV(ST(1)); - float y = (float)SvNV(ST(2)); - float z = (float)SvNV(ST(3)); - VALIDATE_THIS_IS_MOB; - THIS->WalkTo(x, y, z); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_NavigateTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_NavigateTo) { - dXSARGS; - if (items < 4 || items > 5) - Perl_croak(aTHX_ "Usage: Mob::NavigateTo(THIS, float x, float y, float z)"); // @categories Script Utility - { - Mob *THIS; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - VALIDATE_THIS_IS_MOB; - THIS->NavigateTo(x, y, z); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_StopNavigation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_StopNavigation) { - dXSARGS; - if (items < 5 || items > 6) - Perl_croak(aTHX_ - "Usage: Mob::StopNavigation(THIS)"); - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->StopNavigation(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CalculateDistance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CalculateDistance) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Mob::CalculateDistance(THIS, float x, float y, float z)"); // @categories Script Utility - { - Mob *THIS; - float RETVAL; - dXSTARG; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CalculateDistance(x, y, z); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SendTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SendTo) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Mob::SendTo(THIS, float new_x, float new_y, float new_z)"); // @categories Script Utility - { - Mob *THIS; - float new_x = (float) SvNV(ST(1)); - float new_y = (float) SvNV(ST(2)); - float new_z = (float) SvNV(ST(3)); - VALIDATE_THIS_IS_MOB; - THIS->SendTo(new_x, new_y, new_z); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SendToFixZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SendToFixZ) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Mob::SendToFixZ(THIS, float new_x, float new_y, float new_z)"); // @categories Script Utility - { - Mob *THIS; - float new_x = (float) SvNV(ST(1)); - float new_y = (float) SvNV(ST(2)); - float new_z = (float) SvNV(ST(3)); - VALIDATE_THIS_IS_MOB; - THIS->SendToFixZ(new_x, new_y, new_z); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_NPCSpecialAttacks); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_NPCSpecialAttacks) { - dXSARGS; - if (items < 3 || items > 5) - Perl_croak(aTHX_ "Usage: Mob::NPCSpecialAttacks(THIS, string abilities_string, int perm_tag, [bool reset = true], [bool remove = true])"); // @categories Stats and Attributes - { - Mob *THIS; - char *parse = (char *) SvPV_nolen(ST(1)); - int permtag = (int) SvIV(ST(2)); - bool reset = items == 4 ? (bool) SvTRUE(ST(3)) : true; - bool remove = items == 5 ? (bool) SvTRUE(ST(4)) : false; - VALIDATE_THIS_IS_MOB; - THIS->NPCSpecialAttacks(parse, permtag, reset, remove); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_DontHealMeBefore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DontHealMeBefore) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::DontHealMeBefore(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->DontHealMeBefore(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_DontBuffMeBefore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DontBuffMeBefore) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::DontBuffMeBefore(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->DontBuffMeBefore(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_DontDotMeBefore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DontDotMeBefore) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::DontDotMeBefore(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->DontDotMeBefore(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_DontRootMeBefore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DontRootMeBefore) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::DontRootMeBefore(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->DontRootMeBefore(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_DontSnareMeBefore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DontSnareMeBefore) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::DontSnareMeBefore(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->DontSnareMeBefore(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetResist); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetResist) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetResist(THIS, type)"); // @categories Stats and Attributes - { - Mob *THIS; - int16 RETVAL; - dXSTARG; - uint8 type = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetResist(type); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_Charmed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_Charmed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::Charmed(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->Charmed(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetLevelHP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetLevelHP) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetLevelHP(THIS, uint8 level)"); // @categories Stats and Attributes - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - uint8 tlevel = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetLevelHP(tlevel); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetZoneID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetZoneID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetZoneID(THIS)"); // @categories Zones - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetZoneID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_CheckAggroAmount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CheckAggroAmount) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::CheckAggroAmount(THIS, uint16 spell_id)"); // @categories Hate and Aggro - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - uint16 spellid = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CheckAggroAmount(spellid, nullptr); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_CheckHealAggroAmount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CheckHealAggroAmount) { - dXSARGS; - if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: Mob::CheckHealAggroAmount(THIS, uint16 spell_id, uint32 possible_heal_amt)"); // @categories Hate and Aggro - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - uint16 spellid = (uint16) SvUV(ST(1)); - uint32 possible = 0; - VALIDATE_THIS_IS_MOB; - if (items == 3) { - possible = (uint32) SvUV(ST(2)); - } - - RETVAL = THIS->CheckHealAggroAmount(spellid, nullptr, possible); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetAA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAA) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetAA(THIS, uint32 rank_id)"); // @categories Alternative Advancement - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - uint32 rank_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAA(rank_id); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetAAByAAID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAAByAAID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetAAByAAID(THIS, uint32 aa_id)"); // @categories Alternative Advancement - { - Mob *THIS; - uint32 RETVAL; - dXSTARG; - uint32 aa_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAAByAAID(aa_id); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetAA); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetAA) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::SetAA(THIS, int aa_id, int points, [int charges = 0])"); // @categories Alternative Advancement, Script Utility - { - Mob *THIS; - bool RETVAL; - int aa_id = (int) SvIV(ST(1)); - int points = (int) SvIV(ST(2)); - int charges = (items == 4) ? (int) SvIV(ST(3)) : 0; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->SetAA(aa_id, points, charges); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_DivineAura); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DivineAura) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::DivineAura(THIS)"); // @categories Spells and Disciplines - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->DivineAura(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_AddFeignMemory); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_AddFeignMemory) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::AddFeignMemory(THIS, Client* attacker)"); // @categories Script Utility - { - Mob *THIS; - Client *attacker; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - attacker = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "attacker is not of type Client"); - if (attacker == nullptr) - Perl_croak(aTHX_ "attacker is nullptr, avoiding crash."); - - THIS->AddFeignMemory(attacker); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_RemoveFromFeignMemory); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RemoveFromFeignMemory) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::RemoveFromFeignMemory(THIS, Client* attacker)"); // @categories Script Utility, Hate and Aggro - { - Mob *THIS; - Client *attacker; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - attacker = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "attacker is not of type Client"); - if (attacker == nullptr) - Perl_croak(aTHX_ "attacker is nullptr, avoiding crash."); - - THIS->RemoveFromFeignMemory(attacker); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ClearFeignMemory); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ClearFeignMemory) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::ClearFeignMemory(THIS)"); // @categories Script Utility, Hate and Aggro - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->ClearFeignMemory(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetOOCRegen); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetOOCRegen) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetOOCRegen(THIS, int32 new_ooc_regen)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 newoocregen = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetOOCRegen(newoocregen); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetEntityVariable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetEntityVariable) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetEntityVariable(THIS, string id)"); // @categories Script Utility - { - Mob *THIS; - Const_char *id = SvPV_nolen(ST(1)); - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetEntityVariable(id); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_EntityVariableExists); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_EntityVariableExists) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::EntityVariableExists(THIS, string id)"); - { - Mob *THIS; - Const_char *id = SvPV_nolen(ST(1)); - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->EntityVariableExists(id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SetEntityVariable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetEntityVariable) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::SetEntityVariable(THIS, string id, string var)"); // @categories Script Utility - { - Mob *THIS; - Const_char *id = SvPV_nolen(ST(1)); - const char *var = (const char *) SvPV_nolen(ST(2)); - VALIDATE_THIS_IS_MOB; - THIS->SetEntityVariable(id, var); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetHateList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateList) { - dXSARGS; - int num_entries = 0; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHateList(THIS)"); // @categories Hate and Aggro - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - auto hate_list = THIS->GetHateList(); - auto iter = hate_list.begin(); - - while (iter != hate_list.end()) { - struct_HateList *entry = (*iter); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "HateEntry", (void *) entry); - XPUSHs(ST(0)); - num_entries++; - iter++; - } - } - XSRETURN(num_entries); -} - -XS(XS_Mob_SignalClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SignalClient) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::SignalClient(THIS, Client* client, uint32 data)"); // @categories Script Utility - { - Mob *THIS; - Client *client = nullptr; - uint32 data = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - client = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "client is not of type Client"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - - client->Signal(data); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CombatRange); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CombatRange) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::CombatRange(THIS, Mob* target)"); // @categories Script Utility - { - Mob *THIS; - Mob *target = nullptr; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - if (target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - RETVAL = THIS->CombatRange(target); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_DoSpecialAttackDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DoSpecialAttackDamage) { - dXSARGS; - if (items < 4 || items > 6) - Perl_croak(aTHX_ "Usage: Mob::DoSpecialAttackDamage(THIS, Mob* target, int skill, int32 max_damage, [int32 min_damage = 1], [int32 hate_override = -11])"); // @categories Script Utility, Skills and Attributes - { - Mob *THIS; - Mob *target; - EQ::skills::SkillType attack_skill = (EQ::skills::SkillType) SvUV(ST(2)); - int32 max_damage = (int32) SvIV(ST(3)); - int32 min_damage = 1; - int32 hate_override = -11; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - if (target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - if (items > 4) { - min_damage = (int32) SvIV(ST(4)); - } - - if (items == 6) { - hate_override = (int32) SvIV(ST(5)); - } - - THIS->DoSpecialAttackDamage(target, attack_skill, max_damage, min_damage, hate_override); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CheckLoS); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CheckLoS) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::CheckLoS(THIS, Mob*)"); // @categories Script Utility - { - Mob *THIS; - Mob *mob; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - mob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "mob is not of type Mob"); - if (mob == nullptr) - Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); - - RETVAL = THIS->CheckLosFN(mob); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_CheckLoSToLoc); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CheckLoSToLoc) { - dXSARGS; - if (items != 4 && items != 5) - Perl_croak(aTHX_ "Usage: Mob::CheckLoSToLoc(THIS, float x, float y, float z, float mob_size)"); // @categories Script Utility - { - Mob *THIS; - float loc_x = (float) SvNV(ST(1)); - float loc_y = (float) SvNV(ST(2)); - float loc_z = (float) SvNV(ST(3)); - float mob_size; - bool RETVAL; - - if (items == 5) { - mob_size = (float) SvNV(ST(4)); - } else { - mob_size = 6; - } - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CheckLosFN(loc_x, loc_y, loc_z, mob_size); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_FindGroundZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_FindGroundZ) { - dXSARGS; - if (items != 3 && items != 4) - Perl_croak(aTHX_ "Usage: Mob::FindGroundZ(THIS, float x, float y, float z_offset)"); // @categories Script Utility - { - Mob *THIS; - float new_x = (float) SvNV(ST(1)); - float new_y = (float) SvNV(ST(2)); - float z_offset; - float RETVAL; - dXSTARG; - - if (items == 4) { - z_offset = (float) SvNV(ST(3)); - } else { - z_offset = 10; - } - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetGroundZ(new_x, new_y, z_offset); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_ProjectileAnim); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ProjectileAnim) { - dXSARGS; - if (items < 3 || items > 9) - Perl_croak(aTHX_ "Usage: Mob::ProjectileAnim(THIS, Mob* mob, int item_id, [bool is_arrow = false], [float speed = 0], [float angle = 0], [float tilt = 0], [float arc = 0])"); // @categories Script Utility - - { - Mob *THIS; - Mob *mob; - int item_id = SvUV(ST(2)); - bool IsArrow = false; - float speed = 0; - float angle = 0; - float tilt = 0; - float arc = 0; - char *IDFile = nullptr; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - mob = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "mob is not of type Mob"); - if (mob == nullptr) - Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); - - if (items > 3) { - IsArrow = (bool) SvTRUE(ST(3)); - } - if (items > 4) { - speed = (float) SvNV(ST(4)); - } - if (items > 5) { - angle = (float) SvNV(ST(5)); - } - if (items > 6) { - tilt = (float) SvNV(ST(6)); - } - if (items > 7) { - arc = (float) SvNV(ST(7)); - } - - if (items > 8) { IDFile = (char *) SvPV_nolen(ST(8)); } - - THIS->ProjectileAnimation(mob, item_id, IsArrow, speed, angle, tilt, arc, IDFile); - - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_HasNPCSpecialAtk); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_HasNPCSpecialAtk) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::HasNPCSpecialAtk(THIS, string ability_string)"); // @categories Stats and Attributes - { - Mob *THIS; - char *parse = (char *) SvPV_nolen(ST(1)); - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HasNPCSpecialAtk(parse); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SendAppearanceEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SendAppearanceEffect) { - dXSARGS; - if (items < 2 || items > 17) - Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffect(THIS, int32 effect1, [int32 effect2 = 0], [int32 effect3 = 0], [int32 effect4 = 0], [int32 effect5 = 0], [Client* single_client_to_send_to = null]), [uint32 slot1 = 1], [uint32 ground1 = 1], [uint32 slot2 = 1], [uint32 ground2 = 1], [uint32 slot3 = 1], [uint32 ground2 = 1], [uint32 slot4 = 1], [uint32 ground4 = 1], [uint32 slot5 = 1], [uint32 ground5 = 1]"); // @categories Script Utility - { - Mob *THIS; - int32 parm1 = (int32) SvIV(ST(1)); - int32 parm2 = 0; - int32 parm3 = 0; - int32 parm4 = 0; - int32 parm5 = 0; - uint32 value1slot = 1; - uint32 value1ground = 1; - uint32 value2slot = 1; - uint32 value2ground = 1; - uint32 value3slot = 1; - uint32 value3ground = 1; - uint32 value4slot = 1; - uint32 value4ground = 1; - uint32 value5slot = 1; - uint32 value5ground = 1; - Client *client = nullptr; - bool nullclient = false; - VALIDATE_THIS_IS_MOB; - if (items > 2) { parm2 = (int32) SvIV(ST(2)); } - if (items > 3) { parm3 = (int32) SvIV(ST(3)); } - if (items > 4) { parm4 = (int32) SvIV(ST(4)); } - if (items > 5) { parm5 = (int32) SvIV(ST(5)); } - if (items > 6) { - if (sv_derived_from(ST(6), "Client")) { - IV tmp = SvIV((SV *)SvRV(ST(6))); - client = INT2PTR(Client *, tmp); - } - else { - nullclient = true; - } - if (client == nullptr) { - nullclient = true; - } - } - if (items > 7) { value1slot = (uint32)SvIV(ST(7)); } - if (items > 8) { value1ground = (uint32)SvIV(ST(8)); } - if (items > 9) { value2slot = (uint32)SvIV(ST(9)); } - if (items > 10) { value2ground = (uint32)SvIV(ST(10)); } - if (items > 11) { value3slot = (uint32)SvIV(ST(11)); } - if (items > 12) { value3ground = (uint32)SvIV(ST(12)); } - if (items > 13) { value4slot = (uint32)SvIV(ST(13)); } - if (items > 14) { value4ground = (uint32)SvIV(ST(14)); } - if (items > 15) { value5slot = (uint32)SvIV(ST(15)); } - if (items > 16) { value5ground = (uint32)SvIV(ST(16)); } - - if (nullclient) { - THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, 0, value1slot, value1ground, value2slot, value2ground, value3slot, value3ground, - value4slot, value4ground, value5slot, value5ground); - } - else { - THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, value1slot, value1ground, value2slot, value2ground, value3slot, value3ground, - value4slot, value4ground, value5slot, value5ground); - } - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SendAppearanceEffectActor); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SendAppearanceEffectActor) { - dXSARGS; - if (items < 3 || items > 12) - Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffectActor(THIS, int32 effect1, uint32 slot1 = 0, [int32 effect2 = 0], [uint32 slot2 = 0], [int32 effect3 = 0], [uint32 slot3 = 0], [int32 effect4 = 0], [uint32 slot4 = 0], [int32 effect5 = 0], [uint32 slot5 = 0], [Client* single_client_to_send_to = null])"); // @categories Script Utility - { - Mob *THIS; - int32 parm1 = (int32)SvIV(ST(1)); - uint32 value1slot = (uint32)SvIV(ST(2)); - int32 parm2 = 0; - uint32 value2slot = 0; - int32 parm3 = 0; - uint32 value3slot = 0; - int32 parm4 = 0; - uint32 value4slot = 0; - int32 parm5 = 0; - uint32 value5slot = 0; - Client *client = nullptr; - VALIDATE_THIS_IS_MOB; - if (items > 3) { parm2 = (int32)SvIV(ST(3)); } - if (items > 4) { value2slot = (uint32)SvIV(ST(4)); } - if (items > 5) { parm3 = (int32)SvIV(ST(5)); } - if (items > 6) { value3slot = (uint32)SvIV(ST(6)); } - if (items > 7) { parm4 = (int32)SvIV(ST(7)); } - if (items > 8) { value4slot = (uint32)SvIV(ST(8)); } - if (items > 9) { parm5 = (int32)SvIV(ST(9)); } - if (items > 10) { value5slot = (uint32)SvIV(ST(10)); } - if (items > 11) { - if (sv_derived_from(ST(11), "Client")) { - IV tmp = SvIV((SV *)SvRV(ST(11))); - client = INT2PTR(Client *, tmp); - } - else - Perl_croak(aTHX_ "client is not of type Client"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - } - - THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, value1slot, 0, value2slot, 0, value3slot, 0, - value4slot, 0, value5slot, 0); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SendAppearanceEffectGround); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SendAppearanceEffectGround) { - dXSARGS; - if (items < 3 || items > 8) - Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffectGround(THIS, int32 effect1, [int32 effect2 = 0], [int32 effect3 = 0], [int32 effect4 = 0], [int32 effect5 = 0], [Client* single_client_to_send_to = null])"); // @categories Script Utility - { - Mob *THIS; - int32 parm1 = (int32)SvIV(ST(1)); - int32 parm2 = 0; - int32 parm3 = 0; - int32 parm4 = 0; - int32 parm5 = 0; - Client *client = nullptr; - VALIDATE_THIS_IS_MOB; - if (items > 3) { parm2 = (int32)SvIV(ST(2)); } - if (items > 4) { parm3 = (int32)SvIV(ST(3)); } - if (items > 5) { parm4 = (int32)SvIV(ST(4)); } - if (items > 6) { parm5 = (int32)SvIV(ST(5)); } - if (items > 7) { - if (sv_derived_from(ST(6), "Client")) { - IV tmp = SvIV((SV *)SvRV(ST(11))); - client = INT2PTR(Client *, tmp); - } - else - Perl_croak(aTHX_ "client is not of type Client"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - } - - THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_RemoveAllAppearanceEffects); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RemoveAllAppearanceEffects) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::RemoveAllAppearanceEffects(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->SendIllusionPacket(THIS->GetRace(), THIS->GetGender(), THIS->GetTexture(), THIS->GetHelmTexture(), - THIS->GetHairColor(), THIS->GetBeardColor(), THIS->GetEyeColor1(), THIS->GetEyeColor2(), - THIS->GetHairStyle(), THIS->GetLuclinFace(), THIS->GetBeard(), 0xFF, - THIS->GetDrakkinHeritage(), THIS->GetDrakkinTattoo(), THIS->GetDrakkinDetails(), THIS->GetSize(), false); - THIS->ClearAppearenceEffects(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetFlyMode); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetFlyMode) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetFlyMode(THIS, uint8 flymode[0|1|2|3|4|5])"); // @categories Script Utility - { - Mob *THIS; - GravityBehavior flymode = (GravityBehavior) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetFlyMode(flymode); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetTexture); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetTexture) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetTexture(THIS, int32 texture)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 texture = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SendIllusionPacket(THIS->GetRace(), 0xFF, texture); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetRace); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetRace) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetRace(THIS, int32 race)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 race = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SendIllusionPacket(race); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetGender); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetGender) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetGender(THIS, int32 gender)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 gender = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SendIllusionPacket(THIS->GetRace(), gender); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SendIllusion); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SendIllusion) { - dXSARGS; - if (items < 2 || items > 14) - Perl_croak(aTHX_ "Usage: Mob::SendIllusion(THIS, uint16 race, [uint8 gender = 0xFF], [uint8 texture face = 0xFF], [uint8 hairstyle = 0xFF], [uint8 hair_color = 0xFF], [uint8 beard = 0xFF], [uint8 beard_color =FF], [uint32 drakkin_tattoo = 0xFFFFFFFF], [uint32 drakkin_details = 0xFFFFFFFF], [float size = -1])"); // @categories Script Utility - { - Mob *THIS; - uint16 race = (uint16) SvIV(ST(1)); - uint8 gender = 0xFF; - uint8 texture = 0xFF; - uint8 helmtexture = 0xFF; - uint8 face = 0xFF; - uint8 hairstyle = 0xFF; - uint8 haircolor = 0xFF; - uint8 beard = 0xFF; - uint8 beardcolor = 0xFF; - uint32 drakkin_heritage = 0xFFFFFFFF; - uint32 drakkin_tattoo = 0xFFFFFFFF; - uint32 drakkin_details = 0xFFFFFFFF; - float size = -1.0f; - VALIDATE_THIS_IS_MOB; - if (items > 2) { gender = (uint8) SvIV(ST(2)); } - if (items > 3) { texture = (uint8) SvIV(ST(3)); } - if (items > 4) { helmtexture = (uint8) SvIV(ST(4)); } - if (items > 5) { face = (uint8) SvIV(ST(5)); } - if (items > 6) { hairstyle = (uint8) SvIV(ST(6)); } - if (items > 7) { haircolor = (uint8) SvIV(ST(7)); } - if (items > 8) { beard = (uint8) SvIV(ST(8)); } - if (items > 9) { beardcolor = (uint8) SvIV(ST(9)); } - if (items > 10) { drakkin_heritage = (uint32) SvIV(ST(10)); } - if (items > 11) { drakkin_tattoo = (uint32) SvIV(ST(11)); } - if (items > 12) { drakkin_details = (uint32) SvIV(ST(12)); } - if (items > 13) { size = (float) SvNV(ST(13)); } - - THIS->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, - hairstyle, face, beard, 0xFF, drakkin_heritage, drakkin_tattoo, drakkin_details, size); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CameraEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CameraEffect) { - dXSARGS; - if (items < 2 || items > 5) - Perl_croak(aTHX_ "Usage: Mob::CameraEffect(THIS, uint32 duration, [uint32 intensity = 0], [Client* single_client = nullptr], [bool is_world_wide = false])"); // @categories Script Utility - { - Mob *THIS; - uint32 duration = (uint32) SvUV(ST(1)); - uint32 intensity = 0; - Client *client = nullptr; - bool global = false; - bool nullcli = false; - VALIDATE_THIS_IS_MOB; - if (items > 2) { intensity = (uint32) SvUV(ST(2)); } - if (items > 3) { - if (sv_derived_from(ST(3), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(3))); - client = INT2PTR(Client *, tmp); - } else - nullcli = true; - if (client == nullptr) - nullcli = true; - //Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - } - if (items > 4) { global = (bool) SvTRUE(ST(4)); } - - if (nullcli) - THIS->CameraEffect(duration, intensity, 0, global); - else - THIS->CameraEffect(duration, intensity, client, global); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SpellEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SpellEffect) { - dXSARGS; - if (items < 2 || items > 10) - Perl_croak(aTHX_ "Usage: Mob::SpellEffect(THIS, uint32 effect, [uint32 duration = 5000], [uint32 finish_delay = 0], [bool zone_wide = false], [uint32 unk20 = 3000], [bool perm_effect = false], [Client* single_client]), [caster_id = 0], [target_id = 0]"); // @categories Spells and Disciplines - { - Mob *THIS; - uint32 effect = (uint32) SvUV(ST(1)); - uint32 duration = 5000; - uint32 finish_delay = 0; - bool zone_wide = true; - uint32 unk20 = 3000; - bool perm_effect = false; - Client *client = nullptr; - uint32 caster_id = 0; - uint32 target_id = 0; - bool nullclient = false; - VALIDATE_THIS_IS_MOB; - if (items > 2) { duration = (uint32) SvUV(ST(2)); } - if (items > 3) { finish_delay = (uint32) SvUV(ST(3)); } - if (items > 4) { zone_wide = (bool) SvTRUE(ST(4)); } - if (items > 5) { unk20 = (uint32) SvUV(ST(5)); } - if (items > 6) { perm_effect = (bool) SvTRUE(ST(6)); } - if (items > 7) { - if (sv_derived_from(ST(7), "Client")) { - IV tmp = SvIV((SV *)SvRV(ST(7))); - client = INT2PTR(Client *, tmp); - } - else { - nullclient = true; - } - if (client == nullptr) { - nullclient = true; - } - } - if (items > 8) { caster_id = (uint32)SvUV(ST(8)); } - if (items > 9) { target_id = (uint32)SvUV(ST(9)); } - - if (nullclient) { - THIS->SendSpellEffect(effect, duration, finish_delay, zone_wide, unk20, perm_effect, 0, caster_id, target_id); - } - else { - THIS->SendSpellEffect(effect, duration, finish_delay, zone_wide, unk20, perm_effect, client, caster_id, target_id); - } - - } - XSRETURN_EMPTY; -} - - -XS(XS_Mob_TempName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_TempName) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Mob::TempName(THIS, string name)"); // @categories Script Utility - { - Mob *THIS; - char *name = nullptr; - VALIDATE_THIS_IS_MOB; - if (items > 1) { name = (char *) SvPV_nolen(ST(1)); } - - THIS->TempName(name); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetItemStat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetItemStat) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetItemStat(THIS, uint32 item_id, string stat)"); // @categories Inventory and Items, Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - uint32 itemid = (uint32) SvUV(ST(1)); - Const_char *stat = (Const_char *) SvPV_nolen(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetItemStat(itemid, stat); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetGlobal); -XS(XS_Mob_GetGlobal) { - dXSARGS; - if (items < 2) - Perl_croak(aTHX_ "Usage: GetGlobal(THIS, string var_name)"); - { - Mob *THIS; - Const_char *varname = (Const_char *) SvPV_nolen(ST(1)); - std::string ret_val = "Undefined"; - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - if (THIS->GetGlobal(varname) != "Undefined") - ret_val = THIS->GetGlobal(varname); - - RETVAL = ret_val.c_str(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_SetGlobal); -XS(XS_Mob_SetGlobal) { - dXSARGS; - if (items < 5 || items > 6) - Perl_croak(aTHX_ "Usage: SetGlobal(THIS, string var_name, string new_value, int options, string duration, [Mob* other = nullptr])"); - { - Mob *THIS; - char *varname = (char *) SvPV_nolen(ST(1)); - char *newvalue = (char *) SvPV_nolen(ST(2)); - int options = (int) SvIV(ST(3)); - char *duration = (char *) SvPV_nolen(ST(4)); - Mob *other = nullptr; - VALIDATE_THIS_IS_MOB; - if (items > 5) { - if (sv_derived_from(ST(5), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(5))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "THIS is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - } - - THIS->SetGlobal(varname, newvalue, options, duration, other); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_TarGlobal); -XS(XS_Mob_TarGlobal) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: TarGlobal(THIS, string var_name, string value, string duration, int npc_id, int character_id, int zone_id)"); - { - Mob *THIS; - char *varname = (char *) SvPV_nolen(ST(1)); - char *value = (char *) SvPV_nolen(ST(2)); - char *duration = (char *) SvPV_nolen(ST(3)); - int npcid = (int) SvIV(ST(4)); - int charid = (int) SvIV(ST(5)); - int zoneid = (int) SvIV(ST(6)); - VALIDATE_THIS_IS_MOB; - THIS->TarGlobal(varname, value, duration, npcid, charid, zoneid); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_DelGlobal); -XS(XS_Mob_DelGlobal) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: DelGlobal(THIS, string var_name)"); - { - Mob *THIS; - char *varname = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->DelGlobal(varname); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetSlotTint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetSlotTint) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: Mob::SetSlotTint(THIS, uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 material_slot = (uint8) SvIV(ST(1)); - uint8 red_tint = (uint8) SvIV(ST(2)); - uint8 green_tint = (uint8) SvIV(ST(3)); - uint8 blue_tint = (uint8) SvIV(ST(4)); - VALIDATE_THIS_IS_MOB; - THIS->SetSlotTint(material_slot, red_tint, green_tint, blue_tint); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_WearChange); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_WearChange) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::WearChange(THIS, uint8 material_slot, uint16 texture, [uint32 color = 0, uint32 hero_forge_model = 0])"); // @categories Script Utility - { - Mob *THIS; - uint8 material_slot = (uint8) SvIV(ST(1)); - uint16 texture = (uint16) SvUV(ST(2)); - uint32 color = 0; - uint32 hero_forge_model = 0; - VALIDATE_THIS_IS_MOB; - if (items > 3) { - color = (uint32) SvUV(ST(3)); - } - if (items > 4) { - hero_forge_model = (uint32) SvUV(ST(3)); - } - - THIS->WearChange(material_slot, texture, color, hero_forge_model); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_DoKnockback); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DoKnockback) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Mob::DoKnockback(THIS, Mob* caster, uint32 push_back_amount, uint32 push_up_amount)"); // @categories Script Utility - { - Mob *THIS; - Mob *caster; - uint32 push_back = (uint16) SvUV(ST(2)); - uint32 push_up = (uint16) SvUV(ST(2)); - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "caster is not of type Mob"); - if (caster == nullptr) - Perl_croak(aTHX_ "caster is nullptr, avoiding crash."); - - THIS->DoKnockback(caster, push_back, push_up); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_RemoveNimbusEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RemoveNimbusEffect) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::RemoveNimbusEffect(THIS, int32 effect_id)"); // @categories Script Utility - { - Mob *THIS; - int32 effect_id = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->RemoveNimbusEffect(effect_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetRunning); -XS(XS_Mob_SetRunning) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetRunning(THIS, bool value)"); // @categories Script Utility - { - Mob *THIS; - bool value = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetRunning(value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_IsRunning); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsRunning) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsRunning(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsRunning(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SetBodyType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetBodyType) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::SetBodyType(THIS, int32 type, [bool overwrite_orig = false])"); // @categories Stats and Attributes - { - Mob *THIS; - int32 type = (int32) SvIV(ST(1)); - bool overwrite_orig = false; - VALIDATE_THIS_IS_MOB; - if (items == 3) { - overwrite_orig = (bool) SvTRUE(ST(2)); - } - - THIS->SetBodyType((bodyType) type, overwrite_orig); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetDeltas); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetDeltas) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: Mob::SetDeltas(THIS, float delta_x, float delta_y, float delta_z, float delta_h)"); // @categories Script Utility - { - Mob *THIS; - auto delta = glm::vec4((float) SvNV(ST(1)), (float) SvNV(ST(2)), (float) SvNV(ST(3)), (float) SvNV(ST(4))); - VALIDATE_THIS_IS_MOB; - THIS->SetDelta(delta); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetLD); -XS(XS_Mob_SetLD) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetLD(THIS, bool value)"); // @categories Script Utility - { - Mob *THIS; - bool value = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SendAppearancePacket(AT_Linkdead, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetTargetable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetTargetable) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetTargetable(THIS, bool targetable)"); // @categories Stats and Attributes - { - Mob *THIS; - bool on = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetTargetable(on); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ModSkillDmgTaken); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ModSkillDmgTaken) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::ModSkillDmgTaken(THIS, int skill, int16 value)"); // @categories Skills and Recipes, Script Utility - { - Mob *THIS; - EQ::skills::SkillType skill_num = (EQ::skills::SkillType) SvUV(ST(1)); - int16 value = (int16) SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - THIS->ModSkillDmgTaken(skill_num, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetModSkillDmgTaken); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetModSkillDmgTaken) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetModSkillDmgTaken(THIS, int skill_id)"); // @categories Stats and Attributes - { - Mob *THIS; - int16 RETVAL; - dXSTARG; - EQ::skills::SkillType skill_num = (EQ::skills::SkillType) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetModSkillDmgTaken(skill_num); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSkillDmgTaken); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSkillDmgTaken) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetSkillDmgTaken(THIS, int skill_id)"); // @categories Skills and Recipes, Script Utility - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - EQ::skills::SkillType skill_num = (EQ::skills::SkillType) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSkillDmgTaken(skill_num); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetAllowBeneficial); -XS(XS_Mob_SetAllowBeneficial) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetAllowBeneficial(THIS, bool value)"); // @categories Stats and Attributes - { - Mob *THIS; - bool value = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetAllowBeneficial(value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetAllowBeneficial); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetAllowBeneficial) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetAllowBeneficial(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetAllowBeneficial(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsBeneficialAllowed); -XS(XS_Mob_IsBeneficialAllowed) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::IsBeneficialAllowed(THIS, Mob* target)"); // @categories Stats and Attributes - { - dXSTARG; - Mob *THIS; - Mob *target; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - if (target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - RETVAL = THIS->IsBeneficialAllowed(target); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_ModVulnerability); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ModVulnerability) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::ModVulnerability(THIS, uint8 resist, int16 value)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 resist = (uint8) SvIV(ST(1)); - int16 value = (int16) SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - THIS->ModVulnerability(resist, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetModVulnerability); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetModVulnerability) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetModVulnerability(THIS, uint8 resist)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - uint8 resist = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetModVulnerability(resist); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_DoMeleeSkillAttackDmg); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DoMeleeSkillAttackDmg) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: Mob::DoMeleeSkillAttackDmg(THIS, Mob* target, uint16 weapon_damage, int skill, int16 chance_mod, int16 focus, uint8 can_riposte)"); // @categories Script Utility, Skills and Attributes - { - Mob *THIS; - Mob *target; - uint16 weapon_damage = (uint16) SvIV(ST(2)); - EQ::skills::SkillType skill = (EQ::skills::SkillType) SvUV(ST(3)); - int16 chance_mod = (int16) SvIV(ST(4)); - int16 focus = (int16) SvIV(ST(5)); - uint8 CanRiposte = (uint8) SvIV(ST(6)); - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - if (target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - THIS->DoMeleeSkillAttackDmg(target, weapon_damage, skill, chance_mod, focus, CanRiposte); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_DoArcheryAttackDmg); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DoArcheryAttackDmg) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: Mob::DoArcheryAttackDmg(THIS, Mob* target, [range_weapon_item_instance = nullptr], [ammo_item_instance = nullptr], uint16 weapon_damage, int16 chance_mod, int16 focus)"); // @categories Script Utility, Skills and Attributes - { - Mob *THIS; - Mob *target; - EQ::ItemInstance *RangeWeapon = nullptr; - EQ::ItemInstance *Ammo = nullptr; - uint16 weapon_damage = (uint16) SvIV(ST(4)); - int16 chance_mod = (int16) SvIV(ST(5)); - int16 focus = (int16) SvIV(ST(6)); - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - if (target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - THIS->DoArcheryAttackDmg(target, RangeWeapon, Ammo, weapon_damage, chance_mod, focus); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_DoThrowingAttackDmg); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_DoThrowingAttackDmg) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: Mob::DoThrowingAttackDmg(THIS, Mob* target, [range_weapon_item_instance = nullptr], [ammo_item_instance = nullptr], uint16 weapon_damage, int16 chance_mod, int16 focus)"); // @categories Script Utility, Skills and Attributes - { - Mob *THIS; - Mob *target; - EQ::ItemInstance *RangeWeapon = nullptr; - EQ::ItemData *item = nullptr; - uint16 weapon_damage = (uint16) SvIV(ST(4)); - int16 chance_mod = (int16) SvIV(ST(5)); - int16 focus = (int16) SvIV(ST(6)); - VALIDATE_THIS_IS_MOB; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - if (target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - THIS->DoThrowingAttackDmg(target, RangeWeapon, item, weapon_damage, chance_mod, focus); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetDisableMelee); -XS(XS_Mob_SetDisableMelee) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetDisableMelee(THIS, bool value)"); // @categories Script Utility, Stats and Attributes - { - Mob *THIS; - bool value = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetDisableMelee(value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_IsMeleeDisabled); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_IsMeleeDisabled) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsMeleeDisabled(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsMeleeDisabled(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SetFlurryChance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetFlurryChance) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::SetFlurryChance(THIS, uint8 value)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 value = (uint8) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->SetFlurryChance(value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetFlurryChance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetFlurryChance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetFlurryChance(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetFlurryChance(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSpellStat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSpellStat) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::GetSpellStat(THIS, uint32 spell_id, string stat, uint8 slot)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - uint32 spellid = (uint32) SvUV(ST(1)); - Const_char *stat = (Const_char *) SvPV_nolen(ST(2)); - uint8 slot = (uint8) SvUV(ST(3)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - if (items > 4) { slot = 0; } - - - RETVAL = THIS->GetSpellStat(spellid, stat, slot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBuffStatValueBySpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBuffStatValueBySpell) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetBuffStatValueBySpell(THIS, int32 spell_id, string stat)"); // @categories Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - int32 spellid = (int32)SvIV(ST(1)); - Const_char *stat = (Const_char *)SvPV_nolen(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - - RETVAL = THIS->GetBuffStatValueBySpell(spellid, stat); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBuffStatValueBySlot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetBuffStatValueBySlot) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetBuffStatValueBySlot(THIS, uint8 slot, string stat)"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - int32 RETVAL; - uint8 slot = (uint8)SvUV(ST(1)); - Const_char *stat = (Const_char *)SvPV_nolen(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - - RETVAL = THIS->GetBuffStatValueBySlot(slot, stat); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSpecialAbility); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSpecialAbility) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetSpecialAbility(THIS, int special_ability)"); // @categories Stats and Attributes - { - int RETVAL; - Mob *THIS; - int ability = SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSpecialAbility(ability); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetSpecialAbilityParam); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetSpecialAbilityParam) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::GetSpecialAbilityParam(THIS, int special_ability, int param)"); // @categories Stats and Attributes - { - int RETVAL; - Mob *THIS; - int ability = SvIV(ST(1)); - int param = SvIV(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetSpecialAbilityParam(ability, param); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetSpecialAbility); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetSpecialAbility) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Mob::SetSpecialAbility(THIS, int ability, int value)"); // @categories Stats and Attributes - { - Mob *THIS; - int ability = SvIV(ST(1)); - int value = SvIV(ST(2)); - VALIDATE_THIS_IS_MOB; - THIS->SetSpecialAbility(ability, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetSpecialAbilityParam); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetSpecialAbilityParam) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Mob::SetSpecialAbilityParam(THIS, int ability, int param, int value)"); // @categories Stats and Attributes - { - Mob *THIS; - int ability = SvIV(ST(1)); - int param = SvIV(ST(2)); - int value = SvIV(ST(3)); - VALIDATE_THIS_IS_MOB; - THIS->SetSpecialAbilityParam(ability, param, value); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ClearSpecialAbilities); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ClearSpecialAbilities) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::ClearSpecialAbilities(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->ClearSpecialAbilities(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ProcessSpecialAbilities); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ProcessSpecialAbilities) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::ProcessSpecialAbilities(THIS, string str)"); // @categories Script Utility - { - Mob *THIS; - const char *str = (const char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->ProcessSpecialAbilities(str); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_CanClassEquipItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanClassEquipItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::CanClassEquipItem(THIS, uint32 item_id)"); // @categories Inventory and Items, Script Utility - { - Mob *THIS; - bool RETVAL; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CanClassEquipItem(item_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsFeared); -XS(XS_Mob_IsFeared) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsFeared(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsFeared(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsBlind); -XS(XS_Mob_IsBlind) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsBlind(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsBlind(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetInvisibleLevel); -XS(XS_Mob_GetInvisibleLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetInvisibleLevel(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetInvisibleLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetInvisibleUndeadLevel); -XS(XS_Mob_GetInvisibleUndeadLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetInvisibleUndeadLevel(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetInvisibleUndeadLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Mob_SeeInvisible); -XS(XS_Mob_SeeInvisible) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::SeeInvisible(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->SeeInvisible(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SeeInvisibleUndead); -XS(XS_Mob_SeeInvisibleUndead) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::SeeInvisibleUndead(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->SeeInvisibleUndead(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SeeHide); -XS(XS_Mob_SeeHide) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::SeeHide(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->SeeHide(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_SeeImprovedHide); -XS(XS_Mob_SeeImprovedHide) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::SeeImprovedHide(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->SeeImprovedHide(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetNimbusEffect1); -XS(XS_Mob_GetNimbusEffect1) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect1(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetNimbusEffect1(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetNimbusEffect2); -XS(XS_Mob_GetNimbusEffect2) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect2(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetNimbusEffect2(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetNimbusEffect3); -XS(XS_Mob_GetNimbusEffect3) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect3(THIS)"); // @categories Script Utility - { - Mob *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetNimbusEffect3(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsTargetable); -XS(XS_Mob_IsTargetable) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsTargetable(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsTargetable(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_HasShieldEquiped); -XS(XS_Mob_HasShieldEquiped) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::HasShieldEquiped(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HasShieldEquiped(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_HasTwoHandBluntEquiped); -XS(XS_Mob_HasTwoHandBluntEquiped) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::HasTwoHandBluntEquiped(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HasTwoHandBluntEquiped(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_HasTwoHanderEquipped); -XS(XS_Mob_HasTwoHanderEquipped) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::HasTwoHanderEquipped(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HasTwoHanderEquipped(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHerosForgeModel); -XS(XS_Mob_GetHerosForgeModel) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetHerosForgeModel(THIS, uint8 material_slot)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - uint8 material_slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHerosForgeModel(material_slot); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_IsEliteMaterialItem); -XS(XS_Mob_IsEliteMaterialItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::IsEliteMaterialItem(THIS, uint8 material_slot)"); // @categories Script Utility, Stats and Attributes - { - Mob *THIS; - uint32 RETVAL; - uint8 material_slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsEliteMaterialItem(material_slot); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetBaseSize); -XS(XS_Mob_GetBaseSize) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetBaseSize(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetBaseSize(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_HasOwner); -XS(XS_Mob_HasOwner) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::HasOwner(THIS)"); // @categories Pet - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HasOwner(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsPet); -XS(XS_Mob_IsPet) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsPet(THIS)"); // @categories Pet - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsPet(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_HasPet); -XS(XS_Mob_HasPet) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::HasPet(THIS)"); // @categories Pet - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->HasPet(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_RemovePet); -XS(XS_Mob_RemovePet) { - dXSARGS; - if (items != 1) { - Perl_croak(aTHX_ "Usage: Mob::RemovePet(THIS)"); // @categories Pet - } - - Mob* THIS; - VALIDATE_THIS_IS_MOB; - - THIS->SetPet(nullptr); - - XSRETURN_EMPTY; -} - -XS(XS_Mob_SetPet); -XS(XS_Mob_SetPet) { - dXSARGS; - if (items != 2) { - Perl_croak(aTHX_ "Usage: Mob::SetPet(THIS, Mob* new_pet)"); // @categories Pet - } - - Mob* THIS; - VALIDATE_THIS_IS_MOB; - - Mob* new_pet = nullptr; // passing null or invalid new_pet removes pet - if (sv_derived_from(ST(1), "Mob")) - { - IV tmp = SvIV((SV*)SvRV(ST(1))); - new_pet = INT2PTR(Mob*, tmp); - } - - THIS->SetPet(new_pet); - - XSRETURN_EMPTY; -} - -XS(XS_Mob_IsSilenced); -XS(XS_Mob_IsSilenced) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsSilenced(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsSilenced(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_IsAmnesiad); -XS(XS_Mob_IsAmnesiad) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsAmnesiad(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsAmnesiad(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetMeleeMitigation); -XS(XS_Mob_GetMeleeMitigation) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMeleeMitigation(THIS)"); // @categories Stats and Attributes - { - Mob *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetMeleeMitigation(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_TryMoveAlong); -XS(XS_Mob_TryMoveAlong) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::TryMoveAlong(THIS, float distance, float angle, bool send)"); // @categories Script Utility - { - Mob *THIS; - float distance = (float) SvNV(ST(1)); - float angle = (float) SvNV(ST(2)); - bool send = true; - VALIDATE_THIS_IS_MOB; - if (items == 4) - send = (bool) SvTRUE(ST(3)); - - THIS->TryMoveAlong(distance, angle, send); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetClassName); -XS(XS_Mob_GetClassName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetClassName(THIS)"); - { - Mob* THIS; - Const_char *class_name; - dXSTARG; - VALIDATE_THIS_IS_MOB; - class_name = GetClassIDName(THIS->GetClass()); - sv_setpv(TARG, class_name); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_GetRaceName); -XS(XS_Mob_GetRaceName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetRaceName(THIS)"); - { - Mob* THIS; - Const_char *race_name; - dXSTARG; - VALIDATE_THIS_IS_MOB; - race_name = GetRaceIDName(THIS->GetRace()); - sv_setpv(TARG, race_name); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_DeleteBucket); -XS(XS_Mob_DeleteBucket) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::DeleteBucket(THIS, string bucket_name)"); // @categories Script Utility - { - Mob* THIS; - std::string bucket_name = (std::string) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->DeleteBucket(bucket_name); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetBucket); -XS(XS_Mob_GetBucket) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetBucket(THIS, string bucket_name)"); // @categories Script Utility - { - Mob* THIS; - dXSTARG; - std::string bucket_name = (std::string) SvPV_nolen(ST(1)); - std::string bucket_value; - VALIDATE_THIS_IS_MOB; - bucket_value = THIS->GetBucket(bucket_name); - sv_setpv(TARG, bucket_value.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_GetBucketExpires); -XS(XS_Mob_GetBucketExpires) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetBucketExpires(THIS, string bucket_name)"); // @categories Script Utility - { - Mob* THIS; - dXSTARG; - std::string bucket_name = (std::string) SvPV_nolen(ST(1)); - std::string bucket_expiration; - VALIDATE_THIS_IS_MOB; - bucket_expiration = THIS->GetBucketExpires(bucket_name); - sv_setpv(TARG, bucket_expiration.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_GetBucketKey); -XS(XS_Mob_GetBucketKey) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetBucketKey(THIS)"); // @categories Script Utility - { - Mob* THIS; - dXSTARG; - std::string bucket_key; - VALIDATE_THIS_IS_MOB; - bucket_key = THIS->GetBucketKey(); - sv_setpv(TARG, bucket_key.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_GetBucketRemaining); -XS(XS_Mob_GetBucketRemaining) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetBucketRemaining(THIS, string bucket_name)"); // @categories Script Utility - { - Mob* THIS; - dXSTARG; - std::string bucket_name = (std::string) SvPV_nolen(ST(1)); - std::string bucket_remaining; - VALIDATE_THIS_IS_MOB; - bucket_remaining = THIS->GetBucketRemaining(bucket_name); - sv_setpv(TARG, bucket_remaining.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_SetBucket); -XS(XS_Mob_SetBucket) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::SetBucket(THIS, string bucket_name, string bucket_value, [string expiration])"); // @categories Script Utility - { - Mob* THIS; - std::string key = (std::string) SvPV_nolen(ST(1)); - std::string value = (std::string) SvPV_nolen(ST(2)); - std::string expiration; - VALIDATE_THIS_IS_MOB; - if (items == 4) - expiration = (std::string) SvPV_nolen(ST(3)); - - THIS->SetBucket(key, value, expiration); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_IsHorse); -XS(XS_Mob_IsHorse) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::IsHorse(THIS)"); // @categories Script Utility - { - Mob *THIS; - bool RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->IsHorse(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHateListByDistance); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateListByDistance) { - dXSARGS; - int num_entries = 0; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Mob::GetHateListByDistance(THIS, int distance)"); // @categories Hate and Aggro - { - Mob *THIS; - int distance = 0; - VALIDATE_THIS_IS_MOB; - if (items == 2) - distance = (int) SvIV(ST(1)); - - auto list = THIS->GetHateListByDistance(distance); - for (auto hate_entry : list) { - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "HateEntry", (void *) hate_entry); - XPUSHs(ST(0)); - num_entries++; - } - } - XSRETURN(num_entries); -} - -XS(XS_Mob_GetHateClosest); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateClosest) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHateClosest(THIS)"); // @categories Hate and Aggro - { - Mob *THIS; - Mob *closest_mob; - VALIDATE_THIS_IS_MOB; - closest_mob = THIS->GetHateClosest(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Mob", (void *) closest_mob); - } - XSRETURN(1); -} - -XS(XS_Mob_GetLastName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetLastName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetLastName(THIS)"); // @categories Script Utility - { - Mob *THIS; - Const_char *last_name; - dXSTARG; - VALIDATE_THIS_IS_MOB; - last_name = THIS->GetLastName(); - sv_setpv(TARG, last_name); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Mob_CanRaceEquipItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CanRaceEquipItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::CanRaceEquipItem(THIS, uint32 item_id)"); // @categories Inventory and Items, Script Utility - { - Mob *THIS; - bool RETVAL; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CanRaceEquipItem(item_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Mob_RemoveAllNimbusEffects); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_RemoveAllNimbusEffects) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::RemoveAllNimbusEffects(THIS)"); // @categories Script Utility - { - Mob *THIS; - VALIDATE_THIS_IS_MOB; - THIS->RemoveAllNimbusEffects(); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_AddNimbusEffect); -XS(XS_Mob_AddNimbusEffect) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::AddNimbusEffect(THIS, int effect_id)"); // @categories Script Utility - { - Mob* THIS; - int effect_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_MOB; - THIS->AddNimbusEffect(effect_id); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ShieldAbility); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ShieldAbility) { - dXSARGS; - if (items < 2 || items > 6) - Perl_croak(aTHX_ "Usage: Mob::ShieldAbility(THIS, uint32 target_id, [int32 shielder__max_distance = 15], [int32 shield_duration = 12000], [int32 shield_target_mitigation= 50], [int32 shielder_mitigation = 50], [bool use_aa = false], bool [can_shield_npc = true]"); // @categories Spells and Disciplines - { - Mob *THIS; - uint32 target_id = (uint32)SvUV(ST(1)); - int32 shielder_max_distance = (int32)SvUV(ST(2)); - int32 shield_duration = (int32)SvUV(ST(3)); - int32 shield_target_mitigation = (int32)SvUV(ST(4)); - int32 shielder_mitigation = (int32)SvUV(ST(5)); - bool use_aa = (bool)SvTRUE(ST(6)); - bool can_shield_npc = (bool)SvTRUE(ST(7)); - - VALIDATE_THIS_IS_MOB; - if (items < 3) { - shielder_max_distance = 15; - } - - if (items < 4) { - shield_duration = 12000; - } - - if (items < 5) { - shield_target_mitigation = 50; - } - - if (items < 6) { - shielder_mitigation = 50; - } - - if (items < 7) { - use_aa = false; - } - - if (items < 8) { - can_shield_npc = true; - } - THIS->ShieldAbility(target_id, shielder_max_distance, shield_duration, shield_duration, shield_duration, use_aa, can_shield_npc); - - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_GetHateRandomClient); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateRandomClient) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHateRandomClient(THIS)"); // @categories Hate and Aggro - { - Mob* THIS; - Client* RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHateRandomClient(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_GetHateRandomNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateRandomNPC) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHateRandomNPC(THIS)"); // @categories Hate and Aggro - { - Mob* THIS; - NPC* RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHateRandomNPC(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "NPC", (void *) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Mob_SetBuffDuration); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_SetBuffDuration) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::SetBuffDuration(THIS, spell_id, [int duration = 0])"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - int spell_id = (int)SvIV(ST(1)); - int duration = 0; - VALIDATE_THIS_IS_MOB; - - if (items == 3) { - duration = (int)SvIV(ST(2)); - } - - THIS->SetBuffDuration(spell_id, duration); - } - XSRETURN_EMPTY; -} - -XS(XS_Mob_ApplySpellBuff); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_ApplySpellBuff) { - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: Mob::ApplySpellBuff(THIS, spell_id, [int duration = 0])"); // @categories Script Utility, Spells and Disciplines - { - Mob *THIS; - int spell_id = (int)SvIV(ST(1)); - int duration = 0; - VALIDATE_THIS_IS_MOB; - - if (items == 3) { - duration = (int)SvIV(ST(2)); - } - - THIS->ApplySpellBuff(spell_id, duration); - } - XSRETURN_EMPTY; -} - -#ifdef BOTS -XS(XS_Mob_CastToBot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_CastToBot) +bool Perl_Mob_IsClient(Mob* self) // @categories Script Utility { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::CastToBot(THIS)"); - { - Mob* THIS; - Bot* RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->CastToBot(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Bot", (void*)RETVAL); - } - XSRETURN(1); + return self->IsClient(); } -XS(XS_Mob_GetHateRandomBot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetHateRandomBot) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetHateRandomBot(THIS)"); // @categories Hate and Aggro - { - Mob* THIS; - Bot* RETVAL; - VALIDATE_THIS_IS_MOB; - RETVAL = THIS->GetHateRandomBot(); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Bot", (void *) RETVAL); - } - XSRETURN(1); +bool Perl_Mob_IsNPC(Mob* self) // @categories Script Utility +{ + return self->IsNPC(); } -#endif -#ifdef __cplusplus -extern "C" -#endif -XS(boot_Mob); /* prototype to pass -Wmissing-prototypes */ -XS(boot_Mob) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; +bool Perl_Mob_IsBot(Mob* self) // @categories Script Utility +{ + return self->IsBot(); +} - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; +bool Perl_Mob_IsMob(Mob* self) // @categories Script Utility +{ + return self->IsMob(); +} - //add the strcpy stuff to get rid of const warnings.... +bool Perl_Mob_IsCorpse(Mob* self) // @categories Script Utility, Corpse +{ + return self->IsCorpse(); +} - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "AddFeignMemory"), XS_Mob_AddFeignMemory, file, "$$"); - newXSproto(strcpy(buf, "AddNimbusEffect"), XS_Mob_AddNimbusEffect, file, "$$"); - newXSproto(strcpy(buf, "AddToHateList"), XS_Mob_AddToHateList, file, "$$;$$$$$"); - newXSproto(strcpy(buf, "ApplySpellBuff"), XS_Mob_ApplySpellBuff, file, "$$;$"); - newXSproto(strcpy(buf, "Attack"), XS_Mob_Attack, file, "$$;$$"); - newXSproto(strcpy(buf, "BehindMob"), XS_Mob_BehindMob, file, "$;$$$"); - newXSproto(strcpy(buf, "BuffCount"), XS_Mob_BuffCount, file, "$"); - newXSproto(strcpy(buf, "BuffFadeAll"), XS_Mob_BuffFadeAll, file, "$"); - newXSproto(strcpy(buf, "BuffFadeByEffect"), XS_Mob_BuffFadeByEffect, file, "$$;$"); - newXSproto(strcpy(buf, "BuffFadeBySlot"), XS_Mob_BuffFadeBySlot, file, "$$;$"); - newXSproto(strcpy(buf, "BuffFadeBySpellID"), XS_Mob_BuffFadeBySpellID, file, "$$"); - newXSproto(strcpy(buf, "CalculateDistance"), XS_Mob_CalculateDistance, file, "$$$$"); - newXSproto(strcpy(buf, "CalculateHeadingToTarget"), XS_Mob_CalculateHeadingToTarget, file, "$$$"); - newXSproto(strcpy(buf, "CameraEffect"), XS_Mob_CameraEffect, file, "$$;$$$"); - newXSproto(strcpy(buf, "CanBuffStack"), XS_Mob_CanBuffStack, file, "$$$;$"); - newXSproto(strcpy(buf, "CanClassEquipItem"), XS_Mob_CanClassEquipItem, file, "$$"); - newXSproto(strcpy(buf, "CanRaceEquipItem"), XS_Mob_CanRaceEquipItem, file, "$$"); - newXSproto(strcpy(buf, "CanThisClassDodge"), XS_Mob_CanThisClassDodge, file, "$"); - newXSproto(strcpy(buf, "CanThisClassDoubleAttack"), XS_Mob_CanThisClassDoubleAttack, file, "$"); - newXSproto(strcpy(buf, "CanThisClassDualWield"), XS_Mob_CanThisClassDualWield, file, "$"); - newXSproto(strcpy(buf, "CanThisClassParry"), XS_Mob_CanThisClassParry, file, "$"); - newXSproto(strcpy(buf, "CanThisClassRiposte"), XS_Mob_CanThisClassRiposte, file, "$"); - newXSproto(strcpy(buf, "CastSpell"), XS_Mob_CastSpell, file, "$$$;$$$"); -#ifdef BOTS - newXSproto(strcpy(buf, "CastToBot"), XS_Mob_CastToBot, file, "$"); -#endif - newXSproto(strcpy(buf, "CastToClient"), XS_Mob_CastToClient, file, "$"); - newXSproto(strcpy(buf, "CastToCorpse"), XS_Mob_CastToCorpse, file, "$"); - newXSproto(strcpy(buf, "CastToMob"), XS_Mob_CastToMob, file, "$"); - newXSproto(strcpy(buf, "CastToNPC"), XS_Mob_CastToNPC, file, "$"); - newXSproto(strcpy(buf, "CastingSpellID"), XS_Mob_CastingSpellID, file, "$"); - newXSproto(strcpy(buf, "ChangeSize"), XS_Mob_ChangeSize, file, "$$;$"); - newXSproto(strcpy(buf, "Charmed"), XS_Mob_Charmed, file, "$"); - newXSproto(strcpy(buf, "CheckAggro"), XS_Mob_CheckAggro, file, "$$"); - newXSproto(strcpy(buf, "CheckAggroAmount"), XS_Mob_CheckAggroAmount, file, "$$"); - newXSproto(strcpy(buf, "CheckHealAggroAmount"), XS_Mob_CheckHealAggroAmount, file, "$$"); - newXSproto(strcpy(buf, "CheckLoS"), XS_Mob_CheckLoS, file, "$$"); - newXSproto(strcpy(buf, "CheckLoSToLoc"), XS_Mob_CheckLoSToLoc, file, "$$$$;$"); - newXSproto(strcpy(buf, "ClearFeignMemory"), XS_Mob_ClearFeignMemory, file, "$"); - newXSproto(strcpy(buf, "ClearSpecialAbilities"), XS_Mob_ClearSpecialAbilities, file, "$"); - newXSproto(strcpy(buf, "CombatRange"), XS_Mob_CombatRange, file, "$$"); - newXSproto(strcpy(buf, "Damage"), XS_Mob_Damage, file, "$$$$$;$$$"); - newXSproto(strcpy(buf, "DelGlobal"), XS_Mob_DelGlobal, file, "$$"); - newXSproto(strcpy(buf, "DeleteBucket"), XS_Mob_DeleteBucket, file, "$$"); - newXSproto(strcpy(buf, "Depop"), XS_Mob_Depop, file, "$;$"); - newXSproto(strcpy(buf, "DivineAura"), XS_Mob_DivineAura, file, "$"); - newXSproto(strcpy(buf, "DoAnim"), XS_Mob_DoAnim, file, "$$;$"); - newXSproto(strcpy(buf, "DoArcheryAttackDmg"), XS_Mob_DoArcheryAttackDmg, file, "$$$$$$$"); - newXSproto(strcpy(buf, "DoKnockback"), XS_Mob_DoKnockback, file, "$$$$"); - newXSproto(strcpy(buf, "DoMeleeSkillAttackDmg"), XS_Mob_DoMeleeSkillAttackDmg, file, "$$$$$$$"); - newXSproto(strcpy(buf, "DoSpecialAttackDamage"), XS_Mob_DoSpecialAttackDamage, file, "$$$$;$$"); - newXSproto(strcpy(buf, "DoThrowingAttackDmg"), XS_Mob_DoThrowingAttackDmg, file, "$$$$$$$"); - newXSproto(strcpy(buf, "DontBuffMeBefore"), XS_Mob_DontBuffMeBefore, file, "$"); - newXSproto(strcpy(buf, "DontDotMeBefore"), XS_Mob_DontDotMeBefore, file, "$"); - newXSproto(strcpy(buf, "DontHealMeBefore"), XS_Mob_DontHealMeBefore, file, "$"); - newXSproto(strcpy(buf, "DontRootMeBefore"), XS_Mob_DontRootMeBefore, file, "$"); - newXSproto(strcpy(buf, "DontSnareMeBefore"), XS_Mob_DontSnareMeBefore, file, "$"); - newXSproto(strcpy(buf, "DoubleAggro"), XS_Mob_DoubleAggro, file, "$$"); - newXSproto(strcpy(buf, "Emote"), XS_Mob_Emote, file, "$$;@"); - newXSproto(strcpy(buf, "EntityVariableExists"), XS_Mob_EntityVariableExists, file, "$$"); - newXSproto(strcpy(buf, "FaceTarget"), XS_Mob_FaceTarget, file, "$;$$"); - newXSproto(strcpy(buf, "FindBuff"), XS_Mob_FindBuff, file, "$$"); - newXSproto(strcpy(buf, "FindBuffBySlot"), XS_Mob_FindBuffBySlot, file, "$$"); - newXSproto(strcpy(buf, "FindGroundZ"), XS_Mob_FindGroundZ, file, "$$$;$"); - newXSproto(strcpy(buf, "FindType"), XS_Mob_FindType, file, "$$;$$"); - newXSproto(strcpy(buf, "GMMove"), XS_Mob_GMMove, file, "$$$$;$"); - newXSproto(strcpy(buf, "Gate"), XS_Mob_Gate, file, "$"); - newXSproto(strcpy(buf, "GetAA"), XS_Mob_GetAA, file, "$$"); - newXSproto(strcpy(buf, "GetAAByAAID"), XS_Mob_GetAAByAAID, file, "$$"); - newXSproto(strcpy(buf, "GetAC"), XS_Mob_GetAC, file, "$"); - newXSproto(strcpy(buf, "GetAGI"), XS_Mob_GetAGI, file, "$"); - newXSproto(strcpy(buf, "GetATK"), XS_Mob_GetATK, file, "$"); - newXSproto(strcpy(buf, "GetActSpellCasttime"), XS_Mob_GetActSpellCasttime, file, "$$$"); - newXSproto(strcpy(buf, "GetActSpellCost"), XS_Mob_GetActSpellCost, file, "$$$"); - newXSproto(strcpy(buf, "GetActSpellDamage"), XS_Mob_GetActSpellDamage, file, "$$$"); - newXSproto(strcpy(buf, "GetActSpellDuration"), XS_Mob_GetActSpellDuration, file, "$$$"); - newXSproto(strcpy(buf, "GetActSpellHealing"), XS_Mob_GetActSpellHealing, file, "$$$"); - newXSproto(strcpy(buf, "GetActSpellRange"), XS_Mob_GetActSpellRange, file, "$$$"); - newXSproto(strcpy(buf, "GetAggroRange"), XS_Mob_GetAggroRange, file, "$"); - newXSproto(strcpy(buf, "GetAllowBeneficial"), XS_Mob_GetAllowBeneficial, file, "$$"); - newXSproto(strcpy(buf, "GetAppearance"), XS_Mob_GetAppearance, file, "$"); - newXSproto(strcpy(buf, "GetArmorTint"), XS_Mob_GetArmorTint, file, "$$"); - newXSproto(strcpy(buf, "GetAssistRange"), XS_Mob_GetAssistRange, file, "$"); - newXSproto(strcpy(buf, "GetBaseGender"), XS_Mob_GetBaseGender, file, "$"); - newXSproto(strcpy(buf, "GetBaseRace"), XS_Mob_GetBaseRace, file, "$"); - newXSproto(strcpy(buf, "GetBaseSize"), XS_Mob_GetBaseSize, file, "$"); - newXSproto(strcpy(buf, "GetBeard"), XS_Mob_GetBeard, file, "$"); - newXSproto(strcpy(buf, "GetBeardColor"), XS_Mob_GetBeardColor, file, "$"); - newXSproto(strcpy(buf, "GetBodyType"), XS_Mob_GetBodyType, file, "$"); - newXSproto(strcpy(buf, "GetBucket"), XS_Mob_GetBucket, file, "$$"); - newXSproto(strcpy(buf, "GetBucketExpires"), XS_Mob_GetBucketExpires, file, "$$"); - newXSproto(strcpy(buf, "GetBucketKey"), XS_Mob_GetBucketKey, file, "$"); - newXSproto(strcpy(buf, "GetBucketRemaining"), XS_Mob_GetBucketRemaining, file, "$$"); - newXSproto(strcpy(buf, "GetBuffSlotFromType"), XS_Mob_GetBuffSlotFromType, file, "$$"); - newXSproto(strcpy(buf, "GetBuffStatValueBySpell"), XS_Mob_GetBuffStatValueBySpell, file, "$$$"); - newXSproto(strcpy(buf, "GetBuffStatValueBySlot"), XS_Mob_GetBuffStatValueBySlot, file, "$$$"); - newXSproto(strcpy(buf, "GetCHA"), XS_Mob_GetCHA, file, "$"); - newXSproto(strcpy(buf, "GetCR"), XS_Mob_GetCR, file, "$"); - newXSproto(strcpy(buf, "GetCasterLevel"), XS_Mob_GetCasterLevel, file, "$$"); - newXSproto(strcpy(buf, "GetClass"), XS_Mob_GetClass, file, "$"); - newXSproto(strcpy(buf, "GetClassLevelFactor"), XS_Mob_GetClassLevelFactor, file, "$"); - newXSproto(strcpy(buf, "GetClassName"), XS_Mob_GetClassName, file, "$"); - newXSproto(strcpy(buf, "GetCleanName"), XS_Mob_GetCleanName, file, "$"); - newXSproto(strcpy(buf, "GetCorruption"), XS_Mob_GetCorruption, file, "$"); - newXSproto(strcpy(buf, "GetDEX"), XS_Mob_GetDEX, file, "$"); - newXSproto(strcpy(buf, "GetDR"), XS_Mob_GetDR, file, "$"); - newXSproto(strcpy(buf, "GetDamageAmount"), XS_Mob_GetDamageAmount, file, "$$"); - newXSproto(strcpy(buf, "GetDeity"), XS_Mob_GetDeity, file, "$"); - newXSproto(strcpy(buf, "GetDisplayAC"), XS_Mob_GetDisplayAC, file, "$"); - newXSproto(strcpy(buf, "GetDrakkinDetails"), XS_Mob_GetDrakkinDetails, file, "$"); - newXSproto(strcpy(buf, "GetDrakkinHeritage"), XS_Mob_GetDrakkinHeritage, file, "$"); - newXSproto(strcpy(buf, "GetDrakkinTattoo"), XS_Mob_GetDrakkinTattoo, file, "$"); - newXSproto(strcpy(buf, "GetEntityVariable"), XS_Mob_GetEntityVariable, file, "$$"); - newXSproto(strcpy(buf, "GetEquipment"), XS_Mob_GetEquipment, file, "$$"); - newXSproto(strcpy(buf, "GetEquipmentColor"), XS_Mob_GetEquipmentColor, file, "$$"); - newXSproto(strcpy(buf, "GetEquipmentMaterial"), XS_Mob_GetEquipmentMaterial, file, "$$"); - newXSproto(strcpy(buf, "GetEyeColor1"), XS_Mob_GetEyeColor1, file, "$"); - newXSproto(strcpy(buf, "GetEyeColor2"), XS_Mob_GetEyeColor2, file, "$"); - newXSproto(strcpy(buf, "GetFR"), XS_Mob_GetFR, file, "$"); - newXSproto(strcpy(buf, "GetFlurryChance"), XS_Mob_GetFlurryChance, file, "$"); - newXSproto(strcpy(buf, "GetFollowID"), XS_Mob_GetFollowID, file, "$"); - newXSproto(strcpy(buf, "GetGender"), XS_Mob_GetGender, file, "$"); - newXSproto(strcpy(buf, "GetGlobal"), XS_Mob_GetGlobal, file, "$$"); - newXSproto(strcpy(buf, "GetHP"), XS_Mob_GetHP, file, "$"); - newXSproto(strcpy(buf, "GetHPRatio"), XS_Mob_GetHPRatio, file, "$"); - newXSproto(strcpy(buf, "GetHairColor"), XS_Mob_GetHairColor, file, "$"); - newXSproto(strcpy(buf, "GetHairStyle"), XS_Mob_GetHairStyle, file, "$"); - newXSproto(strcpy(buf, "GetHandToHandDamage"), XS_Mob_GetHandToHandDamage, file, "$"); - newXSproto(strcpy(buf, "GetHandToHandDelay"), XS_Mob_GetHandToHandDelay, file, "$"); - newXSproto(strcpy(buf, "GetHaste"), XS_Mob_GetHaste, file, "$"); - newXSproto(strcpy(buf, "GetHateAmount"), XS_Mob_GetHateAmount, file, "$$;$"); - newXSproto(strcpy(buf, "GetHateClosest"), XS_Mob_GetHateClosest, file, "$"); - newXSproto(strcpy(buf, "GetHateDamageTop"), XS_Mob_GetHateDamageTop, file, "$$"); - newXSproto(strcpy(buf, "GetHateList"), XS_Mob_GetHateList, file, "$"); - newXSproto(strcpy(buf, "GetHateListByDistance"), XS_Mob_GetHateListByDistance, file, "$;$"); - newXSproto(strcpy(buf, "GetHateRandom"), XS_Mob_GetHateRandom, file, "$"); -#ifdef BOTS - newXSproto(strcpy(buf, "GetHateRandomBot"), XS_Mob_GetHateRandomBot, file, "$"); -#endif - newXSproto(strcpy(buf, "GetHateRandomClient"), XS_Mob_GetHateRandomClient, file, "$"); - newXSproto(strcpy(buf, "GetHateRandomNPC"), XS_Mob_GetHateRandomNPC, file, "$"); - newXSproto(strcpy(buf, "GetHateTop"), XS_Mob_GetHateTop, file, "$"); - newXSproto(strcpy(buf, "GetHeading"), XS_Mob_GetHeading, file, "$"); - newXSproto(strcpy(buf, "GetHelmTexture"), XS_Mob_GetHelmTexture, file, "$"); - newXSproto(strcpy(buf, "GetHerosForgeModel"), XS_Mob_GetHerosForgeModel, file, "$$"); - newXSproto(strcpy(buf, "GetID"), XS_Mob_GetID, file, "$"); - newXSproto(strcpy(buf, "GetINT"), XS_Mob_GetINT, file, "$"); - newXSproto(strcpy(buf, "GetInvisibleLevel"), XS_Mob_GetInvisibleLevel, file, "$"); - newXSproto(strcpy(buf, "GetInvisibleUndeadLevel"), XS_Mob_GetInvisibleUndeadLevel, file, "$"); - newXSproto(strcpy(buf, "GetInvul"), XS_Mob_GetInvul, file, "$"); - newXSproto(strcpy(buf, "GetItemHPBonuses"), XS_Mob_GetItemHPBonuses, file, "$"); - newXSproto(strcpy(buf, "GetItemStat"), XS_Mob_GetItemStat, file, "$$$"); - newXSproto(strcpy(buf, "GetLastName"), XS_Mob_GetLastName, file, "$"); - newXSproto(strcpy(buf, "GetLevel"), XS_Mob_GetLevel, file, "$"); - newXSproto(strcpy(buf, "GetLevelCon"), XS_Mob_GetLevelCon, file, "$$"); - newXSproto(strcpy(buf, "GetLevelHP"), XS_Mob_GetLevelHP, file, "$$"); - newXSproto(strcpy(buf, "GetLuclinFace"), XS_Mob_GetLuclinFace, file, "$"); - newXSproto(strcpy(buf, "GetMR"), XS_Mob_GetMR, file, "$"); - newXSproto(strcpy(buf, "GetMana"), XS_Mob_GetMana, file, "$"); - newXSproto(strcpy(buf, "GetManaRatio"), XS_Mob_GetManaRatio, file, "$"); - newXSproto(strcpy(buf, "GetMaxAGI"), XS_Mob_GetMaxAGI, file, "$"); - newXSproto(strcpy(buf, "GetMaxCHA"), XS_Mob_GetMaxCHA, file, "$"); - newXSproto(strcpy(buf, "GetMaxDEX"), XS_Mob_GetMaxDEX, file, "$"); - newXSproto(strcpy(buf, "GetMaxHP"), XS_Mob_GetMaxHP, file, "$"); - newXSproto(strcpy(buf, "GetMaxINT"), XS_Mob_GetMaxINT, file, "$"); - newXSproto(strcpy(buf, "GetMaxMana"), XS_Mob_GetMaxMana, file, "$"); - newXSproto(strcpy(buf, "GetMaxSTA"), XS_Mob_GetMaxSTA, file, "$"); - newXSproto(strcpy(buf, "GetMaxSTR"), XS_Mob_GetMaxSTR, file, "$"); - newXSproto(strcpy(buf, "GetMaxWIS"), XS_Mob_GetMaxWIS, file, "$"); - newXSproto(strcpy(buf, "GetMeleeMitigation"), XS_Mob_GetMeleeMitigation, file, "$"); - newXSproto(strcpy(buf, "GetModSkillDmgTaken"), XS_Mob_GetModSkillDmgTaken, file, "$$"); - newXSproto(strcpy(buf, "GetModVulnerability"), XS_Mob_GetModVulnerability, file, "$$"); - newXSproto(strcpy(buf, "GetNPCTypeID"), XS_Mob_GetNPCTypeID, file, "$"); - newXSproto(strcpy(buf, "GetName"), XS_Mob_GetName, file, "$"); - newXSproto(strcpy(buf, "GetNimbusEffect1"), XS_Mob_GetNimbusEffect1, file, "$"); - newXSproto(strcpy(buf, "GetNimbusEffect2"), XS_Mob_GetNimbusEffect2, file, "$"); - newXSproto(strcpy(buf, "GetNimbusEffect3"), XS_Mob_GetNimbusEffect3, file, "$"); - newXSproto(strcpy(buf, "GetOwnerID"), XS_Mob_GetOwnerID, file, "$"); - newXSproto(strcpy(buf, "GetPR"), XS_Mob_GetPR, file, "$"); - newXSproto(strcpy(buf, "GetPetID"), XS_Mob_GetPetID, file, "$"); - newXSproto(strcpy(buf, "GetPetOrder"), XS_Mob_GetPetOrder, file, "$"); - newXSproto(strcpy(buf, "GetPetType"), XS_Mob_GetPetType, file, "$"); - newXSproto(strcpy(buf, "GetPhR"), XS_Mob_GetPhR, file, "$"); - newXSproto(strcpy(buf, "GetRace"), XS_Mob_GetRace, file, "$"); - newXSproto(strcpy(buf, "GetRaceName"), XS_Mob_GetRaceName, file, "$"); - newXSproto(strcpy(buf, "GetResist"), XS_Mob_GetResist, file, "$$"); - newXSproto(strcpy(buf, "GetReverseFactionCon"), XS_Mob_GetReverseFactionCon, file, "$$"); - newXSproto(strcpy(buf, "GetRunAnimSpeed"), XS_Mob_GetRunAnimSpeed, file, "$"); - newXSproto(strcpy(buf, "GetRunspeed"), XS_Mob_GetRunspeed, file, "$"); - newXSproto(strcpy(buf, "GetSTA"), XS_Mob_GetSTA, file, "$"); - newXSproto(strcpy(buf, "GetSTR"), XS_Mob_GetSTR, file, "$"); - newXSproto(strcpy(buf, "GetSize"), XS_Mob_GetSize, file, "$"); - newXSproto(strcpy(buf, "GetSkill"), XS_Mob_GetSkill, file, "$$"); - newXSproto(strcpy(buf, "GetSkillDmgTaken"), XS_Mob_GetSkillDmgTaken, file, "$$"); - newXSproto(strcpy(buf, "GetSpecialAbility"), XS_Mob_GetSpecialAbility, file, "$$"); - newXSproto(strcpy(buf, "GetSpecialAbilityParam"), XS_Mob_GetSpecialAbilityParam, file, "$$$"); - newXSproto(strcpy(buf, "GetSpecializeSkillValue"), XS_Mob_GetSpecializeSkillValue, file, "$$"); - newXSproto(strcpy(buf, "GetSpellHPBonuses"), XS_Mob_GetSpellHPBonuses, file, "$"); - newXSproto(strcpy(buf, "GetSpellIDFromSlot"), XS_Mob_GetSpellIDFromSlot, file, "$$"); - newXSproto(strcpy(buf, "GetSpellStat"), XS_Mob_GetSpellStat, file, "$$$$"); - newXSproto(strcpy(buf, "GetTarget"), XS_Mob_GetTarget, file, "$"); - newXSproto(strcpy(buf, "GetTexture"), XS_Mob_GetTexture, file, "$"); - newXSproto(strcpy(buf, "GetWIS"), XS_Mob_GetWIS, file, "$"); - newXSproto(strcpy(buf, "GetWalkspeed"), XS_Mob_GetWalkspeed, file, "$"); - newXSproto(strcpy(buf, "GetWaypointH"), XS_Mob_GetWaypointH, file, "$"); - newXSproto(strcpy(buf, "GetWaypointID"), XS_Mob_GetWaypointID, file, "$"); - newXSproto(strcpy(buf, "GetWaypointPause"), XS_Mob_GetWaypointPause, file, "$"); - newXSproto(strcpy(buf, "GetWaypointX"), XS_Mob_GetWaypointX, file, "$"); - newXSproto(strcpy(buf, "GetWaypointY"), XS_Mob_GetWaypointY, file, "$"); - newXSproto(strcpy(buf, "GetWaypointZ"), XS_Mob_GetWaypointZ, file, "$"); - newXSproto(strcpy(buf, "GetX"), XS_Mob_GetX, file, "$"); - newXSproto(strcpy(buf, "GetY"), XS_Mob_GetY, file, "$"); - newXSproto(strcpy(buf, "GetZ"), XS_Mob_GetZ, file, "$"); - newXSproto(strcpy(buf, "GetZoneID"), XS_Mob_GetZoneID, file, "$"); - newXSproto(strcpy(buf, "GoToBind"), XS_Mob_GoToBind, file, "$"); - newXSproto(strcpy(buf, "HalveAggro"), XS_Mob_HalveAggro, file, "$$"); - newXSproto(strcpy(buf, "HasNPCSpecialAtk"), XS_Mob_HasNPCSpecialAtk, file, "$$"); - newXSproto(strcpy(buf, "HasOwner"), XS_Mob_HasOwner, file, "$"); - newXSproto(strcpy(buf, "HasPet"), XS_Mob_HasPet, file, "$"); - newXSproto(strcpy(buf, "HasProcs"), XS_Mob_HasProcs, file, "$"); - newXSproto(strcpy(buf, "HasShieldEquiped"), XS_Mob_HasShieldEquiped, file, "$"); - newXSproto(strcpy(buf, "HasTwoHandBluntEquiped"), XS_Mob_HasTwoHandBluntEquiped, file, "$"); - newXSproto(strcpy(buf, "HasTwoHanderEquipped"), XS_Mob_HasTwoHanderEquipped, file, "$"); - newXSproto(strcpy(buf, "HateSummon"), XS_Mob_HateSummon, file, "$"); - newXSproto(strcpy(buf, "Heal"), XS_Mob_Heal, file, "$"); - newXSproto(strcpy(buf, "HealDamage"), XS_Mob_HealDamage, file, "$$;$"); - newXSproto(strcpy(buf, "InterruptSpell"), XS_Mob_InterruptSpell, file, "$;$"); - newXSproto(strcpy(buf, "IsAIControlled"), XS_Mob_IsAIControlled, file, "$"); - newXSproto(strcpy(buf, "IsAmnesiad"), XS_Mob_IsAmnesiad, file, "$"); - newXSproto(strcpy(buf, "IsBeacon"), XS_Mob_IsBeacon, file, "$"); - newXSproto(strcpy(buf, "IsBeneficialAllowed"), XS_Mob_IsBeneficialAllowed, file, "$$"); - newXSproto(strcpy(buf, "IsBlind"), XS_Mob_IsBlind, file, "$"); - newXSproto(strcpy(buf, "IsBot"), XS_Mob_IsBot, file, "$"); - newXSproto(strcpy(buf, "IsCasting"), XS_Mob_IsCasting, file, "$"); - newXSproto(strcpy(buf, "IsClient"), XS_Mob_IsClient, file, "$"); - newXSproto(strcpy(buf, "IsCorpse"), XS_Mob_IsCorpse, file, "$"); - newXSproto(strcpy(buf, "IsDoor"), XS_Mob_IsDoor, file, "$"); - newXSproto(strcpy(buf, "IsEliteMaterialItem"), XS_Mob_IsEliteMaterialItem, file, "$$"); - newXSproto(strcpy(buf, "IsEngaged"), XS_Mob_IsEngaged, file, "$"); - newXSproto(strcpy(buf, "IsEnraged"), XS_Mob_IsEnraged, file, "$"); - newXSproto(strcpy(buf, "IsFeared"), XS_Mob_IsFeared, file, "$"); - newXSproto(strcpy(buf, "IsHorse"), XS_Mob_IsHorse, file, "$"); - newXSproto(strcpy(buf, "IsImmuneToSpell"), XS_Mob_IsImmuneToSpell, file, "$$$"); - newXSproto(strcpy(buf, "IsInvisible"), XS_Mob_IsInvisible, file, "$;$"); - newXSproto(strcpy(buf, "IsMeleeDisabled"), XS_Mob_IsMeleeDisabled, file, "$"); - newXSproto(strcpy(buf, "IsMezzed"), XS_Mob_IsMezzed, file, "$"); - newXSproto(strcpy(buf, "IsMob"), XS_Mob_IsMob, file, "$"); - newXSproto(strcpy(buf, "IsMoving"), XS_Mob_IsMoving, file, "$"); - newXSproto(strcpy(buf, "IsNPC"), XS_Mob_IsNPC, file, "$"); - newXSproto(strcpy(buf, "IsNPCCorpse"), XS_Mob_IsNPCCorpse, file, "$"); - newXSproto(strcpy(buf, "IsObject"), XS_Mob_IsObject, file, "$"); - newXSproto(strcpy(buf, "IsPet"), XS_Mob_IsPet, file, "$"); - newXSproto(strcpy(buf, "IsPlayerCorpse"), XS_Mob_IsPlayerCorpse, file, "$"); - newXSproto(strcpy(buf, "IsRoamer"), XS_Mob_IsRoamer, file, "$"); - newXSproto(strcpy(buf, "IsRooted"), XS_Mob_IsRooted, file, "$"); - newXSproto(strcpy(buf, "IsRunning"), XS_Mob_IsRunning, file, "$"); - newXSproto(strcpy(buf, "IsSilenced"), XS_Mob_IsSilenced, file, "$"); - newXSproto(strcpy(buf, "IsStunned"), XS_Mob_IsStunned, file, "$"); - newXSproto(strcpy(buf, "IsTargetable"), XS_Mob_IsTargetable, file, "$"); - newXSproto(strcpy(buf, "IsTargeted"), XS_Mob_IsTargeted, file, "$"); - newXSproto(strcpy(buf, "IsTrap"), XS_Mob_IsTrap, file, "$"); - newXSproto(strcpy(buf, "IsWarriorClass"), XS_Mob_IsWarriorClass, file, "$"); - newXSproto(strcpy(buf, "Kill"), XS_Mob_Kill, file, "$"); - newXSproto(strcpy(buf, "MakePet"), XS_Mob_MakePet, file, "$$$;$"); - newXSproto(strcpy(buf, "MakeTempPet"), XS_Mob_MakeTempPet, file, "$$;$$$$"); - newXSproto(strcpy(buf, "Mesmerize"), XS_Mob_Mesmerize, file, "$"); - newXSproto(strcpy(buf, "Message"), XS_Mob_Message, file, "$$$;@"); - newXSproto(strcpy(buf, "Message_StringID"), XS_Mob_Message_StringID, file, "$$$;$"); - newXSproto(strcpy(buf, "ModSkillDmgTaken"), XS_Mob_ModSkillDmgTaken, file, "$$$"); - newXSproto(strcpy(buf, "ModVulnerability"), XS_Mob_ModVulnerability, file, "$$$"); - newXSproto(strcpy(buf, "NPCSpecialAttacks"), XS_Mob_NPCSpecialAttacks, file, "$$$;$$"); - newXSproto(strcpy(buf, "NavigateTo"), XS_Mob_NavigateTo, file, "$$$$"); - newXSproto(strcpy(buf, "ProcessSpecialAbilities"), XS_Mob_ProcessSpecialAbilities, file, "$$"); - newXSproto(strcpy(buf, "ProjectileAnim"), XS_Mob_ProjectileAnim, file, "$$$;$$$$$$"); - newXSproto(strcpy(buf, "RandomizeFeatures"), XS_Mob_RandomizeFeatures, file, "$$;$"); - newXSproto(strcpy(buf, "RangedAttack"), XS_Mob_RangedAttack, file, "$$"); - newXSproto(strcpy(buf, "RemoveAllAppearanceEffects"), XS_Mob_RemoveAllAppearanceEffects, file, "$"); - newXSproto(strcpy(buf, "RemoveAllNimbusEffects"), XS_Mob_RemoveAllNimbusEffects, file, "$"); - newXSproto(strcpy(buf, "RemoveFromFeignMemory"), XS_Mob_RemoveFromFeignMemory, file, "$$"); - newXSproto(strcpy(buf, "RemoveNimbusEffect"), XS_Mob_RemoveNimbusEffect, file, "$$"); - newXSproto(strcpy(buf, "RemovePet"), XS_Mob_RemovePet, file, "$"); - newXSproto(strcpy(buf, "ResistSpell"), XS_Mob_ResistSpell, file, "$$$$"); - newXSproto(strcpy(buf, "RogueAssassinate"), XS_Mob_RogueAssassinate, file, "$$"); - newXSproto(strcpy(buf, "RunTo"), XS_Mob_RunTo, file, "$$$$"); - newXSproto(strcpy(buf, "Say"), XS_Mob_Say, file, "$$;@"); - newXSproto(strcpy(buf, "SeeHide"), XS_Mob_SeeHide, file, "$"); - newXSproto(strcpy(buf, "SeeImprovedHide"), XS_Mob_SeeImprovedHide, file, "$"); - newXSproto(strcpy(buf, "SeeInvisible"), XS_Mob_SeeInvisible, file, "$"); - newXSproto(strcpy(buf, "SeeInvisibleUndead"), XS_Mob_SeeInvisibleUndead, file, "$"); - newXSproto(strcpy(buf, "SendAppearanceEffect"), XS_Mob_SendAppearanceEffect, file, "$$;$$$$$$$$$$$$$$"); - newXSproto(strcpy(buf, "SendAppearanceEffectActor"), XS_Mob_SendAppearanceEffectActor, file, "$$$;$$$$$$$$$"); - newXSproto(strcpy(buf, "SendAppearanceEffectGround"), XS_Mob_SendAppearanceEffectGround, file, "$$$;$$$$$$$$$"); - newXSproto(strcpy(buf, "SendIllusion"), XS_Mob_SendIllusion, file, "$$;$$$$$$$$$$$$"); - newXSproto(strcpy(buf, "SendTo"), XS_Mob_SendTo, file, "$$$$"); - newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$"); - newXSproto(strcpy(buf, "SendWearChange"), XS_Mob_SendWearChange, file, "$$"); - newXSproto(strcpy(buf, "SetAA"), XS_Mob_SetAA, file, "$$$;$"); - newXSproto(strcpy(buf, "SetAllowBeneficial"), XS_Mob_SetAllowBeneficial, file, "$$"); - newXSproto(strcpy(buf, "SetAppearance"), XS_Mob_SetAppearance, file, "$$;$"); - newXSproto(strcpy(buf, "SetBodyType"), XS_Mob_SetBodyType, file, "$$;$"); - newXSproto(strcpy(buf, "SetBucket"), XS_Mob_SetBucket, file, "$$$;$"); - newXSproto(strcpy(buf, "SetBuffDuration"), XS_Mob_SetBuffDuration, file, "$$;$"); - newXSproto(strcpy(buf, "SetCurrentWP"), XS_Mob_SetCurrentWP, file, "$$"); - newXSproto(strcpy(buf, "SetDeltas"), XS_Mob_SetDeltas, file, "$$$$$"); - newXSproto(strcpy(buf, "SetDisableMelee"), XS_Mob_SetDisableMelee, file, "$$"); - newXSproto(strcpy(buf, "SetEntityVariable"), XS_Mob_SetEntityVariable, file, "$$$"); - newXSproto(strcpy(buf, "SetExtraHaste"), XS_Mob_SetExtraHaste, file, "$$"); - newXSproto(strcpy(buf, "SetFlurryChance"), XS_Mob_SetFlurryChance, file, "$$"); - newXSproto(strcpy(buf, "SetFlyMode"), XS_Mob_SetFlyMode, file, "$$"); - newXSproto(strcpy(buf, "SetFollowID"), XS_Mob_SetFollowID, file, "$$"); - newXSproto(strcpy(buf, "SetGender"), XS_Mob_SetGender, file, "$$"); - newXSproto(strcpy(buf, "SetGlobal"), XS_Mob_SetGlobal, file, "$$$$$;$"); - newXSproto(strcpy(buf, "SetHP"), XS_Mob_SetHP, file, "$$"); - newXSproto(strcpy(buf, "SetHate"), XS_Mob_SetHate, file, "$$;$$"); - newXSproto(strcpy(buf, "SetHeading"), XS_Mob_SetHeading, file, "$$"); - newXSproto(strcpy(buf, "SetInvisible"), XS_Mob_SetInvisible, file, "$$"); - newXSproto(strcpy(buf, "SetInvul"), XS_Mob_SetInvul, file, "$$"); - newXSproto(strcpy(buf, "SetLD"), XS_Mob_SetLD, file, "$$"); - newXSproto(strcpy(buf, "SetLevel"), XS_Mob_SetLevel, file, "$$;$"); - newXSproto(strcpy(buf, "SetMana"), XS_Mob_SetMana, file, "$$"); - newXSproto(strcpy(buf, "SetMaxHP"), XS_Mob_SetMaxHP, file, "$"); - newXSproto(strcpy(buf, "SetOOCRegen"), XS_Mob_SetOOCRegen, file, "$$"); - newXSproto(strcpy(buf, "SetOwnerID"), XS_Mob_SetOwnerID, file, "$$"); - newXSproto(strcpy(buf, "SetPet"), XS_Mob_SetPet, file, "$$"); - newXSproto(strcpy(buf, "SetPetID"), XS_Mob_SetPetID, file, "$$"); - newXSproto(strcpy(buf, "SetPetOrder"), XS_Mob_SetPetOrder, file, "$$"); - newXSproto(strcpy(buf, "SetRace"), XS_Mob_SetRace, file, "$$"); - newXSproto(strcpy(buf, "SetRunAnimSpeed"), XS_Mob_SetRunAnimSpeed, file, "$$"); - newXSproto(strcpy(buf, "SetRunning"), XS_Mob_SetRunning, file, "$$"); - newXSproto(strcpy(buf, "SetSeeInvisibleLevel"), XS_Mob_SetSeeInvisibleLevel, file, "$$"); - newXSproto(strcpy(buf, "SetSeeInvisibleUndeadLevel"), XS_Mob_SetSeeInvisibleUndeadLevel, file, "$$"); - newXSproto(strcpy(buf, "SetSlotTint"), XS_Mob_SetSlotTint, file, "$$$$$"); - newXSproto(strcpy(buf, "SetSpecialAbility"), XS_Mob_SetSpecialAbility, file, "$$$"); - newXSproto(strcpy(buf, "SetSpecialAbilityParam"), XS_Mob_SetSpecialAbilityParam, file, "$$$$"); - newXSproto(strcpy(buf, "SetTarget"), XS_Mob_SetTarget, file, "$$"); - newXSproto(strcpy(buf, "SetTargetable"), XS_Mob_SetTargetable, file, "$$"); - newXSproto(strcpy(buf, "SetTexture"), XS_Mob_SetTexture, file, "$$"); - newXSproto(strcpy(buf, "ShieldAbility"), XS_Mob_ShieldAbility, file, "$$$$$$$$"); - newXSproto(strcpy(buf, "Shout"), XS_Mob_Shout, file, "$$;@"); - newXSproto(strcpy(buf, "SignalClient"), XS_Mob_SignalClient, file, "$$$"); - newXSproto(strcpy(buf, "SpellEffect"), XS_Mob_SpellEffect, file, "$$;$$$$$$$$"); - newXSproto(strcpy(buf, "SpellFinished"), XS_Mob_SpellFinished, file, "$$;$$"); - newXSproto(strcpy(buf, "Spin"), XS_Mob_Spin, file, "$"); - newXSproto(strcpy(buf, "StartEnrage"), XS_Mob_StartEnrage, file, "$"); - newXSproto(strcpy(buf, "StopNavigation"), XS_Mob_StopNavigation, file, "$"); - newXSproto(strcpy(buf, "Stun"), XS_Mob_Stun, file, "$$"); - newXSproto(strcpy(buf, "TarGlobal"), XS_Mob_TarGlobal, file, "$$$$$$$"); - newXSproto(strcpy(buf, "TempName"), XS_Mob_TempName, file, "$:$"); - newXSproto(strcpy(buf, "ThrowingAttack"), XS_Mob_ThrowingAttack, file, "$$"); - newXSproto(strcpy(buf, "TryMoveAlong"), XS_Mob_TryMoveAlong, file, "$$$;$"); - newXSproto(strcpy(buf, "TypesTempPet"), XS_Mob_TypesTempPet, file, "$$;$$$$$"); - newXSproto(strcpy(buf, "WalkTo"), XS_Mob_WalkTo, file, "$$$$"); - newXSproto(strcpy(buf, "WearChange"), XS_Mob_WearChange, file, "$$$;$$"); - newXSproto(strcpy(buf, "WipeHateList"), XS_Mob_WipeHateList, file, "$"); - XSRETURN_YES; +bool Perl_Mob_IsPlayerCorpse(Mob* self) // @categories Corpse +{ + return self->IsPlayerCorpse(); +} + +bool Perl_Mob_IsNPCCorpse(Mob* self) // @categories Corpse +{ + return self->IsNPCCorpse(); +} + +bool Perl_Mob_IsObject(Mob* self) // @categories Objects +{ + return self->IsObject(); +} + +bool Perl_Mob_IsDoor(Mob* self) // @categories Script Utility, Doors +{ + return self->IsDoor(); +} + +bool Perl_Mob_IsTrap(Mob* self) // @categories Script Utility +{ + return self->IsTrap(); +} + +bool Perl_Mob_IsBeacon(Mob* self) // @categories Script Utility +{ + return self->IsBeacon(); +} + +Client* Perl_Mob_CastToClient(Mob* self) // @categories Account and Character, Script Utility +{ + return self->CastToClient(); +} + +NPC* Perl_Mob_CastToNPC(Mob* self) // @categories Script Utility +{ + return self->CastToNPC(); +} + +Mob* Perl_Mob_CastToMob(Mob* self) // @categories Script Utility +{ + return self->CastToMob(); +} + +Corpse* Perl_Mob_CastToCorpse(Mob* self) // @categories Script Utility, Corpse +{ + return self->CastToCorpse(); +} + +int Perl_Mob_GetID(Mob* self) // @categories Script Utility +{ + return self->GetID(); +} + +std::string Perl_Mob_GetName(Mob* self)// @categories Script Utility +{ + return self->GetName(); +} + +void Perl_Mob_Depop(Mob* self) // @categories Spawns +{ + self->Depop(); +} + +void Perl_Mob_Depop(Mob* self, bool start_spawn_timer) // @categories Spawns +{ + self->Depop(start_spawn_timer); +} + +void Perl_Mob_RogueAssassinate(Mob* self, Mob* other) // @categories Script Utility +{ + return self->RogueAssassinate(other); +} + +bool Perl_Mob_BehindMob(Mob* self, Mob* other) // @categories Script Utility +{ + return self->BehindMob(other); +} + +bool Perl_Mob_BehindMob(Mob* self, Mob* other, float x) // @categories Script Utility +{ + return self->BehindMob(other, x); +} + +bool Perl_Mob_BehindMob(Mob* self, Mob* other, float x, float y) // @categories Script Utility +{ + return self->BehindMob(other, x, y); +} + +void Perl_Mob_SetLevel(Mob* self, uint8_t in_level) // @categories Stats and Attributes +{ + self->SetLevel(in_level); +} + +void Perl_Mob_SetLevel(Mob* self, uint8_t in_level, bool command) // @categories Stats and Attributes +{ + self->SetLevel(in_level, command); +} + +uint32_t Perl_Mob_GetSkill(Mob* self, int skill_id) // @categories Skills and Recipes, Script Utility +{ + return self->GetSkill(static_cast(skill_id)); +} + +void Perl_Mob_SendWearChange(Mob* self, uint8_t material_slot) // @categories Script Utility +{ + self->SendWearChange(material_slot); +} + +int32_t Perl_Mob_GetEquipment(Mob* self, uint8_t material_slot) // @categories Inventory and Items +{ + return self->GetEquippedItemFromTextureSlot(material_slot); +} + +int32_t Perl_Mob_GetEquipmentMaterial(Mob* self, uint8_t material_slot) // @categories Inventory and Items +{ + return self->GetEquipmentMaterial(material_slot); +} + +int32_t Perl_Mob_GetEquipmentColor(Mob* self, uint8_t material_slot) // @categories Inventory and Items +{ + return self->GetEquipmentColor(material_slot); +} + +int32_t Perl_Mob_GetArmorTint(Mob* self, uint8_t material_slot) // @categories Stats and Attributes +{ + return self->GetArmorTint(material_slot); +} + +bool Perl_Mob_IsMoving(Mob* self) // @categories Script Utility +{ + return self->IsMoving(); +} + +void Perl_Mob_GoToBind(Mob* self) // @categories Script Utility +{ + self->GoToBind(); +} + +void Perl_Mob_Gate(Mob* self) // @categories Spells and Disciplines +{ + self->Gate(); +} + +bool Perl_Mob_Attack(Mob* self, Mob* other) // @categories Script Utility, Hate and Aggro +{ + return self->Attack(other); +} + +bool Perl_Mob_Attack(Mob* self, Mob* other, int hand) // @categories Script Utility, Hate and Aggro +{ + return self->Attack(other, hand); +} + +bool Perl_Mob_Attack(Mob* self, Mob* other, int hand, bool from_riposte) // @categories Script Utility, Hate and Aggro +{ + return self->Attack(other, hand, from_riposte); +} + +void Perl_Mob_Damage(Mob* self, Mob* from, int64_t damage, uint16_t spell_id, int attack_skill) // @categories Script Utility +{ + self->Damage(from, damage, spell_id, static_cast(attack_skill)); +} + +void Perl_Mob_Damage(Mob* self, Mob* from, int64_t damage, uint16_t spell_id, int attack_skill, bool avoidable) // @categories Script Utility +{ + self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable); +} + +void Perl_Mob_Damage(Mob* self, Mob* from, int64_t damage, uint16_t spell_id, int attack_skill, bool avoidable, int8_t buffslot) // @categories Script Utility +{ + self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable, buffslot); +} + +void Perl_Mob_Damage(Mob* self, Mob* from, int64_t damage, uint16_t spell_id, int attack_skill, bool avoidable, int8_t buffslot, bool buff_tic) // @categories Script Utility +{ + self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable, buffslot, buff_tic); +} + +void Perl_Mob_RangedAttack(Mob* self, Mob* other) // @categories Skills and Recipes, Script Utility +{ + self->RangedAttack(other); +} + +void Perl_Mob_ThrowingAttack(Mob* self, Mob* other) // @categories Skills and Recipes, Script Utility +{ + self->ThrowingAttack(other); +} + +void Perl_Mob_Heal(Mob* self)// @categories Script Utility +{ + self->Heal(); +} + +void Perl_Mob_HealDamage(Mob* self, int64_t amount) // @categories Script Utility +{ + self->HealDamage(amount); +} + +void Perl_Mob_HealDamage(Mob* self, int64_t amount, Mob* caster) // @categories Script Utility +{ + self->HealDamage(amount, caster); +} + +void Perl_Mob_SetMaxHP(Mob* self) // @categories Stats and Attributes +{ + self->SetMaxHP(); +} + +uint32_t Perl_Mob_GetLevelCon(Mob* self, uint8_t other_level) // @categories Stats and Attributes +{ + return self->GetLevelCon(other_level); +} + +void Perl_Mob_SetHP(Mob* self, int64_t hp) // @categories Stats and Attributes +{ + self->SetHP(hp); +} + +void Perl_Mob_DoAnim(Mob* self, int animation_id) // @categories Script Utility +{ + self->DoAnim(animation_id); +} + +void Perl_Mob_DoAnim(Mob* self, int animation_id, int animation_speed) // @categories Script Utility +{ + self->DoAnim(animation_id, animation_speed); +} + +void Perl_Mob_DoAnim(Mob* self, int animation_id, int animation_speed, bool ackreq) // @categories Script Utility +{ + self->DoAnim(animation_id, animation_speed, ackreq); +} + +void Perl_Mob_DoAnim(Mob* self, int animation_id, int animation_speed, bool ackreq, int filter) // @categories Script Utility +{ + self->DoAnim(animation_id, animation_speed, ackreq, static_cast(filter)); +} + +void Perl_Mob_ChangeSize(Mob* self, float in_size) // @categories Script Utility +{ + self->ChangeSize(in_size); +} + +void Perl_Mob_ChangeSize(Mob* self, float in_size, bool no_restriction) // @categories Script Utility +{ + self->ChangeSize(in_size, no_restriction); +} + +void Perl_Mob_GMMove(Mob* self, float x, float y, float z) // @categories Script Utility +{ + self->GMMove(x, y, z); +} + +void Perl_Mob_GMMove(Mob* self, float x, float y, float z, float heading) // @categories Script Utility +{ + self->GMMove(x, y, z, heading); +} + +bool Perl_Mob_HasProcs(Mob* self) // @categories Stats and Attributes +{ + return self->HasProcs(); +} + +bool Perl_Mob_IsInvisible(Mob* self) // @categories Script Utility +{ + return self->IsInvisible(); +} + +bool Perl_Mob_IsInvisible(Mob* self, Mob* other) // @categories Script Utility +{ + return self->IsInvisible(other); +} + +void Perl_Mob_SetInvisible(Mob* self, uint8_t state) // @categories Script Utility +{ + self->SetInvisible(state); +} + +void Perl_Mob_SetSeeInvisibleLevel(Mob* self, uint8 see_invis_level) // @categories Script Utility +{ + self->SetInnateSeeInvisible(see_invis_level); + self->CalcSeeInvisibleLevel(); +} + +void Perl_Mob_SetSeeInvisibleUndeadLevel(Mob* self, uint8 see_invis_undead_level) // @categories Script Utility +{ + self->SetSeeInvisibleUndead(see_invis_undead_level); +} + +bool Perl_Mob_FindBuff(Mob* self, uint16 spell_id) // @categories Spells and Disciplines, Script Utility +{ + return self->FindBuff(spell_id); +} + +int Perl_Mob_FindBuffBySlot(Mob* self, int slot) // @categories Spells and Disciplines, Script Utility +{ + return self->FindBuffBySlot(slot); +} + +bool Perl_Mob_FindType(Mob* self, uint16_t type) // @categories Script Utility +{ + return self->FindType(type); +} + +bool Perl_Mob_FindType(Mob* self, uint16_t type, bool offensive) // @categories Script Utility +{ + return self->FindType(type, offensive); +} + +bool Perl_Mob_FindType(Mob* self, uint16_t type, bool offensive, uint16_t threshold) // @categories Script Utility +{ + return self->FindType(type, offensive, threshold); +} + +int Perl_Mob_GetBuffSlotFromType(Mob* self, uint16 type) // @categories Spells and Disciplines, Script Utility +{ + return self->GetBuffSlotFromType(type); +} + +void Perl_Mob_MakePet(Mob* self, uint16 spell_id, const char* pet_type) // @categories Pet +{ + self->MakePet(spell_id, pet_type); +} + +void Perl_Mob_MakePet(Mob* self, uint16 spell_id, const char* pet_type, const char* name) // @categories Pet +{ + self->MakePet(spell_id, pet_type, name); +} + +void Perl_Mob_MakeTempPet(Mob* self, uint16 spell_id) // @categories Pet +{ + self->TemporaryPets(spell_id, nullptr); +} + +void Perl_Mob_MakeTempPet(Mob* self, uint16 spell_id, const char* name) // @categories Pet +{ + self->TemporaryPets(spell_id, nullptr, name); +} + +void Perl_Mob_MakeTempPet(Mob* self, uint16 spell_id, const char* name, uint32 duration) // @categories Pet +{ + self->TemporaryPets(spell_id, nullptr, name, duration); +} + +void Perl_Mob_MakeTempPet(Mob* self, uint16 spell_id, const char* name, uint32 duration, Mob* target) // @categories Pet +{ + self->TemporaryPets(spell_id, target, name, duration); +} + +void Perl_Mob_MakeTempPet(Mob* self, uint16 spell_id, const char* name, uint32 duration, Mob* target, bool sticktarg) // @categories Pet +{ + self->TemporaryPets(spell_id, target, name, duration, true, sticktarg); +} + +void Perl_Mob_TypesTempPet(Mob* self, uint32 type_id) // @categories Pet +{ + self->TypesTemporaryPets(type_id, nullptr); +} + +void Perl_Mob_TypesTempPet(Mob* self, uint32 type_id, const char* name) // @categories Pet +{ + self->TypesTemporaryPets(type_id, nullptr, name); +} + +void Perl_Mob_TypesTempPet(Mob* self, uint32 type_id, const char* name, uint32 duration) // @categories Pet +{ + self->TypesTemporaryPets(type_id, nullptr, name, duration); +} + +void Perl_Mob_TypesTempPet(Mob* self, uint32 type_id, const char* name, uint32 duration, bool follow) // @categories Pet +{ + self->TypesTemporaryPets(type_id, nullptr, name, duration, follow); +} + +void Perl_Mob_TypesTempPet(Mob* self, uint32 type_id, const char* name, uint32 duration, bool follow, Mob* target) // @categories Pet +{ + self->TypesTemporaryPets(type_id, target, name, duration, follow); +} + +void Perl_Mob_TypesTempPet(Mob* self, uint32 type_id, const char* name, uint32 duration, bool follow, Mob* target, bool stick_targ) // @categories Pet +{ + self->TypesTemporaryPets(type_id, target, name, duration, follow, stick_targ); +} + +int Perl_Mob_GetBaseRace(Mob* self) // @categories Stats and Attributes +{ + return self->GetBaseRace(); +} + +int Perl_Mob_GetBaseGender(Mob* self) // @categories Stats and Attributes +{ + return self->GetBaseGender(); +} + +int Perl_Mob_GetDeity(Mob* self) // @categories Stats and Attributes +{ + return self->GetDeity(); +} + +int Perl_Mob_GetRace(Mob* self) // @categories Stats and Attributes +{ + return self->GetRace(); +} + +int Perl_Mob_GetGender(Mob* self) // @categories Stats and Attributes +{ + return self->GetGender(); +} + +int Perl_Mob_GetTexture(Mob* self) // @categories Stats and Attributes +{ + return self->GetTexture(); +} + +int Perl_Mob_GetHelmTexture(Mob* self) // @categories Stats and Attributes +{ + return self->GetHelmTexture(); +} + +int Perl_Mob_GetHairColor(Mob* self) // @categories Stats and Attributes +{ + return self->GetHairColor(); +} + +int Perl_Mob_GetBeardColor(Mob* self) // @categories Stats and Attributes +{ + return self->GetBeardColor(); +} + +int Perl_Mob_GetEyeColor1(Mob* self) // @categories Stats and Attributes +{ + return self->GetEyeColor1(); +} + +int Perl_Mob_GetEyeColor2(Mob* self) // @categories Stats and Attributes +{ + return self->GetEyeColor2(); +} + +int Perl_Mob_GetHairStyle(Mob* self) // @categories Stats and Attributes +{ + return self->GetHairStyle(); +} + +int Perl_Mob_GetLuclinFace(Mob* self) // @categories Stats and Attributes +{ + return self->GetLuclinFace(); +} + +int Perl_Mob_GetBeard(Mob* self) // @categories Stats and Attributes +{ + return self->GetBeard(); +} + +int Perl_Mob_GetDrakkinHeritage(Mob* self) // @categories Stats and Attributes +{ + return self->GetDrakkinHeritage(); +} + +int Perl_Mob_GetDrakkinTattoo(Mob* self) // @categories Stats and Attributes +{ + return self->GetDrakkinTattoo(); +} + +int Perl_Mob_GetDrakkinDetails(Mob* self) // @categories Stats and Attributes +{ + return self->GetDrakkinDetails(); +} + +int Perl_Mob_GetClass(Mob* self) // @categories Stats and Attributes +{ + return self->GetClass(); +} + +int Perl_Mob_GetLevel(Mob* self) // @categories Stats and Attributes +{ + return self->GetLevel(); +} + +std::string Perl_Mob_GetCleanName(Mob* self) // @categories Script Utility +{ + return self->GetCleanName(); +} + +Mob* Perl_Mob_GetTarget(Mob* self) // @categories Script Utility +{ + return self->GetTarget(); +} + +void Perl_Mob_SetTarget(Mob* self, Mob* target) // @categories Script Utility +{ + self->SetTarget(target); +} + +float Perl_Mob_GetHPRatio(Mob* self) // @categories Stats and Attributes +{ + return self->GetHPRatio(); +} + +bool Perl_Mob_IsWarriorClass(Mob* self) // @categories Script Utility +{ + return self->IsWarriorClass(); +} + +int64_t Perl_Mob_GetHP(Mob* self) // @categories Stats and Attributes +{ + return self->GetHP(); +} + +int64_t Perl_Mob_GetMaxHP(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxHP(); +} + +int64_t Perl_Mob_GetItemHPBonuses(Mob* self) // @categories Inventory and Items, Stats and Attributes +{ + return self->GetItemHPBonuses(); +} + +int64_t Perl_Mob_GetSpellHPBonuses(Mob* self) // @categories Spells and Disciplines +{ + return self->GetSpellHPBonuses(); +} + +int Perl_Mob_GetSpellIDFromSlot(Mob* self, uint8_t slot) // @categories Spells and Disciplines +{ + return slot <= self->GetMaxBuffSlots() ? self->GetSpellIDFromSlot(slot) : -1; +} + +int Perl_Mob_GetWalkspeed(Mob* self) // @categories Stats and Attributes +{ + return self->GetWalkspeed(); +} + +int Perl_Mob_GetRunspeed(Mob* self) // @categories Stats and Attributes +{ + return self->GetRunspeed(); +} + +int Perl_Mob_GetCasterLevel(Mob* self, uint16_t spell_id) // @categories Stats and Attributes +{ + return self->GetCasterLevel(spell_id); +} + +int64_t Perl_Mob_GetMaxMana(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxMana(); +} + +int64_t Perl_Mob_GetMana(Mob* self) // @categories Stats and Attributes +{ + return self->GetMana(); +} + +int64_t Perl_Mob_SetMana(Mob* self, int64_t amount) // @categories Stats and Attributes +{ + return self->SetMana(amount); +} + +float Perl_Mob_GetManaRatio(Mob* self) // @categories Stats and Attributes +{ + return self->GetManaRatio(); +} + +int Perl_Mob_GetAC(Mob* self) // @categories Stats and Attributes +{ + return self->GetAC(); +} + +int Perl_Mob_GetDisplayAC(Mob* self) +{ + return self->GetDisplayAC(); +} + +int Perl_Mob_GetATK(Mob* self) // @categories Stats and Attributes +{ + return self->GetATK(); +} + +int Perl_Mob_GetSTR(Mob* self) // @categories Stats and Attributes +{ + return self->GetSTR(); +} + +int Perl_Mob_GetSTA(Mob* self) // @categories Stats and Attributes +{ + return self->GetSTA(); +} + +int Perl_Mob_GetDEX(Mob* self) // @categories Stats and Attributes +{ + return self->GetDEX(); +} + +int Perl_Mob_GetAGI(Mob* self) // @categories Stats and Attributes +{ + return self->GetAGI(); +} + +int Perl_Mob_GetINT(Mob* self) // @categories Stats and Attributes +{ + return self->GetINT(); +} + +int Perl_Mob_GetWIS(Mob* self) // @categories Stats and Attributes +{ + return self->GetWIS(); +} + +int Perl_Mob_GetCHA(Mob* self) // @categories Stats and Attributes +{ + return self->GetCHA(); +} + +int Perl_Mob_GetMR(Mob* self) // @categories Stats and Attributes +{ + return self->GetMR(); +} + +int Perl_Mob_GetFR(Mob* self) // @categories Stats and Attributes +{ + return self->GetFR(); +} + +int Perl_Mob_GetDR(Mob* self) // @categories Stats and Attributes +{ + return self->GetDR(); +} + +int Perl_Mob_GetPR(Mob* self) // @categories Stats and Attributes +{ + return self->GetPR(); +} + +int Perl_Mob_GetCR(Mob* self) // @categories Stats and Attributes +{ + return self->GetCR(); +} + +int Perl_Mob_GetCorruption(Mob* self) // @categories Stats and Attributes +{ + return self->GetCorrup(); +} + +int Perl_Mob_GetPhR(Mob* self) // @categories Stats and Attributes +{ + return self->GetPhR(); +} + +int Perl_Mob_GetMaxSTR(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxSTR(); +} + +int Perl_Mob_GetMaxSTA(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxSTA(); +} + +int Perl_Mob_GetMaxDEX(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxDEX(); +} + +int Perl_Mob_GetMaxAGI(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxAGI(); +} + +int Perl_Mob_GetMaxINT(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxINT(); +} + +int Perl_Mob_GetMaxWIS(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxWIS(); +} + +int Perl_Mob_GetMaxCHA(Mob* self) // @categories Stats and Attributes +{ + return self->GetMaxCHA(); +} + +float Perl_Mob_GetActSpellRange(Mob* self, uint16 spell_id, float range) // @categories Spells and Disciplines +{ + return self->GetActSpellRange(spell_id, range); +} + +int64_t Perl_Mob_GetActSpellDamage(Mob* self, uint16 spell_id, int64 value) // @categories Spells and Disciplines +{ + return self->GetActSpellDamage(spell_id, value); +} + +int64_t Perl_Mob_GetActSpellHealing(Mob* self, uint16 spell_id, int64 value) // @categories Spells and Disciplines +{ + return self->GetActSpellHealing(spell_id, value); +} + +int Perl_Mob_GetActSpellCost(Mob* self, uint16 spell_id, int32 cost) // @categories Spells and Disciplines +{ + return self->GetActSpellCost(spell_id, cost); +} + +int Perl_Mob_GetActSpellDuration(Mob* self, uint16 spell_id, int32 duration) // @categories Spells and Disciplines +{ + return self->GetActSpellDuration(spell_id, duration); +} + +int Perl_Mob_GetActSpellCasttime(Mob* self, uint16 spell_id, uint32 cast_time) // @categories Spells and Disciplines +{ + return self->GetActSpellCasttime(spell_id, cast_time); +} + +float Perl_Mob_ResistSpell(Mob* self, uint8 resist_type, uint16 spell_id, Mob* caster) // @categories Spells and Disciplines, Script Utility +{ + return self->ResistSpell(resist_type, spell_id, caster); +} + +int Perl_Mob_GetSpecializeSkillValue(Mob* self, uint16 spell_id) // @categories Skills and Recipes, Spells and Disciplines +{ + return self->GetSpecializeSkillValue(spell_id); +} + +uint32_t Perl_Mob_GetNPCTypeID(Mob* self) // @categories Script Utility +{ + return self->GetNPCTypeID(); +} + +bool Perl_Mob_IsTargeted(Mob* self) // @categories Script Utility +{ + return self->IsTargeted(); +} + +float Perl_Mob_GetX(Mob* self) // @categories Script Utility +{ + return self->GetX(); +} + +float Perl_Mob_GetY(Mob* self) // @categories Script Utility +{ + return self->GetY(); +} + +float Perl_Mob_GetZ(Mob* self) // @categories Script Utility +{ + return self->GetZ(); +} + +float Perl_Mob_GetHeading(Mob* self) // @categories Script Utility +{ + return self->GetHeading(); +} + +float Perl_Mob_GetWaypointX(Mob* self) // @categories Script Utility +{ + return self->GetCurrentWayPoint().x; +} + +float Perl_Mob_GetWaypointY(Mob* self) // @categories Script Utility +{ + return self->GetCurrentWayPoint().y; +} + +float Perl_Mob_GetWaypointZ(Mob* self) // @categories Script Utility +{ + return self->GetCurrentWayPoint().z; +} + +float Perl_Mob_GetWaypointH(Mob* self) // @categories Script Utility +{ + return self->GetCurrentWayPoint().w; +} + +float Perl_Mob_GetWaypointPause(Mob* self) // @categories Script Utility +{ + return self->GetCWPP(); +} + +int Perl_Mob_GetWaypointID(Mob* self) // @categories Script Utility +{ + return self->GetCWP(); +} + +void Perl_Mob_SetCurrentWP(Mob* self, int waypoint) // @categories Script Utility +{ + self->SetCurrentWP(waypoint); +} + +float Perl_Mob_GetSize(Mob* self) // @categories Stats and Attributes +{ + return self->GetSize(); +} + +void Perl_Mob_SetFollowID(Mob* self, uint32_t id) // @categories Script Utility +{ + self->SetFollowID(id); +} + +uint32_t Perl_Mob_GetFollowID(Mob* self) // @categories Script Utility +{ + return self->GetFollowID(); +} + +void Perl_Mob_Message(Mob* self, uint32 type, const char* message) // @categories Script Utility +{ + if (RuleB(Chat, QuestDialogueUsesDialogueWindow) && self->IsClient()) { + DialogueWindow::Render(self->CastToClient(), message); + } + else if (RuleB(Chat, AutoInjectSaylinksToClientMessage)) { + std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(message); + self->Message(type, new_message.c_str()); + } + else { + self->Message(type, message); + } +} + +void Perl_Mob_Message_StringID(Mob* self, uint32 type, uint32 string_id) // @categories Script Utility +{ + self->MessageString(type, string_id); +} + +void Perl_Mob_Message_StringID(Mob* self, uint32 type, uint32 string_id, uint32 distance) // @categories Script Utility +{ + self->MessageString(type, string_id, distance); +} + +void Perl_Mob_Say(Mob* self, const char* message) // @categories Script Utility +{ + self->Say(message); +} + +void Perl_Mob_Shout(Mob* self, const char* message) // @categories Script Utility +{ + self->Shout(message); +} + +void Perl_Mob_Emote(Mob* self, const char* message) // @categories Script Utility +{ + self->Emote(message); +} + +void Perl_Mob_InterruptSpell(Mob* self) // @categories Script Utility +{ + self->InterruptSpell(); +} + +void Perl_Mob_InterruptSpell(Mob* self, uint16 spell_id) // @categories Script Utility +{ + self->InterruptSpell(spell_id); +} + +void Perl_Mob_CastSpell(Mob* self, uint16 spell_id, uint16 target_id) // @categories Spells and Disciplines +{ + self->CastSpell(spell_id, target_id); +} + +void Perl_Mob_CastSpell(Mob* self, uint16 spell_id, uint16 target_id, int slot) // @categories Spells and Disciplines +{ + self->CastSpell(spell_id, target_id, static_cast(slot)); +} + +void Perl_Mob_CastSpell(Mob* self, uint16 spell_id, uint16 target_id, int slot, int cast_time) // @categories Spells and Disciplines +{ + self->CastSpell(spell_id, target_id, static_cast(slot), cast_time); +} + +void Perl_Mob_CastSpell(Mob* self, uint16 spell_id, uint16 target_id, int slot, int cast_time, int mana_cost) // @categories Spells and Disciplines +{ + self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost); +} + +// args differ from lua api (item_slot, timer, timer_duration not supported) +void Perl_Mob_CastSpell(Mob* self, uint16 spell_id, uint16 target_id, int slot, int cast_time, int mana_cost, int16 resist_adjust) // @categories Spells and Disciplines +{ + int16 res = resist_adjust; + self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, 0xFFFFFFFF, 0xFFFFFFFF, 0, &res); +} + +// these don't match lua api for default resist difficulty +void Perl_Mob_SpellFinished(Mob* self, uint16 spell_id) // @categories Spells and Disciplines +{ + self->SpellFinished(spell_id, self, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty); +} + +void Perl_Mob_SpellFinished(Mob* self, uint16 spell_id, Mob* target) // @categories Spells and Disciplines +{ + self->SpellFinished(spell_id, target, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty); +} + +void Perl_Mob_SpellFinished(Mob* self, uint16 spell_id, Mob* target, int32 mana_cost) // @categories Spells and Disciplines +{ + self->SpellFinished(spell_id, target, EQ::spells::CastingSlot::Item, mana_cost, -1, spells[spell_id].resist_difficulty); +} + +void Perl_Mob_SpellFinished(Mob* self, uint16 spell_id, Mob* target, int32 mana_cost, uint16 resist_diff) // @categories Spells and Disciplines +{ + self->SpellFinished(spell_id, target, EQ::spells::CastingSlot::Item, mana_cost, -1, resist_diff); +} + +bool Perl_Mob_IsImmuneToSpell(Mob* self, uint16 spell_id, Mob* caster) // @categories Spells and Disciplines, Script Utility +{ + return self->IsImmuneToSpell(spell_id, caster); +} + +void Perl_Mob_BuffFadeBySpellID(Mob* self, uint16 spell_id) // @categories Script Utility, Spells and Disciplines +{ + self->BuffFadeBySpellID(spell_id); +} + +void Perl_Mob_BuffFadeByEffect(Mob* self, int effect_id) // @categories Script Utility, Spells and Disciplines +{ + self->BuffFadeByEffect(effect_id); +} + +void Perl_Mob_BuffFadeByEffect(Mob* self, int effect_id, int skip_slot) // @categories Script Utility, Spells and Disciplines +{ + self->BuffFadeByEffect(effect_id, skip_slot); +} + +void Perl_Mob_BuffFadeAll(Mob* self) // @categories Script Utility, Spells and Disciplines +{ + self->BuffFadeAll(); +} + +void Perl_Mob_BuffFadeBySlot(Mob* self, int slot) // @categories Script Utility, Spells and Disciplines +{ + self->BuffFadeBySlot(slot); +} + +void Perl_Mob_BuffFadeBySlot(Mob* self, int slot, bool recalc_bonuses) // @categories Script Utility, Spells and Disciplines +{ + self->BuffFadeBySlot(slot, recalc_bonuses); +} + +bool Perl_Mob_CanBuffStack(Mob* self, uint16 spell_id, uint8 caster_level) // @categories Script Utility, Spells and Disciplines +{ + return self->CanBuffStack(spell_id, caster_level); +} + +bool Perl_Mob_CanBuffStack(Mob* self, uint16 spell_id, uint8 caster_level, bool fail_if_overwritten) // @categories Script Utility, Spells and Disciplines +{ + return self->CanBuffStack(spell_id, caster_level, fail_if_overwritten); +} + +bool Perl_Mob_IsCasting(Mob* self) // @categories Script Utility +{ + return self->IsCasting(); +} + +int Perl_Mob_CastingSpellID(Mob* self) // @categories Spells and Disciplines +{ + return self->CastingSpellID(); +} + +void Perl_Mob_SetAppearance(Mob* self, int app) // @categories Stats and Attributes +{ + self->SetAppearance(static_cast(app)); +} + +void Perl_Mob_SetAppearance(Mob* self, int app, bool ignore_self) // @categories Stats and Attributes +{ + self->SetAppearance(static_cast(app), ignore_self); +} + +int Perl_Mob_GetAppearance(Mob* self) // @categories Stats and Attributes +{ + return self->GetAppearance(); +} + +int Perl_Mob_GetRunAnimSpeed(Mob* self) // @categories Stats and Attributes +{ + return self->GetRunAnimSpeed(); +} + +void Perl_Mob_SetRunAnimSpeed(Mob* self, int8 speed) // @categories Stats and Attributes +{ + self->SetRunAnimSpeed(speed); +} + +void Perl_Mob_SetPetID(Mob* self, uint16 new_pet_id) // @categories Pet +{ + self->SetPetID(new_pet_id); +} + +int Perl_Mob_GetPetID(Mob* self) // @categories Script Utility, Pet +{ + return self->GetPetID(); +} + +void Perl_Mob_SetOwnerID(Mob* self, uint16 new_owner_id) // @categories Pet +{ + self->SetOwnerID(new_owner_id); +} + +uint16 Perl_Mob_GetOwnerID(Mob* self) // @categories Script Utility, Pet +{ + return self->GetOwnerID(); +} + +int Perl_Mob_GetPetType(Mob* self) // @categories Script Utility, Pet +{ + return self->GetPetType(); +} + +int Perl_Mob_GetBodyType(Mob* self) // @categories Stats and Attributes +{ + return self->GetBodyType(); +} + +void Perl_Mob_Stun(Mob* self, int duration) +{ + self->Stun(duration); +} + +void Perl_Mob_Spin(Mob* self) // @categories Script Utility +{ + self->Spin(); +} + +void Perl_Mob_Kill(Mob* self) // @categories Script Utility +{ + self->Kill(); +} + +void Perl_Mob_SetInvul(Mob* self, bool value) // @categories Script Utility +{ + self->SetInvul(value); +} + +bool Perl_Mob_GetInvul(Mob* self) // @categories Script Utility, Stats and Attributes +{ + return self->GetInvul(); +} + +void Perl_Mob_SetExtraHaste(Mob* self, int haste) // @categories Script Utility, Stats and Attributes +{ + self->SetExtraHaste(haste); +} + +int Perl_Mob_GetHaste(Mob* self) // @categories Stats and Attributes +{ + return self->GetHaste(); +} + +int Perl_Mob_GetHandToHandDamage(Mob* self) // @categories Stats and Attributes +{ + return self->GetHandToHandDamage(); +} + +bool Perl_Mob_CanThisClassDoubleAttack(Mob* self) // @categories Skills and Recipes +{ + return self->CanThisClassDoubleAttack(); +} + +bool Perl_Mob_CanThisClassDualWield(Mob* self) // @categories Skills and Recipes +{ + return self->CanThisClassDualWield(); +} + +bool Perl_Mob_CanThisClassRiposte(Mob* self) // @categories Skills and Recipes +{ + return self->CanThisClassRiposte(); +} + +bool Perl_Mob_CanThisClassDodge(Mob* self) // @categories Skills and Recipes +{ + return self->CanThisClassDodge(); +} + +bool Perl_Mob_CanThisClassParry(Mob* self) // @categories Skills and Recipes +{ + return self->CanThisClassParry(); +} + +int Perl_Mob_GetHandToHandDelay(Mob* self) // @categories Stats and Attributes +{ + return self->GetHandToHandDelay(); +} + +int Perl_Mob_GetClassLevelFactor(Mob* self) // @categories Stats and Attributes +{ + return self->GetClassLevelFactor(); +} + +void Perl_Mob_Mesmerize(Mob* self) // @categories Script Utility +{ + self->Mesmerize(); +} + +bool Perl_Mob_IsMezzed(Mob* self) // @categories Script Utility +{ + return self->IsMezzed(); +} + +bool Perl_Mob_IsStunned(Mob* self) // @categories Script Utility +{ + return self->IsStunned(); +} + +void Perl_Mob_StartEnrage(Mob* self) // @categories Script Utility +{ + self->StartEnrage(); +} + +bool Perl_Mob_IsEnraged(Mob* self) // @categories Script Utility +{ + return self->IsEnraged(); +} + +int Perl_Mob_GetReverseFactionCon(Mob* self, Mob* other) // @categories Faction +{ + return self->GetReverseFactionCon(other); +} + +bool Perl_Mob_IsAIControlled(Mob* self) // @categories Script Utility +{ + return self->IsAIControlled(); +} + +float Perl_Mob_GetAggroRange(Mob* self) // @categories Stats and Attributes, Hate and Aggro +{ + return self->GetAggroRange(); +} + +float Perl_Mob_GetAssistRange(Mob* self) // @categories Stats and Attributes, Hate and Aggro +{ + return self->GetAssistRange(); +} + +void Perl_Mob_SetPetOrder(Mob* self, int order) // @categories Pet +{ + self->SetPetOrder(static_cast(order)); +} + +int Perl_Mob_GetPetOrder(Mob* self) // @categories Script Utility, Pet +{ + return self->GetPetOrder(); +} + +bool Perl_Mob_IsRoamer(Mob* self) // @categories Script Utility, Spawns +{ + return self->IsRoamer(); +} + +bool Perl_Mob_IsRooted(Mob* self) // @categories Script Utility +{ + return self->IsRooted(); +} + +void Perl_Mob_AddToHateList(Mob* self, Mob* other) // @categories Hate and Aggro +{ + self->AddToHateList(other); +} + +void Perl_Mob_AddToHateList(Mob* self, Mob* other, int64_t hate) // @categories Hate and Aggro +{ + self->AddToHateList(other, hate); +} + +void Perl_Mob_AddToHateList(Mob* self, Mob* other, int64_t hate, int64_t damage) // @categories Hate and Aggro +{ + self->AddToHateList(other, hate, damage); +} + +void Perl_Mob_AddToHateList(Mob* self, Mob* other, int64_t hate, int64_t damage, bool yell_for_help) // @categories Hate and Aggro +{ + self->AddToHateList(other, hate, damage, yell_for_help); +} + +void Perl_Mob_AddToHateList(Mob* self, Mob* other, int64_t hate, int64_t damage, bool yell_for_help, bool frenzy) // @categories Hate and Aggro +{ + self->AddToHateList(other, hate, damage, yell_for_help, frenzy); +} + +void Perl_Mob_AddToHateList(Mob* self, Mob* other, int64_t hate, int64_t damage, bool yell_for_help, bool frenzy, bool buff_tic) // @categories Hate and Aggro +{ + self->AddToHateList(other, hate, damage, yell_for_help, frenzy, buff_tic); +} + +void Perl_Mob_SetHate(Mob* self, Mob* other) // @categories Hate and Aggro +{ + self->SetHateAmountOnEnt(other); +} + +void Perl_Mob_SetHate(Mob* self, Mob* other, int64_t hate) // @categories Hate and Aggro +{ + self->SetHateAmountOnEnt(other, hate); +} + +void Perl_Mob_SetHate(Mob* self, Mob* other, int64_t hate, int64_t damage) // @categories Hate and Aggro +{ + self->SetHateAmountOnEnt(other, hate, damage); +} + +void Perl_Mob_HalveAggro(Mob* self, Mob* other) // @categories Hate and Aggro +{ + self->HalveAggro(other); +} + +void Perl_Mob_DoubleAggro(Mob* self, Mob* other) // @categories Hate and Aggro +{ + self->DoubleAggro(other); +} + +int64_t Perl_Mob_GetHateAmount(Mob* self, Mob* target) // @categories Hate and Aggro +{ + return self->GetHateAmount(target); +} + +int64_t Perl_Mob_GetHateAmount(Mob* self, Mob* target, bool is_damage) // @categories Hate and Aggro +{ + return self->GetHateAmount(target, is_damage); +} + +int64_t Perl_Mob_GetDamageAmount(Mob* self, Mob* target) // @categories Stats and Attributes +{ + return self->GetDamageAmount(target); +} + +Mob* Perl_Mob_GetHateTop(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateTop(); +} + +Mob* Perl_Mob_GetHateDamageTop(Mob* self, Mob* other) // @categories Hate and Aggro +{ + return self->GetHateDamageTop(other); +} + +Mob* Perl_Mob_GetHateRandom(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateRandom(); +} + +bool Perl_Mob_IsEngaged(Mob* self) // @categories Script Utility +{ + return self->IsEngaged(); +} + +bool Perl_Mob_HateSummon(Mob* self) // @categories Hate and Aggro +{ + return self->HateSummon(); +} + +void Perl_Mob_FaceTarget(Mob* self) // @categories Script Utility +{ + self->FaceTarget(); +} + +void Perl_Mob_FaceTarget(Mob* self, Mob* target) // @categories Script Utility +{ + self->FaceTarget(target); +} + +void Perl_Mob_SetHeading(Mob* self, float heading) // @categories Script Utility +{ + self->SetHeading(heading); +} + +void Perl_Mob_WipeHateList(Mob* self) // @categories Hate and Aggro +{ + self->WipeHateList(); +} + +bool Perl_Mob_CheckAggro(Mob* self, Mob* other) // @categories Hate and Aggro +{ + return self->CheckAggro(other); +} + +float Perl_Mob_CalculateHeadingToTarget(Mob* self, float x, float y) // @categories Script Utility +{ + return self->CalculateHeadingToTarget(x, y); +} + +void Perl_Mob_RunTo(Mob* self, float x, float y, float z) +{ + self->RunTo(x, y, z); +} + +void Perl_Mob_WalkTo(Mob* self, float x, float y, float z) +{ + self->WalkTo(x, y, z); +} + +void Perl_Mob_NavigateTo(Mob* self, float x, float y, float z) // @categories Script Utility +{ + self->NavigateTo(x, y, z); +} + +void Perl_Mob_StopNavigation(Mob* self) +{ + self->StopNavigation(); +} + +float Perl_Mob_CalculateDistance(Mob* self, float x, float y, float z) // @categories Script Utility +{ + return self->CalculateDistance(x, y, z); +} + +void Perl_Mob_SendTo(Mob* self, float new_x, float new_y, float new_z) // @categories Script Utility +{ + self->SendTo(new_x, new_y, new_z); +} + +void Perl_Mob_SendToFixZ(Mob* self, float new_x, float new_y, float new_z) // @categories Script Utility +{ + self->SendToFixZ(new_x, new_y, new_z); +} + +void Perl_Mob_NPCSpecialAttacks(Mob* self, const char* abilities_string, int perm_tag) // @categories Stats and Attributes +{ + self->NPCSpecialAttacks(abilities_string, perm_tag); +} + +void Perl_Mob_NPCSpecialAttacks(Mob* self, const char* abilities_string, int perm_tag, bool reset) // @categories Stats and Attributes +{ + self->NPCSpecialAttacks(abilities_string, perm_tag, reset); +} + +void Perl_Mob_NPCSpecialAttacks(Mob* self, const char* abilities_string, int perm_tag, bool reset, bool remove) // @categories Stats and Attributes +{ + self->NPCSpecialAttacks(abilities_string, perm_tag, reset, remove); +} + +uint32_t Perl_Mob_DontHealMeBefore(Mob* self) // @categories Script Utility +{ + return self->DontHealMeBefore(); +} + +uint32_t Perl_Mob_DontBuffMeBefore(Mob* self) // @categories Script Utility +{ + return self->DontBuffMeBefore(); +} + +uint32_t Perl_Mob_DontDotMeBefore(Mob* self) // @categories Script Utility +{ + return self->DontDotMeBefore(); +} + +uint32_t Perl_Mob_DontRootMeBefore(Mob* self) // @categories Script Utility +{ + return self->DontRootMeBefore(); +} + +uint32_t Perl_Mob_DontSnareMeBefore(Mob* self) // @categories Script Utility +{ + return self->DontSnareMeBefore(); +} + +int Perl_Mob_GetResist(Mob* self, uint8_t type) // @categories Stats and Attributes +{ + return self->GetResist(type); +} + +bool Perl_Mob_Charmed(Mob* self) // @categories Script Utility +{ + return self->Charmed(); +} + +uint32_t Perl_Mob_GetLevelHP(Mob* self, uint8 level) // @categories Stats and Attributes +{ + return self->GetLevelHP(level); +} + +uint32_t Perl_Mob_GetZoneID(Mob* self) // @categories Zones +{ + return self->GetZoneID(); +} + +int Perl_Mob_CheckAggroAmount(Mob* self, uint16 spell_id) // @categories Hate and Aggro +{ + return self->CheckAggroAmount(spell_id, nullptr); +} + +int Perl_Mob_CheckHealAggroAmount(Mob* self, uint16 spell_id) // @categories Hate and Aggro +{ + return self->CheckHealAggroAmount(spell_id, nullptr); +} + +int Perl_Mob_CheckHealAggroAmount(Mob* self, uint16 spell_id, uint32 possible) // @categories Hate and Aggro +{ + return self->CheckHealAggroAmount(spell_id, nullptr, possible); +} + +uint32_t Perl_Mob_GetAA(Mob* self, uint32 rank_id) // @categories Alternative Advancement +{ + return self->GetAA(rank_id); +} + +uint32_t Perl_Mob_GetAAByAAID(Mob* self, uint32 aa_id) // @categories Alternative Advancement +{ + return self->GetAAByAAID(aa_id); +} + +bool Perl_Mob_SetAA(Mob* self, int aa_id, int points) // @categories Alternative Advancement, Script Utility +{ + return self->SetAA(aa_id, points); +} + +bool Perl_Mob_SetAA(Mob* self, int aa_id, int points, int charges) // @categories Alternative Advancement, Script Utility +{ + return self->SetAA(aa_id, points, charges); +} + +bool Perl_Mob_DivineAura(Mob* self) // @categories Spells and Disciplines +{ + return self->DivineAura(); +} + +void Perl_Mob_AddFeignMemory(Mob* self, Client* attacker) // @categories Script Utility +{ + self->AddFeignMemory(attacker); +} + +void Perl_Mob_RemoveFromFeignMemory(Mob* self, Client* attacker) // @categories Script Utility, Hate and Aggro +{ + self->RemoveFromFeignMemory(attacker); +} + +void Perl_Mob_ClearFeignMemory(Mob* self) // @categories Script Utility, Hate and Aggro +{ + self->ClearFeignMemory(); +} + +void Perl_Mob_SetOOCRegen(Mob* self, int64 new_ooc_regen) // @categories Stats and Attributes +{ + self->SetOOCRegen(new_ooc_regen); +} + +perl::array Perl_Mob_GetHateList(Mob* self) +{ + perl::array result; + auto hate_list = self->GetHateList(); + for (struct_HateList* entry : hate_list) + { + result.push_back(entry); + } + return result; +} + +void Perl_Mob_SignalClient(Mob* self, Client* client, int signal_id) // @categories Script Utility +{ + client->Signal(signal_id); +} + +bool Perl_Mob_CombatRange(Mob* self, Mob* target) // @categories Script Utility +{ + return self->CombatRange(target); +} + +void Perl_Mob_DoSpecialAttackDamage(Mob* self, Mob* other, int skill, int max_damage) // @categories Script Utility, Skills and Attributes +{ + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage); +} + +void Perl_Mob_DoSpecialAttackDamage(Mob* self, Mob* other, int skill, int max_damage, int min_damage) // @categories Script Utility, Skills and Attributes +{ + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage); +} + +void Perl_Mob_DoSpecialAttackDamage(Mob* self, Mob* other, int skill, int max_damage, int min_damage, int hate_override) // @categories Script Utility, Skills and Attributes +{ + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override); +} + +void Perl_Mob_DoSpecialAttackDamage(Mob* self, Mob* other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time) // @categories Script Utility, Skills and Attributes +{ + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override, reuse_time); +} + +bool Perl_Mob_CheckLoS(Mob* self, Mob* other) // @categories Script Utility +{ + return self->CheckLosFN(other); +} + +bool Perl_Mob_CheckLoSToLoc(Mob* self, float x, float y, float z) +{ + return self->CheckLosFN(x, y, z, 6.0f); +} + +bool Perl_Mob_CheckLoSToLoc(Mob* self, float x, float y, float z, float mob_size) // @categories Script Utility +{ + return self->CheckLosFN(x, y, z, mob_size); +} + +float Perl_Mob_FindGroundZ(Mob* self, float x, float y) +{ + return self->GetGroundZ(x, y); +} + +float Perl_Mob_FindGroundZ(Mob* self, float x, float y, float z_offset) // @categories Script Utility +{ + return self->GetGroundZ(x, y, z_offset); +} + +void Perl_Mob_ProjectileAnim(Mob* self, Mob* to, int item_id) // @categories Script Utility +{ + self->ProjectileAnimation(to, item_id); +} + +void Perl_Mob_ProjectileAnim(Mob* self, Mob* to, int item_id, bool is_arrow) // @categories Script Utility +{ + self->ProjectileAnimation(to, item_id, is_arrow); +} + +void Perl_Mob_ProjectileAnim(Mob* self, Mob* to, int item_id, bool is_arrow, float speed) // @categories Script Utility +{ + self->ProjectileAnimation(to, item_id, is_arrow, speed); +} + +void Perl_Mob_ProjectileAnim(Mob* self, Mob* to, int item_id, bool is_arrow, float speed, float angle) // @categories Script Utility +{ + self->ProjectileAnimation(to, item_id, is_arrow, speed, angle); +} + +void Perl_Mob_ProjectileAnim(Mob* self, Mob* to, int item_id, bool is_arrow, float speed, float angle, float tilt) // @categories Script Utility +{ + self->ProjectileAnimation(to, item_id, is_arrow, speed, angle, tilt); +} + +void Perl_Mob_ProjectileAnim(Mob* self, Mob* to, int item_id, bool is_arrow, float speed, float angle, float tilt, float arc) // @categories Script Utility +{ + self->ProjectileAnimation(to, item_id, is_arrow, speed, angle, tilt, arc); +} + +void Perl_Mob_ProjectileAnim(Mob* self, Mob* to, int item_id, bool is_arrow, float speed, float angle, float tilt, float arc, const char* idfile) // @categories Script Utility +{ + self->ProjectileAnimation(to, item_id, is_arrow, speed, angle, tilt, arc, idfile); +} + +bool Perl_Mob_HasNPCSpecialAtk(Mob* self, const char* ability_string) // @categories Stats and Attributes +{ + return self->HasNPCSpecialAtk(ability_string); +} + +// todo: SendAppearanceEffect should be changed to use a table for arguments +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, 0, 0); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, 0); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get()); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2, uint32 ground2) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2, ground2); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2, uint32 ground2, uint32 slot3) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2, ground2, slot3); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2, uint32 ground2, uint32 slot3, uint32 ground3) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2, ground2, slot3, ground3); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2, uint32 ground2, uint32 slot3, uint32 ground3, uint32 slot4) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2, ground2, slot3, ground3, slot4); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2, uint32 ground2, uint32 slot3, uint32 ground3, uint32 slot4, uint32 ground4) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2, ground2, slot3, ground3, slot4, ground4); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2, uint32 ground2, uint32 slot3, uint32 ground3, uint32 slot4, uint32 ground4, uint32 slot5) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2, ground2, slot3, ground3, slot4, ground4, slot5); +} + +void Perl_Mob_SendAppearanceEffect(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, perl::nullable client, uint32 slot1, uint32 ground1, uint32 slot2, uint32 ground2, uint32 slot3, uint32 ground3, uint32 slot4, uint32 ground4, uint32 slot5, uint32 ground5) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client.get(), slot1, ground1, slot2, ground2, slot3, ground3, slot4, ground4, slot5, ground5); +} + +// todo: SendAppearanceEffectActor should be changed to use a table for arguments +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, 0, 0, 0, 0, nullptr, slot1, 0, 0, 0, 0, 0, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, 0, 0, 0, nullptr, slot1, 0, 0, 0, 0, 0, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, 0, 0, 0, nullptr, slot1, 0, slot2, 0, 0, 0, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2, int32 parm3) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, 0, 0, nullptr, slot1, 0, slot2, 0, 0, 0, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2, int32 parm3, uint32 slot3) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, 0, 0, nullptr, slot1, 0, slot2, 0, slot3, 0, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2, int32 parm3, uint32 slot3, int32 parm4) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, 0, nullptr, slot1, 0, slot2, 0, slot3, 0, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2, int32 parm3, uint32 slot3, int32 parm4, uint32 slot4) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, 0, nullptr, slot1, 0, slot2, 0, slot3, 0, slot4, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2, int32 parm3, uint32 slot3, int32 parm4, uint32 slot4, int32 parm5) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, nullptr, slot1, 0, slot2, 0, slot3, 0, slot4, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2, int32 parm3, uint32 slot3, int32 parm4, uint32 slot4, int32 parm5, uint32 slot5) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, nullptr, slot1, 0, slot2, 0, slot3, 0, slot4, 0, slot5, 0); +} + +void Perl_Mob_SendAppearanceEffectActor(Mob* self, int32 parm1, uint32 slot1, int32 parm2, uint32 slot2, int32 parm3, uint32 slot3, int32 parm4, uint32 slot4, int32 parm5, uint32 slot5, Client* client) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, slot1, 0, slot2, 0, slot3, 0, slot4, 0, slot5, 0); +} + +void Perl_Mob_SendAppearanceEffectGround(Mob* self, int32 parm1) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, 0, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectGround(Mob* self, int32 parm1, int32 parm2) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, 0, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectGround(Mob* self, int32 parm1, int32 parm2, int32 parm3) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, 0, 0); +} + +void Perl_Mob_SendAppearanceEffectGround(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, 0); +} + +void Perl_Mob_SendAppearanceEffectGround(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5); +} + +void Perl_Mob_SendAppearanceEffectGround(Mob* self, int32 parm1, int32 parm2, int32 parm3, int32 parm4, int32 parm5, Client* client) // @categories Script Utility +{ + self->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client); +} + +void Perl_Mob_RemoveAllAppearanceEffects(Mob* self) // @categories Script Utility +{ + self->SendIllusionPacket(self->GetRace(), self->GetGender(), self->GetTexture(), self->GetHelmTexture(), + self->GetHairColor(), self->GetBeardColor(), self->GetEyeColor1(), self->GetEyeColor2(), + self->GetHairStyle(), self->GetLuclinFace(), self->GetBeard(), 0xFF, + self->GetDrakkinHeritage(), self->GetDrakkinTattoo(), self->GetDrakkinDetails(), self->GetSize(), false); + self->ClearAppearenceEffects(); +} + +void Perl_Mob_SetFlyMode(Mob* self, int flymode) // @categories Script Utility +{ + self->SetFlyMode(static_cast(flymode)); +} + +void Perl_Mob_SetTexture(Mob* self, int32 texture) // @categories Stats and Attributes +{ + self->SendIllusionPacket(self->GetRace(), 0xFF, texture); +} + +void Perl_Mob_SetRace(Mob* self, int32 race) // @categories Stats and Attributes +{ + self->SendIllusionPacket(race); +} + +void Perl_Mob_SetGender(Mob* self, int32 gender) // @categories Stats and Attributes +{ + self->SendIllusionPacket(self->GetRace(), gender); +} + +// todo: SendIllusion should be sent in a hash like lua +void Perl_Mob_SendIllusion(Mob* self, uint16 race) // @categories Script Utility +{ + self->SendIllusionPacket(race); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, face); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, 0xFF, 0xFF, 0xFF, 0xFF, hairstyle, face); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, 0xFF, 0xFF, 0xFF, hairstyle, face); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor, uint8 beard) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, 0xFF, 0xFF, 0xFF, hairstyle, face, beard); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor, uint8 beard, uint8 beardcolor) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, hairstyle, face, beard); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor, uint8 beard, uint8 beardcolor, uint32 drakkin_heritage) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, hairstyle, face, beard, 0xFF, drakkin_heritage); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor, uint8 beard, uint8 beardcolor, uint32 drakkin_heritage, uint32 drakkin_tattoo) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, hairstyle, face, beard, 0xFF, drakkin_heritage, drakkin_tattoo); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor, uint8 beard, uint8 beardcolor, uint32 drakkin_heritage, uint32 drakkin_tattoo, uint32 drakkin_details) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, hairstyle, face, beard, 0xFF, drakkin_heritage, drakkin_tattoo, drakkin_details); +} + +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor, uint8 beard, uint8 beardcolor, uint32 drakkin_heritage, uint32 drakkin_tattoo, uint32 drakkin_details, float size) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, hairstyle, face, beard, 0xFF, drakkin_heritage, drakkin_tattoo, drakkin_details, size); +} + +void Perl_Mob_CameraEffect(Mob* self, uint32 duration) // @categories Script Utility +{ + self->CameraEffect(duration, 0.03125f); +} + +void Perl_Mob_CameraEffect(Mob* self, uint32 duration, float intensity) // @categories Script Utility +{ + self->CameraEffect(duration, intensity); +} + +void Perl_Mob_CameraEffect(Mob* self, uint32 duration, float intensity, Client* client) // @categories Script Utility +{ + self->CameraEffect(duration, intensity, client); +} + +void Perl_Mob_CameraEffect(Mob* self, uint32 duration, float intensity, perl::nullable client, bool global) // @categories Script Utility +{ + self->CameraEffect(duration, intensity, client.get(), global); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, 5000, 0, true, 3000); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, 0, true, 3000); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration, uint32 finish_delay) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, finish_delay, true, 3000); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration, uint32 finish_delay, bool zone_wide) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, finish_delay, zone_wide, 3000); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk20) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, finish_delay, zone_wide, unk20); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk20, bool perm_effect) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, finish_delay, zone_wide, unk20, perm_effect); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk20, bool perm_effect, Client* client) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, finish_delay, zone_wide, unk20, perm_effect, client); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk20, bool perm_effect, perl::nullable client, uint32 caster_id) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, finish_delay, zone_wide, unk20, perm_effect, client.get(), caster_id); +} + +void Perl_Mob_SpellEffect(Mob* self, uint32 effect, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk20, bool perm_effect, perl::nullable client, uint32 caster_id, uint32 target_id) // @categories Spells and Disciplines +{ + self->SendSpellEffect(effect, duration, finish_delay, zone_wide, unk20, perm_effect, client.get(), caster_id, target_id); +} + +void Perl_Mob_TempName(Mob* self) // @categories Script Utility +{ + self->TempName(); +} + +void Perl_Mob_TempName(Mob* self, const char* name) // @categories Script Utility +{ + self->TempName(name); +} + +const int Perl_Mob_GetItemStat(Mob* self, uint32 item_id, std::string identifier) // @categories Inventory and Items, Stats and Attributes +{ + return self->GetItemStat(item_id, identifier); +} + +std::string Perl_Mob_GetGlobal(Mob* self, const char* varname) +{ + return self->GetGlobal(varname); +} + +void Perl_Mob_SetGlobal(Mob* self, const char* varname, const char* newvalue, int options, const char* duration) +{ + self->SetGlobal(varname, newvalue, options, duration); +} + +void Perl_Mob_SetGlobal(Mob* self, const char* varname, const char* newvalue, int options, const char* duration, Mob* other) +{ + self->SetGlobal(varname, newvalue, options, duration, other); +} + +void Perl_Mob_TarGlobal(Mob* self, const char* varname, const char* value, const char* duration, int npc_id, int char_id, int zone_id) +{ + self->TarGlobal(varname, value, duration, npc_id, char_id, zone_id); +} + +void Perl_Mob_DelGlobal(Mob* self, const char* var_name) +{ + self->DelGlobal(var_name); +} + +void Perl_Mob_SetSlotTint(Mob* self, uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint) // @categories Stats and Attributes +{ + self->SetSlotTint(material_slot, red_tint, green_tint, blue_tint); +} + +void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint16 texture) // @categories Script Utility +{ + self->WearChange(material_slot, texture); +} + +void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint16 texture, uint32 color) // @categories Script Utility +{ + self->WearChange(material_slot, texture, color); +} + +void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model) // @categories Script Utility +{ + self->WearChange(material_slot, texture, color, hero_forge_model); +} + +void Perl_Mob_DoKnockback(Mob* self, Mob* caster, uint32 push_back, uint32 push_up) // @categories Script Utility +{ + self->DoKnockback(caster, push_back, push_up); +} + +void Perl_Mob_RemoveNimbusEffect(Mob* self, int effect_id) // @categories Script Utility +{ + self->RemoveNimbusEffect(effect_id); +} + +void Perl_Mob_SetRunning(Mob* self, bool value) // @categories Script Utility +{ + self->SetRunning(value); +} + +bool Perl_Mob_IsRunning(Mob* self) // @categories Script Utility +{ + return self->IsRunning(); +} + +void Perl_Mob_SetBodyType(Mob* self, int32 type) // @categories Stats and Attributes +{ + self->SetBodyType(static_cast(type), false); +} + +void Perl_Mob_SetBodyType(Mob* self, int32 type, bool overwrite_orig) // @categories Stats and Attributes +{ + self->SetBodyType(static_cast(type), overwrite_orig); +} + +void Perl_Mob_SetDeltas(Mob* self, float delta_x, float delta_y, float delta_z, float delta_h) // @categories Script Utility +{ + auto delta = glm::vec4(delta_x, delta_y, delta_z, delta_h); + self->SetDelta(delta); +} + +void Perl_Mob_SetLD(Mob* self, bool value) // @categories Script Utility +{ + self->SendAppearancePacket(AT_Linkdead, value); +} + +void Perl_Mob_SetTargetable(Mob* self, bool on) // @categories Stats and Attributes +{ + self->SetTargetable(on); +} + +void Perl_Mob_ModSkillDmgTaken(Mob* self, int skill, int16 value) // @categories Skills and Recipes, Script Utility +{ + self->ModSkillDmgTaken(static_cast(skill), value); +} + +int Perl_Mob_GetModSkillDmgTaken(Mob* self, int skill_id) // @categories Stats and Attributes +{ + return self->GetModSkillDmgTaken(static_cast(skill_id)); +} + +int Perl_Mob_GetSkillDmgTaken(Mob* self, int skill_id) // @categories Skills and Recipes, Script Utility +{ + return self->GetSkillDmgTaken(static_cast(skill_id)); +} + +void Perl_Mob_SetAllowBeneficial(Mob* self, bool value) // @categories Stats and Attributes +{ + self->SetAllowBeneficial(value); +} + +bool Perl_Mob_GetAllowBeneficial(Mob* self) // @categories Stats and Attributes +{ + return self->GetAllowBeneficial(); +} + +bool Perl_Mob_IsBeneficialAllowed(Mob* self, Mob* target) // @categories Stats and Attributes +{ + return self->IsBeneficialAllowed(target); +} + +void Perl_Mob_ModVulnerability(Mob* self, uint8 resist, int16 value) // @categories Stats and Attributes +{ + self->ModVulnerability(resist, value); +} + +int Perl_Mob_GetModVulnerability(Mob* self, uint8 resist) // @categories Stats and Attributes +{ + return self->GetModVulnerability(resist); +} + +void Perl_Mob_DoMeleeSkillAttackDmg(Mob* self, Mob* target, uint16 weapon_damage, int skill, int16 chance_mod, int16 focus, uint8 can_riposte) // @categories Script Utility, Skills and Attributes +{ + self->DoMeleeSkillAttackDmg(target, weapon_damage, static_cast(skill), chance_mod, focus, can_riposte); +} + +void Perl_Mob_DoArcheryAttackDmg(Mob* self, Mob* target, uint16 weapon_damage, int16 chance_mod, int16 focus) // @categories Script Utility, Skills and Attributes +{ + self->DoArcheryAttackDmg(target, nullptr, nullptr, weapon_damage, chance_mod, focus); +} + +void Perl_Mob_DoThrowingAttackDmg(Mob* self, Mob* target, uint16 weapon_damage, int16 chance_mod, int16 focus) // @categories Script Utility, Skills and Attributes +{ + self->DoThrowingAttackDmg(target, nullptr, nullptr, weapon_damage, chance_mod, focus); +} + +void Perl_Mob_SetDisableMelee(Mob* self, bool value) // @categories Script Utility, Stats and Attributes +{ + self->SetDisableMelee(value); +} + +bool Perl_Mob_IsMeleeDisabled(Mob* self) // @categories Stats and Attributes +{ + return self->IsMeleeDisabled(); +} + +void Perl_Mob_SetFlurryChance(Mob* self, uint8 value) // @categories Stats and Attributes +{ + self->SetFlurryChance(value); +} + +int Perl_Mob_GetFlurryChance(Mob* self) // @categories Stats and Attributes +{ + return self->GetFlurryChance(); +} + +int Perl_Mob_GetSpellStat(Mob* self, uint32 spell_id, const char* stat) // @categories Spells and Disciplines +{ + return self->GetSpellStat(spell_id, stat); +} + +int Perl_Mob_GetSpellStat(Mob* self, uint32 spell_id, const char* stat, uint8 slot) // @categories Spells and Disciplines +{ + return self->GetSpellStat(spell_id, stat, slot); +} + +int Perl_Mob_GetBuffStatValueBySpell(Mob* self, int spell_id, const char* stat) // @categories Spells and Disciplines +{ + return self->GetBuffStatValueBySpell(spell_id, stat); +} + +int Perl_Mob_GetBuffStatValueBySlot(Mob* self, uint8 slot, const char* stat)// @categories Script Utility, Spells and Disciplines +{ + return self->GetBuffStatValueBySlot(slot, stat); +} + +int Perl_Mob_GetSpecialAbility(Mob* self, int ability) // @categories Stats and Attributes +{ + return self->GetSpecialAbility(ability); +} + +int Perl_Mob_GetSpecialAbilityParam(Mob* self, int ability, int param) // @categories Stats and Attributes +{ + return self->GetSpecialAbilityParam(ability, param); +} + +void Perl_Mob_SetSpecialAbility(Mob* self, int ability, int value) // @categories Stats and Attributes +{ + self->SetSpecialAbility(ability, value); +} + +void Perl_Mob_SetSpecialAbilityParam(Mob* self, int ability, int param, int value) // @categories Stats and Attributes +{ + self->SetSpecialAbilityParam(ability, param, value); +} + +void Perl_Mob_ClearSpecialAbilities(Mob* self)// @categories Script Utility +{ + self->ClearSpecialAbilities(); +} + +void Perl_Mob_ProcessSpecialAbilities(Mob* self, std::string str) // @categories Script Utility +{ + self->ProcessSpecialAbilities(str); +} + +bool Perl_Mob_CanClassEquipItem(Mob* self, uint32 item_id) // @categories Inventory and Items, Script Utility +{ + return self->CanClassEquipItem(item_id); +} + +bool Perl_Mob_IsFeared(Mob* self) // @categories Script Utility +{ + return self->IsFeared(); +} + +bool Perl_Mob_IsBlind(Mob* self) // @categories Script Utility +{ + return self->IsBlind(); +} + +int Perl_Mob_GetInvisibleLevel(Mob* self) // @categories Stats and Attributes +{ + return self->GetInvisibleLevel(); +} + +int Perl_Mob_GetInvisibleUndeadLevel(Mob* self) // @categories Stats and Attributes +{ + return self->GetInvisibleUndeadLevel(); +} + +int Perl_Mob_SeeInvisible(Mob* self) // @categories Stats and Attributes +{ + return self->SeeInvisible(); +} + +int Perl_Mob_SeeInvisibleUndead(Mob* self) // @categories Stats and Attributes +{ + return self->SeeInvisibleUndead(); +} + +bool Perl_Mob_SeeHide(Mob* self) // @categories Stats and Attributes +{ + return self->SeeHide(); +} + +bool Perl_Mob_SeeImprovedHide(Mob* self) // @categories Stats and Attributes +{ + return self->SeeImprovedHide(); +} + +int Perl_Mob_GetNimbusEffect1(Mob* self) // @categories Script Utility +{ + return self->GetNimbusEffect1(); +} + +int Perl_Mob_GetNimbusEffect2(Mob* self) // @categories Script Utility +{ + return self->GetNimbusEffect2(); +} + +int Perl_Mob_GetNimbusEffect3(Mob* self) // @categories Script Utility +{ + return self->GetNimbusEffect3(); +} + +bool Perl_Mob_IsTargetable(Mob* self) // @categories Stats and Attributes +{ + return self->IsTargetable(); +} + +bool Perl_Mob_HasShieldEquiped(Mob* self) // @categories Stats and Attributes +{ + return self->HasShieldEquiped(); +} + +bool Perl_Mob_HasTwoHandBluntEquiped(Mob* self) // @categories Stats and Attributes +{ + return self->HasTwoHandBluntEquiped(); +} + +bool Perl_Mob_HasTwoHanderEquipped(Mob* self) // @categories Stats and Attributes +{ + return self->HasTwoHanderEquipped(); +} + +int32_t Perl_Mob_GetHerosForgeModel(Mob* self, uint8_t material_slot) // @categories Stats and Attributes +{ + return self->GetHerosForgeModel(material_slot); +} + +bool Perl_Mob_IsEliteMaterialItem(Mob* self, uint8_t material_slot) // @categories Script Utility, Stats and Attributes +{ + return self->IsEliteMaterialItem(material_slot); +} + +float Perl_Mob_GetBaseSize(Mob* self) // @categories Stats and Attributes +{ + return self->GetBaseSize(); +} + +bool Perl_Mob_HasOwner(Mob* self) // @categories Pet +{ + return self->HasOwner(); +} + +bool Perl_Mob_IsPet(Mob* self) // @categories Pet +{ + return self->IsPet(); +} + +bool Perl_Mob_HasPet(Mob* self) // @categories Pet +{ + return self->HasPet(); +} + +void Perl_Mob_RemovePet(Mob* self) // @categories Pet +{ + self->SetPet(nullptr); +} + +void Perl_Mob_SetPet(Mob* self, Mob* new_pet) // @categories Pet +{ + self->SetPet(new_pet); +} + +bool Perl_Mob_IsSilenced(Mob* self) // @categories Script Utility +{ + return self->IsSilenced(); +} + +bool Perl_Mob_IsAmnesiad(Mob* self) // @categories Script Utility +{ + return self->IsAmnesiad(); +} + +int32_t Perl_Mob_GetMeleeMitigation(Mob* self) // @categories Stats and Attributes +{ + return self->GetMeleeMitigation(); +} + +void Perl_Mob_TryMoveAlong(Mob* self, float distance, float angle) // @categories Script Utility +{ + self->TryMoveAlong(distance, angle); +} + +void Perl_Mob_TryMoveAlong(Mob* self, float distance, float angle, bool send) // @categories Script Utility +{ + self->TryMoveAlong(distance, angle, send); +} + +std::string Perl_Mob_GetClassName(Mob* self) +{ + return GetClassIDName(self->GetClass()); +} + +std::string Perl_Mob_GetRaceName(Mob* self) +{ + return GetRaceIDName(self->GetRace()); +} + +void Perl_Mob_DeleteBucket(Mob* self, std::string bucket_name) // @categories Script Utility +{ + self->DeleteBucket(bucket_name); +} + +std::string Perl_Mob_GetBucket(Mob* self, std::string bucket_name) // @categories Script Utility +{ + return self->GetBucket(bucket_name); +} + +std::string Perl_Mob_GetBucketExpires(Mob* self, std::string bucket_name) // @categories Script Utility +{ + return self->GetBucketExpires(bucket_name); +} + +std::string Perl_Mob_GetBucketKey(Mob* self) // @categories Script Utility +{ + return self->GetBucketKey(); +} + +std::string Perl_Mob_GetBucketRemaining(Mob* self, std::string bucket_name) // @categories Script Utility +{ + return self->GetBucketRemaining(bucket_name); +} + +void Perl_Mob_SetBucket(Mob* self, std::string bucket_name, std::string bucket_value) // @categories Script Utility +{ + self->SetBucket(bucket_name, bucket_value); +} + +void Perl_Mob_SetBucket(Mob* self, std::string bucket_name, std::string bucket_value, std::string expiration) // @categories Script Utility +{ + self->SetBucket(bucket_name, bucket_value, expiration); +} + +bool Perl_Mob_IsHorse(Mob* self) // @categories Script Utility +{ + return self->IsHorse(); +} + +perl::array Perl_Mob_GetHateListByDistance(Mob* self) // @categories Hate and Aggro +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(); + for (auto h : h_list) { + result.push_back(h); + } + + return result; +} + +perl::array Perl_Mob_GetHateListByDistance(Mob* self, uint32 distance) // @categories Hate and Aggro +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(EntityFilterType::All, distance); + for (auto h : h_list) { + result.push_back(h); + } + + return result; +} + +Mob* Perl_Mob_GetHateClosest(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateClosest(); +} + +std::string Perl_Mob_GetLastName(Mob* self) // @categories Script Utility +{ + return self->GetLastName(); +} + +bool Perl_Mob_CanRaceEquipItem(Mob* self, uint32 item_id) // @categories Inventory and Items, Script Utility +{ + return self->CanRaceEquipItem(item_id); +} + +void Perl_Mob_RemoveAllNimbusEffects(Mob* self) // @categories Script Utility +{ + self->RemoveAllNimbusEffects(); +} + +void Perl_Mob_AddNimbusEffect(Mob* self, int effect_id) // @categories Script Utility +{ + self->AddNimbusEffect(effect_id); +} + +void Perl_Mob_ShieldAbility(Mob* self, uint32 target_id) // @categories Spells and Disciplines +{ + self->ShieldAbility(target_id); +} + +void Perl_Mob_ShieldAbility(Mob* self, uint32 target_id, int32 shielder_max_distance) // @categories Spells and Disciplines +{ + self->ShieldAbility(target_id, shielder_max_distance); +} + +void Perl_Mob_ShieldAbility(Mob* self, uint32 target_id, int32 shielder_max_distance, int32 shield_duration) // @categories Spells and Disciplines +{ + self->ShieldAbility(target_id, shielder_max_distance, shield_duration); +} + +void Perl_Mob_ShieldAbility(Mob* self, uint32 target_id, int32 shielder_max_distance, int32 shield_duration, int32 shield_target_mitigation) // @categories Spells and Disciplines +{ + self->ShieldAbility(target_id, shielder_max_distance, shield_duration, shield_target_mitigation); +} + +void Perl_Mob_ShieldAbility(Mob* self, uint32 target_id, int32 shielder_max_distance, int32 shield_duration, int32 shield_target_mitigation, int32 shielder_mitigation) // @categories Spells and Disciplines +{ + self->ShieldAbility(target_id, shielder_max_distance, shield_duration, shield_target_mitigation, shielder_mitigation); +} + +void Perl_Mob_ShieldAbility(Mob* self, uint32 target_id, int32 shielder_max_distance, int32 shield_duration, int32 shield_target_mitigation, int32 shielder_mitigation, bool use_aa) // @categories Spells and Disciplines +{ + self->ShieldAbility(target_id, shielder_max_distance, shield_duration, shield_target_mitigation, shielder_mitigation, use_aa); +} + +void Perl_Mob_ShieldAbility(Mob* self, uint32 target_id, int32 shielder_max_distance, int32 shield_duration, int32 shield_target_mitigation, int32 shielder_mitigation, bool use_aa, bool can_shield_npc) // @categories Spells and Disciplines +{ + self->ShieldAbility(target_id, shielder_max_distance, shield_duration, shield_target_mitigation, shielder_mitigation, use_aa, can_shield_npc); +} + +Client* Perl_Mob_GetHateRandomClient(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateRandomClient(); +} + +NPC* Perl_Mob_GetHateRandomNPC(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateRandomNPC(); +} + +void Perl_Mob_SetBuffDuration(Mob* self, int spell_id) // @categories Script Utility, Spells and Disciplines +{ + self->SetBuffDuration(spell_id); +} + +void Perl_Mob_SetBuffDuration(Mob* self, int spell_id, int duration) // @categories Script Utility, Spells and Disciplines +{ + self->SetBuffDuration(spell_id, duration); +} + +void Perl_Mob_ApplySpellBuff(Mob* self, int spell_id) // @categories Script Utility, Spells and Disciplines +{ + self->ApplySpellBuff(spell_id); +} + +void Perl_Mob_ApplySpellBuff(Mob* self, int spell_id, int duration) // @categories Script Utility, Spells and Disciplines +{ + self->ApplySpellBuff(spell_id, duration); +} + +int Perl_Mob_GetSkillDmgAmt(Mob* self, uint16 skill_id) +{ + return self->GetSkillDmgAmt(skill_id); +} + +Mob* Perl_Mob_GetUltimateOwner(Mob* self) // @categories Script Utility, Pet +{ + return self->GetUltimateOwner(); +} + +bool Perl_Mob_RandomizeFeatures(Mob* self) // @categories Script Utility +{ + return self->RandomizeFeatures(); +} + +bool Perl_Mob_RandomizeFeatures(Mob* self, bool send_illusion) // @categories Script Utility +{ + return self->RandomizeFeatures(send_illusion); +} + +bool Perl_Mob_RandomizeFeatures(Mob* self, bool send_illusion, bool save_variables) // @categories Script Utility +{ + return self->RandomizeFeatures(send_illusion, save_variables); +} + +void Perl_Mob_CloneAppearance(Mob* self, Mob* other) // @categories Script Utility +{ + self->CloneAppearance(other); +} + +void Perl_Mob_CloneAppearance(Mob* self, Mob* other, bool clone_name) // @categories Script Utility +{ + self->CloneAppearance(other, clone_name); +} + +Mob* Perl_Mob_GetOwner(Mob* self) // @categories Script Utility, Pet +{ + return self->GetOwner(); +} + +void Perl_Mob_DamageArea(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage); +} + +void Perl_Mob_DamageArea(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::All); +} + +void Perl_Mob_DamageAreaPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage, 0, EntityFilterType::All, true); +} + +void Perl_Mob_DamageAreaPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::All, true); +} + +void Perl_Mob_DamageAreaClients(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage, 0, EntityFilterType::Clients); +} + +void Perl_Mob_DamageAreaClients(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::Clients); +} + +void Perl_Mob_DamageAreaClientsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage, 0, EntityFilterType::Clients, true); +} + +void Perl_Mob_DamageAreaClientsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::Clients, true); +} + +void Perl_Mob_DamageAreaNPCs(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage, 0, EntityFilterType::NPCs); +} + +void Perl_Mob_DamageAreaNPCs(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::NPCs); +} + +void Perl_Mob_DamageAreaNPCsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage, 0, EntityFilterType::NPCs, true); +} + +void Perl_Mob_DamageAreaNPCsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::NPCs, true); +} + +void Perl_Mob_DamageHateList(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage); +} + +void Perl_Mob_DamageHateList(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::All); +} + +void Perl_Mob_DamageHateListPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage, 0, EntityFilterType::All, true); +} + +void Perl_Mob_DamageHateListPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::All, true); +} + +void Perl_Mob_DamageHateListClients(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage, 0, EntityFilterType::Clients); +} + +void Perl_Mob_DamageHateListClients(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::Clients); +} + +void Perl_Mob_DamageHateListClientsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage, 0, EntityFilterType::Clients, true); +} + +void Perl_Mob_DamageHateListClientsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::Clients, true); +} + +void Perl_Mob_DamageHateListNPCs(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage, 0, EntityFilterType::NPCs); +} + +void Perl_Mob_DamageHateListNPCs(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::NPCs); +} + +void Perl_Mob_DamageHateListNPCsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage, 0, EntityFilterType::NPCs, true); +} + +void Perl_Mob_DamageHateListNPCsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::NPCs, true); +} + +perl::array Perl_Mob_GetHateListClients(Mob* self) +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Clients); + for (auto h : h_list) { + result.push_back(h); + } + + return result; +} + +perl::array Perl_Mob_GetHateListClients(Mob* self, uint32 distance) +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Clients, distance); + for (auto h : h_list) { + result.push_back(h); + } + + return result; +} + +perl::array Perl_Mob_GetHateListNPCs(Mob* self) +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs); + for (auto h : h_list) { + result.push_back(h); + } + + return result; +} + +perl::array Perl_Mob_GetHateListNPCs(Mob* self, uint32 distance) +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs, distance); + for (auto h : h_list) { + result.push_back(h); + } + + return result; +} + +bool Perl_Mob_ClearEntityVariables(Mob* self) // @categories Script Utility +{ + return self->ClearEntityVariables(); +} + +bool Perl_Mob_DeleteEntityVariable(Mob* self, std::string variable_name) // @categories Script Utility +{ + return self->DeleteEntityVariable(variable_name); +} + +bool Perl_Mob_EntityVariableExists(Mob* self, std::string variable_name) // @categories Script Utility +{ + return self->EntityVariableExists(variable_name); +} + +std::string Perl_Mob_GetEntityVariable(Mob* self, std::string variable_name) // @categories Script Utility +{ + return self->GetEntityVariable(variable_name); +} + +perl::array Perl_Mob_GetEntityVariables(Mob* self) // @categories Script Utility +{ + perl::array a; + + const auto& l = self->GetEntityVariables(); + for (const auto& v : l) { + a.push_back(v); + } + + return a; +} + +void Perl_Mob_SetEntityVariable(Mob* self, std::string variable_name, std::string variable_value) // @categories Script Utility +{ + self->SetEntityVariable(variable_name, variable_value); +} + +void Perl_Mob_CopyHateList(Mob* self, Mob* to) +{ + self->CopyHateList(to); +} + +bool Perl_Mob_IsAttackAllowed(Mob* self, Mob* target) +{ + return self->IsAttackAllowed(target); +} + +bool Perl_Mob_IsAttackAllowed(Mob* self, Mob* target, bool is_spell_attack) +{ + return self->IsAttackAllowed(target, is_spell_attack); +} + +uint32 Perl_Mob_BuffCount(Mob* self) // @categories Script Utility, Spells and Disciplines +{ + return self->BuffCount(); +} + +uint32 Perl_Mob_BuffCount(Mob* self, bool is_beneficial) // @categories Script Utility, Spells and Disciplines +{ + return self->BuffCount(is_beneficial); +} + +uint32 Perl_Mob_BuffCount(Mob* self, bool is_beneficial, bool is_detrimental) // @categories Script Utility, Spells and Disciplines +{ + return self->BuffCount(is_beneficial, is_detrimental); +} + +void Perl_Mob_DamageAreaBots(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage, 0, EntityFilterType::Bots); +} + +void Perl_Mob_DamageAreaBots(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::Bots); +} + +void Perl_Mob_DamageAreaBotsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageArea(damage, 0, EntityFilterType::Bots, true); +} + +void Perl_Mob_DamageAreaBotsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageArea(damage, distance, EntityFilterType::Bots, true); +} + +void Perl_Mob_DamageHateListBots(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage, 0, EntityFilterType::Bots); +} + +void Perl_Mob_DamageHateListBots(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::Bots); +} + +void Perl_Mob_DamageHateListBotsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro +{ + self->DamageHateList(damage, 0, EntityFilterType::Bots, true); +} + +void Perl_Mob_DamageHateListBotsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro +{ + self->DamageHateList(damage, distance, EntityFilterType::Bots, true); +} + +perl::array Perl_Mob_GetHateListBots(Mob* self) +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Bots); + for (auto h : h_list) { + result.push_back(h); + } + + return result; +} + +perl::array Perl_Mob_GetHateListBots(Mob* self, uint32 distance) +{ + perl::array result; + + auto h_list = self->GetFilteredHateList(EntityFilterType::Bots, distance); + for (auto h : h_list) + { + result.push_back(h); + } + + return result; +} + +Bot* Perl_Mob_CastToBot(Mob* self) +{ + return self->CastToBot(); +} + +Bot* Perl_Mob_GetHateRandomBot(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateRandomBot(); +} + +void perl_register_mob() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Mob"); + package.add("AddFeignMemory", &Perl_Mob_AddFeignMemory); + package.add("AddNimbusEffect", &Perl_Mob_AddNimbusEffect); + package.add("AddToHateList", (void(*)(Mob*, Mob*))&Perl_Mob_AddToHateList); + package.add("AddToHateList", (void(*)(Mob*, Mob*, int64_t))&Perl_Mob_AddToHateList); + package.add("AddToHateList", (void(*)(Mob*, Mob*, int64_t, int64_t))&Perl_Mob_AddToHateList); + package.add("AddToHateList", (void(*)(Mob*, Mob*, int64_t, int64_t, bool))&Perl_Mob_AddToHateList); + package.add("AddToHateList", (void(*)(Mob*, Mob*, int64_t, int64_t, bool, bool))&Perl_Mob_AddToHateList); + package.add("AddToHateList", (void(*)(Mob*, Mob*, int64_t, int64_t, bool, bool, bool))&Perl_Mob_AddToHateList); + package.add("ApplySpellBuff", (void(*)(Mob*, int))&Perl_Mob_ApplySpellBuff); + package.add("ApplySpellBuff", (void(*)(Mob*, int, int))&Perl_Mob_ApplySpellBuff); + package.add("Attack", (bool(*)(Mob*, Mob*))&Perl_Mob_Attack); + package.add("Attack", (bool(*)(Mob*, Mob*, int))&Perl_Mob_Attack); + package.add("Attack", (bool(*)(Mob*, Mob*, int, bool))&Perl_Mob_Attack); + package.add("BehindMob", (bool(*)(Mob*, Mob*))&Perl_Mob_BehindMob); + package.add("BehindMob", (bool(*)(Mob*, Mob*, float))&Perl_Mob_BehindMob); + package.add("BehindMob", (bool(*)(Mob*, Mob*, float, float))&Perl_Mob_BehindMob); + package.add("BuffCount", (uint32(*)(Mob*))&Perl_Mob_BuffCount); + package.add("BuffCount", (uint32(*)(Mob*, bool))&Perl_Mob_BuffCount); + package.add("BuffCount", (uint32(*)(Mob*, bool, bool))&Perl_Mob_BuffCount); + package.add("BuffFadeAll", &Perl_Mob_BuffFadeAll); + package.add("BuffFadeByEffect", (void(*)(Mob*, int))&Perl_Mob_BuffFadeByEffect); + package.add("BuffFadeByEffect", (void(*)(Mob*, int, int))&Perl_Mob_BuffFadeByEffect); + package.add("BuffFadeBySlot", (void(*)(Mob*, int))&Perl_Mob_BuffFadeBySlot); + package.add("BuffFadeBySlot", (void(*)(Mob*, int, bool))&Perl_Mob_BuffFadeBySlot); + package.add("BuffFadeBySpellID", &Perl_Mob_BuffFadeBySpellID); + package.add("CalculateDistance", &Perl_Mob_CalculateDistance); + package.add("CalculateHeadingToTarget", &Perl_Mob_CalculateHeadingToTarget); + package.add("CameraEffect", (void(*)(Mob*, uint32))&Perl_Mob_CameraEffect); + package.add("CameraEffect", (void(*)(Mob*, uint32, float))&Perl_Mob_CameraEffect); + package.add("CameraEffect", (void(*)(Mob*, uint32, float, Client*))&Perl_Mob_CameraEffect); + package.add("CameraEffect", (void(*)(Mob*, uint32, float, perl::nullable, bool))&Perl_Mob_CameraEffect); + package.add("CanBuffStack", (bool(*)(Mob*, uint16, uint8))&Perl_Mob_CanBuffStack); + package.add("CanBuffStack", (bool(*)(Mob*, uint16, uint8, bool))&Perl_Mob_CanBuffStack); + package.add("CanClassEquipItem", &Perl_Mob_CanClassEquipItem); + package.add("CanRaceEquipItem", &Perl_Mob_CanRaceEquipItem); + package.add("CanThisClassDodge", &Perl_Mob_CanThisClassDodge); + package.add("CanThisClassDoubleAttack", &Perl_Mob_CanThisClassDoubleAttack); + package.add("CanThisClassDualWield", &Perl_Mob_CanThisClassDualWield); + package.add("CanThisClassParry", &Perl_Mob_CanThisClassParry); + package.add("CanThisClassRiposte", &Perl_Mob_CanThisClassRiposte); + package.add("CastSpell", (void(*)(Mob*, uint16, uint16))&Perl_Mob_CastSpell); + package.add("CastSpell", (void(*)(Mob*, uint16, uint16, int))&Perl_Mob_CastSpell); + package.add("CastSpell", (void(*)(Mob*, uint16, uint16, int, int))&Perl_Mob_CastSpell); + package.add("CastSpell", (void(*)(Mob*, uint16, uint16, int, int, int))&Perl_Mob_CastSpell); + package.add("CastSpell", (void(*)(Mob*, uint16, uint16, int, int, int, int16))&Perl_Mob_CastSpell); + package.add("CastToBot", &Perl_Mob_CastToBot); + package.add("CastToClient", &Perl_Mob_CastToClient); + package.add("CastToCorpse", &Perl_Mob_CastToCorpse); + package.add("CastToMob", &Perl_Mob_CastToMob); + package.add("CastToNPC", &Perl_Mob_CastToNPC); + package.add("CastingSpellID", &Perl_Mob_CastingSpellID); + package.add("ChangeSize", (void(*)(Mob*, float))&Perl_Mob_ChangeSize); + package.add("ChangeSize", (void(*)(Mob*, float, bool))&Perl_Mob_ChangeSize); + package.add("Charmed", &Perl_Mob_Charmed); + package.add("CheckAggro", &Perl_Mob_CheckAggro); + package.add("CheckAggroAmount", &Perl_Mob_CheckAggroAmount); + package.add("CheckHealAggroAmount", (int(*)(Mob*, uint16))&Perl_Mob_CheckHealAggroAmount); + package.add("CheckHealAggroAmount", (int(*)(Mob*, uint16, uint32))&Perl_Mob_CheckHealAggroAmount); + package.add("CheckLoS", &Perl_Mob_CheckLoS); + package.add("CheckLoSToLoc", (bool(*)(Mob*, float, float, float))&Perl_Mob_CheckLoSToLoc); + package.add("CheckLoSToLoc", (bool(*)(Mob*, float, float, float, float))&Perl_Mob_CheckLoSToLoc); + package.add("ClearEntityVariables", &Perl_Mob_ClearEntityVariables); + package.add("ClearFeignMemory", &Perl_Mob_ClearFeignMemory); + package.add("ClearSpecialAbilities", &Perl_Mob_ClearSpecialAbilities); + package.add("CloneAppearance", (void(*)(Mob*, Mob*))&Perl_Mob_CloneAppearance); + package.add("CloneAppearance", (void(*)(Mob*, Mob*, bool))&Perl_Mob_CloneAppearance); + package.add("CombatRange", &Perl_Mob_CombatRange); + package.add("CopyHateList", &Perl_Mob_CopyHateList); + package.add("Damage", (void(*)(Mob*, Mob*, int64, uint16_t, int))&Perl_Mob_Damage); + package.add("Damage", (void(*)(Mob*, Mob*, int64, uint16_t, int, bool))&Perl_Mob_Damage); + package.add("Damage", (void(*)(Mob*, Mob*, int64, uint16_t, int, bool, int8_t))&Perl_Mob_Damage); + package.add("Damage", (void(*)(Mob*, Mob*, int64, uint16_t, int, bool, int8_t, bool))&Perl_Mob_Damage); + package.add("DamageArea", (void(*)(Mob*, int64))&Perl_Mob_DamageArea); + package.add("DamageArea", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageArea); + package.add("DamageAreaBots", (void(*)(Mob*, int64))&Perl_Mob_DamageAreaBots); + package.add("DamageAreaBots", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageAreaBots); + package.add("DamageAreaBotsPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageAreaBotsPercentage); + package.add("DamageAreaBotsPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageAreaBotsPercentage); + package.add("DamageAreaClients", (void(*)(Mob*, int64))&Perl_Mob_DamageAreaClients); + package.add("DamageAreaClients", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageAreaClients); + package.add("DamageAreaClientsPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageAreaClientsPercentage); + package.add("DamageAreaClientsPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageAreaClientsPercentage); + package.add("DamageAreaNPCs", (void(*)(Mob*, int64))&Perl_Mob_DamageAreaNPCs); + package.add("DamageAreaNPCs", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageAreaNPCs); + package.add("DamageAreaNPCsPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageAreaNPCsPercentage); + package.add("DamageAreaNPCsPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageAreaNPCsPercentage); + package.add("DamageAreaPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageAreaPercentage); + package.add("DamageAreaPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageAreaPercentage); + package.add("DamageHateList", (void(*)(Mob*, int64))&Perl_Mob_DamageHateList); + package.add("DamageHateList", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateList); + package.add("DamageHateListBots", (void(*)(Mob*, int64))&Perl_Mob_DamageHateListBots); + package.add("DamageHateListBots", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateListBots); + package.add("DamageHateListBotsPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageHateListBotsPercentage); + package.add("DamageHateListBotsPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateListBotsPercentage); + package.add("DamageHateListClients", (void(*)(Mob*, int64))&Perl_Mob_DamageHateListClients); + package.add("DamageHateListClients", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateListClients); + package.add("DamageHateListClientsPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageHateListClientsPercentage); + package.add("DamageHateListClientsPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateListClientsPercentage); + package.add("DamageHateListNPCs", (void(*)(Mob*, int64))&Perl_Mob_DamageHateListNPCs); + package.add("DamageHateListNPCs", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateListNPCs); + package.add("DamageHateListNPCsPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageHateListNPCsPercentage); + package.add("DamageHateListNPCsPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateListNPCsPercentage); + package.add("DamageHateListPercentage", (void(*)(Mob*, int64))&Perl_Mob_DamageHateListPercentage); + package.add("DamageHateListPercentage", (void(*)(Mob*, int64, uint32))&Perl_Mob_DamageHateListPercentage); + package.add("DelGlobal", &Perl_Mob_DelGlobal); + package.add("DeleteBucket", &Perl_Mob_DeleteBucket); + package.add("DeleteEntityVariable", &Perl_Mob_DeleteEntityVariable); + package.add("Depop", (void(*)(Mob*))&Perl_Mob_Depop); + package.add("Depop", (void(*)(Mob*, bool))&Perl_Mob_Depop); + package.add("DivineAura", &Perl_Mob_DivineAura); + package.add("DoAnim", (void(*)(Mob*, int))&Perl_Mob_DoAnim); + package.add("DoAnim", (void(*)(Mob*, int, int))&Perl_Mob_DoAnim); + package.add("DoAnim", (void(*)(Mob*, int, int, bool))&Perl_Mob_DoAnim); + package.add("DoAnim", (void(*)(Mob*, int, int, bool, int))&Perl_Mob_DoAnim); + package.add("DoArcheryAttackDmg", &Perl_Mob_DoArcheryAttackDmg); + package.add("DoKnockback", &Perl_Mob_DoKnockback); + package.add("DoMeleeSkillAttackDmg", &Perl_Mob_DoMeleeSkillAttackDmg); + package.add("DoSpecialAttackDamage", (void(*)(Mob*, Mob*, int, int))&Perl_Mob_DoSpecialAttackDamage); + package.add("DoSpecialAttackDamage", (void(*)(Mob*, Mob*, int, int, int))&Perl_Mob_DoSpecialAttackDamage); + package.add("DoSpecialAttackDamage", (void(*)(Mob*, Mob*, int, int, int, int))&Perl_Mob_DoSpecialAttackDamage); + package.add("DoSpecialAttackDamage", (void(*)(Mob*, Mob*, int, int, int, int, int))&Perl_Mob_DoSpecialAttackDamage); + package.add("DoThrowingAttackDmg", &Perl_Mob_DoThrowingAttackDmg); + package.add("DontBuffMeBefore", &Perl_Mob_DontBuffMeBefore); + package.add("DontDotMeBefore", &Perl_Mob_DontDotMeBefore); + package.add("DontHealMeBefore", &Perl_Mob_DontHealMeBefore); + package.add("DontRootMeBefore", &Perl_Mob_DontRootMeBefore); + package.add("DontSnareMeBefore", &Perl_Mob_DontSnareMeBefore); + package.add("DoubleAggro", &Perl_Mob_DoubleAggro); + package.add("Emote", &Perl_Mob_Emote); + package.add("EntityVariableExists", &Perl_Mob_EntityVariableExists); + package.add("FaceTarget", (void(*)(Mob*))&Perl_Mob_FaceTarget); + package.add("FaceTarget", (void(*)(Mob*, Mob*))&Perl_Mob_FaceTarget); + package.add("FindBuff", &Perl_Mob_FindBuff); + package.add("FindBuffBySlot", &Perl_Mob_FindBuffBySlot); + package.add("FindGroundZ", (float(*)(Mob*, float, float))&Perl_Mob_FindGroundZ); + package.add("FindGroundZ", (float(*)(Mob*, float, float, float))&Perl_Mob_FindGroundZ); + package.add("FindType", (bool(*)(Mob*, uint16_t))&Perl_Mob_FindType); + package.add("FindType", (bool(*)(Mob*, uint16_t, bool))&Perl_Mob_FindType); + package.add("FindType", (bool(*)(Mob*, uint16_t, bool, uint16_t))&Perl_Mob_FindType); + package.add("GMMove", (void(*)(Mob*, float, float, float))&Perl_Mob_GMMove); + package.add("GMMove", (void(*)(Mob*, float, float, float, float))&Perl_Mob_GMMove); + package.add("Gate", &Perl_Mob_Gate); + package.add("GetAA", &Perl_Mob_GetAA); + package.add("GetAAByAAID", &Perl_Mob_GetAAByAAID); + package.add("GetAC", &Perl_Mob_GetAC); + package.add("GetAGI", &Perl_Mob_GetAGI); + package.add("GetATK", &Perl_Mob_GetATK); + package.add("GetActSpellCasttime", &Perl_Mob_GetActSpellCasttime); + package.add("GetActSpellCost", &Perl_Mob_GetActSpellCost); + package.add("GetActSpellDamage", &Perl_Mob_GetActSpellDamage); + package.add("GetActSpellDuration", &Perl_Mob_GetActSpellDuration); + package.add("GetActSpellHealing", &Perl_Mob_GetActSpellHealing); + package.add("GetActSpellRange", &Perl_Mob_GetActSpellRange); + package.add("GetAggroRange", &Perl_Mob_GetAggroRange); + package.add("GetAllowBeneficial", &Perl_Mob_GetAllowBeneficial); + package.add("GetAppearance", &Perl_Mob_GetAppearance); + package.add("GetArmorTint", &Perl_Mob_GetArmorTint); + package.add("GetAssistRange", &Perl_Mob_GetAssistRange); + package.add("GetBaseGender", &Perl_Mob_GetBaseGender); + package.add("GetBaseRace", &Perl_Mob_GetBaseRace); + package.add("GetBaseSize", &Perl_Mob_GetBaseSize); + package.add("GetBeard", &Perl_Mob_GetBeard); + package.add("GetBeardColor", &Perl_Mob_GetBeardColor); + package.add("GetBodyType", &Perl_Mob_GetBodyType); + package.add("GetBucket", &Perl_Mob_GetBucket); + package.add("GetBucketExpires", &Perl_Mob_GetBucketExpires); + package.add("GetBucketKey", &Perl_Mob_GetBucketKey); + package.add("GetBucketRemaining", &Perl_Mob_GetBucketRemaining); + package.add("GetBuffSlotFromType", &Perl_Mob_GetBuffSlotFromType); + package.add("GetBuffStatValueBySpell", &Perl_Mob_GetBuffStatValueBySpell); + package.add("GetBuffStatValueBySlot", &Perl_Mob_GetBuffStatValueBySlot); + package.add("GetCHA", &Perl_Mob_GetCHA); + package.add("GetCR", &Perl_Mob_GetCR); + package.add("GetCasterLevel", &Perl_Mob_GetCasterLevel); + package.add("GetClass", &Perl_Mob_GetClass); + package.add("GetClassLevelFactor", &Perl_Mob_GetClassLevelFactor); + package.add("GetClassName", &Perl_Mob_GetClassName); + package.add("GetCleanName", &Perl_Mob_GetCleanName); + package.add("GetCorruption", &Perl_Mob_GetCorruption); + package.add("GetDEX", &Perl_Mob_GetDEX); + package.add("GetDR", &Perl_Mob_GetDR); + package.add("GetDamageAmount", &Perl_Mob_GetDamageAmount); + package.add("GetDeity", &Perl_Mob_GetDeity); + package.add("GetDisplayAC", &Perl_Mob_GetDisplayAC); + package.add("GetDrakkinDetails", &Perl_Mob_GetDrakkinDetails); + package.add("GetDrakkinHeritage", &Perl_Mob_GetDrakkinHeritage); + package.add("GetDrakkinTattoo", &Perl_Mob_GetDrakkinTattoo); + package.add("GetEntityVariable", &Perl_Mob_GetEntityVariable); + package.add("GetEntityVariables", &Perl_Mob_GetEntityVariables); + package.add("GetEquipment", &Perl_Mob_GetEquipment); + package.add("GetEquipmentColor", &Perl_Mob_GetEquipmentColor); + package.add("GetEquipmentMaterial", &Perl_Mob_GetEquipmentMaterial); + package.add("GetEyeColor1", &Perl_Mob_GetEyeColor1); + package.add("GetEyeColor2", &Perl_Mob_GetEyeColor2); + package.add("GetFR", &Perl_Mob_GetFR); + package.add("GetFlurryChance", &Perl_Mob_GetFlurryChance); + package.add("GetFollowID", &Perl_Mob_GetFollowID); + package.add("GetGender", &Perl_Mob_GetGender); + package.add("GetGlobal", &Perl_Mob_GetGlobal); + package.add("GetHP", &Perl_Mob_GetHP); + package.add("GetHPRatio", &Perl_Mob_GetHPRatio); + package.add("GetHairColor", &Perl_Mob_GetHairColor); + package.add("GetHairStyle", &Perl_Mob_GetHairStyle); + package.add("GetHandToHandDamage", &Perl_Mob_GetHandToHandDamage); + package.add("GetHandToHandDelay", &Perl_Mob_GetHandToHandDelay); + package.add("GetHaste", &Perl_Mob_GetHaste); + package.add("GetHateAmount", (int64_t(*)(Mob*, Mob*))&Perl_Mob_GetHateAmount); + package.add("GetHateAmount", (int64_t(*)(Mob*, Mob*, bool))&Perl_Mob_GetHateAmount); + package.add("GetHateClosest", &Perl_Mob_GetHateClosest); + package.add("GetHateDamageTop", &Perl_Mob_GetHateDamageTop); + package.add("GetHateList", &Perl_Mob_GetHateList); + package.add("GetHateListBots", (perl::array(*)(Mob*))&Perl_Mob_GetHateListBots); + package.add("GetHateListBots", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListBots); + package.add("GetHateListClients", (perl::array(*)(Mob*))&Perl_Mob_GetHateListClients); + package.add("GetHateListClients", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListClients); + package.add("GetHateListNPCs", (perl::array(*)(Mob*))&Perl_Mob_GetHateListNPCs); + package.add("GetHateListNPCs", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListNPCs); + package.add("GetHateListByDistance", (perl::array(*)(Mob*))&Perl_Mob_GetHateListByDistance); + package.add("GetHateListByDistance", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListByDistance); + package.add("GetHateRandom", &Perl_Mob_GetHateRandom); + package.add("GetHateRandomBot", &Perl_Mob_GetHateRandomBot); + package.add("GetHateRandomClient", &Perl_Mob_GetHateRandomClient); + package.add("GetHateRandomNPC", &Perl_Mob_GetHateRandomNPC); + package.add("GetHateTop", &Perl_Mob_GetHateTop); + package.add("GetHeading", &Perl_Mob_GetHeading); + package.add("GetHelmTexture", &Perl_Mob_GetHelmTexture); + package.add("GetHerosForgeModel", &Perl_Mob_GetHerosForgeModel); + package.add("GetID", &Perl_Mob_GetID); + package.add("GetINT", &Perl_Mob_GetINT); + package.add("GetInvisibleLevel", &Perl_Mob_GetInvisibleLevel); + package.add("GetInvisibleUndeadLevel", &Perl_Mob_GetInvisibleUndeadLevel); + package.add("GetInvul", &Perl_Mob_GetInvul); + package.add("GetItemHPBonuses", &Perl_Mob_GetItemHPBonuses); + package.add("GetItemStat", &Perl_Mob_GetItemStat); + package.add("GetLastName", &Perl_Mob_GetLastName); + package.add("GetLevel", &Perl_Mob_GetLevel); + package.add("GetLevelCon", &Perl_Mob_GetLevelCon); + package.add("GetLevelHP", &Perl_Mob_GetLevelHP); + package.add("GetLuclinFace", &Perl_Mob_GetLuclinFace); + package.add("GetMR", &Perl_Mob_GetMR); + package.add("GetMana", &Perl_Mob_GetMana); + package.add("GetManaRatio", &Perl_Mob_GetManaRatio); + package.add("GetMaxAGI", &Perl_Mob_GetMaxAGI); + package.add("GetMaxCHA", &Perl_Mob_GetMaxCHA); + package.add("GetMaxDEX", &Perl_Mob_GetMaxDEX); + package.add("GetMaxHP", &Perl_Mob_GetMaxHP); + package.add("GetMaxINT", &Perl_Mob_GetMaxINT); + package.add("GetMaxMana", &Perl_Mob_GetMaxMana); + package.add("GetMaxSTA", &Perl_Mob_GetMaxSTA); + package.add("GetMaxSTR", &Perl_Mob_GetMaxSTR); + package.add("GetMaxWIS", &Perl_Mob_GetMaxWIS); + package.add("GetMeleeMitigation", &Perl_Mob_GetMeleeMitigation); + package.add("GetModSkillDmgTaken", &Perl_Mob_GetModSkillDmgTaken); + package.add("GetModVulnerability", &Perl_Mob_GetModVulnerability); + package.add("GetNPCTypeID", &Perl_Mob_GetNPCTypeID); + package.add("GetName", &Perl_Mob_GetName); + package.add("GetNimbusEffect1", &Perl_Mob_GetNimbusEffect1); + package.add("GetNimbusEffect2", &Perl_Mob_GetNimbusEffect2); + package.add("GetNimbusEffect3", &Perl_Mob_GetNimbusEffect3); + package.add("GetOwner", &Perl_Mob_GetOwner); + package.add("GetOwnerID", &Perl_Mob_GetOwnerID); + package.add("GetPR", &Perl_Mob_GetPR); + package.add("GetPetID", &Perl_Mob_GetPetID); + package.add("GetPetOrder", &Perl_Mob_GetPetOrder); + package.add("GetPetType", &Perl_Mob_GetPetType); + package.add("GetPhR", &Perl_Mob_GetPhR); + package.add("GetRace", &Perl_Mob_GetRace); + package.add("GetRaceName", &Perl_Mob_GetRaceName); + package.add("GetResist", &Perl_Mob_GetResist); + package.add("GetReverseFactionCon", &Perl_Mob_GetReverseFactionCon); + package.add("GetRunAnimSpeed", &Perl_Mob_GetRunAnimSpeed); + package.add("GetRunspeed", &Perl_Mob_GetRunspeed); + package.add("GetSTA", &Perl_Mob_GetSTA); + package.add("GetSTR", &Perl_Mob_GetSTR); + package.add("GetSize", &Perl_Mob_GetSize); + package.add("GetSkill", &Perl_Mob_GetSkill); + package.add("GetSkillDmgAmt", &Perl_Mob_GetSkillDmgAmt); + package.add("GetSkillDmgTaken", &Perl_Mob_GetSkillDmgTaken); + package.add("GetSpecialAbility", &Perl_Mob_GetSpecialAbility); + package.add("GetSpecialAbilityParam", &Perl_Mob_GetSpecialAbilityParam); + package.add("GetSpecializeSkillValue", &Perl_Mob_GetSpecializeSkillValue); + package.add("GetSpellHPBonuses", &Perl_Mob_GetSpellHPBonuses); + package.add("GetSpellIDFromSlot", &Perl_Mob_GetSpellIDFromSlot); + package.add("GetSpellStat", (int(*)(Mob*, uint32, const char*))&Perl_Mob_GetSpellStat); + package.add("GetSpellStat", (int(*)(Mob*, uint32, const char*, uint8))&Perl_Mob_GetSpellStat); + package.add("GetTarget", &Perl_Mob_GetTarget); + package.add("GetTexture", &Perl_Mob_GetTexture); + package.add("GetUltimateOwner", &Perl_Mob_GetUltimateOwner); + package.add("GetWIS", &Perl_Mob_GetWIS); + package.add("GetWalkspeed", &Perl_Mob_GetWalkspeed); + package.add("GetWaypointH", &Perl_Mob_GetWaypointH); + package.add("GetWaypointID", &Perl_Mob_GetWaypointID); + package.add("GetWaypointPause", &Perl_Mob_GetWaypointPause); + package.add("GetWaypointX", &Perl_Mob_GetWaypointX); + package.add("GetWaypointY", &Perl_Mob_GetWaypointY); + package.add("GetWaypointZ", &Perl_Mob_GetWaypointZ); + package.add("GetX", &Perl_Mob_GetX); + package.add("GetY", &Perl_Mob_GetY); + package.add("GetZ", &Perl_Mob_GetZ); + package.add("GetZoneID", &Perl_Mob_GetZoneID); + package.add("GoToBind", &Perl_Mob_GoToBind); + package.add("HalveAggro", &Perl_Mob_HalveAggro); + package.add("HasNPCSpecialAtk", &Perl_Mob_HasNPCSpecialAtk); + package.add("HasOwner", &Perl_Mob_HasOwner); + package.add("HasPet", &Perl_Mob_HasPet); + package.add("HasProcs", &Perl_Mob_HasProcs); + package.add("HasShieldEquiped", &Perl_Mob_HasShieldEquiped); + package.add("HasTwoHandBluntEquiped", &Perl_Mob_HasTwoHandBluntEquiped); + package.add("HasTwoHanderEquipped", &Perl_Mob_HasTwoHanderEquipped); + package.add("HateSummon", &Perl_Mob_HateSummon); + package.add("Heal", &Perl_Mob_Heal); + package.add("HealDamage", (void(*)(Mob*, int64_t))&Perl_Mob_HealDamage); + package.add("HealDamage", (void(*)(Mob*, int64_t, Mob*))&Perl_Mob_HealDamage); + package.add("InterruptSpell", (void(*)(Mob*))&Perl_Mob_InterruptSpell); + package.add("InterruptSpell", (void(*)(Mob*, uint16))&Perl_Mob_InterruptSpell); + package.add("IsAIControlled", &Perl_Mob_IsAIControlled); + package.add("IsAmnesiad", &Perl_Mob_IsAmnesiad); + package.add("IsAttackAllowed", (bool(*)(Mob*, Mob*))&Perl_Mob_IsAttackAllowed); + package.add("IsAttackAllowed", (bool(*)(Mob*, Mob*, bool))&Perl_Mob_IsAttackAllowed); + package.add("IsBeacon", &Perl_Mob_IsBeacon); + package.add("IsBeneficialAllowed", &Perl_Mob_IsBeneficialAllowed); + package.add("IsBlind", &Perl_Mob_IsBlind); + package.add("IsBot", &Perl_Mob_IsBot); + package.add("IsCasting", &Perl_Mob_IsCasting); + package.add("IsClient", &Perl_Mob_IsClient); + package.add("IsCorpse", &Perl_Mob_IsCorpse); + package.add("IsDoor", &Perl_Mob_IsDoor); + package.add("IsEliteMaterialItem", &Perl_Mob_IsEliteMaterialItem); + package.add("IsEngaged", &Perl_Mob_IsEngaged); + package.add("IsEnraged", &Perl_Mob_IsEnraged); + package.add("IsFeared", &Perl_Mob_IsFeared); + package.add("IsHorse", &Perl_Mob_IsHorse); + package.add("IsImmuneToSpell", &Perl_Mob_IsImmuneToSpell); + package.add("IsInvisible", (bool(*)(Mob*))&Perl_Mob_IsInvisible); + package.add("IsInvisible", (bool(*)(Mob*, Mob*))&Perl_Mob_IsInvisible); + package.add("IsMeleeDisabled", &Perl_Mob_IsMeleeDisabled); + package.add("IsMezzed", &Perl_Mob_IsMezzed); + package.add("IsMob", &Perl_Mob_IsMob); + package.add("IsMoving", &Perl_Mob_IsMoving); + package.add("IsNPC", &Perl_Mob_IsNPC); + package.add("IsNPCCorpse", &Perl_Mob_IsNPCCorpse); + package.add("IsObject", &Perl_Mob_IsObject); + package.add("IsPet", &Perl_Mob_IsPet); + package.add("IsPlayerCorpse", &Perl_Mob_IsPlayerCorpse); + package.add("IsRoamer", &Perl_Mob_IsRoamer); + package.add("IsRooted", &Perl_Mob_IsRooted); + package.add("IsRunning", &Perl_Mob_IsRunning); + package.add("IsSilenced", &Perl_Mob_IsSilenced); + package.add("IsStunned", &Perl_Mob_IsStunned); + package.add("IsTargetable", &Perl_Mob_IsTargetable); + package.add("IsTargeted", &Perl_Mob_IsTargeted); + package.add("IsTrap", &Perl_Mob_IsTrap); + package.add("IsWarriorClass", &Perl_Mob_IsWarriorClass); + package.add("Kill", &Perl_Mob_Kill); + package.add("MakePet", (void(*)(Mob*, uint16, const char*))&Perl_Mob_MakePet); + package.add("MakePet", (void(*)(Mob*, uint16, const char*, const char*))&Perl_Mob_MakePet); + package.add("MakeTempPet", (void(*)(Mob*, uint16))&Perl_Mob_MakeTempPet); + package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*))&Perl_Mob_MakeTempPet); + package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32))&Perl_Mob_MakeTempPet); + package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32, Mob*))&Perl_Mob_MakeTempPet); + package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32, Mob*, bool))&Perl_Mob_MakeTempPet); + package.add("Mesmerize", &Perl_Mob_Mesmerize); + package.add("Message", &Perl_Mob_Message); + package.add("Message_StringID", (void(*)(Mob*, uint32, uint32))&Perl_Mob_Message_StringID); + package.add("Message_StringID", (void(*)(Mob*, uint32, uint32, uint32))&Perl_Mob_Message_StringID); + package.add("ModSkillDmgTaken", &Perl_Mob_ModSkillDmgTaken); + package.add("ModVulnerability", &Perl_Mob_ModVulnerability); + package.add("NPCSpecialAttacks", (void(*)(Mob*, const char*, int))&Perl_Mob_NPCSpecialAttacks); + package.add("NPCSpecialAttacks", (void(*)(Mob*, const char*, int, bool))&Perl_Mob_NPCSpecialAttacks); + package.add("NPCSpecialAttacks", (void(*)(Mob*, const char*, int, bool, bool))&Perl_Mob_NPCSpecialAttacks); + package.add("NavigateTo", &Perl_Mob_NavigateTo); + package.add("ProcessSpecialAbilities", &Perl_Mob_ProcessSpecialAbilities); + package.add("ProjectileAnim", (void(*)(Mob*, Mob*, int))&Perl_Mob_ProjectileAnim); + package.add("ProjectileAnim", (void(*)(Mob*, Mob*, int, bool))&Perl_Mob_ProjectileAnim); + package.add("ProjectileAnim", (void(*)(Mob*, Mob*, int, bool, float))&Perl_Mob_ProjectileAnim); + package.add("ProjectileAnim", (void(*)(Mob*, Mob*, int, bool, float, float))&Perl_Mob_ProjectileAnim); + package.add("ProjectileAnim", (void(*)(Mob*, Mob*, int, bool, float, float, float))&Perl_Mob_ProjectileAnim); + package.add("ProjectileAnim", (void(*)(Mob*, Mob*, int, bool, float, float, float, float))&Perl_Mob_ProjectileAnim); + package.add("ProjectileAnim", (void(*)(Mob*, Mob*, int, bool, float, float, float, float, const char*))&Perl_Mob_ProjectileAnim); + package.add("RandomizeFeatures", (bool(*)(Mob*))&Perl_Mob_RandomizeFeatures); + package.add("RandomizeFeatures", (bool(*)(Mob*, bool))&Perl_Mob_RandomizeFeatures); + package.add("RandomizeFeatures", (bool(*)(Mob*, bool, bool))&Perl_Mob_RandomizeFeatures); + package.add("RangedAttack", &Perl_Mob_RangedAttack); + package.add("RemoveAllAppearanceEffects", &Perl_Mob_RemoveAllAppearanceEffects); + package.add("RemoveAllNimbusEffects", &Perl_Mob_RemoveAllNimbusEffects); + package.add("RemoveFromFeignMemory", &Perl_Mob_RemoveFromFeignMemory); + package.add("RemoveNimbusEffect", &Perl_Mob_RemoveNimbusEffect); + package.add("RemovePet", &Perl_Mob_RemovePet); + package.add("ResistSpell", &Perl_Mob_ResistSpell); + package.add("RogueAssassinate", &Perl_Mob_RogueAssassinate); + package.add("RunTo", &Perl_Mob_RunTo); + package.add("Say", &Perl_Mob_Say); + package.add("SeeHide", &Perl_Mob_SeeHide); + package.add("SeeImprovedHide", &Perl_Mob_SeeImprovedHide); + package.add("SeeInvisible", &Perl_Mob_SeeInvisible); + package.add("SeeInvisibleUndead", &Perl_Mob_SeeInvisibleUndead); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffect", (void(*)(Mob*, int32, int32, int32, int32, int32, perl::nullable, uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Mob_SendAppearanceEffect); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32, int32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32, int32, uint32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32, int32, uint32, int32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32, int32, uint32, int32, uint32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32, int32, uint32, int32, uint32, int32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32, int32, uint32, int32, uint32, int32, uint32))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectActor", (void(*)(Mob*, int32, uint32, int32, uint32, int32, uint32, int32, uint32, int32, uint32, Client*))&Perl_Mob_SendAppearanceEffectActor); + package.add("SendAppearanceEffectGround", (void(*)(Mob*, int32))&Perl_Mob_SendAppearanceEffectGround); + package.add("SendAppearanceEffectGround", (void(*)(Mob*, int32, int32))&Perl_Mob_SendAppearanceEffectGround); + package.add("SendAppearanceEffectGround", (void(*)(Mob*, int32, int32, int32))&Perl_Mob_SendAppearanceEffectGround); + package.add("SendAppearanceEffectGround", (void(*)(Mob*, int32, int32, int32, int32))&Perl_Mob_SendAppearanceEffectGround); + package.add("SendAppearanceEffectGround", (void(*)(Mob*, int32, int32, int32, int32, int32))&Perl_Mob_SendAppearanceEffectGround); + package.add("SendAppearanceEffectGround", (void(*)(Mob*, int32, int32, int32, int32, int32, Client*))&Perl_Mob_SendAppearanceEffectGround); + package.add("SendIllusion", (void(*)(Mob*, uint16))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32, uint32))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32, uint32, uint32))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32, uint32, uint32, float))&Perl_Mob_SendIllusion); + package.add("SendTo", &Perl_Mob_SendTo); + package.add("SendToFixZ", &Perl_Mob_SendToFixZ); + package.add("SendWearChange", &Perl_Mob_SendWearChange); + package.add("SetAA", (bool(*)(Mob*, int, int))&Perl_Mob_SetAA); + package.add("SetAA", (bool(*)(Mob*, int, int, int))&Perl_Mob_SetAA); + package.add("SetAllowBeneficial", &Perl_Mob_SetAllowBeneficial); + package.add("SetAppearance", (void(*)(Mob*, int))&Perl_Mob_SetAppearance); + package.add("SetAppearance", (void(*)(Mob*, int, bool))&Perl_Mob_SetAppearance); + package.add("SetBodyType", (void(*)(Mob*, int32))&Perl_Mob_SetBodyType); + package.add("SetBodyType", (void(*)(Mob*, int32, bool))&Perl_Mob_SetBodyType); + package.add("SetBucket", (void(*)(Mob*, std::string, std::string))&Perl_Mob_SetBucket); + package.add("SetBucket", (void(*)(Mob*, std::string, std::string, std::string))&Perl_Mob_SetBucket); + package.add("SetBuffDuration", (void(*)(Mob*, int))&Perl_Mob_SetBuffDuration); + package.add("SetBuffDuration", (void(*)(Mob*, int, int))&Perl_Mob_SetBuffDuration); + package.add("SetCurrentWP", &Perl_Mob_SetCurrentWP); + package.add("SetDeltas", &Perl_Mob_SetDeltas); + package.add("SetDisableMelee", &Perl_Mob_SetDisableMelee); + package.add("SetEntityVariable", &Perl_Mob_SetEntityVariable); + package.add("SetExtraHaste", &Perl_Mob_SetExtraHaste); + package.add("SetFlurryChance", &Perl_Mob_SetFlurryChance); + package.add("SetFlyMode", &Perl_Mob_SetFlyMode); + package.add("SetFollowID", &Perl_Mob_SetFollowID); + package.add("SetGender", &Perl_Mob_SetGender); + package.add("SetGlobal", (void(*)(Mob*, const char*, const char*, int, const char*))&Perl_Mob_SetGlobal); + package.add("SetGlobal", (void(*)(Mob*, const char*, const char*, int, const char*, Mob*))&Perl_Mob_SetGlobal); + package.add("SetHP", &Perl_Mob_SetHP); + package.add("SetHate", (void(*)(Mob*, Mob*))&Perl_Mob_SetHate); + package.add("SetHate", (void(*)(Mob*, Mob*, int64_t))&Perl_Mob_SetHate); + package.add("SetHate", (void(*)(Mob*, Mob*, int64_t, int64_t))&Perl_Mob_SetHate); + package.add("SetHeading", &Perl_Mob_SetHeading); + package.add("SetInvisible", &Perl_Mob_SetInvisible); + package.add("SetInvul", &Perl_Mob_SetInvul); + package.add("SetLD", &Perl_Mob_SetLD); + package.add("SetLevel", (void(*)(Mob*, uint8_t))&Perl_Mob_SetLevel); + package.add("SetLevel", (void(*)(Mob*, uint8_t, bool))&Perl_Mob_SetLevel); + package.add("SetMana", &Perl_Mob_SetMana); + package.add("SetMaxHP", &Perl_Mob_SetMaxHP); + package.add("SetOOCRegen", &Perl_Mob_SetOOCRegen); + package.add("SetOwnerID", &Perl_Mob_SetOwnerID); + package.add("SetPet", &Perl_Mob_SetPet); + package.add("SetPetID", &Perl_Mob_SetPetID); + package.add("SetPetOrder", &Perl_Mob_SetPetOrder); + package.add("SetRace", &Perl_Mob_SetRace); + package.add("SetRunAnimSpeed", &Perl_Mob_SetRunAnimSpeed); + package.add("SetRunning", &Perl_Mob_SetRunning); + package.add("SetSeeInvisibleLevel", &Perl_Mob_SetSeeInvisibleLevel); + package.add("SetSeeInvisibleUndeadLevel", &Perl_Mob_SetSeeInvisibleUndeadLevel); + package.add("SetSlotTint", &Perl_Mob_SetSlotTint); + package.add("SetSpecialAbility", &Perl_Mob_SetSpecialAbility); + package.add("SetSpecialAbilityParam", &Perl_Mob_SetSpecialAbilityParam); + package.add("SetTarget", &Perl_Mob_SetTarget); + package.add("SetTargetable", &Perl_Mob_SetTargetable); + package.add("SetTexture", &Perl_Mob_SetTexture); + package.add("ShieldAbility", (void(*)(Mob*, uint32))&Perl_Mob_ShieldAbility); + package.add("ShieldAbility", (void(*)(Mob*, uint32, int32))&Perl_Mob_ShieldAbility); + package.add("ShieldAbility", (void(*)(Mob*, uint32, int32, int32))&Perl_Mob_ShieldAbility); + package.add("ShieldAbility", (void(*)(Mob*, uint32, int32, int32, int32))&Perl_Mob_ShieldAbility); + package.add("ShieldAbility", (void(*)(Mob*, uint32, int32, int32, int32, int32))&Perl_Mob_ShieldAbility); + package.add("ShieldAbility", (void(*)(Mob*, uint32, int32, int32, int32, int32, bool))&Perl_Mob_ShieldAbility); + package.add("ShieldAbility", (void(*)(Mob*, uint32, int32, int32, int32, int32, bool, bool))&Perl_Mob_ShieldAbility); + package.add("Shout", &Perl_Mob_Shout); + package.add("SignalClient", &Perl_Mob_SignalClient); + package.add("SpellEffect", (void(*)(Mob*, uint32))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32, uint32))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32, uint32, bool))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32, uint32, bool, uint32))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32, uint32, bool, uint32, bool))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32, uint32, bool, uint32, bool, Client*))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32, uint32, bool, uint32, bool, perl::nullable, uint32))&Perl_Mob_SpellEffect); + package.add("SpellEffect", (void(*)(Mob*, uint32, uint32, uint32, bool, uint32, bool, perl::nullable, uint32, uint32))&Perl_Mob_SpellEffect); + package.add("SpellFinished", (void(*)(Mob*, uint16))&Perl_Mob_SpellFinished); + package.add("SpellFinished", (void(*)(Mob*, uint16, Mob*))&Perl_Mob_SpellFinished); + package.add("SpellFinished", (void(*)(Mob*, uint16, Mob*, int32))&Perl_Mob_SpellFinished); + package.add("SpellFinished", (void(*)(Mob*, uint16, Mob*, int32, uint16))&Perl_Mob_SpellFinished); + package.add("Spin", &Perl_Mob_Spin); + package.add("StartEnrage", &Perl_Mob_StartEnrage); + package.add("StopNavigation", &Perl_Mob_StopNavigation); + package.add("Stun", &Perl_Mob_Stun); + package.add("TarGlobal", &Perl_Mob_TarGlobal); + package.add("TempName", (void(*)(Mob*))&Perl_Mob_TempName); + package.add("TempName", (void(*)(Mob*, const char*))&Perl_Mob_TempName); + package.add("ThrowingAttack", &Perl_Mob_ThrowingAttack); + package.add("TryMoveAlong", (void(*)(Mob*, float, float))&Perl_Mob_TryMoveAlong); + package.add("TryMoveAlong", (void(*)(Mob*, float, float, bool))&Perl_Mob_TryMoveAlong); + package.add("TypesTempPet", (void(*)(Mob*, uint32))&Perl_Mob_TypesTempPet); + package.add("TypesTempPet", (void(*)(Mob*, uint32, const char*))&Perl_Mob_TypesTempPet); + package.add("TypesTempPet", (void(*)(Mob*, uint32, const char*, uint32))&Perl_Mob_TypesTempPet); + package.add("TypesTempPet", (void(*)(Mob*, uint32, const char*, uint32, bool))&Perl_Mob_TypesTempPet); + package.add("TypesTempPet", (void(*)(Mob*, uint32, const char*, uint32, bool, Mob*))&Perl_Mob_TypesTempPet); + package.add("TypesTempPet", (void(*)(Mob*, uint32, const char*, uint32, bool, Mob*, bool))&Perl_Mob_TypesTempPet); + package.add("WalkTo", &Perl_Mob_WalkTo); + package.add("WearChange", (void(*)(Mob*, uint8, uint16))&Perl_Mob_WearChange); + package.add("WearChange", (void(*)(Mob*, uint8, uint16, uint32))&Perl_Mob_WearChange); + package.add("WearChange", (void(*)(Mob*, uint8, uint16, uint32, uint32))&Perl_Mob_WearChange); + package.add("WipeHateList", &Perl_Mob_WipeHateList); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 78a9f7402..a5fc52d12 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -4,2046 +4,833 @@ #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - -typedef const char Const_char; - #include "npc.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_NPC \ - do { \ - if (sv_derived_from(ST(0), "NPC")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(NPC*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type NPC"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_NPC_SignalNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SignalNPC) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SignalNPC(THIS, int signal_id)"); // @categories Script Utility - { - NPC *THIS; - int _signal_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SignalNPC(_signal_id); - } - XSRETURN_EMPTY; +void Perl_NPC_SignalNPC(NPC* self, int signal_id) // @categories Script Utility +{ + self->SignalNPC(signal_id); } -XS(XS_NPC_CheckNPCFactionAlly); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CheckNPCFactionAlly) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::CheckNPCFactionAlly(THIS, int32 faction_id)"); // @categories Faction - { - NPC *THIS; - FACTION_VALUE RETVAL; - dXSTARG; - int32 other_faction = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->CheckNPCFactionAlly(other_faction); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +int Perl_NPC_CheckNPCFactionAlly(NPC* self, int32 faction_id) // @categories Faction +{ + return self->CheckNPCFactionAlly(faction_id); } -XS(XS_NPC_AddItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddItem) { - dXSARGS; - if (items < 2 || items > 10) - Perl_croak(aTHX_ "Usage: NPC::AddItem(THIS, uint32 item_id, [uint16 charges = 0], [bool equip_item = true], [uint32 aug1 = 0], [uint32 aug2 = 0], [uint32 aug3 = 0], [uint32 aug4 = 0], [uint32 aug5 = 0], [uint32 aug6 = 0])"); // @categories Inventory and Items - { - NPC *THIS; - uint32 itemid = (uint32) SvUV(ST(1)); - uint16 charges = 0; - bool equipitem = true; - uint32 aug1 = 0; - uint32 aug2 = 0; - uint32 aug3 = 0; - uint32 aug4 = 0; - uint32 aug5 = 0; - uint32 aug6 = 0; - VALIDATE_THIS_IS_NPC; - if (items > 2) - charges = (uint16) SvUV(ST(2)); - if (items > 3) - equipitem = (bool) SvTRUE(ST(3)); - if (items > 4) - aug1 = (uint32) SvUV(ST(4)); - if (items > 5) - aug2 = (uint32) SvUV(ST(5)); - if (items > 6) - aug3 = (uint32) SvUV(ST(6)); - if (items > 7) - aug4 = (uint32) SvUV(ST(7)); - if (items > 8) - aug5 = (uint32) SvUV(ST(8)); - if (items > 9) - aug6 = (uint32) SvUV(ST(9)); - - THIS->AddItem(itemid, charges, equipitem, aug1, aug2, aug3, aug4, aug5, aug6); - } - XSRETURN_EMPTY; +void Perl_NPC_AddItem(NPC* self, uint32 item_id) // @categories Inventory and Items +{ + self->AddItem(item_id, 0); } -XS(XS_NPC_AddLootTable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddLootTable) { - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: NPC::AddLootTable(THIS, [uint32 loottable_id])"); // @categories Inventory and Items - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - uint32 loottable_id = 0; - - if (items > 1) { - loottable_id = (uint32) SvUV(ST(1)); - THIS->AddLootTable(loottable_id); - } else { - THIS->AddLootTable(); - } - } - XSRETURN_EMPTY; +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges) // @categories Inventory and Items +{ + self->AddItem(item_id, charges); } -XS(XS_NPC_RemoveItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveItem) { - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: NPC::RemoveItem(THIS, uint32 item_id, [uint16 quantity = 0], [uint16 slot_id = 0])"); // @categories Inventory and Items - { - NPC *THIS; - uint32 item_id = (uint32) SvUV(ST(1)); - uint16 quantity; - uint16 slot; - VALIDATE_THIS_IS_NPC; - if (items < 3) - quantity = 0; - else { - quantity = (uint16) SvUV(ST(2)); - } - - if (items < 4) - slot = 0; - else { - slot = (uint16) SvUV(ST(3)); - } - - THIS->RemoveItem(item_id, quantity, slot); - } - XSRETURN_EMPTY; +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges, bool equip_item) // @categories Inventory and Items +{ + self->AddItem(item_id, charges, equip_item); } -XS(XS_NPC_ClearItemList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ClearItemList) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::ClearItemList(THIS)"); // @categories Inventory and Items - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->ClearItemList(); - } - XSRETURN_EMPTY; +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges, bool equip_item, uint32 aug1) // @categories Inventory and Items +{ + self->AddItem(item_id, charges, equip_item, aug1); } -XS(XS_NPC_AddCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddCash) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: NPC::AddCash(THIS, uint16 copper, uint16 silver, uint16 gold, uint16 platinum)"); // @categories Currency and Points - { - NPC *THIS; - uint16 in_copper = (uint16) SvUV(ST(1)); - uint16 in_silver = (uint16) SvUV(ST(2)); - uint16 in_gold = (uint16) SvUV(ST(3)); - uint16 in_platinum = (uint16) SvUV(ST(4)); - VALIDATE_THIS_IS_NPC; - THIS->AddCash(in_copper, in_silver, in_gold, in_platinum); - } - XSRETURN_EMPTY; +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges, bool equip_item, uint32 aug1, uint32 aug2) // @categories Inventory and Items +{ + self->AddItem(item_id, charges, equip_item, aug1, aug2); } -XS(XS_NPC_RemoveCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveCash) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::RemoveCash(THIS)"); // @categories Currency and Points - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->RemoveCash(); - } - XSRETURN_EMPTY; +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges, bool equip_item, uint32 aug1, uint32 aug2, uint32 aug3) // @categories Inventory and Items +{ + self->AddItem(item_id, charges, equip_item, aug1, aug2, aug3); } -XS(XS_NPC_CountLoot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CountLoot) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::CountLoot(THIS)"); // @categories Inventory and Items - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->CountLoot(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges, bool equip_item, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4) // @categories Inventory and Items +{ + self->AddItem(item_id, charges, equip_item, aug1, aug2, aug3, aug4); } -XS(XS_NPC_GetLoottableID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetLoottableID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetLoottableID(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetLoottableID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges, bool equip_item, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) // @categories Inventory and Items +{ + self->AddItem(item_id, charges, equip_item, aug1, aug2, aug3, aug4, aug5); } -XS(XS_NPC_GetCopper); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetCopper) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetCopper(THIS)"); // @categories Currency and Points - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetCopper(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AddItem(NPC* self, uint32 item_id, uint16 charges, bool equip_item, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6) // @categories Inventory and Items +{ + self->AddItem(item_id, charges, equip_item, aug1, aug2, aug3, aug4, aug5, aug6); } -XS(XS_NPC_GetSilver); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSilver) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSilver(THIS)"); // @categories Currency and Points - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSilver(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AddLootTable(NPC* self) // @categories Inventory and Items +{ + self->AddLootTable(); } -XS(XS_NPC_GetGold); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGold) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGold(THIS)"); // @categories Currency and Points - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetGold(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AddLootTable(NPC* self, uint32 loottable_id) // @categories Inventory and Items +{ + self->AddLootTable(loottable_id); } -XS(XS_NPC_GetPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPlatinum) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPlatinum(THIS)"); // @categories Currency and Points - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetPlatinum(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_RemoveItem(NPC* self, uint32 item_id) // @categories Inventory and Items +{ + self->RemoveItem(item_id); } -XS(XS_NPC_SetCopper); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetCopper) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetCopper(THIS, uint32 copper_amount)"); // @categories Currency and Points - { - NPC *THIS; - uint32 amt = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetCopper(amt); - } - XSRETURN_EMPTY; +void Perl_NPC_RemoveItem(NPC* self, uint32 item_id, uint16 quantity) // @categories Inventory and Items +{ + self->RemoveItem(item_id, quantity); } -XS(XS_NPC_SetSilver); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSilver) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSilver(THIS, uint32 silver_amount)"); // @categories Currency and Points - { - NPC *THIS; - uint32 amt = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetSilver(amt); - } - XSRETURN_EMPTY; +void Perl_NPC_RemoveItem(NPC* self, uint32 item_id, uint16 quantity, uint16 slot_id) // @categories Inventory and Items +{ + self->RemoveItem(item_id, quantity, slot_id); } -XS(XS_NPC_SetGold); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetGold) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetGold(THIS, uint32 gold_amount)"); // @categories Currency and Points - { - NPC *THIS; - uint32 amt = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetGold(amt); - } - XSRETURN_EMPTY; +void Perl_NPC_ClearItemList(NPC* self) // @categories Inventory and Items +{ + self->ClearItemList(); } -XS(XS_NPC_SetPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPlatinum) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPlatinum(THIS, uint32 platinum_amount)"); // @categories Currency and Points - { - NPC *THIS; - uint32 amt = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetPlatinum(amt); - } - XSRETURN_EMPTY; +void Perl_NPC_AddCash(NPC* self, uint16 copper, uint16 silver, uint16 gold, uint16 platinum) // @categories Currency and Points +{ + self->AddCash(copper, silver, gold, platinum); } -XS(XS_NPC_SetGrid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetGrid) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetGrid(THIS, int32 grid_id)"); // @categories Script Utility - { - NPC *THIS; - int32 grid_ = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetGrid(grid_); - } - XSRETURN_EMPTY; +void Perl_NPC_RemoveCash(NPC* self) // @categories Currency and Points +{ + self->RemoveCash(); } -XS(XS_NPC_SetSaveWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSaveWaypoint) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSaveWaypoint(THIS, uint16 waypoint)"); // @categories Script Utility - { - NPC *THIS; - uint16 waypoint = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetSaveWaypoint(waypoint); - } - XSRETURN_EMPTY; +uint32_t Perl_NPC_CountLoot(NPC* self) // @categories Inventory and Items +{ + return self->CountLoot(); } -XS(XS_NPC_SetSp2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSp2) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSp2(THIS, uint32 set_spawn_group_id)"); // @categories Spawns - { - NPC *THIS; - uint32 sg2 = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetSpawnGroupId(sg2); - } - XSRETURN_EMPTY; +uint32_t Perl_NPC_GetLoottableID(NPC* self) // @categories Stats and Attributes +{ + return self->GetLoottableID(); } -XS(XS_NPC_GetWaypointMax); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetWaypointMax) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetWaypointMax(THIS)"); // @categories Script Utility - { - NPC *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetWaypointMax(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetCopper(NPC* self) // @categories Currency and Points +{ + return self->GetCopper(); } -XS(XS_NPC_GetGrid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGrid) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGrid(THIS)"); // @categories Script Utility, Spawns - { - NPC *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetGrid(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetSilver(NPC* self) // @categories Currency and Points +{ + return self->GetSilver(); } -XS(XS_NPC_GetSp2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSp2) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSp2(THIS)"); // @categories Spawns - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpawnGroupId(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetGold(NPC* self) // @categories Currency and Points +{ + return self->GetGold(); } -XS(XS_NPC_GetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCFactionID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetNPCFactionID(THIS)"); // @categories Faction, Stats and Attributes - { - NPC *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetNPCFactionID(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetPlatinum(NPC* self) // @categories Currency and Points +{ + return self->GetPlatinum(); } -XS(XS_NPC_GetPrimaryFaction); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPrimaryFaction) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPrimaryFaction(THIS)"); // @categories Faction, Stats and Attributes - { - NPC *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetPrimaryFaction(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_SetCopper(NPC* self, uint32 amt) // @categories Currency and Points +{ + self->SetCopper(amt); } -XS(XS_NPC_GetNPCHate); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCHate) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetNPCHate(THIS, Mob* entity)"); // @categories Hate and Aggro - { - NPC *THIS; - int64 RETVAL; - dXSTARG; - Mob *in_ent; - VALIDATE_THIS_IS_NPC; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - in_ent = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "in_ent is not of type Mob"); - if (in_ent == nullptr) - Perl_croak(aTHX_ "in_ent is nullptr, avoiding crash."); - - RETVAL = THIS->GetNPCHate(in_ent); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_SetSilver(NPC* self, uint32 amt) // @categories Currency and Points +{ + self->SetSilver(amt); } -XS(XS_NPC_IsOnHatelist); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsOnHatelist) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::IsOnHatelist(THIS, Mob* target)"); // @categories Hate and Aggro - { - NPC *THIS; - bool RETVAL; - Mob *p; - VALIDATE_THIS_IS_NPC; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - p = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "p is not of type Mob"); - if (p == nullptr) - Perl_croak(aTHX_ "p is nullptr, avoiding crash."); - - RETVAL = THIS->IsOnHatelist(p); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_NPC_SetGold(NPC* self, uint32 amt) // @categories Currency and Points +{ + self->SetGold(amt); } -XS(XS_NPC_RemoveFromHateList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveFromHateList) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveFromHateList(THIS, Mob* target)"); // @categories Hate and Aggro - { - NPC *THIS; - Mob *ent; - VALIDATE_THIS_IS_NPC; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - ent = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "ent is not of type Mob"); - if (ent == nullptr) - Perl_croak(aTHX_ "ent is nullptr, avoiding crash."); - - THIS->RemoveFromHateList(ent); +void Perl_NPC_SetPlatinum(NPC* self, uint32 amt) // @categories Currency and Points +{ + self->SetPlatinum(amt); +} - } - XSRETURN_EMPTY; +void Perl_NPC_SetGrid(NPC* self, int grid) // @categories Script Utility +{ + self->SetGrid(grid); } +void Perl_NPC_SetSaveWaypoint(NPC* self, uint16 wp) // @categories Script Utility +{ + self->SetSaveWaypoint(wp); +} -XS(XS_NPC_SetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetNPCFactionID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetNPCFactionID(THIS, int32 faction_id)"); // @categories Faction - { - NPC *THIS; - int32 in = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetNPCFactionID(in); - } - XSRETURN_EMPTY; +void Perl_NPC_SetSp2(NPC* self, uint32 set_spawn_group_id) // @categories Spawns +{ + self->SetSpawnGroupId(set_spawn_group_id); } -XS(XS_NPC_GetMaxDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxDMG) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMaxDMG(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetMaxDMG(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_NPC_GetWaypointMax(NPC* self) // @categories Script Utility +{ + return self->GetWaypointMax(); } -XS(XS_NPC_GetMinDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMinDMG) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMinDMG(THIS)"); - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetMinDMG(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_NPC_GetGrid(NPC* self) // @categories Script Utility, Spawns +{ + return self->GetGrid(); } +uint32_t Perl_NPC_GetSp2(NPC* self) // @categories Spawns +{ + return self->GetSpawnGroupId(); +} -XS(XS_NPC_IsAnimal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsAnimal) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsAnimal(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - bool RETVAL; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->IsAnimal(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +int Perl_NPC_GetNPCFactionID(NPC* self) // @categories Faction, Stats and Attributes +{ + return self->GetNPCFactionID(); } -XS(XS_NPC_GetPetSpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPetSpellID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPetSpellID(THIS)"); // @categories Stats and Attributes, Pet - { - NPC *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetPetSpellID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_NPC_GetPrimaryFaction(NPC* self) // @categories Faction, Stats and Attributes +{ + return self->GetPrimaryFaction(); } -XS(XS_NPC_SetPetSpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPetSpellID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPetSpellID(THIS, uint16 amount)"); // @categories Pet - { - NPC *THIS; - uint16 amt = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetPetSpellID(amt); - } - XSRETURN_EMPTY; +int64_t Perl_NPC_GetNPCHate(NPC* self, Mob* mob) // @categories Hate and Aggro +{ + return self->GetNPCHate(mob); } -XS(XS_NPC_GetMaxDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxDamage) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetMaxDamage(THIS, uint8 target_level)"); // @categories Stats and Attributes - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - uint8 tlevel = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetMaxDamage(tlevel); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +bool Perl_NPC_IsOnHatelist(NPC* self, Mob* mob) // @categories Hate and Aggro +{ + return self->IsOnHatelist(mob); } -XS(XS_NPC_SetTaunting); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetTaunting) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetTaunting(THIS, bool toggle)"); // @categories Script Utility - { - NPC *THIS; - bool toggle = (bool) SvTRUE(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetTaunting(toggle); - } - XSRETURN_EMPTY; +void Perl_NPC_RemoveFromHateList(NPC* self, Mob* mob) // @categories Hate and Aggro +{ + self->RemoveFromHateList(mob); } -XS(XS_NPC_IsTaunting); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsTaunting) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsTaunting(THIS)"); - { - NPC *THIS; - bool RETVAL; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->IsTaunting(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_NPC_SetNPCFactionID(NPC* self, int faction_id) // @categories Faction +{ + self->SetNPCFactionID(faction_id); } -XS(XS_NPC_PickPocket); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_PickPocket) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::PickPocket(THIS, Client* thief)"); // @categories Skills and Recipes - { - NPC *THIS; - Client *thief; - VALIDATE_THIS_IS_NPC; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - thief = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "thief is not of type Client"); - if (thief == nullptr) - Perl_croak(aTHX_ "thief is nullptr, avoiding crash."); - - THIS->PickPocket(thief); - } - XSRETURN_EMPTY; +uint32_t Perl_NPC_GetMaxDMG(NPC* self) // @categories Stats and Attributes +{ + return self->GetMaxDMG(); } -XS(XS_NPC_StartSwarmTimer); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_StartSwarmTimer) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::StartSwarmTimer(THIS, uint32 duration)"); // @categories Script Utility, Pet - { - NPC *THIS; - uint32 duration = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->StartSwarmTimer(duration); - } - XSRETURN_EMPTY; +uint32_t Perl_NPC_GetMinDMG(NPC* self) +{ + return self->GetMinDMG(); } -XS(XS_NPC_DoClassAttacks); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_DoClassAttacks) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::DoClassAttacks(THIS, Mob* target)"); // @categories Script Utility - { - NPC *THIS; - Mob *target; - VALIDATE_THIS_IS_NPC; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - target = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "target is not of type Mob"); - if (target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - THIS->DoClassAttacks(target); - } - XSRETURN_EMPTY; +bool Perl_NPC_IsAnimal(NPC* self) // @categories Stats and Attributes +{ + return self->IsAnimal(); } -XS(XS_NPC_GetMaxWp); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxWp) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMaxWp(THIS)"); - { - NPC *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetMaxWp(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +int Perl_NPC_GetPetSpellID(NPC* self) // @categories Stats and Attributes, Pet +{ + return self->GetPetSpellID(); } -XS(XS_NPC_DisplayWaypointInfo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_DisplayWaypointInfo) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::DisplayWaypointInfo(THIS, Client* client)"); // @categories Script Utility - { - NPC *THIS; - Client *client; - VALIDATE_THIS_IS_NPC; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - client = INT2PTR(Client *, tmp); - } else { - Perl_croak(aTHX_ "client is not of type Client"); - } - - if (!client) { - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - } - - THIS->DisplayWaypointInfo(client); - } - XSRETURN_EMPTY; +void Perl_NPC_SetPetSpellID(NPC* self, uint16 amount) // @categories Pet +{ + self->SetPetSpellID(amount); } -XS(XS_NPC_CalculateNewWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CalculateNewWaypoint) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::CalculateNewWaypoint(THIS)"); // @categories Script Utility - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->CalculateNewWaypoint(); - } - XSRETURN_EMPTY; +uint32_t Perl_NPC_GetMaxDamage(NPC* self, uint8 target_level) // @categories Stats and Attributes +{ + return self->GetMaxDamage(target_level); } -XS(XS_NPC_AssignWaypoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AssignWaypoints) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::AssignWaypoints(THIS, uint32 grid_id)"); // @categories Script Utility - { - NPC *THIS; - uint32 grid = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->AssignWaypoints(grid); - } - XSRETURN_EMPTY; +void Perl_NPC_SetTaunting(NPC* self, bool on) // @categories Script Utility +{ + self->SetTaunting(on); } -XS(XS_NPC_SetWaypointPause); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetWaypointPause) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::SetWaypointPause(THIS)"); // @categories Script Utility - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->SetWaypointPause(); - } - XSRETURN_EMPTY; +bool Perl_NPC_IsTaunting(NPC* self) +{ + return self->IsTaunting(); } -XS(XS_NPC_UpdateWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_UpdateWaypoint) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::UpdateWaypoint(THIS, int wp_index)"); // @categories Script Utility - { - NPC *THIS; - int wp_index = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->UpdateWaypoint(wp_index); - } - XSRETURN_EMPTY; +void Perl_NPC_PickPocket(NPC* self, Client* thief) // @categories Skills and Recipes +{ + self->PickPocket(thief); } -XS(XS_NPC_StopWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_StopWandering) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::StopWandering(THIS)"); // @categories Script Utility - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->StopWandering(); - } - XSRETURN_EMPTY; +void Perl_NPC_StartSwarmTimer(NPC* self, uint32 duration) // @categories Script Utility, Pet +{ + self->StartSwarmTimer(duration); } -XS(XS_NPC_ResumeWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ResumeWandering) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::ResumeWandering(THIS)"); // @categories Script Utility - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->ResumeWandering(); - } - XSRETURN_EMPTY; +void Perl_NPC_DoClassAttacks(NPC* self, Mob* target) // @categories Script Utility +{ + self->DoClassAttacks(target); } -XS(XS_NPC_PauseWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_PauseWandering) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::PauseWandering(THIS, int pause_time)"); // @categories Script Utility - { - NPC *THIS; - int pausetime = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->PauseWandering(pausetime); - } - XSRETURN_EMPTY; +int Perl_NPC_GetMaxWp(NPC* self) +{ + return self->GetMaxWp(); } -XS(XS_NPC_MoveTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_MoveTo) { - dXSARGS; - if (items != 4 && items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: NPC::MoveTo(THIS, float x, float y, float z, [float heading], [bool save_guard_location = false])"); // @categories Script Utility - { - NPC *THIS; - float mtx = (float) SvNV(ST(1)); - float mty = (float) SvNV(ST(2)); - float mtz = (float) SvNV(ST(3)); - float mth = 0; - bool saveguard = false; - VALIDATE_THIS_IS_NPC; - if (items > 4) - mth = (float) SvNV(ST(4)); - if (items > 5) - saveguard = (bool) SvTRUE(ST(5)); - auto position = glm::vec4(mtx, mty, mtz, mth); - THIS->MoveTo(position, saveguard); - } - XSRETURN_EMPTY; +void Perl_NPC_DisplayWaypointInfo(NPC* self, Client* client) // @categories Script Utility +{ + self->DisplayWaypointInfo(client); } -XS(XS_NPC_NextGuardPosition); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_NextGuardPosition) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::NextGuardPosition(THIS)"); // @categories Script Utility - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->NextGuardPosition(); - } - XSRETURN_EMPTY; +void Perl_NPC_CalculateNewWaypoint(NPC* self) // @categories Script Utility +{ + self->CalculateNewWaypoint(); } -XS(XS_NPC_SaveGuardSpot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SaveGuardSpot) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: NPC::SaveGuardSpot(THIS, x, y, z, heading)"); // @categories Script Utility - { - NPC *THIS; - float x = (float)SvNV(ST(1)); - float y = (float)SvNV(ST(2)); - float z = (float)SvNV(ST(3)); - float heading = (float)SvNV(ST(4)); - VALIDATE_THIS_IS_NPC; - THIS->SaveGuardSpot(glm::vec4(x, y, z, heading)); - } - XSRETURN_EMPTY; +void Perl_NPC_AssignWaypoints(NPC* self, uint32 grid_id) // @categories Script Utility +{ + self->AssignWaypoints(grid_id); } -XS(XS_NPC_IsGuarding); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsGuarding) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsGuarding(THIS)"); // @categories Script Utility - { - NPC *THIS; - bool RETVAL; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->IsGuarding(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_NPC_SetWaypointPause(NPC* self) // @categories Script Utility +{ + self->SetWaypointPause(); } -XS(XS_NPC_AI_SetRoambox); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AI_SetRoambox) { - dXSARGS; - if (items < 6 || items > 8) - Perl_croak(aTHX_ "Usage: NPC::AI_SetRoambox(THIS, float distance, float max_x, float min_x, float max_y, float min_y, [uint32 max_delay = 2500], [uint32 min_delay = 2500])"); // @categories Script Utility - { - NPC *THIS; - float iDist = (float) SvNV(ST(1)); - float iMaxX = (float) SvNV(ST(2)); - float iMinX = (float) SvNV(ST(3)); - float iMaxY = (float) SvNV(ST(4)); - float iMinY = (float) SvNV(ST(5)); - uint32 iDelay; - uint32 iMinDelay; - VALIDATE_THIS_IS_NPC; - if (items < 7) { - iMinDelay = 2500; - iDelay = 2500; - } else if (items < 8) { - iMinDelay = 2500; - iDelay = (uint32) SvUV(ST(6)); - } else { - iDelay = (uint32) SvUV(ST(6)); - iMinDelay = (uint32) SvUV(ST(7)); - } - - THIS->AI_SetRoambox(iDist, iMaxX, iMinX, iMaxY, iMinY, iDelay, iMinDelay); - } - XSRETURN_EMPTY; +void Perl_NPC_UpdateWaypoint(NPC* self, int wp_index) // @categories Script Utility +{ + self->UpdateWaypoint(wp_index); } -XS(XS_NPC_GetNPCSpellsID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCSpellsID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetNPCSpellsID(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetNPCSpellsID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_StopWandering(NPC* self) // @categories Script Utility +{ + self->StopWandering(); } -XS(XS_NPC_GetSpawnPointID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointID(THIS)"); // @categories Spawns - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpawnPointID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_ResumeWandering(NPC* self) // @categories Script Utility +{ + self->ResumeWandering(); } -XS(XS_NPC_GetSpawnPointX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointX(THIS)"); // @categories Spawns - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpawnPoint().x; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_PauseWandering(NPC* self, int pause_time) // @categories Script Utility +{ + self->PauseWandering(pause_time); } -XS(XS_NPC_GetSpawnPointY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointY(THIS)"); // @categories Spawns - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpawnPoint().y; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_MoveTo(NPC* self, float x, float y, float z) // @categories Script Utility +{ + auto position = glm::vec4(x, y, z, 0); + self->MoveTo(position, false); } -XS(XS_NPC_GetSpawnPointZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointZ) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointZ(THIS)"); // @categories Spawns - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpawnPoint().z; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_MoveTo(NPC* self, float x, float y, float z, float h) // @categories Script Utility +{ + auto position = glm::vec4(x, y, z, h); + self->MoveTo(position, false); } -XS(XS_NPC_GetSpawnPointH); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointH) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointH(THIS)"); // @categories Spawns - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpawnPoint().w; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_MoveTo(NPC* self, float x, float y, float z, float h, bool save) // @categories Script Utility +{ + auto position = glm::vec4(x, y, z, h); + self->MoveTo(position, save); } -XS(XS_NPC_GetGuardPointX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointX(THIS)"); // @categories Script Utility, Spawns - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetGuardPoint().x; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_NextGuardPosition(NPC* self) // @categories Script Utility +{ + self->NextGuardPosition(); } -XS(XS_NPC_GetGuardPointY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointY(THIS)"); // @categories Script Utility, Spawns - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetGuardPoint().y; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_SaveGuardSpot(NPC* self) // @categories Script Utility +{ + self->SaveGuardSpot(); } -XS(XS_NPC_GetGuardPointZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointZ) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointZ(THIS)"); // @categories Script Utility, Spawns - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetGuardPoint().z; - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_SaveGuardSpot(NPC* self, bool clear) // @categories Script Utility +{ + self->SaveGuardSpot(clear); } -XS(XS_NPC_SetPrimSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPrimSkill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPrimSkill(THIS, int skill_id)"); // @categories Stats and Attributes - { - NPC *THIS; - int skill_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetPrimSkill(skill_id); - } - XSRETURN_EMPTY; +void Perl_NPC_SaveGuardSpot(NPC* self, float x, float y, float z, float heading) // @categories Script Utility +{ + self->SaveGuardSpot(glm::vec4(x, y, z, heading)); } -XS(XS_NPC_SetSecSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSecSkill) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSecSkill(THIS, int skill_id)"); // @categories Stats and Attributes - { - NPC *THIS; - int skill_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetSecSkill(skill_id); - } - XSRETURN_EMPTY; +bool Perl_NPC_IsGuarding(NPC* self) // @categories Script Utility +{ + return self->IsGuarding(); } -XS(XS_NPC_GetPrimSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPrimSkill) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPrimSkill(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetPrimSkill(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AI_SetRoambox(NPC* self, float distance, float max_x, float min_x, float max_y, float min_y) // @categories Script Utility +{ + self->AI_SetRoambox(distance, max_x, min_x, max_y, min_y); } -XS(XS_NPC_GetSecSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSecSkill) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSecSkill(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSecSkill(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AI_SetRoambox(NPC* self, float distance, float max_x, float min_x, float max_y, float min_y, uint32 max_delay) // @categories Script Utility +{ + self->AI_SetRoambox(distance, max_x, min_x, max_y, min_y, max_delay); } -XS(XS_NPC_GetSwarmOwner); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSwarmOwner) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSwarmOwner(THIS)"); // @categories Pet - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSwarmOwner(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_AI_SetRoambox(NPC* self, float distance, float max_x, float min_x, float max_y, float min_y, uint32 max_delay, uint32 min_delay) // @categories Script Utility +{ + self->AI_SetRoambox(distance, max_x, min_x, max_y, min_y, max_delay, min_delay); } -XS(XS_NPC_GetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSwarmTarget) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSwarmTarget(THIS)"); // @categories Pet - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSwarmTarget(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetNPCSpellsID(NPC* self) // @categories Stats and Attributes +{ + return self->GetNPCSpellsID(); } -XS(XS_NPC_SetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSwarmTarget) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSwarmTarget(THIS, int target_id)"); // @categories Pet - { - NPC *THIS; - int target_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetSwarmTarget(target_id); - } - XSRETURN_EMPTY; +uint32_t Perl_NPC_GetSpawnPointID(NPC* self) // @categories Spawns +{ + return self->GetSpawnPointID(); } -XS(XS_NPC_ModifyNPCStat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ModifyNPCStat) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::ModifyNPCStat(THIS, string key, string value)"); // @categories Stats and Attributes - { - NPC *THIS; - Const_char *identifier = (Const_char *) SvPV_nolen(ST(1)); - Const_char *newValue = (Const_char *) SvPV_nolen(ST(2)); - VALIDATE_THIS_IS_NPC; - THIS->ModifyNPCStat(identifier, newValue); - } - XSRETURN_EMPTY; +float Perl_NPC_GetSpawnPointX(NPC* self) // @categories Spawns +{ + return self->GetSpawnPoint().x; } -XS(XS_NPC_GetNPCStat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCStat) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetNPCStat(THIS, string key)"); // @categories Stats and Attributes - { - NPC *THIS; - float RETVAL; - Const_char *identifier = (Const_char *)SvPV_nolen(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - - RETVAL = THIS->GetNPCStat(identifier); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +float Perl_NPC_GetSpawnPointY(NPC* self) // @categories Spawns +{ + return self->GetSpawnPoint().y; } -XS(XS_NPC_AddSpellToNPCList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddSpellToNPCList) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: NPC::AddAISpell(THIS, int priority, int spell_id, int type, int mana_cost, int recast_delay, int resist_adjust)"); // @categories Spells and Disciplines, Script Utility - { - NPC *THIS; - int priority = (int) SvIV(ST(1)); - int spell_id = (int) SvIV(ST(2)); - int type = (int) SvIV(ST(3)); - int mana_cost = (int) SvIV(ST(4)); - int recast_delay = (int) SvIV(ST(5)); - int resist_adjust = (int) SvIV(ST(6)); - VALIDATE_THIS_IS_NPC; - THIS->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust, 0, 0); - } - XSRETURN_EMPTY; +float Perl_NPC_GetSpawnPointZ(NPC* self) // @categories Spawns +{ + return self->GetSpawnPoint().z; } -XS(XS_NPC_RemoveSpellFromNPCList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveSpellFromNPCList) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveAISpell(THIS, int spell_id)"); // @categories Spells and Disciplines - { - NPC *THIS; - int spell_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->RemoveSpellFromNPCList(spell_id); - } - XSRETURN_EMPTY; +float Perl_NPC_GetSpawnPointH(NPC* self) // @categories Spawns +{ + return self->GetSpawnPoint().w; } -XS(XS_NPC_SetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSpellFocusDMG) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusDMG(THIS, int new_spell_focus_dmg)"); // @categories Stats and Attributes - { - NPC *THIS; - int32 NewSpellFocusDMG = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetSpellFocusDMG(NewSpellFocusDMG); - } - XSRETURN_EMPTY; +float Perl_NPC_GetGuardPointX(NPC* self) // @categories Script Utility, Spawns +{ + return self->GetGuardPoint().x; } -XS(XS_NPC_GetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpellFocusDMG) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusDMG(THIS)"); // @categories Spells and Disciplines - { - NPC *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpellFocusDMG(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +float Perl_NPC_GetGuardPointY(NPC* self) // @categories Script Utility, Spawns +{ + return self->GetGuardPoint().y; } -XS(XS_NPC_SetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSpellFocusHeal) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusHeal(THIS, int32 new_spell_focus_heal)"); // @categories Stats and Attributes - { - NPC *THIS; - int32 NewSpellFocusHeal = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->SetSpellFocusHeal(NewSpellFocusHeal); - } - XSRETURN_EMPTY; +float Perl_NPC_GetGuardPointZ(NPC* self) // @categories Script Utility, Spawns +{ + return self->GetGuardPoint().z; } -XS(XS_NPC_GetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpellFocusHeal) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusHeal(THIS)"); // @categories Spells and Disciplines - { - NPC *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpellFocusHeal(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_SetPrimSkill(NPC* self, int skill_id) // @categories Stats and Attributes +{ + self->SetPrimSkill(skill_id); } -XS(XS_NPC_GetSlowMitigation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSlowMitigation) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSlowMitigation(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +void Perl_NPC_SetSecSkill(NPC* self, int skill_id) // @categories Stats and Attributes +{ + self->SetSecSkill(skill_id); } -XS(XS_NPC_GetAttackSpeed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAttackSpeed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAttackSpeed(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetAttackSpeed(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetPrimSkill(NPC* self) // @categories Stats and Attributes +{ + return self->GetPrimSkill(); } -XS(XS_NPC_GetAttackDelay); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAttackDelay) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAttackDelay(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetAttackDelay(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetSecSkill(NPC* self) // @categories Stats and Attributes +{ + return self->GetSecSkill(); } -XS(XS_NPC_GetAccuracyRating); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAccuracyRating) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAccuracyRating(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetAccuracyRating(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetSwarmOwner(NPC* self) // @categories Pet +{ + return self->GetSwarmOwner(); } -XS(XS_NPC_GetAvoidanceRating); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAvoidanceRating) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAvoidanceRating(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - int32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetAvoidanceRating(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_NPC_GetSwarmTarget(NPC* self) // @categories Pet +{ + return self->GetSwarmTarget(); } -XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnKillCount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnKillCount(THIS)"); // @categories Spawns - { - NPC *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetSpawnKillCount(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_SetSwarmTarget(NPC* self, int target_id) // @categories Pet +{ + self->SetSwarmTarget(target_id); } -XS(XS_NPC_GetScore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetScore) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetScore(THIS)"); // @categories Script Utility - { - NPC *THIS; - int RETVAL; - dXSTARG; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetScore(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +void Perl_NPC_ModifyNPCStat(NPC* self, std::string stat, std::string value) // @categories Stats and Attributes +{ + self->ModifyNPCStat(stat, value); } -XS(XS_NPC_MerchantOpenShop); -XS(XS_NPC_MerchantOpenShop) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::MerchantOpenShop(THIS)"); // @categories Script Utility - { - NPC *THIS; - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->MerchantOpenShop(); - } - XSRETURN_EMPTY; +float Perl_NPC_GetNPCStat(NPC* self, std::string stat) // @categories Stats and Attributes +{ + return self->GetNPCStat(stat); } -XS(XS_NPC_MerchantCloseShop); -XS(XS_NPC_MerchantCloseShop) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::MerchantCloseShop(THIS)"); // @categories Script Utility - { - NPC *THIS; - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->MerchantCloseShop(); - } - XSRETURN_EMPTY; +void Perl_NPC_AddSpellToNPCList(NPC* self, int16 priority, uint16_t spell_id, uint32 type, int mana_cost, int recast_delay, int16 resist_adjust) // @categories Spells and Disciplines, Script Utility +{ + self->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust, 0, 0); } -XS(XS_NPC_AddMeleeProc); -XS(XS_NPC_AddMeleeProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddMeleeProc(THIS, int spell_id, int chance)"); // @categories Script Utility - { - NPC *THIS; - int spell_id = (int) SvIV(ST(1)); - int chance = (int) SvIV(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->AddProcToWeapon(spell_id, true, chance); - } - XSRETURN_EMPTY; +void Perl_NPC_AddSpellToNPCList(NPC* self, int16 priority, uint16_t spell_id, uint32 type, int mana_cost, int recast_delay, int16 resist_adjust, int8 min_hp, int8 max_hp) // @categories Spells and Disciplines, Script Utility +{ + self->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust, min_hp, max_hp); } -XS(XS_NPC_AddRangedProc); -XS(XS_NPC_AddRangedProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddRangedProc(THIS, int spell_id, int chance)"); // @categories Script Utility - { - NPC *THIS; - int spell_id = (int) SvIV(ST(1)); - int chance = (int) SvIV(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->AddRangedProc(spell_id, chance); - } - XSRETURN_EMPTY; +void Perl_NPC_RemoveSpellFromNPCList(NPC* self, uint16_t spell_id) // @categories Spells and Disciplines +{ + self->RemoveSpellFromNPCList(spell_id); } -XS(XS_NPC_AddDefensiveProc); -XS(XS_NPC_AddDefensiveProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddDefensiveProc(THIS, int spell_id, int chance)"); // @categories Script Utility - { - NPC *THIS; - int spell_id = (int) SvIV(ST(1)); - int chance = (int) SvIV(ST(2)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->AddDefensiveProc(spell_id, chance); - } - XSRETURN_EMPTY; +void Perl_NPC_SetSpellFocusDMG(NPC* self, int new_spell_focus_dmg) // @categories Stats and Attributes +{ + self->SetSpellFocusDMG(new_spell_focus_dmg); } -XS(XS_NPC_RemoveMeleeProc); -XS(XS_NPC_RemoveMeleeProc) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveMeleeProc(THIS, int spell_id)"); // @categories Script Utility - { - NPC *THIS; - int spell_id = (int) SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->RemoveProcFromWeapon(spell_id, false); - } - XSRETURN_EMPTY; +int Perl_NPC_GetSpellFocusDMG(NPC* self) // @categories Spells and Disciplines +{ + return self->GetSpellFocusDMG(); } -XS(XS_NPC_RemoveRangedProc); -XS(XS_NPC_RemoveRangedProc) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveRangedProc(THIS, int spell_id)"); // @categories Script Utility - { - NPC *THIS; - int spell_id = (int) SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->RemoveRangedProc(spell_id, false); - } - XSRETURN_EMPTY; +void Perl_NPC_SetSpellFocusHeal(NPC* self, int new_spell_focus_heal) // @categories Stats and Attributes +{ + self->SetSpellFocusHeal(new_spell_focus_heal); } -XS(XS_NPC_RemoveDefensiveProc); -XS(XS_NPC_RemoveDefensiveProc) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveDefensiveProc(THIS, int spell_id)"); // @categories Script Utility - { - NPC *THIS; - int spell_id = (int) SvIV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - THIS->RemoveDefensiveProc(spell_id, false); - } - XSRETURN_EMPTY; +int Perl_NPC_GetSpellFocusHeal(NPC* self) // @categories Spells and Disciplines +{ + return self->GetSpellFocusHeal(); } -XS(XS_NPC_ChangeLastName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ChangeLastName) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: NPC::ChangeLastName(THIS, string name)"); // @categories Script Utility - { - NPC *THIS; - char *name = nullptr; - VALIDATE_THIS_IS_NPC; - if (items > 1) { name = (char *) SvPV_nolen(ST(1)); } +float Perl_NPC_GetSlowMitigation(NPC* self) // @categories Stats and Attributes +{ + return self->GetSlowMitigation(); +} - THIS->ChangeLastName(name); - } - XSRETURN_EMPTY; +float Perl_NPC_GetAttackSpeed(NPC* self) // @categories Stats and Attributes +{ + return self->GetAttackSpeed(); } -XS(XS_NPC_ClearLastName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ClearLastName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::ClearLastName(THIS)"); // @categories Script Utility - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->ClearLastName(); - } - XSRETURN_EMPTY; +int Perl_NPC_GetAttackDelay(NPC* self) // @categories Stats and Attributes +{ + return self->GetAttackDelay(); } -XS(XS_NPC_GetCombatState); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetCombatState) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetCombatState(THIS)"); // @categories Script Utility - { - NPC *THIS; - bool RETVAL; - VALIDATE_THIS_IS_NPC; - RETVAL = THIS->GetCombatEvent(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +int Perl_NPC_GetAccuracyRating(NPC* self) // @categories Stats and Attributes +{ + return self->GetAccuracyRating(); } -XS(XS_NPC_SetSimpleRoamBox); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSimpleRoamBox) { - dXSARGS; - if (items < 2) - Perl_croak(aTHX_ "Usage: NPC::SetSimpleRoamBox(THIS, box_size, move_distance, move_delay)"); // @categories Script Utility - { - NPC *THIS; +int Perl_NPC_GetAvoidanceRating(NPC* self) // @categories Stats and Attributes +{ + return self->GetAvoidanceRating(); +} - auto box_size = (float) SvNV(ST(1)); - float move_distance = 0; - int move_delay = 0; +uint32_t Perl_NPC_GetSpawnKillCount(NPC* self) // @categories Spawns +{ + return self->GetSpawnKillCount(); +} - if (items >= 3) { - move_distance = (float) SvNV(ST(2)); - } +int Perl_NPC_GetScore(NPC* self) // @categories Script Utility +{ + return self->GetScore(); +} - if (items >= 4) { - move_delay = (int) SvIV(ST(3)); - } - VALIDATE_THIS_IS_NPC; - THIS->SetSimpleRoamBox(box_size, move_distance, move_delay); - } - XSRETURN_EMPTY; +void Perl_NPC_MerchantOpenShop(NPC* self) // @categories Script Utility +{ + self->MerchantOpenShop(); } +void Perl_NPC_MerchantCloseShop(NPC* self) // @categories Script Utility +{ + self->MerchantCloseShop(); +} -XS(XS_NPC_RecalculateSkills); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RecalculateSkills) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::RecalculateSkills(THIS)"); // @categories Skills and Recipes - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - THIS->RecalculateSkills(); - } - XSRETURN_EMPTY; +void Perl_NPC_AddMeleeProc(NPC* self, uint16_t spell_id, uint16_t chance) // @categories Script Utility +{ + self->AddProcToWeapon(spell_id, true, chance); } -XS(XS_NPC_ScaleNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ScaleNPC) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::ScaleNPC(THIS, uint8 npc_level)"); - { - NPC *THIS; - uint8 npc_level = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->ScaleNPC(npc_level); - } - XSRETURN_EMPTY; +void Perl_NPC_AddRangedProc(NPC* self, uint16_t spell_id, uint16_t chance) // @categories Script Utility +{ + self->AddRangedProc(spell_id, chance); } -XS(XS_NPC_IsRaidTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsRaidTarget) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsRaidTarget(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - bool is_raid_target; - VALIDATE_THIS_IS_NPC; - is_raid_target = THIS->IsRaidTarget(); - ST(0) = boolSV(is_raid_target); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_NPC_AddDefensiveProc(NPC* self, uint16_t spell_id, uint16_t chance) // @categories Script Utility +{ + self->AddDefensiveProc(spell_id, chance); } -XS(XS_NPC_HasItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_HasItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::HasItem(THIS, uint32 item_id)"); // @categories Script Utility - { - NPC *THIS; - bool has_item = false; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_NPC; - has_item = THIS->HasItem(item_id); - ST(0) = boolSV(has_item); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_NPC_RemoveMeleeProc(NPC* self, uint16_t spell_id) // @categories Script Utility +{ + self->RemoveProcFromWeapon(spell_id, false); } -XS(XS_NPC_CountItem); -XS(XS_NPC_CountItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::CountItem(THIS, uint32 item_id)"); // @categories Script Utility - { - NPC *THIS; - uint16 item_count = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - item_count = THIS->CountItem(item_id); - XSprePUSH; - PUSHu((UV) item_count); - } - XSRETURN(1); +void Perl_NPC_RemoveRangedProc(NPC* self, uint16_t spell_id) // @categories Script Utility +{ + self->RemoveRangedProc(spell_id, false); } -XS(XS_NPC_GetItemIDBySlot); -XS(XS_NPC_GetItemIDBySlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetItemIDBySlot(THIS, uint16 loot_slot)"); // @categories Script Utility - { - NPC *THIS; - uint32 item_id = 0; - uint16 loot_slot = (uint16) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - item_id = THIS->GetItemIDBySlot(loot_slot); - XSprePUSH; - PUSHu((UV) item_id); - } - XSRETURN(1); +void Perl_NPC_RemoveDefensiveProc(NPC* self, uint16_t spell_id) // @categories Script Utility +{ + self->RemoveDefensiveProc(spell_id, false); } -XS(XS_NPC_GetFirstSlotByItemID); -XS(XS_NPC_GetFirstSlotByItemID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetFirstSlotByItemID(THIS, uint32 item_id)"); // @categories Script Utility - { - NPC *THIS; - uint16 loot_slot = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_NPC; - loot_slot = THIS->GetFirstSlotByItemID(item_id); - XSprePUSH; - PUSHu((UV) loot_slot); - } - XSRETURN(1); +void Perl_NPC_ChangeLastName(NPC* self, std::string name) // @categories Script Utility +{ + self->ChangeLastName(name); } -XS(XS_NPC_GetHealScale); -XS(XS_NPC_GetHealScale) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetHealScale(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - float healscale; - dXSTARG; - VALIDATE_THIS_IS_NPC; - healscale = THIS->GetHealScale(); - XSprePUSH; - PUSHn((double) healscale); - } - XSRETURN(1); +void Perl_NPC_ClearLastName(NPC* self) // @categories Script Utility +{ + self->ClearLastName(); } -XS(XS_NPC_GetSpellScale); -XS(XS_NPC_GetSpellScale) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpellScale(THIS)"); // @categories Stats and Attributes - { - NPC *THIS; - float spellscale; - dXSTARG; - VALIDATE_THIS_IS_NPC; - spellscale = THIS->GetSpellScale(); - XSprePUSH; - PUSHn((double) spellscale); - } - XSRETURN(1); +bool Perl_NPC_GetCombatState(NPC* self) // @categories Script Utility +{ + return self->GetCombatEvent(); } -XS(XS_NPC_GetLootList); -XS(XS_NPC_GetLootList) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetLootList(THIS)"); // @categories Script Utility - { - NPC *THIS; - VALIDATE_THIS_IS_NPC; - auto npc_items = THIS->GetLootList(); - auto item_count = npc_items.size(); - if (item_count > 0) { - EXTEND(sp, item_count); - for (int index = 0; index < item_count; ++index) { - ST(index) = sv_2mortal(newSVuv(npc_items[index])); - } - XSRETURN(item_count); - } - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); - } +void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size, float move_distance, int move_delay) // @categories Script Utility +{ + self->SetSimpleRoamBox(box_size, move_distance, move_delay); } -XS(XS_NPC_AddAISpellEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddAISpellEffect) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: NPC::AddAISpellEffect(THIS, int spell_effect_id, int base_value, int limit_value, int max_value)"); // @categories Spells and Disciplines - { - NPC *THIS; +void Perl_NPC_RecalculateSkills(NPC* self) // @categories Skills and Recipes +{ + self->RecalculateSkills(); +} - int spell_effect_id = (int) SvIV(ST(1)); - int base_value = (int) SvIV(ST(2)); - int limit_value = (int) SvIV(ST(3)); - int max_value = (int) SvIV(ST(4)); +void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level) +{ + return self->ScaleNPC(npc_level); +} - VALIDATE_THIS_IS_NPC; - THIS->AddSpellEffectToNPCList(spell_effect_id, base_value, limit_value, max_value, true); - } - XSRETURN_EMPTY; +bool Perl_NPC_IsRaidTarget(NPC* self) +{ + return self->IsRaidTarget(); } -XS(XS_NPC_RemoveAISpellEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveAISpellEffect) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveAISpellEffect(THIS, int spell_effect_id)"); // @categories Spells and Disciplines - { - NPC *THIS; - int spell_effect_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - THIS->RemoveSpellEffectFromNPCList(spell_effect_id, true); - } - XSRETURN_EMPTY; +bool Perl_NPC_HasItem(NPC* self, uint32 item_id) // @categories Script Utility +{ + return self->HasItem(item_id); +} + +int Perl_NPC_CountItem(NPC* self, uint32 item_id) +{ + return self->CountItem(item_id); +} + +uint32_t Perl_NPC_GetItemIDBySlot(NPC* self, uint16 loot_slot) +{ + return self->GetItemIDBySlot(loot_slot); +} + +int Perl_NPC_GetFirstSlotByItemID(NPC* self, uint32 item_id) +{ + return self->GetFirstSlotByItemID(item_id); } -XS(XS_NPC_HasAISpellEffect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_HasAISpellEffect) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::HasAISpellEffect(THIS, int spell_effect_id)"); // @categories Spells and Disciplines +float Perl_NPC_GetHealScale(NPC* self) // @categories Stats and Attributes +{ + return self->GetHealScale(); +} + +float Perl_NPC_GetSpellScale(NPC* self) // @categories Stats and Attributes +{ + return self->GetSpellScale(); +} + +perl::array Perl_NPC_GetLootList(NPC* self) // @categories Script Utility +{ + perl::array result; + auto npc_items = self->GetLootList(); + for (int item_id : npc_items) { - NPC *THIS; - bool has_spell_effect = false; - int spell_effect_id = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_NPC; - has_spell_effect = THIS->HasAISpellEffect(spell_effect_id); - ST(0) = boolSV(has_spell_effect); - sv_2mortal(ST(0)); + result.push_back(item_id); } - XSRETURN(1); -} - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_NPC); /* prototype to pass -Wmissing-prototypes */ -XS(boot_NPC) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "AI_SetRoambox"), XS_NPC_AI_SetRoambox, file, "$$$$$$;$$"); - newXSproto(strcpy(buf, "AddAISpell"), XS_NPC_AddSpellToNPCList, file, "$$$$$$$"); - newXSproto(strcpy(buf, "AddAISpellEffect"), XS_NPC_AddAISpellEffect, file, "$$$$$"); - newXSproto(strcpy(buf, "AddCash"), XS_NPC_AddCash, file, "$$$$$"); - newXSproto(strcpy(buf, "AddDefensiveProc"), XS_NPC_AddDefensiveProc, file, "$$$"); - newXSproto(strcpy(buf, "AddItem"), XS_NPC_AddItem, file, "$$;$$$$$$$$"); - newXSproto(strcpy(buf, "AddLootTable"), XS_NPC_AddLootTable, file, "$"); - newXSproto(strcpy(buf, "AddMeleeProc"), XS_NPC_AddMeleeProc, file, "$$$"); - newXSproto(strcpy(buf, "AddRangedProc"), XS_NPC_AddRangedProc, file, "$$$"); - newXSproto(strcpy(buf, "AssignWaypoints"), XS_NPC_AssignWaypoints, file, "$$"); - newXSproto(strcpy(buf, "CalculateNewWaypoint"), XS_NPC_CalculateNewWaypoint, file, "$"); - newXSproto(strcpy(buf, "ChangeLastName"), XS_NPC_ChangeLastName, file, "$:$"); - newXSproto(strcpy(buf, "CheckNPCFactionAlly"), XS_NPC_CheckNPCFactionAlly, file, "$$"); - newXSproto(strcpy(buf, "ClearItemList"), XS_NPC_ClearItemList, file, "$"); - newXSproto(strcpy(buf, "ClearLastName"), XS_NPC_ClearLastName, file, "$"); - newXSproto(strcpy(buf, "CountItem"), XS_NPC_CountItem, file, "$$"); - newXSproto(strcpy(buf, "CountLoot"), XS_NPC_CountLoot, file, "$"); - newXSproto(strcpy(buf, "DisplayWaypointInfo"), XS_NPC_DisplayWaypointInfo, file, "$$"); - newXSproto(strcpy(buf, "DoClassAttacks"), XS_NPC_DoClassAttacks, file, "$$"); - newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$"); - newXSproto(strcpy(buf, "GetAttackDelay"), XS_NPC_GetAttackDelay, file, "$"); - newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$"); - newXSproto(strcpy(buf, "GetAvoidanceRating"), XS_NPC_GetAvoidanceRating, file, "$"); - newXSproto(strcpy(buf, "GetCombatState"), XS_NPC_GetCombatState, file, "$"); - newXSproto(strcpy(buf, "GetCopper"), XS_NPC_GetCopper, file, "$"); - newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_NPC_GetFirstSlotByItemID, file, "$$"); - newXSproto(strcpy(buf, "GetGold"), XS_NPC_GetGold, file, "$"); - newXSproto(strcpy(buf, "GetGrid"), XS_NPC_GetGrid, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointX"), XS_NPC_GetGuardPointX, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointY"), XS_NPC_GetGuardPointY, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointZ"), XS_NPC_GetGuardPointZ, file, "$"); - newXSproto(strcpy(buf, "GetHealScale"), XS_NPC_GetHealScale, file, "$"); - newXSproto(strcpy(buf, "GetItemIDBySlot"), XS_NPC_GetItemIDBySlot, file, "$$"); - newXSproto(strcpy(buf, "GetLootList"), XS_NPC_GetLootList, file, "$"); - newXSproto(strcpy(buf, "GetLoottableID"), XS_NPC_GetLoottableID, file, "$"); - newXSproto(strcpy(buf, "GetMaxDMG"), XS_NPC_GetMaxDMG, file, "$"); - newXSproto(strcpy(buf, "GetMaxDamage"), XS_NPC_GetMaxDamage, file, "$$"); - newXSproto(strcpy(buf, "GetMaxWp"), XS_NPC_GetMaxWp, file, "$"); - newXSproto(strcpy(buf, "GetMinDMG"), XS_NPC_GetMinDMG, file, "$"); - newXSproto(strcpy(buf, "GetNPCFactionID"), XS_NPC_GetNPCFactionID, file, "$"); - newXSproto(strcpy(buf, "GetNPCHate"), XS_NPC_GetNPCHate, file, "$$"); - newXSproto(strcpy(buf, "GetNPCSpellsID"), XS_NPC_GetNPCSpellsID, file, "$"); - newXSproto(strcpy(buf, "GetNPCStat"), XS_NPC_GetNPCStat, file, "$$"); - newXSproto(strcpy(buf, "GetPetSpellID"), XS_NPC_GetPetSpellID, file, "$"); - newXSproto(strcpy(buf, "GetPlatinum"), XS_NPC_GetPlatinum, file, "$"); - newXSproto(strcpy(buf, "GetPrimSkill"), XS_NPC_GetPrimSkill, file, "$"); - newXSproto(strcpy(buf, "GetPrimaryFaction"), XS_NPC_GetPrimaryFaction, file, "$"); - newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$"); - newXSproto(strcpy(buf, "GetSecSkill"), XS_NPC_GetSecSkill, file, "$"); - newXSproto(strcpy(buf, "GetSilver"), XS_NPC_GetSilver, file, "$"); - newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$"); - newXSproto(strcpy(buf, "GetSp2"), XS_NPC_GetSp2, file, "$"); - newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointH"), XS_NPC_GetSpawnPointH, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointID"), XS_NPC_GetSpawnPointID, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointX"), XS_NPC_GetSpawnPointX, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointY"), XS_NPC_GetSpawnPointY, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointZ"), XS_NPC_GetSpawnPointZ, file, "$"); - newXSproto(strcpy(buf, "GetSpellFocusDMG"), XS_NPC_GetSpellFocusDMG, file, "$"); - newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$"); - newXSproto(strcpy(buf, "GetSpellScale"), XS_NPC_GetSpellScale, file, "$"); - newXSproto(strcpy(buf, "GetSwarmOwner"), XS_NPC_GetSwarmOwner, file, "$"); - newXSproto(strcpy(buf, "GetSwarmTarget"), XS_NPC_GetSwarmTarget, file, "$"); - newXSproto(strcpy(buf, "GetWaypointMax"), XS_NPC_GetWaypointMax, file, "$"); - newXSproto(strcpy(buf, "HasAISpellEffect"), XS_NPC_HasAISpellEffect, file, "$$"); - newXSproto(strcpy(buf, "HasItem"), XS_NPC_HasItem, file, "$$"); - newXSproto(strcpy(buf, "IsAnimal"), XS_NPC_IsAnimal, file, "$"); - newXSproto(strcpy(buf, "IsGuarding"), XS_NPC_IsGuarding, file, "$"); - newXSproto(strcpy(buf, "IsOnHatelist"), XS_NPC_IsOnHatelist, file, "$$"); - newXSproto(strcpy(buf, "IsRaidTarget"), XS_NPC_IsRaidTarget, file, "$"); - newXSproto(strcpy(buf, "IsTaunting"), XS_NPC_IsTaunting, file, "$"); - newXSproto(strcpy(buf, "MerchantCloseShop"), XS_NPC_MerchantCloseShop, file, "$"); - newXSproto(strcpy(buf, "MerchantOpenShop"), XS_NPC_MerchantOpenShop, file, "$"); - newXSproto(strcpy(buf, "ModifyNPCStat"), XS_NPC_ModifyNPCStat, file, "$$$"); - newXSproto(strcpy(buf, "MoveTo"), XS_NPC_MoveTo, file, "$$$$"); - newXSproto(strcpy(buf, "NextGuardPosition"), XS_NPC_NextGuardPosition, file, "$"); - newXSproto(strcpy(buf, "PauseWandering"), XS_NPC_PauseWandering, file, "$$"); - newXSproto(strcpy(buf, "PickPocket"), XS_NPC_PickPocket, file, "$$"); - newXSproto(strcpy(buf, "RecalculateSkills"), XS_NPC_RecalculateSkills, file, "$"); - newXSproto(strcpy(buf, "RemoveAISpell"), XS_NPC_RemoveSpellFromNPCList, file, "$$"); - newXSproto(strcpy(buf, "RemoveAISpellEffect"), XS_NPC_RemoveAISpellEffect, file, "$$"); - newXSproto(strcpy(buf, "RemoveCash"), XS_NPC_RemoveCash, file, "$"); - newXSproto(strcpy(buf, "RemoveDefensiveProc"), XS_NPC_RemoveDefensiveProc, file, "$$"); - newXSproto(strcpy(buf, "RemoveFromHateList"), XS_NPC_RemoveFromHateList, file, "$$"); - newXSproto(strcpy(buf, "RemoveItem"), XS_NPC_RemoveItem, file, "$$;$$"); - newXSproto(strcpy(buf, "RemoveMeleeProc"), XS_NPC_RemoveMeleeProc, file, "$$"); - newXSproto(strcpy(buf, "RemoveRangedProc"), XS_NPC_RemoveRangedProc, file, "$$"); - newXSproto(strcpy(buf, "ResumeWandering"), XS_NPC_ResumeWandering, file, "$"); - newXSproto(strcpy(buf, "SaveGuardSpot"), XS_NPC_SaveGuardSpot, file, "$$$$$"); - newXSproto(strcpy(buf, "ScaleNPC"), XS_NPC_ScaleNPC, file, "$$"); - newXSproto(strcpy(buf, "SetCopper"), XS_NPC_SetCopper, file, "$$"); - newXSproto(strcpy(buf, "SetGold"), XS_NPC_SetGold, file, "$$"); - newXSproto(strcpy(buf, "SetGrid"), XS_NPC_SetGrid, file, "$$"); - newXSproto(strcpy(buf, "SetNPCFactionID"), XS_NPC_SetNPCFactionID, file, "$$"); - newXSproto(strcpy(buf, "SetPetSpellID"), XS_NPC_SetPetSpellID, file, "$$"); - newXSproto(strcpy(buf, "SetPlatinum"), XS_NPC_SetPlatinum, file, "$$"); - newXSproto(strcpy(buf, "SetPrimSkill"), XS_NPC_SetPrimSkill, file, "$$"); - newXSproto(strcpy(buf, "SetSaveWaypoint"), XS_NPC_SetSaveWaypoint, file, "$$"); - newXSproto(strcpy(buf, "SetSecSkill"), XS_NPC_SetSecSkill, file, "$$"); - newXSproto(strcpy(buf, "SetSilver"), XS_NPC_SetSilver, file, "$$"); - newXSproto(strcpy(buf, "SetSimpleRoamBox"), XS_NPC_SetSimpleRoamBox, file, "$$;$$"); - newXSproto(strcpy(buf, "SetSp2"), XS_NPC_SetSp2, file, "$$"); - newXSproto(strcpy(buf, "SetSpellFocusDMG"), XS_NPC_SetSpellFocusDMG, file, "$$"); - newXSproto(strcpy(buf, "SetSpellFocusHeal"), XS_NPC_SetSpellFocusHeal, file, "$$"); - newXSproto(strcpy(buf, "SetSwarmTarget"), XS_NPC_SetSwarmTarget, file, "$$"); - newXSproto(strcpy(buf, "SetTaunting"), XS_NPC_SetTaunting, file, "$$"); - newXSproto(strcpy(buf, "SetWaypointPause"), XS_NPC_SetWaypointPause, file, "$"); - newXSproto(strcpy(buf, "SignalNPC"), XS_NPC_SignalNPC, file, "$$"); - newXSproto(strcpy(buf, "StartSwarmTimer"), XS_NPC_StartSwarmTimer, file, "$$"); - newXSproto(strcpy(buf, "StopWandering"), XS_NPC_StopWandering, file, "$"); - newXSproto(strcpy(buf, "UpdateWaypoint"), XS_NPC_UpdateWaypoint, file, "$$"); - XSRETURN_YES; + return result; +} + +void Perl_NPC_AddAISpellEffect(NPC* self, int spell_effect_id, int base_value, int limit_value, int max_value) // @categories Spells and Disciplines +{ + self->AddSpellEffectToNPCList(spell_effect_id, base_value, limit_value, max_value, true); +} + +void Perl_NPC_RemoveAISpellEffect(NPC* self, int spell_effect_id) // @categories Spells and Disciplines +{ + self->RemoveSpellEffectFromNPCList(spell_effect_id, true); +} + +bool Perl_NPC_HasAISpellEffect(NPC* self, int spell_effect_id) // @categories Spells and Disciplines +{ + return self->HasAISpellEffect(spell_effect_id); +} + +bool Perl_NPC_IsRareSpawn(NPC* self) +{ + return self->IsRareSpawn(); +} + +void Perl_NPC_ReloadSpells(NPC* self) +{ + self->ReloadSpells(); +} + +void Perl_NPC_SendPayload(NPC* self, int payload_id) // @categories Script Utility +{ + self->SendPayload(payload_id); +} + +void Perl_NPC_SendPayload(NPC* self, int payload_id, std::string payload_value) // @categories Script Utility +{ + self->SendPayload(payload_id, payload_value); +} + +bool Perl_NPC_GetKeepsSoldItems(NPC* self) +{ + return self->GetKeepsSoldItems(); +} + +void Perl_NPC_SetKeepsSoldItems(NPC* self, bool keeps_sold_items) +{ + self->SetKeepsSoldItems(keeps_sold_items); +} + +void perl_register_npc() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("NPC"); + package.add_base_class("Mob"); + package.add("AI_SetRoambox", (void(*)(NPC*, float, float, float, float, float))&Perl_NPC_AI_SetRoambox); + package.add("AI_SetRoambox", (void(*)(NPC*, float, float, float, float, float, uint32))&Perl_NPC_AI_SetRoambox); + package.add("AI_SetRoambox", (void(*)(NPC*, float, float, float, float, float, uint32, uint32))&Perl_NPC_AI_SetRoambox); + package.add("AddAISpell", (void(*)(NPC*, int16, uint16, uint32, int, int, int16))&Perl_NPC_AddSpellToNPCList); + package.add("AddAISpell", (void(*)(NPC*, int16, uint16, uint32, int, int, int16, int8, int8))&Perl_NPC_AddSpellToNPCList); + package.add("AddAISpellEffect", &Perl_NPC_AddAISpellEffect); + package.add("AddCash", &Perl_NPC_AddCash); + package.add("AddDefensiveProc", &Perl_NPC_AddDefensiveProc); + package.add("AddItem", (void(*)(NPC*, uint32))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16, bool))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16, bool, uint32))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16, bool, uint32, uint32))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16, bool, uint32, uint32, uint32))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16, bool, uint32, uint32, uint32, uint32))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32))&Perl_NPC_AddItem); + package.add("AddItem", (void(*)(NPC*, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_NPC_AddItem); + package.add("AddLootTable", (void(*)(NPC*))&Perl_NPC_AddLootTable); + package.add("AddLootTable", (void(*)(NPC*, uint32))&Perl_NPC_AddLootTable); + package.add("AddMeleeProc", &Perl_NPC_AddMeleeProc); + package.add("AddRangedProc", &Perl_NPC_AddRangedProc); + package.add("AssignWaypoints", &Perl_NPC_AssignWaypoints); + package.add("CalculateNewWaypoint", &Perl_NPC_CalculateNewWaypoint); + package.add("ChangeLastName", &Perl_NPC_ChangeLastName); + package.add("CheckNPCFactionAlly", &Perl_NPC_CheckNPCFactionAlly); + package.add("ClearItemList", &Perl_NPC_ClearItemList); + package.add("ClearLastName", &Perl_NPC_ClearLastName); + package.add("CountItem", &Perl_NPC_CountItem); + package.add("CountLoot", &Perl_NPC_CountLoot); + package.add("DisplayWaypointInfo", &Perl_NPC_DisplayWaypointInfo); + package.add("DoClassAttacks", &Perl_NPC_DoClassAttacks); + package.add("GetAccuracyRating", &Perl_NPC_GetAccuracyRating); + package.add("GetAttackDelay", &Perl_NPC_GetAttackDelay); + package.add("GetAttackSpeed", &Perl_NPC_GetAttackSpeed); + package.add("GetAvoidanceRating", &Perl_NPC_GetAvoidanceRating); + package.add("GetCombatState", &Perl_NPC_GetCombatState); + package.add("GetCopper", &Perl_NPC_GetCopper); + package.add("GetFirstSlotByItemID", &Perl_NPC_GetFirstSlotByItemID); + package.add("GetGold", &Perl_NPC_GetGold); + package.add("GetGrid", &Perl_NPC_GetGrid); + package.add("GetGuardPointX", &Perl_NPC_GetGuardPointX); + package.add("GetGuardPointY", &Perl_NPC_GetGuardPointY); + package.add("GetGuardPointZ", &Perl_NPC_GetGuardPointZ); + package.add("GetHealScale", &Perl_NPC_GetHealScale); + package.add("GetItemIDBySlot", &Perl_NPC_GetItemIDBySlot); + package.add("GetKeepsSoldItems", &Perl_NPC_GetKeepsSoldItems); + package.add("GetLootList", &Perl_NPC_GetLootList); + package.add("GetLoottableID", &Perl_NPC_GetLoottableID); + package.add("GetMaxDMG", &Perl_NPC_GetMaxDMG); + package.add("GetMaxDamage", &Perl_NPC_GetMaxDamage); + package.add("GetMaxWp", &Perl_NPC_GetMaxWp); + package.add("GetMinDMG", &Perl_NPC_GetMinDMG); + package.add("GetNPCFactionID", &Perl_NPC_GetNPCFactionID); + package.add("GetNPCHate", &Perl_NPC_GetNPCHate); + package.add("GetNPCSpellsID", &Perl_NPC_GetNPCSpellsID); + package.add("GetNPCStat", &Perl_NPC_GetNPCStat); + package.add("GetPetSpellID", &Perl_NPC_GetPetSpellID); + package.add("GetPlatinum", &Perl_NPC_GetPlatinum); + package.add("GetPrimSkill", &Perl_NPC_GetPrimSkill); + package.add("GetPrimaryFaction", &Perl_NPC_GetPrimaryFaction); + package.add("GetScore", &Perl_NPC_GetScore); + package.add("GetSecSkill", &Perl_NPC_GetSecSkill); + package.add("GetSilver", &Perl_NPC_GetSilver); + package.add("GetSlowMitigation", &Perl_NPC_GetSlowMitigation); + package.add("GetSp2", &Perl_NPC_GetSp2); + package.add("GetSpawnKillCount", &Perl_NPC_GetSpawnKillCount); + package.add("GetSpawnPointH", &Perl_NPC_GetSpawnPointH); + package.add("GetSpawnPointID", &Perl_NPC_GetSpawnPointID); + package.add("GetSpawnPointX", &Perl_NPC_GetSpawnPointX); + package.add("GetSpawnPointY", &Perl_NPC_GetSpawnPointY); + package.add("GetSpawnPointZ", &Perl_NPC_GetSpawnPointZ); + package.add("GetSpellFocusDMG", &Perl_NPC_GetSpellFocusDMG); + package.add("GetSpellFocusHeal", &Perl_NPC_GetSpellFocusHeal); + package.add("GetSpellScale", &Perl_NPC_GetSpellScale); + package.add("GetSwarmOwner", &Perl_NPC_GetSwarmOwner); + package.add("GetSwarmTarget", &Perl_NPC_GetSwarmTarget); + package.add("GetWaypointMax", &Perl_NPC_GetWaypointMax); + package.add("HasAISpellEffect", &Perl_NPC_HasAISpellEffect); + package.add("HasItem", &Perl_NPC_HasItem); + package.add("IsAnimal", &Perl_NPC_IsAnimal); + package.add("IsGuarding", &Perl_NPC_IsGuarding); + package.add("IsOnHatelist", &Perl_NPC_IsOnHatelist); + package.add("IsRaidTarget", &Perl_NPC_IsRaidTarget); + package.add("IsRareSpawn", &Perl_NPC_IsRareSpawn); + package.add("IsTaunting", &Perl_NPC_IsTaunting); + package.add("MerchantCloseShop", &Perl_NPC_MerchantCloseShop); + package.add("MerchantOpenShop", &Perl_NPC_MerchantOpenShop); + package.add("ModifyNPCStat", &Perl_NPC_ModifyNPCStat); + package.add("MoveTo", (void(*)(NPC*, float, float, float))&Perl_NPC_MoveTo); + package.add("MoveTo", (void(*)(NPC*, float, float, float, float))&Perl_NPC_MoveTo); + package.add("MoveTo", (void(*)(NPC*, float, float, float, float, bool))&Perl_NPC_MoveTo); + package.add("NextGuardPosition", &Perl_NPC_NextGuardPosition); + package.add("PauseWandering", &Perl_NPC_PauseWandering); + package.add("PickPocket", &Perl_NPC_PickPocket); + package.add("RecalculateSkills", &Perl_NPC_RecalculateSkills); + package.add("ReloadSpells", &Perl_NPC_ReloadSpells); + package.add("RemoveAISpell", &Perl_NPC_RemoveSpellFromNPCList); + package.add("RemoveAISpellEffect", &Perl_NPC_RemoveAISpellEffect); + package.add("RemoveCash", &Perl_NPC_RemoveCash); + package.add("RemoveDefensiveProc", &Perl_NPC_RemoveDefensiveProc); + package.add("RemoveFromHateList", &Perl_NPC_RemoveFromHateList); + package.add("RemoveItem", (void(*)(NPC*, uint32))&Perl_NPC_RemoveItem); + package.add("RemoveItem", (void(*)(NPC*, uint32, uint16))&Perl_NPC_RemoveItem); + package.add("RemoveItem", (void(*)(NPC*, uint32, uint16, uint16))&Perl_NPC_RemoveItem); + package.add("RemoveMeleeProc", &Perl_NPC_RemoveMeleeProc); + package.add("RemoveRangedProc", &Perl_NPC_RemoveRangedProc); + package.add("ResumeWandering", &Perl_NPC_ResumeWandering); + package.add("SaveGuardSpot", (void(*)(NPC*))&Perl_NPC_SaveGuardSpot); + package.add("SaveGuardSpot", (void(*)(NPC*, bool))&Perl_NPC_SaveGuardSpot); + package.add("SaveGuardSpot", (void(*)(NPC*, float, float, float, float))&Perl_NPC_SaveGuardSpot); + package.add("ScaleNPC", &Perl_NPC_ScaleNPC); + package.add("SendPayload", (void(*)(NPC*, int))&Perl_NPC_SendPayload); + package.add("SendPayload", (void(*)(NPC*, int, std::string))&Perl_NPC_SendPayload); + package.add("SetCopper", &Perl_NPC_SetCopper); + package.add("SetKeepsSoldItems", &Perl_NPC_SetKeepsSoldItems); + package.add("SetGold", &Perl_NPC_SetGold); + package.add("SetGrid", &Perl_NPC_SetGrid); + package.add("SetNPCFactionID", &Perl_NPC_SetNPCFactionID); + package.add("SetPetSpellID", &Perl_NPC_SetPetSpellID); + package.add("SetPlatinum", &Perl_NPC_SetPlatinum); + package.add("SetPrimSkill", &Perl_NPC_SetPrimSkill); + package.add("SetSaveWaypoint", &Perl_NPC_SetSaveWaypoint); + package.add("SetSecSkill", &Perl_NPC_SetSecSkill); + package.add("SetSilver", &Perl_NPC_SetSilver); + package.add("SetSimpleRoamBox", &Perl_NPC_SetSimpleRoamBox); + package.add("SetSp2", &Perl_NPC_SetSp2); + package.add("SetSpellFocusDMG", &Perl_NPC_SetSpellFocusDMG); + package.add("SetSpellFocusHeal", &Perl_NPC_SetSpellFocusHeal); + package.add("SetSwarmTarget", &Perl_NPC_SetSwarmTarget); + package.add("SetTaunting", &Perl_NPC_SetTaunting); + package.add("SetWaypointPause", &Perl_NPC_SetWaypointPause); + package.add("SignalNPC", &Perl_NPC_SignalNPC); + package.add("StartSwarmTimer", &Perl_NPC_StartSwarmTimer); + package.add("StopWandering", &Perl_NPC_StopWandering); + package.add("UpdateWaypoint", &Perl_NPC_UpdateWaypoint); } #endif //EMBPERL_XS_CLASSES - diff --git a/zone/perl_object.cpp b/zone/perl_object.cpp index 13b26391e..0b744f93e 100644 --- a/zone/perl_object.cpp +++ b/zone/perl_object.cpp @@ -4,756 +4,297 @@ #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "object.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif +bool Perl_Object_IsGroundSpawn(Object* self) // @categories Objects +{ + return self->IsGroundSpawn(); +} -#define VALIDATE_THIS_IS_OBJECT \ - do { \ - if (sv_derived_from(ST(0), "Object")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Object*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Object"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); +void Perl_Object_Close(Object* self) // @categories Objects +{ + self->Close(); +} -XS(XS_Object_IsGroundSpawn); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_IsGroundSpawn) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::IsGroundSpawn(THIS)"); // @categories Objects - { - Object *THIS; - bool RETVAL; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->IsGroundSpawn(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); +void Perl_Object_Delete(Object* self) // @categories Objects +{ + self->Delete(); +} + +void Perl_Object_Delete(Object* self, bool reset_state) // @categories Objects +{ + self->Delete(reset_state); +} + +void Perl_Object_StartDecay(Object* self) // @categories Objects +{ + self->StartDecay(); +} + +void Perl_Object_DeleteItem(Object* self, uint8_t index) // @categories Objects +{ + self->DeleteItem(index); +} + +bool Perl_Object_IsObject(Object* self) // @categories Objects +{ + return self->IsObject(); +} + +bool Perl_Object_Save(Object* self) // @categories Objects +{ + return self->Save(); +} + +void Perl_Object_SetID(Object* self, uint16_t set_id) // @categories Objects +{ + self->SetID(set_id); +} + +void Perl_Object_ClearUser(Object* self) // @categories Objects +{ + self->ClearUser(); +} + +uint32_t Perl_Object_GetDBID(Object* self) // @categories Objects +{ + return self->GetDBID(); +} + +uint32_t Perl_Object_GetID(Object* self) // @categories Objects +{ + return self->GetID(); +} + +float Perl_Object_GetX(Object* self) // @categories Objects +{ + return self->GetX(); +} + +float Perl_Object_GetY(Object* self) // @categories Objects +{ + return self->GetY(); +} + +float Perl_Object_GetZ(Object* self) // @categories Objects +{ + return self->GetZ(); +} + +float Perl_Object_GetHeading(Object* self) // @categories Objects +{ + return self->GetHeadingData(); +} + +uint32_t Perl_Object_VarSave(Object* self) // @categories Objects +{ + return self->VarSave(); +} + +uint32_t Perl_Object_GetType(Object* self) // @categories Objects +{ + return self->GetType(); +} + +void Perl_Object_SetType(Object* self, uint32_t type) // @categories Objects +{ + self->SetType(type); +} + +uint32_t Perl_Object_GetIcon(Object* self) // @categories Objects +{ + return self->GetIcon(); +} + +void Perl_Object_SetIcon(Object* self, uint32_t icon) // @categories Objects +{ + self->SetIcon(icon); +} + +uint32_t Perl_Object_GetItemID(Object* self) // @categories Objects +{ + return self->GetItemID(); +} + +void Perl_Object_SetItemID(Object* self, uint32_t itemid) // @categories Objects +{ + self->SetItemID(itemid); +} + +void Perl_Object_SetLocation(Object* self, float x, float y, float z) // @categories Objects +{ + self->SetLocation(x, y, z); +} + +void Perl_Object_SetX(Object* self, float x) // @categories Objects +{ + self->SetX(x); +} + +void Perl_Object_SetY(Object* self, float y) // @categories Objects +{ + self->SetY(y); +} + +void Perl_Object_SetZ(Object* self, float z) // @categories Objects +{ + self->SetZ(z); +} + +void Perl_Object_SetHeading(Object* self, float heading) // @categories Objects +{ + self->SetHeading(heading); +} + +void Perl_Object_SetModelName(Object* self, const char* name) // @categories Objects +{ + self->SetModelName(name); +} + +std::string Perl_Object_GetModelName(Object* self) // @categories Objects +{ + return self->GetModelName(); +} + +void Perl_Object_Repop(Object* self) // @categories Objects +{ + self->Repop(); +} + +void Perl_Object_Depop(Object* self) // @categories Objects +{ + self->Depop(); +} + +uint32_t Perl_Object_GetSolidType(Object* self) // @categories Objects +{ + return self->GetSolidType(); +} + +void Perl_Object_SetSolidType(Object* self, uint16_t type) // @categories Objects +{ + self->SetSolidType(type); +} + +float Perl_Object_GetSize(Object* self) // @categories Objects +{ + return self->GetSize(); +} + +void Perl_Object_SetSize(Object* self, float size) // @categories Objects +{ + self->SetSize(size); +} + +void Perl_Object_SetTiltX(Object* self, float tilt_x) // @categories Objects +{ + self->SetTiltX(tilt_x); +} + +void Perl_Object_SetTiltY(Object* self, float tilt_y) // @categories Objects +{ + self->SetTiltY(tilt_y); +} + +float Perl_Object_GetTiltX(Object* self) // @categories Objects +{ + return self->GetTiltX(); +} + +float Perl_Object_GetTiltY(Object* self) // @categories Objects +{ + return self->GetTiltY(); +} + +bool Perl_Object_ClearEntityVariables(Object* self) // @categories Script Utility +{ + return self->ClearEntityVariables(); +} + +bool Perl_Object_DeleteEntityVariable(Object* self, std::string variable_name) // @categories Script Utility +{ + return self->DeleteEntityVariable(variable_name); +} + +bool Perl_Object_EntityVariableExists(Object* self, std::string variable_name) // @categories Objects +{ + return self->EntityVariableExists(variable_name); +} + +std::string Perl_Object_GetEntityVariable(Object* self, std::string variable_name) // @categories Objects +{ + return self->GetEntityVariable(variable_name); +} + +perl::array Perl_Object_GetEntityVariables(Object* self) // @categories Script Utility +{ + perl::array a; + + const auto& l = self->GetEntityVariables(); + for (const auto& v : l) { + a.push_back(v); } - XSRETURN(1); + + return a; } - -XS(XS_Object_Close); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_Close) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::Close(THIS)"); // @categories Objects - { - Object *THIS; - VALIDATE_THIS_IS_OBJECT; - THIS->Close(); - } - XSRETURN_EMPTY; +void Perl_Object_SetEntityVariable(Object* self, std::string variable_name, std::string variable_value) // @categories Objects +{ + self->SetEntityVariable(variable_name, variable_value); } +void perl_register_object() +{ + perl::interpreter perl(PERL_GET_THX); -XS(XS_Object_Delete); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_Delete) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Object::Delete(THIS, [bool reset_state = false])"); // @categories Objects - { - Object *THIS; - bool reset_state; - VALIDATE_THIS_IS_OBJECT; - if (items < 2) - reset_state = false; - else { - reset_state = (bool) SvTRUE(ST(1)); - } - - THIS->Delete(reset_state); - } - XSRETURN_EMPTY; -} -XS(XS_Object_StartDecay); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_StartDecay) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::StartDecay(THIS)"); // @categories Objects - { - Object *THIS; - VALIDATE_THIS_IS_OBJECT; - THIS->StartDecay(); - } - XSRETURN_EMPTY; + auto package = perl.new_class("Object"); + package.add_base_class("Entity"); + package.add("ClearEntityVariables", &Perl_Object_ClearEntityVariables); + package.add("ClearUser", &Perl_Object_ClearUser); + package.add("Close", &Perl_Object_Close); + package.add("Delete", (void(*)(Object*))&Perl_Object_Delete); + package.add("Delete", (void(*)(Object*, bool))&Perl_Object_Delete); + package.add("DeleteEntityVariable", &Perl_Object_DeleteEntityVariable); + package.add("DeleteItem", &Perl_Object_DeleteItem); + package.add("Depop", &Perl_Object_Depop); + package.add("EntityVariableExists", &Perl_Object_EntityVariableExists); + package.add("GetDBID", &Perl_Object_GetDBID); + package.add("GetEntityVariable", &Perl_Object_GetEntityVariable); + package.add("GetEntityVariables", &Perl_Object_GetEntityVariables); + package.add("GetHeading", &Perl_Object_GetHeading); + package.add("GetID", &Perl_Object_GetID); + package.add("GetIcon", &Perl_Object_GetIcon); + package.add("GetItemID", &Perl_Object_GetItemID); + package.add("GetModelName", &Perl_Object_GetModelName); + package.add("GetSize", &Perl_Object_GetSize); + package.add("GetSolidType", &Perl_Object_GetSolidType); + package.add("GetTiltX", &Perl_Object_GetTiltX); + package.add("GetTiltY", &Perl_Object_GetTiltY); + package.add("GetType", &Perl_Object_GetType); + package.add("GetX", &Perl_Object_GetX); + package.add("GetY", &Perl_Object_GetY); + package.add("GetZ", &Perl_Object_GetZ); + package.add("IsGroundSpawn", &Perl_Object_IsGroundSpawn); + package.add("IsObject", &Perl_Object_IsObject); + package.add("Repop", &Perl_Object_Repop); + package.add("Save", &Perl_Object_Save); + package.add("SetEntityVariable", &Perl_Object_SetEntityVariable); + package.add("SetHeading", &Perl_Object_SetHeading); + package.add("SetID", &Perl_Object_SetID); + package.add("SetIcon", &Perl_Object_SetIcon); + package.add("SetItemID", &Perl_Object_SetItemID); + package.add("SetLocation", &Perl_Object_SetLocation); + package.add("SetModelName", &Perl_Object_SetModelName); + package.add("SetSize", &Perl_Object_SetSize); + package.add("SetSolidType", &Perl_Object_SetSolidType); + package.add("SetTiltX", &Perl_Object_SetTiltX); + package.add("SetTiltY", &Perl_Object_SetTiltY); + package.add("SetType", &Perl_Object_SetType); + package.add("SetX", &Perl_Object_SetX); + package.add("SetY", &Perl_Object_SetY); + package.add("SetZ", &Perl_Object_SetZ); + package.add("StartDecay", &Perl_Object_StartDecay); + package.add("VarSave", &Perl_Object_VarSave); } - -XS(XS_Object_DeleteItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_DeleteItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::DeleteItem(THIS, uint8 index)"); // @categories Objects - { - Object *THIS; - uint8 index = (uint8) SvUV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->DeleteItem(index); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_IsObject); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_IsObject) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::IsObject(THIS)"); // @categories Objects - { - Object *THIS; - bool RETVAL; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->IsObject(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - - -XS(XS_Object_Save); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_Save) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::Save(THIS)"); // @categories Objects - { - Object *THIS; - bool RETVAL; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->Save(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - - -XS(XS_Object_SetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetID(THIS, uint16 id)"); // @categories Objects - { - Object *THIS; - uint16 set_id = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetID(set_id); - } - XSRETURN_EMPTY; -} - - -XS(XS_Object_ClearUser); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_ClearUser) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::ClearUser(THIS)"); // @categories Objects - { - Object *THIS; - VALIDATE_THIS_IS_OBJECT; - THIS->ClearUser(); - } - XSRETURN_EMPTY; -} - - -XS(XS_Object_GetDBID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetDBID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetDBID(THIS)"); // @categories Objects - { - Object *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetDBID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Object_GetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetID(THIS)"); // @categories Objects - { - Object *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Object_GetX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetX(THIS)"); // @categories Objects - { - Object *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetX(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Object_GetY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetY(THIS)"); // @categories Objects - { - Object *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetY(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Object_GetZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetZ) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetZ(THIS)"); // @categories Objects - { - Object *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetZ(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Object_GetHeading); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetHeading) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetHeading(THIS)"); // @categories Objects - { - Object *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetHeadingData(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Object_VarSave); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_VarSave) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::VarSave(THIS)"); // @categories Objects - { - Object *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->VarSave(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Object_GetType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetType(THIS)"); // @categories Objects - { - Object *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetType(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Object_SetType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetType) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetType(THIS, uint32 type)"); // @categories Objects - { - Object *THIS; - uint32 type = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetType(type); - } - XSRETURN_EMPTY; -} - - -XS(XS_Object_GetIcon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetIcon) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetIcon(THIS)"); // @categories Objects - { - Object *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetIcon(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Object_SetIcon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetIcon) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetIcon(THIS, uint32 icon)"); // @categories Objects - { - Object *THIS; - uint32 icon = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetIcon(icon); - } - XSRETURN_EMPTY; -} - - -XS(XS_Object_GetItemID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetItemID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetItemID(THIS)"); // @categories Objects - { - Object *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetItemID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Object_SetItemID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetItemID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetItemID(THIS, uint32 item_id)"); // @categories Objects - { - Object *THIS; - uint32 itemid = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetItemID(itemid); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetLocation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetLocation) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Object::SetLocation(THIS, float x, float y, float z)"); // @categories Objects - { - Object *THIS; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetLocation(x, y, z); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetX) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetX(THIS, float x)"); // @categories Objects - { - Object *THIS; - float pos = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetX(pos); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetY) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetY(THIS, float y)"); // @categories Objects - { - Object *THIS; - float pos = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetY(pos); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetZ) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetZ(THIS, float z)"); // @categories Objects - { - Object *THIS; - float pos = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetZ(pos); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetHeading); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetHeading) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetHeading(THIS, float heading)"); // @categories Objects - { - Object *THIS; - float heading = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetHeading(heading); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetModelName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetModelName) { - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: Object::SetModelName(THIS, string name)"); // @categories Objects - { - Object *THIS; - char *name = nullptr; - VALIDATE_THIS_IS_OBJECT; - if (items > 1) { name = (char *) SvPV_nolen(ST(1)); } - - THIS->SetModelName(name); - } - XSRETURN_EMPTY; -} -XS(XS_Object_GetModelName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetModelName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetModelName(THIS)"); // @categories Objects - { - Object *THIS; - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetModelName(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Object_Repop); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_Repop) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::Repop(THIS)"); // @categories Objects - { - Object *THIS; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; THIS->Repop(); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_Depop); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_Depop) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::Depop(THIS)"); // @categories Objects - { - Object *THIS; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; THIS->Depop(); - } - XSRETURN_EMPTY; -} - - -XS(XS_Object_GetEntityVariable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetEntityVariable) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::GetEntityVariable(THIS, string key)"); // @categories Objects - { - Object *THIS; - Const_char *id = SvPV_nolen(ST(1)); - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetEntityVariable(id); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Object_EntityVariableExists); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_EntityVariableExists) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::EntityVariableExists(THIS, string key)"); // @categories Objects - { - Object *THIS; - Const_char *id = SvPV_nolen(ST(1)); - bool RETVAL; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->EntityVariableExists(id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Object_SetEntityVariable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetEntityVariable) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Object::SetEntityVariable(THIS, string key, string var)"); // @categories Objects - { - Object *THIS; - Const_char *id = SvPV_nolen(ST(1)); - const char *var = (const char *) SvPV_nolen(ST(2)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetEntityVariable(id, var); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_GetSolidType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetSolidType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetSolidType(THIS)"); // @categories Objects - { - Object *THIS; - uint16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetSolidType(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Object_SetSolidType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetSolidType) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetSolidType(THIS, uint16 type)"); // @categories Objects - { - Object *THIS; - uint16 type = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetSolidType(type); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_GetSize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetSize) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)"); // @categories Objects - { - Object *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetSize(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - - -XS(XS_Object_SetSize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetSize) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetSize(THIS, float size)"); // @categories Objects - { - Object *THIS; - float size = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetSize(size); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetTiltX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetTiltX) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetTiltX(THIS, float tilt_x)"); // @categories Objects - { - Object *THIS; - float pos = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetTiltX(pos); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_SetTiltY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_SetTiltY) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Object::SetTiltY(THIS, float tilt_y)"); // @categories Objects - { - Object *THIS; - float pos = (float) SvNV(ST(1)); - VALIDATE_THIS_IS_OBJECT; - THIS->SetTiltY(pos); - } - XSRETURN_EMPTY; -} - -XS(XS_Object_GetTiltX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetTiltX) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetTiltX(THIS)"); // @categories Objects - { - Object *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetTiltX(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -XS(XS_Object_GetTiltY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Object_GetTiltY) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Object::GetTiltY(THIS)"); // @categories Objects - { - Object *THIS; - float RETVAL; - dXSTARG; - VALIDATE_THIS_IS_OBJECT; - RETVAL = THIS->GetTiltY(); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); -} - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_Object); /* prototype to pass -Wmissing-prototypes */ -XS(boot_Object) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "ClearUser"), XS_Object_ClearUser, file, "$"); - newXSproto(strcpy(buf, "Close"), XS_Object_Close, file, "$"); - newXSproto(strcpy(buf, "Delete"), XS_Object_Delete, file, "$$"); - newXSproto(strcpy(buf, "DeleteItem"), XS_Object_DeleteItem, file, "$$"); - newXSproto(strcpy(buf, "Depop"), XS_Object_Depop, file, "$"); - newXSproto(strcpy(buf, "EntityVariableExists"), XS_Object_EntityVariableExists, file, "$$"); - newXSproto(strcpy(buf, "GetDBID"), XS_Object_GetDBID, file, "$"); - newXSproto(strcpy(buf, "GetEntityVariable"), XS_Object_GetEntityVariable, file, "$$"); - newXSproto(strcpy(buf, "GetHeading"), XS_Object_GetHeading, file, "$"); - newXSproto(strcpy(buf, "GetID"), XS_Object_GetID, file, "$"); - newXSproto(strcpy(buf, "GetIcon"), XS_Object_GetIcon, file, "$"); - newXSproto(strcpy(buf, "GetItemID"), XS_Object_GetItemID, file, "$"); - newXSproto(strcpy(buf, "GetModelName"), XS_Object_GetModelName, file, "$"); - newXSproto(strcpy(buf, "GetSize"), XS_Object_GetSize, file, "$"); - newXSproto(strcpy(buf, "GetSolidType"), XS_Object_GetSolidType, file, "$"); - newXSproto(strcpy(buf, "GetTiltX"), XS_Object_GetTiltX, file, "$$"); - newXSproto(strcpy(buf, "GetTiltY"), XS_Object_GetTiltY, file, "$"); - newXSproto(strcpy(buf, "GetType"), XS_Object_GetType, file, "$"); - newXSproto(strcpy(buf, "GetX"), XS_Object_GetX, file, "$"); - newXSproto(strcpy(buf, "GetY"), XS_Object_GetY, file, "$"); - newXSproto(strcpy(buf, "GetZ"), XS_Object_GetZ, file, "$"); - newXSproto(strcpy(buf, "IsGroundSpawn"), XS_Object_IsGroundSpawn, file, "$"); - newXSproto(strcpy(buf, "Repop"), XS_Object_Repop, file, "$"); - newXSproto(strcpy(buf, "Save"), XS_Object_Save, file, "$"); - newXSproto(strcpy(buf, "SetEntityVariable"), XS_Object_SetEntityVariable, file, "$$$"); - newXSproto(strcpy(buf, "SetHeading"), XS_Object_SetHeading, file, "$$"); - newXSproto(strcpy(buf, "SetID"), XS_Object_SetID, file, "$$"); - newXSproto(strcpy(buf, "SetIcon"), XS_Object_SetIcon, file, "$$"); - newXSproto(strcpy(buf, "SetItemID"), XS_Object_SetItemID, file, "$$"); - newXSproto(strcpy(buf, "SetLocation"), XS_Object_SetLocation, file, "$$$$"); - newXSproto(strcpy(buf, "SetModelName"), XS_Object_SetModelName, file, "$$"); - newXSproto(strcpy(buf, "SetSize"), XS_Object_SetSize, file, "$$"); - newXSproto(strcpy(buf, "SetSolidType"), XS_Object_SetSolidType, file, "$$"); - newXSproto(strcpy(buf, "SetTiltX"), XS_Object_SetTiltX, file, "$$"); - newXSproto(strcpy(buf, "SetTiltY"), XS_Object_SetTiltY, file, "$"); - newXSproto(strcpy(buf, "SetType"), XS_Object_SetType, file, "$$"); - newXSproto(strcpy(buf, "SetX"), XS_Object_SetX, file, "$$"); - newXSproto(strcpy(buf, "SetY"), XS_Object_SetY, file, "$$"); - newXSproto(strcpy(buf, "SetZ"), XS_Object_SetZ, file, "$$"); - newXSproto(strcpy(buf, "StartDecay"), XS_Object_StartDecay, file, "$$"); - newXSproto(strcpy(buf, "VarSave"), XS_Object_VarSave, file, "$"); - XSRETURN_YES; -} #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_perlpacket.cpp b/zone/perl_perlpacket.cpp index dd3875e7e..1f0a6411d 100644 --- a/zone/perl_perlpacket.cpp +++ b/zone/perl_perlpacket.cpp @@ -3,421 +3,149 @@ #include "../common/global_define.h" #include "../common/types.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "perlpacket.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_PACKET \ - do { \ - if (sv_derived_from(ST(0), "PerlPacket")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(PerlPacket*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type PerlPacket"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_PerlPacket_new); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_new) +PerlPacket* Perl_PerlPacket_new(const char* class_name) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: PerlPacket::new(CLASS, opcode= \"OP_Unknown\", len= 0)"); - { - char *CLASS = (char *)SvPV_nolen(ST(0)); - PerlPacket *RETVAL; - const char *opcode; - uint32 len; - - if (items < 2) - opcode = "OP_Unknown"; - else { - opcode = (char *)SvPV_nolen(ST(1)); - } - - if (items < 3) - len = 0; - else { - len = (uint32)SvUV(ST(2)); - } - - RETVAL = new PerlPacket(opcode, len); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "PerlPacket", (void*)RETVAL); - } - XSRETURN(1); + return new PerlPacket(); } -XS(XS_PerlPacket_DESTROY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_DESTROY) +PerlPacket* Perl_PerlPacket_new(const char* class_name, const char* opcode) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: PerlPacket::DESTROY(THIS)"); - { - PerlPacket * THIS; - VALIDATE_THIS_IS_PACKET; - delete THIS; - } - XSRETURN_EMPTY; + return new PerlPacket(opcode); } -XS(XS_PerlPacket_SetOpcode); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetOpcode) +PerlPacket* Perl_PerlPacket_new(const char* class_name, const char* opcode, uint32_t len) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: PerlPacket::SetOpcode(THIS, opcode)"); - { - PerlPacket * THIS; - bool RETVAL; - char * opcode = (char *)SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_PACKET; - RETVAL = THIS->SetOpcode(opcode); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); + return new PerlPacket(opcode, len); } -XS(XS_PerlPacket_Resize); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_Resize) +void Perl_PerlPacket_DESTROY(PerlPacket* self) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: PerlPacket::Resize(THIS, len)"); - { - PerlPacket * THIS; - uint32 len = (uint32)SvUV(ST(1)); - VALIDATE_THIS_IS_PACKET; - THIS->Resize(len); - } - XSRETURN_EMPTY; + delete self; } -XS(XS_PerlPacket_SendTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SendTo) +bool Perl_PerlPacket_SetOpcode(PerlPacket* self, const char* opcode) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: PerlPacket::SendTo(THIS, who)"); - { - PerlPacket * THIS; - Client * who; - VALIDATE_THIS_IS_PACKET; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - who = INT2PTR(Client *,tmp); - } - else - Perl_croak(aTHX_ "who is not of type Client"); - if(who == nullptr) - Perl_croak(aTHX_ "who is nullptr, avoiding crash."); - - THIS->SendTo(who); - } - XSRETURN_EMPTY; + return self->SetOpcode(opcode); } -XS(XS_PerlPacket_SendToAll); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SendToAll) +void Perl_PerlPacket_Resize(PerlPacket* self, uint32_t len) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: PerlPacket::SendToAll(THIS)"); - { - PerlPacket * THIS; - VALIDATE_THIS_IS_PACKET; - THIS->SendToAll(); - } - XSRETURN_EMPTY; + self->Resize(len); } -XS(XS_PerlPacket_Zero); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_Zero) +void Perl_PerlPacket_SendTo(PerlPacket* self, Client* who) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: PerlPacket::Zero(THIS)"); - { - PerlPacket * THIS; - VALIDATE_THIS_IS_PACKET; - THIS->Zero(); - } - XSRETURN_EMPTY; + self->SendTo(who); } -XS(XS_PerlPacket_FromArray); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_FromArray) +void Perl_PerlPacket_SendToAll(PerlPacket* self) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: PerlPacket::FromArray(THIS, numbers, length)"); - { - PerlPacket * THIS; - int * numbers; - uint32 length = (uint32)SvUV(ST(2)); - VALIDATE_THIS_IS_PACKET; - AV *av_numbers; - if (SvROK(ST(1)) && SvTYPE(SvRV(ST(1)))==SVt_PVAV) - av_numbers = (AV*)SvRV(ST(1)); - else - Perl_croak(aTHX_ "numbers is not an array reference"); - I32 len_numbers = av_len(av_numbers) + 1; - I32 ix_numbers; - numbers = new int[len_numbers]; - for(ix_numbers = 0; ix_numbers < len_numbers; ix_numbers ++) { - SV **tmp = av_fetch(av_numbers, ix_numbers, 0); - if(tmp == nullptr || *tmp == nullptr) { - numbers[ix_numbers] = 0; - continue; - } - numbers[ix_numbers] = (int)SvIV(*tmp); - }; - - THIS->FromArray(numbers, length); - } - XSRETURN_EMPTY; + self->SendToAll(); } -XS(XS_PerlPacket_SetByte); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetByte) +void Perl_PerlPacket_Zero(PerlPacket* self) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: PerlPacket::SetByte(THIS, pos, val)"); - { - PerlPacket * THIS; - uint32 pos = (uint32)SvUV(ST(1)); - uint8 val = (uint8)SvUV(ST(2)); - VALIDATE_THIS_IS_PACKET; - THIS->SetByte(pos, val); - } - XSRETURN_EMPTY; + self->Zero(); } -XS(XS_PerlPacket_SetShort); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetShort) +void Perl_PerlPacket_FromArray(PerlPacket* self, perl::reference avref, uint32_t length) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: PerlPacket::SetShort(THIS, pos, val)"); + perl::array av_numbers = avref; + int* numbers = new int[av_numbers.size()]; + + for (int i = 0; i < av_numbers.size(); ++i) { - PerlPacket * THIS; - uint32 pos = (uint32)SvUV(ST(1)); - uint16 val = (uint16)SvUV(ST(2)); - VALIDATE_THIS_IS_PACKET; - THIS->SetShort(pos, val); + numbers[i] = av_numbers[i]; } - XSRETURN_EMPTY; + + self->FromArray(numbers, length); + + delete[] numbers; } -XS(XS_PerlPacket_SetLong); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetLong) +void Perl_PerlPacket_SetByte(PerlPacket* self, uint32_t pos, uint8_t val) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: PerlPacket::SetLong(THIS, pos, val)"); - { - PerlPacket * THIS; - uint32 pos = (uint32)SvUV(ST(1)); - uint32 val = (uint32)SvUV(ST(2)); - VALIDATE_THIS_IS_PACKET; - THIS->SetLong(pos, val); - } - XSRETURN_EMPTY; + self->SetByte(pos, val); } -XS(XS_PerlPacket_SetFloat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetFloat) +void Perl_PerlPacket_SetShort(PerlPacket* self, uint32_t pos, uint16_t val) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: PerlPacket::SetFloat(THIS, pos, val)"); - { - PerlPacket * THIS; - uint32 pos = (uint32)SvUV(ST(1)); - float val = (float)SvNV(ST(2)); - VALIDATE_THIS_IS_PACKET; - THIS->SetFloat(pos, val); - } - XSRETURN_EMPTY; + self->SetShort(pos, val); } -XS(XS_PerlPacket_SetString); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetString) +void Perl_PerlPacket_SetLong(PerlPacket* self, uint32_t pos, uint32_t val) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: PerlPacket::SetString(THIS, pos, str)"); - { - PerlPacket * THIS; - uint32 pos = (uint32)SvUV(ST(1)); - char * str = (char *)SvPV_nolen(ST(2)); - VALIDATE_THIS_IS_PACKET; - THIS->SetString(pos, str); - } - XSRETURN_EMPTY; + self->SetLong(pos, val); } -XS(XS_PerlPacket_SetEQ1319); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetEQ1319) +void Perl_PerlPacket_SetFloat(PerlPacket* self, uint32_t pos, float val) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: PerlPacket::SetEQ1319(THIS, pos, part13, part19)"); - { - PerlPacket * THIS; - uint32 pos = (uint32)SvUV(ST(1)); - float part13 = (float)SvNV(ST(2)); - float part19 = (float)SvNV(ST(3)); - VALIDATE_THIS_IS_PACKET; - THIS->SetEQ1319(pos, part13, part19); - } - XSRETURN_EMPTY; + self->SetFloat(pos, val); } -XS(XS_PerlPacket_SetEQ1913); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_SetEQ1913) +void Perl_PerlPacket_SetString(PerlPacket* self, uint32_t pos, char* str) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: PerlPacket::SetEQ1913(THIS, pos, part19, part13)"); - { - PerlPacket * THIS; - uint32 pos = (uint32)SvUV(ST(1)); - float part19 = (float)SvNV(ST(2)); - float part13 = (float)SvNV(ST(3)); - VALIDATE_THIS_IS_PACKET; - THIS->SetEQ1913(pos, part19, part13); - } - XSRETURN_EMPTY; + self->SetString(pos, str); } -XS(XS_PerlPacket_GetByte); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_GetByte) +void Perl_PerlPacket_SetEQ1319(PerlPacket* self, uint32_t pos, float part13, float part19) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: PerlPacket::GetByte(THIS, pos)"); - { - PerlPacket * THIS; - uint8 RETVAL; - dXSTARG; - uint32 pos = (uint32)SvUV(ST(1)); - VALIDATE_THIS_IS_PACKET; - RETVAL = THIS->GetByte(pos); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); + self->SetEQ1319(pos, part13, part19); } -XS(XS_PerlPacket_GetShort); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_GetShort) +void Perl_PerlPacket_SetEQ1913(PerlPacket* self, uint32_t pos, float part19, float part13) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: PerlPacket::GetShort(THIS, pos)"); - { - PerlPacket * THIS; - uint16 RETVAL; - dXSTARG; - uint32 pos = (uint32)SvUV(ST(1)); - VALIDATE_THIS_IS_PACKET; - RETVAL = THIS->GetShort(pos); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); + self->SetEQ1913(pos, part19, part13); } -XS(XS_PerlPacket_GetLong); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_GetLong) +uint8_t Perl_PerlPacket_GetByte(PerlPacket* self, uint32_t pos) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: PerlPacket::GetLong(THIS, pos)"); - { - PerlPacket * THIS; - uint32 RETVAL; - dXSTARG; - uint32 pos = (uint32)SvUV(ST(1)); - VALIDATE_THIS_IS_PACKET; - RETVAL = THIS->GetLong(pos); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); + return self->GetByte(pos); } -XS(XS_PerlPacket_GetFloat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_PerlPacket_GetFloat) +uint16_t Perl_PerlPacket_GetShort(PerlPacket* self, uint32_t pos) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: PerlPacket::GetFloat(THIS, pos)"); - { - PerlPacket * THIS; - float RETVAL; - dXSTARG; - uint32 pos = (uint32)SvUV(ST(1)); - VALIDATE_THIS_IS_PACKET; - RETVAL = THIS->GetFloat(pos); - XSprePUSH; - PUSHn((double) RETVAL); - } - XSRETURN(1); + return self->GetShort(pos); } -#ifdef __cplusplus -extern "C" -#endif -XS(boot_PerlPacket); /* prototype to pass -Wmissing-prototypes */ -XS(boot_PerlPacket) +uint32_t Perl_PerlPacket_GetLong(PerlPacket* self, uint32_t pos) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; + return self->GetLong(pos); +} - if(items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; +float Perl_PerlPacket_GetFloat(PerlPacket* self, uint32_t pos) +{ + return self->GetFloat(pos); +} - //add the strcpy stuff to get rid of const warnings.... +void perl_register_perlpacket() +{ + perl::interpreter perl(PERL_GET_THX); - XS_VERSION_BOOTCHECK ; - newXSproto(strcpy(buf, "DESTROY"), XS_PerlPacket_DESTROY, file, "$"); - newXSproto(strcpy(buf, "FromArray"), XS_PerlPacket_FromArray, file, "$$$"); - newXSproto(strcpy(buf, "GetByte"), XS_PerlPacket_GetByte, file, "$$"); - newXSproto(strcpy(buf, "GetFloat"), XS_PerlPacket_GetFloat, file, "$$"); - newXSproto(strcpy(buf, "GetLong"), XS_PerlPacket_GetLong, file, "$$"); - newXSproto(strcpy(buf, "GetShort"), XS_PerlPacket_GetShort, file, "$$"); - newXSproto(strcpy(buf, "Resize"), XS_PerlPacket_Resize, file, "$$"); - newXSproto(strcpy(buf, "SendTo"), XS_PerlPacket_SendTo, file, "$$"); - newXSproto(strcpy(buf, "SendToAll"), XS_PerlPacket_SendToAll, file, "$"); - newXSproto(strcpy(buf, "SetByte"), XS_PerlPacket_SetByte, file, "$$$"); - newXSproto(strcpy(buf, "SetEQ1319"), XS_PerlPacket_SetEQ1319, file, "$$$$"); - newXSproto(strcpy(buf, "SetEQ1913"), XS_PerlPacket_SetEQ1913, file, "$$$$"); - newXSproto(strcpy(buf, "SetFloat"), XS_PerlPacket_SetFloat, file, "$$$"); - newXSproto(strcpy(buf, "SetLong"), XS_PerlPacket_SetLong, file, "$$$"); - newXSproto(strcpy(buf, "SetOpcode"), XS_PerlPacket_SetOpcode, file, "$$"); - newXSproto(strcpy(buf, "SetShort"), XS_PerlPacket_SetShort, file, "$$$"); - newXSproto(strcpy(buf, "SetString"), XS_PerlPacket_SetString, file, "$$$"); - newXSproto(strcpy(buf, "Zero"), XS_PerlPacket_Zero, file, "$"); - newXSproto(strcpy(buf, "new"), XS_PerlPacket_new, file, "$;$$"); - XSRETURN_YES; + auto package = perl.new_class("PerlPacket"); + package.add("DESTROY", &Perl_PerlPacket_DESTROY); + package.add("FromArray", &Perl_PerlPacket_FromArray); + package.add("GetByte", &Perl_PerlPacket_GetByte); + package.add("GetFloat", &Perl_PerlPacket_GetFloat); + package.add("GetLong", &Perl_PerlPacket_GetLong); + package.add("GetShort", &Perl_PerlPacket_GetShort); + package.add("Resize", &Perl_PerlPacket_Resize); + package.add("SendTo", &Perl_PerlPacket_SendTo); + package.add("SendToAll", &Perl_PerlPacket_SendToAll); + package.add("SetByte", &Perl_PerlPacket_SetByte); + package.add("SetEQ1319", &Perl_PerlPacket_SetEQ1319); + package.add("SetEQ1913", &Perl_PerlPacket_SetEQ1913); + package.add("SetFloat", &Perl_PerlPacket_SetFloat); + package.add("SetLong", &Perl_PerlPacket_SetLong); + package.add("SetOpcode", &Perl_PerlPacket_SetOpcode); + package.add("SetShort", &Perl_PerlPacket_SetShort); + package.add("SetString", &Perl_PerlPacket_SetString); + package.add("Zero", &Perl_PerlPacket_Zero); + package.add("new", (PerlPacket*(*)(const char*))&Perl_PerlPacket_new); + package.add("new", (PerlPacket*(*)(const char*, const char*))&Perl_PerlPacket_new); + package.add("new", (PerlPacket*(*)(const char*, const char*, uint32_t))&Perl_PerlPacket_new); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_player_corpse.cpp b/zone/perl_player_corpse.cpp index 2306d3d07..6e347b05f 100644 --- a/zone/perl_player_corpse.cpp +++ b/zone/perl_player_corpse.cpp @@ -4,667 +4,244 @@ #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "corpse.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_CORPSE \ - do { \ - if (sv_derived_from(ST(0), "Corpse")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Corpse*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Corpse"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Corpse_GetCharID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetCharID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetCharID(THIS)"); // @categories Account and Character, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetCharID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Corpse_GetCharID(Corpse* self) // @categories Account and Character, Corpse +{ + return self->GetCharID(); } -XS(XS_Corpse_GetDecayTime); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetDecayTime) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetDecayTime(THIS)"); // @categories Script Utility, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetDecayTime(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Corpse_GetDecayTime(Corpse* self) // @categories Script Utility, Corpse +{ + return self->GetDecayTime(); } -XS(XS_Corpse_Lock); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_Lock) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::Lock(THIS)"); // @categories Corpse - { - Corpse *THIS; - VALIDATE_THIS_IS_CORPSE; - THIS->Lock(); - } - XSRETURN_EMPTY; +void Perl_Corpse_Lock(Corpse* self) // @categories Corpse +{ + self->Lock(); } -XS(XS_Corpse_UnLock); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_UnLock) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::UnLock(THIS)"); // @categories Corpse - { - Corpse *THIS; - VALIDATE_THIS_IS_CORPSE; - THIS->UnLock(); - } - XSRETURN_EMPTY; +void Perl_Corpse_UnLock(Corpse* self) // @categories Corpse +{ + self->UnLock(); } -XS(XS_Corpse_IsLocked); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_IsLocked) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::IsLocked(THIS)"); // @categories Corpse - { - Corpse *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->IsLocked(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Corpse_IsLocked(Corpse* self) // @categories Corpse +{ + return self->IsLocked(); } -XS(XS_Corpse_ResetLooter); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_ResetLooter) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::ResetLooter(THIS)"); // @categories Corpse - { - Corpse *THIS; - VALIDATE_THIS_IS_CORPSE; - THIS->ResetLooter(); - } - XSRETURN_EMPTY; +void Perl_Corpse_ResetLooter(Corpse* self) // @categories Corpse +{ + self->ResetLooter(); } -XS(XS_Corpse_GetDBID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetDBID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetDBID(THIS)"); // @categories Script Utility, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetCorpseDBID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Corpse_GetDBID(Corpse* self) // @categories Script Utility, Corpse +{ + return self->GetCorpseDBID(); } -XS(XS_Corpse_GetOwnerName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetOwnerName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetOwnerName(THIS)"); // @categories Account and Character, Corpse - { - Corpse *THIS; - char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetOwnerName(); - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +std::string Perl_Corpse_GetOwnerName(Corpse* self) // @categories Account and Character, Corpse +{ + return self->GetOwnerName(); } -XS(XS_Corpse_SetDecayTimer); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_SetDecayTimer) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::SetDecayTimer(THIS, uint32 decay_time)"); // @categories Corpse - { - Corpse *THIS; - uint32 decaytime = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CORPSE; - THIS->SetDecayTimer(decaytime); - } - XSRETURN_EMPTY; +void Perl_Corpse_ResetDecayTimer(Corpse* self) // @categories Corpse +{ + self->ResetDecayTimer(); } -XS(XS_Corpse_IsEmpty); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_IsEmpty) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::IsEmpty(THIS)"); // @categories Inventory and Items, Corpse - { - Corpse *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->IsEmpty(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Corpse_SetDecayTimer(Corpse* self, uint32_t decay_time) // @categories Corpse +{ + self->SetDecayTimer(decay_time); } -XS(XS_Corpse_AddItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_AddItem) { - dXSARGS; - if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Corpse::AddItem(THIS, uint32 item_id, uint16 charges, [unt16 slot = 0])"); // @categories Inventory and Items, Corpse - { - Corpse *THIS; - uint32 itemnum = (uint32) SvUV(ST(1)); - uint16 charges = (uint16) SvUV(ST(2)); - int16 slot; - VALIDATE_THIS_IS_CORPSE; - if (items < 4) - slot = 0; - else { - slot = (int16) SvIV(ST(3)); - } - - THIS->AddItem(itemnum, charges, slot); - } - XSRETURN_EMPTY; +bool Perl_Corpse_IsEmpty(Corpse* self) // @categories Inventory and Items, Corpse +{ + return self->IsEmpty(); } -XS(XS_Corpse_GetWornItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetWornItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::GetWornItem(THIS, equipSlot)"); // @categories Inventory and Items, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - int16 equipSlot = (int16) SvIV(ST(1)); - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetWornItem(equipSlot); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Corpse_AddItem(Corpse* self, uint32 item_id, uint16 charges) // @categories Inventory and Items, Corpse +{ + self->AddItem(item_id, charges); } -XS(XS_Corpse_RemoveItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_RemoveItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::RemoveItem(THIS, uint16 loot_slot)"); // @categories Inventory and Items, Corpse - { - Corpse *THIS; - uint16 lootslot = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_CORPSE; - THIS->RemoveItem(lootslot); - } - XSRETURN_EMPTY; +void Perl_Corpse_AddItem(Corpse* self, uint32 item_id, uint16 charges, uint16 slot) // @categories Inventory and Items, Corpse +{ + self->AddItem(item_id, charges, slot); } -XS(XS_Corpse_SetCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_SetCash) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: Corpse::SetCash(THIS, uint16 copper, uint16 silver, uint16 gold, uint16 platinum)"); // @categories Currency and Points, Corpse - { - Corpse *THIS; - uint16 in_copper = (uint16) SvUV(ST(1)); - uint16 in_silver = (uint16) SvUV(ST(2)); - uint16 in_gold = (uint16) SvUV(ST(3)); - uint16 in_platinum = (uint16) SvUV(ST(4)); - VALIDATE_THIS_IS_CORPSE; - THIS->SetCash(in_copper, in_silver, in_gold, in_platinum); - } - XSRETURN_EMPTY; +uint32_t Perl_Corpse_GetWornItem(Corpse* self, uint16_t equip_slot) // @categories Inventory and Items, Corpse +{ + return self->GetWornItem(equip_slot); } -XS(XS_Corpse_RemoveCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_RemoveCash) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::RemoveCash(THIS)"); // @categories Currency and Points, Corpse - { - Corpse *THIS; - VALIDATE_THIS_IS_CORPSE; - THIS->RemoveCash(); - } - XSRETURN_EMPTY; +void Perl_Corpse_RemoveItem(Corpse* self, uint16_t loot_slot) // @categories Inventory and Items, Corpse +{ + self->RemoveItem(loot_slot); } -XS(XS_Corpse_CountItems); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_CountItems) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::CountItems(THIS)"); // @categories Inventory and Items, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->CountItems(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Corpse_SetCash(Corpse* self, uint16 copper, uint16 silver, uint16 gold, uint16 platinum) // @categories Currency and Points, Corpse +{ + self->SetCash(copper, silver, gold, platinum); } -XS(XS_Corpse_Delete); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_Delete) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::Delete(THIS)"); // @categories Corpse - { - Corpse *THIS; - VALIDATE_THIS_IS_CORPSE; - THIS->Delete(); - } - XSRETURN_EMPTY; +void Perl_Corpse_RemoveCash(Corpse* self) // @categories Currency and Points, Corpse +{ + self->RemoveCash(); } -XS(XS_Corpse_GetCopper); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetCopper) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetCopper(THIS)"); // @categories Currency and Points, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetCopper(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Corpse_CountItems(Corpse* self) // @categories Inventory and Items, Corpse +{ + return self->CountItems(); } -XS(XS_Corpse_GetSilver); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetSilver) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetSilver(THIS)"); // @categories Currency and Points, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetSilver(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Corpse_Delete(Corpse* self) // @categories Corpse +{ + self->Delete(); } -XS(XS_Corpse_GetGold); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetGold) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetGold(THIS)"); // @categories Currency and Points, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetGold(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Corpse_GetCopper(Corpse* self) // @categories Currency and Points, Corpse +{ + return self->GetCopper(); } -XS(XS_Corpse_GetPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_GetPlatinum) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetPlatinum(THIS)"); // @categories Currency and Points, Corpse - { - Corpse *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->GetPlatinum(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Corpse_GetSilver(Corpse* self) // @categories Currency and Points, Corpse +{ + return self->GetSilver(); } -XS(XS_Corpse_Summon); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_Summon) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Corpse::Summon(THIS, Client* client, bool is_spell)"); // @categories Corpse - { - Corpse *THIS; - Client *client; - bool spell = (bool) SvTRUE(ST(2)); - VALIDATE_THIS_IS_CORPSE; - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - client = INT2PTR(Client *, tmp); - } else - Perl_croak(aTHX_ "client is not of type Client"); - if (client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - - THIS->Summon(client, spell, true); - } - XSRETURN_EMPTY; +uint32_t Perl_Corpse_GetGold(Corpse* self)// @categories Currency and Points, Corpse +{ + return self->GetGold(); } -XS(XS_Corpse_CastRezz); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_CastRezz) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Corpse::CastRezz(THIS, uint16 spell_id, [Mob* caster = nullptr])"); // @categories Spells and Disciplines, Corpse - { - Corpse *THIS; - uint16 spellid = (uint16) SvUV(ST(1)); - Mob *Caster; - VALIDATE_THIS_IS_CORPSE; - if (sv_derived_from(ST(2), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(2))); - Caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "Caster is not of type Mob"); - if (Caster == nullptr) - Perl_croak(aTHX_ "Caster is nullptr, avoiding crash."); - - THIS->CastRezz(spellid, Caster); - } - XSRETURN_EMPTY; +uint32_t Perl_Corpse_GetPlatinum(Corpse* self) // @categories Currency and Points, Corpse +{ + return self->GetPlatinum(); } -XS(XS_Corpse_CompleteRezz); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_CompleteRezz) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::CompleteRezz(THIS)"); // @categories Spells and Disciplines, Corpse - { - Corpse *THIS; - VALIDATE_THIS_IS_CORPSE; - THIS->CompleteResurrection(); - } - XSRETURN_EMPTY; +void Perl_Corpse_Summon(Corpse* self, Client* client, bool is_spell) // @categories Corpse +{ + self->Summon(client, is_spell, true); } -XS(XS_Corpse_CanMobLoot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_CanMobLoot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::CanMobLoot(THIS, int character_id)"); // @categories Script Utility, Corpse - { - Corpse *THIS; - bool RETVAL; - int charid = (int) SvIV(ST(1)); - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->CanPlayerLoot(charid); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Corpse_CastRezz(Corpse* self, uint16_t spell_id, Mob* caster) // @categories Spells and Disciplines, Corpse +{ + self->CastRezz(spell_id, caster); } -XS(XS_Corpse_AllowMobLoot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_AllowMobLoot) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Corpse::AllowMobLoot(THIS, Mob* them, uint8 slot)"); // @categories Account and Character, Corpse - { - Corpse *THIS; - Mob *them; - uint8 slot = (uint8) SvUV(ST(2)); - VALIDATE_THIS_IS_CORPSE; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - them = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "them is not of type Mob"); - if (them == nullptr) - Perl_croak(aTHX_ "them is nullptr, avoiding crash."); - - THIS->AllowPlayerLoot(them, slot); - } - XSRETURN_EMPTY; +void Perl_Corpse_CompleteRezz(Corpse* self) // @categories Spells and Disciplines, Corpse +{ + self->CompleteResurrection(); } -XS(XS_Corpse_AddLooter); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_AddLooter) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::AddLooter(THIS, Mob* who)"); // @categories Account and Character, Corpse - { - Corpse *THIS; - Mob *who; - VALIDATE_THIS_IS_CORPSE; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - who = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "who is not of type Mob"); - if (who == nullptr) - Perl_croak(aTHX_ "who is nullptr, avoiding crash."); - - THIS->AddLooter(who); - } - XSRETURN_EMPTY; +bool Perl_Corpse_CanMobLoot(Corpse* self, int character_id) // @categories Script Utility, Corpse +{ + return self->CanPlayerLoot(character_id); } -XS(XS_Corpse_IsRezzed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_IsRezzed) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::IsRezzed(THIS)"); // @categories Corpse - { - Corpse *THIS; - bool RETVAL; - VALIDATE_THIS_IS_CORPSE; - RETVAL = THIS->IsRezzed(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Corpse_AllowMobLoot(Corpse* self, Mob* them, uint8_t slot) // @categories Account and Character, Corpse +{ + self->AllowPlayerLoot(them, slot); } -XS(XS_Corpse_HasItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Corpse_HasItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::HasItem(THIS, uint32 item_id)"); // @categories Script Utility - { - Corpse *THIS; - bool has_item = false; - uint32 item_id = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_CORPSE; - has_item = THIS->HasItem(item_id); - ST(0) = boolSV(has_item); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Corpse_AddLooter(Corpse* self, Mob* who) // @categories Account and Character, Corpse +{ + self->AddLooter(who); } -XS(XS_Corpse_CountItem); -XS(XS_Corpse_CountItem) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::CountItem(THIS, uint32 item_id)"); // @categories Script Utility - { - Corpse *THIS; - uint16 item_count = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - item_count = THIS->CountItem(item_id); - XSprePUSH; - PUSHu((UV) item_count); - } - XSRETURN(1); +bool Perl_Corpse_IsRezzed(Corpse* self) // @categories Corpse +{ + return self->IsRezzed(); } -XS(XS_Corpse_GetItemIDBySlot); -XS(XS_Corpse_GetItemIDBySlot) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::GetItemIDBySlot(THIS, uint16 loot_slot)"); // @categories Script Utility - { - Corpse *THIS; - uint32 item_id = 0; - uint16 loot_slot = (uint16) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - item_id = THIS->GetItemIDBySlot(loot_slot); - XSprePUSH; - PUSHu((UV) item_id); - } - XSRETURN(1); +bool Perl_Corpse_HasItem(Corpse* self, uint32_t item_id) // @categories Script Utility +{ + return self->HasItem(item_id); } -XS(XS_Corpse_GetFirstSlotByItemID); -XS(XS_Corpse_GetFirstSlotByItemID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Corpse::GetFirstSlotByItemID(THIS, uint32 item_id)"); // @categories Script Utility - { - Corpse *THIS; - uint16 loot_slot = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_CORPSE; - loot_slot = THIS->GetFirstSlotByItemID(item_id); - XSprePUSH; - PUSHu((UV) loot_slot); - } - XSRETURN(1); +int Perl_Corpse_CountItem(Corpse* self, uint32_t item_id) // @categories Script Utility +{ + return self->CountItem(item_id); } -XS(XS_Corpse_RemoveItemByID); -XS(XS_Corpse_RemoveItemByID) { - dXSARGS; - if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: Corpse::RemoveItemByID(THIS, uint32 item_id, [int quantity = 1])"); // @categories Script Utility - { - Corpse *THIS; - uint32 item_id = (uint32) SvUV(ST(1)); - int quantity = 1; - VALIDATE_THIS_IS_CORPSE; - if (items == 3) - quantity = (int) SvIV(ST(2)); - - THIS->RemoveItemByID(item_id, quantity); - } - XSRETURN_EMPTY; +uint32_t Perl_Corpse_GetItemIDBySlot(Corpse* self, uint16_t loot_slot) // @categories Script Utility +{ + return self->GetItemIDBySlot(loot_slot); } -XS(XS_Corpse_GetLootList); -XS(XS_Corpse_GetLootList) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Corpse::GetLootList(THIS)"); // @categories Script Utility - { - Corpse *THIS; - VALIDATE_THIS_IS_CORPSE; - auto corpse_items = THIS->GetLootList(); - auto item_count = corpse_items.size(); - if (item_count > 0) { - EXTEND(sp, item_count); - for (int index = 0; index < item_count; ++index) { - ST(index) = sv_2mortal(newSVuv(corpse_items[index])); - } - XSRETURN(item_count); - } - SV* return_value = &PL_sv_undef; - ST(0) = return_value; - XSRETURN(1); - } +int Perl_Corpse_GetFirstSlotByItemID(Corpse* self, uint32_t item_id) // @categories Script Utility +{ + return self->GetFirstSlotByItemID(item_id); } -#ifdef __cplusplus -extern "C" -#endif -XS(boot_Corpse); /* prototype to pass -Wmissing-prototypes */ -XS(boot_Corpse) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; +void Perl_Corpse_RemoveItemByID(Corpse* self, uint32_t item_id) // @categories Script Utility +{ + self->RemoveItemByID(item_id); +} - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; +void Perl_Corpse_RemoveItemByID(Corpse* self, uint32_t item_id, int quantity) // @categories Script Utility +{ + self->RemoveItemByID(item_id); +} - //add the strcpy stuff to get rid of const warnings.... +perl::array Perl_Corpse_GetLootList(Corpse* self) // @categories Script Utility +{ + perl::array result; - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "AddItem"), XS_Corpse_AddItem, file, "$$$;$"); - newXSproto(strcpy(buf, "AddLooter"), XS_Corpse_AddLooter, file, "$$"); - newXSproto(strcpy(buf, "AllowMobLoot"), XS_Corpse_AllowMobLoot, file, "$$$"); - newXSproto(strcpy(buf, "CanMobLoot"), XS_Corpse_CanMobLoot, file, "$$"); - newXSproto(strcpy(buf, "CastRezz"), XS_Corpse_CastRezz, file, "$$$"); - newXSproto(strcpy(buf, "CompleteRezz"), XS_Corpse_CompleteRezz, file, "$"); - newXSproto(strcpy(buf, "CountItem"), XS_Corpse_CountItem, file, "$$"); - newXSproto(strcpy(buf, "CountItems"), XS_Corpse_CountItems, file, "$"); - newXSproto(strcpy(buf, "Delete"), XS_Corpse_Delete, file, "$"); - newXSproto(strcpy(buf, "GetCharID"), XS_Corpse_GetCharID, file, "$"); - newXSproto(strcpy(buf, "GetCopper"), XS_Corpse_GetCopper, file, "$"); - newXSproto(strcpy(buf, "GetDBID"), XS_Corpse_GetDBID, file, "$"); - newXSproto(strcpy(buf, "GetDecayTime"), XS_Corpse_GetDecayTime, file, "$"); - newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_Corpse_GetFirstSlotByItemID, file, "$$"); - newXSproto(strcpy(buf, "GetGold"), XS_Corpse_GetGold, file, "$"); - newXSproto(strcpy(buf, "GetItemIDBySlot"), XS_Corpse_GetItemIDBySlot, file, "$$"); - newXSproto(strcpy(buf, "GetLootList"), XS_Corpse_GetLootList, file, "$"); - newXSproto(strcpy(buf, "GetOwnerName"), XS_Corpse_GetOwnerName, file, "$"); - newXSproto(strcpy(buf, "GetPlatinum"), XS_Corpse_GetPlatinum, file, "$"); - newXSproto(strcpy(buf, "GetSilver"), XS_Corpse_GetSilver, file, "$"); - newXSproto(strcpy(buf, "GetWornItem"), XS_Corpse_GetWornItem, file, "$$"); - newXSproto(strcpy(buf, "HasItem"), XS_Corpse_HasItem, file, "$$"); - newXSproto(strcpy(buf, "IsEmpty"), XS_Corpse_IsEmpty, file, "$"); - newXSproto(strcpy(buf, "IsLocked"), XS_Corpse_IsLocked, file, "$"); - newXSproto(strcpy(buf, "IsRezzed"), XS_Corpse_IsRezzed, file, "$"); - newXSproto(strcpy(buf, "Lock"), XS_Corpse_Lock, file, "$"); - newXSproto(strcpy(buf, "RemoveCash"), XS_Corpse_RemoveCash, file, "$"); - newXSproto(strcpy(buf, "RemoveItem"), XS_Corpse_RemoveItem, file, "$$"); - newXSproto(strcpy(buf, "RemoveItemByID"), XS_Corpse_RemoveItemByID, file, "$$;$"); - newXSproto(strcpy(buf, "ResetLooter"), XS_Corpse_ResetLooter, file, "$"); - newXSproto(strcpy(buf, "SetCash"), XS_Corpse_SetCash, file, "$$$$$"); - newXSproto(strcpy(buf, "SetDecayTimer"), XS_Corpse_SetDecayTimer, file, "$$"); - newXSproto(strcpy(buf, "Summon"), XS_Corpse_Summon, file, "$$$"); - newXSproto(strcpy(buf, "UnLock"), XS_Corpse_UnLock, file, "$"); - XSRETURN_YES; + auto corpse_items = self->GetLootList(); + for (int i = 0; i < corpse_items.size(); ++i) + { + result.push_back(corpse_items[i]); + } + + return result; +} + +void perl_register_corpse() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Corpse"); + package.add_base_class("Mob"); + package.add("AddItem", (void(*)(Corpse*, uint32, uint16))&Perl_Corpse_AddItem); + package.add("AddItem", (void(*)(Corpse*, uint32, uint16, uint16))&Perl_Corpse_AddItem); + package.add("AddLooter", &Perl_Corpse_AddLooter); + package.add("AllowMobLoot", &Perl_Corpse_AllowMobLoot); + package.add("CanMobLoot", &Perl_Corpse_CanMobLoot); + package.add("CastRezz", &Perl_Corpse_CastRezz); + package.add("CompleteRezz", &Perl_Corpse_CompleteRezz); + package.add("CountItem", &Perl_Corpse_CountItem); + package.add("CountItems", &Perl_Corpse_CountItems); + package.add("Delete", &Perl_Corpse_Delete); + package.add("GetCharID", &Perl_Corpse_GetCharID); + package.add("GetCopper", &Perl_Corpse_GetCopper); + package.add("GetDBID", &Perl_Corpse_GetDBID); + package.add("GetDecayTime", &Perl_Corpse_GetDecayTime); + package.add("GetFirstSlotByItemID", &Perl_Corpse_GetFirstSlotByItemID); + package.add("GetGold", &Perl_Corpse_GetGold); + package.add("GetItemIDBySlot", &Perl_Corpse_GetItemIDBySlot); + package.add("GetLootList", &Perl_Corpse_GetLootList); + package.add("GetOwnerName", &Perl_Corpse_GetOwnerName); + package.add("GetPlatinum", &Perl_Corpse_GetPlatinum); + package.add("GetSilver", &Perl_Corpse_GetSilver); + package.add("GetWornItem", &Perl_Corpse_GetWornItem); + package.add("HasItem", &Perl_Corpse_HasItem); + package.add("IsEmpty", &Perl_Corpse_IsEmpty); + package.add("IsLocked", &Perl_Corpse_IsLocked); + package.add("IsRezzed", &Perl_Corpse_IsRezzed); + package.add("Lock", &Perl_Corpse_Lock); + package.add("RemoveCash", &Perl_Corpse_RemoveCash); + package.add("RemoveItem", &Perl_Corpse_RemoveItem); + package.add("RemoveItemByID", (void(*)(Corpse*, uint32_t))&Perl_Corpse_RemoveItemByID); + package.add("RemoveItemByID", (void(*)(Corpse*, uint32_t, int))&Perl_Corpse_RemoveItemByID); + package.add("ResetDecayTimer", &Perl_Corpse_ResetDecayTimer); + package.add("ResetLooter", &Perl_Corpse_ResetLooter); + package.add("SetCash", &Perl_Corpse_SetCash); + package.add("SetDecayTimer", &Perl_Corpse_SetDecayTimer); + package.add("Summon", &Perl_Corpse_Summon); + package.add("UnLock", &Perl_Corpse_UnLock); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_questitem.cpp b/zone/perl_questitem.cpp index 8b2d32a02..9b102800a 100644 --- a/zone/perl_questitem.cpp +++ b/zone/perl_questitem.cpp @@ -4,234 +4,106 @@ #ifdef EMBPERL_XS_CLASSES #include "../common/global_define.h" +#include "../common/item_instance.h" #include "embperl.h" -#ifdef seed -#undef seed -#endif - -#include "../common/item_instance.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_ITEM \ - do { \ - if (sv_derived_from(ST(0), "QuestItem")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(EQ::ItemInstance*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type EQ::ItemInstance"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_QuestItem_GetName); -XS(XS_QuestItem_GetName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: QuestItem::GetName(THIS)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - Const_char *RETVAL; - dXSTARG; - VALIDATE_THIS_IS_ITEM; - RETVAL = THIS->GetItem()->Name; - sv_setpv(TARG, RETVAL); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); +std::string Perl_QuestItem_GetName(EQ::ItemInstance* self) // @categories Inventory and Items +{ + return self->GetItem()->Name; } -XS(XS_QuestItem_SetScale); -XS(XS_QuestItem_SetScale) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: QuestItem::SetScale(THIS, float scale_multiplier)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - float Mult; - VALIDATE_THIS_IS_ITEM; - Mult = (float) SvNV(ST(1)); - - if (THIS->IsScaling()) { - THIS->SetExp((int) (Mult * 10000 + .5)); - } +void Perl_QuestItem_SetScale(EQ::ItemInstance* self, float scale_multiplier) // @categories Inventory and Items +{ + if (self->IsScaling()) { + self->SetExp((int) (scale_multiplier * 10000 + .5)); } - XSRETURN_EMPTY; } -XS(XS_QuestItem_ItemSay); -XS(XS_QuestItem_ItemSay) { - dXSARGS; - if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: QuestItem::ItemSay(THIS, string text [int language_id])"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - Const_char *text; - int lang = 0; - VALIDATE_THIS_IS_ITEM; - text = SvPV_nolen(ST(1)); - if (items == 3) - lang = (int) SvUV(ST(2)); - - quest_manager.GetInitiator()->ChannelMessageSend(THIS->GetItem()->Name, 0, 8, lang, 100, text); - } - XSRETURN_EMPTY; +void Perl_QuestItem_ItemSay(EQ::ItemInstance* self, const char* text) // @categories Inventory and Items +{ + quest_manager.GetInitiator()->ChannelMessageSend(self->GetItem()->Name, 0, 8, 0, 100, text); } -XS(XS_QuestItem_IsType); /* prototype to pass -Wmissing-prototypes */ -XS(XS_QuestItem_IsType) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: QuestItem::IsType(THIS, type)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - bool RETVAL; - uint32 type = (int32) SvIV(ST(1)); - VALIDATE_THIS_IS_ITEM; - RETVAL = THIS->IsType((EQ::item::ItemClass) type); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_QuestItem_ItemSay(EQ::ItemInstance* self, const char* text, int language_id) // @categories Inventory and Items +{ + quest_manager.GetInitiator()->ChannelMessageSend(self->GetItem()->Name, 0, 8, language_id, 100, text); } -XS(XS_QuestItem_IsAttuned); /* prototype to pass -Wmissing-prototypes */ -XS(XS_QuestItem_IsAttuned) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: QuestItem::IsAttuned(THIS)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - bool RETVAL; - VALIDATE_THIS_IS_ITEM; - RETVAL = THIS->IsAttuned(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_QuestItem_IsType(EQ::ItemInstance* self, int type) // @categories Inventory and Items +{ + return self->IsType(static_cast(type)); } -XS(XS_QuestItem_GetCharges); /* prototype to pass -Wmissing-prototypes */ -XS(XS_QuestItem_GetCharges) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: QuestItem::GetCharges(THIS)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - int16 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_ITEM; - RETVAL = THIS->GetCharges(); - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +bool Perl_QuestItem_IsAttuned(EQ::ItemInstance* self) // @categories Inventory and Items +{ + return self->IsAttuned(); } -XS(XS_QuestItem_GetAugment); /* prototype to pass -Wmissing-prototypes */ -XS(XS_QuestItem_GetAugment) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: QuestItem::GetAugment(THIS, int16 slot_id)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - int16 slot_id = (int16) SvIV(ST(1)); - EQ::ItemInstance *RETVAL; - VALIDATE_THIS_IS_ITEM; - RETVAL = THIS->GetAugment(slot_id); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "QuestItem", (void *) RETVAL); - } - XSRETURN(1); +int Perl_QuestItem_GetCharges(EQ::ItemInstance* self) // @categories Inventory and Items +{ + return self->GetCharges(); } -XS(XS_QuestItem_GetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_QuestItem_GetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: QuestItem::GetID(THIS)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_ITEM; - RETVAL = THIS->GetItem()->ID; - XSprePUSH; - PUSHi((IV) RETVAL); - } - XSRETURN(1); +EQ::ItemInstance* Perl_QuestItem_GetAugment(EQ::ItemInstance* self, int slot_id) // @categories Inventory and Items +{ + return self->GetAugment(slot_id); } -XS(XS_QuestItem_ContainsAugmentByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_QuestItem_ContainsAugmentByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: QuestItem::ContainsAugmentByID(THIS, uint32 item_id)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - uint32 item_id = (uint32) SvUV(ST(1)); - bool contains_augment = false; - VALIDATE_THIS_IS_ITEM; - contains_augment = THIS->ContainsAugmentByID(item_id); - ST(0) = boolSV(contains_augment); - sv_2mortal(ST(0)); - } - XSRETURN(1); +uint32_t Perl_QuestItem_GetID(EQ::ItemInstance* self) // @categories Inventory and Items +{ + return self->GetItem()->ID; } -XS(XS_QuestItem_CountAugmentByID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_QuestItem_CountAugmentByID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: QuestItem::CountAugmentByID(THIS, uint32 item_id)"); // @categories Inventory and Items - { - EQ::ItemInstance *THIS; - int quantity = 0; - uint32 item_id = (uint32) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_ITEM; - quantity = THIS->CountAugmentByID(item_id); - XSprePUSH; - PUSHi((IV) quantity); - } - XSRETURN(1); +bool Perl_QuestItem_ContainsAugmentByID(EQ::ItemInstance* self, uint32_t item_id) // @categories Inventory and Items +{ + return self->ContainsAugmentByID(item_id); } -#ifdef __cplusplus -extern "C" -#endif +int Perl_QuestItem_CountAugmentByID(EQ::ItemInstance* self, uint32_t item_id) // @categories Inventory and Items +{ + return self->CountAugmentByID(item_id); +} -XS(boot_QuestItem); -XS(boot_QuestItem) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; +bool Perl_QuestItem_IsStackable(EQ::ItemInstance* self) +{ + return self->IsStackable(); +} - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; +void Perl_QuestItem_SetCharges(EQ::ItemInstance* self, int16_t charges) +{ + self->SetCharges(charges); +} - //add the strcpy stuff to get rid of const warnings.... +int Perl_QuestItem_GetTaskDeliveredCount(EQ::ItemInstance* self) +{ + return self->GetTaskDeliveredCount(); +} - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "ContainsAugmentByID"), XS_QuestItem_ContainsAugmentByID, file, "$$"); - newXSproto(strcpy(buf, "CountAugmentByID"), XS_QuestItem_CountAugmentByID, file, "$$"); - newXSproto(strcpy(buf, "GetAugment"), XS_QuestItem_GetAugment, file, "$$"); - newXSproto(strcpy(buf, "GetCharges"), XS_QuestItem_GetCharges, file, "$"); - newXSproto(strcpy(buf, "GetID"), XS_QuestItem_GetID, file, "$"); - newXSproto(strcpy(buf, "GetName"), XS_QuestItem_GetName, file, "$"); - newXSproto(strcpy(buf, "IsAttuned"), XS_QuestItem_IsAttuned, file, "$"); - newXSproto(strcpy(buf, "IsType"), XS_QuestItem_IsType, file, "$$"); - newXSproto(strcpy(buf, "ItemSay"), XS_QuestItem_ItemSay, file, "$"); - newXSproto(strcpy(buf, "SetScale"), XS_QuestItem_SetScale, file, "$"); - XSRETURN_YES; +int Perl_QuestItem_RemoveTaskDeliveredItems(EQ::ItemInstance* self) +{ + return self->RemoveTaskDeliveredItems(); +} + +void perl_register_questitem() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("QuestItem"); + package.add("ContainsAugmentByID", &Perl_QuestItem_ContainsAugmentByID); + package.add("CountAugmentByID", &Perl_QuestItem_CountAugmentByID); + package.add("GetAugment", &Perl_QuestItem_GetAugment); + package.add("GetCharges", &Perl_QuestItem_GetCharges); + package.add("GetID", &Perl_QuestItem_GetID); + package.add("GetName", &Perl_QuestItem_GetName); + package.add("GetTaskDeliveredCount", &Perl_QuestItem_GetTaskDeliveredCount); + package.add("IsAttuned", &Perl_QuestItem_IsAttuned); + package.add("IsStackable", &Perl_QuestItem_IsStackable); + package.add("IsType", &Perl_QuestItem_IsType); + package.add("ItemSay", (void(*)(EQ::ItemInstance*, const char*))&Perl_QuestItem_ItemSay); + package.add("ItemSay", (void(*)(EQ::ItemInstance*, const char*, int))&Perl_QuestItem_ItemSay); + package.add("RemoveTaskDeliveredItems", &Perl_QuestItem_RemoveTaskDeliveredItems); + package.add("SetCharges", &Perl_QuestItem_SetCharges); + package.add("SetScale", &Perl_QuestItem_SetScale); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_raids.cpp b/zone/perl_raids.cpp index c7c07e042..399e6636c 100644 --- a/zone/perl_raids.cpp +++ b/zone/perl_raids.cpp @@ -2,445 +2,195 @@ #ifdef EMBPERL_XS_CLASSES +#include "../common/data_verification.h" #include "../common/global_define.h" #include "embperl.h" - -#ifdef seed -#undef seed -#endif - #include "raids.h" #include "client.h" -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_RAID \ - do { \ - if (sv_derived_from(ST(0), "Raid")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(Raid*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type Raid"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Raid_IsRaidMember); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_IsRaidMember) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::IsRaidMember(THIS, string name)"); // @categories Raid - { - Raid *THIS; - bool RETVAL; - const char *name = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->IsRaidMember(name); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +bool Perl_Raid_IsRaidMember(Raid* self, const char* name) // @categories Raid +{ + return self->IsRaidMember(name); } -XS(XS_Raid_CastGroupSpell); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_CastGroupSpell) { - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Raid::CastGroupSpell(THIS, Mob* caster, uint16 spell_id, uint32 group_id)"); // @categories Group, Raid - { - Raid *THIS; - Mob *caster; - uint16 spellid = (uint16) SvUV(ST(2)); - uint32 gid = (uint32) SvUV(ST(3)); - VALIDATE_THIS_IS_RAID; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - caster = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "caster is not of type Mob"); - if (caster == nullptr) - Perl_croak(aTHX_ "caster is nullptr, avoiding crash."); - - THIS->CastGroupSpell(caster, spellid, gid); - } - XSRETURN_EMPTY; +bool Perl_Raid_IsRaidMember(Raid* self, Client* c) // @categories Raid +{ + return self->IsRaidMember(c); } -XS(XS_Raid_GroupCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_GroupCount) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::GroupCount(THIS, uint32 group_id)"); // @categories Group, Raid - { - Raid *THIS; - uint8 RETVAL; - dXSTARG; - uint32 gid = (uint32) SvUV(ST(1)); - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->GroupCount(gid); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Raid_CastGroupSpell(Raid* self, Mob* caster, uint16 spell_id, uint32 group_id) // @categories Group, Raid +{ + self->CastGroupSpell(caster, spell_id, group_id); } -XS(XS_Raid_RaidCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_RaidCount) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Raid::RaidCount(THIS)"); // @categories Raid - { - Raid *THIS; - uint8 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->RaidCount(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_Raid_GroupCount(Raid* self, uint32_t group_id) // @categories Group, Raid +{ + return self->GroupCount(group_id); } -XS(XS_Raid_GetGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_GetGroup) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::GetGroup(THIS, string name)"); // @categories Group, Raid - { - Raid *THIS; - uint32 RETVAL; - dXSTARG; - const char *name = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->GetGroup(name); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +int Perl_Raid_RaidCount(Raid* self) // @categories Raid +{ + return self->RaidCount(); } -XS(XS_Raid_SplitExp); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_SplitExp) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Raid::SplitExp(THIS, uint32 experience, [Mob* other = nullptr])"); // @categories Experience and Level, Raid - { - Raid *THIS; - uint32 exp = (uint32) SvUV(ST(1)); - Mob *other; - VALIDATE_THIS_IS_RAID; - if (sv_derived_from(ST(2), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(2))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - THIS->SplitExp(exp, other); - } - XSRETURN_EMPTY; +uint32_t Perl_Raid_GetGroup(Raid* self, const char* name) // @categories Group, Raid +{ + return self->GetGroup(name); } -XS(XS_Raid_GetTotalRaidDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_GetTotalRaidDamage) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::GetTotalRaidDamage(THIS, [Mob* other = nullptr])"); // @categories Raid - { - Raid *THIS; - uint32 RETVAL; - dXSTARG; - Mob *other; - VALIDATE_THIS_IS_RAID; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - other = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "other is not of type Mob"); - if (other == nullptr) - Perl_croak(aTHX_ "other is nullptr, avoiding crash."); - - RETVAL = THIS->GetTotalRaidDamage(other); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +uint32_t Perl_Raid_GetGroup(Raid* self, Client* client) // @categories Group, Raid +{ + return self->GetGroup(client); } -XS(XS_Raid_SplitMoney); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_SplitMoney) { - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: Raid::SplitMoney(THIS, uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum)"); // @categories Currency and Points, Raid - { - Raid *THIS; - uint32 gid = (uint32) SvUV(ST(1)); - uint32 copper = (uint32) SvUV(ST(2)); - uint32 silver = (uint32) SvUV(ST(3)); - uint32 gold = (uint32) SvUV(ST(4)); - uint32 platinum = (uint32) SvUV(ST(5)); - VALIDATE_THIS_IS_RAID; - THIS->SplitMoney(gid, copper, silver, gold, platinum); - } - XSRETURN_EMPTY; +void Perl_Raid_SplitExp(Raid* self, uint32 experience, Mob* other) // @categories Experience and Level, Raid +{ + self->SplitExp(experience, other); } -XS(XS_Raid_BalanceHP); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_BalanceHP) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Raid::BalanceHP(THIS, int32 penalty, uint32 group_id)"); // @categories Raid - { - Raid *THIS; - int32 penalty = (int32) SvUV(ST(1)); - uint32 gid = (uint32) SvUV(ST(2)); - VALIDATE_THIS_IS_RAID; - THIS->BalanceHP(penalty, gid); - } - XSRETURN_EMPTY; +uint32_t Perl_Raid_GetTotalRaidDamage(Raid* self, Mob* other) // @categories Raid +{ + return self->GetTotalRaidDamage(other); } -XS(XS_Raid_IsLeader); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_IsLeader) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::IsLeader(THIS, string name)"); // @categories Raid - { - Raid *THIS; - bool RETVAL; - const char *name = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->IsLeader(name); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Raid_SplitMoney(Raid* self, uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum) // @categories Currency and Points, Raid +{ + self->SplitMoney(gid, copper, silver, gold, platinum); } -XS(XS_Raid_IsGroupLeader); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_IsGroupLeader) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::IsGroupLeader(THIS, string name)"); // @categories Group, Raid - { - Raid *THIS; - bool RETVAL; - const char *who = (char *) SvPV_nolen(ST(1)); - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->IsGroupLeader(who); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); +void Perl_Raid_SplitMoney(Raid* self, uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client* splitter) // @categories Currency and Points, Raid +{ + self->SplitMoney(gid, copper, silver, gold, platinum, splitter); } -XS(XS_Raid_GetHighestLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_GetHighestLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Raid::GetHighestLevel(THIS)"); // @categories Raid - { - Raid *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->GetHighestLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +void Perl_Raid_BalanceHP(Raid* self, int32_t penalty, uint32_t group_id) // @categories Raid +{ + self->BalanceHP(penalty, group_id); } -XS(XS_Raid_GetLowestLevel); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_GetLowestLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Raid::GetLowestLevel(THIS)"); // @categories Raid - { - Raid *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->GetLowestLevel(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +bool Perl_Raid_IsLeader(Raid* self, const char* name) // @categories Raid +{ + return self->IsLeader(name); } -XS(XS_Raid_GetClientByIndex); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_GetClientByIndex) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::GetClientByIndex(THIS, uint16 raid_index)"); // @categories Raid - { - Raid *THIS; - Client *RETVAL; - uint16 index = (uint16) SvUV(ST(1)); - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->GetClientByIndex(index); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +bool Perl_Raid_IsLeader(Raid* self, Client* c) // @categories Raid +{ + return self->IsLeader(c); } -XS(XS_Raid_TeleportGroup); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_TeleportGroup) { - dXSARGS; - if (items != 8) - Perl_croak(aTHX_ "Usage: Raid::TeleportGroup(THIS, Mob* sender, uint32 zone_id, float x, float y, float z, float heading, uint32 group_id)"); // @categories Group, Raid - { - Raid *THIS; - Mob *sender; - uint32 zoneID = (uint32) SvUV(ST(2)); - float x = (float) SvNV(ST(3)); - float y = (float) SvNV(ST(4)); - float z = (float) SvNV(ST(5)); - float heading = (float) SvNV(ST(6)); - uint32 gid = (uint32) SvUV(ST(7)); - VALIDATE_THIS_IS_RAID; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - sender = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "sender is not of type Mob"); - if (sender == nullptr) - Perl_croak(aTHX_ "sender is nullptr, avoiding crash."); - - THIS->TeleportGroup(sender, zoneID, 0, x, y, z, heading, gid); - } - XSRETURN_EMPTY; +Client* Perl_Raid_GetLeader(Raid* self) // @categories Raid +{ + return self->GetLeader(); } -XS(XS_Raid_TeleportRaid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_TeleportRaid) { - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: Raid::TeleportRaid(THIS, Mob* sender, uint32 zone_id, float x, float y, float z, float heading)"); // @categories Raid - { - Raid *THIS; - Mob *sender; - uint32 zoneID = (uint32) SvUV(ST(2)); - float x = (float) SvNV(ST(3)); - float y = (float) SvNV(ST(4)); - float z = (float) SvNV(ST(5)); - float heading = (float) SvNV(ST(6)); - VALIDATE_THIS_IS_RAID; - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV *) SvRV(ST(1))); - sender = INT2PTR(Mob *, tmp); - } else - Perl_croak(aTHX_ "sender is not of type Mob"); - if (sender == nullptr) - Perl_croak(aTHX_ "sender is nullptr, avoiding crash."); - - THIS->TeleportRaid(sender, zoneID, 0, x, y, z, heading); - } - XSRETURN_EMPTY; +std::string Perl_Raid_GetLeaderName(Raid* self) // @categories Raid +{ + return self->GetLeaderName(); } -XS(XS_Raid_GetID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Raid_GetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Raid::GetID(THIS)"); // @categories Raid - { - Raid *THIS; - uint32 RETVAL; - dXSTARG; - VALIDATE_THIS_IS_RAID; - RETVAL = THIS->GetID(); - XSprePUSH; - PUSHu((UV) RETVAL); - } - XSRETURN(1); +bool Perl_Raid_IsGroupLeader(Raid* self, const char* who) // @categories Group, Raid +{ + return self->IsGroupLeader(who); } -XS(XS_Raid_GetMember); -XS(XS_Raid_GetMember) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Raid::GetMember(THIS, int raid_index)"); // @categories Raid - { - Raid *THIS; - Client *RETVAL = nullptr; - dXSTARG; - VALIDATE_THIS_IS_RAID; - int index = (int) SvUV(ST(1)); - if (index < 0 || index > 71) - RETVAL = nullptr; - else { - if (THIS->members[index].member != nullptr) - RETVAL = THIS->members[index].member->CastToClient(); - } - - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Client", (void *) RETVAL); - } - XSRETURN(1); +bool Perl_Raid_IsGroupLeader(Raid* self, Client* c) // @categories Group, Raid +{ + return self->IsGroupLeader(c); } -XS(XS_Raid_DoesAnyMemberHaveExpeditionLockout); -XS(XS_Raid_DoesAnyMemberHaveExpeditionLockout) { - dXSARGS; - if (items != 3 && items != 4) { - Perl_croak(aTHX_ "Usage: Raid::DoesAnyMemberHaveExpeditionLockout(THIS, string expedition_name, string event_name, [int max_check_count = 0])"); - } - - Raid* THIS = nullptr; - VALIDATE_THIS_IS_RAID; - std::string expedition_name(SvPV_nolen(ST(1))); - std::string event_name(SvPV_nolen(ST(2))); - int max_check_count = (items == 4) ? static_cast(SvIV(ST(3))) : 0; - - bool result = THIS->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count); - ST(0) = boolSV(result); - XSRETURN(1); +uint32_t Perl_Raid_GetHighestLevel(Raid* self) // @categories Raid +{ + return self->GetHighestLevel(); } -#ifdef __cplusplus -extern "C" -#endif -XS(boot_Raid); /* prototype to pass -Wmissing-prototypes */ -XS(boot_Raid) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; +uint32_t Perl_Raid_GetLowestLevel(Raid* self) // @categories Raid +{ + return self->GetLowestLevel(); +} - if (items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; +Client* Perl_Raid_GetClientByIndex(Raid* self, uint16_t member_index) // @categories Raid +{ + return self->GetClientByIndex(member_index); +} - //add the strcpy stuff to get rid of const warnings.... +void Perl_Raid_TeleportGroup(Raid* self, Mob* sender, uint32 zone_id, float x, float y, float z, float heading, uint32 group_id) // @categories Group, Raid +{ + self->TeleportGroup(sender, zone_id, 0, x, y, z, heading, group_id); +} - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "BalanceHP"), XS_Raid_BalanceHP, file, "$$$"); - newXSproto(strcpy(buf, "CastGroupSpell"), XS_Raid_CastGroupSpell, file, "$$$$"); - newXSproto(strcpy(buf, "DoesAnyMemberHaveExpeditionLockout"), XS_Raid_DoesAnyMemberHaveExpeditionLockout, file, "$$$;$"); - newXSproto(strcpy(buf, "GetClientByIndex"), XS_Raid_GetClientByIndex, file, "$$"); - newXSproto(strcpy(buf, "GetGroup"), XS_Raid_GetGroup, file, "$$"); - newXSproto(strcpy(buf, "GetHighestLevel"), XS_Raid_GetHighestLevel, file, "$"); - newXSproto(strcpy(buf, "GetID"), XS_Raid_GetID, file, "$"); - newXSproto(strcpy(buf, "GetLowestLevel"), XS_Raid_GetLowestLevel, file, "$"); - newXSproto(strcpy(buf, "GetMember"), XS_Raid_GetMember, file, "$$"); - newXSproto(strcpy(buf, "GetTotalRaidDamage"), XS_Raid_GetTotalRaidDamage, file, "$$"); - newXSproto(strcpy(buf, "GroupCount"), XS_Raid_GroupCount, file, "$$"); - newXSproto(strcpy(buf, "IsGroupLeader"), XS_Raid_IsGroupLeader, file, "$$"); - newXSproto(strcpy(buf, "IsLeader"), XS_Raid_IsLeader, file, "$$"); - newXSproto(strcpy(buf, "IsRaidMember"), XS_Raid_IsRaidMember, file, "$$"); - newXSproto(strcpy(buf, "RaidCount"), XS_Raid_RaidCount, file, "$"); - newXSproto(strcpy(buf, "SplitExp"), XS_Raid_SplitExp, file, "$$$"); - newXSproto(strcpy(buf, "SplitMoney"), XS_Raid_SplitMoney, file, "$$$$$$"); - newXSproto(strcpy(buf, "TeleportGroup"), XS_Raid_TeleportGroup, file, "$$$$$$$$"); - newXSproto(strcpy(buf, "TeleportRaid"), XS_Raid_TeleportRaid, file, "$$$$$$$"); - XSRETURN_YES; +void Perl_Raid_TeleportRaid(Raid* self, Mob* sender, uint32 zone_id, float x, float y, float z, float heading) // @categories Raid +{ + self->TeleportRaid(sender, zone_id, 0, x, y, z, heading); +} + +uint32_t Perl_Raid_GetID(Raid* self) // @categories Raid +{ + return self->GetID(); +} + +Client* Perl_Raid_GetMember(Raid* self, int member_index) // @categories Raid +{ + if (!EQ::ValueWithin(member_index, 0, (MAX_RAID_MEMBERS - 1))) { + return nullptr; + } + + return self->members[member_index].member; +} + +bool Perl_Raid_DoesAnyMemberHaveExpeditionLockout(Raid* self, std::string expedition_name, std::string event_name) +{ + return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name); +} + +bool Perl_Raid_DoesAnyMemberHaveExpeditionLockout(Raid* self, std::string expedition_name, std::string event_name, int max_check_count) +{ + return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count); +} + +int Perl_Raid_GetGroupNumber(Raid* self, int member_index) { + if ( + !EQ::ValueWithin(member_index, 0, 71) || + self->members[member_index].GroupNumber == RAID_GROUPLESS + ) { + return -1; + } + + return self->members[member_index].GroupNumber; +} + +void perl_register_raid() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Raid"); + package.add("BalanceHP", &Perl_Raid_BalanceHP); + package.add("CastGroupSpell", &Perl_Raid_CastGroupSpell); + package.add("DoesAnyMemberHaveExpeditionLockout", (bool(*)(Raid*, std::string, std::string))&Perl_Raid_DoesAnyMemberHaveExpeditionLockout); + package.add("DoesAnyMemberHaveExpeditionLockout", (bool(*)(Raid*, std::string, std::string, int))&Perl_Raid_DoesAnyMemberHaveExpeditionLockout); + package.add("GetClientByIndex", &Perl_Raid_GetClientByIndex); + package.add("GetGroup", (uint32(*)(Raid*, const char*))&Perl_Raid_GetGroup); + package.add("GetGroup", (uint32(*)(Raid*, Client*))&Perl_Raid_GetGroup); + package.add("GetGroupNumber", &Perl_Raid_GetGroupNumber); + package.add("GetHighestLevel", &Perl_Raid_GetHighestLevel); + package.add("GetID", &Perl_Raid_GetID); + package.add("GetLowestLevel", &Perl_Raid_GetLowestLevel); + package.add("GetMember", &Perl_Raid_GetMember); + package.add("GetLeader", &Perl_Raid_GetLeader); + package.add("GetLeaderName", &Perl_Raid_GetLeaderName); + package.add("GetTotalRaidDamage", &Perl_Raid_GetTotalRaidDamage); + package.add("GroupCount", &Perl_Raid_GroupCount); + package.add("IsGroupLeader", (bool(*)(Raid*, const char*))&Perl_Raid_IsGroupLeader); + package.add("IsGroupLeader", (bool(*)(Raid*, Client*))&Perl_Raid_IsGroupLeader); + package.add("IsLeader", (bool(*)(Raid*, const char*))&Perl_Raid_IsLeader); + package.add("IsLeader", (bool(*)(Raid*, Client*))&Perl_Raid_IsLeader); + package.add("IsRaidMember", (bool(*)(Raid*, const char*))&Perl_Raid_IsRaidMember); + package.add("IsRaidMember", (bool(*)(Raid*, Client*))&Perl_Raid_IsRaidMember); + package.add("RaidCount", &Perl_Raid_RaidCount); + package.add("SplitExp", &Perl_Raid_SplitExp); + package.add("SplitMoney", (void(*)(Raid*, uint32, uint32, uint32, uint32, uint32))&Perl_Raid_SplitMoney); + package.add("SplitMoney", (void(*)(Raid*, uint32, uint32, uint32, uint32, uint32, Client*))&Perl_Raid_SplitMoney); + package.add("TeleportGroup", &Perl_Raid_TeleportGroup); + package.add("TeleportRaid", &Perl_Raid_TeleportRaid); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_spell.cpp b/zone/perl_spell.cpp index 85aa27d05..d8fd34509 100644 --- a/zone/perl_spell.cpp +++ b/zone/perl_spell.cpp @@ -3,2136 +3,668 @@ #ifdef EMBPERL_XS_CLASSES #include "../common/global_define.h" +#include "../common/spdat.h" #include "embperl.h" -#ifdef seed -#undef seed -#endif - -#include "../common/spdat.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -#define VALIDATE_THIS_IS_SPELL \ - do { \ - if (sv_derived_from(ST(0), "Spell")) { \ - IV tmp = SvIV((SV*)SvRV(ST(0))); \ - THIS = INT2PTR(SPDat_Spell_Struct*, tmp); \ - } else { \ - Perl_croak(aTHX_ "THIS is not of type SPDat_Spell_Struct"); \ - } \ - if (THIS == nullptr) { \ - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ - } \ - } while (0); - -XS(XS_Spell_GetActivated); -XS(XS_Spell_GetActivated) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetActivated(THIS)"); - { - SPDat_Spell_Struct* THIS; - int activated; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - activated = THIS->activated; - XSprePUSH; - PUSHi((IV) activated); - } - XSRETURN(1); -} - -XS(XS_Spell_GetAllowRest); -XS(XS_Spell_GetAllowRest) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetAllowRest(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool allow_rest; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - allow_rest = THIS->allow_rest; - ST(0) = boolSV(allow_rest); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetAOEDuration); -XS(XS_Spell_GetAOEDuration) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetAOEDuration(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint32 aoe_duration; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - aoe_duration = THIS->aoe_duration; - XSprePUSH; - PUSHu((UV) aoe_duration); - } - XSRETURN(1); -} - -XS(XS_Spell_GetAOEMaxTargets); -XS(XS_Spell_GetAOEMaxTargets) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetAOEMaxTargets(THIS)"); - { - SPDat_Spell_Struct* THIS; - int aoe_max_targets; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - aoe_max_targets = THIS->aoe_max_targets; - XSprePUSH; - PUSHi((IV) aoe_max_targets); - } - XSRETURN(1); -} - -XS(XS_Spell_GetAOERange); -XS(XS_Spell_GetAOERange) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetAOERange(THIS)"); - { - SPDat_Spell_Struct* THIS; - float aoe_range; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - aoe_range = THIS->aoe_range; - XSprePUSH; - PUSHn((double) aoe_range); - } - XSRETURN(1); -} - -XS(XS_Spell_GetBaseDifficulty); -XS(XS_Spell_GetBaseDifficulty) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetBaseDifficulty(THIS)"); - { - SPDat_Spell_Struct* THIS; - int base_difficulty; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - base_difficulty = THIS->base_difficulty; - XSprePUSH; - PUSHi((IV) base_difficulty); - } - XSRETURN(1); -} - -XS(XS_Spell_GetBaseValue); -XS(XS_Spell_GetBaseValue) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetBaseValue(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int base_value; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - base_value = THIS->base_value[slot]; - XSprePUSH; - PUSHi((IV) base_value); - } - XSRETURN(1); -} - -XS(XS_Spell_GetBonusHate); -XS(XS_Spell_GetBonusHate) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetBonusHate(THIS)"); - { - SPDat_Spell_Struct* THIS; - int bonus_hate; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - bonus_hate = THIS->bonus_hate; - XSprePUSH; - PUSHi((IV) bonus_hate); - } - XSRETURN(1); -} - -XS(XS_Spell_GetBuffDuration); -XS(XS_Spell_GetBuffDuration) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetBuffDuration(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint32 buff_duration; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - buff_duration = THIS->buff_duration; - XSprePUSH; - PUSHu((UV) buff_duration); - } - XSRETURN(1); -} - -XS(XS_Spell_GetBuffDurationFormula); -XS(XS_Spell_GetBuffDurationFormula) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetBuffDurationFormula(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint32 buff_duration_formula; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - buff_duration_formula = THIS->buff_duration_formula; - XSprePUSH; - PUSHu((UV) buff_duration_formula); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCanCastInCombat); -XS(XS_Spell_GetCanCastInCombat) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCanCastInCombat(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool can_cast_in_combat; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - can_cast_in_combat = THIS->can_cast_in_combat; - ST(0) = boolSV(can_cast_in_combat); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCanCastOutOfCombat); -XS(XS_Spell_GetCanCastOutOfCombat) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCanCastOutOfCombat(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool can_cast_out_of_combat; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - can_cast_out_of_combat = THIS->can_cast_out_of_combat; - ST(0) = boolSV(can_cast_out_of_combat); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCanMGB); -XS(XS_Spell_GetCanMGB) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCanMGB(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool can_mgb; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - can_mgb = THIS->can_mgb; - ST(0) = boolSV(can_mgb); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCastNotStanding); -XS(XS_Spell_GetCastNotStanding) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCastNotStanding(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool cast_not_standing; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - cast_not_standing = THIS->cast_not_standing; - ST(0) = boolSV(cast_not_standing); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCastOnOther); -XS(XS_Spell_GetCastOnOther) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCastOnOther(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string cast_on_other; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - cast_on_other = THIS->cast_on_other; - sv_setpv(TARG, cast_on_other.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetCastOnYou); -XS(XS_Spell_GetCastOnYou) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCastOnYou(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string cast_on_you; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - cast_on_you = THIS->cast_on_you; - sv_setpv(TARG, cast_on_you.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetCastRestriction); -XS(XS_Spell_GetCastRestriction) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCastRestriction(THIS)"); - { - SPDat_Spell_Struct* THIS; - int cast_restriction; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - cast_restriction = THIS->cast_restriction; - XSprePUSH; - PUSHi((IV) cast_restriction); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCastTime); -XS(XS_Spell_GetCastTime) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCastTime(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint32 cast_time; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - cast_time = THIS->cast_time; - XSprePUSH; - PUSHu((UV) cast_time); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCasterRequirementID); -XS(XS_Spell_GetCasterRequirementID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCasterRequirementID(THIS)"); - { - SPDat_Spell_Struct* THIS; - int caster_requirement_id; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - caster_requirement_id = THIS->caster_requirement_id; - XSprePUSH; - PUSHi((IV) caster_requirement_id); - } - XSRETURN(1); -} - -XS(XS_Spell_GetCastingAnimation); -XS(XS_Spell_GetCastingAnimation) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetCastingAnimation(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint8 casting_animation; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - casting_animation = THIS->casting_animation; - XSprePUSH; - PUSHu((UV) casting_animation); - } - XSRETURN(1); -} - -XS(XS_Spell_GetClasses); -XS(XS_Spell_GetClasses) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetClasses(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - uint8 classes; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - classes = THIS->classes[slot]; - XSprePUSH; - PUSHu((UV) classes); - } - XSRETURN(1); -} - -XS(XS_Spell_GetComponent); -XS(XS_Spell_GetComponent) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetComponent(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int component; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - component = THIS->component[slot]; - XSprePUSH; - PUSHi((IV) component); - } - XSRETURN(1); -} - -XS(XS_Spell_GetComponentCount); -XS(XS_Spell_GetComponentCount) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetComponentCount(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int component_count; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - component_count = THIS->component_count[slot]; - XSprePUSH; - PUSHi((IV) component_count); - } - XSRETURN(1); -} - -XS(XS_Spell_GetDeities); -XS(XS_Spell_GetDeities) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetDeities(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int8 deities; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - deities = THIS->deities[slot]; - XSprePUSH; - PUSHi((IV) deities); - } - XSRETURN(1); -} - -XS(XS_Spell_GetDeityAgnostic); -XS(XS_Spell_GetDeityAgnostic) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetDeityAgnostic(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 deity_agnostic; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - deity_agnostic = THIS->deity_agnostic; - XSprePUSH; - PUSHi((IV) deity_agnostic); - } - XSRETURN(1); -} - -XS(XS_Spell_GetDescriptionID); -XS(XS_Spell_GetDescriptionID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetDescriptionID(THIS)"); - { - SPDat_Spell_Struct* THIS; - int description_id; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - description_id = THIS->description_id; - XSprePUSH; - PUSHi((IV) description_id); - } - XSRETURN(1); -} - -XS(XS_Spell_GetDirectionalEnd); -XS(XS_Spell_GetDirectionalEnd) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetDirectionalEnd(THIS)"); - { - SPDat_Spell_Struct* THIS; - float directional_end; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - directional_end = THIS->directional_end; - XSprePUSH; - PUSHn((double) directional_end); - } - XSRETURN(1); -} - -XS(XS_Spell_GetDirectionalStart); -XS(XS_Spell_GetDirectionalStart) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetDirectionalStart(THIS)"); - { - SPDat_Spell_Struct* THIS; - float directional_start; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - directional_start = THIS->directional_start; - XSprePUSH; - PUSHn((double) directional_start); - } - XSRETURN(1); -} - -XS(XS_Spell_GetDisallowSit); -XS(XS_Spell_GetDisallowSit) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetDisallowSit(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 disallow_sit; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - disallow_sit = THIS->disallow_sit; - XSprePUSH; - PUSHi((IV) disallow_sit); - } - XSRETURN(1); -} - -XS(XS_Spell_GetDispelFlag); -XS(XS_Spell_GetDispelFlag) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetDispelFlag(THIS)"); - { - SPDat_Spell_Struct* THIS; - int dispel_flag; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - dispel_flag = THIS->dispel_flag; - XSprePUSH; - PUSHi((IV) dispel_flag); - } - XSRETURN(1); -} - -XS(XS_Spell_GetEffectDescriptionID); -XS(XS_Spell_GetEffectDescriptionID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetEffectDescriptionID(THIS)"); - { - SPDat_Spell_Struct* THIS; - int effect_description_id; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - effect_description_id = THIS->effect_description_id; - XSprePUSH; - PUSHi((IV) effect_description_id); - } - XSRETURN(1); -} - -XS(XS_Spell_GetEffectID); -XS(XS_Spell_GetEffectID) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetEffectID(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int effect_id; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - effect_id = THIS->effect_id[slot]; - XSprePUSH; - PUSHi((IV) effect_id); - } - XSRETURN(1); -} - -XS(XS_Spell_GetEnduranceCost); -XS(XS_Spell_GetEnduranceCost) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetEnduranceCost(THIS)"); - { - SPDat_Spell_Struct* THIS; - int endurance_cost; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - endurance_cost = THIS->endurance_cost; - XSprePUSH; - PUSHi((IV) endurance_cost); - } - XSRETURN(1); -} - -XS(XS_Spell_GetEnduranceUpkeep); -XS(XS_Spell_GetEnduranceUpkeep) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetEnduranceUpkeep(THIS)"); - { - SPDat_Spell_Struct* THIS; - int endurance_upkeep; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - endurance_upkeep = THIS->endurance_upkeep; - XSprePUSH; - PUSHi((IV) endurance_upkeep); - } - XSRETURN(1); -} - -XS(XS_Spell_GetEnvironmentType); -XS(XS_Spell_GetEnvironmentType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetEnvironmentType(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 environment_type; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - environment_type = THIS->environment_type; - XSprePUSH; - PUSHi((IV) environment_type); - } - XSRETURN(1); -} - -XS(XS_Spell_GetFeedbackable); -XS(XS_Spell_GetFeedbackable) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetFeedbackable(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool feedbackable; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - feedbackable = THIS->feedbackable; - ST(0) = boolSV(feedbackable); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetFormula); -XS(XS_Spell_GetFormula) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetFormula(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - uint16 formula; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - formula = THIS->formula[slot]; - XSprePUSH; - PUSHu((UV) formula); - } - XSRETURN(1); -} - -XS(XS_Spell_GetGoodEffect); -XS(XS_Spell_GetGoodEffect) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetGoodEffect(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 good_effect; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - good_effect = THIS->good_effect; - XSprePUSH; - PUSHi((IV) good_effect); - } - XSRETURN(1); -} - -XS(XS_Spell_GetHateAdded); -XS(XS_Spell_GetHateAdded) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetHateAdded(THIS)"); - { - SPDat_Spell_Struct* THIS; - int hate_added; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - hate_added = THIS->hate_added; - XSprePUSH; - PUSHi((IV) hate_added); - } - XSRETURN(1); -} - -XS(XS_Spell_GetHitNumber); -XS(XS_Spell_GetHitNumber) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetHitNumber(THIS)"); - { - SPDat_Spell_Struct* THIS; - int hit_number; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - hit_number = THIS->hit_number; - XSprePUSH; - PUSHi((IV) hit_number); - } - XSRETURN(1); -} - -XS(XS_Spell_GetHitNumberType); -XS(XS_Spell_GetHitNumberType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetHitNumberType(THIS)"); - { - SPDat_Spell_Struct* THIS; - int hit_number_type; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - hit_number_type = THIS->hit_number_type; - XSprePUSH; - PUSHi((IV) hit_number_type); - } - XSRETURN(1); -} - -XS(XS_Spell_GetID); -XS(XS_Spell_GetID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetID(THIS)"); - { - SPDat_Spell_Struct* THIS; - int id; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - id = THIS->id; - XSprePUSH; - PUSHi((IV) id); - } - XSRETURN(1); -} - -XS(XS_Spell_GetIsDiscipline); -XS(XS_Spell_GetIsDiscipline) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetIsDiscipline(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool is_discipline; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - is_discipline = THIS->is_discipline; - ST(0) = boolSV(is_discipline); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetLDoNTrap); -XS(XS_Spell_GetLDoNTrap) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetLDoNTrap(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool ldon_trap; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - ldon_trap = THIS->ldon_trap; - ST(0) = boolSV(ldon_trap); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetLimitValue); -XS(XS_Spell_GetLimitValue) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetLimitValue(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int limit_value; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - limit_value = THIS->limit_value[slot]; - XSprePUSH; - PUSHi((IV) limit_value); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMana); -XS(XS_Spell_GetMana) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMana(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint16 mana; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - mana = THIS->mana; - XSprePUSH; - PUSHu((UV) mana); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMaxDistance); -XS(XS_Spell_GetMaxDistance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMaxDistance(THIS)"); - { - SPDat_Spell_Struct* THIS; - float max_distance; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - max_distance = THIS->max_distance; - XSprePUSH; - PUSHn((double) max_distance); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMaxDistanceMod); -XS(XS_Spell_GetMaxDistanceMod) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMaxDistanceMod(THIS)"); - { - SPDat_Spell_Struct* THIS; - float max_distance_mod; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - max_distance_mod = THIS->max_distance_mod; - XSprePUSH; - PUSHn((double) max_distance_mod); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMaxResist); -XS(XS_Spell_GetMaxResist) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMaxResist(THIS)"); - { - SPDat_Spell_Struct* THIS; - int max_resist; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - max_resist = THIS->max_resist; - XSprePUSH; - PUSHi((IV) max_resist); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMaxValue); -XS(XS_Spell_GetMaxValue) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetMaxValue(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int max_value; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - max_value = THIS->max_value[slot]; - XSprePUSH; - PUSHi((IV) max_value); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMinDistance); -XS(XS_Spell_GetMinDistance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMinDistance(THIS)"); - { - SPDat_Spell_Struct* THIS; - float min_distance; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - min_distance = THIS->min_distance; - XSprePUSH; - PUSHn((double) min_distance); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMinDistanceMod); -XS(XS_Spell_GetMinDistanceMod) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMinDistanceMod(THIS)"); - { - SPDat_Spell_Struct* THIS; - float min_distance_mod; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - min_distance_mod = THIS->min_distance_mod; - XSprePUSH; - PUSHn((double) min_distance_mod); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMinRange); -XS(XS_Spell_GetMinRange) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMinRange(THIS)"); - { - SPDat_Spell_Struct* THIS; - float min_range; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - min_range = THIS->min_range; - XSprePUSH; - PUSHn((double) min_range); - } - XSRETURN(1); -} - -XS(XS_Spell_GetMinResist); -XS(XS_Spell_GetMinResist) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetMinResist(THIS)"); - { - SPDat_Spell_Struct* THIS; - int min_resist; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - min_resist = THIS->min_resist; - XSprePUSH; - PUSHi((IV) min_resist); - } - XSRETURN(1); -} - -XS(XS_Spell_GetName); -XS(XS_Spell_GetName) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetName(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string name; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - name = THIS->name; - sv_setpv(TARG, name.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetNewIcon); -XS(XS_Spell_GetNewIcon) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNewIcon(THIS)"); - { - SPDat_Spell_Struct* THIS; - int16 new_icon; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - new_icon = THIS->new_icon; - XSprePUSH; - PUSHi((IV) new_icon); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNimbusEffect); -XS(XS_Spell_GetNimbusEffect) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNimbusEffect(THIS)"); - { - SPDat_Spell_Struct* THIS; - int nimbus_effect; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - nimbus_effect = THIS->nimbus_effect; - XSprePUSH; - PUSHi((IV) nimbus_effect); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNoBlock); -XS(XS_Spell_GetNoBlock) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNoBlock(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool no_block; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - no_block = THIS->no_block; - ST(0) = boolSV(no_block); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNoDetrimentalSpellAggro); -XS(XS_Spell_GetNoDetrimentalSpellAggro) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNoDetrimentalSpellAggro(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool no_detrimental_spell_aggro; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - no_detrimental_spell_aggro = THIS->no_detrimental_spell_aggro; - ST(0) = boolSV(no_detrimental_spell_aggro); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNoExpendReagent); -XS(XS_Spell_GetNoExpendReagent) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: Spell::GetNoExpendReagent(THIS, uint8 slot)"); - { - SPDat_Spell_Struct* THIS; - int no_expend_reagent; - uint8 slot = (uint8) SvUV(ST(1)); - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - no_expend_reagent = THIS->no_expend_reagent[slot]; - XSprePUSH; - PUSHi((IV) no_expend_reagent); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNoHealDamageItemMod); -XS(XS_Spell_GetNoHealDamageItemMod) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNoHealDamageItemMod(THIS)"); - { - SPDat_Spell_Struct* THIS; - int no_heal_damage_item_mod; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - no_heal_damage_item_mod = THIS->no_heal_damage_item_mod; - XSprePUSH; - PUSHi((IV) no_heal_damage_item_mod); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNoPartialResist); -XS(XS_Spell_GetNoPartialResist) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNoPartialResist(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool no_partial_resist; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - no_partial_resist = THIS->no_partial_resist; - ST(0) = boolSV(no_partial_resist); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNoRemove); -XS(XS_Spell_GetNoRemove) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNoRemove(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool no_remove; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - no_remove = THIS->no_remove; - ST(0) = boolSV(no_remove); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNoResist); -XS(XS_Spell_GetNoResist) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNoResist(THIS)"); - { - SPDat_Spell_Struct* THIS; - int no_resist; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - no_resist = THIS->no_resist; - XSprePUSH; - PUSHi((IV) no_resist); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNotFocusable); -XS(XS_Spell_GetNotFocusable) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNotFocusable(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool not_focusable; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - not_focusable = THIS->not_focusable; - ST(0) = boolSV(not_focusable); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetNPCNoLOS); -XS(XS_Spell_GetNPCNoLOS) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetNPCNoLOS(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool npc_no_los; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - npc_no_los = THIS->npc_no_los; - ST(0) = boolSV(npc_no_los); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetOtherCasts); -XS(XS_Spell_GetOtherCasts) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetOtherCasts(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string other_casts; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - other_casts = THIS->other_casts; - sv_setpv(TARG, other_casts.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetOverrideCritChance); -XS(XS_Spell_GetOverrideCritChance) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetOverrideCritChance(THIS)"); - { - SPDat_Spell_Struct* THIS; - int override_crit_chance; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - override_crit_chance = THIS->override_crit_chance; - XSprePUSH; - PUSHi((IV) override_crit_chance); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPCNPCOnlyFlag); -XS(XS_Spell_GetPCNPCOnlyFlag) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPCNPCOnlyFlag(THIS)"); - { - SPDat_Spell_Struct* THIS; - int pcnpc_only_flag; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - pcnpc_only_flag = THIS->pcnpc_only_flag; - XSprePUSH; - PUSHi((IV) pcnpc_only_flag); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPersistDeath); -XS(XS_Spell_GetPersistDeath) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPersistDeath(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool persist_death; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - persist_death = THIS->persist_death; - ST(0) = boolSV(persist_death); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPlayer_1); -XS(XS_Spell_GetPlayer_1) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPlayer_1(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string player_1; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - player_1 = THIS->player_1; - sv_setpv(TARG, player_1.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetPushBack); -XS(XS_Spell_GetPushBack) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPushBack(THIS)"); - { - SPDat_Spell_Struct* THIS; - float push_back; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - push_back = THIS->push_back; - XSprePUSH; - PUSHn((double) push_back); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPushUp); -XS(XS_Spell_GetPushUp) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPushUp(THIS)"); - { - SPDat_Spell_Struct* THIS; - float push_up; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - push_up = THIS->push_up; - XSprePUSH; - PUSHn((double) push_up); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPVPDuration); -XS(XS_Spell_GetPVPDuration) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPVPDuration(THIS)"); - { - SPDat_Spell_Struct* THIS; - int pvp_duration; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - pvp_duration = THIS->pvp_duration; - XSprePUSH; - PUSHi((IV) pvp_duration); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPVPDurationCap); -XS(XS_Spell_GetPVPDurationCap) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPVPDurationCap(THIS)"); - { - SPDat_Spell_Struct* THIS; - int pvp_duration_cap; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - pvp_duration_cap = THIS->pvp_duration_cap; - XSprePUSH; - PUSHi((IV) pvp_duration_cap); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPVPResistBase); -XS(XS_Spell_GetPVPResistBase) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPVPResistBase(THIS)"); - { - SPDat_Spell_Struct* THIS; - int pvp_resist_base; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - pvp_resist_base = THIS->pvp_resist_base; - XSprePUSH; - PUSHi((IV) pvp_resist_base); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPVPResistCap); -XS(XS_Spell_GetPVPResistCap) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPVPResistCap(THIS)"); - { - SPDat_Spell_Struct* THIS; - int pvp_resist_cap; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - pvp_resist_cap = THIS->pvp_resist_cap; - XSprePUSH; - PUSHi((IV) pvp_resist_cap); - } - XSRETURN(1); -} - -XS(XS_Spell_GetPVPResistPerLevel); -XS(XS_Spell_GetPVPResistPerLevel) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetPVPResistPerLevel(THIS)"); - { - SPDat_Spell_Struct* THIS; - int pvp_resist_per_level; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - pvp_resist_per_level = THIS->pvp_resist_per_level; - XSprePUSH; - PUSHi((IV) pvp_resist_per_level); - } - XSRETURN(1); -} - -XS(XS_Spell_GetRange); -XS(XS_Spell_GetRange) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetRange(THIS)"); - { - SPDat_Spell_Struct* THIS; - float range; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - range = THIS->range; - XSprePUSH; - PUSHn((double) range); - } - XSRETURN(1); -} - -XS(XS_Spell_GetRank); -XS(XS_Spell_GetRank) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetRank(THIS)"); - { - SPDat_Spell_Struct* THIS; - int rank; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - rank = THIS->rank; - XSprePUSH; - PUSHi((IV) rank); - } - XSRETURN(1); -} - -XS(XS_Spell_GetRecastTime); -XS(XS_Spell_GetRecastTime) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetRecastTime(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint32 recast_time; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - recast_time = THIS->recast_time; - XSprePUSH; - PUSHu((UV) recast_time); - } - XSRETURN(1); -} - -XS(XS_Spell_GetRecourseLink); -XS(XS_Spell_GetRecourseLink) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetRecourseLink(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint16 recourse_link; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - recourse_link = THIS->recourse_link; - XSprePUSH; - PUSHu((UV) recourse_link); - } - XSRETURN(1); -} - -XS(XS_Spell_GetRecoveryTime); -XS(XS_Spell_GetRecoveryTime) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetRecoveryTime(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint32 recovery_time; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - recovery_time = THIS->recovery_time; - XSprePUSH; - PUSHu((UV) recovery_time); - } - XSRETURN(1); -} - -XS(XS_Spell_GetReflectable); -XS(XS_Spell_GetReflectable) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetReflectable(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool reflectable; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - reflectable = THIS->reflectable; - ST(0) = boolSV(reflectable); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetResistDifficulty); -XS(XS_Spell_GetResistDifficulty) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetResistDifficulty(THIS)"); - { - SPDat_Spell_Struct* THIS; - int16 resist_difficulty; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - resist_difficulty = THIS->resist_difficulty; - XSprePUSH; - PUSHi((IV) resist_difficulty); - } - XSRETURN(1); -} - -XS(XS_Spell_GetResistType); -XS(XS_Spell_GetResistType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetResistType(THIS)"); - { - SPDat_Spell_Struct* THIS; - int resist_type; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - resist_type = THIS->resist_type; - XSprePUSH; - PUSHi((IV) resist_type); - } - XSRETURN(1); -} - -XS(XS_Spell_GetShortBuffBox); -XS(XS_Spell_GetShortBuffBox) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetShortBuffBox(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 short_buff_box; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - short_buff_box = THIS->short_buff_box; - XSprePUSH; - PUSHi((IV) short_buff_box); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSkill); -XS(XS_Spell_GetSkill) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSkill(THIS)"); - { - SPDat_Spell_Struct* THIS; - EQ::skills::SkillType skill; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - skill = THIS->skill; - XSprePUSH; - PUSHi((IV) skill); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSneak); -XS(XS_Spell_GetSneak) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSneak(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool sneak; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - sneak = THIS->sneak; - ST(0) = boolSV(sneak); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSongCap); -XS(XS_Spell_GetSongCap) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSongCap(THIS)"); - { - SPDat_Spell_Struct* THIS; - int song_cap; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - song_cap = THIS->song_cap; - XSprePUSH; - PUSHi((IV) song_cap); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSpellAffectIndex); -XS(XS_Spell_GetSpellAffectIndex) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSpellAffectIndex(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint16 spell_affect_index; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - spell_affect_index = THIS->spell_affect_index; - XSprePUSH; - PUSHu((UV) spell_affect_index); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSpellCategory); -XS(XS_Spell_GetSpellCategory) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSpellCategory(THIS)"); - { - SPDat_Spell_Struct* THIS; - int spell_category; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - spell_category = THIS->spell_category; - XSprePUSH; - PUSHi((IV) spell_category); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSpellClass); -XS(XS_Spell_GetSpellClass) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSpellClass(THIS)"); - { - SPDat_Spell_Struct* THIS; - int spell_class; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - spell_class = THIS->spell_class; - XSprePUSH; - PUSHi((IV) spell_class); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSpellFades); -XS(XS_Spell_GetSpellFades) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSpellFades(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string spell_fades; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - spell_fades = THIS->spell_fades; - sv_setpv(TARG, spell_fades.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetSpellGroup); -XS(XS_Spell_GetSpellGroup) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSpellGroup(THIS)"); - { - SPDat_Spell_Struct* THIS; - int spell_group; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - spell_group = THIS->spell_group; - XSprePUSH; - PUSHi((IV) spell_group); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSpellSubclass); -XS(XS_Spell_GetSpellSubclass) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSpellSubclass(THIS)"); - { - SPDat_Spell_Struct* THIS; - int spell_subclass; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - spell_subclass = THIS->spell_subclass; - XSprePUSH; - PUSHi((IV) spell_subclass); - } - XSRETURN(1); -} - -XS(XS_Spell_GetSuspendable); -XS(XS_Spell_GetSuspendable) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetSuspendable(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool suspendable; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - suspendable = THIS->suspendable; - ST(0) = boolSV(suspendable); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetTargetType); -XS(XS_Spell_GetTargetType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetTargetType(THIS)"); - { - SPDat_Spell_Struct* THIS; - SpellTargetType target_type; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - target_type = THIS->target_type; - XSprePUSH; - PUSHi((IV) target_type); - } - XSRETURN(1); -} - -XS(XS_Spell_GetTeleportZone); -XS(XS_Spell_GetTeleportZone) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetTeleportZone(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string teleport_zone; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - teleport_zone = THIS->teleport_zone; - sv_setpv(TARG, teleport_zone.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetTimeOfDay); -XS(XS_Spell_GetTimeOfDay) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetTimeOfDay(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 time_of_day; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - time_of_day = THIS->time_of_day; - XSprePUSH; - PUSHi((IV) time_of_day); - } - XSRETURN(1); -} - -XS(XS_Spell_GetTimerID); -XS(XS_Spell_GetTimerID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetTimerID(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 timer_id; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - timer_id = THIS->timer_id; - XSprePUSH; - PUSHi((IV) timer_id); - } - XSRETURN(1); -} - -XS(XS_Spell_GetTypeDescriptionID); -XS(XS_Spell_GetTypeDescriptionID) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetTypeDescriptionID(THIS)"); - { - SPDat_Spell_Struct* THIS; - int type_description_id; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - type_description_id = THIS->type_description_id; - XSprePUSH; - PUSHi((IV) type_description_id); - } - XSRETURN(1); -} - -XS(XS_Spell_GetUninterruptable); -XS(XS_Spell_GetUninterruptable) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetUninterruptable(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool uninterruptable; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - uninterruptable = THIS->uninterruptable; - ST(0) = boolSV(uninterruptable); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetUnstackableDOT); -XS(XS_Spell_GetUnstackableDOT) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetUnstackableDOT(THIS)"); - { - SPDat_Spell_Struct* THIS; - bool unstackable_dot; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - unstackable_dot = THIS->unstackable_dot; - ST(0) = boolSV(unstackable_dot); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_Spell_GetViralRange); -XS(XS_Spell_GetViralRange) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetViralRange(THIS)"); - { - SPDat_Spell_Struct* THIS; - int viral_range; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - viral_range = THIS->viral_range; - XSprePUSH; - PUSHi((IV) viral_range); - } - XSRETURN(1); -} - -XS(XS_Spell_GetViralTargets); -XS(XS_Spell_GetViralTargets) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetViralTargets(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint8 viral_targets; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - viral_targets = THIS->viral_targets; - XSprePUSH; - PUSHu((UV) viral_targets); - } - XSRETURN(1); -} - -XS(XS_Spell_GetViralTimer); -XS(XS_Spell_GetViralTimer) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetViralTimer(THIS)"); - { - SPDat_Spell_Struct* THIS; - uint8 viral_timer; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - viral_timer = THIS->viral_timer; - XSprePUSH; - PUSHu((UV) viral_timer); - } - XSRETURN(1); -} - -XS(XS_Spell_GetYouCast); -XS(XS_Spell_GetYouCast) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetYouCast(THIS)"); - { - SPDat_Spell_Struct* THIS; - std::string you_cast; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - you_cast = THIS->you_cast; - sv_setpv(TARG, you_cast.c_str()); - XSprePUSH; - PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_Spell_GetZoneType); -XS(XS_Spell_GetZoneType) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: Spell::GetZoneType(THIS)"); - { - SPDat_Spell_Struct* THIS; - int8 zone_type; - dXSTARG; - VALIDATE_THIS_IS_SPELL; - - zone_type = THIS->zone_type; - XSprePUSH; - PUSHi((IV) zone_type); - } - XSRETURN(1); -} - -#ifdef __cplusplus -extern "C" -#endif - -XS(boot_Spell); -XS(boot_Spell) { - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - if (items != 1) - fprintf(stderr, "boot_Spell does not take any arguments."); - - char buf[128]; - XS_VERSION_BOOTCHECK; - newXSproto(strcpy(buf, "GetActivated"), XS_Spell_GetActivated, file, "$"); - newXSproto(strcpy(buf, "GetAllowRest"), XS_Spell_GetAllowRest, file, "$"); - newXSproto(strcpy(buf, "GetAOEDuration"), XS_Spell_GetAOEDuration, file, "$"); - newXSproto(strcpy(buf, "GetAOEMaxTargets"), XS_Spell_GetAOEMaxTargets, file, "$"); - newXSproto(strcpy(buf, "GetAOERange"), XS_Spell_GetAOERange, file, "$"); - newXSproto(strcpy(buf, "GetBaseDifficulty"), XS_Spell_GetBaseDifficulty, file, "$"); - newXSproto(strcpy(buf, "GetBaseValue"), XS_Spell_GetBaseValue, file, "$$"); - newXSproto(strcpy(buf, "GetBonusHate"), XS_Spell_GetBonusHate, file, "$"); - newXSproto(strcpy(buf, "GetBuffDuration"), XS_Spell_GetBuffDuration, file, "$"); - newXSproto(strcpy(buf, "GetBuffDurationFormula"), XS_Spell_GetBuffDurationFormula, file, "$"); - newXSproto(strcpy(buf, "GetCanCastInCombat"), XS_Spell_GetCanCastInCombat, file, "$"); - newXSproto(strcpy(buf, "GetCanCastOutOfCombat"), XS_Spell_GetCanCastOutOfCombat, file, "$"); - newXSproto(strcpy(buf, "GetCanMGB"), XS_Spell_GetCanMGB, file, "$"); - newXSproto(strcpy(buf, "GetCastNotStanding"), XS_Spell_GetCastNotStanding, file, "$"); - newXSproto(strcpy(buf, "GetCastOnOther"), XS_Spell_GetCastOnOther, file, "$"); - newXSproto(strcpy(buf, "GetCastOnYou"), XS_Spell_GetCastOnYou, file, "$"); - newXSproto(strcpy(buf, "GetCastRestriction"), XS_Spell_GetCastRestriction, file, "$"); - newXSproto(strcpy(buf, "GetCastTime"), XS_Spell_GetCastTime, file, "$"); - newXSproto(strcpy(buf, "GetCasterRequirementID"), XS_Spell_GetCasterRequirementID, file, "$"); - newXSproto(strcpy(buf, "GetCastingAnimation"), XS_Spell_GetCastingAnimation, file, "$"); - newXSproto(strcpy(buf, "GetClasses"), XS_Spell_GetClasses, file, "$$"); - newXSproto(strcpy(buf, "GetComponent"), XS_Spell_GetComponent, file, "$$"); - newXSproto(strcpy(buf, "GetComponentCount"), XS_Spell_GetComponentCount, file, "$$"); - newXSproto(strcpy(buf, "GetDeities"), XS_Spell_GetDeities, file, "$$"); - newXSproto(strcpy(buf, "GetDeityAgnostic"), XS_Spell_GetDeityAgnostic, file, "$"); - newXSproto(strcpy(buf, "GetDescriptionID"), XS_Spell_GetDescriptionID, file, "$"); - newXSproto(strcpy(buf, "GetDirectionalEnd"), XS_Spell_GetDirectionalEnd, file, "$"); - newXSproto(strcpy(buf, "GetDirectionalStart"), XS_Spell_GetDirectionalStart, file, "$"); - newXSproto(strcpy(buf, "GetDisallowSit"), XS_Spell_GetDisallowSit, file, "$"); - newXSproto(strcpy(buf, "GetDispelFlag"), XS_Spell_GetDispelFlag, file, "$"); - newXSproto(strcpy(buf, "GetEffectDescriptionID"), XS_Spell_GetEffectDescriptionID, file, "$"); - newXSproto(strcpy(buf, "GetEffectID"), XS_Spell_GetEffectID, file, "$$"); - newXSproto(strcpy(buf, "GetEnduranceCost"), XS_Spell_GetEnduranceCost, file, "$"); - newXSproto(strcpy(buf, "GetEnduranceUpkeep"), XS_Spell_GetEnduranceUpkeep, file, "$"); - newXSproto(strcpy(buf, "GetEnvironmentType"), XS_Spell_GetEnvironmentType, file, "$"); - newXSproto(strcpy(buf, "GetFeedbackable"), XS_Spell_GetFeedbackable, file, "$"); - newXSproto(strcpy(buf, "GetFormula"), XS_Spell_GetFormula, file, "$$"); - newXSproto(strcpy(buf, "GetGoodEffect"), XS_Spell_GetGoodEffect, file, "$"); - newXSproto(strcpy(buf, "GetHateAdded"), XS_Spell_GetHateAdded, file, "$"); - newXSproto(strcpy(buf, "GetHitNumber"), XS_Spell_GetHitNumber, file, "$"); - newXSproto(strcpy(buf, "GetHitNumberType"), XS_Spell_GetHitNumberType, file, "$"); - newXSproto(strcpy(buf, "GetID"), XS_Spell_GetID, file, "$"); - newXSproto(strcpy(buf, "GetIsDiscipline"), XS_Spell_GetIsDiscipline, file, "$"); - newXSproto(strcpy(buf, "GetLDoNTrap"), XS_Spell_GetLDoNTrap, file, "$"); - newXSproto(strcpy(buf, "GetLimitValue"), XS_Spell_GetLimitValue, file, "$$"); - newXSproto(strcpy(buf, "GetMana"), XS_Spell_GetMana, file, "$"); - newXSproto(strcpy(buf, "GetMaxDistance"), XS_Spell_GetMaxDistance, file, "$"); - newXSproto(strcpy(buf, "GetMaxDistanceMod"), XS_Spell_GetMaxDistanceMod, file, "$"); - newXSproto(strcpy(buf, "GetMaxResist"), XS_Spell_GetMaxResist, file, "$"); - newXSproto(strcpy(buf, "GetMaxValue"), XS_Spell_GetMaxValue, file, "$$"); - newXSproto(strcpy(buf, "GetMinDistance"), XS_Spell_GetMinDistance, file, "$"); - newXSproto(strcpy(buf, "GetMinDistanceMod"), XS_Spell_GetMinDistanceMod, file, "$"); - newXSproto(strcpy(buf, "GetMinRange"), XS_Spell_GetMinRange, file, "$"); - newXSproto(strcpy(buf, "GetMinResist"), XS_Spell_GetMinResist, file, "$"); - newXSproto(strcpy(buf, "GetName"), XS_Spell_GetName, file, "$"); - newXSproto(strcpy(buf, "GetNewIcon"), XS_Spell_GetNewIcon, file, "$"); - newXSproto(strcpy(buf, "GetNimbusEffect"), XS_Spell_GetNimbusEffect, file, "$"); - newXSproto(strcpy(buf, "GetNoBlock"), XS_Spell_GetNoBlock, file, "$"); - newXSproto(strcpy(buf, "GetNoDetrimentalSpellAggro"), XS_Spell_GetNoDetrimentalSpellAggro, file, "$"); - newXSproto(strcpy(buf, "GetNoExpendReagent"), XS_Spell_GetNoExpendReagent, file, "$$"); - newXSproto(strcpy(buf, "GetNoHealDamageItemMod"), XS_Spell_GetNoHealDamageItemMod, file, "$"); - newXSproto(strcpy(buf, "GetNoPartialResist"), XS_Spell_GetNoPartialResist, file, "$"); - newXSproto(strcpy(buf, "GetNoRemove"), XS_Spell_GetNoRemove, file, "$"); - newXSproto(strcpy(buf, "GetNoResist"), XS_Spell_GetNoResist, file, "$"); - newXSproto(strcpy(buf, "GetNotFocusable"), XS_Spell_GetNotFocusable, file, "$"); - newXSproto(strcpy(buf, "GetNPCNoLOS"), XS_Spell_GetNPCNoLOS, file, "$"); - newXSproto(strcpy(buf, "GetOtherCasts"), XS_Spell_GetOtherCasts, file, "$"); - newXSproto(strcpy(buf, "GetOverrideCritChance"), XS_Spell_GetOverrideCritChance, file, "$"); - newXSproto(strcpy(buf, "GetPCNPCOnlyFlag"), XS_Spell_GetPCNPCOnlyFlag, file, "$"); - newXSproto(strcpy(buf, "GetPersistDeath"), XS_Spell_GetPersistDeath, file, "$"); - newXSproto(strcpy(buf, "GetPlayer_1"), XS_Spell_GetPlayer_1, file, "$"); - newXSproto(strcpy(buf, "GetPushBack"), XS_Spell_GetPushBack, file, "$"); - newXSproto(strcpy(buf, "GetPushUp"), XS_Spell_GetPushUp, file, "$"); - newXSproto(strcpy(buf, "GetPVPDuration"), XS_Spell_GetPVPDuration, file, "$"); - newXSproto(strcpy(buf, "GetPVPDurationCap"), XS_Spell_GetPVPDurationCap, file, "$"); - newXSproto(strcpy(buf, "GetPVPResistBase"), XS_Spell_GetPVPResistBase, file, "$"); - newXSproto(strcpy(buf, "GetPVPResistCap"), XS_Spell_GetPVPResistCap, file, "$"); - newXSproto(strcpy(buf, "GetPVPResistPerLevel"), XS_Spell_GetPVPResistPerLevel, file, "$"); - newXSproto(strcpy(buf, "GetRange"), XS_Spell_GetRange, file, "$"); - newXSproto(strcpy(buf, "GetRank"), XS_Spell_GetRank, file, "$"); - newXSproto(strcpy(buf, "GetRecastTime"), XS_Spell_GetRecastTime, file, "$"); - newXSproto(strcpy(buf, "GetRecourseLink"), XS_Spell_GetRecourseLink, file, "$"); - newXSproto(strcpy(buf, "GetRecoveryTime"), XS_Spell_GetRecoveryTime, file, "$"); - newXSproto(strcpy(buf, "GetReflectable"), XS_Spell_GetReflectable, file, "$"); - newXSproto(strcpy(buf, "GetResistDifficulty"), XS_Spell_GetResistDifficulty, file, "$"); - newXSproto(strcpy(buf, "GetResistType"), XS_Spell_GetResistType, file, "$"); - newXSproto(strcpy(buf, "GetShortBuffBox"), XS_Spell_GetShortBuffBox, file, "$"); - newXSproto(strcpy(buf, "GetSkill"), XS_Spell_GetSkill, file, "$"); - newXSproto(strcpy(buf, "GetSneak"), XS_Spell_GetSneak, file, "$"); - newXSproto(strcpy(buf, "GetSongCap"), XS_Spell_GetSongCap, file, "$"); - newXSproto(strcpy(buf, "GetSpellAffectIndex"), XS_Spell_GetSpellAffectIndex, file, "$"); - newXSproto(strcpy(buf, "GetSpellCategory"), XS_Spell_GetSpellCategory, file, "$"); - newXSproto(strcpy(buf, "GetSpellClass"), XS_Spell_GetSpellClass, file, "$"); - newXSproto(strcpy(buf, "GetSpellFades"), XS_Spell_GetSpellFades, file, "$"); - newXSproto(strcpy(buf, "GetSpellGroup"), XS_Spell_GetSpellGroup, file, "$"); - newXSproto(strcpy(buf, "GetSpellSubclass"), XS_Spell_GetSpellSubclass, file, "$"); - newXSproto(strcpy(buf, "GetSuspendable"), XS_Spell_GetSuspendable, file, "$"); - newXSproto(strcpy(buf, "GetTargetType"), XS_Spell_GetTargetType, file, "$"); - newXSproto(strcpy(buf, "GetTeleportZone"), XS_Spell_GetTeleportZone, file, "$"); - newXSproto(strcpy(buf, "GetTimeOfDay"), XS_Spell_GetTimeOfDay, file, "$"); - newXSproto(strcpy(buf, "GetTimerID"), XS_Spell_GetTimerID, file, "$"); - newXSproto(strcpy(buf, "GetTypeDescriptionID"), XS_Spell_GetTypeDescriptionID, file, "$"); - newXSproto(strcpy(buf, "GetUninterruptable"), XS_Spell_GetUninterruptable, file, "$"); - newXSproto(strcpy(buf, "GetUnstackableDOT"), XS_Spell_GetUnstackableDOT, file, "$"); - newXSproto(strcpy(buf, "GetViralRange"), XS_Spell_GetViralRange, file, "$"); - newXSproto(strcpy(buf, "GetViralTargets"), XS_Spell_GetViralTargets, file, "$"); - newXSproto(strcpy(buf, "GetViralTimer"), XS_Spell_GetViralTimer, file, "$"); - newXSproto(strcpy(buf, "GetYouCast"), XS_Spell_GetYouCast, file, "$"); - newXSproto(strcpy(buf, "GetZoneType"), XS_Spell_GetZoneType, file, "$"); - XSRETURN_YES; +int Perl_Spell_GetActivated(SPDat_Spell_Struct* self) +{ + return self->activated; +} + +bool Perl_Spell_GetAllowRest(SPDat_Spell_Struct* self) +{ + return self->allow_rest; +} + +uint32_t Perl_Spell_GetAOEDuration(SPDat_Spell_Struct* self) +{ + return self->aoe_duration; +} + +int Perl_Spell_GetAOEMaxTargets(SPDat_Spell_Struct* self) +{ + return self->aoe_max_targets; +} + +float Perl_Spell_GetAOERange(SPDat_Spell_Struct* self) +{ + return self->aoe_range; +} + +int Perl_Spell_GetBaseDifficulty(SPDat_Spell_Struct* self) +{ + return self->base_difficulty; +} + +int Perl_Spell_GetBaseValue(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->base_value[slot]; +} + +int Perl_Spell_GetBonusHate(SPDat_Spell_Struct* self) +{ + return self->bonus_hate; +} + +uint32_t Perl_Spell_GetBuffDuration(SPDat_Spell_Struct* self) +{ + return self->buff_duration; +} + +uint32_t Perl_Spell_GetBuffDurationFormula(SPDat_Spell_Struct* self) +{ + return self->buff_duration_formula; +} + +bool Perl_Spell_GetCanCastInCombat(SPDat_Spell_Struct* self) +{ + return self->can_cast_in_combat; +} + +bool Perl_Spell_GetCanCastOutOfCombat(SPDat_Spell_Struct* self) +{ + return self->can_cast_out_of_combat; +} + +bool Perl_Spell_GetCanMGB(SPDat_Spell_Struct* self) +{ + return self->can_mgb; +} + +bool Perl_Spell_GetCastNotStanding(SPDat_Spell_Struct* self) +{ + return self->cast_not_standing; +} + +std::string Perl_Spell_GetCastOnOther(SPDat_Spell_Struct* self) +{ + return self->cast_on_other; +} + +std::string Perl_Spell_GetCastOnYou(SPDat_Spell_Struct* self) +{ + return self->cast_on_you; +} + +int Perl_Spell_GetCastRestriction(SPDat_Spell_Struct* self) +{ + return self->cast_restriction; +} + +uint32_t Perl_Spell_GetCastTime(SPDat_Spell_Struct* self) +{ + return self->cast_time; +} + +int Perl_Spell_GetCasterRequirementID(SPDat_Spell_Struct* self) +{ + return self->caster_requirement_id; +} + +int Perl_Spell_GetCastingAnimation(SPDat_Spell_Struct* self) +{ + return self->casting_animation; +} + +int Perl_Spell_GetClasses(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->classes[slot]; +} + +int Perl_Spell_GetComponent(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->component[slot]; +} + +int Perl_Spell_GetComponentCount(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->component_count[slot]; +} + +int Perl_Spell_GetDeities(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->deities[slot]; +} + +int Perl_Spell_GetDeityAgnostic(SPDat_Spell_Struct* self) +{ + return self->deity_agnostic; +} + +int Perl_Spell_GetDescriptionID(SPDat_Spell_Struct* self) +{ + return self->description_id; +} + +float Perl_Spell_GetDirectionalEnd(SPDat_Spell_Struct* self) +{ + return self->directional_end; +} + +float Perl_Spell_GetDirectionalStart(SPDat_Spell_Struct* self) +{ + return self->directional_start; +} + +int Perl_Spell_GetDisallowSit(SPDat_Spell_Struct* self) +{ + return self->disallow_sit; +} + +int Perl_Spell_GetDispelFlag(SPDat_Spell_Struct* self) +{ + return self->dispel_flag; +} + +int Perl_Spell_GetEffectDescriptionID(SPDat_Spell_Struct* self) +{ + return self->effect_description_id; +} + +int Perl_Spell_GetEffectID(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->effect_id[slot]; +} + +int Perl_Spell_GetEnduranceCost(SPDat_Spell_Struct* self) +{ + return self->endurance_cost; +} + +int Perl_Spell_GetEnduranceUpkeep(SPDat_Spell_Struct* self) +{ + return self->endurance_upkeep; +} + +int Perl_Spell_GetEnvironmentType(SPDat_Spell_Struct* self) +{ + return self->environment_type; +} + +bool Perl_Spell_GetFeedbackable(SPDat_Spell_Struct* self) +{ + return self->feedbackable; +} + +int Perl_Spell_GetFormula(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->formula[slot]; +} + +int Perl_Spell_GetGoodEffect(SPDat_Spell_Struct* self) +{ + return self->good_effect; +} + +int Perl_Spell_GetHateAdded(SPDat_Spell_Struct* self) +{ + return self->hate_added; +} + +int Perl_Spell_GetHitNumber(SPDat_Spell_Struct* self) +{ + return self->hit_number; +} + +int Perl_Spell_GetHitNumberType(SPDat_Spell_Struct* self) +{ + return self->hit_number_type; +} + +int Perl_Spell_GetID(SPDat_Spell_Struct* self) +{ + return self->id; +} + +bool Perl_Spell_GetIsDiscipline(SPDat_Spell_Struct* self) +{ + return self->is_discipline; +} + +bool Perl_Spell_GetLDoNTrap(SPDat_Spell_Struct* self) +{ + return self->ldon_trap; +} + +int Perl_Spell_GetLimitValue(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->limit_value[slot]; +} + +int Perl_Spell_GetMana(SPDat_Spell_Struct* self) +{ + return self->mana; +} + +float Perl_Spell_GetMaxDistance(SPDat_Spell_Struct* self) +{ + return self->max_distance; +} + +float Perl_Spell_GetMaxDistanceMod(SPDat_Spell_Struct* self) +{ + return self->max_distance_mod; +} + +int Perl_Spell_GetMaxResist(SPDat_Spell_Struct* self) +{ + return self->max_resist; +} + +int Perl_Spell_GetMaxValue(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->max_value[slot]; +} + +float Perl_Spell_GetMinDistance(SPDat_Spell_Struct* self) +{ + return self->min_distance; +} + +float Perl_Spell_GetMinDistanceMod(SPDat_Spell_Struct* self) +{ + return self->min_distance_mod; +} + +float Perl_Spell_GetMinRange(SPDat_Spell_Struct* self) +{ + return self->min_range; +} + +int Perl_Spell_GetMinResist(SPDat_Spell_Struct* self) +{ + return self->min_resist; +} + +std::string Perl_Spell_GetName(SPDat_Spell_Struct* self) +{ + return self->name; +} + +int Perl_Spell_GetNewIcon(SPDat_Spell_Struct* self) +{ + return self->new_icon; +} + +int Perl_Spell_GetNimbusEffect(SPDat_Spell_Struct* self) +{ + return self->nimbus_effect; +} + +bool Perl_Spell_GetNoBlock(SPDat_Spell_Struct* self) +{ + return self->no_block; +} + +bool Perl_Spell_GetNoDetrimentalSpellAggro(SPDat_Spell_Struct* self) +{ + return self->no_detrimental_spell_aggro; +} + +int Perl_Spell_GetNoExpendReagent(SPDat_Spell_Struct* self, uint8_t slot) +{ + return self->no_expend_reagent[slot]; +} + +int Perl_Spell_GetNoHealDamageItemMod(SPDat_Spell_Struct* self) +{ + return self->no_heal_damage_item_mod; +} + +bool Perl_Spell_GetNoPartialResist(SPDat_Spell_Struct* self) +{ + return self->no_partial_resist; +} + +bool Perl_Spell_GetNoRemove(SPDat_Spell_Struct* self) +{ + return self->no_remove; +} + +int Perl_Spell_GetNoResist(SPDat_Spell_Struct* self) +{ + return self->no_resist; +} + +bool Perl_Spell_GetNotFocusable(SPDat_Spell_Struct* self) +{ + return self->not_focusable; +} + +bool Perl_Spell_GetNPCNoLOS(SPDat_Spell_Struct* self) +{ + return self->npc_no_los; +} + +std::string Perl_Spell_GetOtherCasts(SPDat_Spell_Struct* self) +{ + return self->other_casts; +} + +int Perl_Spell_GetOverrideCritChance(SPDat_Spell_Struct* self) +{ + return self->override_crit_chance; +} + +int Perl_Spell_GetPCNPCOnlyFlag(SPDat_Spell_Struct* self) +{ + return self->pcnpc_only_flag; +} + +bool Perl_Spell_GetPersistDeath(SPDat_Spell_Struct* self) +{ + return self->persist_death; +} + +std::string Perl_Spell_GetPlayer_1(SPDat_Spell_Struct* self) +{ + return self->player_1; +} + +float Perl_Spell_GetPushBack(SPDat_Spell_Struct* self) +{ + return self->push_back; +} + +float Perl_Spell_GetPushUp(SPDat_Spell_Struct* self) +{ + return self->push_up; +} + +int Perl_Spell_GetPVPDuration(SPDat_Spell_Struct* self) +{ + return self->pvp_duration; +} + +int Perl_Spell_GetPVPDurationCap(SPDat_Spell_Struct* self) +{ + return self->pvp_duration_cap; +} + +int Perl_Spell_GetPVPResistBase(SPDat_Spell_Struct* self) +{ + return self->pvp_resist_base; +} + +int Perl_Spell_GetPVPResistCap(SPDat_Spell_Struct* self) +{ + return self->pvp_resist_cap; +} + +int Perl_Spell_GetPVPResistPerLevel(SPDat_Spell_Struct* self) +{ + return self->pvp_resist_per_level; +} + +float Perl_Spell_GetRange(SPDat_Spell_Struct* self) +{ + return self->range; +} + +int Perl_Spell_GetRank(SPDat_Spell_Struct* self) +{ + return self->rank; +} + +uint32_t Perl_Spell_GetRecastTime(SPDat_Spell_Struct* self) +{ + return self->recast_time; +} + +int Perl_Spell_GetRecourseLink(SPDat_Spell_Struct* self) +{ + return self->recourse_link; +} + +uint32_t Perl_Spell_GetRecoveryTime(SPDat_Spell_Struct* self) +{ + return self->recovery_time; +} + +bool Perl_Spell_GetReflectable(SPDat_Spell_Struct* self) +{ + return self->reflectable; +} + +int Perl_Spell_GetResistDifficulty(SPDat_Spell_Struct* self) +{ + return self->resist_difficulty; +} + +int Perl_Spell_GetResistType(SPDat_Spell_Struct* self) +{ + return self->resist_type; +} + +int Perl_Spell_GetShortBuffBox(SPDat_Spell_Struct* self) +{ + return self->short_buff_box; +} + +int Perl_Spell_GetSkill(SPDat_Spell_Struct* self) +{ + return self->skill; +} + +bool Perl_Spell_GetSneak(SPDat_Spell_Struct* self) +{ + return self->sneak; +} + +int Perl_Spell_GetSongCap(SPDat_Spell_Struct* self) +{ + return self->song_cap; +} + +int Perl_Spell_GetSpellAffectIndex(SPDat_Spell_Struct* self) +{ + return self->spell_affect_index; +} + +int Perl_Spell_GetSpellCategory(SPDat_Spell_Struct* self) +{ + return self->spell_category; +} + +int Perl_Spell_GetSpellClass(SPDat_Spell_Struct* self) +{ + return self->spell_class; +} + +std::string Perl_Spell_GetSpellFades(SPDat_Spell_Struct* self) +{ + return self->spell_fades; +} + +int Perl_Spell_GetSpellGroup(SPDat_Spell_Struct* self) +{ + return self->spell_group; +} + +int Perl_Spell_GetSpellSubclass(SPDat_Spell_Struct* self) +{ + return self->spell_subclass; +} + +bool Perl_Spell_GetSuspendable(SPDat_Spell_Struct* self) +{ + return self->suspendable; +} + +int Perl_Spell_GetTargetType(SPDat_Spell_Struct* self) +{ + return self->target_type; +} + +std::string Perl_Spell_GetTeleportZone(SPDat_Spell_Struct* self) +{ + return self->teleport_zone; +} + +int Perl_Spell_GetTimeOfDay(SPDat_Spell_Struct* self) +{ + return self->time_of_day; +} + +int Perl_Spell_GetTimerID(SPDat_Spell_Struct* self) +{ + return self->timer_id; +} + +int Perl_Spell_GetTypeDescriptionID(SPDat_Spell_Struct* self) +{ + return self->type_description_id; +} + +bool Perl_Spell_GetUninterruptable(SPDat_Spell_Struct* self) +{ + return self->uninterruptable; +} + +bool Perl_Spell_GetUnstackableDOT(SPDat_Spell_Struct* self) +{ + return self->unstackable_dot; +} + +int Perl_Spell_GetViralRange(SPDat_Spell_Struct* self) +{ + return self->viral_range; +} + +int Perl_Spell_GetViralTargets(SPDat_Spell_Struct* self) +{ + return self->viral_targets; +} + +int Perl_Spell_GetViralTimer(SPDat_Spell_Struct* self) +{ + return self->viral_timer; +} + +std::string Perl_Spell_GetYouCast(SPDat_Spell_Struct* self) +{ + return self->you_cast; +} + +int Perl_Spell_GetZoneType(SPDat_Spell_Struct* self) +{ + return self->zone_type; +} + +void perl_register_spell() +{ + perl::interpreter perl(PERL_GET_THX); + + auto package = perl.new_class("Spell"); + package.add("GetActivated", &Perl_Spell_GetActivated); + package.add("GetAllowRest", &Perl_Spell_GetAllowRest); + package.add("GetAOEDuration", &Perl_Spell_GetAOEDuration); + package.add("GetAOEMaxTargets", &Perl_Spell_GetAOEMaxTargets); + package.add("GetAOERange", &Perl_Spell_GetAOERange); + package.add("GetBaseDifficulty", &Perl_Spell_GetBaseDifficulty); + package.add("GetBaseValue", &Perl_Spell_GetBaseValue); + package.add("GetBonusHate", &Perl_Spell_GetBonusHate); + package.add("GetBuffDuration", &Perl_Spell_GetBuffDuration); + package.add("GetBuffDurationFormula", &Perl_Spell_GetBuffDurationFormula); + package.add("GetCanCastInCombat", &Perl_Spell_GetCanCastInCombat); + package.add("GetCanCastOutOfCombat", &Perl_Spell_GetCanCastOutOfCombat); + package.add("GetCanMGB", &Perl_Spell_GetCanMGB); + package.add("GetCastNotStanding", &Perl_Spell_GetCastNotStanding); + package.add("GetCastOnOther", &Perl_Spell_GetCastOnOther); + package.add("GetCastOnYou", &Perl_Spell_GetCastOnYou); + package.add("GetCastRestriction", &Perl_Spell_GetCastRestriction); + package.add("GetCastTime", &Perl_Spell_GetCastTime); + package.add("GetCasterRequirementID", &Perl_Spell_GetCasterRequirementID); + package.add("GetCastingAnimation", &Perl_Spell_GetCastingAnimation); + package.add("GetClasses", &Perl_Spell_GetClasses); + package.add("GetComponent", &Perl_Spell_GetComponent); + package.add("GetComponentCount", &Perl_Spell_GetComponentCount); + package.add("GetDeities", &Perl_Spell_GetDeities); + package.add("GetDeityAgnostic", &Perl_Spell_GetDeityAgnostic); + package.add("GetDescriptionID", &Perl_Spell_GetDescriptionID); + package.add("GetDirectionalEnd", &Perl_Spell_GetDirectionalEnd); + package.add("GetDirectionalStart", &Perl_Spell_GetDirectionalStart); + package.add("GetDisallowSit", &Perl_Spell_GetDisallowSit); + package.add("GetDispelFlag", &Perl_Spell_GetDispelFlag); + package.add("GetEffectDescriptionID", &Perl_Spell_GetEffectDescriptionID); + package.add("GetEffectID", &Perl_Spell_GetEffectID); + package.add("GetEnduranceCost", &Perl_Spell_GetEnduranceCost); + package.add("GetEnduranceUpkeep", &Perl_Spell_GetEnduranceUpkeep); + package.add("GetEnvironmentType", &Perl_Spell_GetEnvironmentType); + package.add("GetFeedbackable", &Perl_Spell_GetFeedbackable); + package.add("GetFormula", &Perl_Spell_GetFormula); + package.add("GetGoodEffect", &Perl_Spell_GetGoodEffect); + package.add("GetHateAdded", &Perl_Spell_GetHateAdded); + package.add("GetHitNumber", &Perl_Spell_GetHitNumber); + package.add("GetHitNumberType", &Perl_Spell_GetHitNumberType); + package.add("GetID", &Perl_Spell_GetID); + package.add("GetIsDiscipline", &Perl_Spell_GetIsDiscipline); + package.add("GetLDoNTrap", &Perl_Spell_GetLDoNTrap); + package.add("GetLimitValue", &Perl_Spell_GetLimitValue); + package.add("GetMana", &Perl_Spell_GetMana); + package.add("GetMaxDistance", &Perl_Spell_GetMaxDistance); + package.add("GetMaxDistanceMod", &Perl_Spell_GetMaxDistanceMod); + package.add("GetMaxResist", &Perl_Spell_GetMaxResist); + package.add("GetMaxValue", &Perl_Spell_GetMaxValue); + package.add("GetMinDistance", &Perl_Spell_GetMinDistance); + package.add("GetMinDistanceMod", &Perl_Spell_GetMinDistanceMod); + package.add("GetMinRange", &Perl_Spell_GetMinRange); + package.add("GetMinResist", &Perl_Spell_GetMinResist); + package.add("GetName", &Perl_Spell_GetName); + package.add("GetNewIcon", &Perl_Spell_GetNewIcon); + package.add("GetNimbusEffect", &Perl_Spell_GetNimbusEffect); + package.add("GetNoBlock", &Perl_Spell_GetNoBlock); + package.add("GetNoDetrimentalSpellAggro", &Perl_Spell_GetNoDetrimentalSpellAggro); + package.add("GetNoExpendReagent", &Perl_Spell_GetNoExpendReagent); + package.add("GetNoHealDamageItemMod", &Perl_Spell_GetNoHealDamageItemMod); + package.add("GetNoPartialResist", &Perl_Spell_GetNoPartialResist); + package.add("GetNoRemove", &Perl_Spell_GetNoRemove); + package.add("GetNoResist", &Perl_Spell_GetNoResist); + package.add("GetNotFocusable", &Perl_Spell_GetNotFocusable); + package.add("GetNPCNoLOS", &Perl_Spell_GetNPCNoLOS); + package.add("GetOtherCasts", &Perl_Spell_GetOtherCasts); + package.add("GetOverrideCritChance", &Perl_Spell_GetOverrideCritChance); + package.add("GetPCNPCOnlyFlag", &Perl_Spell_GetPCNPCOnlyFlag); + package.add("GetPersistDeath", &Perl_Spell_GetPersistDeath); + package.add("GetPlayer_1", &Perl_Spell_GetPlayer_1); + package.add("GetPushBack", &Perl_Spell_GetPushBack); + package.add("GetPushUp", &Perl_Spell_GetPushUp); + package.add("GetPVPDuration", &Perl_Spell_GetPVPDuration); + package.add("GetPVPDurationCap", &Perl_Spell_GetPVPDurationCap); + package.add("GetPVPResistBase", &Perl_Spell_GetPVPResistBase); + package.add("GetPVPResistCap", &Perl_Spell_GetPVPResistCap); + package.add("GetPVPResistPerLevel", &Perl_Spell_GetPVPResistPerLevel); + package.add("GetRange", &Perl_Spell_GetRange); + package.add("GetRank", &Perl_Spell_GetRank); + package.add("GetRecastTime", &Perl_Spell_GetRecastTime); + package.add("GetRecourseLink", &Perl_Spell_GetRecourseLink); + package.add("GetRecoveryTime", &Perl_Spell_GetRecoveryTime); + package.add("GetReflectable", &Perl_Spell_GetReflectable); + package.add("GetResistDifficulty", &Perl_Spell_GetResistDifficulty); + package.add("GetResistType", &Perl_Spell_GetResistType); + package.add("GetShortBuffBox", &Perl_Spell_GetShortBuffBox); + package.add("GetSkill", &Perl_Spell_GetSkill); + package.add("GetSneak", &Perl_Spell_GetSneak); + package.add("GetSongCap", &Perl_Spell_GetSongCap); + package.add("GetSpellAffectIndex", &Perl_Spell_GetSpellAffectIndex); + package.add("GetSpellCategory", &Perl_Spell_GetSpellCategory); + package.add("GetSpellClass", &Perl_Spell_GetSpellClass); + package.add("GetSpellFades", &Perl_Spell_GetSpellFades); + package.add("GetSpellGroup", &Perl_Spell_GetSpellGroup); + package.add("GetSpellSubclass", &Perl_Spell_GetSpellSubclass); + package.add("GetSuspendable", &Perl_Spell_GetSuspendable); + package.add("GetTargetType", &Perl_Spell_GetTargetType); + package.add("GetTeleportZone", &Perl_Spell_GetTeleportZone); + package.add("GetTimeOfDay", &Perl_Spell_GetTimeOfDay); + package.add("GetTimerID", &Perl_Spell_GetTimerID); + package.add("GetTypeDescriptionID", &Perl_Spell_GetTypeDescriptionID); + package.add("GetUninterruptable", &Perl_Spell_GetUninterruptable); + package.add("GetUnstackableDOT", &Perl_Spell_GetUnstackableDOT); + package.add("GetViralRange", &Perl_Spell_GetViralRange); + package.add("GetViralTargets", &Perl_Spell_GetViralTargets); + package.add("GetViralTimer", &Perl_Spell_GetViralTimer); + package.add("GetYouCast", &Perl_Spell_GetYouCast); + package.add("GetZoneType", &Perl_Spell_GetZoneType); } #endif //EMBPERL_XS_CLASSES diff --git a/zone/petitions.cpp b/zone/petitions.cpp index b55236634..d5accbbd3 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -33,7 +33,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/eq_packet_structs.h" #include "../common/servertalk.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "entity.h" #include "petitions.h" @@ -71,8 +71,8 @@ void Petition::SendPetitionToPlayer(Client* clientto) { Petition::Petition(uint32 id) { petid = id; - charclass = 0; - charrace = 0; + charclass = NO_CLASS; + charrace = RACE_DOUG_0; charlevel = 0; checkouts = 0; unavailables = 0; diff --git a/zone/petitions.h b/zone/petitions.h index 4a6e9d2ff..2e8ee96a6 100644 --- a/zone/petitions.h +++ b/zone/petitions.h @@ -25,7 +25,7 @@ #include "client.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" class Client; diff --git a/zone/pets.cpp b/zone/pets.cpp index 8aa726b9a..691ef8ebd 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -18,7 +18,7 @@ #include "../common/global_define.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/types.h" #include "entity.h" @@ -27,13 +27,11 @@ #include "pets.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include -#ifdef BOTS #include "bot.h" -#endif #ifndef WIN32 #include @@ -198,10 +196,8 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);//Client only act_power = CastToClient()->mod_pet_power(act_power, spell_id); } -#ifdef BOTS else if (IsBot()) - act_power = CastToBot()->GetBotFocusEffect(focusPetPower, spell_id); -#endif + act_power = CastToBot()->GetFocusEffect(focusPetPower, spell_id); } else if (petpower > 0) act_power = petpower; @@ -231,11 +227,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, memcpy(npc_type, base, sizeof(NPCType)); // If pet power is set to -1 in the DB, use stat scaling - if ((IsClient() -#ifdef BOTS - || IsBot() -#endif - ) && record.petpower == -1) + if ((IsClient() || IsBot()) && record.petpower == -1) { float scale_power = (float)act_power / 100.0f; if(scale_power > 0) @@ -529,6 +521,23 @@ Mob* Mob::GetPet() { return(tmp); } +bool Mob::HasPet() const { + if (GetPetID() == 0) { + return false; + } + + const auto m = entity_list.GetMob(GetPetID()); + if (!m) { + return false; + } + + if (m->GetOwnerID() != GetID()) { + return false; + } + + return true; +} + void Mob::SetPet(Mob* newpet) { Mob* oldpet = GetPet(); if (oldpet) { @@ -735,11 +744,11 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { return true; } -bool Pet::CheckSpellLevelRestriction(uint16 spell_id) +bool Pet::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id) { auto owner = GetOwner(); if (owner) - return owner->CheckSpellLevelRestriction(spell_id); + return owner->CheckSpellLevelRestriction(caster, spell_id); return true; } diff --git a/zone/pets.h b/zone/pets.h index 1b9811149..f8ab50eca 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -7,7 +7,7 @@ struct NPCType; class Pet : public NPC { public: Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power); - virtual bool CheckSpellLevelRestriction(uint16 spell_id); + virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id); }; diff --git a/zone/position.cpp b/zone/position.cpp index cc4317e0e..c2da54be8 100644 --- a/zone/position.cpp +++ b/zone/position.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "../common/string_util.h" +#include "../common/strings.h" static const float position_eps = 0.0001f; diff --git a/zone/qglobals.cpp b/zone/qglobals.cpp index f1719def5..fee93765d 100644 --- a/zone/qglobals.cpp +++ b/zone/qglobals.cpp @@ -1,4 +1,4 @@ -#include "../common/string_util.h" +#include "../common/strings.h" #include "qglobals.h" #include "client.h" diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index 6e8b57423..de26c6be1 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -18,18 +18,20 @@ Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) #include "../common/global_define.h" #include "../common/servertalk.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "queryserv.h" #include "worldserver.h" extern WorldServer worldserver; -extern QueryServ* QServ; +extern QueryServ *QServ; -QueryServ::QueryServ(){ +QueryServ::QueryServ() +{ } -QueryServ::~QueryServ(){ +QueryServ::~QueryServ() +{ } void QueryServ::SendQuery(std::string Query) @@ -44,7 +46,9 @@ void QueryServ::SendQuery(std::string Query) void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc) { std::string query = StringFormat( - "INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))", - Event_Type, Character_ID, EscapeString(Event_Desc).c_str()); + "INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))", + Event_Type, + Character_ID, + Strings::Escape(Event_Desc).c_str()); SendQuery(query); } diff --git a/zone/queryserv.h b/zone/queryserv.h index 8aafcafda..5cb12332e 100644 --- a/zone/queryserv.h +++ b/zone/queryserv.h @@ -21,7 +21,7 @@ enum PlayerGenericLogEventTypes { Player_Log_Issued_Commands, Player_Log_Money_Transactions, Player_Log_Alternate_Currency_Transactions, -}; +}; class QueryServ{ @@ -32,4 +32,4 @@ class QueryServ{ void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc); }; -#endif /* QUERYSERV_ZONE_H */ \ No newline at end of file +#endif /* QUERYSERV_ZONE_H */ diff --git a/zone/quest_interface.h b/zone/quest_interface.h index 1e7825b2c..cc0b45d2e 100644 --- a/zone/quest_interface.h +++ b/zone/quest_interface.h @@ -20,8 +20,8 @@ #define _EQE_QUESTINTERFACE_H #include "../common/types.h" -#include "../common/any.h" #include "event_codes.h" +#include class Client; class NPC; @@ -34,20 +34,41 @@ namespace EQ class QuestInterface { public: virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } + std::vector *extra_pointers) { return 0; } virtual int EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } + std::vector *extra_pointers) { return 0; } virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } + std::vector *extra_pointers) { return 0; } virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } + std::vector *extra_pointers) { return 0; } virtual int EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } - virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } + std::vector *extra_pointers) { return 0; } + virtual int EventSpell(QuestEventID evt, Mob* mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers) { return 0; } virtual int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } - + std::vector *extra_pointers) { return 0; } + virtual int EventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointer + ) { + return 0; + } + + virtual int EventGlobalBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ) { + return 0; + } + virtual bool HasQuestSub(uint32 npcid, QuestEventID evt) { return false; } virtual bool HasGlobalQuestSub(QuestEventID evt) { return false; } virtual bool PlayerHasQuestSub(QuestEventID evt) { return false; } @@ -55,6 +76,9 @@ public: virtual bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { return false; } virtual bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt) { return false; } virtual bool EncounterHasQuestSub(std::string encounter_name, QuestEventID evt) { return false; } + virtual bool HasEncounterSub(const std::string& package_name, QuestEventID evt) { return false; } + virtual bool BotHasQuestSub(QuestEventID evt) { return false; } + virtual bool GlobalBotHasQuestSub(QuestEventID evt) { return false; } virtual void LoadNPCScript(std::string filename, int npc_id) { } virtual void LoadGlobalNPCScript(std::string filename) { } @@ -63,23 +87,35 @@ public: virtual void LoadItemScript(std::string filename, EQ::ItemInstance *item) { } virtual void LoadSpellScript(std::string filename, uint32 spell_id) { } virtual void LoadEncounterScript(std::string filename, std::string encounter_name) { } + virtual void LoadBotScript(std::string filename) { } + virtual void LoadGlobalBotScript(std::string filename) { } virtual int DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } + std::vector *extra_pointers) { return 0; } virtual int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } + std::vector *extra_pointers) { return 0; } virtual int DispatchEventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } - virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers) { return 0; } - + std::vector *extra_pointers) { return 0; } + virtual int DispatchEventSpell(QuestEventID evt, Mob* mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers) { return 0; } + virtual int DispatchEventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ) { + return 0; + } + virtual void AddVar(std::string name, std::string val) { } virtual std::string GetVar(std::string name) { return std::string(); } virtual void Init() { } virtual void ReloadQuests() { } virtual uint32 GetIdentifier() = 0; virtual void RemoveEncounter(const std::string &name) { } - + //TODO: Set maximum quest errors instead of hard coding it virtual void GetErrors(std::list &quest_errors) { quest_errors.insert(quest_errors.end(), errors_.begin(), errors_.end()); @@ -87,13 +123,14 @@ public: virtual void AddError(std::string error) { LogQuests("{}", error); + LogQuestErrors("{}", Strings::Trim(error)); errors_.push_back(error); if(errors_.size() > 30) { errors_.pop_front(); } } - + protected: std::list errors_; }; diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index d3cdee560..7cedb1e96 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -25,7 +25,8 @@ #include "quest_interface.h" #include "zone.h" #include "questmgr.h" -#include "zone_config.h" +#include "../common/path_manager.h" +#include "../common/repositories/perl_event_export_settings_repository.h" #include @@ -36,6 +37,8 @@ QuestParserCollection::QuestParserCollection() { _player_quest_status = QuestUnloaded; _global_player_quest_status = QuestUnloaded; _global_npc_quest_status = QuestUnloaded; + _bot_quest_status = QuestUnloaded; + _global_bot_quest_status = QuestUnloaded; } QuestParserCollection::~QuestParserCollection() { @@ -70,7 +73,7 @@ void QuestParserCollection::Init() { } void QuestParserCollection::ReloadQuests(bool reset_timers) { - if(reset_timers) { + if (reset_timers) { quest_manager.ClearAllTimers(); } @@ -79,11 +82,14 @@ void QuestParserCollection::ReloadQuests(bool reset_timers) { _player_quest_status = QuestUnloaded; _global_player_quest_status = QuestUnloaded; _global_npc_quest_status = QuestUnloaded; + _bot_quest_status = QuestUnloaded; + _global_bot_quest_status = QuestUnloaded; + _spell_quest_status.clear(); _item_quest_status.clear(); _encounter_quest_status.clear(); auto iter = _load_precedence.begin(); - while(iter != _load_precedence.end()) { + while (iter != _load_precedence.end()) { (*iter)->ReloadQuests(); ++iter; } @@ -97,8 +103,13 @@ void QuestParserCollection::RemoveEncounter(const std::string name) { } } -bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt) { - return HasQuestSubLocal(npcid, evt) || HasQuestSubGlobal(evt); +bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt, bool check_encounters) { + return HasQuestSubLocal(npcid, evt) || HasQuestSubGlobal(evt) || (check_encounters && NPCHasEncounterSub(npcid, evt)); +} + +bool QuestParserCollection::NPCHasEncounterSub(uint32 npc_id, QuestEventID evt) { + std::string package_name = "npc_" + std::to_string(npc_id); + return HasEncounterSub(evt, package_name); } bool QuestParserCollection::HasQuestSubLocal(uint32 npcid, QuestEventID evt) { @@ -151,13 +162,17 @@ bool QuestParserCollection::HasQuestSubGlobal(QuestEventID evt) { return false; } -bool QuestParserCollection::PlayerHasQuestSub(QuestEventID evt) { - return PlayerHasQuestSubLocal(evt) || PlayerHasQuestSubGlobal(evt); +bool QuestParserCollection::PlayerHasQuestSub(QuestEventID evt, bool check_encounters) { + return PlayerHasQuestSubLocal(evt) || PlayerHasQuestSubGlobal(evt) || (check_encounters && PlayerHasEncounterSub(evt)); +} + +bool QuestParserCollection::PlayerHasEncounterSub(QuestEventID evt) { + return HasEncounterSub(evt, "player"); } bool QuestParserCollection::PlayerHasQuestSubLocal(QuestEventID evt) { if(_player_quest_status == QuestUnloaded) { - std::string filename; + std::string filename; QuestInterface *qi = GetQIByPlayerQuest(filename); if(qi) { _player_quest_status = qi->GetIdentifier(); @@ -173,7 +188,7 @@ bool QuestParserCollection::PlayerHasQuestSubLocal(QuestEventID evt) { bool QuestParserCollection::PlayerHasQuestSubGlobal(QuestEventID evt) { if(_global_player_quest_status == QuestUnloaded) { - std::string filename; + std::string filename; QuestInterface *qi = GetQIByGlobalPlayerQuest(filename); if(qi) { _global_player_quest_status = qi->GetIdentifier(); @@ -187,7 +202,16 @@ bool QuestParserCollection::PlayerHasQuestSubGlobal(QuestEventID evt) { return false; } -bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { +bool QuestParserCollection::SpellHasEncounterSub(uint32 spell_id, QuestEventID evt) { + std::string package_name = "spell_" + std::to_string(spell_id); + return HasEncounterSub(evt, package_name); +} + +bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt, bool check_encounters) { + if (check_encounters && SpellHasEncounterSub(spell_id, evt)) { + return true; + } + auto iter = _spell_quest_status.find(spell_id); if(iter != _spell_quest_status.end()) { //loaded or failed to load @@ -209,10 +233,22 @@ bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) return false; } -bool QuestParserCollection::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt) { +bool QuestParserCollection::ItemHasEncounterSub(EQ::ItemInstance* item, QuestEventID evt) { + if (item) { + std::string package_name = "item_" + std::to_string(item->GetID()); + return HasEncounterSub(evt, package_name); + } + return false; +} + +bool QuestParserCollection::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt, bool check_encounters) { if (itm == nullptr) return false; + if (check_encounters && ItemHasEncounterSub(itm, evt)) { + return true; + } + std::string item_script; if(itm->GetItem()->ScriptFileID != 0) { item_script = "script_"; @@ -245,12 +281,24 @@ bool QuestParserCollection::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID return false; } +bool QuestParserCollection::HasEncounterSub(QuestEventID evt, const std::string& package_name) { + for (auto it = _encounter_quest_status.begin(); it != _encounter_quest_status.end(); ++it) { + if (it->second != QuestFailedToLoad) { + auto qit = _interfaces.find(it->second); + if (qit != _interfaces.end() && qit->second->HasEncounterSub(package_name, evt)) { + return true; + } + } + } + return false; +} + int QuestParserCollection::EventNPC(QuestEventID evt, NPC *npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { int rd = DispatchEventNPC(evt, npc, init, data, extra_data, extra_pointers); int rl = EventNPCLocal(evt, npc, init, data, extra_data, extra_pointers); int rg = EventNPCGlobal(evt, npc, init, data, extra_data, extra_pointers); - + //Local quests returning non-default values have priority over global quests if(rl != 0) { return rl; @@ -259,12 +307,12 @@ int QuestParserCollection::EventNPC(QuestEventID evt, NPC *npc, Mob *init, std:: } else if(rd != 0) { return rd; } - + return 0; } int QuestParserCollection::EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { auto iter = _npc_quest_status.find(npc->GetNPCTypeID()); if(iter != _npc_quest_status.end()) { //loaded or failed to load @@ -287,11 +335,11 @@ int QuestParserCollection::EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, } int QuestParserCollection::EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { if(_global_npc_quest_status != QuestUnloaded && _global_npc_quest_status != QuestFailedToLoad) { auto qiter = _interfaces.find(_global_npc_quest_status); return qiter->second->EventGlobalNPC(evt, npc, init, data, extra_data, extra_pointers); - } + } else if(_global_npc_quest_status != QuestFailedToLoad){ std::string filename; QuestInterface *qi = GetQIByGlobalNPCQuest(filename); @@ -307,11 +355,11 @@ int QuestParserCollection::EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, } int QuestParserCollection::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { int rd = DispatchEventPlayer(evt, client, data, extra_data, extra_pointers); int rl = EventPlayerLocal(evt, client, data, extra_data, extra_pointers); int rg = EventPlayerGlobal(evt, client, data, extra_data, extra_pointers); - + //Local quests returning non-default values have priority over global quests if(rl != 0) { return rl; @@ -320,12 +368,12 @@ int QuestParserCollection::EventPlayer(QuestEventID evt, Client *client, std::st } else if(rd != 0) { return rd; } - + return 0; } int QuestParserCollection::EventPlayerLocal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { if(_player_quest_status == QuestUnloaded) { std::string filename; QuestInterface *qi = GetQIByPlayerQuest(filename); @@ -334,7 +382,7 @@ int QuestParserCollection::EventPlayerLocal(QuestEventID evt, Client *client, st qi->LoadPlayerScript(filename); return qi->EventPlayer(evt, client, data, extra_data, extra_pointers); } - } else { + } else { if(_player_quest_status != QuestFailedToLoad) { auto iter = _interfaces.find(_player_quest_status); return iter->second->EventPlayer(evt, client, data, extra_data, extra_pointers); @@ -344,7 +392,7 @@ int QuestParserCollection::EventPlayerLocal(QuestEventID evt, Client *client, st } int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { if(_global_player_quest_status == QuestUnloaded) { std::string filename; QuestInterface *qi = GetQIByGlobalPlayerQuest(filename); @@ -353,7 +401,7 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s qi->LoadGlobalPlayerScript(filename); return qi->EventGlobalPlayer(evt, client, data, extra_data, extra_pointers); } - } else { + } else { if(_global_player_quest_status != QuestFailedToLoad) { auto iter = _interfaces.find(_global_player_quest_status); return iter->second->EventGlobalPlayer(evt, client, data, extra_data, extra_pointers); @@ -363,9 +411,9 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s } int QuestParserCollection::EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { // needs pointer validation check on 'item' argument - + std::string item_script; if(item->GetItem()->ScriptFileID != 0) { item_script = "script_"; @@ -410,45 +458,53 @@ int QuestParserCollection::EventItem(QuestEventID evt, Client *client, EQ::ItemI return 0; } -int QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers) { +int QuestParserCollection::EventSpell( + QuestEventID evt, + Mob* mob, + Client *client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { auto iter = _spell_quest_status.find(spell_id); - if(iter != _spell_quest_status.end()) { + if (iter != _spell_quest_status.end()) { //loaded or failed to load - if(iter->second != QuestFailedToLoad) { - auto qiter = _interfaces.find(iter->second); - int ret = DispatchEventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); - int i = qiter->second->EventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); - if(i != 0) { - ret = i; - } + if (iter->second != QuestFailedToLoad) { + auto qi = _interfaces.find(iter->second); + int ret = DispatchEventSpell(evt, mob, client, spell_id, data, extra_data, extra_pointers); + int i = qi->second->EventSpell(evt, mob, client, spell_id, data, extra_data, extra_pointers); + if (i != 0) { + ret = i; + } + return ret; } - return DispatchEventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); - } - else if (_spell_quest_status[spell_id] != QuestFailedToLoad) { + + return DispatchEventSpell(evt, mob, client, spell_id, data, extra_data, extra_pointers); + } else if (_spell_quest_status[spell_id] != QuestFailedToLoad) { std::string filename; QuestInterface *qi = GetQIBySpellQuest(spell_id, filename); if (qi) { _spell_quest_status[spell_id] = qi->GetIdentifier(); qi->LoadSpellScript(filename, spell_id); - int ret = DispatchEventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); - int i = qi->EventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); + int ret = DispatchEventSpell(evt, mob, client, spell_id, data, extra_data, extra_pointers); + int i = qi->EventSpell(evt, mob, client, spell_id, data, extra_data, extra_pointers); if (i != 0) { ret = i; } + return ret; - } - else { + } else { _spell_quest_status[spell_id] = QuestFailedToLoad; - return DispatchEventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); + return DispatchEventSpell(evt, mob, client, spell_id, data, extra_data, extra_pointers); } } return 0; } int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { auto iter = _encounter_quest_status.find(encounter_name); if(iter != _encounter_quest_status.end()) { //loaded or failed to load @@ -471,11 +527,9 @@ int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounte } QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string &filename) { - //first look for /quests/zone/npcid.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += itoa(npcid); + // first look for /quests/zone/npcid.ext (precedence) + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), zone->GetShortName(), npcid); + std::string tmp; FILE *f = nullptr; @@ -507,7 +561,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } else{ npc_name = npc_type->name; - } + } int sz = static_cast(npc_name.length()); for(int i = 0; i < sz; ++i) { if(npc_name[i] == '`') { @@ -515,10 +569,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } } - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += npc_name; + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), zone->GetShortName(), npc_name); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -536,11 +587,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //third look for /quests/global/npcid.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += itoa(npcid); + // third look for /quests/global/npcid.ext (precedence) + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, npcid); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -557,11 +605,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //fourth look for /quests/global/npcname.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += npc_name; + // fourth look for /quests/global/npcname.ext (precedence) + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, npc_name); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -578,11 +623,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //fifth look for /quests/zone/default.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += "default"; + // fifth look for /quests/zone/default.ext (precedence) + filename = fmt::format("{}/{}/default", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -599,11 +641,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //last look for /quests/global/default.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "default"; + // last look for /quests/global/default.ext (precedence) + filename = fmt::format("{}/{}/default", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -627,12 +666,8 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) if(!zone || !zone->IsLoaded()) return nullptr; - //first look for /quests/zone/player_v[instance_version].ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += "player_v"; - filename += itoa(zone->GetInstanceVersion()); + // first look for /quests/zone/player_v[instance_version].ext (precedence) + filename = fmt::format("{}/{}/player_v{}", path.GetQuestsPath(), zone->GetShortName(), zone->GetInstanceVersion()); std::string tmp; FILE *f = nullptr; @@ -652,11 +687,8 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) ++iter; } - //second look for /quests/zone/player.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += "player"; + // second look for /quests/zone/player.ext (precedence) + filename = fmt::format("{}/{}/player", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -674,11 +706,8 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) ++iter; } - //third look for /quests/global/player.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "player"; + // third look for /quests/global/player.ext (precedence) + filename = fmt::format("{}/{}/player", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -700,15 +729,11 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(std::string &filename) { // simply look for /quests/global/global_npc.ext - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "global_npc"; + filename = fmt::format("{}/{}/global_npc", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); + std::string tmp; FILE *f = nullptr; - - auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -730,11 +755,8 @@ QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(std::string &filena } QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest(std::string &filename) { - //first look for /quests/global/player.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "global_player"; + // first look for /quests/global/player.ext (precedence) + filename = fmt::format("{}/{}/global_player", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); std::string tmp; FILE *f = nullptr; @@ -759,10 +781,7 @@ QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest(std::string &fil QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::string &filename) { //first look for /quests/zone/spells/spell_id.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/spells/"; - filename += itoa(spell_id); + filename = fmt::format("{}/{}/spells/{}", path.GetQuestsPath(), zone->GetShortName(), spell_id); std::string tmp; FILE *f = nullptr; @@ -782,11 +801,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s ++iter; } - //second look for /quests/global/spells/spell_id.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/spells/"; - filename += itoa(spell_id); + // second look for /quests/global/spells/spell_id.ext (precedence) + filename = fmt::format("{}/{}/spells/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, spell_id); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -804,10 +820,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s ++iter; } - //third look for /quests/zone/spells/default.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/spells/default"; + // third look for /quests/zone/spells/default.ext (precedence) + filename = fmt::format("{}/{}/spells/default", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -825,10 +839,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s ++iter; } - //last look for /quests/global/spells/default.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/spells/default"; + // last look for /quests/global/spells/default.ext (precedence) + filename = fmt::format("{}/{}/spells/default", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -850,11 +862,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s } QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, std::string &filename) { - //first look for /quests/zone/items/item_script.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/items/"; - filename += item_script; + // first look for /quests/zone/items/item_script.ext (precedence) + filename = fmt::format("{}/{}/items/{}", path.GetQuestsPath(), zone->GetShortName(), item_script); std::string tmp; FILE *f = nullptr; @@ -873,12 +882,9 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, ++iter; } - - //second look for /quests/global/items/item_script.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/items/"; - filename += item_script; + + // second look for /quests/global/items/item_script.ext (precedence) + filename = fmt::format("{}/{}/items/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, item_script); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -896,11 +902,8 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, ++iter; } - //third look for /quests/zone/items/default.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/items/default"; - + // third look for /quests/zone/items/default.ext (precedence) + filename = fmt::format("{}/{}/items/default", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -917,11 +920,8 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, ++iter; } - //last look for /quests/global/items/default.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/items/default"; - + // last look for /quests/global/items/default.ext (precedence) + filename = fmt::format("{}/{}/items/default", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -942,11 +942,8 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, } QuestInterface *QuestParserCollection::GetQIByEncounterQuest(std::string encounter_name, std::string &filename) { - //first look for /quests/zone/encounters/encounter_name.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/encounters/"; - filename += encounter_name; + // first look for /quests/zone/encounters/encounter_name.ext (precedence) + filename = fmt::format("{}/{}/encounters/{}", path.GetQuestsPath(), zone->GetShortName(), encounter_name); std::string tmp; FILE *f = nullptr; @@ -965,12 +962,9 @@ QuestInterface *QuestParserCollection::GetQIByEncounterQuest(std::string encount ++iter; } - - //second look for /quests/global/encounters/encounter_name.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/encounters/"; - filename += encounter_name; + + // second look for /quests/global/encounters/encounter_name.ext (precedence) + filename = fmt::format("{}/{}/encounters/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, encounter_name); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -1001,7 +995,7 @@ void QuestParserCollection::GetErrors(std::list &quest_errors) { } int QuestParserCollection::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { int ret = 0; auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -1015,7 +1009,7 @@ int QuestParserCollection::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *ini } int QuestParserCollection::DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { int ret = 0; auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -1029,7 +1023,7 @@ int QuestParserCollection::DispatchEventPlayer(QuestEventID evt, Client *client, } int QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, - uint32 extra_data, std::vector *extra_pointers) { + uint32 extra_data, std::vector *extra_pointers) { int ret = 0; auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -1042,55 +1036,272 @@ int QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, E return ret; } -int QuestParserCollection::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers) { - int ret = 0; +int QuestParserCollection::DispatchEventSpell( + QuestEventID evt, + Mob* mob, + Client *client, + uint32 spell_id, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + int ret = 0; auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { - int i = (*iter)->DispatchEventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); - if(i != 0) { - ret = i; - } + int i = (*iter)->DispatchEventSpell(evt, mob, client, spell_id, data, extra_data, extra_pointers); + if(i != 0) { + ret = i; + } ++iter; } - return ret; + return ret; } -void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings) { - - LogInfo("Loading Perl Event Export Settings..."); - - /* Write Defaults First (All Enabled) */ - for (int i = 0; i < _LargestEventID; i++){ - perl_event_export_settings[i].qglobals = 1; - perl_event_export_settings[i].mob = 1; - perl_event_export_settings[i].zone = 1; - perl_event_export_settings[i].item = 1; - perl_event_export_settings[i].event_variables = 1; +void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings *s) +{ + for (int i = 0; i < _LargestEventID; i++) { + s[i].qglobals = 1; + s[i].mob = 1; + s[i].zone = 1; + s[i].item = 1; + s[i].event_variables = 1; } - std::string query = - "SELECT " - "event_id, " - "event_description, " - "export_qglobals, " - "export_mob, " - "export_zone, " - "export_item, " - "export_event " - "FROM " - "perl_event_export_settings " - "ORDER BY event_id"; - - int event_id = 0; - auto results = database.QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { - event_id = atoi(row[0]); - perl_event_export_settings[event_id].qglobals = atoi(row[2]); - perl_event_export_settings[event_id].mob = atoi(row[3]); - perl_event_export_settings[event_id].zone = atoi(row[4]); - perl_event_export_settings[event_id].item = atoi(row[5]); - perl_event_export_settings[event_id].event_variables = atoi(row[6]); + auto settings = PerlEventExportSettingsRepository::All(database); + for (auto &e: settings) { + s[e.event_id].qglobals = e.export_qglobals; + s[e.event_id].mob = e.export_mob; + s[e.event_id].zone = e.export_zone; + s[e.event_id].item = e.export_item; + s[e.event_id].event_variables = e.export_event; } + LogInfo("Loaded [{}] Perl Event Export Settings", settings.size()); +} + +int QuestParserCollection::DispatchEventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + int ret = 0; + auto iter = _load_precedence.begin(); + while (iter != _load_precedence.end()) { + int i = (*iter)->DispatchEventBot(evt, bot, init, data, extra_data, extra_pointers); + if (i != 0) { + ret = i; + } + + ++iter; + } + + return ret; +} + +int QuestParserCollection::EventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + auto rd = DispatchEventBot(evt, bot, init, data, extra_data, extra_pointers); + auto rl = EventBotLocal(evt, bot, init, data, extra_data, extra_pointers); + auto rg = EventBotGlobal(evt, bot, init, data, extra_data, extra_pointers); + + //Local quests returning non-default values have priority over global quests + if (rl != 0) { + return rl; + } else if (rg != 0) { + return rg; + } else if (rd != 0) { + return rd; + } + + return 0; +} + +int QuestParserCollection::EventBotLocal( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + if (_bot_quest_status == QuestUnloaded) { + std::string filename; + QuestInterface *qi = GetQIByBotQuest(filename); + if (qi) { + _bot_quest_status = qi->GetIdentifier(); + qi->LoadBotScript(filename); + return qi->EventBot(evt, bot, init, data, extra_data, extra_pointers); + } + } else { + if (_bot_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_bot_quest_status); + return iter->second->EventBot(evt, bot, init, data, extra_data, extra_pointers); + } + } + + return 0; +} + +int QuestParserCollection::EventBotGlobal( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + if (_global_bot_quest_status == QuestUnloaded) { + std::string filename; + QuestInterface *qi = GetQIByGlobalBotQuest(filename); + if (qi) { + _global_bot_quest_status = qi->GetIdentifier(); + qi->LoadGlobalBotScript(filename); + return qi->EventGlobalBot(evt, bot, init, data, extra_data, extra_pointers); + } + } else { + if (_global_bot_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_global_bot_quest_status); + return iter->second->EventGlobalBot(evt, bot, init, data, extra_data, extra_pointers); + } + } + + return 0; +} + +bool QuestParserCollection::BotHasQuestSubLocal(QuestEventID evt) { + if (_bot_quest_status == QuestUnloaded) { + std::string filename; + QuestInterface *qi = GetQIByBotQuest(filename); + if (qi) { + _bot_quest_status = qi->GetIdentifier(); + qi->LoadBotScript(filename); + return qi->BotHasQuestSub(evt); + } + } else if (_bot_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_bot_quest_status); + return iter->second->BotHasQuestSub(evt); + } + + return false; +} + +bool QuestParserCollection::BotHasQuestSubGlobal(QuestEventID evt) { + if (_global_bot_quest_status == QuestUnloaded) { + std::string filename; + QuestInterface *qi = GetQIByGlobalBotQuest(filename); + if (qi) { + _global_bot_quest_status = qi->GetIdentifier(); + qi->LoadGlobalBotScript(filename); + return qi->GlobalBotHasQuestSub(evt); + } + } else if (_global_bot_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_global_bot_quest_status); + return iter->second->GlobalBotHasQuestSub(evt); + } + + return false; +} + +bool QuestParserCollection::BotHasQuestSub(QuestEventID evt) { + return BotHasQuestSubLocal(evt) || BotHasQuestSubGlobal(evt); +} + +QuestInterface *QuestParserCollection::GetQIByBotQuest(std::string &filename) { + if (!zone || !zone->IsLoaded()) { + return nullptr; + } + + // first look for /quests/zone/bot_v[instance_version].ext (precedence) + filename = fmt::format("{}/{}/bot_v{}", path.GetQuestsPath(), zone->GetShortName(), zone->GetInstanceVersion()); + std::string tmp; + FILE *f = nullptr; + + auto iter = _load_precedence.begin(); + while (iter != _load_precedence.end()) { + auto ext = _extensions.find((*iter)->GetIdentifier()); + + tmp = fmt::format("{}.{}", filename, ext->second); + + f = fopen(tmp.c_str(), "r"); + if (f) { + fclose(f); + filename = tmp; + return (*iter); + } + + ++iter; + } + + // second look for /quests/zone/bot.ext (precedence) + filename = fmt::format("{}/{}/bot", path.GetQuestsPath(), zone->GetShortName()); + + iter = _load_precedence.begin(); + while(iter != _load_precedence.end()) { + auto ext = _extensions.find((*iter)->GetIdentifier()); + + tmp = fmt::format("{}.{}", filename, ext->second); + + f = fopen(tmp.c_str(), "r"); + if (f) { + fclose(f); + filename = tmp; + return (*iter); + } + + ++iter; + } + + // third look for /quests/global/bot.ext (precedence) + filename = fmt::format("{}/{}/bot", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); + iter = _load_precedence.begin(); + while (iter != _load_precedence.end()) { + auto ext = _extensions.find((*iter)->GetIdentifier()); + + tmp = fmt::format("{}.{}", filename, ext->second); + + f = fopen(tmp.c_str(), "r"); + if (f) { + fclose(f); + filename = tmp; + return (*iter); + } + + ++iter; + } + + return nullptr; +} + +QuestInterface *QuestParserCollection::GetQIByGlobalBotQuest(std::string &filename) { + // first look for /quests/global/global_bot.ext (precedence) + filename = fmt::format("{}/{}/global_bot", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); + std::string tmp; + FILE *f = nullptr; + + auto iter = _load_precedence.begin(); + while (iter != _load_precedence.end()) { + auto ext = _extensions.find((*iter)->GetIdentifier()); + + tmp = fmt::format("{}.{}", filename, ext->second); + + f = fopen(tmp.c_str(), "r"); + if (f) { + fclose(f); + filename = tmp; + return (*iter); + } + + ++iter; + } + + return nullptr; } diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index eb5796236..bc2b1d51e 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -67,22 +67,32 @@ public: void ReloadQuests(bool reset_timers = true); void RemoveEncounter(const std::string name); - bool HasQuestSub(uint32 npcid, QuestEventID evt); - bool PlayerHasQuestSub(QuestEventID evt); - bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt); - bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt); + bool HasQuestSub(uint32 npcid, QuestEventID evt, bool check_encounters = false); + bool PlayerHasQuestSub(QuestEventID evt, bool check_encounters = false); + bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt, bool check_encounters = false); + bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt, bool check_encounters = false); + bool BotHasQuestSub(QuestEventID evt); int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers = nullptr); + std::vector *extra_pointers = nullptr); int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers = nullptr); + std::vector *extra_pointers = nullptr); int EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers = nullptr); - int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers = nullptr); + std::vector *extra_pointers = nullptr); + int EventSpell(QuestEventID evt, Mob* mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers = nullptr); int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, - std::vector *extra_pointers = nullptr); - + std::vector *extra_pointers = nullptr); + + int EventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers = nullptr + ); + void GetErrors(std::list &quest_errors); /* @@ -104,18 +114,41 @@ public: PerlEventExportSettings perl_event_export_settings[_LargestEventID]; - void LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings); + void LoadPerlEventExportSettings(PerlEventExportSettings* s); private: bool HasQuestSubLocal(uint32 npcid, QuestEventID evt); bool HasQuestSubGlobal(QuestEventID evt); + bool NPCHasEncounterSub(uint32 npc_id, QuestEventID evt); bool PlayerHasQuestSubLocal(QuestEventID evt); bool PlayerHasQuestSubGlobal(QuestEventID evt); + bool PlayerHasEncounterSub(QuestEventID evt); + bool SpellHasEncounterSub(uint32 spell_id, QuestEventID evt); + bool ItemHasEncounterSub(EQ::ItemInstance* item, QuestEventID evt); + bool HasEncounterSub(QuestEventID evt, const std::string& package_name); + bool BotHasQuestSubLocal(QuestEventID evt); + bool BotHasQuestSubGlobal(QuestEventID evt); - int EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers); - int EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers); - int EventPlayerLocal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); - int EventPlayerGlobal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); + int EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers); + int EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers); + int EventPlayerLocal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); + int EventPlayerGlobal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); + int EventBotLocal( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); + int EventBotGlobal( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); QuestInterface *GetQIByNPCQuest(uint32 npcid, std::string &filename); QuestInterface *GetQIByGlobalNPCQuest(std::string &filename); @@ -124,15 +157,25 @@ private: QuestInterface *GetQIBySpellQuest(uint32 spell_id, std::string &filename); QuestInterface *GetQIByItemQuest(std::string item_script, std::string &filename); QuestInterface *GetQIByEncounterQuest(std::string encounter_name, std::string &filename); - + QuestInterface *GetQIByBotQuest(std::string &filename); + QuestInterface *GetQIByGlobalBotQuest(std::string &filename); + int DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers); + std::vector *extra_pointers); int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers); + std::vector *extra_pointers); int DispatchEventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, - std::vector *extra_pointers); - int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, std::string data, uint32 extra_data, - std::vector *extra_pointers); + std::vector *extra_pointers); + int DispatchEventSpell(QuestEventID evt, Mob* mob, Client *client, uint32 spell_id, std::string data, uint32 extra_data, + std::vector *extra_pointers); + int DispatchEventBot( + QuestEventID evt, + Bot *bot, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers + ); std::map _interfaces; std::map _extensions; @@ -144,6 +187,8 @@ private: uint32 _global_npc_quest_status; uint32 _player_quest_status; uint32 _global_player_quest_status; + uint32 _bot_quest_status; + uint32 _global_bot_quest_status; std::map _spell_quest_status; std::map _item_quest_status; std::map _encounter_quest_status; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index a083233ba..9e6b4859d 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -21,7 +21,7 @@ #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/say_link.h" #include "entity.h" @@ -35,16 +35,17 @@ #include "worldserver.h" #include "zone.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "dialogue_window.h" +#include "string_ids.h" + +#include "../common/repositories/tradeskill_recipe_repository.h" #include #include #include -#ifdef BOTS #include "bot.h" -#endif extern QueryServ* QServ; extern Zone* zone; @@ -91,10 +92,13 @@ void QuestManager::Process() { parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0); } else if (cur->mob->IsEncounter()) { parse->EventEncounter(EVENT_TIMER, cur->mob->CastToEncounter()->GetEncounterName(), cur->name, 0, nullptr); - } else { + } else if (cur->mob->IsClient()) { //this is inheriently unsafe if we ever make it so more than npc/client start timers parse->EventPlayer(EVENT_TIMER, cur->mob->CastToClient(), cur->name, 0); } + else if (cur->mob->IsBot()) { + parse->EventBot(EVENT_TIMER, cur->mob->CastToBot(), nullptr, cur->name, 0); + } //we MUST reset our iterator since the quest could have removed/added any //number of timers... worst case we have to check a bunch of timers twice @@ -189,24 +193,25 @@ void QuestManager::summonitem(uint32 itemid, int16 charges) { void QuestManager::write(const char *file, const char *str) { FILE * pFile; - pFile = fopen (file, "a"); + pFile = fopen (fmt::format("{}/{}", path.GetServerPath(), file).c_str(), "a"); if(!pFile) return; fprintf(pFile, "%s\n", str); fclose (pFile); } -Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& position) { - const NPCType* tmp = 0; - if (tmp = content_db.LoadNPCTypesData(npc_type)) - { - auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Water); +Mob* QuestManager::spawn2(int npc_id, int grid, int unused, const glm::vec4& position) { + const NPCType* t = 0; + if (t = content_db.LoadNPCTypesData(npc_id)) { + auto npc = new NPC(t, nullptr, position, GravityBehavior::Water); npc->AddLootTable(); - if (npc->DropsGlobalLoot()) + if (npc->DropsGlobalLoot()) { npc->CheckGlobalLootTables(); - entity_list.AddNPC(npc,true,true); - if(grid > 0) - { + } + + entity_list.AddNPC(npc, true, true); + + if (grid) { npc->AssignWaypoints(grid); } @@ -395,7 +400,7 @@ void QuestManager::addloot(int item_id, int charges, bool equipitem, int aug1, i void QuestManager::Zone(const char *zone_name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) { initiator->MoveZone(zone_name); } @@ -403,7 +408,7 @@ void QuestManager::Zone(const char *zone_name) { void QuestManager::ZoneGroup(const char *zone_name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { if (!initiator->GetGroup()) { initiator->MoveZone(zone_name); } else { @@ -420,7 +425,7 @@ void QuestManager::ZoneGroup(const char *zone_name) { void QuestManager::ZoneRaid(const char *zone_name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { if (!initiator->GetRaid()) { initiator->MoveZone(zone_name); } else { @@ -860,12 +865,10 @@ void QuestManager::depop_withtimer(int npc_type) { } void QuestManager::depopall(int npc_type) { - QuestManagerCurrentQuestVars(); - if(owner && owner->IsNPC() && (npc_type > 0)) { + if (npc_type) { entity_list.DepopAll(npc_type); - } - else { - LogQuests("QuestManager::depopall called with nullptr owner, non-NPC owner, or invalid NPC Type ID. Probably syntax error in quest file"); + } else { + LogQuests("QuestManager::depopall called with nullptr owner, non-NPC owner, or invalid NPC Type ID. Probably syntax error in quest file."); } } @@ -932,96 +935,82 @@ void QuestManager::changedeity(int deity_id) { //Changes the deity. if(initiator) { - if(initiator->IsClient()) - { - initiator->SetDeity(deity_id); - initiator->Message(Chat::Yellow,"Your Deity has been changed/set to: %i", deity_id); - initiator->Save(1); - initiator->Kick("Deity change by QuestManager"); - } - else - { - initiator->Message(Chat::Yellow,"Error changing Deity"); - } + initiator->SetDeity(deity_id); + initiator->Message(Chat::Yellow,"Your Deity has been changed/set to: %i", deity_id); + initiator->Save(1); + initiator->Kick("Deity change by QuestManager"); } } void QuestManager::exp(int amt) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->AddEXP(amt); } void QuestManager::level(int newlevel) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->SetLevel(newlevel, true); } -void QuestManager::traindisc(int discipline_tome_item_id) { +void QuestManager::traindisc(uint32 discipline_tome_item_id) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) { initiator->TrainDiscipline(discipline_tome_item_id); + } } -bool QuestManager::isdisctome(int item_id) { - const EQ::ItemData *item = database.GetItem(item_id); - if(item == nullptr) { - return(false); +bool QuestManager::isdisctome(uint32 item_id) { + const auto &item = database.GetItem(item_id); + if (!item) { + return false; } if (!item->IsClassCommon() || item->ItemType != EQ::item::ItemTypeSpell) { - return(false); + return false; } //Need a way to determine the difference between a spell and a tome //so they cant turn in a spell and get it as a discipline //this is kinda a hack: - if(!( - item->Name[0] == 'T' && - item->Name[1] == 'o' && - item->Name[2] == 'm' && - item->Name[3] == 'e' && - item->Name[4] == ' ' - ) && !( - item->Name[0] == 'S' && - item->Name[1] == 'k' && - item->Name[2] == 'i' && - item->Name[3] == 'l' && - item->Name[4] == 'l' && - item->Name[5] == ':' && - item->Name[6] == ' ' - )) { - return(false); + + const std::string item_name = item->Name; + + if ( + strcmp(item_name.substr(0, 5).c_str(), "Tome ") && + strcmp(item_name.substr(0, 7).c_str(), "Skill: ") + ) { + return false; } //we know for sure none of the int casters get disciplines - uint32 cbit = 0; - cbit |= 1 << (WIZARD-1); - cbit |= 1 << (ENCHANTER-1); - cbit |= 1 << (MAGICIAN-1); - cbit |= 1 << (NECROMANCER-1); - if(item->Classes & cbit) { - return(false); + uint32 class_bit = 0; + class_bit |= 1 << (WIZARD - 1); + class_bit |= 1 << (ENCHANTER - 1); + class_bit |= 1 << (MAGICIAN - 1); + class_bit |= 1 << (NECROMANCER - 1); + if (item->Classes & class_bit) { + return false; } - uint32 spell_id = item->Scroll.Effect; - if(!IsValidSpell(spell_id)) { - return(false); + const auto& spell_id = static_cast(item->Scroll.Effect); + if (!IsValidSpell(spell_id)) { + return false; } //we know for sure none of the int casters get disciplines - const SPDat_Spell_Struct &spell = spells[spell_id]; + const auto& spell = spells[spell_id]; if( spell.classes[WIZARD - 1] != 255 && spell.classes[ENCHANTER - 1] != 255 && spell.classes[MAGICIAN - 1] != 255 && spell.classes[NECROMANCER - 1] != 255 ) { - return(false); + return false; } - return(true); + return true; } std::string QuestManager::getracename(uint16 race_id) { @@ -1063,7 +1052,7 @@ std::string QuestManager::getconsiderlevelname(uint8 consider_level) { void QuestManager::safemove() { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->GoToSafeCoords(zone->GetZoneID(), zone->GetInstanceID()); } @@ -1088,7 +1077,7 @@ void QuestManager::snow(int weather) { void QuestManager::rename(std::string name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { std::string current_name = initiator->GetName(); if (initiator->ChangeFirstName(name.c_str(), current_name.c_str())) { initiator->Message( @@ -1111,20 +1100,18 @@ void QuestManager::rename(std::string name) { } } -void QuestManager::surname(const char *name) { +void QuestManager::surname(std::string last_name) { QuestManagerCurrentQuestVars(); //Changes the last name. - if(initiator) - { - if(initiator->IsClient()) - { - initiator->ChangeLastName(name); - initiator->Message(Chat::Yellow,"Your surname has been changed/set to: %s", name); - } - else - { - initiator->Message(Chat::Yellow,"Error changing/setting surname"); - } + if (initiator) { + initiator->ChangeLastName(last_name); + initiator->Message( + Chat::White, + fmt::format( + "Your last name has been set to \"{}\".", + last_name + ).c_str() + ); } } @@ -1172,52 +1159,24 @@ void QuestManager::untraindiscs() { initiator->UntrainDiscAll(); } -void QuestManager::givecash(int copper, int silver, int gold, int platinum) { +void QuestManager::givecash(uint32 copper, uint32 silver, uint32 gold, uint32 platinum) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient() && ((copper + silver + gold + platinum) > 0)) - { - initiator->AddMoneyToPP(copper, silver, gold, platinum, true); - - std::string tmp; - if (platinum > 0) - { - tmp = "You receive "; - tmp += itoa(platinum); - tmp += " platinum"; - } - if (gold > 0) - { - if (tmp.length() == 0) - tmp = "You receive "; - else - tmp += ","; - - tmp += itoa(gold); - tmp += " gold"; - } - if(silver > 0) - { - if (tmp.length() == 0) - tmp = "You receive "; - else - tmp += ","; - - tmp += itoa(silver); - tmp += " silver"; - } - if(copper > 0) - { - if (tmp.length() == 0) - tmp = "You receive "; - else - tmp += ","; - - tmp += itoa(copper); - tmp += " copper"; - } - tmp += " pieces."; - if (initiator) - initiator->Message(Chat::OOC, tmp.c_str()); + if ( + initiator && + initiator->IsClient() && + ( + copper || + silver || + gold || + platinum + ) + ) { + initiator->CashReward( + copper, + silver, + gold, + platinum + ); } } @@ -1235,19 +1194,19 @@ void QuestManager::pvp(const char *mode) { void QuestManager::movepc(int zone_id, float x, float y, float z, float heading) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->MovePC(zone_id, x, y, z, heading); } void QuestManager::gmmove(float x, float y, float z) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->GMMove(x, y, z); } void QuestManager::movegrp(int zoneid, float x, float y, float z) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) { Group *g = entity_list.GetGroupByClient(initiator); if (g != nullptr) { @@ -1271,22 +1230,22 @@ void QuestManager::movegrp(int zoneid, float x, float y, float z) { } } -void QuestManager::doanim(int anim_id) { +void QuestManager::doanim(int animation_id, int animation_speed, bool ackreq, eqFilterType filter) { QuestManagerCurrentQuestVars(); - owner->DoAnim(anim_id); + owner->DoAnim(animation_id, animation_speed, ackreq, filter); } void QuestManager::addskill(int skill_id, int value) { QuestManagerCurrentQuestVars(); if (skill_id < 0 || skill_id > EQ::skills::HIGHEST_SKILL) return; - if (initiator && initiator->IsClient()) + if (initiator) initiator->AddSkill((EQ::skills::SkillType) skill_id, value); } void QuestManager::setlanguage(int skill_id, int value) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->SetLanguageSkill(skill_id, value); } @@ -1294,7 +1253,7 @@ void QuestManager::setskill(int skill_id, int value) { QuestManagerCurrentQuestVars(); if (skill_id < 0 || skill_id > EQ::skills::HIGHEST_SKILL) return; - if (initiator && initiator->IsClient()) + if (initiator) initiator->SetSkill((EQ::skills::SkillType) skill_id, value); } @@ -1302,7 +1261,7 @@ void QuestManager::setallskill(int value) { QuestManagerCurrentQuestVars(); if (!initiator) return; - if (initiator && initiator->IsClient()) { + if (initiator) { EQ::skills::SkillType sk; for (sk = EQ::skills::Skill1HBlunt; sk <= EQ::skills::HIGHEST_SKILL; sk = (EQ::skills::SkillType)(sk + 1)) { initiator->SetSkill(sk, value); @@ -1356,14 +1315,14 @@ void QuestManager::attacknpctype(int npc_type_id) { void QuestManager::save() { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->Save(); } void QuestManager::faction(int faction_id, int faction_value, int temp) { QuestManagerCurrentQuestVars(); running_quest run = quests_running_.top(); - if(run.owner->IsCharmed() == false && initiator && initiator->IsClient()) { + if(run.owner->IsCharmed() == false && initiator) { if(faction_id != 0 && faction_value != 0) { initiator->SetFactionLevel2( initiator->CharacterID(), @@ -1377,6 +1336,15 @@ void QuestManager::faction(int faction_id, int faction_value, int temp) { } } +void QuestManager::rewardfaction(int faction_id, int faction_value) { + QuestManagerCurrentQuestVars(); + if (initiator) { + if (faction_id != 0 && faction_value != 0) { + initiator->RewardFaction(faction_id, faction_value); + } + } +} + void QuestManager::setsky(uint8 new_sky) { QuestManagerCurrentQuestVars(); if (zone) @@ -1389,7 +1357,7 @@ void QuestManager::setsky(uint8 new_sky) { void QuestManager::setguild(uint32 new_guild_id, uint8 new_rank) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { guild_mgr.SetGuild(initiator->CharacterID(), new_guild_id, new_rank); } } @@ -1513,7 +1481,7 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti 7 all all all */ - if (initiator && initiator->IsClient()){ // some events like waypoint and spawn don't have a player involved + if (initiator){ // some events like waypoint and spawn don't have a player involved qgCharid=initiator->CharacterID(); } else { @@ -1534,7 +1502,7 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration)); /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){ + if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ std::string event_desc = StringFormat("Update :: qglobal:%s to qvalue:%s zoneid:%i instid:%i", varname, newvalue, initiator->GetZoneID(), initiator->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); } @@ -1619,13 +1587,13 @@ void QuestManager::delglobal(const char *varname) { int qgCharid = 0; int qgNpcid = owner ? owner->GetNPCTypeID() : 0; // encounter scripts don't have an owner - if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved + if (initiator) // some events like waypoint and spawn don't have a player involved qgCharid=initiator->CharacterID(); else qgCharid=-qgNpcid; // make char id negative npc id as a fudge /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){ + if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ std::string event_desc = StringFormat("Deleted :: qglobal:%s zoneid:%i instid:%i", varname, initiator->GetZoneID(), initiator->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); } @@ -1719,21 +1687,21 @@ int QuestManager::QGVarDuration(const char *fmt) void QuestManager::ding() { QuestManagerCurrentQuestVars(); //makes a sound. - if (initiator && initiator->IsClient()) + if (initiator) initiator->SendSound(); } void QuestManager::rebind(int zone_id, const glm::vec3& location) { QuestManagerCurrentQuestVars(); - if(initiator && initiator->IsClient()) { + if(initiator) { initiator->SetBindPoint(0, zone_id, 0, location); } } void QuestManager::rebind(int zone_id, const glm::vec4& location) { QuestManagerCurrentQuestVars(); - if(initiator && initiator->IsClient()) { + if(initiator) { initiator->SetBindPoint2(0, zone_id, 0, location); } } @@ -1847,23 +1815,46 @@ void QuestManager::respawn(int npcTypeID, int grid) { } } -void QuestManager::set_proximity(float minx, float maxx, float miny, float maxy, float minz, float maxz, bool bSay) +void QuestManager::set_proximity_range(float x_range, float y_range, float z_range, bool enable_say) { QuestManagerCurrentQuestVars(); if (!owner || !owner->IsNPC()) { return; } - entity_list.AddProximity(owner->CastToNPC()); + auto n = owner->CastToNPC(); - owner->CastToNPC()->proximity->min_x = minx; - owner->CastToNPC()->proximity->max_x = maxx; - owner->CastToNPC()->proximity->min_y = miny; - owner->CastToNPC()->proximity->max_y = maxy; - owner->CastToNPC()->proximity->min_z = minz; - owner->CastToNPC()->proximity->max_z = maxz; - owner->CastToNPC()->proximity->say = bSay; - owner->CastToNPC()->proximity->proximity_set = true; + entity_list.AddProximity(n); + + n->proximity->min_x = n->GetX() - x_range; + n->proximity->max_x = n->GetX() + x_range; + n->proximity->min_y = n->GetY() - y_range; + n->proximity->max_y = n->GetY() + y_range; + n->proximity->min_z = n->GetZ() - z_range; + n->proximity->max_z = n->GetZ() + z_range; + n->proximity->say = enable_say; + n->proximity->proximity_set = true; +} + +void QuestManager::set_proximity(float min_x, float max_x, float min_y, float max_y, float min_z, float max_z, bool enable_say) +{ + QuestManagerCurrentQuestVars(); + if (!owner || !owner->IsNPC()) { + return; + } + + auto n = owner->CastToNPC(); + + entity_list.AddProximity(n); + + n->proximity->min_x = min_x; + n->proximity->max_x = max_x; + n->proximity->min_y = min_y; + n->proximity->max_y = max_y; + n->proximity->min_z = min_z; + n->proximity->max_z = max_z; + n->proximity->say = enable_say; + n->proximity->proximity_set = true; } void QuestManager::clear_proximity() { @@ -2242,13 +2233,21 @@ void QuestManager::popup(const char *title, const char *text, uint32 popupid, ui initiator->SendPopupToClient(title, text, popupid, buttons, Duration); } -#ifdef BOTS +int QuestManager::createbotcount(uint8 class_id) { + QuestManagerCurrentQuestVars(); + if (initiator) { + return initiator->GetBotCreationLimit(class_id); + } -int QuestManager::createbotcount() { return RuleI(Bots, CreationLimit); } -int QuestManager::spawnbotcount() { +int QuestManager::spawnbotcount(uint8 class_id) { + QuestManagerCurrentQuestVars(); + if (initiator) { + return initiator->GetBotSpawnLimit(class_id); + } + return RuleI(Bots, SpawnLimit); } @@ -2260,49 +2259,178 @@ bool QuestManager::botquest() bool QuestManager::createBot(const char *name, const char *lastname, uint8 level, uint16 race, uint8 botclass, uint8 gender) { QuestManagerCurrentQuestVars(); - uint32 MaxBotCreate = RuleI(Bots, CreationLimit); - if (initiator && initiator->IsClient()) - { - if(Bot::SpawnedBotCount(initiator->CharacterID()) >= MaxBotCreate) - { - initiator->Message(Chat::Yellow,"You have the maximum number of bots allowed."); + if (initiator) { + auto bot_creation_limit = initiator->GetBotCreationLimit(); + auto bot_creation_limit_class = initiator->GetBotCreationLimit(botclass); + auto bot_spawn_limit = initiator->GetBotSpawnLimit(); + auto bot_spawn_limit_class = initiator->GetBotSpawnLimit(botclass); + + uint32 bot_count = 0; + uint32 bot_class_count = 0; + if (!database.botdb.QueryBotCount(initiator->CharacterID(), botclass, bot_count, bot_class_count)) { + initiator->Message(Chat::White, "Failed to query bot count."); + return false; + } + + if (bot_creation_limit >= 0 && bot_count >= bot_creation_limit) { + std::string message; + + if (bot_creation_limit) { + message = fmt::format( + "You cannot create anymore than {} bot{}.", + bot_creation_limit, + bot_creation_limit != 1 ? "s" : "" + ); + } else { + message = "You cannot create any bots."; + } + + initiator->Message(Chat::White, message.c_str()); + return false; + } + + if (bot_creation_limit_class >= 0 && bot_class_count >= bot_creation_limit_class) { + std::string message; + + if (bot_creation_limit_class) { + message = fmt::format( + "You cannot create anymore than {} {} bot{}.", + bot_creation_limit_class, + GetClassIDName(botclass), + bot_creation_limit_class != 1 ? "s" : "" + ); + } else { + message = fmt::format( + "You cannot create any {} bots.", + GetClassIDName(botclass) + ); + } + + initiator->Message(Chat::White, message.c_str()); + return false; + } + + auto spawned_bot_count = Bot::SpawnedBotCount(initiator->CharacterID()); + + if ( + bot_spawn_limit >= 0 && + spawned_bot_count >= bot_spawn_limit && + !initiator->GetGM() + ) { + std::string message; + if (bot_spawn_limit) { + message = fmt::format( + "You cannot have more than {} spawned bot{}.", + bot_spawn_limit, + bot_spawn_limit != 1 ? "s" : "" + ); + } else { + message = "You are not currently allowed to spawn any bots."; + } + + initiator->Message(Chat::White, message.c_str()); + return false; + } + + auto spawned_bot_count_class = Bot::SpawnedBotCount(initiator->CharacterID(), botclass); + + if ( + bot_spawn_limit_class >= 0 && + spawned_bot_count_class >= bot_spawn_limit_class && + !initiator->GetGM() + ) { + std::string message; + if (bot_spawn_limit_class) { + message = fmt::format( + "You cannot have more than {} spawned {} bot{}.", + bot_spawn_limit_class, + GetClassIDName(botclass), + bot_spawn_limit_class != 1 ? "s" : "" + ); + } else { + message = fmt::format( + "You are not currently allowed to spawn any {} bots.", + GetClassIDName(botclass) + ); + } + + initiator->Message(Chat::White, message.c_str()); return false; } std::string test_name = name; bool available_flag = false; - if(!database.botdb.QueryNameAvailablity(test_name, available_flag)) { - initiator->Message(Chat::White, "%s for '%s'", BotDatabase::fail::QueryNameAvailablity(), (char*)name); + if (!database.botdb.QueryNameAvailablity(test_name, available_flag)) { + initiator->Message( + Chat::White, + fmt::format( + "Failed to query name availability for '{}'.", + test_name + ).c_str() + ); return false; } + if (!available_flag) { - initiator->Message(Chat::White, "The name %s is already being used or is invalid. Please choose a different name.", (char*)name); + initiator->Message( + Chat::White, + fmt::format( + "The name {} is already being used or is invalid. Please choose a different name.", + test_name + ).c_str() + ); return false; } - Bot* NewBot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(name, lastname, level, race, botclass, gender), initiator); + Bot* new_bot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(name, lastname, level, race, botclass, gender), initiator); - if(NewBot) - { - if(!NewBot->IsValidRaceClassCombo()) { + if (new_bot) { + if (!new_bot->IsValidRaceClassCombo()) { initiator->Message(Chat::White, "That Race/Class combination cannot be created."); return false; } - if(!NewBot->IsValidName()) { - initiator->Message(Chat::White, "%s has invalid characters. You can use only the A-Z, a-z and _ characters in a bot name.", NewBot->GetCleanName()); + if (!new_bot->IsValidName()) { + initiator->Message( + Chat::White, + fmt::format( + "{} has invalid characters. You can use only the A-Z, a-z and _ characters in a bot name.", + new_bot->GetCleanName() + ).c_str() + ); return false; } // Now that all validation is complete, we can save our newly created bot - if(!NewBot->Save()) - { - initiator->Message(Chat::White, "Unable to save %s as a bot.", NewBot->GetCleanName()); - } - else - { - initiator->Message(Chat::White, "%s saved as bot %u.", NewBot->GetCleanName(), NewBot->GetBotID()); + if (!new_bot->Save()) { + initiator->Message( + Chat::White, + fmt::format( + "Unable to save {} as a bot.", + new_bot->GetCleanName() + ).c_str() + ); + } else { + initiator->Message( + Chat::White, + fmt::format( + "{} saved as bot ID {}.", + new_bot->GetCleanName(), + new_bot->GetBotID() + ).c_str() + ); + + const auto export_string = fmt::format( + "{} {} {} {} {}", + name, + new_bot->GetBotID(), + race, + botclass, + gender + ); + + parse->EventPlayer(EVENT_BOT_CREATE, initiator, export_string, 0); return true; } } @@ -2310,12 +2438,10 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level return false; } -#endif //BOTS - -void QuestManager::taskselector(int taskcount, int *tasks) { +void QuestManager::taskselector(const std::vector& tasks, bool ignore_cooldown) { QuestManagerCurrentQuestVars(); if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager) - initiator->TaskQuestSetSelector(owner, taskcount, tasks); + initiator->TaskQuestSetSelector(owner, tasks, ignore_cooldown); } void QuestManager::enabletask(int taskcount, int *tasks) { QuestManagerCurrentQuestVars(); @@ -2340,11 +2466,11 @@ bool QuestManager::istaskenabled(int taskid) { return false; } -void QuestManager::tasksetselector(int tasksetid) { +void QuestManager::tasksetselector(int tasksetid, bool ignore_cooldown) { QuestManagerCurrentQuestVars(); Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for task set %i", tasksetid); if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager) - initiator->TaskSetSelector(owner, tasksetid); + initiator->TaskSetSelector(owner, tasksetid, ignore_cooldown); } bool QuestManager::istaskactive(int task) { @@ -2390,13 +2516,6 @@ void QuestManager::resettaskactivity(int task, int activity) { initiator->ResetTaskActivity(task, activity); } -void QuestManager::taskexploredarea(int exploreid) { - QuestManagerCurrentQuestVars(); - - if(RuleB(TaskSystem, EnableTaskSystem) && initiator) - initiator->UpdateTasksOnExplore(exploreid); -} - void QuestManager::assigntask(int taskid, bool enforce_level_requirement) { QuestManagerCurrentQuestVars(); @@ -2459,16 +2578,16 @@ int QuestManager::nexttaskinset(int taskset, int taskid) { int QuestManager::activespeaktask() { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner) - return initiator->ActiveSpeakTask(owner->GetNPCTypeID()); + if (RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && owner->IsNPC()) + return initiator->ActiveSpeakTask(owner->CastToNPC()); return 0; } int QuestManager::activespeakactivity(int taskid) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner) - return initiator->ActiveSpeakActivity(owner->GetNPCTypeID(), taskid); + if (RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && owner->IsNPC()) + return initiator->ActiveSpeakActivity(owner->CastToNPC(), taskid); return 0; } @@ -2519,6 +2638,24 @@ std::string QuestManager::gettaskname(uint32 task_id) { return std::string(); } +int QuestManager::GetCurrentDzTaskID() { + QuestManagerCurrentQuestVars(); + + if (RuleB(TaskSystem, EnableTaskSystem) && zone && task_manager) { + return task_manager->GetCurrentDzTaskID(); + } + + return 0; +} + +void QuestManager::EndCurrentDzTask(bool send_fail) { + QuestManagerCurrentQuestVars(); + + if (RuleB(TaskSystem, EnableTaskSystem) && zone && task_manager) { + task_manager->EndCurrentDzTask(send_fail); + } +} + void QuestManager::clearspawntimers() { if (!zone) { return; @@ -2540,22 +2677,29 @@ void QuestManager::we(int type, const char *str) { ); } -void QuestManager::message(int color, const char *message) { +void QuestManager::message(uint32 type, const char *message) { QuestManagerCurrentQuestVars(); - if (!initiator) + if (!initiator) { return; + } - initiator->Message(color, message); + initiator->Message(type, message); } void QuestManager::whisper(const char *message) { QuestManagerCurrentQuestVars(); - if (!initiator || !owner) + if (!initiator || !owner) { return; + } - std::string mob_name = owner->GetCleanName(); - std::string new_message = fmt::format("{} whispers, '{}'", mob_name, message); - initiator->Message(Chat::EchoChat1, new_message.c_str()); + initiator->Message( + Chat::EchoChat1, + fmt::format( + "{} whispers, '{}'", + owner->GetCleanName(), + message + ).c_str() + ); } int QuestManager::getlevel(uint8 type) @@ -2596,7 +2740,7 @@ int QuestManager::getlevel(uint8 type) else return (initiator->GetLevel()); } - else if(type == 4 && initiator->IsClient()) + else if(type == 4) { return (initiator->CastToClient()->GetLevel2()); } @@ -2618,14 +2762,11 @@ uint16 QuestManager::CreateGroundObjectFromModel(const char *model, const glm::v return entid; } -void QuestManager::ModifyNPCStat(const char *identifier, const char *newValue) +void QuestManager::ModifyNPCStat(std::string stat, std::string value) { QuestManagerCurrentQuestVars(); - if(owner){ - if(owner->IsNPC()) - { - owner->CastToNPC()->ModifyNPCStat(identifier, newValue); - } + if (owner && owner->IsNPC()) { + owner->CastToNPC()->ModifyNPCStat(stat, value); } } @@ -2766,19 +2907,38 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { } // Item Link for use in Variables - "my $example_link = quest::varlink(item_id);" -const char* QuestManager::varlink(char* perltext, int item_id) { +std::string QuestManager::varlink( + uint32 item_id, + int16 charges, + uint32 aug1, + uint32 aug2, + uint32 aug3, + uint32 aug4, + uint32 aug5, + uint32 aug6, + bool attuned +) { QuestManagerCurrentQuestVars(); - const EQ::ItemData* item = database.GetItem(item_id); - if (!item) + const auto *item = database.CreateItem( + item_id, + charges, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6, + attuned + ); + if (!item) { return "INVALID ITEM ID IN VARLINK"; + } EQ::SayLinkEngine linker; - linker.SetLinkType(EQ::saylink::SayLinkItemData); - linker.SetItemData(item); + linker.SetLinkType(EQ::saylink::SayLinkItemInst); + linker.SetItemInst(item); - strcpy(perltext, linker.GenerateLink().c_str()); - - return perltext; + return linker.GenerateLink(); } std::string QuestManager::getitemname(uint32 item_id) { @@ -2807,30 +2967,33 @@ std::string QuestManager::getcleannpcnamebyid(uint32 npc_id) { return res; } -uint16 QuestManager::CreateInstance(const char *zone, int16 version, uint32 duration) +uint16 QuestManager::CreateInstance(const char *zone_short_name, int16 instance_version, uint32 duration) { QuestManagerCurrentQuestVars(); - if(initiator) - { - uint32 zone_id = ZoneID(zone); - if(zone_id == 0) - return 0; - uint16 id = 0; - if(!database.GetUnusedInstanceID(id)) - { - initiator->Message(Chat::Red, "Server was unable to find a free instance id."); - return 0; - } - - if(!database.CreateInstance(id, zone_id, version, duration)) - { - initiator->Message(Chat::Red, "Server was unable to create a new instance."); - return 0; - } - return id; + uint32 zone_id = ZoneID(zone_short_name); + if (!zone_id) { + return 0; } - return 0; + + uint16 instance_id = 0; + if (!database.GetUnusedInstanceID(instance_id)) { + if (initiator) { + initiator->Message(Chat::Red, "Server was unable to find a free instance id."); + } + + return 0; + } + + if (!database.CreateInstance(instance_id, zone_id, instance_version, duration)) { + if (initiator) { + initiator->Message(Chat::Red, "Server was unable to create a new instance."); + } + + return 0; + } + + return instance_id; } void QuestManager::DestroyInstance(uint16 instance_id) @@ -2887,6 +3050,20 @@ uint16 QuestManager::GetInstanceID(const char *zone, int16 version) return 0; } +std::vector QuestManager::GetInstanceIDs(std::string zone_name, uint32 character_id) +{ + if (!character_id) { + QuestManagerCurrentQuestVars(); + if (initiator) { + return database.GetInstanceIDs(ZoneID(zone_name), initiator->CharacterID()); + } + + return { }; + } + + return database.GetInstanceIDs(ZoneID(zone_name), character_id); +} + uint16 QuestManager::GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id) { return database.GetInstanceID(ZoneID(zone), char_id, version); } @@ -2949,7 +3126,7 @@ void QuestManager::RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id } bool QuestManager::CheckInstanceByCharID(uint16 instance_id, uint32 char_id) { - return database.CharacterInInstanceGroup(instance_id, char_id); + return database.CheckInstanceByCharID(instance_id, char_id); } void QuestManager::RemoveAllFromInstance(uint16 instance_id) @@ -2957,14 +3134,14 @@ void QuestManager::RemoveAllFromInstance(uint16 instance_id) QuestManagerCurrentQuestVars(); if (initiator) { - std::list charid_list; + std::list character_ids; if (database.RemoveClientsFromInstance(instance_id)) initiator->Message(Chat::Say, "Removed all players from instance."); else { - database.GetCharactersInInstance(instance_id, charid_list); - initiator->Message(Chat::Say, "Failed to remove %i player(s) from instance.", charid_list.size()); // once the expedition system is in, this message it not relevant + database.GetCharactersInInstance(instance_id, character_ids); + initiator->Message(Chat::Say, "Failed to remove %i player(s) from instance.", character_ids.size()); // once the expedition system is in, this message it not relevant } } } @@ -3007,7 +3184,7 @@ std::string QuestManager::saylink(char *saylink_text, bool silent, const char *l { QuestManagerCurrentQuestVars(); - return EQ::SayLinkEngine::GenerateQuestSaylink(saylink_text, silent, link_name); + return Saylink::Create(saylink_text, silent, link_name); } std::string QuestManager::getcharnamebyid(uint32 char_id) { @@ -3188,17 +3365,10 @@ void QuestManager::voicetell(const char *str, int macronum, int racenum, int gen safe_delete(outapp); } else - LogQuests("QuestManager::voicetell from [{}]. Client [{}] not found", owner->GetName(), str); + LogQuests("from [{}]. Client [{}] not found", owner->GetName(), str); } } -void QuestManager::LearnRecipe(uint32 recipe_id) { - QuestManagerCurrentQuestVars(); - if(!initiator) - return; - initiator->LearnRecipe(recipe_id); -} - void QuestManager::SendMail(const char *to, const char *from, const char *subject, const char *message) { if(to == nullptr || from == nullptr || subject == nullptr || message == nullptr) { return; @@ -3288,6 +3458,15 @@ NPC *QuestManager::GetNPC() const { return nullptr; } +Bot *QuestManager::GetBot() const { + if (!quests_running_.empty()) { + running_quest e = quests_running_.top(); + return (e.owner && e.owner->IsBot()) ? e.owner->CastToBot() : nullptr; + } + + return nullptr; +} + Mob *QuestManager::GetOwner() const { if(!quests_running_.empty()) { running_quest e = quests_running_.top(); @@ -3395,11 +3574,11 @@ void QuestManager::UpdateZoneHeader(std::string type, std::string value) { } else if (strcasecmp(type.c_str(), "fog_density") == 0) { zone->newzone_data.fog_density = atof(value.c_str()); } else if (strcasecmp(type.c_str(), "suspendbuffs") == 0) { - zone->newzone_data.SuspendBuffs = atoi(value.c_str()); + zone->newzone_data.suspend_buffs = atoi(value.c_str()); } else if (strcasecmp(type.c_str(), "lavadamage") == 0) { - zone->newzone_data.LavaDamage = atoi(value.c_str()); + zone->newzone_data.lava_damage = atoi(value.c_str()); } else if (strcasecmp(type.c_str(), "minlavadamage") == 0) { - zone->newzone_data.MinLavaDamage = atoi(value.c_str()); + zone->newzone_data.min_lava_damage = atoi(value.c_str()); } auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); @@ -3415,10 +3594,6 @@ EQ::ItemInstance *QuestManager::CreateItem(uint32 item_id, int16 charges, uint32 return nullptr; } -std::string QuestManager::secondstotime(int duration) { - return ConvertSecondsToTime(duration); -} - std::string QuestManager::gethexcolorcode(std::string color_name) { for (auto color : html_colors) { @@ -3430,20 +3605,20 @@ std::string QuestManager::gethexcolorcode(std::string color_name) { return std::string(); } -double QuestManager::GetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id) const { - return database.GetAAEXPModifier(character_id, zone_id); +double QuestManager::GetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, int16 instance_version) const { + return database.GetAAEXPModifier(character_id, zone_id, instance_version); } -double QuestManager::GetEXPModifierByCharID(uint32 character_id, uint32 zone_id) const { - return database.GetEXPModifier(character_id, zone_id); +double QuestManager::GetEXPModifierByCharID(uint32 character_id, uint32 zone_id, int16 instance_version) const { + return database.GetEXPModifier(character_id, zone_id, instance_version); } -void QuestManager::SetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, double aa_modifier) { - database.SetAAEXPModifier(character_id, zone_id, aa_modifier); +void QuestManager::SetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, double aa_modifier, int16 instance_version) { + database.SetAAEXPModifier(character_id, zone_id, aa_modifier, instance_version); } -void QuestManager::SetEXPModifierByCharID(uint32 character_id, uint32 zone_id, double exp_modifier) { - database.SetEXPModifier(character_id, zone_id, exp_modifier); +void QuestManager::SetEXPModifierByCharID(uint32 character_id, uint32 zone_id, double exp_modifier, int16 instance_version) { + database.SetEXPModifier(character_id, zone_id, exp_modifier, instance_version); } std::string QuestManager::getgendername(uint32 gender_id) { @@ -3459,9 +3634,9 @@ std::string QuestManager::getinventoryslotname(int16 slot_id) { return EQ::invslot::GetInvPossessionsSlotName(slot_id); } -int QuestManager::getitemstat(uint32 item_id, std::string stat_identifier) { +const int QuestManager::getitemstat(uint32 item_id, std::string stat_identifier) { QuestManagerCurrentQuestVars(); - return EQ::InventoryProfile::GetItemStatValue(item_id, stat_identifier.c_str()); + return EQ::InventoryProfile::GetItemStatValue(item_id, stat_identifier); } int QuestManager::getspellstat(uint32 spell_id, std::string stat_identifier, uint8 slot) { @@ -3546,12 +3721,12 @@ void QuestManager::CrossZoneSetEntityVariable(uint8 update_type, int update_iden safe_delete(pack); } -void QuestManager::CrossZoneSignal(uint8 update_type, int update_identifier, uint32 signal, const char* client_name) { +void QuestManager::CrossZoneSignal(uint8 update_type, int update_identifier, int signal_id, const char* client_name) { auto pack = new ServerPacket(ServerOP_CZSignal, sizeof(CZSignal_Struct)); CZSignal_Struct* CZS = (CZSignal_Struct*)pack->pBuffer; CZS->update_type = update_type; CZS->update_identifier = update_identifier; - CZS->signal = signal; + CZS->signal_id = signal_id; strn0cpy(CZS->client_name, client_name, 64); worldserver.SendPacket(pack); safe_delete(pack); @@ -3656,11 +3831,11 @@ void QuestManager::WorldWideSetEntityVariable(uint8 update_type, const char* var safe_delete(pack); } -void QuestManager::WorldWideSignal(uint8 update_type, uint32 signal, uint8 min_status, uint8 max_status) { +void QuestManager::WorldWideSignal(uint8 update_type, int signal_id, uint8 min_status, uint8 max_status) { auto pack = new ServerPacket(ServerOP_WWSignal, sizeof(WWSignal_Struct)); WWSignal_Struct* WWS = (WWSignal_Struct*)pack->pBuffer; WWS->update_type = update_type; - WWS->signal = signal; + WWS->signal_id = signal_id; WWS->min_status = min_status; WWS->max_status = max_status; worldserver.SendPacket(pack); @@ -3703,3 +3878,107 @@ std::string QuestManager::getenvironmentaldamagename(uint8 damage_type) { std::string environmental_damage_name = EQ::constants::GetEnvironmentalDamageName(damage_type); return environmental_damage_name; } + +void QuestManager::TrackNPC(uint32 entity_id) { + QuestManagerCurrentQuestVars(); + if (!initiator) { + return; + } + + initiator->SetTrackingID(entity_id); +} + +int QuestManager::GetRecipeMadeCount(uint32 recipe_id) { + QuestManagerCurrentQuestVars(); + if (!initiator) { + return 0; + } + + return initiator->GetRecipeMadeCount(recipe_id); +} + +std::string QuestManager::GetRecipeName(uint32 recipe_id) { + auto r = TradeskillRecipeRepository::GetWhere( + database, + fmt::format("id = {}", recipe_id) + ); + + if (!r.empty() && r[0].id) { + return r[0].name; + } + + return std::string(); +} + +bool QuestManager::HasRecipeLearned(uint32 recipe_id) { + QuestManagerCurrentQuestVars(); + if (!initiator) { + return false; + } + + return initiator->HasRecipeLearned(recipe_id); +} + +void QuestManager::LearnRecipe(uint32 recipe_id) { + QuestManagerCurrentQuestVars(); + if (!initiator) { + return; + } + + initiator->LearnRecipe(recipe_id); +} + +void QuestManager::marquee(uint32 type, std::string message, uint32 duration) +{ + QuestManagerCurrentQuestVars(); + if (!initiator) { + return; + } + + initiator->SendMarqueeMessage(type, message, duration); +} + +void QuestManager::marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message) +{ + QuestManagerCurrentQuestVars(); + if (!initiator) { + return; + } + + initiator->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, message); +} + +bool QuestManager::DoAugmentSlotsMatch(uint32 item_one, uint32 item_two) +{ + const auto* inst_one = database.GetItem(item_one); + if (!inst_one) { + return false; + } + + const auto* inst_two = database.GetItem(item_two); + if (!inst_two) { + return false; + } + + for (auto i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { + if (inst_one->AugSlotType[i] != inst_two->AugSlotType[i]) { + return false; + } + } + + return true; +} + +int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id) +{ + if (!inst) { + return INVALID_INDEX; + } + + const auto* aug_inst = database.GetItem(augment_id); + if (!aug_inst) { + return INVALID_INDEX; + } + + return inst->AvailableAugmentSlot(aug_inst->AugType); +} diff --git a/zone/questmgr.h b/zone/questmgr.h index d5b93b83a..ed7899fbd 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -113,8 +113,8 @@ public: void changedeity(int deity_id); void exp(int amt); void level(int newlevel); - void traindisc(int discipline_tome_item_id); - bool isdisctome(int item_id); + void traindisc(uint32 discipline_tome_item_id); + bool isdisctome(uint32 item_id); std::string getracename(uint16 race_id); std::string getspellname(uint32 spell_id); std::string getskillname(int skill_id); @@ -127,7 +127,7 @@ public: void rain(int weather); void snow(int weather); void rename(std::string name); - void surname(const char *name); + void surname(std::string last_name); void permaclass(int class_id); void permarace(int race_id); void permagender(int gender_id); @@ -135,12 +135,12 @@ public: uint16 traindiscs(uint8 max_level, uint8 min_level = 1); void unscribespells(); void untraindiscs(); - void givecash(int copper, int silver, int gold, int platinum); + void givecash(uint32 copper, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0); void pvp(const char *mode); void movepc(int zone_id, float x, float y, float z, float heading); void gmmove(float x, float y, float z); void movegrp(int zoneid, float x, float y, float z); - void doanim(int anim_id); + void doanim(int animation_id, int animation_speed = 1, bool ackreq = true, eqFilterType filter = FilterNone); void addskill(int skill_id, int value); void setlanguage(int skill_id, int value); void setskill(int skill_id, int value); @@ -150,6 +150,7 @@ public: void attacknpctype(int npc_type_id); void save(); void faction(int faction_id, int faction_value, int temp); + void rewardfaction(int faction_id, int faction_value); void setsky(uint8 new_sky); void setguild(uint32 new_guild_id, uint8 new_rank); void CreateGuild(const char *guild_name, const char *leader); @@ -176,7 +177,8 @@ public: void setnexthpevent(int at); void setnextinchpevent(int at); void respawn(int npc_type, int grid); - void set_proximity(float minx, float maxx, float miny, float maxy, float minz=-999999, float maxz=999999, bool bSay = false); + void set_proximity(float min_x, float max_x, float min_y, float max_y, float min_z = -999999.0f, float max_z = 999999.0f, bool enable_say = false); + void set_proximity_range(float x_range, float y_range, float z_range = 999999.0f, bool enable_say = false); void clear_proximity(); void enable_proximity_say(); void disable_proximity_say(); @@ -209,8 +211,8 @@ public: void playerfeature(char *feature, int setting); void npcfeature(char *feature, int setting); void popup(const char *title, const char *text, uint32 popupid, uint32 buttons, uint32 Duration); - void taskselector(int taskcount, int *tasks); - void tasksetselector(int tasksettid); + void taskselector(const std::vector& tasks, bool ignore_cooldown = false); + void tasksetselector(int tasksettid, bool ignore_cooldown = false); void enabletask(int taskcount, int *tasks); void disabletask(int taskcount, int *tasks); bool istaskenabled(int taskid); @@ -219,7 +221,6 @@ public: int gettaskactivitydonecount(int task, int activity); void updatetaskactivity(int task, int activity, int count, bool ignore_quest_update = false); void resettaskactivity(int task, int activity); - void taskexploredarea(int exploreid); void assigntask(int taskid, bool enforce_level_requirement = false); void failtask(int taskid); int tasktimeleft(int taskid); @@ -234,33 +235,38 @@ public: int completedtasksinset(int taskset); bool istaskappropriate(int task); std::string gettaskname(uint32 task_id); - void clearspawntimers(); + int GetCurrentDzTaskID(); + void EndCurrentDzTask(bool send_fail = false); + void clearspawntimers(); void ze(int type, const char *str); void we(int type, const char *str); - void message(int color, const char *message); + void marquee(uint32 type, std::string message, uint32 duration = 3000); + void marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message); + void message(uint32 type, const char *message); void whisper(const char *message); - int getlevel(uint8 type); - int collectitems(uint32 item_id, bool remove); - int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove); + int getlevel(uint8 type); + int collectitems(uint32 item_id, bool remove); + int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove); int countitem(uint32 item_id); void removeitem(uint32 item_id, uint32 quantity = 1); std::string getitemname(uint32 item_id); - void enabletitle(int titleset); - bool checktitle(int titlecheck); - void removetitle(int titlecheck); + void enabletitle(int titleset); + bool checktitle(int titlecheck); + void removetitle(int titlecheck); uint16 CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time = 300000); uint16 CreateGroundObjectFromModel(const char* model, const glm::vec4& position, uint8 type = 0x00, uint32 decay_time = 0); - void ModifyNPCStat(const char *identifier, const char *newValue); + void ModifyNPCStat(std::string stat, std::string value); void UpdateSpawnTimer(uint32 id, uint32 newTime); void MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity = 0); uint32 MerchantCountItem(uint32 NPCid, uint32 itemid); - uint16 CreateInstance(const char *zone, int16 version, uint32 duration); + uint16 CreateInstance(const char *zone_short_name, int16 instance_version, uint32 duration); void UpdateInstanceTimer(uint16 instance_id, uint32 new_duration); void UpdateZoneHeader(std::string type, std::string value); uint32 GetInstanceTimer(); uint32 GetInstanceTimerByID(uint16 instance_id = 0); void DestroyInstance(uint16 instance_id); uint16 GetInstanceID(const char *zone, int16 version); + std::vector GetInstanceIDs(std::string zone_name, uint32 character_id = 0); uint16 GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id); void AssignToInstance(uint16 instance_id); void AssignToInstanceByCharID(uint16 instance_id, uint32 char_id); @@ -275,7 +281,7 @@ public: void MovePCInstance(int zone_id, int instance_id, const glm::vec4& position); void FlagInstanceByGroupLeader(uint32 zone, int16 version); void FlagInstanceByRaidLeader(uint32 zone, int16 version); - const char* varlink(char* perltext, int item_id); + std::string varlink(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false); std::string saylink(char *saylink_text, bool silent, const char *link_name); std::string getcharnamebyid(uint32 char_id); uint32 getcharidbyname(const char* name); @@ -294,12 +300,12 @@ public: uint8 FactionValue(); void wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0); void voicetell(const char *str, int macronum, int racenum, int gendernum); - void LearnRecipe(uint32 recipe_id); - void SendMail(const char *to, const char *from, const char *subject, const char *message); + void LearnRecipe(uint32 recipe_id); + void SendMail(const char *to, const char *from, const char *subject, const char *message); uint16 CreateDoor( const char* model, float x, float y, float z, float heading, uint8 opentype, uint16 size); - int32 GetZoneID(const char *zone); - static std::string GetZoneLongName(std::string zone_short_name); - static std::string GetZoneLongNameByID(uint32 zone_id); + int32 GetZoneID(const char *zone); + static std::string GetZoneLongName(std::string zone_short_name); + static std::string GetZoneLongNameByID(uint32 zone_id); static std::string GetZoneShortName(uint32 zone_id); void CrossZoneDialogueWindow(uint8 update_type, int update_identifier, const char* message, const char* client_name = ""); void CrossZoneLDoNUpdate(uint8 update_type, uint8 update_subtype, int update_identifier, uint32 theme_id, int points = 1, const char* client_name = ""); @@ -307,7 +313,7 @@ public: void CrossZoneMessage(uint8 update_type, int update_identifier, uint32 type, const char* message, const char* client_name = ""); void CrossZoneMove(uint8 update_type, uint8 update_subtype, int update_identifier, const char* zone_short_name, uint16 instance_id, const char* client_name = ""); void CrossZoneSetEntityVariable(uint8 update_type, int update_identifier, const char* variable_name, const char* variable_value, const char* client_name = ""); - void CrossZoneSignal(uint8 update_type, int update_identifier, uint32 signal, const char* client_name = ""); + void CrossZoneSignal(uint8 update_type, int update_identifier, int signal_id, const char* client_name = ""); void CrossZoneSpell(uint8 update_type, uint8 update_subtype, int update_identifier, uint32 spell_id, const char* client_name = ""); void CrossZoneTaskUpdate(uint8 update_type, uint8 update_subtype, int update_identifier, uint32 task_identifier, int task_subidentifier = -1, int update_count = 1, bool enforce_level_requirement = false, const char* client_name = ""); void WorldWideDialogueWindow(const char* message, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); @@ -316,27 +322,33 @@ public: void WorldWideMessage(uint32 type, const char* message, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); void WorldWideMove(uint8 update_type, const char* zone_short_name, uint16 instance_id = 0, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); void WorldWideSetEntityVariable(uint8 update_type, const char* variable_name, const char* variable_value, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); - void WorldWideSignal(uint8 update_type, uint32 signal, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); + void WorldWideSignal(uint8 update_type, int signal_id, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); void WorldWideSpell(uint8 update_type, uint32 spell_id, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); void WorldWideTaskUpdate(uint8 update_type, uint32 task_identifier, int task_subidentifier = -1, int update_count = 1, bool enforce_level_requirement = false, uint8 min_status = AccountStatus::Player, uint8 max_status = AccountStatus::Player); bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); void ClearNPCTypeCache(int npctype_id); void ReloadZoneStaticData(); - std::string secondstotime(int duration); std::string gethexcolorcode(std::string color_name); - double GetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id) const; - double GetEXPModifierByCharID(uint32 character_id, uint32 zone_id) const; - void SetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, double aa_modifier); - void SetEXPModifierByCharID(uint32 character_id, uint32 zone_id, double exp_modifier); + double GetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, int16 instance_version = -1) const; + double GetEXPModifierByCharID(uint32 character_id, uint32 zone_id, int16 instance_version = -1) const; + void SetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, double aa_modifier, int16 instance_version = -1); + void SetEXPModifierByCharID(uint32 character_id, uint32 zone_id, double exp_modifier, int16 instance_version = -1); std::string getgendername(uint32 gender_id); std::string getdeityname(uint32 deity_id); std::string getinventoryslotname(int16 slot_id); - int getitemstat(uint32 item_id, std::string stat_identifier); + const int getitemstat(uint32 item_id, std::string stat_identifier); int getspellstat(uint32 spell_id, std::string stat_identifier, uint8 slot = 0); const SPDat_Spell_Struct *getspell(uint32 spell_id); std::string getenvironmentaldamagename(uint8 damage_type); + void TrackNPC(uint32 entity_id); + int GetRecipeMadeCount(uint32 recipe_id); + std::string GetRecipeName(uint32 recipe_id); + bool HasRecipeLearned(uint32 recipe_id); + bool DoAugmentSlotsMatch(uint32 item_one, uint32 item_two); + int8 DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id); + Bot *GetBot() const; Client *GetInitiator() const; NPC *GetNPC() const; Mob *GetOwner() const; @@ -346,14 +358,11 @@ public: std::string GetEncounter() const; inline bool ProximitySayInUse() { return HaveProximitySays; } -#ifdef BOTS - int createbotcount(); - int spawnbotcount(); + int createbotcount(uint8 class_id = NO_CLASS); + int spawnbotcount(uint8 class_id = NO_CLASS); bool botquest(); bool createBot(const char *name, const char *lastname, uint8 level, uint16 race, uint8 botclass, uint8 gender); -#endif - inline uint16 GetMana(uint32 spell_id) { return( spells[spell_id].mana); } private: std::stack quests_running_; diff --git a/zone/raids.cpp b/zone/raids.cpp index db57a4eed..b27cae0e0 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "entity.h" @@ -24,6 +24,7 @@ #include "groups.h" #include "mob.h" #include "raids.h" +#include "string_ids.h" #include "worldserver.h" @@ -353,12 +354,26 @@ void Raid::UpdateRaidAAs() SaveRaidLeaderAA(); } -bool Raid::IsGroupLeader(const char *who) +bool Raid::IsGroupLeader(const char* name) { - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if(strcmp(who, members[x].membername) == 0){ - return members[x].IsGroupLeader; + if (name) { + for (const auto &m: members) { + if (!strcmp(m.membername, name)) { + return m.IsGroupLeader; + } + } + } + + return false; +} + +bool Raid::IsGroupLeader(Client *c) +{ + if (c) { + for (const auto &m: members) { + if (m.member == c) { + return true; + } } } @@ -736,93 +751,79 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int3 void Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter) { //avoid unneeded work - if (gid == RAID_GROUPLESS) + if (gid == RAID_GROUPLESS) { return; + } - if(copper == 0 && silver == 0 && gold == 0 && platinum == 0) + if ( + !copper && + !silver && + !gold && + !platinum + ) { return; + } - uint32 i; - uint8 membercount = 0; - for (i = 0; i < MAX_RAID_MEMBERS; i++) { - if (members[i].member != nullptr && members[i].GroupNumber == gid) { - membercount++; + uint8 member_count = 0; + for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) { + if (members[i].member && members[i].GroupNumber == gid) { + member_count++; } } - if (membercount == 0) + if (!member_count) { return; + } - uint32 mod; - //try to handle round off error a little better - if(membercount > 1) { - mod = platinum % membercount; - if((mod) > 0) { - platinum -= mod; - gold += 10 * mod; + uint32 modifier; + if (member_count > 1) { + modifier = platinum % member_count; + + if (modifier) { + platinum -= modifier; + gold += 10 * modifier; } - mod = gold % membercount; - if((mod) > 0) { - gold -= mod; - silver += 10 * mod; + + modifier = gold % member_count; + + if (modifier) { + gold -= modifier; + silver += 10 * modifier; } - mod = silver % membercount; - if((mod) > 0) { - silver -= mod; - copper += 10 * mod; + + modifier = silver % member_count; + + if (modifier) { + silver -= modifier; + copper += 10 * modifier; } } - //calculate the splits - //We can still round off copper pieces, but I dont care - uint32 sc; - uint32 cpsplit = copper / membercount; - sc = copper % membercount; - uint32 spsplit = silver / membercount; - uint32 gpsplit = gold / membercount; - uint32 ppsplit = platinum / membercount; + auto copper_split = copper / member_count; + auto silver_split = silver / member_count; + auto gold_split = gold / member_count; + auto platinum_split = platinum / member_count; - char buf[128]; - buf[63] = '\0'; - std::string msg = "You receive"; - bool one = false; + for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) { + if (members[i].member && members[i].GroupNumber == gid) { // If Group Member is Client + members[i].member->AddMoneyToPP( + copper_split, + silver_split, + gold_split, + platinum_split, + true + ); - if(ppsplit > 0) { - snprintf(buf, 63, " %u platinum", ppsplit); - msg += buf; - one = true; - } - if(gpsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u gold", gpsplit); - msg += buf; - one = true; - } - if(spsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u silver", spsplit); - msg += buf; - one = true; - } - if(cpsplit > 0) { - if(one) - msg += ","; - //this message is not 100% accurate for the splitter - //if they are receiving any roundoff - snprintf(buf, 63, " %u copper", cpsplit); - msg += buf; - one = true; - } - msg += " as your split"; - - for (i = 0; i < MAX_RAID_MEMBERS; i++) { - if (members[i].member != nullptr && members[i].GroupNumber == gid) { // If Group Member is Client - //I could not get MoneyOnCorpse to work, so we use this - members[i].member->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); - - members[i].member->Message(Chat::Green, msg.c_str()); + members[i].member->MessageString( + Chat::MoneySplit, + YOU_RECEIVE_AS_SPLIT, + Strings::Money( + platinum_split, + gold_split, + silver_split, + copper_split + ).c_str() + ); } } } @@ -903,12 +904,29 @@ void Raid::RemoveRaidLooter(const char* looter) safe_delete(pack); } -bool Raid::IsRaidMember(const char *name){ - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if(strcmp(name, members[x].membername) == 0) - return true; +bool Raid::IsRaidMember(const char *name) +{ + if (name) { + for (const auto &m: members) { + if (!strcmp(m.membername, name)) { + return true; + } + } } + + return false; +} + +bool Raid::IsRaidMember(Client* c) +{ + if (c) { + for (const auto &m: members) { + if (m.member == c) { + return true; + } + } + } + return false; } @@ -1448,7 +1466,7 @@ void Raid::GetRaidDetails() void Raid::SaveRaidMOTD() { std::string query = StringFormat("UPDATE raid_details SET motd = '%s' WHERE raidid = %lu", - EscapeString(motd).c_str(), (unsigned long)GetID()); + Strings::Escape(motd).c_str(), (unsigned long)GetID()); auto results = database.QueryDatabase(query); } @@ -1781,7 +1799,7 @@ void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_re uint32 group_id = GetGroup(sender->CastToClient()); /* If this is a group only packet and we're not in a group -- return */ - if (!group_id == 0xFFFFFFFF && group_only) + if (group_id == 0xFFFFFFFF && group_only) return; for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) { diff --git a/zone/raids.h b/zone/raids.h index e1d1cadb3..885dd2fa1 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -102,10 +102,11 @@ public: Raid(uint32 raidID); ~Raid(); - void SetLeader(Client *newLeader) { leader = newLeader; } + void SetLeader(Client* c) { leader = c; } Client* GetLeader() { return leader; } - bool IsLeader(Client *c) { return leader==c; } - bool IsLeader(const char* name) { return (strcmp(leadername, name)==0); } + std::string GetLeaderName() { return leadername; } + bool IsLeader(Client* c) { return c == leader; } + bool IsLeader(const char* name) { return !strcmp(leadername, name); } void SetRaidLeader(const char *wasLead, const char *name); bool Process(); @@ -118,8 +119,10 @@ public: void SetGroupLeader(const char *who, bool glFlag = true); Client *GetGroupLeader(uint32 group_id); void RemoveGroupLeader(const char *who); - bool IsGroupLeader(const char *who); - bool IsRaidMember(const char *name); + bool IsGroupLeader(const char* name); + bool IsGroupLeader(Client *c); + bool IsRaidMember(const char* name); + bool IsRaidMember(Client *c); void UpdateLevel(const char *name, int newLevel); uint32 GetFreeGroup(); @@ -154,7 +157,7 @@ public: void RaidMessageString(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0); void CastGroupSpell(Mob* caster,uint16 spellid, uint32 gid); - void SplitExp(uint32 exp, Mob* other); + void SplitExp(const uint64 exp, Mob* other); uint32 GetTotalRaidDamage(Mob* other); void BalanceHP(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0); void BalanceMana(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0); diff --git a/zone/shared_task_zone_messaging.cpp b/zone/shared_task_zone_messaging.cpp index 89e262847..379b5d6f8 100644 --- a/zone/shared_task_zone_messaging.cpp +++ b/zone/shared_task_zone_messaging.cpp @@ -53,11 +53,11 @@ void SharedTaskZoneMessaging::HandleWorldMessage(ServerPacket *pack) break; } - case ServerOP_SharedTaskAttemptRemove: { - auto p = reinterpret_cast(pack->pBuffer); + case ServerOP_SharedTaskQuit: { + auto p = reinterpret_cast(pack->pBuffer); auto c = entity_list.GetClientByCharID(p->requested_character_id); if (c) { - LogTasks("[ServerOP_SharedTaskAttemptRemove] We're back in zone and I found [{}]", c->GetCleanName()); + LogTasks("[ServerOP_SharedTaskQuit] We're back in zone and I found [{}]", c->GetCleanName()); c->m_requested_shared_task_removal = true; c->GetTaskState()->CancelTask( @@ -169,6 +169,15 @@ void SharedTaskZoneMessaging::HandleWorldMessage(ServerPacket *pack) break; } + case ServerOP_SharedTaskFailed: { + auto buf = reinterpret_cast(pack->pBuffer); + Client* client = entity_list.GetClientByCharID(buf->character_id); + if (client) + { + client->SendTaskFailed(buf->task_id, TASKSLOTSHAREDTASK, TaskType::Shared); + } + break; + } default: break; } diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index d314137bd..be0971953 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -17,7 +17,7 @@ */ #include "../common/global_define.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "entity.h" @@ -26,7 +26,7 @@ #include "worldserver.h" #include "zone.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" extern EntityList entity_list; extern Zone* zone; @@ -157,13 +157,13 @@ bool Spawn2::Process() { if (timer.Check()) { timer.Disable(); - LogSpawns("Spawn2 [{}]: Timer has triggered", spawn2_id); + LogSpawns("[{}]: Timer has triggered", spawn2_id); //first check our spawn condition, if this isnt active //then we reset the timer and try again next time. if (condition_id != SC_AlwaysEnabled && !zone->spawn_conditions.Check(condition_id, condition_min_value)) { - LogSpawns("Spawn2 [{}]: spawning prevented by spawn condition [{}]", spawn2_id, condition_id); + LogSpawns("[{}]: spawning prevented by spawn condition [{}]", spawn2_id, condition_id); Reset(); return (true); } @@ -205,6 +205,11 @@ bool Spawn2::Process() { return (true); } + if (tmp->npc_id == 0) { + LogError("NPC type did not load for npc_id [{}]", npcid); + return true; + } + if (tmp->unique_spawn_by_name) { if (!entity_list.LimitCheckName(tmp->name)) { LogSpawns("Spawn2 [{}]: Spawn group [{}] yeilded NPC type [{}], which is unique and one already exists", spawn2_id, spawngroup_id_, npcid); @@ -570,6 +575,8 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa } } + LogInfo("Loaded [{}] respawn timer(s)", Strings::Commify(results.RowCount())); + const char *zone_name = ZoneName(zoneid); std::string query = StringFormat( "SELECT " @@ -629,6 +636,8 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa spawn2_list.Insert(new_spawn); } + LogInfo("Loaded [{}] spawn2 entries", Strings::Commify(results.RowCount())); + NPC::SpawnZoneController(); return true; @@ -1001,6 +1010,8 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in LogSpawns("Loaded spawn condition [{}] with value [{}] and on_change [{}]", cond.condition_id, cond.value, cond.on_change); } + LogInfo("Loaded [{}] spawn_conditions", Strings::Commify(std::to_string(results.RowCount()))); + //load values query = StringFormat("SELECT id, value FROM spawn_condition_values " "WHERE zone = '%s' AND instance_id = %u", @@ -1027,6 +1038,8 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in return false; } + LogInfo("Loaded [{}] spawn_events", Strings::Commify(std::to_string(results.RowCount()))); + for (auto row = results.begin(); row != results.end(); ++row) { SpawnEvent event; diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index 84ae2a8f9..f20f19977 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -24,7 +24,7 @@ #include "spawngroup.h" #include "zone.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "../common/repositories/criteria/content_filter_criteria.h" extern EntityList entity_list; @@ -225,6 +225,8 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG spawn_group_list->AddSpawnGroup(new_spawn_group); } + LogInfo("Loaded [{}] spawn group(s)", Strings::Commify(results.RowCount())); + query = fmt::format( SQL( SELECT @@ -273,6 +275,9 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG spawn_group->AddSpawnEntry(new_spawn_entry); } + LogInfo("Loaded [{}] spawn entries", Strings::Commify(results.RowCount())); + + return true; } @@ -314,7 +319,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn for (auto row = results.begin(); row != results.end(); ++row) { LogSpawnsDetail( - "[LoadSpawnGroupsByID] Loading spawn_group spawn_group_id [{}] name [{}] spawn_limit [{}] dist [{}]", + "Loading spawn_group spawn_group_id [{}] name [{}] spawn_limit [{}] dist [{}]", row[0], row[1], row[2], @@ -372,7 +377,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn ); LogSpawnsDetail( - "[LoadSpawnGroupsByID] Loading spawn_entry spawn_group_id [{}] npc_id [{}] chance [{}] condition_value_filter [{}] spawn_limit [{}]", + "Loading spawn_entry spawn_group_id [{}] npc_id [{}] chance [{}] condition_value_filter [{}] spawn_limit [{}]", row[0], row[1], row[2], diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 17f6f6e9c..bec56cf1f 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -17,7 +17,7 @@ */ #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "entity.h" @@ -112,13 +112,18 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) auto *inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); if (inst && inst->GetItem() && inst->GetItem()->ItemType == EQ::item::ItemType1HPiercing) { base = inst->GetItemBackstabDamage(true); - if (!inst->GetItemBackstabDamage()) + if (!inst->GetItemBackstabDamage()) { base += inst->GetItemWeaponDamage(true); + } + if (target) { - if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true)) + if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true) && !RuleB(Combat, BackstabIgnoresElemental)) { base += target->ResistElementalWeaponDmg(inst); - if (inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) + } + + if ((inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) && !RuleB(Combat, BackstabIgnoresBane)) { base += target->CheckBaneDamage(inst); + } } } } else if (IsNPC()) { @@ -180,7 +185,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas auto fbash = GetFuriousBash(itm->Focus.Effect); hate = hate * (100 + fbash) / 100; if (fbash) - MessageString(Chat::Spells, GLOWS_RED, itm->Name); + MessageString(Chat::FocusEffect, GLOWS_RED, itm->Name); } } } @@ -1153,52 +1158,52 @@ float Mob::GetRangeDistTargetSizeMod(Mob* other) return (mod + 2.0f); //Add 2.0f as buffer to prevent any chance of failures, client enforce range check regardless. } -void NPC::RangedAttack(Mob* other) +void NPC::RangedAttack(Mob *other) { if (!other) return; - //make sure the attack and ranged timers are up - //if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow - if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())){ - LogCombat("Archery canceled. Timer not up. Attack [{}], ranged [{}]", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); + // make sure the attack and ranged timers are up + // if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow + if ((attack_timer.Enabled() && !attack_timer.Check(false)) || + (ranged_timer.Enabled() && !ranged_timer.Check())) { + LogCombat("Archery canceled. Timer not up. Attack [{}], ranged [{}]", attack_timer.GetRemainingTime(), + ranged_timer.GetRemainingTime()); return; } - if(!CheckLosFN(other)) + if (!HasBowAndArrowEquipped() && !GetSpecialAbility(SPECATK_RANGED_ATK)) return; - int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0); - attacks = attacks > 0 ? attacks : 1; - for(int i = 0; i < attacks; ++i) { + if (!CheckLosFN(other)) + return; - if(!GetSpecialAbility(SPECATK_RANGED_ATK)) + int attacks = 1; + float min_range = static_cast(RuleI(Combat, MinRangedAttackDist)); + float max_range = 250.0f; // needs to be longer than 200(most spells) + + if (GetSpecialAbility(SPECATK_RANGED_ATK)) { + int temp_attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0); + attacks = temp_attacks > 0 ? temp_attacks : 1; + + int temp_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 4); // Min Range of NPC attack + int temp_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); // Max Range of NPC attack + if (temp_max_range) + max_range = static_cast(temp_max_range); + if (temp_min_range) + min_range = static_cast(temp_min_range); + } + + max_range *= max_range; + min_range *= min_range; + + for (int i = 0; i < attacks; ++i) { + if (DistanceSquared(m_Position, other->GetPosition()) > max_range) + return; + else if (DistanceSquared(m_Position, other->GetPosition()) < min_range) return; - int sa_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 4); //Min Range of NPC attack - int sa_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); //Max Range of NPC attack - - float min_range = static_cast(RuleI(Combat, MinRangedAttackDist)); - float max_range = 250; // needs to be longer than 200(most spells) - - if (sa_max_range) - max_range = static_cast(sa_max_range); - - if (sa_min_range) - min_range = static_cast(sa_min_range); - - max_range *= max_range; - if(DistanceSquared(m_Position, other->GetPosition()) > max_range) - return; - else if(DistanceSquared(m_Position, other->GetPosition()) < (min_range * min_range)) - return; - - if(!other || !IsAttackAllowed(other) || - IsCasting() || - DivineAura() || - IsStunned() || - IsFeared() || - IsMezzed() || - (GetAppearance() == eaDead)){ + if (!other || !IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsFeared() || + IsMezzed() || (GetAppearance() == eaDead)) { return; } @@ -1318,7 +1323,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 const EQ::ItemData* item = RangeWeapon->GetItem(); if (item->ItemType != EQ::item::ItemTypeLargeThrowing && item->ItemType != EQ::item::ItemTypeSmallThrowing) { - LogCombat("Ranged attack canceled. Ranged item [{}] is not a throwing weapon. type [{}]", item->ItemType); + LogCombat("Ranged attack canceled. Ranged item [{}] is not a throwing weapon. type [{}]", item->ID, item->ItemType); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(EQ::invslot::slotRange)); return; } @@ -2154,8 +2159,13 @@ void Mob::InstillDoubt(Mob *who) { int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse) { // Only works on YOUR target. - if (defender && defender->GetBodyType() == BT_Humanoid && !defender->IsClient() && - skillInUse == EQ::skills::SkillArchery && GetTarget() == defender) { + if ( + defender && + !defender->IsClient() && + skillInUse == EQ::skills::SkillArchery && + GetTarget() == defender && + (defender->GetBodyType() == BT_Humanoid || !RuleB(Combat, HeadshotOnlyHumanoids)) + ) { uint32 HeadShot_Dmg = aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG]; uint8 HeadShot_Level = 0; // Get Highest Headshot Level HeadShot_Level = std::max({aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX], spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX], itembonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX]}); @@ -2184,8 +2194,13 @@ int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse) int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse) { - if (defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && GetLevel() >= 60 && - (skillInUse == EQ::skills::SkillBackstab || skillInUse == EQ::skills::SkillThrowing)) { + if ( + defender && + !defender->IsClient() && + GetLevel() >= 60 && + (skillInUse == EQ::skills::SkillBackstab || skillInUse == EQ::skills::SkillThrowing) && + (defender->GetBodyType() == BT_Humanoid || !RuleB(Combat, AssassinateOnlyHumanoids)) + ) { int chance = GetDEX(); if (skillInUse == EQ::skills::SkillBackstab) { chance = 100 * chance / (chance + 3500); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b29d48206..42e94134b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -28,6 +28,7 @@ #include "../common/misc_functions.h" #include "quest_parser_collection.h" +#include "lua_parser.h" #include "string_ids.h" #include "worldserver.h" @@ -46,7 +47,7 @@ extern WorldServer worldserver; // the spell can still fail here, if the buff can't stack // in this case false will be returned, true otherwise -bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override, int reflect_effectiveness, int32 duration_override, bool disable_buff_overrwrite) +bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override, int reflect_effectiveness, int32 duration_override, bool disable_buff_overwrite) { int caster_level, buffslot, effect, effect_value, i; EQ::ItemInstance *SummonedItem=nullptr; @@ -119,7 +120,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } else { - buffslot = AddBuff(caster, spell_id, duration_override, -1, disable_buff_overrwrite); + buffslot = AddBuff(caster, spell_id, duration_override, -1, disable_buff_overwrite); } if(buffslot == -1) // stacking failure return false; @@ -129,10 +130,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } #ifdef SPELL_EFFECT_SPAM - Message(0, "You are affected by spell '%s' (id %d)", spell.name, spell_id); + Message(Chat::White, "You are affected by spell '%s' (id %d)", spell.name, spell_id); if(buffslot >= 0) { - Message(0, "Buff slot: %d Duration: %d tics", buffslot, buffs[buffslot].ticsremaining); + Message(Chat::White, "Buff slot: %d Duration: %d tics", buffslot, buffs[buffslot].ticsremaining); } #endif @@ -175,7 +176,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove return true; } } else if (IsNPC()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_NPC, CastToNPC(), nullptr, spell_id, export_string, 0) != 0) { + if (parse->EventSpell(EVENT_SPELL_EFFECT_NPC, this, nullptr, spell_id, export_string, 0) != 0) { + CalcBonuses(); + return true; + } + } else if (IsBot()) { + if (parse->EventSpell(EVENT_SPELL_EFFECT_BOT, this, nullptr, spell_id, export_string, 0) != 0) { CalcBonuses(); return true; } @@ -711,14 +717,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove caster->MessageString(Chat::SpellFailure, IMMUNE_STUN); } else { int stun_resist = itembonuses.StunResist+spellbonuses.StunResist; - if (IsClient()) + if (IsClient() || IsBot()) { stun_resist += aabonuses.StunResist; + } if (stun_resist <= 0 || zone->random.Int(0,99) >= stun_resist) { LogCombat("Stunned. We had [{}] percent resist chance", stun_resist); - if (caster && caster->IsClient()) + if (caster && (caster->IsClient() || caster->IsBot())) { effect_value += effect_value*caster->GetFocusEffect(focusFcStunTimeMod, spell_id)/100; + } Stun(effect_value); } else { @@ -801,7 +809,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove buffs[buffslot].ticsremaining = resistMod * buffs[buffslot].ticsremaining / 100; } - if(IsClient()) + if (IsClient() || IsBot()) { if(buffs[buffslot].ticsremaining > RuleI(Character, MaxCharmDurationForPlayerCharacter)) buffs[buffslot].ticsremaining = RuleI(Character, MaxCharmDurationForPlayerCharacter); @@ -859,21 +867,22 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Fear: %+i", effect_value); #endif - if(IsClient()) + if (IsClient() || IsBot()) { - if(buffs[buffslot].ticsremaining > RuleI(Character, MaxFearDurationForPlayerCharacter)) + if (buffs[buffslot].ticsremaining > RuleI(Character, MaxFearDurationForPlayerCharacter)) { buffs[buffslot].ticsremaining = RuleI(Character, MaxFearDurationForPlayerCharacter); + } } - if(RuleB(Combat, EnableFearPathing)){ - if(IsClient()) + if (RuleB(Combat, EnableFearPathing)) { + if (IsClient()) { CastToClient()->AI_Start(); } CalculateNewFearpoint(); - if(currently_fleeing) + if (currently_fleeing) { break; } @@ -1624,7 +1633,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (IsCorpse() && CastToCorpse()->IsPlayerCorpse()) { if(caster) - LogSpells(" corpse being rezzed using spell [{}] by [{}]", + LogSpells("corpse being rezzed using spell [{}] by [{}]", spell_id, caster->GetName()); CastToCorpse()->CastRezz(spell_id, caster); @@ -2110,7 +2119,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Stop Rain"); #endif - zone->zone_weather = 0; + zone->zone_weather = EQ::constants::WeatherTypes::None; zone->weather_intensity = 0; zone->weatherSend(); break; @@ -2130,20 +2139,30 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_SummonPC: { - if (!caster) + if (!caster) { break; + } + if (IsClient()) { + if (caster->IsClient()) { + if (!entity_list.IsInSameGroupOrRaidGroup(caster->CastToClient(), CastToClient())) { + caster->MessageString(Chat::SpellFailure, TARGET_GROUP_MEMBER); + break; + } + + // clear aggro when summoned in zone and further than aggro clear distance rule. + if (RuleR(Spells, CallOfTheHeroAggroClearDist) == 0 || caster->CalculateDistance(GetX(), GetY(), GetZ()) >= RuleR(Spells, CallOfTheHeroAggroClearDist)) { + entity_list.ClearAggro(this); + } + } + CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), caster->GetX(), caster->GetY(), caster->GetZ(), caster->GetHeading(), 2, SummonPC); - Message(Chat::Yellow, "You have been summoned!"); - // only for beneficial spells like Call of the Hero - // This clear probably isn't actually needed, but need to investigate more - if (IsBeneficialSpell(spell_id)) - entity_list.ClearAggro(this); - } else + MessageString(Chat::Spells, PLAYER_SUMMONED); + } else { caster->Message(Chat::Red, "This spell can only be cast on players."); - + } break; } @@ -2848,7 +2867,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Instant_Mana_Pct: { effect_value = spells[spell_id].base_value[i]; - int64 amt = abs(GetMaxMana() * effect_value / 10000); + int64 amt = std::abs(GetMaxMana() * effect_value / 10000); if (spells[spell_id].max_value[i] && amt > spells[spell_id].max_value[i]) amt = spells[spell_id].max_value[i]; @@ -2864,7 +2883,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Instant_Endurance_Pct: { effect_value = spells[spell_id].base_value[i]; if (IsClient()) { - int32 amt = abs(CastToClient()->GetMaxEndurance() * effect_value / 10000); + int32 amt = std::abs(CastToClient()->GetMaxEndurance() * effect_value / 10000); if (spells[spell_id].max_value[i] && amt > spells[spell_id].max_value[i]) amt = spells[spell_id].max_value[i]; @@ -2883,7 +2902,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove */ case SE_Health_Transfer: { effect_value = spells[spell_id].limit_value[i]; - int64 amt = abs(caster->GetMaxHP() * effect_value / 1000); + int64 amt = std::abs(caster->GetMaxHP() * effect_value / 1000); if (effect_value < 0) { Damage(caster, amt, spell_id, spell.skill, false, buffslot, false); @@ -3055,6 +3074,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_ResistCold: case SE_ResistFire: case SE_AllStats: + case SE_MakeDrunk: case SE_CHA: case SE_WIS: case SE_INT: @@ -3300,12 +3320,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Unknown Effect ID %d", effect); #else - Message(0, "Unknown spell effect %d in spell %s (id %d)", effect, spell.name, spell_id); + Message(Chat::White, "Unknown spell effect %d in spell %s (id %d)", effect, spell.name, spell_id); #endif } } #ifdef SPELL_EFFECT_SPAM - Message(0, ". . . Effect #%i: %s", i + 1, (effect_desc && effect_desc[0]) ? effect_desc : "Unknown"); + Message(Chat::White, ". . . Effect #%i: %s", i + 1, (effect_desc && effect_desc[0]) ? effect_desc : "Unknown"); #endif } @@ -3392,8 +3412,18 @@ int64 Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level } // generic formula calculations -int64 Mob::CalcSpellEffectValue_formula(int64 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining) +int64 Mob::CalcSpellEffectValue_formula(uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining) { +#ifdef LUA_EQEMU + int64 lua_ret = 0; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->CalcSpellEffectValue_formula(this, formula, base_value, max_value, caster_level, spell_id, ticsremaining, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + /* i need those formulas checked!!!! @@ -3445,7 +3475,7 @@ snare has both of them negative, yet their range should work the same: updownsign = 1; } - LogSpells("CSEV: spell [{}], formula [{}], base [{}], max [{}], lvl [{}]. Up/Down [{}]", + LogSpells("spell [{}] formula [{}] base [{}] max [{}] lvl [{}] Up/Down [{}]", spell_id, formula, base_value, max_value, caster_level, updownsign); switch(formula) @@ -3693,7 +3723,7 @@ snare has both of them negative, yet their range should work the same: if (base_value < 0 && result > 0) result *= -1; - LogSpells("Result: [{}] (orig [{}]), cap [{}] [{}]", result, oresult, max_value, (base_value < 0 && result > 0)?"Inverted due to negative base":""); + LogSpells("Result: [{}] (orig [{}]) cap [{}] [{}]", result, oresult, max_value, (base_value < 0 && result > 0)?"Inverted due to negative base":""); return result; } @@ -3772,7 +3802,11 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) return; } } else if (IsNPC()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_NPC, CastToNPC(), nullptr, buff.spellid, export_string, 0) != 0) { + if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_NPC, this, nullptr, buff.spellid, export_string, 0) != 0) { + return; + } + } else if (IsBot()) { + if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_BOT, this, nullptr, buff.spellid, export_string, 0) != 0) { return; } } @@ -4028,7 +4062,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) case SE_Duration_HP_Pct: { effect_value = spells[buff.spellid].base_value[i]; - int64 amt = abs(GetMaxHP() * effect_value / 100); + int64 amt = std::abs(GetMaxHP() * effect_value / 100); if (spells[buff.spellid].max_value[i] && amt > spells[buff.spellid].max_value[i]) amt = spells[buff.spellid].max_value[i]; @@ -4043,7 +4077,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) case SE_Duration_Mana_Pct: { effect_value = spells[buff.spellid].base_value[i]; - int32 amt = abs(GetMaxMana() * effect_value / 100); + int32 amt = std::abs(GetMaxMana() * effect_value / 100); if (spells[buff.spellid].max_value[i] && amt > spells[buff.spellid].max_value[i]) amt = spells[buff.spellid].max_value[i]; @@ -4061,7 +4095,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) effect_value = spells[buff.spellid].base_value[i]; if (IsClient()) { - int32 amt = abs(CastToClient()->GetMaxEndurance() * effect_value / 100); + int32 amt = std::abs(CastToClient()->GetMaxEndurance() * effect_value / 100); if (spells[buff.spellid].max_value[i] && amt > spells[buff.spellid].max_value[i]) amt = spells[buff.spellid].max_value[i]; @@ -4119,7 +4153,11 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) return; } } else if (IsNPC()) { - if (parse->EventSpell(EVENT_SPELL_FADE, CastToNPC(), nullptr, buffs[slot].spellid, export_string, 0) != 0) { + if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { + return; + } + } else if (IsBot()) { + if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { return; } } @@ -4501,9 +4539,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) } if((IsClient() && !CastToClient()->GetPVP()) || (IsPet() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || -#ifdef BOTS (IsBot() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || -#endif (IsMerc() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP())) { EQApplicationPacket *outapp = MakeBuffsPacket(); @@ -4534,7 +4570,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) CalcBonuses(); } -int64 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) +int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) { const SPDat_Spell_Struct &spell = spells[spell_id]; @@ -5460,7 +5496,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; default: - LogInfo("CalcFocusEffect: unknown limit spelltype [{}]", focus_spell.base_value[i]); + LogInfo("unknown limit spelltype [{}]", focus_spell.base_value[i]); break; } break; @@ -6037,7 +6073,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo // this spits up a lot of garbage when calculating spell focuses // since they have all kinds of extra effects on them. default: - LogInfo("CalcFocusEffect: unknown effectid [{}]", + LogInfo("unknown effectid [{}]", focus_spell.effect_id[i]); #endif } @@ -6318,7 +6354,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { return 0; } -int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool from_buff_tic) +int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool from_buff_tic) { if (IsBardSong(spell_id) && type != focusFcBaseEffects && type != focusSpellDuration && type != focusReduceRecastTime) { return 0; @@ -6336,8 +6372,8 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool rand_effectiveness = true; } - //Check if item focus effect exists for the client. - if (itembonuses.FocusEffects[type]){ + //Check if item focus effect exists for the mob. + if (itembonuses.FocusEffects[type]) { const EQ::ItemData* TempItem = nullptr; const EQ::ItemData* UsedItem = nullptr; @@ -6347,12 +6383,13 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool int32 focus_max_real = 0; //item focus - for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++) - { + for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++) { TempItem = nullptr; EQ::ItemInstance* ins = GetInv().GetItem(x); - if (!ins) + if (!ins) { continue; + } + TempItem = ins->GetItem(); if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { @@ -6381,12 +6418,10 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool } } - for (int y = EQ::invaug::SOCKET_BEGIN; y <= EQ::invaug::SOCKET_END; ++y) - { + for (int y = EQ::invaug::SOCKET_BEGIN; y <= EQ::invaug::SOCKET_END; ++y) { EQ::ItemInstance *aug = nullptr; aug = ins->GetAugment(y); - if(aug) - { + if (aug) { const EQ::ItemData* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { @@ -6418,45 +6453,49 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool } } - //Tribute Focus - for (int x = EQ::invslot::TRIBUTE_BEGIN; x <= EQ::invslot::TRIBUTE_END; ++x) - { - TempItem = nullptr; - EQ::ItemInstance* ins = GetInv().GetItem(x); - if (!ins) - continue; - TempItem = ins->GetItem(); - if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { - if(rand_effectiveness) { - focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true); - if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } else if (focus_max < 0 && focus_max < focus_max_real) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } + if (IsClient()) { + //Client Tribute Focus + for (int x = EQ::invslot::TRIBUTE_BEGIN; x <= EQ::invslot::TRIBUTE_END; ++x) { + TempItem = nullptr; + EQ::ItemInstance* ins = GetInv().GetItem(x); + if (!ins) { + continue; } - else { - Total = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id); - if (Total > 0 && realTotal >= 0 && Total > realTotal) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; + + TempItem = ins->GetItem(); + if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { + if (rand_effectiveness) { + focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true); + if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { + focus_max_real = focus_max; + UsedItem = TempItem; + UsedFocusID = TempItem->Focus.Effect; + } else if (focus_max < 0 && focus_max < focus_max_real) { + focus_max_real = focus_max; + UsedItem = TempItem; + UsedFocusID = TempItem->Focus.Effect; + } } - else if (Total < 0 && Total < realTotal) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; + else { + Total = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id); + if (Total > 0 && realTotal >= 0 && Total > realTotal) { + realTotal = Total; + UsedItem = TempItem; + UsedFocusID = TempItem->Focus.Effect; + } + else if (Total < 0 && Total < realTotal) { + realTotal = Total; + UsedItem = TempItem; + UsedFocusID = TempItem->Focus.Effect; + } } } } } - if(UsedItem && rand_effectiveness && focus_max_real != 0) + if (UsedItem && rand_effectiveness && focus_max_real != 0) { realTotal = CalcFocusEffect(type, UsedFocusID, spell_id); + } if ((rand_effectiveness && UsedItem) || (realTotal != 0 && UsedItem)) { // there are a crap ton more of these, I was able to verify these ones though @@ -6497,12 +6536,12 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool default: break; } - MessageString(Chat::Spells, string_id, UsedItem->Name); + MessageString(Chat::FocusEffect, string_id, UsedItem->Name); } } - //Check if spell focus effect exists for the client. - if (spellbonuses.FocusEffects[type]){ + //Check if spell focus effect exists for the mob. + if (spellbonuses.FocusEffects[type]) { //Spell Focus int32 Total2 = 0; @@ -6516,10 +6555,11 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool int buff_max = GetMaxTotalSlots(); for (buff_slot = 0; buff_slot < buff_max; buff_slot++) { focusspellid = buffs[buff_slot].spellid; - if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS) + if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS) { continue; + } - if(rand_effectiveness) { + if (rand_effectiveness) { focus_max2 = CalcFocusEffect(type, focusspellid, spell_id, true, buffs[buff_slot].casterid, caster); if (focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) { focus_max_real2 = focus_max2; @@ -6550,16 +6590,17 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool original_caster_id = buffs[buff_tracker].casterid; } - if(focusspell_tracker && rand_effectiveness && focus_max_real2 != 0) + if (focusspell_tracker && rand_effectiveness && focus_max_real2 != 0) { realTotal2 = CalcFocusEffect(type, focusspell_tracker, spell_id, false, original_caster_id, caster); + } - if(!from_buff_tic && buff_tracker >= 0 && buffs[buff_tracker].hit_number > 0) { + if (!from_buff_tic && buff_tracker >= 0 && buffs[buff_tracker].hit_number > 0) { CheckNumHitsRemaining(NumHit::MatchingSpells, buff_tracker); } } // AA Focus - if (aabonuses.FocusEffects[type]){ + if (aabonuses.FocusEffects[type]) { int32 Total3 = 0; @@ -6568,12 +6609,13 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool auto ability = ability_rank.first; auto rank = ability_rank.second; - if(!ability) { + if (!ability) { continue; } - if (rank->effects.empty()) + if (rank->effects.empty()) { continue; + } Total3 = CalcAAFocus(type, *rank, spell_id); if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { @@ -6585,15 +6627,17 @@ int64 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool } } - if(type == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) + if (type == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) { return 0; + } //Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected //by reagent conservation for obvious reasons. //Non-Live like feature to allow for an additive focus bonus to be applied from foci that are placed in worn slot. (No limit checks) int32 worneffect_bonus = 0; - if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) + if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) { worneffect_bonus = itembonuses.FocusEffectsWorn[type]; + } return realTotal + realTotal2 + realTotal3 + worneffect_bonus; } @@ -6744,11 +6788,9 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id) bool bDepleted = false; int buff_max = GetMaxTotalSlots(); -#ifdef BOTS std::string buff_name; size_t buff_counter = 0; bool buff_update = false; -#endif //Spell specific procs [Type 7,10,11] if (IsValidSpell(spell_id)) { @@ -6756,11 +6798,9 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id) if (buffs[d].spellid == spell_id && buffs[d].hit_number > 0 && spells[buffs[d].spellid].hit_number_type == static_cast(type)) { -#ifdef BOTS buff_name = spells[buffs[d].spellid].name; buff_counter = (buffs[d].hit_number - 1); buff_update = true; -#endif if (--buffs[d].hit_number == 0) { CastOnNumHitFade(buffs[d].spellid); @@ -6774,12 +6814,9 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id) } else if (type == NumHit::MatchingSpells) { if (buff_slot >= 0) { if (--buffs[buff_slot].hit_number == 0) { - -#ifdef BOTS buff_name = spells[buffs[buff_slot].spellid].name; buff_counter = (buffs[buff_slot].hit_number - 1); buff_update = true; -#endif CastOnNumHitFade(buffs[buff_slot].spellid); if (!TryFadeEffect(buff_slot)) @@ -6794,11 +6831,9 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id) if (IsValidSpell(buffs[d].spellid) && buffs[d].hit_number > 0 && spells[buffs[d].spellid].hit_number_type == static_cast(type)) { -#ifdef BOTS buff_name = spells[buffs[d].spellid].name; buff_counter = (buffs[d].hit_number - 1); buff_update = true; -#endif if (--buffs[d].hit_number == 0) { CastOnNumHitFade(buffs[d].spellid); @@ -6811,7 +6846,6 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id) } } -#ifdef BOTS if (IsBot() && buff_update) { auto bot_owner = entity_list.GetBotOwnerByBotEntityID(GetID()); if (bot_owner && bot_owner->GetBotOption(Client::booBuffCounter)) { @@ -6831,7 +6865,6 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id) ); } } -#endif } //for some stupid reason SK procs return theirs one base off... @@ -6943,7 +6976,7 @@ bool Mob::TryDeathSave() { HealAmt = GetMaxHP() - GetHP(); SetHP((GetHP()+HealAmt)); - Message(263, "The gods have healed you for %i points of damage.", HealAmt); + Message(Chat::Emote, "The gods have healed you for %i points of damage.", HealAmt); if(spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE] == 2) entity_list.MessageCloseString( @@ -6982,7 +7015,7 @@ bool Mob::TryDeathSave() { HealAmt = GetMaxHP() - GetHP(); SetHP((GetHP()+HealAmt)); - Message(263, "The gods have healed you for %i points of damage.", HealAmt); + Message(Chat::Emote, "The gods have healed you for %i points of damage.", HealAmt); if(spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE] == 2) entity_list.MessageCloseString( @@ -7067,7 +7100,7 @@ uint16 Mob::GetSympatheticSpellProcID(uint16 spell_id) return 0; } -bool Mob::DoHPToManaCovert(uint16 mana_cost) +bool Mob::DoHPToManaCovert(int32 mana_cost) { if (spellbonuses.HPToManaConvert){ int64 hp_cost = spellbonuses.HPToManaConvert * mana_cost / 100; @@ -7282,8 +7315,9 @@ bool Mob::PassCastRestriction(int value) break; case IS_NOT_ON_HORSE: - if (IsClient() && !CastToClient()->GetHorseId()) + if ((IsClient() && !CastToClient()->GetHorseId()) || IsBot() || IsMerc()) { return true; + } break; case IS_ANIMAL_OR_HUMANOID: @@ -7625,10 +7659,10 @@ bool Mob::PassCastRestriction(int value) } case IS_CLASS_CHAIN_OR_PLATE: - if (IsClient() && - ((GetClass() == WARRIOR) || (GetClass() == BARD) || (GetClass() == SHADOWKNIGHT) || (GetClass() == PALADIN) || (GetClass() == CLERIC) - || (GetClass() == RANGER) || (GetClass() == SHAMAN) || (GetClass() == ROGUE) || (GetClass() == BERSERKER))) + if ((GetClass() == WARRIOR) || (GetClass() == BARD) || (GetClass() == SHADOWKNIGHT) || (GetClass() == PALADIN) || (GetClass() == CLERIC) + || (GetClass() == RANGER) || (GetClass() == SHAMAN) || (GetClass() == ROGUE) || (GetClass() == BERSERKER)) { return true; + } break; case IS_HP_BETWEEN_5_AND_9_PCT: @@ -8056,7 +8090,18 @@ bool Mob::PassCastRestriction(int value) } break; } - + case IS_END_OR_MANA_BELOW_10_PCT: { + if (IsNonSpellFighterClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 10) { + return true; + } + else if (!IsNonSpellFighterClass(GetClass()) && GetManaRatio() <= 10) { + return true; + } + else if (IsHybridClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 10) { + return true; + } + break; + } case IS_END_OR_MANA_BELOW_30_PCT: case IS_END_OR_MANA_BELOW_30_PCT2: { if (IsNonSpellFighterClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 30) { @@ -10214,8 +10259,17 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in } if (buffslot != -1) { - if (caster == this && spell_id != SPELL_MINOR_ILLUSION && spell_id != SPELL_ILLUSION_TREE && - (spellbonuses.IllusionPersistence || aabonuses.IllusionPersistence || itembonuses.IllusionPersistence)) { + if ( + caster == this && + spell_id != SPELL_MINOR_ILLUSION && + spell_id != SPELL_ILLUSION_TREE && + ( + spellbonuses.IllusionPersistence || + aabonuses.IllusionPersistence || + itembonuses.IllusionPersistence || + RuleB(Spells, IllusionsAlwaysPersist) + ) + ) { buffs[buffslot].persistant_buff = 1; } else { @@ -10225,16 +10279,25 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in } bool Mob::HasPersistDeathIllusion(int32 spell_id) { - - if (spellbonuses.IllusionPersistence > 1 || aabonuses.IllusionPersistence > 1 || itembonuses.IllusionPersistence > 1) { - if (spell_id != SPELL_MINOR_ILLUSION && spell_id != SPELL_ILLUSION_TREE && IsEffectInSpell(spell_id, SE_Illusion) && IsBeneficialSpell(spell_id)) { + if ( + spellbonuses.IllusionPersistence > 1 || + aabonuses.IllusionPersistence > 1 || + itembonuses.IllusionPersistence > 1 || + RuleB(Spells, IllusionsAlwaysPersist) + ) { + if ( + spell_id != SPELL_MINOR_ILLUSION && + spell_id != SPELL_ILLUSION_TREE && + IsEffectInSpell(spell_id, SE_Illusion) && + IsBeneficialSpell(spell_id) + ) { return true; } } return false; } -void Mob::SetBuffDuration(int32 spell_id, int32 duration) { +void Mob::SetBuffDuration(int spell_id, int duration) { /* Will refresh the buff with specified spell_id to the specified duration @@ -10273,7 +10336,7 @@ void Mob::SetBuffDuration(int32 spell_id, int32 duration) { } } -void Mob::ApplySpellBuff(int32 spell_id, int32 duration) +void Mob::ApplySpellBuff(int spell_id, int duration) { /* Used for quest command to apply a new buff with custom duration. @@ -10282,11 +10345,12 @@ void Mob::ApplySpellBuff(int32 spell_id, int32 duration) if (!IsValidSpell(spell_id)) { return; } + if (!spells[spell_id].buff_duration) { return; } - if (duration < -1) { + if (duration <= -1) { duration = PERMANENT_BUFF_DURATION; } @@ -10303,7 +10367,7 @@ int Mob::GetBuffStatValueBySpell(int32 spell_id, const char* stat_identifier) return 0; } - std::string id = str_tolower(stat_identifier); + std::string id = Strings::ToLower(stat_identifier); int buff_count = GetMaxTotalSlots(); for (int slot = 0; slot < buff_count; slot++) { @@ -10324,7 +10388,7 @@ int Mob::GetBuffStatValueBySlot(uint8 slot, const char* stat_identifier) return 0; } - std::string id = str_tolower(stat_identifier); + std::string id = Strings::ToLower(stat_identifier); if (id == "caster_level") { return buffs[slot].casterlevel; } else if (id == "spell_id") { return buffs[slot].spellid; } diff --git a/zone/spells.cpp b/zone/spells.cpp index d46ae3528..c15d48491 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -74,10 +74,11 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/data_verification.h" #include "../common/misc_functions.h" +#include "data_bucket.h" #include "quest_parser_collection.h" #include "string_ids.h" #include "worldserver.h" @@ -96,9 +97,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/packet_dump_file.h" #endif -#ifdef BOTS #include "bot.h" -#endif #include "mob_movement_manager.h" #include "client.h" @@ -181,7 +180,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } //Goal of Spells:UseSpellImpliedTargeting is to replicate the EQ2 feature where spells will 'pass through' invalid targets to target's target to try to find a valid target. - if (RuleB(Spells,UseSpellImpliedTargeting) && IsClient()) { + if (RuleB(Spells,UseSpellImpliedTargeting) && IsClient()) { Mob* spell_target = entity_list.GetMobID(target_id); if (spell_target) { Mob* targets_target = spell_target->GetTarget(); @@ -201,7 +200,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } } } - } + } if (!DoCastingChecksOnCaster(spell_id, slot) || !DoCastingChecksZoneRestrictions(true, spell_id) || @@ -244,17 +243,19 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, GetID(), GetCasterLevel(spell_id) ); - if(IsClient()) { + if (IsClient()) { if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0) != 0) { if (IsDiscipline(spell_id)) { CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0); } else { CastToClient()->SendSpellBarEnable(spell_id); } - return(false); + return false; } - } else if(IsNPC()) { + } else if (IsNPC()) { parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0); + } else if (IsBot()) { + parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0); } //To prevent NPC ghosting when spells are cast from scripts @@ -301,8 +302,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, casting_spell_id = spell_id; casting_spell_slot = slot; casting_spell_inventory_slot = item_slot; - if(casting_spell_timer != 0xFFFFFFFF) - { + if (casting_spell_timer != 0xFFFFFFFF) { casting_spell_timer = timer; casting_spell_timer_duration = timer_duration; } @@ -333,6 +333,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, Chat::SpellFailure, (IsClient() ? FilterPCSpells : FilterNPCSpells), (fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER), + 0, /* MessageFormat: You miss a note, bringing your song to a close! (if missed note) MessageFormat: A missed note brings %1's song to a close! @@ -351,13 +352,16 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, // if this spell doesn't require a target, or if it's an optional target // and a target wasn't provided, then it's us; unless TGB is on and this // is a TGB compatible spell. - if((IsGroupSpell(spell_id) || - spell.target_type == ST_AEClientV1 || - spell.target_type == ST_Self || - spell.target_type == ST_AECaster || - spell.target_type == ST_Ring || - spell.target_type == ST_Beam) && target_id == 0) - { + if ( + ( + IsGroupSpell(spell_id) || + spell.target_type == ST_AEClientV1 || + spell.target_type == ST_Self || + spell.target_type == ST_AECaster || + spell.target_type == ST_Ring || + spell.target_type == ST_Beam + ) && target_id == 0 + ) { LogSpells("Spell [{}] auto-targeted the caster. Group? [{}], target type [{}]", spell_id, IsGroupSpell(spell_id), spell.target_type); target_id = GetID(); } @@ -376,8 +380,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, if (cast_time) { cast_time = GetActSpellCasttime(spell_id, cast_time); } - } - else { + } else { orgcasttime = cast_time; } @@ -407,23 +410,21 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, // If you're at full mana, let it cast even if you dont have enough mana // we calculated this above, now enforce it - if(mana_cost > 0 && slot != CastingSlot::Item) { + if (mana_cost > 0 && slot != CastingSlot::Item) { int my_curmana = GetMana(); int my_maxmana = GetMaxMana(); - if(my_curmana < mana_cost) {// not enough mana + if (my_curmana < mana_cost) {// not enough mana //this is a special case for NPCs with no mana... - if(IsNPC() && my_curmana == my_maxmana){ + if (IsNPC() && my_curmana == my_maxmana){ mana_cost = 0; - } - else { + } else { //The client will prevent spell casting if insufficient mana, this is only for serverside enforcement. LogSpells("Spell Error not enough mana spell=[{}] mymana=[{}] cost=[{}]\n", spell_id, my_curmana, mana_cost); - if(IsClient()) { + if (IsClient()) { //clients produce messages... npcs should not for this case MessageString(Chat::Red, INSUFFICIENT_MANA); InterruptSpell(); - } - else { + } else { InterruptSpell(0, 0, 0); //the 0 args should cause no messages } ZeroCastingVars(); @@ -462,22 +463,24 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, // ok we know it has a cast time so we can start the timer now spellend_timer.Start(cast_time); - if (IsAIControlled()) - { + if (IsAIControlled()) { SetRunAnimSpeed(0); pMob = entity_list.GetMob(target_id); - if (pMob && this != pMob) + if (pMob && this != pMob) { FaceTarget(pMob); + } } // if we got here we didn't fizzle, and are starting our cast - if (oSpellWillFinish) + if (oSpellWillFinish) { *oSpellWillFinish = Timer::GetCurrentTime() + cast_time + 100; + } - if (IsClient() && slot == CastingSlot::Item && item_slot != 0xFFFFFFFF) { + if (RuleB(Spells, UseItemCastMessage) && IsClient() && slot == CastingSlot::Item && item_slot != 0xFFFFFFFF) { auto item = CastToClient()->GetInv().GetItem(item_slot); - if (item && item->GetItem()) - MessageString(Chat::Spells, BEGINS_TO_GLOW, item->GetItem()->Name); + if (item && item->GetItem()) { + MessageString(Chat::FocusEffect, BEGINS_TO_GLOW, item->GetItem()->Name); + } } return(true); @@ -727,13 +730,8 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp */ bool ignore_on_casting = false; - bool ignore_if_npc_or_gm = false; - if (!IsClient() || (IsClient() && CastToClient()->GetGM())) { - ignore_if_npc_or_gm = true; - } - - if (check_on_casting){ + if (check_on_casting) { if (spells[spell_id].target_type == ST_AEClientV1 || spells[spell_id].target_type == ST_AECaster || spells[spell_id].target_type == ST_Ring || @@ -797,15 +795,9 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp /* Prevent buffs from being cast on targets who don't meet level restriction */ - if (!ignore_if_npc_or_gm && RuleB(Spells, BuffLevelRestrictions)) { - // casting_spell_targetid is guaranteed to be what we went, check for ST_Self for now should work though - if (spells[spell_id].target_type != ST_Self && !spell_target->CheckSpellLevelRestriction(spell_id)) { - LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id); - if (!IsBardSong(spell_id)) { - MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL); - } - return false; - } + + if (!spell_target->CheckSpellLevelRestriction(this, spell_id)) { + return false; } /* Prevents buff from being cast based on tareget ing PC OR NPC (1 = PCs, 2 = NPCs) @@ -1155,6 +1147,9 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) } } + LogSpells("Interrupt: casting_spell_id [{}] casting_spell_slot [{}]", + casting_spell_id, (int) casting_spell_slot); + if(casting_spell_id && IsNPC()) { CastToNPC()->AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); } @@ -1269,8 +1264,9 @@ void Mob::StopCastSpell(int32 spell_id, bool send_spellbar_enable) -AA that fail at CastSpell because they never get timer set. -Instant cast items that fail at CastSpell because they never get timer set. */ - if (casting_spell_id && IsNPC()) { - CastToNPC()->AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); + // Often called before spell_id and slot are set. For NPCs always update AI + if (IsNPC()) { + CastToNPC()->AI_Event_SpellCastFinished(false, 1); } if (send_spellbar_enable) { @@ -1285,7 +1281,7 @@ void Mob::StopCastSpell(int32 spell_id, bool send_spellbar_enable) // just check timed spell specific things before passing off to SpellFinished // which figures out proper targets etc void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slot, - uint16 mana_used, uint32 inventory_slot, int16 resist_adjust) + int32 mana_used, uint32 inventory_slot, int16 resist_adjust) { if (!IsValidSpell(spell_id)) { @@ -1354,7 +1350,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo { if (IsBardSong(spell_id) && slot < CastingSlot::MaxGems) { if (spells[spell_id].buff_duration == 0xFFFF) { - LogSpells("Bard song [{}] not applying bard logic because duration. dur=[{}], recast=[{}]", spells[spell_id].buff_duration); + LogSpells("Bard song [{}] not applying bard logic because duration. dur=[{}], recast=[{}]", spell_id, spells[spell_id].buff_duration, spells[spell_id].recast_time); } else { if (IsPulsingBardSong(spell_id)) { @@ -1409,7 +1405,6 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo channelchance -= attacked_count * 2; channelchance += channelchance * channelbonuses / 100.0f; } -#ifdef BOTS else if(IsBot()) { float channelbonuses = 0.0f; @@ -1423,7 +1418,6 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo channelchance -= attacked_count * 2; channelchance += channelchance * channelbonuses / 100.0f; } -#endif //BOTS else { // NPCs are just hard to interrupt, otherwise they get pwned channelchance = 85; @@ -1663,10 +1657,12 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo GetID(), GetCasterLevel(spell_id) ); - if(IsClient()) { + if (IsClient()) { parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0); - } else if(IsNPC()) { + } else if (IsNPC()) { parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0); + } else if (IsBot()) { + parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0); } if(bard_song_mode) @@ -2099,7 +2095,6 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } } } -#ifdef BOTS else if(IsBot()) { if(IsGrouped()) @@ -2112,7 +2107,6 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce group_id_caster = (GetRaid()->GetGroup(GetOwner()->CastToClient()) == 0xFFFF) ? 0 : (GetRaid()->GetGroup(GetOwner()->CastToClient()) + 1); } } -#endif //BOTS if(spell_target->IsClient()) { @@ -2147,7 +2141,6 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } } } -#ifdef BOTS else if(spell_target->IsBot()) { if(spell_target->IsGrouped()) @@ -2160,7 +2153,6 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce group_id_target = (spell_target->GetRaid()->GetGroup(spell_target->GetOwner()->CastToClient()) == 0xFFFF) ? 0 : (spell_target->GetRaid()->GetGroup(spell_target->GetOwner()->CastToClient()) + 1); } } -#endif //BOTS if(group_id_caster == 0 || group_id_target == 0) { @@ -2195,11 +2187,14 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce case ST_TargetsTarget: { Mob *spell_target_tot = spell_target ? spell_target->GetTarget() : nullptr; - if(!spell_target_tot) + if (!spell_target_tot) { return false; + } + //Verfied from live - Target's Target needs to be in combat range to recieve the effect - if (!CombatRange(spell_target)) + if (RuleB(Spells, TargetsTargetRequiresCombatRange) && !CombatRange(spell_target)) { return false; + } spell_target = spell_target_tot; CastAction = SingleTarget; @@ -2254,7 +2249,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce // only used from CastedSpellFinished, and procs // we can't interrupt in this, or anything called from this! // if you need to abort the casting, return false -bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, uint16 mana_used, +bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, int32 mana_used, uint32 inventory_slot, int16 resist_adjust, bool isproc, int level_override, uint32 timer, uint32 timer_duration, bool from_casted_spell, uint32 aa_id) { @@ -2264,7 +2259,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui return false; //Death Touch targets the pet owner instead of the pet when said pet is tanking. - if ((RuleB(Spells, CazicTouchTargetsPetOwner) && spell_target && spell_target->HasOwner()) && spell_id == SPELL_CAZIC_TOUCH || spell_id == SPELL_TOUCH_OF_VINITRAS) { + if ((RuleB(Spells, CazicTouchTargetsPetOwner) && spell_target && spell_target->HasOwner()) && (spell_id == SPELL_CAZIC_TOUCH || spell_id == SPELL_TOUCH_OF_VINITRAS)) { Mob* owner = spell_target->GetOwner(); if (owner) { @@ -2272,12 +2267,15 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui } } - //Guard Assist Code + //Guard Assist Code if (RuleB(Character, PVPEnableGuardFactionAssist) && spell_target && IsDetrimentalSpell(spell_id) && spell_target != this) { if (IsClient() && spell_target->IsClient()|| (HasOwner() && GetOwner()->IsClient() && spell_target->IsClient())) { auto& mob_list = entity_list.GetCloseMobList(spell_target); for (auto& e : mob_list) { auto mob = e.second; + if (!mob) { + continue; + } if (mob->IsNPC() && mob->CastToNPC()->IsGuard()) { float distance = Distance(spell_target->GetPosition(), mob->GetPosition()); if ((mob->CheckLosFN(spell_target) || mob->CheckLosFN(this)) && distance <= 70) { @@ -2291,8 +2289,15 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui } } + //determine the type of spell target we have + CastAction_type CastAction; + if (!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction, slot, isproc)) { + LogSpells("Spell [{}]: Determine spell targets failure.", spell_id); + return(false); + } + //If spell was casted then we already checked these so skip, otherwise check here if being called directly from spell finished. - if (!from_casted_spell){ + if (!from_casted_spell) { if (!DoCastingChecksZoneRestrictions(true, spell_id)) { LogSpells("Spell [{}]: Zone restriction failure.", spell_id); return false; @@ -2303,13 +2308,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui } } - //determine the type of spell target we have - CastAction_type CastAction; - if (!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction, slot, isproc)) { - LogSpells("Spell [{}]: Determine spell targets failure.", spell_id); - return(false); - } - LogSpells("Spell [{}]: target type [{}], target [{}], AE center [{}]", spell_id, CastAction, spell_target?spell_target->GetName():"NONE", ae_center?ae_center->GetName():"NONE"); // if a spell has the AEDuration flag, it becomes an AE on target @@ -2419,7 +2417,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui case SingleTarget: { -#ifdef BOTS if(IsBot()) { bool StopLogic = false; if(!CastToBot()->DoFinishedSpellSingleTarget(spell_id, spell_target, slot, StopLogic)) @@ -2427,7 +2424,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui if(StopLogic) break; } -#endif //BOTS if(spell_target == nullptr) { LogSpells("Spell [{}]: Targeted spell, but we have no target", spell_id); @@ -2488,7 +2484,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui case GroupSpell: { -#ifdef BOTS if(IsBot()) { bool StopLogic = false; if(!CastToBot()->DoFinishedSpellGroupTarget(spell_id, spell_target, slot, StopLogic)) @@ -2496,7 +2491,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui if(StopLogic) break; } -#endif //BOTS // We hold off turning MBG off so we can still use it to calc the mana cost if(spells[spell_id].can_mgb && HasMGB()) @@ -2582,8 +2576,8 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui case Beam: { BeamDirectional(spell_id, resist_adjust); - break; - } + break; + } case TargetRing: { @@ -2800,9 +2794,18 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste castlevel = caster_level_override; int res = CalcBuffDuration_formula(castlevel, formula, duration); - if (caster == target && (target->aabonuses.IllusionPersistence || target->spellbonuses.IllusionPersistence || - target->itembonuses.IllusionPersistence) && - spell_id != SPELL_MINOR_ILLUSION && spell_id != SPELL_ILLUSION_TREE && IsEffectInSpell(spell_id, SE_Illusion)) { + if ( + caster == target && + ( + target->aabonuses.IllusionPersistence || + target->spellbonuses.IllusionPersistence || + target->itembonuses.IllusionPersistence || + RuleB(Spells, IllusionsAlwaysPersist) + ) && + spell_id != SPELL_MINOR_ILLUSION && + spell_id != SPELL_ILLUSION_TREE && + IsEffectInSpell(spell_id, SE_Illusion) + ) { res = 10000; // ~16h override } @@ -2867,7 +2870,7 @@ int CalcBuffDuration_formula(int level, int formula, int duration) temp = 10 * (level + 10); break; case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse - // counters, etc. + // counters, etc. return -1; case 51: // Permanent. Cancelled when out of range of aura. return -4; @@ -2927,7 +2930,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, LogSpells("Spells the same but newer is higher or equal level, overwriting"); return 1; } - } else if (spellid1 == 2751) { + } else if (spellid1 == SPELL_MANA_BURN) { LogSpells("Blocking spell because manaburn does not stack with itself"); return -1; } @@ -3090,7 +3093,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, continue; if (IsBardOnlyStackEffect(effect1) && GetSpellLevel(spellid1, BARD) != 255 && - GetSpellLevel(spellid2, BARD) != 255) + GetSpellLevel(spellid2, BARD) != 255) continue; // big ol' list according to the client, wasn't that nice! @@ -3185,29 +3188,60 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // spells 1-50: no restrictons // 51-65: SpellLevel/2+15 // 66+ Group Spells 62, Single Target 61 -bool Mob::CheckSpellLevelRestriction(uint16 spell_id) +bool Mob::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id) { - return true; -} + bool check_for_restrictions = false; + bool can_cast = true; -bool Client::CheckSpellLevelRestriction(uint16 spell_id) -{ - int SpellLevel = GetMinLevel(spell_id); + if (!caster) { + LogSpells("[CheckSpellLevelRestriction] No caster"); + return false; + } - // Only check for beneficial buffs - if (IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { - if (SpellLevel > 65) { - if (IsGroupSpell(spell_id) && GetLevel() < 62) - return false; - else if (GetLevel() < 61) - return false; - } else if (SpellLevel > 50) { // 51-65 - if (GetLevel() < (SpellLevel / 2 + 15)) - return false; + if (caster->IsClient() && caster->CastToClient()->GetGM()) { + LogSpells("[CheckSpellLevelRestriction] GM casting - No restrictions"); + return true; + } + + // NON GM clients might be restricted by rule setting + if (caster->IsClient()) { + if (RuleB(Spells, BuffLevelRestrictions)) { + check_for_restrictions = true; + } + } + // NPCS might be restricted by rule setting + else if (RuleB(Spells, NPCBuffLevelRestrictions)) { + check_for_restrictions = true; + } + + if (check_for_restrictions) { + int spell_level = GetMinLevel(spell_id); + + // Only check for beneficial buffs + if (IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { + if (spell_level > 65) { + if (IsGroupSpell(spell_id) && GetLevel() < 62) { + can_cast = false; + } + else if (GetLevel() < 61) { + can_cast = false; + } + } else if (spell_level > 50) { // 51-65 + if (GetLevel() < (spell_level / 2 + 15)) { + can_cast = false; + } + } } } - return true; + if (!can_cast) { + LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id); + if (!IsBardSong(spell_id)) { + caster->MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL); + } + } + + return can_cast; } uint32 Mob::GetFirstBuffSlot(bool disc, bool song) @@ -3248,7 +3282,7 @@ bool Mob::HasDiscBuff() // stacking problems, and -2 if this is not a buff // if caster is null, the buff will be added with the caster level being // the level of the mob -int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_override, bool disable_buff_overrwrite) +int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_override, bool disable_buff_overwrite) { int buffslot, ret, caster_level, emptyslot = -1; bool will_overwrite = false; @@ -3344,7 +3378,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid // at this point we know that this buff will stick, but we have // to remove some other buffs already worn if will_overwrite is true - if (will_overwrite && !disable_buff_overrwrite) { + if (will_overwrite && !disable_buff_overwrite) { std::vector::iterator cur, end; cur = overwrite_slots.begin(); end = overwrite_slots.end(); @@ -3395,9 +3429,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if((IsClient() && !CastToClient()->GetPVP()) || (IsPet() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || -#ifdef BOTS (IsBot() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || -#endif (IsMerc() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP())) { EQApplicationPacket *outapp = MakeBuffsPacket(); @@ -3431,7 +3463,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) { int i, ret, firstfree = -2; - LogAI("Checking if buff [{}] cast at level [{}] can stack on me.[{}]", spellid, caster_level, iFailIfOverwrite?" failing if we would overwrite something":""); + LogAIDetail("Checking if buff [{}] cast at level [{}] can stack on me.[{}]", spellid, caster_level, iFailIfOverwrite?" failing if we would overwrite something":""); int buff_count = GetMaxTotalSlots(); for (i=0; i < buff_count; i++) @@ -3455,7 +3487,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) if(ret == 1) { // should overwrite current slot if(iFailIfOverwrite) { - LogAI("Buff [{}] would overwrite [{}] in slot [{}], reporting stack failure", spellid, curbuf.spellid, i); + LogAIDetail("Buff [{}] would overwrite [{}] in slot [{}], reporting stack failure", spellid, curbuf.spellid, i); return(-1); } if(firstfree == -2) @@ -3463,12 +3495,12 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) } if(ret == -1) { - LogAI("Buff [{}] would conflict with [{}] in slot [{}], reporting stack failure", spellid, curbuf.spellid, i); + LogAIDetail("Buff [{}] would conflict with [{}] in slot [{}], reporting stack failure", spellid, curbuf.spellid, i); return -1; // stop the spell, can't stack it } } - LogAI("Reporting that buff [{}] could successfully be placed into slot [{}]", spellid, firstfree); + LogAIDetail("Reporting that buff [{}] could successfully be placed into slot [{}]", spellid, firstfree); return firstfree; } @@ -3489,14 +3521,21 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) // and if you don't want effects just return false. interrupting here will // break stuff // -bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectiveness, bool use_resist_adjust, int16 resist_adjust, - bool isproc, int level_override, int32 duration_override, bool disable_buff_overrwrite) -{ +bool Mob::SpellOnTarget( + uint16 spell_id, + Mob *spelltar, + int reflect_effectiveness, + bool use_resist_adjust, + int16 resist_adjust, + bool isproc, + int level_override, + int duration_override, + bool disable_buff_overwrite +) { auto spellOwner = GetOwnerOrSelf(); // well we can't cast a spell on target without a target - if(!spelltar) - { + if (!spelltar) { LogSpells("Unable to apply spell [{}] without a target", spell_id); Message(Chat::Red, "SOT: You must have a target for this spell."); return false; @@ -3506,13 +3545,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes return false; } - if (!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) { return false; + } - bool is_damage_or_lifetap_spell = IsDamageSpell(spell_id) || IsLifetapSpell(spell_id); - - if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && !IsEffectInSpell(spell_id, SE_BindSight)) { - if(!IsClient() || !CastToClient()->GetGM()) { + if ( + IsDetrimentalSpell(spell_id) && + !IsAttackAllowed(spelltar, true) && + !IsResurrectionEffects(spell_id) && + !IsEffectInSpell(spell_id, SE_BindSight) + ) { + if (!IsClient() || !CastToClient()->GetGM()) { MessageString(Chat::SpellFailure, SPELL_NO_HOLD); return false; } @@ -3524,12 +3567,28 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes // these target types skip pcnpc only check (according to dev quotes) // other AE spells this is redundant, oh well // 1 = PCs, 2 = NPCs - if (spells[spell_id].pcnpc_only_flag && spells[spell_id].target_type != ST_AETargetHateList && - spells[spell_id].target_type != ST_HateList) { - if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc() && !spelltar->IsBot()) + if ( + spells[spell_id].pcnpc_only_flag && + spells[spell_id].target_type != ST_AETargetHateList && + spells[spell_id].target_type != ST_HateList + ) { + if ( + spells[spell_id].pcnpc_only_flag == 1 && + !spelltar->IsClient() && + !spelltar->IsMerc() && + !spelltar->IsBot() + ) { return false; - else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc() || spelltar->IsBot())) + } else if ( + spells[spell_id].pcnpc_only_flag == 2 && + ( + spelltar->IsClient() || + spelltar->IsMerc() || + spelltar->IsBot() + ) + ) { return false; + } } uint16 caster_level = level_override > 0 ? level_override : GetCasterLevel(spell_id); @@ -3546,12 +3605,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes Action_Struct* action = (Action_Struct*) action_packet->pBuffer; // select source - if(IsClient() && CastToClient()->GMHideMe()) - { + if (IsClient() && CastToClient()->GMHideMe()) { action->source = spelltar->GetID(); - } - else - { + } else { action->source = GetID(); // this is a hack that makes detrimental buffs work client to client // TODO figure out how to do this right @@ -3567,12 +3623,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes } // select target - if (IsEffectInSpell(spell_id, SE_BindSight)) - { + if (IsEffectInSpell(spell_id, SE_BindSight)) { action->target = GetID(); - } - else - { + } else { action->target = spelltar->GetID(); } @@ -3585,10 +3638,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes action->instrument_mod = GetInstrumentMod(spell_id); action->effect_flag = 0; - if(spelltar != this && spelltar->IsClient()) // send to target + if (spelltar != this && spelltar->IsClient()) { // send to target spelltar->CastToClient()->QueuePacket(action_packet); - if(IsClient()) // send to caster + } + + if (IsClient()) { // send to caster CastToClient()->QueuePacket(action_packet); + } // send to people in the area, ignoring caster and target entity_list.QueueCloseClients( @@ -3602,16 +3658,19 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes ); /* Send the EVENT_CAST_ON event */ - std::string export_string = fmt::format( + const auto export_string = fmt::format( "{} {} {}", spell_id, GetID(), caster_level ); + if (spelltar->IsNPC()) { parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0); } else if (spelltar->IsClient()) { parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0); + } else if (spelltar->IsBot()) { + parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0); } mod_spell_cast(spell_id, spelltar, reflect_effectiveness, use_resist_adjust, resist_adjust, isproc); @@ -3625,25 +3684,37 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes if (RuleB(Spells, EnableBlockedBuffs)) { // We return true here since the caster's client should act like normal if (spelltar->IsBlockedBuff(spell_id)) { - LogSpells("Spell [{}] not applied to [{}] as it is a Blocked Buff", - spell_id, spelltar->GetName()); + LogSpells( + "Spell [{}] not applied to [{}] as it is a Blocked Buff", + spell_id, + spelltar->GetName() + ); safe_delete(action_packet); return true; } - if (spelltar->IsPet() && spelltar->GetOwner() && - spelltar->GetOwner()->IsBlockedPetBuff(spell_id)) { - LogSpells("Spell [{}] not applied to [{}] ([{}]'s pet) as it is a Pet Blocked Buff", - spell_id, spelltar->GetName(), spelltar->GetOwner()->GetName()); + if ( + spelltar->IsPet() && + spelltar->GetOwner() && + spelltar->GetOwner()->IsBlockedPetBuff(spell_id) + ) { + LogSpells( + "Spell [{}] not applied to [{}] ([{}]'s pet) as it is a Pet Blocked Buff", + spell_id, + spelltar->GetName(), + spelltar->GetOwner()->GetName() + ); safe_delete(action_packet); return true; } } // invuln mobs can't be affected by any spells, good or bad, except if caster is casting a spell with 'cast_not_standing' on self. - if ((spelltar->GetInvul() && !spelltar->DivineAura()) || + if ( + (spelltar->GetInvul() && !spelltar->DivineAura()) || (spelltar != this && spelltar->DivineAura()) || - (spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id))) { + (spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id)) + ) { LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName()); safe_delete(action_packet); return false; @@ -3651,7 +3722,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes //cannot hurt untargetable mobs bodyType bt = spelltar->GetBodyType(); - if(bt == BT_NoTarget || bt == BT_NoTarget2) { + if (bt == BT_NoTarget || bt == BT_NoTarget2) { if (RuleB(Pets, UnTargetableSwarmPet)) { if (spelltar->IsNPC()) { if (!spelltar->CastToNPC()->GetSwarmOwner()) { @@ -3675,30 +3746,24 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes // Not sure if all 3 should be stacking //This is not live like behavior (~Kayen confirmed 2/2/22) if (!RuleB(Spells, AllowDoubleInvis)) { - if (IsEffectInSpell(spell_id, SE_Invisibility)) - { - if (spelltar->invisible) - { + if (IsEffectInSpell(spell_id, SE_Invisibility)) { + if (spelltar->invisible) { spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName()); safe_delete(action_packet); return false; } } - if (IsEffectInSpell(spell_id, SE_InvisVsUndead)) - { - if (spelltar->invisible_undead) - { + if (IsEffectInSpell(spell_id, SE_InvisVsUndead)) { + if (spelltar->invisible_undead) { spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName()); safe_delete(action_packet); return false; } } - if (IsEffectInSpell(spell_id, SE_InvisVsAnimals)) - { - if (spelltar->invisible_animals) - { + if (IsEffectInSpell(spell_id, SE_InvisVsAnimals)) { + if (spelltar->invisible_animals) { spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName()); safe_delete(action_packet); return false; @@ -3706,15 +3771,10 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes } } - if(!(IsClient() && CastToClient()->GetGM()) && !IsHarmonySpell(spell_id)) // GMs can cast on anything - { + if (!(IsClient() && CastToClient()->GetGM()) && !IsHarmonySpell(spell_id)) {// GMs can cast on anything // Beneficial spells check - if(IsBeneficialSpell(spell_id)) - { - if(IsClient() && //let NPCs do beneficial spells on anybody if they want, should be the job of the AI, not the spell code to prevent this from going wrong - spelltar != this) - { - + if (IsBeneficialSpell(spell_id)) { + if (IsClient() && spelltar != this) {//let NPCs do beneficial spells on anybody if they want, should be the job of the AI, not the spell code to prevent this from going wrong Client* pClient = nullptr; Raid* pRaid = nullptr; Group* pBasicGroup = nullptr; @@ -3736,60 +3796,89 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes pClient = CastToClient(); pRaid = entity_list.GetRaidByClient(pClient); pBasicGroup = entity_list.GetGroupByMob(this); - if(pRaid) + if (pRaid) { nGroup = pRaid->GetGroup(pClient) + 1; + } //Target client pointers - if(spelltar->IsClient()) - { + if (spelltar->IsClient()) { pClientTarget = spelltar->CastToClient(); pRaidTarget = entity_list.GetRaidByClient(pClientTarget); pBasicGroupTarget = entity_list.GetGroupByMob(spelltar); - if(pRaidTarget) + if (pRaidTarget) { nGroupTarget = pRaidTarget->GetGroup(pClientTarget) + 1; + } } - if(spelltar->IsPet()) - { + if (spelltar->IsPet()) { Mob *owner = spelltar->GetOwner(); - if(owner->IsClient()) - { + if (owner->IsClient()) { pClientTargetPet = owner->CastToClient(); pRaidTargetPet = entity_list.GetRaidByClient(pClientTargetPet); pBasicGroupTargetPet = entity_list.GetGroupByMob(owner); - if(pRaidTargetPet) + if (pRaidTargetPet) { nGroupTargetPet = pRaidTargetPet->GetGroup(pClientTargetPet) + 1; + } } } - if((!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) || + if ( + (!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) || (IsGroupOnlySpell(spell_id) && !( - (pBasicGroup && ((pBasicGroup == pBasicGroupTarget) || (pBasicGroup == pBasicGroupTargetPet))) || //Basic Group - - ((nGroup != cnWTF) && ((nGroup == nGroupTarget) || (nGroup == nGroupTargetPet))) || //Raid group - - (spelltar == GetPet()) //should be able to cast grp spells on self and pet despite grped status. + ( + pBasicGroup && + ( + pBasicGroup == pBasicGroupTarget || + pBasicGroup == pBasicGroupTargetPet + ) + ) || //Basic Group + ( + nGroup != cnWTF && + ( + nGroup == nGroupTarget || + nGroup == nGroupTargetPet + ) + ) || //Raid group + spelltar == GetPet() //should be able to cast grp spells on self and pet despite grped status. ) ) - ) - { - if(spells[spell_id].target_type == ST_AEBard) { + ) { + if (spells[spell_id].target_type == ST_AEBard) { //if it was a beneficial AE bard song don't spam the window that it would not hold - LogSpells("Beneficial ae bard song [{}] can't take hold [{}] -> [{}], IBA? [{}]", spell_id, GetName(), spelltar->GetName(), IsBeneficialAllowed(spelltar)); + LogSpells( + "Beneficial ae bard song [{}] can't take hold [{}] -> [{}], IBA? [{}]", + spell_id, + GetName(), + spelltar->GetName(), + IsBeneficialAllowed(spelltar) + ); } else { - LogSpells("Beneficial spell [{}] can't take hold [{}] -> [{}], IBA? [{}]", spell_id, GetName(), spelltar->GetName(), IsBeneficialAllowed(spelltar)); + LogSpells( + "Beneficial spell [{}] can't take hold [{}] -> [{}], IBA? [{}]", + spell_id, + GetName(), + spelltar->GetName(), + IsBeneficialAllowed(spelltar) + ); MessageString(Chat::SpellFailure, SPELL_NO_HOLD); } safe_delete(action_packet); return false; } } - } - else if ( !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && !IsEffectInSpell(spell_id, SE_BindSight)) // Detrimental spells - PVP check - { - LogSpells("Detrimental spell [{}] can't take hold [{}] -> [{}]", spell_id, GetName(), spelltar->GetName()); + } else if ( + !IsAttackAllowed(spelltar, true) && + !IsResurrectionEffects(spell_id) && + !IsEffectInSpell(spell_id, SE_BindSight) + ) { // Detrimental spells - PVP check + LogSpells( + "Detrimental spell [{}] can't take hold [{}] -> [{}]", + spell_id, + GetName(), + spelltar->GetName() + ); spelltar->MessageString(Chat::SpellFailure, YOU_ARE_PROTECTED, GetCleanName()); safe_delete(action_packet); return false; @@ -3800,8 +3889,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes // but we need to check special cases and resists // check immunities - if(spelltar->IsImmuneToSpell(spell_id, this)) - { + if (spelltar->IsImmuneToSpell(spell_id, this)) { //the above call does the message to the client if needed LogSpells("Spell [{}] can't take hold due to immunity [{}] -> [{}]", spell_id, GetName(), spelltar->GetName()); safe_delete(action_packet); @@ -3809,30 +3897,36 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes } //check for AE_Undead - if(spells[spell_id].target_type == ST_UndeadAE){ - if(spelltar->GetBodyType() != BT_SummonedUndead && + if (spells[spell_id].target_type == ST_UndeadAE){ + if ( + spelltar->GetBodyType() != BT_SummonedUndead && spelltar->GetBodyType() != BT_Undead && - spelltar->GetBodyType() != BT_Vampire) - { + spelltar->GetBodyType() != BT_Vampire + ) { safe_delete(action_packet); return false; } } + //Need this to account for special AOE cases. - if (IsClient() && IsHarmonySpell(spell_id) && !HarmonySpellLevelCheck(spell_id, spelltar)) { + if ( + IsClient() && + IsHarmonySpell(spell_id) && + !HarmonySpellLevelCheck(spell_id, spelltar) + ) { MessageString(Chat::SpellFailure, SPELL_NO_EFFECT); safe_delete(action_packet); return false; } // Block next spell effect should be used up first(since its blocking the next spell) - if(CanBlockSpell()) { + if (CanBlockSpell()) { int buff_count = GetMaxTotalSlots(); int focus = 0; - for (int b=0; b < buff_count; b++) { - if(IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) { + for (int b = 0; b < buff_count; b++) { + if (IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) { focus = CalcFocusEffect(focusBlockNextSpell, buffs[b].spellid, spell_id); - if(focus) { + if (focus) { CheckNumHitsRemaining(NumHit::MatchingSpells, b); MessageString(Chat::SpellFailure, SPELL_WOULDNT_HOLD); safe_delete(action_packet); @@ -3854,67 +3948,83 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes There are a few spells in database that are not detrimental that have Reflectable field set, however from testing, they do not actually reflect. */ - if(spells[spell_id].reflectable && !reflect_effectiveness && spelltar && this != spelltar && IsDetrimentalSpell(spell_id) && - (spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) { + if ( + spells[spell_id].reflectable && + !reflect_effectiveness && + spelltar && + this != spelltar && + IsDetrimentalSpell(spell_id) && + ( + spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] || + spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] || + spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] + ) + ) { bool can_spell_reflect = false; - switch(RuleI(Spells, ReflectType)) - { - case REFLECT_DISABLED: - break; - - case REFLECT_SINGLE_TARGET_SPELLS_ONLY: - { - if(spells[spell_id].target_type == ST_Target) { - for(int y = 0; y < 16; y++) { + switch (RuleI(Spells, ReflectType)) { + case REFLECT_SINGLE_TARGET_SPELLS_ONLY: { + if (spells[spell_id].target_type == ST_Target) { + for (int y = 0; y < 16; y++) { if (spells[spell_id].classes[y] < 255) { can_spell_reflect = true; } } } + break; } - case REFLECT_ALL_PLAYER_SPELLS: - { - for(int y = 0; y < 16; y++) { + case REFLECT_ALL_PLAYER_SPELLS: { + for (int y = 0; y < 16; y++) { if (spells[spell_id].classes[y] < 255) { can_spell_reflect = true; } } + break; } - case RELFECT_ALL_SINGLE_TARGET_SPELLS: - { + case RELFECT_ALL_SINGLE_TARGET_SPELLS: { if (spells[spell_id].target_type == ST_Target) { can_spell_reflect = true; } + break; } - case REFLECT_ALL_SPELLS: //This is live like behavior + case REFLECT_ALL_SPELLS: {//This is live like behavior can_spell_reflect = true; - - default: + } + case REFLECT_DISABLED: + default: { break; + } } - if (can_spell_reflect) { + if (can_spell_reflect) { int reflect_resist_adjust = 0; int reflect_effectiveness_mod = 0; //Need value of 100 to do baseline unmodified damage. - if (spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE])) { - reflect_resist_adjust = spelltar->spellbonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD]; - reflect_effectiveness_mod = spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100; - } - else if (spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE])) { + if ( + spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] && + zone->random.Roll(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE]) + ) { + reflect_resist_adjust = spelltar->spellbonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD]; + reflect_effectiveness_mod = spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] + ? spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100; + } else if ( + spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] && + zone->random.Roll(spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE]) + ) { reflect_effectiveness_mod = 100; reflect_resist_adjust = spelltar->aabonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD]; - } - else if (spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) { - reflect_resist_adjust = spelltar->itembonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD]; - reflect_effectiveness_mod = spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100; + } else if ( + spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] && + zone->random.Roll(spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE]) + ) { + reflect_resist_adjust = spelltar->itembonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD]; + reflect_effectiveness_mod = spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] + ? spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100; } if (reflect_effectiveness_mod) { - if (RuleB(Spells, ReflectMessagesClose)) { entity_list.MessageCloseString( this, /* Sender */ @@ -3925,8 +4035,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes GetCleanName(), /* Message 1 */ spelltar->GetCleanName() /* Message 2 */ ); - } - else { + } else { MessageString(Chat::Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName()); } @@ -3942,40 +4051,62 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes // resist check - every spell can be resisted, beneficial or not // add: ok this isn't true, eqlive's spell data is fucked up, buffs are // not all unresistable, so changing this to only check certain spells - if(IsResistableSpell(spell_id)) - { + if (IsResistableSpell(spell_id)) { spelltar->BreakInvisibleSpells(); //Any detrimental spell cast on you will drop invisible (can be AOE, non damage ect). - if (IsCharmSpell(spell_id) || IsMezSpell(spell_id) || IsFearSpell(spell_id)) - spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resist_type, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override); - else - spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resist_type, spell_id, this, use_resist_adjust, resist_adjust, false, false, false, level_override); + if ( + IsCharmSpell(spell_id) || + IsMezSpell(spell_id) || + IsFearSpell(spell_id) + ) { + spell_effectiveness = spelltar->ResistSpell( + spells[spell_id].resist_type, + spell_id, + this, + use_resist_adjust, + resist_adjust, + true, + false, + false, + level_override + ); + } else { + spell_effectiveness = spelltar->ResistSpell( + spells[spell_id].resist_type, + spell_id, + this, + use_resist_adjust, + resist_adjust, + false, + false, + false, + level_override + ); + } - if(spell_effectiveness < 100) - { - if(spell_effectiveness == 0 || !IsPartialCapableSpell(spell_id) ) - { + if (spell_effectiveness < 100) { + if (spell_effectiveness == 0 || !IsPartialCapableSpell(spell_id)) { LogSpells("Spell [{}] was completely resisted by [{}]", spell_id, spelltar->GetName()); if (spells[spell_id].resist_type == RESIST_PHYSICAL){ MessageString(Chat::SpellFailure, PHYSICAL_RESIST_FAIL,spells[spell_id].name); spelltar->MessageString(Chat::SpellFailure, YOU_RESIST, spells[spell_id].name); - } - else { + } else { MessageString(Chat::SpellFailure, TARGET_RESISTED, spells[spell_id].name); spelltar->MessageString(Chat::SpellFailure, YOU_RESIST, spells[spell_id].name); } if (spelltar->IsAIControlled()) { - int32 aggro = CheckAggroAmount(spell_id, spelltar); + auto aggro = CheckAggroAmount(spell_id, spelltar); if (aggro > 0) { - if (!IsHarmonySpell(spell_id)) + if (!IsHarmonySpell(spell_id)) { spelltar->AddToHateList(this, aggro); - else if (!spelltar->PassCharismaCheck(this, spell_id)) + } else if (!spelltar->PassCharismaCheck(this, spell_id)) { spelltar->AddToHateList(this, aggro); + } } else { - int newhate = spelltar->GetHateAmount(this) + aggro; - spelltar->SetHateAmountOnEnt(this, std::max(1, newhate)); + int64 newhate = spelltar->GetHateAmount(this) + aggro; + spelltar->SetHateAmountOnEnt(this, std::max(static_cast(1), newhate)); } } @@ -3996,33 +4127,41 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes spelltar->CastToClient()->BreakSneakWhenCastOn(this, false); spelltar->CastToClient()->BreakFeignDeathWhenCastOn(false); } - } - else - { + } else { spell_effectiveness = 100; } - if (spells[spell_id].feedbackable && (spelltar->spellbonuses.SpellDamageShield || spelltar->itembonuses.SpellDamageShield || spelltar->aabonuses.SpellDamageShield)) { + if ( + spells[spell_id].feedbackable && + ( + spelltar->spellbonuses.SpellDamageShield || + spelltar->itembonuses.SpellDamageShield || + spelltar->aabonuses.SpellDamageShield + ) + ) { spelltar->DamageShield(this, true); } - if (spelltar->IsAIControlled() && IsDetrimentalSpell(spell_id) && !IsHarmonySpell(spell_id)) { - int32 aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc); + if ( + spelltar->IsAIControlled() && + IsDetrimentalSpell(spell_id) && + !IsHarmonySpell(spell_id) + ) { + auto aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc); LogSpells("Spell [{}] cast on [{}] generated [{}] hate", spell_id, spelltar->GetName(), aggro_amount); if (aggro_amount > 0) { spelltar->AddToHateList(this, aggro_amount); } else { - int32 newhate = spelltar->GetHateAmount(this) + aggro_amount; - spelltar->SetHateAmountOnEnt(this, std::max(newhate, 1)); + int64 newhate = spelltar->GetHateAmount(this) + aggro_amount; + spelltar->SetHateAmountOnEnt(this, std::max(newhate, static_cast(1))); } } else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) { if (this != spelltar && IsClient()){ if (spelltar->IsClient()) { CastToClient()->UpdateRestTimer(spelltar->CastToClient()->GetRestTimer()); - } - else if (spelltar->IsPet()) { - Mob *owner = spelltar->GetOwner(); + } else if (spelltar->IsPet()) { + auto* owner = spelltar->GetOwner(); if (owner && owner != this && owner->IsClient()) { CastToClient()->UpdateRestTimer(owner->CastToClient()->GetRestTimer()); } @@ -4030,23 +4169,34 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes } entity_list.AddHealAggro( - spelltar, this, - CheckHealAggroAmount(spell_id, spelltar, (spelltar->GetMaxHP() - spelltar->GetHP()))); + spelltar, + this, + CheckHealAggroAmount( + spell_id, + spelltar, + (spelltar->GetMaxHP() - spelltar->GetHP()) + ) + ); } // make sure spelltar is high enough level for the buff - if(RuleB(Spells, BuffLevelRestrictions) && !spelltar->CheckSpellLevelRestriction(spell_id)) - { - LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id); - if(!IsBardSong(spell_id)) - MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL); + if (!spelltar->CheckSpellLevelRestriction(this, spell_id)) { safe_delete(action_packet); return false; } // cause the effects to the target - if(!spelltar->SpellEffect(this, spell_id, spell_effectiveness, level_override, reflect_effectiveness, duration_override, disable_buff_overrwrite)) - { + if ( + !spelltar->SpellEffect( + this, + spell_id, + spell_effectiveness, + level_override, + reflect_effectiveness, + duration_override, + disable_buff_overwrite + ) + ) { // if SpellEffect returned false there's a problem applying the // spell. It's most likely a buff that can't stack. LogSpells("Spell [{}] could not apply its effects [{}] -> [{}]\n", spell_id, GetName(), spelltar->GetName()); @@ -4058,18 +4208,27 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes } //Check SE_Fc_Cast_Spell_On_Land SPA 481 on target, if hit by this spell and Conditions are Met then target will cast the specified spell. - if (spelltar) + if (spelltar) { spelltar->CastSpellOnLand(this, spell_id); + } - if (IsValidSpell(spells[spell_id].recourse_link) && spells[spell_id].recourse_link != spell_id) - SpellFinished(spells[spell_id].recourse_link, this, CastingSlot::Item, 0, -1, spells[spells[spell_id].recourse_link].resist_difficulty); + if (IsValidSpell(spells[spell_id].recourse_link) && spells[spell_id].recourse_link != spell_id) { + SpellFinished( + spells[spell_id].recourse_link, + this, + CastingSlot::Item, + 0, + -1, + spells[spells[spell_id].recourse_link].resist_difficulty + ); + } if (IsDetrimentalSpell(spell_id)) { - CheckNumHitsRemaining(NumHit::OutgoingSpells); - if (spelltar) + if (spelltar) { spelltar->CheckNumHitsRemaining(NumHit::IncomingSpells); + } } // send the action packet again now that the spell is successful @@ -4078,16 +4237,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes // the complete sequence is 2 actions and 1 damage message action->effect_flag = 0x04; // this is a success flag - if(spells[spell_id].push_back != 0.0f || spells[spell_id].push_up != 0.0f) - { - if (spelltar->IsClient()) - { - if (!IsBuffSpell(spell_id)) - { + if (spells[spell_id].push_back != 0.0f || spells[spell_id].push_up != 0.0f) { + if (spelltar->IsClient()) { + if (!IsBuffSpell(spell_id)) { spelltar->CastToClient()->cheat_manager.SetExemptStatus(KnockBack, true); } - } - else if (RuleB(Spells, NPCSpellPush) && !spelltar->IsPermaRooted() && !spelltar->IsPseudoRooted() && spelltar->ForcedMovement == 0) { + } else if ( + RuleB(Spells, NPCSpellPush) && + !spelltar->IsPermaRooted() && + !spelltar->IsPseudoRooted() && + !spelltar->ForcedMovement + ) { spelltar->m_Delta.x += action->force * g_Math.FastSin(action->hit_heading); spelltar->m_Delta.y += action->force * g_Math.FastCos(action->hit_heading); spelltar->m_Delta.z += action->hit_pitch; @@ -4095,21 +4255,20 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes } } - if (spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep)) - { + if (spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep)) { spelltar->CastToClient()->cheat_manager.SetExemptStatus(ShadowStep, true); } - if(!IsEffectInSpell(spell_id, SE_BindAffinity)) - { - if(spelltar != this && spelltar->IsClient()) // send to target + if (!IsEffectInSpell(spell_id, SE_BindAffinity)) { + if (spelltar != this && spelltar->IsClient()) {// send to target spelltar->CastToClient()->QueuePacket(action_packet); - if(IsClient()) // send to caster + } + + if(IsClient()) {// send to caster CastToClient()->QueuePacket(action_packet); + } } - // send to people in the area, ignoring caster and target - //live dosent send this to anybody but the caster - //entity_list.QueueCloseClients(spelltar, action_packet, true, 200, this, true, spelltar->IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); + message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct *cd = (CombatDamage_Struct *)message_packet->pBuffer; cd->target = action->target; @@ -4121,7 +4280,12 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes cd->hit_pitch = action->hit_pitch; cd->damage = 0; - if(!IsEffectInSpell(spell_id, SE_BindAffinity) && !is_damage_or_lifetap_spell){ + if ( + !IsLifetapSpell(spell_id) && + !IsEffectInSpell(spell_id, SE_BindAffinity) && + !IsAENukeSpell(spell_id) && + !IsDamageSpell(spell_id) + ) { entity_list.QueueCloseClients( spelltar, /* Sender */ message_packet, /* Packet */ @@ -4131,19 +4295,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes true, /* Packet ACK */ (spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */ ); - } else if (is_damage_or_lifetap_spell) { - // Sends the client owner a message like "%T staggers" - if (spellOwner->IsClient()) { - spellOwner->CastToClient()->QueuePacket(message_packet, true, - Mob::CLIENT_CONNECTINGALL, FilterPCSpells); - } - // Show the "you feel your life force drain away" on target client... - if (IsLifetapSpell(spell_id) && spelltar->IsClient()) { - spelltar->CastToClient()->QueuePacket(message_packet, true, - Mob::CLIENT_CONNECTINGALL, - (spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells)); - } } + safe_delete(action_packet); safe_delete(message_packet); @@ -4215,11 +4368,18 @@ uint16 Mob::FindBuffBySlot(int slot) { return 0; } -uint32 Mob::BuffCount() { +uint32 Mob::BuffCount(bool is_beneficial, bool is_detrimental) { uint32 active_buff_count = 0; int buff_count = GetMaxTotalSlots(); for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { - if (IsValidSpell(buffs[buff_slot].spellid)) { + const auto is_spell_beneficial = IsBeneficialSpell(buffs[buff_slot].spellid); + if ( + IsValidSpell(buffs[buff_slot].spellid) && + ( + (is_beneficial && is_spell_beneficial) || + (is_detrimental && !is_spell_beneficial) + ) + ) { active_buff_count++; } } @@ -5019,30 +5179,28 @@ int16 Mob::CalcResistChanceBonus() { int resistchance = spellbonuses.ResistSpellChance + itembonuses.ResistSpellChance; - if(IsClient()) + if (IsClient() || IsBot()) { resistchance += aabonuses.ResistSpellChance; - + } return resistchance; } int16 Mob::CalcFearResistChance() { int resistchance = spellbonuses.ResistFearChance + itembonuses.ResistFearChance; - if(IsClient()) { + if (IsClient() || IsBot()) { resistchance += aabonuses.ResistFearChance; - if(aabonuses.Fearless == true) + if (aabonuses.Fearless == true) { resistchance = 100; + } } - if(spellbonuses.Fearless == true || itembonuses.Fearless == true) + if (spellbonuses.Fearless == true || itembonuses.Fearless == true) { resistchance = 100; + } return resistchance; } -/** - * @param spell_id - * @return - */ float Mob::GetAOERange(uint16 spell_id) { float range = spells[spell_id].aoe_range; @@ -5518,7 +5676,34 @@ uint32 Client::GetHighestScribedSpellinSpellGroup(uint32 spell_group) return highest_spell_id; } -bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { +std::unordered_map> Client::LoadSpellGroupCache(uint8 min_level, uint8 max_level) { + std::unordered_map> spell_group_cache; + + const auto query = fmt::format( + "SELECT a.spellgroup, a.id, a.rank " + "FROM spells_new a " + "INNER JOIN (" + "SELECT spellgroup, MAX(rank) rank " + "FROM spells_new " + "GROUP BY spellgroup) " + "b ON a.spellgroup = b.spellgroup AND a.rank = b.rank " + "WHERE a.spellgroup IN (SELECT DISTINCT spellgroup FROM spells_new WHERE spellgroup != 0 and classes{} BETWEEN {} AND {}) ORDER BY rank DESC", + m_pp.class_, min_level, max_level + ); + + auto results = database.QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + return spell_group_cache; + } + + for (auto row : results) { + spell_group_cache[std::stoul(row[0])].push_back(static_cast(std::stoul(row[1]))); + } + + return spell_group_cache; +} + +bool Client::SpellGlobalCheck(uint16 spell_id, uint32 character_id) { std::string query = fmt::format( "SELECT qglobal, value FROM spell_globals WHERE spellid = {}", spell_id @@ -5543,8 +5728,8 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { query = fmt::format( "SELECT value FROM quest_globals WHERE charid = {} AND name = '{}'", - char_id, - EscapeString(spell_global_name) + character_id, + Strings::Escape(spell_global_name) ); results = database.QueryDatabase(query); @@ -5553,7 +5738,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { "Spell global [{}] for spell ID [{}] for character ID [{}] query failed.", spell_global_name, spell_id, - char_id + character_id ); return false; // Query failed, do not allow scribing. @@ -5564,7 +5749,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { "Spell global [{}] for spell ID [{}] for character ID [{}] does not exist.", spell_global_name, spell_id, - char_id + character_id ); return false; // No rows found, do not allow scribing. @@ -5572,7 +5757,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { row = results.begin(); std::string global_value = row[0]; - if (StringIsNumber(global_value) && StringIsNumber(spell_global_value)) { + if (Strings::IsNumber(global_value) && Strings::IsNumber(spell_global_value)) { if (std::stoi(global_value) >= std::stoi(spell_global_value)) { return true; // If value is greater than or equal to spell global value, allow scribing. } @@ -5587,7 +5772,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { "Spell global [{}] for spell ID [{}] for character ID [{}] did not match value [{}] value found was [{}].", spell_global_name, spell_id, - char_id, + character_id, spell_global_value, global_value ); @@ -5595,7 +5780,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { return false; } -bool Client::SpellBucketCheck(uint16 spell_id, uint32 char_id) { +bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) { auto query = fmt::format( "SELECT `key`, value FROM spell_buckets WHERE spellid = {}", spell_id @@ -5618,57 +5803,44 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 char_id) { return true; // If the entry in the spell_buckets table has nothing set for the qglobal name, allow scribing. } - query = fmt::format( - "SELECT value FROM data_buckets WHERE `key` = '{}-{}'", - char_id, - EscapeString(spell_bucket_name) + auto new_bucket_name = fmt::format( + "{}-{}", + GetBucketKey(), + spell_bucket_name ); - results = database.QueryDatabase(query); - if (!results.Success()) { - LogError( - "Spell bucket [{}] for spell ID [{}] for character ID [{}] query failed.", - spell_bucket_name, - spell_id, - char_id - ); - - return false; // Query failed, do not allow scribing. - } - - if (!results.RowCount()) { - LogError( - "Spell bucket [{}] for spell ID [{}] for character ID [{}] does not exist.", - spell_bucket_name, - spell_id, - char_id - ); - - return false; // No rows found, do not allow scribing. - } - - row = results.begin(); - std::string bucket_value = row[0]; - if (StringIsNumber(bucket_value) && StringIsNumber(spell_bucket_value)) { - if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { - return true; // If value is greater than or equal to spell bucket value, allow scribing. - } - } else { - if (bucket_value == spell_bucket_value) { - return true; // If value is equal to spell bucket value, allow scribing. + auto bucket_value = DataBucket::GetData(new_bucket_name); + if (!bucket_value.empty()) { + if (Strings::IsNumber(bucket_value) && Strings::IsNumber(spell_bucket_value)) { + if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { + return true; // If value is greater than or equal to spell bucket value, allow scribing. + } + } else { + if (bucket_value == spell_bucket_value) { + return true; // If value is equal to spell bucket value, allow scribing. + } } } - // If user's data bucket does not meet requirements, do not allow scribing. - LogError( - "Spell bucket [{}] for spell ID [{}] for character ID [{}] did not match value [{}] value found was [{}].", - spell_bucket_name, - spell_id, - char_id, - spell_bucket_value, - bucket_value + auto old_bucket_name = fmt::format( + "{}-{}", + character_id, + spell_bucket_name ); + bucket_value = DataBucket::GetData(old_bucket_name); + if (!bucket_value.empty()) { + if (Strings::IsNumber(bucket_value) && Strings::IsNumber(spell_bucket_value)) { + if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { + return true; // If value is greater than or equal to spell bucket value, allow scribing. + } + } else { + if (bucket_value == spell_bucket_value) { + return true; // If value is equal to spell bucket value, allow scribing. + } + } + } + return false; } @@ -5707,9 +5879,12 @@ bool Mob::FindType(uint16 type, bool bOffensive, uint16 threshold) { spells[buffs[i].spellid].base_value[j], spells[buffs[i].spellid].max_value[j], buffs[i].casterlevel, buffs[i].spellid); - Log(Logs::General, Logs::Normal, - "FindType: type = %d; value = %d; threshold = %d", - type, value, threshold); + LogSpells( + "FindType type [{}] value [{}] threshold [{}]", + type, + value, + threshold + ); if (value < threshold) return true; } @@ -5744,7 +5919,7 @@ bool Mob::IsCombatProc(uint16 spell_id) { } } - if (IsClient()) { + if (IsClient() || IsBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.SpellProc[i + 1] == spell_id || aabonuses.RangedProc[i + 1] == spell_id || @@ -6148,17 +6323,19 @@ void NPC::UninitializeBuffSlots() safe_delete_array(buffs); } -void Client::SendSpellAnim(uint16 targetid, uint16 spell_id) +void Client::SendSpellAnim(uint16 target_id, uint16 spell_id) { - if (!targetid || !IsValidSpell(spell_id)) + if (!target_id || !IsValidSpell(spell_id)) { return; + } EQApplicationPacket app(OP_Action, sizeof(Action_Struct)); - Action_Struct* a = (Action_Struct*)app.pBuffer; - a->target = targetid; - a->source = GetID(); - a->type = 231; - a->spell = spell_id; + auto* a = (Action_Struct*) app.pBuffer; + + a->target = target_id; + a->source = GetID(); + a->type = 231; + a->spell = spell_id; a->hit_heading = GetHeading(); app.priority = 1; @@ -6351,7 +6528,7 @@ void Mob::BeamDirectional(uint16 spell_id, int16 resist_adjust) while (iter != targets_in_range.end()) { if (!(*iter) || (beneficial_targets && ((*iter)->IsNPC() && !(*iter)->IsPetOwnerClient())) || - (*iter)->BehindMob(this, (*iter)->GetX(), (*iter)->GetY())) { + (*iter)->BehindMob(this, (*iter)->GetX(), (*iter)->GetY())) { ++iter; continue; } @@ -6440,7 +6617,7 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) } float heading_to_target = - (CalculateHeadingToTarget((*iter)->GetX(), (*iter)->GetY()) * 360.0f / 512.0f); + (CalculateHeadingToTarget((*iter)->GetX(), (*iter)->GetY()) * 360.0f / 512.0f); while (heading_to_target < 0.0f) heading_to_target += 360.0f; @@ -6484,7 +6661,7 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) if (angle_start > angle_end) { if ((heading_to_target >= angle_start && heading_to_target <= 360.0f) || - (heading_to_target >= 0.0f && heading_to_target <= angle_end)) { + (heading_to_target >= 0.0f && heading_to_target <= angle_end)) { if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) { (*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this); SpellOnTarget(spell_id, (*iter), 0, true, resist_adjust); diff --git a/zone/string_ids.h b/zone/string_ids.h index d5b6c52f3..8f44cb48c 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -181,6 +181,7 @@ #define PET_SPELLHOLD_SET_ON 702 //The pet spellhold mode has been set to on. #define PET_SPELLHOLD_SET_OFF 703 //The pet spellhold mode has been set to off. #define GUILD_NAME_IN_USE 711 //You cannot create a guild with that name, that guild already exists on this server. +#define AA_CAP 1000 //You have reached the AA point cap, and cannot gain any further experience until some of your stored AA point pool is used. #define GM_GAINXP 1002 //[GM] You have gained %1 AXP and %2 EXP (%3). #define MALE_SLAYUNDEAD 1007 //%1's holy blade cleanses his target!(%2) #define FEMALE_SLAYUNDEAD 1008 //%1's holy blade cleanses her target!(%2) @@ -210,6 +211,7 @@ #define EATING_MESSAGE 1091 //Chomp, chomp, chomp... %1 takes a bite from a %2. #define DRINKING_MESSAGE 1093 //Glug, glug, glug... %1 takes a drink from a %2. #define SUCCESSFUL_TAUNT 1095 //I'll teach you to interfere with me %3. +#define TRADE_BACK 1105 //I have no need for this %3, you can have it back. #define PET_SIT_STRING 1130 //Changing position, Master. #define PET_CALMING 1131 //Sorry, Master..calming down. #define PET_FOLLOWING 1132 //Following you, Master. @@ -265,6 +267,7 @@ #define DUEL_DECLINE 1383 //%1 has declined your challenge to duel to the death. #define DUEL_ACCEPTED 1384 //%1 has already accepted a duel with someone else. #define DUEL_CONSIDERING 1385 //%1 is considering a duel with someone else. +#define PLAYER_SUMMONED 1393 //You have been summoned! #define PLAYER_REGAIN 1394 //You have control of yourself again. #define REZZ_ALREADY_PENDING 1379 //You were unable to restore the corpse to life, but you may have success with a later attempt. #define IN_USE 1406 //Someone else is using that. Try again later. @@ -293,6 +296,7 @@ #define ALREADY_SHIELDING 3280 //Either you or your target is already shielding another. #define START_SHIELDING 3281 //%1 begins to use %2 as a living shield! #define END_SHIELDING 3282 //%1 ceases protecting %2. +#define OVER_AA_CAP 3374 //Warning: You are currently over the earned Advancement point limit of %1. Please spend some of your stored AA points. The NEXT time you zone all of your AA points over %2 will be deleted. You MUST spend the extra points now. #define TRADESKILL_MISSING_ITEM 3455 //You are missing a %1. #define TRADESKILL_MISSING_COMPONENTS 3456 //Sorry, but you don't have everything you need for this recipe in your general inventory. #define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1! @@ -452,9 +456,12 @@ #define NO_CAST_OUT_OF_COMBAT 9191 //You can not cast this spell while out of combat. #define NO_ABILITY_IN_COMBAT 9192 //You can not use this ability while in combat. #define NO_ABILITY_OUT_OF_COMBAT 9194 //You can not use this ability while out of combat. +#define LESSER_SPELL_VERSION 11004 //%1 is a lesser version of %2 and cannot be scribed #define AE_RAMPAGE 11015 //%1 goes on a WILD RAMPAGE! #define FACE_ACCEPTED 12028 //Facial features accepted. +#define TRACKING_BEGIN 12040 //You begin tracking %1. #define SPELL_LEVEL_TO_LOW 12048 //You will have to achieve level %1 before you can scribe the %2. +#define YOU_RECEIVE_AS_SPLIT 12071 //You receive %1 as your split. #define ATTACKFAILED 12158 //%1 try to %2 %3, but %4! #define HIT_STRING 12183 //hit #define CRUSH_STRING 12191 //crush @@ -476,6 +483,7 @@ #define NO_LONGER_HIDDEN 12337 //You are no longer hidden. #define STOP_SNEAKING 12338 //You stop sneaking #define NOT_IN_CONTROL 12368 //You do not have control of yourself right now. +#define NO_SKILL_WHILE_MOUNTED 12393 //You can not use this skill while on a mount. #define STAND_TO_CAST 12441 //You must be standing to cast a spell. #define ALREADY_CASTING 12442 //You are already casting a spell! #define SHIMMERS_BRIEFLY 12444 //Your %1 shimmers briefly. @@ -516,6 +524,7 @@ #define REPORT_ONCE 12945 //You may only submit a report once per time that you zone. Thank you. #define NOW_INVISIBLE 12950 //%1 is now Invisible. #define NOW_VISIBLE 12951 //%1 is now Visible. +#define YOU_TAKE_DOT 12954 //You have taken %1 damage from %2 by %3 #define GUILD_NOT_MEMBER2 12966 //You are not in a guild. #define HOT_HEAL_SELF 12976 //You have been healed for %1 hit points by your %2. #define HOT_HEAL_OTHER 12997 //You have healed %1 for %2 hit points with your %3. diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index 6d79a41e1..ca7456f04 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -15,6 +15,9 @@ #include "dynamic_zone.h" #include "string_ids.h" +#define EBON_CRYSTAL 40902 +#define RADIANT_CRYSTAL 40903 + extern WorldServer worldserver; extern QueryServ *QServ; @@ -22,7 +25,6 @@ ClientTaskState::ClientTaskState() { m_active_task_count = 0; m_last_completed_task_loaded = 0; - m_checked_touch_activities = false; for (int i = 0; i < MAXACTIVEQUESTS; i++) { m_active_quests[i].slot = i; @@ -45,7 +47,7 @@ ClientTaskState::~ClientTaskState() void ClientTaskState::SendTaskHistory(Client *client, int task_index) { - LogTasks("[SendTaskHistory] Task history requested for completed task index [{}]", task_index); + LogTasks("Task history requested for completed task index [{}]", task_index); // We only sent the most recent 50 completed tasks, so we need to offset the Index the client sent to us. @@ -59,13 +61,12 @@ void ClientTaskState::SendTaskHistory(Client *client, int task_index) } int task_id = m_completed_tasks[adjusted_task_index].task_id; - if ((task_id < 0) || (task_id > MAXTASKS)) { + if (task_id < 0) { return; } - TaskInformation *p_task_data = task_manager->m_task_data[task_id]; - - if (p_task_data == nullptr) { + const auto task_data = task_manager->GetTaskData(task_id); + if (!task_data) { return; } @@ -78,14 +79,14 @@ void ClientTaskState::SendTaskHistory(Client *client, int task_index) int completed_activity_count = 0; int packet_length = sizeof(TaskHistoryReplyHeader_Struct); - for (int i = 0; i < p_task_data->activity_count; i++) { + for (int i = 0; i < task_data->activity_count; i++) { if (m_completed_tasks[adjusted_task_index].activity_done[i]) { completed_activity_count++; packet_length = packet_length + sizeof(TaskHistoryReplyData1_Struct) + - p_task_data->activity_information[i].target_name.size() + 1 + - p_task_data->activity_information[i].item_list.size() + 1 + + task_data->activity_information[i].target_name.size() + 1 + + task_data->activity_information[i].item_list.size() + 1 + sizeof(TaskHistoryReplyData2_Struct) + - p_task_data->activity_information[i].description_override.size() + 1; + task_data->activity_information[i].description_override.size() + 1; } } @@ -99,22 +100,22 @@ void ClientTaskState::SendTaskHistory(Client *client, int task_index) reply = (char *) task_history_reply + sizeof(TaskHistoryReplyHeader_Struct); - for (int i = 0; i < p_task_data->activity_count; i++) { + for (int i = 0; i < task_data->activity_count; i++) { if (m_completed_tasks[adjusted_task_index].activity_done[i]) { task_history_reply_data_1 = (TaskHistoryReplyData1_Struct *) reply; - task_history_reply_data_1->ActivityType = static_cast(p_task_data->activity_information[i].activity_type); + task_history_reply_data_1->ActivityType = static_cast(task_data->activity_information[i].activity_type); reply = (char *) task_history_reply_data_1 + sizeof(TaskHistoryReplyData1_Struct); - VARSTRUCT_ENCODE_STRING(reply, p_task_data->activity_information[i].target_name.c_str()); - VARSTRUCT_ENCODE_STRING(reply, p_task_data->activity_information[i].item_list.c_str()); + VARSTRUCT_ENCODE_STRING(reply, task_data->activity_information[i].target_name.c_str()); + VARSTRUCT_ENCODE_STRING(reply, task_data->activity_information[i].item_list.c_str()); task_history_reply_data_2 = (TaskHistoryReplyData2_Struct *) reply; - task_history_reply_data_2->GoalCount = p_task_data->activity_information[i].goal_count; + task_history_reply_data_2->GoalCount = task_data->activity_information[i].goal_count; task_history_reply_data_2->unknown04 = 0xffffffff; task_history_reply_data_2->unknown08 = 0xffffffff; - task_history_reply_data_2->ZoneID = p_task_data->activity_information[i].zone_ids.empty() ? 0 - : p_task_data->activity_information[i].zone_ids.front(); + task_history_reply_data_2->ZoneID = task_data->activity_information[i].zone_ids.empty() ? 0 + : task_data->activity_information[i].zone_ids.front(); task_history_reply_data_2->unknown16 = 0x00000000; reply = (char *) task_history_reply_data_2 + sizeof(TaskHistoryReplyData2_Struct); - VARSTRUCT_ENCODE_STRING(reply, p_task_data->activity_information[i].description_override.c_str()); + VARSTRUCT_ENCODE_STRING(reply, task_data->activity_information[i].description_override.c_str()); } } @@ -152,9 +153,9 @@ void ClientTaskState::EnableTask(int character_id, int task_count, int *task_lis } } - LogTasksDetail("[EnableTask] New enabled task list"); + LogTasksDetail("New enabled task list"); for (int enabled_task : m_enabled_tasks) { - LogTasksDetail("[EnableTask] enabled [{}] character_id [{}]", enabled_task, character_id); + LogTasksDetail("enabled [{}] character_id [{}]", enabled_task, character_id); } if (tasks_enabled.empty()) { @@ -172,7 +173,7 @@ void ClientTaskState::EnableTask(int character_id, int task_count, int *task_lis database.QueryDatabase(query); } else { - LogTasks("[EnableTask] Called for character_id [{}] but, no tasks exist", character_id); + LogTasks("Called for character_id [{}] but, no tasks exist", character_id); } } @@ -205,9 +206,9 @@ void ClientTaskState::DisableTask(int character_id, int task_count, int *task_li } } - LogTasks("[DisableTask] New enabled task list "); + LogTasks("New enabled task list "); for (int enabled_task : m_enabled_tasks) { - LogTasks("[DisableTask] enabled_tasks [{}]", enabled_task); + LogTasks("enabled_tasks [{}]", enabled_task); } if (tasks_disabled.empty()) { @@ -233,7 +234,7 @@ void ClientTaskState::DisableTask(int character_id, int task_count, int *task_li } else { LogTasks( - "[DisableTask] DisableTask called for character_id [{}] ... but, no tasks exist", + "DisableTask called for character_id [{}] ... but, no tasks exist", character_id ); } @@ -321,7 +322,7 @@ int ClientTaskState::CompletedTasksInSet(int task_set_id) return completed_tasks_count; } -bool ClientTaskState::HasSlotForTask(TaskInformation *task) +bool ClientTaskState::HasSlotForTask(const TaskInformation* task) { if (task == nullptr) { return false; @@ -357,7 +358,7 @@ int ClientTaskState::GetActiveTaskID(int index) static void DeleteCompletedTaskFromDatabase(int character_id, int task_id) { - LogTasks("[DeleteCompletedTasksFromDatabase] character_id [{}], task_id [{}]", character_id, task_id); + LogTasks("character_id [{}], task_id [{}]", character_id, task_id); CompletedTasksRepository::DeleteWhere( database, @@ -365,765 +366,454 @@ static void DeleteCompletedTaskFromDatabase(int character_id, int task_id) ); } -bool ClientTaskState::UnlockActivities(int character_id, ClientTaskInformation &task_info) +bool ClientTaskState::UnlockActivities(Client* client, ClientTaskInformation& task_info) { - bool all_activities_complete = true; - LogTasksDetail( - "[UnlockActivities] Fetching task info for character_id [{}] task [{}] slot [{}] current_step [{}] accepted_time [{}] updated [{}]", - character_id, + "Fetching task info for character_id [{}] task [{}] slot [{}] accepted_time [{}] updated [{}]", + client->CharacterID(), task_info.task_id, task_info.slot, - task_info.current_step, task_info.accepted_time, task_info.updated ); - TaskInformation *p_task_data = task_manager->m_task_data[task_info.task_id]; - if (p_task_data == nullptr) { + const auto task = task_manager->GetTaskData(task_info.task_id); + if (!task) + { return true; } - for (int i = 0; i < p_task_data->activity_count; i++) { + for (int i = 0; i < task->activity_count; ++i) + { if (task_info.activity[i].activity_id >= 0) { LogTasksDetail( - "[UnlockActivities] character_id [{}] task [{}] activity_id [{}] done_count [{}] activity_state [{}] updated [{}] sequence [{}]", - character_id, + "character_id [{}] task [{}] activity_id [{}] done_count [{}] activity_state [{}] updated [{}]", + client->CharacterID(), task_info.task_id, task_info.activity[i].activity_id, task_info.activity[i].done_count, task_info.activity[i].activity_state, - task_info.activity[i].updated, - p_task_data->sequence_mode + task_info.activity[i].updated ); } } - // On loading the client state, all activities that are not completed, are - // marked as hidden. For Sequential (non-stepped) mode, we mark the first - // activity_information as active if not complete. + auto res = Tasks::GetActiveElements(task->activity_information, task_info.activity, task->activity_count); - if (p_task_data->sequence_mode == ActivitiesSequential) { - if (task_info.activity[0].activity_state != ActivityCompleted) { - task_info.activity[0].activity_state = ActivityActive; - } - - // Enable the next Hidden task. - for (int i = 0; i < p_task_data->activity_count; i++) { - if ((task_info.activity[i].activity_state == ActivityActive) && - (!p_task_data->activity_information[i].optional)) { - all_activities_complete = false; - break; - } - - if (task_info.activity[i].activity_state == ActivityHidden) { - task_info.activity[i].activity_state = ActivityActive; - all_activities_complete = false; - break; - } - } - - if (all_activities_complete && RuleB(TaskSystem, RecordCompletedTasks)) { - if (RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { - LogTasks("KeepOneRecord enabled"); - auto iterator = m_completed_tasks.begin(); - int erased_elements = 0; - while (iterator != m_completed_tasks.end()) { - int task_id = (*iterator).task_id; - if (task_id == task_info.task_id) { - iterator = m_completed_tasks.erase(iterator); - erased_elements++; - } - else { - ++iterator; - } - } - - LogTasks("Erased Element count is [{}]", erased_elements); - - if (erased_elements) { - m_last_completed_task_loaded -= erased_elements; - DeleteCompletedTaskFromDatabase(character_id, task_info.task_id); - } - } - - if (p_task_data->type != TaskType::Shared) { - CompletedTaskInformation completed_task_information{}; - completed_task_information.task_id = task_info.task_id; - completed_task_information.completed_time = time(nullptr); - - for (int i = 0; i < p_task_data->activity_count; i++) { - completed_task_information.activity_done[i] = (task_info.activity[i].activity_state == - ActivityCompleted); - } - - m_completed_tasks.push_back(completed_task_information); - } - } - - LogTasks("Returning sequential task, AllActivitiesComplete is [{}]", all_activities_complete); - - return all_activities_complete; - } - - // Stepped Mode - // TODO: This code is probably more complex than it needs to be - - bool current_step_complete = true; - - LogTasks( - "[UnlockActivities] Current step [{}] last_step [{}]", - task_info.current_step, - p_task_data->last_step - ); - - // If current_step is -1, this is the first call to this method since loading the - // client state. Unlock all activities with a step number of 0 - - if (task_info.current_step == -1) { - for (int i = 0; i < p_task_data->activity_count; i++) { - - if (p_task_data->activity_information[i].step_number == 0 && - task_info.activity[i].activity_state == ActivityHidden) { - task_info.activity[i].activity_state = ActivityActive; - // task_info.activity_information[i].updated=true; - } - } - task_info.current_step = 0; - } - - for (int current_step = task_info.current_step; current_step <= p_task_data->last_step; current_step++) { - for (int activity = 0; activity < p_task_data->activity_count; activity++) { - if (p_task_data->activity_information[activity].step_number == (int) task_info.current_step) { - if ((task_info.activity[activity].activity_state != ActivityCompleted) && - (!p_task_data->activity_information[activity].optional)) { - current_step_complete = false; - all_activities_complete = false; - break; - } - } - } - if (!current_step_complete) { - break; - } - task_info.current_step++; - } - - if (all_activities_complete) { - if (RuleB(TaskSystem, RecordCompletedTasks)) { - // If we are only keeping one completed record per task, and the player has done - // the same task again, erase the previous completed entry for this task. - if (RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { - LogTasksDetail("[UnlockActivities] KeepOneRecord enabled"); - auto iterator = m_completed_tasks.begin(); - int erased_elements = 0; - - while (iterator != m_completed_tasks.end()) { - int task_id = (*iterator).task_id; - if (task_id == task_info.task_id) { - iterator = m_completed_tasks.erase(iterator); - erased_elements++; - } - else { - ++iterator; - } - } - - LogTasksDetail("[UnlockActivities] Erased Element count is [{}]", erased_elements); - - if (erased_elements) { - m_last_completed_task_loaded -= erased_elements; - DeleteCompletedTaskFromDatabase(character_id, task_info.task_id); - } - } - - if (p_task_data->type != TaskType::Shared) { - CompletedTaskInformation completed_task_information{}; - completed_task_information.task_id = task_info.task_id; - completed_task_information.completed_time = time(nullptr); - - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - completed_task_information.activity_done[activity_id] = - (task_info.activity[activity_id].activity_state == ActivityCompleted); - } - - m_completed_tasks.push_back(completed_task_information); - } - } - return true; - } - - // Mark all non-completed tasks in the current step as active - for (int activity = 0; activity < p_task_data->activity_count; activity++) { - LogTasksDetail( - "[UnlockActivities] - Debug task [{}] activity [{}] step_number [{}] current_step [{}]", - task_info.task_id, - activity, - p_task_data->activity_information[activity].step_number, - (int) task_info.current_step - - ); - - if ((p_task_data->activity_information[activity].step_number == (int) task_info.current_step) && - (task_info.activity[activity].activity_state == ActivityHidden)) { - - LogTasksDetail( - "[UnlockActivities] -- Debug task [{}] activity [{}] (ActivityActive)", - task_info.task_id, - activity - ); - - task_info.activity[activity].activity_state = ActivityActive; - task_info.activity[activity].updated = true; + for (int activity_id : res.active) + { + ClientActivityInformation& client_activity = task_info.activity[activity_id]; + if (client_activity.activity_state == ActivityHidden) + { + LogTasksDetail("task [{}] activity [{}] (ActivityActive)", task_info.task_id, activity_id); + client_activity.activity_state = ActivityActive; + client_activity.updated = true; } } - return false; + if (res.is_task_complete && RuleB(TaskSystem, RecordCompletedTasks)) + { + RecordCompletedTask(client->CharacterID(), *task, task_info); + } + + // check if client has an explore task in current zone to enable task explore processing + m_has_explore_task = HasExploreTask(client); + + return res.is_task_complete; } -bool ClientTaskState::UpdateTasksOnSpeakWith(Client *client, int npc_type_id) +void ClientTaskState::RecordCompletedTask(uint32_t character_id, const TaskInformation& task, const ClientTaskInformation& client_task) { - return UpdateTasksByNPC(client, TaskActivityType::SpeakWith, npc_type_id); + // If we are only keeping one completed record per task, and the player has done + // the same task again, erase the previous completed entry for this task. + if (RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) + { + size_t before = m_completed_tasks.size(); + + m_completed_tasks.erase(std::remove_if(m_completed_tasks.begin(), m_completed_tasks.end(), + [&](const CompletedTaskInformation& completed) { return completed.task_id == client_task.task_id; } + ), m_completed_tasks.end()); + + size_t erased = m_completed_tasks.size() - before; + + LogTasksDetail("KeepOneRecord erased [{}] elements", erased); + + if (erased > 0) + { + m_last_completed_task_loaded -= erased; + DeleteCompletedTaskFromDatabase(character_id, client_task.task_id); + } + } + + if (task.type != TaskType::Shared) + { + CompletedTaskInformation completed{}; + completed.task_id = client_task.task_id; + completed.completed_time = std::time(nullptr); + + for (int i = 0; i < task.activity_count; ++i) + { + completed.activity_done[i] = (client_task.activity[i].activity_state == ActivityCompleted); + } + + LogTasksDetail("[{}] for character [{}]", client_task.task_id, character_id); + m_completed_tasks.push_back(completed); + } } -bool ClientTaskState::UpdateTasksByNPC(Client *client, TaskActivityType activity_type, int npc_type_id) +const TaskInformation* ClientTaskState::GetTaskData(const ClientTaskInformation& client_task) const { + if (client_task.task_id == TASKSLOTEMPTY) + { + return nullptr; + } - int is_updating = false; + return task_manager->GetTaskData(client_task.task_id); +} - if (!HasActiveTasks()) { +bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter, int task_id, + const ActivityInformation& activity, const ClientActivityInformation& client_activity) const +{ + if (activity.goal_method == METHODQUEST && activity.goal_method != filter.method) + { return false; } - // loop over the union of tasks and quests - for (auto &active_task : m_active_tasks) { - auto current_task = &active_task; - if (current_task->task_id == TASKSLOTEMPTY) { - continue; - } + // todo: some tasks do allow hidden/unlocked elements to silently update + if (client_activity.activity_state != ActivityActive) + { + return false; + } - // Check if there are any active kill activities for this p_task_data - auto p_task_data = task_manager->m_task_data[current_task->task_id]; - if (p_task_data == nullptr) { + if (activity.activity_type != filter.type) + { + return false; + } + + if (activity.dz_switch_id != 0 && activity.dz_switch_id != filter.dz_switch_id) + { + return false; + } + + if (!activity.CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) + { + LogTasks("client [{}] task [{}]-[{}] failed zone filter", client->GetName(), task_id, client_activity.activity_id); + return false; + } + + if (activity.has_area && !filter.ignore_area && RuleB(TaskSystem, EnableTaskProximity)) + { + const glm::vec4& pos = filter.use_pos ? filter.pos : client->GetPosition(); + if (pos.x < activity.min_x || pos.x > activity.max_x || + pos.y < activity.min_y || pos.y > activity.max_y || + pos.z < activity.min_z || pos.z > activity.max_z) + { + LogTasksDetail("client [{}] task [{}]-[{}] failed area filter", client->GetName(), task_id, client_activity.activity_id); return false; } + } - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; + // item is only checked for updates that provide an item to check (unlike npc which may be null for non-npcs) + if (!activity.item_id_list.empty() && filter.item_id != 0 && + !Tasks::IsInMatchList(activity.item_id_list, std::to_string(filter.item_id))) + { + LogTasks("client [{}] task [{}]-[{}] failed item match filter", client->GetName(), task_id, client_activity.activity_id); + return false; + } - // We are not interested in completed or hidden activities - if (client_activity->activity_state != ActivityActive) { - continue; - } - // We are only interested in Kill activities - if (activity_info->activity_type != activity_type) { - continue; - } - // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { - LogTasks( - "[UPDATE] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check", - client->GetName(), - current_task->task_id, - activity_id, - static_cast(activity_type), - npc_type_id - ); - continue; - } - // Is the activity_information to kill this type of NPC ? - switch (activity_info->goal_method) { - case METHODSINGLEID: - if (activity_info->goal_id != npc_type_id) { - continue; - } - break; + // npc filter supports both npc names and ids in match lists + if (!activity.npc_match_list.empty() && (!filter.mob || + (!Tasks::IsInMatchListPartial(activity.npc_match_list, filter.mob->GetName()) && + !Tasks::IsInMatchListPartial(activity.npc_match_list, filter.mob->GetCleanName()) && + !Tasks::IsInMatchList(activity.npc_match_list, std::to_string(filter.mob->GetNPCTypeID()))))) + { + LogTasks("client [{}] task [{}]-[{}] failed npc match filter", client->GetName(), task_id, client_activity.activity_id); + return false; + } - case METHODLIST: - if (!task_manager->m_goal_list_manager.IsInList( - activity_info->goal_id, - npc_type_id - ) && !TaskGoalListManager::IsInMatchList( - activity_info->goal_match_list, - std::to_string(npc_type_id) - )) { - continue; - } - break; + return true; +} + +int ClientTaskState::UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count) +{ + if (!task_manager) + { + return 0; + } + + int max_updated = 0; + + for (const auto& client_task : m_active_tasks) + { + const auto task = GetTaskData(client_task); + if (!task) + { + continue; + } + + // legacy eqemu task update logic loops through group on kill of npc to update a single task + // shared tasks only require one client to receive an update to propagate + if (filter.type == TaskActivityType::Kill && task->type == TaskType::Shared && client != filter.exp_client) + { + continue; + } + + for (const ClientActivityInformation& client_activity : client_task.activity) + { + const ActivityInformation& activity = task->activity_information[client_activity.activity_id]; + + if (CanUpdate(client, filter, client_task.task_id, activity, client_activity)) + { + auto args = fmt::format("{} {} {}", count, client_activity.activity_id, client_task.task_id); + if (parse->EventPlayer(EVENT_TASK_BEFORE_UPDATE, client, args, 0) != 0) + { + LogTasks("client [{}] task [{}]-[{}] update prevented by quest", + client->GetName(), client_task.task_id, client_activity.activity_id); - default: - // If METHODQUEST, don't updated the activity_information here continue; + } + + LogTasks("client [{}] task [{}] activity [{}] increment [{}]", + client->GetName(), client_task.task_id, client_activity.activity_id, count); + + int updated = IncrementDoneCount(client, task, client_task.slot, client_activity.activity_id, count); + max_updated = std::max(max_updated, updated); + + if (RuleB(TaskSystem, UpdateOneElementPerTask)) + { + break; // only one element updated per task, move to next task + } } - // We found an active p_task_data to kill this type of NPC, so increment the done count - LogTasksDetail("Calling increment done count ByNPC"); - IncrementDoneCount(client, p_task_data, current_task->slot, activity_id); - is_updating = true; } } - return is_updating; + return max_updated; } -int ClientTaskState::ActiveSpeakTask(int npc_type_id) +std::pair ClientTaskState::FindTask(Client* client, const TaskUpdateFilter& filter) const { + if (!task_manager) + { + return std::make_pair(0, 0); + } + for (const auto& client_task : m_active_tasks) + { + const auto task = GetTaskData(client_task); + if (!task || (filter.task_id != 0 && client_task.task_id != filter.task_id)) + { + continue; + } + + for (const ClientActivityInformation& client_activity : client_task.activity) + { + const ActivityInformation& activity = task->activity_information[client_activity.activity_id]; + if (CanUpdate(client, filter, client_task.task_id, activity, client_activity)) + { + return std::make_pair(client_task.task_id, client_activity.activity_id); + } + } + } + + return std::make_pair(0, 0); +} + +bool ClientTaskState::HasExploreTask(Client* client) const +{ + TaskUpdateFilter filter{}; + filter.type = TaskActivityType::Explore; + filter.ignore_area = true; // we don't care if client is currently in the explore area + + auto result = FindTask(client, filter); + bool has_explore = result.first != 0; + + LogTasksDetail("client [{}] has explore task in current zone [{}]", client->GetName(), has_explore); + return has_explore; +} + +bool ClientTaskState::UpdateTasksOnSpeakWith(Client* client, NPC* npc) +{ + return UpdateTasksByNPC(client, TaskActivityType::SpeakWith, npc); +} + +bool ClientTaskState::UpdateTasksByNPC(Client* client, TaskActivityType type, NPC* npc) +{ + TaskUpdateFilter filter{}; + filter.type = type; + filter.mob = npc; + + return UpdateTasks(client, filter) > 0; +} + +int ClientTaskState::ActiveSpeakTask(Client* client, NPC* npc) +{ // This method is to be used from Perl quests only and returns the task_id of the first // active task found which has an active SpeakWith activity_information for this NPC. - if (!HasActiveTasks()) { - return 0; - } + TaskUpdateFilter filter{}; + filter.type = TaskActivityType::SpeakWith; + filter.mob = npc; + filter.method = METHODQUEST; - // loop over the union of tasks and quests - for (auto &active_task : m_active_tasks) { - auto current_task = &active_task; - if (current_task->task_id == TASKSLOTEMPTY) { - continue; - } - - TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; - if (p_task_data == nullptr) { - continue; - } - - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; - - // We are not interested in completed or hidden activities - if (client_activity->activity_state != ActivityActive) { - continue; - } - if (activity_info->activity_type != TaskActivityType::SpeakWith) { - continue; - } - // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { - continue; - } - // Is the activity_information to speak with this type of NPC ? - if (activity_info->goal_method == METHODQUEST && activity_info->goal_id == npc_type_id) { - return current_task->task_id; - } - } - } - - return 0; + auto result = FindTask(client, filter); + return result.first; // task id } -int ClientTaskState::ActiveSpeakActivity(int npc_type_id, int task_id) +int ClientTaskState::ActiveSpeakActivity(Client* client, NPC* npc, int task_id) { - // This method is to be used from Perl quests only and returns the activity_id of the first // active activity_information found in the specified task which is to SpeakWith this NPC. - if (!HasActiveTasks()) { - return -1; - } - if (task_id <= 0 || task_id >= MAXTASKS) { + + if (task_id <= 0) + { return -1; } - // loop over the union of tasks and quests - for (auto &active_task : m_active_tasks) { - auto current_task = &active_task; - if (current_task->task_id != task_id) { - continue; - } + TaskUpdateFilter filter{}; + filter.type = TaskActivityType::SpeakWith; + filter.mob = npc; + filter.method = METHODQUEST; + filter.task_id = task_id; - TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; - if (p_task_data == nullptr) { - continue; - } - - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; - - // We are not interested in completed or hidden activities - if (client_activity->activity_state != ActivityActive) { - continue; - } - if (activity_info->activity_type != TaskActivityType::SpeakWith) { - continue; - } - // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { - continue; - } - - // Is the activity_information to speak with this type of NPC ? - if (activity_info->goal_method == METHODQUEST && activity_info->goal_id == npc_type_id) { - return activity_id; - } - } - return 0; - } - return 0; + auto result = FindTask(client, filter); + return result.first != 0 ? result.second : -1; // activity id } -void ClientTaskState::UpdateTasksForItem(Client *client, TaskActivityType activity_type, int item_id, int count) +void ClientTaskState::UpdateTasksForItem(Client* client, TaskActivityType type, int item_id, int count) { // This method updates the client's task activities of the specified type which relate // to the specified item. // - // Type should be one of ActivityLoot, ActivityTradeSkill, ActivityFish or ActivityForage + // Type should be one of ActivityTradeSkill, ActivityFish or ActivityForage - // If the client has no tasks, there is nothing further to check. + LogTasks("activity_type [{}] item_id [{}] count [{}]", static_cast(type), item_id, count); - LogTasks( - "[UpdateTasksForItem] activity_type [{}] item_id [{}]", - static_cast(activity_type), - item_id - ); + TaskUpdateFilter filter{}; + filter.type = type; + filter.item_id = item_id; - if (!HasActiveTasks()) { - return; - } - - // loop over the union of tasks and quests - for (auto &active_task : m_active_tasks) { - auto current_task = &active_task; - if (current_task->task_id == TASKSLOTEMPTY) { - continue; - } - - // Check if there are any active loot activities for this task - - TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; - if (p_task_data == nullptr) { - return; - } - - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; - - // We are not interested in completed or hidden activities - if (client_activity->activity_state != ActivityActive) { - continue; - } - // We are only interested in the ActivityType we were called with - if (activity_info->activity_type != activity_type) { - continue; - } - // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { - LogTasks( - "[UpdateTasksForItem] Error: Character [{}] activity_information type [{}] for Item [{}] failed zone check", - client->GetName(), - static_cast(activity_type), - item_id - ); - continue; - } - // Is the activity_information related to this item ? - // - switch (activity_info->goal_method) { - - case METHODSINGLEID: - if (activity_info->goal_id != item_id) { continue; } - break; - - case METHODLIST: - if (!task_manager->m_goal_list_manager.IsInList( - activity_info->goal_id, - item_id - ) && !TaskGoalListManager::IsInMatchList( - activity_info->goal_match_list, - std::to_string(item_id) - )) { continue; } - break; - - default: - // If METHODQUEST, don't updated the activity_information here - continue; - } - // We found an active task related to this item, so increment the done count - LogTasksDetail("[UpdateTasksForItem] Calling increment done count ForItem"); - IncrementDoneCount(client, p_task_data, current_task->slot, activity_id, count); - } - } + UpdateTasks(client, filter, count); } -void ClientTaskState::UpdateTasksOnExplore(Client *client, int explore_id) +void ClientTaskState::UpdateTasksOnLoot(Client* client, Corpse* corpse, int item_id, int count) { - LogTasks("[UpdateTasksOnExplore] explore_id [{}]", explore_id); + LogTasks("corpse [{}] item_id [{}] count [{}]", corpse->GetName(), item_id, count); - if (!HasActiveTasks()) { - return; - } + TaskUpdateFilter filter{}; + filter.type = TaskActivityType::Loot; + filter.mob = corpse; + filter.item_id = item_id; - // loop over the union of tasks and quests - for (auto &active_task : m_active_tasks) { - auto current_task = &active_task; - if (current_task->task_id == TASKSLOTEMPTY) { - continue; - } - - // Check if there are any active explore activities for this task - - TaskInformation *task_data = task_manager->m_task_data[current_task->task_id]; - if (task_data == nullptr) { - return; - } - - for (int activity_id = 0; activity_id < task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &task_data->activity_information[activity_id]; - - // We are not interested in completed or hidden activities - if (client_activity->activity_state != ActivityActive) { - continue; - } - // We are only interested in explore activities - if (activity_info->activity_type != TaskActivityType::Explore) { - continue; - } - if (!activity_info->CheckZone(zone->GetZoneID())) { - LogTasks( - "[UpdateTasksOnExplore] character [{}] explore_id [{}] failed zone check", - client->GetName(), - explore_id - ); - continue; - } - // Is the activity_information to explore this area id ? - switch (activity_info->goal_method) { - - case METHODSINGLEID: - if (activity_info->goal_id != explore_id) { - continue; - } - break; - - case METHODLIST: - if (!task_manager->m_goal_list_manager.IsInList( - activity_info->goal_id, - explore_id - ) && !TaskGoalListManager::IsInMatchList( - activity_info->goal_match_list, - std::to_string(explore_id) - )) { - continue; - } - break; - - default: - // If METHODQUEST, don't updated the activity_information here - continue; - } - - // We found an active task to explore this area, so set done count to goal count - // (Only a goal count of 1 makes sense for explore activities?) - LogTasks( - "[UpdateTasksOnExplore] character [{}] explore_id [{}] increment on explore", - client->GetName(), - explore_id - ); - - IncrementDoneCount( - client, - task_data, - current_task->slot, - activity_id, - activity_info->goal_count - current_task->activity[activity_id].done_count - ); - } - } + UpdateTasks(client, filter, count); } -bool ClientTaskState::UpdateTasksOnDeliver( - Client *client, - std::list &items, - int cash, - int npc_type_id -) +void ClientTaskState::UpdateTasksOnExplore(Client* client, const glm::vec4& pos) { + LogTasksDetail("client [{}]", client->GetName()); + + TaskUpdateFilter filter{}; + filter.type = TaskActivityType::Explore; + filter.pos = pos; + filter.use_pos = true; + + UpdateTasks(client, filter); +} + +bool ClientTaskState::UpdateTasksOnDeliver(Client* client, std::vector& items, Trade& trade, NPC* npc) +{ + LogTasks("npc [{}]", npc->GetName()); + bool is_updated = false; - LogTasks("[UpdateTasksOnDeliver] [{}]", npc_type_id); + TaskUpdateFilter filter{}; + filter.mob = npc; - if (!HasActiveTasks()) { - return false; + int cash = trade.cp + (trade.sp * 10) + (trade.gp * 100) + (trade.pp * 1000); + if (cash != 0) + { + filter.type = TaskActivityType::GiveCash; + int updated_count = UpdateTasks(client, filter, cash); + if (updated_count > 0) + { + // todo: remove used coin and use Deliver with explicit coin fields instead of custom type + is_updated = true; + } } - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto current_task = &m_active_tasks[i]; - if (current_task->task_id == TASKSLOTEMPTY) { + filter.type = TaskActivityType::Deliver; + for (EQ::ItemInstance*& item : items) + { + // items may have gaps for unused trade slots + if (!item) + { continue; } - // Check if there are any active deliver activities for this task - TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; - if (p_task_data == nullptr) { - return false; - } + filter.item_id = item->GetID(); - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; - - // We are not interested in completed or hidden activities - if (client_activity->activity_state != ActivityActive) { - continue; - } - - // We are only interested in Deliver activities - if (activity_info->activity_type != TaskActivityType::Deliver && - activity_info->activity_type != TaskActivityType::GiveCash) { - continue; - } - // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { - Log( - Logs::General, Logs::Tasks, - "[UPDATE] Char: %s Deliver activity_information failed zone check (current zone %i, need zone " - "%s", - client->GetName(), zone->GetZoneID(), activity_info->zones.c_str()); - continue; - } - // Is the activity_information to deliver to this NPCTypeID ? - if (activity_info->deliver_to_npc != npc_type_id) { - continue; - } - // Is the activity_information related to these items ? - // - if ((activity_info->activity_type == TaskActivityType::GiveCash) && cash) { - LogTasks("[UpdateTasksOnDeliver] Increment on GiveCash"); - IncrementDoneCount(client, p_task_data, i, activity_id, cash); - is_updated = true; - } - else { - for (auto &item : items) { - switch (activity_info->goal_method) { - case METHODSINGLEID: - if (activity_info->goal_id != item->GetID()) { - continue; - } - break; - - case METHODLIST: - if (!task_manager->m_goal_list_manager.IsInList( - activity_info->goal_id, - item->GetID() - ) && !TaskGoalListManager::IsInMatchList( - activity_info->goal_match_list, - std::to_string(item->GetID()) - )) { - continue; - } - break; - - default: - // If METHODQUEST, don't updated the activity_information here - continue; - } - // We found an active task related to this item, so increment the done count - LogTasks("[UpdateTasksOnDeliver] Increment on GiveItem"); - IncrementDoneCount( - client, - p_task_data, - current_task->slot, - activity_id, - item->GetCharges() <= 0 ? 1 : item->GetCharges() - ); - is_updated = true; - } - } + int count = item->IsStackable() ? item->GetCharges() : 1; + int updated_count = UpdateTasks(client, filter, count); + if (updated_count > 0) + { + item->SetTaskDeliveredCount(updated_count); + is_updated = true; } } return is_updated; } -void ClientTaskState::UpdateTasksOnTouch(Client *client, int zone_id) +void ClientTaskState::UpdateTasksOnTouch(Client *client, int dz_switch_id) { - // If the client has no tasks, there is nothing further to check. + LogTasks("dz switch [{}] ", dz_switch_id); - LogTasks("[UpdateTasksOnTouch] [{}] ", zone_id); + TaskUpdateFilter filter{}; + filter.type = TaskActivityType::Touch; + filter.dz_switch_id = dz_switch_id; - if (!HasActiveTasks()) { - return; - } - - // loop over the union of tasks and quests - for (auto &active_task : m_active_tasks) { - auto current_task = &active_task; - if (current_task->task_id == TASKSLOTEMPTY) { - continue; - } - - // Check if there are any active explore activities for this task - TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; - if (p_task_data == nullptr) { - return; - } - - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; - - // We are not interested in completed or hidden activities - if (current_task->activity[activity_id].activity_state != ActivityActive) { - continue; - } - // We are only interested in touch activities - if (activity_info->activity_type != TaskActivityType::Touch) { - continue; - } - if (activity_info->goal_method != METHODSINGLEID) { - continue; - } - if (!activity_info->CheckZone(zone_id)) { - LogTasks( - "[UpdateTasksOnTouch] character [{}] Touch activity_information failed zone check", - client->GetName() - ); - continue; - } - - // We found an active task to zone into this zone, so set done count to goal count - // (Only a goal count of 1 makes sense for touch activities?) - LogTasks("[UpdateTasksOnTouch] Increment on Touch"); - IncrementDoneCount( - client, - p_task_data, - current_task->slot, - activity_id, - activity_info->goal_count - current_task->activity[activity_id].done_count - ); - } - } + UpdateTasks(client, filter); } -void ClientTaskState::IncrementDoneCount( +void ClientTaskState::UpdateTasksOnKill(Client* client, Client* exp_client, NPC* npc) +{ + TaskUpdateFilter filter{}; + filter.type = TaskActivityType::Kill; + filter.mob = npc; + filter.pos = npc->GetPosition(); // or should areas be filtered by client position? + filter.use_pos = true; + filter.exp_client = exp_client; + + UpdateTasks(client, filter); +} + +int ClientTaskState::IncrementDoneCount( Client *client, - TaskInformation *task_information, + const TaskInformation* task_data, int task_index, int activity_id, int count, bool ignore_quest_update ) { - auto info = GetClientTaskInfo(task_information->type, task_index); + auto info = GetClientTaskInfo(task_data->type, task_index); if (info == nullptr) { - return; + return 0; } LogTasks( - "[IncrementDoneCount] client [{}] task_id [{}] activity_id [{}] count [{}]", + "client [{}] task_id [{}] activity_id [{}] count [{}]", client->GetCleanName(), info->task_id, activity_id, count ); + int remaining = task_data->activity_information[activity_id].goal_count - info->activity[activity_id].done_count; + count = std::min(count, remaining); + // shared task shim // intercept and pass to world first before processing normally - if (!client->m_shared_task_update && task_information->type == TaskType::Shared) { + if (!client->m_shared_task_update && task_data->type == TaskType::Shared) { // struct auto pack = new ServerPacket(ServerOP_SharedTaskUpdate, sizeof(ServerSharedTaskActivityUpdate_Struct)); @@ -1137,7 +827,7 @@ void ClientTaskState::IncrementDoneCount( r->ignore_quest_update = ignore_quest_update; LogTasksDetail( - "[IncrementDoneCount] shared_task sending client [{}] task_id [{}] activity_id [{}] count [{}] ignore_quest_update [{}]", + "shared_task sending client [{}] task_id [{}] activity_id [{}] count [{}] ignore_quest_update [{}]", r->source_character_id, r->task_id, r->activity_id, @@ -1147,7 +837,7 @@ void ClientTaskState::IncrementDoneCount( SyncSharedTaskZoneClientDoneCountState( client, - task_information, + task_data->type, task_index, activity_id, r->done_count @@ -1157,15 +847,11 @@ void ClientTaskState::IncrementDoneCount( worldserver.SendPacket(pack); safe_delete(pack); - return; + return count; } info->activity[activity_id].done_count += count; - if (info->activity[activity_id].done_count > task_information->activity_information[activity_id].goal_count) { - info->activity[activity_id].done_count = task_information->activity_information[activity_id].goal_count; - } - if (!ignore_quest_update) { std::string export_string = fmt::format( "{} {} {}", @@ -1176,26 +862,37 @@ void ClientTaskState::IncrementDoneCount( parse->EventPlayer(EVENT_TASK_UPDATE, client, export_string, 0); } + if (task_data->type != TaskType::Shared) { + // live messages for each increment of non-shared tasks + auto activity_type = task_data->activity_information[activity_id].activity_type; + int msg_count = activity_type == TaskActivityType::GiveCash ? 1 : count; + for (int i = 0; i < msg_count; ++i) { + client->MessageString(Chat::DefaultText, TASK_UPDATED, task_data->title.c_str()); + } + } + info->activity[activity_id].updated = true; // Have we reached the goal count for this activity_information ? - if (info->activity[activity_id].done_count >= task_information->activity_information[activity_id].goal_count) { - LogTasks("[IncrementDoneCount] done_count [{}] goal_count [{}] activity_id [{}]", + if (info->activity[activity_id].done_count >= task_data->activity_information[activity_id].goal_count) { + LogTasks("done_count [{}] goal_count [{}] activity_id [{}]", info->activity[activity_id].done_count, - task_information->activity_information[activity_id].goal_count, + task_data->activity_information[activity_id].goal_count, activity_id ); // Flag the activity_information as complete info->activity[activity_id].activity_state = ActivityCompleted; // Unlock subsequent activities for this task - bool task_complete = UnlockActivities(client->CharacterID(), *info); - LogTasks("[IncrementDoneCount] task_complete is [{}]", task_complete); + bool task_complete = UnlockActivities(client, *info); + LogTasks("task_complete is [{}]", task_complete); + // shared tasks only send update messages on activity completion + if (task_data->type == TaskType::Shared) { + client->MessageString(Chat::DefaultText, TASK_UPDATED, task_data->title.c_str()); + } // and by the 'Task Stage Completed' message - client->SendTaskActivityComplete(info->task_id, activity_id, task_index, task_information->type); + client->SendTaskActivityComplete(info->task_id, activity_id, task_index, task_data->type); // Send the updated task/activity_information list to the client task_manager->SendSingleActiveTaskToClient(client, *info, task_complete, false); - // Inform the client the task has been updated, both by a chat message - client->MessageString(Chat::White, TASK_UPDATED, task_information->title.c_str()); if (!ignore_quest_update) { std::string export_string = fmt::format( @@ -1221,13 +918,12 @@ void ClientTaskState::IncrementDoneCount( // updated in UnlockActivities. Send the completed task list to the // client. This is the same sequence the packets are sent on live. if (task_complete) { - std::string export_string = fmt::format( - "{} {} {}", - info->activity[activity_id].done_count, - info->activity[activity_id].activity_id, - info->task_id - ); - parse->EventPlayer(EVENT_TASK_COMPLETE, client, export_string, 0); + // world adds timers for shared tasks + if (task_data->type != TaskType::Shared) { + AddReplayTimer(client, *info, *task_data); + } + + int event_res = DispatchEventTaskComplete(client, *info, activity_id); /* QS: PlayerLogTaskUpdates :: Complete */ if (RuleB(QueryServ, PlayerLogTaskUpdates)) { @@ -1241,26 +937,23 @@ void ClientTaskState::IncrementDoneCount( QServ->PlayerLogEvent(Player_Log_Task_Updates, client->CharacterID(), event_desc); } - client->SendTaskActivityComplete(info->task_id, 0, task_index, task_information->type, 0); - task_manager->SaveClientState(client, this); + client->SendTaskActivityComplete(info->task_id, 0, task_index, task_data->type, 0); // If Experience and/or cash rewards are set, reward them from the task even if reward_method is METHODQUEST - RewardTask(client, task_information); + // do not reward client if EVENT_TASK_COMPLETE returns non-zero + if (event_res == 0) + { + RewardTask(client, task_data, *info); + } //RemoveTask(c, TaskIndex); - // add replay timer (world adds timers to shared task members) - AddReplayTimer(client, *info, *task_information); - // shared tasks linger at the completion step and do not get removed from the task window unlike quests/task - if (task_information->type == TaskType::Shared) { - return; + if (task_data->type != TaskType::Shared) { + task_manager->SendCompletedTasksToClient(client, this); + + client->CancelTask(task_index, task_data->type); } - - task_manager->SendCompletedTasksToClient(client, this); - - client->CancelTask(task_index, task_information->type); } - } else { // Send an updated packet for this single activity_information @@ -1270,68 +963,86 @@ void ClientTaskState::IncrementDoneCount( activity_id, task_index ); - task_manager->SaveClientState(client, this); } + + task_manager->SaveClientState(client, this); + + return count; } -void ClientTaskState::RewardTask(Client *client, TaskInformation *task_information) +int ClientTaskState::DispatchEventTaskComplete(Client* client, ClientTaskInformation& info, int activity_id) { + std::string export_string = fmt::format( + "{} {} {}", + info.activity[activity_id].done_count, + info.activity[activity_id].activity_id, + info.task_id + ); + return parse->EventPlayer(EVENT_TASK_COMPLETE, client, export_string, 0); +} - if (!task_information || !client) { +void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTaskInformation& client_task) +{ + if (!ti || !c || client_task.was_rewarded) { return; } - if (!task_information->completion_emote.empty()) { - client->Message(Chat::Yellow, task_information->completion_emote.c_str()); + client_task.was_rewarded = true; + client_task.updated = true; + + if (!ti->completion_emote.empty()) { + c->Message(Chat::Yellow, ti->completion_emote.c_str()); } - const EQ::ItemData *item_data; - std::vector reward_list; + // TODO: this function should sometimes use QuestReward_Struct and CashReward_Struct + // assumption is they use QuestReward_Struct when there is more than 1 thing getting rewarded + if (ti->reward_method != METHODQUEST) { + for (const auto &i: Strings::Split(ti->reward_id_list, "|")) { + // handle charges + int16 charges = -1; + uint32 item_id = Strings::IsNumber(i) ? std::stoi(i) : 0; + if (Strings::Contains(i, ",")) { + auto s = Strings::Split(i, ","); + if (!s.empty() && s.size() == 2) { + item_id = Strings::IsNumber(s[0]) ? std::stoi(s[0]) : 0; + charges = Strings::IsNumber(s[1]) ? std::stoi(s[1]) : 0; + } + } - switch (task_information->reward_method) { - case METHODSINGLEID: { - if (task_information->reward_id) { - client->SummonItem(task_information->reward_id); - item_data = database.GetItem(task_information->reward_id); - if (item_data) { - client->MessageString(Chat::Yellow, YOU_HAVE_BEEN_GIVEN, item_data->Name); + if (item_id > 0) { + std::unique_ptr inst(database.CreateItem(item_id, charges)); + if (inst && inst->GetItem()) { + bool stacked = c->TryStacking(inst.get()); + if (!stacked) { + int16_t slot = c->GetInv().FindFreeSlot(inst->IsClassBag(), true, inst->GetItem()->Size); + c->SummonItem(item_id, charges, 0, 0, 0, 0, 0, 0, false, slot); + } + c->MessageString(Chat::Yellow, YOU_HAVE_BEEN_GIVEN, inst->GetItem()->Name); } } - break; - } - case METHODLIST: { - reward_list = task_manager->m_goal_list_manager.GetListContents(task_information->reward_id); - for (int item_id : reward_list) { - client->SummonItem(item_id); - item_data = database.GetItem(item_id); - if (item_data) { - client->MessageString(Chat::Yellow, YOU_HAVE_BEEN_GIVEN, item_data->Name); - } - } - break; - } - default: { - // Nothing special done for METHODQUEST - break; } } // just use normal NPC faction ID stuff - if (task_information->faction_reward) { - client->SetFactionLevel( - client->CharacterID(), - task_information->faction_reward, - client->GetBaseClass(), - client->GetBaseRace(), - client->GetDeity() + if (ti->faction_reward && ti->faction_amount == 0) { + c->SetFactionLevel( + c->CharacterID(), + ti->faction_reward, + c->GetBaseClass(), + c->GetBaseRace(), + c->GetDeity() + ); + } else if (ti->faction_reward != 0 && ti->faction_amount != 0) { + c->RewardFaction( + ti->faction_reward, + ti->faction_amount ); } - if (task_information->cash_reward) { + if (ti->cash_reward) { int platinum, gold, silver, copper; - copper = task_information->cash_reward; - client->AddMoneyToPP(copper, true); + copper = ti->cash_reward; platinum = copper / 1000; copper = copper - (platinum * 1000); @@ -1340,66 +1051,29 @@ void ClientTaskState::RewardTask(Client *client, TaskInformation *task_informati silver = copper / 10; copper = copper - (silver * 10); - std::string cash_message; + c->CashReward(copper, silver, gold, platinum); + } - if (platinum > 0) { - cash_message = "You receive "; - cash_message += itoa(platinum); - cash_message += " platinum"; - } - if (gold > 0) { - if (cash_message.length() == 0) { - cash_message = "You receive "; - } - else { - cash_message += ","; - } - cash_message += itoa(gold); - cash_message += " gold"; - } - if (silver > 0) { - if (cash_message.length() == 0) { - cash_message = "You receive "; - } - else { - cash_message += ","; - } - cash_message += itoa(silver); - cash_message += " silver"; - } - if (copper > 0) { - if (cash_message.length() == 0) { - cash_message = "You receive "; - } - else { - cash_message += ","; - } - cash_message += itoa(copper); - cash_message += " copper"; - } - cash_message += " pieces."; - client->Message(Chat::Yellow, cash_message.c_str()); - } - int32 experience_reward = task_information->experience_reward; + auto experience_reward = ti->experience_reward; if (experience_reward > 0) { - client->AddEXP(experience_reward); - } - if (experience_reward < 0) { + c->AddEXP(experience_reward); + } else if (experience_reward < 0) { uint32 pos_reward = experience_reward * -1; // Minimal Level Based Exp reward Setting is 101 (1% exp at level 1) if (pos_reward > 100 && pos_reward < 25700) { uint8 max_level = pos_reward / 100; uint8 exp_percent = pos_reward - (max_level * 100); - client->AddLevelBasedExp(exp_percent, max_level); + c->AddLevelBasedExp(exp_percent, max_level); } } - if (task_information->reward_radiant_crystals > 0 || task_information->reward_ebon_crystals > 0) - { - client->AddCrystals(task_information->reward_radiant_crystals, task_information->reward_ebon_crystals); + if (ti->reward_points > 0) { + if (ti->reward_point_type == static_cast(zone->GetCurrencyID(RADIANT_CRYSTAL))) { + c->AddCrystals(ti->reward_points, 0); + } else if (ti->reward_point_type == static_cast(zone->GetCurrencyID(EBON_CRYSTAL))) { + c->AddCrystals(0, ti->reward_points); + } } - - client->SendSound(); } bool ClientTaskState::IsTaskActive(int task_id) @@ -1428,7 +1102,7 @@ bool ClientTaskState::IsTaskActive(int task_id) void ClientTaskState::FailTask(Client *client, int task_id) { LogTasks( - "[FailTask] Failing task for character [{}] task_id [{}] task_count [{}]", + "Failing task for character [{}] task_id [{}] task_count [{}]", client->GetCleanName(), task_id, m_active_task_count @@ -1443,16 +1117,12 @@ void ClientTaskState::FailTask(Client *client, int task_id) return; } - // type: Shared Task + // type: Shared Task (failed via world for all members) if (m_active_shared_task.task_id == task_id) { - client->SendTaskFailed(task_id, TASKSLOTSHAREDTASK, TaskType::Shared); - // Remove the task from the client - client->CancelTask(TASKSLOTSHAREDTASK, TaskType::Shared); + task_manager->EndSharedTask(*client, task_id, true); return; } - // TODO: shared tasks - if (m_active_task_count == 0) { return; } @@ -1467,10 +1137,9 @@ void ClientTaskState::FailTask(Client *client, int task_id) } } -// TODO: Shared tasks bool ClientTaskState::IsTaskActivityActive(int task_id, int activity_id) { - LogTasks("[IsTaskActivityActive] task_id [{}] activity_id [{}]", task_id, activity_id); + LogTasks("task_id [{}] activity_id [{}]", task_id, activity_id); // Quick sanity check if (activity_id < 0) { @@ -1512,20 +1181,18 @@ bool ClientTaskState::IsTaskActivityActive(int task_id, int activity_id) return false; } - TaskInformation *p_task_data = task_manager->m_task_data[info->task_id]; - - // The task is invalid - if (p_task_data == nullptr) { + const auto task_data = task_manager->GetTaskData(info->task_id); + if (!task_data) { return false; } // The activity_id is out of range - if (activity_id >= p_task_data->activity_count) { + if (activity_id >= task_data->activity_count) { return false; } LogTasks( - "[IsTaskActivityActive] (Update) task_id [{}] activity_id [{}] activity_state [{}]", + "(Update) task_id [{}] activity_id [{}] activity_state [{}]", task_id, activity_id, info->activity[activity_id].activity_state @@ -1585,15 +1252,13 @@ void ClientTaskState::UpdateTaskActivity( return; } - TaskInformation *p_task_data = task_manager->m_task_data[info->task_id]; - - // The task is invalid - if (p_task_data == nullptr) { + const auto task_data = task_manager->GetTaskData(info->task_id); + if (!task_data) { return; } // The activity_id is out of range - if (activity_id >= p_task_data->activity_count) { + if (activity_id >= task_data->activity_count) { return; } @@ -1609,7 +1274,7 @@ void ClientTaskState::UpdateTaskActivity( count ); - IncrementDoneCount(client, p_task_data, active_task_index, activity_id, count, ignore_quest_update); + IncrementDoneCount(client, task_data, active_task_index, activity_id, count, ignore_quest_update); } void ClientTaskState::ResetTaskActivity(Client *client, int task_id, int activity_id) @@ -1657,13 +1322,13 @@ void ClientTaskState::ResetTaskActivity(Client *client, int task_id, int activit return; } - TaskInformation *p_task_data = task_manager->m_task_data[info->task_id]; - if (p_task_data == nullptr) { + const auto task_data = task_manager->GetTaskData(info->task_id); + if (!task_data) { return; } // The activity_id is out of range - if (activity_id >= p_task_data->activity_count) { + if (activity_id >= task_data->activity_count) { return; } @@ -1681,7 +1346,7 @@ void ClientTaskState::ResetTaskActivity(Client *client, int task_id, int activit IncrementDoneCount( client, - p_task_data, + task_data, active_task_index, activity_id, (info->activity[activity_id].done_count * -1), @@ -1691,7 +1356,7 @@ void ClientTaskState::ResetTaskActivity(Client *client, int task_id, int activit void ClientTaskState::ShowClientTaskInfoMessage(ClientTaskInformation *task, Client *c) { - auto task_data = task_manager->m_task_data[task->task_id]; + const auto task_data = task_manager->GetTaskData(task->task_id); c->Message(Chat::White, "------------------------------------------------"); c->Message( @@ -1718,14 +1383,13 @@ void ClientTaskState::ShowClientTaskInfoMessage(ClientTaskInformation *task, Cli std::vector update_saylinks; for (auto &increment: update_increments) { - auto task_update_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + auto task_update_saylink = Saylink::Silent( fmt::format( "#task update {} {} {}", task->task_id, task->activity[activity_id].activity_id, increment ), - false, increment ); @@ -1740,7 +1404,7 @@ void ClientTaskState::ShowClientTaskInfoMessage(ClientTaskInformation *task, Cli task->activity[activity_id].done_count, task->activity[activity_id].activity_state, Tasks::GetActivityStateDescription(task->activity[activity_id].activity_state), - implode(" | ", update_saylinks) + Strings::Implode(" | ", update_saylinks) ).c_str() ); } @@ -1785,16 +1449,16 @@ int ClientTaskState::TaskTimeLeft(int task_id) if (m_active_task.task_id == task_id) { int time_now = time(nullptr); - TaskInformation *p_task_data = task_manager->m_task_data[task_id]; - if (p_task_data == nullptr) { + const auto task_data = task_manager->GetTaskData(task_id); + if (!task_data) { return -1; } - if (!p_task_data->duration) { + if (!task_data->duration) { return -1; } - int time_left = (m_active_task.accepted_time + p_task_data->duration - time_now); + int time_left = (m_active_task.accepted_time + task_data->duration - time_now); return (time_left > 0 ? time_left : 0); } @@ -1803,16 +1467,16 @@ int ClientTaskState::TaskTimeLeft(int task_id) if (m_active_shared_task.task_id == task_id) { int time_now = time(nullptr); - TaskInformation *p_task_data = task_manager->m_task_data[task_id]; - if (p_task_data == nullptr) { + const auto task_data = task_manager->GetTaskData(task_id); + if (!task_data) { return -1; } - if (!p_task_data->duration) { + if (!task_data->duration) { return -1; } - int time_left = (m_active_shared_task.accepted_time + p_task_data->duration - time_now); + int time_left = (m_active_shared_task.accepted_time + task_data->duration - time_now); return (time_left > 0 ? time_left : 0); } @@ -1828,16 +1492,16 @@ int ClientTaskState::TaskTimeLeft(int task_id) int time_now = time(nullptr); - TaskInformation *p_task_data = task_manager->m_task_data[active_quest.task_id]; - if (p_task_data == nullptr) { + const auto task_data = task_manager->GetTaskData(active_quest.task_id); + if (!task_data) { return -1; } - if (!p_task_data->duration) { + if (!task_data->duration) { return -1; } - int time_left = (active_quest.accepted_time + p_task_data->duration - time_now); + int time_left = (active_quest.accepted_time + task_data->duration - time_now); // If Timeleft is negative, return 0, else return the number of seconds left @@ -1859,7 +1523,7 @@ int ClientTaskState::IsTaskCompleted(int task_id) } for (auto &completed_task : m_completed_tasks) { - LogTasks("[IsTaskCompleted] Comparing compelted task [{}] with [{}]", completed_task.task_id, task_id); + LogTasks("Comparing compelted task [{}] with [{}]", completed_task.task_id, task_id); if (completed_task.task_id == task_id) { return 1; } @@ -1877,13 +1541,13 @@ bool ClientTaskState::TaskOutOfTime(TaskType task_type, int index) } // make sure the task_id is at least maybe in our array - if (info->task_id <= 0 || info->task_id >= MAXTASKS) { + if (info->task_id <= 0) { return false; } - int time_now = time(nullptr); - TaskInformation *task_data = task_manager->m_task_data[info->task_id]; - if (task_data == nullptr) { + int time_now = time(nullptr); + const auto task_data = task_manager->GetTaskData(info->task_id); + if (!task_data) { return false; } @@ -1892,6 +1556,7 @@ bool ClientTaskState::TaskOutOfTime(TaskType task_type, int index) void ClientTaskState::TaskPeriodicChecks(Client *client) { + // shared task expiration is handled by world // type "task" if (m_active_task.task_id != TASKSLOTEMPTY) { @@ -1907,20 +1572,6 @@ void ClientTaskState::TaskPeriodicChecks(Client *client) } } - // type "shared" - if (m_active_shared_task.task_id != TASKSLOTEMPTY) { - if (TaskOutOfTime(TaskType::Shared, TASKSLOTSHAREDTASK)) { - // Send Red Task Failed Message - client->SendTaskFailed(m_active_shared_task.task_id, TASKSLOTSHAREDTASK, TaskType::Shared); - // Remove the task from the client - client->CancelTask(TASKSLOTSHAREDTASK, TaskType::Shared); - // It is a conscious decision to only fail one task per call to this method, - // otherwise the player will not see all the failed messages where multiple - // tasks fail at the same time. - return; - } - } - if (m_active_task_count == 0) { return; } @@ -1943,15 +1594,6 @@ void ClientTaskState::TaskPeriodicChecks(Client *client) break; } } - - // Check for activities that require zoning into a specific zone. - // This is done in this method because it gives an extra few seconds for the client screen to display - // the zone before we send the 'Task activity_information Completed' message. - // - if (!m_checked_touch_activities) { - UpdateTasksOnTouch(client, zone->GetZoneID()); - m_checked_touch_activities = true; - } } bool ClientTaskState::IsTaskActivityCompleted(TaskType task_type, int index, int activity_id) @@ -2007,7 +1649,7 @@ ActivityState ClientTaskState::GetTaskActivityState(TaskType task_type, int inde } LogTasksDetail( - "-- [GetTaskActivityState] task_type [{}] ({}) index [{}] activity_id [{}] activity_state [{}] ({})", + "-- task_type [{}] ({}) index [{}] activity_id [{}] activity_state [{}] ({})", Tasks::GetTaskTypeIdentifier(task_type), Tasks::GetTaskTypeDescription(task_type), index, @@ -2102,7 +1744,9 @@ void ClientTaskState::CancelAllTasks(Client *client) m_active_task.task_id = TASKSLOTEMPTY; // shared task + client->m_requested_shared_task_removal = true; CancelTask(client, TASKSLOTSHAREDTASK, TaskType::Shared, false); + client->m_requested_shared_task_removal = false; m_active_shared_task.task_id = TASKSLOTEMPTY; // "quests" @@ -2111,8 +1755,6 @@ void ClientTaskState::CancelAllTasks(Client *client) CancelTask(client, task_index, TaskType::Quest, false); m_active_quests[task_index].task_id = TASKSLOTEMPTY; } - - // TODO: shared } void ClientTaskState::CancelTask(Client *c, int sequence_number, TaskType task_type, bool remove_from_db) @@ -2124,12 +1766,12 @@ void ClientTaskState::CancelTask(Client *c, int sequence_number, TaskType task_t if (!c->m_requested_shared_task_removal && task_type == TaskType::Shared && m_active_shared_task.task_id != 0) { // struct - auto pack = new ServerPacket(ServerOP_SharedTaskAttemptRemove, sizeof(ServerSharedTaskAttemptRemove_Struct)); - auto *r = (ServerSharedTaskAttemptRemove_Struct *) pack->pBuffer; + auto pack = new ServerPacket(ServerOP_SharedTaskQuit, sizeof(ServerSharedTaskQuit_Struct)); + auto *r = (ServerSharedTaskQuit_Struct *) pack->pBuffer; // fill r->requested_character_id = c->CharacterID(); - r->requested_task_id = m_active_shared_task.task_id; + r->task_id = m_active_shared_task.task_id; r->remove_from_db = remove_from_db; // send @@ -2154,6 +1796,7 @@ void ClientTaskState::CancelTask(Client *c, int sequence_number, TaskType task_t // persistence if (remove_from_db) { RemoveTask(c, sequence_number, task_type); + m_has_explore_task = HasExploreTask(c); } } @@ -2172,7 +1815,7 @@ void ClientTaskState::KickPlayersSharedTask(Client* client) void ClientTaskState::RemoveTask(Client *client, int sequence_number, TaskType task_type) { int character_id = client->CharacterID(); - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState Cancel Task %i ", sequence_number); + Log(Logs::General, Logs::Tasks, "ClientTaskState Cancel Task %i ", sequence_number); int task_id = -1; switch (task_type) { @@ -2226,14 +1869,14 @@ void ClientTaskState::RemoveTaskByTaskID(Client *client, uint32 task_id) switch (task_manager->GetTaskType(task_id)) { case TaskType::Task: { if (m_active_task.task_id == task_id) { - LogTasks("[UPDATE] RemoveTaskByTaskID found Task [{}]", task_id); + LogTasks("RemoveTaskByTaskID found Task [{}]", task_id); CancelTask(client, TASKSLOTTASK, TaskType::Task, true); } break; } case TaskType::Shared: { if (m_active_shared_task.task_id == task_id) { - LogTasks("[UPDATE] RemoveTaskByTaskID found Shared Task [{}]", task_id); + LogTasks("RemoveTaskByTaskID found Shared Task [{}]", task_id); CancelTask(client, TASKSLOTSHAREDTASK, TaskType::Shared, true); } break; @@ -2241,7 +1884,7 @@ void ClientTaskState::RemoveTaskByTaskID(Client *client, uint32 task_id) case TaskType::Quest: { for (int active_quest = 0; active_quest < MAXACTIVEQUESTS; active_quest++) { if (m_active_quests[active_quest].task_id == task_id) { - LogTasks("[UPDATE] RemoveTaskByTaskID found Quest [{}] at index [{}]", task_id, active_quest); + LogTasks("RemoveTaskByTaskID found Quest [{}] at index [{}]", task_id, active_quest); CancelTask(client, active_quest, TaskType::Quest, true); } } @@ -2260,13 +1903,13 @@ void ClientTaskState::AcceptNewTask( bool enforce_level_requirement ) { - if (!task_manager || task_id < 0 || task_id >= MAXTASKS) { + if (!task_manager || task_id < 0) { client->Message(Chat::Red, "Task system not functioning, or task_id %i out of range.", task_id); return; } - auto task = task_manager->m_task_data[task_id]; - if (task == nullptr) { + const auto task = task_manager->GetTaskData(task_id); + if (!task) { client->Message(Chat::Red, "Invalid task_id %i", task_id); return; } @@ -2275,7 +1918,7 @@ void ClientTaskState::AcceptNewTask( // intercept and pass to world first before processing normally if (!client->m_requesting_shared_task && task->type == TaskType::Shared) { LogTasksDetail( - "[AcceptNewTask] Initiating shared_task request | task_id [{}] character_id [{}] name [{}]", + "Initiating shared_task request | task_id [{}] character_id [{}] name [{}]", task_id, client->CharacterID(), client->GetCleanName() @@ -2348,8 +1991,19 @@ void ClientTaskState::AcceptNewTask( if (task->type != TaskType::Shared) { auto task_timers = CharacterTaskTimersRepository::GetWhere(database, fmt::format( - "character_id = {} AND task_id = {} AND expire_time > NOW() ORDER BY timer_type ASC LIMIT 1", - client->CharacterID(), task_id + SQL( + character_id = {} + AND (task_id = {} + OR (timer_group > 0 AND timer_type = {} AND timer_group = {}) + OR (timer_group > 0 AND timer_type = {} AND timer_group = {})) + AND expire_time > NOW() ORDER BY timer_type ASC LIMIT 1 + ), + client->CharacterID(), + task_id, + static_cast(TaskTimerType::Replay), + task->replay_timer_group, + static_cast(TaskTimerType::Request), + task->request_timer_group )); if (!task_timers.empty()) @@ -2361,16 +2015,14 @@ void ClientTaskState::AcceptNewTask( auto mins = fmt::format_int((seconds / 60) % 60).str(); // these solo task messages are in SharedTaskMessage for convenience - namespace EQStr = SharedTaskMessage; if (timer_type == TaskTimerType::Replay) { - int eqstr_id = EQStr::TASK_ASSIGN_WAIT_REPLAY_TIMER; - client->MessageString(Chat::Red, eqstr_id, days.c_str(), hours.c_str(), mins.c_str()); + client->MessageString(Chat::Red, TaskStr::ASSIGN_REPLAY_TIMER, days.c_str(), hours.c_str(), mins.c_str()); } else if (timer_type == TaskTimerType::Request) { - int eqstr_id = EQStr::TASK_ASSIGN_WAIT_REQUEST_TIMER; - client->Message(Chat::Red, fmt::format(EQStr::GetEQStr(eqstr_id), days, hours, mins).c_str()); + auto eqstr = TaskStr::Get(TaskStr::ASSIGN_REQUEST_TIMER); + client->Message(Chat::Red, fmt::format(fmt::runtime(eqstr), days, hours, mins).c_str()); } return; @@ -2395,7 +2047,7 @@ void ClientTaskState::AcceptNewTask( case TaskType::Quest: for (int task_index = 0; task_index < MAXACTIVEQUESTS; task_index++) { Log(Logs::General, Logs::Tasks, - "[UPDATE] ClientTaskState Looking for free slot in slot %i, found task_id of %i", task_index, + "ClientTaskState Looking for free slot in slot %i, found task_id of %i", task_index, m_active_quests[task_index].task_id); if (m_active_quests[task_index].task_id == 0) { active_slot = &m_active_quests[task_index]; @@ -2417,16 +2069,16 @@ void ClientTaskState::AcceptNewTask( active_slot->task_id = task_id; active_slot->accepted_time = static_cast(accept_time); active_slot->updated = true; - active_slot->current_step = -1; + active_slot->was_rewarded = false; - for (int activity_id = 0; activity_id < task_manager->m_task_data[task_id]->activity_count; activity_id++) { + for (int activity_id = 0; activity_id < task->activity_count; activity_id++) { active_slot->activity[activity_id].activity_id = activity_id; active_slot->activity[activity_id].done_count = 0; active_slot->activity[activity_id].activity_state = ActivityHidden; active_slot->activity[activity_id].updated = true; } - UnlockActivities(client->CharacterID(), *active_slot); + UnlockActivities(client, *active_slot); if (task->type == TaskType::Quest) { m_active_task_count++; @@ -2446,13 +2098,14 @@ void ClientTaskState::AcceptNewTask( timer.character_id = client->CharacterID(); timer.task_id = task_id; timer.timer_type = static_cast(TaskTimerType::Request); + timer.timer_group = task->request_timer_group; timer.expire_time = expire_time; CharacterTaskTimersRepository::InsertOne(database, timer); } client->Message(Chat::Yellow, fmt::format( - SharedTaskMessage::GetEQStr(SharedTaskMessage::RECEIVED_REQUEST_TIMER), + TaskStr::Get(TaskStr::RECEIVED_REQUEST_TIMER), task->title, fmt::format_int(seconds / 86400).c_str(), // days fmt::format_int((seconds / 3600) % 24).c_str(), // hours @@ -2463,7 +2116,7 @@ void ClientTaskState::AcceptNewTask( task_manager->SendSingleActiveTaskToClient(client, *active_slot, false, true); client->StartTaskRequestCooldownTimer(); - client->MessageString(Chat::White, YOU_ASSIGNED_TASK, task->title.c_str()); + client->MessageString(Chat::DefaultText, YOU_ASSIGNED_TASK, task->title.c_str()); task_manager->SaveClientState(client, this); std::string export_string = std::to_string(task_id); @@ -2476,6 +2129,10 @@ void ClientTaskState::AcceptNewTask( void ClientTaskState::ProcessTaskProximities(Client *client, float x, float y, float z) { + if (!m_has_explore_task) { + return; + } + float last_x = client->ProximityX(); float last_y = client->ProximityY(); float last_z = client->ProximityZ(); @@ -2484,19 +2141,7 @@ void ClientTaskState::ProcessTaskProximities(Client *client, float x, float y, f return; } - LogTasksDetail("[ProcessTaskProximities] Checking proximities for Position x[{}] y[{}] z[{}]", x, y, z); - int explore_id = task_manager->m_proximity_manager.CheckProximities(x, y, z); - if (explore_id > 0) { - LogTasksDetail( - "[ProcessTaskProximities] Position x[{}] y[{}] z[{}] is within proximity explore_id [{}]", - x, - y, - z, - explore_id - ); - - UpdateTasksOnExplore(client, explore_id); - } + UpdateTasksOnExplore(client, glm::vec4(x, y, z, 0.0f)); } void ClientTaskState::SharedTaskIncrementDoneCount( @@ -2507,7 +2152,7 @@ void ClientTaskState::SharedTaskIncrementDoneCount( bool ignore_quest_update ) { - TaskInformation *t = task_manager->m_task_data[task_id]; + const auto t = task_manager->GetTaskData(task_id); auto info = GetClientTaskInfo(t->type, TASKSLOTSHAREDTASK); if (info == nullptr) { @@ -2518,7 +2163,7 @@ void ClientTaskState::SharedTaskIncrementDoneCount( info->activity[activity_id].done_count = done_count; LogTasksDetail( - "[SharedTaskIncrementDoneCount] Setting task_id [{}] to absolute done_count value of [{}] via increment [{}]", + "Setting task_id [{}] to absolute done_count value of [{}] via increment [{}]", task_id, info->activity[activity_id].done_count, done_count @@ -2546,7 +2191,7 @@ bool ClientTaskState::HasActiveSharedTask() void ClientTaskState::CreateTaskDynamicZone(Client* client, int task_id, DynamicZone& dz_request) { - auto task = task_manager->m_task_data[task_id]; + const auto task = task_manager->GetTaskData(task_id); if (!task) { return; @@ -2554,7 +2199,7 @@ void ClientTaskState::CreateTaskDynamicZone(Client* client, int task_id, Dynamic // dz should be named the version-based zone name (used in choose zone window and dz window on live) auto zone_info = zone_store.GetZone(dz_request.GetZoneID(), dz_request.GetZoneVersion()); - dz_request.SetName(zone_info.long_name.empty() ? task->title : zone_info.long_name); + dz_request.SetName(zone_info->long_name.empty() ? task->title : zone_info->long_name); dz_request.SetMinPlayers(task->min_players); dz_request.SetMaxPlayers(task->max_players); @@ -2605,7 +2250,7 @@ void ClientTaskState::CreateTaskDynamicZone(Client* client, int task_id, Dynamic void ClientTaskState::ListTaskTimers(Client* client) { - LogTasksDetail("[ListTaskTimers] Client [{}]", client->GetCleanName()); + LogTasksDetail("Client [{}]", client->GetCleanName()); // this isn't live-like but we need to throttle query (alternative is caching timers) if (!client->m_list_task_timers_rate_limit.Check()) { @@ -2622,7 +2267,7 @@ void ClientTaskState::ListTaskTimers(Client* client) for (const auto& task_timer : character_task_timers) { - auto task = task_manager->m_task_data[task_timer.task_id]; + const auto task = task_manager->GetTaskData(task_timer.task_id); if (task) { auto timer_type = static_cast(task_timer.timer_type); @@ -2633,26 +2278,25 @@ void ClientTaskState::ListTaskTimers(Client* client) if (timer_type == TaskTimerType::Replay) { - client->MessageString(Chat::Yellow, SharedTaskMessage::REPLAY_TIMER_REMAINING, + client->MessageString(Chat::Yellow, TaskStr::REPLAY_TIMER_REMAINING, task->title.c_str(), days.c_str(), hours.c_str(), mins.c_str()); } else { - auto eqstr = SharedTaskMessage::GetEQStr(SharedTaskMessage::REQUEST_TIMER_REMAINING); - client->Message(Chat::Yellow, fmt::format(eqstr, task->title, days, hours, mins).c_str()); + auto eqstr = TaskStr::Get(TaskStr::REQUEST_TIMER_REMAINING); + client->Message(Chat::Yellow, fmt::format(fmt::runtime(eqstr), task->title, days, hours, mins).c_str()); } } } if (character_task_timers.empty()) { - client->MessageString(Chat::Yellow, SharedTaskMessage::YOU_NO_CURRENT_REPLAY_TIMERS); + client->MessageString(Chat::Yellow, TaskStr::NO_REPLAY_TIMERS); } } -void ClientTaskState::AddReplayTimer(Client* client, ClientTaskInformation& client_task, TaskInformation& task) +void ClientTaskState::AddReplayTimer(Client* client, ClientTaskInformation& client_task, const TaskInformation& task) { - // world adds timers for shared tasks and handles messages - if (task.type != TaskType::Shared && task.replay_timer_seconds > 0) + if (task.replay_timer_seconds > 0) { // solo task replay timers are based on completion time auto expire_time = std::time(nullptr) + task.replay_timer_seconds; @@ -2660,13 +2304,22 @@ void ClientTaskState::AddReplayTimer(Client* client, ClientTaskInformation& clie auto timer = CharacterTaskTimersRepository::NewEntity(); timer.character_id = client->CharacterID(); timer.task_id = client_task.task_id; - timer.expire_time = expire_time; timer.timer_type = static_cast(TaskTimerType::Replay); + timer.timer_group = task.replay_timer_group; + timer.expire_time = expire_time; + + // replace any existing replay timer + CharacterTaskTimersRepository::DeleteWhere(database, fmt::format( + "(task_id = {} OR (timer_group > 0 AND timer_group = {})) AND timer_type = {} AND character_id = {}", + client_task.task_id, + task.replay_timer_group, + static_cast(TaskTimerType::Replay), + client->CharacterID())); CharacterTaskTimersRepository::InsertOne(database, timer); client->Message(Chat::Yellow, fmt::format( - SharedTaskMessage::GetEQStr(SharedTaskMessage::RECEIVED_REPLAY_TIMER), + TaskStr::Get(TaskStr::RECEIVED_REPLAY_TIMER), task.title, fmt::format_int(task.replay_timer_seconds / 86400).c_str(), // days fmt::format_int((task.replay_timer_seconds / 3600) % 24).c_str(), // hours @@ -2693,7 +2346,7 @@ void ClientTaskState::AddReplayTimer(Client* client, ClientTaskInformation& clie // zone-level before sending updates to world void ClientTaskState::SyncSharedTaskZoneClientDoneCountState( Client *p_client, - TaskInformation *p_information, + TaskType type, int task_index, int activity_id, uint32 done_count @@ -2702,13 +2355,13 @@ void ClientTaskState::SyncSharedTaskZoneClientDoneCountState( for (auto &e : entity_list.GetClientList()) { auto c = e.second; if (c->GetSharedTaskId() == p_client->GetSharedTaskId()) { - auto t = c->GetTaskState()->GetClientTaskInfo(p_information->type, task_index); + auto t = c->GetTaskState()->GetClientTaskInfo(type, task_index); if (t == nullptr) { continue; } LogTasksDetail( - "[IncrementDoneCount] Setting internally client [{}] to donecount [{}]", + "Setting internally client [{}] to donecount [{}]", c->GetCleanName(), done_count ); @@ -2743,3 +2396,60 @@ bool ClientTaskState::HasActiveTasks() return false; } + +void ClientTaskState::LockSharedTask(Client* client, bool lock) +{ + if (m_active_shared_task.task_id != TASKSLOTEMPTY) + { + ServerPacket pack(ServerOP_SharedTaskLock, sizeof(ServerSharedTaskLock_Struct)); + auto buf = reinterpret_cast(pack.pBuffer); + buf->source_character_id = client->CharacterID(); + buf->task_id = m_active_shared_task.task_id; + buf->lock = lock; + + worldserver.SendPacket(&pack); + } +} + +void ClientTaskState::EndSharedTask(Client* client, bool send_fail) +{ + if (task_manager && m_active_shared_task.task_id != TASKSLOTEMPTY) + { + task_manager->EndSharedTask(*client, m_active_shared_task.task_id, send_fail); + } +} +bool ClientTaskState::CanAcceptNewTask(Client* client, int task_id, int npc_entity_id) const +{ + auto it = std::find_if(m_last_offers.begin(), m_last_offers.end(), + [&](const TaskOffer& offer) { return offer.task_id == task_id; }); + + if (it == m_last_offers.end()) + { + LogTasks("Client [{}] accepted unoffered task [{}]", client->GetName(), task_id); + return false; + } + + if (npc_entity_id != it->npc_entity_id) + { + LogTasks("Client [{}] accepted task [{}] with wrong npc entity id [{}] vs offered [{}]", + client->GetName(), task_id, npc_entity_id, it->npc_entity_id); + return false; + } + + NPC* npc = entity_list.GetID(it->npc_entity_id)->CastToNPC(); + if (!npc) // client window disappears in this case + { + LogTasks("Client [{}] accepted task [{}] from missing npc", client->GetName(), task_id); + return false; + } + + auto dist = npc->CalculateDistance(client->GetX(), client->GetY(), client->GetZ()); + if (dist > MAX_TASK_SELECT_DISTANCE) + { + LogTasks("Client [{}] accepted task [{}] from npc [{}] out of range [{}]", + client->GetName(), task_id, npc->GetCleanName(), dist); + return false; + } + + return true; +} diff --git a/zone/task_client_state.h b/zone/task_client_state.h index b8aa03667..f1c1d6009 100644 --- a/zone/task_client_state.h +++ b/zone/task_client_state.h @@ -8,6 +8,28 @@ #include #include +constexpr float MAX_TASK_SELECT_DISTANCE = 60.0f; // client closes window at this distance + +struct TaskOffer +{ + int task_id; + uint16_t npc_entity_id; +}; + +struct TaskUpdateFilter +{ + int task_id = 0; + int dz_switch_id = 0; + uint32_t item_id = 0; + glm::vec4 pos; + bool use_pos = false; // if true uses pos instead of client position for area filters + bool ignore_area = false; // if true, area check is disabled + Mob* mob = nullptr; + Client* exp_client = nullptr; // used by Kill tasks to filter shared task updates + TaskActivityType type = TaskActivityType::None; + TaskMethodType method = TaskMethodType::METHODSINGLEID; +}; + class ClientTaskState { public: @@ -33,29 +55,35 @@ public: void CancelAllTasks(Client *client); void RemoveTask(Client *client, int sequence_number, TaskType task_type); void RemoveTaskByTaskID(Client *client, uint32 task_id); - bool UpdateTasksByNPC(Client *client, TaskActivityType activity_type, int npc_type_id); - void UpdateTasksForItem(Client *client, TaskActivityType activity_type, int item_id, int count = 1); - void UpdateTasksOnExplore(Client *client, int explore_id); - bool UpdateTasksOnSpeakWith(Client *client, int npc_type_id); - bool UpdateTasksOnDeliver(Client *client, std::list &items, int cash, int npc_type_id); - void UpdateTasksOnTouch(Client *client, int zone_id); + bool UpdateTasksByNPC(Client* client, TaskActivityType type, NPC* npc); + void UpdateTasksForItem(Client* client, TaskActivityType type, int item_id, int count = 1); + void UpdateTasksOnLoot(Client* client, Corpse* corpse, int item_id, int count = 1); + void UpdateTasksOnExplore(Client* client, const glm::vec4& loc); + bool UpdateTasksOnSpeakWith(Client* client, NPC* npc); + bool UpdateTasksOnDeliver(Client* client, std::vector& items, Trade& trade, NPC* npc); + void UpdateTasksOnTouch(Client *client, int dz_switch_id); void ProcessTaskProximities(Client *client, float x, float y, float z); bool TaskOutOfTime(TaskType task_type, int index); void TaskPeriodicChecks(Client *client); void SendTaskHistory(Client *client, int task_index); - void RewardTask(Client *client, TaskInformation *task_information); + void RewardTask(Client* c, const TaskInformation* ti, ClientTaskInformation& client_task); void EnableTask(int character_id, int task_count, int *task_list); void DisableTask(int character_id, int task_count, int *task_list); bool IsTaskEnabled(int task_id); int EnabledTaskCount(int task_set_id); - int ActiveSpeakTask(int npc_type_id); - int ActiveSpeakActivity(int npc_type_id, int task_id); + int ActiveSpeakTask(Client* client, NPC* npc); + int ActiveSpeakActivity(Client* client, NPC* npc, int task_id); int ActiveTasksInSet(int task_set_id); int CompletedTasksInSet(int task_set_id); - bool HasSlotForTask(TaskInformation *task); + bool HasSlotForTask(const TaskInformation* task); void CreateTaskDynamicZone(Client* client, int task_id, DynamicZone& dz); void ListTaskTimers(Client* client); void KickPlayersSharedTask(Client* client); + void LockSharedTask(Client* client, bool lock); + void ClearLastOffers() { m_last_offers.clear(); } + bool CanAcceptNewTask(Client* client, int task_id, int npc_entity_id) const; + bool HasExploreTask(Client* client) const; + void EndSharedTask(Client* client, bool send_fail); inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; } @@ -74,18 +102,28 @@ public: bool HasActiveSharedTask(); private: - void AddReplayTimer(Client *client, ClientTaskInformation& client_task, TaskInformation& task); + const TaskInformation* GetTaskData(const ClientTaskInformation& client_task) const; - void IncrementDoneCount( + void AddOffer(int task_id, uint16_t npc_entity_id) { m_last_offers.push_back({task_id, npc_entity_id}); }; + void AddReplayTimer(Client *client, ClientTaskInformation& client_task, const TaskInformation& task); + bool CanUpdate(Client* client, const TaskUpdateFilter& filter, int task_id, + const ActivityInformation& activity, const ClientActivityInformation& client_activity) const; + int DispatchEventTaskComplete(Client* client, ClientTaskInformation& client_task, int activity_id); + std::pair FindTask(Client* client, const TaskUpdateFilter& filter) const; + void RecordCompletedTask(uint32_t character_id, const TaskInformation& task, const ClientTaskInformation& client_task); + void UpdateTasksOnKill(Client* client, Client* exp_client, NPC* npc); + int UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count = 1); + + int IncrementDoneCount( Client *client, - TaskInformation *task_information, + const TaskInformation* task_data, int task_index, int activity_id, int count = 1, bool ignore_quest_update = false ); - bool UnlockActivities(int character_id, ClientTaskInformation &task_info); + bool UnlockActivities(Client* client, ClientTaskInformation& task_info); inline ClientTaskInformation *GetClientTaskInfo(TaskType task_type, int index) { @@ -128,13 +166,14 @@ private: std::vector m_enabled_tasks; std::vector m_completed_tasks; int m_last_completed_task_loaded; - bool m_checked_touch_activities; + std::vector m_last_offers; + bool m_has_explore_task = false; static void ShowClientTaskInfoMessage(ClientTaskInformation *task, Client *c); void SyncSharedTaskZoneClientDoneCountState( Client *p_client, - TaskInformation *p_information, + TaskType type, int task_index, int activity_id, uint32 done_count @@ -142,5 +181,4 @@ private: bool HasActiveTasks(); }; - #endif //EQEMU_TASK_CLIENT_STATE_H diff --git a/zone/task_goal_list_manager.cpp b/zone/task_goal_list_manager.cpp deleted file mode 100644 index 927099181..000000000 --- a/zone/task_goal_list_manager.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/repositories/goallists_repository.h" -#include "../common/rulesys.h" -#include "client.h" -#include "mob.h" -#include "quest_parser_collection.h" -#include "task_goal_list_manager.h" -#include "tasks.h" -#include "zonedb.h" - -TaskGoalListManager::TaskGoalListManager() -{ - m_goal_lists_count = 0; -} - -TaskGoalListManager::~TaskGoalListManager() {} - -bool TaskGoalListManager::LoadLists() -{ - m_task_goal_lists.clear(); - m_goal_lists_count = 0; - - std::string query = "SELECT `listid`, COUNT(`entry`) FROM `goallists` GROUP by `listid` ORDER BY `listid`"; - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - m_goal_lists_count = results.RowCount(); - LogTasks("Loaded [{}] GoalLists", m_goal_lists_count); - - m_task_goal_lists.reserve(m_goal_lists_count); - - int list_index = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - int list_id = atoi(row[0]); - int list_size = atoi(row[1]); - - m_task_goal_lists.push_back({list_id, 0, 0}); - - m_task_goal_lists[list_index].GoalItemEntries.reserve(list_size); - - list_index++; - } - - auto goal_lists = GoallistsRepository::GetWhere(content_db, "TRUE ORDER BY listid, entry ASC"); - for (list_index = 0; list_index < m_goal_lists_count; list_index++) { - - int list_id = m_task_goal_lists[list_index].ListID; - - for (auto &entry: goal_lists) { - if (entry.listid == list_id) { - if (entry.entry < m_task_goal_lists[list_index].Min) { - m_task_goal_lists[list_index].Min = entry.entry; - } - - if (entry.entry > m_task_goal_lists[list_index].Max) { - m_task_goal_lists[list_index].Max = entry.entry; - } - - m_task_goal_lists[list_index].GoalItemEntries.push_back(entry.entry); - - LogTasksDetail( - "Goal list index [{}] loading list [{}] entry [{}]", - list_index, - list_id, - entry.entry - ); - } - } - } - - return true; - -} - -int TaskGoalListManager::GetListByID(int list_id) -{ - - // Find the list with the specified ListID and return the index - auto it = std::find_if( - m_task_goal_lists.begin(), - m_task_goal_lists.end(), - [list_id](const TaskGoalList_Struct &t) { return t.ListID == list_id; } - ); - - if (it == m_task_goal_lists.end()) { - return -1; - } - - return std::distance(m_task_goal_lists.begin(), it); -} - -int TaskGoalListManager::GetFirstEntry(int list_id) -{ - int list_by_id = GetListByID(list_id); - - if ((list_by_id < 0) || (list_by_id >= m_goal_lists_count)) { - return -1; - } - - if (m_task_goal_lists[list_by_id].GoalItemEntries.empty()) { - return -1; - } - - return m_task_goal_lists[list_by_id].GoalItemEntries[0]; -} - -std::vector TaskGoalListManager::GetListContents(int list_index) -{ - std::vector list_contents; - int list_by_id = GetListByID(list_index); - - if ((list_by_id < 0) || (list_by_id >= m_goal_lists_count)) { - return list_contents; - } - - list_contents = m_task_goal_lists[list_by_id].GoalItemEntries; - - return list_contents; -} - -bool TaskGoalListManager::IsInList(int list_id, int entry) -{ - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i)", list_id, entry); - - int list_index = GetListByID(list_id); - - if ((list_index < 0) || (list_index >= m_goal_lists_count)) { - return false; - } - - if ((entry < m_task_goal_lists[list_index].Min) || (entry > m_task_goal_lists[list_index].Max)) { - return false; - } - - int first_entry = 0; - auto &task = m_task_goal_lists[list_index]; - auto it = std::find(task.GoalItemEntries.begin(), task.GoalItemEntries.end(), entry); - - if (it == task.GoalItemEntries.end()) { - return false; - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i) returning true", list_index, entry); - - return true; -} - -bool TaskGoalListManager::IsInMatchList(const std::string& match_list, const std::string& entry) -{ - for (auto &s: SplitString(match_list, '|')) { - if (s == entry) { - return true; - } - } - - return false; -} - -bool TaskGoalListManager::IsInMatchListPartial(const std::string &match_list, const std::string &entry) -{ - std::string entry_match = str_tolower(entry); - for (auto &s: SplitString(match_list, '|')) { - if (entry_match.find(str_tolower(s)) != std::string::npos) { - return true; - } - } - - return false; -} diff --git a/zone/task_goal_list_manager.h b/zone/task_goal_list_manager.h deleted file mode 100644 index b9c825123..000000000 --- a/zone/task_goal_list_manager.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef EQEMU_TASK_GOAL_LIST_MANAGER_H -#define EQEMU_TASK_GOAL_LIST_MANAGER_H - -#include "tasks.h" -#include "../common/types.h" -#include -#include -#include -#include - -struct TaskGoalList_Struct { - int ListID; - int Min, Max; - std::vector GoalItemEntries; -}; - -// This is used for handling lists, loading them from the database, searching them. -// Used for lists of NPCs to kill, items to loot, etc, as well as lists of items to -// reward the player with on completion of the task. -class TaskGoalListManager { - -public: - TaskGoalListManager(); - ~TaskGoalListManager(); - bool LoadLists(); - int GetListByID(int list_id); - bool IsInList(int list_id, int entry); - int GetFirstEntry(int list_id); - std::vector GetListContents(int list_index); - static bool IsInMatchList(const std::string& match_list, const std::string& entry); - static bool IsInMatchListPartial(const std::string& match_list, const std::string& entry); - -private: - std::vector m_task_goal_lists; - int m_goal_lists_count; -}; - - -#endif //EQEMU_TASK_GOAL_LIST_MANAGER_H diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 01c654eaa..2d61f6b7d 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -8,31 +8,17 @@ #include "../common/repositories/tasks_repository.h" #include "../common/repositories/tasksets_repository.h" #include "client.h" +#include "dynamic_zone.h" #include "string_ids.h" #include "task_manager.h" #include "../common/repositories/shared_task_activity_state_repository.h" +#include "../common/repositories/shared_task_dynamic_zones_repository.h" #include "../common/repositories/shared_task_members_repository.h" #include "../common/shared_tasks.h" #include "worldserver.h" extern WorldServer worldserver; -TaskManager::TaskManager() -{ - for (auto &task : m_task_data) { - task = nullptr; - } -} - -TaskManager::~TaskManager() -{ - for (auto &task : m_task_data) { - if (task != nullptr) { - safe_delete(task); - } - } -} - bool TaskManager::LoadTaskSets() { // Clear all task sets in memory. Done so we can reload them on the fly if required by just calling @@ -44,108 +30,102 @@ bool TaskManager::LoadTaskSets() auto rows = TasksetsRepository::GetWhere( content_db, fmt::format( - "`id` > 0 AND `id` < {} AND `taskid` >= 0 AND `taskid` < {} ORDER BY `id`, `taskid` ASC", - MAXTASKSETS, - MAXTASKS + "`id` > 0 AND `id` < {} AND `taskid` >= 0 ORDER BY `id`, `taskid` ASC", + MAXTASKSETS ) ); for (auto &task_set: rows) { m_task_sets[task_set.id].push_back(task_set.taskid); - LogTasksDetail("[LoadTaskSets] Adding task_id [{}] to task_set [{}]", task_set.taskid, task_set.id); + LogTasksDetail("Adding task_id [{}] to task_set [{}]", task_set.taskid, task_set.id); } return true; } -void TaskManager::ReloadGoalLists() -{ - if (!m_goal_list_manager.LoadLists()) { - Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadLists failed"); - } -} - bool TaskManager::LoadTasks(int single_task) { std::string task_query_filter = fmt::format("id = {}", single_task); std::string query; if (single_task == 0) { - if (!m_goal_list_manager.LoadLists()) { - LogTasks("[TaskManager::LoadTasks] LoadLists failed"); - } - if (!LoadTaskSets()) { - LogTasks("[TaskManager::LoadTasks] LoadTaskSets failed"); + LogTasks("LoadTaskSets failed"); } - task_query_filter = fmt::format("id < {}", MAXTASKS); + task_query_filter = fmt::format("id > 0"); } // load task level data auto repo_tasks = TasksRepository::GetWhere(content_db, task_query_filter); + m_task_data.reserve(repo_tasks.size()); for (auto &task: repo_tasks) { int task_id = task.id; - if ((task_id <= 0) || (task_id >= MAXTASKS)) { + if (task_id <= 0) { // This shouldn't happen, as the SELECT is bounded by MAXTASKS - LogError("[TASKS]Task ID [{}] out of range while loading tasks from database", task_id); + LogError("Task ID [{}] out of range while loading tasks from database", task_id); continue; } // load task data - m_task_data[task_id] = new TaskInformation(); - m_task_data[task_id]->type = static_cast(task.type); - m_task_data[task_id]->duration = task.duration; - m_task_data[task_id]->duration_code = static_cast(task.duration_code); - m_task_data[task_id]->title = task.title; - m_task_data[task_id]->description = task.description; - m_task_data[task_id]->reward = task.reward; - m_task_data[task_id]->reward_id = task.rewardid; - m_task_data[task_id]->cash_reward = task.cashreward; - m_task_data[task_id]->experience_reward = task.xpreward; - m_task_data[task_id]->reward_method = (TaskMethodType) task.rewardmethod; - m_task_data[task_id]->reward_radiant_crystals = task.reward_radiant_crystals; - m_task_data[task_id]->reward_ebon_crystals = task.reward_ebon_crystals; - m_task_data[task_id]->faction_reward = task.faction_reward; - m_task_data[task_id]->min_level = task.minlevel; - m_task_data[task_id]->max_level = task.maxlevel; - m_task_data[task_id]->level_spread = task.level_spread; - m_task_data[task_id]->min_players = task.min_players; - m_task_data[task_id]->max_players = task.max_players; - m_task_data[task_id]->repeatable = task.repeatable; - m_task_data[task_id]->completion_emote = task.completion_emote; - m_task_data[task_id]->replay_timer_seconds = task.replay_timer_seconds; - m_task_data[task_id]->request_timer_seconds = task.request_timer_seconds; - m_task_data[task_id]->activity_count = 0; - m_task_data[task_id]->sequence_mode = ActivitiesSequential; - m_task_data[task_id]->last_step = 0; + TaskInformation ti{}; + ti.type = static_cast(task.type); + ti.duration = task.duration; + ti.duration_code = static_cast(task.duration_code); + ti.title = task.title; + ti.description = task.description; + ti.reward = task.reward_text; + ti.reward_id_list = task.reward_id_list; + ti.cash_reward = task.cash_reward; + ti.experience_reward = task.exp_reward; + ti.reward_method = (TaskMethodType) task.reward_method; + ti.reward_points = task.reward_points; + ti.reward_point_type = task.reward_point_type; + ti.faction_reward = task.faction_reward; + ti.faction_amount = task.faction_amount; + ti.min_level = task.min_level; + ti.max_level = task.max_level; + ti.level_spread = task.level_spread; + ti.min_players = task.min_players; + ti.max_players = task.max_players; + ti.repeatable = task.repeatable; + ti.completion_emote = task.completion_emote; + ti.replay_timer_group = task.replay_timer_group; + ti.replay_timer_seconds = task.replay_timer_seconds; + ti.request_timer_group = task.request_timer_group; + ti.request_timer_seconds = task.request_timer_seconds; + ti.activity_count = 0; + + m_task_data.try_emplace(task_id, std::move(ti)); LogTasksDetail( - "[LoadTasks] (Task) task_id [{}] type [{}] () duration [{}] duration_code [{}] title [{}] description [{}] " - " reward [{}] rewardid [{}] cashreward [{}] xpreward [{}] rewardmethod [{}] faction_reward [{}] minlevel [{}] " - " maxlevel [{}] level_spread [{}] min_players [{}] max_players [{}] repeatable [{}] completion_emote [{}]", - " replay_timer_seconds [{}] request_timer_seconds [{}]", + "(Task) task_id [{}] type [{}] () duration [{}] duration_code [{}] title [{}] description [{}] " + " reward_text [{}] reward_id_list [{}] cash_reward [{}] exp_reward [{}] reward_method [{}] faction_reward [{}] min_level [{}] " + " max_level [{}] level_spread [{}] min_players [{}] max_players [{}] repeatable [{}] completion_emote [{}]" + " replay_group [{}] replay_timer_seconds [{}] request_group [{}] request_timer_seconds [{}]", task.id, task.type, task.duration, task.duration_code, task.title, task.description, - task.reward, - task.rewardid, - task.cashreward, - task.xpreward, - task.rewardmethod, + task.reward_text, + task.reward_id_list, + task.cash_reward, + task.exp_reward, + task.reward_method, task.faction_reward, - task.minlevel, - task.maxlevel, + task.min_level, + task.max_level, task.level_spread, task.min_players, task.max_players, task.repeatable, task.completion_emote, + task.replay_timer_group, task.replay_timer_seconds, + task.request_timer_group, task.request_timer_seconds ); } @@ -161,33 +141,33 @@ bool TaskManager::LoadTasks(int single_task) // if loading only a single task if (single_task == 0) { activities_query_filter = fmt::format( - "taskid < {} and activityid < {} ORDER BY taskid, activityid ASC", - MAXTASKS, + "activityid < {} ORDER BY taskid, activityid ASC", MAXACTIVITIESPERTASK ); } // load activity data auto task_activities = TaskActivitiesRepository::GetWhere(content_db, activities_query_filter); - for (auto &task_activity: task_activities) { - int task_id = task_activity.taskid; - int step = task_activity.step; - int activity_id = task_activity.activityid; + for (auto &a: task_activities) { + int task_id = a.taskid; + int step = a.step; + int activity_id = a.activityid; - if ((task_id <= 0) || (task_id >= MAXTASKS) || (activity_id < 0) || (activity_id >= MAXACTIVITIESPERTASK)) { + if (task_id <= 0 || activity_id < 0 || activity_id >= MAXACTIVITIESPERTASK) { // This shouldn't happen, as the SELECT is bounded by MAXTASKS LogTasks( - "[LoadTasks] Error: Task or activity_information ID ([{}], [{}]) out of range while loading activities from database", + "Error: Task or activity_information ID ([{}], [{}]) out of range while loading activities from database", task_id, activity_id ); continue; } - if (m_task_data[task_id] == nullptr) { + auto task_data = GetTaskData(task_id); + if (!task_data) { LogTasks( - "[LoadTasks] Error: activity_information for non-existent task ([{}], [{}]) while loading activities from database", + "Error: activity_information for non-existent task ([{}], [{}]) while loading activities from database", task_id, activity_id ); @@ -195,81 +175,88 @@ bool TaskManager::LoadTasks(int single_task) } // create pointer to activity data since declarations get unruly long - int activity_index = m_task_data[task_id]->activity_count; - ActivityInformation *activity_data = &m_task_data[task_id]->activity_information[activity_index]; - - m_task_data[task_id]->activity_information[m_task_data[task_id]->activity_count].step_number = step; - - if (step != 0) { - m_task_data[task_id]->sequence_mode = ActivitiesStepped; - } - - if (step > m_task_data[task_id]->last_step) { - m_task_data[task_id]->last_step = step; - } + int activity_index = task_data->activity_count; + ActivityInformation *ad = &task_data->activity_information[activity_index]; // Task Activities MUST be numbered sequentially from 0. If not, log an error // and set the task to nullptr. Subsequent activities for this task will raise // ERR_NOTASK errors. // Change to (activityID != (Tasks[taskID]->activity_count + 1)) to index from 1 - if (activity_id != m_task_data[task_id]->activity_count) { + if (activity_id != task_data->activity_count) { LogTasks( - "[LoadTasks] Error: Activities for Task [{}] (activity_id [{}]) are not sequential starting at 0. Not loading task ", + "Error: Activities for Task [{}] (activity_id [{}]) are not sequential starting at 0. Not loading task ", task_id, activity_id ); - m_task_data[task_id] = nullptr; + m_task_data.erase(task_id); continue; } // set activity data - activity_data->activity_type = static_cast(task_activity.activitytype); - activity_data->target_name = task_activity.target_name; - activity_data->item_list = task_activity.item_list; - activity_data->skill_list = task_activity.skill_list; - activity_data->skill_id = std::stoi(task_activity.skill_list); // for older clients - activity_data->spell_list = task_activity.spell_list; - activity_data->spell_id = std::stoi(task_activity.spell_list); // for older clients - activity_data->description_override = task_activity.description_override; - activity_data->goal_id = task_activity.goalid; - activity_data->goal_method = (TaskMethodType) task_activity.goalmethod; - activity_data->goal_match_list = task_activity.goal_match_list; - activity_data->goal_count = task_activity.goalcount; - activity_data->deliver_to_npc = task_activity.delivertonpc; + ad->req_activity_id = a.req_activity_id; + ad->step = step; + ad->activity_type = static_cast(a.activitytype); + ad->target_name = a.target_name; + ad->item_list = a.item_list; + ad->skill_list = a.skill_list; + ad->skill_id = Strings::IsNumber(a.skill_list) ? std::stoi(a.skill_list) : 0; // for older clients + ad->spell_list = a.spell_list; + ad->spell_id = Strings::IsNumber(a.spell_list) ? std::stoi(a.spell_list) : 0; // for older clients + ad->description_override = a.description_override; + ad->npc_match_list = a.npc_match_list; + ad->item_id_list = a.item_id_list; + ad->dz_switch_id = a.dz_switch_id; + ad->goal_method = (TaskMethodType) a.goalmethod; + ad->goal_count = a.goalcount; + ad->min_x = a.min_x; + ad->min_y = a.min_y; + ad->min_z = a.min_z; + ad->max_x = a.max_x; + ad->max_y = a.max_y; + ad->max_z = a.max_z; + ad->zone_version = a.zone_version >= 0 ? a.zone_version : -1; + ad->has_area = false; + + if (std::abs(a.max_x - a.min_x) > 0.0f && + std::abs(a.max_y - a.min_y) > 0.0f && + std::abs(a.max_z - a.min_z) > 0.0f) + { + ad->has_area = true; + } // zones - activity_data->zones = task_activity.zones; - auto zones = SplitString( - task_activity.zones, + ad->zones = a.zones; + auto zones = Strings::Split( + a.zones, ';' ); for (auto &&e : zones) { - activity_data->zone_ids.push_back(std::stoi(e)); + if (Strings::IsNumber(e)) { + ad->zone_ids.push_back(std::stoi(e)); + } } - activity_data->optional = task_activity.optional; + ad->optional = a.optional; LogTasksDetail( - "[LoadTasks] (Activity) task_id [{}] activity_id [{}] slot [{}] activity_type [{}] goal_id [{}] goal_method [{}] goal_count [{}] zones [{}]" - " target_name [{}] item_list [{}] skill_list [{}] spell_list [{}] description_override [{}] sequence [{}]", + "(Activity) task_id [{}] activity_id [{}] slot [{}] activity_type [{}] goal_method [{}] goal_count [{}] zones [{}]" + " target_name [{}] item_list [{}] skill_list [{}] spell_list [{}] description_override [{}]", task_id, activity_id, - m_task_data[task_id]->activity_count, - static_cast(activity_data->activity_type), - activity_data->goal_id, - activity_data->goal_method, - activity_data->goal_count, - activity_data->zones.c_str(), - activity_data->target_name.c_str(), - activity_data->item_list.c_str(), - activity_data->skill_list.c_str(), - activity_data->spell_list.c_str(), - activity_data->description_override.c_str(), - (m_task_data[task_id]->sequence_mode == ActivitiesStepped ? "stepped" : "sequential") + task_data->activity_count, + static_cast(ad->activity_type), + ad->goal_method, + ad->goal_count, + ad->zones.c_str(), + ad->target_name.c_str(), + ad->item_list.c_str(), + ad->skill_list.c_str(), + ad->spell_list.c_str(), + ad->description_override.c_str() ); - m_task_data[task_id]->activity_count++; + task_data->activity_count++; } LogTasks("Loaded [{}] Task Activities", task_activities.size()); @@ -277,49 +264,52 @@ bool TaskManager::LoadTasks(int single_task) return true; } -bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_state) +bool TaskManager::SaveClientState(Client *client, ClientTaskState *cts) { // I am saving the slot in the ActiveTasks table, because unless a Task is cancelled/completed, the client // doesn't seem to like tasks moving slots between zoning and you can end up with 'bogus' activities if the task // previously in that slot had more activities than the one now occupying it. Hopefully retaining the slot // number for the duration of a session will overcome this. - if (!client || !client_task_state) { + if (!client || !cts) { return false; } - const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::SaveClientState {}"; + constexpr const char *ERR_MYSQLERROR = "Error in TaskManager::SaveClientState {}"; int character_id = client->CharacterID(); - LogTasks("[SaveClientState] character_id [{}]", character_id); + LogTasks("character_id [{}]", character_id); - if (client_task_state->m_active_task_count > 0 || - client_task_state->m_active_task.task_id != TASKSLOTEMPTY || - client_task_state->m_active_shared_task.task_id != TASKSLOTEMPTY) { - for (auto &active_task : client_task_state->m_active_tasks) { + if (cts->m_active_task_count > 0 || + cts->m_active_task.task_id != TASKSLOTEMPTY || + cts->m_active_shared_task.task_id != TASKSLOTEMPTY) { + for (auto &active_task : cts->m_active_tasks) { int task_id = active_task.task_id; if (task_id == TASKSLOTEMPTY) { continue; } + const auto task_data = GetTaskData(task_id); + int slot = active_task.slot; if (active_task.updated) { LogTasks( - "[SaveClientState] character_id [{}] updating task_index [{}] task_id [{}]", + "character_id [{}] updating task_index [{}] task_id [{}]", character_id, slot, task_id ); std::string query = StringFormat( - "REPLACE INTO character_tasks (charid, taskid, slot, type, acceptedtime) " - "VALUES (%i, %i, %i, %i, %i)", + "REPLACE INTO character_tasks (charid, taskid, slot, type, acceptedtime, was_rewarded) " + "VALUES (%i, %i, %i, %i, %i, %d)", character_id, task_id, slot, - static_cast(m_task_data[task_id]->type), - active_task.accepted_time + static_cast(task_data->type), + active_task.accepted_time, + active_task.was_rewarded ); auto results = database.QueryDatabase(query); @@ -337,13 +327,13 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s int updated_activity_count = 0; - for (int activity_index = 0; activity_index < m_task_data[task_id]->activity_count; ++activity_index) { + for (int activity_index = 0; activity_index < task_data->activity_count; ++activity_index) { if (!active_task.activity[activity_index].updated) { continue; } LogTasks( - "[SaveClientState] Updating activity character_id [{}] updating task_index [{}] task_id [{}] activity_index [{}]", + "Updating activity character_id [{}] updating task_index [{}] task_id [{}] activity_index [{}]", character_id, slot, task_id, @@ -384,33 +374,34 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s } active_task.updated = false; - for (int activity_index = 0; activity_index < m_task_data[task_id]->activity_count; ++activity_index) { + for (int activity_index = 0; activity_index < task_data->activity_count; ++activity_index) { active_task.activity[activity_index].updated = false; } } } - if (!RuleB(TaskSystem, RecordCompletedTasks) || (client_task_state->m_completed_tasks.size() <= - (unsigned int) client_task_state->m_last_completed_task_loaded)) { - client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + if (!RuleB(TaskSystem, RecordCompletedTasks) || (cts->m_completed_tasks.size() <= + (unsigned int) cts->m_last_completed_task_loaded)) { + cts->m_last_completed_task_loaded = cts->m_completed_tasks.size(); return true; } const char *completed_task_query = "REPLACE INTO completed_tasks (charid, completedtime, taskid, activityid) " "VALUES (%i, %i, %i, %i)"; - for (unsigned int task_index = client_task_state->m_last_completed_task_loaded; - task_index < client_task_state->m_completed_tasks.size(); + for (unsigned int task_index = cts->m_last_completed_task_loaded; + task_index < cts->m_completed_tasks.size(); task_index++) { - int task_id = client_task_state->m_completed_tasks[task_index].task_id; + int task_id = cts->m_completed_tasks[task_index].task_id; - if ((task_id <= 0) || (task_id >= MAXTASKS) || (m_task_data[task_id] == nullptr)) { + const auto task_data = GetTaskData(task_id); + if (!task_data) { continue; } // we don't record completed shared tasks in the task quest log - if (m_task_data[task_id]->type == TaskType::Shared) { + if (task_data->type == TaskType::Shared) { break; } @@ -421,7 +412,7 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s std::string query = StringFormat( completed_task_query, character_id, - client_task_state->m_completed_tasks[task_index].completed_time, + cts->m_completed_tasks[task_index].completed_time, task_id, -1 ); @@ -438,16 +429,16 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s } // Insert one record for each completed optional task. - for (int activity_id = 0; activity_id < m_task_data[task_id]->activity_count; activity_id++) { - if (!m_task_data[task_id]->activity_information[activity_id].optional || - !client_task_state->m_completed_tasks[task_index].activity_done[activity_id]) { + for (int activity_id = 0; activity_id < task_data->activity_count; activity_id++) { + if (!task_data->activity_information[activity_id].optional || + !cts->m_completed_tasks[task_index].activity_done[activity_id]) { continue; } query = StringFormat( completed_task_query, character_id, - client_task_state->m_completed_tasks[task_index].completed_time, + cts->m_completed_tasks[task_index].completed_time, task_id, activity_id ); @@ -458,7 +449,7 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s } } - client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + cts->m_last_completed_task_loaded = cts->m_completed_tasks.size(); return true; } @@ -517,15 +508,16 @@ int TaskManager::NextTaskInSet(int task_set, int task_id) bool TaskManager::ValidateLevel(int task_id, int player_level) { - if (m_task_data[task_id] == nullptr) { + const auto task_data = GetTaskData(task_id); + if (!task_data) { return false; } - if (m_task_data[task_id]->min_level && (player_level < m_task_data[task_id]->min_level)) { + if (task_data->min_level && (player_level < task_data->min_level)) { return false; } - if (m_task_data[task_id]->max_level && (player_level > m_task_data[task_id]->max_level)) { + if (task_data->max_level && (player_level > task_data->max_level)) { return false; } @@ -534,9 +526,10 @@ bool TaskManager::ValidateLevel(int task_id, int player_level) std::string TaskManager::GetTaskName(uint32 task_id) { - if (task_id > 0 && task_id < MAXTASKS) { - if (m_task_data[task_id] != nullptr) { - return m_task_data[task_id]->title; + if (task_id > 0) { + const auto task_data = GetTaskData(task_id); + if (task_data) { + return task_data->title; } } @@ -545,19 +538,19 @@ std::string TaskManager::GetTaskName(uint32 task_id) TaskType TaskManager::GetTaskType(uint32 task_id) { - if (task_id > 0 && task_id < MAXTASKS) { - if (m_task_data[task_id] != nullptr) { - return m_task_data[task_id]->type; + if (task_id > 0) { + const auto task_data = GetTaskData(task_id); + if (task_data) { + return task_data->type; } } return TaskType::Task; } -void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_state, Mob *mob, int task_set_id) +void TaskManager::TaskSetSelector(Client* client, Mob* mob, int task_set_id, bool ignore_cooldown) { - int task_list[MAXCHOOSERENTRIES]; - int task_list_index = 0; int player_level = client->GetLevel(); + ClientTaskState* client_task_state = client->GetTaskState(); LogTasks( "TaskSetSelector called for task_set_id [{}] EnableTaskSize is [{}]", @@ -572,13 +565,14 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s // forward to shared task selector validation if set contains a shared task for (const auto& task_id : m_task_sets[task_set_id]) { - if (m_task_data[task_id] && m_task_data[task_id]->type == TaskType::Shared) { - SharedTaskSelector(client, mob, m_task_sets[task_set_id].size(), m_task_sets[task_set_id].data()); + const auto task_data = GetTaskData(task_id); + if (task_data && task_data->type == TaskType::Shared) { + SharedTaskSelector(client, mob, m_task_sets[task_set_id], ignore_cooldown); return; } } - if (client->HasTaskRequestCooldownTimer()) { + if (!ignore_cooldown && client->HasTaskRequestCooldownTimer()) { client->SendTaskRequestCooldownTimerMessage(); return; } @@ -592,7 +586,7 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s // A task_id of 0 in a TaskSet indicates that all Tasks in the set are enabled for all players. if (m_task_sets[task_set_id][0] == 0) { - LogTasks("[TaskSetSelector] TaskSets[{}][0] == 0. All Tasks in Set enabled.", task_set_id); + LogTasks("TaskSets[{}][0] == 0. All Tasks in Set enabled.", task_set_id); all_enabled = true; } @@ -601,22 +595,25 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s ++iterator; } // skip first when all enabled since it's useless data - while (iterator != m_task_sets[task_set_id].end() && task_list_index < MAXCHOOSERENTRIES) { + std::vector task_list; + while (iterator != m_task_sets[task_set_id].end() && task_list.size() < MAXCHOOSERENTRIES) { auto task = *iterator; + const auto task_data = GetTaskData(task); + // verify level, we're not currently on it, repeatable status, if it's a (shared) task // we aren't currently on another, and if it's enabled if not all_enabled if ((all_enabled || client_task_state->IsTaskEnabled(task)) && ValidateLevel(task, player_level) && - !client_task_state->IsTaskActive(task) && client_task_state->HasSlotForTask(m_task_data[task]) && + !client_task_state->IsTaskActive(task) && client_task_state->HasSlotForTask(task_data) && // this slot checking is a bit silly, but we allow mixing of task types ... (IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) { - task_list[task_list_index++] = task; + task_list.push_back(task); } ++iterator; } - if (task_list_index > 0) { - SendTaskSelector(client, mob, task_list_index, task_list); + if (!task_list.empty()) { + SendTaskSelector(client, mob, task_list); } else { client->MessageString(Chat::Yellow, NO_TASK_OFFERS, ".", ".", client->GetName()); @@ -625,76 +622,77 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s // unlike the non-Quest version of this function, it does not check enabled, that is assumed the responsibility of the quest to handle // we do however still want it to check the other stuff like level, active, room, etc -void TaskManager::TaskQuestSetSelector( - Client *client, - ClientTaskState *client_task_state, - Mob *mob, - int count, - int *tasks -) +void TaskManager::TaskQuestSetSelector(Client* client, Mob* mob, const std::vector& tasks, bool ignore_cooldown) { - int task_list[MAXCHOOSERENTRIES]; - int task_list_index = 0; + std::vector task_list; int player_level = client->GetLevel(); + ClientTaskState* client_task_state = client->GetTaskState(); - LogTasks("[UPDATE] TaskQuestSetSelector called for array size [{}]", count); + LogTasks("TaskQuestSetSelector called with size [{}]", tasks.size()); - if (count <= 0) { + if (tasks.empty()) { return; } // live prevents mixing selection types (also uses diff opcodes for solo vs shared tasks) // to keep shared task validation live-like (and simple), any shared task will // forward this to shared task validation and non-shared tasks will be dropped - for (int i = 0; i < count; ++i) { + for (int i = 0; i < tasks.size(); ++i) { auto task = tasks[i]; - if (m_task_data[task] && m_task_data[task]->type == TaskType::Shared) { - SharedTaskSelector(client, mob, count, tasks); + const auto task_data = GetTaskData(task); + if (task_data && task_data->type == TaskType::Shared) { + SharedTaskSelector(client, mob, tasks, ignore_cooldown); return; } } - if (client->HasTaskRequestCooldownTimer()) { + if (!ignore_cooldown && client->HasTaskRequestCooldownTimer()) { client->SendTaskRequestCooldownTimerMessage(); return; } - for (int i = 0; i < count; ++i) { + for (int i = 0; i < tasks.size() && task_list.size() < MAXCHOOSERENTRIES; ++i) { auto task = tasks[i]; + const auto task_data = GetTaskData(task); // verify level, we're not currently on it, repeatable status, if it's a (shared) task // we aren't currently on another, and if it's enabled if not all_enabled if (ValidateLevel(task, player_level) && !client_task_state->IsTaskActive(task) && - client_task_state->HasSlotForTask(m_task_data[task]) && + client_task_state->HasSlotForTask(task_data) && // this slot checking is a bit silly, but we allow mixing of task types ... (IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) { - task_list[task_list_index++] = task; + task_list.push_back(task); } } - if (task_list_index > 0) { - SendTaskSelector(client, mob, task_list_index, task_list); + if (!task_list.empty()) { + SendTaskSelector(client, mob, task_list); } else { client->MessageString(Chat::Yellow, NO_TASK_OFFERS, ".", ".", client->GetName()); } } -void TaskManager::SharedTaskSelector(Client *client, Mob *mob, int count, const int *tasks) +void TaskManager::SharedTaskSelector(Client* client, Mob* mob, const std::vector& tasks, bool ignore_cooldown) { - LogTasks("[UPDATE] SharedTaskSelector called for array size [{}]", count); + LogTasks("SharedTaskSelector called with size [{}]", tasks.size()); - if (count <= 0 || client->HasTaskRequestCooldownTimer()) { + if (tasks.empty()) { + return; + } + + if (!ignore_cooldown && client->HasTaskRequestCooldownTimer()) { client->SendTaskRequestCooldownTimerMessage(); return; } // check if requester already has a shared task (no need to query group/raid members if so) if (client->GetTaskState()->HasActiveSharedTask()) { - client->MessageString(Chat::Red, SharedTaskMessage::NO_REQUEST_BECAUSE_HAVE_ONE); + client->MessageString(Chat::Red, TaskStr::REQUEST_HAVE); return; } // get group/raid member character data from db (need to query for character ids) + // todo: group/raids need refactored to avoid queries and ignore offline members (through world) auto request = SharedTask::GetRequestCharacters(database, client->CharacterID()); // check if any group/raid member already has a shared task (already checked solo character) @@ -707,25 +705,17 @@ void TaskManager::SharedTaskSelector(Client *client, Mob *mob, int count, const if (!shared_task_members.empty()) { validation_failed = true; - auto it = std::find_if( - request.characters.begin(), request.characters.end(), - [&](const CharacterDataRepository::CharacterData &char_data) { - return char_data.id == shared_task_members.front().character_id; - } - ); + auto it = std::find_if(request.members.begin(), request.members.end(), + [&](const SharedTaskMember& member) { + return member.character_id == shared_task_members.front().character_id; + }); - if (it != request.characters.end()) { + if (it != request.members.end()) { if (request.group_type == SharedTaskRequestGroupType::Group) { - client->MessageString( - Chat::Red, - SharedTaskMessage::NO_REQUEST_BECAUSE_GROUP_HAS_ONE, - it->name.c_str()); + client->MessageString(Chat::Red, TaskStr::REQUEST_GROUP_HAS, it->character_name.c_str()); } else { - client->MessageString( - Chat::Red, - SharedTaskMessage::NO_REQUEST_BECAUSE_RAID_HAS_ONE, - it->name.c_str()); + client->MessageString(Chat::Red, TaskStr::REQUEST_RAID_HAS, it->character_name.c_str()); } } } @@ -733,52 +723,74 @@ void TaskManager::SharedTaskSelector(Client *client, Mob *mob, int count, const if (!validation_failed) { // run type and level filters on task selections - int task_list[MAXCHOOSERENTRIES] = {0}; - int task_list_index = 0; + std::vector task_list; - for (int i = 0; i < count && task_list_index < MAXCHOOSERENTRIES; ++i) { - // todo: are there non repeatable shared tasks? (would need to check all group/raid members) - auto task = tasks[i]; - if (m_task_data[task] && - m_task_data[task]->type == TaskType::Shared && - request.lowest_level >= m_task_data[task]->min_level && - (m_task_data[task]->max_level == 0 || request.highest_level <= m_task_data[task]->max_level)) { - task_list[task_list_index++] = task; + for (int i = 0; i < tasks.size() && task_list.size() < MAXCHOOSERENTRIES; ++i) { + if (CanOfferSharedTask(tasks[i], request)) + { + task_list.push_back(tasks[i]); } } // check if any tasks are left to offer after filtering - if (task_list_index > 0) { - SendSharedTaskSelector(client, mob, task_list_index, task_list); + if (!task_list.empty()) { + SendSharedTaskSelector(client, mob, task_list); } else { - client->MessageString(Chat::Red, SharedTaskMessage::YOU_DO_NOT_MEET_REQ_AVAILABLE); + client->MessageString(Chat::Red, TaskStr::NOT_MEET_REQ); } } } -// sends task selector to client -void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int *task_list) +bool TaskManager::CanOfferSharedTask(int task_id, const SharedTaskRequest& request) { - LogTasks("TaskSelector for [{}] Tasks", task_count); - int player_level = client->GetLevel(); - - // Check if any of the tasks exist - for (int i = 0; i < task_count; i++) { - if (m_task_data[task_list[i]] != nullptr) { - break; - } + // todo: are there non repeatable shared tasks? (would need to check all group/raid members) + const auto task = GetTaskData(task_id); + if (!task) + { + LogTasksDetail("task data for task id [{}] not found", task_id); + return false; } + if (task->type != TaskType::Shared) + { + LogTasksDetail("task [{}] is not a shared task type", task_id); + return false; + } + + if (task->min_level > 0 && request.lowest_level < task->min_level) + { + LogTasksDetail("lowest level [{}] is below task [{}] min level [{}]", + request.lowest_level, task_id, task->min_level); + return false; + } + + if (task->max_level > 0 && request.highest_level > task->max_level) + { + LogTasksDetail("highest level [{}] exceeds task [{}] max level [{}]", + request.highest_level, task_id, task->max_level); + return false; + } + + return true; +} + +// sends task selector to client +void TaskManager::SendTaskSelector(Client* client, Mob* mob, const std::vector& task_list) +{ + LogTasks("TaskSelector for [{}] Tasks", task_list.size()); + int player_level = client->GetLevel(); + client->GetTaskState()->ClearLastOffers(); + int valid_tasks_count = 0; - for (int task_index = 0; task_index < task_count; task_index++) { - if (!ValidateLevel(task_list[task_index], player_level)) { + for (int task_index : task_list) { + if (!ValidateLevel(task_index, player_level)) { continue; } - if (client->IsTaskActive(task_list[task_index])) { + if (client->IsTaskActive(task_index)) { continue; } - if (!IsTaskRepeatable(task_list[task_index]) && client->IsTaskCompleted(task_list[task_index])) { + if (!IsTaskRepeatable(task_index) && client->IsTaskCompleted(task_index)) { continue; } @@ -797,7 +809,7 @@ void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int // this is also sent in OP_TaskDescription buf.WriteUInt32(mob->GetID()); // TaskGiver - for (int i = 0; i < task_count; i++) { // max 40 + for (int i = 0; i < task_list.size(); i++) { // max 40 if (!ValidateLevel(task_list[i], player_level)) { continue; } @@ -809,31 +821,33 @@ void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int } buf.WriteUInt32(task_list[i]); // task_id - m_task_data[task_list[i]]->SerializeSelector(buf, client->ClientVersion()); + m_task_data[task_list[i]].SerializeSelector(buf, client->ClientVersion()); + client->GetTaskState()->AddOffer(task_list[i], mob->GetID()); } auto outapp = std::make_unique(OP_TaskSelectWindow, buf); client->QueuePacket(outapp.get()); } -void TaskManager::SendSharedTaskSelector(Client *client, Mob *mob, int task_count, int *task_list) +void TaskManager::SendSharedTaskSelector(Client* client, Mob* mob, const std::vector& task_list) { - LogTasks("SendSharedTaskSelector for [{}] Tasks", task_count); + LogTasks("[{}] Tasks", task_list.size()); // request timer is only set when shared task selection shown (not for failed validations) client->StartTaskRequestCooldownTimer(); + client->GetTaskState()->ClearLastOffers(); SerializeBuffer buf; - buf.WriteUInt32(task_count); // number of tasks + buf.WriteUInt32(static_cast(task_list.size())); // number of tasks // shared task selection (live doesn't mix types) makes client send shared task specific opcode for accepts buf.WriteUInt32(static_cast(TaskType::Shared)); buf.WriteUInt32(mob->GetID()); // task giver entity id - for (int i = 0; i < task_count; ++i) { - int task_id = task_list[i]; + for (int task_id: task_list) { buf.WriteUInt32(task_id); - m_task_data[task_id]->SerializeSelector(buf, client->ClientVersion()); + m_task_data[task_id].SerializeSelector(buf, client->ClientVersion()); + client->GetTaskState()->AddOffer(task_id, mob->GetID()); } auto outapp = std::make_unique(OP_SharedTaskSelectWindow, buf); @@ -842,80 +856,42 @@ void TaskManager::SendSharedTaskSelector(Client *client, Mob *mob, int task_coun int TaskManager::GetActivityCount(int task_id) { - if ((task_id > 0) && (task_id < MAXTASKS)) { - if (m_task_data[task_id]) { return m_task_data[task_id]->activity_count; } + if (task_id > 0) { + const auto task_data = GetTaskData(task_id); + if (task_data) { + return task_data->activity_count; + } } return 0; } -void TaskManager::ExplainTask(Client *client, int task_id) -{ - - // TODO: This method is not finished (hardly started). It was intended to - // explain in English, what each activity_information did, conditions for step unlocking, etc. - // - return; - - if (!client) { return; } - - if ((task_id <= 0) || (task_id >= MAXTASKS)) { - client->Message(Chat::White, "task_id out-of-range."); - return; - } - - if (m_task_data[task_id] == nullptr) { - client->Message(Chat::White, "Task does not exist."); - return; - } - - char explanation[1000], *ptr; - client->Message(Chat::White, "Task %4i: title: %s", task_id, m_task_data[task_id]->description.c_str()); - client->Message(Chat::White, "%3i Activities", m_task_data[task_id]->activity_count); - ptr = explanation; - for (int i = 0; i < m_task_data[task_id]->activity_count; i++) { - - sprintf(ptr, "Act: %3i: ", i); - ptr = ptr + strlen(ptr); - switch (m_task_data[task_id]->activity_information[i].activity_type) { - case TaskActivityType::Deliver: - sprintf(ptr, "Deliver"); - break; - } - - } -} - bool TaskManager::IsTaskRepeatable(int task_id) { - if ((task_id <= 0) || (task_id >= MAXTASKS)) { - return false; - } - - TaskInformation *task_data = task_manager->m_task_data[task_id]; - if (task_data == nullptr) { + const auto task_data = GetTaskData(task_id); + if (!task_data) { return false; } return task_data->repeatable; } -void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_task_state) +void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *cts) { int packet_length = 4; //vector::const_iterator iterator; // The client only display the first 50 Completed Tasks send, so send the 50 most recent int first_task_to_send = 0; - int last_task_to_send = client_task_state->m_completed_tasks.size(); + int last_task_to_send = cts->m_completed_tasks.size(); - if (client_task_state->m_completed_tasks.size() > 50) { - first_task_to_send = client_task_state->m_completed_tasks.size() - 50; + if (cts->m_completed_tasks.size() > 50) { + first_task_to_send = cts->m_completed_tasks.size() - 50; } LogTasks( - "[SendCompletedTasksToClient] completed task count [{}] first tank to send is [{}] last is [{}]", - client_task_state->m_completed_tasks.size(), + "completed task count [{}] first tank to send is [{}] last is [{}]", + cts->m_completed_tasks.size(), first_task_to_send, last_task_to_send ); @@ -928,9 +904,10 @@ void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_ } */ for (int i = first_task_to_send; i < last_task_to_send; i++) { - int TaskID = client_task_state->m_completed_tasks[i].task_id; - if (m_task_data[TaskID] == nullptr) { continue; } - packet_length = packet_length + 8 + m_task_data[TaskID]->title.size() + 1; + int task_id = cts->m_completed_tasks[i].task_id; + const auto task_data = GetTaskData(task_id); + if (!task_data) { continue; } + packet_length = packet_length + 8 + task_data->title.size() + 1; } auto outapp = new EQApplicationPacket(OP_CompletedTasks, packet_length); @@ -942,15 +919,16 @@ void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_ //for(iterator=activity_state->CompletedTasks.begin(); iterator!=activity_state->CompletedTasks.end(); iterator++) { // int task_id = (*iterator).task_id; for (int i = first_task_to_send; i < last_task_to_send; i++) { - int task_id = client_task_state->m_completed_tasks[i].task_id; - if (m_task_data[task_id] == nullptr) { continue; } + int task_id = cts->m_completed_tasks[i].task_id; + const auto task_data = GetTaskData(task_id); + if (!task_data) { continue; } *(uint32 *) buf = task_id; buf = buf + 4; - sprintf(buf, "%s", m_task_data[task_id]->title.c_str()); + sprintf(buf, "%s", task_data->title.c_str()); buf = buf + strlen(buf) + 1; //*(uint32 *)buf = (*iterator).CompletedTime; - *(uint32 *) buf = client_task_state->m_completed_tasks[i].completed_time; + *(uint32 *) buf = cts->m_completed_tasks[i].completed_time; buf = buf + 4; } @@ -962,14 +940,16 @@ void TaskManager::SendTaskActivityShort(Client *client, int task_id, int activit { // This activity_information Packet is sent for activities that have not yet been unlocked and appear as ??? // in the client. + const auto task_data = GetTaskData(task_id); + auto outapp = std::make_unique(OP_TaskActivity, 25); outapp->WriteUInt32(client_task_index); - outapp->WriteUInt32(static_cast(m_task_data[task_id]->type)); + outapp->WriteUInt32(static_cast(task_data->type)); outapp->WriteUInt32(task_id); outapp->WriteUInt32(activity_id); outapp->WriteUInt32(0); outapp->WriteUInt32(0xffffffff); - outapp->WriteUInt8(m_task_data[task_id]->activity_information[activity_id].optional ? 1 : 0); + outapp->WriteUInt8(task_data->activity_information[activity_id].optional ? 1 : 0); client->QueuePacket(outapp.get()); } @@ -981,16 +961,18 @@ void TaskManager::SendTaskActivityLong( bool task_complete ) { + const auto task_data = GetTaskData(task_id); + SerializeBuffer buf(100); buf.WriteUInt32(client_task_index); // TaskSequenceNumber - buf.WriteUInt32(static_cast(m_task_data[task_id]->type)); // task type + buf.WriteUInt32(static_cast(task_data->type)); // task type buf.WriteUInt32(task_id); buf.WriteUInt32(activity_id); buf.WriteUInt32(0); // unknown3 - const auto &activity = m_task_data[task_id]->activity_information[activity_id]; - int done_count = client->GetTaskActivityDoneCount(m_task_data[task_id]->type, client_task_index, activity_id); + const auto& activity = task_data->activity_information[activity_id]; + int done_count = client->GetTaskActivityDoneCount(task_data->type, client_task_index, activity_id); activity.SerializeObjective(buf, client->ClientVersion(), done_count); @@ -1010,10 +992,12 @@ void TaskManager::SendActiveTaskToClient( return; } + const auto task_data = GetTaskData(task->task_id); + int start_time = task->accepted_time; int task_id = task->task_id; - auto task_type = m_task_data[task_id]->type; - auto task_duration = m_task_data[task_id]->duration; + auto task_type = task_data->type; + auto task_duration = task_data->duration; SendActiveTaskDescription( client, @@ -1024,7 +1008,7 @@ void TaskManager::SendActiveTaskToClient( false ); - LogTasks("[SendActiveTasksToClient] task_id [{}] activity_count [{}] task_index [{}]", + LogTasks("task_id [{}] activity_count [{}] task_index [{}]", task_id, GetActivityCount(task_id), task_index); @@ -1034,7 +1018,7 @@ void TaskManager::SendActiveTaskToClient( for (int activity_id = 0; activity_id < GetActivityCount(task_id); activity_id++) { if (client->GetTaskActivityState(task_type, fixed_index, activity_id) != ActivityHidden) { LogTasks( - "[SendActiveTasksToClient] (Long Update) task_id [{}] activity_id [{}] fixed_index [{}] task_complete [{}]", + "(Long Update) task_id [{}] activity_id [{}] fixed_index [{}] task_complete [{}]", task_id, activity_id, fixed_index, @@ -1062,7 +1046,7 @@ void TaskManager::SendActiveTaskToClient( } else { LogTasks( - "[SendActiveTasksToClient] (Short Update) task_id [{}] activity_id [{}] fixed_index [{}]", + "(Short Update) task_id [{}] activity_id [{}] fixed_index [{}]", task_id, activity_id, fixed_index @@ -1094,12 +1078,13 @@ void TaskManager::SendActiveTasksToClient(Client *client, bool task_complete) // quests for (int task_index = 0; task_index < MAXACTIVEQUESTS; task_index++) { int task_id = state->m_active_quests[task_index].task_id; - if ((task_id == 0) || (m_task_data[task_id] == nullptr)) { + const auto task_data = GetTaskData(task_id); + if (!task_data) { continue; } LogTasksDetail("--"); - LogTasksDetail("[SendActiveTasksToClient] Task [{}]", m_task_data[task_id]->title); + LogTasksDetail("Task [{}]", task_data->title); SendActiveTaskToClient(&state->m_active_quests[task_index], client, task_index, task_complete); } @@ -1111,7 +1096,8 @@ void TaskManager::SendSingleActiveTaskToClient( ) { int task_id = task_info.task_id; - if (task_id == 0 || m_task_data[task_id] == nullptr) { + const auto task_data = GetTaskData(task_id); + if (!task_data) { return; } @@ -1121,18 +1107,18 @@ void TaskManager::SendSingleActiveTaskToClient( task_id, task_info, start_time, - m_task_data[task_id]->duration, + task_data->duration, bring_up_task_journal ); Log(Logs::General, Logs::Tasks, - "[UPDATE] SendSingleActiveTasksToClient: Task %i, Activities: %i", + "SendSingleActiveTasksToClient: Task %i, Activities: %i", task_id, GetActivityCount(task_id)); for (int activity_id = 0; activity_id < GetActivityCount(task_id); activity_id++) { if (task_info.activity[activity_id].activity_state != ActivityHidden) { - LogTasks("[SendSingleActiveTaskToClient] Long [{}] [{}] complete [{}]", + LogTasks("Long [{}] [{}] complete [{}]", task_id, activity_id, task_complete); @@ -1144,7 +1130,7 @@ void TaskManager::SendSingleActiveTaskToClient( } } else { - LogTasks("[SendSingleActiveTaskToClient] Short [{}] [{}]", task_id, activity_id); + LogTasks("Short [{}] [{}]", task_id, activity_id); SendTaskActivityShort(client, task_id, activity_id, task_info.slot); } } @@ -1159,29 +1145,22 @@ void TaskManager::SendActiveTaskDescription( bool bring_up_task_journal ) { - if ((task_id < 1) || (task_id >= MAXTASKS) || !m_task_data[task_id]) { + auto t = GetTaskData(task_id); + if (!t) { return; } - int packet_length = sizeof(TaskDescriptionHeader_Struct) + m_task_data[task_id]->title.length() + 1 - + sizeof(TaskDescriptionData1_Struct) + m_task_data[task_id]->description.length() + 1 + int packet_length = sizeof(TaskDescriptionHeader_Struct) + t->title.length() + 1 + + sizeof(TaskDescriptionData1_Struct) + t->description.length() + 1 + sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct); // If there is an item make the reward text into a link to the item (only the first item if a list // is specified). I have been unable to get multiple item links to work. // - if (m_task_data[task_id]->reward_id && m_task_data[task_id]->item_link.empty()) { - int item_id = 0; - // If the reward is a list of items, and the first entry on the list is valid - if (m_task_data[task_id]->reward_method == METHODSINGLEID) { - item_id = m_task_data[task_id]->reward_id; - } - else if (m_task_data[task_id]->reward_method == METHODLIST) { - item_id = m_goal_list_manager.GetFirstEntry(m_task_data[task_id]->reward_id); - if (item_id < 0) { - item_id = 0; - } - } + if (!t->reward_id_list.empty() && t->item_link.empty()) { + auto items = Strings::Split(t->reward_id_list, "|"); + auto item = items.front(); + int item_id = Strings::IsNumber(items.front()) ? std::stoi(items.front()) : 0; if (item_id) { const EQ::ItemData *reward_item = database.GetItem(item_id); @@ -1190,11 +1169,11 @@ void TaskManager::SendActiveTaskDescription( linker.SetLinkType(EQ::saylink::SayLinkItemData); linker.SetItemData(reward_item); linker.SetTaskUse(); - m_task_data[task_id]->item_link = linker.GenerateLink(); + t->item_link = linker.GenerateLink(); } } - packet_length += m_task_data[task_id]->reward.length() + 1 + m_task_data[task_id]->item_link.length() + 1; + packet_length += t->reward.length() + 1 + t->item_link.length() + 1; char *Ptr; TaskDescriptionHeader_Struct *task_description_header; @@ -1209,27 +1188,26 @@ void TaskManager::SendActiveTaskDescription( task_description_header->SequenceNumber = task_info.slot; task_description_header->TaskID = task_id; task_description_header->open_window = bring_up_task_journal; - task_description_header->task_type = static_cast(m_task_data[task_id]->type); + task_description_header->task_type = static_cast(t->type); - constexpr uint32_t reward_radiant_type = 4; // Radiant Crystals, anything else is Ebon for shared tasks - task_description_header->reward_type = m_task_data[task_id]->reward_radiant_crystals > 0 ? reward_radiant_type : 0; + task_description_header->reward_type = t->reward_point_type; Ptr = (char *) task_description_header + sizeof(TaskDescriptionHeader_Struct); - sprintf(Ptr, "%s", m_task_data[task_id]->title.c_str()); - Ptr += m_task_data[task_id]->title.length() + 1; + sprintf(Ptr, "%s", t->title.c_str()); + Ptr += t->title.length() + 1; tdd1 = (TaskDescriptionData1_Struct *) Ptr; tdd1->Duration = duration; - tdd1->dur_code = static_cast(m_task_data[task_id]->duration_code); + tdd1->dur_code = static_cast(t->duration_code); tdd1->StartTime = start_time; Ptr = (char *) tdd1 + sizeof(TaskDescriptionData1_Struct); - sprintf(Ptr, "%s", m_task_data[task_id]->description.c_str()); - Ptr += m_task_data[task_id]->description.length() + 1; + sprintf(Ptr, "%s", t->description.c_str()); + Ptr += t->description.length() + 1; tdd2 = (TaskDescriptionData2_Struct *) Ptr; @@ -1238,36 +1216,34 @@ void TaskManager::SendActiveTaskDescription( // "has_reward_selection" is after this bool! Smaller packet when this is 0 tdd2->has_rewards = 1; - tdd2->coin_reward = m_task_data[task_id]->cash_reward; - tdd2->xp_reward = m_task_data[task_id]->experience_reward ? 1 : 0; // just booled - tdd2->faction_reward = m_task_data[task_id]->faction_reward ? 1 : 0; // faction booled + tdd2->coin_reward = t->cash_reward; + tdd2->xp_reward = t->experience_reward ? 1 : 0; // just booled + tdd2->faction_reward = t->faction_reward ? 1 : 0; // faction booled Ptr = (char *) tdd2 + sizeof(TaskDescriptionData2_Struct); // we actually have 2 strings here. One is max length 96 and not parsed for item links // We actually skipped past that string incorrectly before, so TODO: fix item link string - sprintf(Ptr, "%s", m_task_data[task_id]->reward.c_str()); - Ptr += m_task_data[task_id]->reward.length() + 1; + sprintf(Ptr, "%s", t->reward.c_str()); + Ptr += t->reward.length() + 1; // second string is parsed for item links - sprintf(Ptr, "%s", m_task_data[task_id]->item_link.c_str()); - Ptr += m_task_data[task_id]->item_link.length() + 1; + sprintf(Ptr, "%s", t->item_link.c_str()); + Ptr += t->item_link.length() + 1; tdt = (TaskDescriptionTrailer_Struct *) Ptr; // shared tasks show radiant/ebon crystal reward, non-shared tasks show generic points - tdt->Points = m_task_data[task_id]->reward_ebon_crystals; - if (m_task_data[task_id]->reward_radiant_crystals > 0) { - tdt->Points = m_task_data[task_id]->reward_radiant_crystals; - } + tdt->Points = t->reward_points; + tdt->has_reward_selection = 0; // TODO: new rewards window client->QueuePacket(outapp); safe_delete(outapp); } -bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_state) +bool TaskManager::LoadClientState(Client *client, ClientTaskState *cts) { - if (!client || !client_task_state) { + if (!client || !cts) { return false; } @@ -1275,9 +1251,9 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s int character_id = client->CharacterID(); - client_task_state->m_active_task_count = 0; + cts->m_active_task_count = 0; - LogTasks("[LoadClientState] for character_id [{}]", character_id); + LogTasks("for character_id [{}]", character_id); // in a case where a client somehow lost local state with what state exists in world - we need // to perform an inverse sync where we inject the task @@ -1296,9 +1272,9 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // this should just load from the tasks table auto type = task_manager->GetTaskType(character_task.taskid); - if ((task_id < 0) || (task_id >= MAXTASKS)) { + if (task_id < 0) { LogTasks( - "[LoadClientState] Error: task_id [{}] out of range while loading character tasks from database", + "Error: task_id [{}] out of range while loading character tasks from database", task_id ); continue; @@ -1307,24 +1283,24 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // client data bucket pointer // this actually fetches the proper task type instances to be loaded with data // whether it be quest / task / shared task - auto task_info = client_task_state->GetClientTaskInfo(type, slot); + auto task_info = cts->GetClientTaskInfo(type, slot); if (task_info == nullptr) { LogTasks( - "[LoadClientState] Error: slot [{}] out of range while loading character tasks from database", + "Error: slot [{}] out of range while loading character tasks from database", slot ); continue; } if (task_info->task_id != TASKSLOTEMPTY) { - LogTasks("[LoadClientState] Error: slot [{}] for task [{}] is already occupied", slot, task_id); + LogTasks("Error: slot [{}] for task [{}] is already occupied", slot, task_id); continue; } task_info->task_id = task_id; - task_info->current_step = -1; task_info->accepted_time = character_task.acceptedtime; task_info->updated = false; + task_info->was_rewarded = character_task.was_rewarded; for (auto &i : task_info->activity) { i.activity_id = -1; @@ -1332,20 +1308,21 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // this check keeps a lot of core task updating code from working properly (shared or otherwise) if (type == TaskType::Quest) { - ++client_task_state->m_active_task_count; + ++cts->m_active_task_count; } LogTasks( - "[LoadClientState] character_id [{}] task_id [{}] slot [{}] accepted_time [{}]", + "character_id [{}] task_id [{}] slot [{}] accepted_time [{}] was_rewarded [{}]", character_id, task_id, slot, - character_task.acceptedtime + character_task.acceptedtime, + character_task.was_rewarded ); } // Load Activities - LogTasks("[LoadClientState] Loading activities for character_id [{}]", character_id); + LogTasks("Loading activities for character_id [{}]", character_id); auto character_activities = CharacterActivitiesRepository::GetWhere( database, @@ -1354,9 +1331,9 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s for (auto &character_activity: character_activities) { int task_id = character_activity.taskid; - if ((task_id < 0) || (task_id >= MAXTASKS)) { + if (task_id < 0) { LogTasks( - "[LoadClientState] Error: task_id [{}] out of range while loading character activities from database character_id [{}]", + "Error: task_id [{}] out of range while loading character activities from database character_id [{}]", task_id, character_id ); @@ -1366,7 +1343,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s int activity_id = character_activity.activityid; if ((activity_id < 0) || (activity_id >= MAXACTIVITIESPERTASK)) { LogTasks( - "[LoadClientState] Error: activity_id [{}] out of range while loading character activities from database character_id [{}]", + "Error: activity_id [{}] out of range while loading character activities from database character_id [{}]", activity_id, character_id ); @@ -1376,18 +1353,18 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // type: task ClientTaskInformation *task_info = nullptr; - if (client_task_state->m_active_task.task_id == task_id) { - task_info = &client_task_state->m_active_task; + if (cts->m_active_task.task_id == task_id) { + task_info = &cts->m_active_task; } // type: shared task - if (client_task_state->m_active_shared_task.task_id == task_id) { - task_info = &client_task_state->m_active_shared_task; + if (cts->m_active_shared_task.task_id == task_id) { + task_info = &cts->m_active_shared_task; } // type: quest if (task_info == nullptr) { - for (auto &active_quest : client_task_state->m_active_quests) { + for (auto &active_quest : cts->m_active_quests) { if (active_quest.task_id == task_id) { task_info = &active_quest; } @@ -1396,7 +1373,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s if (task_info == nullptr) { LogTasks( - "[LoadClientState] Error: activity_id [{}] found for task_id [{}] which client does not have character_id [{}]", + "Error: activity_id [{}] found for task_id [{}] which client does not have character_id [{}]", activity_id, task_id, character_id @@ -1417,7 +1394,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s task_info->activity[activity_id].updated = false; LogTasks( - "[LoadClientState] character_id [{}] task_id [{}] activity_id [{}] done_count [{}] completed [{}]", + "character_id [{}] task_id [{}] activity_id [{}] done_count [{}] completed [{}]", character_id, task_id, activity_id, @@ -1426,12 +1403,12 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s ); } - SyncClientSharedTaskState(client, client_task_state); + SyncClientSharedTaskState(client, cts); if (RuleB(TaskSystem, RecordCompletedTasks)) { - CompletedTaskInformation completed_task_information{}; + CompletedTaskInformation cti{}; - for (bool &i : completed_task_information.activity_done) { + for (bool &i : cti.activity_done) { i = false; } @@ -1445,8 +1422,8 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s for (auto &character_completed_task: character_completed_tasks) { int task_id = character_completed_task.taskid; - if ((task_id <= 0) || (task_id >= MAXTASKS)) { - LogError("[TASKS]Task ID [{}] out of range while loading completed tasks from database", task_id); + if (task_id <= 0) { + LogError("Task ID [{}] out of range while loading completed tasks from database", task_id); continue; } @@ -1456,7 +1433,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // completed. int activity_id = character_completed_task.activityid; if ((activity_id < -1) || (activity_id >= MAXACTIVITIESPERTASK)) { - LogError("[TASKS]activity_information ID [{}] out of range while loading completed tasks from database", + LogError("activity_information ID [{}] out of range while loading completed tasks from database", activity_id); continue; } @@ -1464,53 +1441,53 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s int completed_time = character_completed_task.completedtime; if ((previous_task_id != -1) && ((task_id != previous_task_id) || (completed_time != previous_completed_time))) { - client_task_state->m_completed_tasks.push_back(completed_task_information); - for (bool &activity_done : completed_task_information.activity_done) { + cts->m_completed_tasks.push_back(cti); + for (bool &activity_done : cti.activity_done) { activity_done = false; } } - completed_task_information.task_id = previous_task_id = task_id; - completed_task_information.completed_time = previous_completed_time = completed_time; + cti.task_id = previous_task_id = task_id; + cti.completed_time = previous_completed_time = completed_time; // If activity_id is -1, Mark all the non-optional tasks as completed. if (activity_id < 0) { - TaskInformation *task = m_task_data[task_id]; - if (task == nullptr) { + const auto task_data = GetTaskData(task_id); + if (!task_data) { continue; } - for (int i = 0; i < task->activity_count; i++) { - if (!task->activity_information[i].optional) { - completed_task_information.activity_done[i] = true; + for (int i = 0; i < task_data->activity_count; i++) { + if (!task_data->activity_information[i].optional) { + cti.activity_done[i] = true; } } } else { - completed_task_information.activity_done[activity_id] = true; + cti.activity_done[activity_id] = true; } } if (previous_task_id != -1) { - client_task_state->m_completed_tasks.push_back(completed_task_information); + cts->m_completed_tasks.push_back(cti); } - client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + cts->m_last_completed_task_loaded = cts->m_completed_tasks.size(); } std::string query = StringFormat( "SELECT `taskid` FROM character_enabledtasks " - "WHERE `charid` = %i AND `taskid` >0 AND `taskid` < %i " + "WHERE `charid` = %i AND `taskid` > 0 " "ORDER BY `taskid` ASC", - character_id, MAXTASKS + character_id ); auto results = database.QueryDatabase(query); if (results.Success()) { for (auto row = results.begin(); row != results.end(); ++row) { int task_id = atoi(row[0]); - client_task_state->m_enabled_tasks.push_back(task_id); - LogTasksDetail("[LoadClientState] Adding task_id [{}] to enabled tasks", task_id); + cts->m_enabled_tasks.push_back(task_id); + LogTasksDetail("Adding task_id [{}] to enabled tasks", task_id); } } @@ -1518,11 +1495,12 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // This should only break if a ServerOP adds or deletes activites for a task that players already // have active, or due to a bug. for (int task_index = 0; task_index < MAXACTIVEQUESTS + 1; task_index++) { - int task_id = client_task_state->m_active_tasks[task_index].task_id; + int task_id = cts->m_active_tasks[task_index].task_id; if (task_id == TASKSLOTEMPTY) { continue; } - if (!m_task_data[task_id]) { + const auto task_data = GetTaskData(task_id); + if (!task_data) { client->Message( Chat::Red, "Active Task Slot %i, references a task (%i), that does not exist. " @@ -1531,63 +1509,61 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s task_id ); - LogError("[LoadClientState] Character [{}] has task [{}] which does not exist", character_id, task_id); - client_task_state->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; + LogError("Character [{}] has task [{}] which does not exist", character_id, task_id); + cts->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; continue; } - for (int activity_index = 0; activity_index < m_task_data[task_id]->activity_count; activity_index++) { - if (client_task_state->m_active_tasks[task_index].activity[activity_index].activity_id != activity_index) { + for (int activity_index = 0; activity_index < task_data->activity_count; activity_index++) { + if (cts->m_active_tasks[task_index].activity[activity_index].activity_id != activity_index) { client->Message( Chat::Red, "Active Task %i, %s. activity_information count does not match expected value." "Removing from memory. Contact a GM to resolve this.", - task_id, m_task_data[task_id]->title.c_str() + task_id, task_data->title.c_str() ); LogTasks( - "[LoadClientState] Fatal error in character [{}] task state. activity_information [{}] for Task [{}] either missing from client state or from task", + "Fatal error in character [{}] task state. activity_information [{}] for Task [{}] either missing from client state or from task", character_id, activity_index, task_id ); - client_task_state->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; + cts->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; break; } } } LogTasksDetail( - "[LoadClientState] m_active_task task_id is [{}] slot [{}]", - client_task_state->m_active_task.task_id, - client_task_state->m_active_task.slot + "m_active_task task_id is [{}] slot [{}]", + cts->m_active_task.task_id, + cts->m_active_task.slot ); - if (client_task_state->m_active_task.task_id != TASKSLOTEMPTY) { - client_task_state->UnlockActivities(character_id, client_task_state->m_active_task); + if (cts->m_active_task.task_id != TASKSLOTEMPTY) { + cts->UnlockActivities(client, cts->m_active_task); // purely debugging LogTasksDetail( - "[LoadClientState] Fetching task info for character_id [{}] task [{}] slot [{}] current_step [{}] accepted_time [{}] updated [{}]", + "Fetching task info for character_id [{}] task [{}] slot [{}] accepted_time [{}] updated [{}]", character_id, - client_task_state->m_active_task.task_id, - client_task_state->m_active_task.slot, - client_task_state->m_active_task.current_step, - client_task_state->m_active_task.accepted_time, - client_task_state->m_active_task.updated + cts->m_active_task.task_id, + cts->m_active_task.slot, + cts->m_active_task.accepted_time, + cts->m_active_task.updated ); - TaskInformation *p_task_data = task_manager->m_task_data[client_task_state->m_active_task.task_id]; - if (p_task_data != nullptr) { - for (int i = 0; i < p_task_data->activity_count; i++) { - if (client_task_state->m_active_task.activity[i].activity_id >= 0) { + const auto task_data = GetTaskData(cts->m_active_task.task_id); + if (task_data) { + for (int i = 0; i < task_data->activity_count; i++) { + if (cts->m_active_task.activity[i].activity_id >= 0) { LogTasksDetail( - "[LoadClientState] -- character_id [{}] task [{}] activity_id [{}] done_count [{}] activity_state [{}] updated [{}] sequence [{}]", + "-- character_id [{}] task [{}] activity_id [{}] done_count [{}] activity_state [{}] updated [{}]", character_id, - client_task_state->m_active_task.task_id, - client_task_state->m_active_task.activity[i].activity_id, - client_task_state->m_active_task.activity[i].done_count, - client_task_state->m_active_task.activity[i].activity_state, - client_task_state->m_active_task.activity[i].updated, - p_task_data->sequence_mode + cts->m_active_task.task_id, + cts->m_active_task.activity[i].activity_id, + cts->m_active_task.activity[i].done_count, + cts->m_active_task.activity[i].activity_state, + cts->m_active_task.activity[i].updated ); } } @@ -1596,22 +1572,22 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // shared task LogTasksDetail( - "[LoadClientState] m_active_shared_task task_id is [{}] slot [{}]", - client_task_state->m_active_shared_task.task_id, - client_task_state->m_active_shared_task.slot + "m_active_shared_task task_id is [{}] slot [{}]", + cts->m_active_shared_task.task_id, + cts->m_active_shared_task.slot ); - if (client_task_state->m_active_shared_task.task_id != TASKSLOTEMPTY) { - client_task_state->UnlockActivities(character_id, client_task_state->m_active_shared_task); + if (cts->m_active_shared_task.task_id != TASKSLOTEMPTY) { + cts->UnlockActivities(client, cts->m_active_shared_task); } // quests (max 20 or 40 depending on client) - for (auto &active_quest : client_task_state->m_active_quests) { + for (auto &active_quest : cts->m_active_quests) { if (active_quest.task_id != TASKSLOTEMPTY) { - client_task_state->UnlockActivities(character_id, active_quest); + cts->UnlockActivities(client, active_quest); } } - LogTasksDetail("[LoadClientState] for Character ID [{}] DONE!", character_id); + LogTasksDetail("for Character ID [{}] DONE!", character_id); LogTasksDetail("---", character_id); return true; @@ -1669,7 +1645,7 @@ void TaskManager::SyncClientSharedTaskWithPersistedState(Client *c, ClientTaskSt for (auto &a: activities) { LogTasksDetail( - "[LoadClientState] shared_task loop local [{}] shared [{}]", + "shared_task loop local [{}] shared [{}]", shared_task->activity[a.activity_id].done_count, a.done_count ); @@ -1684,6 +1660,9 @@ void TaskManager::SyncClientSharedTaskWithPersistedState(Client *c, ClientTaskSt shared_task->activity[a.activity_id].activity_state = (a.completed_time > 0 ? ActivityCompleted : ActivityHidden); + // flag to update character_activities table entry on save + shared_task->activity[a.activity_id].updated = true; + // set flag to persist later fell_behind_state = true; } @@ -1691,6 +1670,17 @@ void TaskManager::SyncClientSharedTaskWithPersistedState(Client *c, ClientTaskSt // fell behind, force a save of client state if (fell_behind_state) { + // give reward if member was offline for shared task completion + // live does this as long as the shared task is still active when entering game + if (!shared_task->was_rewarded && IsActiveTaskComplete(*shared_task)) + { + LogTasksDetail("Syncing shared task completion for client [{}]", c->GetName()); + const auto task_data = GetTaskData(shared_task->task_id); + cts->AddReplayTimer(c, *shared_task, *task_data); // live updates a fresh timer + cts->DispatchEventTaskComplete(c, *shared_task, task_data->activity_count - 1); + cts->RewardTask(c, task_data, *shared_task); + } + SaveClientState(c, cts); } @@ -1716,7 +1706,7 @@ void TaskManager::SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTa // if we don't actually have a membership anywhere, remove ourself locally if (members.empty()) { LogTasksDetail( - "[SyncClientSharedTaskRemoveLocalIfNotExists] Client [{}] Shared task [{}] doesn't exist in world, removing from local", + "Client [{}] Shared task [{}] doesn't exist in world, removing from local", c->GetCleanName(), cts->m_active_shared_task.task_id ); @@ -1729,8 +1719,8 @@ void TaskManager::SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTa CharacterTasksRepository::DeleteWhere(database, delete_where); CharacterActivitiesRepository::DeleteWhere(database, delete_where); - c->MessageString(Chat::Yellow, SharedTaskMessage::YOU_ARE_NO_LONGER_A_MEMBER, - m_task_data[cts->m_active_shared_task.task_id]->title.c_str()); + c->MessageString(Chat::Yellow, TaskStr::NO_LONGER_MEMBER_TITLE, + m_task_data[cts->m_active_shared_task.task_id].title.c_str()); // remove as active task if doesn't exist cts->m_active_shared_task = {}; @@ -1761,7 +1751,7 @@ void TaskManager::SyncClientSharedTaskStateToLocal( } if (!has_character_shared_task) { - LogTasksDetail("[SyncClientSharedTaskStateToLocal] We don't have a shared character task locally"); + LogTasksDetail("We don't have a shared character task locally"); auto stm = SharedTaskMembersRepository::GetWhere( database, fmt::format( @@ -1771,14 +1761,14 @@ void TaskManager::SyncClientSharedTaskStateToLocal( ); if (!stm.empty()) { - LogTasksDetail("[SyncClientSharedTaskStateToLocal] We have membership in database"); + LogTasksDetail("We have membership in database"); auto s = SharedTasksRepository::FindOne( database, (int) stm.front().shared_task_id ); if (s.id > 0) { - LogTasksDetail("[SyncClientSharedTaskStateToLocal] Creating entity"); + LogTasksDetail("Creating entity"); // create task locally auto ct = CharacterTasksRepository::NewEntity(); @@ -1816,101 +1806,79 @@ void TaskManager::SyncClientSharedTaskStateToLocal( } } -void TaskManager::HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id, std::string npc_name) +void TaskManager::HandleUpdateTasksOnKill(Client* client, NPC* npc) { for (auto &c: client->GetPartyMembers()) { if (!c->ClientDataLoaded() || !c->HasTaskState()) { continue; } - LogTasksDetail("[HandleUpdateTasksOnKill] Looping through client [{}]", c->GetCleanName()); + LogTasksDetail("Looping through client [{}]", c->GetCleanName()); - // loop over the union of tasks and quests - for (auto &active_task : c->GetTaskState()->m_active_tasks) { - auto current_task = &active_task; - if (current_task->task_id == TASKSLOTEMPTY) { - continue; - } - - // Check if there are any active kill activities for this p_task_data - auto p_task_data = m_task_data[current_task->task_id]; - if (p_task_data == nullptr) { - return; - } - - for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { - ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; - ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; - - // We are not interested in completed or hidden activities - if (client_activity->activity_state != ActivityActive) { - continue; - } - - // We are only interested in Kill activities - if (activity_info->activity_type != TaskActivityType::Kill) { - continue; - } - - // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { - LogTasks( - "[HandleUpdateTasksOnKill] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check", - client->GetName(), - current_task->task_id, - activity_id, - static_cast(TaskActivityType::Kill), - npc_type_id - ); - continue; - } - // Is the activity_information to kill this type of NPC ? - switch (activity_info->goal_method) { - case METHODSINGLEID: - if (activity_info->goal_id != npc_type_id) { - LogTasksDetail("[HandleUpdateTasksOnKill] Matched single goal"); - continue; - } - break; - - case METHODLIST: - if (!m_goal_list_manager.IsInList( - activity_info->goal_id, - (int) npc_type_id - ) && !TaskGoalListManager::IsInMatchList( - activity_info->goal_match_list, - std::to_string(npc_type_id) - ) && !TaskGoalListManager::IsInMatchListPartial( - activity_info->goal_match_list, - npc_name - )) { - LogTasksDetail("[HandleUpdateTasksOnKill] Matched list goal"); - continue; - } - break; - - default: - // If METHODQUEST, don't updated the activity_information here - continue; - } - - LogTasksDetail("[HandleUpdateTasksOnKill] passed checks"); - - // handle actual update - // legacy eqemu task update logic loops through group on kill of npc to update a single task - if (p_task_data->type != TaskType::Shared) { - LogTasksDetail("[HandleUpdateTasksOnKill] Non-Shared Update"); - c->GetTaskState()->IncrementDoneCount(c, p_task_data, current_task->slot, activity_id); - continue; - } - - LogTasksDetail("[HandleUpdateTasksOnKill] Shared update"); - - // shared tasks only require one client to receive an update to propagate - if (c == client) { - c->GetTaskState()->IncrementDoneCount(c, p_task_data, current_task->slot, activity_id); - } - } - } + c->GetTaskState()->UpdateTasksOnKill(c, client, npc); } } + +bool TaskManager::IsActiveTaskComplete(ClientTaskInformation& client_task) +{ + const auto task_data = GetTaskData(client_task.task_id); + if (!task_data) + { + return false; + } + + for (int i = 0; i < task_data->activity_count; ++i) + { + if (client_task.activity[i].activity_state != ActivityCompleted && + !task_data->activity_information[i].optional) + { + return false; + } + } + return true; +} + +int TaskManager::GetCurrentDzTaskID() +{ + auto dz = zone->GetDynamicZone(); + if (dz) + { + // currently only supports shared tasks + auto res = SharedTasksRepository::GetWhere(database, fmt::format( + "id = (SELECT shared_task_id FROM shared_task_dynamic_zones WHERE dynamic_zone_id = {})", dz->GetID())); + + if (!res.empty()) + { + return res.front().task_id; + } + } + return 0; +} + +void TaskManager::EndCurrentDzTask(bool send_fail) +{ + auto dz = zone->GetDynamicZone(); + if (dz) + { + EndSharedTask(dz->GetID(), send_fail); + } +} + +void TaskManager::EndSharedTask(uint32_t dz_id, bool send_fail) +{ + ServerPacket pack(ServerOP_SharedTaskEndByDz, sizeof(ServerSharedTaskEnd_Struct)); + auto buf = reinterpret_cast(pack.pBuffer); + buf->dz_id = dz_id; + buf->send_fail = send_fail; + worldserver.SendPacket(&pack); +} + +void TaskManager::EndSharedTask(Client& client, int task_id, bool send_fail) +{ + ServerPacket pack(ServerOP_SharedTaskEnd, sizeof(ServerSharedTaskEnd_Struct)); + auto buf = reinterpret_cast(pack.pBuffer); + buf->character_id = client.CharacterID(); + buf->task_id = task_id; + buf->send_fail = send_fail; + worldserver.SendPacket(&pack); +} diff --git a/zone/task_manager.h b/zone/task_manager.h index 1acac00d3..e1f1a1154 100644 --- a/zone/task_manager.h +++ b/zone/task_manager.h @@ -3,8 +3,6 @@ #include "tasks.h" #include "task_client_state.h" -#include "task_proximity_manager.h" -#include "task_goal_list_manager.h" #include "../common/types.h" #include "../common/repositories/character_tasks_repository.h" #include @@ -13,38 +11,25 @@ #include class Client; - class Mob; +class SharedTaskRequest; class TaskManager { public: - TaskManager(); - ~TaskManager(); int GetActivityCount(int task_id); bool LoadTasks(int single_task = 0); - void ReloadGoalLists(); - inline void LoadProximities(int zone_id) - { - m_proximity_manager.LoadProximities(zone_id); - } bool LoadTaskSets(); - bool LoadClientState(Client *client, ClientTaskState *client_task_state); - bool SaveClientState(Client *client, ClientTaskState *client_task_state); - void SendTaskSelector(Client *client, Mob *mob, int task_count, int *task_list); + bool LoadClientState(Client *client, ClientTaskState *cts); + bool SaveClientState(Client *client, ClientTaskState *cts); + void SendTaskSelector(Client* client, Mob* mob, const std::vector& tasks); bool ValidateLevel(int task_id, int player_level); std::string GetTaskName(uint32 task_id); TaskType GetTaskType(uint32 task_id); - void TaskSetSelector(Client *client, ClientTaskState *client_task_state, Mob *mob, int task_set_id); + void TaskSetSelector(Client* client, Mob* mob, int task_set_id, bool ignore_cooldown); // task list provided by QuestManager (perl/lua) - void TaskQuestSetSelector( - Client *client, - ClientTaskState *client_task_state, - Mob *mob, - int count, - int *tasks - ); - void SharedTaskSelector(Client* client, Mob* mob, int count, const int* tasks); + void TaskQuestSetSelector(Client* client, Mob* mob, const std::vector& tasks, bool ignore_cooldown); + void SharedTaskSelector(Client* client, Mob* mob, const std::vector& tasks, bool ignore_cooldown); void SendActiveTasksToClient(Client *client, bool task_complete = false); void SendSingleActiveTaskToClient( Client *client, @@ -60,25 +45,34 @@ public: int client_task_index, bool task_complete = false ); - void SendCompletedTasksToClient(Client *c, ClientTaskState *client_task_state); - void ExplainTask(Client *client, int task_id); + void SendCompletedTasksToClient(Client *c, ClientTaskState *cts); int FirstTaskInSet(int task_set); int LastTaskInSet(int task_set); int NextTaskInSet(int task_set, int task_id); bool IsTaskRepeatable(int task_id); + bool IsActiveTaskComplete(ClientTaskInformation& client_task); + int GetCurrentDzTaskID(); + void EndCurrentDzTask(bool send_fail); + void EndSharedTask(Client& client, int task_id, bool send_fail); + void EndSharedTask(uint32_t dz_id, bool send_fail); friend class ClientTaskState; // shared tasks void SyncClientSharedTaskState(Client *c, ClientTaskState *cts); - void HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id, std::string npc_name); + void HandleUpdateTasksOnKill(Client* client, NPC* npc); + + const std::unordered_map& GetTaskData() const { return m_task_data; } + TaskInformation* GetTaskData(int task_id) + { + auto it = m_task_data.find(task_id); + return it != m_task_data.end() ? &it->second : nullptr; + } private: - TaskGoalListManager m_goal_list_manager; - TaskProximityManager m_proximity_manager; - TaskInformation *m_task_data[MAXTASKS]{}; - std::vector m_task_sets[MAXTASKSETS]; + std::vector m_task_sets[MAXTASKSETS]; + std::unordered_map m_task_data; void SendActiveTaskDescription( Client *client, int task_id, @@ -91,9 +85,10 @@ private: void SendActiveTaskToClient(ClientTaskInformation *task, Client *client, int task_index, bool task_complete); // shared tasks + bool CanOfferSharedTask(int task_id, const SharedTaskRequest& request); void SyncClientSharedTaskWithPersistedState(Client *c, ClientTaskState *cts); void SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTaskState *cts); - void SendSharedTaskSelector(Client* client, Mob* mob, int task_count, int* task_list); + void SendSharedTaskSelector(Client* client, Mob* mob, const std::vector& tasks); void SyncClientSharedTaskStateToLocal(Client *c); }; diff --git a/zone/task_proximity_manager.cpp b/zone/task_proximity_manager.cpp deleted file mode 100644 index ee46acbcb..000000000 --- a/zone/task_proximity_manager.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "../common/global_define.h" -#include "../common/repositories/proximities_repository.h" -#include "../common/rulesys.h" -#include "client.h" -#include "mob.h" -#include "quest_parser_collection.h" -#include "task_proximity_manager.h" -#include "tasks.h" -#include "zonedb.h" - -TaskProximityManager::TaskProximityManager() -{ - - -} - -TaskProximityManager::~TaskProximityManager() -{ - - -} - -bool TaskProximityManager::LoadProximities(int zone_id) -{ - TaskProximity proximity{}; - m_task_proximities.clear(); - - auto proximities = ProximitiesRepository::GetWhere( - content_db, - fmt::format("zoneid = {} ORDER BY `zoneid` ASC", zone_id) - ); - - for (auto &row: proximities) { - proximity.explore_id = row.exploreid; - proximity.min_x = row.minx; - proximity.max_x = row.maxx; - proximity.min_y = row.miny; - proximity.max_y = row.maxy; - proximity.min_z = row.minz; - proximity.max_z = row.maxz; - - m_task_proximities.push_back(proximity); - } - - LogTasks("Loaded [{}] Task Proximities", proximities.size()); - - return true; -} - -int TaskProximityManager::CheckProximities(float x, float y, float z) -{ - for (auto &task_proximity : m_task_proximities) { - - TaskProximity *p_proximity = &task_proximity; - - Log( - Logs::General, - Logs::Tasks, - "[Proximity] Checking %8.3f, %8.3f, %8.3f against %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f", - x, - y, - z, - p_proximity->min_x, - p_proximity->max_x, - p_proximity->min_y, - p_proximity->max_y, - p_proximity->min_z, - p_proximity->max_z - ); - - if (x < p_proximity->min_x || x > p_proximity->max_x || y < p_proximity->min_y || y > p_proximity->max_y || - z < p_proximity->min_z || z > p_proximity->max_z) { - continue; - } - - return p_proximity->explore_id; - } - - return 0; -} diff --git a/zone/task_proximity_manager.h b/zone/task_proximity_manager.h deleted file mode 100644 index a3fe44c07..000000000 --- a/zone/task_proximity_manager.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef EQEMU_TASK_PROXIMITY_MANAGER_H -#define EQEMU_TASK_PROXIMITY_MANAGER_H - -struct TaskProximity { - int explore_id; - float min_x; - float max_x; - float min_y; - float max_y; - float min_z; - float max_z; -}; - -// This class is used for managing proximities so that Quest NPC proximities don't need to be used. -class TaskProximityManager { - -public: - TaskProximityManager(); - ~TaskProximityManager(); - bool LoadProximities(int zone_id); - int CheckProximities(float x, float y, float z); - -private: - std::vector m_task_proximities; -}; - -#endif //EQEMU_TASK_PROXIMITY_MANAGER_H diff --git a/zone/tasks.cpp b/zone/tasks.cpp index a524ebd5f..a7232e67c 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1,7 +1,7 @@ #include "../common/global_define.h" #include "../common/misc_functions.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "queryserv.h" #include "quest_parser_collection.h" @@ -112,7 +112,7 @@ void Client::SendTaskFailed(int task_id, int task_index, TaskType task_type) task_activity_complete->task_completed = 0; //Fail task_activity_complete->stage_complete = 0; // 0 for task complete or failed. - LogTasks("[SendTaskFailed] Sending failure to client [{}]", GetCleanName()); + LogTasks("Sending failure to client [{}]", GetCleanName()); QueuePacket(outapp); safe_delete(outapp); diff --git a/zone/titles.cpp b/zone/titles.cpp index 8bdabc678..085243e33 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -17,7 +17,7 @@ */ #include "../common/eq_packet_structs.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/misc_functions.h" #include "../common/repositories/titles_repository.h" @@ -64,6 +64,8 @@ bool TitleManager::LoadTitles() titles.push_back(title); } + LogInfo("Loaded [{}] titles", Strings::Commify(std::to_string(results.RowCount()))); + return true; } @@ -225,9 +227,9 @@ bool TitleManager::IsNewTradeSkillTitleAvailable(int skill_id, int skill_value) return false; } -void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) +void TitleManager::CreateNewPlayerTitle(Client *client, std::string title) { - if (!client || !title) { + if (!client || title.empty()) { return; } @@ -235,7 +237,7 @@ void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) auto query = fmt::format( "SELECT `id` FROM titles WHERE `prefix` = '{}' AND char_id = {}", - EscapeString(title), + Strings::Escape(title), client->CharacterID() ); auto results = database.QueryDatabase(query); @@ -246,7 +248,7 @@ void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) query = fmt::format( "INSERT INTO titles (`char_id`, `prefix`) VALUES ({}, '{}')", client->CharacterID(), - EscapeString(title) + Strings::Escape(title) ); results = database.QueryDatabase(query); if (!results.Success()) { @@ -258,17 +260,17 @@ void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) safe_delete(pack); } -void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix) +void TitleManager::CreateNewPlayerSuffix(Client *client, std::string suffix) { - if (!client || !suffix) { + if (!client || suffix.empty()) { return; } client->SetTitleSuffix(suffix); - std::string query = fmt::format( + auto query = fmt::format( "SELECT `id` FROM titles WHERE `suffix` = '{}' AND char_id = {}", - EscapeString(suffix), + Strings::Escape(suffix), client->CharacterID() ); auto results = database.QueryDatabase(query); @@ -279,7 +281,7 @@ void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix) query = fmt::format( "INSERT INTO titles (`char_id`, `suffix`) VALUES ({}, '{}')", client->CharacterID(), - EscapeString(suffix) + Strings::Escape(suffix) ); results = database.QueryDatabase(query); if (!results.Success()) { @@ -291,24 +293,24 @@ void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix) safe_delete(pack); } -void Client::SetAATitle(const char *title) +void Client::SetAATitle(std::string title) { - strn0cpy(m_pp.title, title, sizeof(m_pp.title)); + strn0cpy(m_pp.title, title.c_str(), sizeof(m_pp.title)); auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); - SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer; - strn0cpy(strs->title, title, sizeof(strs->title)); + auto strs = (SetTitleReply_Struct *) outapp->pBuffer; + strn0cpy(strs->title, title.c_str(), sizeof(strs->title)); strs->entity_id = GetID(); entity_list.QueueClients(this, outapp, false); safe_delete(outapp); } -void Client::SetTitleSuffix(const char *suffix) +void Client::SetTitleSuffix(std::string suffix) { - strn0cpy(m_pp.suffix, suffix, sizeof(m_pp.suffix)); + strn0cpy(m_pp.suffix, suffix.c_str(), sizeof(m_pp.suffix)); auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); - SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer; + auto strs = (SetTitleReply_Struct *) outapp->pBuffer; strs->is_suffix = 1; - strn0cpy(strs->title, suffix, sizeof(strs->title)); + strn0cpy(strs->title, suffix.c_str(), sizeof(strs->title)); strs->entity_id = GetID(); entity_list.QueueClients(this, outapp, false); safe_delete(outapp); diff --git a/zone/titles.h b/zone/titles.h index 640d4d29a..5e29e512c 100644 --- a/zone/titles.h +++ b/zone/titles.h @@ -55,8 +55,8 @@ public: bool IsClientEligibleForTitle(Client *client, TitleEntry title); bool IsNewAATitleAvailable(int aa_points, int class_id); bool IsNewTradeSkillTitleAvailable(int skill_id, int skill_value); - void CreateNewPlayerTitle(Client *client, const char *title); - void CreateNewPlayerSuffix(Client *client, const char *suffix); + void CreateNewPlayerTitle(Client *client, std::string title); + void CreateNewPlayerSuffix(Client *client, std::string suffix); bool HasTitle(Client* client, uint32 title_id); protected: diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 9afde880b..e782dfce5 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -26,15 +26,15 @@ #endif #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "queryserv.h" #include "quest_parser_collection.h" #include "string_ids.h" #include "titles.h" #include "zonedb.h" -#include "zone_store.h" -#include "../common/repositories/character_recipe_list_repository.h" +#include "../common/repositories/char_recipe_list_repository.h" +#include "../common/zone_store.h" #include "../common/repositories/tradeskill_recipe_repository.h" extern QueryServ* QServ; @@ -134,12 +134,24 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme EQ::ItemInstance *aug = tobe_auged->GetAugment(slot); if(aug) { - std::vector args; + std::vector args; args.push_back(aug); parse->EventItem(EVENT_AUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args); args.assign(1, tobe_auged); parse->EventItem(EVENT_AUGMENT_INSERT, user, aug, nullptr, "", slot, &args); + + args.push_back(aug); + + const auto export_string = fmt::format( + "{} {} {} {}", + tobe_auged->GetID(), + -1, + aug->GetID(), + slot + ); + + parse->EventPlayer(EVENT_AUGMENT_INSERT_CLIENT, user, export_string, 0, &args); } item_one_to_push = tobe_auged->Clone(); @@ -164,7 +176,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme user->Message(Chat::Red, "Error: Wrong augmentation distiller for safely removing this augment."); return; } - std::vector args; + std::vector args; args.push_back(aug); parse->EventItem(EVENT_UNAUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args); @@ -228,7 +240,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } LogTradeskills( - "[HandleCombine] container_slot [{}] guildtribute_slot [{}]", + "container_slot [{}] guildtribute_slot [{}]", in_combine->container_slot, in_combine->guildtribute_slot ); @@ -314,7 +326,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob safe_delete(outapp); LogTradeskills( - "[HandleCombine] inst_item [{}] container_item [{}]", + "inst_item [{}] container_item [{}]", inst->GetItem()->ID, container->GetItem()->ID ); @@ -323,7 +335,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } if (container->GetItem() && container->GetItem()->BagType == EQ::item::BagTypeDetransformationmold) { - LogTradeskillsDetail("[HandleCombine] Check 1"); + LogTradeskillsDetail("Check 1"); const EQ::ItemInstance* inst = container->GetItem(0); if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { @@ -353,7 +365,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob if (!content_db.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) { - LogTradeskillsDetail("[HandleCombine] Check 2"); + LogTradeskillsDetail("Check 2"); user->MessageString(Chat::Emote,TRADESKILL_NOCOMBINE); auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); @@ -370,7 +382,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob // bit 6 (0x20): unlisted recipe flag if ((spec.must_learn & 0xF) == 1 && !spec.has_learnt) { - LogTradeskillsDetail("[HandleCombine] Check 3"); + LogTradeskillsDetail("Check 3"); // Made up message for the client. Just giving a DNC is the other option. user->Message(Chat::LightBlue, "You need to learn how to combine these first."); @@ -512,6 +524,15 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac return; } + // Character does not have the required skill. + if (spec.skill_needed > 0 && user->GetSkill(spec.tradeskill) < spec.skill_needed) { + // Notify client. + user->Message(Chat::Red, "You are not skilled enough."); + user->QueuePacket(outapp); + safe_delete(outapp); + return; + } + //pull the list of components std::string query = StringFormat("SELECT tre.item_id, tre.componentcount " "FROM tradeskill_recipe_entries AS tre " @@ -749,7 +770,11 @@ void Client::SendTradeskillSearchResults( return; } - auto character_learned_recipe_list = CharacterRecipeListRepository::GetLearnedRecipeList(CharacterID()); + + auto character_learned_recipe_list = CharRecipeListRepository::GetWhere( + database, + fmt::format("char_id = {}", CharacterID()) + ); for (auto row = results.begin(); row != results.end(); ++row) { if (row == nullptr || row[0] == nullptr || row[1] == nullptr || row[2] == nullptr || row[3] == nullptr || @@ -768,8 +793,7 @@ void Client::SendTradeskillSearchResults( // Skip the recipes that exceed the threshold in skill difference // Recipes that have either been made before or were // explicitly learned are excempt from that limit - - auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe( + auto character_learned_recipe = CharRecipeListRepository::GetCharRecipeListEntry( character_learned_recipe_list, recipe_id ); @@ -780,7 +804,7 @@ void Client::SendTradeskillSearchResults( LogTradeskills("Checking limit recipe_id [{}] name [{}]", recipe_id, name); - if (character_learned_recipe.made_count == 0) { + if (character_learned_recipe.madecount == 0) { continue; } } @@ -935,37 +959,37 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { // Remember: skillup_modifier is (float). Lower is better switch(spec->tradeskill) { case EQ::skills::SkillFletching: - skillup_modifier = RuleI(Character, TradeskillUpFletching); + skillup_modifier = RuleR(Character, TradeskillUpFletching); break; case EQ::skills::SkillAlchemy: - skillup_modifier = RuleI(Character, TradeskillUpAlchemy); + skillup_modifier = RuleR(Character, TradeskillUpAlchemy); break; case EQ::skills::SkillJewelryMaking: - skillup_modifier = RuleI(Character, TradeskillUpJewelcrafting); + skillup_modifier = RuleR(Character, TradeskillUpJewelcrafting); break; case EQ::skills::SkillPottery: - skillup_modifier = RuleI(Character, TradeskillUpPottery); + skillup_modifier = RuleR(Character, TradeskillUpPottery); break; case EQ::skills::SkillBaking: - skillup_modifier = RuleI(Character, TradeskillUpBaking); + skillup_modifier = RuleR(Character, TradeskillUpBaking); break; case EQ::skills::SkillBrewing: - skillup_modifier = RuleI(Character, TradeskillUpBrewing); + skillup_modifier = RuleR(Character, TradeskillUpBrewing); break; case EQ::skills::SkillBlacksmithing: - skillup_modifier = RuleI(Character, TradeskillUpBlacksmithing); + skillup_modifier = RuleR(Character, TradeskillUpBlacksmithing); break; case EQ::skills::SkillResearch: - skillup_modifier = RuleI(Character, TradeskillUpResearch); + skillup_modifier = RuleR(Character, TradeskillUpResearch); break; case EQ::skills::SkillMakePoison: - skillup_modifier = RuleI(Character, TradeskillUpMakePoison); + skillup_modifier = RuleR(Character, TradeskillUpMakePoison); break; case EQ::skills::SkillTinkering: - skillup_modifier = RuleI(Character, TradeskillUpTinkering); + skillup_modifier = RuleR(Character, TradeskillUpTinkering); break; case EQ::skills::SkillTailoring: - skillup_modifier = RuleI(Character, TradeskillUpTailoring); + skillup_modifier = RuleR(Character, TradeskillUpTailoring); break; default: skillup_modifier = 2; @@ -1051,9 +1075,9 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { itr = spec->onsuccess.begin(); while(itr != spec->onsuccess.end() && !spec->quest) { - SummonItem(itr->first, itr->second); item = database.GetItem(itr->first); if (item) { + SummonItem(itr->first, itr->second); if (GetGroup()) { entity_list.MessageGroup(this, true, Chat::Skills, "%s has successfully fashioned %s!", GetName(), item->Name); } @@ -1189,9 +1213,9 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float NotifyNewTitlesAvailable(); } - LogTradeskills("[CheckIncreaseTradeskill] skillup_modifier: [{}] , success_modifier: [{}] , stat modifier: [{}]", skillup_modifier , success_modifier , stat_modifier); - LogTradeskills("[CheckIncreaseTradeskill] Stage1 chance was: [{}] percent", chance_stage1); - LogTradeskills("[CheckIncreaseTradeskill] Stage2 chance was: [{}] percent. 0 percent means stage1 failed", chance_stage2); + LogTradeskills("skillup_modifier: [{}] , success_modifier: [{}] , stat modifier: [{}]", skillup_modifier , success_modifier , stat_modifier); + LogTradeskills("Stage1 chance was: [{}] percent", chance_stage1); + LogTradeskills("Stage2 chance was: [{}] percent. 0 percent means stage1 failed", chance_stage2); } bool ZoneDatabase::GetTradeRecipe( @@ -1203,7 +1227,7 @@ bool ZoneDatabase::GetTradeRecipe( ) { if (container == nullptr) { - LogTradeskills("[GetTradeRecipe] Container null"); + LogTradeskills("Container null"); return false; } @@ -1222,7 +1246,7 @@ bool ZoneDatabase::GetTradeRecipe( uint32 count = 0; uint32 sum = 0; for (uint8 i = 0; i < 10; i++) { // TODO: need to determine if this is bound to world/item container size - LogTradeskills("[GetTradeRecipe] Fetching item [{}]", i); + LogTradeskills("Fetching item [{}]", i); const EQ::ItemInstance *inst = container->GetItem(i); if (!inst) { @@ -1231,7 +1255,7 @@ bool ZoneDatabase::GetTradeRecipe( const EQ::ItemData *item = database.GetItem(inst->GetItem()->ID); if (!item) { - LogTradeskills("[GetTradeRecipe] item [{}] not found!", inst->GetItem()->ID); + LogTradeskills("item [{}] not found!", inst->GetItem()->ID); continue; } @@ -1247,7 +1271,7 @@ bool ZoneDatabase::GetTradeRecipe( count++; LogTradeskills( - "[GetTradeRecipe] Item in container index [{}] item [{}] found [{}]", + "Item in container index [{}] item [{}] found [{}]", i, item->ID, count @@ -1391,7 +1415,7 @@ bool ZoneDatabase::GetTradeRecipe( } LogTradeskills( - "[GetTradeRecipe] Component count loop [{}] item [{}] recipe component_count [{}]", + "Component count loop [{}] item [{}] recipe component_count [{}]", component_count, item->ID, atoi(row[1]) @@ -1475,17 +1499,16 @@ bool ZoneDatabase::GetTradeRecipe( spec->madecount = 0; spec->recipe_id = recipe_id; - auto character_learned_recipe_list = CharacterRecipeListRepository::GetLearnedRecipeList(char_id); - auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe( - character_learned_recipe_list, - recipe_id + auto r = CharRecipeListRepository::GetWhere( + database, + fmt::format("char_id = {} and recipe_id = {}", char_id, recipe_id) ); - if (character_learned_recipe.recipe_id) { //If this exists we learned it - LogTradeskills("[GetTradeRecipe] made_count [{}]", character_learned_recipe.made_count); + if (!r.empty() && r[0].recipe_id) { //If this exists we learned it + LogTradeskills("made_count [{}]", r[0].madecount); spec->has_learnt = true; - spec->madecount = (uint32)character_learned_recipe.made_count; + spec->madecount = (uint32) r[0].madecount; } //Pull the on-success items... @@ -1589,7 +1612,7 @@ void Client::LearnRecipe(uint32 recipe_id) } LogTradeskills( - "[LearnRecipe] recipe_id [{}] name [{}] learned [{}]", + "recipe_id [{}] name [{}] learned [{}]", recipe_id, tradeskill_recipe.name, results.RowCount() diff --git a/zone/trading.cpp b/zone/trading.cpp index 741c6b888..63c8f51a5 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -19,7 +19,7 @@ #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/misc_functions.h" #include "client.h" @@ -499,7 +499,11 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st LogTrading("Giving container [{}] ([{}]) in slot [{}] to [{}]", inst->GetItem()->Name, inst->GetItem()->ID, trade_slot, other->GetName()); // TODO: need to check bag items/augments for no drop..everything for attuned... - if (inst->GetItem()->NoDrop != 0 || Admin() >= RuleI(Character, MinStatusForNoDropExemptions) || RuleI(World, FVNoDropFlag) == 1 || other == this) { + if ( + inst->GetItem()->NoDrop != 0 || + CanTradeFVNoDropItem() || + other == this + ) { int16 free_slot = other->GetInv().FindFreeSlotForTradeItem(inst); if (free_slot != INVALID_INDEX) { @@ -717,7 +721,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st LogTrading("Giving item [{}] ([{}]) in slot [{}] to [{}]", inst->GetItem()->Name, inst->GetItem()->ID, trade_slot, other->GetName()); // TODO: need to check bag items/augments for no drop..everything for attuned... - if (inst->GetItem()->NoDrop != 0 || Admin() >= RuleI(Character, MinStatusForNoDropExemptions) || RuleI(World, FVNoDropFlag) == 1 || other == this) { + if (inst->GetItem()->NoDrop != 0 || CanTradeFVNoDropItem() || other == this) { int16 free_slot = other->GetInv().FindFreeSlotForTradeItem(inst); if (free_slot != INVALID_INDEX) { @@ -871,25 +875,50 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } bool quest_npc = false; - if(parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE)) { + if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE, true)) { // This is a quest NPC quest_npc = true; } - std::vector item_list; - std::list items; + // take ownership of all trade slot items + EQ::ItemInstance* insts[4] = { 0 }; for (int i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_NPC_END; ++i) { - EQ::ItemInstance *inst = m_inv.GetItem(i); - if(inst) { - items.push_back(inst); - item_list.push_back(inst); - } else { - item_list.push_back((EQ::ItemInstance*)nullptr); - continue; - } + insts[i - EQ::invslot::TRADE_BEGIN] = m_inv.PopItem(i); + database.SaveInventory(CharacterID(), nullptr, i); + } + + // copy to be filtered by task updates, null trade slots preserved for quest event arg + std::vector items(insts, insts + std::size(insts)); + + if (RuleB(TaskSystem, EnableTaskSystem)) { + if (UpdateTasksOnDeliver(items, *trade, tradingWith->CastToNPC())) { + if (!tradingWith->IsMoving()) + tradingWith->FaceTarget(this); + + EVENT_ITEM_ScriptStopReturn(); + + } + } + + // todo: rule or npc field to auto return normal items also + if (!quest_npc) + { + for (EQ::ItemInstance* inst : items) { + if (!inst || !inst->GetItem()) { + continue; + } + + // remove delivered task items + if (RuleB(TaskSystem, EnableTaskSystem) && inst->GetTaskDeliveredCount() > 0) { + int remaining = inst->RemoveTaskDeliveredItems(); + if (remaining <= 0) { + inst = nullptr; + continue; // all items in trade slot consumed by task update + } + } + + const EQ::ItemData* item = inst->GetItem(); - const EQ::ItemData* item = inst->GetItem(); - if(item && quest_npc == false) { bool isPetAndCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) && _CLIENTPET(tradingWith) && tradingWith->GetPetType()<=petOther); @@ -916,6 +945,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st ); } else if (RuleB(NPC, ReturnNonQuestNoDropItems)) { + tradingWith->SayString(TRADE_BACK, GetCleanName()); PushItemOnCursor(*baginst, true); } } @@ -935,23 +965,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // Return NO DROP and Attuned items being handed into a non-quest NPC if the rule is true else if (RuleB(NPC, ReturnNonQuestNoDropItems)) { + tradingWith->SayString(TRADE_BACK, GetCleanName()); PushItemOnCursor(*inst, true); - DeleteItemInInventory(i); } } } - if(RuleB(TaskSystem, EnableTaskSystem)) { - int Cash = trade->cp + (trade->sp * 10) + (trade->gp * 100) + (trade->pp * 1000); - if(UpdateTasksOnDeliver(items, Cash, tradingWith->GetNPCTypeID())) { - if(!tradingWith->IsMoving()) - tradingWith->FaceTarget(this); - - EVENT_ITEM_ScriptStopReturn(); - - } - } - char temp1[100] = { 0 }; char temp2[100] = { 0 }; snprintf(temp1, 100, "copper.%d", tradingWith->GetNPCTypeID()); @@ -971,12 +990,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st tradingWith->FaceTarget(this); } - EQ::ItemInstance *insts[4] = { 0 }; - for (int i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_NPC_END; ++i) { - insts[i - EQ::invslot::TRADE_BEGIN] = m_inv.PopItem(i); - database.SaveInventory(CharacterID(), nullptr, i); - } - + std::vector item_list(items.begin(), items.end()); parse->EventNPC(EVENT_TRADE, tradingWith->CastToNPC(), this, "", 0, &item_list); for(int i = 0; i < 4; ++i) { @@ -1078,6 +1092,7 @@ void Client::Trader_CustomerBrowsing(Client *Customer) { sis->TraderID = Customer->GetID(); QueuePacket(outapp); + safe_delete(outapp); } @@ -1151,8 +1166,8 @@ void Client::Trader_EndTrader() { } safe_delete(outapp); - safe_delete(gis); } + safe_delete(gis); } database.DeleteTraderItem(CharacterID()); @@ -1506,6 +1521,8 @@ void Client::FindAndNukeTraderItem(int32 SerialNumber, int16 Quantity, Client* C Trader_EndTrader(); } + safe_delete(TraderItems); + return; } else @@ -1836,13 +1853,13 @@ void Client::SendBazaarResults( search_criteria.append(" AND items.itemclass = 2"); break; case 46: - search_criteria.append(" AND items.spellid > 0 AND items.spellid < 65000"); + search_criteria.append(" AND items.scrolleffect > 0 AND items.scrolleffect < 65000"); break; case 47: - search_criteria.append(" AND items.spellid = 998"); + search_criteria.append(" AND items.worneffect = 998"); break; case 48: - search_criteria.append(" AND items.spellid >= 1298 AND items.spellid <= 1307"); + search_criteria.append(" AND items.worneffect >= 1298 AND items.worneffect <= 1307"); break; case 49: search_criteria.append(" AND items.focuseffect > 0"); @@ -2582,6 +2599,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); QueuePacket(outapp); + safe_delete(outapp); } } diff --git a/zone/trap.cpp b/zone/trap.cpp index 68189aad9..37436fa3a 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -17,7 +17,7 @@ */ #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/types.h" #include "client.h" @@ -495,6 +495,8 @@ bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) { Log(Logs::General, Logs::Traps, "Trap %d successfully loaded.", trap->trap_id); } + LogInfo("Loaded [{}] trap(s)", Strings::Commify(results.RowCount())); + return true; } diff --git a/zone/tribute.cpp b/zone/tribute.cpp index ed8c69cf5..3e0011049 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -403,6 +403,8 @@ bool ZoneDatabase::LoadTributes() { tribute_list[id] = tributeData; } + LogInfo("Loaded [{}] tributes", Strings::Commify(results.RowCount())); + const std::string query2 = "SELECT tribute_id, level, cost, item_id FROM tribute_levels ORDER BY tribute_id, level"; results = QueryDatabase(query2); if (!results.Success()) { @@ -432,6 +434,8 @@ bool ZoneDatabase::LoadTributes() { cur.tier_count++; } + LogInfo("Loaded [{}] tribute levels", Strings::Commify(results.RowCount())); + return true; } diff --git a/zone/tune.cpp b/zone/tune.cpp index 1c2d770d1..dcd51a0cc 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -26,7 +26,7 @@ #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/data_verification.h" #include "../common/misc_functions.h" #include "queryserv.h" @@ -45,9 +45,7 @@ #include #include -#ifdef BOTS #include "bot.h" -#endif extern QueryServ* QServ; extern WorldServer worldserver; @@ -906,7 +904,6 @@ int64 Mob::TuneClientAttack(Mob* other, bool no_avoid, bool no_hit_chance, int h // Now figure out damage my_hit.damage_done = 1; my_hit.min_damage = 0; - uint8 mylevel = GetLevel() ? GetLevel() : 1; int64 hate = 0; if (weapon) hate = (weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt); diff --git a/zone/water_map.cpp b/zone/water_map.cpp index ec5575f24..b7d367c47 100644 --- a/zone/water_map.cpp +++ b/zone/water_map.cpp @@ -4,21 +4,14 @@ #include "water_map_v1.h" #include "water_map_v2.h" #include "../common/eqemu_logsys.h" +#include "../common/file.h" +#include "../common/path_manager.h" #include #include #include #include -/** - * @param name - * @return - */ -inline bool file_exists(const std::string& name) { - std::ifstream f(name.c_str()); - return f.good(); -} - /** * @param zone_name * @return @@ -26,18 +19,7 @@ inline bool file_exists(const std::string& name) { WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { std::transform(zone_name.begin(), zone_name.end(), zone_name.begin(), ::tolower); - std::string filename; - if (file_exists("maps")) { - filename = "maps"; - } - else if (file_exists("Maps")) { - filename = "Maps"; - } - else { - filename = Config->MapDir; - } - - std::string file_path = filename + "/water/" + zone_name + std::string(".wtr"); + std::string file_path = fmt::format("{}/water/{}.wtr", path.GetMapsPath(), zone_name); LogDebug("Attempting to load water map with path [{}]", file_path.c_str()); FILE *f = fopen(file_path.c_str(), "rb"); if(f) { @@ -48,19 +30,19 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { fclose(f); return nullptr; } - + if(strncmp(magic, "EQEMUWATER", 10)) { LogDebug("Failed to load water map, bad magic string in header"); fclose(f); return nullptr; } - + if(fread(&version, sizeof(version), 1, f) != 1) { LogDebug("Failed to load water map, error reading version"); fclose(f); return nullptr; } - + LogDebug("Attempting to V[{}] load water map [{}]", version, file_path.c_str()); if(version == 1) { auto wm = new WaterMapV1(); @@ -90,7 +72,7 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { return nullptr; } } - + LogDebug("Failed to load water map, could not open file for reading [{}]", file_path.c_str()); return nullptr; } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 91016544c..f92cc6a26 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/features.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/misc_functions.h" #include "../common/eqemu_logsys.h" @@ -116,7 +116,7 @@ void NPC::DisplayWaypointInfo(Client *client) { current_waypoint.pause ? fmt::format( "{} ({})", - ConvertSecondsToTime(current_waypoint.pause), + Strings::SecondsToTime(current_waypoint.pause), current_waypoint.pause ) : "" @@ -205,14 +205,14 @@ void NPC::MoveTo(const glm::vec4 &position, bool saveguardspot) if (IsNPC() && GetGrid() != 0) { // he is on a grid if (GetGrid() < 0) { // currently stopped by a quest command SetGrid(0 - GetGrid()); // get him moving again - LogAI("MoveTo during quest wandering. Canceling quest wandering and going back to grid [{}] when MoveTo is done", GetGrid()); + LogAIDetail("MoveTo during quest wandering. Canceling quest wandering and going back to grid [{}] when MoveTo is done", GetGrid()); } AI_walking_timer->Disable(); // disable timer in case he is paused at a wp if (cur_wp >= 0) { // we've not already done a MoveTo() save_wp = cur_wp; // save the current waypoint cur_wp = EQ::WaypointStatus::QuestControlGrid; } - LogAI("MoveTo [{}], pausing regular grid wandering. Grid [{}], save_wp [{}]", + LogAIDetail("MoveTo [{}], pausing regular grid wandering. Grid [{}], save_wp [{}]", to_string(static_cast(position)).c_str(), -GetGrid(), save_wp); @@ -221,7 +221,7 @@ void NPC::MoveTo(const glm::vec4 &position, bool saveguardspot) roamer = true; save_wp = 0; cur_wp = EQ::WaypointStatus::QuestControlNoGrid; - LogAI("MoveTo [{}] without a grid", to_string(static_cast(position)).c_str()); + LogAIDetail("MoveTo [{}] without a grid", to_string(static_cast(position)).c_str()); } glm::vec3 dest(position); @@ -239,7 +239,7 @@ void NPC::MoveTo(const glm::vec4 &position, bool saveguardspot) if (m_GuardPoint.w == -1) m_GuardPoint.w = CalculateHeadingToTarget(position.x, position.y); - LogAI("Setting guard position to [{}]", to_string(static_cast(m_GuardPoint)).c_str()); + LogAIDetail("Setting guard position to [{}]", to_string(static_cast(m_GuardPoint)).c_str()); } cur_wp_pause = 0; @@ -252,7 +252,7 @@ void NPC::MoveTo(const glm::vec4 &position, bool saveguardspot) void NPC::UpdateWaypoint(int wp_index) { if (wp_index >= static_cast(Waypoints.size())) { - LogAI("Update to waypoint [{}] failed. Not found", wp_index); + LogAIDetail("Update to waypoint [{}] failed. Not found", wp_index); return; } std::vector::iterator cur; @@ -261,7 +261,7 @@ void NPC::UpdateWaypoint(int wp_index) m_CurrentWayPoint = glm::vec4(cur->x, cur->y, cur->z, cur->heading); cur_wp_pause = cur->pause; - LogAI("Next waypoint [{}]: ({}, {}, {}, {})", wp_index, m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, m_CurrentWayPoint.w); + LogAIDetail("Next waypoint [{}]: ({}, {}, {}, {})", wp_index, m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, m_CurrentWayPoint.w); } @@ -557,13 +557,27 @@ void NPC::SetWaypointPause() } } +void NPC::SaveGuardSpot(bool ClearGuardSpot) { + if (ClearGuardSpot) { + LogAIDetail("Clearing guard order."); + m_GuardPoint = glm::vec4(); + } else { + m_GuardPoint = m_Position; + + if (m_GuardPoint.w == 0) { + m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler + } + LogAIDetail("Setting guard position to [{}]", to_string(static_cast(m_GuardPoint))); + } +} + void NPC::SaveGuardSpot(const glm::vec4 &pos) { m_GuardPoint = pos; if (m_GuardPoint.w == 0) m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler - LogAI("Setting guard position to {0}", to_string(static_cast(m_GuardPoint))); + LogAIDetail("Setting guard position to [{}]", to_string(static_cast(m_GuardPoint))); } void NPC::NextGuardPosition() { @@ -698,7 +712,7 @@ void Mob::SendTo(float new_x, float new_y, float new_z) { m_Position.x = new_x; m_Position.y = new_y; m_Position.z = new_z; - LogAI("Sent To ({}, {}, {})", new_x, new_y, new_z); + LogAIDetail("Sent To ({}, {}, {})", new_x, new_y, new_z); if (flymode == GravityBehavior::Flying) return; @@ -714,7 +728,7 @@ void Mob::SendTo(float new_x, float new_y, float new_z) { float newz = zone->zonemap->FindBestZ(dest, nullptr); - LogAI("BestZ returned {} at {}, {}, {}", newz, m_Position.x, m_Position.y, m_Position.z); + LogAIDetail("BestZ returned {} at {}, {}, {}", newz, m_Position.x, m_Position.y, m_Position.z); if ((newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaSendTo)) // Sanity check. m_Position.z = newz + 1; @@ -778,7 +792,7 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) { auto duration = timer.elapsed(); - LogFixZ("Mob::GetFixedZ() ([{}]) returned [{}] at [{}], [{}], [{}] - Took [{}]", + LogFixZ("[{}] returned [{}] at [{}] [{}] [{}] - Took [{}]", GetCleanName(), new_z, destination.x, @@ -795,6 +809,10 @@ void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) { return; } + if (GetIsBoat()) { + return; + } + if (flymode == GravityBehavior::Flying) { return; } @@ -860,8 +878,6 @@ float Mob::GetZOffset() const { offset = 1.0f; break; case RACE_DRAGON_438: - offset = 0.776f; - break; case RACE_DRAGON_452: offset = 0.776f; break; @@ -871,9 +887,8 @@ float Mob::GetZOffset() const { case RACE_SPIDER_440: offset = 0.938f; break; + case RACE_IMP_46: case RACE_SNAKE_468: - offset = 1.0f; - break; case RACE_CORATHUS_459: offset = 1.0f; break; @@ -884,8 +899,6 @@ float Mob::GetZOffset() const { offset = 1.2f; break; case RACE_GOO_549: - offset = 0.5f; - break; case RACE_GOO_548: offset = 0.5f; break; @@ -902,14 +915,13 @@ float Mob::GetZOffset() const { offset = 4.0f; break; case RACE_ARMOR_OF_MARR_323: - offset = 5.0f; - break; case RACE_AMYGDALAN_663: offset = 5.0f; break; case RACE_SANDMAN_664: offset = 4.0f; break; + case RACE_LAVA_DRAGON_49: case RACE_ALARAN_SENTRY_STONE_703: offset = 9.0f; break; @@ -919,9 +931,31 @@ float Mob::GetZOffset() const { case RACE_BLIND_DREAMER_669: offset = 7.0f; break; - case RACE_GORAL_687: - offset = 2.0f; + case RACE_SIREN_187: + case RACE_HALAS_CITIZEN_90: + case RACE_OTTERMAN_190: + offset = .5f; break; + case RACE_COLDAIN_183: + offset = .6f; + break; + case RACE_WEREWOLF_14: + offset = 1.2f; + break; + case RACE_DWARF_8: + offset = .7f; + break; + case RACE_HORSE_216: + offset = 1.4f; + break; + case RACE_ENCHANTED_ARMOR_175: + case RACE_TIGER_63: + offset = 1.75f; + break; + case RACE_STATUE_OF_RALLOS_ZEK_66: + offset = 1.0f; + break; + case RACE_GORAL_687: case RACE_SELYRAH_686: offset = 2.0f; break; @@ -1138,7 +1172,7 @@ void ZoneDatabase::AddWP(Client *client, uint32 gridid, uint32 wpnum, const glm: * DeleteWaypoint - Removes a specific waypoint from the grid * grid_id: The ID number of the grid whose wp is being deleted * wp_num: The number of the waypoint being deleted -* zoneid: The ID number of the zone that contains the waypoint being deleted +* zoneid: The ID number of the zone that Contains the waypoint being deleted */ void ZoneDatabase::DeleteWaypoint(Client *client, uint32 grid_num, uint32 wp_num, uint16 zoneid) { @@ -1296,7 +1330,6 @@ void NPC::RestoreGuardSpotCharm() /****************** * Bot-specific overloads to make them play nice with the new movement system */ -#ifdef BOTS #include "bot.h" void Bot::WalkTo(float x, float y, float z) @@ -1314,4 +1347,3 @@ void Bot::RunTo(float x, float y, float z) Mob::RunTo(x, y, z); } -#endif diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 4820b791a..90aa34f66 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/profanity_manager.h" #include "client.h" +#include "command.h" #include "corpse.h" #include "entity.h" #include "expedition.h" @@ -57,6 +58,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/shared_tasks.h" #include "shared_task_zone_messaging.h" #include "dialogue_window.h" +#include "queryserv.h" extern EntityList entity_list; extern Zone* zone; @@ -202,12 +204,14 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) ServerConnectInfo* sci = (ServerConnectInfo*)pack->pBuffer; if (sci->port == 0) { - LogCritical("World did not have a port to assign from this server, the port range was not large enough."); + LogError("World did not have a port to assign from this server, the port range was not large enough."); Shutdown(); } else { - LogInfo("World assigned Port: [{}] for this zone", sci->port); + LogInfo("World assigned Port [{}] for this zone", sci->port); ZoneConfig::SetZonePort(sci->port); + + LogSys.SetDiscordHandler(&Zone::DiscordWebhookMessageHandler); } break; } @@ -358,9 +362,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) ZoneChange_Struct* zc2 = (ZoneChange_Struct*)outapp->pBuffer; if (ztz->response <= 0) { - zc2->success = ZONE_ERROR_NOTREADY; + zc2->success = ZoningMessage::ZoneNotReady; entity->CastToMob()->SetZone(ztz->current_zone_id, ztz->current_instance_id); entity->CastToClient()->SetZoning(false); + entity->CastToClient()->SetLockSavePosition(false); } else { entity->CastToClient()->UpdateWho(1); @@ -409,8 +414,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) ztz->response = -1; else { ztz->response = 1; - // since they asked about comming, lets assume they are on their way and not shut down. - zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } SendPacket(pack); @@ -546,7 +549,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) SetZoneData(zone->GetZoneID(), zone->GetInstanceID()); if (zst->zoneid == zone->GetZoneID()) { // This packet also doubles as "incoming client" notification, lets not shut down before they get here - zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); +// zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } else { SendEmoteMessage( @@ -586,8 +589,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) zone->RemoveAuth(szic->lsid); zone->AddAuth(szic); - // This packet also doubles as "incoming client" notification, lets not shut down before they get here - zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } } else { @@ -632,7 +633,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } else if (client->GetAnon() == 1 && client->Admin() > szp->adminrank) { break; } else { - std::string name = str_tolower(szp->name); + std::string name = Strings::ToLower(szp->name); name[0] = toupper(name[0]); SendEmoteMessage( @@ -668,7 +669,13 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_KickPlayer: { ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack->pBuffer; - Client* client = entity_list.GetClientByName(skp->name); + Client* client; + if (strlen(skp->name)) { + client = entity_list.GetClientByName(skp->name); + } else if (skp->account_id) { + client = entity_list.GetClientByAccID(skp->account_id); + } + if (client) { if (skp->adminrank >= client->Admin()) { client->WorldKick(); @@ -820,7 +827,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } ServerUptime_Struct* sus = (ServerUptime_Struct*)pack->pBuffer; uint32 ms = Timer::GetCurrentTime(); - std::string time_string = ConvertMillisecondsToTime(ms); + std::string time_string = Strings::MillisecondsToTime(ms); SendEmoteMessage( sus->adminname, 0, @@ -863,7 +870,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) //pendingrezexp is the amount of XP on the corpse. Setting it to a value >= 0 //also serves to inform Client::OPRezzAnswer to expect a packet. client->SetPendingRezzData(srs->exp, srs->dbid, srs->rez.spellid, srs->rez.corpse_name); - LogSpells("OP_RezzRequest in zone [{}] for [{}], spellid:[{}]", + LogSpells("[WorldServer::HandleMessage] OP_RezzRequest in zone [{}] for [{}] spellid [{}]", zone->GetShortName(), client->GetName(), srs->rez.spellid); auto outapp = new EQApplicationPacket(OP_RezzRequest, sizeof(Resurrect_Struct)); @@ -878,10 +885,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) // to the zone that the corpse is in. Corpse* corpse = entity_list.GetCorpseByName(srs->rez.corpse_name); if (corpse && corpse->IsCorpse()) { - LogSpells("OP_RezzComplete received in zone [{}] for corpse [{}]", + LogSpells("[WorldServer::HandleMessage] OP_RezzComplete received in zone [{}] for corpse [{}]", zone->GetShortName(), srs->rez.corpse_name); - LogSpells("Found corpse. Marking corpse as rezzed if needed"); + LogSpells("[WorldServer::HandleMessage] Found corpse. Marking corpse as rezzed if needed"); // I don't know why Rezzed is not set to true in CompleteRezz(). if (!IsEffectInSpell(srs->rez.spellid, SE_SummonToCorpse)) { corpse->IsRezzed(true); @@ -958,7 +965,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) break; } case ServerOP_OOCMute: { - oocmuted = *(pack->pBuffer); + auto o = (ServerOOCMute_Struct *) pack->pBuffer; + oocmuted = o->is_muted; break; } case ServerOP_Revoke: { @@ -1895,20 +1903,32 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_ReloadAAData: { - zone->SendReloadMessage("Alternate Advancement Data"); - zone->LoadAlternateAdvancement(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Alternate Advancement Data"); + zone->LoadAlternateAdvancement(); + } break; } case ServerOP_ReloadAlternateCurrencies: { - zone->SendReloadMessage("Alternate Currencies"); - zone->LoadAlternateCurrencies(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Alternate Currencies"); + zone->LoadAlternateCurrencies(); + } break; } case ServerOP_ReloadBlockedSpells: { - zone->SendReloadMessage("Blocked Spells"); - zone->LoadZoneBlockedSpells(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Blocked Spells"); + zone->LoadZoneBlockedSpells(); + } + break; + } + case ServerOP_ReloadCommands: + { + zone->SendReloadMessage("Commands"); + command_init(); break; } case ServerOP_ReloadContentFlags: @@ -1919,46 +1939,67 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_ReloadDoors: { - zone->SendReloadMessage("Doors"); - entity_list.RemoveAllDoors(); - zone->LoadZoneDoors(); - entity_list.RespawnAllDoors(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Doors"); + entity_list.RemoveAllDoors(); + zone->LoadZoneDoors(); + entity_list.RespawnAllDoors(); + } + break; + } + case ServerOP_ReloadDzTemplates: + { + if (zone) + { + zone->SendReloadMessage("Dynamic Zone Templates"); + zone->LoadDynamicZoneTemplates(); + } break; } case ServerOP_ReloadGroundSpawns: { - zone->SendReloadMessage("Ground Spawns"); - zone->LoadGroundSpawns(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Ground Spawns"); + zone->LoadGroundSpawns(); + } break; } case ServerOP_ReloadLevelEXPMods: { - zone->SendReloadMessage("Level Based Experience Modifiers"); - zone->LoadLevelEXPMods(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Level Based Experience Modifiers"); + zone->LoadLevelEXPMods(); + } break; } case ServerOP_ReloadLogs: { - zone->SendReloadMessage("Log Settings"); - LogSys.LoadLogDatabaseSettings(); + zone->SendReloadMessage("Log Settings"); + LogSys.LoadLogDatabaseSettings(); break; } case ServerOP_ReloadMerchants: { - zone->SendReloadMessage("Merchants"); - entity_list.ReloadMerchants(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Merchants"); + entity_list.ReloadMerchants(); + } break; } case ServerOP_ReloadNPCEmotes: { - zone->SendReloadMessage("NPC Emotes"); - zone->LoadNPCEmotes(&zone->NPCEmoteList); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("NPC Emotes"); + zone->LoadNPCEmotes(&zone->NPCEmoteList); + } break; } case ServerOP_ReloadObjects: { - zone->SendReloadMessage("Objects"); - entity_list.RemoveAllObjects(); - zone->LoadZoneObjects(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Objects"); + entity_list.RemoveAllObjects(); + zone->LoadZoneObjects(); + } break; } case ServerOP_ReloadPerlExportSettings: @@ -1974,13 +2015,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) break; } case ServerOP_ReloadStaticZoneData: { - zone->SendReloadMessage("Static Zone Data"); - zone->ReloadStaticData(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Static Zone Data"); + zone->ReloadStaticData(); + } break; } case ServerOP_ReloadTasks: { - if (RuleB(Tasks, EnableTaskSystem)) { + if (RuleB(Tasks, EnableTaskSystem) && zone && zone->IsLoaded()) { zone->SendReloadMessage("Tasks"); HandleReloadTasks(pack); } @@ -1989,26 +2032,35 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_ReloadTitles: { - zone->SendReloadMessage("Titles"); - title_manager.LoadTitles(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Titles"); + title_manager.LoadTitles(); + } break; } case ServerOP_ReloadTraps: { - zone->SendReloadMessage("Traps"); - entity_list.UpdateAllTraps(true, true); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Traps"); + entity_list.UpdateAllTraps(true, true); + } + break; } case ServerOP_ReloadVariables: { - zone->SendReloadMessage("Variables"); - database.LoadVariables(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Variables"); + database.LoadVariables(); + } break; } case ServerOP_ReloadVeteranRewards: { - zone->SendReloadMessage("Veteran Rewards"); - zone->LoadVeteranRewards(); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Veteran Rewards"); + zone->LoadVeteranRewards(); + } break; } case ServerOP_ReloadWorld: @@ -2021,8 +2073,19 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_ReloadZonePoints: { - zone->SendReloadMessage("Zone Points"); - content_db.LoadStaticZonePoints(&zone->zone_point_list, zone->GetShortName(), zone->GetInstanceVersion()); + if (zone && zone->IsLoaded()) { + zone->SendReloadMessage("Zone Points"); + content_db.LoadStaticZonePoints(&zone->zone_point_list, zone->GetShortName(), zone->GetInstanceVersion()); + } + break; + } + case ServerOP_ReloadZoneData: + { + zone_store.LoadZones(content_db); + if (zone && zone->IsLoaded()) { + zone->LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion()); + zone->SendReloadMessage("Zone Data"); + } break; } case ServerOP_CameraShake: @@ -2501,8 +2564,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) CZSetEntityVariable_Struct* CZSEV = (CZSetEntityVariable_Struct*) pack->pBuffer; uint8 update_type = CZSEV->update_type; int update_identifier = CZSEV->update_identifier; - const char* variable_name = CZSEV->variable_name; - const char* variable_value = CZSEV->variable_value; + std::string variable_name = CZSEV->variable_name; + std::string variable_value = CZSEV->variable_value; const char* client_name = CZSEV->client_name; if (update_type == CZUpdateType_Character) { auto client = entity_list.GetClientByCharID(update_identifier); @@ -2559,12 +2622,12 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) CZSignal_Struct* CZS = (CZSignal_Struct*) pack->pBuffer; uint8 update_type = CZS->update_type; int update_identifier = CZS->update_identifier; - uint32 signal = CZS->signal; + int signal_id = CZS->signal_id; const char* client_name = CZS->client_name; if (update_type == CZUpdateType_Character) { auto client = entity_list.GetClientByCharID(update_identifier); if (client) { - client->Signal(signal); + client->Signal(signal_id); } } else if (update_type == CZUpdateType_Group) { auto client_group = entity_list.GetGroupByID(update_identifier); @@ -2572,7 +2635,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (int member_index = 0; member_index < MAX_GROUP_MEMBERS; member_index++) { if (client_group->members[member_index] && client_group->members[member_index]->IsClient()) { auto group_member = client_group->members[member_index]->CastToClient(); - group_member->Signal(signal); + group_member->Signal(signal_id); } } } @@ -2582,31 +2645,31 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (int member_index = 0; member_index < MAX_RAID_MEMBERS; member_index++) { if (client_raid->members[member_index].member && client_raid->members[member_index].member->IsClient()) { auto raid_member = client_raid->members[member_index].member->CastToClient(); - raid_member->Signal(signal); + raid_member->Signal(signal_id); } } } } else if (update_type == CZUpdateType_Guild) { for (auto &client: entity_list.GetClientList()) { if (client.second->GuildID() > 0 && client.second->GuildID() == update_identifier) { - client.second->Signal(signal); + client.second->Signal(signal_id); } } } else if (update_type == CZUpdateType_Expedition) { for (auto &client: entity_list.GetClientList()) { if (client.second->GetExpedition() && client.second->GetExpedition()->GetID() == update_identifier) { - client.second->Signal(signal); + client.second->Signal(signal_id); } } } else if (update_type == CZUpdateType_ClientName) { auto client = entity_list.GetClientByName(client_name); if (client) { - client->Signal(signal); + client->Signal(signal_id); } } else if (update_type == CZUpdateType_NPC) { auto npc = entity_list.GetNPCByNPCTypeID(update_identifier); if (npc) { - npc->SignalNPC(signal); + npc->SignalNPC(signal_id); } } break; @@ -3007,8 +3070,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { WWSetEntityVariable_Struct* WWSEV = (WWSetEntityVariable_Struct*) pack->pBuffer; uint8 update_type = WWSEV->update_type; - const char* variable_name = WWSEV->variable_name; - const char* variable_value = WWSEV->variable_value; + std::string variable_name = WWSEV->variable_name; + std::string variable_value = WWSEV->variable_value; uint8 min_status = WWSEV->min_status; uint8 max_status = WWSEV->max_status; if (update_type == WWSetEntityVariableUpdateType_Character) { @@ -3028,18 +3091,18 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { WWSignal_Struct* WWS = (WWSignal_Struct*) pack->pBuffer; uint8 update_type = WWS->update_type; - uint32 signal = WWS->signal; + int signal_id = WWS->signal_id; uint8 min_status = WWS->min_status; uint8 max_status = WWS->max_status; if (update_type == WWSignalUpdateType_Character) { for (auto &client : entity_list.GetClientList()) { if (client.second->Admin() >= min_status && (client.second->Admin() <= max_status || max_status == AccountStatus::Player)) { - client.second->Signal(signal); + client.second->Signal(signal_id); } } } else if (update_type == WWSignalUpdateType_NPC) { for (auto &npc : entity_list.GetNPCList()) { - npc.second->SignalNPC(signal); + npc.second->SignalNPC(signal_id); } } break; @@ -3134,16 +3197,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (request_zone_short_name == local_zone_short_name || can_reload_global_script) { zone->SetQuestHotReloadQueued(true); } else if (request_zone_short_name == "all") { - std::string reload_quest_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload quest", - false, - "Locally" - ); - std::string reload_world_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( - "#reload world", - false, - "Globally" - ); + std::string reload_quest_saylink = Saylink::Silent("#reload quest", "Locally"); + std::string reload_world_saylink = Saylink::Silent("#reload world", "Globally"); worldserver.SendEmoteMessage( 0, 0, @@ -3171,6 +3226,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) LogError("Loading npcs faction lists failed!"); } + LogInfo("Loading faction association hits"); + if (!content_db.LoadFactionAssociation(hotfix_name)) { + LogError("Loading faction association hits failed!"); + } + LogInfo("Loading loot tables"); if (!content_db.LoadLoot(hotfix_name)) { LogError("Loading loot failed!"); @@ -3223,26 +3283,29 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) case ServerOP_DzSetCompass: case ServerOP_DzSetSafeReturn: case ServerOP_DzSetZoneIn: + case ServerOP_DzSetSwitchID: case ServerOP_DzUpdateMemberStatus: case ServerOP_DzLeaderChanged: case ServerOP_DzExpireWarning: + case ServerOP_DzMovePC: { DynamicZone::HandleWorldMessage(pack); break; } case ServerOP_SharedTaskAcceptNewTask: case ServerOP_SharedTaskUpdate: - case ServerOP_SharedTaskAttemptRemove: + case ServerOP_SharedTaskQuit: case ServerOP_SharedTaskMemberlist: case ServerOP_SharedTaskMemberChange: case ServerOP_SharedTaskInvitePlayer: case ServerOP_SharedTaskPurgeAllCommand: + case ServerOP_SharedTaskFailed: { SharedTaskZoneMessaging::HandleWorldMessage(pack); break; } default: { - LogInfo("[HandleMessage] Unknown ZS Opcode [{}] size [{}]", (int)pack->opcode, pack->size); + LogInfo("Unknown ZS Opcode [{}] size [{}]", (int)pack->opcode, pack->size); break; } } @@ -3387,7 +3450,7 @@ bool WorldServer::SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 bool WorldServer::RezzPlayer(EQApplicationPacket* rpack, uint32 rezzexp, uint32 dbid, uint16 opcode) { - LogSpells("WorldServer::RezzPlayer rezzexp is [{}] (0 is normal for RezzComplete", rezzexp); + LogSpells("rezzexp is [{}] (0 is normal for RezzComplete", rezzexp); auto pack = new ServerPacket(ServerOP_RezzPlayer, sizeof(RezzPlayer_Struct)); RezzPlayer_Struct* sem = (RezzPlayer_Struct*)pack->pBuffer; sem->rezzopcode = opcode; @@ -3412,6 +3475,7 @@ void WorldServer::SendReloadTasks(uint8 reload_type, uint32 task_id) { rts->task_id = task_id; SendPacket(pack); + safe_delete(pack); } void WorldServer::HandleReloadTasks(ServerPacket *pack) @@ -3433,10 +3497,6 @@ void WorldServer::HandleReloadTasks(ServerPacket *pack) task_manager = new TaskManager; task_manager->LoadTasks(); - if (zone) { - task_manager->LoadProximities(zone->GetZoneID()); - } - entity_list.ReloadAllClientsTaskState(); } else { LogTasks("Global reload of Task ID [{}]", rts->task_id); @@ -3446,21 +3506,6 @@ void WorldServer::HandleReloadTasks(ServerPacket *pack) break; } - case RELOADTASKPROXIMITIES: - { - if (zone) { - LogTasks("Global reload of all Task Proximities"); - task_manager->LoadProximities(zone->GetZoneID()); - } - - break; - } - case RELOADTASKGOALLISTS: - { - LogTasks("Global reload of all Task Goal Lists"); - task_manager->ReloadGoalLists(); - break; - } case RELOADTASKSETS: { LogTasks("Global reload of all Task Sets"); diff --git a/zone/zone.cpp b/zone/zone.cpp old mode 100755 new mode 100644 index f796b8416..8005c6537 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -34,7 +34,7 @@ #include "../common/features.h" #include "../common/rulesys.h" #include "../common/seperator.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "../common/eqemu_logsys.h" #include "expedition.h" @@ -59,7 +59,9 @@ #include "zone_reload.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/content_flags_repository.h" +#include "../common/repositories/rule_sets_repository.h" #include "../common/repositories/zone_points_repository.h" +#include "../common/serverinfo.h" #include #include @@ -149,8 +151,8 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool is_static) { delete pack; } - LogInfo("---- Zone server [{}], listening on port:[{}] ----", zonename, ZoneConfig::get()->ZonePort); - LogInfo("Zone Bootup: [{}] [{}] ([{}]: [{}])", + LogInfo("Zone server [{}] listening on port [{}]", zonename, ZoneConfig::get()->ZonePort); + LogInfo("Zone bootup type [{}] short_name [{}] zone_id [{}] instance_id [{}]", (is_static) ? "Static" : "Dynamic", zonename, iZoneID, iInstanceID); parse->Init(); UpdateWindowTitle(nullptr); @@ -158,18 +160,12 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool is_static) { // Dynamic zones need to Sync here. // Static zones sync when they connect in worldserver.cpp. // Static zones cannot sync here as request is ignored by worldserver. - if (!is_static) - { + if (!is_static) { zone->GetTimeSync(); } zone->RequestUCSServerStatus(); - - /** - * Set Shutdown timer - */ - uint32 shutdown_timer = static_cast(content_db.getZoneShutDownDelay(zone->GetZoneID(), zone->GetInstanceVersion())); - zone->StartShutdownTimer(shutdown_timer); + zone->StartShutdownTimer(); /* * Set Logging @@ -197,7 +193,6 @@ bool Zone::LoadZoneObjects() return false; } - LogInfo("Loading Objects from DB"); for (auto row = results.begin(); row != results.end(); ++row) { if (atoi(row[9]) == 0) { // Type == 0 - Static Object @@ -320,6 +315,8 @@ bool Zone::LoadZoneObjects() safe_delete(inst); } + LogInfo("Loaded [{}] world objects", Strings::Commify(results.RowCount())); + return true; } @@ -329,11 +326,11 @@ bool Zone::LoadGroundSpawns() { memset(&groundspawn, 0, sizeof(groundspawn)); int gsindex=0; - LogInfo("Loading Ground Spawns from DB"); content_db.LoadGroundSpawns(zoneid, GetInstanceVersion(), &groundspawn); uint32 ix=0; char* name = nullptr; uint32 gsnumber=0; + int added = 0; for(gsindex=0;gsindex<50;gsindex++){ if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].item 0) { - database.SaveMerchantTemp(npcid, ml.origslot, item, ml.charges); + database.SaveMerchantTemp(npcid, ml.origslot, GetZoneID(), GetInstanceID(), item, ml.charges); tmp_merlist.push_back(ml); } else { - database.DeleteMerchantTemp(npcid, ml.origslot); + database.DeleteMerchantTemp(npcid, ml.origslot, GetZoneID(), GetInstanceID()); } } } @@ -493,7 +494,7 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg first_empty_mslot = idx; - database.SaveMerchantTemp(npcid, first_empty_slot, item, charges); + database.SaveMerchantTemp(npcid, first_empty_slot, GetZoneID(), GetInstanceID(), item, charges); tmp_merlist = tmpmerchanttable[npcid]; TempMerchantList ml2; ml2.charges = charges; @@ -525,8 +526,6 @@ uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) { void Zone::LoadTempMerchantData() { - LogInfo("Loading Temporary Merchant Lists"); - auto results = content_db.QueryDatabase( fmt::format( SQL( @@ -564,11 +563,16 @@ void Zone::LoadTempMerchantData() itemid FROM merchantlist_temp WHERE npcid IN ({}) + AND zone_id = {} + AND instance_id = {} ), - implode(", ", npc_ids) + Strings::Implode(", ", npc_ids), + GetZoneID(), GetInstanceID() ) ); + LogInfo("Loaded [{}] temporary merchant entries", Strings::Commify(results.RowCount())); + std::map >::iterator temp_merchant_table_entry; uint32 npc_id = 0; @@ -591,7 +595,7 @@ void Zone::LoadTempMerchantData() temp_merchant_list.origslot = temp_merchant_list.slot; LogMerchants( - "[LoadTempMerchantData] Loading merchant temp items npc_id [{}] slot [{}] charges [{}] item [{}] origslot [{}]", + "Loading merchant temp items npc_id [{}] slot [{}] charges [{}] item [{}] origslot [{}]", npc_id, temp_merchant_list.slot, temp_merchant_list.charges, @@ -653,43 +657,40 @@ void Zone::LoadNewMerchantData(uint32 merchantid) { } void Zone::GetMerchantDataForZoneLoad() { - LogInfo("Loading Merchant Lists"); auto query = fmt::format( SQL ( SELECT - DISTINCT merchantlist.merchantid, - merchantlist.slot, - merchantlist.item, - merchantlist.faction_required, - merchantlist.level_required, - merchantlist.alt_currency_cost, - merchantlist.classes_required, - merchantlist.probability, - merchantlist.bucket_name, - merchantlist.bucket_value, - merchantlist.bucket_comparison - FROM - merchantlist, - npc_types, - spawnentry, - spawn2 - WHERE - npc_types.merchant_id = merchantlist.merchantid - AND npc_types.id = spawnentry.npcid - AND spawnentry.spawngroupid = spawn2.spawngroupid - AND spawn2.zone = '{}' - AND spawn2.version = {} - {} + merchantid, + slot, + item, + faction_required, + level_required, + alt_currency_cost, + classes_required, + probability, + bucket_name, + bucket_value, + bucket_comparison + from merchantlist where merchantid IN ( + select merchant_id from npc_types where id in ( + select npcID from spawnentry where spawngroupID IN ( + select spawngroupID from spawn2 where `zone` = '{}' and (`version` = {} OR `version` = -1) + ) + ) + ) + {} ORDER BY - merchantlist.slot + merchantlist.slot ), GetShortName(), GetInstanceVersion(), - ContentFilterCriteria::apply("merchantlist") + ContentFilterCriteria::apply() ); auto results = content_db.QueryDatabase(query); + LogInfo("Loaded [{}] merchant lists", Strings::Commify(results.RowCount())); + std::map >::iterator merchant_list; uint32 npc_id = 0; @@ -723,7 +724,7 @@ void Zone::GetMerchantDataForZoneLoad() { if (found) { continue; } - + mle.slot = std::stoul(row[1]); mle.item = std::stoul(row[2]); mle.faction_required = static_cast(std::stoi(row[3])); @@ -902,11 +903,23 @@ void Zone::Shutdown(bool quiet) } zone->ldon_trap_entry_list.clear(); - LogInfo("Zone Shutdown: [{}] ([{}])", zone->GetShortName(), zone->GetZoneID()); + LogInfo( + "Zone [{}] zone_id [{}] version [{}] instance_id [{}]", + zone->GetShortName(), + zone->GetZoneID(), + zone->GetInstanceVersion(), + zone->GetInstanceID() + ); petition_list.ClearPetitions(); zone->SetZoneHasCurrentTime(false); if (!quiet) { - LogInfo("Zone Shutdown: Going to sleep"); + LogInfo( + "Zone [{}] zone_id [{}] version [{}] instance_id [{}] Going to sleep", + zone->GetShortName(), + zone->GetZoneID(), + zone->GetInstanceVersion(), + zone->GetInstanceID() + ); } is_zone_loaded = false; @@ -920,15 +933,13 @@ void Zone::Shutdown(bool quiet) LogSys.CloseFileLogs(); if (RuleB(Zone, KillProcessOnDynamicShutdown)) { - LogInfo("[KillProcessOnDynamicShutdown] Shutting down"); + LogInfo("Shutting down"); EQ::EventLoop::Get().Shutdown(); } } void Zone::LoadZoneDoors() { - LogInfo("Loading doors for [{}] ", GetShortName()); - auto door_entries = content_db.LoadDoors(GetShortName(), GetInstanceVersion()); if (door_entries.empty()) { LogInfo("No doors loaded"); @@ -943,14 +954,14 @@ void Zone::LoadZoneDoors() } Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) -: initgrids_timer(10000), - autoshutdown_timer((RuleI(Zone, AutoShutdownDelay))), - clientauth_timer(AUTHENTICATION_TIMEOUT * 1000), - spawn2_timer(1000), - hot_reload_timer(1000), - qglobal_purge_timer(30000), - m_SafePoint(0.0f,0.0f,0.0f,0.0f), - m_Graveyard(0.0f,0.0f,0.0f,0.0f) +: initgrids_timer(10000), + autoshutdown_timer((RuleI(Zone, AutoShutdownDelay))), + clientauth_timer(AUTHENTICATION_TIMEOUT * 1000), + spawn2_timer(1000), + hot_reload_timer(1000), + qglobal_purge_timer(30000), + m_safe_points(0.0f, 0.0f, 0.0f, 0.0f), + m_graveyard(0.0f, 0.0f, 0.0f, 0.0f) { zoneid = in_zoneid; instanceid = in_instanceid; @@ -970,29 +981,45 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) tradevar = 0; lootvar = 0; - if(RuleB(TaskSystem, EnableTaskSystem)) { - task_manager->LoadProximities(zoneid); - } - short_name = strcpy(new char[strlen(in_short_name)+1], in_short_name); strlwr(short_name); memset(file_name, 0, sizeof(file_name)); long_name = 0; - aggroedmobs =0; - pgraveyard_id = 0; + aggroedmobs =0; + m_graveyard_id = 0; pgraveyard_zoneid = 0; - pMaxClients = 0; - pvpzone = false; - if(database.GetServerType() == 1) + m_max_clients = 0; + pvpzone = false; + + if (database.GetServerType() == 1) { pvpzone = true; - content_db.GetZoneLongName(short_name, &long_name, file_name, &m_SafePoint.x, &m_SafePoint.y, &m_SafePoint.z, &pgraveyard_id, &pMaxClients); - if(graveyard_id() > 0) - { + } + + auto z = GetZoneVersionWithFallback(ZoneID(short_name), instanceversion); + if (z) { + long_name = strcpy(new char[strlen(z->long_name.c_str()) + 1], z->long_name.c_str()); + + m_safe_points.x = z->safe_x; + m_safe_points.y = z->safe_y; + m_safe_points.z = z->safe_z; + m_safe_points.w = z->safe_heading; + m_graveyard_id = z->graveyard_id; + m_max_clients = z->maxclients; + + if (z->file_name.empty()) { + strcpy(file_name, short_name); + } + else { + strcpy(file_name, z->file_name.c_str()); + } + } + + if (graveyard_id() > 0) { LogDebug("Graveyard ID is [{}]", graveyard_id()); - bool GraveYardLoaded = content_db.GetZoneGraveyard(graveyard_id(), &pgraveyard_zoneid, &m_Graveyard.x, &m_Graveyard.y, &m_Graveyard.z, &m_Graveyard.w); + bool GraveYardLoaded = content_db.GetZoneGraveyard(graveyard_id(), &pgraveyard_zoneid, &m_graveyard.x, &m_graveyard.y, &m_graveyard.z, &m_graveyard.w); if (GraveYardLoaded) { - LogDebug("Loaded a graveyard for zone [{}]: graveyard zoneid is [{}] at [{}]", short_name, graveyard_zoneid(), to_string(m_Graveyard).c_str()); + LogDebug("Loaded a graveyard for zone [{}]: graveyard zoneid is [{}] at [{}]", short_name, graveyard_zoneid(), to_string(m_graveyard).c_str()); } else { LogError("Unable to load the graveyard id [{}] for zone [{}]", graveyard_id(), short_name); @@ -1001,11 +1028,10 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) if (long_name == 0) { long_name = strcpy(new char[18], "Long zone missing"); } - autoshutdown_timer.Start(AUTHENTICATION_TIMEOUT * 1000, false); Weather_Timer = new Timer(60000); Weather_Timer->Start(); LogDebug("The next weather check for zone: [{}] will be in [{}] seconds", short_name, Weather_Timer->GetRemainingTime()/1000); - zone_weather = 0; + zone_weather = EQ::constants::WeatherTypes::None; weather_intensity = 0; blocked_spells = nullptr; zone_total_blocked_spells = 0; @@ -1091,7 +1117,7 @@ bool Zone::Init(bool is_static) { } // if that fails, try the file name, then load defaults if (RuleManager::Instance()->GetActiveRulesetID() != default_ruleset) { - std::string r_name = RuleManager::Instance()->GetRulesetName(&database, default_ruleset); + std::string r_name = RuleSetsRepository::GetRuleSetName(database, default_ruleset); if (r_name.size() > 0) { RuleManager::Instance()->LoadRules(&database, r_name.c_str(), false); } @@ -1101,37 +1127,31 @@ bool Zone::Init(bool is_static) { watermap = WaterMap::LoadWaterMapfile(map_name); pathing = IPathfinder::Load(map_name); - LogInfo("Loading spawn conditions"); if(!spawn_conditions.LoadSpawnConditions(short_name, instanceid)) { LogError("Loading spawn conditions failed, continuing without them"); } - LogInfo("Loading static zone points"); if (!content_db.LoadStaticZonePoints(&zone_point_list, short_name, GetInstanceVersion())) { LogError("Loading static zone points failed"); return false; } - LogInfo("Loading spawn groups"); if (!content_db.LoadSpawnGroups(short_name, GetInstanceVersion(), &spawn_group_list)) { LogError("Loading spawn groups failed"); return false; } - LogInfo("Loading spawn2 points"); if (!content_db.PopulateZoneSpawnList(zoneid, spawn2_list, GetInstanceVersion())) { LogError("Loading spawn2 points failed"); return false; } - LogInfo("Loading player corpses"); if (!database.LoadCharacterCorpses(zoneid, instanceid)) { LogError("Loading player corpses failed"); return false; } - LogInfo("Loading traps"); if (!content_db.LoadTraps(short_name, GetInstanceVersion())) { LogError("Loading traps failed"); @@ -1141,19 +1161,16 @@ bool Zone::Init(bool is_static) { LogInfo("Loading adventure flavor text"); LoadAdventureFlavor(); - LogInfo("Loading ground spawns"); if (!LoadGroundSpawns()) { LogError("Loading ground spawns failed. continuing"); } - LogInfo("Loading World Objects from DB"); if (!LoadZoneObjects()) { LogError("Loading World Objects failed. continuing"); } - LogInfo("Flushing old respawn timers"); database.QueryDatabase("DELETE FROM `respawn_times` WHERE (`start` + `duration`) < UNIX_TIMESTAMP(NOW())"); LoadZoneDoors(); @@ -1194,16 +1211,15 @@ bool Zone::Init(bool is_static) { petition_list.ClearPetitions(); petition_list.ReadDatabase(); - LogInfo("Loading dynamic zones"); - DynamicZone::CacheAllFromDatabase(); + LoadDynamicZoneTemplates(); - LogInfo("Loading active Expeditions"); + DynamicZone::CacheAllFromDatabase(); Expedition::CacheAllFromDatabase(); LogInfo("Loading timezone data"); zone_time.setEQTimeZone(content_db.GetZoneTZ(zoneid, GetInstanceVersion())); - LogInfo("Init Finished: ZoneID = [{}], Time Offset = [{}]", zoneid, zone_time.getEQTimeZone()); + LogInfo("Zone booted successfully zone_id [{}] time_offset [{}]", zoneid, zone_time.getEQTimeZone()); LoadGrids(); LoadTickItems(); @@ -1211,13 +1227,17 @@ bool Zone::Init(bool is_static) { //MODDING HOOK FOR ZONE INIT mod_init(); + // logging origination information + LogSys.origination_info.zone_short_name = zone->short_name; + LogSys.origination_info.zone_long_name = zone->long_name; + LogSys.origination_info.instance_id = zone->instanceid; + return true; } void Zone::ReloadStaticData() { LogInfo("Reloading Zone Static Data"); - LogInfo("Reloading static zone points"); if (!content_db.LoadStaticZonePoints(&zone_point_list, GetShortName(), GetInstanceVersion())) { LogError("Loading static zone points failed"); } @@ -1267,58 +1287,131 @@ void Zone::ReloadStaticData() { bool Zone::LoadZoneCFG(const char* filename, uint16 instance_version) { + auto z = zone_store.GetZoneWithFallback(ZoneID(filename), instance_version); + + if (!z) { + LogError("Failed to load zone data for [{}] instance_version [{}]", filename, instance_version); + return false; + } memset(&newzone_data, 0, sizeof(NewZone_Struct)); map_name = nullptr; + map_name = new char[100]; + newzone_data.zone_id = zoneid; - if (!content_db.GetZoneCFG( - ZoneID(filename), - instance_version, - &newzone_data, - can_bind, - can_combat, - can_levitate, - can_castoutdoor, - is_city, - is_hotzone, - allow_mercs, - max_movement_update_range, - zone_type, - default_ruleset, - &map_name - )) { - // If loading a non-zero instance failed, try loading the default - if (instance_version != 0) { - safe_delete_array(map_name); - if (!content_db.GetZoneCFG( - ZoneID(filename), - 0, - &newzone_data, - can_bind, - can_combat, - can_levitate, - can_castoutdoor, - is_city, - is_hotzone, - allow_mercs, - max_movement_update_range, - zone_type, - default_ruleset, - &map_name - )) { - LogError("Error loading the Zone Config"); - return false; - } - } + strcpy(map_name, "default"); + + newzone_data.ztype = z->ztype; + zone_type = newzone_data.ztype; + + // fog:red + newzone_data.fog_red[0] = z->fog_red; + newzone_data.fog_red[1] = z->fog_red2; + newzone_data.fog_red[2] = z->fog_red3; + newzone_data.fog_red[3] = z->fog_red4; + + // fog:blue + newzone_data.fog_blue[0] = z->fog_blue; + newzone_data.fog_blue[1] = z->fog_blue2; + newzone_data.fog_blue[2] = z->fog_blue3; + newzone_data.fog_blue[3] = z->fog_blue4; + + // fog:green + newzone_data.fog_green[0] = z->fog_green; + newzone_data.fog_green[1] = z->fog_green2; + newzone_data.fog_green[2] = z->fog_green3; + newzone_data.fog_green[3] = z->fog_green4; + + // fog:minclip + newzone_data.fog_minclip[0] = z->fog_minclip; + newzone_data.fog_minclip[1] = z->fog_minclip2; + newzone_data.fog_minclip[2] = z->fog_minclip3; + newzone_data.fog_minclip[3] = z->fog_minclip4; + + // fog:maxclip + newzone_data.fog_maxclip[0] = z->fog_maxclip; + newzone_data.fog_maxclip[1] = z->fog_maxclip2; + newzone_data.fog_maxclip[2] = z->fog_maxclip3; + newzone_data.fog_maxclip[3] = z->fog_maxclip4; + + // rain_chance + newzone_data.rain_chance[0] = z->rain_chance1; + newzone_data.rain_chance[1] = z->rain_chance2; + newzone_data.rain_chance[2] = z->rain_chance3; + newzone_data.rain_chance[3] = z->rain_chance4; + + // rain_duration + newzone_data.rain_duration[0] = z->rain_duration1; + newzone_data.rain_duration[1] = z->rain_duration2; + newzone_data.rain_duration[2] = z->rain_duration3; + newzone_data.rain_duration[3] = z->rain_duration4; + + // snow_chance + newzone_data.snow_chance[0] = z->snow_chance1; + newzone_data.snow_chance[1] = z->snow_chance2; + newzone_data.snow_chance[2] = z->snow_chance3; + newzone_data.snow_chance[3] = z->snow_chance4; + + // snow_duration + newzone_data.snow_duration[0] = z->snow_duration1; + newzone_data.snow_duration[1] = z->snow_duration2; + newzone_data.snow_duration[2] = z->snow_duration3; + newzone_data.snow_duration[3] = z->snow_duration4; + + // misc + newzone_data.fog_density = z->fog_density; + newzone_data.sky = z->sky; + newzone_data.zone_exp_multiplier = z->zone_exp_multiplier; + newzone_data.safe_x = z->safe_x; + newzone_data.safe_y = z->safe_y; + newzone_data.safe_z = z->safe_z; + newzone_data.underworld = z->underworld; + newzone_data.minclip = z->minclip; + newzone_data.maxclip = z->maxclip; + newzone_data.time_type = z->time_type; + newzone_data.gravity = z->gravity; + newzone_data.fast_regen_hp = z->fast_regen_hp; + newzone_data.fast_regen_mana = z->fast_regen_mana; + newzone_data.fast_regen_endurance = z->fast_regen_endurance; + newzone_data.npc_aggro_max_dist = z->npc_max_aggro_dist; + newzone_data.underworld_teleport_index = z->underworld_teleport_index; + newzone_data.lava_damage = z->lava_damage; + newzone_data.min_lava_damage = z->min_lava_damage; + newzone_data.suspend_buffs = z->suspendbuffs; + + // local attributes + can_bind = z->canbind != 0; + is_city = z->canbind == 2; + can_combat = z->cancombat != 0; + can_levitate = z->canlevitate != 0; + can_castoutdoor = z->castoutdoor != 0; + is_hotzone = z->hotzone != 0; + max_movement_update_range = z->max_movement_update_range; + default_ruleset = z->ruleset; + allow_mercs = true; + m_graveyard_id = z->graveyard_id; + m_max_clients = z->maxclients; + + // safe coordinates + m_safe_points.x = z->safe_x; + m_safe_points.y = z->safe_y; + m_safe_points.z = z->safe_z; + m_safe_points.w = z->safe_heading; + + if (!z->map_file_name.empty()) { + strcpy(map_name, z->map_file_name.c_str()); + } + else { + strcpy(map_name, z->short_name.c_str()); } - //overwrite with our internal variables + // overwrite with our internal variables strcpy(newzone_data.zone_short_name, GetShortName()); strcpy(newzone_data.zone_long_name, GetLongName()); strcpy(newzone_data.zone_short_name2, GetShortName()); LogInfo( - "Successfully loaded Zone Config for Zone [{}] ({}) Version [{}] Instance ID [{}]", + "Successfully loaded zone headers for zone [{}] long_name [{}] version [{}] instance_id [{}]", GetShortName(), GetLongName(), GetInstanceVersion(), @@ -1487,9 +1580,9 @@ bool Zone::Process() { } } - if(!staticzone) { + if (!staticzone) { if (autoshutdown_timer.Check()) { - StartShutdownTimer(); + ResetShutdownTimer(); if (numclients == 0) { return false; } @@ -1603,133 +1696,158 @@ void Zone::ChangeWeather() } int chance = zone->random.Int(0, 3); - uint8 rainchance = zone->newzone_data.rain_chance[chance]; - uint8 rainduration = zone->newzone_data.rain_duration[chance]; - uint8 snowchance = zone->newzone_data.snow_chance[chance]; - uint8 snowduration = zone->newzone_data.snow_duration[chance]; - uint32 weathertimer = 0; - uint16 tmpweather = zone->random.Int(0, 100); + auto rain_chance = zone->newzone_data.rain_chance[chance]; + auto rain_duration = zone->newzone_data.rain_duration[chance]; + auto snow_chance = zone->newzone_data.snow_chance[chance]; + auto snow_duration = zone->newzone_data.snow_duration[chance]; + uint32 weather_timer = 0; + auto temporary_weather = static_cast(zone->random.Int(0, 100)); uint8 duration = 0; - uint8 tmpOldWeather = zone->zone_weather; + auto temporary_old_weather = zone->zone_weather; bool changed = false; - if(tmpOldWeather == 0) - { - if(rainchance > 0 || snowchance > 0) - { - uint8 intensity = zone->random.Int(1, 10); - if((rainchance > snowchance) || (rainchance == snowchance)) - { - //It's gunna rain! - if(rainchance >= tmpweather) - { - if(rainduration == 0) + if (temporary_old_weather == EQ::constants::WeatherTypes::None) { + if (rain_chance || snow_chance) { + auto intensity = static_cast(zone->random.Int(1, 10)); + if (rain_chance > snow_chance || rain_chance == snow_chance) { // Rain + if (rain_chance >= temporary_weather) { + if (!rain_duration) { duration = 1; - else - duration = rainduration*3; //Duration is 1 EQ hour which is 3 earth minutes. + } else { + duration = rain_duration * 3; //Duration is 1 EQ hour which is 3 earth minutes. + } - weathertimer = (duration*60)*1000; - Weather_Timer->Start(weathertimer); - zone->zone_weather = 1; + weather_timer = (duration * 60) * 1000; + Weather_Timer->Start(weather_timer); + zone->zone_weather = EQ::constants::WeatherTypes::Raining; zone->weather_intensity = intensity; changed = true; } - } - else - { - //It's gunna snow! - if(snowchance >= tmpweather) - { - if(snowduration == 0) + } else { // Snow + if (snow_chance >= temporary_weather) { + if (!snow_duration) { duration = 1; - else - duration = snowduration*3; - weathertimer = (duration*60)*1000; - Weather_Timer->Start(weathertimer); - zone->zone_weather = 2; + } else { + duration = snow_duration * 3; //Duration is 1 EQ hour which is 3 earth minutes. + } + + weather_timer = (duration * 60) * 1000; + Weather_Timer->Start(weather_timer); + zone->zone_weather = EQ::constants::WeatherTypes::Snowing; zone->weather_intensity = intensity; changed = true; } } } - } - else - { + } else { changed = true; //We've had weather, now taking a break - if(tmpOldWeather == 1) - { - if(rainduration == 0) + if (temporary_old_weather == EQ::constants::WeatherTypes::Raining) { + if (!rain_duration) { duration = 1; - else - duration = rainduration*3; //Duration is 1 EQ hour which is 3 earth minutes. + } else { + duration = rain_duration * 3; //Duration is 1 EQ hour which is 3 earth minutes. + } - weathertimer = (duration*60)*1000; - Weather_Timer->Start(weathertimer); + weather_timer = (duration * 60) * 1000; + Weather_Timer->Start(weather_timer); zone->weather_intensity = 0; - } - else if(tmpOldWeather == 2) - { - if(snowduration == 0) + } else if (temporary_old_weather == EQ::constants::WeatherTypes::Snowing) { + if (!snow_duration) { duration = 1; - else - duration = snowduration*3; //Duration is 1 EQ hour which is 3 earth minutes. + } else { + duration = snow_duration * 3; //Duration is 1 EQ hour which is 3 earth minutes. + } - weathertimer = (duration*60)*1000; - Weather_Timer->Start(weathertimer); + weather_timer = (duration * 60) * 1000; + Weather_Timer->Start(weather_timer); zone->weather_intensity = 0; } } - if(changed == false) - { - if(weathertimer == 0) - { - uint32 weatherTimerRule = RuleI(Zone, WeatherTimer); - weathertimer = weatherTimerRule*1000; - Weather_Timer->Start(weathertimer); + if (!changed) { + if (!weather_timer) { + uint32 weather_timer_rule = RuleI(Zone, WeatherTimer); + weather_timer = weather_timer_rule * 1000; + Weather_Timer->Start(weather_timer); } LogDebug("The next weather check for zone: [{}] will be in [{}] seconds", zone->GetShortName(), Weather_Timer->GetRemainingTime()/1000); - } - else - { - LogDebug("The weather for zone: [{}] has changed. Old weather was = [{}]. New weather is = [{}] The next check will be in [{}] seconds. Rain chance: [{}], Rain duration: [{}], Snow chance [{}], Snow duration: [{}]", zone->GetShortName(), tmpOldWeather, zone_weather,Weather_Timer->GetRemainingTime()/1000,rainchance,rainduration,snowchance,snowduration); + } else { + LogDebug("The weather for zone: [{}] has changed. Old weather was = [{}]. New weather is = [{}] The next check will be in [{}] seconds. Rain chance: [{}], Rain duration: [{}], Snow chance [{}], Snow duration: [{}]", zone->GetShortName(), temporary_old_weather, zone_weather,Weather_Timer->GetRemainingTime()/1000,rain_chance,rain_duration,snow_chance,snow_duration); weatherSend(); - if (zone->weather_intensity == 0) - { - zone->zone_weather = 0; + if (!zone->weather_intensity) { + zone->zone_weather = EQ::constants::WeatherTypes::None; } } } bool Zone::HasWeather() { - uint8 rain1 = zone->newzone_data.rain_chance[0]; - uint8 rain2 = zone->newzone_data.rain_chance[1]; - uint8 rain3 = zone->newzone_data.rain_chance[2]; - uint8 rain4 = zone->newzone_data.rain_chance[3]; - uint8 snow1 = zone->newzone_data.snow_chance[0]; - uint8 snow2 = zone->newzone_data.snow_chance[1]; - uint8 snow3 = zone->newzone_data.snow_chance[2]; - uint8 snow4 = zone->newzone_data.snow_chance[3]; + auto rain_chance_one = zone->newzone_data.rain_chance[0]; + auto rain_chance_two = zone->newzone_data.rain_chance[1]; + auto rain_chance_three = zone->newzone_data.rain_chance[2]; + auto rain_chance_four = zone->newzone_data.rain_chance[3]; - if(rain1 == 0 && rain2 == 0 && rain3 == 0 && rain4 == 0 && snow1 == 0 && snow2 == 0 && snow3 == 0 && snow4 == 0) + auto snow_chance_one = zone->newzone_data.snow_chance[0]; + auto snow_chance_two = zone->newzone_data.snow_chance[1]; + auto snow_chance_three = zone->newzone_data.snow_chance[2]; + auto snow_chance_four = zone->newzone_data.snow_chance[3]; + + if ( + !rain_chance_one && + !rain_chance_two && + !rain_chance_three && + !rain_chance_four && + !snow_chance_one && + !snow_chance_two && + !snow_chance_three && + !snow_chance_four + ) { return false; - else + } else { return true; + } } -void Zone::StartShutdownTimer(uint32 set_time) { - if (set_time > autoshutdown_timer.GetRemainingTime()) { - if (set_time == (RuleI(Zone, AutoShutdownDelay))) { - set_time = static_cast(content_db.getZoneShutDownDelay(GetZoneID(), GetInstanceVersion())); +void Zone::StartShutdownTimer(uint32 set_time) +{ + // if we pass in the default value, we should pull from the zone and use it is different + std::string loaded_from = "rules"; + if (set_time == (RuleI(Zone, AutoShutdownDelay))) { + auto delay = content_db.getZoneShutDownDelay( + GetZoneID(), + GetInstanceVersion() + ); + if (delay != RuleI(Zone, AutoShutdownDelay)) { + set_time = delay; + loaded_from = "zone table"; } - - autoshutdown_timer.SetTimer(set_time); - LogDebug("Zone::StartShutdownTimer set to {}", set_time); } - LogDebug("Zone::StartShutdownTimer trigger - set_time: [{}] remaining_time: [{}] diff: [{}]", set_time, autoshutdown_timer.GetRemainingTime(), (set_time - autoshutdown_timer.GetRemainingTime())); + if (set_time != autoshutdown_timer.GetDuration()) { + LogInfo( + "Reset to [{}] {} from original remaining time [{}] duration [{}] zone [{}]", + Strings::SecondsToTime(set_time, true), + !loaded_from.empty() ? fmt::format("(Loaded from [{}])", loaded_from) : "", + Strings::SecondsToTime(autoshutdown_timer.GetRemainingTime(), true), + Strings::SecondsToTime(autoshutdown_timer.GetDuration(), true), + zone->GetZoneDescription() + ); + } + + autoshutdown_timer.SetTimer(set_time); +} + +void Zone::ResetShutdownTimer() { + LogInfo( + "Reset to [{}] from original remaining time [{}] duration [{}] zone [{}]", + Strings::SecondsToTime(autoshutdown_timer.GetDuration(), true), + Strings::SecondsToTime(autoshutdown_timer.GetRemainingTime(), true), + Strings::SecondsToTime(autoshutdown_timer.GetDuration(), true), + zone->GetZoneDescription() + ); + + autoshutdown_timer.Start(autoshutdown_timer.GetDuration(), true); } bool Zone::Depop(bool StartSpawnTimer) { @@ -1747,6 +1865,7 @@ bool Zone::Depop(bool StartSpawnTimer) { // clear spell cache database.ClearNPCSpells(); + database.ClearBotSpells(); zone->spawn_group_list.ReloadSpawnGroups(); @@ -1801,7 +1920,6 @@ void Zone::Repop() LogError("Loading spawn groups failed"); } - LogInfo("Loading spawn conditions"); if (!spawn_conditions.LoadSpawnConditions(short_name, instanceid)) { LogError("Loading spawn conditions failed, continuing without them"); } @@ -2044,6 +2162,8 @@ bool ZoneDatabase::LoadStaticZonePoints(LinkedList *zone_point_list zone->numzonepoints++; } + LogInfo("Loaded [{}] zone_points", Strings::Commify(std::to_string(zone_points.size()))); + return true; } @@ -2064,24 +2184,28 @@ bool ZoneDatabase::GetDecayTimes(npcDecayTimes_Struct *npcCorpseDecayTimes) npcCorpseDecayTimes[index].seconds = std::min(24 * 60 * 60, atoi(row[1])); } + LogInfo("Loaded [{}] decay timers", Strings::Commify(results.RowCount())); + return true; } void Zone::weatherSend(Client *client) { auto outapp = new EQApplicationPacket(OP_Weather, 8); - if (zone_weather > 0) { + if (zone_weather > EQ::constants::WeatherTypes::None) { outapp->pBuffer[0] = zone_weather - 1; } - if (zone_weather > 0) { + + if (zone_weather > EQ::constants::WeatherTypes::None) { outapp->pBuffer[4] = zone->weather_intensity; } + if (client) { client->QueuePacket(outapp); - } - else { + } else { entity_list.QueueClients(0, outapp); } + safe_delete(outapp); } @@ -2096,7 +2220,7 @@ bool Zone::HasGraveyard() { void Zone::SetGraveyard(uint32 zoneid, const glm::vec4& graveyardPosition) { pgraveyard_zoneid = zoneid; - m_Graveyard = graveyardPosition; + m_graveyard = graveyardPosition; } void Zone::LoadZoneBlockedSpells() @@ -2110,6 +2234,8 @@ void Zone::LoadZoneBlockedSpells() ClearBlockedSpells(); } } + + LogInfo("Loaded [{}] blocked spells(s)", Strings::Commify(zone_total_blocked_spells)); } } @@ -2283,6 +2409,8 @@ void Zone::LoadVeteranRewards() return; } + LogInfo("Loaded [{}] veteran reward(s)", Strings::Commify(results.RowCount())); + int index = 0; for (auto row = results.begin(); row != results.end(); ++row, ++index) { @@ -2334,6 +2462,7 @@ void Zone::LoadAlternateCurrencies() AlternateCurrencies.push_back(current_currency); } + LogInfo("Loaded [{}] alternate currencies", Strings::Commify(results.RowCount())); } void Zone::UpdateQGlobal(uint32 qid, QGlobal newGlobal) @@ -2379,6 +2508,7 @@ void Zone::LoadAdventureFlavor() adventure_entry_list_flavor[id] = row[1]; } + LogInfo("Loaded [{}] adventure text entries", Strings::Commify(results.RowCount())); } void Zone::DoAdventureCountIncrease() @@ -2409,24 +2539,28 @@ void Zone::DoAdventureAssassinationCountIncrease() void Zone::DoAdventureActions() { - ServerZoneAdventureDataReply_Struct* ds = (ServerZoneAdventureDataReply_Struct*)adv_data; - if(ds->type == Adventure_Collect) - { - int count = (ds->total - ds->count) * 25 / 10; + const auto* ds = (ServerZoneAdventureDataReply_Struct*) adv_data; + if (ds->type == Adventure_Collect) { + int count = (ds->total - ds->count) * 25 / RuleI(Adventure, LDoNLootCountModifier); entity_list.AddLootToNPCS(ds->data_id, count); did_adventure_actions = true; - } - else if(ds->type == Adventure_Assassinate) - { - if(ds->assa_count >= RuleI(Adventure, NumberKillsForBossSpawn)) - { - const NPCType* tmp = content_db.LoadNPCTypesData(ds->data_id); - if(tmp) - { - NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), GravityBehavior::Water); + } else if (ds->type == Adventure_Assassinate) { + if (ds->assa_count >= RuleI(Adventure, NumberKillsForBossSpawn)) { + const auto* d = content_db.LoadNPCTypesData(ds->data_id); + if (d) { + NPC* npc = new NPC( + d, + nullptr, + glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), + GravityBehavior::Water + ); + npc->AddLootTable(); - if (npc->DropsGlobalLoot()) + + if (npc->DropsGlobalLoot()) { npc->CheckGlobalLootTables(); + } + entity_list.AddNPC(npc); npc->Shout("Rarrrgh!"); did_adventure_actions = true; @@ -2460,6 +2594,8 @@ void Zone::LoadNPCEmotes(LinkedList* NPCEmoteList) NPCEmoteList->Insert(nes); } + LogInfo("Loaded [{}] npc emotes", Strings::Commify(results.RowCount())); + } void Zone::ReloadWorld(uint8 global_repop) @@ -2549,6 +2685,7 @@ void Zone::LoadTickItems() } + LogInfo("Loaded [{}] item_tick entries", Strings::Commify(results.RowCount())); } uint32 Zone::GetSpawnKillCount(uint32 in_spawnid) { @@ -2633,9 +2770,9 @@ void Zone::CalculateNpcUpdateDistanceSpread() } } - int x_spread = int(abs(max_x - min_x)); - int y_spread = int(abs(max_y - min_y)); - int combined_spread = int(abs((x_spread + y_spread) / 2)); + int x_spread = int(std::abs(max_x - min_x)); + int y_spread = int(std::abs(max_y - min_y)); + int combined_spread = int(std::abs((x_spread + y_spread) / 2)); int update_distance = EQ::ClampLower(int(combined_spread / 4), int(zone->GetMaxMovementUpdateRange())); SetNpcPositionUpdateDistance(update_distance); @@ -2659,8 +2796,14 @@ void Zone::SetQuestHotReloadQueued(bool in_quest_hot_reload_queued) void Zone::LoadGrids() { - zone_grids = GridRepository::GetZoneGrids(GetZoneID()); - zone_grid_entries = GridEntriesRepository::GetZoneGridEntries(GetZoneID()); + zone_grids = GridRepository::GetZoneGrids(content_db, GetZoneID()); + zone_grid_entries = GridEntriesRepository::GetZoneGridEntries(content_db, GetZoneID()); + + LogInfo( + "Loaded [{}] grids and [{}] grid_entries", + Strings::Commify(zone_grids.size()), + Strings::Commify(zone_grid_entries.size()) + ); } Timer Zone::GetInitgridsTimer() @@ -2734,8 +2877,16 @@ uint32 Zone::GetCurrencyItemID(uint32 currency_id) std::string Zone::GetZoneDescription() { - auto d = fmt::format( - "{} ({}){}{}", + if (!IsLoaded()) { + return fmt::format( + "PID ({})", + EQ::GetPID() + ); + } + + return fmt::format( + "PID ({}) {} ({}){}{}", + EQ::GetPID(), GetLongName(), GetZoneID(), ( @@ -2755,8 +2906,6 @@ std::string Zone::GetZoneDescription() "" ) ); - - return d; } void Zone::SendReloadMessage(std::string reload_type) @@ -2773,3 +2922,245 @@ void Zone::SendReloadMessage(std::string reload_type) ).c_str() ); } + +void Zone::SendDiscordMessage(int webhook_id, const std::string& message) +{ + if (worldserver.Connected()) { + auto pack = new ServerPacket(ServerOP_DiscordWebhookMessage, sizeof(DiscordWebhookMessage_Struct) + 1); + auto *q = (DiscordWebhookMessage_Struct *) pack->pBuffer; + + strn0cpy(q->message, message.c_str(), 2000); + q->webhook_id = webhook_id; + + worldserver.SendPacket(pack); + safe_delete(pack); + } +} + +void Zone::SendDiscordMessage(const std::string& webhook_name, const std::string &message) +{ + bool not_found = true; + + for (int i= 0; i < MAX_DISCORD_WEBHOOK_ID; i++) { + auto &w = LogSys.GetDiscordWebhooks()[i]; + if (w.webhook_name == webhook_name) { + SendDiscordMessage(w.id, message + "\n"); + not_found = false; + } + } + + if (not_found) { + LogDiscord("Did not find valid webhook by webhook name [{}]", webhook_name); + } +} + +void Zone::LoadDynamicZoneTemplates() +{ + dz_template_cache.clear(); + auto dz_templates = DynamicZoneTemplatesRepository::All(content_db); + for (const auto& dz_template : dz_templates) + { + dz_template_cache[dz_template.id] = dz_template; + } +} + +std::string Zone::GetAAName(int aa_id) +{ + if (!aa_id) { + return std::string(); + } + + int current_aa_id = 0; + + const auto& r = aa_ranks.find(aa_id); + if ( + r != aa_ranks.end() && + r->second.get()->base_ability + ) { + current_aa_id = r->second.get()->base_ability->id; + } + + if (current_aa_id) { + const auto& a = aa_abilities.find(current_aa_id); + if (a != aa_abilities.end()) { + return a->second.get()->name; + } + } + + return std::string(); +} + +bool Zone::CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, std::string player_value) +{ + std::vector bucket_checks; + bool found = false; + bool passes = false; + + switch (bucket_comparison) { + case BucketComparison::BucketEqualTo: + { + if (player_value != bucket_value) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketNotEqualTo: + { + if (player_value == bucket_value) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketGreaterThanOrEqualTo: + { + if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) { + break; + } + + if (std::stoll(player_value) < std::stoll(bucket_value)) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketLesserThanOrEqualTo: + { + if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) { + break; + } + + if (std::stoll(player_value) > std::stoll(bucket_value)) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketGreaterThan: + { + if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) { + break; + } + + if (std::stoll(player_value) <= std::stoll(bucket_value)) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketLesserThan: + { + if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) { + break; + } + + if (std::stoll(player_value) >= std::stoll(bucket_value)) { + break; + } + + passes = true; + + break; + } + case BucketComparison::BucketIsAny: + { + bucket_checks = Strings::Split(bucket_value, "|"); + if (bucket_checks.empty()) { + break; + } + + if (std::find(bucket_checks.begin(), bucket_checks.end(), player_value) != bucket_checks.end()) { + found = true; + } + + if (!found) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketIsNotAny: + { + bucket_checks = Strings::Split(bucket_value, "|"); + if (bucket_checks.empty()) { + break; + } + + if (std::find(bucket_checks.begin(), bucket_checks.end(), player_value) != bucket_checks.end()) { + found = true; + } + + if (found) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketIsBetween: + { + bucket_checks = Strings::Split(bucket_value, "|"); + if (bucket_checks.empty()) { + break; + } + + if ( + !Strings::IsNumber(player_value) || + !Strings::IsNumber(bucket_checks[0]) || + !Strings::IsNumber(bucket_checks[1]) + ) { + break; + } + + if ( + !EQ::ValueWithin( + std::stoll(player_value), + std::stoll(bucket_checks[0]), + std::stoll(bucket_checks[1]) + ) + ) { + break; + } + + passes = true; + break; + } + case BucketComparison::BucketIsNotBetween: + { + bucket_checks = Strings::Split(bucket_value, "|"); + if (bucket_checks.empty()) { + break; + } + + if ( + !Strings::IsNumber(player_value) || + !Strings::IsNumber(bucket_checks[0]) || + !Strings::IsNumber(bucket_checks[1]) + ) { + break; + } + + if ( + EQ::ValueWithin( + std::stoll(player_value), + std::stoll(bucket_checks[0]), + std::stoll(bucket_checks[1]) + ) + ) { + break; + } + + passes = true; + break; + } + } + + return passes; +} diff --git a/zone/zone.h b/zone/zone.h index 8450b0f18..3d404397c 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -23,9 +23,9 @@ #include "../common/rulesys.h" #include "../common/types.h" #include "../common/random.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "zonedb.h" -#include "zone_store.h" +#include "../common/zone_store.h" #include "../common/repositories/grid_repository.h" #include "../common/repositories/grid_entries_repository.h" #include "../common/repositories/zone_points_repository.h" @@ -35,6 +35,9 @@ #include "aa_ability.h" #include "pathfinder_interface.h" #include "global_loot_manager.h" +#include "queryserv.h" +#include "../common/discord/discord.h" +#include "../common/repositories/dynamic_zone_templates_repository.h" class DynamicZone; @@ -147,11 +150,12 @@ public: const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location); EQ::Random random; - EQTime zone_time; + EQTime zone_time; - ZonePoint *GetClosestZonePoint(const glm::vec3 &location, const char *to_name, Client *client, float max_distance = 40000.0f); + ZonePoint * + GetClosestZonePoint(const glm::vec3 &location, const char *to_name, Client *client, float max_distance = 40000.0f); - inline bool BuffTimersSuspended() const { return newzone_data.SuspendBuffs != 0; }; + inline bool BuffTimersSuspended() const { return newzone_data.suspend_buffs != 0; }; inline bool HasMap() { return zonemap != nullptr; } inline bool HasWaterMap() { return watermap != nullptr; } inline bool InstantGrids() { return (!initgrids_timer.Enabled()); } @@ -162,13 +166,13 @@ public: inline const char *GetShortName() { return short_name; } inline const uint8 GetZoneType() const { return zone_type; } inline const uint16 GetInstanceVersion() const { return instanceversion; } - inline const uint32 &GetMaxClients() { return pMaxClients; } - inline const uint32 &graveyard_id() { return pgraveyard_id; } + inline const uint32 &GetMaxClients() { return m_max_clients; } + inline const uint32 &graveyard_id() { return m_graveyard_id; } inline const uint32 &graveyard_zoneid() { return pgraveyard_zoneid; } inline const uint32 GetInstanceID() const { return instanceid; } inline const uint32 GetZoneID() const { return zoneid; } - inline glm::vec4 GetSafePoint() { return m_SafePoint; } - inline glm::vec4 GetGraveyardPoint() { return m_Graveyard; } + inline glm::vec4 GetSafePoint() { return m_safe_points; } + inline glm::vec4 GetGraveyardPoint() { return m_graveyard; } inline std::vector GetGlobalLootTables(NPC *mob) const { return m_global_loot.GetGlobalLootTables(mob); } inline Timer *GetInstanceTimer() { return Instance_Timer; } inline void AddGlobalLootEntry(GlobalLootEntry &in) { return m_global_loot.AddEntry(in); } @@ -179,7 +183,7 @@ public: void DumpMerchantList(uint32 npcid); int SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold = false); int32 MobsAggroCount() { return aggroedmobs; } - DynamicZone* GetDynamicZone(); + DynamicZone *GetDynamicZone(); IPathfinder *pathing; LinkedList NPCEmoteList; @@ -187,31 +191,31 @@ public: LinkedList zone_point_list; std::vector virtual_zone_point_list; - Map *zonemap; + Map *zonemap; MercTemplate *GetMercTemplate(uint32 template_id); - NewZone_Struct newzone_data; + NewZone_Struct newzone_data; QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; } QGlobalCache *GetQGlobals() { return qGlobals; } - SpawnConditionManager spawn_conditions; - SpawnGroupList spawn_group_list; + SpawnConditionManager spawn_conditions; + SpawnGroupList spawn_group_list; - std::list AlternateCurrencies; - std::list VeteranRewards; - std::map ldon_trap_list; - std::map merc_templates; - std::map merctable; - std::map npctable; - std::map > ldon_trap_entry_list; - std::map > merchanttable; - std::map > merc_spells_list; - std::map > merc_stance_list; - std::map > tmpmerchanttable; - std::map adventure_entry_list_flavor; - std::map level_exp_mod; + std::list AlternateCurrencies; + std::list VeteranRewards; + std::map ldon_trap_list; + std::map merc_templates; + std::map merctable; + std::map npctable; + std::map > ldon_trap_entry_list; + std::map > merchanttable; + std::map > merc_spells_list; + std::map > merc_stance_list; + std::map > tmpmerchanttable; + std::map adventure_entry_list_flavor; + std::map level_exp_mod; std::pair GetAlternateAdvancementAbilityAndRank(int id, int points_spent); @@ -219,11 +223,12 @@ public: std::unordered_map> aa_abilities; std::unordered_map> aa_ranks; - std::vector zone_grids; - std::vector zone_grid_entries; + std::vector zone_grids; + std::vector zone_grid_entries; std::unordered_map> dynamic_zone_cache; - std::unordered_map> expedition_cache; + std::unordered_map> expedition_cache; + std::unordered_map dz_template_cache; time_t weather_timer; Timer spawn2_timer; @@ -244,6 +249,11 @@ public: uint32 GetCurrencyID(uint32 item_id); uint32 GetCurrencyItemID(uint32 currency_id); + std::string GetAAName(int aa_id); + + inline bool IsRaining() { return zone_weather == EQ::constants::WeatherTypes::Raining; } + inline bool IsSnowing() { return zone_weather == EQ::constants::WeatherTypes::Snowing; } + std::string GetZoneDescription(); void SendReloadMessage(std::string reload_type); @@ -264,6 +274,7 @@ public: void LoadAdventureFlavor(); void LoadAlternateAdvancement(); void LoadAlternateCurrencies(); + void LoadDynamicZoneTemplates(); void LoadZoneBlockedSpells(); void LoadLDoNTrapEntries(); void LoadLDoNTraps(); @@ -292,6 +303,7 @@ public: void SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp); void SpawnConditionChanged(const SpawnCondition &c, int16 old_value); void StartShutdownTimer(uint32 set_time = (RuleI(Zone, AutoShutdownDelay))); + void ResetShutdownTimer(); void UpdateQGlobal(uint32 qid, QGlobal newGlobal); void weatherSend(Client *client = nullptr); void ClearSpawnTimers(); @@ -299,6 +311,8 @@ public: bool IsQuestHotReloadQueued() const; void SetQuestHotReloadQueued(bool in_quest_hot_reload_queued); + bool CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, std::string player_value); + WaterMap *watermap; ZonePoint *GetClosestZonePoint(const glm::vec3 &location, uint32 to, Client *client, float max_distance = 40000.0f); ZonePoint *GetClosestZonePointWithoutZone(float x, float y, float z, Client *client, float max_distance = 40000.0f); @@ -313,8 +327,13 @@ public: * @param log_category * @param message */ - static void GMSayHookCallBackProcess(uint16 log_category, std::string message) + static void GMSayHookCallBackProcess(uint16 log_category, const char *func, std::string message) { + // we don't want to loop up with chat messages + if (message.find("OP_SpecialMesg") != std::string::npos) { + return; + } + /** * Cut messages down to 4000 max to prevent client crash */ @@ -325,10 +344,10 @@ public: /** * Replace Occurrences of % or MessageStatus will crash */ - find_replace(message, std::string("%"), std::string(".")); + Strings::FindReplace(message, std::string("%"), std::string(".")); if (message.find('\n') != std::string::npos) { - auto message_split = SplitString(message, '\n'); + auto message_split = Strings::Split(message, '\n'); entity_list.MessageStatus( 0, AccountStatus::QuestTroupe, @@ -344,19 +363,36 @@ public: fmt::format( "--- {}", message_split[iter] - ).c_str() + ).c_str() ); } - } else { + } + else { entity_list.MessageStatus( 0, AccountStatus::QuestTroupe, LogSys.GetGMSayColorFromCategory(log_category), - message.c_str() + fmt::format("[{}] [{}] {}", Logs::LogCategoryName[log_category], func, message).c_str() ); } } + static void SendDiscordMessage(int webhook_id, const std::string& message); + static void SendDiscordMessage(const std::string& webhook_name, const std::string& message); + static void DiscordWebhookMessageHandler(uint16 log_category, int webhook_id, const std::string &message) + { + std::string message_prefix; + if (!LogSys.origination_info.zone_short_name.empty()) { + message_prefix = fmt::format( + "[**{}**] **Zone** [**{}**] ", + Logs::LogCategoryName[log_category], + LogSys.origination_info.zone_short_name + ); + } + + SendDiscordMessage(webhook_id, message_prefix + Discord::FormatDiscordMessage(log_category, message)); + }; + double GetMaxMovementUpdateRange() const { return max_movement_update_range; } /** @@ -385,8 +421,8 @@ private: char *map_name; char *short_name; char file_name[16]; - glm::vec4 m_SafePoint; - glm::vec4 m_Graveyard; + glm::vec4 m_safe_points; + glm::vec4 m_graveyard; int default_ruleset; int zone_total_blocked_spells; int npc_position_update_distance; @@ -395,8 +431,8 @@ private: uint16 instanceversion; uint32 instanceid; uint32 instance_time_remaining; - uint32 pgraveyard_id, pgraveyard_zoneid; - uint32 pMaxClients; + uint32 m_graveyard_id, pgraveyard_zoneid; + uint32 m_max_clients; uint32 zoneid; uint32 m_last_ucss_update; diff --git a/zone/zone_config.h b/zone/zone_config.h index 43f5b723c..a8e7401b6 100644 --- a/zone/zone_config.h +++ b/zone/zone_config.h @@ -43,13 +43,13 @@ class ZoneConfig : public EQEmuConfig { } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_zone_config != nullptr) delete _zone_config; _zone_config=new ZoneConfig; _config=_zone_config; - return _config->parseFile(); + return _config->parseFile(path); } // Accessors for the static private object diff --git a/zone/zone_event_scheduler.cpp b/zone/zone_event_scheduler.cpp index 2294ad50e..839dfa981 100644 --- a/zone/zone_event_scheduler.cpp +++ b/zone/zone_event_scheduler.cpp @@ -35,7 +35,7 @@ void ZoneEventScheduler::Process(Zone *zone, WorldContentService *content_servic LogSchedulerDetail("Looping active event validated [{}]", e.event_type); if (e.event_type == ServerEvents::EVENT_TYPE_HOT_ZONE_ACTIVE) { LogScheduler("Deactivating event [{}] disabling hotzone status", e.description); - if (search_deliminated_string(e.event_data, zone->GetShortName()) != std::string::npos) { + if (Strings::SearchDelim(e.event_data, zone->GetShortName()) != std::string::npos) { zone->SetIsHotzone(false); } RemoveActiveEvent(e); @@ -85,7 +85,7 @@ void ZoneEventScheduler::Process(Zone *zone, WorldContentService *content_servic // such as broadcasts, reloads if (ValidateEventReadyToActivate(e) && !IsEventActive(e)) { if (e.event_type == ServerEvents::EVENT_TYPE_HOT_ZONE_ACTIVE) { - if (search_deliminated_string(e.event_data, zone->GetShortName()) != std::string::npos) { + if (Strings::SearchDelim(e.event_data, zone->GetShortName()) != std::string::npos) { zone->SetIsHotzone(true); LogScheduler("Activating Event [{}] Enabling zone as hotzone", e.description); } @@ -93,7 +93,7 @@ void ZoneEventScheduler::Process(Zone *zone, WorldContentService *content_servic } if (e.event_type == ServerEvents::EVENT_TYPE_RULE_CHANGE) { - auto params = SplitString(e.event_data, '='); + auto params = Strings::Split(e.event_data, '='); auto rule_key = params[0]; auto rule_value = params[1]; if (!rule_key.empty() && !rule_value.empty()) { diff --git a/zone/zone_reload.cpp b/zone/zone_reload.cpp index f39b35fc7..fbe9e55f7 100644 --- a/zone/zone_reload.cpp +++ b/zone/zone_reload.cpp @@ -32,11 +32,11 @@ void ZoneReload::HotReloadQuests() if (RuleB(HotReload, QuestsRepopWithReload)) { zone->Repop(); } - + zone->SetQuestHotReloadQueued(false); LogHotReload( - "[Quests] Reloading [{}] repop [{}] reset_timers [{}] repop_when_not_in_combat [{}] Time [{:.4f}]", + "Reloading [{}] repop [{}] reset_timers [{}] repop_when_not_in_combat [{}] Time [{:.4f}]", zone->GetShortName(), (RuleB(HotReload, QuestsRepopWithReload) ? "true" : "false"), (RuleB(HotReload, QuestsResetTimersWithReload) ? "true" : "false"), diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index c370e14ce..b81eef4c5 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3,7 +3,7 @@ #include "../common/extprofile.h" #include "../common/item_instance.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "client.h" #include "corpse.h" @@ -11,7 +11,6 @@ #include "merc.h" #include "zone.h" #include "zonedb.h" -#include "zone_store.h" #include "aura.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/npc_types_repository.h" @@ -95,182 +94,6 @@ bool ZoneDatabase::SaveZoneCFG(uint32 zoneid, uint16 instance_version, NewZone_S return true; } -bool ZoneDatabase::GetZoneCFG( - uint32 zoneid, - uint16 instance_version, - NewZone_Struct *zone_data, - bool &can_bind, - bool &can_combat, - bool &can_levitate, - bool &can_castoutdoor, - bool &is_city, - bool &is_hotzone, - bool &allow_mercs, - double &max_movement_update_range, - uint8 &zone_type, - int &ruleset, - char **map_filename) { - - *map_filename = new char[100]; - zone_data->zone_id = zoneid; - - std::string query = fmt::format( - "SELECT " - "ztype, " // 0 - "fog_red, " // 1 - "fog_green, " // 2 - "fog_blue, " // 3 - "fog_minclip, " // 4 - "fog_maxclip, " // 5 - "fog_red2, " // 6 - "fog_green2, " // 7 - "fog_blue2, " // 8 - "fog_minclip2, " // 9 - "fog_maxclip2, " // 10 - "fog_red3, " // 11 - "fog_green3, " // 12 - "fog_blue3, " // 13 - "fog_minclip3, " // 14 - "fog_maxclip3, " // 15 - "fog_red4, " // 16 - "fog_green4, " // 17 - "fog_blue4, " // 18 - "fog_minclip4, " // 19 - "fog_maxclip4, " // 20 - "fog_density, " // 21 - "sky, " // 22 - "zone_exp_multiplier, " // 23 - "safe_x, " // 24 - "safe_y, " // 25 - "safe_z, " // 26 - "underworld, " // 27 - "minclip, " // 28 - "maxclip, " // 29 - "time_type, " // 30 - "canbind, " // 31 - "cancombat, " // 32 - "canlevitate, " // 33 - "castoutdoor, " // 34 - "hotzone, " // 35 - "ruleset, " // 36 - "suspendbuffs, " // 37 - "map_file_name, " // 38 - "short_name, " // 39 - "rain_chance1, " // 40 - "rain_chance2, " // 41 - "rain_chance3, " // 42 - "rain_chance4, " // 43 - "rain_duration1, " // 44 - "rain_duration2, " // 45 - "rain_duration3, " // 46 - "rain_duration4, " // 47 - "snow_chance1, " // 48 - "snow_chance2, " // 49 - "snow_chance3, " // 50 - "snow_chance4, " // 51 - "snow_duration1, " // 52 - "snow_duration2, " // 53 - "snow_duration3, " // 54 - "snow_duration4, " // 55 - "gravity, " // 56 - "fast_regen_hp, " // 57 - "fast_regen_mana, " // 58 - "fast_regen_endurance, " // 59 - "npc_max_aggro_dist, " // 60 - "max_movement_update_range, " // 61 - "underworld_teleport_index, " // 62 - "lava_damage, " // 63 - "min_lava_damage " // 64 - "FROM zone WHERE zoneidnumber = {} AND version = {} {}", - zoneid, - instance_version, - ContentFilterCriteria::apply() - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - strcpy(*map_filename, "default"); - return false; - } - - if (results.RowCount() == 0) { - strcpy(*map_filename, "default"); - return false; - } - - auto row = results.begin(); - - memset(zone_data, 0, sizeof(NewZone_Struct)); - zone_data->ztype = atoi(row[0]); - zone_type = zone_data->ztype; - - int index; - for (index = 0; index < 4; index++) { - zone_data->fog_red[index] = atoi(row[1 + index * 5]); - zone_data->fog_green[index] = atoi(row[2 + index * 5]); - zone_data->fog_blue[index] = atoi(row[3 + index * 5]); - zone_data->fog_minclip[index] = atof(row[4 + index * 5]); - zone_data->fog_maxclip[index] = atof(row[5 + index * 5]); - } - - zone_data->fog_density = atof(row[21]); - zone_data->sky = atoi(row[22]); - zone_data->zone_exp_multiplier = atof(row[23]); - zone_data->safe_x = atof(row[24]); - zone_data->safe_y = atof(row[25]); - zone_data->safe_z = atof(row[26]); - zone_data->underworld = atof(row[27]); - zone_data->minclip = atof(row[28]); - zone_data->maxclip = atof(row[29]); - zone_data->time_type = atoi(row[30]); - - //not in the DB yet: - zone_data->gravity = atof(row[56]); - LogDebug("Zone Gravity is [{}]", zone_data->gravity); - allow_mercs = true; - - zone_data->FastRegenHP = atoi(row[57]); - zone_data->FastRegenMana = atoi(row[58]); - zone_data->FastRegenEndurance = atoi(row[59]); - zone_data->NPCAggroMaxDist = atoi(row[60]); - zone_data->underworld_teleport_index = atoi(row[62]); - zone_data->LavaDamage = atoi(row[63]); - zone_data->MinLavaDamage = atoi(row[64]); - - int bindable = 0; - bindable = atoi(row[31]); - - can_bind = bindable == 0 ? false : true; - is_city = bindable == 2 ? true : false; - can_combat = atoi(row[32]) == 0 ? false : true; - can_levitate = atoi(row[33]) == 0 ? false : true; - can_castoutdoor = atoi(row[34]) == 0 ? false : true; - is_hotzone = atoi(row[35]) == 0 ? false : true; - max_movement_update_range = atof(row[61]); - - ruleset = atoi(row[36]); - zone_data->SuspendBuffs = atoi(row[37]); - - char *file = row[38]; - if (file) - strcpy(*map_filename, file); - else - strcpy(*map_filename, row[39]); - - for (index = 0; index < 4; index++) - zone_data->rain_chance[index] = atoi(row[40 + index]); - - for (index = 0; index < 4; index++) - zone_data->rain_duration[index] = atoi(row[44 + index]); - - for (index = 0; index < 4; index++) - zone_data->snow_chance[index] = atoi(row[48 + index]); - - for (index = 0; index < 4; index++) - zone_data->snow_duration[index] = atof(row[52 + index]); - - return true; -} - void ZoneDatabase::UpdateRespawnTime(uint32 spawn2_id, uint16 instance_id, uint32 time_left) { @@ -323,7 +146,7 @@ uint32 ZoneDatabase::GetSpawnTimeLeft(uint32 id, uint16 instance_id) if (results.RowCount() != 1) return 0; - auto row = results.begin(); + auto& row = results.begin(); timeval tv; gettimeofday(&tv, nullptr); @@ -373,259 +196,7 @@ bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 stat return true; } -void ZoneDatabase::RegisterBug(BugReport_Struct* bug_report) { - if (!bug_report) - return; - size_t len = 0; - char* name_ = nullptr; - char* ui_ = nullptr; - char* type_ = nullptr; - char* target_ = nullptr; - char* bug_ = nullptr; - - len = strlen(bug_report->reporter_name); - if (len) { - if (len > 63) // check against db column size - len = 63; - name_ = new char[(2 * len + 1)]; - memset(name_, 0, (2 * len + 1)); - DoEscapeString(name_, bug_report->reporter_name, len); - } - - len = strlen(bug_report->ui_path); - if (len) { - if (len > 127) - len = 127; - ui_ = new char[(2 * len + 1)]; - memset(ui_, 0, (2 * len + 1)); - DoEscapeString(ui_, bug_report->ui_path, len); - } - - len = strlen(bug_report->category_name); - if (len) { - if (len > 63) - len = 63; - type_ = new char[(2 * len + 1)]; - memset(type_, 0, (2 * len + 1)); - DoEscapeString(type_, bug_report->category_name, len); - } - - len = strlen(bug_report->target_name); - if (len) { - if (len > 63) - len = 63; - target_ = new char[(2 * len + 1)]; - memset(target_, 0, (2 * len + 1)); - DoEscapeString(target_, bug_report->target_name, len); - } - - len = strlen(bug_report->bug_report); - if (len) { - if (len > 1023) - len = 1023; - bug_ = new char[(2 * len + 1)]; - memset(bug_, 0, (2 * len + 1)); - DoEscapeString(bug_, bug_report->bug_report, len); - } - - //x and y are intentionally swapped because eq is inversexy coords //is this msg out-of-date or are the parameters wrong? - std::string query = StringFormat( - "INSERT INTO `bugs` (`zone`, `name`, `ui`, `x`, `y`, `z`, `type`, `flag`, `target`, `bug`, `date`) " - "VALUES('%s', '%s', '%s', '%.2f', '%.2f', '%.2f', '%s', %d, '%s', '%s', CURDATE())", - zone->GetShortName(), - (name_ ? name_ : ""), - (ui_ ? ui_ : ""), - bug_report->pos_x, - bug_report->pos_y, - bug_report->pos_z, - (type_ ? type_ : ""), - bug_report->optional_info_mask, - (target_ ? target_ : "Unknown Target"), - (bug_ ? bug_ : "") - ); - safe_delete_array(name_); - safe_delete_array(ui_); - safe_delete_array(type_); - safe_delete_array(target_); - safe_delete_array(bug_); - - QueryDatabase(query); -} - -void ZoneDatabase::RegisterBug(Client* client, BugReport_Struct* bug_report) { - if (!client || !bug_report) - return; - - size_t len = 0; - char* category_name_ = nullptr; - char* reporter_name_ = nullptr; - char* ui_path_ = nullptr; - char* target_name_ = nullptr; - char* bug_report_ = nullptr; - char* system_info_ = nullptr; - - len = strlen(bug_report->category_name); - if (len) { - if (len > 63) // check against db column size - len = 63; - category_name_ = new char[(2 * len + 1)]; - memset(category_name_, 0, (2 * len + 1)); - DoEscapeString(category_name_, bug_report->category_name, len); - } - - len = strlen(bug_report->reporter_name); - if (len) { - if (len > 63) - len = 63; - reporter_name_ = new char[(2 * len + 1)]; - memset(reporter_name_, 0, (2 * len + 1)); - DoEscapeString(reporter_name_, bug_report->reporter_name, len); - } - - len = strlen(bug_report->ui_path); - if (len) { - if (len > 127) - len = 127; - ui_path_ = new char[(2 * len + 1)]; - memset(ui_path_, 0, (2 * len + 1)); - DoEscapeString(ui_path_, bug_report->ui_path, len); - } - - len = strlen(bug_report->target_name); - if (len) { - if (len > 63) - len = 63; - target_name_ = new char[(2 * len + 1)]; - memset(target_name_, 0, (2 * len + 1)); - DoEscapeString(target_name_, bug_report->target_name, len); - } - - len = strlen(bug_report->bug_report); - if (len) { - if (len > 1023) - len = 1023; - bug_report_ = new char[(2 * len + 1)]; - memset(bug_report_, 0, (2 * len + 1)); - DoEscapeString(bug_report_, bug_report->bug_report, len); - } - - len = strlen(bug_report->system_info); - if (len) { - if (len > 1023) - len = 1023; - system_info_ = new char[(2 * len + 1)]; - memset(system_info_, 0, (2 * len + 1)); - DoEscapeString(system_info_, bug_report->system_info, len); - } - - std::string query = StringFormat( - "INSERT INTO `bug_reports` " - "(`zone`," - " `client_version_id`," - " `client_version_name`," - " `account_id`," - " `character_id`," - " `character_name`," - " `reporter_spoof`," - " `category_id`," - " `category_name`," - " `reporter_name`," - " `ui_path`," - " `pos_x`," - " `pos_y`," - " `pos_z`," - " `heading`," - " `time_played`," - " `target_id`," - " `target_name`," - " `optional_info_mask`," - " `_can_duplicate`," - " `_crash_bug`," - " `_target_info`," - " `_character_flags`," - " `_unknown_value`," - " `bug_report`," - " `system_info`) " - "VALUES " - "('%s'," - " '%u'," - " '%s'," - " '%u'," - " '%u'," - " '%s'," - " '%u'," - " '%u'," - " '%s'," - " '%s'," - " '%s'," - " '%1.1f'," - " '%1.1f'," - " '%1.1f'," - " '%u'," - " '%u'," - " '%u'," - " '%s'," - " '%u'," - " '%u'," - " '%u'," - " '%u'," - " '%u'," - " '%u'," - " '%s'," - " '%s')", - zone->GetShortName(), - client->ClientVersion(), - EQ::versions::ClientVersionName(client->ClientVersion()), - client->AccountID(), - client->CharacterID(), - client->GetName(), - (strcmp(client->GetName(), reporter_name_) != 0 ? 1 : 0), - bug_report->category_id, - (category_name_ ? category_name_ : ""), - (reporter_name_ ? reporter_name_ : ""), - (ui_path_ ? ui_path_ : ""), - bug_report->pos_x, - bug_report->pos_y, - bug_report->pos_z, - bug_report->heading, - bug_report->time_played, - bug_report->target_id, - (target_name_ ? target_name_ : ""), - bug_report->optional_info_mask, - ((bug_report->optional_info_mask & EQ::bug::infoCanDuplicate) != 0 ? 1 : 0), - ((bug_report->optional_info_mask & EQ::bug::infoCrashBug) != 0 ? 1 : 0), - ((bug_report->optional_info_mask & EQ::bug::infoTargetInfo) != 0 ? 1 : 0), - ((bug_report->optional_info_mask & EQ::bug::infoCharacterFlags) != 0 ? 1 : 0), - ((bug_report->optional_info_mask & EQ::bug::infoUnknownValue) != 0 ? 1 : 0), - (bug_report_ ? bug_report_ : ""), - (system_info_ ? system_info_ : "") - ); - safe_delete_array(category_name_); - safe_delete_array(reporter_name_); - safe_delete_array(ui_path_); - safe_delete_array(target_name_); - safe_delete_array(bug_report_); - safe_delete_array(system_info_); - - auto result = QueryDatabase(query); - - // TODO: Entity dumping [RuleB(Bugs, DumpTargetEntity)] -} - -//void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug) { -// -// uint32 len = strlen(bug->text); -// auto bugtext = new char[2 * len + 1]; -// memset(bugtext, 0, 2 * len + 1); -// DoEscapeString(bugtext, bug->text, len); -// -// std::string query = StringFormat("INSERT INTO bugs (type, name, bugtext, flag) " -// "VALUES('%s', '%s', '%s', %i)", -// "Petition", bug->name, bugtext, 25); -// safe_delete_array(bugtext); -// QueryDatabase(query); -//} bool ZoneDatabase::SetSpecialAttkFlag(uint8 id, const char* flag) { @@ -656,7 +227,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, EQ::ItemInstance* contain return; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { uint8 index = (uint8)atoi(row[0]); uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); @@ -675,8 +246,8 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, EQ::ItemInstance* contain inst->PutAugment(&database, i, aug[i]); // Put item inside world container container->PutItem(index, *inst); - safe_delete(inst); } + safe_delete(inst); } } @@ -756,7 +327,7 @@ Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id) } loadti->Code = BazaarTrader_ShowItems; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { if (atoi(row[5]) >= 80 || atoi(row[4]) < 0) { LogTrading("Bad Slot number when trying to load trader information!\n"); continue; @@ -780,7 +351,7 @@ TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id) return loadti; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { if (atoi(row[5]) >= 80 || atoi(row[5]) < 0) { LogTrading("Bad Slot number when trying to load trader information!\n"); continue; @@ -806,7 +377,7 @@ EQ::ItemInstance* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNu return nullptr; } - auto row = results.begin(); + auto& row = results.begin(); int ItemID = atoi(row[1]); int Charges = atoi(row[3]); @@ -1075,7 +646,7 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* "character_data " "WHERE `id` = %i ", character_id); auto results = database.QueryDatabase(query); int r = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { strcpy(pp->name, row[r]); r++; // "`name`, " strcpy(pp->last_name, row[r]); r++; // "last_name, " pp->gender = atoi(row[r]); r++; // "gender, " @@ -1176,7 +747,7 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map & val_list) { std::string query = StringFormat("SELECT `faction_id`, `current_value` FROM `faction_values` WHERE `char_id` = %i", character_id); auto results = database.QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { val_list[atoi(row[0])] = atoi(row[1]); } + for (auto& row = results.begin(); row != results.end(); ++row) { val_list[atoi(row[0])] = atoi(row[1]); } return true; } @@ -1194,7 +765,7 @@ bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_ for (i = 0; i < EQ::spells::SPELL_GEM_COUNT; i++){ pp->mem_spells[i] = 0xFFFFFFFF; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); if (i < EQ::spells::SPELL_GEM_COUNT && atoi(row[1]) <= SPDAT_RECORDS){ pp->mem_spells[i] = atoi(row[1]); @@ -1222,7 +793,7 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str // they have scribed spells on a newer one that exceeds the older one's limit. // Load them all so that server actions are valid..but, nix them in translators. - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { int idx = atoi(row[0]); int id = atoi(row[1]); @@ -1250,7 +821,7 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str for (i = 0; i < MAX_PP_LANGUAGE; ++i) pp->languages[i] = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); if (i < MAX_PP_LANGUAGE){ pp->languages[i] = atoi(row[1]); @@ -1263,7 +834,7 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str bool ZoneDatabase::LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat("SELECT slot, `rank` FROM character_leadership_abilities WHERE `id` = %u", character_id); auto results = database.QueryDatabase(query); uint32 slot = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { slot = atoi(row[0]); pp->leader_abilities.ranks[slot] = atoi(row[1]); } @@ -1282,7 +853,7 @@ bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_S /* Initialize Disciplines */ memset(pp->disciplines.values, 0, (sizeof(pp->disciplines.values[0]) * MAX_PP_DISCIPLINES)); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { if (i < MAX_PP_DISCIPLINES) pp->disciplines.values[i] = atoi(row[0]); ++i; @@ -1304,7 +875,7 @@ bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct for (i = 0; i < MAX_PP_SKILL; ++i) pp->skills[i] = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); if (i < MAX_PP_SKILL) pp->skills[i] = atoi(row[1]); @@ -1336,7 +907,7 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru "character_currency " "WHERE `id` = %i ", character_id); auto results = database.QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { pp->platinum = atoi(row[0]); pp->gold = atoi(row[1]); pp->silver = atoi(row[2]); @@ -1360,7 +931,7 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat("SELECT slot, blue, green, red, use_tint, color FROM `character_material` WHERE `id` = %u LIMIT 9", character_id); auto results = database.QueryDatabase(query); int i = 0; int r = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { r = 0; i = atoi(row[r]); /* Slot */ r++; pp->item_tint.Slot[i].Blue = atoi(row[r]); r++; @@ -1385,7 +956,7 @@ bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Str } } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { r = 0; i = atoi(row[r]); /* Bandolier ID */ r++; si = atoi(row[r]); /* Bandolier Slot */ r++; @@ -1417,7 +988,7 @@ bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struc pp->tributes[i].tier = 0; } i = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { if(atoi(row[1]) != TRIBUTE_NONE){ pp->tributes[i].tier = atoi(row[0]); pp->tributes[i].tribute = atoi(row[1]); @@ -1440,7 +1011,7 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc pp->potionbelt.Items[i].Name[0] = '\0'; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); const EQ::ItemData *item_data = database.GetItem(atoi(row[1])); if (!item_data) @@ -1463,7 +1034,7 @@ bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Str if (!results.RowCount()) // SHIT -- this actually isn't good return true; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { int index = atoi(row[0]); if (index < 0 || index > 4) continue; @@ -1573,16 +1144,24 @@ bool ZoneDatabase::SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_ return true; } -bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp){ +bool ZoneDatabase::SaveCharacterData( + Client* c, + PlayerProfile_Struct* pp, + ExtendedProfile_Struct* m_epp +) { + if (!c) { + return false; + } /* If this is ever zero - the client hasn't fully loaded and potentially crashed during zone */ - if (account_id <= 0) + if (c->AccountID() <= 0) { return false; + } - std::string mail_key = database.GetMailKey(character_id); + const auto mail_key = database.GetMailKey(c->CharacterID()); clock_t t = std::clock(); /* Function timer start */ - std::string query = StringFormat( + const auto query = fmt::format( "REPLACE INTO `character_data` (" " id, " " account_id, " @@ -1614,6 +1193,7 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla " title, " " suffix, " " exp, " + " exp_enabled, " " points, " " mana, " " cur_hp, " @@ -1681,106 +1261,107 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla " mailkey " ") " "VALUES (" - "%u," // id " id, " - "%u," // account_id " account_id, " - "'%s'," // `name` pp->name, " `name`, " - "'%s'," // last_name pp->last_name, " last_name, " - "%u," // gender pp->gender, " gender, " - "%u," // race pp->race, " race, " - "%u," // class pp->class_, " class, " - "%u," // `level` pp->level, " `level`, " - "%u," // deity pp->deity, " deity, " - "%u," // birthday pp->birthday, " birthday, " - "%u," // last_login pp->lastlogin, " last_login, " - "%u," // time_played pp->timePlayedMin, " time_played, " - "%u," // pvp_status pp->pvp, " pvp_status, " - "%u," // level2 pp->level2, " level2, " - "%u," // anon pp->anon, " anon, " - "%u," // gm pp->gm, " gm, " - "%u," // intoxication pp->intoxication, " intoxication, " - "%u," // hair_color pp->haircolor, " hair_color, " - "%u," // beard_color pp->beardcolor, " beard_color, " - "%u," // eye_color_1 pp->eyecolor1, " eye_color_1, " - "%u," // eye_color_2 pp->eyecolor2, " eye_color_2, " - "%u," // hair_style pp->hairstyle, " hair_style, " - "%u," // beard pp->beard, " beard, " - "%u," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, " - "%u," // ability_number pp->ability_number, " ability_number, " - "%u," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, " - "%u," // ability_time_hours pp->ability_time_hours, " ability_time_hours, " - "'%s'," // title pp->title, " title, " " - "'%s'," // suffix pp->suffix, " suffix, " - "%u," // exp pp->exp, " exp, " - "%u," // points pp->points, " points, " - "%u," // mana pp->mana, " mana, " - "%u," // cur_hp pp->cur_hp, " cur_hp, " - "%u," // str pp->STR, " str, " - "%u," // sta pp->STA, " sta, " - "%u," // cha pp->CHA, " cha, " - "%u," // dex pp->DEX, " dex, " - "%u," // `int` pp->INT, " `int`, " - "%u," // agi pp->AGI, " agi, " - "%u," // wis pp->WIS, " wis, " - "%u," // face pp->face, " face, " - "%f," // y pp->y, " y, " - "%f," // x pp->x, " x, " - "%f," // z pp->z, " z, " - "%f," // heading pp->heading, " heading, " - "%u," // pvp2 pp->pvp2, " pvp2, " - "%u," // pvp_type pp->pvptype, " pvp_type, " - "%u," // autosplit_enabled pp->autosplit, " autosplit_enabled, " - "%u," // zone_change_count pp->zone_change_count, " zone_change_count, " - "%u," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, " - "%u," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, " - "%u," // drakkin_details pp->drakkin_details, " drakkin_details, " - "%i," // toxicity pp->toxicity, " toxicity, " - "%i," // hunger_level pp->hunger_level, " hunger_level, " - "%i," // thirst_level pp->thirst_level, " thirst_level, " - "%u," // ability_up pp->ability_up, " ability_up, " - "%u," // zone_id pp->zone_id, " zone_id, " - "%u," // zone_instance pp->zoneInstance, " zone_instance, " - "%u," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, " - "%u," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, " - "%u," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, " - "%u," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, " - "%u," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, " - "%u," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, " - "%u," // ldon_points_available pp->ldon_points_available, " ldon_points_available, " - "%u," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, " - "%u," // show_helm pp->showhelm, " show_helm, " - "%u," // career_tribute_points pp->career_tribute_points, " career_tribute_points, " - "%u," // tribute_points pp->tribute_points, " tribute_points, " - "%u," // tribute_active pp->tribute_active, " tribute_active, " - "%u," // endurance pp->endurance, " endurance, " - "%u," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, " - "%u," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, " - "%u," // group_leadership_points pp->group_leadership_points, " group_leadership_points, " - "%u," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, " - "%u," // air_remaining pp->air_remaining, " air_remaining, " - "%u," // pvp_kills pp->PVPKills, " pvp_kills, " - "%u," // pvp_deaths pp->PVPDeaths, " pvp_deaths, " - "%u," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, " - "%u," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, " - "%u," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, " - "%u," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, " - "%u," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, " - "%u," // aa_points_spent pp->aapoints_spent, " aa_points_spent, " - "%u," // aa_exp pp->expAA, " aa_exp, " - "%u," // aa_points pp->aapoints, " aa_points, " - "%u," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " - "%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " - "%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " - "%u," // RestTimer pp->RestTimer, " RestTimer) " - "%u," // e_aa_effects - "%u," // e_percent_to_aa - "%u," // e_expended_aa_spent - "%u," // e_last_invsnapshot - "'%s'" // mailkey mail_key + "{}," // id " id, " + "{}," // account_id " account_id, " + "'{}'," // `name` pp->name, " `name`, " + "'{}'," // last_name pp->last_name, " last_name, " + "{}," // gender pp->gender, " gender, " + "{}," // race pp->race, " race, " + "{}," // class pp->class_, " class, " + "{}," // `level` pp->level, " `level`, " + "{}," // deity pp->deity, " deity, " + "{}," // birthday pp->birthday, " birthday, " + "{}," // last_login pp->lastlogin, " last_login, " + "{}," // time_played pp->timePlayedMin, " time_played, " + "{}," // pvp_status pp->pvp, " pvp_status, " + "{}," // level2 pp->level2, " level2, " + "{}," // anon pp->anon, " anon, " + "{}," // gm pp->gm, " gm, " + "{}," // intoxication pp->intoxication, " intoxication, " + "{}," // hair_color pp->haircolor, " hair_color, " + "{}," // beard_color pp->beardcolor, " beard_color, " + "{}," // eye_color_1 pp->eyecolor1, " eye_color_1, " + "{}," // eye_color_2 pp->eyecolor2, " eye_color_2, " + "{}," // hair_style pp->hairstyle, " hair_style, " + "{}," // beard pp->beard, " beard, " + "{}," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, " + "{}," // ability_number pp->ability_number, " ability_number, " + "{}," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, " + "{}," // ability_time_hours pp->ability_time_hours, " ability_time_hours, " + "'{}'," // title pp->title, " title, " " + "'{}'," // suffix pp->suffix, " suffix, " + "{}," // exp pp->exp, " exp, " + "{}," // exp_enabled epp->exp_enabled, " exp_enabled, " + "{}," // points pp->points, " points, " + "{}," // mana pp->mana, " mana, " + "{}," // cur_hp pp->cur_hp, " cur_hp, " + "{}," // str pp->STR, " str, " + "{}," // sta pp->STA, " sta, " + "{}," // cha pp->CHA, " cha, " + "{}," // dex pp->DEX, " dex, " + "{}," // `int` pp->INT, " `int`, " + "{}," // agi pp->AGI, " agi, " + "{}," // wis pp->WIS, " wis, " + "{}," // face pp->face, " face, " + "{:.2f}," // y pp->y, " y, " + "{:.2f}," // x pp->x, " x, " + "{:.2f}," // z pp->z, " z, " + "{:.2f}," // heading pp->heading, " heading, " + "{}," // pvp2 pp->pvp2, " pvp2, " + "{}," // pvp_type pp->pvptype, " pvp_type, " + "{}," // autosplit_enabled pp->autosplit, " autosplit_enabled, " + "{}," // zone_change_count pp->zone_change_count, " zone_change_count, " + "{}," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, " + "{}," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, " + "{}," // drakkin_details pp->drakkin_details, " drakkin_details, " + "{}," // toxicity pp->toxicity, " toxicity, " + "{}," // hunger_level pp->hunger_level, " hunger_level, " + "{}," // thirst_level pp->thirst_level, " thirst_level, " + "{}," // ability_up pp->ability_up, " ability_up, " + "{}," // zone_id pp->zone_id, " zone_id, " + "{}," // zone_instance pp->zoneInstance, " zone_instance, " + "{}," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, " + "{}," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, " + "{}," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, " + "{}," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, " + "{}," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, " + "{}," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, " + "{}," // ldon_points_available pp->ldon_points_available, " ldon_points_available, " + "{}," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, " + "{}," // show_helm pp->showhelm, " show_helm, " + "{}," // career_tribute_points pp->career_tribute_points, " career_tribute_points, " + "{}," // tribute_points pp->tribute_points, " tribute_points, " + "{}," // tribute_active pp->tribute_active, " tribute_active, " + "{}," // endurance pp->endurance, " endurance, " + "{}," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, " + "{}," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, " + "{}," // group_leadership_points pp->group_leadership_points, " group_leadership_points, " + "{}," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, " + "{}," // air_remaining pp->air_remaining, " air_remaining, " + "{}," // pvp_kills pp->PVPKills, " pvp_kills, " + "{}," // pvp_deaths pp->PVPDeaths, " pvp_deaths, " + "{}," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, " + "{}," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, " + "{}," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, " + "{}," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, " + "{}," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, " + "{}," // aa_points_spent pp->aapoints_spent, " aa_points_spent, " + "{}," // aa_exp pp->expAA, " aa_exp, " + "{}," // aa_points pp->aapoints, " aa_points, " + "{}," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " + "{}," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " + "{}," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " + "{}," // RestTimer pp->RestTimer, " RestTimer) " + "{}," // e_aa_effects + "{}," // e_percent_to_aa + "{}," // e_expended_aa_spent + "{}," // e_last_invsnapshot + "'{}'" // mailkey mail_key ")", - character_id, // " id, " - account_id, // " account_id, " - EscapeString(pp->name).c_str(), // " `name`, " - EscapeString(pp->last_name).c_str(), // " last_name, " + c->CharacterID(), // " id, " + c->AccountID(), // " account_id, " + Strings::Escape(pp->name), // " `name`, " + Strings::Escape(pp->last_name), // " last_name, " pp->gender, // " gender, " pp->race, // " race, " pp->class_, // " class, " @@ -1804,9 +1385,10 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla pp->ability_number, // " ability_number, " pp->ability_time_minutes, // " ability_time_minutes, " pp->ability_time_hours, // " ability_time_hours, " - EscapeString(pp->title).c_str(), // " title, " - EscapeString(pp->suffix).c_str(), // " suffix, " + Strings::Escape(pp->title), // " title, " + Strings::Escape(pp->suffix), // " suffix, " pp->exp, // " exp, " + c->IsEXPEnabled(), // " exp_enabled, " pp->points, // " points, " pp->mana, // " mana, " pp->cur_hp, // " cur_hp, " @@ -1874,7 +1456,11 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla mail_key.c_str() ); auto results = database.QueryDatabase(query); - LogDebug("ZoneDatabase::SaveCharacterData [{}], done Took [{}] seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + LogDebug( + "ZoneDatabase::SaveCharacterData [{}], done Took [{}] seconds", + c->CharacterID(), + ((float)(std::clock() - t)) / CLOCKS_PER_SEC + ); return true; } @@ -1993,7 +1579,7 @@ bool ZoneDatabase::NoRentExpired(const char* name){ if (results.RowCount() != 1) return false; - auto row = results.begin(); + auto& row = results.begin(); uint32 seconds = atoi(row[0]); return (seconds>1800); @@ -2049,7 +1635,7 @@ bool ZoneDatabase::SaveCharacterInvSnapshot(uint32 character_id) { character_id ); auto results = database.QueryDatabase(query); - LogInventory("ZoneDatabase::SaveCharacterInventorySnapshot [{}] ([{}])", character_id, (results.Success() ? "pass" : "fail")); + LogInventory("[{}] ([{}])", character_id, (results.Success() ? "pass" : "fail")); return results.Success(); } @@ -2073,7 +1659,7 @@ int ZoneDatabase::CountCharacterInvSnapshots(uint32 character_id) { if (!results.Success()) return -1; - auto row = results.begin(); + auto& row = results.begin(); int64 count = atoll(row[0]); if (count > 2147483647) @@ -2266,7 +1852,7 @@ bool ZoneDatabase::RestoreCharacterInvSnapshot(uint32 character_id, uint32 times // we should know what we're doing by the time we call this function..but, // this is to prevent inventory deletions where no timestamp entries exists if (!ValidateCharacterInvSnapshotTimestamp(character_id, timestamp)) { - LogError("ZoneDatabase::RestoreCharacterInvSnapshot() called for id: [{}] without valid snapshot entries @ [{}]", character_id, timestamp); + LogError("called for id: [{}] without valid snapshot entries @ [{}]", character_id, timestamp); return false; } @@ -2331,7 +1917,7 @@ bool ZoneDatabase::RestoreCharacterInvSnapshot(uint32 character_id, uint32 times ); results = database.QueryDatabase(query); - LogInventory("ZoneDatabase::RestoreCharacterInvSnapshot() [{}] snapshot for [{}] @ [{}]", + LogInventory("[{}] snapshot for [{}] @ [{}]", (results.Success() ? "restored" : "failed to restore"), character_id, timestamp); return results.Success(); @@ -2356,7 +1942,7 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load SQL( id IN ( select npcID from spawnentry where spawngroupID IN ( - select spawngroupID from spawn2 where `zone` = '{}' and `version` = {} + select spawngroupID from spawn2 where `zone` = '{}' and (`version` = {} OR `version` = -1) ) ) ), @@ -2490,7 +2076,7 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load armor_tint_id = 0; } else { - auto armorTint_row = armortint_results.begin(); + auto& armorTint_row = armortint_results.begin(); for (int index = EQ::textures::textureBegin; index <= EQ::textures::LastTexture; index++) { t->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; @@ -2511,8 +2097,8 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load t->see_invis = n.see_invis != 0; t->see_invis_undead = n.see_invis_undead != 0; // Set see_invis_undead flag - if (!n.lastname.empty()) { - strn0cpy(t->lastname, n.lastname.c_str(), 32); + if (!RuleB(NPC, DisableLastNames) && !n.lastname.empty()) { + strn0cpy(t->lastname, n.lastname.c_str(), sizeof(t->lastname)); } t->qglobal = n.qglobal != 0; // qglobal @@ -2560,7 +2146,10 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load t->always_aggro = n.always_aggro != 0; t->exp_mod = n.exp_mod; t->skip_auto_scale = false; // hardcoded here for now - t->hp_regen_per_second = n.hp_regen_rate; + t->hp_regen_per_second = n.hp_regen_per_second; + t->heroic_strikethrough = n.heroic_strikethrough; + t->faction_amount = n.faction_amount; + t->keeps_sold_items = n.keeps_sold_items; // If NPC with duplicate NPC id already in table, // free item we attempted to add. @@ -2663,7 +2252,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client const NPCType *npc = nullptr; // Process each row returned. - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { NPCType *tmpNPCType; tmpNPCType = new NPCType; memset(tmpNPCType, 0, sizeof *tmpNPCType); @@ -2745,7 +2334,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client if (!results.Success() || results.RowCount() == 0) armor_tint_id = 0; else { - auto armorTint_row = results.begin(); + auto& armorTint_row = results.begin(); for (int index = EQ::textures::textureBegin; index <= EQ::textures::LastTexture; index++) { tmpNPCType->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; @@ -2795,7 +2384,7 @@ bool ZoneDatabase::LoadMercInfo(Client *client) { if(results.RowCount() == 0) return false; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { uint8 slot = atoi(row[1]); if(slot >= MAXMERCS) @@ -2853,7 +2442,7 @@ bool ZoneDatabase::LoadCurrentMerc(Client *client) { return false; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { client->GetMercInfo(slot).mercid = atoi(row[0]); client->GetMercInfo(slot).slot = slot; snprintf(client->GetMercInfo(slot).merc_name, 64, "%s", row[1]); @@ -3019,7 +2608,7 @@ void ZoneDatabase::LoadMercBuffs(Merc *merc) { } int buffCount = 0; - for (auto row = results.begin(); row != results.end(); ++row, ++buffCount) { + for (auto& row = results.begin(); row != results.end(); ++row, ++buffCount) { if(buffCount == BUFF_COUNT) break; @@ -3105,7 +2694,7 @@ void ZoneDatabase::LoadMercEquipment(Merc *merc) { } int itemCount = 0; - for(auto row = results.begin(); row != results.end(); ++row) { + for(auto& row = results.begin(); row != results.end(); ++row) { if (itemCount == EQ::invslot::EQUIPMENT_COUNT) break; @@ -3128,20 +2717,21 @@ uint8 ZoneDatabase::GetGridType(uint32 grid, uint32 zoneid ) { if (results.RowCount() != 1) return 0; - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } -void ZoneDatabase::SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges){ +void ZoneDatabase::SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 zone_id, uint32 instance_id, uint32 item, uint32 charges){ - std::string query = StringFormat("REPLACE INTO merchantlist_temp (npcid, slot, itemid, charges) " - "VALUES(%d, %d, %d, %d)", npcid, slot, item, charges); + std::string query = StringFormat("REPLACE INTO merchantlist_temp (npcid, slot, zone_id, instance_id, itemid, charges) " + "VALUES(%d, %d, %d, %d, %d, %d)", npcid, slot, zone_id, instance_id, item, charges); QueryDatabase(query); } -void ZoneDatabase::DeleteMerchantTemp(uint32 npcid, uint32 slot){ - std::string query = StringFormat("DELETE FROM merchantlist_temp WHERE npcid=%d AND slot=%d", npcid, slot); +void ZoneDatabase::DeleteMerchantTemp(uint32 npcid, uint32 slot, uint32 zone_id, uint32 instance_id) { + std::string query = StringFormat("DELETE FROM merchantlist_temp WHERE npcid=%d AND slot=%d AND zone_id=%d AND instance_id=%d", + npcid, slot, zone_id, instance_id); QueryDatabase(query); } @@ -3159,7 +2749,7 @@ uint32 ZoneDatabase::GetZoneTZ(uint32 zoneid, uint32 version) { if (results.RowCount() == 0) return 0; - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } @@ -3245,7 +2835,7 @@ uint8 ZoneDatabase::GroupCount(uint32 groupid) { if (results.RowCount() == 0) return 0; - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } @@ -3263,7 +2853,7 @@ uint8 ZoneDatabase::RaidGroupCount(uint32 raidid, uint32 groupid) { if (results.RowCount() == 0) return 0; - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } @@ -3279,7 +2869,7 @@ int32 ZoneDatabase::GetBlockedSpellsCount(uint32 zoneid) if (results.RowCount() == 0) return -1; - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } @@ -3299,7 +2889,7 @@ bool ZoneDatabase::LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked return true; int32 index = 0; - for(auto row = results.begin(); row != results.end(); ++row, ++index) { + for(auto& row = results.begin(); row != results.end(); ++row, ++index) { if(index >= blockedSpellsCount) { std::cerr << "Error, Blocked Spells Count of " << blockedSpellsCount << " exceeded." << std::endl; break; @@ -3318,22 +2908,9 @@ bool ZoneDatabase::LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked int ZoneDatabase::getZoneShutDownDelay(uint32 zoneID, uint32 version) { - std::string query = StringFormat("SELECT shutdowndelay FROM zone " - "WHERE zoneidnumber = %i AND (version=%i OR version=0) " - "ORDER BY version DESC", zoneID, version); - auto results = QueryDatabase(query); - if (!results.Success()) { - return (RuleI(Zone, AutoShutdownDelay)); - } + auto z = GetZoneVersionWithFallback(zoneID, version); - if (results.RowCount() == 0) { - std::cerr << "Error in getZoneShutDownDelay no result '" << query << "' " << std::endl; - return (RuleI(Zone, AutoShutdownDelay)); - } - - auto row = results.begin(); - - return atoi(row[0]); + return z ? z->shutdowndelay : RuleI(Zone, AutoShutdownDelay); } uint32 ZoneDatabase::GetKarma(uint32 acct_id) @@ -3343,7 +2920,7 @@ uint32 ZoneDatabase::GetKarma(uint32 acct_id) if (!results.Success()) return 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atoi(row[0]); } @@ -3437,7 +3014,7 @@ void ZoneDatabase::ListAllInstances(Client* client, uint32 character_id) auto remaining_time = ((start_time + duration) - current_time); if (!never_expires) { if (remaining_time > 0) { - remaining_time_string = ConvertSecondsToTime(remaining_time); + remaining_time_string = Strings::SecondsToTime(remaining_time); } else { remaining_time_string = "Already Expired"; } @@ -3498,17 +3075,51 @@ void ZoneDatabase::QGlobalPurge() database.QueryDatabase(query); } -void ZoneDatabase::InsertDoor(uint32 ddoordbid, uint16 ddoorid, const char* ddoor_name, const glm::vec4& position, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize, bool ddisabletimer){ +void ZoneDatabase::InsertDoor( + uint32 database_id, + uint8 id, + std::string name, + const glm::vec4 &position, + uint8 open_type, + uint16 guild_id, + uint32 lockpick, + uint32 key_item_id, + uint8 door_param, + uint8 invert, + int incline, + uint16 size, + bool disable_timer +) { + auto e = DoorsRepository::NewEntity(); - std::string query = StringFormat("REPLACE INTO doors (id, doorid, zone, version, name, " - "pos_x, pos_y, pos_z, heading, opentype, guild, lockpick, " - "keyitem, disable_timer, door_param, invert_state, incline, size) " - "VALUES('%i', '%i', '%s', '%i', '%s', '%f', '%f', " - "'%f', '%f', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i')", - ddoordbid, ddoorid, zone->GetShortName(), zone->GetInstanceVersion(), - ddoor_name, position.x, position.y, position.z, position.w, - dopentype, dguildid, dlockpick, dkeyitem, (ddisabletimer ? 1 : 0), ddoor_param, dinvert, dincline, dsize); - QueryDatabase(query); + e.id = database_id; + e.doorid = id; + e.zone = zone->GetShortName(); + e.version = zone->GetInstanceVersion(); + e.name = name; + e.pos_x = position.x; + e.pos_y = position.y; + e.pos_z = position.z; + e.opentype = open_type; + e.guild = guild_id; + e.lockpick = lockpick; + e.keyitem = key_item_id; + e.disable_timer = static_cast(disable_timer); + e.door_param = door_param; + e.invert_state = invert; + e.incline = incline; + e.size = size; + + const auto& n = DoorsRepository::InsertOne(*this, e); + if (!n.id) { + LogError( + "Failed to create door in Zone [{}] Version [{}] Database ID [{}] ID [{}]", + zone->GetShortName(), + zone->GetInstanceVersion(), + database_id, + id + ); + } } void ZoneDatabase::LoadAltCurrencyValues(uint32 char_id, std::map ¤cy) { @@ -3521,7 +3132,7 @@ void ZoneDatabase::LoadAltCurrencyValues(uint32 char_id, std::map= client->GetMaxBuffSlots()) continue; @@ -3685,7 +3296,7 @@ void ZoneDatabase::LoadAuras(Client *c) if (!results.Success()) return; - for (auto row = results.begin(); row != results.end(); ++row) + for (auto& row = results.begin(); row != results.end(); ++row) c->MakeAura(atoi(row[0])); } @@ -3797,7 +3408,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) } PetInfo *pi; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { uint16 pet = atoi(row[0]); if (pet == 0) @@ -3825,7 +3436,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) return; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { uint16 pet = atoi(row[0]); if (pet == 0) pi = petinfo; @@ -3868,7 +3479,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) return; } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { uint16 pet = atoi(row[0]); if (pet == 0) pi = petinfo; @@ -4038,7 +3649,7 @@ bool ZoneDatabase::LoadFactionData() return false; } - auto fmr_row = faction_max_results.begin(); + auto& fmr_row = faction_max_results.begin(); max_faction = atoul(fmr_row[0]); faction_array = new Faction *[max_faction + 1]; @@ -4078,9 +3689,9 @@ bool ZoneDatabase::LoadFactionData() faction_ids.push_back(fr_row[0]); } - LogInfo("[{}] Faction(s) loaded...", faction_ids.size()); + LogInfo("Loaded [{}] faction(s)", Strings::Commify(std::to_string(faction_ids.size()))); - const std::string faction_id_criteria(implode(",", faction_ids)); + const std::string faction_id_criteria(Strings::Implode(",", faction_ids)); // load faction mins/maxes query = fmt::format("SELECT `client_faction_id`, `min`, `max` FROM `faction_base_data` WHERE `client_faction_id` IN ({})", faction_id_criteria); @@ -4105,7 +3716,7 @@ bool ZoneDatabase::LoadFactionData() faction_array[index]->max = atoi(br_row[2]); } - LogInfo("[{}] Faction Base(s) loaded...", base_results.RowCount()); + LogInfo("Loaded [{}] faction base(s)", Strings::Commify(std::to_string(base_results.RowCount()))); } else { LogInfo("Unable to load Faction Base data..."); @@ -4133,7 +3744,7 @@ bool ZoneDatabase::LoadFactionData() faction_array[index]->mods[mr_row[2]] = atoi(mr_row[1]); } - LogInfo("[{}] Faction Modifier(s) loaded", modifier_results.RowCount()); + LogInfo("Loaded [{}] faction modifier(s)", Strings::Commify(std::to_string(modifier_results.RowCount()))); } else { LogError("Unable to load Faction Modifier data"); @@ -4187,39 +3798,6 @@ bool ZoneDatabase::GetFactionIdsForNPC(uint32 nfl_id, std::listrandom.Real(-20,20)); @@ -4250,7 +3828,7 @@ void ZoneDatabase::SendCharacterCorpseToNonInstance(uint32 corpse_db_id) uint32 ZoneDatabase::GetCharacterCorpseDecayTimer(uint32 corpse_db_id){ std::string query = StringFormat("SELECT(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) FROM `character_corpses` WHERE `id` = %d AND NOT `time_of_death` = 0", corpse_db_id); auto results = QueryDatabase(query); - auto row = results.begin(); + auto& row = results.begin(); if (results.Success() && results.RowsAffected() != 0) return atoul(row[0]); @@ -4271,7 +3849,7 @@ uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const c "`wc_2` = %u, `wc_3` = %u, `wc_4` = %u, `wc_5` = %u, `wc_6` = %u, " "`wc_7` = %u, `wc_8` = %u, `wc_9` = %u " "WHERE `id` = %u", - EscapeString(char_name).c_str(), zone_id, instance_id, char_id, + Strings::Escape(char_name).c_str(), zone_id, instance_id, char_id, position.x, position.y, position.z, position.w, guild_id, dbpc->locked, dbpc->exp, dbpc->size, dbpc->level, dbpc->race, dbpc->gender, dbpc->class_, dbpc->deity, dbpc->texture, @@ -4348,7 +3926,7 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui "`wc_7` = %u, " "`wc_8` = %u, " "`wc_9` = %u ", - EscapeString(charname).c_str(), + Strings::Escape(charname).c_str(), zoneid, instanceid, charid, @@ -4442,7 +4020,7 @@ uint32 ZoneDatabase::GetCharacterBuriedCorpseCount(uint32 char_id) { std::string query = StringFormat("SELECT COUNT(*) FROM `character_corpses` WHERE `charid` = '%u' AND `is_buried` = 1", char_id); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atoi(row[0]); } return 0; @@ -4452,7 +4030,7 @@ uint32 ZoneDatabase::GetCharacterCorpseCount(uint32 char_id) { std::string query = StringFormat("SELECT COUNT(*) FROM `character_corpses` WHERE `charid` = '%u'", char_id); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atoi(row[0]); } return 0; @@ -4462,7 +4040,7 @@ uint32 ZoneDatabase::GetCharacterCorpseID(uint32 char_id, uint8 corpse) { std::string query = StringFormat("SELECT `id` FROM `character_corpses` WHERE `charid` = '%u' limit %d, 1", char_id, corpse); auto results = QueryDatabase(query); - auto row = results.begin(); + auto& row = results.begin(); if (row != results.end()) return atoul(row[0]); @@ -4475,7 +4053,7 @@ uint32 ZoneDatabase::GetCharacterCorpseItemCount(uint32 corpse_id){ corpse_id ); auto results = QueryDatabase(query); - auto row = results.begin(); + auto& row = results.begin(); if (results.Success() && results.RowsAffected() != 0){ return atoi(row[0]); } @@ -4536,7 +4114,7 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct ); auto results = QueryDatabase(query); uint16 i = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { pcs->locked = atoi(row[i++]); // is_locked, pcs->exp = atoul(row[i++]); // exp, pcs->size = atoi(row[i++]); // size, @@ -4594,7 +4172,7 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct i = 0; pcs->itemcount = results.RowCount(); uint16 r = 0; - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { memset(&pcs->items[i], 0, sizeof (player_lootitem::ServerLootItem_Struct)); pcs->items[i].equip_slot = atoi(row[r++]); // equip_slot, pcs->items[i].item_id = atoul(row[r++]); // item_id, @@ -4622,7 +4200,7 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z char_id); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { corpse = Corpse::LoadCharacterCorpseEntity( atoul(row[0]), // uint32 in_dbid char_id, // uint32 in_charid @@ -4662,7 +4240,7 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id char_id); results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { corpse = Corpse::LoadCharacterCorpseEntity( atoul(row[0]), char_id, @@ -4700,7 +4278,7 @@ int ZoneDatabase::CountCharacterCorpses(uint32 char_id) { char_id ); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atoi(row[0]); } return 0; @@ -4722,7 +4300,7 @@ int ZoneDatabase::CountCharacterCorpsesByZoneID(uint32 char_id, uint32 zone_id) zone_id ); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atoi(row[0]); } return 0; @@ -4750,7 +4328,7 @@ Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) { player_corpse_id ); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { auto position = glm::vec4(atof(row[3]), atof(row[4]), atof(row[5]), atof(row[6])); NewCorpse = Corpse::LoadCharacterCorpseEntity( atoul(row[0]), // id uint32 in_dbid @@ -4777,7 +4355,7 @@ bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) { } auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { auto position = glm::vec4(atof(row[3]), atof(row[4]), atof(row[5]), atof(row[6])); entity_list.AddCorpse( Corpse::LoadCharacterCorpseEntity( @@ -4792,13 +4370,15 @@ bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) { ); } + LogInfo("Loaded [{}] player corpse(s)", Strings::Commify(results.RowCount())); + return true; } uint32 ZoneDatabase::GetFirstCorpseID(uint32 char_id) { std::string query = StringFormat("SELECT `id` FROM `character_corpses` WHERE `charid` = '%u' AND `is_buried` = 0 ORDER BY `time_of_death` LIMIT 1", char_id); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atoi(row[0]); } return 0; @@ -4825,7 +4405,7 @@ bool ZoneDatabase::BuryCharacterCorpse(uint32 db_id) { bool ZoneDatabase::BuryAllCharacterCorpses(uint32 char_id) { std::string query = StringFormat("SELECT `id` FROM `character_corpses` WHERE `charid` = %u", char_id); auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { BuryCharacterCorpse(atoi(row[0])); return true; } @@ -4857,7 +4437,7 @@ uint32 ZoneDatabase::LoadSaylinkID(const char* saylink_text, bool auto_insert) return 0; } - auto row = results.begin(); + auto& row = results.begin(); return atoi(row[0]); } @@ -4874,8 +4454,8 @@ uint32 ZoneDatabase::SaveSaylinkID(const char* saylink_text) return results.LastInsertedID(); } -double ZoneDatabase::GetAAEXPModifier(uint32 character_id, uint32 zone_id) const { - std::string query = fmt::format( +double ZoneDatabase::GetAAEXPModifier(uint32 character_id, uint32 zone_id, int16 instance_version) const { + const std::string query = fmt::format( SQL( SELECT `aa_modifier` @@ -4884,22 +4464,26 @@ double ZoneDatabase::GetAAEXPModifier(uint32 character_id, uint32 zone_id) const WHERE `character_id` = {} AND - (`zone_id` = {} OR `zone_id` = 0) - ORDER BY `zone_id` DESC + (`zone_id` = {} OR `zone_id` = 0) AND + (`instance_version` = {} OR `instance_version` = -1) + ORDER BY `zone_id`, `instance_version` DESC LIMIT 1 ), character_id, - zone_id + zone_id, + instance_version ); + auto results = database.QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atof(row[0]); } + return 1.0f; } -double ZoneDatabase::GetEXPModifier(uint32 character_id, uint32 zone_id) const { - std::string query = fmt::format( +double ZoneDatabase::GetEXPModifier(uint32 character_id, uint32 zone_id, int16 instance_version) const { + const std::string query = fmt::format( SQL( SELECT `exp_modifier` @@ -4908,48 +4492,54 @@ double ZoneDatabase::GetEXPModifier(uint32 character_id, uint32 zone_id) const { WHERE `character_id` = {} AND - (`zone_id` = {} OR `zone_id` = 0) - ORDER BY `zone_id` DESC + (`zone_id` = {} OR `zone_id` = 0) AND + (`instance_version` = {} OR `instance_version` = -1) + ORDER BY `zone_id`, `instance_version` DESC LIMIT 1 ), character_id, - zone_id + zone_id, + instance_version ); + auto results = database.QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto& row = results.begin(); row != results.end(); ++row) { return atof(row[0]); } + return 1.0f; } -void ZoneDatabase::SetAAEXPModifier(uint32 character_id, uint32 zone_id, double aa_modifier) { - float exp_modifier = GetEXPModifier(character_id, zone_id); +void ZoneDatabase::SetAAEXPModifier(uint32 character_id, uint32 zone_id, double aa_modifier, int16 instance_version) { + float exp_modifier = GetEXPModifier(character_id, zone_id, instance_version); std::string query = fmt::format( SQL( REPLACE INTO `character_exp_modifiers` VALUES - ({}, {}, {}, {}) + ({}, {}, {}, {}, {}) ), character_id, zone_id, + instance_version, aa_modifier, exp_modifier ); database.QueryDatabase(query); } -void ZoneDatabase::SetEXPModifier(uint32 character_id, uint32 zone_id, double exp_modifier) { - float aa_modifier = GetAAEXPModifier(character_id, zone_id); +void ZoneDatabase::SetEXPModifier(uint32 character_id, uint32 zone_id, double exp_modifier, int16 instance_version) { + float aa_modifier = GetAAEXPModifier(character_id, zone_id, instance_version); std::string query = fmt::format( SQL( REPLACE INTO `character_exp_modifiers` VALUES - ({}, {}, {}, {}) + ({}, {}, {}, {}, {}) ), character_id, zone_id, + instance_version, aa_modifier, exp_modifier ); diff --git a/zone/zonedb.h b/zone/zonedb.h index 08ded3155..3903bd3a8 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -12,9 +12,7 @@ #include "event_codes.h" #include "../common/repositories/doors_repository.h" -#ifdef BOTS #include "bot_database.h" -#endif #define WOLF 42 @@ -107,6 +105,47 @@ struct DBnpcspellseffects_Struct { DBnpcspellseffects_entries_Struct entries[0]; }; +#pragma pack(1) +struct DBbotspells_entries_Struct { + uint16 spellid; + uint8 minlevel; + uint8 maxlevel; + uint32 type; + int16 manacost; + int16 priority; + int32 recast_delay; + int16 resist_adjust; + int8 min_hp; + int8 max_hp; + std::string bucket_name; + std::string bucket_value; + uint8 bucket_comparison; +}; +#pragma pack() + +struct DBbotspells_Struct { + uint32 parent_list; + uint16 attack_proc; + uint8 proc_chance; + uint16 range_proc; + int16 rproc_chance; + uint16 defensive_proc; + int16 dproc_chance; + uint32 fail_recast; + uint32 engaged_no_sp_recast_min; + uint32 engaged_no_sp_recast_max; + uint8 engaged_beneficial_self_chance; + uint8 engaged_beneficial_other_chance; + uint8 engaged_detrimental_chance; + uint32 pursue_no_sp_recast_min; + uint32 pursue_no_sp_recast_max; + uint8 pursue_detrimental_chance; + uint32 idle_no_sp_recast_min; + uint32 idle_no_sp_recast_max; + uint8 idle_beneficial_chance; + std::vector entries; +}; + struct DBTradeskillRecipe_Struct { EQ::skills::SkillType tradeskill; int16 skill_needed; @@ -246,7 +285,7 @@ struct ClientMercEntry { uint32 npcid; }; -namespace BeastlordPetData { +namespace BeastlordPetData { struct PetStruct { uint16 race_id = WOLF; uint8 texture = 0; @@ -359,7 +398,7 @@ public: bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_number); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); - bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); + bool SaveCharacterData(Client* c, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); bool SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); @@ -369,11 +408,11 @@ public: bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); - - double GetAAEXPModifier(uint32 character_id, uint32 zone_id) const; - double GetEXPModifier(uint32 character_id, uint32 zone_id) const; - void SetAAEXPModifier(uint32 character_id, uint32 zone_id, double aa_modifier); - void SetEXPModifier(uint32 character_id, uint32 zone_id, double exp_modifier); + + double GetAAEXPModifier(uint32 character_id, uint32 zone_id, int16 instance_version = -1) const; + double GetEXPModifier(uint32 character_id, uint32 zone_id, int16 instance_version = -1) const; + void SetAAEXPModifier(uint32 character_id, uint32 zone_id, double aa_modifier, int16 instance_version = -1); + void SetEXPModifier(uint32 character_id, uint32 zone_id, double exp_modifier, int16 instance_version = -1); /* Character Inventory */ bool NoRentExpired(const char* name); @@ -386,7 +425,7 @@ public: void DivergeCharacterInvSnapshotFromInventory(uint32 character_id, uint32 timestamp, std::list> &compare_list); void DivergeCharacterInventoryFromInvSnapshot(uint32 character_id, uint32 timestamp, std::list> &compare_list); bool RestoreCharacterInvSnapshot(uint32 character_id, uint32 timestamp); - + /* Corpses */ bool DeleteItemOffCharacterCorpse(uint32 db_id, uint32 equip_slot, uint32 item_id); uint32 GetCharacterCorpseItemCount(uint32 corpse_id); @@ -399,17 +438,13 @@ public: bool BuryAllCharacterCorpses(uint32 charid); bool DeleteCharacterCorpse(uint32 dbid); bool SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, const glm::vec4& position); - bool SummonAllGraveyardCorpses(uint32 cur_zoneid, uint32 dest_zoneid, uint16 dest_instanceid, const glm::vec4& position); int CountCharacterCorpses(uint32 char_id); int CountCharacterCorpsesByZoneID(uint32 char_id, uint32 zone_id); bool UnburyCharacterCorpse(uint32 dbid, uint32 new_zoneid, uint16 dest_instanceid, const glm::vec4& position); bool LoadCharacterCorpses(uint32 iZoneID, uint16 iInstanceID); - bool DeleteGraveyard(uint32 zone_id, uint32 graveyard_id); uint32 GetCharacterCorpseDecayTimer(uint32 corpse_db_id); uint32 GetCharacterBuriedCorpseCount(uint32 char_id); uint32 SendCharacterCorpseToGraveyard(uint32 dbid, uint32 zoneid, uint16 instanceid, const glm::vec4& position); - uint32 CreateGraveyardRecord(uint32 graveyard_zoneid, const glm::vec4& position); - uint32 AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id); uint32 SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid); uint32 UpdateCharacterCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid, bool rezzed = false); uint32 UpdateCharacterCorpseConsent(uint32 charid, uint32 guildid); @@ -436,21 +471,6 @@ public: bool LoadAlternateAdvancement(Client *c); /* Zone related */ - bool GetZoneCFG( - uint32 zoneid, - uint16 instance_version, - NewZone_Struct *data, - bool &can_bind, - bool &can_combat, - bool &can_levitate, - bool &can_castoutdoor, - bool &is_city, - bool &is_hotzone, - bool &allow_mercs, - double &max_movement_update_range, - uint8 &zone_type, - int &ruleset, - char **map_filename); bool SaveZoneCFG(uint32 zoneid, uint16 instance_version, NewZone_Struct* zd); bool LoadStaticZonePoints(LinkedList* zone_point_list,const char* zonename, uint32 version); int getZoneShutDownDelay(uint32 zoneID, uint32 version); @@ -510,6 +530,10 @@ public: void ClearNPCSpells() { npc_spells_cache.clear(); npc_spells_loadtried.clear(); } const NPCType* LoadNPCTypesData(uint32 id, bool bulk_load = false); + /*Bots */ + DBbotspells_Struct* GetBotSpells(uint32 bot_spell_id); + void ClearBotSpells() { bot_spells_cache.clear(); bot_spells_loadtried.clear(); } + /* Mercs */ const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel); void LoadMercEquipment(Merc *merc); @@ -521,17 +545,14 @@ public: bool DeleteMerc(uint32 merc_id); /* Petitions */ - void RegisterBug(BugReport_Struct* bug_report); // old method - void RegisterBug(Client* client, BugReport_Struct* bug_report); // new method - //void UpdateBug(PetitionBug_Struct* bug); void DeletePetitionFromDB(Petition* wpet); void UpdatePetitionToDB(Petition* wpet); void InsertPetitionToDB(Petition* wpet); void RefreshPetitionsFromDB(); /* Merchants */ - void SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges); - void DeleteMerchantTemp(uint32 npcid, uint32 slot); + void SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 zone_id, uint32 instance_id, uint32 item, uint32 charges); + void DeleteMerchantTemp(uint32 npcid, uint32 slot, uint32 zone_id, uint32 instance_id); /* Tradeskills */ bool GetTradeRecipe(const EQ::ItemInstance* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); @@ -547,12 +568,23 @@ public: /* Doors */ std::vector LoadDoors(const std::string& zone_name, int16 version); - uint32 GetGuildEQID(uint32 guilddbid); - void UpdateDoorGuildID(int doorid, int guild_id); - int32 GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version); - int32 GetDoorsCountPlusOne(const char *zone_name, int16 version); - int32 GetDoorsDBCountPlusOne(const char *zone_name, int16 version); - void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, const glm::vec4& position, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize, bool ddisabletimer = false); + uint32 GetDoorsCountPlusOne(); + int GetDoorsDBCountPlusOne(std::string zone_short_name, int16 version); + void InsertDoor( + uint32 database_id, + uint8 id, + std::string name, + const glm::vec4 &position, + uint8 open_type, + uint16 guild_id, + uint32 ockpick, + uint32 key_item_id, + uint8 door_param, + uint8 invert, + int incline, + uint16 size, + bool disable_timer = false + ); /* Blocked Spells */ int32 GetBlockedSpellsCount(uint32 zoneid); @@ -599,10 +631,8 @@ public: /* Things which really dont belong here... */ int16 CommandRequirement(const char* commandname); -#ifdef BOTS // bot database add-on to eliminate the need for a second database connection BotDatabase botdb; -#endif protected: void ZDBInitVars(); @@ -614,6 +644,9 @@ protected: std::unordered_set npc_spells_loadtried; DBnpcspellseffects_Struct** npc_spellseffects_cache; bool* npc_spellseffects_loadtried; + std::unordered_map bot_spells_cache; + std::unordered_set bot_spells_loadtried; + }; extern ZoneDatabase database; diff --git a/zone/zonedump.h b/zone/zonedump.h index c3936786c..51b21ee31 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -34,122 +34,125 @@ spawn2 mediumblob, npcs mediumblob, npc_loot mediumblob, gmspawntype mediumblob, struct NPCType { - char name[64]; - char lastname[70]; - int64 current_hp; - int64 max_hp; - float size; - float runspeed; - uint8 gender; - uint16 race; - uint8 class_; - uint8 bodytype; // added for targettype support - uint32 deity; //not loaded from DB - uint8 level; - uint32 npc_id; - uint8 texture; - uint8 helmtexture; - uint32 herosforgemodel; - uint32 loottable_id; - uint32 npc_spells_id; - uint32 npc_spells_effects_id; - int32 npc_faction_id; - uint32 merchanttype; - uint32 alt_currency_type; - uint32 adventure_template; - uint32 trap_template; - uint8 light; - uint32 AC; - uint64 Mana; //not loaded from DB - uint32 ATK; //not loaded from DB - uint32 STR; - uint32 STA; - uint32 DEX; - uint32 AGI; - uint32 INT; - uint32 WIS; - uint32 CHA; - int32 MR; - int32 FR; - int32 CR; - int32 PR; - int32 DR; - int32 Corrup; - int32 PhR; - uint8 haircolor; - uint8 beardcolor; - uint8 eyecolor1; // the eyecolors always seem to be the same, maybe left and right eye? - uint8 eyecolor2; - uint8 hairstyle; - uint8 luclinface; // - uint8 beard; // - uint32 drakkin_heritage; - uint32 drakkin_tattoo; - uint32 drakkin_details; - EQ::TintProfile armor_tint; - uint32 min_dmg; - uint32 max_dmg; - uint32 charm_ac; - uint32 charm_min_dmg; - uint32 charm_max_dmg; - int charm_attack_delay; - int charm_accuracy_rating; - int charm_avoidance_rating; - int charm_atk; - int16 attack_count; - char special_abilities[512]; - uint16 d_melee_texture1; - uint16 d_melee_texture2; - char ammo_idfile[30]; - uint8 prim_melee_type; - uint8 sec_melee_type; - uint8 ranged_type; - int64 hp_regen; - int64 hp_regen_per_second; - int64 mana_regen; - int32 aggroradius; // added for AI improvement - neotokyo - int32 assistradius; // assist radius, defaults to aggroradis if not set - uint16 see_invis; // See Invis flag added - uint16 see_invis_undead; // See Invis vs. Undead flag added - bool see_hide; - bool see_improved_hide; - bool qglobal; - bool npc_aggro; - uint8 spawn_limit; //only this many may be in zone at a time (0=no limit) - uint8 mount_color; //only used by horse class - float attack_speed; //%+- on attack delay of the mob. - int attack_delay; //delay between attacks in ms - int accuracy_rating; // flat bonus before mods - int avoidance_rating; // flat bonus before mods - bool findable; //can be found with find command - bool trackable; - int16 slow_mitigation; - uint8 maxlevel; - uint32 scalerate; - bool private_corpse; - bool unique_spawn_by_name; - bool underwater; - uint32 emoteid; - float spellscale; - float healscale; - bool no_target_hotkey; - bool raid_target; - uint8 armtexture; - uint8 bracertexture; - uint8 handtexture; - uint8 legtexture; - uint8 feettexture; - bool ignore_despawn; - bool show_name; // should default on - bool untargetable; - bool skip_global_loot; - bool rare_spawn; - bool skip_auto_scale; // just so it doesn't mess up bots or mercs, probably should add to DB too just in case - int8 stuck_behavior; - uint16 use_model; - int8 flymode; - bool always_aggro; - int exp_mod; + char name[64]; + char lastname[64]; + int64 current_hp; + int64 max_hp; + float size; + float runspeed; + uint8 gender; + uint16 race; + uint8 class_; + uint8 bodytype; // added for targettype support + uint32 deity; //not loaded from DB + uint8 level; + uint32 npc_id; + uint8 texture; + uint8 helmtexture; + uint32 herosforgemodel; + uint32 loottable_id; + uint32 npc_spells_id; + uint32 npc_spells_effects_id; + int32 npc_faction_id; + int32 faction_amount; // faction association magnitude, will use primary faction + uint32 merchanttype; + uint32 alt_currency_type; + uint32 adventure_template; + uint32 trap_template; + uint8 light; + uint32 AC; + uint64 Mana; //not loaded from DB + uint32 ATK; //not loaded from DB + uint32 STR; + uint32 STA; + uint32 DEX; + uint32 AGI; + uint32 INT; + uint32 WIS; + uint32 CHA; + int32 MR; + int32 FR; + int32 CR; + int32 PR; + int32 DR; + int32 Corrup; + int32 PhR; + uint8 haircolor; + uint8 beardcolor; + uint8 eyecolor1; // the eyecolors always seem to be the same, maybe left and right eye? + uint8 eyecolor2; + uint8 hairstyle; + uint8 luclinface; // + uint8 beard; // + uint32 drakkin_heritage; + uint32 drakkin_tattoo; + uint32 drakkin_details; + EQ::TintProfile armor_tint; + uint32 min_dmg; + uint32 max_dmg; + uint32 charm_ac; + uint32 charm_min_dmg; + uint32 charm_max_dmg; + int charm_attack_delay; + int charm_accuracy_rating; + int charm_avoidance_rating; + int charm_atk; + int16 attack_count; + char special_abilities[512]; + uint16 d_melee_texture1; + uint16 d_melee_texture2; + char ammo_idfile[30]; + uint8 prim_melee_type; + uint8 sec_melee_type; + uint8 ranged_type; + int64 hp_regen; + int64 hp_regen_per_second; + int64 mana_regen; + int32 aggroradius; // added for AI improvement - neotokyo + int32 assistradius; // assist radius, defaults to aggroradis if not set + uint16 see_invis; // See Invis flag added + uint16 see_invis_undead; // See Invis vs. Undead flag added + bool see_hide; + bool see_improved_hide; + bool qglobal; + bool npc_aggro; + uint8 spawn_limit; //only this many may be in zone at a time (0=no limit) + uint8 mount_color; //only used by horse class + float attack_speed; //%+- on attack delay of the mob. + int attack_delay; //delay between attacks in ms + int accuracy_rating; // flat bonus before mods + int avoidance_rating; // flat bonus before mods + bool findable; //can be found with find command + bool trackable; + int16 slow_mitigation; + uint8 maxlevel; + uint32 scalerate; + bool private_corpse; + bool unique_spawn_by_name; + bool underwater; + uint32 emoteid; + float spellscale; + float healscale; + bool no_target_hotkey; + bool raid_target; + uint8 armtexture; + uint8 bracertexture; + uint8 handtexture; + uint8 legtexture; + uint8 feettexture; + bool ignore_despawn; + bool show_name; // should default on + bool untargetable; + bool skip_global_loot; + bool rare_spawn; + bool skip_auto_scale; // just so it doesn't mess up bots or mercs, probably should add to DB too just in case + int8 stuck_behavior; + uint16 use_model; + int8 flymode; + bool always_aggro; + int exp_mod; + int heroic_strikethrough; + bool keeps_sold_items; }; namespace player_lootitem { diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 410241411..f2ea57e1b 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -19,7 +19,7 @@ #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/rulesys.h" -#include "../common/string_util.h" +#include "../common/strings.h" #include "expedition.h" #include "queryserv.h" @@ -28,23 +28,22 @@ #include "worldserver.h" #include "zone.h" -#ifdef BOTS #include "bot.h" -#endif extern QueryServ* QServ; extern WorldServer worldserver; extern Zone* zone; -#include "../common/repositories/zone_repository.h" #include "../common/content/world_content_service.h" +#include "../common/repositories/character_peqzone_flags_repository.h" +#include "../common/repositories/zone_repository.h" + void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { -#ifdef BOTS - // This block is necessary to clean up any bot objects owned by a Client - Bot::ProcessClientZoneChange(this); -#endif + if (RuleB(Bots, Enabled)) { + Bot::ProcessClientZoneChange(this); + } bZoning = true; if (app->size != sizeof(ZoneChange_Struct)) { @@ -56,80 +55,73 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { LogDebug("Zone request from [{}]", GetName()); DumpPacket(app); #endif - ZoneChange_Struct* zc=(ZoneChange_Struct*)app->pBuffer; + auto* zc = (ZoneChange_Struct*)app->pBuffer; uint16 target_zone_id = 0; - uint16 target_instance_id = zc->instanceID; + auto target_instance_id = zc->instanceID; ZonePoint* zone_point = nullptr; //figure out where they are going. - if(zc->zoneID == 0) { + if (zc->zoneID == 0) { //client dosent know where they are going... //try to figure it out for them. switch(zone_mode) { - case EvacToSafeCoords: - case ZoneToSafeCoords: - //going to safe coords, but client dosent know where? - //assume it is this zone for now. - target_zone_id = zone->GetZoneID(); - break; - case GMSummon: - target_zone_id = zonesummon_id; - break; - case GateToBindPoint: - target_zone_id = m_pp.binds[0].zone_id; - target_instance_id = m_pp.binds[0].instance_id; - break; - case ZoneToBindPoint: - target_zone_id = m_pp.binds[0].zone_id; - target_instance_id = m_pp.binds[0].instance_id; - break; - case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going. - target_zone_id = zonesummon_id; - break; - case ZoneUnsolicited: //client came up with this on its own. - zone_point = zone->GetClosestZonePointWithoutZone(GetX(), GetY(), GetZ(), this, ZONEPOINT_NOZONE_RANGE); - if(zone_point) { - //we found a zone point, which is a reasonable distance away - //assume that is the one were going with. - target_zone_id = zone_point->target_zone_id; - target_instance_id = zone_point->target_zone_instance; - } else { - //unable to find a zone point... is there anything else - //that can be a valid un-zolicited zone request? + case EvacToSafeCoords: + case ZoneToSafeCoords: + //going to safe coords, but client dosent know where? + //assume it is this zone for now. + target_zone_id = zone->GetZoneID(); + break; + case GMSummon: + target_zone_id = zonesummon_id; + break; + case GateToBindPoint: + target_zone_id = m_pp.binds[0].zone_id; + target_instance_id = m_pp.binds[0].instance_id; + break; + case ZoneToBindPoint: + target_zone_id = m_pp.binds[0].zone_id; + target_instance_id = m_pp.binds[0].instance_id; + break; + case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going. + target_zone_id = zonesummon_id; + break; + case ZoneUnsolicited: //client came up with this on its own. + zone_point = zone->GetClosestZonePointWithoutZone(GetX(), GetY(), GetZ(), this, ZONEPOINT_NOZONE_RANGE); + if (zone_point) { + //we found a zone point, which is a reasonable distance away + //assume that is the one were going with. + target_zone_id = zone_point->target_zone_id; + target_instance_id = zone_point->target_zone_instance; + } else { + //unable to find a zone point... is there anything else + //that can be a valid un-zolicited zone request? - Message(Chat::Red, "Invalid unsolicited zone request."); - LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]", GetName(), target_zone_id); - if (GetBindZoneID() == target_zone_id) { - cheat_manager.CheatDetected(MQGate, glm::vec3(zc->x, zc->y, zc->z)); + Message(Chat::Red, "Invalid unsolicited zone request."); + LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]", GetName(), target_zone_id); + cheat_manager.CheatDetected(GetBindZoneID() == target_zone_id ? MQGate : MQZone, glm::vec3(zc->x, zc->y, zc->z)); + SendZoneCancel(zc); + return; } - else { - cheat_manager.CheatDetected(MQZone, glm::vec3(zc->x, zc->y, zc->z)); - } - SendZoneCancel(zc); - return; - } - break; - default: - break; + break; + default: + break; }; - } - else { + } else { // This is to allow both 6.2 and Titanium clients to perform a proper zoning of the client when evac/succor // WildcardX 27 January 2008 - if(zone_mode == EvacToSafeCoords && zonesummon_id > 0) + if (zone_mode == EvacToSafeCoords && zonesummon_id) { target_zone_id = zonesummon_id; - else + } else { target_zone_id = zc->zoneID; + } //if we are zoning to a specific zone unsolicied, //then until otherwise determined, they must be zoning //on a zone line. - if(zone_mode == ZoneUnsolicited) - { - if(target_zone_id == zone->GetZoneID()) - { + if (zone_mode == ZoneUnsolicited) { + if (target_zone_id == zone->GetZoneID()) { SendZoneCancel(zc); return; } @@ -137,41 +129,46 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { zone_point = zone->GetClosestZonePoint(glm::vec3(GetPosition()), target_zone_id, this, ZONEPOINT_ZONE_RANGE); //if we didnt get a zone point, or its to a different zone, //then we assume this is invalid. - if(!zone_point || zone_point->target_zone_id != target_zone_id) { + if (!zone_point || zone_point->target_zone_id != target_zone_id) { LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]", GetName(), target_zone_id); - if (GetBindZoneID() == target_zone_id) { - cheat_manager.CheatDetected(MQGate, glm::vec3(zc->x, zc->y, zc->z)); - } - else { - cheat_manager.CheatDetected(MQZone, glm::vec3(zc->x, zc->y, zc->z)); - } + cheat_manager.CheatDetected(GetBindZoneID() == target_zone_id ? MQGate : MQZone, glm::vec3(zc->x, zc->y, zc->z)); SendZoneCancel(zc); return; } } } - if(target_instance_id > 0) - { + if (target_instance_id) { //make sure we are in it and it's unexpired. - if(!database.VerifyInstanceAlive(target_instance_id, CharacterID())) - { - Message(Chat::Red, "Instance ID was expired or you were not in it."); + if (!database.VerifyInstanceAlive(target_instance_id, CharacterID())) { + Message( + Chat::Red, + fmt::format( + "Instance ID {} was expired or you were not a member of it.", + target_instance_id + ).c_str() + ); SendZoneCancel(zc); return; } - if(!database.VerifyZoneInstance(target_zone_id, target_instance_id)) - { - Message(Chat::Red, "Instance ID was %u does not go with zone id %u", target_instance_id, target_zone_id); + if (!database.VerifyZoneInstance(target_zone_id, target_instance_id)) { + Message( + Chat::Red, + fmt::format( + "Instance ID was {}, this does not match Zone ID {}.", + target_instance_id, + target_zone_id + ).c_str() + ); SendZoneCancel(zc); return; } } /* Check for Valid Zone */ - const char *target_zone_name = ZoneName(target_zone_id); - if(target_zone_name == nullptr) { + auto* target_zone_name = ZoneName(target_zone_id); + if (!target_zone_name) { //invalid zone... Message(Chat::Red, "Invalid target zone ID."); LogError("Zoning [{}]: Unable to get zone name for zone id [{}]", GetName(), target_zone_id); @@ -179,34 +176,41 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { return; } - /* Load up the Safe Coordinates, restrictions and verify the zone name*/ - float safe_x, safe_y, safe_z, safe_heading; - int16 min_status = AccountStatus::Player; - uint8 min_level = 0; - char flag_needed[128]; - if(!content_db.GetSafePoints( - target_zone_name, - database.GetInstanceVersion(target_instance_id), - &safe_x, - &safe_y, - &safe_z, - &safe_heading, - &min_status, - &min_level, - flag_needed - )) { - //invalid zone... + auto target_instance_version = database.GetInstanceVersion(target_instance_id); + auto zone_data = GetZoneVersionWithFallback( + ZoneID(target_zone_name), + target_instance_version + ); + if (!zone_data) { Message(Chat::Red, "Invalid target zone while getting safe points."); LogError("Zoning [{}]: Unable to get safe coordinates for zone [{}]", GetName(), target_zone_name); SendZoneCancel(zc); return; } - std::string export_string = fmt::format( - "{} {}", + float safe_x, safe_y, safe_z, safe_heading; + int16 min_status = AccountStatus::Player; + uint8 min_level = 0; + + LogInfo("Loaded zone flag [{}]", zone_data->flag_needed); + + safe_x = zone_data->safe_x; + safe_y = zone_data->safe_y; + safe_z = zone_data->safe_z; + safe_heading = zone_data->safe_heading; + min_status = zone_data->min_status; + min_level = zone_data->min_level; + + const auto& export_string = fmt::format( + "{} {} {} {} {} {}", zone->GetZoneID(), - target_zone_id + zone->GetInstanceID(), + zone->GetInstanceVersion(), + target_zone_id, + target_instance_id, + target_instance_version ); + if (parse->EventPlayer(EVENT_ZONE, this, export_string, 0) != 0) { SendZoneCancel(zc); return; @@ -217,119 +221,87 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { uint8 ignore_restrictions = zonesummon_ignorerestrictions; zonesummon_ignorerestrictions = 0; - float target_x = 0, target_y = 0, target_z = 0, target_heading = 0; - switch(zone_mode) { - case EvacToSafeCoords: - case ZoneToSafeCoords: - LogDebug( - "Zoning [{}] to safe coords ([{}], [{}], [{}], [{}]) in [{}] ([{}])", - GetName(), - safe_x, - safe_y, - safe_z, - safe_heading, - target_zone_name, - target_zone_id - ); - target_x = safe_x; - target_y = safe_y; - target_z = safe_z; - target_heading = safe_heading; - break; - case GMSummon: - target_x = m_ZoneSummonLocation.x; - target_y = m_ZoneSummonLocation.y; - target_z = m_ZoneSummonLocation.z; - target_heading = m_ZoneSummonLocation.w; - ignore_restrictions = 1; - break; - case GateToBindPoint: - target_x = m_pp.binds[0].x; - target_y = m_pp.binds[0].y; - target_z = m_pp.binds[0].z; - target_heading = m_pp.binds[0].heading; - break; - case ZoneToBindPoint: - target_x = m_pp.binds[0].x; - target_y = m_pp.binds[0].y; - target_z = m_pp.binds[0].z; - target_heading = m_pp.binds[0].heading; - ignore_restrictions = 1; //can always get to our bind point? seems exploitable - break; - case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going. - //recycle zonesummon variables - target_x = m_ZoneSummonLocation.x; - target_y = m_ZoneSummonLocation.y; - target_z = m_ZoneSummonLocation.z; - target_heading = m_ZoneSummonLocation.w; - break; - case ZoneUnsolicited: //client came up with this on its own. - //client requested a zoning... what are the cases when this could happen? - - //Handle zone point case: - if(zone_point != nullptr) { - //they are zoning using a valid zone point, figure out coords - - //999999 is a placeholder for 'same as where they were from' - if(zone_point->target_x == 999999) - target_x = GetX(); - else - target_x = zone_point->target_x; - - if(zone_point->target_y == 999999) - target_y = GetY(); - else - target_y = zone_point->target_y; - - if(zone_point->target_z == 999999) - target_z = GetZ(); - else - target_z = zone_point->target_z; - - if(zone_point->target_heading == 999) - target_heading = GetHeading(); - else - target_heading = zone_point->target_heading; - + auto target_x = 0.0f, target_y = 0.0f, target_z = 0.0f, target_heading = 0.0f; + switch (zone_mode) { + case EvacToSafeCoords: + case ZoneToSafeCoords: + LogDebug( + "Zoning [{}] to safe coords ([{}], [{}], [{}], [{}]) in [{}] ([{}])", + GetName(), + safe_x, + safe_y, + safe_z, + safe_heading, + target_zone_name, + target_zone_id + ); + target_x = safe_x; + target_y = safe_y; + target_z = safe_z; + target_heading = safe_heading; break; - } + case GMSummon: + target_x = m_ZoneSummonLocation.x; + target_y = m_ZoneSummonLocation.y; + target_z = m_ZoneSummonLocation.z; + target_heading = m_ZoneSummonLocation.w; + ignore_restrictions = 1; + break; + case GateToBindPoint: + target_x = m_pp.binds[0].x; + target_y = m_pp.binds[0].y; + target_z = m_pp.binds[0].z; + target_heading = m_pp.binds[0].heading; + break; + case ZoneToBindPoint: + target_x = m_pp.binds[0].x; + target_y = m_pp.binds[0].y; + target_z = m_pp.binds[0].z; + target_heading = m_pp.binds[0].heading; + ignore_restrictions = 1; //can always get to our bind point? seems exploitable + break; + case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going. + //recycle zonesummon variables + target_x = m_ZoneSummonLocation.x; + target_y = m_ZoneSummonLocation.y; + target_z = m_ZoneSummonLocation.z; + target_heading = m_ZoneSummonLocation.w; + break; + case ZoneUnsolicited: //client came up with this on its own. + //client requested a zoning... what are the cases when this could happen? - //for now, there are no other cases... + //Handle zone point case: + if (zone_point) { + //they are zoning using a valid zone point, figure out coords - //could not find a valid reason for them to be zoning, stop it. - if (GetBindZoneID() == target_zone_id) { - cheat_manager.CheatDetected(MQGate, glm::vec3(zc->x, zc->y, zc->z)); - } - else { - cheat_manager.CheatDetected(MQZone, glm::vec3(zc->x, zc->y, zc->z)); - } - LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]. Not near a zone point", GetName(), target_zone_name); - SendZoneCancel(zc); - return; - default: - break; + //999999 is a placeholder for 'same as where they were from' + target_x = zone_point->target_x == 999999 ? GetX() : zone_point->target_x; + target_y = zone_point->target_y == 999999 ? GetY() : zone_point->target_y; + target_z = zone_point->target_z == 999999 ? GetZ() : zone_point->target_z; + target_heading = zone_point->target_heading == 999 ? GetHeading() : zone_point->target_heading; + break; + } + + //for now, there are no other cases... + + //could not find a valid reason for them to be zoning, stop it. + cheat_manager.CheatDetected(GetBindZoneID() == target_zone_id ? MQGate : MQZone, glm::vec3(zc->x, zc->y, zc->z)); + + LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]. Not near a zone point", GetName(), target_zone_name); + SendZoneCancel(zc); + return; + default: + break; }; - //OK, now we should know where were going... + auto zoning_message = ZoningMessage::ZoneSuccess; - //Check some rules first. - int8 myerror = 1; //1 is succes - - //not sure when we would use ZONE_ERROR_NOTREADY - - //enforce min status and level - if (!ignore_restrictions && (Admin() < min_status || GetLevel() < min_level)) - { - myerror = ZONE_ERROR_NOEXPERIENCE; - } - - if(!ignore_restrictions && flag_needed[0] != '\0') { - //the flag needed string is not empty, meaning a flag is required. - if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id)) - { - Message(Chat::Red, "You do not have the flag to enter %s.", target_zone_name); - myerror = ZONE_ERROR_NOEXPERIENCE; - } + // Check Minimum Status, Minimum Level, Maximum Level, and Zone Flag + if ( + !ignore_restrictions && + !CanEnterZone(ZoneName(target_zone_id), target_instance_version) + ) { + zoning_message = ZoningMessage::ZoneNoExperience; } //TODO: ADVENTURE ENTRANCE CHECK @@ -338,48 +310,23 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { * Expansion check */ if (content_service.GetCurrentExpansion() >= Expansion::Classic && !GetGM()) { + bool meets_zone_expansion_check = false; - /** - * Hit the zone cache first so we're not hitting the database every time someone attempts to zone - */ - bool meets_zone_expansion_check = false; - bool found_zone = false; - for (auto &z: zone_store.zones) { - if (z.short_name == target_zone_name && z.version == 0) { - found_zone = true; - if (z.expansion <= (content_service.GetCurrentExpansion() + 1)) { - meets_zone_expansion_check = true; - break; - } - } - } - - /** - * If we fail to find a cached zone lookup because someone just so happened to change some data, second attempt - * In 99% of cases we would never get here and this would be fallback - */ - if (!found_zone) { - auto zones = ZoneRepository::GetWhere(content_db, - fmt::format( - "expansion <= {} AND short_name = '{}' and version = 0", - (content_service.GetCurrentExpansion() + 1), - target_zone_name - ) - ); - - meets_zone_expansion_check = !zones.empty(); + auto z = zone_store.GetZoneWithFallback(ZoneID(target_zone_name), 0); + if (z->expansion <= content_service.GetCurrentExpansion() || z->bypass_expansion_check) { + meets_zone_expansion_check = true; } LogInfo( "Checking zone request [{}] for expansion [{}] ({}) success [{}]", target_zone_name, - (content_service.GetCurrentExpansion() + 1), + (content_service.GetCurrentExpansion()), content_service.GetCurrentExpansionName(), meets_zone_expansion_check ? "true" : "false" ); if (!meets_zone_expansion_check) { - myerror = ZONE_ERROR_NOEXPANSION; + zoning_message = ZoningMessage::ZoneNoExpansion; } } @@ -387,12 +334,11 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { LogInfo("[{}] Bypassing Expansion zone checks because GM status is set", GetCleanName()); } - if(myerror == 1) { - //we have successfully zoned + if (zoning_message == ZoningMessage::ZoneSuccess) { DoZoneSuccess(zc, target_zone_id, target_instance_id, target_x, target_y, target_z, target_heading, ignore_restrictions); } else { LogError("Zoning [{}]: Rules prevent this char from zoning into [{}]", GetName(), target_zone_name); - SendZoneError(zc, myerror); + SendZoneError(zc, zoning_message); } } @@ -413,6 +359,8 @@ void Client::SendZoneCancel(ZoneChange_Struct *zc) { zone_mode = ZoneUnsolicited; // reset since we're not zoning anymore bZoning = false; + // remove save position lock + m_lock_save_position = false; } void Client::SendZoneError(ZoneChange_Struct *zc, int8 err) @@ -432,6 +380,8 @@ void Client::SendZoneError(ZoneChange_Struct *zc, int8 err) zone_mode = ZoneUnsolicited; // reset since we're not zoning anymore bZoning = false; + // remove save position lock + m_lock_save_position = false; } void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instance_id, float dest_x, float dest_y, float dest_z, float dest_h, int8 ignore_r) { @@ -462,7 +412,16 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc } } - LogInfo("Zoning [{}] to: [{}] ([{}]) - ([{}]) x [{}] y [{}] z [{}]", m_pp.name, ZoneName(zone_id), zone_id, instance_id, dest_x, dest_y, dest_z); + LogInfo( + "Zoning [{}] to: [{}] ([{}]) - ([{}]) x [{}] y [{}] z [{}]", + m_pp.name, + ZoneName(zone_id), + zone_id, + instance_id, + dest_x, + dest_y, + dest_z + ); //set the player's coordinates in the new zone so they have them //when they zone into it @@ -477,6 +436,8 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc //Force a save so its waiting for them when they zone Save(2); + m_lock_save_position = true; + if (zone_id == zone->GetZoneID() && instance_id == zone->GetInstanceID()) { // No need to ask worldserver if we're zoning to ourselves (most // likely to a bind point), also fixes a bug since the default response was failure @@ -488,24 +449,22 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc zc2->success = 1; outapp->priority = 6; FastQueuePacket(&outapp); - - zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } else { - // vesuvias - zoneing to another zone so we need to the let the world server - //handle things with the client for a while - auto pack = new ServerPacket(ServerOP_ZoneToZoneRequest, sizeof(ZoneToZone_Struct)); - ZoneToZone_Struct *ztz = (ZoneToZone_Struct *)pack->pBuffer; - ztz->response = 0; - ztz->current_zone_id = zone->GetZoneID(); - ztz->current_instance_id = zone->GetInstanceID(); - ztz->requested_zone_id = zone_id; - ztz->requested_instance_id = instance_id; - ztz->admin = admin; - ztz->ignorerestrictions = ignore_r; - strcpy(ztz->name, GetName()); - ztz->guild_id = GuildID(); - worldserver.SendPacket(pack); - safe_delete(pack); + // vesuvias - zoneing to another zone so we need to the let the world server + //handle things with the client for a while + auto pack = new ServerPacket(ServerOP_ZoneToZoneRequest, sizeof(ZoneToZone_Struct)); + ZoneToZone_Struct *ztz = (ZoneToZone_Struct *)pack->pBuffer; + ztz->response = 0; + ztz->current_zone_id = zone->GetZoneID(); + ztz->current_instance_id = zone->GetInstanceID(); + ztz->requested_zone_id = zone_id; + ztz->requested_instance_id = instance_id; + ztz->admin = admin; + ztz->ignorerestrictions = ignore_r; + strcpy(ztz->name, GetName()); + ztz->guild_id = GuildID(); + worldserver.SendPacket(pack); + safe_delete(pack); } //reset to unsolicited. @@ -513,6 +472,9 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc m_ZoneSummonLocation = glm::vec4(); zonesummon_id = 0; zonesummon_ignorerestrictions = 0; + + // this simply resets the zone shutdown timer + zone->ResetShutdownTimer(); } void Client::MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm) { @@ -532,68 +494,69 @@ void Client::MovePC(uint32 zoneID, uint32 instanceID, float x, float y, float z, ProcessMovePC(zoneID, instanceID, x, y, z, heading, ignorerestrictions, zm); } -void Client::MoveZone(const char *zone_short_name) { - ProcessMovePC(ZoneID(zone_short_name), 0, 0.0f, 0.0f, 0.0f, 0.0f, 3, ZoneToSafeCoords); +void Client::MoveZone(const char *zone_short_name, const glm::vec4 &location) { + ProcessMovePC(ZoneID(zone_short_name), 0, location.x, location.y, location.z, location.w, 3, ZoneToSafeCoords); } -void Client::MoveZoneGroup(const char *zone_short_name) { +void Client::MoveZoneGroup(const char *zone_short_name, const glm::vec4 &location) { if (!GetGroup()) { - MoveZone(zone_short_name); + MoveZone(zone_short_name, location); } else { auto client_group = GetGroup(); for (int member_index = 0; member_index < MAX_GROUP_MEMBERS; member_index++) { if (client_group->members[member_index] && client_group->members[member_index]->IsClient()) { auto group_member = client_group->members[member_index]->CastToClient(); - group_member->MoveZone(zone_short_name); + group_member->MoveZone(zone_short_name, location); } } } } -void Client::MoveZoneRaid(const char *zone_short_name) { +void Client::MoveZoneRaid(const char *zone_short_name, const glm::vec4 &location) { if (!GetRaid()) { - MoveZone(zone_short_name); + MoveZone(zone_short_name, location); } else { auto client_raid = GetRaid(); for (int member_index = 0; member_index < MAX_RAID_MEMBERS; member_index++) { if (client_raid->members[member_index].member && client_raid->members[member_index].member->IsClient()) { auto raid_member = client_raid->members[member_index].member->CastToClient(); - raid_member->MoveZone(zone_short_name); + raid_member->MoveZone(zone_short_name, location); } } } } -void Client::MoveZoneInstance(uint16 instance_id) { - if (!database.CharacterInInstanceGroup(instance_id, CharacterID())) { +void Client::MoveZoneInstance(uint16 instance_id, const glm::vec4 &location) { + if (!database.CheckInstanceByCharID(instance_id, CharacterID())) { database.AddClientToInstance(instance_id, CharacterID()); } - ProcessMovePC(database.ZoneIDFromInstanceID(instance_id), instance_id, 0.0f, 0.0f, 0.0f, 0.0f, 3, ZoneToSafeCoords); + + ProcessMovePC(database.GetInstanceZoneID(instance_id), instance_id, location.x, location.y, location.z, location.w, 3, ZoneToSafeCoords); } -void Client::MoveZoneInstanceGroup(uint16 instance_id) { +void Client::MoveZoneInstanceGroup(uint16 instance_id, const glm::vec4 &location) { if (!GetGroup()) { - MoveZoneInstance(instance_id); + MoveZoneInstance(instance_id, location); } else { auto client_group = GetGroup(); for (int member_index = 0; member_index < MAX_GROUP_MEMBERS; member_index++) { if (client_group->members[member_index] && client_group->members[member_index]->IsClient()) { auto group_member = client_group->members[member_index]->CastToClient(); - group_member->MoveZoneInstance(instance_id); + group_member->MoveZoneInstance(instance_id, location); } } } } -void Client::MoveZoneInstanceRaid(uint16 instance_id) { +void Client::MoveZoneInstanceRaid(uint16 instance_id, const glm::vec4 &location) { if (!GetRaid()) { - MoveZoneInstance(instance_id); + MoveZoneInstance(instance_id, location); } else { auto client_raid = GetRaid(); for (int member_index = 0; member_index < MAX_RAID_MEMBERS; member_index++) { if (client_raid->members[member_index].member && client_raid->members[member_index].member->IsClient()) { auto raid_member = client_raid->members[member_index].member->CastToClient(); - raid_member->MoveZoneInstance(instance_id); + raid_member->MoveZoneInstance(instance_id, location); } } } @@ -663,7 +626,23 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z char* pZoneName = nullptr; pShortZoneName = ZoneName(zoneID); - content_db.GetZoneLongName(pShortZoneName, &pZoneName); + + auto zd = GetZoneVersionWithFallback(zoneID, zone->GetInstanceVersion()); + if (zd) { + pZoneName = strcpy(new char[strlen(zd->long_name.c_str()) + 1], zd->long_name.c_str()); + } + + LogInfo( + "Client [{}] zone_id [{}] x [{}] y [{}] z [{}] heading [{}] ignorerestrictions [{}] zone_mode [{}]", + GetCleanName(), + zoneID, + x, + y, + z, + heading, + ignorerestrictions, + zm + ); cheat_manager.SetExemptStatus(Port, true); @@ -778,7 +757,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z outapp->priority = 6; FastQueuePacket(&outapp); - safe_delete(outapp); } else if(zm == ZoneSolicited || zm == ZoneToSafeCoords) { auto outapp = @@ -795,7 +773,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z outapp->priority = 6; FastQueuePacket(&outapp); - safe_delete(outapp); } else if(zm == EvacToSafeCoords) { auto outapp = @@ -829,7 +806,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z outapp->priority = 6; FastQueuePacket(&outapp); - safe_delete(outapp); } else { if(zoneID == GetZoneID()) { @@ -854,7 +830,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z gmg->type = 0x01; //an observed value, not sure of meaning outapp->priority = 6; FastQueuePacket(&outapp); - safe_delete(outapp); } LogDebug("Player [{}] has requested a zoning to LOC x=[{}], y=[{}], z=[{}], heading=[{}] in zoneid=[{}]", GetName(), x, y, z, heading, zoneID); @@ -876,9 +851,11 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z safe_delete_array(pZoneName); } -void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) { - if(zone_id == 0) +void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) +{ + if (zone_id == 0) { zone_id = zone->GetZoneID(); + } MovePC(zone_id, instance_id, 0.0f, 0.0f, 0.0f, 0.0f, 0, ZoneToSafeCoords); } @@ -1004,7 +981,7 @@ bool Client::HasZoneFlag(uint32 zone_id) const { } void Client::LoadZoneFlags() { - std::string query = fmt::format( + const auto query = fmt::format( "SELECT zoneID from zone_flags WHERE charID = {}", CharacterID() ); @@ -1015,6 +992,10 @@ void Client::LoadZoneFlags() { return; } + if (!results.RowCount()) { + return; + } + zone_flags.clear(); for (auto row : results) { @@ -1048,36 +1029,25 @@ void Client::SendZoneFlagInfo(Client *to) const { for (const auto& zone_id : zone_flags) { int flag_number = (flag_count + 1); const char* zone_short_name = ZoneName(zone_id, true); - if (zone_short_name != "UNKNOWN") { + if (strncmp(zone_short_name, "UNKNOWN", strlen(zone_short_name)) != 0) { std::string zone_long_name = ZoneLongName(zone_id); - float safe_x, safe_y, safe_z, safe_heading; - int16 min_status = AccountStatus::Player; - uint8 min_level = 0; - char flag_name[128]; - if (!content_db.GetSafePoints( - zone_short_name, - 0, - &safe_x, - &safe_y, - &safe_z, - &safe_heading, - &min_status, - &min_level, - flag_name - )) { - strcpy(flag_name, "ERROR"); + std::string flag_name = "ERROR"; + + auto z = GetZone(zone_id); + if (z) { + flag_name = z->flag_needed; } to->Message( Chat::White, fmt::format( - "Flag {} | Zone ID: {} Zone Name: {} ({}){}", + "Flag {} | Zone: {} ({}) ID: {}", flag_number, - zone_id, zone_long_name, zone_short_name, + zone_id, ( - flag_name != "" ? + !flag_name.empty() ? fmt::format( " Flag Required: {}", flag_name @@ -1108,7 +1078,7 @@ void Client::SetZoneFlag(uint32 zone_id) { zone_flags.insert(zone_id); - std::string query = fmt::format( + const auto query = fmt::format( "INSERT INTO zone_flags (charID, zoneID) VALUES ({}, {})", CharacterID(), zone_id @@ -1127,15 +1097,8 @@ void Client::ClearPEQZoneFlag(uint32 zone_id) { peqzone_flags.erase(zone_id); - auto query = fmt::format( - "DELETE FROM character_peqzone_flags WHERE id = {} AND zone_id = {}", - CharacterID(), - zone_id - ); - auto results = database.QueryDatabase(query); - - if (!results.Success()) { - LogError("MySQL Error while trying to clear zone flag for [{}]: [{}]", GetName(), results.ErrorMessage().c_str()); + if (!CharacterPeqzoneFlagsRepository::DeleteFlag(database, CharacterID(), zone_id)) { + LogError("MySQL Error while trying to clear PEQZone flag for [{}]", GetName()); } } @@ -1144,21 +1107,21 @@ bool Client::HasPEQZoneFlag(uint32 zone_id) const { } void Client::LoadPEQZoneFlags() { - std::string query = fmt::format( - "SELECT zone_id from character_peqzone_flags WHERE id = {}", - CharacterID() + const auto l = CharacterPeqzoneFlagsRepository::GetWhere( + database, + fmt::format( + "id = {}", + CharacterID() + ) ); - auto results = database.QueryDatabase(query); - - if (!results.Success()) { - LogError("MySQL Error while trying to load zone flags for [{}]: [{}]", GetName(), results.ErrorMessage().c_str()); + if (l.empty()) { return; } peqzone_flags.clear(); - for (auto row : results) { - peqzone_flags.insert(std::stoul(row[0])); + for (const auto& f : l) { + peqzone_flags.insert(f.zone_id); } } @@ -1193,11 +1156,11 @@ void Client::SendPEQZoneFlagInfo(Client *to) const { to->Message( Chat::White, fmt::format( - "Flag {} | Zone ID: {} Zone Name: {} ({})", + "Flag {} | Zone: {} ({}) ID: {}", flag_number, - zone_id, zone_long_name, - zone_short_name + zone_short_name, + zone_id ).c_str() ); flag_count++; @@ -1222,62 +1185,74 @@ void Client::SetPEQZoneFlag(uint32 zone_id) { peqzone_flags.insert(zone_id); - auto query = fmt::format( - "INSERT INTO character_peqzone_flags (id, zone_id) VALUES ({}, {})", - CharacterID(), - zone_id - ); - auto results = database.QueryDatabase(query); + auto f = CharacterPeqzoneFlagsRepository::NewEntity(); - if (!results.Success()) { - LogError("MySQL Error while trying to set zone flag for [{}]: [{}]", GetName(), results.ErrorMessage().c_str()); + f.id = CharacterID(); + f.zone_id = zone_id; + + if (!CharacterPeqzoneFlagsRepository::InsertOne(database, f).id) { + LogError("MySQL Error while trying to set zone flag for [{}]", GetName()); } } -bool Client::CanBeInZone() { +bool Client::CanEnterZone(const std::string& zone_short_name, int16 instance_version) { //check some critial rules to see if this char needs to be booted from the zone //only enforce rules here which are serious enough to warrant being kicked from //the zone - if(Admin() >= RuleI(GM, MinStatusToZoneAnywhere)) - return(true); - - float safe_x, safe_y, safe_z, safe_heading; - int16 min_status = AccountStatus::Player; - uint8 min_level = 0; - char flag_needed[128]; - if(!content_db.GetSafePoints( - zone->GetShortName(), - zone->GetInstanceVersion(), - &safe_x, - &safe_y, - &safe_z, - &safe_heading, - &min_status, - &min_level, - flag_needed - )) { - //this should not happen... - LogDebug("[CLIENT] Unable to query zone info for ourself [{}]", zone->GetShortName()); - return(false); + if (Admin() >= RuleI(GM, MinStatusToZoneAnywhere)) { + return true; } - if(GetLevel() < min_level) { - LogDebug("[CLIENT] Character does not meet min level requirement ([{}] < [{}])!", GetLevel(), min_level); - return(false); - } - if(Admin() < min_status) { - LogDebug("[CLIENT] Character does not meet min status requirement ([{}] < [{}])!", Admin(), min_status); - return(false); + auto z = GetZoneVersionWithFallback( + zone_short_name.empty() ? ZoneID(zone->GetShortName()) : ZoneID(zone_short_name), + instance_version == -1 ? zone->GetInstanceVersion() : instance_version + ); + + if (!z) { + return false; } - if(flag_needed[0] != '\0') { - //the flag needed string is not empty, meaning a flag is required. - if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(zone->GetZoneID())) { - LogDebug("[CLIENT] Character does not have the flag to be in this zone ([{}])!", flag_needed); - return(false); + if (GetLevel() < z->min_level) { + LogInfo( + "Character [{}] does not meet minimum level requirement ([{}] < [{}])!", + GetCleanName(), + GetLevel(), + z->min_level + ); + return false; + } + + if (GetLevel() > z->max_level) { + LogInfo( + "Character [{}] does not meet maximum level requirement ([{}] > [{}])!", + GetCleanName(), + GetLevel(), + z->max_level + ); + return false; + } + + if (Admin() < z->min_status) { + LogInfo( + "Character [{}] does not meet minimum status requirement ([{}] < [{}])!", + GetCleanName(), + Admin(), + z->min_status + ); + return false; + } + + if (!z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && std::stoi(z->flag_needed) == 1) { + if (Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(z->zoneidnumber)) { + LogInfo( + "Character [{}] does not have the flag to be in this zone [{}]!", + GetCleanName(), + z->flag_needed + ); + return false; } } - return(true); + return true; }